1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/PTdecode/CImg-1.3.0/CImg.h Mon Aug 03 14:09:20 2009 +0100 1.3 @@ -0,0 +1,36840 @@ 1.4 +/* 1.5 + # 1.6 + # File : CImg.h 1.7 + # ( C++ header file ) 1.8 + # 1.9 + # Description : The C++ Template Image Processing Library. 1.10 + # This file is the main part of the CImg Library project. 1.11 + # ( http://cimg.sourceforge.net ) 1.12 + # 1.13 + # Project manager : David Tschumperle. 1.14 + # ( http://www.greyc.ensicaen.fr/~dtschump/ ) 1.15 + # 1.16 + # The complete contributor list can be seen in the 'README.txt' file. 1.17 + # 1.18 + # Licenses : This file is "dual-licensed", you have to choose one 1.19 + # of the two licenses below to apply on this file. 1.20 + # 1.21 + # CeCILL-C 1.22 + # The CeCILL-C license is close to the GNU LGPL. 1.23 + # ( http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html ) 1.24 + # 1.25 + # or CeCILL v2.0 1.26 + # The CeCILL license is compatible with the GNU GPL. 1.27 + # ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html ) 1.28 + # 1.29 + # This software is governed either by the CeCILL or the CeCILL-C license 1.30 + # under French law and abiding by the rules of distribution of free software. 1.31 + # You can use, modify and or redistribute the software under the terms of 1.32 + # the CeCILL or CeCILL-C licenses as circulated by CEA, CNRS and INRIA 1.33 + # at the following URL : "http://www.cecill.info". 1.34 + # 1.35 + # As a counterpart to the access to the source code and rights to copy, 1.36 + # modify and redistribute granted by the license, users are provided only 1.37 + # with a limited warranty and the software's author, the holder of the 1.38 + # economic rights, and the successive licensors have only limited 1.39 + # liability. 1.40 + # 1.41 + # In this respect, the user's attention is drawn to the risks associated 1.42 + # with loading, using, modifying and/or developing or reproducing the 1.43 + # software by the user in light of its specific status of free software, 1.44 + # that may mean that it is complicated to manipulate, and that also 1.45 + # therefore means that it is reserved for developers and experienced 1.46 + # professionals having in-depth computer knowledge. Users are therefore 1.47 + # encouraged to load and test the software's suitability as regards their 1.48 + # requirements in conditions enabling the security of their systems and/or 1.49 + # data to be ensured and, more generally, to use and operate it in the 1.50 + # same conditions as regards security. 1.51 + # 1.52 + # The fact that you are presently reading this means that you have had 1.53 + # knowledge of the CeCILL and CeCILL-C licenses and that you accept its terms. 1.54 + # 1.55 +*/ 1.56 + 1.57 +// Define version number of the current file. 1.58 +// 1.59 +#ifndef cimg_version 1.60 +#define cimg_version 130 1.61 + 1.62 +/*----------------------------------------------------------- 1.63 + # 1.64 + # Test/auto-set CImg configuration variables 1.65 + # and include required headers. 1.66 + # 1.67 + # If you find that default configuration variables are 1.68 + # not adapted, you can override their values before including 1.69 + # the header file "CImg.h" (using the #define directive). 1.70 + # 1.71 + ------------------------------------------------------------*/ 1.72 + 1.73 +// Include required standard C++ headers. 1.74 +// 1.75 +#include <cstdio> 1.76 +#include <cstdlib> 1.77 +#include <cstdarg> 1.78 +#include <cstring> 1.79 +#include <cmath> 1.80 +#include <ctime> 1.81 + 1.82 +// Operating system configuration. 1.83 +// 1.84 +// Define 'cimg_OS' to : 0 for an unknown OS (will try to minize library dependancies). 1.85 +// 1 for a Unix-like OS (Linux, Solaris, BSD, MacOSX, Irix, ...). 1.86 +// 2 for Microsoft Windows. 1.87 +// 1.88 +#ifndef cimg_OS 1.89 +#if defined(unix) || defined(__unix) || defined(__unix__) \ 1.90 + || defined(linux) || defined(__linux) || defined(__linux__) \ 1.91 + || defined(sun) || defined(__sun) \ 1.92 + || defined(BSD) || defined(__OpenBSD__) || defined(__NetBSD__) \ 1.93 + || defined(__FreeBSD__) || defined __DragonFly__ \ 1.94 + || defined(sgi) || defined(__sgi) \ 1.95 + || defined(__MACOSX__) || defined(__APPLE__) \ 1.96 + || defined(__CYGWIN__) 1.97 +#define cimg_OS 1 1.98 +#elif defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \ 1.99 + || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) 1.100 +#define cimg_OS 2 1.101 +#else 1.102 +#define cimg_OS 0 1.103 +#endif 1.104 +#elif !(cimg_OS==0 || cimg_OS==1 || cimg_OS==2) 1.105 +#error CImg Library : Configuration variable 'cimg_OS' is badly defined. 1.106 +#error (valid values are '0=unknown OS', '1=Unix-like OS', '2=Microsoft Windows'). 1.107 +#endif 1.108 + 1.109 +// Compiler configuration. 1.110 +// 1.111 +// Try to detect Microsoft VC++ compilers. 1.112 +// (lot of workarounds are needed afterwards to 1.113 +// make CImg working, particularly with VC++ 6.0). 1.114 +// 1.115 +#ifdef _MSC_VER 1.116 +#pragma warning(push) 1.117 +#pragma warning(disable:4311) 1.118 +#pragma warning(disable:4312) 1.119 +#pragma warning(disable:4800) 1.120 +#pragma warning(disable:4804) 1.121 +#pragma warning(disable:4996) 1.122 +#define _CRT_SECURE_NO_DEPRECATE 1 1.123 +#define _CRT_NONSTDC_NO_DEPRECATE 1 1.124 +#if _MSC_VER<1300 1.125 +#define cimg_use_visualcpp6 1.126 +#define cimg_std 1.127 +#define _WIN32_WINNT 0x0500 1.128 +#endif 1.129 +#endif 1.130 + 1.131 +// Include OS-specific headers. 1.132 +// 1.133 +#if cimg_OS==1 1.134 +#include <sys/time.h> 1.135 +#include <unistd.h> 1.136 +#elif cimg_OS==2 1.137 +#include <windows.h> 1.138 +#ifndef _WIN32_IE 1.139 +#define _WIN32_IE 0x0400 1.140 +#endif 1.141 +#include <shlobj.h> 1.142 +#endif 1.143 + 1.144 +// Define defaut pipe for output messages 1.145 +// 1.146 +// Define 'cimg_stdout' to : stdout to print CImg messages on the standard output. 1.147 +// stderr to print CImg messages on the standart error output (default behavior). 1.148 +// 1.149 +#ifndef cimg_std 1.150 +#define cimg_std std 1.151 +#endif 1.152 +#ifndef cimg_stdout 1.153 +#define cimg_stdout stderr 1.154 +#endif 1.155 + 1.156 +// Output messages configuration. 1.157 +// 1.158 +// Define 'cimg_debug' to : 0 to hide debug messages (quiet mode, but exceptions are still thrown). 1.159 +// 1 to display debug messages on the console. 1.160 +// 2 to display debug messages with dialog windows (default behavior). 1.161 +// 3 to do as 1 + add extra warnings (may slow down the code !). 1.162 +// 4 to do as 2 + add extra warnings (may slow down the code !). 1.163 +// 1.164 +// Define 'cimg_strict_warnings' to replace warning messages by exception throwns. 1.165 +// 1.166 +// Define 'cimg_use_vt100' to allow output of color messages (require VT100-compatible terminal). 1.167 +// 1.168 +#ifndef cimg_debug 1.169 +#define cimg_debug 2 1.170 +#elif !(cimg_debug==0 || cimg_debug==1 || cimg_debug==2 || cimg_debug==3 || cimg_debug==4) 1.171 +#error CImg Library : Configuration variable 'cimg_debug' is badly defined. 1.172 +#error (valid values are '0=quiet', '1=console', '2=dialog', '3=console+warnings', '4=dialog+warnings'). 1.173 +#endif 1.174 + 1.175 +// Display framework configuration. 1.176 +// 1.177 +// Define 'cimg_display' to : 0 to disable display capabilities. 1.178 +// 1 to use X-Window framework (X11). 1.179 +// 2 to use Microsoft GDI32 framework. 1.180 +// 3 to use Apple Carbon framework. 1.181 +// 1.182 +#ifndef cimg_display 1.183 +#if cimg_OS==0 1.184 +#define cimg_display 0 1.185 +#elif cimg_OS==1 1.186 +#if defined(__MACOSX__) || defined(__APPLE__) 1.187 +#define cimg_display 1 1.188 +#else 1.189 +#define cimg_display 1 1.190 +#endif 1.191 +#elif cimg_OS==2 1.192 +#define cimg_display 2 1.193 +#endif 1.194 +#elif !(cimg_display==0 || cimg_display==1 || cimg_display==2 || cimg_display==3) 1.195 +#error CImg Library : Configuration variable 'cimg_display' is badly defined. 1.196 +#error (valid values are '0=disable', '1=X-Window (X11)', '2=Microsoft GDI32', '3=Apple Carbon'). 1.197 +#endif 1.198 + 1.199 +// Include display-specific headers. 1.200 +// 1.201 +#if cimg_display==1 1.202 +#include <X11/Xlib.h> 1.203 +#include <X11/Xutil.h> 1.204 +#include <X11/keysym.h> 1.205 +#include <pthread.h> 1.206 +#ifdef cimg_use_xshm 1.207 +#include <sys/ipc.h> 1.208 +#include <sys/shm.h> 1.209 +#include <X11/extensions/XShm.h> 1.210 +#endif 1.211 +#ifdef cimg_use_xrandr 1.212 +#include <X11/extensions/Xrandr.h> 1.213 +#endif 1.214 +#elif cimg_display==3 1.215 +#include <Carbon/Carbon.h> 1.216 +#include <pthread.h> 1.217 +#endif 1.218 + 1.219 +// OpenMP configuration. 1.220 +// (http://www.openmp.org) 1.221 +// 1.222 +// Define 'cimg_use_openmp' to enable OpenMP support. 1.223 +// 1.224 +// OpenMP directives can be used in few CImg functions to get 1.225 +// advantages of multi-core CPUs. Using OpenMP is not mandatory. 1.226 +// 1.227 +#ifdef cimg_use_openmp 1.228 +#include "omp.h" 1.229 +#endif 1.230 + 1.231 +// LibPNG configuration. 1.232 +// (http://www.libpng.org) 1.233 +// 1.234 +// Define 'cimg_use_png' to enable LibPNG support. 1.235 +// 1.236 +// LibPNG can be used in functions 'CImg<T>::{load,save}_png()' 1.237 +// to get a builtin support of PNG files. Using LibPNG is not mandatory. 1.238 +// 1.239 +#ifdef cimg_use_png 1.240 +extern "C" { 1.241 +#include "png.h" 1.242 +} 1.243 +#endif 1.244 + 1.245 +// LibJPEG configuration. 1.246 +// (http://en.wikipedia.org/wiki/Libjpeg) 1.247 +// 1.248 +// Define 'cimg_use_jpeg' to enable LibJPEG support. 1.249 +// 1.250 +// LibJPEG can be used in functions 'CImg<T>::{load,save}_jpeg()' 1.251 +// to get a builtin support of JPEG files. Using LibJPEG is not mandatory. 1.252 +// 1.253 +#ifdef cimg_use_jpeg 1.254 +extern "C" { 1.255 +#include "jpeglib.h" 1.256 +} 1.257 +#endif 1.258 + 1.259 +// LibTIFF configuration. 1.260 +// (http://www.libtiff.org) 1.261 +// 1.262 +// Define 'cimg_use_tiff' to enable LibTIFF support. 1.263 +// 1.264 +// LibTIFF can be used in functions 'CImg[List]<T>::{load,save}_tiff()' 1.265 +// to get a builtin support of TIFF files. Using LibTIFF is not mandatory. 1.266 +// 1.267 +#ifdef cimg_use_tiff 1.268 +extern "C" { 1.269 +#include "tiffio.h" 1.270 +} 1.271 +#endif 1.272 + 1.273 +// FFMPEG Avcodec and Avformat libraries configuration. 1.274 +// (http://www.ffmpeg.org) 1.275 +// 1.276 +// Define 'cimg_use_ffmpeg' to enable FFMPEG lib support. 1.277 +// 1.278 +// Avcodec and Avformat libraries can be used in functions 1.279 +// 'CImg[List]<T>::load_ffmpeg()' to get a builtin 1.280 +// support of various image sequences files. 1.281 +// Using FFMPEG libraries is not mandatory. 1.282 +// 1.283 +#ifdef cimg_use_ffmpeg 1.284 +extern "C" { 1.285 +#include "avformat.h" 1.286 +#include "avcodec.h" 1.287 +#include "swscale.h" 1.288 +} 1.289 +#endif 1.290 + 1.291 +// Zlib configuration 1.292 +// (http://www.zlib.net) 1.293 +// 1.294 +// Define 'cimg_use_zlib' to enable Zlib support. 1.295 +// 1.296 +// Zlib can be used in functions 'CImg[List]<T>::{load,save}_cimg()' 1.297 +// to allow compressed data in '.cimg' files. Using Zlib is not mandatory. 1.298 +// 1.299 +#ifdef cimg_use_zlib 1.300 +extern "C" { 1.301 +#include "zlib.h" 1.302 +} 1.303 +#endif 1.304 + 1.305 +// Magick++ configuration. 1.306 +// (http://www.imagemagick.org/Magick++) 1.307 +// 1.308 +// Define 'cimg_use_magick' to enable Magick++ support. 1.309 +// 1.310 +// Magick++ library can be used in functions 'CImg<T>::{load,save}()' 1.311 +// to get a builtin support of various image formats (PNG,JPEG,TIFF,...). 1.312 +// Using Magick++ is not mandatory. 1.313 +// 1.314 +#ifdef cimg_use_magick 1.315 +#include "Magick++.h" 1.316 +#endif 1.317 + 1.318 +// FFTW3 configuration. 1.319 +// (http://www.fftw.org) 1.320 +// 1.321 +// Define 'cimg_use_fftw3' to enable libFFTW3 support. 1.322 +// 1.323 +// FFTW3 library can be used in functions 'CImg[List]<T>::FFT()' to 1.324 +// efficiently compile the Fast Fourier Transform of image data. 1.325 +// 1.326 +#ifdef cimg_use_fftw3 1.327 +extern "C" { 1.328 +#include "fftw3.h" 1.329 +} 1.330 +#endif 1.331 + 1.332 +// Board configuration. 1.333 +// (http://libboard.sourceforge.net/) 1.334 +// 1.335 +// Define 'cimg_use_board' to enable Board support. 1.336 +// 1.337 +// Board library can be used in functions 'CImg<T>::draw_object3d()' 1.338 +// to draw objects 3D in vector-graphics canvas that can be saved 1.339 +// as .PS or .SVG files afterwards. 1.340 +// 1.341 +#ifdef cimg_use_board 1.342 +#include "Board.h" 1.343 +#endif 1.344 + 1.345 +// Lapack configuration. 1.346 +// (http://www.netlib.org/lapack) 1.347 +// 1.348 +// Define 'cimg_use_lapack' to enable LAPACK support. 1.349 +// 1.350 +// Lapack can be used in various CImg functions dealing with 1.351 +// matrix computation and algorithms (eigenvalues, inverse, ...). 1.352 +// Using Lapack is not mandatory. 1.353 +// 1.354 +#ifdef cimg_use_lapack 1.355 +extern "C" { 1.356 + extern void sgetrf_(int*, int*, float*, int*, int*, int*); 1.357 + extern void sgetri_(int*, float*, int*, int*, float*, int*, int*); 1.358 + extern void sgetrs_(char*, int*, int*, float*, int*, int*, float*, int*, int*); 1.359 + extern void sgesvd_(char*, char*, int*, int*, float*, int*, float*, float*, int*, float*, int*, float*, int*, int*); 1.360 + extern void ssyev_(char*, char*, int*, float*, int*, float*, float*, int*, int*); 1.361 + extern void dgetrf_(int*, int*, double*, int*, int*, int*); 1.362 + extern void dgetri_(int*, double*, int*, int*, double*, int*, int*); 1.363 + extern void dgetrs_(char*, int*, int*, double*, int*, int*, double*, int*, int*); 1.364 + extern void dgesvd_(char*, char*, int*, int*, double*, int*, double*, double*, int*, double*, int*, double*, int*, int*); 1.365 + extern void dsyev_(char*, char*, int*, double*, int*, double*, double*, int*, int*); 1.366 +} 1.367 +#endif 1.368 + 1.369 +// Check if min/max macros are defined. 1.370 +// 1.371 +// CImg does not compile if macros 'min' or 'max' are defined, 1.372 +// because min() and max() functions are also defined in the cimg:: namespace. 1.373 +// so it '#undef' these macros if necessary, and restore them to reasonable 1.374 +// values at the end of the file. 1.375 +// 1.376 +#ifdef min 1.377 +#undef min 1.378 +#define _cimg_redefine_min 1.379 +#endif 1.380 +#ifdef max 1.381 +#undef max 1.382 +#define _cimg_redefine_max 1.383 +#endif 1.384 + 1.385 +// Set the current working directory for native MacOSX bundled applications. 1.386 +// 1.387 +// By default, MacOS bundled applications set the cwd at the root directory '/', 1.388 +// the code below allows to set it to the current exec directory instead when 1.389 +// a CImg-based program is executed. 1.390 +// 1.391 +#if cimg_OS==1 && cimg_display==3 1.392 +static struct _cimg_macosx_setcwd { 1.393 + _cimg_macosx_setcwd() { 1.394 + FSRef location; 1.395 + ProcessSerialNumber psn; 1.396 + char filePath[512]; 1.397 + if (GetCurrentProcess(&psn)!=noErr) return; 1.398 + if (GetProcessBundleLocation(&psn,&location)!=noErr) return; 1.399 + FSRefMakePath(&location,(UInt8*)filePath,sizeof(filePath)-1); 1.400 + int p = cimg_std::strlen(filePath); 1.401 + while (filePath[p] != '/') --p; 1.402 + filePath[p] = 0; 1.403 + chdir(filePath); 1.404 + } 1.405 +} cimg_macosx_setcwd; 1.406 +#endif 1.407 + 1.408 +/*------------------------------------------------------------------------------ 1.409 + # 1.410 + # Define user-friendly macros. 1.411 + # 1.412 + # User macros are prefixed by 'cimg_' and can be used in your own code. 1.413 + # They are particularly useful for option parsing, and image loops creation. 1.414 + # 1.415 + ------------------------------------------------------------------------------*/ 1.416 + 1.417 +// Define the program usage, and retrieve command line arguments. 1.418 +// 1.419 +#define cimg_usage(usage) cimg_library::cimg::option((char*)0,argc,argv,(char*)0,usage) 1.420 +#define cimg_help(str) cimg_library::cimg::option((char*)0,argc,argv,str,(char*)0) 1.421 +#define cimg_option(name,defaut,usage) cimg_library::cimg::option(name,argc,argv,defaut,usage) 1.422 +#define cimg_argument(pos) cimg_library::cimg::argument(pos,argc,argv) 1.423 +#define cimg_argument1(pos,s0) cimg_library::cimg::argument(pos,argc,argv,1,s0) 1.424 +#define cimg_argument2(pos,s0,s1) cimg_library::cimg::argument(pos,argc,argv,2,s0,s1) 1.425 +#define cimg_argument3(pos,s0,s1,s2) cimg_library::cimg::argument(pos,argc,argv,3,s0,s1,s2) 1.426 +#define cimg_argument4(pos,s0,s1,s2,s3) cimg_library::cimg::argument(pos,argc,argv,4,s0,s1,s2,s3) 1.427 +#define cimg_argument5(pos,s0,s1,s2,s3,s4) cimg_library::cimg::argument(pos,argc,argv,5,s0,s1,s2,s3,s4) 1.428 +#define cimg_argument6(pos,s0,s1,s2,s3,s4,s5) cimg_library::cimg::argument(pos,argc,argv,6,s0,s1,s2,s3,s4,s5) 1.429 +#define cimg_argument7(pos,s0,s1,s2,s3,s4,s5,s6) cimg_library::cimg::argument(pos,argc,argv,7,s0,s1,s2,s3,s4,s5,s6) 1.430 +#define cimg_argument8(pos,s0,s1,s2,s3,s4,s5,s6,s7) cimg_library::cimg::argument(pos,argc,argv,8,s0,s1,s2,s3,s4,s5,s6,s7) 1.431 +#define cimg_argument9(pos,s0,s1,s2,s3,s4,s5,s6,s7,s8) cimg_library::cimg::argument(pos,argc,argv,9,s0,s1,s2,s3,s4,s5,s6,s7,s8) 1.432 + 1.433 +// Define and manipulate local neighborhoods. 1.434 +// 1.435 +#define CImg_2x2(I,T) T I[4]; \ 1.436 + T& I##cc = I[0]; T& I##nc = I[1]; \ 1.437 + T& I##cn = I[2]; T& I##nn = I[3]; \ 1.438 + I##cc = I##nc = \ 1.439 + I##cn = I##nn = 0 1.440 + 1.441 +#define CImg_3x3(I,T) T I[9]; \ 1.442 + T& I##pp = I[0]; T& I##cp = I[1]; T& I##np = I[2]; \ 1.443 + T& I##pc = I[3]; T& I##cc = I[4]; T& I##nc = I[5]; \ 1.444 + T& I##pn = I[6]; T& I##cn = I[7]; T& I##nn = I[8]; \ 1.445 + I##pp = I##cp = I##np = \ 1.446 + I##pc = I##cc = I##nc = \ 1.447 + I##pn = I##cn = I##nn = 0 1.448 + 1.449 +#define CImg_4x4(I,T) T I[16]; \ 1.450 + T& I##pp = I[0]; T& I##cp = I[1]; T& I##np = I[2]; T& I##ap = I[3]; \ 1.451 + T& I##pc = I[4]; T& I##cc = I[5]; T& I##nc = I[6]; T& I##ac = I[7]; \ 1.452 + T& I##pn = I[8]; T& I##cn = I[9]; T& I##nn = I[10]; T& I##an = I[11]; \ 1.453 + T& I##pa = I[12]; T& I##ca = I[13]; T& I##na = I[14]; T& I##aa = I[15]; \ 1.454 + I##pp = I##cp = I##np = I##ap = \ 1.455 + I##pc = I##cc = I##nc = I##ac = \ 1.456 + I##pn = I##cn = I##nn = I##an = \ 1.457 + I##pa = I##ca = I##na = I##aa = 0 1.458 + 1.459 +#define CImg_5x5(I,T) T I[25]; \ 1.460 + 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]; \ 1.461 + 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]; \ 1.462 + 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]; \ 1.463 + 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]; \ 1.464 + 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]; \ 1.465 + I##bb = I##pb = I##cb = I##nb = I##ab = \ 1.466 + I##bp = I##pp = I##cp = I##np = I##ap = \ 1.467 + I##bc = I##pc = I##cc = I##nc = I##ac = \ 1.468 + I##bn = I##pn = I##cn = I##nn = I##an = \ 1.469 + I##ba = I##pa = I##ca = I##na = I##aa = 0 1.470 + 1.471 +#define CImg_2x2x2(I,T) T I[8]; \ 1.472 + T& I##ccc = I[0]; T& I##ncc = I[1]; \ 1.473 + T& I##cnc = I[2]; T& I##nnc = I[3]; \ 1.474 + T& I##ccn = I[4]; T& I##ncn = I[5]; \ 1.475 + T& I##cnn = I[6]; T& I##nnn = I[7]; \ 1.476 + I##ccc = I##ncc = \ 1.477 + I##cnc = I##nnc = \ 1.478 + I##ccn = I##ncn = \ 1.479 + I##cnn = I##nnn = 0 1.480 + 1.481 +#define CImg_3x3x3(I,T) T I[27]; \ 1.482 + T& I##ppp = I[0]; T& I##cpp = I[1]; T& I##npp = I[2]; \ 1.483 + T& I##pcp = I[3]; T& I##ccp = I[4]; T& I##ncp = I[5]; \ 1.484 + T& I##pnp = I[6]; T& I##cnp = I[7]; T& I##nnp = I[8]; \ 1.485 + T& I##ppc = I[9]; T& I##cpc = I[10]; T& I##npc = I[11]; \ 1.486 + T& I##pcc = I[12]; T& I##ccc = I[13]; T& I##ncc = I[14]; \ 1.487 + T& I##pnc = I[15]; T& I##cnc = I[16]; T& I##nnc = I[17]; \ 1.488 + T& I##ppn = I[18]; T& I##cpn = I[19]; T& I##npn = I[20]; \ 1.489 + T& I##pcn = I[21]; T& I##ccn = I[22]; T& I##ncn = I[23]; \ 1.490 + T& I##pnn = I[24]; T& I##cnn = I[25]; T& I##nnn = I[26]; \ 1.491 + I##ppp = I##cpp = I##npp = \ 1.492 + I##pcp = I##ccp = I##ncp = \ 1.493 + I##pnp = I##cnp = I##nnp = \ 1.494 + I##ppc = I##cpc = I##npc = \ 1.495 + I##pcc = I##ccc = I##ncc = \ 1.496 + I##pnc = I##cnc = I##nnc = \ 1.497 + I##ppn = I##cpn = I##npn = \ 1.498 + I##pcn = I##ccn = I##ncn = \ 1.499 + I##pnn = I##cnn = I##nnn = 0 1.500 + 1.501 +#define cimg_get2x2(img,x,y,z,v,I) \ 1.502 + I[0] = (img)(x,y,z,v), I[1] = (img)(_n1##x,y,z,v), I[2] = (img)(x,_n1##y,z,v), I[3] = (img)(_n1##x,_n1##y,z,v) 1.503 + 1.504 +#define cimg_get3x3(img,x,y,z,v,I) \ 1.505 + I[0] = (img)(_p1##x,_p1##y,z,v), I[1] = (img)(x,_p1##y,z,v), I[2] = (img)(_n1##x,_p1##y,z,v), I[3] = (img)(_p1##x,y,z,v), \ 1.506 + I[4] = (img)(x,y,z,v), I[5] = (img)(_n1##x,y,z,v), I[6] = (img)(_p1##x,_n1##y,z,v), I[7] = (img)(x,_n1##y,z,v), \ 1.507 + I[8] = (img)(_n1##x,_n1##y,z,v) 1.508 + 1.509 +#define cimg_get4x4(img,x,y,z,v,I) \ 1.510 + I[0] = (img)(_p1##x,_p1##y,z,v), I[1] = (img)(x,_p1##y,z,v), I[2] = (img)(_n1##x,_p1##y,z,v), I[3] = (img)(_n2##x,_p1##y,z,v), \ 1.511 + I[4] = (img)(_p1##x,y,z,v), I[5] = (img)(x,y,z,v), I[6] = (img)(_n1##x,y,z,v), I[7] = (img)(_n2##x,y,z,v), \ 1.512 + I[8] = (img)(_p1##x,_n1##y,z,v), I[9] = (img)(x,_n1##y,z,v), I[10] = (img)(_n1##x,_n1##y,z,v), I[11] = (img)(_n2##x,_n1##y,z,v), \ 1.513 + I[12] = (img)(_p1##x,_n2##y,z,v), I[13] = (img)(x,_n2##y,z,v), I[14] = (img)(_n1##x,_n2##y,z,v), I[15] = (img)(_n2##x,_n2##y,z,v) 1.514 + 1.515 +#define cimg_get5x5(img,x,y,z,v,I) \ 1.516 + I[0] = (img)(_p2##x,_p2##y,z,v), I[1] = (img)(_p1##x,_p2##y,z,v), I[2] = (img)(x,_p2##y,z,v), I[3] = (img)(_n1##x,_p2##y,z,v), \ 1.517 + I[4] = (img)(_n2##x,_p2##y,z,v), I[5] = (img)(_p2##x,_p1##y,z,v), I[6] = (img)(_p1##x,_p1##y,z,v), I[7] = (img)(x,_p1##y,z,v), \ 1.518 + I[8] = (img)(_n1##x,_p1##y,z,v), I[9] = (img)(_n2##x,_p1##y,z,v), I[10] = (img)(_p2##x,y,z,v), I[11] = (img)(_p1##x,y,z,v), \ 1.519 + I[12] = (img)(x,y,z,v), I[13] = (img)(_n1##x,y,z,v), I[14] = (img)(_n2##x,y,z,v), I[15] = (img)(_p2##x,_n1##y,z,v), \ 1.520 + I[16] = (img)(_p1##x,_n1##y,z,v), I[17] = (img)(x,_n1##y,z,v), I[18] = (img)(_n1##x,_n1##y,z,v), I[19] = (img)(_n2##x,_n1##y,z,v), \ 1.521 + I[20] = (img)(_p2##x,_n2##y,z,v), I[21] = (img)(_p1##x,_n2##y,z,v), I[22] = (img)(x,_n2##y,z,v), I[23] = (img)(_n1##x,_n2##y,z,v), \ 1.522 + I[24] = (img)(_n2##x,_n2##y,z,v) 1.523 + 1.524 +#define cimg_get6x6(img,x,y,z,v,I) \ 1.525 + I[0] = (img)(_p2##x,_p2##y,z,v), I[1] = (img)(_p1##x,_p2##y,z,v), I[2] = (img)(x,_p2##y,z,v), I[3] = (img)(_n1##x,_p2##y,z,v), \ 1.526 + I[4] = (img)(_n2##x,_p2##y,z,v), I[5] = (img)(_n3##x,_p2##y,z,v), I[6] = (img)(_p2##x,_p1##y,z,v), I[7] = (img)(_p1##x,_p1##y,z,v), \ 1.527 + I[8] = (img)(x,_p1##y,z,v), I[9] = (img)(_n1##x,_p1##y,z,v), I[10] = (img)(_n2##x,_p1##y,z,v), I[11] = (img)(_n3##x,_p1##y,z,v), \ 1.528 + I[12] = (img)(_p2##x,y,z,v), I[13] = (img)(_p1##x,y,z,v), I[14] = (img)(x,y,z,v), I[15] = (img)(_n1##x,y,z,v), \ 1.529 + I[16] = (img)(_n2##x,y,z,v), I[17] = (img)(_n3##x,y,z,v), I[18] = (img)(_p2##x,_n1##y,z,v), I[19] = (img)(_p1##x,_n1##y,z,v), \ 1.530 + I[20] = (img)(x,_n1##y,z,v), I[21] = (img)(_n1##x,_n1##y,z,v), I[22] = (img)(_n2##x,_n1##y,z,v), I[23] = (img)(_n3##x,_n1##y,z,v), \ 1.531 + I[24] = (img)(_p2##x,_n2##y,z,v), I[25] = (img)(_p1##x,_n2##y,z,v), I[26] = (img)(x,_n2##y,z,v), I[27] = (img)(_n1##x,_n2##y,z,v), \ 1.532 + I[28] = (img)(_n2##x,_n2##y,z,v), I[29] = (img)(_n3##x,_n2##y,z,v), I[30] = (img)(_p2##x,_n3##y,z,v), I[31] = (img)(_p1##x,_n3##y,z,v), \ 1.533 + I[32] = (img)(x,_n3##y,z,v), I[33] = (img)(_n1##x,_n3##y,z,v), I[34] = (img)(_n2##x,_n3##y,z,v), I[35] = (img)(_n3##x,_n3##y,z,v) 1.534 + 1.535 +#define cimg_get7x7(img,x,y,z,v,I) \ 1.536 + I[0] = (img)(_p3##x,_p3##y,z,v), I[1] = (img)(_p2##x,_p3##y,z,v), I[2] = (img)(_p1##x,_p3##y,z,v), I[3] = (img)(x,_p3##y,z,v), \ 1.537 + I[4] = (img)(_n1##x,_p3##y,z,v), I[5] = (img)(_n2##x,_p3##y,z,v), I[6] = (img)(_n3##x,_p3##y,z,v), I[7] = (img)(_p3##x,_p2##y,z,v), \ 1.538 + I[8] = (img)(_p2##x,_p2##y,z,v), I[9] = (img)(_p1##x,_p2##y,z,v), I[10] = (img)(x,_p2##y,z,v), I[11] = (img)(_n1##x,_p2##y,z,v), \ 1.539 + I[12] = (img)(_n2##x,_p2##y,z,v), I[13] = (img)(_n3##x,_p2##y,z,v), I[14] = (img)(_p3##x,_p1##y,z,v), I[15] = (img)(_p2##x,_p1##y,z,v), \ 1.540 + I[16] = (img)(_p1##x,_p1##y,z,v), I[17] = (img)(x,_p1##y,z,v), I[18] = (img)(_n1##x,_p1##y,z,v), I[19] = (img)(_n2##x,_p1##y,z,v), \ 1.541 + I[20] = (img)(_n3##x,_p1##y,z,v), I[21] = (img)(_p3##x,y,z,v), I[22] = (img)(_p2##x,y,z,v), I[23] = (img)(_p1##x,y,z,v), \ 1.542 + I[24] = (img)(x,y,z,v), I[25] = (img)(_n1##x,y,z,v), I[26] = (img)(_n2##x,y,z,v), I[27] = (img)(_n3##x,y,z,v), \ 1.543 + I[28] = (img)(_p3##x,_n1##y,z,v), I[29] = (img)(_p2##x,_n1##y,z,v), I[30] = (img)(_p1##x,_n1##y,z,v), I[31] = (img)(x,_n1##y,z,v), \ 1.544 + I[32] = (img)(_n1##x,_n1##y,z,v), I[33] = (img)(_n2##x,_n1##y,z,v), I[34] = (img)(_n3##x,_n1##y,z,v), I[35] = (img)(_p3##x,_n2##y,z,v), \ 1.545 + I[36] = (img)(_p2##x,_n2##y,z,v), I[37] = (img)(_p1##x,_n2##y,z,v), I[38] = (img)(x,_n2##y,z,v), I[39] = (img)(_n1##x,_n2##y,z,v), \ 1.546 + I[40] = (img)(_n2##x,_n2##y,z,v), I[41] = (img)(_n3##x,_n2##y,z,v), I[42] = (img)(_p3##x,_n3##y,z,v), I[43] = (img)(_p2##x,_n3##y,z,v), \ 1.547 + I[44] = (img)(_p1##x,_n3##y,z,v), I[45] = (img)(x,_n3##y,z,v), I[46] = (img)(_n1##x,_n3##y,z,v), I[47] = (img)(_n2##x,_n3##y,z,v), \ 1.548 + I[48] = (img)(_n3##x,_n3##y,z,v) 1.549 + 1.550 +#define cimg_get8x8(img,x,y,z,v,I) \ 1.551 + I[0] = (img)(_p3##x,_p3##y,z,v), I[1] = (img)(_p2##x,_p3##y,z,v), I[2] = (img)(_p1##x,_p3##y,z,v), I[3] = (img)(x,_p3##y,z,v), \ 1.552 + I[4] = (img)(_n1##x,_p3##y,z,v), I[5] = (img)(_n2##x,_p3##y,z,v), I[6] = (img)(_n3##x,_p3##y,z,v), I[7] = (img)(_n4##x,_p3##y,z,v), \ 1.553 + I[8] = (img)(_p3##x,_p2##y,z,v), I[9] = (img)(_p2##x,_p2##y,z,v), I[10] = (img)(_p1##x,_p2##y,z,v), I[11] = (img)(x,_p2##y,z,v), \ 1.554 + I[12] = (img)(_n1##x,_p2##y,z,v), I[13] = (img)(_n2##x,_p2##y,z,v), I[14] = (img)(_n3##x,_p2##y,z,v), I[15] = (img)(_n4##x,_p2##y,z,v), \ 1.555 + I[16] = (img)(_p3##x,_p1##y,z,v), I[17] = (img)(_p2##x,_p1##y,z,v), I[18] = (img)(_p1##x,_p1##y,z,v), I[19] = (img)(x,_p1##y,z,v), \ 1.556 + I[20] = (img)(_n1##x,_p1##y,z,v), I[21] = (img)(_n2##x,_p1##y,z,v), I[22] = (img)(_n3##x,_p1##y,z,v), I[23] = (img)(_n4##x,_p1##y,z,v), \ 1.557 + I[24] = (img)(_p3##x,y,z,v), I[25] = (img)(_p2##x,y,z,v), I[26] = (img)(_p1##x,y,z,v), I[27] = (img)(x,y,z,v), \ 1.558 + I[28] = (img)(_n1##x,y,z,v), I[29] = (img)(_n2##x,y,z,v), I[30] = (img)(_n3##x,y,z,v), I[31] = (img)(_n4##x,y,z,v), \ 1.559 + I[32] = (img)(_p3##x,_n1##y,z,v), I[33] = (img)(_p2##x,_n1##y,z,v), I[34] = (img)(_p1##x,_n1##y,z,v), I[35] = (img)(x,_n1##y,z,v), \ 1.560 + I[36] = (img)(_n1##x,_n1##y,z,v), I[37] = (img)(_n2##x,_n1##y,z,v), I[38] = (img)(_n3##x,_n1##y,z,v), I[39] = (img)(_n4##x,_n1##y,z,v), \ 1.561 + I[40] = (img)(_p3##x,_n2##y,z,v), I[41] = (img)(_p2##x,_n2##y,z,v), I[42] = (img)(_p1##x,_n2##y,z,v), I[43] = (img)(x,_n2##y,z,v), \ 1.562 + I[44] = (img)(_n1##x,_n2##y,z,v), I[45] = (img)(_n2##x,_n2##y,z,v), I[46] = (img)(_n3##x,_n2##y,z,v), I[47] = (img)(_n4##x,_n2##y,z,v), \ 1.563 + I[48] = (img)(_p3##x,_n3##y,z,v), I[49] = (img)(_p2##x,_n3##y,z,v), I[50] = (img)(_p1##x,_n3##y,z,v), I[51] = (img)(x,_n3##y,z,v), \ 1.564 + I[52] = (img)(_n1##x,_n3##y,z,v), I[53] = (img)(_n2##x,_n3##y,z,v), I[54] = (img)(_n3##x,_n3##y,z,v), I[55] = (img)(_n4##x,_n3##y,z,v), \ 1.565 + I[56] = (img)(_p3##x,_n4##y,z,v), I[57] = (img)(_p2##x,_n4##y,z,v), I[58] = (img)(_p1##x,_n4##y,z,v), I[59] = (img)(x,_n4##y,z,v), \ 1.566 + I[60] = (img)(_n1##x,_n4##y,z,v), I[61] = (img)(_n2##x,_n4##y,z,v), I[62] = (img)(_n3##x,_n4##y,z,v), I[63] = (img)(_n4##x,_n4##y,z,v); 1.567 + 1.568 +#define cimg_get9x9(img,x,y,z,v,I) \ 1.569 + I[0] = (img)(_p4##x,_p4##y,z,v), I[1] = (img)(_p3##x,_p4##y,z,v), I[2] = (img)(_p2##x,_p4##y,z,v), I[3] = (img)(_p1##x,_p4##y,z,v), \ 1.570 + I[4] = (img)(x,_p4##y,z,v), I[5] = (img)(_n1##x,_p4##y,z,v), I[6] = (img)(_n2##x,_p4##y,z,v), I[7] = (img)(_n3##x,_p4##y,z,v), \ 1.571 + I[8] = (img)(_n4##x,_p4##y,z,v), I[9] = (img)(_p4##x,_p3##y,z,v), I[10] = (img)(_p3##x,_p3##y,z,v), I[11] = (img)(_p2##x,_p3##y,z,v), \ 1.572 + I[12] = (img)(_p1##x,_p3##y,z,v), I[13] = (img)(x,_p3##y,z,v), I[14] = (img)(_n1##x,_p3##y,z,v), I[15] = (img)(_n2##x,_p3##y,z,v), \ 1.573 + I[16] = (img)(_n3##x,_p3##y,z,v), I[17] = (img)(_n4##x,_p3##y,z,v), I[18] = (img)(_p4##x,_p2##y,z,v), I[19] = (img)(_p3##x,_p2##y,z,v), \ 1.574 + I[20] = (img)(_p2##x,_p2##y,z,v), I[21] = (img)(_p1##x,_p2##y,z,v), I[22] = (img)(x,_p2##y,z,v), I[23] = (img)(_n1##x,_p2##y,z,v), \ 1.575 + I[24] = (img)(_n2##x,_p2##y,z,v), I[25] = (img)(_n3##x,_p2##y,z,v), I[26] = (img)(_n4##x,_p2##y,z,v), I[27] = (img)(_p4##x,_p1##y,z,v), \ 1.576 + I[28] = (img)(_p3##x,_p1##y,z,v), I[29] = (img)(_p2##x,_p1##y,z,v), I[30] = (img)(_p1##x,_p1##y,z,v), I[31] = (img)(x,_p1##y,z,v), \ 1.577 + I[32] = (img)(_n1##x,_p1##y,z,v), I[33] = (img)(_n2##x,_p1##y,z,v), I[34] = (img)(_n3##x,_p1##y,z,v), I[35] = (img)(_n4##x,_p1##y,z,v), \ 1.578 + I[36] = (img)(_p4##x,y,z,v), I[37] = (img)(_p3##x,y,z,v), I[38] = (img)(_p2##x,y,z,v), I[39] = (img)(_p1##x,y,z,v), \ 1.579 + I[40] = (img)(x,y,z,v), I[41] = (img)(_n1##x,y,z,v), I[42] = (img)(_n2##x,y,z,v), I[43] = (img)(_n3##x,y,z,v), \ 1.580 + I[44] = (img)(_n4##x,y,z,v), I[45] = (img)(_p4##x,_n1##y,z,v), I[46] = (img)(_p3##x,_n1##y,z,v), I[47] = (img)(_p2##x,_n1##y,z,v), \ 1.581 + I[48] = (img)(_p1##x,_n1##y,z,v), I[49] = (img)(x,_n1##y,z,v), I[50] = (img)(_n1##x,_n1##y,z,v), I[51] = (img)(_n2##x,_n1##y,z,v), \ 1.582 + I[52] = (img)(_n3##x,_n1##y,z,v), I[53] = (img)(_n4##x,_n1##y,z,v), I[54] = (img)(_p4##x,_n2##y,z,v), I[55] = (img)(_p3##x,_n2##y,z,v), \ 1.583 + I[56] = (img)(_p2##x,_n2##y,z,v), I[57] = (img)(_p1##x,_n2##y,z,v), I[58] = (img)(x,_n2##y,z,v), I[59] = (img)(_n1##x,_n2##y,z,v), \ 1.584 + I[60] = (img)(_n2##x,_n2##y,z,v), I[61] = (img)(_n3##x,_n2##y,z,v), I[62] = (img)(_n4##x,_n2##y,z,v), I[63] = (img)(_p4##x,_n3##y,z,v), \ 1.585 + I[64] = (img)(_p3##x,_n3##y,z,v), I[65] = (img)(_p2##x,_n3##y,z,v), I[66] = (img)(_p1##x,_n3##y,z,v), I[67] = (img)(x,_n3##y,z,v), \ 1.586 + I[68] = (img)(_n1##x,_n3##y,z,v), I[69] = (img)(_n2##x,_n3##y,z,v), I[70] = (img)(_n3##x,_n3##y,z,v), I[71] = (img)(_n4##x,_n3##y,z,v), \ 1.587 + I[72] = (img)(_p4##x,_n4##y,z,v), I[73] = (img)(_p3##x,_n4##y,z,v), I[74] = (img)(_p2##x,_n4##y,z,v), I[75] = (img)(_p1##x,_n4##y,z,v), \ 1.588 + I[76] = (img)(x,_n4##y,z,v), I[77] = (img)(_n1##x,_n4##y,z,v), I[78] = (img)(_n2##x,_n4##y,z,v), I[79] = (img)(_n3##x,_n4##y,z,v), \ 1.589 + I[80] = (img)(_n4##x,_n4##y,z,v) 1.590 + 1.591 +#define cimg_get2x2x2(img,x,y,z,v,I) \ 1.592 + I[0] = (img)(x,y,z,v), I[1] = (img)(_n1##x,y,z,v), I[2] = (img)(x,_n1##y,z,v), I[3] = (img)(_n1##x,_n1##y,z,v), \ 1.593 + I[4] = (img)(x,y,_n1##z,v), I[5] = (img)(_n1##x,y,_n1##z,v), I[6] = (img)(x,_n1##y,_n1##z,v), I[7] = (img)(_n1##x,_n1##y,_n1##z,v) 1.594 + 1.595 +#define cimg_get3x3x3(img,x,y,z,v,I) \ 1.596 + I[0] = (img)(_p1##x,_p1##y,_p1##z,v), I[1] = (img)(x,_p1##y,_p1##z,v), I[2] = (img)(_n1##x,_p1##y,_p1##z,v), \ 1.597 + I[3] = (img)(_p1##x,y,_p1##z,v), I[4] = (img)(x,y,_p1##z,v), I[5] = (img)(_n1##x,y,_p1##z,v), \ 1.598 + I[6] = (img)(_p1##x,_n1##y,_p1##z,v), I[7] = (img)(x,_n1##y,_p1##z,v), I[8] = (img)(_n1##x,_n1##y,_p1##z,v), \ 1.599 + I[9] = (img)(_p1##x,_p1##y,z,v), I[10] = (img)(x,_p1##y,z,v), I[11] = (img)(_n1##x,_p1##y,z,v), \ 1.600 + I[12] = (img)(_p1##x,y,z,v), I[13] = (img)(x,y,z,v), I[14] = (img)(_n1##x,y,z,v), \ 1.601 + I[15] = (img)(_p1##x,_n1##y,z,v), I[16] = (img)(x,_n1##y,z,v), I[17] = (img)(_n1##x,_n1##y,z,v), \ 1.602 + I[18] = (img)(_p1##x,_p1##y,_n1##z,v), I[19] = (img)(x,_p1##y,_n1##z,v), I[20] = (img)(_n1##x,_p1##y,_n1##z,v), \ 1.603 + I[21] = (img)(_p1##x,y,_n1##z,v), I[22] = (img)(x,y,_n1##z,v), I[23] = (img)(_n1##x,y,_n1##z,v), \ 1.604 + I[24] = (img)(_p1##x,_n1##y,_n1##z,v), I[25] = (img)(x,_n1##y,_n1##z,v), I[26] = (img)(_n1##x,_n1##y,_n1##z,v) 1.605 + 1.606 +// Define various image loops. 1.607 +// 1.608 +// These macros generally avoid the use of iterators, but you are not forced to used them ! 1.609 +// 1.610 +#define cimg_for(img,ptr,T_ptr) for (T_ptr *ptr = (img).data + (img).size(); (ptr--)>(img).data; ) 1.611 +#define cimg_foroff(img,off) for (unsigned int off = 0, _max##off = (unsigned int)(img).size(); off<_max##off; ++off) 1.612 +#define cimglist_for(list,l) for (unsigned int l=0; l<(list).size; ++l) 1.613 +#define cimglist_apply(list,fn) cimglist_for(list,__##fn) (list)[__##fn].fn 1.614 + 1.615 +#define cimg_for1(bound,i) for (int i = 0; i<(int)(bound); ++i) 1.616 +#define cimg_forX(img,x) cimg_for1((img).width,x) 1.617 +#define cimg_forY(img,y) cimg_for1((img).height,y) 1.618 +#define cimg_forZ(img,z) cimg_for1((img).depth,z) 1.619 +#define cimg_forV(img,v) cimg_for1((img).dim,v) 1.620 +#define cimg_forXY(img,x,y) cimg_forY(img,y) cimg_forX(img,x) 1.621 +#define cimg_forXZ(img,x,z) cimg_forZ(img,z) cimg_forX(img,x) 1.622 +#define cimg_forYZ(img,y,z) cimg_forZ(img,z) cimg_forY(img,y) 1.623 +#define cimg_forXV(img,x,v) cimg_forV(img,v) cimg_forX(img,x) 1.624 +#define cimg_forYV(img,y,v) cimg_forV(img,v) cimg_forY(img,y) 1.625 +#define cimg_forZV(img,z,v) cimg_forV(img,v) cimg_forZ(img,z) 1.626 +#define cimg_forXYZ(img,x,y,z) cimg_forZ(img,z) cimg_forXY(img,x,y) 1.627 +#define cimg_forXYV(img,x,y,v) cimg_forV(img,v) cimg_forXY(img,x,y) 1.628 +#define cimg_forXZV(img,x,z,v) cimg_forV(img,v) cimg_forXZ(img,x,z) 1.629 +#define cimg_forYZV(img,y,z,v) cimg_forV(img,v) cimg_forYZ(img,y,z) 1.630 +#define cimg_forXYZV(img,x,y,z,v) cimg_forV(img,v) cimg_forXYZ(img,x,y,z) 1.631 + 1.632 +#define cimg_for_in1(bound,i0,i1,i) \ 1.633 + for (int i = (int)(i0)<0?0:(int)(i0), _max##i = (int)(i1)<(int)(bound)?(int)(i1):(int)(bound)-1; i<=_max##i; ++i) 1.634 +#define cimg_for_inX(img,x0,x1,x) cimg_for_in1((img).width,x0,x1,x) 1.635 +#define cimg_for_inY(img,y0,y1,y) cimg_for_in1((img).height,y0,y1,y) 1.636 +#define cimg_for_inZ(img,z0,z1,z) cimg_for_in1((img).depth,z0,z1,z) 1.637 +#define cimg_for_inV(img,v0,v1,v) cimg_for_in1((img).dim,v0,v1,v) 1.638 +#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) 1.639 +#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) 1.640 +#define cimg_for_inXV(img,x0,v0,x1,v1,x,v) cimg_for_inV(img,v0,v1,v) cimg_for_inX(img,x0,x1,x) 1.641 +#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) 1.642 +#define cimg_for_inYV(img,y0,v0,y1,v1,y,v) cimg_for_inV(img,v0,v1,v) cimg_for_inY(img,y0,y1,y) 1.643 +#define cimg_for_inZV(img,z0,v0,z1,v1,z,v) cimg_for_inV(img,v0,v1,v) cimg_for_inZ(img,z0,z1,z) 1.644 +#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) 1.645 +#define cimg_for_inXYV(img,x0,y0,v0,x1,y1,v1,x,y,v) cimg_for_inV(img,v0,v1,v) cimg_for_inXY(img,x0,y0,x1,y1,x,y) 1.646 +#define cimg_for_inXZV(img,x0,z0,v0,x1,z1,v1,x,z,v) cimg_for_inV(img,v0,v1,v) cimg_for_inXZ(img,x0,z0,x1,z1,x,z) 1.647 +#define cimg_for_inYZV(img,y0,z0,v0,y1,z1,v1,y,z,v) cimg_for_inV(img,v0,v1,v) cimg_for_inYZ(img,y0,z0,y1,z1,y,z) 1.648 +#define cimg_for_inXYZV(img,x0,y0,z0,v0,x1,y1,z1,v1,x,y,z,v) cimg_for_inV(img,v0,v1,v) cimg_for_inXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) 1.649 +#define cimg_for_insideX(img,x,n) cimg_for_inX(img,n,(img).width-1-(n),x) 1.650 +#define cimg_for_insideY(img,y,n) cimg_for_inY(img,n,(img).height-1-(n),y) 1.651 +#define cimg_for_insideZ(img,z,n) cimg_for_inZ(img,n,(img).depth-1-(n),z) 1.652 +#define cimg_for_insideV(img,v,n) cimg_for_inV(img,n,(img).dim-1-(n),v) 1.653 +#define cimg_for_insideXY(img,x,y,n) cimg_for_inXY(img,n,n,(img).width-1-(n),(img).height-1-(n),x,y) 1.654 +#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) 1.655 +#define cimg_for_insideXYZV(img,x,y,z,v,n) cimg_for_inXYZ(img,n,n,n,(img).width-1-(n),(img).height-1-(n),(img).depth-1-(n),x,y,z) 1.656 + 1.657 +#define cimg_for_out1(boundi,i0,i1,i) \ 1.658 + for (int i = (int)(i0)>0?0:(int)(i1)+1; i<(int)(boundi); ++i, i = i==(int)(i0)?(int)(i1)+1:i) 1.659 +#define cimg_for_out2(boundi,boundj,i0,j0,i1,j1,i,j) \ 1.660 + for (int j = 0; j<(int)(boundj); ++j) \ 1.661 + for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j?0:(int)(i0)>0?0:(int)(i1)+1; i<(int)(boundi); \ 1.662 + ++i, i = _n1j?i:(i==(int)(i0)?(int)(i1)+1:i)) 1.663 +#define cimg_for_out3(boundi,boundj,boundk,i0,j0,k0,i1,j1,k1,i,j,k) \ 1.664 + for (int k = 0; k<(int)(boundk); ++k) \ 1.665 + for (int _n1k = (int)(k<(int)(k0) || k>(int)(k1)), j = 0; j<(int)(boundj); ++j) \ 1.666 + for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j || _n1k?0:(int)(i0)>0?0:(int)(i1)+1; i<(int)(boundi); \ 1.667 + ++i, i = _n1j || _n1k?i:(i==(int)(i0)?(int)(i1)+1:i)) 1.668 +#define cimg_for_out4(boundi,boundj,boundk,boundl,i0,j0,k0,l0,i1,j1,k1,l1,i,j,k,l) \ 1.669 + for (int l = 0; l<(int)(boundl); ++l) \ 1.670 + for (int _n1l = (int)(l<(int)(l0) || l>(int)(l1)), k = 0; k<(int)(boundk); ++k) \ 1.671 + for (int _n1k = (int)(k<(int)(k0) || k>(int)(k1)), j = 0; j<(int)(boundj); ++j) \ 1.672 + 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); \ 1.673 + ++i, i = _n1j || _n1k || _n1l?i:(i==(int)(i0)?(int)(i1)+1:i)) 1.674 +#define cimg_for_outX(img,x0,x1,x) cimg_for_out1((img).width,x0,x1,x) 1.675 +#define cimg_for_outY(img,y0,y1,y) cimg_for_out1((img).height,y0,y1,y) 1.676 +#define cimg_for_outZ(img,z0,z1,z) cimg_for_out1((img).depth,z0,z1,z) 1.677 +#define cimg_for_outV(img,v0,v1,v) cimg_for_out1((img).dim,v0,v1,v) 1.678 +#define cimg_for_outXY(img,x0,y0,x1,y1,x,y) cimg_for_out2((img).width,(img).height,x0,y0,x1,y1,x,y) 1.679 +#define cimg_for_outXZ(img,x0,z0,x1,z1,x,z) cimg_for_out2((img).width,(img).depth,x0,z0,x1,z1,x,z) 1.680 +#define cimg_for_outXV(img,x0,v0,x1,v1,x,v) cimg_for_out2((img).width,(img).dim,x0,v0,x1,v1,x,v) 1.681 +#define cimg_for_outYZ(img,y0,z0,y1,z1,y,z) cimg_for_out2((img).height,(img).depth,y0,z0,y1,z1,y,z) 1.682 +#define cimg_for_outYV(img,y0,v0,y1,v1,y,v) cimg_for_out2((img).height,(img).dim,y0,v0,y1,v1,y,v) 1.683 +#define cimg_for_outZV(img,z0,v0,z1,v1,z,v) cimg_for_out2((img).depth,(img).dim,z0,v0,z1,v1,z,v) 1.684 +#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) 1.685 +#define cimg_for_outXYV(img,x0,y0,v0,x1,y1,v1,x,y,v) cimg_for_out3((img).width,(img).height,(img).dim,x0,y0,v0,x1,y1,v1,x,y,v) 1.686 +#define cimg_for_outXZV(img,x0,z0,v0,x1,z1,v1,x,z,v) cimg_for_out3((img).width,(img).depth,(img).dim,x0,z0,v0,x1,z1,v1,x,z,v) 1.687 +#define cimg_for_outYZV(img,y0,z0,v0,y1,z1,v1,y,z,v) cimg_for_out3((img).height,(img).depth,(img).dim,y0,z0,v0,y1,z1,v1,y,z,v) 1.688 +#define cimg_for_outXYZV(img,x0,y0,z0,v0,x1,y1,z1,v1,x,y,z,v) \ 1.689 + cimg_for_out4((img).width,(img).height,(img).depth,(img).dim,x0,y0,z0,v0,x1,y1,z1,v1,x,y,z,v) 1.690 +#define cimg_for_borderX(img,x,n) cimg_for_outX(img,n,(img).width-1-(n),x) 1.691 +#define cimg_for_borderY(img,y,n) cimg_for_outY(img,n,(img).height-1-(n),y) 1.692 +#define cimg_for_borderZ(img,z,n) cimg_for_outZ(img,n,(img).depth-1-(n),z) 1.693 +#define cimg_for_borderV(img,v,n) cimg_for_outV(img,n,(img).dim-1-(n),v) 1.694 +#define cimg_for_borderXY(img,x,y,n) cimg_for_outXY(img,n,n,(img).width-1-(n),(img).height-1-(n),x,y) 1.695 +#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) 1.696 +#define cimg_for_borderXYZV(img,x,y,z,v,n) \ 1.697 + cimg_for_outXYZV(img,n,n,n,n,(img).width-1-(n),(img).height-1-(n),(img).depth-1-(n),(img).dim-1-(n),x,y,z,v) 1.698 + 1.699 +#define cimg_for_spiralXY(img,x,y) \ 1.700 + for (int x = 0, y = 0, _n1##x = 1, _n1##y = (int)((img).width*(img).height); _n1##y; \ 1.701 + --_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) 1.702 + 1.703 +#define cimg_for_lineXY(x,y,x0,y0,x1,y1) \ 1.704 + for (int x = (int)(x0), y = (int)(y0), _sx = 1, _sy = 1, _steep = 0, \ 1.705 + _dx=(x1)>(x0)?(int)(x1)-(int)(x0):(_sx=-1,(int)(x0)-(int)(x1)), \ 1.706 + _dy=(y1)>(y0)?(int)(y1)-(int)(y0):(_sy=-1,(int)(y0)-(int)(y1)), \ 1.707 + _counter = _dx, \ 1.708 + _err = _dx>_dy?(_dy>>1):((_steep=1),(_counter=_dy),(_dx>>1)); \ 1.709 + _counter>=0; \ 1.710 + --_counter, x+=_steep? \ 1.711 + (y+=_sy,(_err-=_dx)<0?_err+=_dy,_sx:0): \ 1.712 + (y+=(_err-=_dy)<0?_err+=_dx,_sy:0,_sx)) 1.713 + 1.714 +#define cimg_for2(bound,i) \ 1.715 + for (int i = 0, _n1##i = 1>=(bound)?(int)(bound)-1:1; \ 1.716 + _n1##i<(int)(bound) || i==--_n1##i; \ 1.717 + ++i, ++_n1##i) 1.718 +#define cimg_for2X(img,x) cimg_for2((img).width,x) 1.719 +#define cimg_for2Y(img,y) cimg_for2((img).height,y) 1.720 +#define cimg_for2Z(img,z) cimg_for2((img).depth,z) 1.721 +#define cimg_for2V(img,v) cimg_for2((img).dim,v) 1.722 +#define cimg_for2XY(img,x,y) cimg_for2Y(img,y) cimg_for2X(img,x) 1.723 +#define cimg_for2XZ(img,x,z) cimg_for2Z(img,z) cimg_for2X(img,x) 1.724 +#define cimg_for2XV(img,x,v) cimg_for2V(img,v) cimg_for2X(img,x) 1.725 +#define cimg_for2YZ(img,y,z) cimg_for2Z(img,z) cimg_for2Y(img,y) 1.726 +#define cimg_for2YV(img,y,v) cimg_for2V(img,v) cimg_for2Y(img,y) 1.727 +#define cimg_for2ZV(img,z,v) cimg_for2V(img,v) cimg_for2Z(img,z) 1.728 +#define cimg_for2XYZ(img,x,y,z) cimg_for2Z(img,z) cimg_for2XY(img,x,y) 1.729 +#define cimg_for2XZV(img,x,z,v) cimg_for2V(img,v) cimg_for2XZ(img,x,z) 1.730 +#define cimg_for2YZV(img,y,z,v) cimg_for2V(img,v) cimg_for2YZ(img,y,z) 1.731 +#define cimg_for2XYZV(img,x,y,z,v) cimg_for2V(img,v) cimg_for2XYZ(img,x,y,z) 1.732 + 1.733 +#define cimg_for_in2(bound,i0,i1,i) \ 1.734 + for (int i = (int)(i0)<0?0:(int)(i0), \ 1.735 + _n1##i = i+1>=(int)(bound)?(int)(bound)-1:i+1; \ 1.736 + i<=(int)(i1) && (_n1##i<(int)(bound) || i==--_n1##i); \ 1.737 + ++i, ++_n1##i) 1.738 +#define cimg_for_in2X(img,x0,x1,x) cimg_for_in2((img).width,x0,x1,x) 1.739 +#define cimg_for_in2Y(img,y0,y1,y) cimg_for_in2((img).height,y0,y1,y) 1.740 +#define cimg_for_in2Z(img,z0,z1,z) cimg_for_in2((img).depth,z0,z1,z) 1.741 +#define cimg_for_in2V(img,v0,v1,v) cimg_for_in2((img).dim,v0,v1,v) 1.742 +#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) 1.743 +#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) 1.744 +#define cimg_for_in2XV(img,x0,v0,x1,v1,x,v) cimg_for_in2V(img,v0,v1,v) cimg_for_in2X(img,x0,x1,x) 1.745 +#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) 1.746 +#define cimg_for_in2YV(img,y0,v0,y1,v1,y,v) cimg_for_in2V(img,v0,v1,v) cimg_for_in2Y(img,y0,y1,y) 1.747 +#define cimg_for_in2ZV(img,z0,v0,z1,v1,z,v) cimg_for_in2V(img,v0,v1,v) cimg_for_in2Z(img,z0,z1,z) 1.748 +#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) 1.749 +#define cimg_for_in2XZV(img,x0,z0,v0,x1,y1,v1,x,z,v) cimg_for_in2V(img,v0,v1,v) cimg_for_in2XZ(img,x0,y0,x1,y1,x,z) 1.750 +#define cimg_for_in2YZV(img,y0,z0,v0,y1,z1,v1,y,z,v) cimg_for_in2V(img,v0,v1,v) cimg_for_in2YZ(img,y0,z0,y1,z1,y,z) 1.751 +#define cimg_for_in2XYZV(img,x0,y0,z0,v0,x1,y1,z1,v1,x,y,z,v) cimg_for_in2V(img,v0,v1,v) cimg_for_in2XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) 1.752 + 1.753 +#define cimg_for3(bound,i) \ 1.754 + for (int i = 0, _p1##i = 0, \ 1.755 + _n1##i = 1>=(bound)?(int)(bound)-1:1; \ 1.756 + _n1##i<(int)(bound) || i==--_n1##i; \ 1.757 + _p1##i = i++, ++_n1##i) 1.758 +#define cimg_for3X(img,x) cimg_for3((img).width,x) 1.759 +#define cimg_for3Y(img,y) cimg_for3((img).height,y) 1.760 +#define cimg_for3Z(img,z) cimg_for3((img).depth,z) 1.761 +#define cimg_for3V(img,v) cimg_for3((img).dim,v) 1.762 +#define cimg_for3XY(img,x,y) cimg_for3Y(img,y) cimg_for3X(img,x) 1.763 +#define cimg_for3XZ(img,x,z) cimg_for3Z(img,z) cimg_for3X(img,x) 1.764 +#define cimg_for3XV(img,x,v) cimg_for3V(img,v) cimg_for3X(img,x) 1.765 +#define cimg_for3YZ(img,y,z) cimg_for3Z(img,z) cimg_for3Y(img,y) 1.766 +#define cimg_for3YV(img,y,v) cimg_for3V(img,v) cimg_for3Y(img,y) 1.767 +#define cimg_for3ZV(img,z,v) cimg_for3V(img,v) cimg_for3Z(img,z) 1.768 +#define cimg_for3XYZ(img,x,y,z) cimg_for3Z(img,z) cimg_for3XY(img,x,y) 1.769 +#define cimg_for3XZV(img,x,z,v) cimg_for3V(img,v) cimg_for3XZ(img,x,z) 1.770 +#define cimg_for3YZV(img,y,z,v) cimg_for3V(img,v) cimg_for3YZ(img,y,z) 1.771 +#define cimg_for3XYZV(img,x,y,z,v) cimg_for3V(img,v) cimg_for3XYZ(img,x,y,z) 1.772 + 1.773 +#define cimg_for_in3(bound,i0,i1,i) \ 1.774 + for (int i = (int)(i0)<0?0:(int)(i0), \ 1.775 + _p1##i = i-1<0?0:i-1, \ 1.776 + _n1##i = i+1>=(int)(bound)?(int)(bound)-1:i+1; \ 1.777 + i<=(int)(i1) && (_n1##i<(int)(bound) || i==--_n1##i); \ 1.778 + _p1##i = i++, ++_n1##i) 1.779 +#define cimg_for_in3X(img,x0,x1,x) cimg_for_in3((img).width,x0,x1,x) 1.780 +#define cimg_for_in3Y(img,y0,y1,y) cimg_for_in3((img).height,y0,y1,y) 1.781 +#define cimg_for_in3Z(img,z0,z1,z) cimg_for_in3((img).depth,z0,z1,z) 1.782 +#define cimg_for_in3V(img,v0,v1,v) cimg_for_in3((img).dim,v0,v1,v) 1.783 +#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) 1.784 +#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) 1.785 +#define cimg_for_in3XV(img,x0,v0,x1,v1,x,v) cimg_for_in3V(img,v0,v1,v) cimg_for_in3X(img,x0,x1,x) 1.786 +#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) 1.787 +#define cimg_for_in3YV(img,y0,v0,y1,v1,y,v) cimg_for_in3V(img,v0,v1,v) cimg_for_in3Y(img,y0,y1,y) 1.788 +#define cimg_for_in3ZV(img,z0,v0,z1,v1,z,v) cimg_for_in3V(img,v0,v1,v) cimg_for_in3Z(img,z0,z1,z) 1.789 +#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) 1.790 +#define cimg_for_in3XZV(img,x0,z0,v0,x1,y1,v1,x,z,v) cimg_for_in3V(img,v0,v1,v) cimg_for_in3XZ(img,x0,y0,x1,y1,x,z) 1.791 +#define cimg_for_in3YZV(img,y0,z0,v0,y1,z1,v1,y,z,v) cimg_for_in3V(img,v0,v1,v) cimg_for_in3YZ(img,y0,z0,y1,z1,y,z) 1.792 +#define cimg_for_in3XYZV(img,x0,y0,z0,v0,x1,y1,z1,v1,x,y,z,v) cimg_for_in3V(img,v0,v1,v) cimg_for_in3XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) 1.793 + 1.794 +#define cimg_for4(bound,i) \ 1.795 + for (int i = 0, _p1##i = 0, _n1##i = 1>=(bound)?(int)(bound)-1:1, \ 1.796 + _n2##i = 2>=(bound)?(int)(bound)-1:2; \ 1.797 + _n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i); \ 1.798 + _p1##i = i++, ++_n1##i, ++_n2##i) 1.799 +#define cimg_for4X(img,x) cimg_for4((img).width,x) 1.800 +#define cimg_for4Y(img,y) cimg_for4((img).height,y) 1.801 +#define cimg_for4Z(img,z) cimg_for4((img).depth,z) 1.802 +#define cimg_for4V(img,v) cimg_for4((img).dim,v) 1.803 +#define cimg_for4XY(img,x,y) cimg_for4Y(img,y) cimg_for4X(img,x) 1.804 +#define cimg_for4XZ(img,x,z) cimg_for4Z(img,z) cimg_for4X(img,x) 1.805 +#define cimg_for4XV(img,x,v) cimg_for4V(img,v) cimg_for4X(img,x) 1.806 +#define cimg_for4YZ(img,y,z) cimg_for4Z(img,z) cimg_for4Y(img,y) 1.807 +#define cimg_for4YV(img,y,v) cimg_for4V(img,v) cimg_for4Y(img,y) 1.808 +#define cimg_for4ZV(img,z,v) cimg_for4V(img,v) cimg_for4Z(img,z) 1.809 +#define cimg_for4XYZ(img,x,y,z) cimg_for4Z(img,z) cimg_for4XY(img,x,y) 1.810 +#define cimg_for4XZV(img,x,z,v) cimg_for4V(img,v) cimg_for4XZ(img,x,z) 1.811 +#define cimg_for4YZV(img,y,z,v) cimg_for4V(img,v) cimg_for4YZ(img,y,z) 1.812 +#define cimg_for4XYZV(img,x,y,z,v) cimg_for4V(img,v) cimg_for4XYZ(img,x,y,z) 1.813 + 1.814 +#define cimg_for_in4(bound,i0,i1,i) \ 1.815 + for (int i = (int)(i0)<0?0:(int)(i0), \ 1.816 + _p1##i = i-1<0?0:i-1, \ 1.817 + _n1##i = i+1>=(int)(bound)?(int)(bound)-1:i+1, \ 1.818 + _n2##i = i+2>=(int)(bound)?(int)(bound)-1:i+2; \ 1.819 + i<=(int)(i1) && (_n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i)); \ 1.820 + _p1##i = i++, ++_n1##i, ++_n2##i) 1.821 +#define cimg_for_in4X(img,x0,x1,x) cimg_for_in4((img).width,x0,x1,x) 1.822 +#define cimg_for_in4Y(img,y0,y1,y) cimg_for_in4((img).height,y0,y1,y) 1.823 +#define cimg_for_in4Z(img,z0,z1,z) cimg_for_in4((img).depth,z0,z1,z) 1.824 +#define cimg_for_in4V(img,v0,v1,v) cimg_for_in4((img).dim,v0,v1,v) 1.825 +#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) 1.826 +#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) 1.827 +#define cimg_for_in4XV(img,x0,v0,x1,v1,x,v) cimg_for_in4V(img,v0,v1,v) cimg_for_in4X(img,x0,x1,x) 1.828 +#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) 1.829 +#define cimg_for_in4YV(img,y0,v0,y1,v1,y,v) cimg_for_in4V(img,v0,v1,v) cimg_for_in4Y(img,y0,y1,y) 1.830 +#define cimg_for_in4ZV(img,z0,v0,z1,v1,z,v) cimg_for_in4V(img,v0,v1,v) cimg_for_in4Z(img,z0,z1,z) 1.831 +#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) 1.832 +#define cimg_for_in4XZV(img,x0,z0,v0,x1,y1,v1,x,z,v) cimg_for_in4V(img,v0,v1,v) cimg_for_in4XZ(img,x0,y0,x1,y1,x,z) 1.833 +#define cimg_for_in4YZV(img,y0,z0,v0,y1,z1,v1,y,z,v) cimg_for_in4V(img,v0,v1,v) cimg_for_in4YZ(img,y0,z0,y1,z1,y,z) 1.834 +#define cimg_for_in4XYZV(img,x0,y0,z0,v0,x1,y1,z1,v1,x,y,z,v) cimg_for_in4V(img,v0,v1,v) cimg_for_in4XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) 1.835 + 1.836 +#define cimg_for5(bound,i) \ 1.837 + for (int i = 0, _p2##i = 0, _p1##i = 0, \ 1.838 + _n1##i = 1>=(bound)?(int)(bound)-1:1, \ 1.839 + _n2##i = 2>=(bound)?(int)(bound)-1:2; \ 1.840 + _n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i); \ 1.841 + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i) 1.842 +#define cimg_for5X(img,x) cimg_for5((img).width,x) 1.843 +#define cimg_for5Y(img,y) cimg_for5((img).height,y) 1.844 +#define cimg_for5Z(img,z) cimg_for5((img).depth,z) 1.845 +#define cimg_for5V(img,v) cimg_for5((img).dim,v) 1.846 +#define cimg_for5XY(img,x,y) cimg_for5Y(img,y) cimg_for5X(img,x) 1.847 +#define cimg_for5XZ(img,x,z) cimg_for5Z(img,z) cimg_for5X(img,x) 1.848 +#define cimg_for5XV(img,x,v) cimg_for5V(img,v) cimg_for5X(img,x) 1.849 +#define cimg_for5YZ(img,y,z) cimg_for5Z(img,z) cimg_for5Y(img,y) 1.850 +#define cimg_for5YV(img,y,v) cimg_for5V(img,v) cimg_for5Y(img,y) 1.851 +#define cimg_for5ZV(img,z,v) cimg_for5V(img,v) cimg_for5Z(img,z) 1.852 +#define cimg_for5XYZ(img,x,y,z) cimg_for5Z(img,z) cimg_for5XY(img,x,y) 1.853 +#define cimg_for5XZV(img,x,z,v) cimg_for5V(img,v) cimg_for5XZ(img,x,z) 1.854 +#define cimg_for5YZV(img,y,z,v) cimg_for5V(img,v) cimg_for5YZ(img,y,z) 1.855 +#define cimg_for5XYZV(img,x,y,z,v) cimg_for5V(img,v) cimg_for5XYZ(img,x,y,z) 1.856 + 1.857 +#define cimg_for_in5(bound,i0,i1,i) \ 1.858 + for (int i = (int)(i0)<0?0:(int)(i0), \ 1.859 + _p2##i = i-2<0?0:i-2, \ 1.860 + _p1##i = i-1<0?0:i-1, \ 1.861 + _n1##i = i+1>=(int)(bound)?(int)(bound)-1:i+1, \ 1.862 + _n2##i = i+2>=(int)(bound)?(int)(bound)-1:i+2; \ 1.863 + i<=(int)(i1) && (_n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i)); \ 1.864 + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i) 1.865 +#define cimg_for_in5X(img,x0,x1,x) cimg_for_in5((img).width,x0,x1,x) 1.866 +#define cimg_for_in5Y(img,y0,y1,y) cimg_for_in5((img).height,y0,y1,y) 1.867 +#define cimg_for_in5Z(img,z0,z1,z) cimg_for_in5((img).depth,z0,z1,z) 1.868 +#define cimg_for_in5V(img,v0,v1,v) cimg_for_in5((img).dim,v0,v1,v) 1.869 +#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) 1.870 +#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) 1.871 +#define cimg_for_in5XV(img,x0,v0,x1,v1,x,v) cimg_for_in5V(img,v0,v1,v) cimg_for_in5X(img,x0,x1,x) 1.872 +#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) 1.873 +#define cimg_for_in5YV(img,y0,v0,y1,v1,y,v) cimg_for_in5V(img,v0,v1,v) cimg_for_in5Y(img,y0,y1,y) 1.874 +#define cimg_for_in5ZV(img,z0,v0,z1,v1,z,v) cimg_for_in5V(img,v0,v1,v) cimg_for_in5Z(img,z0,z1,z) 1.875 +#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) 1.876 +#define cimg_for_in5XZV(img,x0,z0,v0,x1,y1,v1,x,z,v) cimg_for_in5V(img,v0,v1,v) cimg_for_in5XZ(img,x0,y0,x1,y1,x,z) 1.877 +#define cimg_for_in5YZV(img,y0,z0,v0,y1,z1,v1,y,z,v) cimg_for_in5V(img,v0,v1,v) cimg_for_in5YZ(img,y0,z0,y1,z1,y,z) 1.878 +#define cimg_for_in5XYZV(img,x0,y0,z0,v0,x1,y1,z1,v1,x,y,z,v) cimg_for_in5V(img,v0,v1,v) cimg_for_in5XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) 1.879 + 1.880 +#define cimg_for6(bound,i) \ 1.881 + for (int i = 0, _p2##i = 0, _p1##i = 0, \ 1.882 + _n1##i = 1>=(bound)?(int)(bound)-1:1, \ 1.883 + _n2##i = 2>=(bound)?(int)(bound)-1:2, \ 1.884 + _n3##i = 3>=(bound)?(int)(bound)-1:3; \ 1.885 + _n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i); \ 1.886 + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) 1.887 +#define cimg_for6X(img,x) cimg_for6((img).width,x) 1.888 +#define cimg_for6Y(img,y) cimg_for6((img).height,y) 1.889 +#define cimg_for6Z(img,z) cimg_for6((img).depth,z) 1.890 +#define cimg_for6V(img,v) cimg_for6((img).dim,v) 1.891 +#define cimg_for6XY(img,x,y) cimg_for6Y(img,y) cimg_for6X(img,x) 1.892 +#define cimg_for6XZ(img,x,z) cimg_for6Z(img,z) cimg_for6X(img,x) 1.893 +#define cimg_for6XV(img,x,v) cimg_for6V(img,v) cimg_for6X(img,x) 1.894 +#define cimg_for6YZ(img,y,z) cimg_for6Z(img,z) cimg_for6Y(img,y) 1.895 +#define cimg_for6YV(img,y,v) cimg_for6V(img,v) cimg_for6Y(img,y) 1.896 +#define cimg_for6ZV(img,z,v) cimg_for6V(img,v) cimg_for6Z(img,z) 1.897 +#define cimg_for6XYZ(img,x,y,z) cimg_for6Z(img,z) cimg_for6XY(img,x,y) 1.898 +#define cimg_for6XZV(img,x,z,v) cimg_for6V(img,v) cimg_for6XZ(img,x,z) 1.899 +#define cimg_for6YZV(img,y,z,v) cimg_for6V(img,v) cimg_for6YZ(img,y,z) 1.900 +#define cimg_for6XYZV(img,x,y,z,v) cimg_for6V(img,v) cimg_for6XYZ(img,x,y,z) 1.901 + 1.902 +#define cimg_for_in6(bound,i0,i1,i) \ 1.903 + for (int i = (int)(i0)<0?0:(int)(i0), \ 1.904 + _p2##i = i-2<0?0:i-2, \ 1.905 + _p1##i = i-1<0?0:i-1, \ 1.906 + _n1##i = i+1>=(int)(bound)?(int)(bound)-1:i+1, \ 1.907 + _n2##i = i+2>=(int)(bound)?(int)(bound)-1:i+2, \ 1.908 + _n3##i = i+3>=(int)(bound)?(int)(bound)-1:i+3; \ 1.909 + i<=(int)(i1) && (_n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i)); \ 1.910 + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) 1.911 +#define cimg_for_in6X(img,x0,x1,x) cimg_for_in6((img).width,x0,x1,x) 1.912 +#define cimg_for_in6Y(img,y0,y1,y) cimg_for_in6((img).height,y0,y1,y) 1.913 +#define cimg_for_in6Z(img,z0,z1,z) cimg_for_in6((img).depth,z0,z1,z) 1.914 +#define cimg_for_in6V(img,v0,v1,v) cimg_for_in6((img).dim,v0,v1,v) 1.915 +#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) 1.916 +#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) 1.917 +#define cimg_for_in6XV(img,x0,v0,x1,v1,x,v) cimg_for_in6V(img,v0,v1,v) cimg_for_in6X(img,x0,x1,x) 1.918 +#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) 1.919 +#define cimg_for_in6YV(img,y0,v0,y1,v1,y,v) cimg_for_in6V(img,v0,v1,v) cimg_for_in6Y(img,y0,y1,y) 1.920 +#define cimg_for_in6ZV(img,z0,v0,z1,v1,z,v) cimg_for_in6V(img,v0,v1,v) cimg_for_in6Z(img,z0,z1,z) 1.921 +#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) 1.922 +#define cimg_for_in6XZV(img,x0,z0,v0,x1,y1,v1,x,z,v) cimg_for_in6V(img,v0,v1,v) cimg_for_in6XZ(img,x0,y0,x1,y1,x,z) 1.923 +#define cimg_for_in6YZV(img,y0,z0,v0,y1,z1,v1,y,z,v) cimg_for_in6V(img,v0,v1,v) cimg_for_in6YZ(img,y0,z0,y1,z1,y,z) 1.924 +#define cimg_for_in6XYZV(img,x0,y0,z0,v0,x1,y1,z1,v1,x,y,z,v) cimg_for_in6V(img,v0,v1,v) cimg_for_in6XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) 1.925 + 1.926 +#define cimg_for7(bound,i) \ 1.927 + for (int i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \ 1.928 + _n1##i = 1>=(bound)?(int)(bound)-1:1, \ 1.929 + _n2##i = 2>=(bound)?(int)(bound)-1:2, \ 1.930 + _n3##i = 3>=(bound)?(int)(bound)-1:3; \ 1.931 + _n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i); \ 1.932 + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) 1.933 +#define cimg_for7X(img,x) cimg_for7((img).width,x) 1.934 +#define cimg_for7Y(img,y) cimg_for7((img).height,y) 1.935 +#define cimg_for7Z(img,z) cimg_for7((img).depth,z) 1.936 +#define cimg_for7V(img,v) cimg_for7((img).dim,v) 1.937 +#define cimg_for7XY(img,x,y) cimg_for7Y(img,y) cimg_for7X(img,x) 1.938 +#define cimg_for7XZ(img,x,z) cimg_for7Z(img,z) cimg_for7X(img,x) 1.939 +#define cimg_for7XV(img,x,v) cimg_for7V(img,v) cimg_for7X(img,x) 1.940 +#define cimg_for7YZ(img,y,z) cimg_for7Z(img,z) cimg_for7Y(img,y) 1.941 +#define cimg_for7YV(img,y,v) cimg_for7V(img,v) cimg_for7Y(img,y) 1.942 +#define cimg_for7ZV(img,z,v) cimg_for7V(img,v) cimg_for7Z(img,z) 1.943 +#define cimg_for7XYZ(img,x,y,z) cimg_for7Z(img,z) cimg_for7XY(img,x,y) 1.944 +#define cimg_for7XZV(img,x,z,v) cimg_for7V(img,v) cimg_for7XZ(img,x,z) 1.945 +#define cimg_for7YZV(img,y,z,v) cimg_for7V(img,v) cimg_for7YZ(img,y,z) 1.946 +#define cimg_for7XYZV(img,x,y,z,v) cimg_for7V(img,v) cimg_for7XYZ(img,x,y,z) 1.947 + 1.948 +#define cimg_for_in7(bound,i0,i1,i) \ 1.949 + for (int i = (int)(i0)<0?0:(int)(i0), \ 1.950 + _p3##i = i-3<0?0:i-3, \ 1.951 + _p2##i = i-2<0?0:i-2, \ 1.952 + _p1##i = i-1<0?0:i-1, \ 1.953 + _n1##i = i+1>=(int)(bound)?(int)(bound)-1:i+1, \ 1.954 + _n2##i = i+2>=(int)(bound)?(int)(bound)-1:i+2, \ 1.955 + _n3##i = i+3>=(int)(bound)?(int)(bound)-1:i+3; \ 1.956 + i<=(int)(i1) && (_n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i)); \ 1.957 + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) 1.958 +#define cimg_for_in7X(img,x0,x1,x) cimg_for_in7((img).width,x0,x1,x) 1.959 +#define cimg_for_in7Y(img,y0,y1,y) cimg_for_in7((img).height,y0,y1,y) 1.960 +#define cimg_for_in7Z(img,z0,z1,z) cimg_for_in7((img).depth,z0,z1,z) 1.961 +#define cimg_for_in7V(img,v0,v1,v) cimg_for_in7((img).dim,v0,v1,v) 1.962 +#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) 1.963 +#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) 1.964 +#define cimg_for_in7XV(img,x0,v0,x1,v1,x,v) cimg_for_in7V(img,v0,v1,v) cimg_for_in7X(img,x0,x1,x) 1.965 +#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) 1.966 +#define cimg_for_in7YV(img,y0,v0,y1,v1,y,v) cimg_for_in7V(img,v0,v1,v) cimg_for_in7Y(img,y0,y1,y) 1.967 +#define cimg_for_in7ZV(img,z0,v0,z1,v1,z,v) cimg_for_in7V(img,v0,v1,v) cimg_for_in7Z(img,z0,z1,z) 1.968 +#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) 1.969 +#define cimg_for_in7XZV(img,x0,z0,v0,x1,y1,v1,x,z,v) cimg_for_in7V(img,v0,v1,v) cimg_for_in7XZ(img,x0,y0,x1,y1,x,z) 1.970 +#define cimg_for_in7YZV(img,y0,z0,v0,y1,z1,v1,y,z,v) cimg_for_in7V(img,v0,v1,v) cimg_for_in7YZ(img,y0,z0,y1,z1,y,z) 1.971 +#define cimg_for_in7XYZV(img,x0,y0,z0,v0,x1,y1,z1,v1,x,y,z,v) cimg_for_in7V(img,v0,v1,v) cimg_for_in7XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) 1.972 + 1.973 +#define cimg_for8(bound,i) \ 1.974 + for (int i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \ 1.975 + _n1##i = 1>=(bound)?(int)(bound)-1:1, \ 1.976 + _n2##i = 2>=(bound)?(int)(bound)-1:2, \ 1.977 + _n3##i = 3>=(bound)?(int)(bound)-1:3, \ 1.978 + _n4##i = 4>=(bound)?(int)(bound)-1:4; \ 1.979 + _n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ 1.980 + i==(_n4##i = _n3##i = _n2##i = --_n1##i); \ 1.981 + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) 1.982 +#define cimg_for8X(img,x) cimg_for8((img).width,x) 1.983 +#define cimg_for8Y(img,y) cimg_for8((img).height,y) 1.984 +#define cimg_for8Z(img,z) cimg_for8((img).depth,z) 1.985 +#define cimg_for8V(img,v) cimg_for8((img).dim,v) 1.986 +#define cimg_for8XY(img,x,y) cimg_for8Y(img,y) cimg_for8X(img,x) 1.987 +#define cimg_for8XZ(img,x,z) cimg_for8Z(img,z) cimg_for8X(img,x) 1.988 +#define cimg_for8XV(img,x,v) cimg_for8V(img,v) cimg_for8X(img,x) 1.989 +#define cimg_for8YZ(img,y,z) cimg_for8Z(img,z) cimg_for8Y(img,y) 1.990 +#define cimg_for8YV(img,y,v) cimg_for8V(img,v) cimg_for8Y(img,y) 1.991 +#define cimg_for8ZV(img,z,v) cimg_for8V(img,v) cimg_for8Z(img,z) 1.992 +#define cimg_for8XYZ(img,x,y,z) cimg_for8Z(img,z) cimg_for8XY(img,x,y) 1.993 +#define cimg_for8XZV(img,x,z,v) cimg_for8V(img,v) cimg_for8XZ(img,x,z) 1.994 +#define cimg_for8YZV(img,y,z,v) cimg_for8V(img,v) cimg_for8YZ(img,y,z) 1.995 +#define cimg_for8XYZV(img,x,y,z,v) cimg_for8V(img,v) cimg_for8XYZ(img,x,y,z) 1.996 + 1.997 +#define cimg_for_in8(bound,i0,i1,i) \ 1.998 + for (int i = (int)(i0)<0?0:(int)(i0), \ 1.999 + _p3##i = i-3<0?0:i-3, \ 1.1000 + _p2##i = i-2<0?0:i-2, \ 1.1001 + _p1##i = i-1<0?0:i-1, \ 1.1002 + _n1##i = i+1>=(int)(bound)?(int)(bound)-1:i+1, \ 1.1003 + _n2##i = i+2>=(int)(bound)?(int)(bound)-1:i+2, \ 1.1004 + _n3##i = i+3>=(int)(bound)?(int)(bound)-1:i+3, \ 1.1005 + _n4##i = i+4>=(int)(bound)?(int)(bound)-1:i+4; \ 1.1006 + i<=(int)(i1) && (_n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ 1.1007 + i==(_n4##i = _n3##i = _n2##i = --_n1##i)); \ 1.1008 + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) 1.1009 +#define cimg_for_in8X(img,x0,x1,x) cimg_for_in8((img).width,x0,x1,x) 1.1010 +#define cimg_for_in8Y(img,y0,y1,y) cimg_for_in8((img).height,y0,y1,y) 1.1011 +#define cimg_for_in8Z(img,z0,z1,z) cimg_for_in8((img).depth,z0,z1,z) 1.1012 +#define cimg_for_in8V(img,v0,v1,v) cimg_for_in8((img).dim,v0,v1,v) 1.1013 +#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) 1.1014 +#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) 1.1015 +#define cimg_for_in8XV(img,x0,v0,x1,v1,x,v) cimg_for_in8V(img,v0,v1,v) cimg_for_in8X(img,x0,x1,x) 1.1016 +#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) 1.1017 +#define cimg_for_in8YV(img,y0,v0,y1,v1,y,v) cimg_for_in8V(img,v0,v1,v) cimg_for_in8Y(img,y0,y1,y) 1.1018 +#define cimg_for_in8ZV(img,z0,v0,z1,v1,z,v) cimg_for_in8V(img,v0,v1,v) cimg_for_in8Z(img,z0,z1,z) 1.1019 +#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) 1.1020 +#define cimg_for_in8XZV(img,x0,z0,v0,x1,y1,v1,x,z,v) cimg_for_in8V(img,v0,v1,v) cimg_for_in8XZ(img,x0,y0,x1,y1,x,z) 1.1021 +#define cimg_for_in8YZV(img,y0,z0,v0,y1,z1,v1,y,z,v) cimg_for_in8V(img,v0,v1,v) cimg_for_in8YZ(img,y0,z0,y1,z1,y,z) 1.1022 +#define cimg_for_in8XYZV(img,x0,y0,z0,v0,x1,y1,z1,v1,x,y,z,v) cimg_for_in8V(img,v0,v1,v) cimg_for_in8XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) 1.1023 + 1.1024 +#define cimg_for9(bound,i) \ 1.1025 + for (int i = 0, _p4##i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \ 1.1026 + _n1##i = 1>=(int)(bound)?(int)(bound)-1:1, \ 1.1027 + _n2##i = 2>=(int)(bound)?(int)(bound)-1:2, \ 1.1028 + _n3##i = 3>=(int)(bound)?(int)(bound)-1:3, \ 1.1029 + _n4##i = 4>=(int)(bound)?(int)(bound)-1:4; \ 1.1030 + _n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ 1.1031 + i==(_n4##i = _n3##i = _n2##i = --_n1##i); \ 1.1032 + _p4##i = _p3##i, _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) 1.1033 +#define cimg_for9X(img,x) cimg_for9((img).width,x) 1.1034 +#define cimg_for9Y(img,y) cimg_for9((img).height,y) 1.1035 +#define cimg_for9Z(img,z) cimg_for9((img).depth,z) 1.1036 +#define cimg_for9V(img,v) cimg_for9((img).dim,v) 1.1037 +#define cimg_for9XY(img,x,y) cimg_for9Y(img,y) cimg_for9X(img,x) 1.1038 +#define cimg_for9XZ(img,x,z) cimg_for9Z(img,z) cimg_for9X(img,x) 1.1039 +#define cimg_for9XV(img,x,v) cimg_for9V(img,v) cimg_for9X(img,x) 1.1040 +#define cimg_for9YZ(img,y,z) cimg_for9Z(img,z) cimg_for9Y(img,y) 1.1041 +#define cimg_for9YV(img,y,v) cimg_for9V(img,v) cimg_for9Y(img,y) 1.1042 +#define cimg_for9ZV(img,z,v) cimg_for9V(img,v) cimg_for9Z(img,z) 1.1043 +#define cimg_for9XYZ(img,x,y,z) cimg_for9Z(img,z) cimg_for9XY(img,x,y) 1.1044 +#define cimg_for9XZV(img,x,z,v) cimg_for9V(img,v) cimg_for9XZ(img,x,z) 1.1045 +#define cimg_for9YZV(img,y,z,v) cimg_for9V(img,v) cimg_for9YZ(img,y,z) 1.1046 +#define cimg_for9XYZV(img,x,y,z,v) cimg_for9V(img,v) cimg_for9XYZ(img,x,y,z) 1.1047 + 1.1048 +#define cimg_for_in9(bound,i0,i1,i) \ 1.1049 + for (int i = (int)(i0)<0?0:(int)(i0), \ 1.1050 + _p4##i = i-4<0?0:i-4, \ 1.1051 + _p3##i = i-3<0?0:i-3, \ 1.1052 + _p2##i = i-2<0?0:i-2, \ 1.1053 + _p1##i = i-1<0?0:i-1, \ 1.1054 + _n1##i = i+1>=(int)(bound)?(int)(bound)-1:i+1, \ 1.1055 + _n2##i = i+2>=(int)(bound)?(int)(bound)-1:i+2, \ 1.1056 + _n3##i = i+3>=(int)(bound)?(int)(bound)-1:i+3, \ 1.1057 + _n4##i = i+4>=(int)(bound)?(int)(bound)-1:i+4; \ 1.1058 + i<=(int)(i1) && (_n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ 1.1059 + i==(_n4##i = _n3##i = _n2##i = --_n1##i)); \ 1.1060 + _p4##i = _p3##i, _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) 1.1061 +#define cimg_for_in9X(img,x0,x1,x) cimg_for_in9((img).width,x0,x1,x) 1.1062 +#define cimg_for_in9Y(img,y0,y1,y) cimg_for_in9((img).height,y0,y1,y) 1.1063 +#define cimg_for_in9Z(img,z0,z1,z) cimg_for_in9((img).depth,z0,z1,z) 1.1064 +#define cimg_for_in9V(img,v0,v1,v) cimg_for_in9((img).dim,v0,v1,v) 1.1065 +#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) 1.1066 +#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) 1.1067 +#define cimg_for_in9XV(img,x0,v0,x1,v1,x,v) cimg_for_in9V(img,v0,v1,v) cimg_for_in9X(img,x0,x1,x) 1.1068 +#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) 1.1069 +#define cimg_for_in9YV(img,y0,v0,y1,v1,y,v) cimg_for_in9V(img,v0,v1,v) cimg_for_in9Y(img,y0,y1,y) 1.1070 +#define cimg_for_in9ZV(img,z0,v0,z1,v1,z,v) cimg_for_in9V(img,v0,v1,v) cimg_for_in9Z(img,z0,z1,z) 1.1071 +#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) 1.1072 +#define cimg_for_in9XZV(img,x0,z0,v0,x1,y1,v1,x,z,v) cimg_for_in9V(img,v0,v1,v) cimg_for_in9XZ(img,x0,y0,x1,y1,x,z) 1.1073 +#define cimg_for_in9YZV(img,y0,z0,v0,y1,z1,v1,y,z,v) cimg_for_in9V(img,v0,v1,v) cimg_for_in9YZ(img,y0,z0,y1,z1,y,z) 1.1074 +#define cimg_for_in9XYZV(img,x0,y0,z0,v0,x1,y1,z1,v1,x,y,z,v) cimg_for_in9V(img,v0,v1,v) cimg_for_in9XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) 1.1075 + 1.1076 +#define cimg_for2x2(img,x,y,z,v,I) \ 1.1077 + cimg_for2((img).height,y) for (int x = 0, \ 1.1078 + _n1##x = (int)( \ 1.1079 + (I[0] = (img)(0,y,z,v)), \ 1.1080 + (I[2] = (img)(0,_n1##y,z,v)), \ 1.1081 + 1>=(img).width?(int)((img).width)-1:1); \ 1.1082 + (_n1##x<(int)((img).width) && ( \ 1.1083 + (I[1] = (img)(_n1##x,y,z,v)), \ 1.1084 + (I[3] = (img)(_n1##x,_n1##y,z,v)),1)) || \ 1.1085 + x==--_n1##x; \ 1.1086 + I[0] = I[1], \ 1.1087 + I[2] = I[3], \ 1.1088 + ++x, ++_n1##x) 1.1089 + 1.1090 +#define cimg_for_in2x2(img,x0,y0,x1,y1,x,y,z,v,I) \ 1.1091 + cimg_for_in2((img).height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ 1.1092 + _n1##x = (int)( \ 1.1093 + (I[0] = (img)(x,y,z,v)), \ 1.1094 + (I[2] = (img)(x,_n1##y,z,v)), \ 1.1095 + x+1>=(int)(img).width?(int)((img).width)-1:x+1); \ 1.1096 + x<=(int)(x1) && ((_n1##x<(int)((img).width) && ( \ 1.1097 + (I[1] = (img)(_n1##x,y,z,v)), \ 1.1098 + (I[3] = (img)(_n1##x,_n1##y,z,v)),1)) || \ 1.1099 + x==--_n1##x); \ 1.1100 + I[0] = I[1], \ 1.1101 + I[2] = I[3], \ 1.1102 + ++x, ++_n1##x) 1.1103 + 1.1104 +#define cimg_for3x3(img,x,y,z,v,I) \ 1.1105 + cimg_for3((img).height,y) for (int x = 0, \ 1.1106 + _p1##x = 0, \ 1.1107 + _n1##x = (int)( \ 1.1108 + (I[0] = I[1] = (img)(0,_p1##y,z,v)), \ 1.1109 + (I[3] = I[4] = (img)(0,y,z,v)), \ 1.1110 + (I[6] = I[7] = (img)(0,_n1##y,z,v)), \ 1.1111 + 1>=(img).width?(int)((img).width)-1:1); \ 1.1112 + (_n1##x<(int)((img).width) && ( \ 1.1113 + (I[2] = (img)(_n1##x,_p1##y,z,v)), \ 1.1114 + (I[5] = (img)(_n1##x,y,z,v)), \ 1.1115 + (I[8] = (img)(_n1##x,_n1##y,z,v)),1)) || \ 1.1116 + x==--_n1##x; \ 1.1117 + I[0] = I[1], I[1] = I[2], \ 1.1118 + I[3] = I[4], I[4] = I[5], \ 1.1119 + I[6] = I[7], I[7] = I[8], \ 1.1120 + _p1##x = x++, ++_n1##x) 1.1121 + 1.1122 +#define cimg_for_in3x3(img,x0,y0,x1,y1,x,y,z,v,I) \ 1.1123 + cimg_for_in3((img).height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ 1.1124 + _p1##x = x-1<0?0:x-1, \ 1.1125 + _n1##x = (int)( \ 1.1126 + (I[0] = (img)(_p1##x,_p1##y,z,v)), \ 1.1127 + (I[3] = (img)(_p1##x,y,z,v)), \ 1.1128 + (I[6] = (img)(_p1##x,_n1##y,z,v)), \ 1.1129 + (I[1] = (img)(x,_p1##y,z,v)), \ 1.1130 + (I[4] = (img)(x,y,z,v)), \ 1.1131 + (I[7] = (img)(x,_n1##y,z,v)), \ 1.1132 + x+1>=(int)(img).width?(int)((img).width)-1:x+1); \ 1.1133 + x<=(int)(x1) && ((_n1##x<(int)((img).width) && ( \ 1.1134 + (I[2] = (img)(_n1##x,_p1##y,z,v)), \ 1.1135 + (I[5] = (img)(_n1##x,y,z,v)), \ 1.1136 + (I[8] = (img)(_n1##x,_n1##y,z,v)),1)) || \ 1.1137 + x==--_n1##x); \ 1.1138 + I[0] = I[1], I[1] = I[2], \ 1.1139 + I[3] = I[4], I[4] = I[5], \ 1.1140 + I[6] = I[7], I[7] = I[8], \ 1.1141 + _p1##x = x++, ++_n1##x) 1.1142 + 1.1143 +#define cimg_for4x4(img,x,y,z,v,I) \ 1.1144 + cimg_for4((img).height,y) for (int x = 0, \ 1.1145 + _p1##x = 0, \ 1.1146 + _n1##x = 1>=(img).width?(int)((img).width)-1:1, \ 1.1147 + _n2##x = (int)( \ 1.1148 + (I[0] = I[1] = (img)(0,_p1##y,z,v)), \ 1.1149 + (I[4] = I[5] = (img)(0,y,z,v)), \ 1.1150 + (I[8] = I[9] = (img)(0,_n1##y,z,v)), \ 1.1151 + (I[12] = I[13] = (img)(0,_n2##y,z,v)), \ 1.1152 + (I[2] = (img)(_n1##x,_p1##y,z,v)), \ 1.1153 + (I[6] = (img)(_n1##x,y,z,v)), \ 1.1154 + (I[10] = (img)(_n1##x,_n1##y,z,v)), \ 1.1155 + (I[14] = (img)(_n1##x,_n2##y,z,v)), \ 1.1156 + 2>=(img).width?(int)((img).width)-1:2); \ 1.1157 + (_n2##x<(int)((img).width) && ( \ 1.1158 + (I[3] = (img)(_n2##x,_p1##y,z,v)), \ 1.1159 + (I[7] = (img)(_n2##x,y,z,v)), \ 1.1160 + (I[11] = (img)(_n2##x,_n1##y,z,v)), \ 1.1161 + (I[15] = (img)(_n2##x,_n2##y,z,v)),1)) || \ 1.1162 + _n1##x==--_n2##x || x==(_n2##x = --_n1##x); \ 1.1163 + I[0] = I[1], I[1] = I[2], I[2] = I[3], \ 1.1164 + I[4] = I[5], I[5] = I[6], I[6] = I[7], \ 1.1165 + I[8] = I[9], I[9] = I[10], I[10] = I[11], \ 1.1166 + I[12] = I[13], I[13] = I[14], I[14] = I[15], \ 1.1167 + _p1##x = x++, ++_n1##x, ++_n2##x) 1.1168 + 1.1169 +#define cimg_for_in4x4(img,x0,y0,x1,y1,x,y,z,v,I) \ 1.1170 + cimg_for_in4((img).height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ 1.1171 + _p1##x = x-1<0?0:x-1, \ 1.1172 + _n1##x = x+1>=(int)(img).width?(int)((img).width)-1:x+1, \ 1.1173 + _n2##x = (int)( \ 1.1174 + (I[0] = (img)(_p1##x,_p1##y,z,v)), \ 1.1175 + (I[4] = (img)(_p1##x,y,z,v)), \ 1.1176 + (I[8] = (img)(_p1##x,_n1##y,z,v)), \ 1.1177 + (I[12] = (img)(_p1##x,_n2##y,z,v)), \ 1.1178 + (I[1] = (img)(x,_p1##y,z,v)), \ 1.1179 + (I[5] = (img)(x,y,z,v)), \ 1.1180 + (I[9] = (img)(x,_n1##y,z,v)), \ 1.1181 + (I[13] = (img)(x,_n2##y,z,v)), \ 1.1182 + (I[2] = (img)(_n1##x,_p1##y,z,v)), \ 1.1183 + (I[6] = (img)(_n1##x,y,z,v)), \ 1.1184 + (I[10] = (img)(_n1##x,_n1##y,z,v)), \ 1.1185 + (I[14] = (img)(_n1##x,_n2##y,z,v)), \ 1.1186 + x+2>=(int)(img).width?(int)((img).width)-1:x+2); \ 1.1187 + x<=(int)(x1) && ((_n2##x<(int)((img).width) && ( \ 1.1188 + (I[3] = (img)(_n2##x,_p1##y,z,v)), \ 1.1189 + (I[7] = (img)(_n2##x,y,z,v)), \ 1.1190 + (I[11] = (img)(_n2##x,_n1##y,z,v)), \ 1.1191 + (I[15] = (img)(_n2##x,_n2##y,z,v)),1)) || \ 1.1192 + _n1##x==--_n2##x || x==(_n2##x = --_n1##x)); \ 1.1193 + I[0] = I[1], I[1] = I[2], I[2] = I[3], \ 1.1194 + I[4] = I[5], I[5] = I[6], I[6] = I[7], \ 1.1195 + I[8] = I[9], I[9] = I[10], I[10] = I[11], \ 1.1196 + I[12] = I[13], I[13] = I[14], I[14] = I[15], \ 1.1197 + _p1##x = x++, ++_n1##x, ++_n2##x) 1.1198 + 1.1199 +#define cimg_for5x5(img,x,y,z,v,I) \ 1.1200 + cimg_for5((img).height,y) for (int x = 0, \ 1.1201 + _p2##x = 0, _p1##x = 0, \ 1.1202 + _n1##x = 1>=(img).width?(int)((img).width)-1:1, \ 1.1203 + _n2##x = (int)( \ 1.1204 + (I[0] = I[1] = I[2] = (img)(0,_p2##y,z,v)), \ 1.1205 + (I[5] = I[6] = I[7] = (img)(0,_p1##y,z,v)), \ 1.1206 + (I[10] = I[11] = I[12] = (img)(0,y,z,v)), \ 1.1207 + (I[15] = I[16] = I[17] = (img)(0,_n1##y,z,v)), \ 1.1208 + (I[20] = I[21] = I[22] = (img)(0,_n2##y,z,v)), \ 1.1209 + (I[3] = (img)(_n1##x,_p2##y,z,v)), \ 1.1210 + (I[8] = (img)(_n1##x,_p1##y,z,v)), \ 1.1211 + (I[13] = (img)(_n1##x,y,z,v)), \ 1.1212 + (I[18] = (img)(_n1##x,_n1##y,z,v)), \ 1.1213 + (I[23] = (img)(_n1##x,_n2##y,z,v)), \ 1.1214 + 2>=(img).width?(int)((img).width)-1:2); \ 1.1215 + (_n2##x<(int)((img).width) && ( \ 1.1216 + (I[4] = (img)(_n2##x,_p2##y,z,v)), \ 1.1217 + (I[9] = (img)(_n2##x,_p1##y,z,v)), \ 1.1218 + (I[14] = (img)(_n2##x,y,z,v)), \ 1.1219 + (I[19] = (img)(_n2##x,_n1##y,z,v)), \ 1.1220 + (I[24] = (img)(_n2##x,_n2##y,z,v)),1)) || \ 1.1221 + _n1##x==--_n2##x || x==(_n2##x = --_n1##x); \ 1.1222 + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], \ 1.1223 + I[5] = I[6], I[6] = I[7], I[7] = I[8], I[8] = I[9], \ 1.1224 + I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], \ 1.1225 + I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], \ 1.1226 + I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ 1.1227 + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x) 1.1228 + 1.1229 +#define cimg_for_in5x5(img,x0,y0,x1,y1,x,y,z,v,I) \ 1.1230 + cimg_for_in5((img).height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ 1.1231 + _p2##x = x-2<0?0:x-2, \ 1.1232 + _p1##x = x-1<0?0:x-1, \ 1.1233 + _n1##x = x+1>=(int)(img).width?(int)((img).width)-1:x+1, \ 1.1234 + _n2##x = (int)( \ 1.1235 + (I[0] = (img)(_p2##x,_p2##y,z,v)), \ 1.1236 + (I[5] = (img)(_p2##x,_p1##y,z,v)), \ 1.1237 + (I[10] = (img)(_p2##x,y,z,v)), \ 1.1238 + (I[15] = (img)(_p2##x,_n1##y,z,v)), \ 1.1239 + (I[20] = (img)(_p2##x,_n2##y,z,v)), \ 1.1240 + (I[1] = (img)(_p1##x,_p2##y,z,v)), \ 1.1241 + (I[6] = (img)(_p1##x,_p1##y,z,v)), \ 1.1242 + (I[11] = (img)(_p1##x,y,z,v)), \ 1.1243 + (I[16] = (img)(_p1##x,_n1##y,z,v)), \ 1.1244 + (I[21] = (img)(_p1##x,_n2##y,z,v)), \ 1.1245 + (I[2] = (img)(x,_p2##y,z,v)), \ 1.1246 + (I[7] = (img)(x,_p1##y,z,v)), \ 1.1247 + (I[12] = (img)(x,y,z,v)), \ 1.1248 + (I[17] = (img)(x,_n1##y,z,v)), \ 1.1249 + (I[22] = (img)(x,_n2##y,z,v)), \ 1.1250 + (I[3] = (img)(_n1##x,_p2##y,z,v)), \ 1.1251 + (I[8] = (img)(_n1##x,_p1##y,z,v)), \ 1.1252 + (I[13] = (img)(_n1##x,y,z,v)), \ 1.1253 + (I[18] = (img)(_n1##x,_n1##y,z,v)), \ 1.1254 + (I[23] = (img)(_n1##x,_n2##y,z,v)), \ 1.1255 + x+2>=(int)(img).width?(int)((img).width)-1:x+2); \ 1.1256 + x<=(int)(x1) && ((_n2##x<(int)((img).width) && ( \ 1.1257 + (I[4] = (img)(_n2##x,_p2##y,z,v)), \ 1.1258 + (I[9] = (img)(_n2##x,_p1##y,z,v)), \ 1.1259 + (I[14] = (img)(_n2##x,y,z,v)), \ 1.1260 + (I[19] = (img)(_n2##x,_n1##y,z,v)), \ 1.1261 + (I[24] = (img)(_n2##x,_n2##y,z,v)),1)) || \ 1.1262 + _n1##x==--_n2##x || x==(_n2##x = --_n1##x)); \ 1.1263 + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], \ 1.1264 + I[5] = I[6], I[6] = I[7], I[7] = I[8], I[8] = I[9], \ 1.1265 + I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], \ 1.1266 + I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], \ 1.1267 + I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ 1.1268 + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x) 1.1269 + 1.1270 +#define cimg_for6x6(img,x,y,z,v,I) \ 1.1271 + cimg_for6((img).height,y) for (int x = 0, \ 1.1272 + _p2##x = 0, _p1##x = 0, \ 1.1273 + _n1##x = 1>=(img).width?(int)((img).width)-1:1, \ 1.1274 + _n2##x = 2>=(img).width?(int)((img).width)-1:2, \ 1.1275 + _n3##x = (int)( \ 1.1276 + (I[0] = I[1] = I[2] = (img)(0,_p2##y,z,v)), \ 1.1277 + (I[6] = I[7] = I[8] = (img)(0,_p1##y,z,v)), \ 1.1278 + (I[12] = I[13] = I[14] = (img)(0,y,z,v)), \ 1.1279 + (I[18] = I[19] = I[20] = (img)(0,_n1##y,z,v)), \ 1.1280 + (I[24] = I[25] = I[26] = (img)(0,_n2##y,z,v)), \ 1.1281 + (I[30] = I[31] = I[32] = (img)(0,_n3##y,z,v)), \ 1.1282 + (I[3] = (img)(_n1##x,_p2##y,z,v)), \ 1.1283 + (I[9] = (img)(_n1##x,_p1##y,z,v)), \ 1.1284 + (I[15] = (img)(_n1##x,y,z,v)), \ 1.1285 + (I[21] = (img)(_n1##x,_n1##y,z,v)), \ 1.1286 + (I[27] = (img)(_n1##x,_n2##y,z,v)), \ 1.1287 + (I[33] = (img)(_n1##x,_n3##y,z,v)), \ 1.1288 + (I[4] = (img)(_n2##x,_p2##y,z,v)), \ 1.1289 + (I[10] = (img)(_n2##x,_p1##y,z,v)), \ 1.1290 + (I[16] = (img)(_n2##x,y,z,v)), \ 1.1291 + (I[22] = (img)(_n2##x,_n1##y,z,v)), \ 1.1292 + (I[28] = (img)(_n2##x,_n2##y,z,v)), \ 1.1293 + (I[34] = (img)(_n2##x,_n3##y,z,v)), \ 1.1294 + 3>=(img).width?(int)((img).width)-1:3); \ 1.1295 + (_n3##x<(int)((img).width) && ( \ 1.1296 + (I[5] = (img)(_n3##x,_p2##y,z,v)), \ 1.1297 + (I[11] = (img)(_n3##x,_p1##y,z,v)), \ 1.1298 + (I[17] = (img)(_n3##x,y,z,v)), \ 1.1299 + (I[23] = (img)(_n3##x,_n1##y,z,v)), \ 1.1300 + (I[29] = (img)(_n3##x,_n2##y,z,v)), \ 1.1301 + (I[35] = (img)(_n3##x,_n3##y,z,v)),1)) || \ 1.1302 + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3## x = _n2##x = --_n1##x); \ 1.1303 + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], \ 1.1304 + I[6] = I[7], I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], \ 1.1305 + I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], I[16] = I[17], \ 1.1306 + I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ 1.1307 + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], \ 1.1308 + I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], I[34] = I[35], \ 1.1309 + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) 1.1310 + 1.1311 +#define cimg_for_in6x6(img,x0,y0,x1,y1,x,y,z,v,I) \ 1.1312 + cimg_for_in6((img).height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)x0, \ 1.1313 + _p2##x = x-2<0?0:x-2, \ 1.1314 + _p1##x = x-1<0?0:x-1, \ 1.1315 + _n1##x = x+1>=(int)(img).width?(int)((img).width)-1:x+1, \ 1.1316 + _n2##x = x+2>=(int)(img).width?(int)((img).width)-1:x+2, \ 1.1317 + _n3##x = (int)( \ 1.1318 + (I[0] = (img)(_p2##x,_p2##y,z,v)), \ 1.1319 + (I[6] = (img)(_p2##x,_p1##y,z,v)), \ 1.1320 + (I[12] = (img)(_p2##x,y,z,v)), \ 1.1321 + (I[18] = (img)(_p2##x,_n1##y,z,v)), \ 1.1322 + (I[24] = (img)(_p2##x,_n2##y,z,v)), \ 1.1323 + (I[30] = (img)(_p2##x,_n3##y,z,v)), \ 1.1324 + (I[1] = (img)(_p1##x,_p2##y,z,v)), \ 1.1325 + (I[7] = (img)(_p1##x,_p1##y,z,v)), \ 1.1326 + (I[13] = (img)(_p1##x,y,z,v)), \ 1.1327 + (I[19] = (img)(_p1##x,_n1##y,z,v)), \ 1.1328 + (I[25] = (img)(_p1##x,_n2##y,z,v)), \ 1.1329 + (I[31] = (img)(_p1##x,_n3##y,z,v)), \ 1.1330 + (I[2] = (img)(x,_p2##y,z,v)), \ 1.1331 + (I[8] = (img)(x,_p1##y,z,v)), \ 1.1332 + (I[14] = (img)(x,y,z,v)), \ 1.1333 + (I[20] = (img)(x,_n1##y,z,v)), \ 1.1334 + (I[26] = (img)(x,_n2##y,z,v)), \ 1.1335 + (I[32] = (img)(x,_n3##y,z,v)), \ 1.1336 + (I[3] = (img)(_n1##x,_p2##y,z,v)), \ 1.1337 + (I[9] = (img)(_n1##x,_p1##y,z,v)), \ 1.1338 + (I[15] = (img)(_n1##x,y,z,v)), \ 1.1339 + (I[21] = (img)(_n1##x,_n1##y,z,v)), \ 1.1340 + (I[27] = (img)(_n1##x,_n2##y,z,v)), \ 1.1341 + (I[33] = (img)(_n1##x,_n3##y,z,v)), \ 1.1342 + (I[4] = (img)(_n2##x,_p2##y,z,v)), \ 1.1343 + (I[10] = (img)(_n2##x,_p1##y,z,v)), \ 1.1344 + (I[16] = (img)(_n2##x,y,z,v)), \ 1.1345 + (I[22] = (img)(_n2##x,_n1##y,z,v)), \ 1.1346 + (I[28] = (img)(_n2##x,_n2##y,z,v)), \ 1.1347 + (I[34] = (img)(_n2##x,_n3##y,z,v)), \ 1.1348 + x+3>=(int)(img).width?(int)((img).width)-1:x+3); \ 1.1349 + x<=(int)(x1) && ((_n3##x<(int)((img).width) && ( \ 1.1350 + (I[5] = (img)(_n3##x,_p2##y,z,v)), \ 1.1351 + (I[11] = (img)(_n3##x,_p1##y,z,v)), \ 1.1352 + (I[17] = (img)(_n3##x,y,z,v)), \ 1.1353 + (I[23] = (img)(_n3##x,_n1##y,z,v)), \ 1.1354 + (I[29] = (img)(_n3##x,_n2##y,z,v)), \ 1.1355 + (I[35] = (img)(_n3##x,_n3##y,z,v)),1)) || \ 1.1356 + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3## x = _n2##x = --_n1##x)); \ 1.1357 + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], \ 1.1358 + I[6] = I[7], I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], \ 1.1359 + I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], I[16] = I[17], \ 1.1360 + I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ 1.1361 + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], \ 1.1362 + I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], I[34] = I[35], \ 1.1363 + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) 1.1364 + 1.1365 +#define cimg_for7x7(img,x,y,z,v,I) \ 1.1366 + cimg_for7((img).height,y) for (int x = 0, \ 1.1367 + _p3##x = 0, _p2##x = 0, _p1##x = 0, \ 1.1368 + _n1##x = 1>=(img).width?(int)((img).width)-1:1, \ 1.1369 + _n2##x = 2>=(img).width?(int)((img).width)-1:2, \ 1.1370 + _n3##x = (int)( \ 1.1371 + (I[0] = I[1] = I[2] = I[3] = (img)(0,_p3##y,z,v)), \ 1.1372 + (I[7] = I[8] = I[9] = I[10] = (img)(0,_p2##y,z,v)), \ 1.1373 + (I[14] = I[15] = I[16] = I[17] = (img)(0,_p1##y,z,v)), \ 1.1374 + (I[21] = I[22] = I[23] = I[24] = (img)(0,y,z,v)), \ 1.1375 + (I[28] = I[29] = I[30] = I[31] = (img)(0,_n1##y,z,v)), \ 1.1376 + (I[35] = I[36] = I[37] = I[38] = (img)(0,_n2##y,z,v)), \ 1.1377 + (I[42] = I[43] = I[44] = I[45] = (img)(0,_n3##y,z,v)), \ 1.1378 + (I[4] = (img)(_n1##x,_p3##y,z,v)), \ 1.1379 + (I[11] = (img)(_n1##x,_p2##y,z,v)), \ 1.1380 + (I[18] = (img)(_n1##x,_p1##y,z,v)), \ 1.1381 + (I[25] = (img)(_n1##x,y,z,v)), \ 1.1382 + (I[32] = (img)(_n1##x,_n1##y,z,v)), \ 1.1383 + (I[39] = (img)(_n1##x,_n2##y,z,v)), \ 1.1384 + (I[46] = (img)(_n1##x,_n3##y,z,v)), \ 1.1385 + (I[5] = (img)(_n2##x,_p3##y,z,v)), \ 1.1386 + (I[12] = (img)(_n2##x,_p2##y,z,v)), \ 1.1387 + (I[19] = (img)(_n2##x,_p1##y,z,v)), \ 1.1388 + (I[26] = (img)(_n2##x,y,z,v)), \ 1.1389 + (I[33] = (img)(_n2##x,_n1##y,z,v)), \ 1.1390 + (I[40] = (img)(_n2##x,_n2##y,z,v)), \ 1.1391 + (I[47] = (img)(_n2##x,_n3##y,z,v)), \ 1.1392 + 3>=(img).width?(int)((img).width)-1:3); \ 1.1393 + (_n3##x<(int)((img).width) && ( \ 1.1394 + (I[6] = (img)(_n3##x,_p3##y,z,v)), \ 1.1395 + (I[13] = (img)(_n3##x,_p2##y,z,v)), \ 1.1396 + (I[20] = (img)(_n3##x,_p1##y,z,v)), \ 1.1397 + (I[27] = (img)(_n3##x,y,z,v)), \ 1.1398 + (I[34] = (img)(_n3##x,_n1##y,z,v)), \ 1.1399 + (I[41] = (img)(_n3##x,_n2##y,z,v)), \ 1.1400 + (I[48] = (img)(_n3##x,_n3##y,z,v)),1)) || \ 1.1401 + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3##x = _n2##x = --_n1##x); \ 1.1402 + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], \ 1.1403 + I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], \ 1.1404 + I[14] = I[15], I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], \ 1.1405 + I[21] = I[22], I[22] = I[23], I[23] = I[24], I[24] = I[25], I[25] = I[26], I[26] = I[27], \ 1.1406 + I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], \ 1.1407 + I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], I[40] = I[41], \ 1.1408 + I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ 1.1409 + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) 1.1410 + 1.1411 +#define cimg_for_in7x7(img,x0,y0,x1,y1,x,y,z,v,I) \ 1.1412 + cimg_for_in7((img).height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ 1.1413 + _p3##x = x-3<0?0:x-3, \ 1.1414 + _p2##x = x-2<0?0:x-2, \ 1.1415 + _p1##x = x-1<0?0:x-1, \ 1.1416 + _n1##x = x+1>=(int)(img).width?(int)((img).width)-1:x+1, \ 1.1417 + _n2##x = x+2>=(int)(img).width?(int)((img).width)-1:x+2, \ 1.1418 + _n3##x = (int)( \ 1.1419 + (I[0] = (img)(_p3##x,_p3##y,z,v)), \ 1.1420 + (I[7] = (img)(_p3##x,_p2##y,z,v)), \ 1.1421 + (I[14] = (img)(_p3##x,_p1##y,z,v)), \ 1.1422 + (I[21] = (img)(_p3##x,y,z,v)), \ 1.1423 + (I[28] = (img)(_p3##x,_n1##y,z,v)), \ 1.1424 + (I[35] = (img)(_p3##x,_n2##y,z,v)), \ 1.1425 + (I[42] = (img)(_p3##x,_n3##y,z,v)), \ 1.1426 + (I[1] = (img)(_p2##x,_p3##y,z,v)), \ 1.1427 + (I[8] = (img)(_p2##x,_p2##y,z,v)), \ 1.1428 + (I[15] = (img)(_p2##x,_p1##y,z,v)), \ 1.1429 + (I[22] = (img)(_p2##x,y,z,v)), \ 1.1430 + (I[29] = (img)(_p2##x,_n1##y,z,v)), \ 1.1431 + (I[36] = (img)(_p2##x,_n2##y,z,v)), \ 1.1432 + (I[43] = (img)(_p2##x,_n3##y,z,v)), \ 1.1433 + (I[2] = (img)(_p1##x,_p3##y,z,v)), \ 1.1434 + (I[9] = (img)(_p1##x,_p2##y,z,v)), \ 1.1435 + (I[16] = (img)(_p1##x,_p1##y,z,v)), \ 1.1436 + (I[23] = (img)(_p1##x,y,z,v)), \ 1.1437 + (I[30] = (img)(_p1##x,_n1##y,z,v)), \ 1.1438 + (I[37] = (img)(_p1##x,_n2##y,z,v)), \ 1.1439 + (I[44] = (img)(_p1##x,_n3##y,z,v)), \ 1.1440 + (I[3] = (img)(x,_p3##y,z,v)), \ 1.1441 + (I[10] = (img)(x,_p2##y,z,v)), \ 1.1442 + (I[17] = (img)(x,_p1##y,z,v)), \ 1.1443 + (I[24] = (img)(x,y,z,v)), \ 1.1444 + (I[31] = (img)(x,_n1##y,z,v)), \ 1.1445 + (I[38] = (img)(x,_n2##y,z,v)), \ 1.1446 + (I[45] = (img)(x,_n3##y,z,v)), \ 1.1447 + (I[4] = (img)(_n1##x,_p3##y,z,v)), \ 1.1448 + (I[11] = (img)(_n1##x,_p2##y,z,v)), \ 1.1449 + (I[18] = (img)(_n1##x,_p1##y,z,v)), \ 1.1450 + (I[25] = (img)(_n1##x,y,z,v)), \ 1.1451 + (I[32] = (img)(_n1##x,_n1##y,z,v)), \ 1.1452 + (I[39] = (img)(_n1##x,_n2##y,z,v)), \ 1.1453 + (I[46] = (img)(_n1##x,_n3##y,z,v)), \ 1.1454 + (I[5] = (img)(_n2##x,_p3##y,z,v)), \ 1.1455 + (I[12] = (img)(_n2##x,_p2##y,z,v)), \ 1.1456 + (I[19] = (img)(_n2##x,_p1##y,z,v)), \ 1.1457 + (I[26] = (img)(_n2##x,y,z,v)), \ 1.1458 + (I[33] = (img)(_n2##x,_n1##y,z,v)), \ 1.1459 + (I[40] = (img)(_n2##x,_n2##y,z,v)), \ 1.1460 + (I[47] = (img)(_n2##x,_n3##y,z,v)), \ 1.1461 + x+3>=(int)(img).width?(int)((img).width)-1:x+3); \ 1.1462 + x<=(int)(x1) && ((_n3##x<(int)((img).width) && ( \ 1.1463 + (I[6] = (img)(_n3##x,_p3##y,z,v)), \ 1.1464 + (I[13] = (img)(_n3##x,_p2##y,z,v)), \ 1.1465 + (I[20] = (img)(_n3##x,_p1##y,z,v)), \ 1.1466 + (I[27] = (img)(_n3##x,y,z,v)), \ 1.1467 + (I[34] = (img)(_n3##x,_n1##y,z,v)), \ 1.1468 + (I[41] = (img)(_n3##x,_n2##y,z,v)), \ 1.1469 + (I[48] = (img)(_n3##x,_n3##y,z,v)),1)) || \ 1.1470 + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3##x = _n2##x = --_n1##x)); \ 1.1471 + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], \ 1.1472 + I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], \ 1.1473 + I[14] = I[15], I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], \ 1.1474 + I[21] = I[22], I[22] = I[23], I[23] = I[24], I[24] = I[25], I[25] = I[26], I[26] = I[27], \ 1.1475 + I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], \ 1.1476 + I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], I[40] = I[41], \ 1.1477 + I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ 1.1478 + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) 1.1479 + 1.1480 +#define cimg_for8x8(img,x,y,z,v,I) \ 1.1481 + cimg_for8((img).height,y) for (int x = 0, \ 1.1482 + _p3##x = 0, _p2##x = 0, _p1##x = 0, \ 1.1483 + _n1##x = 1>=((img).width)?(int)((img).width)-1:1, \ 1.1484 + _n2##x = 2>=((img).width)?(int)((img).width)-1:2, \ 1.1485 + _n3##x = 3>=((img).width)?(int)((img).width)-1:3, \ 1.1486 + _n4##x = (int)( \ 1.1487 + (I[0] = I[1] = I[2] = I[3] = (img)(0,_p3##y,z,v)), \ 1.1488 + (I[8] = I[9] = I[10] = I[11] = (img)(0,_p2##y,z,v)), \ 1.1489 + (I[16] = I[17] = I[18] = I[19] = (img)(0,_p1##y,z,v)), \ 1.1490 + (I[24] = I[25] = I[26] = I[27] = (img)(0,y,z,v)), \ 1.1491 + (I[32] = I[33] = I[34] = I[35] = (img)(0,_n1##y,z,v)), \ 1.1492 + (I[40] = I[41] = I[42] = I[43] = (img)(0,_n2##y,z,v)), \ 1.1493 + (I[48] = I[49] = I[50] = I[51] = (img)(0,_n3##y,z,v)), \ 1.1494 + (I[56] = I[57] = I[58] = I[59] = (img)(0,_n4##y,z,v)), \ 1.1495 + (I[4] = (img)(_n1##x,_p3##y,z,v)), \ 1.1496 + (I[12] = (img)(_n1##x,_p2##y,z,v)), \ 1.1497 + (I[20] = (img)(_n1##x,_p1##y,z,v)), \ 1.1498 + (I[28] = (img)(_n1##x,y,z,v)), \ 1.1499 + (I[36] = (img)(_n1##x,_n1##y,z,v)), \ 1.1500 + (I[44] = (img)(_n1##x,_n2##y,z,v)), \ 1.1501 + (I[52] = (img)(_n1##x,_n3##y,z,v)), \ 1.1502 + (I[60] = (img)(_n1##x,_n4##y,z,v)), \ 1.1503 + (I[5] = (img)(_n2##x,_p3##y,z,v)), \ 1.1504 + (I[13] = (img)(_n2##x,_p2##y,z,v)), \ 1.1505 + (I[21] = (img)(_n2##x,_p1##y,z,v)), \ 1.1506 + (I[29] = (img)(_n2##x,y,z,v)), \ 1.1507 + (I[37] = (img)(_n2##x,_n1##y,z,v)), \ 1.1508 + (I[45] = (img)(_n2##x,_n2##y,z,v)), \ 1.1509 + (I[53] = (img)(_n2##x,_n3##y,z,v)), \ 1.1510 + (I[61] = (img)(_n2##x,_n4##y,z,v)), \ 1.1511 + (I[6] = (img)(_n3##x,_p3##y,z,v)), \ 1.1512 + (I[14] = (img)(_n3##x,_p2##y,z,v)), \ 1.1513 + (I[22] = (img)(_n3##x,_p1##y,z,v)), \ 1.1514 + (I[30] = (img)(_n3##x,y,z,v)), \ 1.1515 + (I[38] = (img)(_n3##x,_n1##y,z,v)), \ 1.1516 + (I[46] = (img)(_n3##x,_n2##y,z,v)), \ 1.1517 + (I[54] = (img)(_n3##x,_n3##y,z,v)), \ 1.1518 + (I[62] = (img)(_n3##x,_n4##y,z,v)), \ 1.1519 + 4>=((img).width)?(int)((img).width)-1:4); \ 1.1520 + (_n4##x<(int)((img).width) && ( \ 1.1521 + (I[7] = (img)(_n4##x,_p3##y,z,v)), \ 1.1522 + (I[15] = (img)(_n4##x,_p2##y,z,v)), \ 1.1523 + (I[23] = (img)(_n4##x,_p1##y,z,v)), \ 1.1524 + (I[31] = (img)(_n4##x,y,z,v)), \ 1.1525 + (I[39] = (img)(_n4##x,_n1##y,z,v)), \ 1.1526 + (I[47] = (img)(_n4##x,_n2##y,z,v)), \ 1.1527 + (I[55] = (img)(_n4##x,_n3##y,z,v)), \ 1.1528 + (I[63] = (img)(_n4##x,_n4##y,z,v)),1)) || \ 1.1529 + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x); \ 1.1530 + 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], \ 1.1531 + 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], \ 1.1532 + 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], \ 1.1533 + 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], \ 1.1534 + 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], \ 1.1535 + 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], \ 1.1536 + 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], \ 1.1537 + 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], \ 1.1538 + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) 1.1539 + 1.1540 +#define cimg_for_in8x8(img,x0,y0,x1,y1,x,y,z,v,I) \ 1.1541 + cimg_for_in8((img).height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ 1.1542 + _p3##x = x-3<0?0:x-3, \ 1.1543 + _p2##x = x-2<0?0:x-2, \ 1.1544 + _p1##x = x-1<0?0:x-1, \ 1.1545 + _n1##x = x+1>=(int)((img).width)?(int)((img).width)-1:x+1, \ 1.1546 + _n2##x = x+2>=(int)((img).width)?(int)((img).width)-1:x+2, \ 1.1547 + _n3##x = x+3>=(int)((img).width)?(int)((img).width)-1:x+3, \ 1.1548 + _n4##x = (int)( \ 1.1549 + (I[0] = (img)(_p3##x,_p3##y,z,v)), \ 1.1550 + (I[8] = (img)(_p3##x,_p2##y,z,v)), \ 1.1551 + (I[16] = (img)(_p3##x,_p1##y,z,v)), \ 1.1552 + (I[24] = (img)(_p3##x,y,z,v)), \ 1.1553 + (I[32] = (img)(_p3##x,_n1##y,z,v)), \ 1.1554 + (I[40] = (img)(_p3##x,_n2##y,z,v)), \ 1.1555 + (I[48] = (img)(_p3##x,_n3##y,z,v)), \ 1.1556 + (I[56] = (img)(_p3##x,_n4##y,z,v)), \ 1.1557 + (I[1] = (img)(_p2##x,_p3##y,z,v)), \ 1.1558 + (I[9] = (img)(_p2##x,_p2##y,z,v)), \ 1.1559 + (I[17] = (img)(_p2##x,_p1##y,z,v)), \ 1.1560 + (I[25] = (img)(_p2##x,y,z,v)), \ 1.1561 + (I[33] = (img)(_p2##x,_n1##y,z,v)), \ 1.1562 + (I[41] = (img)(_p2##x,_n2##y,z,v)), \ 1.1563 + (I[49] = (img)(_p2##x,_n3##y,z,v)), \ 1.1564 + (I[57] = (img)(_p2##x,_n4##y,z,v)), \ 1.1565 + (I[2] = (img)(_p1##x,_p3##y,z,v)), \ 1.1566 + (I[10] = (img)(_p1##x,_p2##y,z,v)), \ 1.1567 + (I[18] = (img)(_p1##x,_p1##y,z,v)), \ 1.1568 + (I[26] = (img)(_p1##x,y,z,v)), \ 1.1569 + (I[34] = (img)(_p1##x,_n1##y,z,v)), \ 1.1570 + (I[42] = (img)(_p1##x,_n2##y,z,v)), \ 1.1571 + (I[50] = (img)(_p1##x,_n3##y,z,v)), \ 1.1572 + (I[58] = (img)(_p1##x,_n4##y,z,v)), \ 1.1573 + (I[3] = (img)(x,_p3##y,z,v)), \ 1.1574 + (I[11] = (img)(x,_p2##y,z,v)), \ 1.1575 + (I[19] = (img)(x,_p1##y,z,v)), \ 1.1576 + (I[27] = (img)(x,y,z,v)), \ 1.1577 + (I[35] = (img)(x,_n1##y,z,v)), \ 1.1578 + (I[43] = (img)(x,_n2##y,z,v)), \ 1.1579 + (I[51] = (img)(x,_n3##y,z,v)), \ 1.1580 + (I[59] = (img)(x,_n4##y,z,v)), \ 1.1581 + (I[4] = (img)(_n1##x,_p3##y,z,v)), \ 1.1582 + (I[12] = (img)(_n1##x,_p2##y,z,v)), \ 1.1583 + (I[20] = (img)(_n1##x,_p1##y,z,v)), \ 1.1584 + (I[28] = (img)(_n1##x,y,z,v)), \ 1.1585 + (I[36] = (img)(_n1##x,_n1##y,z,v)), \ 1.1586 + (I[44] = (img)(_n1##x,_n2##y,z,v)), \ 1.1587 + (I[52] = (img)(_n1##x,_n3##y,z,v)), \ 1.1588 + (I[60] = (img)(_n1##x,_n4##y,z,v)), \ 1.1589 + (I[5] = (img)(_n2##x,_p3##y,z,v)), \ 1.1590 + (I[13] = (img)(_n2##x,_p2##y,z,v)), \ 1.1591 + (I[21] = (img)(_n2##x,_p1##y,z,v)), \ 1.1592 + (I[29] = (img)(_n2##x,y,z,v)), \ 1.1593 + (I[37] = (img)(_n2##x,_n1##y,z,v)), \ 1.1594 + (I[45] = (img)(_n2##x,_n2##y,z,v)), \ 1.1595 + (I[53] = (img)(_n2##x,_n3##y,z,v)), \ 1.1596 + (I[61] = (img)(_n2##x,_n4##y,z,v)), \ 1.1597 + (I[6] = (img)(_n3##x,_p3##y,z,v)), \ 1.1598 + (I[14] = (img)(_n3##x,_p2##y,z,v)), \ 1.1599 + (I[22] = (img)(_n3##x,_p1##y,z,v)), \ 1.1600 + (I[30] = (img)(_n3##x,y,z,v)), \ 1.1601 + (I[38] = (img)(_n3##x,_n1##y,z,v)), \ 1.1602 + (I[46] = (img)(_n3##x,_n2##y,z,v)), \ 1.1603 + (I[54] = (img)(_n3##x,_n3##y,z,v)), \ 1.1604 + (I[62] = (img)(_n3##x,_n4##y,z,v)), \ 1.1605 + x+4>=(int)((img).width)?(int)((img).width)-1:x+4); \ 1.1606 + x<=(int)(x1) && ((_n4##x<(int)((img).width) && ( \ 1.1607 + (I[7] = (img)(_n4##x,_p3##y,z,v)), \ 1.1608 + (I[15] = (img)(_n4##x,_p2##y,z,v)), \ 1.1609 + (I[23] = (img)(_n4##x,_p1##y,z,v)), \ 1.1610 + (I[31] = (img)(_n4##x,y,z,v)), \ 1.1611 + (I[39] = (img)(_n4##x,_n1##y,z,v)), \ 1.1612 + (I[47] = (img)(_n4##x,_n2##y,z,v)), \ 1.1613 + (I[55] = (img)(_n4##x,_n3##y,z,v)), \ 1.1614 + (I[63] = (img)(_n4##x,_n4##y,z,v)),1)) || \ 1.1615 + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x)); \ 1.1616 + 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], \ 1.1617 + 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], \ 1.1618 + 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], \ 1.1619 + 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], \ 1.1620 + 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], \ 1.1621 + 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], \ 1.1622 + 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], \ 1.1623 + 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], \ 1.1624 + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) 1.1625 + 1.1626 +#define cimg_for9x9(img,x,y,z,v,I) \ 1.1627 + cimg_for9((img).height,y) for (int x = 0, \ 1.1628 + _p4##x = 0, _p3##x = 0, _p2##x = 0, _p1##x = 0, \ 1.1629 + _n1##x = 1>=((img).width)?(int)((img).width)-1:1, \ 1.1630 + _n2##x = 2>=((img).width)?(int)((img).width)-1:2, \ 1.1631 + _n3##x = 3>=((img).width)?(int)((img).width)-1:3, \ 1.1632 + _n4##x = (int)( \ 1.1633 + (I[0] = I[1] = I[2] = I[3] = I[4] = (img)(0,_p4##y,z,v)), \ 1.1634 + (I[9] = I[10] = I[11] = I[12] = I[13] = (img)(0,_p3##y,z,v)), \ 1.1635 + (I[18] = I[19] = I[20] = I[21] = I[22] = (img)(0,_p2##y,z,v)), \ 1.1636 + (I[27] = I[28] = I[29] = I[30] = I[31] = (img)(0,_p1##y,z,v)), \ 1.1637 + (I[36] = I[37] = I[38] = I[39] = I[40] = (img)(0,y,z,v)), \ 1.1638 + (I[45] = I[46] = I[47] = I[48] = I[49] = (img)(0,_n1##y,z,v)), \ 1.1639 + (I[54] = I[55] = I[56] = I[57] = I[58] = (img)(0,_n2##y,z,v)), \ 1.1640 + (I[63] = I[64] = I[65] = I[66] = I[67] = (img)(0,_n3##y,z,v)), \ 1.1641 + (I[72] = I[73] = I[74] = I[75] = I[76] = (img)(0,_n4##y,z,v)), \ 1.1642 + (I[5] = (img)(_n1##x,_p4##y,z,v)), \ 1.1643 + (I[14] = (img)(_n1##x,_p3##y,z,v)), \ 1.1644 + (I[23] = (img)(_n1##x,_p2##y,z,v)), \ 1.1645 + (I[32] = (img)(_n1##x,_p1##y,z,v)), \ 1.1646 + (I[41] = (img)(_n1##x,y,z,v)), \ 1.1647 + (I[50] = (img)(_n1##x,_n1##y,z,v)), \ 1.1648 + (I[59] = (img)(_n1##x,_n2##y,z,v)), \ 1.1649 + (I[68] = (img)(_n1##x,_n3##y,z,v)), \ 1.1650 + (I[77] = (img)(_n1##x,_n4##y,z,v)), \ 1.1651 + (I[6] = (img)(_n2##x,_p4##y,z,v)), \ 1.1652 + (I[15] = (img)(_n2##x,_p3##y,z,v)), \ 1.1653 + (I[24] = (img)(_n2##x,_p2##y,z,v)), \ 1.1654 + (I[33] = (img)(_n2##x,_p1##y,z,v)), \ 1.1655 + (I[42] = (img)(_n2##x,y,z,v)), \ 1.1656 + (I[51] = (img)(_n2##x,_n1##y,z,v)), \ 1.1657 + (I[60] = (img)(_n2##x,_n2##y,z,v)), \ 1.1658 + (I[69] = (img)(_n2##x,_n3##y,z,v)), \ 1.1659 + (I[78] = (img)(_n2##x,_n4##y,z,v)), \ 1.1660 + (I[7] = (img)(_n3##x,_p4##y,z,v)), \ 1.1661 + (I[16] = (img)(_n3##x,_p3##y,z,v)), \ 1.1662 + (I[25] = (img)(_n3##x,_p2##y,z,v)), \ 1.1663 + (I[34] = (img)(_n3##x,_p1##y,z,v)), \ 1.1664 + (I[43] = (img)(_n3##x,y,z,v)), \ 1.1665 + (I[52] = (img)(_n3##x,_n1##y,z,v)), \ 1.1666 + (I[61] = (img)(_n3##x,_n2##y,z,v)), \ 1.1667 + (I[70] = (img)(_n3##x,_n3##y,z,v)), \ 1.1668 + (I[79] = (img)(_n3##x,_n4##y,z,v)), \ 1.1669 + 4>=((img).width)?(int)((img).width)-1:4); \ 1.1670 + (_n4##x<(int)((img).width) && ( \ 1.1671 + (I[8] = (img)(_n4##x,_p4##y,z,v)), \ 1.1672 + (I[17] = (img)(_n4##x,_p3##y,z,v)), \ 1.1673 + (I[26] = (img)(_n4##x,_p2##y,z,v)), \ 1.1674 + (I[35] = (img)(_n4##x,_p1##y,z,v)), \ 1.1675 + (I[44] = (img)(_n4##x,y,z,v)), \ 1.1676 + (I[53] = (img)(_n4##x,_n1##y,z,v)), \ 1.1677 + (I[62] = (img)(_n4##x,_n2##y,z,v)), \ 1.1678 + (I[71] = (img)(_n4##x,_n3##y,z,v)), \ 1.1679 + (I[80] = (img)(_n4##x,_n4##y,z,v)),1)) || \ 1.1680 + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x); \ 1.1681 + 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], \ 1.1682 + 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], \ 1.1683 + 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], \ 1.1684 + 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], \ 1.1685 + 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], \ 1.1686 + 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], \ 1.1687 + 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], \ 1.1688 + 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], \ 1.1689 + 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], \ 1.1690 + _p4##x = _p3##x, _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) 1.1691 + 1.1692 +#define cimg_for_in9x9(img,x0,y0,x1,y1,x,y,z,v,I) \ 1.1693 + cimg_for_in9((img).height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ 1.1694 + _p4##x = x-4<0?0:x-4, \ 1.1695 + _p3##x = x-3<0?0:x-3, \ 1.1696 + _p2##x = x-2<0?0:x-2, \ 1.1697 + _p1##x = x-1<0?0:x-1, \ 1.1698 + _n1##x = x+1>=(int)((img).width)?(int)((img).width)-1:x+1, \ 1.1699 + _n2##x = x+2>=(int)((img).width)?(int)((img).width)-1:x+2, \ 1.1700 + _n3##x = x+3>=(int)((img).width)?(int)((img).width)-1:x+3, \ 1.1701 + _n4##x = (int)( \ 1.1702 + (I[0] = (img)(_p4##x,_p4##y,z,v)), \ 1.1703 + (I[9] = (img)(_p4##x,_p3##y,z,v)), \ 1.1704 + (I[18] = (img)(_p4##x,_p2##y,z,v)), \ 1.1705 + (I[27] = (img)(_p4##x,_p1##y,z,v)), \ 1.1706 + (I[36] = (img)(_p4##x,y,z,v)), \ 1.1707 + (I[45] = (img)(_p4##x,_n1##y,z,v)), \ 1.1708 + (I[54] = (img)(_p4##x,_n2##y,z,v)), \ 1.1709 + (I[63] = (img)(_p4##x,_n3##y,z,v)), \ 1.1710 + (I[72] = (img)(_p4##x,_n4##y,z,v)), \ 1.1711 + (I[1] = (img)(_p3##x,_p4##y,z,v)), \ 1.1712 + (I[10] = (img)(_p3##x,_p3##y,z,v)), \ 1.1713 + (I[19] = (img)(_p3##x,_p2##y,z,v)), \ 1.1714 + (I[28] = (img)(_p3##x,_p1##y,z,v)), \ 1.1715 + (I[37] = (img)(_p3##x,y,z,v)), \ 1.1716 + (I[46] = (img)(_p3##x,_n1##y,z,v)), \ 1.1717 + (I[55] = (img)(_p3##x,_n2##y,z,v)), \ 1.1718 + (I[64] = (img)(_p3##x,_n3##y,z,v)), \ 1.1719 + (I[73] = (img)(_p3##x,_n4##y,z,v)), \ 1.1720 + (I[2] = (img)(_p2##x,_p4##y,z,v)), \ 1.1721 + (I[11] = (img)(_p2##x,_p3##y,z,v)), \ 1.1722 + (I[20] = (img)(_p2##x,_p2##y,z,v)), \ 1.1723 + (I[29] = (img)(_p2##x,_p1##y,z,v)), \ 1.1724 + (I[38] = (img)(_p2##x,y,z,v)), \ 1.1725 + (I[47] = (img)(_p2##x,_n1##y,z,v)), \ 1.1726 + (I[56] = (img)(_p2##x,_n2##y,z,v)), \ 1.1727 + (I[65] = (img)(_p2##x,_n3##y,z,v)), \ 1.1728 + (I[74] = (img)(_p2##x,_n4##y,z,v)), \ 1.1729 + (I[3] = (img)(_p1##x,_p4##y,z,v)), \ 1.1730 + (I[12] = (img)(_p1##x,_p3##y,z,v)), \ 1.1731 + (I[21] = (img)(_p1##x,_p2##y,z,v)), \ 1.1732 + (I[30] = (img)(_p1##x,_p1##y,z,v)), \ 1.1733 + (I[39] = (img)(_p1##x,y,z,v)), \ 1.1734 + (I[48] = (img)(_p1##x,_n1##y,z,v)), \ 1.1735 + (I[57] = (img)(_p1##x,_n2##y,z,v)), \ 1.1736 + (I[66] = (img)(_p1##x,_n3##y,z,v)), \ 1.1737 + (I[75] = (img)(_p1##x,_n4##y,z,v)), \ 1.1738 + (I[4] = (img)(x,_p4##y,z,v)), \ 1.1739 + (I[13] = (img)(x,_p3##y,z,v)), \ 1.1740 + (I[22] = (img)(x,_p2##y,z,v)), \ 1.1741 + (I[31] = (img)(x,_p1##y,z,v)), \ 1.1742 + (I[40] = (img)(x,y,z,v)), \ 1.1743 + (I[49] = (img)(x,_n1##y,z,v)), \ 1.1744 + (I[58] = (img)(x,_n2##y,z,v)), \ 1.1745 + (I[67] = (img)(x,_n3##y,z,v)), \ 1.1746 + (I[76] = (img)(x,_n4##y,z,v)), \ 1.1747 + (I[5] = (img)(_n1##x,_p4##y,z,v)), \ 1.1748 + (I[14] = (img)(_n1##x,_p3##y,z,v)), \ 1.1749 + (I[23] = (img)(_n1##x,_p2##y,z,v)), \ 1.1750 + (I[32] = (img)(_n1##x,_p1##y,z,v)), \ 1.1751 + (I[41] = (img)(_n1##x,y,z,v)), \ 1.1752 + (I[50] = (img)(_n1##x,_n1##y,z,v)), \ 1.1753 + (I[59] = (img)(_n1##x,_n2##y,z,v)), \ 1.1754 + (I[68] = (img)(_n1##x,_n3##y,z,v)), \ 1.1755 + (I[77] = (img)(_n1##x,_n4##y,z,v)), \ 1.1756 + (I[6] = (img)(_n2##x,_p4##y,z,v)), \ 1.1757 + (I[15] = (img)(_n2##x,_p3##y,z,v)), \ 1.1758 + (I[24] = (img)(_n2##x,_p2##y,z,v)), \ 1.1759 + (I[33] = (img)(_n2##x,_p1##y,z,v)), \ 1.1760 + (I[42] = (img)(_n2##x,y,z,v)), \ 1.1761 + (I[51] = (img)(_n2##x,_n1##y,z,v)), \ 1.1762 + (I[60] = (img)(_n2##x,_n2##y,z,v)), \ 1.1763 + (I[69] = (img)(_n2##x,_n3##y,z,v)), \ 1.1764 + (I[78] = (img)(_n2##x,_n4##y,z,v)), \ 1.1765 + (I[7] = (img)(_n3##x,_p4##y,z,v)), \ 1.1766 + (I[16] = (img)(_n3##x,_p3##y,z,v)), \ 1.1767 + (I[25] = (img)(_n3##x,_p2##y,z,v)), \ 1.1768 + (I[34] = (img)(_n3##x,_p1##y,z,v)), \ 1.1769 + (I[43] = (img)(_n3##x,y,z,v)), \ 1.1770 + (I[52] = (img)(_n3##x,_n1##y,z,v)), \ 1.1771 + (I[61] = (img)(_n3##x,_n2##y,z,v)), \ 1.1772 + (I[70] = (img)(_n3##x,_n3##y,z,v)), \ 1.1773 + (I[79] = (img)(_n3##x,_n4##y,z,v)), \ 1.1774 + x+4>=(int)((img).width)?(int)((img).width)-1:x+4); \ 1.1775 + x<=(int)(x1) && ((_n4##x<(int)((img).width) && ( \ 1.1776 + (I[8] = (img)(_n4##x,_p4##y,z,v)), \ 1.1777 + (I[17] = (img)(_n4##x,_p3##y,z,v)), \ 1.1778 + (I[26] = (img)(_n4##x,_p2##y,z,v)), \ 1.1779 + (I[35] = (img)(_n4##x,_p1##y,z,v)), \ 1.1780 + (I[44] = (img)(_n4##x,y,z,v)), \ 1.1781 + (I[53] = (img)(_n4##x,_n1##y,z,v)), \ 1.1782 + (I[62] = (img)(_n4##x,_n2##y,z,v)), \ 1.1783 + (I[71] = (img)(_n4##x,_n3##y,z,v)), \ 1.1784 + (I[80] = (img)(_n4##x,_n4##y,z,v)),1)) || \ 1.1785 + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x)); \ 1.1786 + 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], \ 1.1787 + 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], \ 1.1788 + 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], \ 1.1789 + 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], \ 1.1790 + 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], \ 1.1791 + 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], \ 1.1792 + 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], \ 1.1793 + 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], \ 1.1794 + 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], \ 1.1795 + _p4##x = _p3##x, _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) 1.1796 + 1.1797 +#define cimg_for2x2x2(img,x,y,z,v,I) \ 1.1798 + cimg_for2((img).depth,z) cimg_for2((img).height,y) for (int x = 0, \ 1.1799 + _n1##x = (int)( \ 1.1800 + (I[0] = (img)(0,y,z,v)), \ 1.1801 + (I[2] = (img)(0,_n1##y,z,v)), \ 1.1802 + (I[4] = (img)(0,y,_n1##z,v)), \ 1.1803 + (I[6] = (img)(0,_n1##y,_n1##z,v)), \ 1.1804 + 1>=(img).width?(int)((img).width)-1:1); \ 1.1805 + (_n1##x<(int)((img).width) && ( \ 1.1806 + (I[1] = (img)(_n1##x,y,z,v)), \ 1.1807 + (I[3] = (img)(_n1##x,_n1##y,z,v)), \ 1.1808 + (I[5] = (img)(_n1##x,y,_n1##z,v)), \ 1.1809 + (I[7] = (img)(_n1##x,_n1##y,_n1##z,v)),1)) || \ 1.1810 + x==--_n1##x; \ 1.1811 + I[0] = I[1], I[2] = I[3], I[4] = I[5], I[6] = I[7], \ 1.1812 + ++x, ++_n1##x) 1.1813 + 1.1814 +#define cimg_for_in2x2x2(img,x0,y0,z0,x1,y1,z1,x,y,z,v,I) \ 1.1815 + 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), \ 1.1816 + _n1##x = (int)( \ 1.1817 + (I[0] = (img)(x,y,z,v)), \ 1.1818 + (I[2] = (img)(x,_n1##y,z,v)), \ 1.1819 + (I[4] = (img)(x,y,_n1##z,v)), \ 1.1820 + (I[6] = (img)(x,_n1##y,_n1##z,v)), \ 1.1821 + x+1>=(int)(img).width?(int)((img).width)-1:x+1); \ 1.1822 + x<=(int)(x1) && ((_n1##x<(int)((img).width) && ( \ 1.1823 + (I[1] = (img)(_n1##x,y,z,v)), \ 1.1824 + (I[3] = (img)(_n1##x,_n1##y,z,v)), \ 1.1825 + (I[5] = (img)(_n1##x,y,_n1##z,v)), \ 1.1826 + (I[7] = (img)(_n1##x,_n1##y,_n1##z,v)),1)) || \ 1.1827 + x==--_n1##x); \ 1.1828 + I[0] = I[1], I[2] = I[3], I[4] = I[5], I[6] = I[7], \ 1.1829 + ++x, ++_n1##x) 1.1830 + 1.1831 +#define cimg_for3x3x3(img,x,y,z,v,I) \ 1.1832 + cimg_for3((img).depth,z) cimg_for3((img).height,y) for (int x = 0, \ 1.1833 + _p1##x = 0, \ 1.1834 + _n1##x = (int)( \ 1.1835 + (I[0] = I[1] = (img)(0,_p1##y,_p1##z,v)), \ 1.1836 + (I[3] = I[4] = (img)(0,y,_p1##z,v)), \ 1.1837 + (I[6] = I[7] = (img)(0,_n1##y,_p1##z,v)), \ 1.1838 + (I[9] = I[10] = (img)(0,_p1##y,z,v)), \ 1.1839 + (I[12] = I[13] = (img)(0,y,z,v)), \ 1.1840 + (I[15] = I[16] = (img)(0,_n1##y,z,v)), \ 1.1841 + (I[18] = I[19] = (img)(0,_p1##y,_n1##z,v)), \ 1.1842 + (I[21] = I[22] = (img)(0,y,_n1##z,v)), \ 1.1843 + (I[24] = I[25] = (img)(0,_n1##y,_n1##z,v)), \ 1.1844 + 1>=(img).width?(int)((img).width)-1:1); \ 1.1845 + (_n1##x<(int)((img).width) && ( \ 1.1846 + (I[2] = (img)(_n1##x,_p1##y,_p1##z,v)), \ 1.1847 + (I[5] = (img)(_n1##x,y,_p1##z,v)), \ 1.1848 + (I[8] = (img)(_n1##x,_n1##y,_p1##z,v)), \ 1.1849 + (I[11] = (img)(_n1##x,_p1##y,z,v)), \ 1.1850 + (I[14] = (img)(_n1##x,y,z,v)), \ 1.1851 + (I[17] = (img)(_n1##x,_n1##y,z,v)), \ 1.1852 + (I[20] = (img)(_n1##x,_p1##y,_n1##z,v)), \ 1.1853 + (I[23] = (img)(_n1##x,y,_n1##z,v)), \ 1.1854 + (I[26] = (img)(_n1##x,_n1##y,_n1##z,v)),1)) || \ 1.1855 + x==--_n1##x; \ 1.1856 + I[0] = I[1], I[1] = I[2], I[3] = I[4], I[4] = I[5], I[6] = I[7], I[7] = I[8], \ 1.1857 + I[9] = I[10], I[10] = I[11], I[12] = I[13], I[13] = I[14], I[15] = I[16], I[16] = I[17], \ 1.1858 + I[18] = I[19], I[19] = I[20], I[21] = I[22], I[22] = I[23], I[24] = I[25], I[25] = I[26], \ 1.1859 + _p1##x = x++, ++_n1##x) 1.1860 + 1.1861 +#define cimg_for_in3x3x3(img,x0,y0,z0,x1,y1,z1,x,y,z,v,I) \ 1.1862 + 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), \ 1.1863 + _p1##x = x-1<0?0:x-1, \ 1.1864 + _n1##x = (int)( \ 1.1865 + (I[0] = (img)(_p1##x,_p1##y,_p1##z,v)), \ 1.1866 + (I[3] = (img)(_p1##x,y,_p1##z,v)), \ 1.1867 + (I[6] = (img)(_p1##x,_n1##y,_p1##z,v)), \ 1.1868 + (I[9] = (img)(_p1##x,_p1##y,z,v)), \ 1.1869 + (I[12] = (img)(_p1##x,y,z,v)), \ 1.1870 + (I[15] = (img)(_p1##x,_n1##y,z,v)), \ 1.1871 + (I[18] = (img)(_p1##x,_p1##y,_n1##z,v)), \ 1.1872 + (I[21] = (img)(_p1##x,y,_n1##z,v)), \ 1.1873 + (I[24] = (img)(_p1##x,_n1##y,_n1##z,v)), \ 1.1874 + (I[1] = (img)(x,_p1##y,_p1##z,v)), \ 1.1875 + (I[4] = (img)(x,y,_p1##z,v)), \ 1.1876 + (I[7] = (img)(x,_n1##y,_p1##z,v)), \ 1.1877 + (I[10] = (img)(x,_p1##y,z,v)), \ 1.1878 + (I[13] = (img)(x,y,z,v)), \ 1.1879 + (I[16] = (img)(x,_n1##y,z,v)), \ 1.1880 + (I[19] = (img)(x,_p1##y,_n1##z,v)), \ 1.1881 + (I[22] = (img)(x,y,_n1##z,v)), \ 1.1882 + (I[25] = (img)(x,_n1##y,_n1##z,v)), \ 1.1883 + x+1>=(int)(img).width?(int)((img).width)-1:x+1); \ 1.1884 + x<=(int)(x1) && ((_n1##x<(int)((img).width) && ( \ 1.1885 + (I[2] = (img)(_n1##x,_p1##y,_p1##z,v)), \ 1.1886 + (I[5] = (img)(_n1##x,y,_p1##z,v)), \ 1.1887 + (I[8] = (img)(_n1##x,_n1##y,_p1##z,v)), \ 1.1888 + (I[11] = (img)(_n1##x,_p1##y,z,v)), \ 1.1889 + (I[14] = (img)(_n1##x,y,z,v)), \ 1.1890 + (I[17] = (img)(_n1##x,_n1##y,z,v)), \ 1.1891 + (I[20] = (img)(_n1##x,_p1##y,_n1##z,v)), \ 1.1892 + (I[23] = (img)(_n1##x,y,_n1##z,v)), \ 1.1893 + (I[26] = (img)(_n1##x,_n1##y,_n1##z,v)),1)) || \ 1.1894 + x==--_n1##x); \ 1.1895 + I[0] = I[1], I[1] = I[2], I[3] = I[4], I[4] = I[5], I[6] = I[7], I[7] = I[8], \ 1.1896 + I[9] = I[10], I[10] = I[11], I[12] = I[13], I[13] = I[14], I[15] = I[16], I[16] = I[17], \ 1.1897 + I[18] = I[19], I[19] = I[20], I[21] = I[22], I[22] = I[23], I[24] = I[25], I[25] = I[26], \ 1.1898 + _p1##x = x++, ++_n1##x) 1.1899 + 1.1900 +/*------------------------------------------------ 1.1901 + # 1.1902 + # 1.1903 + # Definition of the cimg_library:: namespace 1.1904 + # 1.1905 + # 1.1906 + -------------------------------------------------*/ 1.1907 +//! This namespace encompasses all classes and functions of the %CImg library. 1.1908 +/** 1.1909 + This namespace is defined to avoid functions and class names collisions 1.1910 + that could happen with the include of other C++ header files. 1.1911 + Anyway, it should not happen often and you should reasonnably start most of your 1.1912 + %CImg-based programs with 1.1913 + \code 1.1914 + #include "CImg.h" 1.1915 + using namespace cimg_library; 1.1916 + \endcode 1.1917 + to simplify the declaration of %CImg Library variables afterwards. 1.1918 +**/ 1.1919 +namespace cimg_library { 1.1920 + 1.1921 + // Declare the only four classes of the CImg Library. 1.1922 + // 1.1923 + template<typename T=float> struct CImg; 1.1924 + template<typename T=float> struct CImgList; 1.1925 + struct CImgDisplay; 1.1926 + struct CImgException; 1.1927 + 1.1928 + // (Pre)declare the cimg namespace. 1.1929 + // This is not the complete namespace declaration. It only contains some 1.1930 + // necessary stuffs to ensure a correct declaration order of classes and functions 1.1931 + // defined afterwards. 1.1932 + // 1.1933 + namespace cimg { 1.1934 + 1.1935 +#ifdef cimg_use_vt100 1.1936 + const char t_normal[] = { 0x1b,'[','0',';','0',';','0','m','\0' }; 1.1937 + const char t_red[] = { 0x1b,'[','4',';','3','1',';','5','9','m','\0' }; 1.1938 + const char t_bold[] = { 0x1b,'[','1','m','\0' }; 1.1939 + const char t_purple[] = { 0x1b,'[','0',';','3','5',';','5','9','m','\0' }; 1.1940 + const char t_green[] = { 0x1b,'[','0',';','3','2',';','5','9','m','\0' }; 1.1941 +#else 1.1942 + const char t_normal[] = { '\0' }; 1.1943 + const char *const t_red = cimg::t_normal, *const t_bold = cimg::t_normal, 1.1944 + *const t_purple = cimg::t_normal, *const t_green = cimg::t_normal; 1.1945 +#endif 1.1946 + 1.1947 + inline void info(); 1.1948 + 1.1949 + //! Get/set the current CImg exception mode. 1.1950 + /** 1.1951 + The way error messages are handled by CImg can be changed dynamically, using this function. 1.1952 + Possible values are : 1.1953 + - 0 to hide debug messages (quiet mode, but exceptions are still thrown). 1.1954 + - 1 to display debug messages on standard error (console). 1.1955 + - 2 to display debug messages in modal windows (default behavior). 1.1956 + - 3 to do as 1 + add extra warnings (may slow down the code !). 1.1957 + - 4 to do as 2 + add extra warnings (may slow down the code !). 1.1958 + **/ 1.1959 + inline unsigned int& exception_mode() { static unsigned int mode = cimg_debug; return mode; } 1.1960 + 1.1961 + inline int dialog(const char *title, const char *msg, const char *button1_txt="OK", 1.1962 + const char *button2_txt=0, const char *button3_txt=0, 1.1963 + const char *button4_txt=0, const char *button5_txt=0, 1.1964 + const char *button6_txt=0, const bool centering=false); 1.1965 + } 1.1966 + 1.1967 + /*---------------------------------------------- 1.1968 + # 1.1969 + # Definition of the CImgException structures 1.1970 + # 1.1971 + ----------------------------------------------*/ 1.1972 + //! Instances of this class are thrown when errors occur during a %CImg library function call. 1.1973 + /** 1.1974 + \section ex1 Overview 1.1975 + 1.1976 + CImgException is the base class of %CImg exceptions. 1.1977 + Exceptions are thrown by the %CImg Library when an error occured in a %CImg library function call. 1.1978 + CImgException is seldom thrown itself. Children classes that specify the kind of error encountered 1.1979 + are generally used instead. These sub-classes are : 1.1980 + 1.1981 + - \b CImgInstanceException : Thrown when the instance associated to the called %CImg function is not 1.1982 + correctly defined. Generally, this exception is thrown when one tries to process \a empty images. The example 1.1983 + below will throw a \a CImgInstanceException. 1.1984 + \code 1.1985 + CImg<float> img; // Construct an empty image. 1.1986 + img.blur(10); // Try to blur the image. 1.1987 + \endcode 1.1988 + 1.1989 + - \b CImgArgumentException : Thrown when one of the arguments given to the called %CImg function is not correct. 1.1990 + Generally, this exception is thrown when arguments passed to the function are outside an admissible range of values. 1.1991 + The example below will throw a \a CImgArgumentException. 1.1992 + \code 1.1993 + CImg<float> img(100,100,1,3); // Define a 100x100 color image with float pixels. 1.1994 + img = 0; // Try to fill pixels from the 0 pointer (invalid argument to operator=() ). 1.1995 + \endcode 1.1996 + 1.1997 + - \b CImgIOException : Thrown when an error occured when trying to load or save image files. 1.1998 + The example below will throw a \a CImgIOException. 1.1999 + \code 1.2000 + CImg<float> img("file_doesnt_exist.jpg"); // Try to load a file that doesn't exist. 1.2001 + \endcode 1.2002 + 1.2003 + - \b CImgDisplayException : Thrown when an error occured when trying to display an image in a window. 1.2004 + This exception is thrown when image display request cannot be satisfied. 1.2005 + 1.2006 + The parent class CImgException may be thrown itself when errors that cannot be classified in one of 1.2007 + the above type occur. It is recommended not to throw CImgExceptions yourself, since there are normally 1.2008 + reserved to %CImg Library functions. 1.2009 + \b CImgInstanceException, \b CImgArgumentException, \b CImgIOException and \b CImgDisplayException are simple 1.2010 + subclasses of CImgException and are thus not detailled more in this reference documentation. 1.2011 + 1.2012 + \section ex2 Exception handling 1.2013 + 1.2014 + When an error occurs, the %CImg Library first displays the error in a modal window. 1.2015 + Then, it throws an instance of the corresponding exception class, generally leading the program to stop 1.2016 + (this is the default behavior). 1.2017 + You can bypass this default behavior by handling the exceptions yourself, 1.2018 + using a code block <tt>try { ... } catch() { ... }</tt>. 1.2019 + In this case, you can avoid the apparition of the modal window, by 1.2020 + defining the environment variable <tt>cimg_debug</tt> to 0 before including the %CImg header file. 1.2021 + The example below shows how to cleanly handle %CImg Library exceptions : 1.2022 + \code 1.2023 + #define cimg_debug 0 // Disable modal window in CImg exceptions. 1.2024 + #define "CImg.h" 1.2025 + int main() { 1.2026 + try { 1.2027 + ...; // Here, do what you want. 1.2028 + } 1.2029 + catch (CImgInstanceException &e) { 1.2030 + std::fprintf(stderr,"CImg Library Error : %s",e.message); // Display your own error message 1.2031 + ... // Do what you want now. 1.2032 + } 1.2033 + } 1.2034 + \endcode 1.2035 + **/ 1.2036 + struct CImgException { 1.2037 +#define _cimg_exception_err(etype,disp_flag) \ 1.2038 + cimg_std::va_list ap; va_start(ap,format); cimg_std::vsprintf(message,format,ap); va_end(ap); \ 1.2039 + switch (cimg::exception_mode()) { \ 1.2040 + case 0 : break; \ 1.2041 + case 2 : case 4 : try { cimg::dialog(etype,message,"Abort"); } catch (CImgException&) { \ 1.2042 + cimg_std::fprintf(cimg_stdout,"\n%s# %s%s :\n%s\n\n",cimg::t_red,etype,cimg::t_normal,message); \ 1.2043 + } break; \ 1.2044 + default : cimg_std::fprintf(cimg_stdout,"\n%s# %s%s :\n%s\n\n",cimg::t_red,etype,cimg::t_normal,message); \ 1.2045 + } \ 1.2046 + if (cimg::exception_mode()>=3) cimg_library::cimg::info(); 1.2047 + 1.2048 + char message[1024]; //!< Message associated with the error that thrown the exception. 1.2049 + CImgException() { message[0]='\0'; } 1.2050 + CImgException(const char *format, ...) { _cimg_exception_err("CImgException",true); } 1.2051 + }; 1.2052 + 1.2053 + // The \ref CImgInstanceException class is used to throw an exception related 1.2054 + // to a non suitable instance encountered in a library function call. 1.2055 + struct CImgInstanceException: public CImgException { 1.2056 + CImgInstanceException(const char *format, ...) { _cimg_exception_err("CImgInstanceException",true); } 1.2057 + }; 1.2058 + 1.2059 + // The \ref CImgArgumentException class is used to throw an exception related 1.2060 + // to invalid arguments encountered in a library function call. 1.2061 + struct CImgArgumentException: public CImgException { 1.2062 + CImgArgumentException(const char *format, ...) { _cimg_exception_err("CImgArgumentException",true); } 1.2063 + }; 1.2064 + 1.2065 + // The \ref CImgIOException class is used to throw an exception related 1.2066 + // to Input/Output file problems encountered in a library function call. 1.2067 + struct CImgIOException: public CImgException { 1.2068 + CImgIOException(const char *format, ...) { _cimg_exception_err("CImgIOException",true); } 1.2069 + }; 1.2070 + 1.2071 + // The CImgDisplayException class is used to throw an exception related to display problems 1.2072 + // encountered in a library function call. 1.2073 + struct CImgDisplayException: public CImgException { 1.2074 + CImgDisplayException(const char *format, ...) { _cimg_exception_err("CImgDisplayException",false); } 1.2075 + }; 1.2076 + 1.2077 + // The CImgWarningException class is used to throw an exception for warnings 1.2078 + // encountered in a library function call. 1.2079 + struct CImgWarningException: public CImgException { 1.2080 + CImgWarningException(const char *format, ...) { _cimg_exception_err("CImgWarningException",false); } 1.2081 + }; 1.2082 + 1.2083 + /*------------------------------------- 1.2084 + # 1.2085 + # Definition of the namespace 'cimg' 1.2086 + # 1.2087 + --------------------------------------*/ 1.2088 + //! Namespace that encompasses \a low-level functions and variables of the %CImg Library. 1.2089 + /** 1.2090 + Most of the functions and variables within this namespace are used by the library for low-level processing. 1.2091 + Nevertheless, documented variables and functions of this namespace may be used safely in your own source code. 1.2092 + 1.2093 + \warning Never write <tt>using namespace cimg_library::cimg;</tt> in your source code, since a lot of functions of the 1.2094 + <tt>cimg::</tt> namespace have prototypes similar to standard C functions that could defined in the global namespace <tt>::</tt>. 1.2095 + **/ 1.2096 + namespace cimg { 1.2097 + 1.2098 + // Define the traits that will be used to determine the best data type to work with. 1.2099 + // 1.2100 + template<typename T> struct type { 1.2101 + static const char* string() { 1.2102 + static const char* s[] = { "unknown", "unknown8", "unknown16", "unknown24", 1.2103 + "unknown32", "unknown40", "unknown48", "unknown56", 1.2104 + "unknown64", "unknown72", "unknown80", "unknown88", 1.2105 + "unknown96", "unknown104", "unknown112", "unknown120", 1.2106 + "unknown128" }; 1.2107 + return s[(sizeof(T)<17)?sizeof(T):0]; 1.2108 + } 1.2109 + static bool is_float() { return false; } 1.2110 + static T min() { return (T)-1>0?(T)0:(T)-1<<(8*sizeof(T)-1); } 1.2111 + static T max() { return (T)-1>0?(T)-1:~((T)-1<<(8*sizeof(T)-1)); } 1.2112 + static const char* format() { return "%s"; } 1.2113 + static const char* format(const T val) { static const char *s = "unknown"; return s; } 1.2114 + }; 1.2115 + 1.2116 + template<> struct type<bool> { 1.2117 + static const char* string() { static const char *const s = "bool"; return s; } 1.2118 + static bool is_float() { return false; } 1.2119 + static bool min() { return false; } 1.2120 + static bool max() { return true; } 1.2121 + static const char* format() { return "%s"; } 1.2122 + static const char* format(const bool val) { static const char* s[] = { "false", "true" }; return s[val?1:0]; } 1.2123 + }; 1.2124 + 1.2125 + template<> struct type<unsigned char> { 1.2126 + static const char* string() { static const char *const s = "unsigned char"; return s; } 1.2127 + static bool is_float() { return false; } 1.2128 + static unsigned char min() { return 0; } 1.2129 + static unsigned char max() { return (unsigned char)~0U; } 1.2130 + static const char* format() { return "%u"; } 1.2131 + static unsigned int format(const unsigned char val) { return (unsigned int)val; } 1.2132 + }; 1.2133 + 1.2134 + template<> struct type<char> { 1.2135 + static const char* string() { static const char *const s = "char"; return s; } 1.2136 + static bool is_float() { return false; } 1.2137 + static char min() { return (char)(-1L<<(8*sizeof(char)-1)); } 1.2138 + static char max() { return ~((char)(-1L<<(8*sizeof(char)-1))); } 1.2139 + static const char* format() { return "%d"; } 1.2140 + static int format(const char val) { return (int)val; } 1.2141 + }; 1.2142 + 1.2143 + template<> struct type<signed char> { 1.2144 + static const char* string() { static const char *const s = "signed char"; return s; } 1.2145 + static bool is_float() { return false; } 1.2146 + static signed char min() { return (signed char)(-1L<<(8*sizeof(signed char)-1)); } 1.2147 + static signed char max() { return ~((signed char)(-1L<<(8*sizeof(signed char)-1))); } 1.2148 + static const char* format() { return "%d"; } 1.2149 + static unsigned int format(const signed char val) { return (int)val; } 1.2150 + }; 1.2151 + 1.2152 + template<> struct type<unsigned short> { 1.2153 + static const char* string() { static const char *const s = "unsigned short"; return s; } 1.2154 + static bool is_float() { return false; } 1.2155 + static unsigned short min() { return 0; } 1.2156 + static unsigned short max() { return (unsigned short)~0U; } 1.2157 + static const char* format() { return "%u"; } 1.2158 + static unsigned int format(const unsigned short val) { return (unsigned int)val; } 1.2159 + }; 1.2160 + 1.2161 + template<> struct type<short> { 1.2162 + static const char* string() { static const char *const s = "short"; return s; } 1.2163 + static bool is_float() { return false; } 1.2164 + static short min() { return (short)(-1L<<(8*sizeof(short)-1)); } 1.2165 + static short max() { return ~((short)(-1L<<(8*sizeof(short)-1))); } 1.2166 + static const char* format() { return "%d"; } 1.2167 + static int format(const short val) { return (int)val; } 1.2168 + }; 1.2169 + 1.2170 + template<> struct type<unsigned int> { 1.2171 + static const char* string() { static const char *const s = "unsigned int"; return s; } 1.2172 + static bool is_float() { return false; } 1.2173 + static unsigned int min() { return 0; } 1.2174 + static unsigned int max() { return (unsigned int)~0U; } 1.2175 + static const char* format() { return "%u"; } 1.2176 + static unsigned int format(const unsigned int val) { return val; } 1.2177 + }; 1.2178 + 1.2179 + template<> struct type<int> { 1.2180 + static const char* string() { static const char *const s = "int"; return s; } 1.2181 + static bool is_float() { return false; } 1.2182 + static int min() { return (int)(-1L<<(8*sizeof(int)-1)); } 1.2183 + static int max() { return ~((int)(-1L<<(8*sizeof(int)-1))); } 1.2184 + static const char* format() { return "%d"; } 1.2185 + static int format(const int val) { return val; } 1.2186 + }; 1.2187 + 1.2188 + template<> struct type<unsigned long> { 1.2189 + static const char* string() { static const char *const s = "unsigned long"; return s; } 1.2190 + static bool is_float() { return false; } 1.2191 + static unsigned long min() { return 0; } 1.2192 + static unsigned long max() { return (unsigned long)~0UL; } 1.2193 + static const char* format() { return "%lu"; } 1.2194 + static unsigned long format(const unsigned long val) { return val; } 1.2195 + }; 1.2196 + 1.2197 + template<> struct type<long> { 1.2198 + static const char* string() { static const char *const s = "long"; return s; } 1.2199 + static bool is_float() { return false; } 1.2200 + static long min() { return (long)(-1L<<(8*sizeof(long)-1)); } 1.2201 + static long max() { return ~((long)(-1L<<(8*sizeof(long)-1))); } 1.2202 + static const char* format() { return "%ld"; } 1.2203 + static long format(const long val) { return val; } 1.2204 + }; 1.2205 + 1.2206 + template<> struct type<float> { 1.2207 + static const char* string() { static const char *const s = "float"; return s; } 1.2208 + static bool is_float() { return true; } 1.2209 + static float min() { return -3.4E38f; } 1.2210 + static float max() { return 3.4E38f; } 1.2211 + static const char* format() { return "%g"; } 1.2212 + static double format(const float val) { return (double)val; } 1.2213 + }; 1.2214 + 1.2215 + template<> struct type<double> { 1.2216 + static const char* string() { static const char *const s = "double"; return s; } 1.2217 + static bool is_float() { return true; } 1.2218 + static double min() { return -1.7E308; } 1.2219 + static double max() { return 1.7E308; } 1.2220 + static const char* format() { return "%g"; } 1.2221 + static double format(const double val) { return val; } 1.2222 + }; 1.2223 + 1.2224 + template<typename T, typename t> struct superset { typedef T type; }; 1.2225 + template<> struct superset<bool,unsigned char> { typedef unsigned char type; }; 1.2226 + template<> struct superset<bool,char> { typedef char type; }; 1.2227 + template<> struct superset<bool,signed char> { typedef signed char type; }; 1.2228 + template<> struct superset<bool,unsigned short> { typedef unsigned short type; }; 1.2229 + template<> struct superset<bool,short> { typedef short type; }; 1.2230 + template<> struct superset<bool,unsigned int> { typedef unsigned int type; }; 1.2231 + template<> struct superset<bool,int> { typedef int type; }; 1.2232 + template<> struct superset<bool,unsigned long> { typedef unsigned long type; }; 1.2233 + template<> struct superset<bool,long> { typedef long type; }; 1.2234 + template<> struct superset<bool,float> { typedef float type; }; 1.2235 + template<> struct superset<bool,double> { typedef double type; }; 1.2236 + template<> struct superset<unsigned char,char> { typedef short type; }; 1.2237 + template<> struct superset<unsigned char,signed char> { typedef short type; }; 1.2238 + template<> struct superset<unsigned char,unsigned short> { typedef unsigned short type; }; 1.2239 + template<> struct superset<unsigned char,short> { typedef short type; }; 1.2240 + template<> struct superset<unsigned char,unsigned int> { typedef unsigned int type; }; 1.2241 + template<> struct superset<unsigned char,int> { typedef int type; }; 1.2242 + template<> struct superset<unsigned char,unsigned long> { typedef unsigned long type; }; 1.2243 + template<> struct superset<unsigned char,long> { typedef long type; }; 1.2244 + template<> struct superset<unsigned char,float> { typedef float type; }; 1.2245 + template<> struct superset<unsigned char,double> { typedef double type; }; 1.2246 + template<> struct superset<signed char,unsigned char> { typedef short type; }; 1.2247 + template<> struct superset<signed char,char> { typedef short type; }; 1.2248 + template<> struct superset<signed char,unsigned short> { typedef int type; }; 1.2249 + template<> struct superset<signed char,short> { typedef short type; }; 1.2250 + template<> struct superset<signed char,unsigned int> { typedef long type; }; 1.2251 + template<> struct superset<signed char,int> { typedef int type; }; 1.2252 + template<> struct superset<signed char,unsigned long> { typedef long type; }; 1.2253 + template<> struct superset<signed char,long> { typedef long type; }; 1.2254 + template<> struct superset<signed char,float> { typedef float type; }; 1.2255 + template<> struct superset<signed char,double> { typedef double type; }; 1.2256 + template<> struct superset<char,unsigned char> { typedef short type; }; 1.2257 + template<> struct superset<char,signed char> { typedef short type; }; 1.2258 + template<> struct superset<char,unsigned short> { typedef int type; }; 1.2259 + template<> struct superset<char,short> { typedef short type; }; 1.2260 + template<> struct superset<char,unsigned int> { typedef long type; }; 1.2261 + template<> struct superset<char,int> { typedef int type; }; 1.2262 + template<> struct superset<char,unsigned long> { typedef long type; }; 1.2263 + template<> struct superset<char,long> { typedef long type; }; 1.2264 + template<> struct superset<char,float> { typedef float type; }; 1.2265 + template<> struct superset<char,double> { typedef double type; }; 1.2266 + template<> struct superset<unsigned short,char> { typedef int type; }; 1.2267 + template<> struct superset<unsigned short,signed char> { typedef int type; }; 1.2268 + template<> struct superset<unsigned short,short> { typedef int type; }; 1.2269 + template<> struct superset<unsigned short,unsigned int> { typedef unsigned int type; }; 1.2270 + template<> struct superset<unsigned short,int> { typedef int type; }; 1.2271 + template<> struct superset<unsigned short,unsigned long> { typedef unsigned long type; }; 1.2272 + template<> struct superset<unsigned short,long> { typedef long type; }; 1.2273 + template<> struct superset<unsigned short,float> { typedef float type; }; 1.2274 + template<> struct superset<unsigned short,double> { typedef double type; }; 1.2275 + template<> struct superset<short,unsigned short> { typedef int type; }; 1.2276 + template<> struct superset<short,unsigned int> { typedef long type; }; 1.2277 + template<> struct superset<short,int> { typedef int type; }; 1.2278 + template<> struct superset<short,unsigned long> { typedef long type; }; 1.2279 + template<> struct superset<short,long> { typedef long type; }; 1.2280 + template<> struct superset<short,float> { typedef float type; }; 1.2281 + template<> struct superset<short,double> { typedef double type; }; 1.2282 + template<> struct superset<unsigned int,char> { typedef long type; }; 1.2283 + template<> struct superset<unsigned int,signed char> { typedef long type; }; 1.2284 + template<> struct superset<unsigned int,short> { typedef long type; }; 1.2285 + template<> struct superset<unsigned int,int> { typedef long type; }; 1.2286 + template<> struct superset<unsigned int,unsigned long> { typedef unsigned long type; }; 1.2287 + template<> struct superset<unsigned int,long> { typedef long type; }; 1.2288 + template<> struct superset<unsigned int,float> { typedef float type; }; 1.2289 + template<> struct superset<unsigned int,double> { typedef double type; }; 1.2290 + template<> struct superset<int,unsigned int> { typedef long type; }; 1.2291 + template<> struct superset<int,unsigned long> { typedef long type; }; 1.2292 + template<> struct superset<int,long> { typedef long type; }; 1.2293 + template<> struct superset<int,float> { typedef float type; }; 1.2294 + template<> struct superset<int,double> { typedef double type; }; 1.2295 + template<> struct superset<unsigned long,char> { typedef long type; }; 1.2296 + template<> struct superset<unsigned long,signed char> { typedef long type; }; 1.2297 + template<> struct superset<unsigned long,short> { typedef long type; }; 1.2298 + template<> struct superset<unsigned long,int> { typedef long type; }; 1.2299 + template<> struct superset<unsigned long,long> { typedef long type; }; 1.2300 + template<> struct superset<unsigned long,float> { typedef float type; }; 1.2301 + template<> struct superset<unsigned long,double> { typedef double type; }; 1.2302 + template<> struct superset<long,float> { typedef float type; }; 1.2303 + template<> struct superset<long,double> { typedef double type; }; 1.2304 + template<> struct superset<float,double> { typedef double type; }; 1.2305 + 1.2306 + template<typename t1, typename t2, typename t3> struct superset2 { 1.2307 + typedef typename superset<t1, typename superset<t2,t3>::type>::type type; 1.2308 + }; 1.2309 + 1.2310 + template<typename t1, typename t2, typename t3, typename t4> struct superset3 { 1.2311 + typedef typename superset<t1, typename superset2<t2,t3,t4>::type>::type type; 1.2312 + }; 1.2313 + 1.2314 + template<typename t1, typename t2> struct last { typedef t2 type; }; 1.2315 + 1.2316 +#define _cimg_Tuchar typename cimg::superset<T,unsigned char>::type 1.2317 +#define _cimg_Tint typename cimg::superset<T,int>::type 1.2318 +#define _cimg_Tfloat typename cimg::superset<T,float>::type 1.2319 +#define _cimg_Tdouble typename cimg::superset<T,double>::type 1.2320 +#define _cimg_Tt typename cimg::superset<T,t>::type 1.2321 + 1.2322 + // Define internal library variables. 1.2323 + // 1.2324 +#if cimg_display==1 1.2325 + struct X11info { 1.2326 + volatile unsigned int nb_wins; 1.2327 + pthread_t* event_thread; 1.2328 + CImgDisplay* wins[1024]; 1.2329 + Display* display; 1.2330 + unsigned int nb_bits; 1.2331 + GC* gc; 1.2332 + bool blue_first; 1.2333 + bool byte_order; 1.2334 + bool shm_enabled; 1.2335 +#ifdef cimg_use_xrandr 1.2336 + XRRScreenSize *resolutions; 1.2337 + Rotation curr_rotation; 1.2338 + unsigned int curr_resolution; 1.2339 + unsigned int nb_resolutions; 1.2340 +#endif 1.2341 + X11info():nb_wins(0),event_thread(0),display(0), 1.2342 + nb_bits(0),gc(0),blue_first(false),byte_order(false),shm_enabled(false) { 1.2343 +#ifdef cimg_use_xrandr 1.2344 + resolutions = 0; 1.2345 + curr_rotation = 0; 1.2346 + curr_resolution = nb_resolutions = 0; 1.2347 +#endif 1.2348 + } 1.2349 + }; 1.2350 +#if defined(cimg_module) 1.2351 + X11info& X11attr(); 1.2352 +#elif defined(cimg_main) 1.2353 + X11info& X11attr() { static X11info val; return val; } 1.2354 +#else 1.2355 + inline X11info& X11attr() { static X11info val; return val; } 1.2356 +#endif 1.2357 + 1.2358 +#elif cimg_display==2 1.2359 + struct Win32info { 1.2360 + HANDLE wait_event; 1.2361 + Win32info() { wait_event = CreateEvent(0,FALSE,FALSE,0); } 1.2362 + }; 1.2363 +#if defined(cimg_module) 1.2364 + Win32info& Win32attr(); 1.2365 +#elif defined(cimg_main) 1.2366 + Win32info& Win32attr() { static Win32info val; return val; } 1.2367 +#else 1.2368 + inline Win32info& Win32attr() { static Win32info val; return val; } 1.2369 +#endif 1.2370 + 1.2371 +#elif cimg_display==3 1.2372 + struct CarbonInfo { 1.2373 + MPCriticalRegionID windowListCR; // Protects access to the list of windows 1.2374 + int windowCount; // Count of displays used on the screen 1.2375 + pthread_t event_thread; // The background event thread 1.2376 + MPSemaphoreID sync_event; // Event used to perform tasks synchronizations 1.2377 + MPSemaphoreID wait_event; // Event used to notify that new events occured on the display 1.2378 + MPQueueID com_queue; // The message queue 1.2379 + CarbonInfo(): windowCount(0),event_thread(0),sync_event(0),com_queue(0) { 1.2380 + if (MPCreateCriticalRegion(&windowListCR) != noErr) // Create the critical region 1.2381 + throw CImgDisplayException("MPCreateCriticalRegion failed."); 1.2382 + if (MPCreateSemaphore(1, 0, &sync_event) != noErr) // Create the inter-thread sync object 1.2383 + throw CImgDisplayException("MPCreateSemaphore failed."); 1.2384 + if (MPCreateSemaphore(1, 0, &wait_event) != noErr) // Create the event sync object 1.2385 + throw CImgDisplayException("MPCreateSemaphore failed."); 1.2386 + if (MPCreateQueue(&com_queue) != noErr) // Create the shared queue 1.2387 + throw CImgDisplayException("MPCreateQueue failed."); 1.2388 + } 1.2389 + ~CarbonInfo() { 1.2390 + if (event_thread != 0) { // Terminates the resident thread, if needed 1.2391 + pthread_cancel(event_thread); 1.2392 + pthread_join(event_thread, NULL); 1.2393 + event_thread = 0; 1.2394 + } 1.2395 + if (MPDeleteCriticalRegion(windowListCR) != noErr) // Delete the critical region 1.2396 + throw CImgDisplayException("MPDeleteCriticalRegion failed."); 1.2397 + if (MPDeleteSemaphore(wait_event) != noErr) // Delete the event sync event 1.2398 + throw CImgDisplayException("MPDeleteEvent failed."); 1.2399 + if (MPDeleteSemaphore(sync_event) != noErr) // Delete the inter-thread sync event 1.2400 + throw CImgDisplayException("MPDeleteEvent failed."); 1.2401 + if (MPDeleteQueue(com_queue) != noErr) // Delete the shared queue 1.2402 + throw CImgDisplayException("MPDeleteQueue failed."); 1.2403 + } 1.2404 + }; 1.2405 +#if defined(cimg_module) 1.2406 + CarbonInfo& CarbonAttr(); 1.2407 +#elif defined(cimg_main) 1.2408 + CarbonInfo CarbonAttr() { static CarbonInfo val; return val; } 1.2409 +#else 1.2410 + inline CarbonInfo& CarbonAttr() { static CarbonInfo val; return val; } 1.2411 +#endif 1.2412 +#endif 1.2413 + 1.2414 +#if cimg_display==1 1.2415 + // Keycodes for X11-based graphical systems. 1.2416 + // 1.2417 + const unsigned int keyESC = XK_Escape; 1.2418 + const unsigned int keyF1 = XK_F1; 1.2419 + const unsigned int keyF2 = XK_F2; 1.2420 + const unsigned int keyF3 = XK_F3; 1.2421 + const unsigned int keyF4 = XK_F4; 1.2422 + const unsigned int keyF5 = XK_F5; 1.2423 + const unsigned int keyF6 = XK_F6; 1.2424 + const unsigned int keyF7 = XK_F7; 1.2425 + const unsigned int keyF8 = XK_F8; 1.2426 + const unsigned int keyF9 = XK_F9; 1.2427 + const unsigned int keyF10 = XK_F10; 1.2428 + const unsigned int keyF11 = XK_F11; 1.2429 + const unsigned int keyF12 = XK_F12; 1.2430 + const unsigned int keyPAUSE = XK_Pause; 1.2431 + const unsigned int key1 = XK_1; 1.2432 + const unsigned int key2 = XK_2; 1.2433 + const unsigned int key3 = XK_3; 1.2434 + const unsigned int key4 = XK_4; 1.2435 + const unsigned int key5 = XK_5; 1.2436 + const unsigned int key6 = XK_6; 1.2437 + const unsigned int key7 = XK_7; 1.2438 + const unsigned int key8 = XK_8; 1.2439 + const unsigned int key9 = XK_9; 1.2440 + const unsigned int key0 = XK_0; 1.2441 + const unsigned int keyBACKSPACE = XK_BackSpace; 1.2442 + const unsigned int keyINSERT = XK_Insert; 1.2443 + const unsigned int keyHOME = XK_Home; 1.2444 + const unsigned int keyPAGEUP = XK_Page_Up; 1.2445 + const unsigned int keyTAB = XK_Tab; 1.2446 + const unsigned int keyQ = XK_q; 1.2447 + const unsigned int keyW = XK_w; 1.2448 + const unsigned int keyE = XK_e; 1.2449 + const unsigned int keyR = XK_r; 1.2450 + const unsigned int keyT = XK_t; 1.2451 + const unsigned int keyY = XK_y; 1.2452 + const unsigned int keyU = XK_u; 1.2453 + const unsigned int keyI = XK_i; 1.2454 + const unsigned int keyO = XK_o; 1.2455 + const unsigned int keyP = XK_p; 1.2456 + const unsigned int keyDELETE = XK_Delete; 1.2457 + const unsigned int keyEND = XK_End; 1.2458 + const unsigned int keyPAGEDOWN = XK_Page_Down; 1.2459 + const unsigned int keyCAPSLOCK = XK_Caps_Lock; 1.2460 + const unsigned int keyA = XK_a; 1.2461 + const unsigned int keyS = XK_s; 1.2462 + const unsigned int keyD = XK_d; 1.2463 + const unsigned int keyF = XK_f; 1.2464 + const unsigned int keyG = XK_g; 1.2465 + const unsigned int keyH = XK_h; 1.2466 + const unsigned int keyJ = XK_j; 1.2467 + const unsigned int keyK = XK_k; 1.2468 + const unsigned int keyL = XK_l; 1.2469 + const unsigned int keyENTER = XK_Return; 1.2470 + const unsigned int keySHIFTLEFT = XK_Shift_L; 1.2471 + const unsigned int keyZ = XK_z; 1.2472 + const unsigned int keyX = XK_x; 1.2473 + const unsigned int keyC = XK_c; 1.2474 + const unsigned int keyV = XK_v; 1.2475 + const unsigned int keyB = XK_b; 1.2476 + const unsigned int keyN = XK_n; 1.2477 + const unsigned int keyM = XK_m; 1.2478 + const unsigned int keySHIFTRIGHT = XK_Shift_R; 1.2479 + const unsigned int keyARROWUP = XK_Up; 1.2480 + const unsigned int keyCTRLLEFT = XK_Control_L; 1.2481 + const unsigned int keyAPPLEFT = XK_Super_L; 1.2482 + const unsigned int keyALT = XK_Alt_L; 1.2483 + const unsigned int keySPACE = XK_space; 1.2484 + const unsigned int keyALTGR = XK_Alt_R; 1.2485 + const unsigned int keyAPPRIGHT = XK_Super_R; 1.2486 + const unsigned int keyMENU = XK_Menu; 1.2487 + const unsigned int keyCTRLRIGHT = XK_Control_R; 1.2488 + const unsigned int keyARROWLEFT = XK_Left; 1.2489 + const unsigned int keyARROWDOWN = XK_Down; 1.2490 + const unsigned int keyARROWRIGHT = XK_Right; 1.2491 + const unsigned int keyPAD0 = XK_KP_0; 1.2492 + const unsigned int keyPAD1 = XK_KP_1; 1.2493 + const unsigned int keyPAD2 = XK_KP_2; 1.2494 + const unsigned int keyPAD3 = XK_KP_3; 1.2495 + const unsigned int keyPAD4 = XK_KP_4; 1.2496 + const unsigned int keyPAD5 = XK_KP_5; 1.2497 + const unsigned int keyPAD6 = XK_KP_6; 1.2498 + const unsigned int keyPAD7 = XK_KP_7; 1.2499 + const unsigned int keyPAD8 = XK_KP_8; 1.2500 + const unsigned int keyPAD9 = XK_KP_9; 1.2501 + const unsigned int keyPADADD = XK_KP_Add; 1.2502 + const unsigned int keyPADSUB = XK_KP_Subtract; 1.2503 + const unsigned int keyPADMUL = XK_KP_Multiply; 1.2504 + const unsigned int keyPADDIV = XK_KP_Divide; 1.2505 + 1.2506 +#elif cimg_display==2 1.2507 + // Keycodes for Windows. 1.2508 + // 1.2509 + const unsigned int keyESC = VK_ESCAPE; 1.2510 + const unsigned int keyF1 = VK_F1; 1.2511 + const unsigned int keyF2 = VK_F2; 1.2512 + const unsigned int keyF3 = VK_F3; 1.2513 + const unsigned int keyF4 = VK_F4; 1.2514 + const unsigned int keyF5 = VK_F5; 1.2515 + const unsigned int keyF6 = VK_F6; 1.2516 + const unsigned int keyF7 = VK_F7; 1.2517 + const unsigned int keyF8 = VK_F8; 1.2518 + const unsigned int keyF9 = VK_F9; 1.2519 + const unsigned int keyF10 = VK_F10; 1.2520 + const unsigned int keyF11 = VK_F11; 1.2521 + const unsigned int keyF12 = VK_F12; 1.2522 + const unsigned int keyPAUSE = VK_PAUSE; 1.2523 + const unsigned int key1 = '1'; 1.2524 + const unsigned int key2 = '2'; 1.2525 + const unsigned int key3 = '3'; 1.2526 + const unsigned int key4 = '4'; 1.2527 + const unsigned int key5 = '5'; 1.2528 + const unsigned int key6 = '6'; 1.2529 + const unsigned int key7 = '7'; 1.2530 + const unsigned int key8 = '8'; 1.2531 + const unsigned int key9 = '9'; 1.2532 + const unsigned int key0 = '0'; 1.2533 + const unsigned int keyBACKSPACE = VK_BACK; 1.2534 + const unsigned int keyINSERT = VK_INSERT; 1.2535 + const unsigned int keyHOME = VK_HOME; 1.2536 + const unsigned int keyPAGEUP = VK_PRIOR; 1.2537 + const unsigned int keyTAB = VK_TAB; 1.2538 + const unsigned int keyQ = 'Q'; 1.2539 + const unsigned int keyW = 'W'; 1.2540 + const unsigned int keyE = 'E'; 1.2541 + const unsigned int keyR = 'R'; 1.2542 + const unsigned int keyT = 'T'; 1.2543 + const unsigned int keyY = 'Y'; 1.2544 + const unsigned int keyU = 'U'; 1.2545 + const unsigned int keyI = 'I'; 1.2546 + const unsigned int keyO = 'O'; 1.2547 + const unsigned int keyP = 'P'; 1.2548 + const unsigned int keyDELETE = VK_DELETE; 1.2549 + const unsigned int keyEND = VK_END; 1.2550 + const unsigned int keyPAGEDOWN = VK_NEXT; 1.2551 + const unsigned int keyCAPSLOCK = VK_CAPITAL; 1.2552 + const unsigned int keyA = 'A'; 1.2553 + const unsigned int keyS = 'S'; 1.2554 + const unsigned int keyD = 'D'; 1.2555 + const unsigned int keyF = 'F'; 1.2556 + const unsigned int keyG = 'G'; 1.2557 + const unsigned int keyH = 'H'; 1.2558 + const unsigned int keyJ = 'J'; 1.2559 + const unsigned int keyK = 'K'; 1.2560 + const unsigned int keyL = 'L'; 1.2561 + const unsigned int keyENTER = VK_RETURN; 1.2562 + const unsigned int keySHIFTLEFT = VK_SHIFT; 1.2563 + const unsigned int keyZ = 'Z'; 1.2564 + const unsigned int keyX = 'X'; 1.2565 + const unsigned int keyC = 'C'; 1.2566 + const unsigned int keyV = 'V'; 1.2567 + const unsigned int keyB = 'B'; 1.2568 + const unsigned int keyN = 'N'; 1.2569 + const unsigned int keyM = 'M'; 1.2570 + const unsigned int keySHIFTRIGHT = VK_SHIFT; 1.2571 + const unsigned int keyARROWUP = VK_UP; 1.2572 + const unsigned int keyCTRLLEFT = VK_CONTROL; 1.2573 + const unsigned int keyAPPLEFT = VK_LWIN; 1.2574 + const unsigned int keyALT = VK_LMENU; 1.2575 + const unsigned int keySPACE = VK_SPACE; 1.2576 + const unsigned int keyALTGR = VK_CONTROL; 1.2577 + const unsigned int keyAPPRIGHT = VK_RWIN; 1.2578 + const unsigned int keyMENU = VK_APPS; 1.2579 + const unsigned int keyCTRLRIGHT = VK_CONTROL; 1.2580 + const unsigned int keyARROWLEFT = VK_LEFT; 1.2581 + const unsigned int keyARROWDOWN = VK_DOWN; 1.2582 + const unsigned int keyARROWRIGHT = VK_RIGHT; 1.2583 + const unsigned int keyPAD0 = 0x60; 1.2584 + const unsigned int keyPAD1 = 0x61; 1.2585 + const unsigned int keyPAD2 = 0x62; 1.2586 + const unsigned int keyPAD3 = 0x63; 1.2587 + const unsigned int keyPAD4 = 0x64; 1.2588 + const unsigned int keyPAD5 = 0x65; 1.2589 + const unsigned int keyPAD6 = 0x66; 1.2590 + const unsigned int keyPAD7 = 0x67; 1.2591 + const unsigned int keyPAD8 = 0x68; 1.2592 + const unsigned int keyPAD9 = 0x69; 1.2593 + const unsigned int keyPADADD = VK_ADD; 1.2594 + const unsigned int keyPADSUB = VK_SUBTRACT; 1.2595 + const unsigned int keyPADMUL = VK_MULTIPLY; 1.2596 + const unsigned int keyPADDIV = VK_DIVIDE; 1.2597 + 1.2598 +#elif cimg_display==3 1.2599 + // Keycodes for MacOSX, when using the Carbon framework. 1.2600 + // 1.2601 + const unsigned int keyESC = kEscapeCharCode; 1.2602 + const unsigned int keyF1 = 2U; 1.2603 + const unsigned int keyF2 = 3U; 1.2604 + const unsigned int keyF3 = 4U; 1.2605 + const unsigned int keyF4 = 5U; 1.2606 + const unsigned int keyF5 = 6U; 1.2607 + const unsigned int keyF6 = 7U; 1.2608 + const unsigned int keyF7 = 8U; 1.2609 + const unsigned int keyF8 = 9U; 1.2610 + const unsigned int keyF9 = 10U; 1.2611 + const unsigned int keyF10 = 11U; 1.2612 + const unsigned int keyF11 = 12U; 1.2613 + const unsigned int keyF12 = 13U; 1.2614 + const unsigned int keyPAUSE = 14U; 1.2615 + const unsigned int key1 = '1'; 1.2616 + const unsigned int key2 = '2'; 1.2617 + const unsigned int key3 = '3'; 1.2618 + const unsigned int key4 = '4'; 1.2619 + const unsigned int key5 = '5'; 1.2620 + const unsigned int key6 = '6'; 1.2621 + const unsigned int key7 = '7'; 1.2622 + const unsigned int key8 = '8'; 1.2623 + const unsigned int key9 = '9'; 1.2624 + const unsigned int key0 = '0'; 1.2625 + const unsigned int keyBACKSPACE = kBackspaceCharCode; 1.2626 + const unsigned int keyINSERT = 26U; 1.2627 + const unsigned int keyHOME = kHomeCharCode; 1.2628 + const unsigned int keyPAGEUP = kPageUpCharCode; 1.2629 + const unsigned int keyTAB = kTabCharCode; 1.2630 + const unsigned int keyQ = 'q'; 1.2631 + const unsigned int keyW = 'w'; 1.2632 + const unsigned int keyE = 'e'; 1.2633 + const unsigned int keyR = 'r'; 1.2634 + const unsigned int keyT = 't'; 1.2635 + const unsigned int keyY = 'y'; 1.2636 + const unsigned int keyU = 'u'; 1.2637 + const unsigned int keyI = 'i'; 1.2638 + const unsigned int keyO = 'o'; 1.2639 + const unsigned int keyP = 'p'; 1.2640 + const unsigned int keyDELETE = kDeleteCharCode; 1.2641 + const unsigned int keyEND = kEndCharCode; 1.2642 + const unsigned int keyPAGEDOWN = kPageDownCharCode; 1.2643 + const unsigned int keyCAPSLOCK = 43U; 1.2644 + const unsigned int keyA = 'a'; 1.2645 + const unsigned int keyS = 's'; 1.2646 + const unsigned int keyD = 'd'; 1.2647 + const unsigned int keyF = 'f'; 1.2648 + const unsigned int keyG = 'g'; 1.2649 + const unsigned int keyH = 'h'; 1.2650 + const unsigned int keyJ = 'j'; 1.2651 + const unsigned int keyK = 'k'; 1.2652 + const unsigned int keyL = 'l'; 1.2653 + const unsigned int keyENTER = kEnterCharCode; 1.2654 + const unsigned int keySHIFTLEFT = 54U; //Macintosh modifier key, emulated 1.2655 + const unsigned int keyZ = 'z'; 1.2656 + const unsigned int keyX = 'x'; 1.2657 + const unsigned int keyC = 'c'; 1.2658 + const unsigned int keyV = 'v'; 1.2659 + const unsigned int keyB = 'b'; 1.2660 + const unsigned int keyN = 'n'; 1.2661 + const unsigned int keyM = 'm'; 1.2662 + const unsigned int keySHIFTRIGHT = 62U; //Macintosh modifier key, emulated 1.2663 + const unsigned int keyARROWUP = kUpArrowCharCode; 1.2664 + const unsigned int keyCTRLLEFT = 64U; //Macintosh modifier key, emulated 1.2665 + const unsigned int keyAPPLEFT = 65U; //Macintosh modifier key, emulated 1.2666 + const unsigned int keyALT = 66U; 1.2667 + const unsigned int keySPACE = kSpaceCharCode; 1.2668 + const unsigned int keyALTGR = 67U; //Macintosh modifier key, emulated 1.2669 + const unsigned int keyAPPRIGHT = 68U; //Aliased on keyAPPLEFT 1.2670 + const unsigned int keyMENU = 69U; 1.2671 + const unsigned int keyCTRLRIGHT = 70U; //Macintosh modifier key, emulated 1.2672 + const unsigned int keyARROWLEFT = kLeftArrowCharCode; 1.2673 + const unsigned int keyARROWDOWN = kDownArrowCharCode; 1.2674 + const unsigned int keyARROWRIGHT = kRightArrowCharCode; 1.2675 + const unsigned int keyPAD0 = 74U; 1.2676 + const unsigned int keyPAD1 = 75U; 1.2677 + const unsigned int keyPAD2 = 76U; 1.2678 + const unsigned int keyPAD3 = 77U; 1.2679 + const unsigned int keyPAD4 = 78U; 1.2680 + const unsigned int keyPAD5 = 79U; 1.2681 + const unsigned int keyPAD6 = 80U; 1.2682 + const unsigned int keyPAD7 = 81U; 1.2683 + const unsigned int keyPAD8 = 82U; 1.2684 + const unsigned int keyPAD9 = 83U; 1.2685 + const unsigned int keyPADADD = 84U; 1.2686 + const unsigned int keyPADSUB = 85U; 1.2687 + const unsigned int keyPADMUL = 86U; 1.2688 + const unsigned int keyPADDIV = 87U; 1.2689 + 1.2690 +#else 1.2691 + // Define unknow keycodes when no display are available. 1.2692 + // (should rarely be used then !). 1.2693 + // 1.2694 + const unsigned int keyESC = 1U; 1.2695 + const unsigned int keyF1 = 2U; 1.2696 + const unsigned int keyF2 = 3U; 1.2697 + const unsigned int keyF3 = 4U; 1.2698 + const unsigned int keyF4 = 5U; 1.2699 + const unsigned int keyF5 = 6U; 1.2700 + const unsigned int keyF6 = 7U; 1.2701 + const unsigned int keyF7 = 8U; 1.2702 + const unsigned int keyF8 = 9U; 1.2703 + const unsigned int keyF9 = 10U; 1.2704 + const unsigned int keyF10 = 11U; 1.2705 + const unsigned int keyF11 = 12U; 1.2706 + const unsigned int keyF12 = 13U; 1.2707 + const unsigned int keyPAUSE = 14U; 1.2708 + const unsigned int key1 = 15U; 1.2709 + const unsigned int key2 = 16U; 1.2710 + const unsigned int key3 = 17U; 1.2711 + const unsigned int key4 = 18U; 1.2712 + const unsigned int key5 = 19U; 1.2713 + const unsigned int key6 = 20U; 1.2714 + const unsigned int key7 = 21U; 1.2715 + const unsigned int key8 = 22U; 1.2716 + const unsigned int key9 = 23U; 1.2717 + const unsigned int key0 = 24U; 1.2718 + const unsigned int keyBACKSPACE = 25U; 1.2719 + const unsigned int keyINSERT = 26U; 1.2720 + const unsigned int keyHOME = 27U; 1.2721 + const unsigned int keyPAGEUP = 28U; 1.2722 + const unsigned int keyTAB = 29U; 1.2723 + const unsigned int keyQ = 30U; 1.2724 + const unsigned int keyW = 31U; 1.2725 + const unsigned int keyE = 32U; 1.2726 + const unsigned int keyR = 33U; 1.2727 + const unsigned int keyT = 34U; 1.2728 + const unsigned int keyY = 35U; 1.2729 + const unsigned int keyU = 36U; 1.2730 + const unsigned int keyI = 37U; 1.2731 + const unsigned int keyO = 38U; 1.2732 + const unsigned int keyP = 39U; 1.2733 + const unsigned int keyDELETE = 40U; 1.2734 + const unsigned int keyEND = 41U; 1.2735 + const unsigned int keyPAGEDOWN = 42U; 1.2736 + const unsigned int keyCAPSLOCK = 43U; 1.2737 + const unsigned int keyA = 44U; 1.2738 + const unsigned int keyS = 45U; 1.2739 + const unsigned int keyD = 46U; 1.2740 + const unsigned int keyF = 47U; 1.2741 + const unsigned int keyG = 48U; 1.2742 + const unsigned int keyH = 49U; 1.2743 + const unsigned int keyJ = 50U; 1.2744 + const unsigned int keyK = 51U; 1.2745 + const unsigned int keyL = 52U; 1.2746 + const unsigned int keyENTER = 53U; 1.2747 + const unsigned int keySHIFTLEFT = 54U; 1.2748 + const unsigned int keyZ = 55U; 1.2749 + const unsigned int keyX = 56U; 1.2750 + const unsigned int keyC = 57U; 1.2751 + const unsigned int keyV = 58U; 1.2752 + const unsigned int keyB = 59U; 1.2753 + const unsigned int keyN = 60U; 1.2754 + const unsigned int keyM = 61U; 1.2755 + const unsigned int keySHIFTRIGHT = 62U; 1.2756 + const unsigned int keyARROWUP = 63U; 1.2757 + const unsigned int keyCTRLLEFT = 64U; 1.2758 + const unsigned int keyAPPLEFT = 65U; 1.2759 + const unsigned int keyALT = 66U; 1.2760 + const unsigned int keySPACE = 67U; 1.2761 + const unsigned int keyALTGR = 68U; 1.2762 + const unsigned int keyAPPRIGHT = 69U; 1.2763 + const unsigned int keyMENU = 70U; 1.2764 + const unsigned int keyCTRLRIGHT = 71U; 1.2765 + const unsigned int keyARROWLEFT = 72U; 1.2766 + const unsigned int keyARROWDOWN = 73U; 1.2767 + const unsigned int keyARROWRIGHT = 74U; 1.2768 + const unsigned int keyPAD0 = 75U; 1.2769 + const unsigned int keyPAD1 = 76U; 1.2770 + const unsigned int keyPAD2 = 77U; 1.2771 + const unsigned int keyPAD3 = 78U; 1.2772 + const unsigned int keyPAD4 = 79U; 1.2773 + const unsigned int keyPAD5 = 80U; 1.2774 + const unsigned int keyPAD6 = 81U; 1.2775 + const unsigned int keyPAD7 = 82U; 1.2776 + const unsigned int keyPAD8 = 83U; 1.2777 + const unsigned int keyPAD9 = 84U; 1.2778 + const unsigned int keyPADADD = 85U; 1.2779 + const unsigned int keyPADSUB = 86U; 1.2780 + const unsigned int keyPADMUL = 87U; 1.2781 + const unsigned int keyPADDIV = 88U; 1.2782 +#endif 1.2783 + 1.2784 + const double valuePI = 3.14159265358979323846; //!< Definition of the mathematical constant PI 1.2785 + 1.2786 + // Definition of a 7x11 font, used to return a default font for drawing text. 1.2787 + const unsigned int font7x11[7*11*256/32] = { 1.2788 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2789 + 0x0,0x0,0x0,0x0,0x0,0x0,0x90,0x0,0x7f0000,0x40000,0x0,0x0,0x4010c0a4,0x82000040,0x11848402,0x18480050,0x80430292,0x8023,0x9008000, 1.2790 + 0x40218140,0x4000040,0x21800402,0x18000051,0x1060500,0x8083,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x24002,0x4031,0x80000000,0x10000, 1.2791 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x81c0400,0x40020000,0x80070080,0x40440e00,0x0,0x0,0x1,0x88180000,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2792 + 0x0,0x200000,0x0,0x0,0x80000,0x0,0x0,0x20212140,0x5000020,0x22400204,0x240000a0,0x40848500,0x4044,0x80010038,0x20424285,0xa000020, 1.2793 + 0x42428204,0x2428e0a0,0x82090a14,0x4104,0x85022014,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10240a7,0x88484040,0x40800000,0x270c3,0x87811e0e, 1.2794 + 0x7c70e000,0x78,0x3c23c1ef,0x1f3e1e89,0xf1c44819,0xa23cf0f3,0xc3cff120,0xc18307f4,0x4040400,0x20000,0x80080080,0x40200,0x0, 1.2795 + 0x40000,0x2,0x8040000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8188,0x50603800,0xf3c00000,0x1c004003,0xc700003e,0x18180,0xc993880,0x10204081, 1.2796 + 0x2071ef9,0xf3e7cf9f,0x3e7c7911,0xe3c78f1e,0x7d1224,0x48906048,0x0,0x4000000,0x0,0x9000,0x0,0x0,0x2000,0x0,0x0,0x0,0x0,0x0,0x0, 1.2797 + 0x0,0x10240aa,0x14944080,0x23610000,0x68940,0x40831010,0x8891306,0x802044,0x44522208,0x90202088,0x40448819,0xb242890a,0x24011111, 1.2798 + 0x49448814,0x4040a00,0xe2c3c7,0x8e3f3cb9,0xc1c44216,0xee38b0f2,0xe78f9120,0xc18507e2,0x8040000,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2799 + 0x101c207,0x88a04001,0x9c00000,0x2200a041,0x8200113a,0x8240,0x50a3110,0x2850a142,0x850c2081,0x2040204,0x8104592,0x142850a1, 1.2800 + 0x42cd1224,0x4888bc48,0x70e1c387,0xe3b3c70,0xe1c38e1c,0x38707171,0xc3870e1c,0x10791224,0x48906c41,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2801 + 0x10003ee,0x15140080,0x21810000,0x48840,0x40851020,0x8911306,0x31fd804,0x9c522408,0x90204088,0x4045081a,0xba42890a,0x24011111, 1.2802 + 0x49285024,0x2041b00,0x132408,0x910844c8,0x4044821b,0x7244c913,0x24041111,0x49488822,0x8040000,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2803 + 0x28204,0x85006001,0x6a414000,0x3a004043,0xc700113a,0x8245,0x50a3a00,0x2850a142,0x850c4081,0x2040204,0x81045d2,0x142850a1, 1.2804 + 0x24951224,0x48852250,0x8102040,0x81054089,0x12244204,0x8108992,0x24489122,0x991224,0x4888b222,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2805 + 0x1000143,0xa988080,0x2147c01f,0x88840,0x83091c2c,0x1070f000,0xc000608,0xa48bc408,0x9e3c46f8,0x40460816,0xaa42f10b,0xc3811111, 1.2806 + 0x35102044,0x1041100,0xf22408,0x9f084488,0x40470212,0x62448912,0x6041111,0x55308846,0x8061c80,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2807 + 0x1028704,0x8f805801,0x4be28fdf,0x220001f0,0x111a,0x60000182,0x82c5c710,0x44891224,0x489640f1,0xe3c78204,0x810e552,0x142850a1, 1.2808 + 0x18a51224,0x48822250,0x78f1e3c7,0x8f1f40f9,0xf3e7c204,0x8108912,0x24489122,0x7ea91224,0x4888a222,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2809 + 0x10007e2,0x85648080,0x20010000,0x88841,0x8f8232,0x20881000,0xc1fc610,0xbefa2408,0x90204288,0x40450816,0xa642810a,0x4041110a, 1.2810 + 0x36282084,0x1042080,0x1122408,0x90084488,0x40450212,0x62448912,0x184110a,0x55305082,0x8042700,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2811 + 0x1028207,0x82004801,0x68050040,0x1c000040,0x110a,0x60000001,0x45484d10,0x7cf9f3e7,0xcf944081,0x2040204,0x8104532,0x142850a1, 1.2812 + 0x18a51224,0x48822248,0x89122448,0x91244081,0x2040204,0x8108912,0x24489122,0xc91224,0x48852214,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x282, 1.2813 + 0x89630080,0x20010c00,0x30108842,0x810222,0x20882306,0x3001800,0x408a2208,0x90202288,0x40448814,0xa642810a,0x2041110a,0x26442104, 1.2814 + 0x840000,0x1122408,0x90084488,0x40448212,0x62448912,0x84130a,0x36485102,0x8040000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x101c208,0x4f802801, 1.2815 + 0x8028040,0x40,0x130a,0x2,0x85e897a0,0x44891224,0x489c2081,0x2040204,0x8104532,0x142850a1,0x24cd1224,0x48823c44,0x89122448, 1.2816 + 0x91244081,0x2040204,0x8108912,0x24489122,0xc93264,0xc9852214,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100028f,0x109f0080,0x20010c00, 1.2817 + 0x303071f3,0xc7011c1c,0x4071c306,0x802010,0x3907c1ef,0x1f201e89,0xf3844f90,0xa23c80f2,0x17810e04,0x228223f4,0x840000,0xfbc3c7, 1.2818 + 0x8f083c88,0x40444212,0x6238f0f2,0x7039d04,0x228423e2,0x8040000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1008780,0x2201800,0xf0014000,0x1f0, 1.2819 + 0x1d0a,0x5,0x851e140,0x83060c18,0x30671ef9,0xf3e7cf9f,0x3e7c7911,0xe3c78f1e,0x42f8e1c3,0x8702205c,0x7cf9f3e7,0xcf9b3c78,0xf1e3c204, 1.2820 + 0x8107111,0xc3870e1c,0x10f1d3a7,0x4e823c08,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2,0x40,0x40000400,0x200000,0x0,0x2,0x0,0x0,0x0,0x0,0x18, 1.2821 + 0x0,0x4,0x44007f,0x0,0x400,0x400000,0x8010,0x0,0x6002,0x8040000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000000,0x200800,0x0,0x0,0x100a, 1.2822 + 0x400000,0x44,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x800,0x0,0x0,0x0,0x0,0x62018,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x31,0x80000800, 1.2823 + 0x400000,0x0,0x4,0x0,0x0,0x0,0x0,0xc,0x0,0x7,0x3c0000,0x0,0x3800,0x3800000,0x8010,0x0,0x1c001,0x881c0000,0x0,0x0,0x0,0x0,0x0,0x0, 1.2824 + 0x0,0x0,0x207000,0x0,0x0,0x100a,0xc00000,0x3c,0x0,0xc00,0x0,0x0,0x0,0x0,0x0,0x0,0x1800,0x0,0x0,0x0,0x0,0x1c2070 1.2825 + }; 1.2826 + 1.2827 + // Definition of a 10x13 font (used in dialog boxes). 1.2828 + const unsigned int font10x13[256*10*13/32] = { 1.2829 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2830 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80100c0, 1.2831 + 0x68000300,0x801,0xc00010,0x100c000,0x68100,0x100c0680,0x2,0x403000,0x1000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2832 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2833 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfc,0x0,0x0,0x0,0x0,0x0,0x4020120, 1.2834 + 0x58120480,0x402,0x1205008,0x2012050,0x58080,0x20120581,0x40000001,0x804812,0x2000000,0x0,0x300,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2835 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x140,0x80000,0x200402,0x800000,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2836 + 0x0,0x7010,0x7000000,0x8000200,0x20000,0xc0002000,0x8008,0x0,0x0,0x0,0x0,0x808,0x4000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2837 + 0x0,0x0,0x80000000,0x0,0x0,0x0,0x40000,0x0,0x0,0x0,0x0,0x480,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x70,0x80100c0,0x68000480,0x1001, 1.2838 + 0xc00010,0x1018000,0x68100,0x100c0680,0x4,0x403000,0x1020000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20140,0x28081883,0x200801, 1.2839 + 0x2a00000,0x10,0x1c0201c0,0x70040f80,0xc0f81c07,0x0,0x70,0x3e0303c0,0x3c3c0f83,0xe03c2107,0xe08810,0x18c31070,0x3c0703c0, 1.2840 + 0x783e0842,0x22222208,0x83e04010,0x1008000,0x4000200,0x20001,0x2002,0x408008,0x0,0x0,0x100000,0x0,0x1008,0x2000000,0x0,0x0,0x0, 1.2841 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20080,0x38000880,0x8078140f,0x81c00000,0x3e000,0xc020180,0x60080001,0xe0000002,0xc00042,0x108e2010, 1.2842 + 0xc0300c0,0x300c0303,0xf83c3e0f,0x83e0f81c,0x701c070,0x3c0c41c0,0x701c0701,0xc0001d08,0x42108421,0x8820088,0x4020120,0x58140480, 1.2843 + 0x802,0x1205008,0x3014050,0xc058080,0x20120581,0x40000002,0x804814,0x2020050,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20140, 1.2844 + 0x281e2484,0x80200801,0x1c02000,0x10,0x22060220,0x880c0801,0x82208,0x80000001,0x20008,0x41030220,0x40220802,0x402102,0x209010, 1.2845 + 0x18c31088,0x22088220,0x80080842,0x22222208,0x80204010,0x1014000,0x200,0x20001,0x2000,0x8008,0x0,0x0,0x100000,0x0,0x1008, 1.2846 + 0x2000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x40000500,0x80800010,0x40200000,0x41000,0x12020040,0x10000003,0xa0000006, 1.2847 + 0x12000c4,0x31014000,0xc0300c0,0x300c0302,0x80402008,0x2008008,0x2008020,0x220c4220,0x88220882,0x20002208,0x42108421,0x8820088, 1.2848 + 0x0,0x300,0x0,0x0,0x0,0x14000000,0x0,0x200200,0x0,0x20000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000,0xfc282504,0x80001000, 1.2849 + 0x82a02000,0x20,0x22020020,0x8140802,0x102208,0x80801006,0x18008,0x9c848220,0x80210802,0x802102,0x20a010,0x15429104,0x22104220, 1.2850 + 0x80080842,0x22221405,0x404008,0x1022000,0x703c0,0x381e0701,0xc0783c02,0xc09008,0x1d83c070,0x3c078140,0x381c0882,0x21242208, 1.2851 + 0x81e01008,0x2000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x201e0,0x40220500,0x80800027,0x20e02800,0x9c800,0x12020040, 1.2852 + 0x20000883,0xa0200002,0x120a044,0x11064010,0x12048120,0x48120484,0x80802008,0x2008008,0x2008020,0x210a4411,0x4411044,0x10884508, 1.2853 + 0x42108421,0x503c0b0,0x1c0701c0,0x701c0707,0x70381c07,0x1c07008,0x2008020,0x20f01c0,0x701c0701,0xc0201c08,0x82208822,0x883c088, 1.2854 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000,0x50281903,0x20001000,0x80802000,0x20,0x22020040,0x30240f03,0xc0101c08,0x80801018, 1.2855 + 0x1fc06010,0xa48483c0,0x80210f03,0xe0803f02,0x20c010,0x15429104,0x22104220,0x70080841,0x41540805,0x804008,0x1041000,0x8220, 1.2856 + 0x40220881,0x882202,0x40a008,0x12422088,0x22088180,0x40100882,0x21241408,0x80201008,0x2031000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2857 + 0x0,0x20280,0x401c0200,0x700028,0x21205000,0x92800,0xc1fc080,0x10000883,0xa0200002,0x1205049,0x12c19010,0x12048120,0x48120484, 1.2858 + 0xf0803c0f,0x3c0f008,0x2008020,0x790a4411,0x4411044,0x10504908,0x42108421,0x5022088,0x2008020,0x8020080,0x88402208,0x82208808, 1.2859 + 0x2008020,0x1e088220,0x88220882,0x20002608,0x82208822,0x8822088,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000,0x501c0264, 1.2860 + 0xa0001000,0x8001fc00,0x7000020,0x22020080,0x83e0082,0x20202207,0x80000020,0x1020,0xa4848220,0x80210802,0x9c2102,0x20c010, 1.2861 + 0x12425104,0x3c1043c0,0x8080841,0x41540802,0x804008,0x1000000,0x78220,0x40220f81,0x882202,0x40c008,0x12422088,0x22088100, 1.2862 + 0x60100881,0x41540805,0x406008,0x1849000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20280,0xf0140200,0x880028,0x20e0a03f,0x709c800, 1.2863 + 0x201c0,0x60000881,0xa0000007,0xc0284b,0x122eb020,0x12048120,0x48120487,0x80802008,0x2008008,0x2008020,0x21094411,0x4411044, 1.2864 + 0x10204908,0x42108421,0x2022088,0x1e0781e0,0x781e0787,0xf8403e0f,0x83e0f808,0x2008020,0x22088220,0x88220882,0x21fc2a08,0x82208822, 1.2865 + 0x5022050,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20001,0xf80a0294,0x40001000,0x80002000,0x20,0x22020100,0x8040082,0x20202200, 1.2866 + 0x80000018,0x1fc06020,0xa48fc220,0x80210802,0x842102,0x20a010,0x12425104,0x20104240,0x8080841,0x41541402,0x1004008,0x1000000, 1.2867 + 0x88220,0x40220801,0x882202,0x40a008,0x12422088,0x22088100,0x18100881,0x41540805,0x801008,0x2046000,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2868 + 0x0,0x0,0x0,0x20280,0x401c0f80,0x80880028,0x20005001,0x94800,0x20000,0x880,0xa0000000,0x5015,0x4215040,0x3f0fc3f0,0xfc3f0fc8, 1.2869 + 0x80802008,0x2008008,0x2008020,0x21094411,0x4411044,0x10505108,0x42108421,0x203c088,0x22088220,0x88220888,0x80402008,0x2008008, 1.2870 + 0x2008020,0x22088220,0x88220882,0x20002a08,0x82208822,0x5022050,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xa00a0494,0x60001000, 1.2871 + 0x80002004,0x8020,0x22020200,0x88040882,0x20402201,0x801006,0x18000,0x9f084220,0x40220802,0x442102,0x209010,0x10423088,0x20088220, 1.2872 + 0x8080840,0x80882202,0x2004008,0x1000000,0x88220,0x40220881,0x882202,0x409008,0x12422088,0x22088100,0x8100880,0x80881402, 1.2873 + 0x1001008,0x2000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20280,0x40220200,0x80700027,0x20002801,0x92800,0x1fc000,0x980, 1.2874 + 0xa0000000,0xa017,0x84417840,0x21084210,0x84210848,0x80402008,0x2008008,0x2008020,0x2208c220,0x88220882,0x20882208,0x42108421, 1.2875 + 0x2020088,0x22088220,0x88220888,0xc8402208,0x82208808,0x2008020,0x22088220,0x88220882,0x20203208,0x82208822,0x2022020,0x0,0x0,0x0, 1.2876 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000,0xa03c0463,0x90000801,0x2004,0x8040,0x1c0703e0,0x70040701,0xc0401c06,0x801001,0x20020, 1.2877 + 0x400843c0,0x3c3c0f82,0x3c2107,0x1c0881e,0x10423070,0x20070210,0xf0080780,0x80882202,0x3e04004,0x1000000,0x783c0,0x381e0701, 1.2878 + 0x782202,0x408808,0x12422070,0x3c078100,0x700c0780,0x80882202,0x1e01008,0x2000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x201e0, 1.2879 + 0xf8000200,0x80080010,0x40000001,0x41000,0x0,0xe80,0xa0000000,0x21,0x8e21038,0x21084210,0x84210848,0xf83c3e0f,0x83e0f81c, 1.2880 + 0x701c070,0x3c08c1c0,0x701c0701,0xc0005c07,0x81e0781e,0x20200b0,0x1e0781e0,0x781e0787,0x30381c07,0x1c07008,0x2008020,0x1c0881c0, 1.2881 + 0x701c0701,0xc0201c07,0x81e0781e,0x203c020,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80000,0x801,0x4,0x40,0x0,0x0,0x0,0x1000, 1.2882 + 0x0,0x3c000000,0x0,0x0,0x0,0x0,0x10000,0x0,0x0,0x4004,0x1000000,0x0,0x0,0x80000,0x400000,0x0,0x20008000,0x0,0x4,0x1008,0x2000000, 1.2883 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x0,0x8008000f,0x80000000,0x3e000,0x0,0x800,0xa0000400,0x0,0x0,0x0,0x0,0x80000,0x0, 1.2884 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100000,0x0,0x0,0x0,0x0,0x2000,0x0,0x4020040,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80000, 1.2885 + 0x402,0x8,0x40,0x0,0x0,0x0,0x2000,0x0,0x0,0x0,0x0,0x0,0x0,0xc000,0x0,0x0,0x7004,0x70000fc,0x0,0x0,0x700000,0x800000,0x0,0x20008000, 1.2886 + 0x0,0x4,0x808,0x4000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x0,0x80f00000,0x0,0x0,0x0,0x800,0xa0001800,0x0,0x0,0x0,0x0, 1.2887 + 0x300000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600000,0x0,0x0,0x0,0x0,0x0,0x0,0x4020040 1.2888 + }; 1.2889 + 1.2890 + // Definition of a 8x17 font. 1.2891 + const unsigned int font8x17[8*17*256/32] = { 1.2892 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2893 + 0x0,0x0,0x0,0x2400,0x2400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20081834,0x1c0000,0x20081800,0x20081800,0x342008, 1.2894 + 0x18340000,0x200818,0x80000,0x0,0x180000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4200000,0x0,0x0, 1.2895 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x380000,0x4000,0x2000c00,0x40100840,0x70000000,0x0,0x0,0x1c,0x10700000,0x7,0x0, 1.2896 + 0x1800,0x1800,0x0,0x0,0x0,0x14,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1010242c,0x14140000,0x10102414,0x10102414,0x2c1010,0x242c1400, 1.2897 + 0x101024,0x14100038,0x0,0x240000,0x0,0x0,0x30000000,0x0,0x0,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x12,0x0,0x8100000,0x0, 1.2898 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10,0x80000,0x10004000,0x2001000,0x40000040,0x10000000,0x0,0x0,0x10,0x10100000,0x4, 1.2899 + 0x0,0x18000000,0x0,0x0,0x0,0x34002400,0x2400,0x0,0x0,0x0,0x3c,0x0,0x8000000,0x0,0x60607800,0x0,0x140000,0x0,0x0,0x0,0x0,0x0, 1.2900 + 0x44,0x10081834,0x240000,0x10081800,0x10081800,0x1c341008,0x18340000,0x100818,0x84000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x102812, 1.2901 + 0x8601c10,0x8100800,0x2,0x1c383e3e,0x67e1e7f,0x3e3c0000,0x38,0x1e087e1e,0x7c7f7f1e,0x417c1c42,0x4063611c,0x7e1c7e3e,0xfe414181, 1.2902 + 0x63827f10,0x40081000,0x8004000,0x2001000,0x40000040,0x10000000,0x0,0x10000000,0x10,0x10100000,0x3c000008,0x0,0x24003e00, 1.2903 + 0x3f007f00,0x0,0x0,0x2ce91800,0x1882,0x10101c,0xc2103c,0x143c3c00,0x3c00,0x18003c3c,0x10001f00,0x181c00,0x20200810,0x8080808, 1.2904 + 0x8083e1e,0x7f7f7f7f,0x7c7c7c7c,0x7c611c1c,0x1c1c1c00,0x1e414141,0x41824044,0x810242c,0x14180000,0x8102414,0x8102414,0x382c0810, 1.2905 + 0x242c1400,0x81024,0x14104014,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x102816,0x3e902010,0x10084910,0x4,0x22084343,0xa402102,0x41620000, 1.2906 + 0x44,0x33144121,0x42404021,0x41100444,0x40636122,0x43224361,0x10416381,0x22440310,0x20082800,0x4000,0x2001000,0x40000040, 1.2907 + 0x10000000,0x0,0x10000000,0x10,0x10100000,0x24000008,0x0,0x606100,0x68000300,0x8106c,0x34000000,0x4f0000,0x44,0x101020,0x441040, 1.2908 + 0x420200,0x4200,0x24000404,0x7d00,0x82200,0x20203010,0x14141414,0x14082821,0x40404040,0x10101010,0x42612222,0x22222200,0x23414141, 1.2909 + 0x41447e48,0x0,0x0,0x0,0x0,0x4000000,0x18,0x0,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10287f,0x49902010,0x10083e10,0x4,0x41080101, 1.2910 + 0x1a404002,0x41411818,0x1004004,0x21144140,0x41404040,0x41100448,0x40555141,0x41414140,0x10412281,0x14280610,0x20084400,0x1c7c1c, 1.2911 + 0x3e3c7c3a,0x5c703844,0x107f5c3c,0x7c3e3c3c,0x7e424281,0x66427e10,0x10100000,0x40100008,0x1010,0xa04000,0x48100610,0x100c3024, 1.2912 + 0x24000000,0x4f3c00,0x2c107e28,0x3820,0x42281060,0x9d1e12,0xbd00,0x24100818,0x427d00,0x82248,0x20200800,0x14141414,0x14142840, 1.2913 + 0x40404040,0x10101010,0x41514141,0x41414142,0x43414141,0x41284350,0x1c1c1c1c,0x1c1c6c1c,0x3c3c3c3c,0x70707070,0x3c5c3c3c, 1.2914 + 0x3c3c3c18,0x3e424242,0x42427c42,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x102824,0x48623010,0x10081c10,0x8,0x41080103,0x127c5e04, 1.2915 + 0x41411818,0xe7f3808,0x4f144140,0x41404040,0x41100450,0x40555141,0x41414160,0x1041225a,0x1c280410,0x1008c600,0x226622,0x66661066, 1.2916 + 0x62100848,0x10496266,0x66663242,0x10426681,0x24220260,0x100c0000,0xf8280008,0x1010,0x606000,0x48280428,0x28042014,0x48000000, 1.2917 + 0x494200,0x52280228,0x105420,0x3cee1058,0xa12236,0xa500,0x18101004,0x427d00,0x8226c,0x76767e10,0x14141414,0x14142840,0x40404040, 1.2918 + 0x10101010,0x41514141,0x41414124,0x45414141,0x41284150,0x22222222,0x22221222,0x66666666,0x10101010,0x66626666,0x66666600, 1.2919 + 0x66424242,0x42226622,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100024,0x381c4900,0x10086bfe,0x8,0x4908021c,0x22036304,0x3e630000, 1.2920 + 0x70000710,0x51227e40,0x417f7f43,0x7f100470,0x40554941,0x43417e3e,0x1041225a,0x8100810,0x10080000,0x24240,0x42421042,0x42100850, 1.2921 + 0x10494242,0x42422040,0x1042245a,0x18240410,0x10103900,0x407c003e,0x1818,0x1c3e10,0x4f7c087c,0x7c002010,0x48000000,0x4008, 1.2922 + 0x527c0410,0x105078,0x2410104c,0xa13e6c,0x7f00b900,0xfe3c3c,0x421d18,0x1c1c36,0x38383810,0x22222222,0x22144e40,0x7f7f7f7f, 1.2923 + 0x10101010,0xf1494141,0x41414118,0x49414141,0x4110435c,0x2020202,0x2021240,0x42424242,0x10101010,0x42424242,0x424242ff,0x4e424242, 1.2924 + 0x42244224,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000fe,0xe664d00,0x10080810,0x380010,0x41080c03,0x42014108,0x633d0000,0x70000710, 1.2925 + 0x51224140,0x41404041,0x41100448,0x40494541,0x7e414203,0x1041145a,0x14101010,0x10080000,0x3e4240,0x427e1042,0x42100870,0x10494242, 1.2926 + 0x4242203c,0x1042245a,0x18241810,0x10104600,0xf8f60008,0x1010,0x600320,0x48f610f6,0xf6000000,0x187eff,0x3c04,0x5ef61810,0x105020, 1.2927 + 0x24fe0064,0x9d006c,0x138ad00,0x100000,0x420518,0x36,0xc0c0c020,0x22222222,0x22224840,0x40404040,0x10101010,0x41454141,0x41414118, 1.2928 + 0x51414141,0x41107e46,0x3e3e3e3e,0x3e3e7e40,0x7e7e7e7e,0x10101010,0x42424242,0x42424200,0x5a424242,0x42244224,0x0,0x0,0x0, 1.2929 + 0x0,0x0,0x0,0x0,0x0,0x28,0x9094500,0x10080010,0x10,0x41081801,0x7f014118,0x41010000,0xe7f3800,0x513e4140,0x41404041,0x41100444, 1.2930 + 0x40414541,0x40414101,0x10411466,0x36103010,0x8080000,0x424240,0x42401042,0x42100848,0x10494242,0x42422002,0x10423c5a,0x18142010, 1.2931 + 0x10100000,0x407c0010,0x1010,0x260140,0x487c307c,0x7c000000,0x180000,0x202,0x507c2010,0x105020,0x3c10003c,0x423e36,0x1004200, 1.2932 + 0x100000,0x420500,0x3e6c,0x41e0440,0x3e3e3e3e,0x3e3e7840,0x40404040,0x10101010,0x41454141,0x41414124,0x61414141,0x41104042, 1.2933 + 0x42424242,0x42425040,0x40404040,0x10101010,0x42424242,0x42424218,0x72424242,0x42144214,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100048, 1.2934 + 0x49096200,0x8100010,0x18001810,0x22082043,0x2432310,0x61421818,0x1004010,0x4f634121,0x42404021,0x41104444,0x40414322,0x40234143, 1.2935 + 0x10411466,0x22106010,0x8080000,0x466622,0x66621066,0x42100844,0x10494266,0x66662042,0x10461824,0x24184010,0x10100000,0x24381010, 1.2936 + 0x34001018,0xda4320,0x68386038,0x38000000,0x0,0x4204,0x50384010,0x105420,0x4210100c,0x3c0012,0x3c00,0x0,0x460500,0x48,0xc020c44, 1.2937 + 0x63636363,0x63228821,0x40404040,0x10101010,0x42432222,0x22222242,0x62414141,0x41104042,0x46464646,0x46465022,0x62626262, 1.2938 + 0x10101010,0x66426666,0x66666618,0x66464646,0x46186618,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100048,0x3e063d00,0x8100000,0x18001820, 1.2939 + 0x1c3e7f3e,0x23c1e20,0x3e3c1818,0x10,0x20417e1e,0x7c7f401e,0x417c3842,0x7f41431c,0x401e40be,0x103e0866,0x41107f10,0x4080000, 1.2940 + 0x3a5c1c,0x3a3c103a,0x427c0842,0xe49423c,0x7c3e203c,0xe3a1824,0x66087e10,0x10100000,0x3c103010,0x245a1010,0x5a3e10,0x3f107f10, 1.2941 + 0x10000000,0x0,0x3c08,0x2e107e10,0x1038fc,0x101004,0x0,0x0,0xfe0000,0x7f0500,0x0,0x14041438,0x41414141,0x41418e1e,0x7f7f7f7f, 1.2942 + 0x7c7c7c7c,0x7c431c1c,0x1c1c1c00,0xbc3e3e3e,0x3e10405c,0x3a3a3a3a,0x3a3a6e1c,0x3c3c3c3c,0x7c7c7c7c,0x3c423c3c,0x3c3c3c00, 1.2943 + 0x7c3a3a3a,0x3a087c08,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8000000,0x4200000,0x10000020,0x0,0x0,0x10,0x0,0x30000000,0x0, 1.2944 + 0x0,0x0,0x60000,0x0,0x1c,0x4380000,0x0,0x2,0x800,0x0,0x40020000,0x0,0x8000c,0x10600000,0x2010,0x48000000,0x240000,0x0,0x0, 1.2945 + 0x0,0x0,0x0,0x1000,0x1078,0x0,0x0,0x0,0x400500,0x0,0x1e081e00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2946 + 0x84008,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8000000,0x0,0x20000040,0x0,0x0,0x20,0x0,0x1e000000,0x0,0x0,0x0,0x20000,0x0, 1.2947 + 0x0,0x2000000,0x0,0x26,0x800,0x0,0x40020000,0x0,0x100000,0x10000000,0x2030,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000,0x1000,0x0, 1.2948 + 0x0,0x0,0x400000,0x8000000,0x41e0400,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x104010,0x0,0x0,0x0,0x0, 1.2949 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfe,0x0,0x1c,0x7000,0x0,0x40020000,0x0,0x300000, 1.2950 + 0x0,0xe0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000,0x0,0x0,0x0,0x400000,0x38000000,0x0,0x0,0x1c,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2951 + 0x1c,0x0,0x0,0x0,0x0,0x0,0x304030,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2952 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2953 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2954 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2955 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 }; 1.2956 + 1.2957 + // Definition of a 10x19 font. 1.2958 + const unsigned int font10x19[10*19*256/32] = { 1.2959 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2960 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3600000,0x36000,0x0,0x0,0x0,0x0,0x6c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2961 + 0x0,0x180181c0,0xe81b0300,0x1801,0x81c06c18,0x181c06c,0xe8180,0x181c0e81,0xb0000006,0x60701b,0x1800000,0x0,0x0,0x0,0x0,0x0, 1.2962 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2963 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c00000,0x1c000,0x0,0x0,0x0,0x0,0x6c,0x0,0x0,0x0,0x0, 1.2964 + 0x0,0x0,0x0,0x0,0x0,0x0,0xc030360,0xb81b0480,0xc03,0x3606c0c,0x303606c,0xb80c0,0x30360b81,0xb0000003,0xc0d81b,0x3000000,0x0, 1.2965 + 0x300,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.2966 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x2200000, 1.2967 + 0x22000,0x0,0x0,0x0,0x0,0x0,0x0,0x30000,0x0,0xe0,0x38078000,0x0,0x480,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3000c080,0x480,0x3000, 1.2968 + 0xc0800030,0xc08000,0x300,0xc080000,0xc,0x302000,0xc00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20120,0x41c01,0xe020060c, 1.2969 + 0x800000,0x4,0x1e0703e0,0xf8060fc1,0xe1fe1e07,0x80000000,0x78,0x307e0,0x3c7c1fe7,0xf83c408f,0x80f10440,0x18660878,0x7e0787e0, 1.2970 + 0x78ff9024,0xa0140a0,0x27f83840,0x700e000,0x18000400,0x8000,0x70004002,0x410078,0x0,0x0,0x0,0x0,0x1808,0xc000000,0xf000000, 1.2971 + 0xe000000,0x1400,0x1e0001f,0x8007f800,0x0,0x0,0x3a3b,0x61400000,0x14202,0x20000,0x38002020,0x3c1b00,0x3e00000,0xf8,0x1c0001c0, 1.2972 + 0x78060001,0xf800000e,0x1e00020,0x8004020,0xc0300c0,0x300c0301,0xf83c7f9f,0xe7f9fe3e,0xf83e0f8,0x7c1821e0,0x781e0781,0xe0001f10, 1.2973 + 0x24090240,0xa02400f8,0x18018140,0xe81b0480,0x1801,0x81406c18,0x181406c,0x190e8180,0x18140e81,0xb0000006,0x60501b,0x184006c, 1.2974 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20120,0x26042202,0x200c06,0x800000,0x8,0x210d0611,0x40e0803,0x10026188,0x40000000, 1.2975 + 0x8c,0xf030418,0xc6431004,0xc64082,0x110840,0x18660884,0x41084410,0x8c081024,0xa012110,0x40082020,0x101b000,0xc000400,0x8000, 1.2976 + 0x80004002,0x410008,0x0,0x0,0x100000,0x0,0x2008,0x2000000,0x18800000,0x10000000,0x2200,0x2300024,0x800,0x0,0x0,0x2e13,0x60800000, 1.2977 + 0x8104,0x20040,0x64001040,0x80401b07,0x80100000,0x1e000,0x22000020,0x40c0003,0xc8000002,0x3300020,0x8004020,0xc0300c0,0x300c0301, 1.2978 + 0x40c64010,0x4010008,0x2008020,0x43182210,0x84210842,0x10002190,0x24090240,0x9044018c,0xc030220,0xb81b0300,0xc03,0x2206c0c, 1.2979 + 0x302206c,0x1e0b80c0,0x30220b81,0xb0000003,0xc0881b,0x304006c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20120,0x241f2202, 1.2980 + 0x200802,0x4900000,0x8,0x21010408,0x20a0802,0x44090,0x20000000,0x4,0x11878408,0x80411004,0x804082,0x111040,0x1ce50986,0x40986409, 1.2981 + 0x81022,0x12012108,0x80102020,0x1031800,0x400,0x8000,0x80004000,0x10008,0x0,0x0,0x100000,0x0,0x2008,0x2000000,0x10000000, 1.2982 + 0x10000000,0x18,0x4000044,0x1000,0x30180,0xd81b0000,0x13,0xe0000000,0x88,0x40,0x400018c0,0x80400018,0x61f00000,0x61800,0x22020020, 1.2983 + 0x4000007,0xc8000002,0x2100020,0x8038000,0x1e0781e0,0x781e0301,0x40804010,0x4010008,0x2008020,0x41142619,0x86619866,0x18002190, 1.2984 + 0x24090240,0x8887e104,0x0,0x0,0x0,0x0,0x0,0x2000000,0x0,0x0,0x0,0x40000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20120,0x2434a202, 1.2985 + 0x200802,0x3e00000,0x10,0x40810008,0x21a0804,0x44090,0x20000000,0x80040004,0x20848409,0x409004,0x1004082,0x112040,0x14a50902, 1.2986 + 0x40902409,0x81022,0x11321208,0x80202010,0x1060c00,0x7c5e0,0x781e8783,0xf07a5f0e,0x1c10808,0xfc5f078,0x5e07a170,0x7c7e1024, 1.2987 + 0xa016190,0x27f82008,0x2000000,0x20000000,0x10000000,0x80200024,0x4000044,0x2000,0x18180,0xc8320000,0x12,0xa1f00037,0x7f888, 1.2988 + 0x1e0,0x40410880,0x80600017,0xa2100000,0x5e800,0x22020040,0x38001027,0xc8000002,0x2100020,0x8004020,0x12048120,0x48120482, 1.2989 + 0x41004010,0x4010008,0x2008020,0x40942409,0x2409024,0x9044390,0x24090240,0x88841918,0x1f07c1f0,0x7c1f07c3,0x70781e07,0x81e07838, 1.2990 + 0xe0380e0,0x1f17c1e0,0x781e0781,0xe0001f90,0x24090240,0x9025e102,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20001,0xff241c41, 1.2991 + 0x1001,0x1c02000,0x10,0x40810008,0x6120f85,0xe0086190,0x20c03007,0x8007800c,0x27848419,0x409004,0x1004082,0x114040,0x14a48902, 1.2992 + 0x40902409,0x81022,0x11321205,0x602010,0x1000000,0x86610,0x84218840,0x80866182,0x411008,0x9261884,0x61086189,0x82101022,0x12012108, 1.2993 + 0x40082008,0x2000000,0x20030000,0x20000000,0x80200024,0x4000044,0x3006030,0xc018100,0x4c260000,0x12,0x26080048,0x83000850, 1.2994 + 0x20250,0x403e0500,0x8078002c,0x12302200,0x92400,0x1c0200c0,0x4001027,0xc8000002,0x3308820,0x8004020,0x12048120,0x48120482, 1.2995 + 0x41004010,0x4010008,0x2008020,0x40922409,0x2409024,0x8884690,0x24090240,0x85040920,0x21886218,0x86218860,0x88842108,0x42108408, 1.2996 + 0x2008020,0x21186210,0x84210842,0x10302190,0x24090240,0x88461084,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000,0x4c240182, 1.2997 + 0x80001001,0x6b02000,0x20,0x4c810010,0x78220846,0x10081e10,0x20c0301c,0x1fe0e018,0x4d8487e1,0x409fe7,0xf9007f82,0x11a040, 1.2998 + 0x13248902,0x41102418,0xe0081022,0x11320c05,0x402008,0x1000000,0x2409,0x409020,0x81024082,0x412008,0x9240902,0x40902101,0x101022, 1.2999 + 0x11321208,0x40102008,0x2000000,0x7e0c8000,0xfc000003,0xf0fc0018,0x43802047,0x8c8040c8,0x32008300,0x44240000,0x0,0x4000048, 1.3000 + 0x8c801050,0x20440,0x40221dc0,0x808c0028,0x11d0667f,0x8009c400,0x1fc180,0x4001023,0xc8300002,0x1e0ccfb,0x3ec7b020,0x12048120, 1.3001 + 0x48120482,0x79007f9f,0xe7f9fe08,0x2008020,0xf0922409,0x2409024,0x8504490,0x24090240,0x85040920,0x802008,0x2008020,0x89004090, 1.3002 + 0x24090208,0x2008020,0x40902409,0x2409024,0x8304390,0x24090240,0x88440884,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000, 1.3003 + 0x481c0606,0xc8001001,0x802000,0x20,0x4c810020,0x4220024,0x8102108,0x60000070,0x3820,0x48884419,0x409004,0x10e4082,0x112040, 1.3004 + 0x13244902,0x7e1027e0,0x3c081021,0x21320c02,0x802008,0x1000000,0x7e409,0x409020,0x81024082,0x414008,0x9240902,0x40902101, 1.3005 + 0x80101022,0x11320c08,0x40202008,0x2038800,0x200bc000,0x20000000,0x80200003,0x80f04044,0xbc080bc,0x2f000200,0x0,0x0,0x6001048, 1.3006 + 0x8bc02020,0x20441,0xf8220200,0x80820028,0x1000cc00,0x80094400,0x201e0,0x78001021,0xc830000f,0x8000663c,0xf03c0c0,0x21084210, 1.3007 + 0x84210846,0x41004010,0x4010008,0x2008020,0x40912409,0x2409024,0x8204890,0x24090240,0x82040930,0x1f87e1f8,0x7e1f87e0,0x89004090, 1.3008 + 0x24090208,0x2008020,0x40902409,0x2409024,0x8004690,0x24090240,0x88440884,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000, 1.3009 + 0x480719c4,0x48001001,0x81fc00,0x7800020,0x40810040,0x2420024,0x8104087,0xa0000070,0x3820,0x48884409,0x409004,0x1024082,0x111040, 1.3010 + 0x13244902,0x40102410,0x2081021,0x214a1202,0x1802008,0x1000000,0x182409,0x409fe0,0x81024082,0x41a008,0x9240902,0x40902100, 1.3011 + 0xf8101021,0x214a0c04,0x80c0c008,0x1847000,0x7c1ee000,0x20000000,0x8020000c,0x8c044,0x1ee181ee,0x7b800000,0x707,0xf3ff0000, 1.3012 + 0x3e0084f,0x9ee0c020,0x20440,0x40221fc0,0xc2002c,0x13f11000,0x87892400,0x20000,0x1020,0x48000000,0x3f011c6,0x31cc6180,0x21084210, 1.3013 + 0x84210844,0x41004010,0x4010008,0x2008020,0x40912409,0x2409024,0x8505090,0x24090240,0x8204191c,0x60982609,0x82609823,0xf9007f9f, 1.3014 + 0xe7f9fe08,0x2008020,0x40902409,0x2409024,0x9fe4c90,0x24090240,0x84840848,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0xfe048224, 1.3015 + 0x28001001,0x2000,0x40,0x40810080,0x27f8024,0x8104080,0x2000001c,0x1fe0e020,0x488fc409,0x409004,0x1024082,0x110840,0x10242902, 1.3016 + 0x40102408,0x2081021,0x214a1202,0x1002004,0x1000000,0x102409,0x409000,0x81024082,0x411008,0x9240902,0x40902100,0x6101021, 1.3017 + 0x214a0c04,0x81002008,0x2000000,0x201dc000,0x20000000,0x80200000,0x98044,0x1dc101dc,0x77000000,0x700,0x0,0x180448,0x1dc10020, 1.3018 + 0x20440,0x403e0200,0x620017,0xa000cc00,0x80052800,0x20000,0x1020,0x48000000,0x6606,0x206100,0x3f0fc3f0,0xfc3f0fc7,0xc1004010, 1.3019 + 0x4010008,0x2008020,0x4090a409,0x2409024,0x8886090,0x24090240,0x8207e106,0x40902409,0x2409024,0x81004010,0x4010008,0x2008020, 1.3020 + 0x40902409,0x2409024,0x8005890,0x24090240,0x84840848,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x98048224,0x30001001,0x2000, 1.3021 + 0x40,0x21010100,0x2020024,0x8204080,0x40000007,0x80078000,0x48884408,0x80411004,0x824082,0x110840,0x10242986,0x40086409,0x2081021, 1.3022 + 0xe14a2102,0x2002004,0x1000000,0x106409,0x409000,0x81024082,0x410808,0x9240902,0x40902100,0x2101021,0x214a1202,0x82002008, 1.3023 + 0x2000000,0x300f8000,0x20000000,0x80fc001d,0xe4088044,0xf8200f8,0x3e000000,0x300,0x0,0x80c48,0xf820020,0x20640,0x40410200, 1.3024 + 0x803c0018,0x60006600,0x61800,0x0,0x1020,0x48000000,0xcc0a,0x20a100,0x21084210,0x84210844,0x40804010,0x4010008,0x2008020, 1.3025 + 0x4110a619,0x86619866,0x19046110,0x24090240,0x82040102,0x41906419,0x6419064,0x81004010,0x4010008,0x2008020,0x40902409,0x2409024, 1.3026 + 0x8307090,0x24090240,0x82840828,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000,0x90248222,0x30000802,0x200c,0xc080,0x21010301, 1.3027 + 0x4021042,0x10202108,0xc0c03000,0x80040020,0x4d902418,0xc6431004,0xc24082,0x6210440,0x10241884,0x40084409,0x86080840,0xc0842102, 1.3028 + 0x4002002,0x1000000,0x18e610,0x84218820,0x80864082,0x410408,0x9240884,0x61086101,0x6101860,0xc0842103,0x4002008,0x2000000, 1.3029 + 0x10850180,0x20330000,0x80200013,0x26184024,0x5040050,0x14000000,0x0,0x0,0x4180848,0x85040020,0x20350,0x40000200,0x800c0007, 1.3030 + 0x80002200,0x1e000,0x0,0x1860,0x48000000,0x880a,0x40a188,0x40902409,0x2409028,0x40c64010,0x4010008,0x2008020,0x43106210,0x84210842, 1.3031 + 0x10006108,0x42108421,0x2040102,0x6398e639,0x8e6398e4,0x88842088,0x22088208,0x2008020,0x21102210,0x84210842,0x10306118,0x66198661, 1.3032 + 0x83061030,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20001,0x901f01c1,0xe8000802,0xc,0xc080,0x1e07c7f8,0xf8020f81,0xe0401e07, 1.3033 + 0x80c03000,0x20,0x279027e0,0x3c7c1fe4,0x3c408f,0x83c1027f,0x90241878,0x4007c404,0xf8080780,0xc0844082,0x7f82002,0x1000000, 1.3034 + 0xfa5e0,0x781e87c0,0x807a409f,0xc0410207,0x9240878,0x5e07a100,0xf80e0fa0,0xc0846183,0x7f82008,0x2000000,0xf020100,0x40321360, 1.3035 + 0x80200014,0xa3e0201f,0x8207f820,0x8000000,0x0,0x0,0x3e01037,0x207f820,0x201e1,0xfc000200,0x80040000,0x0,0x0,0x1fc000,0x17b0, 1.3036 + 0x48000000,0x12,0xc120f0,0x40902409,0x2409028,0x783c7f9f,0xe7f9fe3e,0xf83e0f8,0x7c1061e0,0x781e0781,0xe000be07,0x81e0781e, 1.3037 + 0x204017c,0x3e8fa3e8,0xfa3e8fa3,0x70781f07,0xc1f07c7f,0x1fc7f1fc,0x1e1021e0,0x781e0781,0xe0007e0f,0xa3e8fa3e,0x8305e030,0x0, 1.3038 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40000,0xc06,0xc,0x100,0x0,0x0,0x0,0x3000,0x0,0x20000000,0x0,0x0,0x0,0x0,0xc000, 1.3039 + 0x0,0x0,0x2001,0x1000000,0x0,0x0,0x20000,0x400000,0x0,0x40002000,0x0,0x1,0x2008,0x2000000,0x100,0x40240000,0x80200008,0x40000000, 1.3040 + 0x0,0x0,0x0,0x0,0x0,0x0,0x40,0x0,0x80040000,0x0,0x0,0x0,0x1000,0x48000000,0x1f,0x181f000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3041 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1040010,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40000,0x60c,0x18,0x0, 1.3042 + 0x0,0x0,0x0,0x6000,0x0,0x10000000,0x0,0x0,0x0,0x0,0x4000,0x0,0x0,0x3800,0x7000000,0x0,0x0,0x840000,0x400000,0x0,0x40002000, 1.3043 + 0x0,0x2,0x2008,0x2000000,0x200,0x40440000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40,0x0,0x80780000,0x0,0x0,0x0,0x1000,0x48000400, 1.3044 + 0x2,0x1e02000,0x0,0x0,0x80000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80000,0x0,0x0,0x0,0x0,0x0,0x0,0x2040020,0x0,0x0,0x0,0x0, 1.3045 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x0,0x4000,0x0,0xf000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3046 + 0x780000,0x3800000,0x0,0x40002000,0x0,0xe,0x1808,0xc000000,0x3,0x80000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80000000, 1.3047 + 0x0,0x0,0x0,0x1000,0x1c00,0x0,0x0,0x0,0x0,0x380000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x380000,0x0,0x0,0x0,0x0,0x0,0x0,0xe0400e0, 1.3048 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3fc, 1.3049 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3050 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 }; 1.3051 + 1.3052 + // Definition of a 12x24 font. 1.3053 + const unsigned int font12x24[12*24*256/32] = { 1.3054 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3055 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x19,0x80000000,0x198000,0x0,0x0,0x0,0x0, 1.3056 + 0x0,0x198,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc001806,0xc81980,0x60000000,0xc001806,0x1980c00,0x18060198,0xc80c, 1.3057 + 0x180600,0xc8198000,0xc001,0x80601980,0x18000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3058 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3059 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0x0,0xf0000,0x0,0x0,0x0,0x0,0x0,0x198,0x0,0x0,0x0,0x0,0x0,0x0, 1.3060 + 0x0,0x0,0x0,0x0,0x0,0x0,0x600300f,0x1301980,0x90000000,0x600300f,0x1980600,0x300f0198,0x13006,0x300f01,0x30198000,0x6003, 1.3061 + 0xf01980,0x30000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3062 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3063 + 0x0,0x0,0x0,0x0,0x0,0x0,0x6,0x0,0x60000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7007,0x3c0000,0x3006019, 1.3064 + 0x80000000,0x90000000,0x3006019,0x80000300,0x60198000,0x3,0x601980,0x0,0x3006,0x1980000,0x60000000,0x0,0x0,0xe0000000,0x0, 1.3065 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3066 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000000, 1.3067 + 0x0,0x0,0x0,0x0,0x0,0xc800019,0x80000000,0x198000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc0,0x0,0x0,0x1001,0x420000,0x0,0x0,0x90000000, 1.3068 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18000c06,0xc80001,0x10000000,0x18000c06,0x1800,0xc060000,0xc818,0xc0600,0xc8000000, 1.3069 + 0x18000,0xc0600000,0xc000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6019,0x80660207,0x800f8060,0x300c004,0x0,0x6, 1.3070 + 0xe00703f,0x3f00383,0xf80f07fc,0x1f01f000,0x0,0xf8,0x607f,0x7c7e07,0xfe7fe0f8,0x6063fc1f,0x86066007,0xe7060f0,0x7f80f07f, 1.3071 + 0x81f8fff6,0x6606c03,0x70ee077f,0xe0786000,0xf0070000,0xc000060,0xc0,0x3e000,0x60006003,0x600fc00,0x0,0x0,0x0,0x0,0x0,0x3c0603, 1.3072 + 0xc0000000,0x7800000,0xf0000,0x0,0xf00001f,0x80001fe0,0x7fe000,0x0,0x0,0x0,0x168fe609,0x0,0x90e07,0x6000,0x3c000e,0x70000f8, 1.3073 + 0x1980001f,0x0,0x1f8,0xf00000f,0xf00180,0xfe000,0xe00e,0x1001,0x20060,0x6006006,0x600600,0x600fe07c,0x7fe7fe7f,0xe7fe3fc3, 1.3074 + 0xfc3fc3fc,0x7e07060f,0xf00f00,0xf00f0000,0xf360660,0x6606606e,0x76001e0,0xc00180f,0x1681981,0x10000000,0xc00180f,0x1980c00, 1.3075 + 0x180f0198,0x3801680c,0x180f01,0x68198000,0xc001,0x80f01980,0x18600198,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6019, 1.3076 + 0x8044020c,0xc01f8060,0x2004004,0x0,0xc,0x3f81f07f,0x87f80383,0xf81f87fc,0x3f83f800,0x0,0x1fc,0x780607f,0x81fe7f87,0xfe7fe1fc, 1.3077 + 0x6063fc1f,0x860c6007,0xe7061f8,0x7fc1f87f,0xc3fcfff6,0x6606c03,0x30c6067f,0xe0783000,0xf00d8000,0x6000060,0xc0,0x7e000,0x60006003, 1.3078 + 0x600fc00,0x0,0x0,0xc00,0x0,0x0,0x7c0603,0xe0000000,0xfc00000,0x1f0000,0x0,0x900003f,0xc0003fe0,0x7fe000,0x0,0x0,0x0,0x1302660f, 1.3079 + 0x0,0xf0606,0x6004,0x7e0006,0x60601f8,0x19800001,0x80000000,0x1f8,0x19800010,0x81080300,0x3f2000,0x2011,0x1001,0x1c0060,0x6006006, 1.3080 + 0x600600,0x601fe1fe,0x7fe7fe7f,0xe7fe3fc3,0xfc3fc3fc,0x7f87061f,0x81f81f81,0xf81f8000,0x3fa60660,0x66066066,0x66003f0,0x6003009, 1.3081 + 0x1301981,0x10000000,0x6003009,0x1980600,0x30090198,0x1f013006,0x300901,0x30198000,0x6003,0x901980,0x30600198,0x0,0x0,0x0, 1.3082 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6019,0x80cc0f8c,0xc0180060,0x6006044,0x40000000,0xc,0x3181b041,0xc41c0783,0x388018, 1.3083 + 0x71c71800,0x0,0x106,0x18c0f061,0xc38261c6,0x600384,0x60606001,0x86186007,0xe78630c,0x60e30c60,0xe7040606,0x630cc03,0x39c30c00, 1.3084 + 0xc0603000,0x3018c000,0x3000060,0xc0,0x60000,0x60000000,0x6000c00,0x0,0x0,0xc00,0x0,0x0,0x600600,0x60000000,0x18400000,0x180000, 1.3085 + 0x0,0x19800070,0x40003600,0xc000,0x0,0x0,0x0,0x25a06,0x0,0x6030c,0x4,0xe20007,0xe060180,0xf000,0x80000000,0xf0000,0x10800000, 1.3086 + 0x80080600,0x7f2000,0x2020,0x80001001,0x20000,0xf00f00f,0xf00f00,0x601b0382,0x60060060,0x6000600,0x60060060,0x61c78630,0xc30c30c3, 1.3087 + 0xc30c000,0x30e60660,0x66066063,0xc600738,0x3006019,0x80000000,0xe0000000,0x3006019,0x80000300,0x60198000,0x3e000003,0x601980, 1.3088 + 0x0,0x3006,0x1980000,0x60600000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6019,0x80cc1fcc,0xc0180060,0x6006035,0x80000000, 1.3089 + 0x18,0x71c03000,0xc00c0583,0x300018,0x60c60c00,0x0,0x6,0x3060f060,0xc30060c6,0x600300,0x60606001,0x86306007,0x9e78670e,0x60670e60, 1.3090 + 0x66000606,0x630c606,0x19830c01,0xc0601800,0x30306000,0x60,0xc0,0x60000,0x60000000,0x6000c00,0x0,0x0,0xc00,0x0,0x0,0x600600, 1.3091 + 0x60000000,0x18000000,0x300000,0x0,0x78060,0x6600,0x1c000,0x300c,0x39819c0,0x0,0x25a00,0x0,0x30c,0x4,0xc00003,0xc060180,0x30c1f, 1.3092 + 0x80000000,0x30c000,0x10800001,0x80700000,0x7f2000,0x2020,0x80001001,0x20060,0xf00f00f,0xf00f00,0xf01b0300,0x60060060,0x6000600, 1.3093 + 0x60060060,0x60c78670,0xe70e70e7,0xe70e000,0x70c60660,0x66066063,0xc7f8618,0x0,0x0,0x0,0x0,0x0,0x0,0x7000000,0x0,0x0,0x0, 1.3094 + 0x0,0x600000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6019,0x87ff3a4c,0xc0180060,0x400600e,0x600000,0x18,0x60c03000, 1.3095 + 0xc00c0d83,0x700018,0x60c60c00,0x20,0x400006,0x3060f060,0xc6006066,0x600600,0x60606001,0x86606006,0x966c6606,0x60660660,0x66000606, 1.3096 + 0x630c666,0xf019801,0x80601800,0x30603000,0x1f06f,0xf01ec0,0xf03fe1ec,0x6703e01f,0x61c0c06,0xdc6701f0,0x6f01ec0c,0xe1f87fc6, 1.3097 + 0xc60cc03,0x71c60c7f,0xc0600600,0x60000000,0x30000000,0x300000,0x40040,0x88060,0x6600,0x18000,0x300c,0x1981980,0x0,0x2421f, 1.3098 + 0x80003ce0,0x7fc198,0x601f,0xc02021,0x980600c0,0x40230,0x80000000,0x402000,0x19806003,0x80006,0xc7f2000,0x2020,0x80001001, 1.3099 + 0x420060,0xf00f00f,0xf00f00,0xf01b0600,0x60060060,0x6000600,0x60060060,0x6066c660,0x66066066,0x6606208,0x60e60660,0x66066061, 1.3100 + 0x987fc670,0x1f01f01f,0x1f01f01,0xf039c0f0,0xf00f00f,0xf03e03,0xe03e03e0,0x1f06701f,0x1f01f01,0xf01f0060,0x1e660c60,0xc60c60c6, 1.3101 + 0xc6f060c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x7ff3207,0x8c0c0000,0xc00300e,0x600000,0x30,0x60c03000, 1.3102 + 0xc01c0983,0xf0600030,0x31860c06,0x6001e0,0x78000e,0x23e1f861,0xc6006066,0x600600,0x60606001,0x86c06006,0x966c6606,0x60660660, 1.3103 + 0xe7000606,0x630c666,0xf01f803,0x600c00,0x30000000,0x3f87f,0x83f83fc3,0xf83fe3fc,0x7f83e01f,0x6380c07,0xfe7f83f8,0x7f83fc0d, 1.3104 + 0xf3fc7fc6,0xc71cc03,0x3183187f,0xc0600600,0x60000000,0xff806000,0x300000,0x40040,0x88070,0x6600,0x60030060,0x6001818,0x1883180, 1.3105 + 0x0,0x2423f,0xc0007ff0,0x607fc1f8,0x603f,0x80c01fc1,0xf80601e0,0x5f220,0x80420000,0x5f2000,0xf006006,0x80006,0xc7f2000,0x2020, 1.3106 + 0x82107c07,0xc03c0060,0x1f81f81f,0x81f81f80,0xf03b0600,0x60060060,0x6000600,0x60060060,0x6066c660,0x66066066,0x660671c,0x61660660, 1.3107 + 0x66066061,0xf860e6c0,0x3f83f83f,0x83f83f83,0xf87fe3f8,0x3f83f83f,0x83f83e03,0xe03e03e0,0x3f87f83f,0x83f83f83,0xf83f8060, 1.3108 + 0x3fc60c60,0xc60c60c3,0x187f8318,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x883200,0x300c0000,0xc003035,0x80600000, 1.3109 + 0x30,0x66c03001,0xc0f81983,0xf86f0030,0x1f071c06,0x600787,0xfe1e001c,0x6261987f,0x86006067,0xfe7fc600,0x7fe06001,0x87c06006, 1.3110 + 0xf6646606,0x60e6067f,0xc3e00606,0x61986f6,0x600f007,0x600c00,0x30000000,0x21c71,0x830831c3,0x1c06031c,0x71c06003,0x6700c06, 1.3111 + 0x6671c318,0x71831c0f,0x16040c06,0xc318606,0x1b031803,0x80600600,0x60000000,0x30009000,0x300000,0x40040,0x7003e,0x67e0,0x90070090, 1.3112 + 0x9001818,0x8c3100,0x0,0x60,0x4000e730,0x900380f0,0x6034,0x80c018c7,0xfe060338,0xb0121,0x80c60000,0x909000,0x6008,0x1080006, 1.3113 + 0xc3f2000,0x2011,0x3180060,0x60060e0,0x19819819,0x81981981,0x9833c600,0x7fe7fe7f,0xe7fe0600,0x60060060,0x60664660,0x66066066, 1.3114 + 0x66063b8,0x62660660,0x66066060,0xf06066c0,0x21c21c21,0xc21c21c2,0x1c466308,0x31c31c31,0xc31c0600,0x60060060,0x31871c31,0x83183183, 1.3115 + 0x18318000,0x71860c60,0xc60c60c3,0x18718318,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x1981a00,0xe03e0000,0xc003044, 1.3116 + 0x40600000,0x60,0x66c03001,0x80f03182,0x1c7f8030,0x3f83fc06,0x601e07,0xfe078038,0x6661987f,0x86006067,0xfe7fc61e,0x7fe06001, 1.3117 + 0x87e06006,0x66666606,0x7fc6067f,0x81f80606,0x61986f6,0x6006006,0x600600,0x30000000,0xc60,0xc60060c6,0xc06060c,0x60c06003, 1.3118 + 0x6e00c06,0x6660c60c,0x60c60c0e,0x6000c06,0xc318666,0x1f031803,0x600600,0x603c2000,0x30016800,0x1fe0000,0x1f81f8,0x1c1f,0x804067e1, 1.3119 + 0x68060168,0x16800810,0xc42300,0x0,0x60,0x20c331,0x68030060,0x6064,0x3fc1040,0xf006031c,0xa011e,0x818c7fe0,0x909000,0x7fe1f, 1.3120 + 0x80f00006,0xc0f2060,0xf80e,0x18c0780,0x780781c0,0x19819819,0x81981981,0x9833c600,0x7fe7fe7f,0xe7fe0600,0x60060060,0xfc666660, 1.3121 + 0x66066066,0x66061f0,0x66660660,0x66066060,0x606066e0,0xc00c00,0xc00c00c0,0xc066600,0x60c60c60,0xc60c0600,0x60060060,0x60c60c60, 1.3122 + 0xc60c60c6,0xc60c000,0x61c60c60,0xc60c60c3,0x1860c318,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x1980f81,0x80373000, 1.3123 + 0xc003004,0x7fe0001,0xf0000060,0x60c03003,0x183180,0xc71c060,0x3181ec00,0x7000,0xe070,0x66619860,0xc6006066,0x60061e,0x60606001, 1.3124 + 0x87606006,0x66626606,0x7f860661,0xc01c0606,0x6198696,0xf00600e,0x600600,0x30000000,0x1fc60,0xc60060c7,0xfc06060c,0x60c06003, 1.3125 + 0x7c00c06,0x6660c60c,0x60c60c0c,0x7f00c06,0xc3b8666,0xe01b007,0x3c00600,0x3c7fe000,0xff03ec00,0x1fe0000,0x40040,0xe001,0xc0806603, 1.3126 + 0xec0e03ec,0x3ec00010,0x0,0x60000000,0x7f,0x10c3f3,0xec070060,0x6064,0x3fc1040,0x6000030c,0xa0100,0x3187fe1,0xf09f1000,0x7fe00, 1.3127 + 0x6,0xc012060,0x0,0xc63c03,0xc03c0380,0x19819819,0x81981981,0x98330600,0x60060060,0x6000600,0x60060060,0xfc662660,0x66066066, 1.3128 + 0x66060e0,0x6c660660,0x66066060,0x6060e630,0x1fc1fc1f,0xc1fc1fc1,0xfc3fe600,0x7fc7fc7f,0xc7fc0600,0x60060060,0x60c60c60,0xc60c60c6, 1.3129 + 0xc60c7fe,0x62c60c60,0xc60c60c1,0xb060c1b0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0xffe02c6,0x3c633000,0xc003004, 1.3130 + 0x7fe0001,0xf00000c0,0x60c03006,0xc6180,0xc60c060,0x60c00c00,0x7000,0xe060,0x66639c60,0x66006066,0x600606,0x60606001,0x86306006, 1.3131 + 0x66636606,0x60060660,0xc0060606,0x61f8696,0xf00600c,0x600300,0x30000000,0x3fc60,0xc60060c7,0xfc06060c,0x60c06003,0x7c00c06, 1.3132 + 0x6660c60c,0x60c60c0c,0x1f80c06,0xc1b0666,0xe01b00e,0x3c00600,0x3c43c000,0x3007de00,0x600000,0x40040,0x30000,0x61006607,0xde0c07de, 1.3133 + 0x7de00000,0x0,0xf07fefff,0x1f,0x8008c3f7,0xde0e0060,0x6064,0xc01047,0xfe00018c,0xb013f,0x86300061,0xf0911000,0x6000,0x6, 1.3134 + 0xc012060,0x3f,0x8063c0cc,0x3cc0c700,0x39c39c39,0xc39c39c1,0x98630600,0x60060060,0x6000600,0x60060060,0x60663660,0x66066066, 1.3135 + 0x66061f0,0x78660660,0x66066060,0x607fc618,0x3fc3fc3f,0xc3fc3fc3,0xfc7fe600,0x7fc7fc7f,0xc7fc0600,0x60060060,0x60c60c60,0xc60c60c6, 1.3136 + 0xc60c7fe,0x64c60c60,0xc60c60c1,0xb060c1b0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0xffe0260,0x6661b000,0xc003000, 1.3137 + 0x600000,0xc0,0x60c0300c,0xc7fe0,0xc60c060,0x60c01c00,0x1e07,0xfe078060,0x6663fc60,0x66006066,0x600606,0x60606001,0x86386006, 1.3138 + 0x6636606,0x60060660,0xe0060606,0x60f039c,0x1b806018,0x600300,0x30000000,0x70c60,0xc60060c6,0x6060c,0x60c06003,0x7600c06, 1.3139 + 0x6660c60c,0x60c60c0c,0x1c0c06,0xc1b03fc,0xe01f01c,0xe00600,0x70000000,0x3007fc00,0x600000,0x40040,0x0,0x62006607,0xfc1807fc, 1.3140 + 0x7fc00000,0x0,0xf0000000,0x1,0xc004c307,0xfc1c0060,0x6064,0xc018c0,0x600000d8,0x5f200,0x3180060,0x50a000,0x6000,0x6,0xc012000, 1.3141 + 0x0,0xc601c0,0x4201c600,0x3fc3fc3f,0xc3fc3fc3,0xfc7f0600,0x60060060,0x6000600,0x60060060,0x60663660,0x66066066,0x66063b8, 1.3142 + 0x70660660,0x66066060,0x607f860c,0x70c70c70,0xc70c70c7,0xcc60600,0x60060060,0x6000600,0x60060060,0x60c60c60,0xc60c60c6,0xc60c000, 1.3143 + 0x68c60c60,0xc60c60c1,0xf060c1f0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3300260,0x6661e000,0xc003000,0x600000, 1.3144 + 0x180,0x71c03018,0xc7fe0,0xc60c0c0,0x60c01800,0x787,0xfe1e0060,0x6663fc60,0x630060c6,0x600306,0x60606001,0x86186006,0x661e70e, 1.3145 + 0x60070c60,0x60060606,0x60f039c,0x19806038,0x600180,0x30000000,0x60c60,0xc60060c6,0x6060c,0x60c06003,0x6700c06,0x6660c60c, 1.3146 + 0x60c60c0c,0xc0c06,0xc1b039c,0x1f00e018,0x600600,0x60000000,0x1803f800,0x600000,0x40040,0x39e00,0x63006603,0xf83803f8,0x3f800000, 1.3147 + 0x0,0x60000000,0x0,0xc00cc303,0xf8180060,0x6064,0xc01fc0,0x60060070,0x40200,0x18c0060,0x402000,0x6000,0x6,0xc012000,0x0,0x18c0140, 1.3148 + 0x2014600,0x3fc3fc3f,0xc3fc3fc3,0xfc7f0300,0x60060060,0x6000600,0x60060060,0x60c61e70,0xe70e70e7,0xe70e71c,0x60e60660,0x66066060, 1.3149 + 0x6060060c,0x60c60c60,0xc60c60c6,0xcc60600,0x60060060,0x6000600,0x60060060,0x60c60c60,0xc60c60c6,0xc60c000,0x70c60c60,0xc60c60c0, 1.3150 + 0xe060c0e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x33022e0,0x6670c000,0xc003000,0x600600,0x60180,0x31803030, 1.3151 + 0x41c0184,0x1831c0c0,0x71c23806,0x6001e0,0x780000,0x62630c60,0xe38261c6,0x600386,0x60606043,0x860c6006,0x661e30c,0x60030c60, 1.3152 + 0x740e0607,0xe0f039c,0x31c06030,0x600180,0x30000000,0x61c71,0x830831c3,0x406031c,0x60c06003,0x6300c06,0x6660c318,0x71831c0c, 1.3153 + 0x41c0c07,0x1c0e039c,0x1b00e030,0x600600,0x60000000,0x1c41b00e,0x601cc0,0x401f8,0x45240,0xe1803601,0xb03001b0,0x1b000000, 1.3154 + 0x0,0x0,0x41,0xc008e711,0xb0300060,0x6034,0x80c02020,0x60060030,0x30c00,0xc60000,0x30c000,0x0,0x7,0x1c012000,0x0,0x3180240, 1.3155 + 0x6024608,0x30c30c30,0xc30c30c3,0xc630382,0x60060060,0x6000600,0x60060060,0x61c61e30,0xc30c30c3,0xc30c208,0x70c70e70,0xe70e70e0, 1.3156 + 0x6060068c,0x61c61c61,0xc61c61c6,0x1cc62308,0x30430430,0x43040600,0x60060060,0x31860c31,0x83183183,0x18318060,0x31c71c71, 1.3157 + 0xc71c71c0,0xe07180e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x2203fc0,0x663f6000,0x6006000,0x600600,0x60300, 1.3158 + 0x3f81fe7f,0xc7f80187,0xf83f80c0,0x3f83f006,0x600020,0x400060,0x33e6067f,0xc1fe7f87,0xfe6001fe,0x6063fc7f,0x60e7fe6,0x660e3f8, 1.3159 + 0x6001f860,0x37fc0603,0xfc06030c,0x30c0607f,0xe06000c0,0x30000000,0x7fc7f,0x83f83fc3,0xfc0603fc,0x60c7fe03,0x61807c6,0x6660c3f8, 1.3160 + 0x7f83fc0c,0x7f80fc3,0xfc0e039c,0x3180607f,0xc0600600,0x60000000,0xfc0e00c,0x601986,0x66040040,0x4527f,0xc0803fe0,0xe07fe0e0, 1.3161 + 0xe000000,0x0,0x0,0x7f,0x80107ff0,0xe07fc060,0x603f,0x83fe0000,0x60060018,0xf000,0x420000,0xf0000,0x7fe00,0x7,0xfe012000, 1.3162 + 0x0,0x2100640,0xc0643f8,0x60660660,0x66066067,0xec3e1fe,0x7fe7fe7f,0xe7fe3fc3,0xfc3fc3fc,0x7f860e3f,0x83f83f83,0xf83f8000, 1.3163 + 0x5fc3fc3f,0xc3fc3fc0,0x606006fc,0x7fc7fc7f,0xc7fc7fc7,0xfcffe3f8,0x3fc3fc3f,0xc3fc7fe7,0xfe7fe7fe,0x3f860c3f,0x83f83f83, 1.3164 + 0xf83f8060,0x7f83fc3f,0xc3fc3fc0,0x607f8060,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x2201f80,0x3c1e7000,0x6006000, 1.3165 + 0x600,0x60300,0xe01fe7f,0xc3f00183,0xe01f0180,0x1f01e006,0x600000,0x60,0x3006067f,0x807c7e07,0xfe6000f8,0x6063fc3e,0x6067fe6, 1.3166 + 0x660e0f0,0x6000f060,0x3bf80601,0xf806030c,0x60e0607f,0xe06000c0,0x30000000,0x1ec6f,0xf01ec0,0xf80601ec,0x60c7fe03,0x61c03c6, 1.3167 + 0x6660c1f0,0x6f01ec0c,0x3f007c1,0xcc0e030c,0x71c0c07f,0xc0600600,0x60000000,0x7804018,0xe01186,0x66040040,0x39e3f,0x80401fe0, 1.3168 + 0x407fe040,0x4000000,0x0,0x0,0x3f,0x203ce0,0x407fc060,0x601f,0x3fe0000,0x60060018,0x0,0x0,0x0,0x7fe00,0x6,0xe6012000,0x0, 1.3169 + 0x7e0,0x1807e1f0,0x60660660,0x66066066,0x6c3e07c,0x7fe7fe7f,0xe7fe3fc3,0xfc3fc3fc,0x7e060e0f,0xf00f00,0xf00f0000,0x8f01f81f, 1.3170 + 0x81f81f80,0x60600670,0x1ec1ec1e,0xc1ec1ec1,0xec79c0f0,0xf80f80f,0x80f87fe7,0xfe7fe7fe,0x1f060c1f,0x1f01f01,0xf01f0000,0x4f01cc1c, 1.3171 + 0xc1cc1cc0,0xc06f00c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x200,0x0,0x6006000,0x600,0x600,0x0,0x0,0x0,0x0, 1.3172 + 0x600000,0x0,0x18000000,0x0,0x0,0x0,0x0,0x0,0x1800,0x0,0x0,0x0,0x600060,0x30000000,0x0,0x0,0xc,0x3,0x0,0x0,0x60000c00,0x0, 1.3173 + 0x0,0xc000,0x600600,0x60000000,0x18,0xc03100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x601f8,0x0,0x0,0x0,0x0,0x6, 1.3174 + 0x12000,0x2000000,0x40,0x20004000,0x0,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3175 + 0x0,0xc06000c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x200,0x0,0x2004000,0xc00,0x0,0x0,0x0,0x0,0x0,0xc00000, 1.3176 + 0x0,0x1c000000,0x0,0x0,0x0,0x0,0x0,0xc00,0x0,0x0,0x0,0x780000,0xf0000000,0x0,0x0,0x21c,0x3,0x0,0x0,0x60000c00,0x0,0x0,0xc000, 1.3177 + 0x7c0603,0xe0000000,0x10,0xc02300,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x601f0,0x0,0x0,0x0,0x0,0x6,0x12000,0x1000000, 1.3178 + 0x40,0x7e004000,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc06000c0,0x0, 1.3179 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x200,0x0,0x300c000,0xc00,0x0,0x0,0x0,0x0,0x0,0xc00000,0x0,0x7800000,0x0, 1.3180 + 0x0,0x0,0x0,0x0,0x800,0x0,0x0,0x0,0x780000,0xf0000000,0x0,0x0,0x3f8,0x3e,0x0,0x0,0x60000c00,0x0,0x0,0x38000,0x3c0603,0xc0000000, 1.3181 + 0x10,0xfc00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x60000,0x0,0x0,0x0,0x0,0x6,0x0,0x1000000,0x0,0x0,0x0,0x0, 1.3182 + 0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x80600380,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3183 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffc,0x0, 1.3184 + 0x0,0x1f0,0x3c,0x0,0x0,0x60000c00,0x0,0x0,0x38000,0x600,0x0,0x0,0xf000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3185 + 0x0,0x0,0x0,0x0,0x0,0x6,0x0,0xe000000,0x0,0x0,0x0,0x0,0x70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x70,0x0,0x0,0x0,0x0, 1.3186 + 0x0,0x0,0x0,0x3,0x80600380,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3187 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3188 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3189 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 }; 1.3190 + 1.3191 + // Definition of a 16x32 font. 1.3192 + const unsigned int font16x32[16*32*256/32] = { 1.3193 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3194 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3195 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc300000,0x0,0xc300000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3196 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x70000e0,0x3c00730,0xe7001c0,0x0,0x70000e0,0x3c00e70,0x70000e0,0x3c00e70,0x730,0x70000e0,0x3c00730, 1.3197 + 0xe700000,0x700,0xe003c0,0xe7000e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3198 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3199 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3200 + 0x0,0x0,0x6600000,0x0,0x6600000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3201 + 0x0,0x0,0x18001c0,0x6600ff0,0xe7003e0,0x0,0x18001c0,0x6600e70,0x18001c0,0x6600e70,0xff0,0x18001c0,0x6600ff0,0xe700000,0x180, 1.3202 + 0x1c00660,0xe7001c0,0x0,0x0,0x0,0x380,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3203 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3204 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000, 1.3205 + 0x0,0x3c00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c00380, 1.3206 + 0xc300ce0,0xe700630,0x0,0x1c00380,0xc300e70,0x1c00380,0xc300e70,0xce0,0x1c00380,0xc300ce0,0xe700000,0x1c0,0x3800c30,0xe700380, 1.3207 + 0x0,0x0,0x0,0x7c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3208 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3209 + 0x0,0x0,0x0,0x0,0xe000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1800000,0x0,0x0,0x0, 1.3210 + 0x0,0x0,0x0,0x0,0x0,0xc300000,0x0,0xc300000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x700000,0x0,0x0,0x0,0x7c007c00,0x3e000000, 1.3211 + 0x0,0x0,0x630,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe000070,0x1800000,0xc60,0x0,0xe000070,0x1800000,0xe000070, 1.3212 + 0x1800000,0x0,0xe000070,0x1800000,0x0,0xe00,0x700180,0x70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3213 + 0x0,0x0,0x0,0x800000,0x0,0x600600,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3214 + 0x0,0x0,0x3f0,0xfc0,0x0,0x7000000,0x38000000,0x1c0000,0xfc0000,0x380001c0,0xe01c00,0x7f800000,0x0,0x0,0x0,0x0,0x0,0x0,0x7c, 1.3215 + 0x1801f00,0x0,0x0,0x1c,0x0,0x0,0x3c00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7300000,0x6600000,0x0,0x6600000,0x0,0x0,0x0,0x0,0xe700000, 1.3216 + 0x0,0x0,0x0,0x0,0x0,0xe00000,0x0,0x0,0x0,0xc000c00,0x43800000,0x0,0x0,0x630,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3217 + 0xf80,0x70000e0,0x3c00730,0xe700c60,0x0,0x70000e0,0x3c00e70,0x70000e0,0x3c00e70,0xe000730,0x70000e0,0x3c00730,0xe700000,0x700, 1.3218 + 0xe003c0,0xe7000e0,0x38000e70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x6300000,0x803c00,0x7c00180, 1.3219 + 0xc00300,0x1000000,0x0,0x1c,0x3c007c0,0xfc007e0,0xe01ff8,0x3f03ffc,0x7e007c0,0x0,0x0,0x7c0,0x1c0,0x7f8003f0,0x7f007ff8,0x7ff803f0, 1.3220 + 0x70381ffc,0xff0700e,0x7000783c,0x783807c0,0x7fc007c0,0x7fc00fc0,0x7fff7038,0x700ee007,0x780f780f,0x7ffc03f0,0x70000fc0,0x3c00000, 1.3221 + 0x3000000,0x38000000,0x1c0000,0x1fc0000,0x380001c0,0xe01c00,0x7f800000,0x0,0x0,0x0,0x0,0x0,0x0,0xfc,0x1801f80,0x0,0x1f80000, 1.3222 + 0x7e,0x0,0x0,0x2400000,0xfc00000,0x7ff0000,0x7ffc0000,0x0,0x0,0x0,0x0,0xf30fb0c,0x2400000,0x0,0x240780f,0x1c0,0xfc,0x780f, 1.3223 + 0x18003f0,0xe700000,0x7c00000,0x0,0xff0,0x3c00000,0x78007c0,0xc00000,0xff80000,0xf80,0x7c00000,0xc000c00,0x18001c0,0x1c001c0, 1.3224 + 0x1c001c0,0x1c003e0,0x7fe03f0,0x7ff87ff8,0x7ff87ff8,0x1ffc1ffc,0x1ffc1ffc,0x7f007838,0x7c007c0,0x7c007c0,0x7c00000,0x7c67038, 1.3225 + 0x70387038,0x7038780f,0x70001fe0,0x30000c0,0x2400f30,0xe700c60,0x0,0x30000c0,0x2400e70,0x30000c0,0x2400e70,0xf700f30,0x30000c0, 1.3226 + 0x2400f30,0xe700000,0x300,0xc00240,0xe7000c0,0x38000e70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0, 1.3227 + 0x630018c,0x807e00,0xfe00180,0xc00300,0x1000000,0x0,0x38,0xff01fc0,0x3ff01ff0,0x1e01ff8,0x7f83ffc,0x1ff80ff0,0x0,0x0,0xff0, 1.3228 + 0x1f003e0,0x7fe00ff8,0x7fc07ff8,0x7ff80ff8,0x70381ffc,0xff0701c,0x7000783c,0x78381ff0,0x7fe01ff0,0x7fe01ff0,0x7fff7038,0x781ee007, 1.3229 + 0x3c1e380e,0x7ffc0380,0x380001c0,0x3c00000,0x1800000,0x38000000,0x1c0000,0x3c00000,0x380001c0,0xe01c00,0x3800000,0x0,0x0, 1.3230 + 0x0,0x7000000,0x0,0x0,0x1e0,0x18003c0,0x0,0x3fc0000,0x70,0x0,0x0,0x6600000,0x1ff00000,0x1fff0000,0x7ffc0000,0x0,0x0,0x0,0x0, 1.3231 + 0xcf0239c,0x3c00000,0x0,0x3c0380e,0x1c0,0x2001fe,0x380e,0x18007f8,0xe700000,0x8600000,0x0,0xff0,0x7e00000,0x8c00870,0x1800000, 1.3232 + 0x1ff80000,0x180,0xc600000,0xc000c00,0x38001c0,0x3e003e0,0x3e003e0,0x3e001c0,0x7fe0ff8,0x7ff87ff8,0x7ff87ff8,0x1ffc1ffc,0x1ffc1ffc, 1.3233 + 0x7fc07838,0x1ff01ff0,0x1ff01ff0,0x1ff00000,0x1fec7038,0x70387038,0x7038380e,0x70003ce0,0x1800180,0x6600cf0,0xe7007c0,0x0, 1.3234 + 0x1800180,0x6600e70,0x1800180,0x6600e70,0x7c00cf0,0x1800180,0x6600cf0,0xe700000,0x180,0x1800660,0xe700180,0x38000e70,0x0, 1.3235 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x630030c,0x3f0e700,0x1e200180,0x1800180,0x21100000,0x0, 1.3236 + 0x38,0x1e7819c0,0x38781038,0x1e01c00,0xf080038,0x1c381c38,0x0,0x0,0x1878,0x7fc03e0,0x70e01e18,0x70e07000,0x70001e18,0x703801c0, 1.3237 + 0x707038,0x70007c7c,0x7c381c70,0x70701c70,0x70703830,0x1c07038,0x381ce007,0x1c1c3c1e,0x3c0380,0x380001c0,0x7e00000,0xc00000, 1.3238 + 0x38000000,0x1c0000,0x3800000,0x38000000,0x1c00,0x3800000,0x0,0x0,0x0,0x7000000,0x0,0x0,0x1c0,0x18001c0,0x0,0x70c0000,0xe0, 1.3239 + 0x0,0x0,0xc300000,0x38300000,0x3c700000,0x3c0000,0x0,0x0,0x0,0x0,0xce022f4,0x1800000,0x0,0x1803c1e,0x1c0,0x2003c2,0x3c1e, 1.3240 + 0x1800e08,0x7e0,0x300000,0x0,0x7e00000,0xe700000,0x600030,0x3000000,0x3f980000,0x180,0x18200000,0xc000c00,0x1e0001c0,0x3e003e0, 1.3241 + 0x3e003e0,0x3e003e0,0xfe01e18,0x70007000,0x70007000,0x1c001c0,0x1c001c0,0x70e07c38,0x1c701c70,0x1c701c70,0x1c700000,0x3c787038, 1.3242 + 0x70387038,0x70383c1e,0x70003870,0xc00300,0xc300ce0,0x380,0x0,0xc00300,0xc300000,0xc00300,0xc300000,0xfc00ce0,0xc00300,0xc300ce0, 1.3243 + 0x0,0xc0,0x3000c30,0x300,0x38000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x630031c,0xff8c300, 1.3244 + 0x1c000180,0x1800180,0x39380000,0x0,0x70,0x1c3801c0,0x203c001c,0x3e01c00,0x1c000038,0x381c3838,0x0,0x0,0x1038,0xe0e03e0,0x70703c08, 1.3245 + 0x70707000,0x70003808,0x703801c0,0x707070,0x70007c7c,0x7c383838,0x70383838,0x70387010,0x1c07038,0x381c700e,0x1e3c1c1c,0x780380, 1.3246 + 0x1c0001c0,0xe700000,0x0,0x38000000,0x1c0000,0x3800000,0x38000000,0x1c00,0x3800000,0x0,0x0,0x0,0x7000000,0x0,0x0,0x1c0,0x18001c0, 1.3247 + 0x0,0xe000000,0xe0,0x0,0x1000100,0x3800,0x70100000,0x38700000,0x780000,0x1c0,0x7801ce0,0xe380000,0x0,0x2264,0x0,0x0,0x1c1c, 1.3248 + 0x0,0x200780,0x1c1c,0x1800c00,0x1818,0x7f00000,0x0,0x18180000,0xc300000,0x600070,0x0,0x7f980000,0x180,0x18300000,0xc000c00, 1.3249 + 0x3000000,0x3e003e0,0x3e003e0,0x3e003e0,0xee03c08,0x70007000,0x70007000,0x1c001c0,0x1c001c0,0x70707c38,0x38383838,0x38383838, 1.3250 + 0x38380000,0x38387038,0x70387038,0x70381c1c,0x7fc03870,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xbc00000,0x0,0x0,0x0,0x0,0x0,0x0, 1.3251 + 0x38000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x6300318,0xe88c300,0x1c000180,0x38001c0, 1.3252 + 0xfe00180,0x0,0x70,0x1c3801c0,0x1c001c,0x6e01c00,0x1c000078,0x381c3818,0x0,0x40000,0x40000038,0x1c0607e0,0x70703800,0x70707000, 1.3253 + 0x70003800,0x703801c0,0x7070e0,0x70007c7c,0x7c383838,0x70383838,0x70387000,0x1c07038,0x381c700e,0xf780e38,0x700380,0x1c0001c0, 1.3254 + 0x1c380000,0x0,0x38000000,0x1c0000,0x3800000,0x38000000,0x1c00,0x3800000,0x0,0x0,0x0,0x7000000,0x0,0x0,0x1c0,0x18001c0,0x0, 1.3255 + 0xe000000,0xe0,0x0,0x1000100,0x4400,0x70000000,0x38700000,0x700000,0xe0,0x7001c70,0xe380000,0x0,0x2264,0x0,0x0,0xe38,0x0, 1.3256 + 0x200700,0xe38,0x1800c00,0x300c,0xc300000,0x0,0x300c0000,0xc300180,0x6003c0,0x0,0x7f980000,0x180,0x18300000,0xc000c00,0x1800000, 1.3257 + 0x7e007e0,0x7e007e0,0x7e003e0,0xee03800,0x70007000,0x70007000,0x1c001c0,0x1c001c0,0x70707c38,0x38383838,0x38383838,0x38380000, 1.3258 + 0x38387038,0x70387038,0x70380e38,0x7ff039f0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1e00000,0x0,0x0,0x0,0x40000,0x0,0x0,0x38000000, 1.3259 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x6300318,0x1c80e700,0x1c000180,0x38001c0,0x3800180, 1.3260 + 0x0,0xe0,0x381c01c0,0x1c001c,0x6e01c00,0x38000070,0x381c381c,0x0,0x3c0000,0x78000078,0x38030770,0x70707800,0x70387000,0x70007000, 1.3261 + 0x703801c0,0x7071c0,0x7000745c,0x7638701c,0x7038701c,0x70387000,0x1c07038,0x1c38718e,0x7700f78,0xf00380,0xe0001c0,0x381c0000, 1.3262 + 0x7e0,0x39e003e0,0x79c03f0,0x3ffc079c,0x39e01fc0,0xfe01c1e,0x3807778,0x39e007e0,0x39e0079c,0x73c07e0,0x7ff83838,0x701ce007, 1.3263 + 0x783c701c,0x1ffc01c0,0x18001c0,0x0,0x1c000100,0xe0,0x0,0x1000100,0x4200,0x70000000,0x70700100,0xf00100,0x10000e0,0x7000c70, 1.3264 + 0xc700000,0x0,0x2204,0x7e00000,0x1e380100,0x1ffc0f78,0x0,0xf80700,0xf78,0x1800e00,0x63e6,0x18300000,0x0,0x6fe60000,0xe700180, 1.3265 + 0xc00060,0x3838,0x7f980000,0x180,0x18300000,0xc000c00,0x18001c0,0x7700770,0x7700770,0x77007f0,0xee07800,0x70007000,0x70007000, 1.3266 + 0x1c001c0,0x1c001c0,0x70387638,0x701c701c,0x701c701c,0x701c1008,0x707c7038,0x70387038,0x70380f78,0x707039c0,0x7e007e0,0x7e007e0, 1.3267 + 0x7e007e0,0x1f3c03e0,0x3f003f0,0x3f003f0,0x1fc01fc0,0x1fc01fc0,0x7f039e0,0x7e007e0,0x7e007e0,0x7e00380,0x7ce3838,0x38383838, 1.3268 + 0x3838701c,0x39e0701c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x6307fff,0x1c807e0c,0xe000180, 1.3269 + 0x30000c0,0x3800180,0x0,0xe0,0x381c01c0,0x1c001c,0xce01fe0,0x38000070,0x381c381c,0x3800380,0xfc0000,0x7e0000f0,0x30030770, 1.3270 + 0x70707000,0x70387000,0x70007000,0x703801c0,0x707380,0x700076dc,0x7638701c,0x7038701c,0x70387800,0x1c07038,0x1c3873ce,0x7f00770, 1.3271 + 0xe00380,0xe0001c0,0x700e0000,0x1ff8,0x3ff00ff0,0xffc0ff8,0x3ffc0ffc,0x3bf01fc0,0xfe01c3c,0x3807f78,0x3bf00ff0,0x3ff00ffc, 1.3272 + 0x77e0ff0,0x7ff83838,0x3838e007,0x3c783838,0x1ffc01c0,0x18001c0,0x0,0x7ff00380,0x1e0,0x0,0x1000100,0x4200,0x78000000,0x70700380, 1.3273 + 0xe00380,0x3800060,0xe000e30,0x1c600000,0x0,0x2204,0xff00000,0x7f7c0380,0x1ffc0770,0x1c0,0x3fc0700,0x18040770,0x1800780,0x4e12, 1.3274 + 0x18300104,0x0,0x4c320000,0x7e00180,0x1c00030,0x3838,0x7f980000,0x180,0x18302080,0xc000c00,0x18001c0,0x7700770,0x7700770, 1.3275 + 0x7700770,0x1ee07000,0x70007000,0x70007000,0x1c001c0,0x1c001c0,0x70387638,0x701c701c,0x701c701c,0x701c381c,0x705c7038,0x70387038, 1.3276 + 0x70380770,0x70383b80,0x1ff81ff8,0x1ff81ff8,0x1ff81ff8,0x3fbe0ff0,0xff80ff8,0xff80ff8,0x1fc01fc0,0x1fc01fc0,0xff83bf0,0xff00ff0, 1.3277 + 0xff00ff0,0xff00380,0xffc3838,0x38383838,0x38383838,0x3ff03838,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3278 + 0x0,0x1c0,0x7fff,0x1c803c38,0xf000000,0x70000e0,0xfe00180,0x0,0x1c0,0x381c01c0,0x3c0078,0xce01ff0,0x39e000f0,0x1c38381c,0x3800380, 1.3279 + 0x3e07ffc,0xf8001f0,0x307b0770,0x70e07000,0x70387000,0x70007000,0x703801c0,0x707700,0x700076dc,0x7638701c,0x7038701c,0x70387e00, 1.3280 + 0x1c07038,0x1c3873ce,0x3e007f0,0x1e00380,0x70001c0,0x0,0x1038,0x3c381e18,0x1c7c1e3c,0x3801e3c,0x3c7801c0,0xe01c78,0x380739c, 1.3281 + 0x3c781c38,0x3c381c3c,0x7c21e10,0x7003838,0x3838700e,0x1ef03838,0x3c01c0,0x18001c0,0x0,0x7fe007c0,0x1c0,0x0,0x1000100,0x6400, 1.3282 + 0x7e000000,0x707007c0,0x1e007c0,0x7c00070,0xe000638,0x18600000,0x0,0x0,0x1e100000,0x73ce07c0,0x3c07f0,0x1c0,0x7240700,0x1ddc3ffe, 1.3283 + 0x1800de0,0x8c01,0x1870030c,0x0,0x8c310000,0x3c00180,0x3800030,0x3838,0x7f980000,0x180,0x183030c0,0xc000c00,0x430001c0,0x7700770, 1.3284 + 0x7700770,0x7700770,0x1ce07000,0x70007000,0x70007000,0x1c001c0,0x1c001c0,0x70387638,0x701c701c,0x701c701c,0x701c1c38,0x70dc7038, 1.3285 + 0x70387038,0x703807f0,0x70383b80,0x10381038,0x10381038,0x10381038,0x21e71e18,0x1e3c1e3c,0x1e3c1e3c,0x1c001c0,0x1c001c0,0x1e383c78, 1.3286 + 0x1c381c38,0x1c381c38,0x1c380380,0x1c383838,0x38383838,0x38383838,0x3c383838,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3287 + 0x0,0x0,0x0,0x0,0x0,0x1c0,0x630,0x1e8000e0,0x1f000000,0x70000e0,0x39380180,0x0,0x1c0,0x3b9c01c0,0x3c07f0,0x18e01078,0x3bf800e0, 1.3288 + 0x7e0383c,0x3800380,0x1f807ffc,0x3f001c0,0x61ff0e38,0x7fc07000,0x70387ff0,0x7ff07000,0x7ff801c0,0x707f00,0x7000729c,0x7338701c, 1.3289 + 0x7070701c,0x70703fc0,0x1c07038,0x1e7873ce,0x1c003e0,0x3c00380,0x70001c0,0x0,0x1c,0x3c381c00,0x1c3c1c1c,0x3801c3c,0x383801c0, 1.3290 + 0xe01cf0,0x380739c,0x38381c38,0x3c381c3c,0x7801c00,0x7003838,0x3838700e,0xfe03c78,0x7801c0,0x18001c0,0x0,0x1c000c20,0xff8, 1.3291 + 0x0,0x1ff01ff0,0x3818,0x3fc00100,0x707e0c20,0x3c00c20,0xc200030,0xc000618,0x18c00000,0x0,0x0,0x1c000080,0xe1ce0c20,0x7803e0, 1.3292 + 0x1c0,0xe200700,0xff83ffe,0x1801878,0x9801,0x1cf0071c,0x7ffc0000,0x8c310000,0x7ffe,0x7000030,0x3838,0x3f980380,0x180,0xc6038e0, 1.3293 + 0x7f9c7f9c,0x3e1c01c0,0xe380e38,0xe380e38,0xe380f78,0x1cfc7000,0x7ff07ff0,0x7ff07ff0,0x1c001c0,0x1c001c0,0xfe387338,0x701c701c, 1.3294 + 0x701c701c,0x701c0e70,0x719c7038,0x70387038,0x703803e0,0x70383b80,0x1c001c,0x1c001c,0x1c001c,0xe71c00,0x1c1c1c1c,0x1c1c1c1c, 1.3295 + 0x1c001c0,0x1c001c0,0x1c383838,0x1c381c38,0x1c381c38,0x1c380000,0x3c383838,0x38383838,0x38383c78,0x3c383c78,0x0,0x0,0x0,0x0, 1.3296 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x630,0xf800380,0x3f830000,0x70000e0,0x31080180,0x0,0x380,0x3b9c01c0, 1.3297 + 0x7807e0,0x38e00038,0x3c3800e0,0xff01c3c,0x3800380,0x7c000000,0x7c03c0,0x61870e38,0x7fc07000,0x70387ff0,0x7ff070fc,0x7ff801c0, 1.3298 + 0x707f80,0x7000739c,0x7338701c,0x7ff0701c,0x7fe00ff0,0x1c07038,0xe7073ce,0x1c003e0,0x3800380,0x38001c0,0x0,0x1c,0x381c3800, 1.3299 + 0x381c380e,0x380381c,0x383801c0,0xe01de0,0x380739c,0x3838381c,0x381c381c,0x7001e00,0x7003838,0x1c70718e,0x7e01c70,0xf00380, 1.3300 + 0x18001e0,0x1e000000,0x1c001bb0,0xff8,0x0,0x1000100,0xe0,0xff00300,0x707e1bb0,0x3801bb0,0x1bb00010,0x8000308,0x30c00000,0x0, 1.3301 + 0x0,0x1e0000c0,0xe1ce1bb0,0xf003e0,0x1c0,0x1c203ff8,0x63003e0,0x180181c,0x9801,0xfb00e38,0x7ffc0000,0x8fc10000,0x7ffe,0xe000860, 1.3302 + 0x3838,0x1f980380,0x180,0x7c01c70,0x1f001f0,0x1f003c0,0xe380e38,0xe380e38,0xe380e38,0x1cfc7000,0x7ff07ff0,0x7ff07ff0,0x1c001c0, 1.3303 + 0x1c001c0,0xfe387338,0x701c701c,0x701c701c,0x701c07e0,0x731c7038,0x70387038,0x703803e0,0x70383980,0x1c001c,0x1c001c,0x1c001c, 1.3304 + 0xe73800,0x380e380e,0x380e380e,0x1c001c0,0x1c001c0,0x381c3838,0x381c381c,0x381c381c,0x381c0000,0x387c3838,0x38383838,0x38381c70, 1.3305 + 0x381c1c70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0xc30,0x7f00e00,0x33c30000,0x70000e0,0x1007ffe, 1.3306 + 0x0,0x380,0x3b9c01c0,0xf00078,0x30e0001c,0x3c1c01c0,0x1c381fdc,0x0,0x70000000,0x1c0380,0x63030e38,0x70707000,0x70387000,0x700070fc, 1.3307 + 0x703801c0,0x707b80,0x7000739c,0x7338701c,0x7fc0701c,0x7fc001f0,0x1c07038,0xe703e5c,0x3e001c0,0x7800380,0x38001c0,0x0,0x7fc, 1.3308 + 0x381c3800,0x381c380e,0x380381c,0x383801c0,0xe01fe0,0x380739c,0x3838381c,0x381c381c,0x7001fc0,0x7003838,0x1c70718e,0x7c01c70, 1.3309 + 0xe01f00,0x180007c,0x7f8c0000,0x7fc03fb8,0x1c0,0x0,0x1000100,0x700,0x1f00600,0x70703fb8,0x7803fb8,0x3fb80000,0x8000000,0x180, 1.3310 + 0x0,0x0,0x1fc00060,0xe1ce3fb8,0xe001c0,0x1c0,0x1c203ff8,0xc1801c0,0x180c,0x9801,0x1c70,0xc0000,0x8cc10000,0x180,0xfe007c0, 1.3311 + 0x3838,0x7980380,0xff0,0xe38,0x3e003e00,0x3e000380,0xe380e38,0xe380e38,0xe380e38,0x38e07000,0x70007000,0x70007000,0x1c001c0, 1.3312 + 0x1c001c0,0x70387338,0x701c701c,0x701c701c,0x701c03c0,0x731c7038,0x70387038,0x703801c0,0x703838e0,0x7fc07fc,0x7fc07fc,0x7fc07fc, 1.3313 + 0xe73800,0x380e380e,0x380e380e,0x1c001c0,0x1c001c0,0x381c3838,0x381c381c,0x381c381c,0x381c7ffc,0x38dc3838,0x38383838,0x38381c70, 1.3314 + 0x381c1c70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0xc60,0xf83878,0x71e30000,0x70000e0,0x1007ffe, 1.3315 + 0x7f0,0x380,0x381c01c0,0x1e0003c,0x60e0001c,0x381c01c0,0x381c079c,0x0,0x7c000000,0x7c0380,0x63031c1c,0x70307000,0x70387000, 1.3316 + 0x7000701c,0x703801c0,0x7071c0,0x7000739c,0x71b8701c,0x7000701c,0x71e00078,0x1c07038,0xe703e7c,0x7e001c0,0xf000380,0x38001c0, 1.3317 + 0x0,0x1ffc,0x381c3800,0x381c3ffe,0x380381c,0x383801c0,0xe01fc0,0x380739c,0x3838381c,0x381c381c,0x7000ff0,0x7003838,0x1ef03bdc, 1.3318 + 0x3800ee0,0x1e01f00,0x180007c,0x61fc0000,0x7fc07f3c,0x1c0,0x0,0x1000100,0x1800,0x780c00,0x70707f3c,0xf007f3c,0x7f3c0000,0x0, 1.3319 + 0x3c0,0x3ffcffff,0x0,0xff00030,0xe1fe7f3c,0x1e001c0,0x1c0,0x1c200700,0xc183ffe,0xe0c,0x9801,0x1ff038e0,0xc07f0,0x8c610000, 1.3320 + 0x180,0x0,0x3838,0x1980380,0x0,0x1ff0071c,0xe000e000,0xe0000f80,0x1c1c1c1c,0x1c1c1c1c,0x1c1c1e38,0x38e07000,0x70007000,0x70007000, 1.3321 + 0x1c001c0,0x1c001c0,0x703871b8,0x701c701c,0x701c701c,0x701c03c0,0x761c7038,0x70387038,0x703801c0,0x70703870,0x1ffc1ffc,0x1ffc1ffc, 1.3322 + 0x1ffc1ffc,0xfff3800,0x3ffe3ffe,0x3ffe3ffe,0x1c001c0,0x1c001c0,0x381c3838,0x381c381c,0x381c381c,0x381c7ffc,0x389c3838,0x38383838, 1.3323 + 0x38380ee0,0x381c0ee0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0xfffc,0xbc60fc,0x70e30000,0x70000e0, 1.3324 + 0x180,0x7f0,0x700,0x381c01c0,0x3e0001c,0x7ffc001c,0x381c03c0,0x381c001c,0x0,0x1f807ffc,0x3f00380,0x63031ffc,0x70387000,0x70387000, 1.3325 + 0x7000701c,0x703801c0,0x7071e0,0x7000701c,0x71b8701c,0x7000701c,0x70f00038,0x1c07038,0x7e03e7c,0x77001c0,0xe000380,0x1c001c0, 1.3326 + 0x0,0x3c1c,0x381c3800,0x381c3ffe,0x380381c,0x383801c0,0xe01fe0,0x380739c,0x3838381c,0x381c381c,0x70003f8,0x7003838,0xee03bdc, 1.3327 + 0x3c00ee0,0x3c00380,0x18000e0,0xf00000,0x1c007e7c,0x3c0,0x0,0x1000100,0x0,0x381800,0x70707e7c,0xe007e7c,0x7e7c0000,0x0,0x7c0, 1.3328 + 0x0,0x0,0x3f80018,0xe1fe7e7c,0x3c001c0,0x1c0,0x1c200700,0xc183ffe,0xf0c,0x8c01,0x38e0,0xc07f0,0x8c710000,0x180,0x0,0x3838, 1.3329 + 0x1980000,0x0,0x71c,0x7000f0,0x700f00,0x1ffc1ffc,0x1ffc1ffc,0x1ffc1ffc,0x3fe07000,0x70007000,0x70007000,0x1c001c0,0x1c001c0, 1.3330 + 0x703871b8,0x701c701c,0x701c701c,0x701c07e0,0x7c1c7038,0x70387038,0x703801c0,0x7ff03838,0x3c1c3c1c,0x3c1c3c1c,0x3c1c3c1c, 1.3331 + 0x3fff3800,0x3ffe3ffe,0x3ffe3ffe,0x1c001c0,0x1c001c0,0x381c3838,0x381c381c,0x381c381c,0x381c0000,0x391c3838,0x38383838,0x38380ee0, 1.3332 + 0x381c0ee0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfffc,0x9c01ce,0x70f60000,0x70000e0,0x180, 1.3333 + 0x0,0x700,0x381c01c0,0x780001c,0x7ffc001c,0x381c0380,0x381c003c,0x0,0x3e07ffc,0xf800380,0x63031ffc,0x70387000,0x70387000, 1.3334 + 0x7000701c,0x703801c0,0x7070f0,0x7000701c,0x71b8701c,0x7000701c,0x70700038,0x1c07038,0x7e03e7c,0xf7801c0,0x1e000380,0x1c001c0, 1.3335 + 0x0,0x381c,0x381c3800,0x381c3800,0x380381c,0x383801c0,0xe01fe0,0x380739c,0x3838381c,0x381c381c,0x7000078,0x7003838,0xee03a5c, 1.3336 + 0x7c00fe0,0x78001c0,0x18001c0,0x0,0x1c003ef8,0x380,0x0,0x1000100,0x810,0x383000,0x70703ef8,0x1e003ef8,0x3ef80000,0x0,0x7c0, 1.3337 + 0x0,0x0,0x78000c,0xe1c03ef8,0x78001c0,0x1c0,0x1c200700,0x63001c0,0x18003f8,0x4e12,0x1c70,0xc0000,0x4c320000,0x180,0x0,0x3838, 1.3338 + 0x1980000,0x0,0xe38,0x700118,0x701e00,0x1ffc1ffc,0x1ffc1ffc,0x1ffc1ffc,0x7fe07000,0x70007000,0x70007000,0x1c001c0,0x1c001c0, 1.3339 + 0x703871b8,0x701c701c,0x701c701c,0x701c0e70,0x7c1c7038,0x70387038,0x703801c0,0x7fc0381c,0x381c381c,0x381c381c,0x381c381c, 1.3340 + 0x78e03800,0x38003800,0x38003800,0x1c001c0,0x1c001c0,0x381c3838,0x381c381c,0x381c381c,0x381c0000,0x3b1c3838,0x38383838,0x38380fe0, 1.3341 + 0x381c0fe0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1860,0x9c0186,0x707e0000,0x30000c0,0x180, 1.3342 + 0x0,0xe00,0x183801c0,0xf00001c,0xe0001c,0x181c0380,0x381c0038,0x0,0xfc0000,0x7e000000,0x61873c1e,0x70383800,0x70707000,0x7000381c, 1.3343 + 0x703801c0,0x707070,0x7000701c,0x70f83838,0x70003838,0x70780038,0x1c07038,0x7e03c3c,0xe3801c0,0x1c000380,0xe001c0,0x0,0x381c, 1.3344 + 0x381c3800,0x381c3800,0x380381c,0x383801c0,0xe01ef0,0x380739c,0x3838381c,0x381c381c,0x7000038,0x7003838,0xfe03e7c,0xfe007c0, 1.3345 + 0x70001c0,0x18001c0,0x0,0xe001ff0,0x380,0x0,0x1000100,0x162c,0x381800,0x30701ff0,0x1c001ff0,0x1ff00000,0x0,0x3c0,0x0,0x0, 1.3346 + 0x380018,0xe1c01ff0,0x70001c0,0x1c0,0x1c200700,0xff801c0,0x18000f0,0x63e6,0xe38,0x0,0x6c3e0000,0x0,0x0,0x3838,0x1980000,0x0, 1.3347 + 0x1c70,0xf0000c,0xf01c00,0x3c1e3c1e,0x3c1e3c1e,0x3c1e3c1c,0x70e03800,0x70007000,0x70007000,0x1c001c0,0x1c001c0,0x707070f8, 1.3348 + 0x38383838,0x38383838,0x38381c38,0x38387038,0x70387038,0x703801c0,0x7000381c,0x381c381c,0x381c381c,0x381c381c,0x70e03800, 1.3349 + 0x38003800,0x38003800,0x1c001c0,0x1c001c0,0x381c3838,0x381c381c,0x381c381c,0x381c0380,0x3e1c3838,0x38383838,0x383807c0,0x381c07c0, 1.3350 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18c0,0x9c0186,0x783c0000,0x38001c0,0x180,0x3800000, 1.3351 + 0x3800e00,0x1c3801c0,0x1e00003c,0xe00038,0x1c1c0780,0x381c0038,0x3800380,0x3c0000,0x78000000,0x61ff380e,0x70383808,0x70707000, 1.3352 + 0x7000381c,0x703801c0,0x40707078,0x7000701c,0x70f83838,0x70003838,0x70384038,0x1c07038,0x7e03c3c,0x1e3c01c0,0x3c000380,0xe001c0, 1.3353 + 0x0,0x383c,0x3c381c00,0x1c3c1c00,0x3801c3c,0x383801c0,0xe01c78,0x380739c,0x38381c38,0x3c381c3c,0x7000038,0x7003878,0x7c01e78, 1.3354 + 0x1ef007c0,0xf0001c0,0x18001c0,0x0,0xe000ee0,0x7800380,0xe380000,0x1001ff0,0x2242,0x40380c00,0x38700ee0,0x3c000ee0,0xee00000, 1.3355 + 0x0,0x0,0x0,0x0,0x380030,0xe1c00ee0,0xf0001c0,0x1c0,0xe200700,0xdd801c0,0x1800038,0x300c,0x71c,0x0,0x300c0000,0x0,0x0,0x3838, 1.3356 + 0x1980000,0x0,0x38e0,0xb0000c,0xb01c08,0x380e380e,0x380e380e,0x380e380e,0x70e03808,0x70007000,0x70007000,0x1c001c0,0x1c001c0, 1.3357 + 0x707070f8,0x38383838,0x38383838,0x3838381c,0x38387038,0x70387038,0x703801c0,0x7000381c,0x383c383c,0x383c383c,0x383c383c, 1.3358 + 0x70e01c00,0x1c001c00,0x1c001c00,0x1c001c0,0x1c001c0,0x1c383838,0x1c381c38,0x1c381c38,0x1c380380,0x1c383878,0x38783878,0x387807c0, 1.3359 + 0x3c3807c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x18c0,0x10b801ce,0x3c3e0000,0x38001c0,0x180, 1.3360 + 0x3800000,0x3801c00,0x1e7801c0,0x3c002078,0xe02078,0x1c380700,0x1c3810f0,0x3800380,0x40000,0x40000380,0x307b380e,0x70701e18, 1.3361 + 0x70e07000,0x70001c1c,0x703801c0,0x60e0703c,0x7000701c,0x70f83c78,0x70003c70,0x703c70f0,0x1c03870,0x3c01c3c,0x3c1c01c0,0x78000380, 1.3362 + 0x7001c0,0x0,0x3c7c,0x3c381e18,0x1c7c1e0c,0x3801c3c,0x383801c0,0xe01c38,0x3c0739c,0x38381c38,0x3c381c3c,0x7001078,0x7803c78, 1.3363 + 0x7c01c38,0x1c780380,0x1e0001c0,0x18001c0,0x0,0x70c06c0,0x7000380,0xe300000,0x1000100,0x2142,0x70f00600,0x3c7006c0,0x780006c0, 1.3364 + 0x6c00000,0x0,0x0,0x0,0x0,0x10780060,0x73e206c0,0x1e0001c0,0x1c0,0x7240700,0x180c01c0,0x1800018,0x1818,0x30c,0x0,0x18180000, 1.3365 + 0x0,0x0,0x3c78,0x1980000,0x0,0x30c0,0x130000c,0x1301c18,0x380e380e,0x380e380e,0x380e380e,0x70e01e18,0x70007000,0x70007000, 1.3366 + 0x1c001c0,0x1c001c0,0x70e070f8,0x3c783c78,0x3c783c78,0x3c781008,0x7c783870,0x38703870,0x387001c0,0x70003a3c,0x3c7c3c7c,0x3c7c3c7c, 1.3367 + 0x3c7c3c7c,0x79f11e18,0x1e0c1e0c,0x1e0c1e0c,0x1c001c0,0x1c001c0,0x1c783838,0x1c381c38,0x1c381c38,0x1c380380,0x1c383c78,0x3c783c78, 1.3368 + 0x3c780380,0x3c380380,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x38c0,0x1ff800fc,0x1fee0000, 1.3369 + 0x1800180,0x180,0x3800000,0x3801c00,0xff01ffc,0x3ffc3ff0,0xe03ff0,0xff00700,0x1ff81fe0,0x3800380,0x0,0x380,0x3000780f,0x7ff00ff8, 1.3370 + 0x7fc07ff8,0x70000ffc,0x70381ffc,0x7fe0701c,0x7ff8701c,0x70781ff0,0x70001ff0,0x701c7ff0,0x1c01fe0,0x3c01c38,0x380e01c0,0x7ffc0380, 1.3371 + 0x7001c0,0x0,0x1fdc,0x3ff00ff0,0xffc0ffc,0x3800fdc,0x38383ffe,0xe01c3c,0x1fc739c,0x38380ff0,0x3ff00ffc,0x7001ff0,0x3f81fb8, 1.3372 + 0x7c01c38,0x3c3c0380,0x1ffc01c0,0x18001c0,0x0,0x3fc0380,0x7000380,0xc70718c,0x1000100,0x2244,0x7ff00200,0x1fff0380,0x7ffc0380, 1.3373 + 0x3800000,0x0,0x0,0x0,0x0,0x1ff000c0,0x7f7e0380,0x1ffc01c0,0x1c0,0x3fc3ffe,0x1c0,0x1800018,0x7e0,0x104,0x0,0x7e00000,0x7ffe, 1.3374 + 0x0,0x3fde,0x1980000,0x0,0x2080,0x3300018,0x3300ff0,0x780f780f,0x780f780f,0x780f780e,0xf0fe0ff8,0x7ff87ff8,0x7ff87ff8,0x1ffc1ffc, 1.3375 + 0x1ffc1ffc,0x7fc07078,0x1ff01ff0,0x1ff01ff0,0x1ff00000,0x7ff01fe0,0x1fe01fe0,0x1fe001c0,0x70003bf8,0x1fdc1fdc,0x1fdc1fdc, 1.3376 + 0x1fdc1fdc,0x3fbf0ff0,0xffc0ffc,0xffc0ffc,0x3ffe3ffe,0x3ffe3ffe,0xff03838,0xff00ff0,0xff00ff0,0xff00000,0x3ff01fb8,0x1fb81fb8, 1.3377 + 0x1fb80380,0x3ff00380,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x31c0,0x7e00078,0x7cf0000,0x1800180, 1.3378 + 0x0,0x3800000,0x3803800,0x3c01ffc,0x3ffc0fe0,0xe01fc0,0x3e00e00,0x7e00f80,0x3800380,0x0,0x380,0x18007007,0x7fc003f0,0x7f007ff8, 1.3379 + 0x700003f0,0x70381ffc,0x3f80701e,0x7ff8701c,0x707807c0,0x700007c0,0x701e1fc0,0x1c00fc0,0x3c01818,0x780f01c0,0x7ffc0380,0x3801c0, 1.3380 + 0x0,0xf9c,0x39e003e0,0x79c03f0,0x380079c,0x38383ffe,0xe01c1e,0x7c739c,0x383807e0,0x39e0079c,0x7000fc0,0x1f80f38,0x3801c38, 1.3381 + 0x781e0380,0x1ffc01c0,0x18001c0,0x0,0x1f80100,0xe000700,0x1c60718c,0x1000100,0x1e3c,0x1fc00100,0x7ff0100,0x7ffc0100,0x1000000, 1.3382 + 0x0,0x0,0x0,0x0,0xfc00080,0x3e3c0100,0x1ffc01c0,0x1c0,0xf83ffe,0x1c0,0x1800838,0x0,0x0,0x0,0x0,0x7ffe,0x0,0x3b9e,0x1980000, 1.3383 + 0x0,0x0,0x2300038,0x23003e0,0x70077007,0x70077007,0x70077007,0xe0fe03f0,0x7ff87ff8,0x7ff87ff8,0x1ffc1ffc,0x1ffc1ffc,0x7f007078, 1.3384 + 0x7c007c0,0x7c007c0,0x7c00000,0xc7c00fc0,0xfc00fc0,0xfc001c0,0x700039f0,0xf9c0f9c,0xf9c0f9c,0xf9c0f9c,0x1f1e03e0,0x3f003f0, 1.3385 + 0x3f003f0,0x3ffe3ffe,0x3ffe3ffe,0x7e03838,0x7e007e0,0x7e007e0,0x7e00000,0x63e00f38,0xf380f38,0xf380380,0x39e00380,0x0,0x0, 1.3386 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x800000,0x0,0xc00300,0x0,0x3000000,0x3800,0x0,0x0,0x0,0x0, 1.3387 + 0x0,0x300,0x0,0x0,0x1c000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe0,0x0,0x0,0x0,0x0,0x380,0x3801c0,0x0,0x0,0x0,0x0,0x1c,0x0,0xe00000, 1.3388 + 0x0,0x0,0x3800001c,0x0,0x0,0x0,0x700,0x1c0,0x18001c0,0x0,0x0,0xe000700,0x18600000,0x1000100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3389 + 0x0,0x0,0x0,0x0,0x0,0x200000,0x0,0x1800ff0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x1980000,0x1800000,0x0,0x6300070,0x6300000,0x0, 1.3390 + 0x0,0x0,0xc0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40000000, 1.3391 + 0x0,0x700,0x38000700,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x800000,0x0,0xc00300,0x0,0x7000000, 1.3392 + 0x7000,0x0,0x0,0x0,0x0,0x0,0x700,0x0,0x0,0xf040000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x78,0x0,0x0,0x0,0x0,0x3f0,0x1c0fc0,0x0,0x0, 1.3393 + 0x0,0x0,0x1c,0x0,0xe00000,0x0,0x0,0x3800001c,0x0,0x0,0x0,0x700,0x1e0,0x18003c0,0x0,0x0,0xc000700,0x18c00000,0x1000000,0x0, 1.3394 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x200000,0x0,0x18007e0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x1980000,0xc00000, 1.3395 + 0x0,0x7f800e0,0x7f80000,0x0,0x0,0x0,0x60,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x60,0x0,0x0,0x0,0x0, 1.3396 + 0x0,0x0,0x0,0x0,0x0,0x0,0x700,0x38000700,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x800000, 1.3397 + 0x0,0x600600,0x0,0x6000000,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x7fc0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30,0x0,0x0,0x0,0x0, 1.3398 + 0x3f0,0xfc0,0x0,0x0,0x0,0x0,0x838,0x0,0x1e00000,0x0,0x0,0x3800001c,0x0,0x0,0x0,0xf00,0xfc,0x1801f80,0x0,0x0,0x8008e00,0x30c00000, 1.3399 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x200000,0x0,0x1800000,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x1980000,0xc00000, 1.3400 + 0x0,0x3001c0,0x300000,0x0,0x0,0x0,0x60,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x60,0x0,0x0,0x0,0x0,0x0, 1.3401 + 0x0,0x0,0x0,0x0,0x0,0xf00,0x38000f00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x800000,0x0, 1.3402 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfc0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3403 + 0x0,0x0,0xff0,0x0,0x1fc00000,0x0,0x0,0x3800001c,0x0,0x0,0x0,0x3e00,0x7c,0x1801f00,0x0,0x0,0x800fe00,0x0,0x0,0x0,0x0,0x0,0x0, 1.3404 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x200000,0x0,0x1800000,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x0,0x7c00000,0x0,0x3001fc,0x300000, 1.3405 + 0x0,0x0,0x0,0x3e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3406 + 0x3e00,0x38003e00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3407 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfff8,0x0,0x0,0x0,0x7e0,0x0,0x1f000000, 1.3408 + 0x0,0x0,0x3800001c,0x0,0x0,0x0,0x3c00,0x0,0x1800000,0x0,0x0,0x7800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3409 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x0,0x7800000,0x0,0x0,0x0,0x0,0x0,0x0,0x3c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3410 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00,0x38003c00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3411 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3412 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfff8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1800000,0x0,0x0,0x0,0x0, 1.3413 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3414 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3415 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3416 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3417 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3418 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3419 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3420 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3421 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3422 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3423 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0 }; 1.3424 + 1.3425 + // Definition of a 19x38 font. 1.3426 + const unsigned int font19x38[19*38*256/32] = { 1.3427 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3428 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3429 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c380000,0x0,0x1c380,0x0,0x0,0x0,0x0,0x0, 1.3430 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800007,0x3c003,0x86000000, 1.3431 + 0x1e00000,0x3,0x80000700,0x3c00000,0x380000,0x70003c00,0x0,0xe1800e,0x1c00,0xf000e18,0x0,0x0,0x700000e0,0x780000,0x7000,0x0, 1.3432 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3433 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3434 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3435 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe700000,0x0,0xe700,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x38e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3436 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0000e,0x7e003,0xe60071c0,0x7f80000,0x1,0xc0000e00,0x7e0038e,0x1c0000, 1.3437 + 0xe0007e00,0x38e00000,0xf98007,0x3800,0x1f800f98,0x1c70000,0x0,0x380001c0,0xfc0071,0xc000e000,0x0,0x0,0x0,0x0,0x3e00000,0x0, 1.3438 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3439 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3440 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3441 + 0x0,0x0,0x0,0x7e00000,0x0,0x7e00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x38e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3442 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe0001c,0xe7006,0x7c0071c0,0xe180000,0x0,0xe0001c00,0xe70038e,0xe0001,0xc000e700,0x38e00000, 1.3443 + 0x19f0003,0x80007000,0x39c019f0,0x1c70000,0x0,0x1c000380,0x1ce0071,0xc001c000,0x0,0x0,0x0,0x0,0x7f00000,0x0,0x0,0x0,0x0,0x0, 1.3444 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3445 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3446 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000, 1.3447 + 0x0,0x3c00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x38e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3448 + 0x0,0x0,0x700038,0x1c3806,0x3c0071c0,0xc0c0000,0x0,0x70003800,0x1c38038e,0x70003,0x8001c380,0x38e00000,0x18f0001,0xc000e000, 1.3449 + 0x70e018f0,0x1c70000,0x0,0xe000700,0x3870071,0xc0038000,0x0,0x0,0x0,0x0,0xe380000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3450 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3451 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3452 + 0xe000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x60000000,0x0,0x0, 1.3453 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c38,0x0,0x1,0xc3800000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c00000,0x0,0x0,0x0, 1.3454 + 0x0,0x0,0x0,0x0,0x0,0x0,0xc0c0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe000003,0x80018000,0x0,0xc180000, 1.3455 + 0xe,0x380,0x1800000,0xe00000,0x38001800,0x0,0x38,0xe00,0x6000000,0x0,0x1,0xc0000070,0x300000,0x3800,0x0,0x0,0x0,0x0,0x0,0x0, 1.3456 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3457 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7000000,0x0,0x0,0x0,0x0,0x0,0x0, 1.3458 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x78c00,0xc30, 1.3459 + 0x0,0x0,0xc3000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800000,0x0,0x0,0x0,0xe0,0x1c000f,0xc0000000,0x0,0x0, 1.3460 + 0x0,0xc0c0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7000007,0x3c003,0xc6000000,0xc180000,0x7,0x700, 1.3461 + 0x3c00000,0x700000,0x70003c00,0x0,0xf1801c,0x1c00,0xf000f18,0x0,0x0,0xe00000e0,0x780000,0x7000,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3462 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x1c007000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3463 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfe0000,0xfe000,0x0,0x3800000,0x700000,0x38, 1.3464 + 0x7,0xe000001c,0x1c00,0x1c00700,0x7fc0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf800e,0x3e0000,0x0,0x0,0x0,0x1e00000,0x0,0x1, 1.3465 + 0xf8000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7cc00,0x660,0x0,0x0,0x66000000,0x0,0x0,0x0,0x0,0x7,0x1c000000,0x0,0x0,0x0,0x3fe00000, 1.3466 + 0x0,0x0,0x7000000,0x0,0x0,0x0,0x3e0,0x7c001f,0xe0000000,0x0,0x0,0x0,0xe1c0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3467 + 0x0,0x0,0x0,0x1f80,0x380000e,0x7e007,0xe60071c0,0xc180000,0x3,0x80000e00,0x7e0038e,0x380000,0xe0007e00,0x38e00f00,0x1f9800e, 1.3468 + 0x3800,0x1f801f98,0x1c70000,0x0,0x700001c0,0xfc0071,0xc000e007,0x38e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3469 + 0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x1c7000,0x61c00600,0x1e00007e,0x70000,0x18003000,0x1800000,0x0,0x0,0x1c01f0,0x7e003f,0xc003f800, 1.3470 + 0x1e03ffc,0x7f01ff,0xfc03f000,0x7e000000,0x0,0x0,0xfc0,0x1e,0x7fe000,0x7e03fe00,0x3fff07ff,0xe007e038,0x383ffe0,0xff81c01, 1.3471 + 0xe1c000f8,0xf8f00e0,0xfc01ffc,0x3f00ff,0xc000fe07,0xfffc7007,0x1c007700,0x73c01ef,0x78ffff,0xfe0380,0xfe000,0x38000000,0x1800000, 1.3472 + 0x700000,0x38,0x1f,0xe000001c,0x1c00,0x1c00700,0x7fc0000,0x0,0x0,0x0,0x0,0x1c000000,0x0,0x0,0x0,0x3f800e,0x3f8000,0x0,0xfc0000, 1.3473 + 0x0,0x7f00000,0x0,0x1,0x98000000,0x7f00000,0x3ffe00,0xffff0,0x0,0x0,0x0,0x0,0x0,0xcf81f,0xee3807e0,0x0,0x0,0x7e03c01e,0x1c, 1.3474 + 0x0,0x1f800000,0xf0078038,0xfc007,0x1c000000,0xfe00000,0x0,0x0,0x3fe000f0,0xf,0xc001f800,0x6000000,0xffc000,0x0,0x1c0007e0, 1.3475 + 0x360,0x6c0010,0x70000700,0xf0001e,0x3c000,0x78000f00,0x7f800ff,0xf007e01f,0xff83fff0,0x7ffe0fff,0xc1fff03f,0xfe07ffc0,0xfff83fc0, 1.3476 + 0x7807007,0xe000fc00,0x1f8003f0,0x7e0000,0x1f867,0x70e00e,0x1c01c380,0x38f00787,0x3fe0,0x180000c,0x66006,0x7c0071c0,0xe380000, 1.3477 + 0x1,0x80000c00,0x660038e,0x180000,0xc0006600,0x38e0078e,0x19f0006,0x3000,0x198019f0,0x1c70000,0x0,0x30000180,0xcc0071,0xc000c007, 1.3478 + 0x38e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x1c7000,0x61800600,0x7f8001ff,0x70000, 1.3479 + 0x38003800,0x1800000,0x0,0x0,0x3807fc,0x1fe00ff,0xf00ffe00,0x3e03ffc,0xff81ff,0xfc07fc01,0xff800000,0x0,0x0,0x3fe0,0xfe001e, 1.3480 + 0x7ff801,0xff83ff80,0x3fff07ff,0xe01ff838,0x383ffe0,0xff81c03,0xc1c000f8,0xf8f80e0,0x3ff01fff,0xffc0ff,0xf003ff87,0xfffc7007, 1.3481 + 0x1e00f700,0x71c03c7,0x70ffff,0xfe01c0,0xfe000,0x7c000000,0xc00000,0x700000,0x38,0x3f,0xe000001c,0x1c00,0x1c00700,0x7fc0000, 1.3482 + 0x0,0x0,0x0,0x0,0x1c000000,0x0,0x0,0x0,0x3f800e,0x3f8000,0x0,0x3fe0000,0x0,0xff00000,0x0,0x3,0xc000000,0x1ffc0000,0xfffe00, 1.3483 + 0xffff0,0x0,0x0,0x0,0x0,0x0,0xc781f,0xee3803c0,0x0,0x0,0x3c01c01c,0x1c,0xc000,0x7fc00000,0x70070038,0x3fe007,0x1c000000,0x1ff80000, 1.3484 + 0x0,0x0,0x3fe003fc,0x1f,0xe003fc00,0xc000000,0x3ffc000,0x0,0x7c000ff0,0x60,0xc0000,0x30000700,0xf0001e,0x3c000,0x78000f00, 1.3485 + 0x3f000ff,0xf01ff81f,0xff83fff0,0x7ffe0fff,0xc1fff03f,0xfe07ffc0,0xfff83ff8,0x7c0701f,0xf803ff00,0x7fe00ffc,0x1ff8000,0x7fe67, 1.3486 + 0x70e00e,0x1c01c380,0x38700707,0x7ff0,0xc00018,0xc3006,0x3c0071c0,0x7f00000,0x0,0xc0001800,0xc30038e,0xc0001,0x8000c300,0x38e003fc, 1.3487 + 0x18f0003,0x6000,0x30c018f0,0x1c70000,0x0,0x18000300,0x1860071,0xc0018007,0x38e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3488 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x1c7000,0xe1801fc0,0x618001ff,0x70000,0x30001800,0x21840000,0x0,0x0,0x380ffe,0x1fe00ff, 1.3489 + 0xfc0fff00,0x3e03ffc,0x1ff81ff,0xfc0ffe03,0xffc00000,0x0,0x0,0x7ff0,0x3ff803f,0x7ffc03,0xffc3ffc0,0x3fff07ff,0xe03ffc38,0x383ffe0, 1.3490 + 0xff81c07,0x81c000f8,0xf8f80e0,0x7ff81fff,0x81ffe0ff,0xf80fff87,0xfffc7007,0xe00e700,0x70e0387,0x80f0ffff,0xe001c0,0xe000, 1.3491 + 0xfe000000,0xe00000,0x700000,0x38,0x3c,0x1c,0x1c00,0x1c00700,0x1c0000,0x0,0x0,0x0,0x0,0x1c000000,0x0,0x0,0x0,0x78000e,0x3c000, 1.3492 + 0x0,0x7ff0000,0x0,0xf100000,0x0,0x7,0xe000000,0x7ffc0000,0x1fffe00,0xffff0,0x0,0x0,0x0,0x0,0x0,0x3,0xf780180,0x0,0x0,0x1801e03c, 1.3493 + 0x1c,0xc000,0xffc00000,0x780f0038,0x786000,0x7f00,0x18380000,0x0,0xfe00,0x30c,0x10,0x70020e00,0x1c000000,0x7f8c000,0x0,0x6c001c38, 1.3494 + 0x60,0xc0000,0x70000700,0x1f8003f,0x7e000,0xfc001f80,0x3f000ff,0xf03ffc1f,0xff83fff0,0x7ffe0fff,0xc1fff03f,0xfe07ffc0,0xfff83ffc, 1.3495 + 0x7c0703f,0xfc07ff80,0xfff01ffe,0x3ffc000,0xffec7,0x70e00e,0x1c01c380,0x38780f07,0xf070,0xe00038,0x1c3800,0x0,0x3e00000,0x0, 1.3496 + 0xe0003800,0x1c380000,0xe0003,0x8001c380,0x3e0,0x3,0x8000e000,0x70e00000,0x0,0x0,0x1c000700,0x3870000,0x38007,0x0,0x0,0x0, 1.3497 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x1c7000,0xe3807ff0,0xc0c003c1,0x70000,0x70001c00, 1.3498 + 0x718e0000,0x0,0x0,0x700f1e,0x1ce00c0,0x3c0c0f80,0x7e03800,0x3e08000,0x381e0f03,0xc1e00000,0x0,0x0,0x7078,0x783c03f,0x701e07, 1.3499 + 0xc1c383e0,0x38000700,0x7c1c38,0x3801c00,0x381c0f,0x1c000fc,0x1f8f80e0,0x78781c07,0x81e1e0e0,0x780f0180,0xe007007,0xe00e380, 1.3500 + 0xe0f0783,0x80e0000e,0xe000e0,0xe001,0xef000000,0x0,0x700000,0x38,0x38,0x1c,0x0,0x700,0x1c0000,0x0,0x0,0x0,0x0,0x1c000000, 1.3501 + 0x0,0x0,0x0,0x70000e,0x1c000,0x0,0xf830000,0x0,0x1e000000,0x0,0x0,0x10000,0x780c0000,0x3e38000,0xe0,0x0,0x0,0x0,0x0,0x0,0x3, 1.3502 + 0xd580000,0x0,0x0,0xe038,0x1c,0xc000,0xf0400000,0x380e0038,0x702000,0x1ffc0,0xc0000,0x0,0x3ff80,0x606,0x0,0x30000600,0x0, 1.3503 + 0x7f8c000,0x0,0xc001818,0x60,0xc0003,0xe0000700,0x1f8003f,0x7e000,0xfc001f80,0x73801ee,0x7c1c1c,0x38000,0x70000e00,0xe0001, 1.3504 + 0xc0003800,0x700383e,0x7c0703c,0x3c078780,0xf0f01e1e,0x3c3c000,0xf0f87,0x70e00e,0x1c01c380,0x38380e07,0xe038,0x0,0x0,0x0, 1.3505 + 0x0,0x0,0x0,0x0,0x0,0x0,0xff0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3506 + 0x0,0x0,0x0,0x0,0x0,0x1c,0x1c7000,0xc380fff0,0xc0c00380,0x70000,0x70001c00,0x3dbc0070,0x0,0x0,0x701e0f,0xe0000,0x1e000380, 1.3507 + 0x6e03800,0x7800000,0x781c0707,0x80e00000,0x0,0x0,0x4038,0xe00c03f,0x700e07,0x4380f0,0x38000700,0x700438,0x3801c00,0x381c0e, 1.3508 + 0x1c000ec,0x1b8fc0e0,0xf03c1c03,0xc3c0f0e0,0x3c1e0000,0xe007007,0xe00e380,0xe070703,0xc1e0001e,0xe000e0,0xe001,0xc7000000, 1.3509 + 0x0,0x700000,0x38,0x38,0x1c,0x0,0x700,0x1c0000,0x0,0x0,0x0,0x0,0x1c000000,0x0,0x0,0x0,0x70000e,0x1c000,0x0,0xe010000,0x0, 1.3510 + 0x1c000000,0x10,0x20000,0x6c000,0xf0000000,0x3838000,0x1e0,0x0,0xf000f,0xf1e00,0x78f00000,0x0,0x3,0xdd80000,0x0,0x0,0xf078, 1.3511 + 0x0,0xc001,0xe0000000,0x1c1c0038,0x700000,0x3c1e0,0xc0000,0x0,0x783c0,0x606,0x0,0x30000e00,0x0,0xff8c000,0x0,0xc00300c,0x60, 1.3512 + 0xc0003,0xe0000000,0x1f8003f,0x7e000,0xfc001f80,0x73801ce,0x70041c,0x38000,0x70000e00,0xe0001,0xc0003800,0x700380f,0x7e07078, 1.3513 + 0x1e0f03c1,0xe0783c0f,0x781e000,0x1c0787,0x70e00e,0x1c01c380,0x383c1e07,0xff00e038,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x878, 1.3514 + 0x0,0x0,0x0,0x7,0x80000080,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c, 1.3515 + 0x1c7000,0xc301e630,0xc0c00380,0x70000,0xe0000e00,0xff00070,0x0,0x0,0xe01c07,0xe0000,0xe000380,0xce03800,0x7000000,0x701c0707, 1.3516 + 0x600000,0x0,0x4000010,0x38,0x1c00e07f,0x80700e0e,0x38070,0x38000700,0xe00038,0x3801c00,0x381c1c,0x1c000ec,0x1b8ec0e0,0xe01c1c01, 1.3517 + 0xc38070e0,0x1c1c0000,0xe007007,0x701c380,0xe078e01,0xc1c0003c,0xe00070,0xe003,0x83800000,0x7f,0x71f000,0x3e003e38,0x3f007ff, 1.3518 + 0xe01f1c1c,0x7801fc00,0x3fc00701,0xe01c0077,0x8f071e00,0xf801c7c,0x7c700e,0x3e01fc03,0xfff8380e,0xe007700,0x73c0787,0x387ffc, 1.3519 + 0x70000e,0x1c000,0x0,0xe000000,0x0,0x1c000000,0x10,0x20000,0xc2000,0xe0000000,0x3838000,0x3c0,0x0,0xf000f,0x78e00,0x70e00000, 1.3520 + 0x0,0x3,0xc980fe0,0x1f0,0xf8000007,0xffc07070,0x0,0x3f801,0xc0000000,0x1e3c0038,0x700000,0x70070,0x7fc0000,0x0,0xe00e0,0x606, 1.3521 + 0x1c0000,0x70007c00,0x380e,0xff8c000,0x0,0xc00300c,0x60,0xc0000,0x70000000,0x3fc007f,0x800ff001,0xfe003fc0,0x73801ce,0xe0001c, 1.3522 + 0x38000,0x70000e00,0xe0001,0xc0003800,0x7003807,0x7607070,0xe0e01c1,0xc0383807,0x700e000,0x1c0387,0x70e00e,0x1c01c380,0x381c1c07, 1.3523 + 0xffc0e0f8,0x3f8007f,0xfe001,0xfc003f80,0x7f007e3,0xe003e001,0xf8003f00,0x7e000fc,0xfe001f,0xc003f800,0x7f00003c,0x38f0007, 1.3524 + 0xc000f800,0x1f0003e0,0x7c0007,0x8003f0c3,0x80e0701c,0xe0381c0,0x70700387,0x1f01c00e,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3525 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x1c701f,0xfff1c600,0xc0c00380,0x70000,0xe0000e00,0x3c00070,0x0,0x0,0xe03c07, 1.3526 + 0x800e0000,0xe000380,0x1ce03800,0x7000000,0x701c0707,0x7003c0,0x780000,0x3c00001e,0x38,0x18006073,0x80700e0e,0x38070,0x38000700, 1.3527 + 0xe00038,0x3801c00,0x381c38,0x1c000ee,0x3b8ee0e1,0xe01e1c01,0xc78078e0,0x1c1c0000,0xe007007,0x701c387,0xe03de00,0xe3800038, 1.3528 + 0xe00070,0xe007,0x1c00000,0x1ff,0xc077f801,0xff807fb8,0xff807ff,0xe03fdc1d,0xfc01fc00,0x3fc00703,0xc01c007f,0xdf877f00,0x3fe01dfe, 1.3529 + 0xff700e,0xff07ff03,0xfff8380e,0x700f700,0x71e0f03,0x80707ffc,0x70000e,0x1c000,0x0,0x1c000008,0x0,0x1c000000,0x10,0x20000, 1.3530 + 0x82000,0xe0000000,0x7038000,0x80000380,0x2000040,0x7000e,0x38700,0xf1e00000,0x0,0x3,0xc183ff8,0x3fd,0xfc008007,0xffc038e0, 1.3531 + 0x0,0xffc01,0xc0008008,0xe380038,0x380000,0xe3e38,0x1ffc0040,0x80000000,0x1cfc70,0x606,0x1c0000,0xe0007c00,0x380e,0xff8c000, 1.3532 + 0x0,0xc00300c,0x8100060,0xc0000,0x30000700,0x39c0073,0x800e7001,0xce0039c0,0x73801ce,0xe0001c,0x38000,0x70000e00,0xe0001, 1.3533 + 0xc0003800,0x7003807,0x77070f0,0xf1e01e3,0xc03c7807,0x8f00f080,0x83c0787,0x70e00e,0x1c01c380,0x380e3807,0xffe0e1c0,0xffe01ff, 1.3534 + 0xc03ff807,0xff00ffe0,0x1ffc0ff7,0xf01ff807,0xfc00ff80,0x1ff003fe,0xfe001f,0xc003f800,0x7f0003fc,0x3bf801f,0xf003fe00,0x7fc00ff8, 1.3535 + 0x1ff0007,0x8007fd83,0x80e0701c,0xe0381c0,0x70380707,0x7f80e01c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3536 + 0x0,0x0,0x0,0x0,0x1c,0x1c701f,0xfff1c600,0x618081c0,0x70000,0xe0000e00,0x3c00070,0x0,0x0,0xe03803,0x800e0000,0xe000380,0x18e03800, 1.3537 + 0xf000000,0xf01c0707,0x7003c0,0x780000,0xfc00001f,0x80000078,0x301e6073,0x80700e1c,0x38038,0x38000700,0x1c00038,0x3801c00, 1.3538 + 0x381c70,0x1c000e6,0x338ee0e1,0xc00e1c01,0xc70038e0,0x1c1c0000,0xe007007,0x701c387,0xe01dc00,0xf7800078,0xe00070,0xe00e,0xe00000, 1.3539 + 0x3ff,0xe07ffc03,0xffc0fff8,0x1ffc07ff,0xe07ffc1d,0xfe01fc00,0x3fc00707,0x801c007f,0xdf877f80,0x7ff01fff,0x1fff00e,0xff07ff03, 1.3540 + 0xfff8380e,0x700e380,0xe0e0e03,0x80707ffc,0x70000e,0x1c000,0x0,0x7ffc001c,0x0,0x1c000000,0x10,0x20000,0x82000,0xe0000000, 1.3541 + 0x7038001,0xc0000780,0x70000e0,0x3800e,0x38700,0xe1c00000,0x0,0x3,0xc183ff8,0x7ff,0xfc01c007,0xffc03de0,0x0,0x1ffc01,0xc001c01c, 1.3542 + 0xf780038,0x3c0000,0xcff18,0x380c00c1,0x80000000,0x18fe30,0x30c,0x1c0001,0xc0000e00,0x380e,0xff8c000,0x0,0xc00300c,0xc180060, 1.3543 + 0xc0000,0x30000700,0x39c0073,0x800e7001,0xce0039c0,0xe1c038e,0x1c0001c,0x38000,0x70000e00,0xe0001,0xc0003800,0x7003803,0x877070e0, 1.3544 + 0x71c00e3,0x801c7003,0x8e0071c0,0x1c380fc7,0x70e00e,0x1c01c380,0x380f7807,0x1e0e380,0x1fff03ff,0xe07ffc0f,0xff81fff0,0x3ffe0fff, 1.3545 + 0xf03ffc0f,0xfe01ffc0,0x3ff807ff,0xfe001f,0xc003f800,0x7f0007fe,0x3bfc03f,0xf807ff00,0xffe01ffc,0x3ff8007,0x800fff83,0x80e0701c, 1.3546 + 0xe0381c0,0x70380707,0xffc0e01c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x1c701f, 1.3547 + 0xfff1c600,0x7f8381e0,0x70000,0xc0000600,0xff00070,0x0,0x0,0x1c03803,0x800e0000,0xe000f00,0x38e03fe0,0xe000000,0xe00e0e07, 1.3548 + 0x7003c0,0x780007,0xf0ffff87,0xf00000f0,0x307fe0f3,0xc0703c1c,0x38038,0x38000700,0x1c00038,0x3801c00,0x381ce0,0x1c000e6,0x338e70e1, 1.3549 + 0xc00e1c01,0xc70038e0,0x3c1e0000,0xe007007,0x783c38f,0x8e01fc00,0x770000f0,0xe00038,0xe01c,0x700000,0x381,0xe07c1e07,0xc0c1e0f8, 1.3550 + 0x3c1e0038,0xf07c1f,0xe001c00,0x1c0070f,0x1c0079,0xf3c7c380,0xf0781f07,0x83c1f00f,0xc10f0300,0x1c00380e,0x700e380,0xe0f1e03, 1.3551 + 0xc0f00078,0x70000e,0x1c000,0x0,0xfff8003e,0x0,0x3c000000,0x10,0x20000,0xc6000,0xf0000000,0x7038003,0xe0000f00,0xf8001f0, 1.3552 + 0x3801c,0x18300,0xe1800000,0x0,0x3,0xc187818,0x70f,0x9e03e000,0x7801dc0,0x1c,0x3cc401,0xc000efb8,0x7f7f0038,0x3f0000,0x1ce11c, 1.3553 + 0x300c01c3,0x80000000,0x38c638,0x3fc,0x1c0003,0x80000600,0x380e,0xff8c000,0x0,0xc00300c,0xe1c0060,0xc0010,0x70000700,0x79e00f3, 1.3554 + 0xc01e7803,0xcf0079e0,0xe1c038e,0x1c0001c,0x38000,0x70000e00,0xe0001,0xc0003800,0x7003803,0x873870e0,0x71c00e3,0x801c7003, 1.3555 + 0x8e0070e0,0x38381dc7,0x70e00e,0x1c01c380,0x38077007,0xf0e700,0x1c0f0381,0xe0703c0e,0x781c0f0,0x381e083e,0x787c0c1e,0xf03c1e0, 1.3556 + 0x783c0f07,0x800e0001,0xc0003800,0x7000fff,0x3e1c078,0x3c0f0781,0xe0f03c1e,0x783c000,0x1e0f03,0x80e0701c,0xe0381c0,0x70380f07, 1.3557 + 0xc1e0e03c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x1,0x8701c600,0x1e0f01e0,0x1, 1.3558 + 0xc0000700,0x3dbc0070,0x0,0x0,0x1c03803,0x800e0000,0x1e01fe00,0x70e03ff8,0xe3e0001,0xe007fc07,0x80f003c0,0x78001f,0xc0ffff81, 1.3559 + 0xfc0001e0,0x30e1e0e1,0xc07ff81c,0x38038,0x3ffe07ff,0xc1c0003f,0xff801c00,0x381de0,0x1c000e7,0x738e70e1,0xc00e1c03,0xc70038e0, 1.3560 + 0x780f8000,0xe007007,0x383838d,0x8e00f800,0x7f0000e0,0xe00038,0xe000,0x0,0x200,0xf0780e07,0x8041c078,0x380e0038,0xe03c1e, 1.3561 + 0xf001c00,0x1c0071e,0x1c0070,0xe1c783c0,0xe0381e03,0x8380f00f,0xe0000,0x1c00380e,0x381c380,0xe07bc01,0xc0e00078,0x70000e, 1.3562 + 0x1c000,0x0,0x1c000061,0x0,0x38000000,0x10,0x20000,0x7c000,0x7c000000,0x703fc06,0x10000e00,0x18400308,0x1801c,0x1c381,0xc3800000, 1.3563 + 0x0,0x0,0x7000,0xe0f,0xe061000,0x7801fc0,0x1c,0x38c001,0xc0007ff0,0x7fff0038,0x77c000,0x19c00c,0x301c0387,0x0,0x30c618,0xf0, 1.3564 + 0x1c0007,0x600,0x380e,0x7f8c007,0x80000000,0xc001818,0x70e03fc,0x387f871f,0xe0e00700,0x70e00e1,0xc01c3803,0x870070e0,0xe1c038f, 1.3565 + 0xe1c0001f,0xff03ffe0,0x7ffc0fff,0x800e0001,0xc0003800,0x7003803,0x873870e0,0x71c00e3,0x801c7003,0x8e007070,0x703839c7,0x70e00e, 1.3566 + 0x1c01c380,0x3807f007,0x70e700,0x10078200,0xf0401e08,0x3c10078,0x200f001c,0x3878041c,0x70380e0,0x701c0e03,0x800e0001,0xc0003800, 1.3567 + 0x7001e0f,0x3c1e070,0x1c0e0381,0xc070380e,0x701c000,0x1c0f03,0x80e0701c,0xe0381c0,0x701c0e07,0x80e07038,0x0,0x0,0x0,0x0,0x0, 1.3568 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x3,0x8600e600,0x7803f0,0x1,0xc0000700,0x718e0070,0x0,0x0,0x38038c3, 1.3569 + 0x800e0000,0x3c01f800,0x60e03ffc,0xeff8001,0xc001f003,0xc1f003c0,0x7800fe,0xffff80,0x3f8003c0,0x60c0e0e1,0xc07fe01c,0x38038, 1.3570 + 0x3ffe07ff,0xc1c07e3f,0xff801c00,0x381fe0,0x1c000e3,0x638e30e1,0xc00e1c07,0x870038ff,0xf00ff800,0xe007007,0x38381cd,0x9c007000, 1.3571 + 0x3e0001e0,0xe0001c,0xe000,0x0,0x0,0x70780f0f,0x3c078,0x70070038,0x1e03c1c,0x7001c00,0x1c0073c,0x1c0070,0xe1c701c1,0xe03c1e03, 1.3572 + 0xc780f00f,0xe0000,0x1c00380e,0x381c387,0xe03f801,0xc0e000f0,0x70000e,0x1c007,0xe0100000,0x1c0000cd,0x80000003,0xffc00000, 1.3573 + 0x3ff,0x807ff000,0xe0,0x7fc00060,0x703fc0c,0xd8001e00,0x3360066c,0x1c018,0xc181,0x83000000,0x0,0x0,0x7000,0x300e07,0xe0cd800, 1.3574 + 0xf000f80,0x1c,0x78c00f,0xff0038e0,0x3e00038,0xe1e000,0x19800c,0x383c070e,0x7fffc00,0x30fc18,0x0,0xffff80e,0x20e00,0x380e, 1.3575 + 0x7f8c007,0x80000000,0xc001c38,0x38703ff,0xf87fff0f,0xcfe00f00,0x70e00e1,0xc01c3803,0x870070e0,0x1e1e078f,0xe1c0001f,0xff03ffe0, 1.3576 + 0x7ffc0fff,0x800e0001,0xc0003800,0x700ff83,0x871870e0,0x71c00e3,0x801c7003,0x8e007038,0xe03871c7,0x70e00e,0x1c01c380,0x3803e007, 1.3577 + 0x70e700,0x38000,0x70000e00,0x1c00038,0x7001c,0x38f00038,0x3870070,0xe00e1c01,0xc00e0001,0xc0003800,0x7001c07,0x380e0f0,0x1e1e03c3, 1.3578 + 0xc078780f,0xf01e000,0x3c0f03,0x80e0701c,0xe0381c0,0x701c0e07,0x80f07038,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3579 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x3,0x8600ff00,0x1e00778,0x38000001,0xc0000700,0x21843fff,0xe0000000,0x0,0x38039e3,0x800e0000, 1.3580 + 0x7c01fe00,0xe0e0203e,0xeffc001,0xc00ffe03,0xff700000,0x7f0,0x0,0x7f00380,0x618060e1,0xc07ffc1c,0x38038,0x3ffe07ff,0xc1c07e3f, 1.3581 + 0xff801c00,0x381ff0,0x1c000e3,0x638e38e1,0xc00e1fff,0x870038ff,0xc003fe00,0xe007007,0x38381cd,0x9c00f800,0x3e0003c0,0xe0001c, 1.3582 + 0xe000,0x0,0x0,0x7070070e,0x38038,0x70070038,0x1c01c1c,0x7001c00,0x1c00778,0x1c0070,0xe1c701c1,0xc01c1c01,0xc700700e,0xfc000, 1.3583 + 0x1c00380e,0x381c3c7,0x1e01f001,0xe1e001e0,0xf0000e,0x1e01f,0xf8300000,0x1c00019c,0xc0000003,0xffc00000,0x10,0x20000,0x700, 1.3584 + 0x1ff000c0,0x703fc19,0xcc003c00,0x67300ce6,0xc038,0xc181,0x83000000,0x0,0x0,0x7e00,0x180e07,0xe19cc00,0x1e000f80,0x1c,0x70c00f, 1.3585 + 0xff007070,0x3e00038,0xe0f000,0x19800c,0x1fec0e1c,0x7fffc00,0x30f818,0x0,0xffff81f,0xf003fc00,0x380e,0x3f8c007,0x80000000, 1.3586 + 0x7f800ff0,0x1c3803f,0xe007fc00,0xff800e00,0x70e00e1,0xc01c3803,0x870070e0,0x1c0e070f,0xe1c0001f,0xff03ffe0,0x7ffc0fff,0x800e0001, 1.3587 + 0xc0003800,0x700ff83,0x871c70e0,0x71c00e3,0x801c7003,0x8e00701d,0xc038e1c7,0x70e00e,0x1c01c380,0x3803e007,0x70e3c0,0x38000, 1.3588 + 0x70000e00,0x1c00038,0x7001c,0x38e00038,0x3870070,0xe00e1c01,0xc00e0001,0xc0003800,0x7003c07,0x8380e0e0,0xe1c01c3,0x80387007, 1.3589 + 0xe00e1ff,0xfe381b83,0x80e0701c,0xe0381c0,0x701e1e07,0x707878,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3590 + 0x0,0x0,0x0,0x0,0x1c,0x3,0xe007fe0,0x7800e3c,0x38000001,0xc0000700,0x1803fff,0xe0000000,0x0,0x70039c3,0x800e0000,0xf8000f80, 1.3591 + 0xc0e0000e,0xf83c003,0xc01e0f01,0xff700000,0x7c0,0x0,0x1f00780,0x618061c0,0xe0701e1c,0x38038,0x38000700,0x1c07e38,0x3801c00, 1.3592 + 0x381e78,0x1c000e3,0xe38e18e1,0xc00e1fff,0x70038ff,0xe0007f80,0xe007007,0x1c701dd,0x9c00f800,0x1c000780,0xe0000e,0xe000,0x0, 1.3593 + 0x7f,0xf070070e,0x38038,0x7fff0038,0x1c01c1c,0x7001c00,0x1c007f8,0x1c0070,0xe1c701c1,0xc01c1c01,0xc700700e,0x7fc00,0x1c00380e, 1.3594 + 0x1c381c7,0x1c01f000,0xe1c001c0,0xfe0000e,0xfe1f,0xfff00000,0x7ff003fc,0xe0000003,0xffc00000,0x10,0x20000,0x3800,0x3fc0180, 1.3595 + 0x703803f,0xce007800,0xff381fe7,0x30,0x0,0xc0,0x0,0x0,0x3fe0,0xc0e07,0xfe3fce00,0x1c000700,0x1c,0x70c00f,0xff006030,0x1c00000, 1.3596 + 0xe07800,0x19800c,0xfcc1c38,0x7fffc00,0x30d818,0x0,0xffff81f,0xf001f800,0x380e,0xf8c007,0x80000000,0x7f8007e0,0xe1c3fe,0x7fc00f, 1.3597 + 0xf8001e00,0xe0701c0,0xe0381c07,0x380e070,0x1c0e070e,0x1c0001c,0x38000,0x70000e00,0xe0001,0xc0003800,0x700ff83,0x870c70e0, 1.3598 + 0x71c00e3,0x801c7003,0x8e00700f,0x8038c1c7,0x70e00e,0x1c01c380,0x3801c007,0xf0e3e0,0x3ff807f,0xf00ffe01,0xffc03ff8,0x7ff03ff, 1.3599 + 0xf8e0003f,0xff87fff0,0xfffe1fff,0xc00e0001,0xc0003800,0x7003803,0x8380e0e0,0xe1c01c3,0x80387007,0xe00e1ff,0xfe383383,0x80e0701c, 1.3600 + 0xe0381c0,0x700e1c07,0x703870,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x3,0xc000ff0, 1.3601 + 0x3c1e1c1c,0x38000001,0xc0000700,0x1803fff,0xe0000007,0xf8000000,0x7003803,0x800e0001,0xf0000381,0xc0e00007,0xf01e003,0x801c0700, 1.3602 + 0x7c700000,0x7c0,0x0,0x1f00700,0x618061c0,0xe0700e1c,0x38038,0x38000700,0x1c00e38,0x3801c00,0x381e38,0x1c000e1,0xc38e1ce1, 1.3603 + 0xc00e1ffc,0x70038e0,0xf0000780,0xe007007,0x1c701dd,0xdc01fc00,0x1c000780,0xe0000e,0xe000,0x0,0x1ff,0xf070070e,0x38038,0x7fff0038, 1.3604 + 0x1c01c1c,0x7001c00,0x1c007f8,0x1c0070,0xe1c701c1,0xc01c1c01,0xc700700e,0x3ff00,0x1c00380e,0x1c381cd,0x9c00e000,0xe1c003c0, 1.3605 + 0xf80000e,0x3e18,0x3ff00000,0xffe007fd,0xf0000000,0x38000000,0x10,0x20000,0x1c000,0x3c0300,0x703807f,0xdf007801,0xff7c3fef, 1.3606 + 0x80000000,0x0,0x3e0,0x7ffe7ff,0xff000000,0x1ff8,0x60e07,0xfe7fdf00,0x3c000700,0x1c,0x70c001,0xc0006030,0x7fff0000,0xf03800, 1.3607 + 0x19800c,0x1c38,0x1c07,0xf830cc18,0x0,0x1c0000,0x0,0x380e,0x18c007,0x80000000,0x0,0xe1cfe0,0x1fc003f,0x80003c00,0xe0701c0, 1.3608 + 0xe0381c07,0x380e070,0x1c0e070e,0x1c0001c,0x38000,0x70000e00,0xe0001,0xc0003800,0x7003803,0x870e70e0,0x71c00e3,0x801c7003, 1.3609 + 0x8e007007,0x3981c7,0x70e00e,0x1c01c380,0x3801c007,0x1e0e0f8,0xfff81ff,0xf03ffe07,0xffc0fff8,0x1fff07ff,0xf8e0003f,0xff87fff0, 1.3610 + 0xfffe1fff,0xc00e0001,0xc0003800,0x7003803,0x8380e0e0,0xe1c01c3,0x80387007,0xe00e1ff,0xfe386383,0x80e0701c,0xe0381c0,0x700e1c07, 1.3611 + 0x703870,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x7f,0xffc00678,0x707f9c1e,0x38000001, 1.3612 + 0xc0000700,0x70,0x7,0xf8000000,0xe003803,0x800e0003,0xe00001c3,0x80e00007,0xe00e007,0x80380380,0x700000,0x7f0,0x0,0x7f00700, 1.3613 + 0x618061ff,0xe070071c,0x38038,0x38000700,0x1c00e38,0x3801c00,0x381c3c,0x1c000e1,0xc38e1ce1,0xc00e1c00,0x70038e0,0x700003c0, 1.3614 + 0xe007007,0x1c701d8,0xdc03dc00,0x1c000f00,0xe00007,0xe000,0x0,0x3ff,0xf070070e,0x38038,0x7fff0038,0x1c01c1c,0x7001c00,0x1c007fc, 1.3615 + 0x1c0070,0xe1c701c1,0xc01c1c01,0xc700700e,0x3f00,0x1c00380e,0x1c381cd,0x9c01f000,0x73800780,0xfe0000e,0xfe10,0x7c00000,0x1c000ffb, 1.3616 + 0xf8000000,0x38000000,0x10,0x20000,0x20000,0x1e0700,0x70380ff,0xbf80f003,0xfefe7fdf,0xc0000000,0x0,0x3f0,0x7ffe7ff,0xff000000, 1.3617 + 0x1f8,0x30e07,0xfeffbf80,0x78000700,0x1c,0x70c001,0xc0006030,0x7fff0000,0x783800,0x1ce11c,0xe1c,0x1c07,0xf838ce38,0x0,0x1c0000, 1.3618 + 0x0,0x380e,0x18c000,0x0,0x0,0x1c38c00,0x1800030,0x7800,0xfff01ff,0xe03ffc07,0xff80fff0,0x3fff0ffe,0x1c0001c,0x38000,0x70000e00, 1.3619 + 0xe0001,0xc0003800,0x7003803,0x870e70e0,0x71c00e3,0x801c7003,0x8e00700f,0x803b81c7,0x70e00e,0x1c01c380,0x3801c007,0xffe0e03c, 1.3620 + 0x1fff83ff,0xf07ffe0f,0xffc1fff8,0x3fff0fff,0xf8e0003f,0xff87fff0,0xfffe1fff,0xc00e0001,0xc0003800,0x7003803,0x8380e0e0,0xe1c01c3, 1.3621 + 0x80387007,0xe00e000,0x38c383,0x80e0701c,0xe0381c0,0x70073807,0x701ce0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3622 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f,0xffc0063c,0x40619c0f,0x30000001,0xc0000700,0x70,0x7,0xf8000000,0xe003803,0x800e0007,0xc00001c3, 1.3623 + 0xfffc0007,0xe00e007,0x380380,0xf00000,0xfe,0xffff80,0x3f800700,0x618063ff,0xf070071c,0x38038,0x38000700,0x1c00e38,0x3801c00, 1.3624 + 0x381c1e,0x1c000e0,0x38e0ee1,0xc00e1c00,0x70038e0,0x380001c0,0xe007007,0x1ef01d8,0xdc038e00,0x1c001e00,0xe00007,0xe000,0x0, 1.3625 + 0x7c0,0x7070070e,0x38038,0x70000038,0x1c01c1c,0x7001c00,0x1c0079e,0x1c0070,0xe1c701c1,0xc01c1c01,0xc700700e,0x780,0x1c00380e, 1.3626 + 0xe701cd,0x9c01f000,0x73800f00,0xe0000e,0xe000,0x0,0x1c0007f7,0xf0000000,0x70000000,0x10,0x20000,0x0,0xe0e00,0x703807f,0x7f01e001, 1.3627 + 0xfdfc3fbf,0x80000000,0x0,0x7f0,0x0,0x0,0x3c,0x18e07,0x7f7f00,0xf0000700,0x1c,0x70c001,0xc0007070,0x1c00000,0x3e7000,0xcff18, 1.3628 + 0x3ffc070e,0x1c07,0xf818c630,0x0,0x1c0000,0x0,0x380e,0x18c000,0x0,0x3ffc,0x3870000,0xe000fc00,0x380f000,0x1fff83ff,0xf07ffe0f, 1.3629 + 0xffc1fff8,0x3fff0ffe,0x1c0001c,0x38000,0x70000e00,0xe0001,0xc0003800,0x7003803,0x870770e0,0x71c00e3,0x801c7003,0x8e00701d, 1.3630 + 0xc03f01c7,0x70e00e,0x1c01c380,0x3801c007,0xffc0e01c,0x3e0387c0,0x70f80e1f,0x1c3e038,0x7c071e1c,0xe00038,0x70000,0xe0001c00, 1.3631 + 0xe0001,0xc0003800,0x7003803,0x8380e0e0,0xe1c01c3,0x80387007,0xe00e000,0x398383,0x80e0701c,0xe0381c0,0x70073807,0x701ce0, 1.3632 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f,0xffc0061c,0xc0dc07,0xf0000001,0xc0000700, 1.3633 + 0x70,0x0,0x0,0x1c003c07,0x800e000f,0x1c3,0xfffc0007,0xe00e007,0x380380,0xe00000,0x1f,0xc0ffff81,0xfc000700,0x618063ff,0xf070070e, 1.3634 + 0x38070,0x38000700,0xe00e38,0x3801c00,0x381c0e,0x1c000e0,0x38e0ee1,0xe01e1c00,0x78078e0,0x380001c0,0xe007007,0xee01f8,0xfc078f00, 1.3635 + 0x1c001c00,0xe00003,0x8000e000,0x0,0x700,0x7070070e,0x38038,0x70000038,0x1c01c1c,0x7001c00,0x1c0070e,0x1c0070,0xe1c701c1, 1.3636 + 0xc01c1c01,0xc700700e,0x380,0x1c00380e,0xe700ed,0xb803f800,0x77800f00,0x70000e,0x1c000,0x0,0xe0003f7,0xe0000000,0x70000000, 1.3637 + 0x10,0x20000,0x1c0e0,0xe1c00,0x703803f,0x7e01c000,0xfdf81fbf,0x0,0x0,0x3f0,0x0,0x0,0x1c,0x1ce07,0x3f7e00,0xf0000700,0x1c, 1.3638 + 0x70c001,0xc00038e0,0x1c00038,0xf7000,0xe3e38,0x3ffc0387,0x1c00,0x1cc770,0x0,0x1c0000,0x0,0x380e,0x18c000,0x0,0x3ffc,0x70e0001, 1.3639 + 0xe001fe00,0x780e000,0x1fff83ff,0xf07ffe0f,0xffc1fff8,0x3fff0ffe,0xe0001c,0x38000,0x70000e00,0xe0001,0xc0003800,0x7003807, 1.3640 + 0x70770f0,0xf1e01e3,0xc03c7807,0x8f00f038,0xe03e03c7,0x70e00e,0x1c01c380,0x3801c007,0xff00e00e,0x38038700,0x70e00e1c,0x1c38038, 1.3641 + 0x70071c1c,0xe00038,0x70000,0xe0001c00,0xe0001,0xc0003800,0x7003803,0x8380e0e0,0xe1c01c3,0x80387007,0xe00e000,0x3b0383,0x80e0701c, 1.3642 + 0xe0381c0,0x70077807,0x701de0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6,0x1c00061c, 1.3643 + 0xc0de03,0xe0000001,0xc0000700,0x70,0x0,0x0,0x1c001c07,0xe001e,0x1c3,0xfffc0007,0x600e00e,0x380380,0xe00000,0x7,0xf0ffff87, 1.3644 + 0xf0000000,0x60c0e380,0x7070070e,0x38070,0x38000700,0xe00e38,0x3801c00,0x381c0f,0x1c000e0,0x38e06e0,0xe01c1c00,0x38070e0, 1.3645 + 0x1c0001c0,0xe007007,0xee00f8,0xf80f0700,0x1c003c00,0xe00003,0x8000e000,0x0,0x700,0x70780f0f,0x3c078,0x70000038,0x1e03c1c, 1.3646 + 0x7001c00,0x1c0070f,0x1c0070,0xe1c701c1,0xe03c1e03,0xc780f00e,0x380,0x1c00380e,0xe700f8,0xf807bc00,0x3f001e00,0x70000e,0x1c000, 1.3647 + 0x0,0xe0001ff,0xc0000000,0x70000000,0x10,0x20000,0x33110,0xe0e00,0x383801f,0xfc03c000,0x7ff00ffe,0x0,0x0,0x3e0,0x0,0x0,0x1c, 1.3648 + 0x38e07,0x1ffc01,0xe0000700,0x1c,0x78c001,0xc0007ff0,0x1c00038,0x7c000,0x70070,0x1c3,0x80001c00,0xe00e0,0x0,0x1c0000,0x0, 1.3649 + 0x380e,0x18c000,0x0,0x0,0xe1c0001,0xe0010700,0x780e000,0x1c038380,0x70700e0e,0x1c1c038,0x78070e0e,0xe0001c,0x38000,0x70000e00, 1.3650 + 0xe0001,0xc0003800,0x7003807,0x7037070,0xe0e01c1,0xc0383807,0x700e070,0x701c0387,0x70e00e,0x1c01c380,0x3801c007,0xe00e,0x38038700, 1.3651 + 0x70e00e1c,0x1c38038,0x70071c1c,0xf00038,0x70000,0xe0001c00,0xe0001,0xc0003800,0x7003c07,0x8380e0f0,0x1e1e03c3,0xc078780f, 1.3652 + 0xf01e007,0x803e0783,0x80e0701c,0xe0381c0,0x7003f007,0x80f00fc0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3653 + 0x0,0x0,0x0,0x0,0x0,0x6,0x1800061c,0xc0de01,0xc0000000,0xc0000e00,0x70,0xf0000,0x3c00,0x38001c0f,0xe003c,0x3c0,0xe0000e,0x701e00e, 1.3654 + 0x3c0780,0x1e003c0,0x780000,0xfc00001f,0x80000000,0x60e1e780,0x78700f07,0x4380f0,0x38000700,0xf00e38,0x3801c00,0xc0781c07, 1.3655 + 0x81c000e0,0x38e07e0,0xe03c1c00,0x380f0e0,0x1e0003c0,0xe00780f,0xee00f0,0x780e0780,0x1c007800,0xe00001,0xc000e000,0x0,0x700, 1.3656 + 0xf0780e07,0x8041c078,0x38020038,0xe03c1c,0x7001c00,0x1c00707,0x801c0070,0xe1c701c0,0xe0381e03,0x8380f00e,0x80380,0x1c003c1e, 1.3657 + 0x7e00f8,0xf80f1e00,0x3f003c00,0x70000e,0x1c000,0x0,0xf0100f7,0x80078000,0x700078f0,0x10,0x7ff000,0x61208,0x1e0700,0x383800f, 1.3658 + 0x78078000,0x3de007bc,0x0,0x0,0x0,0x0,0x0,0x401c,0x70e0f,0xf7803,0xc0000700,0x1c,0x38c001,0xc000efb8,0x1c00038,0x1e000,0x3c1e0, 1.3659 + 0xc1,0x80000000,0x783c0,0x0,0x0,0x0,0x3c1e,0x18c000,0x0,0x0,0xc180003,0x60000300,0xd80e010,0x3c03c780,0x78f00f1e,0x1e3c03c, 1.3660 + 0x70039c0e,0x70041c,0x38000,0x70000e00,0xe0001,0xc0003800,0x700380f,0x703f070,0x1e0e03c1,0xc078380f,0x701e0e0,0x381c0787, 1.3661 + 0x80f0f01e,0x1e03c3c0,0x7801c007,0xe00e,0x38078700,0xf0e01e1c,0x3c38078,0x700f1c1c,0x78041c,0x1038020,0x70040e00,0x800e0001, 1.3662 + 0xc0003800,0x7001c07,0x380e070,0x1c0e0381,0xc070380e,0x701c007,0x801e0703,0xc1e0783c,0xf0781e0,0xf003f007,0x80e00fc0,0x0, 1.3663 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0xe,0x1801867c,0xc0cf83,0xe0000000,0xe0000e00, 1.3664 + 0x70,0xf0000,0x3c00,0x38000f1e,0xe0070,0x180780,0xe0603e,0x783c01e,0x1e0f01,0x7c003c0,0x780000,0x3c00001e,0x700,0x307fe700, 1.3665 + 0x38701e07,0xc1c383e0,0x38000700,0x7c1e38,0x3801c00,0xe0f01c03,0x81c000e0,0x38e03e0,0x78781c00,0x1e1e0e0,0xe180780,0xe003c1e, 1.3666 + 0x7c00f0,0x781e03c0,0x1c007000,0xe00001,0xc000e000,0x0,0x783,0xf07c1e07,0xc0c1e0f8,0x3e0e0038,0xf07c1c,0x7001c00,0x1c00703, 1.3667 + 0xc01e0070,0xe1c701c0,0xf0781f07,0x83c1f00e,0xe0f80,0x1e003c3e,0x7e00f8,0xf80e0e00,0x3f003800,0x70000e,0x1c000,0x0,0x7830077, 1.3668 + 0xf0000,0x700078f0,0x10,0x20000,0x41208,0xc03c0380,0x3c38007,0x70070000,0x1dc003b8,0x0,0x0,0x0,0x0,0x0,0x707c,0x6070f,0x86077003, 1.3669 + 0x80000700,0x1c,0x3ec401,0xc001c01c,0x1c00038,0xf000,0x1ffc0,0x40,0x80000000,0x3ff80,0x0,0x0,0x0,0x3e3e,0x18c000,0x0,0x0, 1.3670 + 0x8100006,0x60000300,0x1980f070,0x3801c700,0x38e0071c,0xe3801c,0x70039c0e,0x7c1c1c,0x38000,0x70000e00,0xe0001,0xc0003800, 1.3671 + 0x700383e,0x701f03c,0x3c078780,0xf0f01e1e,0x3c3c1c0,0x1c3f0f03,0xc1e0783c,0xf0781e0,0xf001c007,0xe81e,0x3c1f8783,0xf0f07e1e, 1.3672 + 0xfc3c1f8,0x783f1e3e,0x187c0c1f,0x703e0e0,0x7c1c0f83,0x800e0001,0xc0003800,0x7001e0f,0x380e078,0x3c0f0781,0xe0f03c1e,0x783c007, 1.3673 + 0x801e0f03,0xc3e0787c,0xf0f81e1,0xf003f007,0xc1e00fc0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3674 + 0x0,0x0,0x1c,0xe,0x3801fff8,0x6187ff,0xe0000000,0xe0000e00,0x70,0xf0000,0x3c00,0x38000ffe,0x1fff0ff,0xfe1fff80,0xe07ffc,0x3ffc01c, 1.3675 + 0x1fff01,0xff8003c0,0x780000,0x4000010,0x700,0x301e6700,0x387ffe03,0xffc3ffc0,0x3fff0700,0x3ffe38,0x383ffe0,0xfff01c03,0xc1fff8e0, 1.3676 + 0x38e03e0,0x7ff81c00,0x1ffe0e0,0xf1fff80,0xe003ffe,0x7c00f0,0x781c01c0,0x1c00ffff,0xe00001,0xc000e000,0x0,0x3ff,0x707ffc03, 1.3677 + 0xffc0fff8,0x1ffe0038,0x7ffc1c,0x707fff0,0x1c00701,0xc00ff070,0xe1c701c0,0x7ff01fff,0x1fff00e,0xfff00,0xff81fee,0x7e00f0, 1.3678 + 0x781e0f00,0x1e007ffc,0x70000e,0x1c000,0x0,0x3ff003e,0xf0000,0xe00070e0,0x60830010,0x20000,0x41208,0xfffc01c0,0x1fffe03,0xe00ffff0, 1.3679 + 0xf8001f0,0x0,0x0,0x0,0x0,0x0,0x7ff8,0xc07fd,0xfe03e007,0xffc00700,0x1c,0x1ffc1f,0xffc08008,0x1c00038,0x7000,0x7f00,0x0,0x0, 1.3680 + 0xfe00,0x0,0xffff800,0x0,0x3ff7,0x8018c000,0x0,0x0,0x6,0x60000700,0x19807ff0,0x3801c700,0x38e0071c,0xe3801c,0x70039c0f,0xf03ffc1f, 1.3681 + 0xff83fff0,0x7ffe0fff,0xc1fff03f,0xfe07ffc0,0xfff83ffc,0x701f03f,0xfc07ff80,0xfff01ffe,0x3ffc080,0x83fff03,0xffe07ffc,0xfff81ff, 1.3682 + 0xf001c007,0xeffc,0x1ffb83ff,0x707fee0f,0xfdc1ffb8,0x3ff70ff7,0xf83ffc0f,0xff01ffe0,0x3ffc07ff,0x83fff87f,0xff0fffe1,0xfffc0ffe, 1.3683 + 0x380e03f,0xf807ff00,0xffe01ffc,0x3ff8007,0x803ffe01,0xfee03fdc,0x7fb80ff,0x7001e007,0xffc00780,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3684 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0xc,0x3801fff0,0x7f83fe,0x70000000,0xe0000e00,0x0,0xf0000,0x3c00,0x700007fc, 1.3685 + 0x1fff0ff,0xfe1ffe00,0xe07ff8,0x1ff801c,0xffe01,0xff0003c0,0x780000,0x0,0x700,0x38000f00,0x3c7ffc01,0xff83ff80,0x3fff0700, 1.3686 + 0x1ffc38,0x383ffe0,0x7fe01c01,0xe1fff8e0,0x38e03e0,0x3ff01c00,0xffc0e0,0x71fff00,0xe001ffc,0x7c00f0,0x783c01e0,0x1c00ffff, 1.3687 + 0xe00000,0xe000e000,0x0,0x1ff,0x7077f801,0xff807fb8,0xffc0038,0x3fdc1c,0x707fff0,0x1c00701,0xe007f070,0xe1c701c0,0x3fe01dfe, 1.3688 + 0xff700e,0x7fe00,0xff80fee,0x3c0070,0x703c0780,0x1e007ffc,0x70000e,0x1c000,0x0,0x1fe001c,0xe0000,0xe000e1c0,0x71c78010,0x20000, 1.3689 + 0x21318,0xfff800c0,0xfffe01,0xc00ffff0,0x70000e0,0x0,0x0,0x0,0x0,0x0,0x3ff0,0x1803fd,0xfe01c007,0xffc00700,0x1c,0xffc1f,0xffc00000, 1.3690 + 0x1c00038,0x7000,0x0,0x0,0x0,0x0,0x0,0xffff800,0x0,0x3ff7,0x8018c000,0x0,0x0,0xc,0x60000e00,0x31803fe0,0x7801ef00,0x3de007bc, 1.3691 + 0xf7801e,0xf003fc0f,0xf01ff81f,0xff83fff0,0x7ffe0fff,0xc1fff03f,0xfe07ffc0,0xfff83ff8,0x701f01f,0xf803ff00,0x7fe00ffc,0x1ff8000, 1.3692 + 0x67fe01,0xffc03ff8,0x7ff00ff,0xe001c007,0xeff8,0xffb81ff,0x703fee07,0xfdc0ffb8,0x1ff70ff7,0xf81ff807,0xfe00ffc0,0x1ff803ff, 1.3693 + 0x3fff87f,0xff0fffe1,0xfffc07fc,0x380e01f,0xf003fe00,0x7fc00ff8,0x1ff0000,0x37fc00,0xfee01fdc,0x3fb807f,0x7001e007,0x7f800780, 1.3694 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0xc,0x30007fc0,0x1e00f8,0x78000000,0x70001c00, 1.3695 + 0x0,0xe0000,0x3c00,0x700001f0,0x1fff0ff,0xfe07f800,0xe01fe0,0x7e0038,0x3f800,0xfc0003c0,0x700000,0x0,0x700,0x18000e00,0x1c7ff000, 1.3696 + 0x7e03fe00,0x3fff0700,0x7f038,0x383ffe0,0x1f801c00,0xf1fff8e0,0x38e01e0,0xfc01c00,0x3f80e0,0x787fc00,0xe0007f0,0x7c00f0,0x387800f0, 1.3697 + 0x1c00ffff,0xe00000,0xe000e000,0x0,0xfc,0x7071f000,0x3f003e38,0x3f00038,0x1f1c1c,0x707fff0,0x1c00700,0xf003f070,0xe1c701c0, 1.3698 + 0x1f801c7c,0x7c700e,0x1f800,0x3f8078e,0x3c0070,0x707803c0,0x1c007ffc,0x70000e,0x1c000,0x0,0x7c0008,0x1e0000,0xe000e1c0,0x71c30010, 1.3699 + 0x20000,0x1e1f0,0x3fe00020,0x3ffe00,0x800ffff0,0x2000040,0x0,0x0,0x0,0x0,0x0,0xfc0,0x3001f0,0x78008007,0xffc00700,0x1c,0x3f81f, 1.3700 + 0xffc00000,0x1c00038,0x407000,0x0,0x0,0x0,0x0,0x0,0xffff800,0x0,0x39c7,0x18c000,0x0,0x0,0x18,0x60001c00,0x61801f80,0x7000ee00, 1.3701 + 0x1dc003b8,0x77000e,0xe001f80f,0xf007e01f,0xff83fff0,0x7ffe0fff,0xc1fff03f,0xfe07ffc0,0xfff83fc0,0x700f007,0xe000fc00,0x1f8003f0, 1.3702 + 0x7e0000,0xe1f800,0x7f000fe0,0x1fc003f,0x8001c007,0xe7f0,0x7e380fc,0x701f8e03,0xf1c07e38,0xfc703c1,0xe003f001,0xf8003f00, 1.3703 + 0x7e000fc,0x3fff87f,0xff0fffe1,0xfffc03f8,0x380e00f,0xc001f800,0x3f0007e0,0xfc0000,0x61f800,0x78e00f1c,0x1e3803c,0x7001c007, 1.3704 + 0x1f000700,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x70001c00,0x0, 1.3705 + 0x1c0000,0x0,0xe0000000,0x0,0x0,0x0,0x0,0x0,0x0,0xe00000,0x0,0x0,0xc000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c000,0x0, 1.3706 + 0x0,0x0,0x0,0x0,0xe00000,0x7000e000,0x0,0x0,0x0,0x0,0x0,0x1c00,0x0,0x1c00000,0x0,0x0,0x1c00,0x7000,0x0,0x0,0x0,0x0,0x1c000000, 1.3707 + 0x70000e,0x1c000,0x0,0x0,0x1c0000,0xe000c180,0x10,0x20000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc000, 1.3708 + 0x0,0x38,0x70e000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x18c000,0x2000,0x0,0x1f,0xf8003800,0x7fe00000,0x0,0x0,0x0,0x0,0x4000, 1.3709 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x400000, 1.3710 + 0x0,0x0,0x1c007,0x700,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x30001800, 1.3711 + 0x0,0x1c0000,0x0,0xe0000000,0x0,0x0,0x0,0x0,0x0,0x0,0xe00000,0x0,0x0,0xe000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1e000, 1.3712 + 0x0,0x0,0x0,0x0,0x0,0xe00000,0x7000e000,0x0,0x0,0x0,0x0,0x0,0x1c00,0x0,0x1c00000,0x0,0x0,0x1c00,0x7000,0x0,0x0,0x0,0x0,0x1c000000, 1.3713 + 0x70000e,0x1c000,0x0,0x0,0x1c0001,0xe001c380,0x10,0x20000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc000, 1.3714 + 0x0,0x38,0x7fe000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x18c000,0x3000,0x0,0x1f,0xf8007000,0x7fe00000,0x0,0x0,0x0,0x0,0x6000, 1.3715 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3716 + 0x0,0x1c007,0x700,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x38003800, 1.3717 + 0x0,0x380000,0x1,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x1c00000,0x0,0x0,0x3c18000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf000, 1.3718 + 0x0,0x0,0x0,0x0,0x0,0xfe0000,0x380fe000,0x0,0x0,0x0,0x0,0x0,0x3800,0x0,0x1c00000,0x0,0x0,0x1c00,0x7000,0x0,0x0,0x0,0x0,0x38000000, 1.3719 + 0x78000e,0x3c000,0x0,0x0,0x180001,0xc0018300,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc000,0x0, 1.3720 + 0x38,0x1f8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x18c000,0x1800,0x0,0x0,0x6000e000,0x1800000,0x0,0x0,0x0,0x0,0x3000,0x0, 1.3721 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3722 + 0x38007,0xe00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x18003000, 1.3723 + 0x0,0x300000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1800000,0x0,0x0,0x1ff8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4000,0x0,0x0, 1.3724 + 0x0,0x0,0x0,0xfe0000,0xfe000,0x0,0x0,0x0,0x0,0x0,0x607800,0x0,0x3c00000,0x0,0x0,0x1c00,0x7000,0x0,0x0,0x0,0x0,0x78000000, 1.3725 + 0x3f800e,0x3f8000,0x0,0x0,0x300043,0xc0018200,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc000, 1.3726 + 0x0,0x38,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x0,0x11800,0x0,0x0,0x6001ff00,0x1800000,0x0,0x0,0x0,0x0,0x23000,0x0,0x0, 1.3727 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x23000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x78007, 1.3728 + 0x1e00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x1c007000,0x0,0x0, 1.3729 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfe0000, 1.3730 + 0xfe000,0x0,0x0,0x0,0x0,0x0,0x7ff000,0x0,0x7f800000,0x0,0x0,0x1c00,0x7000,0x0,0x0,0x0,0x3,0xf8000000,0x3f800e,0x3f8000,0x0, 1.3731 + 0x0,0x10007f,0x80000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc000,0x0,0x38,0x0,0x0,0x0,0x0, 1.3732 + 0x0,0x0,0x0,0x0,0x3800,0x0,0x1f800,0x0,0x0,0x6001ff00,0x1800000,0x0,0x0,0x0,0x0,0x3f000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3733 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3f000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3f8007,0xfe00,0x0,0x0,0x0,0x0, 1.3734 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3735 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7fff8,0x0,0x0,0x0,0x0,0x7fe000,0x0, 1.3736 + 0x7f000000,0x0,0x0,0x1c00,0x7000,0x0,0x0,0x0,0x3,0xf0000000,0xf800e,0x3e0000,0x0,0x0,0x7f,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3737 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x0,0x1f000,0x0,0x0,0x0,0x0,0x0, 1.3738 + 0x0,0x0,0x0,0x3e000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3e000,0x0,0x0,0x0,0x0,0x0,0x0, 1.3739 + 0x0,0x0,0x0,0x0,0x0,0x0,0x3f0007,0xfc00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3740 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3741 + 0x0,0x0,0x0,0x0,0x7fff8,0x0,0x0,0x0,0x0,0x1fc000,0x0,0x7e000000,0x0,0x0,0x1c00,0x7000,0x0,0x0,0x0,0x3,0xc0000000,0xe,0x0, 1.3742 + 0x0,0x0,0x3e,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3743 + 0x0,0x0,0x3800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3744 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c0007,0xf000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3745 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3746 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7fff8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3747 + 0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3748 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3749 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 }; 1.3750 + 1.3751 + // Definition of a 29x57 font. 1.3752 + const unsigned int font29x57[29*57*256/32] = { 1.3753 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3754 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3755 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3756 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3757 + 0x0,0x781e00,0x0,0x0,0x7,0x81e00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3758 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7c0000,0xf8000,0x7e00000,0x0,0x7, 1.3759 + 0xc0000000,0x0,0x7c00,0xf80,0x7e000,0x0,0x7c00000,0xf80000,0x7e000000,0x0,0x0,0x1f00,0x3e0,0x1f800,0x0,0x0,0x0,0x3,0xe0000000, 1.3760 + 0x7c00003f,0x0,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3761 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3762 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3763 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3764 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3765 + 0x0,0x0,0x0,0x0,0x0,0x0,0x3c3c00,0x0,0x0,0x3,0xc3c00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3e1f00, 1.3766 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3e0000, 1.3767 + 0x1f0000,0x7e00000,0xf838001f,0xf80001f,0xf0000000,0x0,0x3e00,0x1f00,0x7e000,0x3e1f000,0x3e00000,0x1f00000,0x7e00003e,0x1f000000, 1.3768 + 0x3e0,0xe0000f80,0x7c0,0x1f800,0x3e0e00,0x7c3e000,0x0,0x1,0xf0000000,0xf800003f,0x1f0f,0x800001f0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3769 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3770 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3771 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3772 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3773 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1e7800,0x0,0x0, 1.3774 + 0x1,0xe7800000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3e1f00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3775 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1e0000,0x1e0000,0xff00001,0xfe38001f,0xf80003f, 1.3776 + 0xf8000000,0x0,0x1e00,0x1e00,0xff000,0x3e1f000,0x1e00000,0x1e00000,0xff00003e,0x1f000000,0x7f8,0xe0000780,0x780,0x3fc00,0x7f8e00, 1.3777 + 0x7c3e000,0x0,0x0,0xf0000000,0xf000007f,0x80001f0f,0x800001e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3778 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3779 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3780 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3781 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3782 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xef000,0x0,0x0,0x0,0xef000000,0x0,0x0,0x0,0x0,0x0,0x0, 1.3783 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3e1f00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3784 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf0000,0x3c0000,0x1e780003,0xfff8001f,0xf80003c,0x78000000,0x0,0xf00,0x3c00,0x1e7800, 1.3785 + 0x3e1f000,0xf00000,0x3c00001,0xe780003e,0x1f000000,0xfff,0xe00003c0,0xf00,0x79e00,0xfffe00,0x7c3e000,0x0,0x0,0x78000001,0xe00000f3, 1.3786 + 0xc0001f0f,0x800003c0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3787 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3788 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3789 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3790 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3791 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7e000,0x0,0x0,0x0,0x7e000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3792 + 0x3e1f00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3793 + 0x0,0x78000,0x780000,0x3c3c0003,0x8ff0001f,0xf800078,0x3c000000,0x0,0x780,0x7800,0x3c3c00,0x3e1f000,0x780000,0x7800003,0xc3c0003e, 1.3794 + 0x1f000000,0xe3f,0xc00001e0,0x1e00,0xf0f00,0xe3fc00,0x7c3e000,0x0,0x0,0x3c000003,0xc00001e1,0xe0001f0f,0x80000780,0x0,0x0, 1.3795 + 0x0,0x0,0x0,0x0,0x1f,0xf0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3796 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3797 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3798 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3799 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3800 + 0x0,0x7e000,0x0,0x0,0x0,0x7e000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3e1f00,0x0,0x0,0x0,0x0,0x0,0x0, 1.3801 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfc00,0x7e000,0xfe000,0x0,0x3c000,0xf00000,0x781e0003, 1.3802 + 0x83e0001f,0xf800070,0x1c000000,0x0,0x3c0,0xf000,0x781e00,0x3e1f000,0x3c0000,0xf000007,0x81e0003e,0x1f000000,0xe0f,0x800000f0, 1.3803 + 0x3c00,0x1e0780,0xe0f800,0x7c3e000,0x0,0x0,0x1e000007,0x800003c0,0xf0001f0f,0x80000f00,0x0,0x0,0x0,0x0,0x0,0x0,0x3f,0xf8000000, 1.3804 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3805 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3806 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3807 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3808 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3809 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3810 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3fc00,0x1fe000,0x3ff800,0x0,0x0,0x0,0x0,0x0,0x70,0x1c000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3811 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c,0x78000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3812 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3813 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3814 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3815 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1f00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3816 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3817 + 0x0,0x0,0x78,0xf000000,0x0,0x0,0x780f0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7c0, 1.3818 + 0x0,0x0,0x0,0x0,0x0,0x0,0x3fc00,0x1fe000,0x3ffc00,0x0,0x0,0x0,0x0,0x0,0x70,0x1c000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3819 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1f00000,0x3e000,0x3e00000,0x0,0x78,0x3c000000,0x0,0x1f000,0x3e0, 1.3820 + 0x3e000,0x0,0x1f000000,0x3e0000,0x3e000000,0x0,0x0,0x7c00,0xf8,0xf800,0x0,0x0,0x0,0xf,0x80000000,0x1f00001f,0x0,0x3e,0x0, 1.3821 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3822 + 0x0,0x0,0x0,0x30000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3823 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf80000, 1.3824 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3825 + 0x0,0x0,0x0,0x0,0xf80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x781c0000,0x38,0xe000000,0x0,0x0,0x380e0,0x0, 1.3826 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf80,0x0,0x0,0x0,0x0,0x0,0x0,0x39c00,0x1ce000,0x303e00, 1.3827 + 0x0,0x0,0x0,0x0,0x0,0x78,0x3c000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4000,0x0,0x0,0x0,0x0, 1.3828 + 0x0,0x0,0xf80000,0x7c000,0x3e00000,0xf0380000,0x70,0x1c000000,0x0,0xf800,0x7c0,0x3e000,0x0,0xf800000,0x7c0000,0x3e000000, 1.3829 + 0x0,0x3c0,0xe0003e00,0x1f0,0xf800,0x3c0e00,0x0,0x0,0x7,0xc0000000,0x3e00001f,0x0,0x7c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3830 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000,0xff,0x0, 1.3831 + 0xf8,0xf8000,0x1c000,0x0,0x0,0x0,0x0,0x1f,0xc0000000,0x1ff8,0xff00,0x0,0x0,0x3fe000,0x0,0x1fc00001,0xfe000000,0x0,0x0,0x0, 1.3832 + 0x0,0x7f800,0x0,0x0,0x0,0xff00000,0x0,0x0,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0xf8000000,0xfe,0x0,0x7f80,0x0,0x0,0x0,0x0,0x0, 1.3833 + 0x0,0x3f,0xf0000000,0x7fe0,0x0,0x0,0x780000,0x1,0xe0000000,0x0,0x780000,0x3,0xfe000000,0x78000,0x3c00,0xf000,0x7800003,0xffe00000, 1.3834 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfc0000f0,0x3f000,0x0,0x0,0x3fc00,0x0,0x0,0x1fc000,0x0,0x0,0x0,0x1fc0, 1.3835 + 0x0,0xff000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfe1c0000,0x1c,0x1c000000,0x0,0x0,0x1c1c0,0x0,0x0,0x0,0x0,0x1fe0000, 1.3836 + 0x0,0x0,0x1ff,0x1f0f8,0x0,0xff000,0x0,0x0,0x0,0x3f,0xff00000f,0x80000000,0xfe0,0x3f80,0xf00,0x0,0x0,0x0,0x1,0xf8000003,0xe0000000, 1.3837 + 0x1c00,0xe000,0xe00,0x0,0x0,0x0,0x0,0x0,0x3c,0x78000000,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f0,0x3f80,0x1fc00,0xfe000, 1.3838 + 0x7f0000,0x0,0x1fc07000,0x0,0x0,0x0,0x0,0x0,0x3f800,0x780000,0x78000,0x7f00001,0xfc38001f,0xf800070,0x1c000000,0x0,0x7800, 1.3839 + 0x780,0x7f000,0x3e1f000,0x7800000,0x780000,0x7f00003e,0x1f0003f0,0x7f0,0xe0001e00,0x1e0,0x1fc00,0x7f0e00,0x7c3e000,0x0,0x3, 1.3840 + 0xc0000000,0x3c00003f,0x80001f0f,0x80000078,0x1e0000,0x3e1f00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3841 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x3c1e0000,0x1e078000,0x30000000,0x3ff,0xc00001e0,0xf0, 1.3842 + 0x78000,0x1c000,0x0,0x0,0x0,0x0,0x1e0007f,0xf000007e,0x1ffff,0x7ffe0,0x1f80,0x3ffff80,0xfff803,0xfffff800,0xfff80007,0xff800000, 1.3843 + 0x0,0x0,0x0,0x0,0x1ffe00,0x0,0xfe0003,0xfff80000,0x3ffe01ff,0xe00003ff,0xffe01fff,0xff0003ff,0xe01e0007,0x803ffff0,0xfff80, 1.3844 + 0x3c000fc0,0x7800001f,0x8003f07e,0x1e000f,0xfe0007ff,0xf00003ff,0x8007ffe0,0x1fff8,0x7fffffe,0xf0003c1,0xe000079e,0xf1f,0x1f3e0, 1.3845 + 0x1f01ff,0xfff8003f,0xf003c000,0x7fe0,0x3f00,0x0,0x3c0000,0x1,0xe0000000,0x0,0x780000,0xf,0xfe000000,0x78000,0x3c00,0xf000, 1.3846 + 0x7800003,0xffe00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xfc0000f0,0x3fe00,0x0,0x0,0xfff00,0x0,0x0,0x3fe000, 1.3847 + 0x0,0x0,0x0,0x1dc0,0x0,0x3fff00,0x0,0x3ffff80,0x1f,0xffff8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xff1c07ff,0x3c0f001e,0x3c000000, 1.3848 + 0x0,0x0,0x1e3c0,0xf80007c,0x0,0x780000,0x0,0xfff8000,0x3e00,0x1f00000,0x7ff,0xc001f0f8,0x0,0x3ffc00,0x0,0x0,0x0,0x3f,0xff00003f, 1.3849 + 0xe0000000,0x3ff8,0xffe0,0x1e00,0x0,0xfffc00,0x0,0x7,0xf800000f,0xf8000000,0x1c00,0xe000,0xe00,0xf000,0x1fc000,0xfe0000,0x7f00000, 1.3850 + 0x3f800001,0xfc00003f,0xf80000ff,0xffc003ff,0xe007ffff,0xc03ffffe,0x1fffff0,0xfffff80,0x7fffe003,0xffff001f,0xfff800ff,0xffc01ffc, 1.3851 + 0xfc00,0x3c001ffc,0xffe0,0x7ff00,0x3ff800,0x1ffc000,0x0,0x7ff8f0f0,0x3c0780,0x1e03c00,0xf01e000,0x783e0001,0xf01e0000,0xffe00, 1.3852 + 0x3c0000,0xf0000,0x7700001,0xfe38001f,0xf800070,0x1c000000,0x0,0x3c00,0xf00,0x77000,0x3e1f000,0x3c00000,0xf00000,0x7700003e, 1.3853 + 0x1f0000f8,0xc0007f8,0xe0000f00,0x3c0,0x1dc00,0x7f8e00,0x7c3e000,0x0,0x1,0xe0000000,0x7800003b,0x80001f0f,0x800000f0,0x1e0000, 1.3854 + 0x3e1f00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3855 + 0x0,0x0,0x780000,0x3c1e0000,0x1e070000,0x300001f0,0x7ff,0xc00001e0,0x1e0,0x7c000,0x1c000,0x0,0x0,0x0,0x0,0x3c000ff,0xf80007fe, 1.3856 + 0x3ffff,0x801ffff8,0x1f80,0x3ffff80,0x3fff803,0xfffff801,0xfffc000f,0xffc00000,0x0,0x0,0x0,0x0,0x7fff80,0x0,0xfe0003,0xffff0000, 1.3857 + 0xffff01ff,0xfc0003ff,0xffe01fff,0xff000fff,0xf01e0007,0x803ffff0,0xfff80,0x3c001f80,0x7800001f,0xc007f07e,0x1e001f,0xff0007ff, 1.3858 + 0xfc0007ff,0xc007fffc,0x3fffc,0x7fffffe,0xf0003c1,0xf0000f9e,0xf0f,0x8003e1e0,0x1e01ff,0xfff8003f,0xf001e000,0x7fe0,0x3f00, 1.3859 + 0x0,0x1e0000,0x1,0xe0000000,0x0,0x780000,0x1f,0xfe000000,0x78000,0x3c00,0xf000,0x7800003,0xffe00000,0x0,0x0,0x0,0x0,0x0,0x0, 1.3860 + 0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xfc0000f0,0x3ff00,0x0,0x0,0x1fff80,0x0,0x0,0xffe000,0x0,0x0,0x0,0x3de0,0x0,0x7fff80,0x0,0xfffff80, 1.3861 + 0x1f,0xffff8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xe7bc07ff,0x3e1f000f,0x78000000,0x0,0x0,0xf780,0x7800078,0x0,0x780000,0x180000, 1.3862 + 0x1fff8000,0x1e00,0x1e0003c,0xfff,0xc001f0f8,0x0,0x7ffe00,0x0,0x0,0x0,0x3f,0xff00007f,0xf0000000,0x3ffc,0xfff0,0x3c00,0x0, 1.3863 + 0x7fffc00,0x0,0x7,0xf800003f,0xfe000000,0x1c00,0xe000,0xe00,0xf000,0x1fc000,0xfe0000,0x7f00000,0x3f800001,0xfc00001f,0xe00001ff, 1.3864 + 0xffc00fff,0xf007ffff,0xc03ffffe,0x1fffff0,0xfffff80,0x7fffe003,0xffff001f,0xfff800ff,0xffc01fff,0xc000fc00,0x3c003ffe,0x1fff0, 1.3865 + 0xfff80,0x7ffc00,0x3ffe000,0x0,0xfffce0f0,0x3c0780,0x1e03c00,0xf01e000,0x781e0001,0xe01e0000,0x3fff00,0x1e0000,0x1e0000,0xf780003, 1.3866 + 0xcf78001f,0xf800078,0x3c000000,0x0,0x1e00,0x1e00,0xf7800,0x3e1f000,0x1e00000,0x1e00000,0xf780003e,0x1f0000fc,0x7c000f3d, 1.3867 + 0xe0000780,0x780,0x3de00,0xf3de00,0x7c3e000,0x0,0x0,0xf0000000,0xf000007b,0xc0001f0f,0x800001e0,0x1e0000,0x3e1f00,0x0,0x0, 1.3868 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000, 1.3869 + 0x3c1e0000,0x1e0f0000,0x300007fc,0xfff,0xc00001e0,0x1e0,0x3c000,0x1c000,0x0,0x0,0x0,0x0,0x3c001ff,0xfc001ffe,0x3ffff,0xc01ffffc, 1.3870 + 0x3f80,0x3ffff80,0x7fff803,0xfffff803,0xfffe001f,0xffe00000,0x0,0x0,0x0,0x0,0xffff80,0x7f800,0xfe0003,0xffff8001,0xffff01ff, 1.3871 + 0xff0003ff,0xffe01fff,0xff001fff,0xf01e0007,0x803ffff0,0xfff80,0x3c003f00,0x7800001f,0xc007f07f,0x1e003f,0xff8007ff,0xff000fff, 1.3872 + 0xe007ffff,0x7fffc,0x7fffffe,0xf0003c0,0xf0000f1e,0xf07,0x8003c1f0,0x3e01ff,0xfff8003f,0xf001e000,0x7fe0,0x7f80,0x0,0xe0000, 1.3873 + 0x1,0xe0000000,0x0,0x780000,0x1f,0xfe000000,0x78000,0x3c00,0xf000,0x7800003,0xffe00000,0x0,0x0,0x0,0x0,0x0,0x0,0x3c000,0x0, 1.3874 + 0x0,0x0,0x0,0x0,0xf,0xfc0000f0,0x3ff00,0x0,0x0,0x3fff80,0x0,0x0,0xffe000,0x0,0x0,0x0,0x78f0,0x0,0xffff80,0x0,0x3fffff80,0x1f, 1.3875 + 0xffff8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xc7f80070,0x3e1f0007,0x70000000,0x0,0x0,0x7700,0x7c000f8,0x0,0x780000,0x180000, 1.3876 + 0x3fff8000,0x1f00,0x3e0003c,0x1f03,0xc001f0f8,0x0,0x703f00,0x0,0x0,0x0,0x3f,0xff0000f0,0xf8000000,0x303e,0xc0f8,0x7800,0x0, 1.3877 + 0xffffc00,0x0,0x7,0x3800003e,0x3e000000,0x1c00,0xe000,0x3c00,0xf000,0x1fc000,0xfe0000,0x7f00000,0x3f800001,0xfc00000f,0xe00001ff, 1.3878 + 0xffc01fff,0xf007ffff,0xc03ffffe,0x1fffff0,0xfffff80,0x7fffe003,0xffff001f,0xfff800ff,0xffc01fff,0xf000fe00,0x3c007fff,0x3fff8, 1.3879 + 0x1fffc0,0xfffe00,0x7fff000,0x1,0xffffc0f0,0x3c0780,0x1e03c00,0xf01e000,0x781f0003,0xe01e0000,0x3fff80,0xe0000,0x3c0000,0x1e3c0003, 1.3880 + 0x8ff0001f,0xf80003c,0x78000000,0x0,0xe00,0x3c00,0x1e3c00,0x3e1f000,0xe00000,0x3c00001,0xe3c0003e,0x1f00007f,0xf8000e3f,0xc0000380, 1.3881 + 0xf00,0x78f00,0xe3fc00,0x7c3e000,0x0,0x0,0x70000001,0xe00000f1,0xe0001f0f,0x800003c0,0x1e0000,0x3e1f00,0x0,0x0,0x0,0x0,0x0, 1.3882 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x3c1e0000,0x3c0f0000, 1.3883 + 0x30000ffe,0xf80,0xc00001e0,0x3c0,0x1e000,0x101c040,0x0,0x0,0x0,0x0,0x78003f0,0x7e001ffe,0x3f807,0xe01f00fe,0x3f80,0x3ffff80, 1.3884 + 0x7e01803,0xfffff007,0xe03f003f,0x3f00000,0x0,0x0,0x0,0x0,0xfc0fc0,0x3ffe00,0xfe0003,0xffffc003,0xf81f01ff,0xff8003ff,0xffe01fff, 1.3885 + 0xff003f01,0xf01e0007,0x803ffff0,0xfff80,0x3c007e00,0x7800001f,0xc007f07f,0x1e007e,0xfc007ff,0xff801f83,0xf007ffff,0x800fc07c, 1.3886 + 0x7fffffe,0xf0003c0,0xf0000f0f,0x1e07,0xc007c0f8,0x7c01ff,0xfff8003c,0xf000,0x1e0,0xffc0,0x0,0xf0000,0x1,0xe0000000,0x0,0x780000, 1.3887 + 0x3e,0x0,0x78000,0x3c00,0xf000,0x7800000,0x1e00000,0x0,0x0,0x0,0x0,0x0,0x0,0x3c000,0x0,0x0,0x0,0x0,0x0,0x1f,0x800000f0,0x1f80, 1.3888 + 0x0,0x0,0x7e0780,0x0,0x0,0x1f82000,0x0,0x0,0x0,0x7070,0x0,0x1f80f80,0x0,0x7fffff80,0x1f,0xffff8000,0x0,0x0,0x0,0x0,0x0,0x0, 1.3889 + 0x0,0x1,0xc3f80070,0x3f3f0007,0xf0000000,0x0,0x0,0x7f00,0x3e001f0,0x0,0x780000,0x180000,0x7f018000,0xf80,0x7c0003c,0x3e00, 1.3890 + 0x4001f0f8,0xfe00,0x400f00,0x0,0x0,0x0,0x7f000000,0xe0,0x38000000,0x1e,0x38,0x7800,0x0,0x1ffe1c00,0x0,0x0,0x38000078,0xf000000, 1.3891 + 0x1c00,0xe000,0x7f800,0xf000,0x1fc000,0xfe0000,0x7f00000,0x3f800001,0xfc00001f,0xf00001ff,0xffc03f81,0xf007ffff,0xc03ffffe, 1.3892 + 0x1fffff0,0xfffff80,0x7fffe003,0xffff001f,0xfff800ff,0xffc01fff,0xf800fe00,0x3c00fc1f,0x8007e0fc,0x3f07e0,0x1f83f00,0xfc1f800, 1.3893 + 0x3,0xf07fc0f0,0x3c0780,0x1e03c00,0xf01e000,0x780f8007,0xc01e0000,0x7e0fc0,0xf0000,0x3c0000,0x1c1c0003,0x87f0001f,0xf80003f, 1.3894 + 0xf8000000,0x0,0xf00,0x3c00,0x1c1c00,0x3e1f000,0xf00000,0x3c00001,0xc1c0003e,0x1f00003f,0xc0000e1f,0xc00003c0,0xf00,0x70700, 1.3895 + 0xe1fc00,0x7c3e000,0x0,0x0,0x78000001,0xe00000e0,0xe0001f0f,0x800003c0,0x1e0000,0x3e1f00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3896 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x3c1e0000,0x3c0f0001,0xff801e0f, 1.3897 + 0x1f00,0x1e0,0x3c0,0x1e000,0x3c1c1e0,0x0,0x0,0x0,0x0,0x78007c0,0x1f001f9e,0x3c001,0xf010003e,0x7780,0x3c00000,0xf800000,0xf007, 1.3898 + 0xc01f007c,0x1f80000,0x0,0x0,0x0,0x0,0xe003e0,0x7fff00,0x1ef0003,0xc007e007,0xc00301e0,0x1fc003c0,0x1e00,0x7c00,0x301e0007, 1.3899 + 0x80007800,0x780,0x3c00fc00,0x7800001f,0xe00ff07f,0x1e00f8,0x3e00780,0x1fc03e00,0xf807801f,0xc01f001c,0xf000,0xf0003c0,0xf0000f0f, 1.3900 + 0x1e03,0xc00f8078,0x780000,0xf0003c,0xf000,0x1e0,0x1f3e0,0x0,0x78000,0x1,0xe0000000,0x0,0x780000,0x3c,0x0,0x78000,0x0,0x0, 1.3901 + 0x7800000,0x1e00000,0x0,0x0,0x0,0x0,0x0,0x0,0x3c000,0x0,0x0,0x0,0x0,0x0,0x1f,0xf0,0xf80,0x0,0x0,0xf80180,0x0,0x0,0x1e00000, 1.3902 + 0x0,0x0,0x0,0xe038,0x0,0x3e00380,0x0,0xfe0f0000,0x0,0xf0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xc0f00070,0x3b370003,0xe0000000, 1.3903 + 0x0,0x0,0x3e00,0x1e001e0,0x0,0x780000,0x180000,0x7c000000,0x780,0x780003c,0x3c00,0x0,0x7ffc0,0x780,0x0,0x0,0x3,0xffe00000, 1.3904 + 0x1c0,0x3c000000,0xe,0x38,0xf000,0x0,0x3ffe1c00,0x0,0x0,0x38000078,0xf000000,0x1c00,0xe000,0x7f000,0xf000,0x3de000,0x1ef0000, 1.3905 + 0xf780000,0x7bc00003,0xde00001e,0xf00003e7,0x80007c00,0x30078000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001, 1.3906 + 0xe0001e03,0xfc00fe00,0x3c01f007,0xc00f803e,0x7c01f0,0x3e00f80,0x1f007c00,0x7,0xc01f80f0,0x3c0780,0x1e03c00,0xf01e000,0x78078007, 1.3907 + 0x801e0000,0x7803c0,0x78000,0x780000,0x380e0003,0x81e00000,0x1f,0xf0000000,0x0,0x780,0x7800,0x380e00,0x0,0x780000,0x7800003, 1.3908 + 0x80e00000,0x1ff,0x80000e07,0x800001e0,0x1e00,0xe0380,0xe07800,0x0,0x0,0x0,0x3c000003,0xc00001c0,0x70000000,0x780,0x1e0000, 1.3909 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3910 + 0x780000,0x3c1e0000,0x3c0e0007,0xfff01c07,0x1e00,0x1e0,0x780,0xf000,0x3e1c3e0,0x0,0x0,0x0,0x0,0xf0007c0,0x1f00181e,0x20000, 1.3911 + 0xf000001f,0xf780,0x3c00000,0x1f000000,0x1f00f,0x800f8078,0xf80000,0x0,0x0,0x0,0x0,0x8003e0,0x1fc0f80,0x1ef0003,0xc001e007, 1.3912 + 0x800101e0,0x7e003c0,0x1e00,0x7800,0x101e0007,0x80007800,0x780,0x3c00f800,0x7800001e,0xe00ef07f,0x801e00f0,0x1e00780,0x7c03c00, 1.3913 + 0x78078007,0xc01e0004,0xf000,0xf0003c0,0x78001e0f,0x1e03,0xe00f807c,0xf80000,0x1f0003c,0x7800,0x1e0,0x3e1f0,0x0,0x3c000,0x1, 1.3914 + 0xe0000000,0x0,0x780000,0x3c,0x0,0x78000,0x0,0x0,0x7800000,0x1e00000,0x0,0x0,0x0,0x0,0x0,0x0,0x3c000,0x0,0x0,0x0,0x0,0x0, 1.3915 + 0x1e,0xf0,0x780,0x0,0x0,0x1f00080,0x0,0x0,0x3c00000,0x0,0x0,0x0,0x1e03c,0x0,0x3c00080,0x0,0xf80f0000,0x0,0x1f0000,0x0,0x0, 1.3916 + 0x0,0x0,0x0,0x0,0x0,0x0,0x70,0x3bf70003,0xe0000000,0x0,0x0,0x3e00,0x1f003e0,0x0,0x780000,0x180000,0x78000000,0x7c0,0xf80003c, 1.3917 + 0x3c00,0x0,0x1f01f0,0x780,0x0,0x0,0xf,0x80f80000,0x1c0,0x1c000000,0xe,0x38,0x1e000,0x0,0x7ffe1c00,0x0,0x0,0x380000f0,0x7800000, 1.3918 + 0x1c00,0xe000,0x7fc00,0xf000,0x3de000,0x1ef0000,0xf780000,0x7bc00003,0xde00001e,0xf00003c7,0x80007800,0x10078000,0x3c0000, 1.3919 + 0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x7e00ff00,0x3c01e003,0xc00f001e,0x7800f0,0x3c00780,0x1e003c00, 1.3920 + 0x7,0x800f00f0,0x3c0780,0x1e03c00,0xf01e000,0x7807c00f,0x801e0000,0xf803c0,0x3c000,0xf00000,0x780f0000,0x0,0x7,0xc0000000, 1.3921 + 0x0,0x3c0,0xf000,0x780f00,0x0,0x3c0000,0xf000007,0x80f00000,0x7ff,0xc0000000,0xf0,0x3c00,0x1e03c0,0x0,0x0,0x0,0x0,0x1e000007, 1.3922 + 0x800003c0,0x78000000,0xf00,0x1e0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3923 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x3c1e0000,0x3c1e001f,0xfff03803,0x80001e00,0x1e0,0x780,0xf000,0xf9cf80, 1.3924 + 0x0,0x0,0x0,0x0,0xf000780,0xf00001e,0x0,0xf800000f,0xe780,0x3c00000,0x1e000000,0x1e00f,0x78078,0x7c0000,0x0,0x0,0x0,0x0,0x1e0, 1.3925 + 0x3f003c0,0x1ef0003,0xc000f00f,0x800001e0,0x1f003c0,0x1e00,0xf000,0x1e0007,0x80007800,0x780,0x3c01f000,0x7800001e,0xe00ef07f, 1.3926 + 0x801e01f0,0x1e00780,0x3c07c00,0x78078003,0xc03e0000,0xf000,0xf0003c0,0x78001e0f,0x1e01,0xf01f003c,0xf00000,0x3e0003c,0x7800, 1.3927 + 0x1e0,0x7c0f8,0x0,0x0,0x1,0xe0000000,0x0,0x780000,0x3c,0x0,0x78000,0x0,0x0,0x7800000,0x1e00000,0x0,0x0,0x0,0x0,0x0,0x0,0x3c000, 1.3928 + 0x0,0x0,0x0,0x0,0x0,0x1e,0xf0,0x780,0x0,0x0,0x1e00000,0x0,0x0,0x3c00000,0x0,0x8,0x40,0x0,0x7e0000,0x7c00000,0x1,0xf00f0000, 1.3929 + 0x0,0x3e0000,0x0,0x3f,0xfc0,0xfc3f0,0xfc3f0,0x0,0x0,0x0,0x70,0x39e70000,0x0,0x0,0x0,0x0,0xf003c0,0x0,0x0,0x180000,0xf8000000, 1.3930 + 0x3c0,0xf00003c,0x3c00,0x0,0x3c0078,0x7ff80,0x0,0x0,0x1e,0x3c0000,0x1c0,0x1c000000,0xe,0xf0,0x0,0x0,0x7ffe1c00,0x0,0x0,0x380000f0, 1.3931 + 0x7800000,0x1c00,0xe000,0x3c00,0x0,0x3de000,0x1ef0000,0xf780000,0x7bc00003,0xde00001e,0xf00003c7,0x8000f800,0x78000,0x3c0000, 1.3932 + 0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x1f00ff00,0x3c03e003,0xc01f001e,0xf800f0,0x7c00780,0x3e003c00, 1.3933 + 0xf,0x800f80f0,0x3c0780,0x1e03c00,0xf01e000,0x7803c00f,0x1fffc0,0xf001e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3934 + 0x0,0x0,0x307,0xe0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1e0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3935 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x3c1e0000,0x781e003f,0xfff03803, 1.3936 + 0x80001e00,0x1e0,0xf80,0xf000,0x3dde00,0x0,0x0,0x0,0x0,0xf000f00,0x780001e,0x0,0x7800000f,0x1e780,0x3c00000,0x3e000000,0x3e00f, 1.3937 + 0x780f0,0x7c0000,0x0,0x0,0x0,0x0,0x1e0,0x7c001e0,0x3ef8003,0xc000f00f,0x1e0,0xf003c0,0x1e00,0xf000,0x1e0007,0x80007800,0x780, 1.3938 + 0x3c03e000,0x7800001e,0xf01ef07b,0xc01e01e0,0xf00780,0x3e07800,0x3c078003,0xe03c0000,0xf000,0xf0003c0,0x78001e0f,0x1e00,0xf01e003e, 1.3939 + 0x1f00000,0x3c0003c,0x7800,0x1e0,0x78078,0x0,0x0,0x1,0xe0000000,0x0,0x780000,0x3c,0x0,0x78000,0x0,0x0,0x7800000,0x1e00000, 1.3940 + 0x0,0x0,0x0,0x0,0x0,0x0,0x3c000,0x0,0x0,0x0,0x0,0x0,0x1e,0xf0,0x780,0x0,0x0,0x1e00000,0x0,0x0,0x3c00000,0x0,0x18,0xc0,0x0, 1.3941 + 0xe70000,0x7800000,0x1,0xe00f0000,0x0,0x3c0000,0x0,0x3f,0xfc0,0xfc1f0,0x1f83f0,0x0,0x0,0x0,0x70,0x39e70000,0x0,0x0,0x0,0x0, 1.3942 + 0xf807c0,0x0,0x0,0x180000,0xf0000000,0x3e0,0x1f00003c,0x3e00,0x0,0x70001c,0x3fff80,0x0,0x0,0x38,0xe0000,0x1c0,0x1c000078, 1.3943 + 0x1c,0x1fe0,0x0,0x0,0xfffe1c00,0x0,0x0,0x380000f0,0x7800000,0x1c00,0xe000,0xe00,0x0,0x7df000,0x3ef8000,0x1f7c0000,0xfbe00007, 1.3944 + 0xdf00003c,0x780003c7,0x8000f000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0xf00f780, 1.3945 + 0x3c03c001,0xe01e000f,0xf00078,0x78003c0,0x3c001e00,0xf,0xf80f0,0x3c0780,0x1e03c00,0xf01e000,0x7803e01f,0x1ffff8,0xf001e0, 1.3946 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0xe0000000,0x0,0x0,0x0,0x0,0x0,0x0,0xc000,0x0,0x0,0x0,0x0,0x1e0000, 1.3947 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3948 + 0x780000,0x3c1e0000,0x781e003e,0x30703803,0x80001e00,0x1e0,0xf00,0x7800,0xff800,0x1e0000,0x0,0x0,0x0,0x1e000f00,0x780001e, 1.3949 + 0x0,0x7800000f,0x3c780,0x3c00000,0x3c000000,0x3c00f,0x780f0,0x3c0000,0x0,0x0,0x2000000,0x800000,0x1e0,0x78000e0,0x3c78003, 1.3950 + 0xc000f01e,0x1e0,0xf803c0,0x1e00,0x1e000,0x1e0007,0x80007800,0x780,0x3c07c000,0x7800001e,0x701cf07b,0xc01e01e0,0xf00780,0x1e07800, 1.3951 + 0x3c078001,0xe03c0000,0xf000,0xf0003c0,0x7c003e0f,0x1e00,0xf83e001e,0x1e00000,0x7c0003c,0x3c00,0x1e0,0xf807c,0x0,0x0,0x1fe0001, 1.3952 + 0xe1fc0000,0x7f00003,0xf8780007,0xf000003c,0x7f0,0x783f0,0x0,0x0,0x7800000,0x1e00000,0x3e0f8000,0xfc00007,0xf8000007,0xf00001fc, 1.3953 + 0xf,0xc0003fc0,0x3c000,0x0,0x0,0x0,0x0,0x0,0x1e,0xf0,0x780,0x0,0x0,0x3c00000,0x0,0x0,0x3c00000,0x0,0x18,0xc0,0x0,0x1818000, 1.3954 + 0x7800000,0x1,0xe00f0000,0x0,0x7c0000,0x0,0x1f,0x80001f80,0x7c1f8,0x1f83e0,0x0,0x0,0x0,0x70,0x38c70007,0xf8000000,0x7f03, 1.3955 + 0xf0000000,0x0,0x780780,0x0,0x0,0xfe0000,0xf0000000,0x1e0,0x1e00003c,0x3f00,0x0,0xe07f0e,0x7fff80,0x0,0x0,0x70,0x70000,0x1c0, 1.3956 + 0x1c000078,0x3c,0x1fc0,0x0,0x0,0xfffe1c00,0x0,0x0,0x380000f0,0x7800000,0x1c00,0xe000,0xe00,0x0,0x78f000,0x3c78000,0x1e3c0000, 1.3957 + 0xf1e00007,0x8f00003c,0x78000787,0x8001e000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00, 1.3958 + 0xf80f780,0x3c03c001,0xe01e000f,0xf00078,0x78003c0,0x3c001e00,0xf,0x1f80f0,0x3c0780,0x1e03c00,0xf01e000,0x7801e01e,0x1ffffc, 1.3959 + 0xf007e0,0x3fc000,0x1fe0000,0xff00000,0x7f800003,0xfc00001f,0xe0000fc0,0xfc00007f,0xfe0,0x7f00,0x3f800,0x1fc000,0x0,0x0,0x0, 1.3960 + 0x1,0xf000001f,0x80000ff0,0x7f80,0x3fc00,0x1fe000,0xff0000,0x1f80000,0x1fc1e000,0x0,0x0,0x0,0x0,0x1e1fc0,0x0,0x0,0x0,0x0, 1.3961 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x3c1e0000, 1.3962 + 0x781c007c,0x30003803,0x80001f00,0x1e0,0xf00,0x7800,0x7f000,0x1e0000,0x0,0x0,0x0,0x1e000f00,0x780001e,0x0,0x7800000f,0x3c780, 1.3963 + 0x3c00000,0x3c000000,0x3c00f,0x780f0,0x3c0000,0x0,0x0,0x1e000000,0xf00000,0x3e0,0xf0000e0,0x3c78003,0xc000f01e,0x1e0,0x7803c0, 1.3964 + 0x1e00,0x1e000,0x1e0007,0x80007800,0x780,0x3c0f8000,0x7800001e,0x701cf079,0xe01e01e0,0xf00780,0x1e07800,0x3c078001,0xe03c0000, 1.3965 + 0xf000,0xf0003c0,0x3c003c0f,0x3e00,0x787c001f,0x3e00000,0xf80003c,0x3c00,0x1e0,0x1f003e,0x0,0x0,0x1fffc001,0xe7ff0000,0x3ffe000f, 1.3966 + 0xfe78003f,0xfc001fff,0xfe001ffc,0xf0078ffc,0x1ffc00,0x7ff000,0x7800f80,0x1e0000f,0x7f1fc01e,0x3ff0001f,0xfe00079f,0xfc0007ff, 1.3967 + 0x3c003c7f,0xf001fff8,0x1fffff0,0x3c003c0,0xf0000f1e,0xf1f,0x7c1f0,0x1f00ff,0xffe0001e,0xf0,0x780,0x0,0x0,0x3c00000,0x100000, 1.3968 + 0x0,0x7800000,0x0,0x18,0xc0,0x0,0x1818000,0x7800000,0x1,0xe00f0000,0x1000000,0xf80000,0x40000002,0xf,0x80001f00,0x7e0f8,0x1f07c0, 1.3969 + 0x0,0x0,0x0,0x70,0x38c7003f,0xff000000,0xff8f,0xf8000100,0xffffe,0x7c0f80,0x0,0x0,0x3ffc000,0xf0000020,0x1001f0,0x3c00003c, 1.3970 + 0x1f80,0x0,0x1c3ffc7,0x7c0780,0x0,0x0,0xe3,0xff038000,0xe0,0x38000078,0x78,0x1ff0,0x0,0x3c003c0,0xfffe1c00,0x0,0x0,0x380000f0, 1.3971 + 0x7800000,0x1c00,0xe000,0xe00,0xf000,0x78f000,0x3c78000,0x1e3c0000,0xf1e00007,0x8f00003c,0x78000787,0x8001e000,0x78000,0x3c0000, 1.3972 + 0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x780f3c0,0x3c03c001,0xe01e000f,0xf00078,0x78003c0,0x3c001e00, 1.3973 + 0x4000200f,0x3f80f0,0x3c0780,0x1e03c00,0xf01e000,0x7801f03e,0x1ffffe,0xf01fe0,0x3fff800,0x1fffc000,0xfffe0007,0xfff0003f, 1.3974 + 0xff8001ff,0xfc003ff3,0xfe0003ff,0xe0007ff8,0x3ffc0,0x1ffe00,0xfff000,0x3ff80001,0xffc0000f,0xfe00007f,0xf000003f,0xf8003c7f, 1.3975 + 0xe0003ffc,0x1ffe0,0xfff00,0x7ff800,0x3ffc000,0x1f80000,0xfff1c03c,0x3c01e0,0x1e00f00,0xf007800,0x781f0001,0xf01e7ff0,0x7c0007c, 1.3976 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000, 1.3977 + 0x3c1e003f,0xfffff078,0x30003803,0x80000f00,0x1e0,0x1f00,0x7800,0x7f000,0x1e0000,0x0,0x0,0x0,0x3c000f00,0x780001e,0x0,0x7800000f, 1.3978 + 0x78780,0x3c00000,0x3c000000,0x7c00f,0x780f0,0x3c0007,0xe000003f,0x0,0xfe000000,0xfe0000,0x3c0,0x1f000070,0x7c7c003,0xc000f01e, 1.3979 + 0x1e0,0x7803c0,0x1e00,0x1e000,0x1e0007,0x80007800,0x780,0x3c1f0000,0x7800001e,0x783cf079,0xe01e03c0,0xf00780,0x1e0f000,0x3c078001, 1.3980 + 0xe03c0000,0xf000,0xf0003c0,0x3c003c07,0x81f03c00,0x7c7c000f,0x87c00000,0xf00003c,0x1e00,0x1e0,0x3e001f,0x0,0x0,0x3fffe001, 1.3981 + 0xefff8000,0x7fff001f,0xff78007f,0xfe001fff,0xfe003ffe,0xf0079ffe,0x1ffc00,0x7ff000,0x7801f00,0x1e0000f,0xffbfe01e,0x7ff8003f, 1.3982 + 0xff0007bf,0xfe000fff,0xbc003cff,0xf803fffc,0x1fffff0,0x3c003c0,0x78001e1e,0xf0f,0x800f80f0,0x1e00ff,0xffe0001e,0xf0,0x780, 1.3983 + 0x0,0x0,0x3c00000,0x380000,0x0,0x7800000,0x0,0x18,0xc0,0x0,0x1008000,0x7800000,0x3,0xe00f0000,0x3800000,0xf00000,0xe0000007, 1.3984 + 0xf,0x80001f00,0x3e0f8,0x1e07c0,0x0,0x0,0x0,0x70,0x3807007f,0xff800000,0x1ffdf,0xfc000380,0xffffe,0x3e1f00,0x0,0x0,0xfffe000, 1.3985 + 0xf0000030,0x3800f8,0x7c00003c,0xfc0,0x0,0x18780c3,0xf00780,0x80100,0x0,0xc3,0xffc18000,0xf0,0x78000078,0xf0,0xf0,0x0,0x3c003c0, 1.3986 + 0xfffe1c00,0x0,0x0,0x380000f0,0x7800801,0x1c00,0xe000,0x1e00,0xf000,0xf8f800,0x7c7c000,0x3e3e0001,0xf1f0000f,0x8f80007c,0x7c000787, 1.3987 + 0x8001e000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x780f3c0,0x3c078001,0xe03c000f, 1.3988 + 0x1e00078,0xf0003c0,0x78001e00,0xe000701f,0x3fc0f0,0x3c0780,0x1e03c00,0xf01e000,0x7800f87c,0x1e007f,0xf07e00,0x7fffc00,0x3fffe001, 1.3989 + 0xffff000f,0xfff8007f,0xffc003ff,0xfe007ff7,0xff0007ff,0xf000fffc,0x7ffe0,0x3fff00,0x1fff800,0x3ff80001,0xffc0000f,0xfe00007f, 1.3990 + 0xf00000ff,0xf8003cff,0xf0007ffe,0x3fff0,0x1fff80,0xfffc00,0x7ffe000,0x1f80001,0xfffb803c,0x3c01e0,0x1e00f00,0xf007800,0x780f0001, 1.3991 + 0xe01efff8,0x3c00078,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.3992 + 0x0,0x0,0x0,0x0,0x0,0x780000,0x3c1e003f,0xfffff078,0x30001c07,0xf80,0x1e0,0x1e00,0x3c00,0xff800,0x1e0000,0x0,0x0,0x0,0x3c001e00, 1.3993 + 0x3c0001e,0x0,0x7800001e,0x70780,0x3c00000,0x78000000,0x78007,0x800f00f0,0x3e0007,0xe000003f,0x3,0xfe000000,0xff8000,0x7c0, 1.3994 + 0x1e000070,0x783c003,0xc001f01e,0x1e0,0x7803c0,0x1e00,0x1e000,0x1e0007,0x80007800,0x780,0x3c3e0000,0x7800001e,0x3838f079, 1.3995 + 0xe01e03c0,0x780780,0x1e0f000,0x1e078001,0xe03c0000,0xf000,0xf0003c0,0x3c007c07,0x81f03c00,0x3ef80007,0x87800000,0x1f00003c, 1.3996 + 0x1e00,0x1e0,0x7c000f,0x80000000,0x0,0x3ffff001,0xffffc000,0xffff003f,0xff7800ff,0xff001fff,0xfe007ffe,0xf007bffe,0x1ffc00, 1.3997 + 0x7ff000,0x7803e00,0x1e0000f,0xffffe01e,0xfff8007f,0xff8007ff,0xff001fff,0xbc003dff,0xf807fffc,0x1fffff0,0x3c003c0,0x78001e0f, 1.3998 + 0x1e07,0xc01f00f0,0x1e00ff,0xffe0001e,0xf0,0x780,0x0,0x0,0x7c00000,0x7c0000,0x0,0x7800000,0x0,0x18,0xc0,0x0,0x1018000,0x7800000, 1.3999 + 0x3,0xc00f0000,0x7c00000,0x1f00001,0xf000000f,0x80000007,0xc0003e00,0x1e07c,0x3e0780,0x0,0x0,0x0,0x70,0x380700ff,0xff800000, 1.4000 + 0x3ffff,0xfe0007c0,0xffffe,0x1e1e00,0x0,0x780000,0x1fffe000,0xf0000078,0x7c0078,0x7800003c,0xff0,0x0,0x38e0003,0x80f00780, 1.4001 + 0x180300,0x0,0x1c3,0x81e1c000,0x7f,0xf0000078,0x1e0,0x38,0x0,0x3c003c0,0xfffe1c00,0x0,0x0,0x380000f0,0x7800c01,0x80001c00, 1.4002 + 0xe000,0x603e00,0xf000,0xf07800,0x783c000,0x3c1e0001,0xe0f0000f,0x7800078,0x3c000f87,0x8001e000,0x78000,0x3c0000,0x1e00000, 1.4003 + 0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x780f3c0,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f01,0xf000f81e, 1.4004 + 0x7bc0f0,0x3c0780,0x1e03c00,0xf01e000,0x78007878,0x1e001f,0xf0f800,0x7fffe00,0x3ffff001,0xffff800f,0xfffc007f,0xffe003ff, 1.4005 + 0xff007fff,0xff800fff,0xf001fffe,0xffff0,0x7fff80,0x3fffc00,0x3ff80001,0xffc0000f,0xfe00007f,0xf00001ff,0xfc003dff,0xf000ffff, 1.4006 + 0x7fff8,0x3fffc0,0x1fffe00,0xffff000,0x1f80003,0xffff803c,0x3c01e0,0x1e00f00,0xf007800,0x780f0001,0xe01ffffc,0x3c00078,0x0, 1.4007 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000, 1.4008 + 0x3c1e003f,0xfffff078,0x30001e0f,0x300780,0x1e0,0x1e00,0x3c00,0x3dde00,0x1e0000,0x0,0x0,0x0,0x78001e00,0x3c0001e,0x0,0xf800003e, 1.4009 + 0xf0780,0x3dfc000,0x783f8000,0xf8007,0xc01f00f0,0x3e0007,0xe000003f,0x1f,0xfc000000,0x7ff000,0xf80,0x3e007c70,0x783c003,0xc001e03c, 1.4010 + 0x1e0,0x3c03c0,0x1e00,0x3c000,0x1e0007,0x80007800,0x780,0x3c7c0000,0x7800001e,0x3878f078,0xf01e03c0,0x780780,0x1e0f000,0x1e078001, 1.4011 + 0xe03e0000,0xf000,0xf0003c0,0x1e007807,0x83f03c00,0x3ef00007,0xcf800000,0x3e00003c,0xf00,0x1e0,0xf80007,0xc0000000,0x0,0x3e01f801, 1.4012 + 0xfe07e001,0xf80f007e,0x7f801f8,0x1f801fff,0xfe00fc0f,0xf007f83f,0x1ffc00,0x7ff000,0x7807c00,0x1e0000f,0x87e1e01f,0xe0fc00fc, 1.4013 + 0xfc007f8,0x1f803f03,0xfc003df0,0x3807e03c,0x1fffff0,0x3c003c0,0x78003e0f,0x1e03,0xe03e00f8,0x3e00ff,0xffe0001e,0xf0,0x780, 1.4014 + 0x0,0x0,0x7800000,0xfe0000,0x0,0x7800000,0x0,0x18,0xc0,0x0,0x1818000,0x7c00000,0x3,0xc00f0000,0xfe00000,0x3e00003,0xf800001f, 1.4015 + 0xc0000007,0xc0003e00,0x1e03c,0x3c0f80,0x0,0x0,0x0,0x70,0x380700fc,0x7800000,0x7c1fe,0x3e000fe0,0xffffe,0x1f3e00,0x0,0x780000, 1.4016 + 0x3f98e000,0xf000003c,0xfcf8007c,0xf800003c,0x3ffc,0x0,0x31c0001,0x80f00f80,0x380700,0x0,0x183,0x80e0c000,0x3f,0xe0000078, 1.4017 + 0x3c0,0x38,0x0,0x3c003c0,0xfffe1c00,0x0,0x0,0x38000078,0xf000e01,0xc003ffe0,0x1fff00,0x7ffc00,0xf000,0xf07800,0x783c000,0x3c1e0001, 1.4018 + 0xe0f0000f,0x7800078,0x3c000f07,0x8003c000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00, 1.4019 + 0x3c0f1e0,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0xf801f01e,0xf3c0f0,0x3c0780,0x1e03c00,0xf01e000,0x78007cf8, 1.4020 + 0x1e000f,0x80f0f000,0x7c03f00,0x3e01f801,0xf00fc00f,0x807e007c,0x3f003e0,0x1f80707f,0x8f801f80,0xf003f03f,0x1f81f8,0xfc0fc0, 1.4021 + 0x7e07e00,0x3ff80001,0xffc0000f,0xfe00007f,0xf00003ff,0xfc003fc1,0xf801f81f,0x800fc0fc,0x7e07e0,0x3f03f00,0x1f81f800,0x1f80007, 1.4022 + 0xe07f003c,0x3c01e0,0x1e00f00,0xf007800,0x780f8003,0xe01fe07e,0x3e000f8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4023 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x3f,0xfffff078,0x30000ffe,0x1f007c0,0x0,0x1e00, 1.4024 + 0x3c00,0xf9cf80,0x1e0000,0x0,0x0,0x0,0x78001e00,0x3c0001e,0x0,0xf00000fc,0x1e0780,0x3fff800,0x78ffe000,0xf0003,0xe03e00f0, 1.4025 + 0x3e0007,0xe000003f,0x7f,0xe01fffff,0xf00ffc00,0x1f80,0x3c01ff70,0x783c003,0xc007e03c,0x1e0,0x3c03c0,0x1e00,0x3c000,0x1e0007, 1.4026 + 0x80007800,0x780,0x3cfc0000,0x7800001e,0x3c78f078,0xf01e03c0,0x780780,0x3e0f000,0x1e078003,0xc01f0000,0xf000,0xf0003c0,0x1e007807, 1.4027 + 0x83f83c00,0x1ff00003,0xcf000000,0x3e00003c,0xf00,0x1e0,0x0,0x0,0x0,0x20007801,0xfc03e003,0xe003007c,0x3f803e0,0x7c0003c, 1.4028 + 0xf807,0xf007e00f,0x3c00,0xf000,0x780f800,0x1e0000f,0x87e1f01f,0x803c00f8,0x7c007f0,0xf803e01,0xfc003f80,0x80f8004,0x3c000, 1.4029 + 0x3c003c0,0x3c003c0f,0x1e03,0xe03e0078,0x3c0000,0x7c0001e,0xf0,0x780,0x0,0x0,0x3ffff800,0x1ff0000,0x0,0x7800000,0x0,0x18, 1.4030 + 0xc0,0x0,0x1818000,0x3e00000,0x3,0xc00f0000,0x1ff00000,0x3e00007,0xfc00003f,0xe0000003,0xc0003c00,0xf03c,0x3c0f00,0x0,0x0, 1.4031 + 0x0,0x70,0x380701f0,0x800000,0x780fc,0x1e001ff0,0x7c,0xf3c00,0x0,0x780000,0x7e182000,0xf000001f,0xfff00ffc,0xffc0003c,0x3cfe, 1.4032 + 0x0,0x31c0001,0x80f01f80,0x780f00,0x0,0x183,0x80e0c000,0xf,0x80000078,0x780,0x38,0x0,0x3c003c0,0x7ffe1c00,0x0,0x0,0x38000078, 1.4033 + 0xf000f01,0xe003ffe0,0x1fff00,0x7ff800,0xf000,0xf07800,0x783c000,0x3c1e0001,0xe0f0000f,0x78000f8,0x3e000f07,0x8003c000,0x78000, 1.4034 + 0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x3c0f1e0,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0, 1.4035 + 0x78000f00,0x7c03e01e,0x1e3c0f0,0x3c0780,0x1e03c00,0xf01e000,0x78003cf0,0x1e0007,0x80f1e000,0x4000f00,0x20007801,0x3c008, 1.4036 + 0x1e0040,0xf00200,0x780403f,0x7803e00,0x3007c00f,0x803e007c,0x1f003e0,0xf801f00,0x780000,0x3c00000,0x1e000000,0xf00007f0, 1.4037 + 0x3e003f00,0x7801f00f,0x800f807c,0x7c03e0,0x3e01f00,0x1f00f800,0x1f80007,0xc03e003c,0x3c01e0,0x1e00f00,0xf007800,0x78078003, 1.4038 + 0xc01fc03e,0x1e000f0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4039 + 0x0,0x0,0x0,0x0,0x0,0x780000,0x0,0xf078007c,0x300007fc,0x7e00fe0,0x0,0x1e00,0x3c00,0x3e1c3e0,0x1e0000,0x0,0x0,0x0,0xf0001e00, 1.4040 + 0x3c0001e,0x1,0xf000fff8,0x1e0780,0x3fffe00,0x79fff000,0x1f0001,0xfffc00f0,0x7e0007,0xe000003f,0x3ff,0x801fffff,0xf003ff80, 1.4041 + 0x3f00,0x3c03fff0,0xf01e003,0xffffc03c,0x1e0,0x3c03ff,0xffc01fff,0xfe03c000,0x1fffff,0x80007800,0x780,0x3df80000,0x7800001e, 1.4042 + 0x1c70f078,0x781e03c0,0x780780,0x3c0f000,0x1e078007,0xc01f8000,0xf000,0xf0003c0,0x1e007807,0x83f83c00,0xfe00003,0xff000000, 1.4043 + 0x7c00003c,0x780,0x1e0,0x0,0x0,0x0,0x7c01,0xf801f007,0xc00100f8,0x1f803c0,0x3c0003c,0x1f003,0xf007c00f,0x80003c00,0xf000, 1.4044 + 0x783f000,0x1e0000f,0x3c0f01f,0x3e01f0,0x3e007e0,0x7c07c00,0xfc003f00,0xf0000,0x3c000,0x3c003c0,0x3c003c0f,0x1e01,0xf07c007c, 1.4045 + 0x7c0000,0xfc0001e,0xf0,0x780,0x0,0x0,0x3ffff000,0x3838000,0x0,0x7800000,0x0,0x18,0xc0,0x0,0xff0000,0x3f00000,0x3,0xc00fff00, 1.4046 + 0x38380000,0x7c0000e,0xe000070,0x70000001,0xe0003c00,0xf01e,0x780e00,0x0,0x0,0x0,0x0,0x1e0,0x0,0x780f8,0xf003838,0xfc,0xffc00, 1.4047 + 0x0,0x780000,0x7c180000,0xf000000f,0xffe00fff,0xffc0003c,0x783f,0x80000000,0x6380000,0xc0f83f80,0xf81f00,0x0,0x303,0x80e06000, 1.4048 + 0x0,0x78,0xf00,0x78,0x0,0x3c003c0,0x7ffe1c00,0x0,0x0,0x3800003c,0x3e000f81,0xf003ffe0,0x1fff00,0x1fc000,0xf000,0x1e03c00, 1.4049 + 0xf01e000,0x780f0003,0xc078001e,0x3c000f0,0x1e000f07,0xff83c000,0x7ffff,0x803ffffc,0x1ffffe0,0xfffff00,0xf00000,0x7800000, 1.4050 + 0x3c000001,0xe0001e00,0x3c0f0f0,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0x3e07c01e,0x1e3c0f0,0x3c0780,0x1e03c00, 1.4051 + 0xf01e000,0x78003ff0,0x1e0007,0x80f1e000,0xf80,0x7c00,0x3e000,0x1f0000,0xf80000,0x7c0001e,0x3c07c00,0x10078007,0x803c003c, 1.4052 + 0x1e001e0,0xf000f00,0x780000,0x3c00000,0x1e000000,0xf00007c0,0x1e003e00,0x7c03e007,0xc01f003e,0xf801f0,0x7c00f80,0x3e007c00, 1.4053 + 0xf,0x801f003c,0x3c01e0,0x1e00f00,0xf007800,0x7807c007,0xc01f801f,0x1f001f0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4054 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x0,0xe078003c,0x300001f0,0x3f801ff0,0x0, 1.4055 + 0x3c00,0x1e00,0x3c1c1e0,0x1e0000,0x0,0x0,0x0,0xf0001e0f,0x3c0001e,0x3,0xe000fff0,0x3c0780,0x3ffff00,0x7bfff800,0x1e0000,0x7ff00078, 1.4056 + 0x7e0007,0xe000003f,0x1ffc,0x1fffff,0xf0007ff0,0x7e00,0x3c07c3f0,0xf01e003,0xffff003c,0x1e0,0x3c03ff,0xffc01fff,0xfe03c000, 1.4057 + 0x1fffff,0x80007800,0x780,0x3ffc0000,0x7800001e,0x1ef0f078,0x781e03c0,0x780780,0x7c0f000,0x1e07801f,0x800ff000,0xf000,0xf0003c0, 1.4058 + 0xf00f807,0x83b83c00,0xfc00001,0xfe000000,0xf800003c,0x780,0x1e0,0x0,0x0,0x0,0x3c01,0xf000f007,0xc00000f0,0xf80780,0x3c0003c, 1.4059 + 0x1e001,0xf007c007,0x80003c00,0xf000,0x787e000,0x1e0000f,0x3c0f01f,0x1e01e0,0x1e007c0,0x3c07800,0x7c003f00,0xf0000,0x3c000, 1.4060 + 0x3c003c0,0x3e007c07,0x80003c00,0xf8f8003c,0x780000,0xf80001e,0xf0,0x780,0x0,0x0,0x7ffff000,0x601c000,0x3,0xffff0000,0x0, 1.4061 + 0xfff,0xf8007fff,0xc0000000,0x7e003c,0x1fe0000,0xc0003,0xc00fff00,0x601c0000,0xf800018,0x70000c0,0x38000001,0xe0007800,0x701e, 1.4062 + 0x701e00,0x0,0x0,0x0,0x0,0x1e0,0x6,0x700f8,0xf00601c,0xf8,0x7f800,0x0,0x780000,0xf8180000,0xf000000f,0x87c00fff,0xffc0003c, 1.4063 + 0xf01f,0xc0000000,0x6380000,0xc07ff780,0x1f03e03,0xfffffe00,0x303,0x81c06000,0x0,0x1ffff,0xfe001e00,0x180f8,0x0,0x3c003c0, 1.4064 + 0x3ffe1c00,0x3f00000,0x0,0x3800003f,0xfe0007c0,0xf8000000,0x18000000,0xc0000006,0x1f000,0x1e03c00,0xf01e000,0x780f0003,0xc078001e, 1.4065 + 0x3c000f0,0x1e001f07,0xff83c000,0x7ffff,0x803ffffc,0x1ffffe0,0xfffff00,0xf00000,0x7800000,0x3c000001,0xe000fff8,0x3c0f0f0, 1.4066 + 0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0x1f0f801e,0x3c3c0f0,0x3c0780,0x1e03c00,0xf01e000,0x78001fe0,0x1e0007, 1.4067 + 0x80f1e000,0x780,0x3c00,0x1e000,0xf0000,0x780000,0x3c0001e,0x3c07c00,0xf0007,0x8078003c,0x3c001e0,0x1e000f00,0x780000,0x3c00000, 1.4068 + 0x1e000000,0xf0000f80,0x1f003e00,0x3c03c003,0xc01e001e,0xf000f0,0x7800780,0x3c003c00,0xf,0x3f003c,0x3c01e0,0x1e00f00,0xf007800, 1.4069 + 0x7803c007,0x801f000f,0xf001e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4070 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1,0xe078003f,0xb0000000,0xfc003cf0,0x0,0x3c00,0x1e00,0x101c040,0x1e0000,0x0,0x0,0x1, 1.4071 + 0xe0001e1f,0x83c0001e,0x7,0xe000fff0,0x3c0780,0x3c03f80,0x7fc0fc00,0x1e0000,0xfff80078,0xfe0007,0xe000003f,0x7fe0,0x1fffff, 1.4072 + 0xf0000ffc,0xfc00,0x780f81f0,0xf01e003,0xffff003c,0x1e0,0x3c03ff,0xffc01fff,0xfe03c000,0x1fffff,0x80007800,0x780,0x3ffc0000, 1.4073 + 0x7800001e,0x1ef0f078,0x3c1e03c0,0x780780,0x1fc0f000,0x1e07ffff,0x7ff00,0xf000,0xf0003c0,0xf00f007,0xc3b87c00,0x7c00001,0xfe000000, 1.4074 + 0xf800003c,0x3c0,0x1e0,0x0,0x0,0x0,0x3c01,0xf000f007,0x800000f0,0xf80780,0x1e0003c,0x1e001,0xf0078007,0x80003c00,0xf000,0x78fc000, 1.4075 + 0x1e0000f,0x3c0f01e,0x1e01e0,0x1e007c0,0x3c07800,0x7c003e00,0xf0000,0x3c000,0x3c003c0,0x1e007807,0x80003c00,0x7df0003c,0x780000, 1.4076 + 0x1f00001e,0xf0,0x780,0x0,0x0,0x7800000,0xe7ce000,0x3,0xffff0000,0x0,0xfff,0xf8007fff,0xc0000000,0x1f0,0xffe000,0x1c0003, 1.4077 + 0xc00fff00,0xe7ce0000,0xf800039,0xf38001cf,0x9c000000,0xe0007800,0x780e,0x701c00,0x0,0x0,0x0,0x0,0x1e0,0x7,0xf0078,0xf00e7ce, 1.4078 + 0x1f0,0x7f800,0x0,0x780000,0xf0180000,0xf000000e,0x1c0001f,0xe000003c,0xf007,0xe0000000,0x6380000,0xc03fe780,0x3e07c03,0xfffffe00, 1.4079 + 0x303,0xffc06000,0x0,0x1ffff,0xfe003ffe,0x1fff0,0x0,0x3c003c0,0x1ffe1c00,0x3f00000,0x7,0xffc0001f,0xfc0003e0,0x7c000001,0xfc00000f, 1.4080 + 0xe000007f,0x1e000,0x1e03c00,0xf01e000,0x780f0003,0xc078001e,0x3c000f0,0x1e001e07,0xff83c000,0x7ffff,0x803ffffc,0x1ffffe0, 1.4081 + 0xfffff00,0xf00000,0x7800000,0x3c000001,0xe000fff8,0x3c0f078,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0xf9f001e, 1.4082 + 0x783c0f0,0x3c0780,0x1e03c00,0xf01e000,0x78001fe0,0x1e0007,0x80f1e000,0x780,0x3c00,0x1e000,0xf0000,0x780000,0x3c0001e,0x3c07800, 1.4083 + 0xf0003,0xc078001e,0x3c000f0,0x1e000780,0x780000,0x3c00000,0x1e000000,0xf0000f00,0xf003c00,0x3c03c003,0xc01e001e,0xf000f0, 1.4084 + 0x7800780,0x3c003c00,0xf,0x7f003c,0x3c01e0,0x1e00f00,0xf007800,0x7803c007,0x801f000f,0xf001e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4085 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1,0xe070001f,0xf8000007, 1.4086 + 0xf0007cf8,0x7800000,0x3c00,0x1e00,0x1c000,0x1e0000,0x0,0x0,0x1,0xe0001e1f,0x83c0001e,0xf,0xc000fff8,0x780780,0x2000f80,0x7f803e00, 1.4087 + 0x3e0003,0xfffe007c,0x1fe0000,0x0,0x3ff00,0x0,0x1ff,0x8001f000,0x780f00f0,0x1f00f003,0xffffc03c,0x1e0,0x3c03ff,0xffc01fff, 1.4088 + 0xfe03c00f,0xf81fffff,0x80007800,0x780,0x3ffe0000,0x7800001e,0xee0f078,0x3c1e03c0,0x7807ff,0xff80f000,0x1e07fffe,0x3ffe0, 1.4089 + 0xf000,0xf0003c0,0xf00f003,0xc7bc7800,0xfc00000,0xfc000001,0xf000003c,0x3c0,0x1e0,0x0,0x0,0x0,0x3c01,0xe000f80f,0x800001e0, 1.4090 + 0xf80f00,0x1e0003c,0x3c000,0xf0078007,0x80003c00,0xf000,0x79f8000,0x1e0000f,0x3c0f01e,0x1e03c0,0x1f00780,0x3e0f000,0x7c003e00, 1.4091 + 0xf0000,0x3c000,0x3c003c0,0x1e007807,0x81e03c00,0x7df0003e,0xf80000,0x3e00003e,0xf0,0x7c0,0xfc000,0x80000000,0x7800000,0x1e7cf000, 1.4092 + 0x3,0xffff0000,0x0,0x18,0xc0,0x0,0xf80,0x7ffc00,0x380003,0xc00fff01,0xe7cf0000,0x1f000079,0xf3c003cf,0x9e000000,0xe0007000, 1.4093 + 0x380e,0xe01c00,0x0,0x0,0x0,0x0,0x1e0,0x3,0x800f0078,0xf01e7cf,0x3e0,0x3f000,0x0,0x780000,0xf018001f,0xfff8001e,0x1e0000f, 1.4094 + 0xc000003c,0xf003,0xe0000000,0x6380000,0xc00fc780,0x7c0f803,0xfffffe00,0x303,0xfe006000,0x0,0x1ffff,0xfe003ffe,0x1ffe0,0x0, 1.4095 + 0x3c003c0,0xffe1c00,0x3f00000,0x7,0xffc00007,0xf00001f0,0x3e00001f,0xfc0000ff,0xe00007ff,0x3e000,0x3e01e00,0x1f00f000,0xf8078007, 1.4096 + 0xc03c003e,0x1e001e0,0xf001e07,0xff83c000,0x7ffff,0x803ffffc,0x1ffffe0,0xfffff00,0xf00000,0x7800000,0x3c000001,0xe000fff8, 1.4097 + 0x3c0f078,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0x7fe001e,0xf03c0f0,0x3c0780,0x1e03c00,0xf01e000,0x78000fc0, 1.4098 + 0x1e0007,0x80f1f000,0x780,0x3c00,0x1e000,0xf0000,0x780000,0x3c0001e,0x3c0f800,0x1e0003,0xc0f0001e,0x78000f0,0x3c000780,0x780000, 1.4099 + 0x3c00000,0x1e000000,0xf0000f00,0xf003c00,0x3c078003,0xe03c001f,0x1e000f8,0xf0007c0,0x78003e00,0x1e,0xf7803c,0x3c01e0,0x1e00f00, 1.4100 + 0xf007800,0x7803e00f,0x801e000f,0x80f803e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4101 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1,0xe0f0000f,0xff00001f,0x8000f87c,0x7800000,0x3c00,0x1e00,0x1c000,0x7fffff80, 1.4102 + 0x0,0x0,0x3,0xc0001e1f,0x83c0001e,0x1f,0x800000fe,0xf00780,0x7c0,0x7f001e00,0x3c0007,0xe03f003f,0x3fe0000,0x0,0x3fc00,0x0, 1.4103 + 0x7f,0x8001e000,0x781f00f0,0x1e00f003,0xc007e03c,0x1e0,0x3c03c0,0x1e00,0x3c00f,0xf81e0007,0x80007800,0x780,0x3f9f0000,0x7800001e, 1.4104 + 0xfe0f078,0x3c1e03c0,0x7807ff,0xff00f000,0x1e07fff8,0xfff8,0xf000,0xf0003c0,0xf81f003,0xc7bc7800,0xfe00000,0x78000003,0xe000003c, 1.4105 + 0x1e0,0x1e0,0x0,0x0,0x0,0x1fffc01,0xe000780f,0x1e0,0x780f00,0x1e0003c,0x3c000,0xf0078007,0x80003c00,0xf000,0x7bf0000,0x1e0000f, 1.4106 + 0x3c0f01e,0x1e03c0,0xf00780,0x1e0f000,0x3c003c00,0xf8000,0x3c000,0x3c003c0,0x1f00f807,0x81f03c00,0x3fe0001e,0xf00000,0x7c00007c, 1.4107 + 0xf0,0x3e0,0x3ff801,0x80000000,0x7800000,0x3cfcf800,0x3,0xffff0000,0x0,0x18,0xc0,0x0,0x7c00,0x1fff00,0x700003,0xc00f0003, 1.4108 + 0xcfcf8000,0x3e0000f3,0xf3e0079f,0x9f000000,0xf000,0x1000,0x0,0x0,0x0,0x0,0x0,0x1f0,0x1,0xc00f0078,0xf03cfcf,0x800007c0,0x1e000, 1.4109 + 0x0,0x780001,0xe018001f,0xfff8001c,0xe00007,0x8000003c,0xf001,0xf0000000,0x6380000,0xc0000000,0xf81f003,0xfffffe00,0x303, 1.4110 + 0x87006000,0x0,0x1ffff,0xfe003ffe,0x7f00,0x0,0x3c003c0,0x3fe1c00,0x3f00000,0x7,0xffc00000,0xf8,0x1f0001ff,0xf0000fff,0x80007ffc, 1.4111 + 0xfc000,0x3c01e00,0x1e00f000,0xf0078007,0x803c003c,0x1e001e0,0xf001e07,0x8003c000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000, 1.4112 + 0x7800000,0x3c000001,0xe000fff8,0x3c0f078,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0x3fc001e,0x1e03c0f0,0x3c0780, 1.4113 + 0x1e03c00,0xf01e000,0x78000780,0x1e0007,0x80f0fc00,0x3fff80,0x1fffc00,0xfffe000,0x7fff0003,0xfff8001f,0xffc0001e,0x3c0f000, 1.4114 + 0x1e0003,0xc0f0001e,0x78000f0,0x3c000780,0x780000,0x3c00000,0x1e000000,0xf0001e00,0xf803c00,0x3c078001,0xe03c000f,0x1e00078, 1.4115 + 0xf0003c0,0x78001e07,0xfffffe1e,0x1e7803c,0x3c01e0,0x1e00f00,0xf007800,0x7801e00f,0x1e0007,0x807803c0,0x0,0x0,0x0,0x0,0x0, 1.4116 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x3,0xc0f00007, 1.4117 + 0xffc0007e,0xf03e,0x7800000,0x3c00,0x1e00,0x1c000,0x7fffff80,0x0,0x0,0x3,0xc0001e1f,0x83c0001e,0x3f,0x3e,0xf00780,0x3c0,0x7e001e00, 1.4118 + 0x7c000f,0x800f001f,0xffde0000,0x0,0x3e000,0x0,0xf,0x8003e000,0x781e0070,0x1e00f003,0xc001f03c,0x1e0,0x3c03c0,0x1e00,0x3c00f, 1.4119 + 0xf81e0007,0x80007800,0x780,0x3f1f0000,0x7800001e,0x7c0f078,0x1e1e03c0,0x7807ff,0xfc00f000,0x1e07fffe,0xffc,0xf000,0xf0003c0, 1.4120 + 0x781e003,0xc71c7800,0x1ff00000,0x78000003,0xe000003c,0x1e0,0x1e0,0x0,0x0,0x0,0xffffc01,0xe000780f,0x1e0,0x780fff,0xffe0003c, 1.4121 + 0x3c000,0xf0078007,0x80003c00,0xf000,0x7ff0000,0x1e0000f,0x3c0f01e,0x1e03c0,0xf00780,0x1e0f000,0x3c003c00,0x7f000,0x3c000, 1.4122 + 0x3c003c0,0xf00f007,0xc1f07c00,0x1fc0001f,0x1f00000,0xfc000ff8,0xf0,0x1ff,0xfffe07,0x80000000,0x7800000,0x7ffcfc00,0x0,0xf000000, 1.4123 + 0x0,0x18,0xc0,0x0,0x3e000,0x1ff80,0xe00003,0xc00f0007,0xffcfc000,0x3e0001ff,0xf3f00fff,0x9f800000,0x6000,0x0,0x0,0x7c000, 1.4124 + 0x0,0x0,0x0,0xfe,0x0,0xe00f007f,0xff07ffcf,0xc0000fc0,0x1e000,0x0,0x780001,0xe018001f,0xfff8001c,0xe00007,0x80000000,0xf800, 1.4125 + 0xf0000000,0x6380000,0xc0000000,0x1f03c000,0x1e00,0x303,0x83806000,0x0,0x78,0x0,0x0,0x0,0x3c003c0,0xfe1c00,0x3f00000,0x0, 1.4126 + 0x0,0x3c,0xf801fff,0xfff8,0x7ffc0,0x1f8000,0x3c01e00,0x1e00f000,0xf0078007,0x803c003c,0x1e001e0,0xf003c07,0x8003c000,0x78000, 1.4127 + 0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x3c0f03c,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0, 1.4128 + 0x78000f00,0x1f8001e,0x1e03c0f0,0x3c0780,0x1e03c00,0xf01e000,0x78000780,0x1e000f,0x80f0ff00,0x1ffff80,0xffffc00,0x7fffe003, 1.4129 + 0xffff001f,0xfff800ff,0xffc007ff,0xffc0f000,0x1fffff,0xc0fffffe,0x7fffff0,0x3fffff80,0x780000,0x3c00000,0x1e000000,0xf0001e00, 1.4130 + 0x7803c00,0x3c078001,0xe03c000f,0x1e00078,0xf0003c0,0x78001e07,0xfffffe1e,0x3c7803c,0x3c01e0,0x1e00f00,0xf007800,0x7801f01f, 1.4131 + 0x1e0007,0x807c07c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4132 + 0x0,0x0,0x0,0x0,0x780000,0x3,0xc0f00000,0xfff003f0,0x1f00f03e,0x7800000,0x3c00,0x1e00,0x1c000,0x7fffff80,0x0,0x7ff80000,0x3, 1.4133 + 0xc0001e0f,0x3c0001e,0x7e,0x1f,0x1e00780,0x3e0,0x7e000f00,0x78000f,0x7800f,0xff9e0000,0x0,0x3fc00,0x0,0x7f,0x8003c000,0x781e0070, 1.4134 + 0x3e00f803,0xc000f03c,0x1e0,0x3c03c0,0x1e00,0x3c00f,0xf81e0007,0x80007800,0x780,0x3e0f8000,0x7800001e,0x7c0f078,0x1e1e03c0, 1.4135 + 0x7807ff,0xf000f000,0x1e07807f,0xfe,0xf000,0xf0003c0,0x781e003,0xc71c7800,0x3ef00000,0x78000007,0xc000003c,0x1e0,0x1e0,0x0, 1.4136 + 0x0,0x0,0x1ffffc01,0xe000780f,0x1e0,0x780fff,0xffe0003c,0x3c000,0xf0078007,0x80003c00,0xf000,0x7ff0000,0x1e0000f,0x3c0f01e, 1.4137 + 0x1e03c0,0xf00780,0x1e0f000,0x3c003c00,0x7ff80,0x3c000,0x3c003c0,0xf00f003,0xc1f07800,0x1fc0000f,0x1e00000,0xf8000ff0,0xf0, 1.4138 + 0xff,0xffffff,0x80000000,0x3fffc000,0xfff9fe00,0x0,0xf000000,0x0,0x18,0xc0,0x0,0x1f0000,0x1fc0,0x1c00003,0xc00f000f,0xff9fe000, 1.4139 + 0x7c0003ff,0xe7f81fff,0x3fc00000,0x0,0x0,0x0,0xfe000,0x1ffffc0f,0xfffffc00,0x0,0xff,0xf0000000,0x700f007f,0xff0fff9f,0xe0000f80, 1.4140 + 0x1e000,0x0,0x780001,0xe018001f,0xfff8001c,0xe00fff,0xffc00000,0xf800,0xf0000000,0x6380000,0xc0ffff80,0x3e078000,0x1e00,0x7ff80303, 1.4141 + 0x83c06000,0x0,0x78,0x0,0x0,0x0,0x3c003c0,0xe1c00,0x3f00000,0x0,0x7f,0xff00001e,0x7c1fff0,0xfff80,0x7ffc00,0x3f0000,0x7c01f00, 1.4142 + 0x3e00f801,0xf007c00f,0x803e007c,0x1f003e0,0xf803c07,0x8003c000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001, 1.4143 + 0xe0001e00,0x3c0f03c,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0x1f8001e,0x3c03c0f0,0x3c0780,0x1e03c00,0xf01e000, 1.4144 + 0x78000780,0x1e001f,0xf07f80,0x3ffff80,0x1ffffc00,0xffffe007,0xffff003f,0xfff801ff,0xffc03fff,0xffc0f000,0x1fffff,0xc0fffffe, 1.4145 + 0x7fffff0,0x3fffff80,0x780000,0x3c00000,0x1e000000,0xf0001e00,0x7803c00,0x3c078001,0xe03c000f,0x1e00078,0xf0003c0,0x78001e07, 1.4146 + 0xfffffe1e,0x787803c,0x3c01e0,0x1e00f00,0xf007800,0x7800f01e,0x1e0007,0x803c0780,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4147 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1ff,0xffff8000,0x3ff80fc0,0x7fc1e01f, 1.4148 + 0x7800000,0x3c00,0x1e00,0x0,0x7fffff80,0x0,0x7ff80000,0x7,0x80001e00,0x3c0001e,0xfc,0xf,0x1e00780,0x1e0,0x7c000f00,0x78000f, 1.4149 + 0x78007,0xff1e0000,0x0,0x3ff00,0x0,0x1ff,0x8003c000,0x781e0070,0x3c007803,0xc000f03c,0x1e0,0x3c03c0,0x1e00,0x3c000,0x781e0007, 1.4150 + 0x80007800,0x780,0x3c07c000,0x7800001e,0x7c0f078,0xf1e03c0,0x780780,0xf000,0x1e07801f,0x3e,0xf000,0xf0003c0,0x781e003,0xcf1c7800, 1.4151 + 0x3cf80000,0x7800000f,0x8000003c,0xf0,0x1e0,0x0,0x0,0x0,0x3ffffc01,0xe000780f,0x1e0,0x780fff,0xffe0003c,0x3c000,0xf0078007, 1.4152 + 0x80003c00,0xf000,0x7ff8000,0x1e0000f,0x3c0f01e,0x1e03c0,0xf00780,0x1e0f000,0x3c003c00,0x3fff0,0x3c000,0x3c003c0,0xf81f003, 1.4153 + 0xc3b87800,0xf80000f,0x1e00001,0xf0000ff0,0xf0,0xff,0xf03fff,0x80000000,0x3fff8001,0xfff1ff00,0x0,0xf000000,0x0,0x18,0xc0, 1.4154 + 0x0,0x380000,0x7c0,0x3c00003,0xc00f001f,0xff1ff000,0xf80007ff,0xc7fc3ffe,0x3fe00000,0x0,0x0,0x0,0x1ff000,0x7ffffe1f,0xffffff00, 1.4155 + 0x0,0x7f,0xfe000000,0x780f007f,0xff1fff1f,0xf0001f00,0x1e000,0x0,0x780001,0xe0180000,0xf000001c,0xe00fff,0xffc00000,0x7c00, 1.4156 + 0xf0000000,0x31c0001,0x80ffff80,0x3e078000,0x1e00,0x7ff80183,0x81c0c000,0x0,0x78,0x0,0x0,0x0,0x3c003c0,0xe1c00,0x3f00000, 1.4157 + 0x0,0x7f,0xff00001e,0x7c7ff03,0xc03ff8fe,0x1ffc0f0,0x7e0000,0x7800f00,0x3c007801,0xe003c00f,0x1e0078,0xf003c0,0x7803c07,0x8003c000, 1.4158 + 0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x3c0f01e,0x3c078000,0xf03c0007,0x81e0003c, 1.4159 + 0xf0001e0,0x78000f00,0x3fc001e,0x7803c0f0,0x3c0780,0x1e03c00,0xf01e000,0x78000780,0x1e007f,0xf03fe0,0x7ffff80,0x3ffffc01, 1.4160 + 0xffffe00f,0xffff007f,0xfff803ff,0xffc07fff,0xffc0f000,0x1fffff,0xc0fffffe,0x7fffff0,0x3fffff80,0x780000,0x3c00000,0x1e000000, 1.4161 + 0xf0001e00,0x7803c00,0x3c078001,0xe03c000f,0x1e00078,0xf0003c0,0x78001e07,0xfffffe1e,0x707803c,0x3c01e0,0x1e00f00,0xf007800, 1.4162 + 0x7800f01e,0x1e0007,0x803c0780,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4163 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1ff,0xffff8000,0x30f81f00,0xffe1e00f,0x87800000,0x3c00,0x1e00,0x0,0x1e0000,0x0,0x7ff80000, 1.4164 + 0x7,0x80001e00,0x3c0001e,0x1f8,0x7,0x83c00780,0x1e0,0x7c000f00,0xf8001e,0x3c001,0xfc1e0000,0x0,0x7fe0,0x0,0xffc,0x3c000,0x781e0070, 1.4165 + 0x3ffff803,0xc000783c,0x1e0,0x3c03c0,0x1e00,0x3c000,0x781e0007,0x80007800,0x780,0x3c07c000,0x7800001e,0x380f078,0xf1e03c0, 1.4166 + 0x780780,0xf000,0x1e07800f,0x8000001e,0xf000,0xf0003c0,0x3c3c003,0xcf1e7800,0x7c780000,0x7800000f,0x8000003c,0xf0,0x1e0,0x0, 1.4167 + 0x0,0x0,0x7f003c01,0xe000780f,0x1e0,0x780fff,0xffe0003c,0x3c000,0xf0078007,0x80003c00,0xf000,0x7f7c000,0x1e0000f,0x3c0f01e, 1.4168 + 0x1e03c0,0xf00780,0x1e0f000,0x3c003c00,0xfff8,0x3c000,0x3c003c0,0x781e003,0xc3b87800,0x1fc00007,0x83e00003,0xe0000ff8,0xf0, 1.4169 + 0x1ff,0xc007fe,0x0,0x7fff8001,0xffe3ff00,0x0,0x1e000000,0x0,0x18,0xc0,0x0,0x0,0x3c0,0x7800003,0xc00f001f,0xfe3ff000,0xf80007ff, 1.4170 + 0x8ffc3ffc,0x7fe00000,0x0,0x0,0x0,0x1ff000,0x0,0x0,0x0,0x1f,0xff000000,0x3c0f007f,0xff1ffe3f,0xf0003e00,0x1e000,0x0,0x780001, 1.4171 + 0xe0180000,0xf000001e,0x1e00fff,0xffc00000,0x3f00,0xf0000000,0x31c0001,0x80ffff80,0x1f03c000,0x1e00,0x7ff80183,0x81c0c000, 1.4172 + 0x0,0x78,0x0,0x0,0x0,0x3c003c0,0xe1c00,0x0,0x0,0x7f,0xff00003c,0xf87f007,0xc03f83ff,0x81fc01f0,0x7c0000,0x7ffff00,0x3ffff801, 1.4173 + 0xffffc00f,0xfffe007f,0xfff003ff,0xff807fff,0x8003c000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001, 1.4174 + 0xe0001e00,0x3c0f01e,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0x7fe001e,0xf003c0f0,0x3c0780,0x1e03c00,0xf01e000, 1.4175 + 0x78000780,0x1ffffe,0xf00ff0,0xfe00780,0x7f003c03,0xf801e01f,0xc00f00fe,0x7807f0,0x3c0ffff,0xffc0f000,0x1fffff,0xc0fffffe, 1.4176 + 0x7fffff0,0x3fffff80,0x780000,0x3c00000,0x1e000000,0xf0001e00,0x7803c00,0x3c078001,0xe03c000f,0x1e00078,0xf0003c0,0x78001e00, 1.4177 + 0x1e,0xf07803c,0x3c01e0,0x1e00f00,0xf007800,0x7800783e,0x1e0007,0x801e0f80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4178 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1ff,0xffff8000,0x307c0801,0xe1f1e00f,0x87000000, 1.4179 + 0x3c00,0x1e00,0x0,0x1e0000,0x0,0x7ff80000,0xf,0x1e00,0x3c0001e,0x3f0,0x7,0x83fffffc,0x1e0,0x7c000f00,0xf0001e,0x3c000,0x3e0000, 1.4180 + 0x0,0x1ffc,0x1fffff,0xf0007ff0,0x3c000,0x781e0070,0x7ffffc03,0xc000781e,0x1e0,0x7803c0,0x1e00,0x3c000,0x781e0007,0x80007800, 1.4181 + 0x780,0x3c03e000,0x7800001e,0xf078,0x79e03c0,0x780780,0xf000,0x1e078007,0x8000000f,0xf000,0xf0003c0,0x3c3c001,0xee0ef000, 1.4182 + 0xf87c0000,0x7800001f,0x3c,0x78,0x1e0,0x0,0x0,0x0,0x7c003c01,0xe000780f,0x1e0,0x780f00,0x3c,0x3c000,0xf0078007,0x80003c00, 1.4183 + 0xf000,0x7e3e000,0x1e0000f,0x3c0f01e,0x1e03c0,0xf00780,0x1e0f000,0x3c003c00,0x1ffc,0x3c000,0x3c003c0,0x781e003,0xe3b8f800, 1.4184 + 0x1fc00007,0x83c00007,0xc00000fc,0xf0,0x3e0,0x8001f8,0x0,0x7800000,0xffc7fe00,0x0,0x1e000000,0x0,0x18,0xc0,0x0,0x0,0x1e0, 1.4185 + 0xf000003,0xc00f000f,0xfc7fe001,0xf00003ff,0x1ff81ff8,0xffc00000,0x0,0x0,0x0,0x1ff000,0x0,0x0,0x0,0x3,0xff800000,0x1e0f0078, 1.4186 + 0xffc7f,0xe0007c00,0x1e000,0x0,0x780001,0xe0180000,0xf000000e,0x1c00007,0x80000000,0x1f81,0xe0000000,0x38e0003,0x80000000, 1.4187 + 0xf81f000,0x1e00,0x7ff801c3,0x80e1c000,0x0,0x78,0x0,0x0,0x0,0x3c003c0,0xe1c00,0x0,0x0,0x0,0xf8,0x1f070007,0xc03803ff,0xc1c001f0, 1.4188 + 0xf80000,0xfffff00,0x7ffff803,0xffffc01f,0xfffe00ff,0xfff007ff,0xffc07fff,0x8001e000,0x78000,0x3c0000,0x1e00000,0xf000000, 1.4189 + 0xf00000,0x7800000,0x3c000001,0xe0001e00,0x780f00f,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0xf9f001e,0xf003c0f0, 1.4190 + 0x3c0780,0x1e03c00,0xf01e000,0x78000780,0x1ffffc,0xf003f8,0xf800780,0x7c003c03,0xe001e01f,0xf00f8,0x7807c0,0x3c0fc1e,0xf000, 1.4191 + 0x1e0000,0xf00000,0x7800000,0x3c000000,0x780000,0x3c00000,0x1e000000,0xf0001e00,0x7803c00,0x3c078001,0xe03c000f,0x1e00078, 1.4192 + 0xf0003c0,0x78001e00,0x1e,0x1e07803c,0x3c01e0,0x1e00f00,0xf007800,0x7800783c,0x1e0007,0x801e0f00,0x0,0x0,0x0,0x0,0x0,0x0, 1.4193 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1ff,0xffff8000,0x303c0001, 1.4194 + 0xc071e007,0xcf000000,0x3c00,0x1e00,0x0,0x1e0000,0x0,0x0,0xf,0xf00,0x780001e,0x7e0,0x7,0x83fffffc,0x1e0,0x7c000f00,0x1f0001e, 1.4195 + 0x3c000,0x3c0000,0x0,0x3ff,0x801fffff,0xf003ff80,0x3c000,0x781e0070,0x7ffffc03,0xc000781e,0x1e0,0x7803c0,0x1e00,0x1e000,0x781e0007, 1.4196 + 0x80007800,0x780,0x3c01f000,0x7800001e,0xf078,0x79e03c0,0xf00780,0xf000,0x3e078007,0xc000000f,0xf000,0xf0003c0,0x3c3c001, 1.4197 + 0xee0ef000,0xf03e0000,0x7800003e,0x3c,0x78,0x1e0,0x0,0x0,0x0,0xf8003c01,0xe000780f,0x1e0,0x780f00,0x3c,0x3c000,0xf0078007, 1.4198 + 0x80003c00,0xf000,0x7c3e000,0x1e0000f,0x3c0f01e,0x1e03c0,0xf00780,0x1e0f000,0x3c003c00,0xfc,0x3c000,0x3c003c0,0x3c3e001,0xe7b8f000, 1.4199 + 0x3fe00007,0xc7c0000f,0xc000003e,0xf0,0x7c0,0x0,0x0,0x7c00000,0x7fcffc00,0x0,0x1e000000,0x0,0x18,0xc0,0x0,0x0,0x1e0,0x1e000003, 1.4200 + 0xc00f0007,0xfcffc003,0xe00001ff,0x3ff00ff9,0xff800000,0x0,0x0,0x0,0x1ff000,0x0,0x0,0x0,0x0,0x1f800000,0xf0f0078,0x7fcff, 1.4201 + 0xc000fc00,0x1e000,0x0,0x780001,0xe0180000,0xf000000f,0x87c00007,0x80000000,0xfe3,0xe0000000,0x18780c3,0x0,0x7c0f800,0x1e00, 1.4202 + 0xc3,0x80e18000,0x0,0x78,0x0,0x0,0x0,0x3c003c0,0xe1c00,0x0,0x0,0x0,0x1f0,0x3e00000f,0xc0000303,0xe00003f0,0xf00000,0xfffff80, 1.4203 + 0x7ffffc03,0xffffe01f,0xffff00ff,0xfff807ff,0xffc07fff,0x8001e000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000, 1.4204 + 0x3c000001,0xe0001e00,0x780f00f,0x3c078001,0xe03c000f,0x1e00078,0xf0003c0,0x78001e00,0x1f0f801f,0xe00780f0,0x3c0780,0x1e03c00, 1.4205 + 0xf01e000,0x78000780,0x1ffff8,0xf000f8,0x1f000780,0xf8003c07,0xc001e03e,0xf01f0,0x780f80,0x3c1f01e,0xf000,0x1e0000,0xf00000, 1.4206 + 0x7800000,0x3c000000,0x780000,0x3c00000,0x1e000000,0xf0001e00,0x7803c00,0x3c078001,0xe03c000f,0x1e00078,0xf0003c0,0x78001e00, 1.4207 + 0x1e,0x3c07803c,0x3c01e0,0x1e00f00,0xf007800,0x78007c7c,0x1e0007,0x801f1f00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4208 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x81c00000,0x303c0003,0x8039e003,0xef000000, 1.4209 + 0x3c00,0x1e00,0x0,0x1e0000,0x0,0x0,0x1e,0xf00,0x780001e,0xfc0,0x7,0x83fffffc,0x1e0,0x3c000f00,0x1e0001e,0x3c000,0x3c0000, 1.4210 + 0x0,0x7f,0xe01fffff,0xf00ffc00,0x3c000,0x781f00f0,0x7ffffc03,0xc000781e,0x1e0,0x7803c0,0x1e00,0x1e000,0x781e0007,0x80007800, 1.4211 + 0x780,0x3c01f000,0x7800001e,0xf078,0x7de01e0,0xf00780,0x7800,0x3c078003,0xc000000f,0xf000,0xf0003c0,0x3e7c001,0xee0ef001, 1.4212 + 0xf01e0000,0x7800003e,0x3c,0x3c,0x1e0,0x0,0x0,0x0,0xf0003c01,0xe000780f,0x1e0,0x780f00,0x3c,0x3c000,0xf0078007,0x80003c00, 1.4213 + 0xf000,0x781f000,0x1e0000f,0x3c0f01e,0x1e03c0,0xf00780,0x1e0f000,0x3c003c00,0x3e,0x3c000,0x3c003c0,0x3c3c001,0xe71cf000,0x7df00003, 1.4214 + 0xc780000f,0x8000003e,0xf0,0x780,0x0,0x0,0x3c00000,0x3fcff800,0x0,0x1e000000,0x0,0x18,0xc0,0x0,0x1f00fc,0x1e0,0x1e000001, 1.4215 + 0xe00f0003,0xfcff8003,0xe00000ff,0x3fe007f9,0xff000000,0x0,0x0,0x0,0x1ff000,0x0,0x0,0x0,0x0,0x7c00000,0xf0f0078,0x3fcff,0x8000f800, 1.4216 + 0x1e000,0x0,0x780001,0xe0180000,0xf000001f,0xffe00007,0x8000003c,0x7ff,0xc0000000,0x1c3ffc7,0x0,0x3e07c00,0x1e00,0xe3,0x80738000, 1.4217 + 0x0,0x78,0x0,0x0,0x0,0x3c003c0,0xe1c00,0x0,0x0,0x0,0x3e0,0x7c00001d,0xc0000001,0xe0000770,0x1f00000,0xfffff80,0x7ffffc03, 1.4218 + 0xffffe01f,0xffff00ff,0xfff807ff,0xffc07fff,0x8001e000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001, 1.4219 + 0xe0001e00,0x780f00f,0x3c03c001,0xe01e000f,0xf00078,0x78003c0,0x3c001e00,0x3e07c01f,0xc00780f0,0x3c0780,0x1e03c00,0xf01e000, 1.4220 + 0x78000780,0x1fffc0,0xf0007c,0x1e000780,0xf0003c07,0x8001e03c,0xf01e0,0x780f00,0x3c1e01e,0xf000,0x1e0000,0xf00000,0x7800000, 1.4221 + 0x3c000000,0x780000,0x3c00000,0x1e000000,0xf0001e00,0x7803c00,0x3c078001,0xe03c000f,0x1e00078,0xf0003c0,0x78001e00,0x1e,0x7807803c, 1.4222 + 0x3c01e0,0x1e00f00,0xf007800,0x78003c78,0x1e0007,0x800f1e00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4223 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x83c00000,0x303c0003,0x8039e001,0xee000000,0x1e00,0x3c00, 1.4224 + 0x0,0x1e0000,0x0,0x0,0x1e,0xf00,0x780001e,0x1f80,0x7,0x83fffffc,0x1e0,0x3c000f00,0x1e0001e,0x3c000,0x3c0000,0x0,0x1f,0xfc1fffff, 1.4225 + 0xf07ff000,0x0,0x780f00f0,0x78003c03,0xc000781e,0x1e0,0xf803c0,0x1e00,0x1e000,0x781e0007,0x80007800,0x780,0x3c00f800,0x7800001e, 1.4226 + 0xf078,0x3de01e0,0xf00780,0x7800,0x3c078003,0xe000000f,0xf000,0xf0003c0,0x1e78001,0xfe0ff003,0xe01f0000,0x7800007c,0x3c,0x3c, 1.4227 + 0x1e0,0x0,0x0,0x0,0xf0007c01,0xe000f80f,0x800001e0,0xf80f00,0x3c,0x1e001,0xf0078007,0x80003c00,0xf000,0x780f800,0x1e0000f, 1.4228 + 0x3c0f01e,0x1e03c0,0x1f00780,0x3e0f000,0x7c003c00,0x1e,0x3c000,0x3c003c0,0x3c3c001,0xe71cf000,0xf8f80003,0xe780001f,0x1e, 1.4229 + 0xf0,0x780,0x0,0x0,0x3c00000,0x1ffff000,0x0,0x1e000000,0x0,0x18,0xc0,0x0,0x3bc1de,0x1e0,0xf000001,0xe00f0001,0xffff0007,0xc000007f, 1.4230 + 0xffc003ff,0xfe000000,0x0,0x0,0x0,0xfe000,0x0,0x0,0x0,0x0,0x3c00000,0x1e0f0078,0x1ffff,0x1f000,0x1e000,0x0,0x780000,0xf0180000, 1.4231 + 0xf000001f,0xfff00007,0x8000003c,0x1ff,0x80000000,0xe0ff0e,0x0,0x1f03e00,0x1e00,0x70,0x70000,0x0,0x78,0x0,0x0,0x0,0x3c003c0, 1.4232 + 0xe1c00,0x0,0x0,0x0,0x7c0,0xf8000019,0xc0000000,0xe0000670,0x1e00000,0xf000780,0x78003c03,0xc001e01e,0xf00f0,0x780780,0x3c0f807, 1.4233 + 0x8001e000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0xf80f007,0xbc03c001,0xe01e000f, 1.4234 + 0xf00078,0x78003c0,0x3c001e00,0x7c03e00f,0x800780f0,0x3c0780,0x1e03c00,0xf01e000,0x78000780,0x1e0000,0xf0003c,0x1e000f80, 1.4235 + 0xf0007c07,0x8003e03c,0x1f01e0,0xf80f00,0x7c1e01e,0xf800,0x1e0000,0xf00000,0x7800000,0x3c000000,0x780000,0x3c00000,0x1e000000, 1.4236 + 0xf0001e00,0x7803c00,0x3c078003,0xe03c001f,0x1e000f8,0xf0007c0,0x78003e00,0x1f8001f,0xf00f803c,0x3c01e0,0x1e00f00,0xf007800, 1.4237 + 0x78003e78,0x1e000f,0x800f9e00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4238 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0x3c00000,0x303c0003,0x8039f001,0xfe000000,0x1e00,0x3c00,0x0,0x1e0000,0x0,0x0,0x3c,0xf00, 1.4239 + 0x780001e,0x3f00,0x7,0x80000780,0x3e0,0x3e000f00,0x3c0001e,0x3c000,0x7c0000,0x0,0x3,0xfe000000,0xff8000,0x0,0x3c0f81f0,0xf0001e03, 1.4240 + 0xc000780f,0x1e0,0xf003c0,0x1e00,0xf000,0x781e0007,0x80007800,0x780,0x3c007c00,0x7800001e,0xf078,0x3de01e0,0xf00780,0x7800, 1.4241 + 0x3c078001,0xe000000f,0xf000,0xf0003c0,0x1e78001,0xfc07f003,0xe00f0000,0x78000078,0x3c,0x1e,0x1e0,0x0,0x0,0x0,0xf0007c01, 1.4242 + 0xf000f007,0x800000f0,0xf80780,0x3c,0x1e001,0xf0078007,0x80003c00,0xf000,0x7807c00,0x1e0000f,0x3c0f01e,0x1e01e0,0x1e007c0, 1.4243 + 0x3c07800,0x7c003c00,0x1e,0x3c000,0x3c007c0,0x1e78001,0xe71df000,0xf8f80001,0xef80003e,0x1e,0xf0,0x780,0x0,0x0,0x3c00000, 1.4244 + 0xfffe000,0x0,0x3e000000,0x0,0x18,0x7fff,0xc0000000,0x60c306,0x1e0,0x7800001,0xe00f0000,0xfffe0007,0x8000003f,0xff8001ff, 1.4245 + 0xfc000000,0x0,0x0,0x0,0x7c000,0x0,0x0,0x0,0x0,0x3c00000,0x3c0f0078,0xfffe,0x3e000,0x1e000,0x0,0x780000,0xf0180000,0xf000003c, 1.4246 + 0xfcf80007,0x8000003c,0x7f,0x0,0x70001c,0x0,0xf81f00,0x0,0x38,0xe0000,0x0,0x0,0x0,0x0,0x0,0x3c003c0,0xe1c00,0x0,0x0,0x0,0xf81, 1.4247 + 0xf0000039,0xc0000000,0xe0000e70,0x1e00000,0x1e0003c0,0xf0001e07,0x8000f03c,0x781e0,0x3c0f00,0x1e0f007,0x8000f000,0x78000, 1.4248 + 0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0xf00f007,0xbc03c001,0xe01e000f,0xf00078,0x78003c0, 1.4249 + 0x3c001e00,0xf801f00f,0x800780f0,0x3c0780,0x1e03c00,0xf01e000,0x78000780,0x1e0000,0xf0003c,0x1e000f80,0xf0007c07,0x8003e03c, 1.4250 + 0x1f01e0,0xf80f00,0x7c1e01e,0x7800,0xf0000,0x780000,0x3c00000,0x1e000000,0x780000,0x3c00000,0x1e000000,0xf0000f00,0xf003c00, 1.4251 + 0x3c03c003,0xc01e001e,0xf000f0,0x7800780,0x3c003c00,0x1f8000f,0xe00f003c,0x7c01e0,0x3e00f00,0x1f007800,0xf8001ef8,0x1f000f, 1.4252 + 0x7be00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4253 + 0x0,0x0,0xf,0x3c00000,0x307c0003,0x8038f000,0xfc000000,0x1e00,0x3c00,0x0,0x1e0000,0xfc0000,0x0,0x7e00003c,0x780,0xf00001e, 1.4254 + 0x7e00,0xf,0x80000780,0x3c0,0x3e001e00,0x3c0001f,0x7c000,0x780007,0xe000003f,0x0,0xfe000000,0xfe0000,0x0,0x3c07c3f0,0xf0001e03, 1.4255 + 0xc000f80f,0x800001e0,0x1f003c0,0x1e00,0xf000,0x781e0007,0x80007800,0x4000f80,0x3c003c00,0x7800001e,0xf078,0x1fe01f0,0x1f00780, 1.4256 + 0x7c00,0x7c078001,0xf000001f,0xf000,0xf0003c0,0x1e78001,0xfc07f007,0xc00f8000,0x780000f8,0x3c,0x1e,0x1e0,0x0,0x0,0x0,0xf0007c01, 1.4257 + 0xf000f007,0xc00000f0,0xf80780,0x3c,0x1f003,0xf0078007,0x80003c00,0xf000,0x7807c00,0x1e0000f,0x3c0f01e,0x1e01e0,0x1e007c0, 1.4258 + 0x3c07800,0x7c003c00,0x1e,0x3c000,0x3c007c0,0x1e78000,0xfe0fe001,0xf07c0001,0xef00007c,0x1e,0xf0,0x780,0x0,0x0,0x1e00000, 1.4259 + 0x7cfc000,0xfc00000,0x3c00000f,0xc3f00000,0x18,0x7fff,0xc0000000,0x406303,0x3e0,0x3c00001,0xf00f0000,0x7cfc000f,0x8000001f, 1.4260 + 0x3f0000f9,0xf8000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0x780700f8,0x7cfc,0x7c000,0x1e000,0x0,0x780000,0xf8180000, 1.4261 + 0xf0000070,0x3c0007,0x8000003c,0x3f,0x80000000,0x3c0078,0x0,0x780f00,0x0,0x1e,0x3c0000,0x0,0x0,0x0,0x0,0x0,0x3e007c0,0xe1c00, 1.4262 + 0x0,0x0,0x0,0xf01,0xe0000071,0xc0000000,0xe0001c70,0x1e00000,0x1e0003c0,0xf0001e07,0x8000f03c,0x781e0,0x3c0f00,0x1e0f007, 1.4263 + 0x8000f800,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x1f00f003,0xfc03e003,0xe01f001f, 1.4264 + 0xf800f8,0x7c007c0,0x3e003e01,0xf000f80f,0xf00f0,0x3c0780,0x1e03c00,0xf01e000,0x78000780,0x1e0000,0xf0003c,0x1e000f80,0xf0007c07, 1.4265 + 0x8003e03c,0x1f01e0,0xf80f00,0x7c1e01e,0x7c00,0xf0000,0x780000,0x3c00000,0x1e000000,0x780000,0x3c00000,0x1e000000,0xf0000f00, 1.4266 + 0xf003c00,0x3c03c003,0xc01e001e,0xf000f0,0x7800780,0x3c003c00,0x1f8000f,0xc00f003c,0x7c01e0,0x3e00f00,0x1f007800,0xf8001ef0, 1.4267 + 0x1f000f,0x7bc00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4268 + 0x0,0x0,0x0,0x0,0x780000,0xf,0x3800040,0x30780003,0x8038f800,0x78000000,0x1e00,0x3c00,0x0,0x1e0000,0xfc0000,0x0,0x7e000078, 1.4269 + 0x780,0x1f00001e,0xfc00,0x20001f,0x780,0x80007c0,0x1f001e00,0x7c0000f,0x78000,0xf80007,0xe000003f,0x0,0x1e000000,0xf00000, 1.4270 + 0x3c000,0x3c03fff0,0xf0001e03,0xc001f007,0x800101e0,0x7e003c0,0x1e00,0x7800,0x781e0007,0x80007800,0x6000f00,0x3c003e00,0x7800001e, 1.4271 + 0xf078,0x1fe00f0,0x1e00780,0x3c00,0x78078000,0xf020001e,0xf000,0x7800780,0xff0001,0xfc07f00f,0x8007c000,0x780001f0,0x3c,0xf, 1.4272 + 0x1e0,0x0,0x0,0x0,0xf800fc01,0xf801f007,0xc00100f8,0x1f807c0,0x40003c,0xf807,0xf0078007,0x80003c00,0xf000,0x7803e00,0x1f0000f, 1.4273 + 0x3c0f01e,0x1e01f0,0x3e007e0,0x7c07c00,0xfc003c00,0x1e,0x3e000,0x3e007c0,0x1ff8000,0xfe0fe003,0xe03e0001,0xff0000fc,0x1e, 1.4274 + 0xf0,0x780,0x0,0x0,0x1f00080,0x3cf8000,0xfc00000,0x3c00001f,0x83f00000,0x18,0xc0,0x0,0xc06203,0x40003c0,0x1c00000,0xf80f0000, 1.4275 + 0x3cf8001f,0xf,0x3e000079,0xf0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0x700780fc,0x3cf8,0xfc000,0x1e000,0x0,0x780000, 1.4276 + 0x7c180000,0xf0000020,0x100007,0x8000003c,0xf,0x80000000,0x1f01f0,0x0,0x380700,0x0,0xf,0x80f80000,0x0,0x0,0x0,0x0,0x0,0x3e007c0, 1.4277 + 0xe1c00,0x0,0x0,0x0,0xe01,0xc0000071,0xc0000001,0xc0001c70,0x1e00040,0x1e0003c0,0xf0001e07,0x8000f03c,0x781e0,0x3c0f00,0x1e0f007, 1.4278 + 0x80007800,0x10078000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x7e00f003,0xfc01e003,0xc00f001e, 1.4279 + 0x7800f0,0x3c00780,0x1e003c00,0xe000700f,0x800f0078,0x7803c0,0x3c01e00,0x1e00f000,0xf0000780,0x1e0000,0xf0003c,0x1f001f80, 1.4280 + 0xf800fc07,0xc007e03e,0x3f01f0,0x1f80f80,0xfc1e01f,0x7c00,0x100f8000,0x807c0004,0x3e00020,0x1f000100,0x780000,0x3c00000,0x1e000000, 1.4281 + 0xf0000f80,0x1f003c00,0x3c03e007,0xc01f003e,0xf801f0,0x7c00f80,0x3e007c00,0x1f8000f,0x801f003e,0x7c01f0,0x3e00f80,0x1f007c00, 1.4282 + 0xf8001ff0,0x1f801f,0x7fc00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4283 + 0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0xf,0x7800078,0x31f80001,0xc070fc00,0xfc000000,0x1e00,0x7c00,0x0,0x1e0000,0xfc0000,0x0,0x7e000078, 1.4284 + 0x7c0,0x1f00001e,0x1f000,0x38003f,0x780,0xe000f80,0x1f803e00,0x780000f,0x800f8000,0x1f00007,0xe000003f,0x0,0x2000000,0x800000, 1.4285 + 0x3c000,0x3e01ff71,0xf0001f03,0xc007f007,0xc00301e0,0x1fc003c0,0x1e00,0x7c00,0x781e0007,0x80007800,0x7801f00,0x3c001f00,0x7800001e, 1.4286 + 0xf078,0xfe00f8,0x3e00780,0x3e00,0xf8078000,0xf838003e,0xf000,0x7c00f80,0xff0000,0xfc07e00f,0x8003c000,0x780001e0,0x3c,0xf, 1.4287 + 0x1e0,0x0,0x0,0x0,0xf801fc01,0xfc03e003,0xe003007c,0x3f803e0,0x1c0003c,0xfc0f,0xf0078007,0x80003c00,0xf000,0x7801f00,0xf8000f, 1.4288 + 0x3c0f01e,0x1e00f8,0x7c007f0,0xf803e01,0xfc003c00,0x8003e,0x1f000,0x1e00fc0,0xff0000,0xfe0fe007,0xc01f0000,0xfe0000f8,0x1e, 1.4289 + 0xf0,0x780,0x0,0x0,0xf80180,0x1cf0000,0x1f800000,0x3c00001f,0x83e00000,0x18,0xc0,0x0,0xc06203,0x70007c0,0xe00000,0x7e0f0000, 1.4290 + 0x1cf0001e,0x7,0x3c000039,0xe0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100,0x7c00000,0xe00780fc,0x2001cf0,0xf8000,0x1e000,0x0, 1.4291 + 0x780000,0x7e182000,0xf0000000,0x7,0x8000003c,0x7,0xc0000000,0x7ffc0,0x0,0x180300,0x0,0x3,0xffe00000,0x0,0x0,0x0,0x0,0x0, 1.4292 + 0x3f00fc0,0xe1c00,0x0,0x0,0x0,0xc01,0x800000e1,0xc0000003,0xc0003870,0x1f001c0,0x3e0003e1,0xf0001f0f,0x8000f87c,0x7c3e0,0x3e1f00, 1.4293 + 0x1f1e007,0x80007c00,0x30078000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e03,0xfc00f001,0xfc01f007, 1.4294 + 0xc00f803e,0x7c01f0,0x3e00f80,0x1f007c00,0x4000201f,0xc01f007c,0xf803e0,0x7c01f00,0x3e00f801,0xf0000780,0x1e0000,0xf0007c, 1.4295 + 0x1f003f80,0xf801fc07,0xc00fe03e,0x7f01f0,0x3f80f80,0x1fc1f03f,0x803e00,0x3007c003,0x803e001c,0x1f000e0,0xf800700,0x780000, 1.4296 + 0x3c00000,0x1e000000,0xf00007c0,0x3e003c00,0x3c01f00f,0x800f807c,0x7c03e0,0x3e01f00,0x1f00f800,0x1f80007,0xc03e001e,0xfc00f0, 1.4297 + 0x7e00780,0x3f003c01,0xf8000fe0,0x1fc03e,0x3f800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4298 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1e,0x780007f,0xfff00001,0xe0f07f03,0xfe000000,0xf00,0x7800,0x0, 1.4299 + 0x1e0000,0xfc0000,0x0,0x7e0000f0,0x3f0,0x7e000fff,0xfc03ffff,0xf83f00fe,0x780,0xfc03f80,0xfc0fc00,0xf800007,0xe03f0018,0x7e00007, 1.4300 + 0xe000003f,0x0,0x0,0x0,0x3c000,0x1e007c71,0xe0000f03,0xffffe003,0xf01f01ff,0xff8003ff,0xffe01e00,0x3f01,0xf81e0007,0x803ffff0, 1.4301 + 0x7e03f00,0x3c000f00,0x7ffffe1e,0xf078,0xfe007e,0xfc00780,0x1f83,0xf0078000,0x783f00fe,0xf000,0x3f03f00,0xff0000,0xfc07e01f, 1.4302 + 0x3e000,0x780003ff,0xfffc003c,0x7,0x800001e0,0x0,0x0,0x0,0x7e07fc01,0xfe07e001,0xf80f007e,0x7f801f8,0xfc0003c,0x7ffe,0xf0078007, 1.4303 + 0x807ffffe,0xf000,0x7801f00,0xfff00f,0x3c0f01e,0x1e00fc,0xfc007f8,0x1f803f03,0xfc003c00,0xf80fc,0x1fff0,0x1f83fc0,0xff0000, 1.4304 + 0xfc07e007,0xc01f0000,0xfe0001ff,0xffe0001e,0xf0,0x780,0x0,0x0,0xfe0780,0xfe0000,0x1f000000,0x3c00001f,0x7c00e03,0x81c00018, 1.4305 + 0xc0,0x0,0x406203,0x7e01fc0,0x700000,0x7fffff80,0xfe0003f,0xffffc003,0xf800001f,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1f0, 1.4306 + 0x1f800001,0xc007c1fe,0x6000fe0,0x1ffffe,0x1e000,0x0,0x780000,0x3f98e03f,0xffff8000,0x7,0x8000003c,0x7,0xc0000000,0xfe00, 1.4307 + 0x0,0x80100,0x0,0x0,0x7f000000,0x0,0x1ffff,0xfe000000,0x0,0x0,0x3f83fe8,0xe1c00,0x0,0x0,0x0,0x801,0xc1,0xc0000007,0x80003070, 1.4308 + 0xfc0fc0,0x3c0001e1,0xe0000f0f,0x7878,0x3c3c0,0x1e1e00,0xf1e007,0xffc03f01,0xf007ffff,0xc03ffffe,0x1fffff0,0xfffff80,0x7fffe003, 1.4309 + 0xffff001f,0xfff800ff,0xffc01fff,0xf800f001,0xfc00fc1f,0x8007e0fc,0x3f07e0,0x1f83f00,0xfc1f800,0x1f,0xf07e003f,0x3f001f8, 1.4310 + 0x1f800fc0,0xfc007e07,0xe0000780,0x1e0000,0xf301f8,0xfc0ff80,0x7e07fc03,0xf03fe01f,0x81ff00fc,0xff807e0,0x7fc0f87f,0x81801f80, 1.4311 + 0xf003f01f,0x801f80fc,0xfc07e0,0x7e03f00,0xfffffc07,0xffffe03f,0xffff01ff,0xfff807e0,0x7e003c00,0x3c01f81f,0x800fc0fc,0x7e07e0, 1.4312 + 0x3f03f00,0x1f81f800,0x1f8000f,0xe07e001f,0x83fc00fc,0x1fe007e0,0xff003f07,0xf8000fe0,0x1fe07e,0x3f800,0x0,0x0,0x0,0x0,0x0, 1.4313 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1e,0x780007f, 1.4314 + 0xffe00000,0xffe03fff,0xdf000000,0xf00,0x7800,0x0,0x0,0xfc0000,0x0,0x7e0000f0,0x1ff,0xfc000fff,0xfc03ffff,0xf83ffffc,0x780, 1.4315 + 0xfffff00,0x7fff800,0xf000007,0xffff001f,0xffe00007,0xe000003f,0x0,0x0,0x0,0x3c000,0x1e000001,0xe0000f03,0xffffc001,0xffff01ff, 1.4316 + 0xff0003ff,0xffe01e00,0x1fff,0xf81e0007,0x803ffff0,0x7fffe00,0x3c000f80,0x7ffffe1e,0xf078,0xfe003f,0xff800780,0xfff,0xf0078000, 1.4317 + 0x7c3ffffc,0xf000,0x3ffff00,0xff0000,0xf803e01e,0x1e000,0x780003ff,0xfffc003c,0x7,0x800001e0,0x0,0x0,0x0,0x7fffbc01,0xffffc000, 1.4318 + 0xffff003f,0xfff800ff,0xffc0003c,0x3ffe,0xf0078007,0x807ffffe,0xf000,0x7800f80,0x7ff00f,0x3c0f01e,0x1e007f,0xff8007ff,0xff001fff, 1.4319 + 0xbc003c00,0xffffc,0x1fff0,0x1fffbc0,0xff0000,0x7c07c00f,0x800f8000,0x7e0001ff,0xffe0001e,0xf0,0x780,0x0,0x0,0x7fff80,0x7c0000, 1.4320 + 0x1f000000,0x3c00001e,0x7c00f07,0xc1e00018,0xc0,0x0,0x60e303,0x7ffff80,0x380000,0x3fffff80,0x7c0003f,0xffffc001,0xf000000f, 1.4321 + 0x80000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1ff,0xff800003,0x8003ffff,0xfe0007c0,0x1ffffe,0x1e000,0x0,0x780000,0x1fffe03f,0xffff8000, 1.4322 + 0x7,0x8000003c,0x3,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1ffff,0xfe000000,0x0,0x0,0x3fffdf8,0xe1c00,0x0,0x0,0x0,0x0,0x1c1, 1.4323 + 0xc000000f,0x7070,0x7fffc0,0x3c0001e1,0xe0000f0f,0x7878,0x3c3c0,0x1e1e00,0xf1e007,0xffc01fff,0xf007ffff,0xc03ffffe,0x1fffff0, 1.4324 + 0xfffff80,0x7fffe003,0xffff001f,0xfff800ff,0xffc01fff,0xf000f001,0xfc007fff,0x3fff8,0x1fffc0,0xfffe00,0x7fff000,0x3b,0xfffc003f, 1.4325 + 0xfff001ff,0xff800fff,0xfc007fff,0xe0000780,0x1e0000,0xf3fff8,0xffff780,0x7fffbc03,0xfffde01f,0xffef00ff,0xff7807ff,0xfbc0ffff, 1.4326 + 0xff800fff,0xf001ffff,0x800ffffc,0x7fffe0,0x3ffff00,0xfffffc07,0xffffe03f,0xffff01ff,0xfff803ff,0xfc003c00,0x3c00ffff,0x7fff8, 1.4327 + 0x3fffc0,0x1fffe00,0xffff000,0x1f,0xfffc001f,0xffbc00ff,0xfde007ff,0xef003fff,0x780007e0,0x1ffffc,0x1f800,0x0,0x0,0x0,0x0, 1.4328 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1e,0x700003f, 1.4329 + 0xffc00000,0x7fc01fff,0x9f800000,0xf80,0xf800,0x0,0x0,0xfc0000,0x0,0x7e0000f0,0xff,0xf8000fff,0xfc03ffff,0xf83ffff8,0x780, 1.4330 + 0xffffe00,0x7fff000,0xf000003,0xfffe001f,0xffc00007,0xe000003f,0x0,0x0,0x0,0x3c000,0xf000003,0xe0000f83,0xffff0000,0xffff01ff, 1.4331 + 0xfc0003ff,0xffe01e00,0xfff,0xf01e0007,0x803ffff0,0x7fffc00,0x3c0007c0,0x7ffffe1e,0xf078,0x7e003f,0xff000780,0x7ff,0xe0078000, 1.4332 + 0x3c3ffff8,0xf000,0x1fffe00,0x7e0000,0xf803e03e,0x1f000,0x780003ff,0xfffc003c,0x7,0x800001e0,0x0,0x0,0x0,0x3fff3c01,0xefff8000, 1.4333 + 0x7ffe001f,0xff78007f,0xff80003c,0x1ffc,0xf0078007,0x807ffffe,0xf000,0x78007c0,0x3ff00f,0x3c0f01e,0x1e003f,0xff0007bf,0xfe000fff, 1.4334 + 0xbc003c00,0xffff8,0xfff0,0xfff3c0,0x7e0000,0x7c07c01f,0x7c000,0x7c0001ff,0xffe0001e,0xf0,0x780,0x0,0x0,0x3fff80,0x380000, 1.4335 + 0x3e000000,0x7c00003e,0x7801f07,0xc1e00018,0xc0,0x0,0x39c1ce,0x7ffff00,0x1c0000,0xfffff80,0x380003f,0xffffc000,0xe0000007, 1.4336 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1ff,0xff000007,0x1ffcf,0xfe000380,0x1ffffe,0x1e000,0x0,0x780000,0xfffe03f,0xffff8000,0x7, 1.4337 + 0x8000003c,0x3,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1ffff,0xfe000000,0x0,0x0,0x3dffdf8,0xe1c00,0x0,0x0,0x0,0x0,0x381, 1.4338 + 0xc000001e,0xe070,0x7fff80,0x7c0001f3,0xe0000f9f,0x7cf8,0x3e7c0,0x1f3e00,0xfbe007,0xffc00fff,0xf007ffff,0xc03ffffe,0x1fffff0, 1.4339 + 0xfffff80,0x7fffe003,0xffff001f,0xfff800ff,0xffc01fff,0xc000f000,0xfc007ffe,0x3fff0,0x1fff80,0xfffc00,0x7ffe000,0x79,0xfff8001f, 1.4340 + 0xffe000ff,0xff0007ff,0xf8003fff,0xc0000780,0x1e0000,0xf3fff0,0x7ffe780,0x3fff3c01,0xfff9e00f,0xffcf007f,0xfe7803ff,0xf3c07ff3, 1.4341 + 0xff8007ff,0xe000ffff,0x7fff8,0x3fffc0,0x1fffe00,0xfffffc07,0xffffe03f,0xffff01ff,0xfff801ff,0xf8003c00,0x3c007ffe,0x3fff0, 1.4342 + 0x1fff80,0xfffc00,0x7ffe000,0x1d,0xfff8000f,0xff3c007f,0xf9e003ff,0xcf001ffe,0x780007c0,0x1efff8,0x1f000,0x0,0x0,0x0,0x0, 1.4343 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1e,0xf000003, 1.4344 + 0xfe000000,0x1f000fff,0xfc00000,0x780,0xf000,0x0,0x0,0xf80000,0x0,0x7e0001e0,0x7f,0xf0000fff,0xfc03ffff,0xf81ffff0,0x780, 1.4345 + 0x7fff800,0x1ffe000,0x1f000000,0xfff8001f,0xff000007,0xe000003e,0x0,0x0,0x0,0x3c000,0xf800003,0xc0000783,0xfff80000,0x3ffe01ff, 1.4346 + 0xe00003ff,0xffe01e00,0x7ff,0xc01e0007,0x803ffff0,0x3fff800,0x3c0003c0,0x7ffffe1e,0xf078,0x7e000f,0xfe000780,0x3ff,0xc0078000, 1.4347 + 0x3e1fffe0,0xf000,0x7ff800,0x7e0000,0xf803e07c,0xf800,0x780003ff,0xfffc003c,0x3,0xc00001e0,0x0,0x0,0x0,0xffe3c01,0xe7ff0000, 1.4348 + 0x3ffc000f,0xfe78003f,0xfe00003c,0x7f0,0xf0078007,0x807ffffe,0xf000,0x78003e0,0xff00f,0x3c0f01e,0x1e001f,0xfe00079f,0xfc0007ff, 1.4349 + 0x3c003c00,0x7ffe0,0x1ff0,0x7fe3c0,0x7e0000,0x7c07c03e,0x3e000,0x7c0001ff,0xffe0001e,0xf0,0x780,0x0,0x0,0xfff00,0x100000, 1.4350 + 0x3e000000,0x7800003c,0xf800f07,0xc1e00018,0xc0,0x0,0x1f80fc,0x3fffc00,0xc0000,0x3ffff80,0x100003f,0xffffc000,0x40000002, 1.4351 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0xfc000006,0xff87,0xfc000100,0x1ffffe,0x1e000,0x0,0x780000,0x3ffc03f,0xffff8000,0x7, 1.4352 + 0x8000003c,0x3,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1ffff,0xfe000000,0x0,0x0,0x3dff9f8,0xe1c00,0x0,0x0,0x0,0x0,0x3ff, 1.4353 + 0xf800003c,0xfffe,0x1ffe00,0x780000f3,0xc000079e,0x3cf0,0x1e780,0xf3c00,0x7bc007,0xffc003ff,0xe007ffff,0xc03ffffe,0x1fffff0, 1.4354 + 0xfffff80,0x7fffe003,0xffff001f,0xfff800ff,0xffc01ffc,0xf000,0xfc001ffc,0xffe0,0x7ff00,0x3ff800,0x1ffc000,0x70,0xfff00007, 1.4355 + 0xff80003f,0xfc0001ff,0xe0000fff,0x780,0x1e0000,0xf3ffe0,0x1ffc780,0xffe3c00,0x7ff1e003,0xff8f001f,0xfc7800ff,0xe3c03fe1, 1.4356 + 0xff0003ff,0xc0007ffc,0x3ffe0,0x1fff00,0xfff800,0xfffffc07,0xffffe03f,0xffff01ff,0xfff800ff,0xf0003c00,0x3c003ffc,0x1ffe0, 1.4357 + 0xfff00,0x7ff800,0x3ffc000,0x38,0xfff00007,0xfe3c003f,0xf1e001ff,0x8f000ffc,0x780007c0,0x1e7ff0,0x1f000,0x0,0x0,0x0,0x0,0x0, 1.4358 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000, 1.4359 + 0x1fc,0x0,0x780,0xf000,0x0,0x0,0x1f80000,0x0,0x1e0,0x1f,0xc0000000,0x0,0x1ff80,0x0,0xffc000,0x7f8000,0x0,0x3fe00007,0xfc000000, 1.4360 + 0x7e,0x0,0x0,0x0,0x0,0x7c00000,0x0,0x0,0xff00000,0x0,0x0,0xfe,0x0,0x0,0x3fc000,0x0,0x0,0x0,0x3,0xf8000000,0xff,0xc0000000, 1.4361 + 0x1ff00,0x0,0x1fe000,0x0,0x0,0x0,0x0,0x3c,0x3,0xc00001e0,0x0,0x0,0x0,0x3f80000,0x1fc0000,0x7f00003,0xf8000007,0xf0000000, 1.4362 + 0x0,0xf0000000,0x0,0xf000,0x0,0x0,0x0,0x7,0xf8000787,0xf00001fc,0x3c000000,0x7f80,0x0,0x1f8000,0x0,0x0,0x0,0x7c000000,0x1e, 1.4363 + 0xf0,0x780,0x0,0x0,0x3fc00,0x0,0x3c000000,0x7800003c,0xf000601,0xc00018,0xc0,0x0,0x0,0x3fe000,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4364 + 0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xf0000000,0x7e03,0xf0000000,0x0,0x0,0x0,0x0,0xfe0000,0x0,0x0,0x3c,0x2007,0x80000000,0x0,0x0, 1.4365 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c7e0f0,0xe1c00,0x0,0x3800000,0x0,0x0,0x3ff,0xf8000078,0xfffe,0x7f800,0x0,0x0,0x0,0x0, 1.4366 + 0x0,0x0,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f0,0x3f80,0x1fc00,0xfe000,0x7f0000,0x70,0x3fc00001,0xfe00000f,0xf000007f, 1.4367 + 0x800003fc,0x0,0x0,0xff00,0x7f0000,0x3f80000,0x1fc00000,0xfe000007,0xf000003f,0x80001f80,0xfc00007f,0xfe0,0x7f00,0x3f800, 1.4368 + 0x1fc000,0x0,0x0,0x0,0x3f,0xc0000000,0xff0,0x7f80,0x3fc00,0x1fe000,0xff0000,0x78,0x3fc00001,0xf800000f,0xc000007e,0x3f0,0x7c0, 1.4369 + 0x1e1fc0,0x1f000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4370 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000,0x0,0x0,0x3c0,0x1e000,0x0,0x0,0x1f00000,0x0,0x3c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4371 + 0x0,0x0,0x7c,0x0,0x0,0x0,0x0,0x3e00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xe0000000,0x0,0x0,0x0, 1.4372 + 0x0,0x0,0x0,0x0,0x3c,0x1,0xe00001e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf0000000,0x0,0xf000,0x0,0x0,0x0,0x0,0x780,0x0,0x3c000000, 1.4373 + 0x0,0x0,0x0,0x0,0x0,0x0,0x78000000,0x1e,0xf0,0x780,0x0,0x0,0x0,0x0,0x3c000000,0x78000078,0xf000000,0x18,0xc0,0x0,0x0,0x0, 1.4374 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x180000,0x0,0x0,0x3c,0x3c0f,0x80000000, 1.4375 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0xe1c00,0x0,0x1800000,0x0,0x0,0x3ff,0xf80000f0,0xfffe,0x0,0x0,0x0,0x0, 1.4376 + 0x0,0x0,0x0,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4377 + 0x0,0x0,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30,0x0,0x0,0x0,0x0,0x780,0x1e0000,0x1e000,0x0,0x0,0x0, 1.4378 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000, 1.4379 + 0x0,0x0,0x3c0,0x1e000,0x0,0x0,0x1f00000,0x0,0x3c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7c,0x0,0x0,0x0,0x0,0x1f80000, 1.4380 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0xf0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c,0x1,0xe00001e0,0x0, 1.4381 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xe0000000,0x0,0xf000,0x0,0x0,0x0,0x0,0x780,0x0,0x3c000000,0x0,0x0,0x0,0x0,0x0,0x0,0xf8000000, 1.4382 + 0x1f,0xf0,0xf80,0x0,0x0,0x0,0x0,0x78000000,0xf8000078,0x1e000000,0x8,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4383 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x180000,0x0,0x0,0x3c,0x3fff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4384 + 0x0,0x3c00000,0xe1c00,0x0,0x1c00000,0x0,0x0,0x1,0xc00001e0,0x70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4385 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4386 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf80,0x1e0000,0x3e000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4387 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000,0x0,0x0,0x1e0,0x3c000,0x0,0x0,0x1f00000, 1.4388 + 0x0,0x780,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7c,0x0,0x0,0x0,0x0,0xfe0100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4389 + 0x0,0x0,0x0,0x0,0xf8000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3f,0xf0000000,0xf0007fe0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xe0000000, 1.4390 + 0x0,0xf000,0x0,0x0,0x0,0x0,0x780,0x0,0x3c000000,0x0,0x0,0x0,0x0,0x0,0x0,0xf0000000,0x1f,0x800000f0,0x1f80,0x0,0x0,0x0,0x0, 1.4391 + 0x78000000,0xf0000070,0x1c000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4392 + 0x0,0x0,0x0,0x0,0x180000,0x0,0x0,0x3c,0x3ffe,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0xe1c00,0x0,0xe00000, 1.4393 + 0x0,0x0,0x1,0xc00003ff,0xe0000070,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4394 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4395 + 0x0,0x0,0x0,0xf00,0x1e0000,0x3c000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4396 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000,0x0,0x0,0x1e0,0x7c000,0x0,0x0,0x1e00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4397 + 0x0,0x0,0x0,0x0,0x0,0x78,0x0,0x0,0x0,0x0,0x7fff80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x78000000, 1.4398 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3f,0xf0000000,0x7fe0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4003,0xe0000000,0x0,0x1f000,0x0,0x0, 1.4399 + 0x0,0x0,0x780,0x0,0x3c000000,0x0,0x0,0x0,0x0,0x0,0x1,0xf0000000,0xf,0xfc0000f0,0x3ff00,0x0,0x0,0x0,0x0,0x70000001,0xf00000e0, 1.4400 + 0x1c000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x180000, 1.4401 + 0x0,0x0,0x3c,0xff8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0xe1c00,0x0,0xe00000,0x0,0x0,0x1,0xc00003ff, 1.4402 + 0xe0000070,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4403 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1f00,0x1e0000, 1.4404 + 0x7c000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4405 + 0x0,0x0,0x0,0x0,0x30000000,0x0,0x0,0xf0,0x78000,0x0,0x0,0x3e00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf8,0x0, 1.4406 + 0x0,0x0,0x0,0x1fff80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3f, 1.4407 + 0xf0000000,0x7fe0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780f,0xc0000000,0x0,0x3e000,0x0,0x0,0x0,0x0,0x780,0x0,0x3c000000,0x0, 1.4408 + 0x0,0x0,0x0,0x0,0x3,0xe0000000,0xf,0xfc0000f0,0x3ff00,0x0,0x0,0x0,0x0,0xf0000103,0xe0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4409 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x180000,0x0,0x0,0x3c,0x0,0x0,0x0,0x0,0x0,0x0, 1.4410 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0x0,0x0,0x21e00000,0x0,0x0,0x1,0xc00003ff,0xe0000070,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10f, 1.4411 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10f,0x0, 1.4412 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3e00,0x1e0000,0xf8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4413 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000,0x0,0x0, 1.4414 + 0xf8,0xf8000,0x0,0x0,0x3c00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf0,0x0,0x0,0x0,0x0,0x1fe00,0x0,0x0,0x0,0x0, 1.4415 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3f,0xf0000000,0x7fe0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4416 + 0x0,0x0,0x7fff,0xc0000000,0x0,0x3ffe000,0x0,0x0,0x0,0x0,0x780,0x0,0x3c000000,0x0,0x0,0x0,0x0,0x0,0x7f,0xe0000000,0x7,0xfc0000f0, 1.4417 + 0x3fe00,0x0,0x0,0x0,0x0,0x600001ff,0xe0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4418 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x180000,0x0,0x0,0x3c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0x0,0x0, 1.4419 + 0x3fe00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1ff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4420 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1ff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4421 + 0x0,0x0,0x0,0x0,0x7fe00,0x1e0000,0x1ff8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4422 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4423 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4424 + 0x0,0x0,0x0,0x0,0x1fffffe0,0x0,0x0,0x0,0x0,0x0,0x0,0x7fff,0x80000000,0x0,0x3ffc000,0x0,0x0,0x0,0x0,0x780,0x0,0x3c000000,0x0, 1.4425 + 0x0,0x0,0x0,0x0,0x7f,0xc0000000,0x0,0xfc0000f0,0x3f000,0x0,0x0,0x0,0x0,0x1ff,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4426 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4427 + 0x0,0x0,0x0,0x0,0x0,0x3c00000,0x0,0x0,0x3fc00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1fe,0x0,0x0,0x0,0x0,0x0, 1.4428 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1fe,0x0,0x0,0x0,0x0,0x0,0x0, 1.4429 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7fc00,0x1e0000,0x1ff0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4430 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4431 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4432 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1fffffe0,0x0,0x0,0x0,0x0,0x0,0x0,0x3ffe,0x0,0x0,0x3ff8000,0x0,0x0,0x0, 1.4433 + 0x0,0x780,0x0,0x3c000000,0x0,0x0,0x0,0x0,0x0,0x7f,0x80000000,0x0,0xf0,0x0,0x0,0x0,0x0,0x0,0x1ff,0x80000000,0x0,0x0,0x0,0x0, 1.4434 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4435 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0x0,0x0,0x3f800000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1fc,0x0, 1.4436 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1fc,0x0,0x0, 1.4437 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f800,0x1e0000,0x1fe0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4438 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4439 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4440 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1fffffe0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f8,0x0,0x0,0x3fe0000, 1.4441 + 0x0,0x0,0x0,0x0,0x780,0x0,0x3c000000,0x0,0x0,0x0,0x0,0x0,0x7e,0x0,0x0,0xf0,0x0,0x0,0x0,0x0,0x0,0xfe,0x0,0x0,0x0,0x0,0x0,0x0, 1.4442 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4443 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4444 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4445 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7e000,0x1e0000,0x1f80000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4446 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4447 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4448 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1fffffe0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4449 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4450 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4451 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4452 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4453 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4454 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4455 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4456 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf0,0x0,0x0,0x0, 1.4457 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4458 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4459 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 1.4460 + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 }; 1.4461 + 1.4462 + // Definition of a 40x38 'danger' color logo. 1.4463 + const unsigned char logo40x38[4576] = { 1.4464 + 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.4465 + 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, 1.4466 + 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.4467 + 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, 1.4468 + 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, 1.4469 + 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, 1.4470 + 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, 1.4471 + 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, 1.4472 + 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.4473 + 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, 1.4474 + 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, 1.4475 + 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, 1.4476 + 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, 1.4477 + 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, 1.4478 + 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, 1.4479 + 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, 1.4480 + 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, 1.4481 + 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, 1.4482 + 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, 1.4483 + 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, 1.4484 + 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, 1.4485 + 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, 1.4486 + 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, 1.4487 + 200,200,200,91,49,124,118,124,71,32,124,95,49,56,114,52,82,121,0}; 1.4488 + 1.4489 + //! Display a warning message. 1.4490 + /** 1.4491 + \param format is a C-string describing the format of the message, as in <tt>std::printf()</tt>. 1.4492 + **/ 1.4493 + inline void warn(const char *format, ...) { 1.4494 + if (cimg::exception_mode()>=1) { 1.4495 + char message[8192]; 1.4496 + cimg_std::va_list ap; 1.4497 + va_start(ap,format); 1.4498 + cimg_std::vsprintf(message,format,ap); 1.4499 + va_end(ap); 1.4500 +#ifdef cimg_strict_warnings 1.4501 + throw CImgWarningException(message); 1.4502 +#else 1.4503 + cimg_std::fprintf(cimg_stdout,"\n%s# CImg Warning%s :\n%s\n",cimg::t_red,cimg::t_normal,message); 1.4504 +#endif 1.4505 + } 1.4506 + } 1.4507 + 1.4508 + // Execute an external system command. 1.4509 + /** 1.4510 + \note This function is similar to <tt>std::system()</tt> 1.4511 + and is here because using the <tt>std::</tt> version on 1.4512 + Windows may open undesired consoles. 1.4513 + **/ 1.4514 + inline int system(const char *const command, const char *const module_name=0) { 1.4515 +#if cimg_OS==2 1.4516 + PROCESS_INFORMATION pi; 1.4517 + STARTUPINFO si; 1.4518 + cimg_std::memset(&pi,0,sizeof(PROCESS_INFORMATION)); 1.4519 + cimg_std::memset(&si,0,sizeof(STARTUPINFO)); 1.4520 + GetStartupInfo(&si); 1.4521 + si.cb = sizeof(si); 1.4522 + si.wShowWindow = SW_HIDE; 1.4523 + si.dwFlags |= SW_HIDE; 1.4524 + const BOOL res = CreateProcess((LPCTSTR)module_name,(LPTSTR)command,0,0,FALSE,0,0,0,&si,&pi); 1.4525 + if (res) { 1.4526 + WaitForSingleObject(pi.hProcess, INFINITE); 1.4527 + CloseHandle(pi.hThread); 1.4528 + CloseHandle(pi.hProcess); 1.4529 + return 0; 1.4530 + } else 1.4531 +#endif 1.4532 + return cimg_std::system(command); 1.4533 + return module_name?0:1; 1.4534 + } 1.4535 + 1.4536 + //! Return a reference to a temporary variable of type T. 1.4537 + template<typename T> 1.4538 + inline T& temporary(const T&) { 1.4539 + static T temp; 1.4540 + return temp; 1.4541 + } 1.4542 + 1.4543 + //! Exchange values of variables \p a and \p b. 1.4544 + template<typename T> 1.4545 + inline void swap(T& a, T& b) { T t = a; a = b; b = t; } 1.4546 + 1.4547 + //! Exchange values of variables (\p a1,\p a2) and (\p b1,\p b2). 1.4548 + template<typename T1, typename T2> 1.4549 + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2) { 1.4550 + cimg::swap(a1,b1); cimg::swap(a2,b2); 1.4551 + } 1.4552 + 1.4553 + //! Exchange values of variables (\p a1,\p a2,\p a3) and (\p b1,\p b2,\p b3). 1.4554 + template<typename T1, typename T2, typename T3> 1.4555 + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3) { 1.4556 + cimg::swap(a1,b1,a2,b2); cimg::swap(a3,b3); 1.4557 + } 1.4558 + 1.4559 + //! Exchange values of variables (\p a1,\p a2,...,\p a4) and (\p b1,\p b2,...,\p b4). 1.4560 + template<typename T1, typename T2, typename T3, typename T4> 1.4561 + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4) { 1.4562 + cimg::swap(a1,b1,a2,b2,a3,b3); cimg::swap(a4,b4); 1.4563 + } 1.4564 + 1.4565 + //! Exchange values of variables (\p a1,\p a2,...,\p a5) and (\p b1,\p b2,...,\p b5). 1.4566 + template<typename T1, typename T2, typename T3, typename T4, typename T5> 1.4567 + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5) { 1.4568 + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4); cimg::swap(a5,b5); 1.4569 + } 1.4570 + 1.4571 + //! Exchange values of variables (\p a1,\p a2,...,\p a6) and (\p b1,\p b2,...,\p b6). 1.4572 + template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> 1.4573 + 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) { 1.4574 + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5); cimg::swap(a6,b6); 1.4575 + } 1.4576 + 1.4577 + //! Exchange values of variables (\p a1,\p a2,...,\p a7) and (\p b1,\p b2,...,\p b7). 1.4578 + template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7> 1.4579 + 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, 1.4580 + T7& a7, T7& b7) { 1.4581 + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6); cimg::swap(a7,b7); 1.4582 + } 1.4583 + 1.4584 + //! Exchange values of variables (\p a1,\p a2,...,\p a8) and (\p b1,\p b2,...,\p b8). 1.4585 + template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> 1.4586 + 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, 1.4587 + T7& a7, T7& b7, T8& a8, T8& b8) { 1.4588 + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6,a7,b7); cimg::swap(a8,b8); 1.4589 + } 1.4590 + 1.4591 + //! Return the current endianness of the CPU. 1.4592 + /** 1.4593 + \return \c false for "Little Endian", \c true for "Big Endian". 1.4594 + **/ 1.4595 + inline bool endianness() { 1.4596 + const int x = 1; 1.4597 + return ((unsigned char*)&x)[0]?false:true; 1.4598 + } 1.4599 + 1.4600 + //! Invert endianness of a memory buffer. 1.4601 + template<typename T> 1.4602 + inline void invert_endianness(T* const buffer, const unsigned int size) { 1.4603 + if (size) switch (sizeof(T)) { 1.4604 + case 1 : break; 1.4605 + case 2 : { for (unsigned short *ptr = (unsigned short*)buffer+size; ptr>(unsigned short*)buffer; ) { 1.4606 + const unsigned short val = *(--ptr); 1.4607 + *ptr = (unsigned short)((val>>8)|((val<<8))); 1.4608 + }} break; 1.4609 + case 4 : { for (unsigned int *ptr = (unsigned int*)buffer+size; ptr>(unsigned int*)buffer; ) { 1.4610 + const unsigned int val = *(--ptr); 1.4611 + *ptr = (val>>24)|((val>>8)&0xff00)|((val<<8)&0xff0000)|(val<<24); 1.4612 + }} break; 1.4613 + default : { for (T* ptr = buffer+size; ptr>buffer; ) { 1.4614 + unsigned char *pb = (unsigned char*)(--ptr), *pe = pb + sizeof(T); 1.4615 + for (int i=0; i<(int)sizeof(T)/2; ++i) swap(*(pb++),*(--pe)); 1.4616 + }} 1.4617 + } 1.4618 + } 1.4619 + 1.4620 + //! Invert endianness of a single variable. 1.4621 + template<typename T> 1.4622 + inline T& invert_endianness(T& a) { 1.4623 + invert_endianness(&a,1); 1.4624 + return a; 1.4625 + } 1.4626 + 1.4627 + //! Get the value of a system timer with a millisecond precision. 1.4628 + inline unsigned long time() { 1.4629 +#if cimg_OS==1 1.4630 + struct timeval st_time; 1.4631 + gettimeofday(&st_time,0); 1.4632 + return (unsigned long)(st_time.tv_usec/1000 + st_time.tv_sec*1000); 1.4633 +#elif cimg_OS==2 1.4634 + static SYSTEMTIME st_time; 1.4635 + GetSystemTime(&st_time); 1.4636 + return (unsigned long)(st_time.wMilliseconds + 1000*(st_time.wSecond + 60*(st_time.wMinute + 60*st_time.wHour))); 1.4637 +#else 1.4638 + return 0; 1.4639 +#endif 1.4640 + } 1.4641 + 1.4642 + //! Sleep for a certain numbers of milliseconds. 1.4643 + /** 1.4644 + This function frees the CPU ressources during the sleeping time. 1.4645 + It may be used to temporize your program properly, without wasting CPU time. 1.4646 + **/ 1.4647 + inline void sleep(const unsigned int milliseconds) { 1.4648 +#if cimg_OS==1 1.4649 + struct timespec tv; 1.4650 + tv.tv_sec = milliseconds/1000; 1.4651 + tv.tv_nsec = (milliseconds%1000)*1000000; 1.4652 + nanosleep(&tv,0); 1.4653 +#elif cimg_OS==2 1.4654 + Sleep(milliseconds); 1.4655 +#endif 1.4656 + } 1.4657 + 1.4658 + inline unsigned int _sleep(const unsigned int milliseconds, unsigned long& timer) { 1.4659 + if (!timer) timer = cimg::time(); 1.4660 + const unsigned long current_time = cimg::time(); 1.4661 + if (current_time>=timer+milliseconds) { timer = current_time; return 0; } 1.4662 + const unsigned long time_diff = timer + milliseconds - current_time; 1.4663 + timer = current_time + time_diff; 1.4664 + cimg::sleep(time_diff); 1.4665 + return (unsigned int)time_diff; 1.4666 + } 1.4667 + 1.4668 + //! Wait for a certain number of milliseconds since the last call. 1.4669 + /** 1.4670 + This function is equivalent to sleep() but the waiting time is computed with regard to the last call 1.4671 + of wait(). It may be used to temporize your program properly. 1.4672 + **/ 1.4673 + inline unsigned int wait(const unsigned int milliseconds) { 1.4674 + static unsigned long timer = 0; 1.4675 + if (!timer) timer = cimg::time(); 1.4676 + return _sleep(milliseconds,timer); 1.4677 + } 1.4678 + 1.4679 + // Use a specific srand initialization to avoid multi-threads to have to the 1.4680 + // same series of random numbers (executed only once for a single program). 1.4681 + inline void srand() { 1.4682 + static bool first_time = true; 1.4683 + if (first_time) { 1.4684 + cimg_std::srand(cimg::time()); 1.4685 + unsigned char *const rand_ptr = new unsigned char[1+cimg_std::rand()%2048]; 1.4686 + cimg_std::srand((unsigned int)cimg_std::rand() + *(unsigned int*)(void*)rand_ptr); 1.4687 + delete[] rand_ptr; 1.4688 + first_time = false; 1.4689 + } 1.4690 + } 1.4691 + 1.4692 + //! Return a left bitwise-rotated number. 1.4693 + template<typename T> 1.4694 + inline const T rol(const T a, const unsigned int n=1) { 1.4695 + return n?(T)((a<<n)|(a>>((sizeof(T)<<3)-n))):a; 1.4696 + } 1.4697 + 1.4698 + //! Return a right bitwise-rotated number. 1.4699 + template<typename T> 1.4700 + inline const T ror(const T a, const unsigned int n=1) { 1.4701 + return n?(T)((a>>n)|(a<<((sizeof(T)<<3)-n))):a; 1.4702 + } 1.4703 + 1.4704 + //! Return the absolute value of a number. 1.4705 + /** 1.4706 + \note This function is different from <tt>std::abs()</tt> or <tt>std::fabs()</tt> 1.4707 + because it is able to consider a variable of any type, without cast needed. 1.4708 + **/ 1.4709 + template<typename T> 1.4710 + inline T abs(const T a) { 1.4711 + return a>=0?a:-a; 1.4712 + } 1.4713 + inline bool abs(const bool a) { 1.4714 + return a; 1.4715 + } 1.4716 + inline unsigned char abs(const unsigned char a) { 1.4717 + return a; 1.4718 + } 1.4719 + inline unsigned short abs(const unsigned short a) { 1.4720 + return a; 1.4721 + } 1.4722 + inline unsigned int abs(const unsigned int a) { 1.4723 + return a; 1.4724 + } 1.4725 + inline unsigned long abs(const unsigned long a) { 1.4726 + return a; 1.4727 + } 1.4728 + inline double abs(const double a) { 1.4729 + return cimg_std::fabs(a); 1.4730 + } 1.4731 + inline float abs(const float a) { 1.4732 + return (float)cimg_std::fabs((double)a); 1.4733 + } 1.4734 + inline int abs(const int a) { 1.4735 + return cimg_std::abs(a); 1.4736 + } 1.4737 + 1.4738 + //! Return the square of a number. 1.4739 + template<typename T> 1.4740 + inline T sqr(const T val) { 1.4741 + return val*val; 1.4742 + } 1.4743 + 1.4744 + //! Return 1 + log_10(x). 1.4745 + inline int xln(const int x) { 1.4746 + return x>0?(int)(1+cimg_std::log10((double)x)):1; 1.4747 + } 1.4748 + 1.4749 + //! Return the minimum value between two numbers. 1.4750 + template<typename t1, typename t2> 1.4751 + inline typename cimg::superset<t1,t2>::type min(const t1& a, const t2& b) { 1.4752 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.4753 + return (t1t2)(a<=b?a:b); 1.4754 + } 1.4755 + 1.4756 + //! Return the minimum value between three numbers. 1.4757 + template<typename t1, typename t2, typename t3> 1.4758 + inline typename cimg::superset2<t1,t2,t3>::type min(const t1& a, const t2& b, const t3& c) { 1.4759 + typedef typename cimg::superset2<t1,t2,t3>::type t1t2t3; 1.4760 + return (t1t2t3)cimg::min(cimg::min(a,b),c); 1.4761 + } 1.4762 + 1.4763 + //! Return the minimum value between four numbers. 1.4764 + template<typename t1, typename t2, typename t3, typename t4> 1.4765 + inline typename cimg::superset3<t1,t2,t3,t4>::type min(const t1& a, const t2& b, const t3& c, const t4& d) { 1.4766 + typedef typename cimg::superset3<t1,t2,t3,t4>::type t1t2t3t4; 1.4767 + return (t1t2t3t4)cimg::min(cimg::min(a,b,c),d); 1.4768 + } 1.4769 + 1.4770 + //! Return the maximum value between two numbers. 1.4771 + template<typename t1, typename t2> 1.4772 + inline typename cimg::superset<t1,t2>::type max(const t1& a, const t2& b) { 1.4773 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.4774 + return (t1t2)(a>=b?a:b); 1.4775 + } 1.4776 + 1.4777 + //! Return the maximum value between three numbers. 1.4778 + template<typename t1, typename t2, typename t3> 1.4779 + inline typename cimg::superset2<t1,t2,t3>::type max(const t1& a, const t2& b, const t3& c) { 1.4780 + typedef typename cimg::superset2<t1,t2,t3>::type t1t2t3; 1.4781 + return (t1t2t3)cimg::max(cimg::max(a,b),c); 1.4782 + } 1.4783 + 1.4784 + //! Return the maximum value between four numbers. 1.4785 + template<typename t1, typename t2, typename t3, typename t4> 1.4786 + inline typename cimg::superset3<t1,t2,t3,t4>::type max(const t1& a, const t2& b, const t3& c, const t4& d) { 1.4787 + typedef typename cimg::superset3<t1,t2,t3,t4>::type t1t2t3t4; 1.4788 + return (t1t2t3t4)cimg::max(cimg::max(a,b,c),d); 1.4789 + } 1.4790 + 1.4791 + //! Return the sign of a number. 1.4792 + template<typename T> 1.4793 + inline T sign(const T x) { 1.4794 + return (x<0)?(T)(-1):(x==0?(T)0:(T)1); 1.4795 + } 1.4796 + 1.4797 + //! Return the nearest power of 2 higher than a given number. 1.4798 + template<typename T> 1.4799 + inline unsigned long nearest_pow2(const T x) { 1.4800 + unsigned long i = 1; 1.4801 + while (x>i) i<<=1; 1.4802 + return i; 1.4803 + } 1.4804 + 1.4805 + //! Return the modulo of a number. 1.4806 + /** 1.4807 + \note This modulo function accepts negative and floating-points modulo numbers, as well as 1.4808 + variable of any type. 1.4809 + **/ 1.4810 + template<typename T> 1.4811 + inline T mod(const T& x, const T& m) { 1.4812 + const double dx = (double)x, dm = (double)m; 1.4813 + if (x<0) { return (T)(dm+dx+dm*cimg_std::floor(-dx/dm)); } 1.4814 + return (T)(dx-dm*cimg_std::floor(dx/dm)); 1.4815 + } 1.4816 + inline int mod(const bool x, const bool m) { 1.4817 + return m?(x?1:0):0; 1.4818 + } 1.4819 + inline int mod(const char x, const char m) { 1.4820 + return x>=0?x%m:(x%m?m+x%m:0); 1.4821 + } 1.4822 + inline int mod(const short x, const short m) { 1.4823 + return x>=0?x%m:(x%m?m+x%m:0); 1.4824 + } 1.4825 + inline int mod(const int x, const int m) { 1.4826 + return x>=0?x%m:(x%m?m+x%m:0); 1.4827 + } 1.4828 + inline int mod(const long x, const long m) { 1.4829 + return x>=0?x%m:(x%m?m+x%m:0); 1.4830 + } 1.4831 + inline int mod(const unsigned char x, const unsigned char m) { 1.4832 + return x%m; 1.4833 + } 1.4834 + inline int mod(const unsigned short x, const unsigned short m) { 1.4835 + return x%m; 1.4836 + } 1.4837 + inline int mod(const unsigned int x, const unsigned int m) { 1.4838 + return x%m; 1.4839 + } 1.4840 + inline int mod(const unsigned long x, const unsigned long m) { 1.4841 + return x%m; 1.4842 + } 1.4843 + 1.4844 + //! Return the minmod of two numbers. 1.4845 + /** 1.4846 + <i>minmod(\p a,\p b)</i> is defined to be : 1.4847 + - <i>minmod(\p a,\p b) = min(\p a,\p b)</i>, if \p a and \p b have the same sign. 1.4848 + - <i>minmod(\p a,\p b) = 0</i>, if \p a and \p b have different signs. 1.4849 + **/ 1.4850 + template<typename T> 1.4851 + inline T minmod(const T a, const T b) { 1.4852 + return a*b<=0?0:(a>0?(a<b?a:b):(a<b?b:a)); 1.4853 + } 1.4854 + 1.4855 + //! Return a random variable between [0,1] with respect to an uniform distribution. 1.4856 + inline double rand() { 1.4857 + static bool first_time = true; 1.4858 + if (first_time) { cimg::srand(); first_time = false; } 1.4859 + return (double)cimg_std::rand()/RAND_MAX; 1.4860 + } 1.4861 + 1.4862 + //! Return a random variable between [-1,1] with respect to an uniform distribution. 1.4863 + inline double crand() { 1.4864 + return 1-2*cimg::rand(); 1.4865 + } 1.4866 + 1.4867 + //! Return a random variable following a gaussian distribution and a standard deviation of 1. 1.4868 + inline double grand() { 1.4869 + double x1, w; 1.4870 + do { 1.4871 + const double x2 = 2*cimg::rand() - 1.0; 1.4872 + x1 = 2*cimg::rand()-1.0; 1.4873 + w = x1*x1 + x2*x2; 1.4874 + } while (w<=0 || w>=1.0); 1.4875 + return x1*cimg_std::sqrt((-2*cimg_std::log(w))/w); 1.4876 + } 1.4877 + 1.4878 + //! Return a random variable following a Poisson distribution of parameter z. 1.4879 + inline unsigned int prand(const double z) { 1.4880 + if (z<=1.0e-10) return 0; 1.4881 + if (z>100.0) return (unsigned int)((std::sqrt(z) * cimg::grand()) + z); 1.4882 + unsigned int k = 0; 1.4883 + const double y = std::exp(-z); 1.4884 + for (double s = 1.0; s>=y; ++k) s*=cimg::rand(); 1.4885 + return k-1; 1.4886 + } 1.4887 + 1.4888 + //! Return a rounded number. 1.4889 + /** 1.4890 + \param x is the number to be rounded. 1.4891 + \param y is the rounding precision. 1.4892 + \param rounding_type defines the type of rounding (0=nearest, -1=backward, 1=forward). 1.4893 + **/ 1.4894 + inline double round(const double x, const double y, const int rounding_type=0) { 1.4895 + if (y<=0) return x; 1.4896 + const double delta = cimg::mod(x,y); 1.4897 + if (delta==0.0) return x; 1.4898 + const double 1.4899 + backward = x - delta, 1.4900 + forward = backward + y; 1.4901 + return rounding_type<0?backward:(rounding_type>0?forward:(2*delta<y?backward:forward)); 1.4902 + } 1.4903 + 1.4904 + inline double _pythagore(double a, double b) { 1.4905 + const double absa = cimg::abs(a), absb = cimg::abs(b); 1.4906 + if (absa>absb) { const double tmp = absb/absa; return absa*cimg_std::sqrt(1.0+tmp*tmp); } 1.4907 + else { const double tmp = absa/absb; return (absb==0?0:absb*cimg_std::sqrt(1.0+tmp*tmp)); } 1.4908 + } 1.4909 + 1.4910 + //! Remove the 'case' of an ASCII character. 1.4911 + inline char uncase(const char x) { 1.4912 + return (char)((x<'A'||x>'Z')?x:x-'A'+'a'); 1.4913 + } 1.4914 + 1.4915 + //! Remove the 'case' of a C string. 1.4916 + /** 1.4917 + Acts in-place. 1.4918 + **/ 1.4919 + inline void uncase(char *const string) { 1.4920 + if (string) for (char *ptr = string; *ptr; ++ptr) *ptr = uncase(*ptr); 1.4921 + } 1.4922 + 1.4923 + //! Read a float number from a C-string. 1.4924 + /** 1.4925 + \note This function is quite similar to <tt>std::atof()</tt>, 1.4926 + but that it allows the retrieval of fractions as in "1/2". 1.4927 + **/ 1.4928 + inline float atof(const char *const str) { 1.4929 + float x = 0,y = 1; 1.4930 + if (!str) return 0; else { cimg_std::sscanf(str,"%g/%g",&x,&y); return x/y; } 1.4931 + } 1.4932 + 1.4933 + //! Compute the length of a C-string. 1.4934 + /** 1.4935 + \note This function is similar to <tt>std::strlen()</tt> 1.4936 + and is here because some old compilers do not 1.4937 + define the <tt>std::</tt> version. 1.4938 + **/ 1.4939 + inline int strlen(const char *const s) { 1.4940 + if (!s) return -1; 1.4941 + int k = 0; 1.4942 + for (const char *ns = s; *ns; ++ns) ++k; 1.4943 + return k; 1.4944 + } 1.4945 + 1.4946 + //! Compare the first \p n characters of two C-strings. 1.4947 + /** 1.4948 + \note This function is similar to <tt>std::strncmp()</tt> 1.4949 + and is here because some old compilers do not 1.4950 + define the <tt>std::</tt> version. 1.4951 + **/ 1.4952 + inline int strncmp(const char *const s1, const char *const s2, const int l) { 1.4953 + if (!s1) return s2?-1:0; 1.4954 + const char *ns1 = s1, *ns2 = s2; 1.4955 + int k, diff = 0; for (k = 0; k<l && !(diff = *ns1-*ns2); ++k) { ++ns1; ++ns2; } 1.4956 + return k!=l?diff:0; 1.4957 + } 1.4958 + 1.4959 + //! Compare the first \p n characters of two C-strings, ignoring the case. 1.4960 + /** 1.4961 + \note This function is similar to <tt>std::strncasecmp()</tt> 1.4962 + and is here because some old compilers do not 1.4963 + define the <tt>std::</tt> version. 1.4964 + **/ 1.4965 + inline int strncasecmp(const char *const s1, const char *const s2, const int l) { 1.4966 + if (!s1) return s2?-1:0; 1.4967 + const char *ns1 = s1, *ns2 = s2; 1.4968 + int k, diff = 0; for (k = 0; k<l && !(diff = uncase(*ns1)-uncase(*ns2)); ++k) { ++ns1; ++ns2; } 1.4969 + return k!=l?diff:0; 1.4970 + } 1.4971 + 1.4972 + //! Compare two C-strings. 1.4973 + /** 1.4974 + \note This function is similar to <tt>std::strcmp()</tt> 1.4975 + and is here because some old compilers do not 1.4976 + define the <tt>std::</tt> version. 1.4977 + **/ 1.4978 + inline int strcmp(const char *const s1, const char *const s2) { 1.4979 + const int l1 = cimg::strlen(s1), l2 = cimg::strlen(s2); 1.4980 + return cimg::strncmp(s1,s2,1+(l1<l2?l1:l2)); 1.4981 + } 1.4982 + 1.4983 + //! Compare two C-strings, ignoring the case. 1.4984 + /** 1.4985 + \note This function is similar to <tt>std::strcasecmp()</tt> 1.4986 + and is here because some old compilers do not 1.4987 + define the <tt>std::</tt> version. 1.4988 + **/ 1.4989 + inline int strcasecmp(const char *const s1, const char *const s2) { 1.4990 + const int l1 = cimg::strlen(s1), l2 = cimg::strlen(s2); 1.4991 + return cimg::strncasecmp(s1,s2,1+(l1<l2?l1:l2)); 1.4992 + } 1.4993 + 1.4994 + //! Find a character in a C-string. 1.4995 + inline int strfind(const char *const s, const char c) { 1.4996 + if (!s) return -1; 1.4997 + int l; for (l = cimg::strlen(s); l>=0 && s[l]!=c; --l) {} 1.4998 + return l; 1.4999 + } 1.5000 + 1.5001 + //! Remove useless delimiters on the borders of a C-string 1.5002 + inline bool strpare(char *const s, const char delimiter=' ', const bool symmetric=false) { 1.5003 + if (!s) return false; 1.5004 + const int l = cimg::strlen(s); 1.5005 + int p, q; 1.5006 + if (symmetric) for (p = 0, q = l-1; p<q && s[p]==delimiter && s[q]==delimiter; ++p) --q; 1.5007 + else { 1.5008 + for (p = 0; p<l && s[p]==delimiter; ) ++p; 1.5009 + for (q = l-1; q>p && s[q]==delimiter; ) --q; 1.5010 + } 1.5011 + const int n = q - p + 1; 1.5012 + if (n!=l) { cimg_std::memmove(s,s+p,n); s[n] = '\0'; return true; } 1.5013 + return false; 1.5014 + } 1.5015 + 1.5016 + //! Remove useless spaces and symmetric delimiters ', " and ` from a C-string. 1.5017 + inline void strclean(char *const s) { 1.5018 + if (!s) return; 1.5019 + strpare(s,' ',false); 1.5020 + for (bool need_iter = true; need_iter; ) { 1.5021 + need_iter = false; 1.5022 + need_iter |= strpare(s,'\'',true); 1.5023 + need_iter |= strpare(s,'\"',true); 1.5024 + need_iter |= strpare(s,'`',true); 1.5025 + } 1.5026 + } 1.5027 + 1.5028 + //! Replace explicit escape sequences '\x' in C-strings (where x in [ntvbrfa?'"0]). 1.5029 + inline void strescape(char *const s) { 1.5030 +#define cimg_strescape(ci,co) case ci: *nd = co; break; 1.5031 + char *ns, *nd; 1.5032 + for (ns = nd = s; *ns; ++ns, ++nd) 1.5033 + if (*ns=='\\') switch (*(++ns)) { 1.5034 + cimg_strescape('n','\n'); 1.5035 + cimg_strescape('t','\t'); 1.5036 + cimg_strescape('v','\v'); 1.5037 + cimg_strescape('b','\b'); 1.5038 + cimg_strescape('r','\r'); 1.5039 + cimg_strescape('f','\f'); 1.5040 + cimg_strescape('a','\a'); 1.5041 + cimg_strescape('\\','\\'); 1.5042 + cimg_strescape('\?','\?'); 1.5043 + cimg_strescape('\'','\''); 1.5044 + cimg_strescape('\"','\"'); 1.5045 + cimg_strescape('\0','\0'); 1.5046 + } 1.5047 + else *nd = *ns; 1.5048 + *nd = 0; 1.5049 + } 1.5050 + 1.5051 + //! Compute the basename of a filename. 1.5052 + inline const char* basename(const char *const s) { 1.5053 + return (cimg_OS!=2)?(s?s+1+cimg::strfind(s,'/'):0):(s?s+1+cimg::strfind(s,'\\'):0); 1.5054 + } 1.5055 + 1.5056 + // Generate a random filename. 1.5057 + inline const char* filenamerand() { 1.5058 + static char id[9] = { 0,0,0,0,0,0,0,0,0 }; 1.5059 + cimg::srand(); 1.5060 + for (unsigned int k=0; k<8; ++k) { 1.5061 + const int v = (int)cimg_std::rand()%3; 1.5062 + id[k] = (char)(v==0?('0'+(cimg_std::rand()%10)):(v==1?('a'+(cimg_std::rand()%26)):('A'+(cimg_std::rand()%26)))); 1.5063 + } 1.5064 + return id; 1.5065 + } 1.5066 + 1.5067 + // Convert filename into a Windows-style filename. 1.5068 + inline void winformat_string(char *const s) { 1.5069 + if (s && s[0]) { 1.5070 +#if cimg_OS==2 1.5071 + char *const ns = new char[MAX_PATH]; 1.5072 + if (GetShortPathNameA(s,ns,MAX_PATH)) cimg_std::strcpy(s,ns); 1.5073 +#endif 1.5074 + } 1.5075 + } 1.5076 + 1.5077 + //! Return or set path to store temporary files. 1.5078 + inline const char* temporary_path(const char *const user_path=0, const bool reinit_path=false) { 1.5079 +#define _cimg_test_temporary_path(p) \ 1.5080 + if (!path_found) { \ 1.5081 + cimg_std::sprintf(st_path,"%s",p); \ 1.5082 + cimg_std::sprintf(tmp,"%s%s%s",st_path,cimg_OS==2?"\\":"/",filetmp); \ 1.5083 + if ((file=cimg_std::fopen(tmp,"wb"))!=0) { cimg_std::fclose(file); cimg_std::remove(tmp); path_found = true; } \ 1.5084 + } 1.5085 + static char *st_path = 0; 1.5086 + if (reinit_path && st_path) { delete[] st_path; st_path = 0; } 1.5087 + if (user_path) { 1.5088 + if (!st_path) st_path = new char[1024]; 1.5089 + cimg_std::memset(st_path,0,1024); 1.5090 + cimg_std::strncpy(st_path,user_path,1023); 1.5091 + } else if (!st_path) { 1.5092 + st_path = new char[1024]; 1.5093 + cimg_std::memset(st_path,0,1024); 1.5094 + bool path_found = false; 1.5095 + char tmp[1024], filetmp[512]; 1.5096 + cimg_std::FILE *file = 0; 1.5097 + cimg_std::sprintf(filetmp,"%s.tmp",cimg::filenamerand()); 1.5098 + char *tmpPath = getenv("TMP"); 1.5099 + if (!tmpPath) { tmpPath = getenv("TEMP"); winformat_string(tmpPath); } 1.5100 + if (tmpPath) _cimg_test_temporary_path(tmpPath); 1.5101 +#if cimg_OS==2 1.5102 + _cimg_test_temporary_path("C:\\WINNT\\Temp"); 1.5103 + _cimg_test_temporary_path("C:\\WINDOWS\\Temp"); 1.5104 + _cimg_test_temporary_path("C:\\Temp"); 1.5105 + _cimg_test_temporary_path("C:"); 1.5106 + _cimg_test_temporary_path("D:\\WINNT\\Temp"); 1.5107 + _cimg_test_temporary_path("D:\\WINDOWS\\Temp"); 1.5108 + _cimg_test_temporary_path("D:\\Temp"); 1.5109 + _cimg_test_temporary_path("D:"); 1.5110 +#else 1.5111 + _cimg_test_temporary_path("/tmp"); 1.5112 + _cimg_test_temporary_path("/var/tmp"); 1.5113 +#endif 1.5114 + if (!path_found) { 1.5115 + st_path[0]='\0'; 1.5116 + cimg_std::strcpy(tmp,filetmp); 1.5117 + if ((file=cimg_std::fopen(tmp,"wb"))!=0) { cimg_std::fclose(file); cimg_std::remove(tmp); path_found = true; } 1.5118 + } 1.5119 + if (!path_found) 1.5120 + throw CImgIOException("cimg::temporary_path() : Unable to find a temporary path accessible for writing\n" 1.5121 + "you have to set the macro 'cimg_temporary_path' to a valid path where you have writing access :\n" 1.5122 + "#define cimg_temporary_path \"path\" (before including 'CImg.h')"); 1.5123 + } 1.5124 + return st_path; 1.5125 + } 1.5126 + 1.5127 + // Return or set path to the "Program files/" directory (windows only). 1.5128 +#if cimg_OS==2 1.5129 + inline const char* programfiles_path(const char *const user_path=0, const bool reinit_path=false) { 1.5130 + static char *st_path = 0; 1.5131 + if (reinit_path && st_path) { delete[] st_path; st_path = 0; } 1.5132 + if (user_path) { 1.5133 + if (!st_path) st_path = new char[1024]; 1.5134 + cimg_std::memset(st_path,0,1024); 1.5135 + cimg_std::strncpy(st_path,user_path,1023); 1.5136 + } else if (!st_path) { 1.5137 + st_path = new char[MAX_PATH]; 1.5138 + cimg_std::memset(st_path,0,MAX_PATH); 1.5139 + // Note : in the following line, 0x26 = CSIDL_PROGRAM_FILES (not defined on every compiler). 1.5140 +#if !defined(__INTEL_COMPILER) 1.5141 + if (!SHGetSpecialFolderPathA(0,st_path,0x0026,false)) { 1.5142 + const char *pfPath = getenv("PROGRAMFILES"); 1.5143 + if (pfPath) cimg_std::strncpy(st_path,pfPath,MAX_PATH-1); 1.5144 + else cimg_std::strcpy(st_path,"C:\\PROGRA~1"); 1.5145 + } 1.5146 +#else 1.5147 + cimg_std::strcpy(st_path,"C:\\PROGRA~1"); 1.5148 +#endif 1.5149 + } 1.5150 + return st_path; 1.5151 + } 1.5152 +#endif 1.5153 + 1.5154 + //! Return or set path to the ImageMagick's \c convert tool. 1.5155 + inline const char* imagemagick_path(const char *const user_path=0, const bool reinit_path=false) { 1.5156 + static char *st_path = 0; 1.5157 + if (reinit_path && st_path) { delete[] st_path; st_path = 0; } 1.5158 + if (user_path) { 1.5159 + if (!st_path) st_path = new char[1024]; 1.5160 + cimg_std::memset(st_path,0,1024); 1.5161 + cimg_std::strncpy(st_path,user_path,1023); 1.5162 + } else if (!st_path) { 1.5163 + st_path = new char[1024]; 1.5164 + cimg_std::memset(st_path,0,1024); 1.5165 + bool path_found = false; 1.5166 + cimg_std::FILE *file = 0; 1.5167 +#if cimg_OS==2 1.5168 + const char *pf_path = programfiles_path(); 1.5169 + if (!path_found) { 1.5170 + cimg_std::sprintf(st_path,".\\convert.exe"); 1.5171 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5172 + } 1.5173 + { for (int k=32; k>=10 && !path_found; --k) { 1.5174 + cimg_std::sprintf(st_path,"%s\\IMAGEM~1.%.2d-\\convert.exe",pf_path,k); 1.5175 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5176 + }} 1.5177 + { for (int k=9; k>=0 && !path_found; --k) { 1.5178 + cimg_std::sprintf(st_path,"%s\\IMAGEM~1.%d-Q\\convert.exe",pf_path,k); 1.5179 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5180 + }} 1.5181 + { for (int k=32; k>=0 && !path_found; --k) { 1.5182 + cimg_std::sprintf(st_path,"%s\\IMAGEM~1.%d\\convert.exe",pf_path,k); 1.5183 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5184 + }} 1.5185 + { for (int k=32; k>=10 && !path_found; --k) { 1.5186 + cimg_std::sprintf(st_path,"%s\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\convert.exe",pf_path,k); 1.5187 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5188 + }} 1.5189 + { for (int k=9; k>=0 && !path_found; --k) { 1.5190 + cimg_std::sprintf(st_path,"%s\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\convert.exe",pf_path,k); 1.5191 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5192 + }} 1.5193 + { for (int k=32; k>=0 && !path_found; --k) { 1.5194 + cimg_std::sprintf(st_path,"%s\\IMAGEM~1.%d\\VISUA~1\\BIN\\convert.exe",pf_path,k); 1.5195 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5196 + }} 1.5197 + { for (int k=32; k>=10 && !path_found; --k) { 1.5198 + cimg_std::sprintf(st_path,"C:\\IMAGEM~1.%.2d-\\convert.exe",k); 1.5199 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5200 + }} 1.5201 + { for (int k=9; k>=0 && !path_found; --k) { 1.5202 + cimg_std::sprintf(st_path,"C:\\IMAGEM~1.%d-Q\\convert.exe",k); 1.5203 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5204 + }} 1.5205 + { for (int k=32; k>=0 && !path_found; --k) { 1.5206 + cimg_std::sprintf(st_path,"C:\\IMAGEM~1.%d\\convert.exe",k); 1.5207 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5208 + }} 1.5209 + { for (int k=32; k>=10 && !path_found; --k) { 1.5210 + cimg_std::sprintf(st_path,"C:\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\convert.exe",k); 1.5211 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5212 + }} 1.5213 + { for (int k=9; k>=0 && !path_found; --k) { 1.5214 + cimg_std::sprintf(st_path,"C:\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\convert.exe",k); 1.5215 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5216 + }} 1.5217 + { for (int k=32; k>=0 && !path_found; --k) { 1.5218 + cimg_std::sprintf(st_path,"C:\\IMAGEM~1.%d\\VISUA~1\\BIN\\convert.exe",k); 1.5219 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5220 + }} 1.5221 + { for (int k=32; k>=10 && !path_found; --k) { 1.5222 + cimg_std::sprintf(st_path,"D:\\IMAGEM~1.%.2d-\\convert.exe",k); 1.5223 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5224 + }} 1.5225 + { for (int k=9; k>=0 && !path_found; --k) { 1.5226 + cimg_std::sprintf(st_path,"D:\\IMAGEM~1.%d-Q\\convert.exe",k); 1.5227 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5228 + }} 1.5229 + { for (int k=32; k>=0 && !path_found; --k) { 1.5230 + cimg_std::sprintf(st_path,"D:\\IMAGEM~1.%d\\convert.exe",k); 1.5231 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5232 + }} 1.5233 + { for (int k=32; k>=10 && !path_found; --k) { 1.5234 + cimg_std::sprintf(st_path,"D:\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\convert.exe",k); 1.5235 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5236 + }} 1.5237 + { for (int k=9; k>=0 && !path_found; --k) { 1.5238 + cimg_std::sprintf(st_path,"D:\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\convert.exe",k); 1.5239 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5240 + }} 1.5241 + { for (int k=32; k>=0 && !path_found; --k) { 1.5242 + cimg_std::sprintf(st_path,"D:\\IMAGEM~1.%d\\VISUA~1\\BIN\\convert.exe",k); 1.5243 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5244 + }} 1.5245 + if (!path_found) cimg_std::strcpy(st_path,"convert.exe"); 1.5246 +#else 1.5247 + if (!path_found) { 1.5248 + cimg_std::sprintf(st_path,"./convert"); 1.5249 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5250 + } 1.5251 + if (!path_found) cimg_std::strcpy(st_path,"convert"); 1.5252 +#endif 1.5253 + winformat_string(st_path); 1.5254 + } 1.5255 + return st_path; 1.5256 + } 1.5257 + 1.5258 + //! Return path of the GraphicsMagick's \c gm tool. 1.5259 + inline const char* graphicsmagick_path(const char *const user_path=0, const bool reinit_path=false) { 1.5260 + static char *st_path = 0; 1.5261 + if (reinit_path && st_path) { delete[] st_path; st_path = 0; } 1.5262 + if (user_path) { 1.5263 + if (!st_path) st_path = new char[1024]; 1.5264 + cimg_std::memset(st_path,0,1024); 1.5265 + cimg_std::strncpy(st_path,user_path,1023); 1.5266 + } else if (!st_path) { 1.5267 + st_path = new char[1024]; 1.5268 + cimg_std::memset(st_path,0,1024); 1.5269 + bool path_found = false; 1.5270 + cimg_std::FILE *file = 0; 1.5271 +#if cimg_OS==2 1.5272 + const char* pf_path = programfiles_path(); 1.5273 + if (!path_found) { 1.5274 + cimg_std::sprintf(st_path,".\\gm.exe"); 1.5275 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5276 + } 1.5277 + { for (int k=32; k>=10 && !path_found; --k) { 1.5278 + cimg_std::sprintf(st_path,"%s\\GRAPHI~1.%.2d-\\gm.exe",pf_path,k); 1.5279 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5280 + }} 1.5281 + { for (int k=9; k>=0 && !path_found; --k) { 1.5282 + cimg_std::sprintf(st_path,"%s\\GRAPHI~1.%d-Q\\gm.exe",pf_path,k); 1.5283 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5284 + }} 1.5285 + { for (int k=32; k>=0 && !path_found; --k) { 1.5286 + cimg_std::sprintf(st_path,"%s\\GRAPHI~1.%d\\gm.exe",pf_path,k); 1.5287 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5288 + }} 1.5289 + { for (int k=32; k>=10 && !path_found; --k) { 1.5290 + cimg_std::sprintf(st_path,"%s\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",pf_path,k); 1.5291 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5292 + }} 1.5293 + { for (int k=9; k>=0 && !path_found; --k) { 1.5294 + cimg_std::sprintf(st_path,"%s\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",pf_path,k); 1.5295 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5296 + }} 1.5297 + { for (int k=32; k>=0 && !path_found; --k) { 1.5298 + cimg_std::sprintf(st_path,"%s\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",pf_path,k); 1.5299 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5300 + }} 1.5301 + { for (int k=32; k>=10 && !path_found; --k) { 1.5302 + cimg_std::sprintf(st_path,"C:\\GRAPHI~1.%.2d-\\gm.exe",k); 1.5303 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5304 + }} 1.5305 + { for (int k=9; k>=0 && !path_found; --k) { 1.5306 + cimg_std::sprintf(st_path,"C:\\GRAPHI~1.%d-Q\\gm.exe",k); 1.5307 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5308 + }} 1.5309 + { for (int k=32; k>=0 && !path_found; --k) { 1.5310 + cimg_std::sprintf(st_path,"C:\\GRAPHI~1.%d\\gm.exe",k); 1.5311 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5312 + }} 1.5313 + { for (int k=32; k>=10 && !path_found; --k) { 1.5314 + cimg_std::sprintf(st_path,"C:\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",k); 1.5315 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5316 + }} 1.5317 + { for (int k=9; k>=0 && !path_found; --k) { 1.5318 + cimg_std::sprintf(st_path,"C:\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",k); 1.5319 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5320 + }} 1.5321 + { for (int k=32; k>=0 && !path_found; --k) { 1.5322 + cimg_std::sprintf(st_path,"C:\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",k); 1.5323 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5324 + }} 1.5325 + { for (int k=32; k>=10 && !path_found; --k) { 1.5326 + cimg_std::sprintf(st_path,"D:\\GRAPHI~1.%.2d-\\gm.exe",k); 1.5327 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5328 + }} 1.5329 + { for (int k=9; k>=0 && !path_found; --k) { 1.5330 + cimg_std::sprintf(st_path,"D:\\GRAPHI~1.%d-Q\\gm.exe",k); 1.5331 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5332 + }} 1.5333 + { for (int k=32; k>=0 && !path_found; --k) { 1.5334 + cimg_std::sprintf(st_path,"D:\\GRAPHI~1.%d\\gm.exe",k); 1.5335 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5336 + }} 1.5337 + { for (int k=32; k>=10 && !path_found; --k) { 1.5338 + cimg_std::sprintf(st_path,"D:\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",k); 1.5339 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5340 + }} 1.5341 + { for (int k=9; k>=0 && !path_found; --k) { 1.5342 + cimg_std::sprintf(st_path,"D:\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",k); 1.5343 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5344 + }} 1.5345 + { for (int k=32; k>=0 && !path_found; --k) { 1.5346 + cimg_std::sprintf(st_path,"D:\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",k); 1.5347 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5348 + }} 1.5349 + if (!path_found) cimg_std::strcpy(st_path,"gm.exe"); 1.5350 +#else 1.5351 + if (!path_found) { 1.5352 + cimg_std::sprintf(st_path,"./gm"); 1.5353 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5354 + } 1.5355 + if (!path_found) cimg_std::strcpy(st_path,"gm"); 1.5356 +#endif 1.5357 + winformat_string(st_path); 1.5358 + } 1.5359 + return st_path; 1.5360 + } 1.5361 + 1.5362 + //! Return or set path of the \c XMedcon tool. 1.5363 + inline const char* medcon_path(const char *const user_path=0, const bool reinit_path=false) { 1.5364 + static char *st_path = 0; 1.5365 + if (reinit_path && st_path) { delete[] st_path; st_path = 0; } 1.5366 + if (user_path) { 1.5367 + if (!st_path) st_path = new char[1024]; 1.5368 + cimg_std::memset(st_path,0,1024); 1.5369 + cimg_std::strncpy(st_path,user_path,1023); 1.5370 + } else if (!st_path) { 1.5371 + st_path = new char[1024]; 1.5372 + cimg_std::memset(st_path,0,1024); 1.5373 + bool path_found = false; 1.5374 + cimg_std::FILE *file = 0; 1.5375 +#if cimg_OS==2 1.5376 + const char* pf_path = programfiles_path(); 1.5377 + if (!path_found) { 1.5378 + cimg_std::sprintf(st_path,".\\medcon.bat"); 1.5379 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5380 + } 1.5381 + if (!path_found) { 1.5382 + cimg_std::sprintf(st_path,".\\medcon.exe"); 1.5383 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5384 + } 1.5385 + if (!path_found) { 1.5386 + cimg_std::sprintf(st_path,"%s\\XMedCon\\bin\\medcon.bat",pf_path); 1.5387 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5388 + } 1.5389 + if (!path_found) { 1.5390 + cimg_std::sprintf(st_path,"%s\\XMedCon\\bin\\medcon.exe",pf_path); 1.5391 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5392 + } 1.5393 + if (!path_found) cimg_std::strcpy(st_path,"medcon.bat"); 1.5394 +#else 1.5395 + if (!path_found) { 1.5396 + cimg_std::sprintf(st_path,"./medcon"); 1.5397 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5398 + } 1.5399 + if (!path_found) cimg_std::strcpy(st_path,"medcon"); 1.5400 +#endif 1.5401 + winformat_string(st_path); 1.5402 + } 1.5403 + return st_path; 1.5404 + } 1.5405 + 1.5406 + //! Return or set path to the 'ffmpeg' command. 1.5407 + inline const char *ffmpeg_path(const char *const user_path=0, const bool reinit_path=false) { 1.5408 + static char *st_path = 0; 1.5409 + if (reinit_path && st_path) { delete[] st_path; st_path = 0; } 1.5410 + if (user_path) { 1.5411 + if (!st_path) st_path = new char[1024]; 1.5412 + cimg_std::memset(st_path,0,1024); 1.5413 + cimg_std::strncpy(st_path,user_path,1023); 1.5414 + } else if (!st_path) { 1.5415 + st_path = new char[1024]; 1.5416 + cimg_std::memset(st_path,0,1024); 1.5417 + bool path_found = false; 1.5418 + cimg_std::FILE *file = 0; 1.5419 +#if cimg_OS==2 1.5420 + if (!path_found) { 1.5421 + cimg_std::sprintf(st_path,".\\ffmpeg.exe"); 1.5422 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5423 + } 1.5424 + if (!path_found) cimg_std::strcpy(st_path,"ffmpeg.exe"); 1.5425 +#else 1.5426 + if (!path_found) { 1.5427 + cimg_std::sprintf(st_path,"./ffmpeg"); 1.5428 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5429 + } 1.5430 + if (!path_found) cimg_std::strcpy(st_path,"ffmpeg"); 1.5431 +#endif 1.5432 + winformat_string(st_path); 1.5433 + } 1.5434 + return st_path; 1.5435 + } 1.5436 + 1.5437 + //! Return or set path to the 'gzip' command. 1.5438 + inline const char *gzip_path(const char *const user_path=0, const bool reinit_path=false) { 1.5439 + static char *st_path = 0; 1.5440 + if (reinit_path && st_path) { delete[] st_path; st_path = 0; } 1.5441 + if (user_path) { 1.5442 + if (!st_path) st_path = new char[1024]; 1.5443 + cimg_std::memset(st_path,0,1024); 1.5444 + cimg_std::strncpy(st_path,user_path,1023); 1.5445 + } else if (!st_path) { 1.5446 + st_path = new char[1024]; 1.5447 + cimg_std::memset(st_path,0,1024); 1.5448 + bool path_found = false; 1.5449 + cimg_std::FILE *file = 0; 1.5450 +#if cimg_OS==2 1.5451 + if (!path_found) { 1.5452 + cimg_std::sprintf(st_path,".\\gzip.exe"); 1.5453 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5454 + } 1.5455 + if (!path_found) cimg_std::strcpy(st_path,"gzip.exe"); 1.5456 +#else 1.5457 + if (!path_found) { 1.5458 + cimg_std::sprintf(st_path,"./gzip"); 1.5459 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5460 + } 1.5461 + if (!path_found) cimg_std::strcpy(st_path,"gzip"); 1.5462 +#endif 1.5463 + winformat_string(st_path); 1.5464 + } 1.5465 + return st_path; 1.5466 + } 1.5467 + 1.5468 + //! Return or set path to the 'gunzip' command. 1.5469 + inline const char *gunzip_path(const char *const user_path=0, const bool reinit_path=false) { 1.5470 + static char *st_path = 0; 1.5471 + if (reinit_path && st_path) { delete[] st_path; st_path = 0; } 1.5472 + if (user_path) { 1.5473 + if (!st_path) st_path = new char[1024]; 1.5474 + cimg_std::memset(st_path,0,1024); 1.5475 + cimg_std::strncpy(st_path,user_path,1023); 1.5476 + } else if (!st_path) { 1.5477 + st_path = new char[1024]; 1.5478 + cimg_std::memset(st_path,0,1024); 1.5479 + bool path_found = false; 1.5480 + cimg_std::FILE *file = 0; 1.5481 +#if cimg_OS==2 1.5482 + if (!path_found) { 1.5483 + cimg_std::sprintf(st_path,".\\gunzip.exe"); 1.5484 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5485 + } 1.5486 + if (!path_found) cimg_std::strcpy(st_path,"gunzip.exe"); 1.5487 +#else 1.5488 + if (!path_found) { 1.5489 + cimg_std::sprintf(st_path,"./gunzip"); 1.5490 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5491 + } 1.5492 + if (!path_found) cimg_std::strcpy(st_path,"gunzip"); 1.5493 +#endif 1.5494 + winformat_string(st_path); 1.5495 + } 1.5496 + return st_path; 1.5497 + } 1.5498 + 1.5499 + //! Return or set path to the 'dcraw' command. 1.5500 + inline const char *dcraw_path(const char *const user_path=0, const bool reinit_path=false) { 1.5501 + static char *st_path = 0; 1.5502 + if (reinit_path && st_path) { delete[] st_path; st_path = 0; } 1.5503 + if (user_path) { 1.5504 + if (!st_path) st_path = new char[1024]; 1.5505 + cimg_std::memset(st_path,0,1024); 1.5506 + cimg_std::strncpy(st_path,user_path,1023); 1.5507 + } else if (!st_path) { 1.5508 + st_path = new char[1024]; 1.5509 + cimg_std::memset(st_path,0,1024); 1.5510 + bool path_found = false; 1.5511 + cimg_std::FILE *file = 0; 1.5512 +#if cimg_OS==2 1.5513 + if (!path_found) { 1.5514 + cimg_std::sprintf(st_path,".\\dcraw.exe"); 1.5515 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5516 + } 1.5517 + if (!path_found) cimg_std::strcpy(st_path,"dcraw.exe"); 1.5518 +#else 1.5519 + if (!path_found) { 1.5520 + cimg_std::sprintf(st_path,"./dcraw"); 1.5521 + if ((file=cimg_std::fopen(st_path,"r"))!=0) { cimg_std::fclose(file); path_found = true; } 1.5522 + } 1.5523 + if (!path_found) cimg_std::strcpy(st_path,"dcraw"); 1.5524 +#endif 1.5525 + winformat_string(st_path); 1.5526 + } 1.5527 + return st_path; 1.5528 + } 1.5529 + 1.5530 + //! Split a filename into two strings 'body' and 'extension'. 1.5531 + inline const char *split_filename(const char *const filename, char *const body=0) { 1.5532 + if (!filename) { if (body) body[0]='\0'; return 0; } 1.5533 + int l = cimg::strfind(filename,'.'); 1.5534 + if (l>=0) { if (body) { cimg_std::strncpy(body,filename,l); body[l]='\0'; }} 1.5535 + else { if (body) cimg_std::strcpy(body,filename); l = (int)cimg::strlen(filename)-1; } 1.5536 + return filename+l+1; 1.5537 + } 1.5538 + 1.5539 + //! Create a numbered version of a filename. 1.5540 + inline char* number_filename(const char *const filename, const int number, const unsigned int n, char *const string) { 1.5541 + if (!filename) { if (string) string[0]='\0'; return 0; } 1.5542 + char format[1024],body[1024]; 1.5543 + const char *ext = cimg::split_filename(filename,body); 1.5544 + if (n>0) cimg_std::sprintf(format,"%s_%%.%ud.%s",body,n,ext); 1.5545 + else cimg_std::sprintf(format,"%s_%%d.%s",body,ext); 1.5546 + cimg_std::sprintf(string,format,number); 1.5547 + return string; 1.5548 + } 1.5549 + 1.5550 + //! Open a file, and check for possible errors. 1.5551 + inline cimg_std::FILE *fopen(const char *const path, const char *const mode) { 1.5552 + if(!path || !mode) 1.5553 + throw CImgArgumentException("cimg::fopen() : File '%s', cannot open with mode '%s'.", 1.5554 + path?path:"(null)",mode?mode:"(null)"); 1.5555 + if (path[0]=='-') return (mode[0]=='r')?stdin:stdout; 1.5556 + cimg_std::FILE *dest = cimg_std::fopen(path,mode); 1.5557 + if (!dest) 1.5558 + throw CImgIOException("cimg::fopen() : File '%s', cannot open file %s", 1.5559 + path,mode[0]=='r'?"for reading.":(mode[0]=='w'?"for writing.":"."),path); 1.5560 + return dest; 1.5561 + } 1.5562 + 1.5563 + //! Close a file, and check for possible errors. 1.5564 + inline int fclose(cimg_std::FILE *file) { 1.5565 + if (!file) warn("cimg::fclose() : Can't close (null) file"); 1.5566 + if (!file || file==stdin || file==stdout) return 0; 1.5567 + const int errn = cimg_std::fclose(file); 1.5568 + if (errn!=0) warn("cimg::fclose() : Error %d during file closing",errn); 1.5569 + return errn; 1.5570 + } 1.5571 + 1.5572 + //! Try to guess the image format of a filename, using its magick numbers. 1.5573 + inline const char *file_type(cimg_std::FILE *const file, const char *const filename) { 1.5574 + static const char 1.5575 + *const _pnm = "pnm", 1.5576 + *const _bmp = "bmp", 1.5577 + *const _gif = "gif", 1.5578 + *const _jpeg = "jpeg", 1.5579 + *const _off = "off", 1.5580 + *const _pan = "pan", 1.5581 + *const _png = "png", 1.5582 + *const _tiff = "tiff"; 1.5583 + if (!filename && !file) throw CImgArgumentException("cimg::file_type() : Cannot load (null) filename."); 1.5584 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); 1.5585 + const char *ftype = 0, *head; 1.5586 + char header[2048], item[1024]; 1.5587 + const unsigned char *const uheader = (unsigned char*)header; 1.5588 + int err; 1.5589 + const unsigned int siz = (unsigned int)cimg_std::fread(header,2048,1,nfile); // Read first 2048 bytes. 1.5590 + if (!file) cimg::fclose(nfile); 1.5591 + if (!ftype) { // Check for BMP format. 1.5592 + if (header[0]=='B' && header[1]=='M') ftype = _bmp; 1.5593 + } 1.5594 + if (!ftype) { // Check for GIF format. 1.5595 + if (header[0]=='G' && header[1]=='I' && header[2]=='F' && header[3]=='8' && header[5]=='a' && 1.5596 + (header[4]=='7' || header[4]=='9')) ftype = _gif; 1.5597 + } 1.5598 + if (!ftype) { // Check for JPEG format. 1.5599 + if (uheader[0]==0xFF && uheader[1]==0xD8 && uheader[2]==0xFF) ftype = _jpeg; 1.5600 + } 1.5601 + if (!ftype) { // Check for OFF format. 1.5602 + if (header[0]=='O' && header[1]=='F' && header[2]=='F' && header[3]=='\n') ftype = _off; 1.5603 + } 1.5604 + if (!ftype) { // Check for PAN format. 1.5605 + if (header[0]=='P' && header[1]=='A' && header[2]=='N' && header[3]=='D' && header[4]=='O' && 1.5606 + header[5]=='R' && header[6]=='E') ftype = _pan; 1.5607 + } 1.5608 + if (!ftype) { // Check for PNG format. 1.5609 + if (uheader[0]==0x89 && uheader[1]==0x50 && uheader[2]==0x4E && uheader[3]==0x47 && 1.5610 + uheader[4]==0x0D && uheader[5]==0x0A && uheader[6]==0x1A && uheader[7]==0x0A) ftype = _png; 1.5611 + } 1.5612 + if (!ftype) { // Check for PNM format. 1.5613 + head = header; 1.5614 + while (head<header+siz && (err=cimg_std::sscanf(head,"%1023[^\n]",item))!=EOF && (item[0]=='#' || !err)) 1.5615 + head+=1+(err?cimg::strlen(item):0); 1.5616 + if (cimg_std::sscanf(item," P%d",&err)==1) ftype = _pnm; 1.5617 + } 1.5618 + if (!ftype) { // Check for TIFF format. 1.5619 + if ((uheader[0]==0x49 && uheader[1]==0x49) || (uheader[0]==0x4D && uheader[1]==0x4D)) ftype = _tiff; 1.5620 + } 1.5621 + return ftype; 1.5622 + } 1.5623 + 1.5624 + //! Read file data, and check for possible errors. 1.5625 + template<typename T> 1.5626 + inline int fread(T *const ptr, const unsigned int nmemb, cimg_std::FILE *stream) { 1.5627 + if (!ptr || nmemb<=0 || !stream) 1.5628 + throw CImgArgumentException("cimg::fread() : Can't read %u x %u bytes of file pointer '%p' in buffer '%p'", 1.5629 + nmemb,sizeof(T),stream,ptr); 1.5630 + const unsigned long wlimitT = 63*1024*1024, wlimit = wlimitT/sizeof(T); 1.5631 + unsigned int toread = nmemb, alread = 0, ltoread = 0, lalread = 0; 1.5632 + do { 1.5633 + ltoread = (toread*sizeof(T))<wlimitT?toread:wlimit; 1.5634 + lalread = (unsigned int)cimg_std::fread((void*)(ptr+alread),sizeof(T),ltoread,stream); 1.5635 + alread+=lalread; 1.5636 + toread-=lalread; 1.5637 + } while (ltoread==lalread && toread>0); 1.5638 + if (toread>0) warn("cimg::fread() : File reading problems, only %u/%u elements read",alread,nmemb); 1.5639 + return alread; 1.5640 + } 1.5641 + 1.5642 + //! Write data to a file, and check for possible errors. 1.5643 + template<typename T> 1.5644 + inline int fwrite(const T *ptr, const unsigned int nmemb, cimg_std::FILE *stream) { 1.5645 + if (!ptr || !stream) 1.5646 + throw CImgArgumentException("cimg::fwrite() : Can't write %u x %u bytes of file pointer '%p' from buffer '%p'", 1.5647 + nmemb,sizeof(T),stream,ptr); 1.5648 + if (nmemb<=0) return 0; 1.5649 + const unsigned long wlimitT = 63*1024*1024, wlimit = wlimitT/sizeof(T); 1.5650 + unsigned int towrite = nmemb, alwrite = 0, ltowrite = 0, lalwrite = 0; 1.5651 + do { 1.5652 + ltowrite = (towrite*sizeof(T))<wlimitT?towrite:wlimit; 1.5653 + lalwrite = (unsigned int)cimg_std::fwrite((void*)(ptr+alwrite),sizeof(T),ltowrite,stream); 1.5654 + alwrite+=lalwrite; 1.5655 + towrite-=lalwrite; 1.5656 + } while (ltowrite==lalwrite && towrite>0); 1.5657 + if (towrite>0) warn("cimg::fwrite() : File writing problems, only %u/%u elements written",alwrite,nmemb); 1.5658 + return alwrite; 1.5659 + } 1.5660 + 1.5661 + inline const char* option(const char *const name, const int argc, const char *const *const argv, 1.5662 + const char *defaut, const char *const usage=0) { 1.5663 + static bool first = true, visu = false; 1.5664 + const char *res = 0; 1.5665 + if (first) { 1.5666 + first=false; 1.5667 + visu = (cimg::option("-h",argc,argv,(char*)0)!=0); 1.5668 + visu |= (cimg::option("-help",argc,argv,(char*)0)!=0); 1.5669 + visu |= (cimg::option("--help",argc,argv,(char*)0)!=0); 1.5670 + } 1.5671 + if (!name && visu) { 1.5672 + if (usage) { 1.5673 + cimg_std::fprintf(cimg_stdout,"\n %s%s%s",cimg::t_red,cimg::basename(argv[0]),cimg::t_normal); 1.5674 + cimg_std::fprintf(cimg_stdout," : %s",usage); 1.5675 + cimg_std::fprintf(cimg_stdout," (%s, %s)\n\n",__DATE__,__TIME__); 1.5676 + } 1.5677 + if (defaut) cimg_std::fprintf(cimg_stdout,"%s\n",defaut); 1.5678 + } 1.5679 + if (name) { 1.5680 + if (argc>0) { 1.5681 + int k = 0; 1.5682 + while (k<argc && cimg::strcmp(argv[k],name)) ++k; 1.5683 + res = (k++==argc?defaut:(k==argc?argv[--k]:argv[k])); 1.5684 + } else res = defaut; 1.5685 + if (visu && usage) cimg_std::fprintf(cimg_stdout," %s%-16s%s %-24s %s%s%s\n", 1.5686 + cimg::t_bold,name,cimg::t_normal,res?res:"0",cimg::t_green,usage,cimg::t_normal); 1.5687 + } 1.5688 + return res; 1.5689 + } 1.5690 + 1.5691 + inline bool option(const char *const name, const int argc, const char *const *const argv, 1.5692 + const bool defaut, const char *const usage=0) { 1.5693 + const char *s = cimg::option(name,argc,argv,(char*)0); 1.5694 + const bool res = s?(cimg::strcasecmp(s,"false") && cimg::strcasecmp(s,"off") && cimg::strcasecmp(s,"0")):defaut; 1.5695 + cimg::option(name,0,0,res?"true":"false",usage); 1.5696 + return res; 1.5697 + } 1.5698 + 1.5699 + inline int option(const char *const name, const int argc, const char *const *const argv, 1.5700 + const int defaut, const char *const usage=0) { 1.5701 + const char *s = cimg::option(name,argc,argv,(char*)0); 1.5702 + const int res = s?cimg_std::atoi(s):defaut; 1.5703 + char tmp[256]; 1.5704 + cimg_std::sprintf(tmp,"%d",res); 1.5705 + cimg::option(name,0,0,tmp,usage); 1.5706 + return res; 1.5707 + } 1.5708 + 1.5709 + inline char option(const char *const name, const int argc, const char *const *const argv, 1.5710 + const char defaut, const char *const usage=0) { 1.5711 + const char *s = cimg::option(name,argc,argv,(char*)0); 1.5712 + const char res = s?s[0]:defaut; 1.5713 + char tmp[8]; 1.5714 + tmp[0] = res; tmp[1] ='\0'; 1.5715 + cimg::option(name,0,0,tmp,usage); 1.5716 + return res; 1.5717 + } 1.5718 + 1.5719 + inline float option(const char *const name, const int argc, const char *const *const argv, 1.5720 + const float defaut, const char *const usage=0) { 1.5721 + const char *s = cimg::option(name,argc,argv,(char*)0); 1.5722 + const float res = s?cimg::atof(s):defaut; 1.5723 + char tmp[256]; 1.5724 + cimg_std::sprintf(tmp,"%g",res); 1.5725 + cimg::option(name,0,0,tmp,usage); 1.5726 + return res; 1.5727 + } 1.5728 + 1.5729 + inline double option(const char *const name, const int argc, const char *const *const argv, 1.5730 + const double defaut, const char *const usage=0) { 1.5731 + const char *s = cimg::option(name,argc,argv,(char*)0); 1.5732 + const double res = s?cimg::atof(s):defaut; 1.5733 + char tmp[256]; 1.5734 + cimg_std::sprintf(tmp,"%g",res); 1.5735 + cimg::option(name,0,0,tmp,usage); 1.5736 + return res; 1.5737 + } 1.5738 + 1.5739 + inline const char* argument(const unsigned int nb, const int argc, const char *const *const argv, const unsigned int nb_singles=0, ...) { 1.5740 + for (int k = 1, pos = 0; k<argc;) { 1.5741 + const char *const item = argv[k]; 1.5742 + bool option = (*item=='-'), single_option = false; 1.5743 + if (option) { 1.5744 + va_list ap; 1.5745 + va_start(ap,nb_singles); 1.5746 + for (unsigned int i=0; i<nb_singles; ++i) if (!cimg::strcasecmp(item,va_arg(ap,char*))) { single_option = true; break; } 1.5747 + va_end(ap); 1.5748 + } 1.5749 + if (option) { ++k; if (!single_option) ++k; } 1.5750 + else { if (pos++==(int)nb) return item; else ++k; } 1.5751 + } 1.5752 + return 0; 1.5753 + } 1.5754 + 1.5755 + //! Print informations about %CImg environement variables. 1.5756 + /** 1.5757 + Printing is done on the standard error output. 1.5758 + **/ 1.5759 + inline void info() { 1.5760 + char tmp[1024] = { 0 }; 1.5761 + cimg_std::fprintf(cimg_stdout,"\n %sCImg Library %u.%u.%u%s, compiled %s ( %s ) with the following flags :\n\n", 1.5762 + cimg::t_red,cimg_version/100,(cimg_version/10)%10,cimg_version%10, 1.5763 + cimg::t_normal,__DATE__,__TIME__); 1.5764 + 1.5765 + cimg_std::fprintf(cimg_stdout," > Operating System : %s%-13s%s %s('cimg_OS'=%d)%s\n", 1.5766 + cimg::t_bold, 1.5767 + cimg_OS==1?"Unix":(cimg_OS==2?"Windows":"Unknow"), 1.5768 + cimg::t_normal,cimg::t_green, 1.5769 + cimg_OS, 1.5770 + cimg::t_normal); 1.5771 + 1.5772 + cimg_std::fprintf(cimg_stdout," > CPU endianness : %s%s Endian%s\n", 1.5773 + cimg::t_bold, 1.5774 + cimg::endianness()?"Big":"Little", 1.5775 + cimg::t_normal); 1.5776 + 1.5777 +#ifdef cimg_use_visualcpp6 1.5778 + cimg_std::fprintf(cimg_stdout," > Using Visual C++ 6.0 : %s%-13s%s %s('cimg_use_visualcpp6' defined)%s\n", 1.5779 + cimg::t_bold,"Yes",cimg::t_normal,cimg::t_green,cimg::t_normal); 1.5780 +#endif 1.5781 + 1.5782 + cimg_std::fprintf(cimg_stdout," > Debug messages : %s%-13s%s %s('cimg_debug'=%d)%s\n", 1.5783 + cimg::t_bold, 1.5784 + cimg_debug==0?"Quiet":(cimg_debug==1?"Console":(cimg_debug==2?"Dialog":(cimg_debug==3?"Console+Warnings":"Dialog+Warnings"))), 1.5785 + cimg::t_normal,cimg::t_green, 1.5786 + cimg_debug, 1.5787 + cimg::t_normal); 1.5788 + 1.5789 + cimg_std::fprintf(cimg_stdout," > Stricts warnings : %s%-13s%s %s('cimg_strict_warnings' %s)%s\n", 1.5790 + cimg::t_bold, 1.5791 +#ifdef cimg_strict_warnings 1.5792 + "Yes",cimg::t_normal,cimg::t_green,"defined", 1.5793 +#else 1.5794 + "No",cimg::t_normal,cimg::t_green,"undefined", 1.5795 +#endif 1.5796 + cimg::t_normal); 1.5797 + 1.5798 + cimg_std::fprintf(cimg_stdout," > Using VT100 messages : %s%-13s%s %s('cimg_use_vt100' %s)%s\n", 1.5799 + cimg::t_bold, 1.5800 +#ifdef cimg_use_vt100 1.5801 + "Yes",cimg::t_normal,cimg::t_green,"defined", 1.5802 +#else 1.5803 + "No",cimg::t_normal,cimg::t_green,"undefined", 1.5804 +#endif 1.5805 + cimg::t_normal); 1.5806 + 1.5807 + cimg_std::fprintf(cimg_stdout," > Display type : %s%-13s%s %s('cimg_display'=%d)%s\n", 1.5808 + cimg::t_bold, 1.5809 + cimg_display==0?"No display": 1.5810 + (cimg_display==1?"X11": 1.5811 + (cimg_display==2?"Windows GDI": 1.5812 + (cimg_display==3?"Carbon":"Unknow"))), 1.5813 + cimg::t_normal,cimg::t_green, 1.5814 + cimg_display, 1.5815 + cimg::t_normal); 1.5816 + 1.5817 +#if cimg_display==1 1.5818 + cimg_std::fprintf(cimg_stdout," > Using XShm for X11 : %s%-13s%s %s('cimg_use_xshm' %s)%s\n", 1.5819 + cimg::t_bold, 1.5820 +#ifdef cimg_use_xshm 1.5821 + "Yes",cimg::t_normal,cimg::t_green,"defined", 1.5822 +#else 1.5823 + "No",cimg::t_normal,cimg::t_green,"undefined", 1.5824 +#endif 1.5825 + cimg::t_normal); 1.5826 + 1.5827 + cimg_std::fprintf(cimg_stdout," > Using XRand for X11 : %s%-13s%s %s('cimg_use_xrandr' %s)%s\n", 1.5828 + cimg::t_bold, 1.5829 +#ifdef cimg_use_xrandr 1.5830 + "Yes",cimg::t_normal,cimg::t_green,"defined", 1.5831 +#else 1.5832 + "No",cimg::t_normal,cimg::t_green,"undefined", 1.5833 +#endif 1.5834 + cimg::t_normal); 1.5835 +#endif 1.5836 + cimg_std::fprintf(cimg_stdout," > Using OpenMP : %s%-13s%s %s('cimg_use_openmp' %s)%s\n", 1.5837 + cimg::t_bold, 1.5838 +#ifdef cimg_use_openmp 1.5839 + "Yes",cimg::t_normal,cimg::t_green,"defined", 1.5840 +#else 1.5841 + "No",cimg::t_normal,cimg::t_green,"undefined", 1.5842 +#endif 1.5843 + cimg::t_normal); 1.5844 + cimg_std::fprintf(cimg_stdout," > Using PNG library : %s%-13s%s %s('cimg_use_png' %s)%s\n", 1.5845 + cimg::t_bold, 1.5846 +#ifdef cimg_use_png 1.5847 + "Yes",cimg::t_normal,cimg::t_green,"defined", 1.5848 +#else 1.5849 + "No",cimg::t_normal,cimg::t_green,"undefined", 1.5850 +#endif 1.5851 + cimg::t_normal); 1.5852 + cimg_std::fprintf(cimg_stdout," > Using JPEG library : %s%-13s%s %s('cimg_use_jpeg' %s)%s\n", 1.5853 + cimg::t_bold, 1.5854 +#ifdef cimg_use_jpeg 1.5855 + "Yes",cimg::t_normal,cimg::t_green,"defined", 1.5856 +#else 1.5857 + "No",cimg::t_normal,cimg::t_green,"undefined", 1.5858 +#endif 1.5859 + cimg::t_normal); 1.5860 + 1.5861 + cimg_std::fprintf(cimg_stdout," > Using TIFF library : %s%-13s%s %s('cimg_use_tiff' %s)%s\n", 1.5862 + cimg::t_bold, 1.5863 +#ifdef cimg_use_tiff 1.5864 + "Yes",cimg::t_normal,cimg::t_green,"defined", 1.5865 +#else 1.5866 + "No",cimg::t_normal,cimg::t_green,"undefined", 1.5867 +#endif 1.5868 + cimg::t_normal); 1.5869 + 1.5870 + cimg_std::fprintf(cimg_stdout," > Using Magick++ library : %s%-13s%s %s('cimg_use_magick' %s)%s\n", 1.5871 + cimg::t_bold, 1.5872 +#ifdef cimg_use_magick 1.5873 + "Yes",cimg::t_normal,cimg::t_green,"defined", 1.5874 +#else 1.5875 + "No",cimg::t_normal,cimg::t_green,"undefined", 1.5876 +#endif 1.5877 + cimg::t_normal); 1.5878 + 1.5879 + cimg_std::fprintf(cimg_stdout," > Using FFTW3 library : %s%-13s%s %s('cimg_use_fftw3' %s)%s\n", 1.5880 + cimg::t_bold, 1.5881 +#ifdef cimg_use_fftw3 1.5882 + "Yes",cimg::t_normal,cimg::t_green,"defined", 1.5883 +#else 1.5884 + "No",cimg::t_normal,cimg::t_green,"undefined", 1.5885 +#endif 1.5886 + cimg::t_normal); 1.5887 + 1.5888 + cimg_std::fprintf(cimg_stdout," > Using LAPACK library : %s%-13s%s %s('cimg_use_lapack' %s)%s\n", 1.5889 + cimg::t_bold, 1.5890 +#ifdef cimg_use_lapack 1.5891 + "Yes",cimg::t_normal,cimg::t_green,"defined", 1.5892 +#else 1.5893 + "No",cimg::t_normal,cimg::t_green,"undefined", 1.5894 +#endif 1.5895 + cimg::t_normal); 1.5896 + 1.5897 + cimg_std::sprintf(tmp,"\"%.1020s\"",cimg::imagemagick_path()); 1.5898 + cimg_std::fprintf(cimg_stdout," > Path of ImageMagick : %s%-13s%s\n", 1.5899 + cimg::t_bold, 1.5900 + tmp, 1.5901 + cimg::t_normal); 1.5902 + 1.5903 + cimg_std::sprintf(tmp,"\"%.1020s\"",cimg::graphicsmagick_path()); 1.5904 + cimg_std::fprintf(cimg_stdout," > Path of GraphicsMagick : %s%-13s%s\n", 1.5905 + cimg::t_bold, 1.5906 + tmp, 1.5907 + cimg::t_normal); 1.5908 + 1.5909 + cimg_std::sprintf(tmp,"\"%.1020s\"",cimg::medcon_path()); 1.5910 + cimg_std::fprintf(cimg_stdout," > Path of 'medcon' : %s%-13s%s\n", 1.5911 + cimg::t_bold, 1.5912 + tmp, 1.5913 + cimg::t_normal); 1.5914 + 1.5915 + cimg_std::sprintf(tmp,"\"%.1020s\"",cimg::temporary_path()); 1.5916 + cimg_std::fprintf(cimg_stdout," > Temporary path : %s%-13s%s\n", 1.5917 + cimg::t_bold, 1.5918 + tmp, 1.5919 + cimg::t_normal); 1.5920 + 1.5921 + cimg_std::fprintf(cimg_stdout,"\n"); 1.5922 + } 1.5923 + 1.5924 + // Declare LAPACK function signatures if necessary. 1.5925 + // 1.5926 +#ifdef cimg_use_lapack 1.5927 + template<typename T> 1.5928 + inline void getrf(int &N, T *lapA, int *IPIV, int &INFO) { 1.5929 + dgetrf_(&N,&N,lapA,&N,IPIV,&INFO); 1.5930 + } 1.5931 + 1.5932 + inline void getrf(int &N, float *lapA, int *IPIV, int &INFO) { 1.5933 + sgetrf_(&N,&N,lapA,&N,IPIV,&INFO); 1.5934 + } 1.5935 + 1.5936 + template<typename T> 1.5937 + inline void getri(int &N, T *lapA, int *IPIV, T* WORK, int &LWORK, int &INFO) { 1.5938 + dgetri_(&N,lapA,&N,IPIV,WORK,&LWORK,&INFO); 1.5939 + } 1.5940 + 1.5941 + inline void getri(int &N, float *lapA, int *IPIV, float* WORK, int &LWORK, int &INFO) { 1.5942 + sgetri_(&N,lapA,&N,IPIV,WORK,&LWORK,&INFO); 1.5943 + } 1.5944 + 1.5945 + template<typename T> 1.5946 + inline void gesvd(char &JOB, int &M, int &N, T *lapA, int &MN, 1.5947 + T *lapS, T *lapU, T *lapV, T *WORK, int &LWORK, int &INFO) { 1.5948 + dgesvd_(&JOB,&JOB,&M,&N,lapA,&MN,lapS,lapU,&M,lapV,&N,WORK,&LWORK,&INFO); 1.5949 + } 1.5950 + 1.5951 + inline void gesvd(char &JOB, int &M, int &N, float *lapA, int &MN, 1.5952 + float *lapS, float *lapU, float *lapV, float *WORK, int &LWORK, int &INFO) { 1.5953 + sgesvd_(&JOB,&JOB,&M,&N,lapA,&MN,lapS,lapU,&M,lapV,&N,WORK,&LWORK,&INFO); 1.5954 + } 1.5955 + 1.5956 + template<typename T> 1.5957 + inline void getrs(char &TRANS, int &N, T *lapA, int *IPIV, T *lapB, int &INFO) { 1.5958 + int one = 1; 1.5959 + dgetrs_(&TRANS,&N,&one,lapA,&N,IPIV,lapB,&N,&INFO); 1.5960 + } 1.5961 + 1.5962 + inline void getrs(char &TRANS, int &N, float *lapA, int *IPIV, float *lapB, int &INFO) { 1.5963 + int one = 1; 1.5964 + sgetrs_(&TRANS,&N,&one,lapA,&N,IPIV,lapB,&N,&INFO); 1.5965 + } 1.5966 + 1.5967 + template<typename T> 1.5968 + inline void syev(char &JOB, char &UPLO, int &N, T *lapA, T *lapW, T *WORK, int &LWORK, int &INFO) { 1.5969 + dsyev_(&JOB,&UPLO,&N,lapA,&N,lapW,WORK,&LWORK,&INFO); 1.5970 + } 1.5971 + 1.5972 + inline void syev(char &JOB, char &UPLO, int &N, float *lapA, float *lapW, float *WORK, int &LWORK, int &INFO) { 1.5973 + ssyev_(&JOB,&UPLO,&N,lapA,&N,lapW,WORK,&LWORK,&INFO); 1.5974 + } 1.5975 +#endif 1.5976 + 1.5977 + // End of the 'cimg' namespace 1.5978 + } 1.5979 + 1.5980 + /*------------------------------------------------ 1.5981 + # 1.5982 + # 1.5983 + # Definition of mathematical operators and 1.5984 + # external functions. 1.5985 + # 1.5986 + # 1.5987 + -------------------------------------------------*/ 1.5988 + // 1.5989 + // These functions are extern to any classes and can be used for a "functional-style" programming, 1.5990 + // such as writting : 1.5991 + // cos(img); 1.5992 + // instead of img.get_cos(); 1.5993 + // 1.5994 + // Note that only the arithmetic operators and functions are implemented here. 1.5995 + // 1.5996 + 1.5997 +#ifdef cimg_use_visualcpp6 1.5998 + template<typename t> 1.5999 + inline CImg<t> operator+(const CImg<t>& img, const t val) { 1.6000 + return CImg<t>(img,false)+=val; 1.6001 + } 1.6002 +#else 1.6003 + template<typename t1, typename t2> 1.6004 + inline CImg<typename cimg::superset<t1,t2>::type> operator+(const CImg<t1>& img, const t2 val) { 1.6005 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6006 + return CImg<t1t2>(img,false)+=val; 1.6007 + } 1.6008 +#endif 1.6009 + 1.6010 +#ifdef cimg_use_visualcpp6 1.6011 + template<typename t> 1.6012 + inline CImg<t> operator+(const t val, const CImg<t>& img) { 1.6013 + return img + val; 1.6014 + } 1.6015 +#else 1.6016 + template<typename t1, typename t2> 1.6017 + inline CImg<typename cimg::superset<t1,t2>::type> operator+(const t1 val, const CImg<t2>& img) { 1.6018 + return img + val; 1.6019 + } 1.6020 +#endif 1.6021 + 1.6022 +#ifdef cimg_use_visualcpp6 1.6023 + template<typename t> 1.6024 + inline CImgList<t> operator+(const CImgList<t>& list, const t val) { 1.6025 + return CImgList<t>(list)+=val; 1.6026 + } 1.6027 +#else 1.6028 + template<typename t1, typename t2> 1.6029 + inline CImgList<typename cimg::superset<t1,t2>::type> operator+(const CImgList<t1>& list, const t2 val) { 1.6030 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6031 + return CImgList<t1t2>(list)+=val; 1.6032 + } 1.6033 +#endif 1.6034 + 1.6035 +#ifdef cimg_use_visualcpp6 1.6036 + template<typename t> 1.6037 + inline CImgList<t> operator+(const t val, const CImgList<t>& list) { 1.6038 + return list + val; 1.6039 + } 1.6040 +#else 1.6041 + template<typename t1, typename t2> 1.6042 + inline CImgList<typename cimg::superset<t1,t2>::type> operator+(const t1 val, const CImgList<t2>& list) { 1.6043 + return list + val; 1.6044 + } 1.6045 +#endif 1.6046 + 1.6047 + template<typename t1, typename t2> 1.6048 + inline CImg<typename cimg::superset<t1,t2>::type> operator+(const CImg<t1>& img1, const CImg<t2>& img2) { 1.6049 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6050 + return CImg<t1t2>(img1,false)+=img2; 1.6051 + } 1.6052 + 1.6053 + template<typename t1, typename t2> 1.6054 + inline CImgList<typename cimg::superset<t1,t2>::type> operator+(const CImg<t1>& img, const CImgList<t2>& list) { 1.6055 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6056 + return CImgList<t1t2>(list)+=img; 1.6057 + } 1.6058 + 1.6059 + template<typename t1, typename t2> 1.6060 + inline CImgList<typename cimg::superset<t1,t2>::type> operator+(const CImgList<t1>& list, const CImg<t2>& img) { 1.6061 + return img + list; 1.6062 + } 1.6063 + 1.6064 + template<typename t1, typename t2> 1.6065 + inline CImgList<typename cimg::superset<t1,t2>::type> operator+(const CImgList<t1>& list1, const CImgList<t2>& list2) { 1.6066 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6067 + return CImgList<t1t2>(list1)+=list2; 1.6068 + } 1.6069 + 1.6070 +#ifdef cimg_use_visualcpp6 1.6071 + template<typename t> 1.6072 + inline CImg<t> operator-(const CImg<t>& img, const t val) { 1.6073 + return CImg<t>(img,false)-=val; 1.6074 + } 1.6075 +#else 1.6076 + template<typename t1, typename t2> 1.6077 + inline CImg<typename cimg::superset<t1,t2>::type> operator-(const CImg<t1>& img, const t2 val) { 1.6078 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6079 + return CImg<t1t2>(img,false)-=val; 1.6080 + } 1.6081 +#endif 1.6082 + 1.6083 +#ifdef cimg_use_visualcpp6 1.6084 + template<typename t> 1.6085 + inline CImg<t> operator-(const t val, const CImg<t>& img) { 1.6086 + return CImg<t>(img.width,img.height,img.depth,img.dim,val)-=img; 1.6087 + } 1.6088 +#else 1.6089 + template<typename t1, typename t2> 1.6090 + inline CImg<typename cimg::superset<t1,t2>::type> operator-(const t1 val, const CImg<t2>& img) { 1.6091 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6092 + return CImg<t1t2>(img.width,img.height,img.depth,img.dim,(t1t2)val)-=img; 1.6093 + } 1.6094 +#endif 1.6095 + 1.6096 +#ifdef cimg_use_visualcpp6 1.6097 + template<typename t> 1.6098 + inline CImgList<t> operator-(const CImgList<t>& list, const t val) { 1.6099 + return CImgList<t>(list)-=val; 1.6100 + } 1.6101 +#else 1.6102 + template<typename t1, typename t2> 1.6103 + inline CImgList<typename cimg::superset<t1,t2>::type> operator-(const CImgList<t1>& list, const t2 val) { 1.6104 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6105 + return CImgList<t1t2>(list)-=val; 1.6106 + } 1.6107 +#endif 1.6108 + 1.6109 +#ifdef cimg_use_visualcpp6 1.6110 + template<typename t> 1.6111 + inline CImgList<double> operator-(const t val, const CImgList<t>& list) { 1.6112 + CImgList<t> res(list.size); 1.6113 + cimglist_for(res,l) res[l] = val - list[l]; 1.6114 + return res; 1.6115 + } 1.6116 +#else 1.6117 + template<typename t1, typename t2> 1.6118 + inline CImgList<typename cimg::superset<t1,t2>::type> operator-(const t1 val, const CImgList<t2>& list) { 1.6119 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6120 + CImgList<t1t2> res(list.size); 1.6121 + cimglist_for(res,l) res[l] = val - list[l]; 1.6122 + return res; 1.6123 + } 1.6124 +#endif 1.6125 + 1.6126 + template<typename t1, typename t2> 1.6127 + inline CImg<typename cimg::superset<t1,t2>::type> operator-(const CImg<t1>& img1, const CImg<t2>& img2) { 1.6128 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6129 + return CImg<t1t2>(img1,false)-=img2; 1.6130 + } 1.6131 + 1.6132 + template<typename t1, typename t2> 1.6133 + inline CImgList<typename cimg::superset<t1,t2>::type> operator-(const CImg<t1>& img, const CImgList<t2>& list) { 1.6134 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6135 + CImgList<t1t2> res(list.size); 1.6136 + cimglist_for(res,l) res[l] = img - list[l]; 1.6137 + return res; 1.6138 + } 1.6139 + 1.6140 + template<typename t1, typename t2> 1.6141 + inline CImgList<typename cimg::superset<t1,t2>::type> operator-(const CImgList<t1>& list, const CImg<t2>& img) { 1.6142 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6143 + return CImgList<t1t2>(list)-=img; 1.6144 + } 1.6145 + 1.6146 + template<typename t1, typename t2> 1.6147 + inline CImgList<typename cimg::superset<t1,t2>::type> operator-(const CImgList<t1>& list1, const CImgList<t2>& list2) { 1.6148 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6149 + return CImgList<t1t2>(list1)-=list2; 1.6150 + } 1.6151 + 1.6152 +#ifdef cimg_use_visualcpp6 1.6153 + template<typename t> 1.6154 + inline CImg<t> operator*(const CImg<t>& img, const double val) { 1.6155 + return CImg<t>(img,false)*=val; 1.6156 + } 1.6157 +#else 1.6158 + template<typename t1, typename t2> 1.6159 + inline CImg<typename cimg::superset<t1,t2>::type> operator*(const CImg<t1>& img, const t2 val) { 1.6160 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6161 + return CImg<t1t2>(img,false)*=val; 1.6162 + } 1.6163 +#endif 1.6164 + 1.6165 +#ifdef cimg_use_visualcpp6 1.6166 + template<typename t> 1.6167 + inline CImg<t> operator*(const double val, const CImg<t>& img) { 1.6168 + return img*val; 1.6169 + } 1.6170 +#else 1.6171 + template<typename t1, typename t2> 1.6172 + inline CImg<typename cimg::superset<t1,t2>::type> operator*(const t1 val, const CImg<t2>& img) { 1.6173 + return img*val; 1.6174 + } 1.6175 +#endif 1.6176 + 1.6177 +#ifdef cimg_use_visualcpp6 1.6178 + template<typename t> 1.6179 + inline CImgList<t> operator*(const CImgList<t>& list, const double val) { 1.6180 + return CImgList<t>(list)*=val; 1.6181 + } 1.6182 +#else 1.6183 + template<typename t1, typename t2> 1.6184 + inline CImgList<typename cimg::superset<t1,t2>::type> operator*(const CImgList<t1>& list, const t2 val) { 1.6185 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6186 + return CImgList<t1t2>(list)*=val; 1.6187 + } 1.6188 +#endif 1.6189 + 1.6190 +#ifdef cimg_use_visualcpp6 1.6191 + template<typename t> 1.6192 + inline CImgList<t> operator*(const double val, const CImgList<t>& list) { 1.6193 + return list*val; 1.6194 + } 1.6195 +#else 1.6196 + template<typename t1, typename t2> 1.6197 + inline CImgList<typename cimg::superset<t1,t2>::type> operator*(const t1 val, const CImgList<t2>& list) { 1.6198 + return list*val; 1.6199 + } 1.6200 +#endif 1.6201 + 1.6202 + template<typename t1, typename t2> 1.6203 + inline CImg<typename cimg::superset<t1,t2>::type> operator*(const CImg<t1>& img1, const CImg<t2>& img2) { 1.6204 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6205 + if (img1.width!=img2.height) 1.6206 + throw CImgArgumentException("operator*() : can't multiply a matrix (%ux%u) by a matrix (%ux%u)", 1.6207 + img1.width,img1.height,img2.width,img2.height); 1.6208 + CImg<t1t2> res(img2.width,img1.height); 1.6209 + t1t2 val; 1.6210 +#ifdef cimg_use_openmp 1.6211 +#pragma omp parallel for if (img1.size()>=1000 && img2.size()>=1000) private(val) 1.6212 +#endif 1.6213 + cimg_forXY(res,i,j) { val = 0; cimg_forX(img1,k) val+=img1(k,j)*img2(i,k); res(i,j) = val; } 1.6214 + return res; 1.6215 + } 1.6216 + 1.6217 + template<typename t1, typename t2> 1.6218 + inline CImgList<typename cimg::superset<t1,t2>::type> operator*(const CImg<t1>& img, const CImgList<t2>& list) { 1.6219 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6220 + CImgList<t1t2> res(list.size); 1.6221 + cimglist_for(res,l) res[l] = img*list[l]; 1.6222 + return res; 1.6223 + } 1.6224 + 1.6225 + template<typename t1, typename t2> 1.6226 + inline CImgList<typename cimg::superset<t1,t2>::type> operator*(const CImgList<t1>& list, const CImg<t2>& img) { 1.6227 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6228 + CImgList<t1t2> res(list.size); 1.6229 + cimglist_for(res,l) res[l] = list[l]*img; 1.6230 + return res; 1.6231 + } 1.6232 + 1.6233 + template<typename t1, typename t2> 1.6234 + inline CImgList<typename cimg::superset<t1,t2>::type> operator*(const CImgList<t1>& list1, const CImgList<t2>& list2) { 1.6235 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6236 + CImgList<t1t2> res(cimg::min(list1.size,list2.size)); 1.6237 + cimglist_for(res,l) res[l] = list1[l]*list2[l]; 1.6238 + return res; 1.6239 + } 1.6240 + 1.6241 +#ifdef cimg_use_visualcpp6 1.6242 + template<typename t> 1.6243 + inline CImg<t> operator/(const CImg<t>& img, const double val) { 1.6244 + return CImg<t>(img,false)/=val; 1.6245 + } 1.6246 +#else 1.6247 + template<typename t1, typename t2> 1.6248 + inline CImg<typename cimg::superset<t1,t2>::type> operator/(const CImg<t1>& img, const t2 val) { 1.6249 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6250 + return CImg<t1t2>(img,false)/=val; 1.6251 + } 1.6252 +#endif 1.6253 + 1.6254 +#ifdef cimg_use_visualcpp6 1.6255 + template<typename t> 1.6256 + inline CImg<t> operator/(const double val, CImg<t>& img) { 1.6257 + return val*img.get_invert(); 1.6258 + } 1.6259 +#else 1.6260 + template<typename t1, typename t2> 1.6261 + inline CImg<typename cimg::superset<t1,t2>::type> operator/(const t1 val, CImg<t2>& img) { 1.6262 + return val*img.get_invert(); 1.6263 + } 1.6264 +#endif 1.6265 + 1.6266 +#ifdef cimg_use_visualcpp6 1.6267 + template<typename t> 1.6268 + inline CImgList<t> operator/(const CImgList<t>& list, const double val) { 1.6269 + return CImgList<t>(list)/=val; 1.6270 + } 1.6271 +#else 1.6272 + template<typename t1, typename t2> 1.6273 + inline CImgList<typename cimg::superset<t1,t2>::type> operator/(const CImgList<t1>& list, const t2 val) { 1.6274 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6275 + return CImgList<t1t2>(list)/=val; 1.6276 + } 1.6277 +#endif 1.6278 + 1.6279 +#ifdef cimg_use_visualcpp6 1.6280 + template<typename t> 1.6281 + inline CImgList<t> operator/(const double val, const CImgList<t>& list) { 1.6282 + CImgList<t> res(list.size); 1.6283 + cimglist_for(res,l) res[l] = val/list[l]; 1.6284 + return res; 1.6285 + } 1.6286 +#else 1.6287 + template<typename t1, typename t2> 1.6288 + inline CImgList<typename cimg::superset<t1,t2>::type> operator/(const t1 val, const CImgList<t2>& list) { 1.6289 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6290 + CImgList<t1t2> res(list.size); 1.6291 + cimglist_for(res,l) res[l] = val/list[l]; 1.6292 + return res; 1.6293 + } 1.6294 +#endif 1.6295 + 1.6296 + template<typename t1, typename t2> 1.6297 + inline CImg<typename cimg::superset<t1,t2>::type> operator/(const CImg<t1>& img1, const CImg<t2>& img2) { 1.6298 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6299 + return CImg<t1t2>(img1,false)*=img2.get_invert(); 1.6300 + } 1.6301 + 1.6302 + template<typename t1, typename t2> 1.6303 + inline CImg<typename cimg::superset<t1,t2>::type> operator/(const CImg<t1>& img, const CImgList<t2>& list) { 1.6304 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6305 + CImgList<t1t2> res(list.size); 1.6306 + cimglist_for(res,l) res[l] = img/list[l]; 1.6307 + return res; 1.6308 + } 1.6309 + 1.6310 + template<typename t1, typename t2> 1.6311 + inline CImgList<typename cimg::superset<t1,t2>::type> operator/(const CImgList<t1>& list, const CImg<t2>& img) { 1.6312 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6313 + return CImgList<t1t2>(list)/=img; 1.6314 + } 1.6315 + 1.6316 + template<typename t1, typename t2> 1.6317 + inline CImgList<typename cimg::superset<t1,t2>::type> operator/(const CImgList<t1>& list1, const CImgList<t2>& list2) { 1.6318 + typedef typename cimg::superset<t1,t2>::type t1t2; 1.6319 + return CImgList<t1t2>(list1)/=list2; 1.6320 + } 1.6321 + 1.6322 + template<typename T> 1.6323 + inline CImg<_cimg_Tfloat> sqr(const CImg<T>& instance) { 1.6324 + return instance.get_sqr(); 1.6325 + } 1.6326 + 1.6327 + template<typename T> 1.6328 + inline CImg<_cimg_Tfloat> sqrt(const CImg<T>& instance) { 1.6329 + return instance.get_sqrt(); 1.6330 + } 1.6331 + 1.6332 + template<typename T> 1.6333 + inline CImg<_cimg_Tfloat> exp(const CImg<T>& instance) { 1.6334 + return instance.get_exp(); 1.6335 + } 1.6336 + 1.6337 + template<typename T> 1.6338 + inline CImg<_cimg_Tfloat> log(const CImg<T>& instance) { 1.6339 + return instance.get_log(); 1.6340 + } 1.6341 + 1.6342 + template<typename T> 1.6343 + inline CImg<_cimg_Tfloat> log10(const CImg<T>& instance) { 1.6344 + return instance.get_log10(); 1.6345 + } 1.6346 + 1.6347 + template<typename T> 1.6348 + inline CImg<_cimg_Tfloat> abs(const CImg<T>& instance) { 1.6349 + return instance.get_abs(); 1.6350 + } 1.6351 + 1.6352 + template<typename T> 1.6353 + inline CImg<_cimg_Tfloat> cos(const CImg<T>& instance) { 1.6354 + return instance.get_cos(); 1.6355 + } 1.6356 + 1.6357 + template<typename T> 1.6358 + inline CImg<_cimg_Tfloat> sin(const CImg<T>& instance) { 1.6359 + return instance.get_sin(); 1.6360 + } 1.6361 + 1.6362 + template<typename T> 1.6363 + inline CImg<_cimg_Tfloat> tan(const CImg<T>& instance) { 1.6364 + return instance.get_tan(); 1.6365 + } 1.6366 + 1.6367 + template<typename T> 1.6368 + inline CImg<_cimg_Tfloat> acos(const CImg<T>& instance) { 1.6369 + return instance.get_acos(); 1.6370 + } 1.6371 + 1.6372 + template<typename T> 1.6373 + inline CImg<_cimg_Tfloat> asin(const CImg<T>& instance) { 1.6374 + return instance.get_asin(); 1.6375 + } 1.6376 + 1.6377 + template<typename T> 1.6378 + inline CImg<_cimg_Tfloat> atan(const CImg<T>& instance) { 1.6379 + return instance.get_atan(); 1.6380 + } 1.6381 + 1.6382 + template<typename T> 1.6383 + inline CImg<T> transpose(const CImg<T>& instance) { 1.6384 + return instance.get_transpose(); 1.6385 + } 1.6386 + 1.6387 + template<typename T> 1.6388 + inline CImg<_cimg_Tfloat> invert(const CImg<T>& instance) { 1.6389 + return instance.get_invert(); 1.6390 + } 1.6391 + 1.6392 + template<typename T> 1.6393 + inline CImg<_cimg_Tfloat> pseudoinvert(const CImg<T>& instance) { 1.6394 + return instance.get_pseudoinvert(); 1.6395 + } 1.6396 + 1.6397 + /*------------------------------------------- 1.6398 + # 1.6399 + # 1.6400 + # 1.6401 + # Definition of the CImgDisplay structure 1.6402 + # 1.6403 + # 1.6404 + # 1.6405 + --------------------------------------------*/ 1.6406 + 1.6407 + //! This class represents a window which can display \ref CImg images and handles mouse and keyboard events. 1.6408 + /** 1.6409 + Creating a \c CImgDisplay instance opens a window that can be used to display a \c CImg<T> image 1.6410 + of a \c CImgList<T> image list inside. When a display is created, associated window events 1.6411 + (such as mouse motion, keyboard and window size changes) are handled and can be easily 1.6412 + detected by testing specific \c CImgDisplay data fields. 1.6413 + See \ref cimg_displays for a complete tutorial on using the \c CImgDisplay class. 1.6414 + **/ 1.6415 + 1.6416 + struct CImgDisplay { 1.6417 + 1.6418 + //! Width of the display 1.6419 + unsigned int width; 1.6420 + 1.6421 + //! Height of the display 1.6422 + unsigned int height; 1.6423 + 1.6424 + //! Normalization type used for the display 1.6425 + unsigned int normalization; 1.6426 + 1.6427 + //! Display title 1.6428 + char* title; 1.6429 + 1.6430 + //! X-pos of the display on the screen 1.6431 + volatile int window_x; 1.6432 + 1.6433 + //! Y-pos of the display on the screen 1.6434 + volatile int window_y; 1.6435 + 1.6436 + //! Width of the underlying window 1.6437 + volatile unsigned int window_width; 1.6438 + 1.6439 + //! Height of the underlying window 1.6440 + volatile unsigned int window_height; 1.6441 + 1.6442 + //! X-coordinate of the mouse pointer on the display 1.6443 + volatile int mouse_x; 1.6444 + 1.6445 + //! Y-coordinate of the mouse pointer on the display 1.6446 + volatile int mouse_y; 1.6447 + 1.6448 + //! Button state of the mouse 1.6449 + volatile unsigned int buttons[512]; 1.6450 + volatile unsigned int& button; 1.6451 + 1.6452 + //! Wheel state of the mouse 1.6453 + volatile int wheel; 1.6454 + 1.6455 + //! Key value if pressed 1.6456 + volatile unsigned int& key; 1.6457 + volatile unsigned int keys[512]; 1.6458 + 1.6459 + //! Key value if released 1.6460 + volatile unsigned int& released_key; 1.6461 + volatile unsigned int released_keys[512]; 1.6462 + 1.6463 + //! Closed state of the window 1.6464 + volatile bool is_closed; 1.6465 + 1.6466 + //! Resized state of the window 1.6467 + volatile bool is_resized; 1.6468 + 1.6469 + //! Moved state of the window 1.6470 + volatile bool is_moved; 1.6471 + 1.6472 + //! Event state of the window 1.6473 + volatile bool is_event; 1.6474 + 1.6475 + //! Current state of the corresponding key (exists for all referenced keys). 1.6476 + volatile bool is_keyESC; 1.6477 + volatile bool is_keyF1; 1.6478 + volatile bool is_keyF2; 1.6479 + volatile bool is_keyF3; 1.6480 + volatile bool is_keyF4; 1.6481 + volatile bool is_keyF5; 1.6482 + volatile bool is_keyF6; 1.6483 + volatile bool is_keyF7; 1.6484 + volatile bool is_keyF8; 1.6485 + volatile bool is_keyF9; 1.6486 + volatile bool is_keyF10; 1.6487 + volatile bool is_keyF11; 1.6488 + volatile bool is_keyF12; 1.6489 + volatile bool is_keyPAUSE; 1.6490 + volatile bool is_key1; 1.6491 + volatile bool is_key2; 1.6492 + volatile bool is_key3; 1.6493 + volatile bool is_key4; 1.6494 + volatile bool is_key5; 1.6495 + volatile bool is_key6; 1.6496 + volatile bool is_key7; 1.6497 + volatile bool is_key8; 1.6498 + volatile bool is_key9; 1.6499 + volatile bool is_key0; 1.6500 + volatile bool is_keyBACKSPACE; 1.6501 + volatile bool is_keyINSERT; 1.6502 + volatile bool is_keyHOME; 1.6503 + volatile bool is_keyPAGEUP; 1.6504 + volatile bool is_keyTAB; 1.6505 + volatile bool is_keyQ; 1.6506 + volatile bool is_keyW; 1.6507 + volatile bool is_keyE; 1.6508 + volatile bool is_keyR; 1.6509 + volatile bool is_keyT; 1.6510 + volatile bool is_keyY; 1.6511 + volatile bool is_keyU; 1.6512 + volatile bool is_keyI; 1.6513 + volatile bool is_keyO; 1.6514 + volatile bool is_keyP; 1.6515 + volatile bool is_keyDELETE; 1.6516 + volatile bool is_keyEND; 1.6517 + volatile bool is_keyPAGEDOWN; 1.6518 + volatile bool is_keyCAPSLOCK; 1.6519 + volatile bool is_keyA; 1.6520 + volatile bool is_keyS; 1.6521 + volatile bool is_keyD; 1.6522 + volatile bool is_keyF; 1.6523 + volatile bool is_keyG; 1.6524 + volatile bool is_keyH; 1.6525 + volatile bool is_keyJ; 1.6526 + volatile bool is_keyK; 1.6527 + volatile bool is_keyL; 1.6528 + volatile bool is_keyENTER; 1.6529 + volatile bool is_keySHIFTLEFT; 1.6530 + volatile bool is_keyZ; 1.6531 + volatile bool is_keyX; 1.6532 + volatile bool is_keyC; 1.6533 + volatile bool is_keyV; 1.6534 + volatile bool is_keyB; 1.6535 + volatile bool is_keyN; 1.6536 + volatile bool is_keyM; 1.6537 + volatile bool is_keySHIFTRIGHT; 1.6538 + volatile bool is_keyARROWUP; 1.6539 + volatile bool is_keyCTRLLEFT; 1.6540 + volatile bool is_keyAPPLEFT; 1.6541 + volatile bool is_keyALT; 1.6542 + volatile bool is_keySPACE; 1.6543 + volatile bool is_keyALTGR; 1.6544 + volatile bool is_keyAPPRIGHT; 1.6545 + volatile bool is_keyMENU; 1.6546 + volatile bool is_keyCTRLRIGHT; 1.6547 + volatile bool is_keyARROWLEFT; 1.6548 + volatile bool is_keyARROWDOWN; 1.6549 + volatile bool is_keyARROWRIGHT; 1.6550 + volatile bool is_keyPAD0; 1.6551 + volatile bool is_keyPAD1; 1.6552 + volatile bool is_keyPAD2; 1.6553 + volatile bool is_keyPAD3; 1.6554 + volatile bool is_keyPAD4; 1.6555 + volatile bool is_keyPAD5; 1.6556 + volatile bool is_keyPAD6; 1.6557 + volatile bool is_keyPAD7; 1.6558 + volatile bool is_keyPAD8; 1.6559 + volatile bool is_keyPAD9; 1.6560 + volatile bool is_keyPADADD; 1.6561 + volatile bool is_keyPADSUB; 1.6562 + volatile bool is_keyPADMUL; 1.6563 + volatile bool is_keyPADDIV; 1.6564 + 1.6565 + //! Fullscreen state of the display 1.6566 + bool is_fullscreen; 1.6567 + 1.6568 + float fps_fps, min, max; 1.6569 + unsigned long timer, fps_frames, fps_timer; 1.6570 + 1.6571 +#ifdef cimgdisplay_plugin 1.6572 +#include cimgdisplay_plugin 1.6573 +#endif 1.6574 +#ifdef cimgdisplay_plugin1 1.6575 +#include cimgdisplay_plugin1 1.6576 +#endif 1.6577 +#ifdef cimgdisplay_plugin2 1.6578 +#include cimgdisplay_plugin2 1.6579 +#endif 1.6580 +#ifdef cimgdisplay_plugin3 1.6581 +#include cimgdisplay_plugin3 1.6582 +#endif 1.6583 +#ifdef cimgdisplay_plugin4 1.6584 +#include cimgdisplay_plugin4 1.6585 +#endif 1.6586 +#ifdef cimgdisplay_plugin5 1.6587 +#include cimgdisplay_plugin5 1.6588 +#endif 1.6589 +#ifdef cimgdisplay_plugin6 1.6590 +#include cimgdisplay_plugin6 1.6591 +#endif 1.6592 +#ifdef cimgdisplay_plugin7 1.6593 +#include cimgdisplay_plugin7 1.6594 +#endif 1.6595 +#ifdef cimgdisplay_plugin8 1.6596 +#include cimgdisplay_plugin8 1.6597 +#endif 1.6598 + 1.6599 + //! Create an empty display window. 1.6600 + CImgDisplay(): 1.6601 + width(0),height(0),normalization(0),title(0), 1.6602 + window_x(0),window_y(0),window_width(0),window_height(0), 1.6603 + mouse_x(0),mouse_y(0),button(*buttons),wheel(0),key(*keys),released_key(*released_keys), 1.6604 + is_closed(true),is_resized(false),is_moved(false),is_event(false),is_fullscreen(false), 1.6605 + min(0),max(0) {} 1.6606 + 1.6607 + //! Create a display window with a specified size \p pwidth x \p height. 1.6608 + /** \param dimw Width of the display window. 1.6609 + \param dimh Height of the display window. 1.6610 + \param title Title of the display window. 1.6611 + \param normalization_type Normalization type of the display window (0=none, 1=always, 2=once). 1.6612 + \param fullscreen_flag : Fullscreen mode. 1.6613 + \param closed_flag : Initially visible mode. 1.6614 + A black image will be initially displayed in the display window. 1.6615 + **/ 1.6616 + CImgDisplay(const unsigned int dimw, const unsigned int dimh, const char *title=0, 1.6617 + const unsigned int normalization_type=3, 1.6618 + const bool fullscreen_flag=false, const bool closed_flag=false): 1.6619 + width(0),height(0),normalization(0),title(0), 1.6620 + window_x(0),window_y(0),window_width(0),window_height(0), 1.6621 + mouse_x(0),mouse_y(0),button(*buttons),wheel(0),key(*keys),released_key(*released_keys), 1.6622 + is_closed(true),is_resized(false),is_moved(false),is_event(false),is_fullscreen(false), 1.6623 + min(0),max(0) { 1.6624 + assign(dimw,dimh,title,normalization_type,fullscreen_flag,closed_flag); 1.6625 + } 1.6626 + 1.6627 + //! Create a display window from an image. 1.6628 + /** \param img : Image that will be used to create the display window. 1.6629 + \param title : Title of the display window 1.6630 + \param normalization_type : Normalization type of the display window. 1.6631 + \param fullscreen_flag : Fullscreen mode. 1.6632 + \param closed_flag : Initially visible mode. 1.6633 + **/ 1.6634 + template<typename T> 1.6635 + CImgDisplay(const CImg<T>& img, const char *title=0, 1.6636 + const unsigned int normalization_type=3, 1.6637 + const bool fullscreen_flag=false, const bool closed_flag=false): 1.6638 + width(0),height(0),normalization(0),title(0), 1.6639 + window_x(0),window_y(0),window_width(0),window_height(0), 1.6640 + mouse_x(0),mouse_y(0),button(*buttons),wheel(0),key(*keys),released_key(*released_keys), 1.6641 + is_closed(true),is_resized(false),is_moved(false),is_event(false),is_fullscreen(false),min(0),max(0) { 1.6642 + assign(img,title,normalization_type,fullscreen_flag,closed_flag); 1.6643 + } 1.6644 + 1.6645 + //! Create a display window from an image list. 1.6646 + /** \param list : The list of images to display. 1.6647 + \param title : Title of the display window 1.6648 + \param normalization_type : Normalization type of the display window. 1.6649 + \param fullscreen_flag : Fullscreen mode. 1.6650 + \param closed_flag : Initially visible mode. 1.6651 + **/ 1.6652 + template<typename T> 1.6653 + CImgDisplay(const CImgList<T>& list, const char *title=0, 1.6654 + const unsigned int normalization_type=3, 1.6655 + const bool fullscreen_flag=false, const bool closed_flag=false): 1.6656 + width(0),height(0),normalization(0),title(0), 1.6657 + window_x(0),window_y(0),window_width(0),window_height(0), 1.6658 + mouse_x(0),mouse_y(0),button(*buttons),wheel(0),key(*keys),released_key(*released_keys), 1.6659 + is_closed(true),is_resized(false),is_moved(false),is_event(false),is_fullscreen(false),min(0),max(0) { 1.6660 + assign(list,title,normalization_type,fullscreen_flag,closed_flag); 1.6661 + } 1.6662 + 1.6663 + //! Create a display window by copying another one. 1.6664 + /** 1.6665 + \param disp : Display window to copy. 1.6666 + **/ 1.6667 + CImgDisplay(const CImgDisplay& disp): 1.6668 + width(0),height(0),normalization(0),title(0), 1.6669 + window_x(0),window_y(0),window_width(0),window_height(0), 1.6670 + mouse_x(0),mouse_y(0),button(*buttons),wheel(0),key(*keys),released_key(*released_keys), 1.6671 + is_closed(true),is_resized(false),is_moved(false),is_event(false),is_fullscreen(false),min(0),max(0) { 1.6672 + assign(disp); 1.6673 + } 1.6674 + 1.6675 + //! Destructor. 1.6676 + ~CImgDisplay() { 1.6677 + assign(); 1.6678 + } 1.6679 + 1.6680 + //! Assignment operator. 1.6681 + CImgDisplay& operator=(const CImgDisplay& disp) { 1.6682 + return assign(disp); 1.6683 + } 1.6684 + 1.6685 + //! Return true is display is empty. 1.6686 + bool is_empty() const { 1.6687 + return (!width || !height); 1.6688 + } 1.6689 + 1.6690 + //! Return true if display is not empty. 1.6691 + operator bool() const { 1.6692 + return !is_empty(); 1.6693 + } 1.6694 + 1.6695 + //! Return display width. 1.6696 + int dimx() const { 1.6697 + return (int)width; 1.6698 + } 1.6699 + 1.6700 + //! Return display height. 1.6701 + int dimy() const { 1.6702 + return (int)height; 1.6703 + } 1.6704 + 1.6705 + //! Return display window width. 1.6706 + int window_dimx() const { 1.6707 + return (int)window_width; 1.6708 + } 1.6709 + 1.6710 + //! Return display window height. 1.6711 + int window_dimy() const { 1.6712 + return (int)window_height; 1.6713 + } 1.6714 + 1.6715 + //! Return X-coordinate of the window. 1.6716 + int window_posx() const { 1.6717 + return window_x; 1.6718 + } 1.6719 + 1.6720 + //! Return Y-coordinate of the window. 1.6721 + int window_posy() const { 1.6722 + return window_y; 1.6723 + } 1.6724 + 1.6725 + //! Synchronized waiting function. Same as cimg::wait(). 1.6726 + CImgDisplay& wait(const unsigned int milliseconds) { 1.6727 + cimg::_sleep(milliseconds,timer); 1.6728 + return *this; 1.6729 + } 1.6730 + 1.6731 + //! Wait for an event occuring on the current display. 1.6732 + CImgDisplay& wait() { 1.6733 + if (!is_empty()) wait(*this); 1.6734 + return *this; 1.6735 + } 1.6736 + 1.6737 + //! Wait for any event occuring on the display \c disp1. 1.6738 + static void wait(CImgDisplay& disp1) { 1.6739 + disp1.is_event = 0; 1.6740 + while (!disp1.is_event) wait_all(); 1.6741 + } 1.6742 + 1.6743 + //! Wait for any event occuring either on the display \c disp1 or \c disp2. 1.6744 + static void wait(CImgDisplay& disp1, CImgDisplay& disp2) { 1.6745 + disp1.is_event = disp2.is_event = 0; 1.6746 + while (!disp1.is_event && !disp2.is_event) wait_all(); 1.6747 + } 1.6748 + 1.6749 + //! Wait for any event occuring either on the display \c disp1, \c disp2 or \c disp3. 1.6750 + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3) { 1.6751 + disp1.is_event = disp2.is_event = disp3.is_event = 0; 1.6752 + while (!disp1.is_event && !disp2.is_event && !disp3.is_event) wait_all(); 1.6753 + } 1.6754 + 1.6755 + //! Wait for any event occuring either on the display \c disp1, \c disp2, \c disp3 or \c disp4. 1.6756 + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4) { 1.6757 + disp1.is_event = disp2.is_event = disp3.is_event = disp4.is_event = 0; 1.6758 + while (!disp1.is_event && !disp2.is_event && !disp3.is_event && !disp4.is_event) wait_all(); 1.6759 + } 1.6760 + 1.6761 + //! Return the frame per second rate. 1.6762 + float frames_per_second() { 1.6763 + if (!fps_timer) fps_timer = cimg::time(); 1.6764 + const float delta = (cimg::time()-fps_timer)/1000.0f; 1.6765 + ++fps_frames; 1.6766 + if (delta>=1) { 1.6767 + fps_fps = fps_frames/delta; 1.6768 + fps_frames = 0; 1.6769 + fps_timer = cimg::time(); 1.6770 + } 1.6771 + return fps_fps; 1.6772 + } 1.6773 + 1.6774 + //! Display an image list CImgList<T> into a display window. 1.6775 + /** First, all images of the list are appended into a single image used for visualization, 1.6776 + then this image is displayed in the current display window. 1.6777 + \param list : The list of images to display. 1.6778 + \param axis : The axis used to append the image for visualization. Can be 'x' (default),'y','z' or 'v'. 1.6779 + \param align : Defines the relative alignment of images when displaying images of different sizes. 1.6780 + Can be '\p c' (centered, which is the default), '\p p' (top alignment) and '\p n' (bottom aligment). 1.6781 + **/ 1.6782 + template<typename T> 1.6783 + CImgDisplay& display(const CImgList<T>& list, const char axis='x', const char align='p') { 1.6784 + return display(list.get_append(axis,align)); 1.6785 + } 1.6786 + 1.6787 + //! Display an image CImg<T> into a display window. 1.6788 + template<typename T> 1.6789 + CImgDisplay& operator<<(const CImg<T>& img) { 1.6790 + return display(img); 1.6791 + } 1.6792 + 1.6793 + //! Display an image CImg<T> into a display window. 1.6794 + template<typename T> 1.6795 + CImgDisplay& operator<<(const CImgList<T>& list) { 1.6796 + return display(list); 1.6797 + } 1.6798 + 1.6799 + //! Resize a display window with the size of an image. 1.6800 + /** \param img : Input image. \p image.width and \p image.height give the new dimensions of the display window. 1.6801 + \param redraw : If \p true (default), the current displayed image in the display window will 1.6802 + be bloc-interpolated to fit the new dimensions. If \p false, a black image will be drawn in the resized window. 1.6803 + **/ 1.6804 + template<typename T> 1.6805 + CImgDisplay& resize(const CImg<T>& img, const bool redraw=true) { 1.6806 + return resize(img.width,img.height,redraw); 1.6807 + } 1.6808 + 1.6809 + //! Resize a display window using the size of the given display \p disp. 1.6810 + CImgDisplay& resize(const CImgDisplay& disp, const bool redraw=true) { 1.6811 + return resize(disp.width,disp.height,redraw); 1.6812 + } 1.6813 + 1.6814 + //! Resize a display window in its current size. 1.6815 + CImgDisplay& resize(const bool redraw=true) { 1.6816 + resize(window_width,window_height,redraw); 1.6817 + return *this; 1.6818 + } 1.6819 + 1.6820 + //! Set fullscreen mode. 1.6821 + CImgDisplay& fullscreen(const bool redraw=true) { 1.6822 + if (is_empty() || is_fullscreen) return *this; 1.6823 + return toggle_fullscreen(redraw); 1.6824 + } 1.6825 + 1.6826 + //! Set normal screen mode. 1.6827 + CImgDisplay& normalscreen(const bool redraw=true) { 1.6828 + if (is_empty() || !is_fullscreen) return *this; 1.6829 + return toggle_fullscreen(redraw); 1.6830 + } 1.6831 + 1.6832 + // Inner routine used for fast resizing of buffer to display size. 1.6833 + template<typename t, typename T> 1.6834 + static void _render_resize(const T *ptrs, const unsigned int ws, const unsigned int hs, 1.6835 + t *ptrd, const unsigned int wd, const unsigned int hd) { 1.6836 + unsigned int *const offx = new unsigned int[wd], *const offy = new unsigned int[hd+1], *poffx, *poffy; 1.6837 + float s, curr, old; 1.6838 + s = (float)ws/wd; 1.6839 + poffx = offx; curr = 0; for (unsigned int x=0; x<wd; ++x) { old=curr; curr+=s; *(poffx++) = (unsigned int)curr-(unsigned int)old; } 1.6840 + s = (float)hs/hd; 1.6841 + poffy = offy; curr = 0; for (unsigned int y=0; y<hd; ++y) { old=curr; curr+=s; *(poffy++) = ws*((unsigned int)curr-(unsigned int)old); } 1.6842 + *poffy = 0; 1.6843 + poffy = offy; 1.6844 + {for (unsigned int y=0; y<hd; ) { 1.6845 + const T *ptr = ptrs; 1.6846 + poffx = offx; 1.6847 + for (unsigned int x=0; x<wd; ++x) { *(ptrd++) = *ptr; ptr+=*(poffx++); } 1.6848 + ++y; 1.6849 + unsigned int dy=*(poffy++); 1.6850 + for (;!dy && y<hd; cimg_std::memcpy(ptrd, ptrd-wd, sizeof(t)*wd), ++y, ptrd+=wd, dy=*(poffy++)) {} 1.6851 + ptrs+=dy; 1.6852 + }} 1.6853 + delete[] offx; delete[] offy; 1.6854 + } 1.6855 + 1.6856 + //! Clear all events of the current display. 1.6857 + CImgDisplay& flush() { 1.6858 + cimg_std::memset((void*)buttons,0,512*sizeof(unsigned int)); 1.6859 + cimg_std::memset((void*)keys,0,512*sizeof(unsigned int)); 1.6860 + cimg_std::memset((void*)released_keys,0,512*sizeof(unsigned int)); 1.6861 + is_keyESC = is_keyF1 = is_keyF2 = is_keyF3 = is_keyF4 = is_keyF5 = is_keyF6 = is_keyF7 = is_keyF8 = is_keyF9 = 1.6862 + is_keyF10 = is_keyF11 = is_keyF12 = is_keyPAUSE = is_key1 = is_key2 = is_key3 = is_key4 = is_key5 = is_key6 = 1.6863 + is_key7 = is_key8 = is_key9 = is_key0 = is_keyBACKSPACE = is_keyINSERT = is_keyHOME = is_keyPAGEUP = is_keyTAB = 1.6864 + is_keyQ = is_keyW = is_keyE = is_keyR = is_keyT = is_keyY = is_keyU = is_keyI = is_keyO = is_keyP = is_keyDELETE = 1.6865 + is_keyEND = is_keyPAGEDOWN = is_keyCAPSLOCK = is_keyA = is_keyS = is_keyD = is_keyF = is_keyG = is_keyH = is_keyJ = 1.6866 + is_keyK = is_keyL = is_keyENTER = is_keySHIFTLEFT = is_keyZ = is_keyX = is_keyC = is_keyV = is_keyB = is_keyN = 1.6867 + is_keyM = is_keySHIFTRIGHT = is_keyARROWUP = is_keyCTRLLEFT = is_keyAPPLEFT = is_keyALT = is_keySPACE = is_keyALTGR = is_keyAPPRIGHT = 1.6868 + is_keyMENU = is_keyCTRLRIGHT = is_keyARROWLEFT = is_keyARROWDOWN = is_keyARROWRIGHT = is_keyPAD0 = is_keyPAD1 = is_keyPAD2 = 1.6869 + is_keyPAD3 = is_keyPAD4 = is_keyPAD5 = is_keyPAD6 = is_keyPAD7 = is_keyPAD8 = is_keyPAD9 = is_keyPADADD = is_keyPADSUB = 1.6870 + is_keyPADMUL = is_keyPADDIV = false; 1.6871 + is_resized = is_moved = is_event = false; 1.6872 + fps_timer = fps_frames = timer = wheel = 0; 1.6873 + mouse_x = mouse_y = -1; 1.6874 + fps_fps = 0; 1.6875 + return *this; 1.6876 + } 1.6877 + 1.6878 + // Update 'is_key' fields. 1.6879 + void update_iskey(const unsigned int key, const bool pressed=true) { 1.6880 +#define _cimg_iskey_case(k) if (key==cimg::key##k) is_key##k = pressed; 1.6881 + _cimg_iskey_case(ESC); _cimg_iskey_case(F1); _cimg_iskey_case(F2); _cimg_iskey_case(F3); 1.6882 + _cimg_iskey_case(F4); _cimg_iskey_case(F5); _cimg_iskey_case(F6); _cimg_iskey_case(F7); 1.6883 + _cimg_iskey_case(F8); _cimg_iskey_case(F9); _cimg_iskey_case(F10); _cimg_iskey_case(F11); 1.6884 + _cimg_iskey_case(F12); _cimg_iskey_case(PAUSE); _cimg_iskey_case(1); _cimg_iskey_case(2); 1.6885 + _cimg_iskey_case(3); _cimg_iskey_case(4); _cimg_iskey_case(5); _cimg_iskey_case(6); 1.6886 + _cimg_iskey_case(7); _cimg_iskey_case(8); _cimg_iskey_case(9); _cimg_iskey_case(0); 1.6887 + _cimg_iskey_case(BACKSPACE); _cimg_iskey_case(INSERT); _cimg_iskey_case(HOME); 1.6888 + _cimg_iskey_case(PAGEUP); _cimg_iskey_case(TAB); _cimg_iskey_case(Q); _cimg_iskey_case(W); 1.6889 + _cimg_iskey_case(E); _cimg_iskey_case(R); _cimg_iskey_case(T); _cimg_iskey_case(Y); 1.6890 + _cimg_iskey_case(U); _cimg_iskey_case(I); _cimg_iskey_case(O); _cimg_iskey_case(P); 1.6891 + _cimg_iskey_case(DELETE); _cimg_iskey_case(END); _cimg_iskey_case(PAGEDOWN); 1.6892 + _cimg_iskey_case(CAPSLOCK); _cimg_iskey_case(A); _cimg_iskey_case(S); _cimg_iskey_case(D); 1.6893 + _cimg_iskey_case(F); _cimg_iskey_case(G); _cimg_iskey_case(H); _cimg_iskey_case(J); 1.6894 + _cimg_iskey_case(K); _cimg_iskey_case(L); _cimg_iskey_case(ENTER); 1.6895 + _cimg_iskey_case(SHIFTLEFT); _cimg_iskey_case(Z); _cimg_iskey_case(X); _cimg_iskey_case(C); 1.6896 + _cimg_iskey_case(V); _cimg_iskey_case(B); _cimg_iskey_case(N); _cimg_iskey_case(M); 1.6897 + _cimg_iskey_case(SHIFTRIGHT); _cimg_iskey_case(ARROWUP); _cimg_iskey_case(CTRLLEFT); 1.6898 + _cimg_iskey_case(APPLEFT); _cimg_iskey_case(ALT); _cimg_iskey_case(SPACE); _cimg_iskey_case(ALTGR); 1.6899 + _cimg_iskey_case(APPRIGHT); _cimg_iskey_case(MENU); _cimg_iskey_case(CTRLRIGHT); 1.6900 + _cimg_iskey_case(ARROWLEFT); _cimg_iskey_case(ARROWDOWN); _cimg_iskey_case(ARROWRIGHT); 1.6901 + _cimg_iskey_case(PAD0); _cimg_iskey_case(PAD1); _cimg_iskey_case(PAD2); 1.6902 + _cimg_iskey_case(PAD3); _cimg_iskey_case(PAD4); _cimg_iskey_case(PAD5); 1.6903 + _cimg_iskey_case(PAD6); _cimg_iskey_case(PAD7); _cimg_iskey_case(PAD8); 1.6904 + _cimg_iskey_case(PAD9); _cimg_iskey_case(PADADD); _cimg_iskey_case(PADSUB); 1.6905 + _cimg_iskey_case(PADMUL); _cimg_iskey_case(PADDIV); 1.6906 + } 1.6907 + 1.6908 + //! Test if any key has been pressed. 1.6909 + bool is_key(const bool remove=false) { 1.6910 + for (unsigned int *ptrs=(unsigned int*)keys+512-1; ptrs>=keys; --ptrs) if (*ptrs) { if (remove) *ptrs = 0; return true; } 1.6911 + return false; 1.6912 + } 1.6913 + 1.6914 + //! Test if a key has been pressed. 1.6915 + bool is_key(const unsigned int key1, const bool remove) { 1.6916 + for (unsigned int *ptrs=(unsigned int*)keys+512-1; ptrs>=keys; --ptrs) if (*ptrs==key1) { if (remove) *ptrs = 0; return true; } 1.6917 + return false; 1.6918 + } 1.6919 + 1.6920 + //! Test if a key sequence has been typed. 1.6921 + bool is_key(const unsigned int key1, const unsigned int key2, const bool remove) { 1.6922 + const unsigned int seq[] = { key1, key2 }; 1.6923 + return is_key(seq,2,remove); 1.6924 + } 1.6925 + 1.6926 + //! Test if a key sequence has been typed. 1.6927 + bool is_key(const unsigned int key1, const unsigned int key2, const unsigned int key3, const bool remove) { 1.6928 + const unsigned int seq[] = { key1, key2, key3 }; 1.6929 + return is_key(seq,3,remove); 1.6930 + } 1.6931 + 1.6932 + //! Test if a key sequence has been typed. 1.6933 + bool is_key(const unsigned int key1, const unsigned int key2, const unsigned int key3, 1.6934 + const unsigned int key4, const bool remove) { 1.6935 + const unsigned int seq[] = { key1, key2, key3, key4 }; 1.6936 + return is_key(seq,4,remove); 1.6937 + } 1.6938 + 1.6939 + //! Test if a key sequence has been typed. 1.6940 + bool is_key(const unsigned int key1, const unsigned int key2, const unsigned int key3, 1.6941 + const unsigned int key4, const unsigned int key5, const bool remove) { 1.6942 + const unsigned int seq[] = { key1, key2, key3, key4, key5 }; 1.6943 + return is_key(seq,5,remove); 1.6944 + } 1.6945 + 1.6946 + //! Test if a key sequence has been typed. 1.6947 + bool is_key(const unsigned int key1, const unsigned int key2, const unsigned int key3, 1.6948 + const unsigned int key4, const unsigned int key5, const unsigned int key6, const bool remove) { 1.6949 + const unsigned int seq[] = { key1, key2, key3, key4, key5, key6 }; 1.6950 + return is_key(seq,6,remove); 1.6951 + } 1.6952 + 1.6953 + //! Test if a key sequence has been typed. 1.6954 + bool is_key(const unsigned int key1, const unsigned int key2, const unsigned int key3, 1.6955 + const unsigned int key4, const unsigned int key5, const unsigned int key6, 1.6956 + const unsigned int key7, const bool remove) { 1.6957 + const unsigned int seq[] = { key1, key2, key3, key4, key5, key6, key7 }; 1.6958 + return is_key(seq,7,remove); 1.6959 + } 1.6960 + 1.6961 + //! Test if a key sequence has been typed. 1.6962 + bool is_key(const unsigned int key1, const unsigned int key2, const unsigned int key3, 1.6963 + const unsigned int key4, const unsigned int key5, const unsigned int key6, 1.6964 + const unsigned int key7, const unsigned int key8, const bool remove) { 1.6965 + const unsigned int seq[] = { key1, key2, key3, key4, key5, key6, key7, key8 }; 1.6966 + return is_key(seq,8,remove); 1.6967 + } 1.6968 + 1.6969 + //! Test if a key sequence has been typed. 1.6970 + bool is_key(const unsigned int key1, const unsigned int key2, const unsigned int key3, 1.6971 + const unsigned int key4, const unsigned int key5, const unsigned int key6, 1.6972 + const unsigned int key7, const unsigned int key8, const unsigned int key9, const bool remove) { 1.6973 + const unsigned int seq[] = { key1, key2, key3, key4, key5, key6, key7, key8, key9 }; 1.6974 + return is_key(seq,9,remove); 1.6975 + } 1.6976 + 1.6977 + //! Test if a key sequence has been typed. 1.6978 + bool is_key(const unsigned int *const keyseq, const unsigned int N, const bool remove=true) { 1.6979 + if (keyseq && N) { 1.6980 + const unsigned int *const ps_end = keyseq+N-1, k = *ps_end, *const pk_end = (unsigned int*)keys+1+512-N; 1.6981 + for (unsigned int *pk = (unsigned int*)keys; pk<pk_end; ) { 1.6982 + if (*(pk++)==k) { 1.6983 + bool res = true; 1.6984 + const unsigned int *ps = ps_end, *pk2 = pk; 1.6985 + for (unsigned int i=1; i<N; ++i) res = (*(--ps)==*(pk2++)); 1.6986 + if (res) { 1.6987 + if (remove) cimg_std::memset((void*)(pk-1),0,sizeof(unsigned int)*N); 1.6988 + return true; 1.6989 + } 1.6990 + } 1.6991 + } 1.6992 + } 1.6993 + return false; 1.6994 + } 1.6995 + 1.6996 + // Find the good width and height of a window to display an image (internal routine). 1.6997 +#define cimg_fitscreen(dx,dy,dz) CImgDisplay::_fitscreen(dx,dy,dz,128,-85,false),CImgDisplay::_fitscreen(dx,dy,dz,128,-85,true) 1.6998 + static unsigned int _fitscreen(const unsigned int dx, const unsigned int dy=1, const unsigned int dz=1, 1.6999 + const int dmin=128, const int dmax=-85,const bool return_last=false) { 1.7000 + unsigned int nw = dx + (dz>1?dz:0), nh = dy + (dz>1?dz:0); 1.7001 + const unsigned int 1.7002 + sw = CImgDisplay::screen_dimx(), sh = CImgDisplay::screen_dimy(), 1.7003 + mw = dmin<0?(unsigned int)(sw*-dmin/100):(unsigned int)dmin, 1.7004 + mh = dmin<0?(unsigned int)(sh*-dmin/100):(unsigned int)dmin, 1.7005 + Mw = dmax<0?(unsigned int)(sw*-dmax/100):(unsigned int)dmax, 1.7006 + Mh = dmax<0?(unsigned int)(sh*-dmax/100):(unsigned int)dmax; 1.7007 + if (nw<mw) { nh = nh*mw/nw; nh+=(nh==0); nw = mw; } 1.7008 + if (nh<mh) { nw = nw*mh/nh; nw+=(nw==0); nh = mh; } 1.7009 + if (nw>Mw) { nh = nh*Mw/nw; nh+=(nh==0); nw = Mw; } 1.7010 + if (nh>Mh) { nw = nw*Mh/nh; nw+=(nw==0); nh = Mh; } 1.7011 + if (nw<mw) nw = mw; 1.7012 + if (nh<mh) nh = mh; 1.7013 + if (return_last) return nh; 1.7014 + return nw; 1.7015 + } 1.7016 + 1.7017 + // When no display available 1.7018 + //--------------------------- 1.7019 +#if cimg_display==0 1.7020 + 1.7021 + //! Return the width of the screen resolution. 1.7022 + static int screen_dimx() { 1.7023 + return 0; 1.7024 + } 1.7025 + 1.7026 + //! Return the height of the screen resolution. 1.7027 + static int screen_dimy() { 1.7028 + return 0; 1.7029 + } 1.7030 + 1.7031 + //! Wait for a window event in any CImg window. 1.7032 + static void wait_all() {} 1.7033 + 1.7034 + //! In-place version of the destructor. 1.7035 + CImgDisplay& assign() { 1.7036 + return *this; 1.7037 + } 1.7038 + 1.7039 + //! In-place version of the previous constructor. 1.7040 + CImgDisplay& assign(const unsigned int dimw, const unsigned int dimh, const char *title=0, 1.7041 + const unsigned int normalization_type=3, 1.7042 + const bool fullscreen_flag=false, const bool closed_flag=false) { 1.7043 + throw CImgDisplayException("CImgDisplay() : Display has been required but is not available (cimg_display=0)"); 1.7044 + const char* avoid_warning = title + dimw + dimh + normalization_type + (int)fullscreen_flag + (int)closed_flag; 1.7045 + avoid_warning = 0; 1.7046 + return *this; 1.7047 + } 1.7048 + 1.7049 + //! In-place version of the previous constructor. 1.7050 + template<typename T> 1.7051 + CImgDisplay& assign(const CImg<T>& img, const char *title=0, 1.7052 + const unsigned int normalization_type=3, 1.7053 + const bool fullscreen_flag=false, const bool closed_flag=false) { 1.7054 + throw CImgDisplayException("CImgDisplay()::assign() : Display has been required but is not available (cimg_display=0)"); 1.7055 + const char* avoid_warning = title + img.width + normalization_type + (int)fullscreen_flag + (int)closed_flag; 1.7056 + avoid_warning = 0; 1.7057 + return assign(0,0); 1.7058 + } 1.7059 + 1.7060 + //! In-place version of the previous constructor. 1.7061 + template<typename T> 1.7062 + CImgDisplay& assign(const CImgList<T>& list, const char *title=0, 1.7063 + const unsigned int normalization_type=3, 1.7064 + const bool fullscreen_flag=false, const bool closed_flag=false) { 1.7065 + throw CImgDisplayException("CImgDisplay()::assign() : Display has been required but is not available (cimg_display=0)"); 1.7066 + const char* avoid_warning = title + list.size + normalization_type + (int)fullscreen_flag + (int)closed_flag; 1.7067 + avoid_warning = 0; 1.7068 + return assign(0,0); 1.7069 + } 1.7070 + 1.7071 + //! In-place version of the previous constructor. 1.7072 + CImgDisplay& assign(const CImgDisplay &disp) { 1.7073 + return assign(disp.width,disp.height); 1.7074 + } 1.7075 + 1.7076 + //! Resize window. 1.7077 + CImgDisplay& resize(const int width, const int height, const bool redraw=true) { 1.7078 + int avoid_warning = width | height | (int)redraw; 1.7079 + avoid_warning = 0; 1.7080 + return *this; 1.7081 + } 1.7082 + 1.7083 + //! Toggle fullscreen mode. 1.7084 + CImgDisplay& toggle_fullscreen(const bool redraw=true) { 1.7085 + bool avoid_warning = redraw; 1.7086 + avoid_warning = false; 1.7087 + return *this; 1.7088 + } 1.7089 + 1.7090 + //! Show a closed display. 1.7091 + CImgDisplay& show() { 1.7092 + return *this; 1.7093 + } 1.7094 + 1.7095 + //! Close a visible display. 1.7096 + CImgDisplay& close() { 1.7097 + return *this; 1.7098 + } 1.7099 + 1.7100 + //! Move window. 1.7101 + CImgDisplay& move(const int posx, const int posy) { 1.7102 + int avoid_warning = posx | posy; 1.7103 + avoid_warning = 0; 1.7104 + return *this; 1.7105 + } 1.7106 + 1.7107 + //! Show mouse pointer. 1.7108 + CImgDisplay& show_mouse() { 1.7109 + return *this; 1.7110 + } 1.7111 + 1.7112 + //! Hide mouse pointer. 1.7113 + CImgDisplay& hide_mouse() { 1.7114 + return *this; 1.7115 + } 1.7116 + 1.7117 + //! Move mouse pointer to a specific location. 1.7118 + CImgDisplay& set_mouse(const int posx, const int posy) { 1.7119 + int avoid_warning = posx | posy; 1.7120 + avoid_warning = 0; 1.7121 + return *this; 1.7122 + } 1.7123 + 1.7124 + //! Set the window title. 1.7125 + CImgDisplay& set_title(const char *format, ...) { 1.7126 + const char *avoid_warning = format; 1.7127 + avoid_warning = 0; 1.7128 + return *this; 1.7129 + } 1.7130 + 1.7131 + //! Display an image in a window. 1.7132 + template<typename T> 1.7133 + CImgDisplay& display(const CImg<T>& img) { 1.7134 + unsigned int avoid_warning = img.width; 1.7135 + avoid_warning = 0; 1.7136 + return *this; 1.7137 + } 1.7138 + 1.7139 + //! Re-paint image content in window. 1.7140 + CImgDisplay& paint() { 1.7141 + return *this; 1.7142 + } 1.7143 + 1.7144 + //! Render image buffer into GDI native image format. 1.7145 + template<typename T> 1.7146 + CImgDisplay& render(const CImg<T>& img) { 1.7147 + unsigned int avoid_warning = img.width; 1.7148 + avoid_warning = 0; 1.7149 + return *this; 1.7150 + } 1.7151 + 1.7152 + //! Take a snapshot of the display in the specified image. 1.7153 + template<typename T> 1.7154 + const CImgDisplay& snapshot(CImg<T>& img) const { 1.7155 + img.assign(width,height,1,3,0); 1.7156 + return *this; 1.7157 + } 1.7158 + 1.7159 + // X11-based display 1.7160 + //------------------- 1.7161 +#elif cimg_display==1 1.7162 + Atom wm_delete_window, wm_delete_protocol; 1.7163 + Window window, background_window; 1.7164 + Colormap colormap; 1.7165 + XImage *image; 1.7166 + void *data; 1.7167 +#ifdef cimg_use_xshm 1.7168 + XShmSegmentInfo *shminfo; 1.7169 +#endif 1.7170 + 1.7171 + static int screen_dimx() { 1.7172 + int res = 0; 1.7173 + if (!cimg::X11attr().display) { 1.7174 + Display *disp = XOpenDisplay((cimg_std::getenv("DISPLAY")?cimg_std::getenv("DISPLAY"):":0.0")); 1.7175 + if (!disp) 1.7176 + throw CImgDisplayException("CImgDisplay::screen_dimx() : Can't open X11 display."); 1.7177 + res = DisplayWidth(disp,DefaultScreen(disp)); 1.7178 + XCloseDisplay(disp); 1.7179 + } else { 1.7180 +#ifdef cimg_use_xrandr 1.7181 + if (cimg::X11attr().resolutions && cimg::X11attr().curr_resolution) 1.7182 + res = cimg::X11attr().resolutions[cimg::X11attr().curr_resolution].width; 1.7183 + else 1.7184 +#endif 1.7185 + res = DisplayWidth(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)); 1.7186 + } 1.7187 + return res; 1.7188 + } 1.7189 + 1.7190 + static int screen_dimy() { 1.7191 + int res = 0; 1.7192 + if (!cimg::X11attr().display) { 1.7193 + Display *disp = XOpenDisplay((cimg_std::getenv("DISPLAY") ? cimg_std::getenv("DISPLAY") : ":0.0")); 1.7194 + if (!disp) 1.7195 + throw CImgDisplayException("CImgDisplay::screen_dimy() : Can't open X11 display."); 1.7196 + res = DisplayHeight(disp,DefaultScreen(disp)); 1.7197 + XCloseDisplay(disp); 1.7198 + } else { 1.7199 +#ifdef cimg_use_xrandr 1.7200 + if (cimg::X11attr().resolutions && cimg::X11attr().curr_resolution) 1.7201 + res = cimg::X11attr().resolutions[cimg::X11attr().curr_resolution].height; 1.7202 + else 1.7203 +#endif 1.7204 + res = DisplayHeight(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)); 1.7205 + } 1.7206 + return res; 1.7207 + } 1.7208 + 1.7209 + static void wait_all() { 1.7210 + if (cimg::X11attr().display) { 1.7211 + XLockDisplay(cimg::X11attr().display); 1.7212 + bool flag = true; 1.7213 + XEvent event; 1.7214 + while (flag) { 1.7215 + XNextEvent(cimg::X11attr().display, &event); 1.7216 + for (unsigned int i = 0; i<cimg::X11attr().nb_wins; ++i) 1.7217 + if (!cimg::X11attr().wins[i]->is_closed && event.xany.window==cimg::X11attr().wins[i]->window) { 1.7218 + cimg::X11attr().wins[i]->_handle_events(&event); 1.7219 + if (cimg::X11attr().wins[i]->is_event) flag = false; 1.7220 + } 1.7221 + } 1.7222 + XUnlockDisplay(cimg::X11attr().display); 1.7223 + } 1.7224 + } 1.7225 + 1.7226 + void _handle_events(const XEvent *const pevent) { 1.7227 + XEvent event = *pevent; 1.7228 + switch (event.type) { 1.7229 + case ClientMessage : { 1.7230 + if ((int)event.xclient.message_type==(int)wm_delete_protocol && 1.7231 + (int)event.xclient.data.l[0]==(int)wm_delete_window) { 1.7232 + XUnmapWindow(cimg::X11attr().display,window); 1.7233 + mouse_x = mouse_y = -1; 1.7234 + if (button) { cimg_std::memmove((void*)(buttons+1),(void*)buttons,512-1); button = 0; } 1.7235 + if (key) { cimg_std::memmove((void*)(keys+1),(void*)keys,512-1); key = 0; } 1.7236 + if (released_key) { cimg_std::memmove((void*)(released_keys+1),(void*)released_keys,512-1); released_key = 0; } 1.7237 + is_closed = is_event = true; 1.7238 + } 1.7239 + } break; 1.7240 + case ConfigureNotify : { 1.7241 + while (XCheckWindowEvent(cimg::X11attr().display,window,StructureNotifyMask,&event)) {} 1.7242 + const unsigned int 1.7243 + nw = event.xconfigure.width, 1.7244 + nh = event.xconfigure.height; 1.7245 + const int 1.7246 + nx = event.xconfigure.x, 1.7247 + ny = event.xconfigure.y; 1.7248 + if (nw && nh && (nw!=window_width || nh!=window_height)) { 1.7249 + window_width = nw; 1.7250 + window_height = nh; 1.7251 + mouse_x = mouse_y = -1; 1.7252 + XResizeWindow(cimg::X11attr().display,window,window_width,window_height); 1.7253 + is_resized = is_event = true; 1.7254 + } 1.7255 + if (nx!=window_x || ny!=window_y) { 1.7256 + window_x = nx; 1.7257 + window_y = ny; 1.7258 + is_moved = is_event = true; 1.7259 + } 1.7260 + } break; 1.7261 + case Expose : { 1.7262 + while (XCheckWindowEvent(cimg::X11attr().display,window,ExposureMask,&event)) {} 1.7263 + _paint(false); 1.7264 + if (is_fullscreen) { 1.7265 + XWindowAttributes attr; 1.7266 + XGetWindowAttributes(cimg::X11attr().display, window, &attr); 1.7267 + while (attr.map_state != IsViewable) XSync(cimg::X11attr().display, False); 1.7268 + XSetInputFocus(cimg::X11attr().display, window, RevertToParent, CurrentTime); 1.7269 + } 1.7270 + } break; 1.7271 + case ButtonPress : { 1.7272 + do { 1.7273 + mouse_x = event.xmotion.x; 1.7274 + mouse_y = event.xmotion.y; 1.7275 + if (mouse_x<0 || mouse_y<0 || mouse_x>=dimx() || mouse_y>=dimy()) mouse_x = mouse_y = -1; 1.7276 + switch (event.xbutton.button) { 1.7277 + case 1 : cimg_std::memmove((void*)(buttons+1),(void*)buttons,512-1); button|=1; is_event = true; break; 1.7278 + case 2 : cimg_std::memmove((void*)(buttons+1),(void*)buttons,512-1); button|=4; is_event = true; break; 1.7279 + case 3 : cimg_std::memmove((void*)(buttons+1),(void*)buttons,512-1); button|=2; is_event = true; break; 1.7280 + } 1.7281 + } while (XCheckWindowEvent(cimg::X11attr().display,window,ButtonPressMask,&event)); 1.7282 + } break; 1.7283 + case ButtonRelease : { 1.7284 + do { 1.7285 + mouse_x = event.xmotion.x; 1.7286 + mouse_y = event.xmotion.y; 1.7287 + if (mouse_x<0 || mouse_y<0 || mouse_x>=dimx() || mouse_y>=dimy()) mouse_x = mouse_y = -1; 1.7288 + switch (event.xbutton.button) { 1.7289 + case 1 : cimg_std::memmove((void*)(buttons+1),(void*)buttons,512-1); button&=~1U; is_event = true; break; 1.7290 + case 2 : cimg_std::memmove((void*)(buttons+1),(void*)buttons,512-1); button&=~4U; is_event = true; break; 1.7291 + case 3 : cimg_std::memmove((void*)(buttons+1),(void*)buttons,512-1); button&=~2U; is_event = true; break; 1.7292 + case 4 : ++wheel; is_event = true; break; 1.7293 + case 5 : --wheel; is_event = true; break; 1.7294 + } 1.7295 + } while (XCheckWindowEvent(cimg::X11attr().display,window,ButtonReleaseMask,&event)); 1.7296 + } break; 1.7297 + case KeyPress : { 1.7298 + char tmp; 1.7299 + KeySym ksym; 1.7300 + XLookupString(&event.xkey,&tmp,1,&ksym,0); 1.7301 + update_iskey((unsigned int)ksym,true); 1.7302 + if (key) cimg_std::memmove((void*)(keys+1),(void*)keys,512-1); 1.7303 + key = (unsigned int)ksym; 1.7304 + if (released_key) { cimg_std::memmove((void*)(released_keys+1),(void*)released_keys,512-1); released_key = 0; } 1.7305 + is_event = true; 1.7306 + } break; 1.7307 + case KeyRelease : { 1.7308 + char tmp; 1.7309 + KeySym ksym; 1.7310 + XLookupString(&event.xkey,&tmp,1,&ksym,0); 1.7311 + update_iskey((unsigned int)ksym,false); 1.7312 + if (key) { cimg_std::memmove((void*)(keys+1),(void*)keys,512-1); key = 0; } 1.7313 + if (released_key) cimg_std::memmove((void*)(released_keys+1),(void*)released_keys,512-1); 1.7314 + released_key = (unsigned int)ksym; 1.7315 + is_event = true; 1.7316 + } break; 1.7317 + case EnterNotify: { 1.7318 + while (XCheckWindowEvent(cimg::X11attr().display,window,EnterWindowMask,&event)) {} 1.7319 + mouse_x = event.xmotion.x; 1.7320 + mouse_y = event.xmotion.y; 1.7321 + if (mouse_x<0 || mouse_y<0 || mouse_x>=dimx() || mouse_y>=dimy()) mouse_x = mouse_y = -1; 1.7322 + } break; 1.7323 + case LeaveNotify : { 1.7324 + while (XCheckWindowEvent(cimg::X11attr().display,window,LeaveWindowMask,&event)) {} 1.7325 + mouse_x = mouse_y =-1; 1.7326 + is_event = true; 1.7327 + } break; 1.7328 + case MotionNotify : { 1.7329 + while (XCheckWindowEvent(cimg::X11attr().display,window,PointerMotionMask,&event)) {} 1.7330 + mouse_x = event.xmotion.x; 1.7331 + mouse_y = event.xmotion.y; 1.7332 + if (mouse_x<0 || mouse_y<0 || mouse_x>=dimx() || mouse_y>=dimy()) mouse_x = mouse_y = -1; 1.7333 + is_event = true; 1.7334 + } break; 1.7335 + } 1.7336 + } 1.7337 + 1.7338 + static void* _events_thread(void *arg) { 1.7339 + arg = 0; 1.7340 + XEvent event; 1.7341 + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,0); 1.7342 + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,0); 1.7343 + for (;;) { 1.7344 + XLockDisplay(cimg::X11attr().display); 1.7345 + bool event_flag = XCheckTypedEvent(cimg::X11attr().display, ClientMessage, &event); 1.7346 + if (!event_flag) event_flag = XCheckMaskEvent(cimg::X11attr().display, 1.7347 + ExposureMask|StructureNotifyMask|ButtonPressMask| 1.7348 + KeyPressMask|PointerMotionMask|EnterWindowMask|LeaveWindowMask| 1.7349 + ButtonReleaseMask|KeyReleaseMask,&event); 1.7350 + if (event_flag) { 1.7351 + for (unsigned int i=0; i<cimg::X11attr().nb_wins; ++i) 1.7352 + if (!cimg::X11attr().wins[i]->is_closed && event.xany.window==cimg::X11attr().wins[i]->window) 1.7353 + cimg::X11attr().wins[i]->_handle_events(&event); 1.7354 + } 1.7355 + XUnlockDisplay(cimg::X11attr().display); 1.7356 + pthread_testcancel(); 1.7357 + cimg::sleep(7); 1.7358 + } 1.7359 + return 0; 1.7360 + } 1.7361 + 1.7362 + void _set_colormap(Colormap& colormap, const unsigned int dim) { 1.7363 + XColor palette[256]; 1.7364 + switch (dim) { 1.7365 + case 1 : { // palette for greyscale images 1.7366 + for (unsigned int index=0; index<256; ++index) { 1.7367 + palette[index].pixel = index; 1.7368 + palette[index].red = palette[index].green = palette[index].blue = (unsigned short)(index<<8); 1.7369 + palette[index].flags = DoRed | DoGreen | DoBlue; 1.7370 + } 1.7371 + } break; 1.7372 + case 2 : { // palette for RG images 1.7373 + for (unsigned int index=0, r=8; r<256; r+=16) 1.7374 + for (unsigned int g=8; g<256; g+=16) { 1.7375 + palette[index].pixel = index; 1.7376 + palette[index].red = palette[index].blue = (unsigned short)(r<<8); 1.7377 + palette[index].green = (unsigned short)(g<<8); 1.7378 + palette[index++].flags = DoRed | DoGreen | DoBlue; 1.7379 + } 1.7380 + } break; 1.7381 + default : { // palette for RGB images 1.7382 + for (unsigned int index=0, r=16; r<256; r+=32) 1.7383 + for (unsigned int g=16; g<256; g+=32) 1.7384 + for (unsigned int b=32; b<256; b+=64) { 1.7385 + palette[index].pixel = index; 1.7386 + palette[index].red = (unsigned short)(r<<8); 1.7387 + palette[index].green = (unsigned short)(g<<8); 1.7388 + palette[index].blue = (unsigned short)(b<<8); 1.7389 + palette[index++].flags = DoRed | DoGreen | DoBlue; 1.7390 + } 1.7391 + } 1.7392 + } 1.7393 + XStoreColors(cimg::X11attr().display,colormap,palette,256); 1.7394 + } 1.7395 + 1.7396 + void _map_window() { 1.7397 + XWindowAttributes attr; 1.7398 + XEvent event; 1.7399 + bool exposed = false, mapped = false; 1.7400 + XMapRaised(cimg::X11attr().display,window); 1.7401 + XSync(cimg::X11attr().display,False); 1.7402 + do { 1.7403 + XWindowEvent(cimg::X11attr().display,window,StructureNotifyMask | ExposureMask,&event); 1.7404 + switch (event.type) { 1.7405 + case MapNotify : mapped = true; break; 1.7406 + case Expose : exposed = true; break; 1.7407 + default : XSync(cimg::X11attr().display, False); cimg::sleep(10); 1.7408 + } 1.7409 + } while (!(exposed && mapped)); 1.7410 + do { 1.7411 + XGetWindowAttributes(cimg::X11attr().display, window, &attr); 1.7412 + if (attr.map_state!=IsViewable) { XSync(cimg::X11attr().display,False); cimg::sleep(10); } 1.7413 + } while (attr.map_state != IsViewable); 1.7414 + window_x = attr.x; 1.7415 + window_y = attr.y; 1.7416 + } 1.7417 + 1.7418 + void _paint(const bool wait_expose=true) { 1.7419 + if (!is_closed) { 1.7420 + if (wait_expose) { 1.7421 + static XEvent event; 1.7422 + event.xexpose.type = Expose; 1.7423 + event.xexpose.serial = 0; 1.7424 + event.xexpose.send_event = True; 1.7425 + event.xexpose.display = cimg::X11attr().display; 1.7426 + event.xexpose.window = window; 1.7427 + event.xexpose.x = 0; 1.7428 + event.xexpose.y = 0; 1.7429 + event.xexpose.width = dimx(); 1.7430 + event.xexpose.height = dimy(); 1.7431 + event.xexpose.count = 0; 1.7432 + XSendEvent(cimg::X11attr().display, window, False, 0, &event); 1.7433 + } else { 1.7434 +#ifdef cimg_use_xshm 1.7435 + if (shminfo) XShmPutImage(cimg::X11attr().display,window,*cimg::X11attr().gc,image,0,0,0,0,width,height,False); 1.7436 + else 1.7437 +#endif 1.7438 + XPutImage(cimg::X11attr().display,window,*cimg::X11attr().gc,image,0,0,0,0,width,height); 1.7439 + XSync(cimg::X11attr().display, False); 1.7440 + } 1.7441 + } 1.7442 + } 1.7443 + 1.7444 + template<typename T> 1.7445 + void _resize(T foo, const unsigned int ndimx, const unsigned int ndimy, const bool redraw) { 1.7446 + foo = 0; 1.7447 +#ifdef cimg_use_xshm 1.7448 + if (shminfo) { 1.7449 + XShmSegmentInfo *nshminfo = new XShmSegmentInfo; 1.7450 + XImage *nimage = XShmCreateImage(cimg::X11attr().display,DefaultVisual(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)), 1.7451 + cimg::X11attr().nb_bits,ZPixmap,0,nshminfo,ndimx,ndimy); 1.7452 + if (!nimage) { 1.7453 + delete nshminfo; 1.7454 + return; 1.7455 + } else { 1.7456 + nshminfo->shmid = shmget(IPC_PRIVATE, ndimx*ndimy*sizeof(T), IPC_CREAT | 0777); 1.7457 + if (nshminfo->shmid==-1) { 1.7458 + XDestroyImage(nimage); 1.7459 + delete nshminfo; 1.7460 + return; 1.7461 + } else { 1.7462 + nshminfo->shmaddr = nimage->data = (char*)shmat(nshminfo->shmid,0,0); 1.7463 + if (nshminfo->shmaddr==(char*)-1) { 1.7464 + shmctl(nshminfo->shmid,IPC_RMID,0); 1.7465 + XDestroyImage(nimage); 1.7466 + delete nshminfo; 1.7467 + return; 1.7468 + } else { 1.7469 + nshminfo->readOnly = False; 1.7470 + cimg::X11attr().shm_enabled = true; 1.7471 + XErrorHandler oldXErrorHandler = XSetErrorHandler(_assign_xshm); 1.7472 + XShmAttach(cimg::X11attr().display, nshminfo); 1.7473 + XSync(cimg::X11attr().display, False); 1.7474 + XSetErrorHandler(oldXErrorHandler); 1.7475 + if (!cimg::X11attr().shm_enabled) { 1.7476 + shmdt(nshminfo->shmaddr); 1.7477 + shmctl(nshminfo->shmid,IPC_RMID,0); 1.7478 + XDestroyImage(nimage); 1.7479 + delete nshminfo; 1.7480 + return; 1.7481 + } else { 1.7482 + T *const ndata = (T*)nimage->data; 1.7483 + if (redraw) _render_resize((T*)data,width,height,ndata,ndimx,ndimy); 1.7484 + else cimg_std::memset(ndata,0,sizeof(T)*ndimx*ndimy); 1.7485 + XShmDetach(cimg::X11attr().display, shminfo); 1.7486 + XDestroyImage(image); 1.7487 + shmdt(shminfo->shmaddr); 1.7488 + shmctl(shminfo->shmid,IPC_RMID,0); 1.7489 + delete shminfo; 1.7490 + shminfo = nshminfo; 1.7491 + image = nimage; 1.7492 + data = (void*)ndata; 1.7493 + } 1.7494 + } 1.7495 + } 1.7496 + } 1.7497 + } else 1.7498 +#endif 1.7499 + { 1.7500 + T *ndata = (T*)cimg_std::malloc(ndimx*ndimy*sizeof(T)); 1.7501 + if (redraw) _render_resize((T*)data,width,height,ndata,ndimx,ndimy); 1.7502 + else cimg_std::memset(ndata,0,sizeof(T)*ndimx*ndimy); 1.7503 + data = (void*)ndata; 1.7504 + XDestroyImage(image); 1.7505 + image = XCreateImage(cimg::X11attr().display,DefaultVisual(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)), 1.7506 + cimg::X11attr().nb_bits,ZPixmap,0,(char*)data,ndimx,ndimy,8,0); 1.7507 + } 1.7508 + } 1.7509 + 1.7510 + void _init_fullscreen() { 1.7511 + background_window = 0; 1.7512 + if (is_fullscreen && !is_closed) { 1.7513 +#ifdef cimg_use_xrandr 1.7514 + int foo; 1.7515 + if (XRRQueryExtension(cimg::X11attr().display,&foo,&foo)) { 1.7516 + XRRRotations(cimg::X11attr().display, DefaultScreen(cimg::X11attr().display), &cimg::X11attr().curr_rotation); 1.7517 + if (!cimg::X11attr().resolutions) { 1.7518 + cimg::X11attr().resolutions = XRRSizes(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display),&foo); 1.7519 + cimg::X11attr().nb_resolutions = (unsigned int)foo; 1.7520 + } 1.7521 + if (cimg::X11attr().resolutions) { 1.7522 + cimg::X11attr().curr_resolution = 0; 1.7523 + for (unsigned int i=0; i<cimg::X11attr().nb_resolutions; ++i) { 1.7524 + const unsigned int 1.7525 + nw = (unsigned int)(cimg::X11attr().resolutions[i].width), 1.7526 + nh = (unsigned int)(cimg::X11attr().resolutions[i].height); 1.7527 + if (nw>=width && nh>=height && 1.7528 + nw<=(unsigned int)(cimg::X11attr().resolutions[cimg::X11attr().curr_resolution].width) && 1.7529 + nh<=(unsigned int)(cimg::X11attr().resolutions[cimg::X11attr().curr_resolution].height)) 1.7530 + cimg::X11attr().curr_resolution = i; 1.7531 + } 1.7532 + if (cimg::X11attr().curr_resolution>0) { 1.7533 + XRRScreenConfiguration *config = XRRGetScreenInfo(cimg::X11attr().display, DefaultRootWindow(cimg::X11attr().display)); 1.7534 + XRRSetScreenConfig(cimg::X11attr().display, config, DefaultRootWindow(cimg::X11attr().display), 1.7535 + cimg::X11attr().curr_resolution, cimg::X11attr().curr_rotation, CurrentTime); 1.7536 + XRRFreeScreenConfigInfo(config); 1.7537 + XSync(cimg::X11attr().display, False); 1.7538 + } 1.7539 + } 1.7540 + } 1.7541 + if (!cimg::X11attr().resolutions) 1.7542 + cimg::warn("CImgDisplay::_create_window() : Xrandr extension is not supported by the X server."); 1.7543 +#endif 1.7544 + const unsigned int sx = screen_dimx(), sy = screen_dimy(); 1.7545 + XSetWindowAttributes winattr; 1.7546 + winattr.override_redirect = True; 1.7547 + if (sx!=width || sy!=height) { 1.7548 + background_window = XCreateWindow(cimg::X11attr().display, 1.7549 + RootWindow(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)),0,0, 1.7550 + sx,sy,0,0,InputOutput,CopyFromParent,CWOverrideRedirect,&winattr); 1.7551 + const unsigned int bufsize = sx*sy*(cimg::X11attr().nb_bits==8?1:(cimg::X11attr().nb_bits==16?2:4)); 1.7552 + void *background_data = cimg_std::malloc(bufsize); 1.7553 + cimg_std::memset(background_data,0,bufsize); 1.7554 + XImage *background_image = XCreateImage(cimg::X11attr().display,DefaultVisual(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)), 1.7555 + cimg::X11attr().nb_bits,ZPixmap,0,(char*)background_data,sx,sy,8,0); 1.7556 + XEvent event; 1.7557 + XSelectInput(cimg::X11attr().display,background_window,StructureNotifyMask); 1.7558 + XMapRaised(cimg::X11attr().display,background_window); 1.7559 + do XWindowEvent(cimg::X11attr().display,background_window,StructureNotifyMask,&event); 1.7560 + while (event.type!=MapNotify); 1.7561 +#ifdef cimg_use_xshm 1.7562 + if (shminfo) XShmPutImage(cimg::X11attr().display,background_window,*cimg::X11attr().gc,background_image,0,0,0,0,sx,sy,False); 1.7563 + else 1.7564 +#endif 1.7565 + XPutImage(cimg::X11attr().display,background_window,*cimg::X11attr().gc,background_image,0,0,0,0,sx,sy); 1.7566 + XWindowAttributes attr; 1.7567 + XGetWindowAttributes(cimg::X11attr().display, background_window, &attr); 1.7568 + while (attr.map_state != IsViewable) XSync(cimg::X11attr().display, False); 1.7569 + XDestroyImage(background_image); 1.7570 + } 1.7571 + } 1.7572 + } 1.7573 + 1.7574 + void _desinit_fullscreen() { 1.7575 + if (is_fullscreen) { 1.7576 + XUngrabKeyboard(cimg::X11attr().display,CurrentTime); 1.7577 +#ifdef cimg_use_xrandr 1.7578 + if (cimg::X11attr().resolutions && cimg::X11attr().curr_resolution) { 1.7579 + XRRScreenConfiguration *config = XRRGetScreenInfo(cimg::X11attr().display, DefaultRootWindow(cimg::X11attr().display)); 1.7580 + XRRSetScreenConfig(cimg::X11attr().display, config, DefaultRootWindow(cimg::X11attr().display), 1.7581 + 0, cimg::X11attr().curr_rotation, CurrentTime); 1.7582 + XRRFreeScreenConfigInfo(config); 1.7583 + XSync(cimg::X11attr().display, False); 1.7584 + cimg::X11attr().curr_resolution = 0; 1.7585 + } 1.7586 +#endif 1.7587 + if (background_window) XDestroyWindow(cimg::X11attr().display,background_window); 1.7588 + background_window = 0; 1.7589 + is_fullscreen = false; 1.7590 + } 1.7591 + } 1.7592 + 1.7593 + static int _assign_xshm(Display *dpy, XErrorEvent *error) { 1.7594 + dpy = 0; error = 0; 1.7595 + cimg::X11attr().shm_enabled = false; 1.7596 + return 0; 1.7597 + } 1.7598 + 1.7599 + void _assign(const unsigned int dimw, const unsigned int dimh, const char *ptitle=0, 1.7600 + const unsigned int normalization_type=3, 1.7601 + const bool fullscreen_flag=false, const bool closed_flag=false) { 1.7602 + 1.7603 + // Allocate space for window title 1.7604 + const int s = cimg::strlen(ptitle)+1; 1.7605 + char *tmp_title = s?new char[s]:0; 1.7606 + if (s) cimg_std::memcpy(tmp_title,ptitle,s*sizeof(char)); 1.7607 + 1.7608 + // Destroy previous display window if existing 1.7609 + if (!is_empty()) assign(); 1.7610 + 1.7611 + // Open X11 display if necessary. 1.7612 + if (!cimg::X11attr().display) { 1.7613 + static bool xinit_threads = false; 1.7614 + if (!xinit_threads) { XInitThreads(); xinit_threads = true; } 1.7615 + cimg::X11attr().nb_wins = 0; 1.7616 + cimg::X11attr().display = XOpenDisplay((cimg_std::getenv("DISPLAY")?cimg_std::getenv("DISPLAY"):":0.0")); 1.7617 + if (!cimg::X11attr().display) 1.7618 + throw CImgDisplayException("CImgDisplay::_create_window() : Can't open X11 display"); 1.7619 + cimg::X11attr().nb_bits = DefaultDepth(cimg::X11attr().display, DefaultScreen(cimg::X11attr().display)); 1.7620 + if (cimg::X11attr().nb_bits!=8 && cimg::X11attr().nb_bits!=16 && cimg::X11attr().nb_bits!=24 && cimg::X11attr().nb_bits!=32) 1.7621 + throw CImgDisplayException("CImgDisplay::_create_window() : %u bits mode is not supported " 1.7622 + "(only 8, 16, 24 and 32 bits modes are supported)",cimg::X11attr().nb_bits); 1.7623 + cimg::X11attr().gc = new GC; 1.7624 + *cimg::X11attr().gc = DefaultGC(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)); 1.7625 + Visual *visual = DefaultVisual(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)); 1.7626 + XVisualInfo vtemplate; 1.7627 + vtemplate.visualid = XVisualIDFromVisual(visual); 1.7628 + int nb_visuals; 1.7629 + XVisualInfo *vinfo = XGetVisualInfo(cimg::X11attr().display,VisualIDMask,&vtemplate,&nb_visuals); 1.7630 + if (vinfo && vinfo->red_mask<vinfo->blue_mask) cimg::X11attr().blue_first = true; 1.7631 + cimg::X11attr().byte_order = ImageByteOrder(cimg::X11attr().display); 1.7632 + XFree(vinfo); 1.7633 + XLockDisplay(cimg::X11attr().display); 1.7634 + cimg::X11attr().event_thread = new pthread_t; 1.7635 + pthread_create(cimg::X11attr().event_thread,0,_events_thread,0); 1.7636 + } else XLockDisplay(cimg::X11attr().display); 1.7637 + 1.7638 + // Set display variables 1.7639 + width = cimg::min(dimw,(unsigned int)screen_dimx()); 1.7640 + height = cimg::min(dimh,(unsigned int)screen_dimy()); 1.7641 + normalization = normalization_type<4?normalization_type:3; 1.7642 + is_fullscreen = fullscreen_flag; 1.7643 + window_x = window_y = 0; 1.7644 + is_closed = closed_flag; 1.7645 + title = tmp_title; 1.7646 + flush(); 1.7647 + 1.7648 + // Create X11 window and palette (if 8bits display) 1.7649 + if (is_fullscreen) { 1.7650 + if (!is_closed) _init_fullscreen(); 1.7651 + const unsigned int sx = screen_dimx(), sy = screen_dimy(); 1.7652 + XSetWindowAttributes winattr; 1.7653 + winattr.override_redirect = True; 1.7654 + window = XCreateWindow(cimg::X11attr().display, 1.7655 + RootWindow(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)), 1.7656 + (sx-width)/2,(sy-height)/2, 1.7657 + width,height,0,0,InputOutput,CopyFromParent,CWOverrideRedirect,&winattr); 1.7658 + } else 1.7659 + window = XCreateSimpleWindow(cimg::X11attr().display, 1.7660 + RootWindow(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)), 1.7661 + 0,0,width,height,2,0,0x0L); 1.7662 + XStoreName(cimg::X11attr().display,window,title?title:" "); 1.7663 + if (cimg::X11attr().nb_bits==8) { 1.7664 + colormap = XCreateColormap(cimg::X11attr().display,window,DefaultVisual(cimg::X11attr().display, 1.7665 + DefaultScreen(cimg::X11attr().display)),AllocAll); 1.7666 + _set_colormap(colormap,3); 1.7667 + XSetWindowColormap(cimg::X11attr().display,window,colormap); 1.7668 + } 1.7669 + window_width = width; 1.7670 + window_height = height; 1.7671 + 1.7672 + // Create XImage 1.7673 + const unsigned int bufsize = width*height*(cimg::X11attr().nb_bits==8?1:(cimg::X11attr().nb_bits==16?2:4)); 1.7674 +#ifdef cimg_use_xshm 1.7675 + shminfo = 0; 1.7676 + if (XShmQueryExtension(cimg::X11attr().display)) { 1.7677 + shminfo = new XShmSegmentInfo; 1.7678 + image = XShmCreateImage(cimg::X11attr().display,DefaultVisual(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)), 1.7679 + cimg::X11attr().nb_bits,ZPixmap,0,shminfo,width,height); 1.7680 + if (!image) { 1.7681 + delete shminfo; 1.7682 + shminfo = 0; 1.7683 + } else { 1.7684 + shminfo->shmid = shmget(IPC_PRIVATE, bufsize, IPC_CREAT | 0777); 1.7685 + if (shminfo->shmid==-1) { 1.7686 + XDestroyImage(image); 1.7687 + delete shminfo; 1.7688 + shminfo = 0; 1.7689 + } else { 1.7690 + shminfo->shmaddr = image->data = (char*)(data = shmat(shminfo->shmid,0,0)); 1.7691 + if (shminfo->shmaddr==(char*)-1) { 1.7692 + shmctl(shminfo->shmid,IPC_RMID,0); 1.7693 + XDestroyImage(image); 1.7694 + delete shminfo; 1.7695 + shminfo = 0; 1.7696 + } else { 1.7697 + shminfo->readOnly = False; 1.7698 + cimg::X11attr().shm_enabled = true; 1.7699 + XErrorHandler oldXErrorHandler = XSetErrorHandler(_assign_xshm); 1.7700 + XShmAttach(cimg::X11attr().display, shminfo); 1.7701 + XSync(cimg::X11attr().display, False); 1.7702 + XSetErrorHandler(oldXErrorHandler); 1.7703 + if (!cimg::X11attr().shm_enabled) { 1.7704 + shmdt(shminfo->shmaddr); 1.7705 + shmctl(shminfo->shmid,IPC_RMID,0); 1.7706 + XDestroyImage(image); 1.7707 + delete shminfo; 1.7708 + shminfo = 0; 1.7709 + } 1.7710 + } 1.7711 + } 1.7712 + } 1.7713 + } 1.7714 + if (!shminfo) 1.7715 +#endif 1.7716 + { 1.7717 + data = cimg_std::malloc(bufsize); 1.7718 + image = XCreateImage(cimg::X11attr().display,DefaultVisual(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)), 1.7719 + cimg::X11attr().nb_bits,ZPixmap,0,(char*)data,width,height,8,0); 1.7720 + } 1.7721 + 1.7722 + wm_delete_window = XInternAtom(cimg::X11attr().display, "WM_DELETE_WINDOW", False); 1.7723 + wm_delete_protocol = XInternAtom(cimg::X11attr().display, "WM_PROTOCOLS", False); 1.7724 + XSetWMProtocols(cimg::X11attr().display, window, &wm_delete_window, 1); 1.7725 + XSelectInput(cimg::X11attr().display,window, 1.7726 + ExposureMask | StructureNotifyMask | ButtonPressMask | KeyPressMask | PointerMotionMask | 1.7727 + EnterWindowMask | LeaveWindowMask | ButtonReleaseMask | KeyReleaseMask); 1.7728 + if (is_fullscreen) XGrabKeyboard(cimg::X11attr().display, window, True, GrabModeAsync, GrabModeAsync, CurrentTime); 1.7729 + cimg::X11attr().wins[cimg::X11attr().nb_wins++]=this; 1.7730 + if (!is_closed) _map_window(); else { window_x = window_y = cimg::type<int>::min(); } 1.7731 + XUnlockDisplay(cimg::X11attr().display); 1.7732 + } 1.7733 + 1.7734 + CImgDisplay& assign() { 1.7735 + if (is_empty()) return *this; 1.7736 + XLockDisplay(cimg::X11attr().display); 1.7737 + 1.7738 + // Remove display window from event thread list. 1.7739 + unsigned int i; 1.7740 + for (i = 0; i<cimg::X11attr().nb_wins && cimg::X11attr().wins[i]!=this; ++i) {} 1.7741 + for (; i<cimg::X11attr().nb_wins-1; ++i) cimg::X11attr().wins[i] = cimg::X11attr().wins[i+1]; 1.7742 + --cimg::X11attr().nb_wins; 1.7743 + 1.7744 + // Destroy window, image, colormap and title. 1.7745 + if (is_fullscreen && !is_closed) _desinit_fullscreen(); 1.7746 + XDestroyWindow(cimg::X11attr().display,window); 1.7747 + window = 0; 1.7748 +#ifdef cimg_use_xshm 1.7749 + if (shminfo) { 1.7750 + XShmDetach(cimg::X11attr().display, shminfo); 1.7751 + XDestroyImage(image); 1.7752 + shmdt(shminfo->shmaddr); 1.7753 + shmctl(shminfo->shmid,IPC_RMID,0); 1.7754 + delete shminfo; 1.7755 + shminfo = 0; 1.7756 + } else 1.7757 +#endif 1.7758 + XDestroyImage(image); 1.7759 + data = 0; image = 0; 1.7760 + if (cimg::X11attr().nb_bits==8) XFreeColormap(cimg::X11attr().display,colormap); 1.7761 + colormap = 0; 1.7762 + XSync(cimg::X11attr().display, False); 1.7763 + 1.7764 + // Reset display variables 1.7765 + if (title) delete[] title; 1.7766 + width = height = normalization = window_width = window_height = 0; 1.7767 + window_x = window_y = 0; 1.7768 + is_fullscreen = false; 1.7769 + is_closed = true; 1.7770 + min = max = 0; 1.7771 + title = 0; 1.7772 + flush(); 1.7773 + 1.7774 + // End event thread and close display if necessary 1.7775 + XUnlockDisplay(cimg::X11attr().display); 1.7776 + 1.7777 + /* The code below was used to close the X11 display when not used anymore, 1.7778 + unfortunately, since the latest Xorg versions, it randomely hangs, so 1.7779 + I prefer to remove it. A fix would be needed anyway. 1.7780 + 1.7781 + if (!cimg::X11attr().nb_wins) { 1.7782 + // Kill event thread 1.7783 + pthread_cancel(*cimg::X11attr().event_thread); 1.7784 + XUnlockDisplay(cimg::X11attr().display); 1.7785 + pthread_join(*cimg::X11attr().event_thread,0); 1.7786 + delete cimg::X11attr().event_thread; 1.7787 + cimg::X11attr().event_thread = 0; 1.7788 + XCloseDisplay(cimg::X11attr().display); 1.7789 + cimg::X11attr().display = 0; 1.7790 + delete cimg::X11attr().gc; 1.7791 + cimg::X11attr().gc = 0; 1.7792 + } else XUnlockDisplay(cimg::X11attr().display); 1.7793 + */ 1.7794 + return *this; 1.7795 + } 1.7796 + 1.7797 + CImgDisplay& assign(const unsigned int dimw, const unsigned int dimh, const char *title=0, 1.7798 + const unsigned int normalization_type=3, 1.7799 + const bool fullscreen_flag=false, const bool closed_flag=false) { 1.7800 + if (!dimw || !dimh) return assign(); 1.7801 + _assign(dimw,dimh,title,normalization_type,fullscreen_flag,closed_flag); 1.7802 + min = max = 0; 1.7803 + cimg_std::memset(data,0,(cimg::X11attr().nb_bits==8?sizeof(unsigned char): 1.7804 + (cimg::X11attr().nb_bits==16?sizeof(unsigned short):sizeof(unsigned int)))*width*height); 1.7805 + return paint(); 1.7806 + } 1.7807 + 1.7808 + template<typename T> 1.7809 + CImgDisplay& assign(const CImg<T>& img, const char *title=0, 1.7810 + const unsigned int normalization_type=3, 1.7811 + const bool fullscreen_flag=false, const bool closed_flag=false) { 1.7812 + if (!img) return assign(); 1.7813 + CImg<T> tmp; 1.7814 + const CImg<T>& nimg = (img.depth==1)?img:(tmp=img.get_projections2d(img.width/2,img.height/2,img.depth/2)); 1.7815 + _assign(nimg.width,nimg.height,title,normalization_type,fullscreen_flag,closed_flag); 1.7816 + if (normalization==2) min = (float)nimg.minmax(max); 1.7817 + return render(nimg).paint(); 1.7818 + } 1.7819 + 1.7820 + template<typename T> 1.7821 + CImgDisplay& assign(const CImgList<T>& list, const char *title=0, 1.7822 + const unsigned int normalization_type=3, 1.7823 + const bool fullscreen_flag=false, const bool closed_flag=false) { 1.7824 + if (!list) return assign(); 1.7825 + CImg<T> tmp; 1.7826 + const CImg<T> img = list.get_append('x','p'), 1.7827 + &nimg = (img.depth==1)?img:(tmp=img.get_projections2d(img.width/2,img.height/2,img.depth/2)); 1.7828 + _assign(nimg.width,nimg.height,title,normalization_type,fullscreen_flag,closed_flag); 1.7829 + if (normalization==2) min = (float)nimg.minmax(max); 1.7830 + return render(nimg).paint(); 1.7831 + } 1.7832 + 1.7833 + CImgDisplay& assign(const CImgDisplay& win) { 1.7834 + if (!win) return assign(); 1.7835 + _assign(win.width,win.height,win.title,win.normalization,win.is_fullscreen,win.is_closed); 1.7836 + cimg_std::memcpy(data,win.data,(cimg::X11attr().nb_bits==8?sizeof(unsigned char): 1.7837 + cimg::X11attr().nb_bits==16?sizeof(unsigned short): 1.7838 + sizeof(unsigned int))*width*height); 1.7839 + return paint(); 1.7840 + } 1.7841 + 1.7842 + CImgDisplay& resize(const int nwidth, const int nheight, const bool redraw=true) { 1.7843 + if (!nwidth || !nheight || (is_empty() && (nwidth<0 || nheight<0))) return assign(); 1.7844 + if (is_empty()) return assign(nwidth,nheight); 1.7845 + const unsigned int 1.7846 + tmpdimx = (nwidth>0)?nwidth:(-nwidth*width/100), 1.7847 + tmpdimy = (nheight>0)?nheight:(-nheight*height/100), 1.7848 + dimx = tmpdimx?tmpdimx:1, 1.7849 + dimy = tmpdimy?tmpdimy:1; 1.7850 + XLockDisplay(cimg::X11attr().display); 1.7851 + if (window_width!=dimx || window_height!=dimy) XResizeWindow(cimg::X11attr().display,window,dimx,dimy); 1.7852 + if (width!=dimx || height!=dimy) switch (cimg::X11attr().nb_bits) { 1.7853 + case 8 : { unsigned char foo = 0; _resize(foo,dimx,dimy,redraw); } break; 1.7854 + case 16 : { unsigned short foo = 0; _resize(foo,dimx,dimy,redraw); } break; 1.7855 + default : { unsigned int foo = 0; _resize(foo,dimx,dimy,redraw); } 1.7856 + } 1.7857 + window_width = width = dimx; window_height = height = dimy; 1.7858 + is_resized = false; 1.7859 + XUnlockDisplay(cimg::X11attr().display); 1.7860 + if (is_fullscreen) move((screen_dimx()-width)/2,(screen_dimy()-height)/2); 1.7861 + if (redraw) return paint(); 1.7862 + return *this; 1.7863 + } 1.7864 + 1.7865 + CImgDisplay& toggle_fullscreen(const bool redraw=true) { 1.7866 + if (is_empty()) return *this; 1.7867 + if (redraw) { 1.7868 + const unsigned int bufsize = width*height*(cimg::X11attr().nb_bits==8?1:(cimg::X11attr().nb_bits==16?2:4)); 1.7869 + void *odata = cimg_std::malloc(bufsize); 1.7870 + cimg_std::memcpy(odata,data,bufsize); 1.7871 + assign(width,height,title,normalization,!is_fullscreen,false); 1.7872 + cimg_std::memcpy(data,odata,bufsize); 1.7873 + cimg_std::free(odata); 1.7874 + return paint(false); 1.7875 + } 1.7876 + return assign(width,height,title,normalization,!is_fullscreen,false); 1.7877 + } 1.7878 + 1.7879 + CImgDisplay& show() { 1.7880 + if (!is_empty() && is_closed) { 1.7881 + XLockDisplay(cimg::X11attr().display); 1.7882 + if (is_fullscreen) _init_fullscreen(); 1.7883 + _map_window(); 1.7884 + is_closed = false; 1.7885 + XUnlockDisplay(cimg::X11attr().display); 1.7886 + return paint(); 1.7887 + } 1.7888 + return *this; 1.7889 + } 1.7890 + 1.7891 + CImgDisplay& close() { 1.7892 + if (!is_empty() && !is_closed) { 1.7893 + XLockDisplay(cimg::X11attr().display); 1.7894 + if (is_fullscreen) _desinit_fullscreen(); 1.7895 + XUnmapWindow(cimg::X11attr().display,window); 1.7896 + window_x = window_y = -1; 1.7897 + is_closed = true; 1.7898 + XUnlockDisplay(cimg::X11attr().display); 1.7899 + } 1.7900 + return *this; 1.7901 + } 1.7902 + 1.7903 + CImgDisplay& move(const int posx, const int posy) { 1.7904 + if (is_empty()) return *this; 1.7905 + show(); 1.7906 + XLockDisplay(cimg::X11attr().display); 1.7907 + XMoveWindow(cimg::X11attr().display,window,posx,posy); 1.7908 + window_x = posx; window_y = posy; 1.7909 + is_moved = false; 1.7910 + XUnlockDisplay(cimg::X11attr().display); 1.7911 + return paint(); 1.7912 + } 1.7913 + 1.7914 + CImgDisplay& show_mouse() { 1.7915 + if (is_empty()) return *this; 1.7916 + XLockDisplay(cimg::X11attr().display); 1.7917 + XDefineCursor(cimg::X11attr().display,window,None); 1.7918 + XUnlockDisplay(cimg::X11attr().display); 1.7919 + return *this; 1.7920 + } 1.7921 + 1.7922 + CImgDisplay& hide_mouse() { 1.7923 + if (is_empty()) return *this; 1.7924 + XLockDisplay(cimg::X11attr().display); 1.7925 + const char pix_data[8] = { 0 }; 1.7926 + XColor col; 1.7927 + col.red = col.green = col.blue = 0; 1.7928 + Pixmap pix = XCreateBitmapFromData(cimg::X11attr().display,window,pix_data,8,8); 1.7929 + Cursor cur = XCreatePixmapCursor(cimg::X11attr().display,pix,pix,&col,&col,0,0); 1.7930 + XFreePixmap(cimg::X11attr().display,pix); 1.7931 + XDefineCursor(cimg::X11attr().display,window,cur); 1.7932 + XUnlockDisplay(cimg::X11attr().display); 1.7933 + return *this; 1.7934 + } 1.7935 + 1.7936 + CImgDisplay& set_mouse(const int posx, const int posy) { 1.7937 + if (is_empty() || is_closed) return *this; 1.7938 + XLockDisplay(cimg::X11attr().display); 1.7939 + XWarpPointer(cimg::X11attr().display,None,window,0,0,0,0,posx,posy); 1.7940 + mouse_x = posx; mouse_y = posy; 1.7941 + is_moved = false; 1.7942 + XSync(cimg::X11attr().display, False); 1.7943 + XUnlockDisplay(cimg::X11attr().display); 1.7944 + return *this; 1.7945 + } 1.7946 + 1.7947 + CImgDisplay& set_title(const char *format, ...) { 1.7948 + if (is_empty()) return *this; 1.7949 + char tmp[1024] = {0}; 1.7950 + va_list ap; 1.7951 + va_start(ap, format); 1.7952 + cimg_std::vsprintf(tmp,format,ap); 1.7953 + va_end(ap); 1.7954 + if (title) delete[] title; 1.7955 + const int s = cimg::strlen(tmp)+1; 1.7956 + title = new char[s]; 1.7957 + cimg_std::memcpy(title,tmp,s*sizeof(char)); 1.7958 + XLockDisplay(cimg::X11attr().display); 1.7959 + XStoreName(cimg::X11attr().display,window,tmp); 1.7960 + XUnlockDisplay(cimg::X11attr().display); 1.7961 + return *this; 1.7962 + } 1.7963 + 1.7964 + template<typename T> 1.7965 + CImgDisplay& display(const CImg<T>& img) { 1.7966 + if (img.is_empty()) 1.7967 + throw CImgArgumentException("CImgDisplay::display() : Cannot display empty image."); 1.7968 + if (is_empty()) assign(img.width,img.height); 1.7969 + return render(img).paint(false); 1.7970 + } 1.7971 + 1.7972 + CImgDisplay& paint(const bool wait_expose=true) { 1.7973 + if (is_empty()) return *this; 1.7974 + XLockDisplay(cimg::X11attr().display); 1.7975 + _paint(wait_expose); 1.7976 + XUnlockDisplay(cimg::X11attr().display); 1.7977 + return *this; 1.7978 + } 1.7979 + 1.7980 + template<typename T> 1.7981 + CImgDisplay& render(const CImg<T>& img, const bool flag8=false) { 1.7982 + if (is_empty()) return *this; 1.7983 + if (!img) 1.7984 + throw CImgArgumentException("CImgDisplay::_render_image() : Specified input image (%u,%u,%u,%u,%p) is empty.", 1.7985 + img.width,img.height,img.depth,img.dim,img.data); 1.7986 + if (img.depth!=1) return render(img.get_projections2d(img.width/2,img.height/2,img.depth/2)); 1.7987 + if (cimg::X11attr().nb_bits==8 && (img.width!=width || img.height!=height)) return render(img.get_resize(width,height,1,-100,1)); 1.7988 + if (cimg::X11attr().nb_bits==8 && !flag8 && img.dim==3) return render(img.get_RGBtoLUT(true),true); 1.7989 + 1.7990 + const T 1.7991 + *data1 = img.data, 1.7992 + *data2 = (img.dim>1)?img.ptr(0,0,0,1):data1, 1.7993 + *data3 = (img.dim>2)?img.ptr(0,0,0,2):data1; 1.7994 + 1.7995 + if (cimg::X11attr().blue_first) cimg::swap(data1,data3); 1.7996 + XLockDisplay(cimg::X11attr().display); 1.7997 + 1.7998 + if (!normalization || (normalization==3 && cimg::type<T>::string()==cimg::type<unsigned char>::string())) { 1.7999 + min = max = 0; 1.8000 + switch (cimg::X11attr().nb_bits) { 1.8001 + case 8 : { // 256 color palette, no normalization 1.8002 + _set_colormap(colormap,img.dim); 1.8003 + unsigned char *const ndata = (img.width==width && img.height==height)?(unsigned char*)data:new unsigned char[img.width*img.height]; 1.8004 + unsigned char *ptrd = (unsigned char*)ndata; 1.8005 + switch (img.dim) { 1.8006 + case 1 : for (unsigned int xy = img.width*img.height; xy>0; --xy) (*ptrd++) = (unsigned char)*(data1++); 1.8007 + break; 1.8008 + case 2 : for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8009 + const unsigned char R = (unsigned char)*(data1++), G = (unsigned char)*(data2++); 1.8010 + (*ptrd++) = (R&0xf0) | (G>>4); 1.8011 + } break; 1.8012 + default : for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8013 + const unsigned char R = (unsigned char)*(data1++), G = (unsigned char)*(data2++), B = (unsigned char)*(data3++); 1.8014 + (*ptrd++) = (R&0xe0) | ((G>>5)<<2) | (B>>6); 1.8015 + } 1.8016 + } 1.8017 + if (ndata!=data) { _render_resize(ndata,img.width,img.height,(unsigned char*)data,width,height); delete[] ndata; } 1.8018 + } break; 1.8019 + case 16 : { // 16 bits colors, no normalization 1.8020 + unsigned short *const ndata = (img.width==width && img.height==height)?(unsigned short*)data:new unsigned short[img.width*img.height]; 1.8021 + unsigned char *ptrd = (unsigned char*)ndata; 1.8022 + const unsigned int M = 248; 1.8023 + switch (img.dim) { 1.8024 + case 1 : 1.8025 + if (cimg::X11attr().byte_order) for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8026 + const unsigned char val = (unsigned char)*(data1++), G = val>>2; 1.8027 + *(ptrd++) = (val&M) | (G>>3); 1.8028 + *(ptrd++) = (G<<5) | (G>>1); 1.8029 + } else for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8030 + const unsigned char val = (unsigned char)*(data1++), G = val>>2; 1.8031 + *(ptrd++) = (G<<5) | (G>>1); 1.8032 + *(ptrd++) = (val&M) | (G>>3); 1.8033 + } 1.8034 + break; 1.8035 + case 2 : 1.8036 + if (cimg::X11attr().byte_order) for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8037 + const unsigned char G = (unsigned char)*(data2++)>>2; 1.8038 + *(ptrd++) = ((unsigned char)*(data1++)&M) | (G>>3); 1.8039 + *(ptrd++) = (G<<5); 1.8040 + } else for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8041 + const unsigned char G = (unsigned char)*(data2++)>>2; 1.8042 + *(ptrd++) = (G<<5); 1.8043 + *(ptrd++) = ((unsigned char)*(data1++)&M) | (G>>3); 1.8044 + } 1.8045 + break; 1.8046 + default : 1.8047 + if (cimg::X11attr().byte_order) for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8048 + const unsigned char G = (unsigned char)*(data2++)>>2; 1.8049 + *(ptrd++) = ((unsigned char)*(data1++)&M) | (G>>3); 1.8050 + *(ptrd++) = (G<<5) | ((unsigned char)*(data3++)>>3); 1.8051 + } else for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8052 + const unsigned char G = (unsigned char)*(data2++)>>2; 1.8053 + *(ptrd++) = (G<<5) | ((unsigned char)*(data3++)>>3); 1.8054 + *(ptrd++) = ((unsigned char)*(data1++)&M) | (G>>3); 1.8055 + } 1.8056 + } 1.8057 + if (ndata!=data) { _render_resize(ndata,img.width,img.height,(unsigned short*)data,width,height); delete[] ndata; } 1.8058 + } break; 1.8059 + default : { // 24 bits colors, no normalization 1.8060 + unsigned int *const ndata = (img.width==width && img.height==height)?(unsigned int*)data:new unsigned int[img.width*img.height]; 1.8061 + if (sizeof(int)==4) { // 32 bits int uses optimized version 1.8062 + unsigned int *ptrd = ndata; 1.8063 + switch (img.dim) { 1.8064 + case 1 : 1.8065 + if (cimg::X11attr().byte_order==cimg::endianness()) 1.8066 + for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8067 + const unsigned char val = (unsigned char)*(data1++); 1.8068 + *(ptrd++) = (val<<16) | (val<<8) | val; 1.8069 + } 1.8070 + else 1.8071 + for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8072 + const unsigned char val = (unsigned char)*(data1++)<<8; 1.8073 + *(ptrd++) = (val<<16) | (val<<8) | val; 1.8074 + } 1.8075 + break; 1.8076 + case 2 : 1.8077 + if (cimg::X11attr().byte_order==cimg::endianness()) 1.8078 + for (unsigned int xy = img.width*img.height; xy>0; --xy) 1.8079 + *(ptrd++) = ((unsigned char)*(data1++)<<16) | ((unsigned char)*(data2++)<<8); 1.8080 + else 1.8081 + for (unsigned int xy = img.width*img.height; xy>0; --xy) 1.8082 + *(ptrd++) = ((unsigned char)*(data2++)<<16) | ((unsigned char)*(data1++)<<8); 1.8083 + break; 1.8084 + default : 1.8085 + if (cimg::X11attr().byte_order==cimg::endianness()) 1.8086 + for (unsigned int xy = img.width*img.height; xy>0; --xy) 1.8087 + *(ptrd++) = ((unsigned char)*(data1++)<<16) | ((unsigned char)*(data2++)<<8) | (unsigned char)*(data3++); 1.8088 + else 1.8089 + for (unsigned int xy = img.width*img.height; xy>0; --xy) 1.8090 + *(ptrd++) = ((unsigned char)*(data3++)<<24) | ((unsigned char)*(data2++)<<16) | ((unsigned char)*(data1++)<<8); 1.8091 + } 1.8092 + } else { 1.8093 + unsigned char *ptrd = (unsigned char*)ndata; 1.8094 + switch (img.dim) { 1.8095 + case 1 : 1.8096 + if (cimg::X11attr().byte_order) for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8097 + *(ptrd++) = 0; 1.8098 + *(ptrd++) = (unsigned char)*(data1++); 1.8099 + *(ptrd++) = 0; 1.8100 + *(ptrd++) = 0; 1.8101 + } else for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8102 + *(ptrd++) = 0; 1.8103 + *(ptrd++) = 0; 1.8104 + *(ptrd++) = (unsigned char)*(data1++); 1.8105 + *(ptrd++) = 0; 1.8106 + } 1.8107 + break; 1.8108 + case 2 : 1.8109 + if (cimg::X11attr().byte_order) cimg::swap(data1,data2); 1.8110 + for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8111 + *(ptrd++) = 0; 1.8112 + *(ptrd++) = (unsigned char)*(data2++); 1.8113 + *(ptrd++) = (unsigned char)*(data1++); 1.8114 + *(ptrd++) = 0; 1.8115 + } 1.8116 + break; 1.8117 + default : 1.8118 + if (cimg::X11attr().byte_order) for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8119 + *(ptrd++) = 0; 1.8120 + *(ptrd++) = (unsigned char)*(data1++); 1.8121 + *(ptrd++) = (unsigned char)*(data2++); 1.8122 + *(ptrd++) = (unsigned char)*(data3++); 1.8123 + } else for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8124 + *(ptrd++) = (unsigned char)*(data3++); 1.8125 + *(ptrd++) = (unsigned char)*(data2++); 1.8126 + *(ptrd++) = (unsigned char)*(data1++); 1.8127 + *(ptrd++) = 0; 1.8128 + } 1.8129 + } 1.8130 + } 1.8131 + if (ndata!=data) { _render_resize(ndata,img.width,img.height,(unsigned int*)data,width,height); delete[] ndata; } 1.8132 + } 1.8133 + }; 1.8134 + } else { 1.8135 + if (normalization==3) { 1.8136 + if (cimg::type<T>::is_float()) min = (float)img.minmax(max); 1.8137 + else { min = (float)cimg::type<T>::min(); max = (float)cimg::type<T>::max(); } 1.8138 + } else if ((min>max) || normalization==1) min = (float)img.minmax(max); 1.8139 + const float delta = max-min, mm = delta?delta:1.0f; 1.8140 + switch (cimg::X11attr().nb_bits) { 1.8141 + case 8 : { // 256 color palette, with normalization 1.8142 + _set_colormap(colormap,img.dim); 1.8143 + unsigned char *const ndata = (img.width==width && img.height==height)?(unsigned char*)data:new unsigned char[img.width*img.height]; 1.8144 + unsigned char *ptrd = (unsigned char*)ndata; 1.8145 + switch (img.dim) { 1.8146 + case 1 : for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8147 + const unsigned char R = (unsigned char)(255*(*(data1++)-min)/mm); 1.8148 + *(ptrd++) = R; 1.8149 + } break; 1.8150 + case 2 : for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8151 + const unsigned char 1.8152 + R = (unsigned char)(255*(*(data1++)-min)/mm), 1.8153 + G = (unsigned char)(255*(*(data2++)-min)/mm); 1.8154 + (*ptrd++) = (R&0xf0) | (G>>4); 1.8155 + } break; 1.8156 + default : 1.8157 + for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8158 + const unsigned char 1.8159 + R = (unsigned char)(255*(*(data1++)-min)/mm), 1.8160 + G = (unsigned char)(255*(*(data2++)-min)/mm), 1.8161 + B = (unsigned char)(255*(*(data3++)-min)/mm); 1.8162 + *(ptrd++) = (R&0xe0) | ((G>>5)<<2) | (B>>6); 1.8163 + } 1.8164 + } 1.8165 + if (ndata!=data) { _render_resize(ndata,img.width,img.height,(unsigned char*)data,width,height); delete[] ndata; } 1.8166 + } break; 1.8167 + case 16 : { // 16 bits colors, with normalization 1.8168 + unsigned short *const ndata = (img.width==width && img.height==height)?(unsigned short*)data:new unsigned short[img.width*img.height]; 1.8169 + unsigned char *ptrd = (unsigned char*)ndata; 1.8170 + const unsigned int M = 248; 1.8171 + switch (img.dim) { 1.8172 + case 1 : 1.8173 + if (cimg::X11attr().byte_order) for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8174 + const unsigned char val = (unsigned char)(255*(*(data1++)-min)/mm), G = val>>2; 1.8175 + *(ptrd++) = (val&M) | (G>>3); 1.8176 + *(ptrd++) = (G<<5) | (val>>3); 1.8177 + } else for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8178 + const unsigned char val = (unsigned char)(255*(*(data1++)-min)/mm), G = val>>2; 1.8179 + *(ptrd++) = (G<<5) | (val>>3); 1.8180 + *(ptrd++) = (val&M) | (G>>3); 1.8181 + } 1.8182 + break; 1.8183 + case 2 : 1.8184 + if (cimg::X11attr().byte_order) for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8185 + const unsigned char G = (unsigned char)(255*(*(data2++)-min)/mm)>>2; 1.8186 + *(ptrd++) = ((unsigned char)(255*(*(data1++)-min)/mm)&M) | (G>>3); 1.8187 + *(ptrd++) = (G<<5); 1.8188 + } else for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8189 + const unsigned char G = (unsigned char)(255*(*(data2++)-min)/mm)>>2; 1.8190 + *(ptrd++) = (G<<5); 1.8191 + *(ptrd++) = ((unsigned char)(255*(*(data1++)-min)/mm)&M) | (G>>3); 1.8192 + } 1.8193 + break; 1.8194 + default : 1.8195 + if (cimg::X11attr().byte_order) for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8196 + const unsigned char G = (unsigned char)(255*(*(data2++)-min)/mm)>>2; 1.8197 + *(ptrd++) = ((unsigned char)(255*(*(data1++)-min)/mm)&M) | (G>>3); 1.8198 + *(ptrd++) = (G<<5) | ((unsigned char)(255*(*(data3++)-min)/mm)>>3); 1.8199 + } else for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8200 + const unsigned char G = (unsigned char)(255*(*(data2++)-min)/mm)>>2; 1.8201 + *(ptrd++) = (G<<5) | ((unsigned char)(255*(*(data3++)-min)/mm)>>3); 1.8202 + *(ptrd++) = ((unsigned char)(255*(*(data1++)-min)/mm)&M) | (G>>3); 1.8203 + } 1.8204 + } 1.8205 + if (ndata!=data) { _render_resize(ndata,img.width,img.height,(unsigned short*)data,width,height); delete[] ndata; } 1.8206 + } break; 1.8207 + default : { // 24 bits colors, with normalization 1.8208 + unsigned int *const ndata = (img.width==width && img.height==height)?(unsigned int*)data:new unsigned int[img.width*img.height]; 1.8209 + if (sizeof(int)==4) { // 32 bits int uses optimized version 1.8210 + unsigned int *ptrd = ndata; 1.8211 + switch (img.dim) { 1.8212 + case 1 : 1.8213 + if (cimg::X11attr().byte_order==cimg::endianness()) 1.8214 + for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8215 + const unsigned char val = (unsigned char)(255*(*(data1++)-min)/mm); 1.8216 + *(ptrd++) = (val<<16) | (val<<8) | val; 1.8217 + } 1.8218 + else 1.8219 + for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8220 + const unsigned char val = (unsigned char)(255*(*(data1++)-min)/mm); 1.8221 + *(ptrd++) = (val<<24) | (val<<16) | (val<<8); 1.8222 + } 1.8223 + break; 1.8224 + case 2 : 1.8225 + if (cimg::X11attr().byte_order==cimg::endianness()) 1.8226 + for (unsigned int xy = img.width*img.height; xy>0; --xy) 1.8227 + *(ptrd++) = 1.8228 + ((unsigned char)(255*(*(data1++)-min)/mm)<<16) | 1.8229 + ((unsigned char)(255*(*(data2++)-min)/mm)<<8); 1.8230 + else 1.8231 + for (unsigned int xy = img.width*img.height; xy>0; --xy) 1.8232 + *(ptrd++) = 1.8233 + ((unsigned char)(255*(*(data2++)-min)/mm)<<16) | 1.8234 + ((unsigned char)(255*(*(data1++)-min)/mm)<<8); 1.8235 + break; 1.8236 + default : 1.8237 + if (cimg::X11attr().byte_order==cimg::endianness()) 1.8238 + for (unsigned int xy = img.width*img.height; xy>0; --xy) 1.8239 + *(ptrd++) = 1.8240 + ((unsigned char)(255*(*(data1++)-min)/mm)<<16) | 1.8241 + ((unsigned char)(255*(*(data2++)-min)/mm)<<8) | 1.8242 + (unsigned char)(255*(*(data3++)-min)/mm); 1.8243 + else 1.8244 + for (unsigned int xy = img.width*img.height; xy>0; --xy) 1.8245 + *(ptrd++) = 1.8246 + ((unsigned char)(255*(*(data3++)-min)/mm)<<24) | 1.8247 + ((unsigned char)(255*(*(data2++)-min)/mm)<<16) | 1.8248 + ((unsigned char)(255*(*(data1++)-min)/mm)<<8); 1.8249 + } 1.8250 + } else { 1.8251 + unsigned char *ptrd = (unsigned char*)ndata; 1.8252 + switch (img.dim) { 1.8253 + case 1 : 1.8254 + if (cimg::X11attr().byte_order) for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8255 + const unsigned char val = (unsigned char)(255*(*(data1++)-min)/mm); 1.8256 + (*ptrd++) = 0; 1.8257 + (*ptrd++) = val; 1.8258 + (*ptrd++) = val; 1.8259 + (*ptrd++) = val; 1.8260 + } else for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8261 + const unsigned char val = (unsigned char)(255*(*(data1++)-min)/mm); 1.8262 + (*ptrd++) = val; 1.8263 + (*ptrd++) = val; 1.8264 + (*ptrd++) = val; 1.8265 + (*ptrd++) = 0; 1.8266 + } 1.8267 + break; 1.8268 + case 2 : 1.8269 + if (cimg::X11attr().byte_order) cimg::swap(data1,data2); 1.8270 + for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8271 + (*ptrd++) = 0; 1.8272 + (*ptrd++) = (unsigned char)(255*(*(data2++)-min)/mm); 1.8273 + (*ptrd++) = (unsigned char)(255*(*(data1++)-min)/mm); 1.8274 + (*ptrd++) = 0; 1.8275 + } 1.8276 + break; 1.8277 + default : 1.8278 + if (cimg::X11attr().byte_order) for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8279 + (*ptrd++) = 0; 1.8280 + (*ptrd++) = (unsigned char)(255*(*(data1++)-min)/mm); 1.8281 + (*ptrd++) = (unsigned char)(255*(*(data2++)-min)/mm); 1.8282 + (*ptrd++) = (unsigned char)(255*(*(data3++)-min)/mm); 1.8283 + } else for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8284 + (*ptrd++) = (unsigned char)(255*(*(data3++)-min)/mm); 1.8285 + (*ptrd++) = (unsigned char)(255*(*(data2++)-min)/mm); 1.8286 + (*ptrd++) = (unsigned char)(255*(*(data1++)-min)/mm); 1.8287 + (*ptrd++) = 0; 1.8288 + } 1.8289 + } 1.8290 + } 1.8291 + if (ndata!=data) { _render_resize(ndata,img.width,img.height,(unsigned int*)data,width,height); delete[] ndata; } 1.8292 + } 1.8293 + } 1.8294 + } 1.8295 + XUnlockDisplay(cimg::X11attr().display); 1.8296 + return *this; 1.8297 + } 1.8298 + 1.8299 + template<typename T> 1.8300 + const CImgDisplay& snapshot(CImg<T>& img) const { 1.8301 + if (is_empty()) img.assign(); 1.8302 + else { 1.8303 + img.assign(width,height,1,3); 1.8304 + T 1.8305 + *data1 = img.ptr(0,0,0,0), 1.8306 + *data2 = img.ptr(0,0,0,1), 1.8307 + *data3 = img.ptr(0,0,0,2); 1.8308 + if (cimg::X11attr().blue_first) cimg::swap(data1,data3); 1.8309 + switch (cimg::X11attr().nb_bits) { 1.8310 + case 8 : { 1.8311 + unsigned char *ptrs = (unsigned char*)data; 1.8312 + for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8313 + const unsigned char val = *(ptrs++); 1.8314 + *(data1++) = val&0xe0; 1.8315 + *(data2++) = (val&0x1c)<<3; 1.8316 + *(data3++) = val<<6; 1.8317 + } 1.8318 + } break; 1.8319 + case 16 : { 1.8320 + unsigned char *ptrs = (unsigned char*)data; 1.8321 + if (cimg::X11attr().byte_order) for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8322 + const unsigned char val0 = *(ptrs++), val1 = *(ptrs++); 1.8323 + *(data1++) = val0&0xf8; 1.8324 + *(data2++) = (val0<<5) | ((val1&0xe0)>>5); 1.8325 + *(data3++) = val1<<3; 1.8326 + } else for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8327 + const unsigned short val0 = *(ptrs++), val1 = *(ptrs++); 1.8328 + *(data1++) = val1&0xf8; 1.8329 + *(data2++) = (val1<<5) | ((val0&0xe0)>>5); 1.8330 + *(data3++) = val0<<3; 1.8331 + } 1.8332 + } break; 1.8333 + default : { 1.8334 + unsigned char *ptrs = (unsigned char*)data; 1.8335 + if (cimg::X11attr().byte_order) for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8336 + ++ptrs; 1.8337 + *(data1++) = *(ptrs++); 1.8338 + *(data2++) = *(ptrs++); 1.8339 + *(data3++) = *(ptrs++); 1.8340 + } else for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8341 + *(data3++) = *(ptrs++); 1.8342 + *(data2++) = *(ptrs++); 1.8343 + *(data1++) = *(ptrs++); 1.8344 + ++ptrs; 1.8345 + } 1.8346 + } 1.8347 + } 1.8348 + } 1.8349 + return *this; 1.8350 + } 1.8351 + 1.8352 + // Windows-based display 1.8353 + //----------------------- 1.8354 +#elif cimg_display==2 1.8355 + CLIENTCREATESTRUCT ccs; 1.8356 + BITMAPINFO bmi; 1.8357 + unsigned int *data; 1.8358 + DEVMODE curr_mode; 1.8359 + HWND window; 1.8360 + HWND background_window; 1.8361 + HDC hdc; 1.8362 + HANDLE thread; 1.8363 + HANDLE created; 1.8364 + HANDLE mutex; 1.8365 + bool mouse_tracking; 1.8366 + bool visible_cursor; 1.8367 + 1.8368 + static int screen_dimx() { 1.8369 + DEVMODE mode; 1.8370 + mode.dmSize = sizeof(DEVMODE); 1.8371 + mode.dmDriverExtra = 0; 1.8372 + EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&mode); 1.8373 + return mode.dmPelsWidth; 1.8374 + } 1.8375 + 1.8376 + static int screen_dimy() { 1.8377 + DEVMODE mode; 1.8378 + mode.dmSize = sizeof(DEVMODE); 1.8379 + mode.dmDriverExtra = 0; 1.8380 + EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&mode); 1.8381 + return mode.dmPelsHeight; 1.8382 + } 1.8383 + 1.8384 + static void wait_all() { 1.8385 + WaitForSingleObject(cimg::Win32attr().wait_event,INFINITE); 1.8386 + } 1.8387 + 1.8388 + static LRESULT APIENTRY _handle_events(HWND window,UINT msg,WPARAM wParam,LPARAM lParam) { 1.8389 +#ifdef _WIN64 1.8390 + CImgDisplay* disp = (CImgDisplay*)GetWindowLongPtr(window,GWLP_USERDATA); 1.8391 +#else 1.8392 + CImgDisplay* disp = (CImgDisplay*)GetWindowLong(window,GWL_USERDATA); 1.8393 +#endif 1.8394 + MSG st_msg; 1.8395 + 1.8396 + switch (msg) { 1.8397 + case WM_CLOSE : 1.8398 + disp->mouse_x = disp->mouse_y = -1; 1.8399 + disp->window_x = disp->window_y = 0; 1.8400 + if (disp->button) { 1.8401 + cimg_std::memmove((void*)(disp->buttons+1),(void*)disp->buttons,512-1); 1.8402 + disp->button = 0; 1.8403 + } 1.8404 + if (disp->key) { 1.8405 + cimg_std::memmove((void*)(disp->keys+1),(void*)disp->keys,512-1); 1.8406 + disp->key = 0; 1.8407 + } 1.8408 + if (disp->released_key) { cimg_std::memmove((void*)(disp->released_keys+1),(void*)disp->released_keys,512-1); disp->released_key = 0; } 1.8409 + disp->is_closed = true; 1.8410 + ReleaseMutex(disp->mutex); 1.8411 + ShowWindow(disp->window,SW_HIDE); 1.8412 + disp->is_event = true; 1.8413 + SetEvent(cimg::Win32attr().wait_event); 1.8414 + return 0; 1.8415 + case WM_SIZE : { 1.8416 + while (PeekMessage(&st_msg,window,WM_SIZE,WM_SIZE,PM_REMOVE)) {} 1.8417 + WaitForSingleObject(disp->mutex,INFINITE); 1.8418 + const unsigned int nw = LOWORD(lParam),nh = HIWORD(lParam); 1.8419 + if (nw && nh && (nw!=disp->width || nh!=disp->height)) { 1.8420 + disp->window_width = nw; 1.8421 + disp->window_height = nh; 1.8422 + disp->mouse_x = disp->mouse_y = -1; 1.8423 + disp->is_resized = disp->is_event = true; 1.8424 + SetEvent(cimg::Win32attr().wait_event); 1.8425 + } 1.8426 + ReleaseMutex(disp->mutex); 1.8427 + } break; 1.8428 + case WM_MOVE : { 1.8429 + while (PeekMessage(&st_msg,window,WM_SIZE,WM_SIZE,PM_REMOVE)) {} 1.8430 + WaitForSingleObject(disp->mutex,INFINITE); 1.8431 + const int nx = (int)(short)(LOWORD(lParam)), ny = (int)(short)(HIWORD(lParam)); 1.8432 + if (nx!=disp->window_x || ny!=disp->window_y) { 1.8433 + disp->window_x = nx; 1.8434 + disp->window_y = ny; 1.8435 + disp->is_moved = disp->is_event = true; 1.8436 + SetEvent(cimg::Win32attr().wait_event); 1.8437 + } 1.8438 + ReleaseMutex(disp->mutex); 1.8439 + } break; 1.8440 + case WM_PAINT : 1.8441 + disp->paint(); 1.8442 + break; 1.8443 + case WM_KEYDOWN : 1.8444 + disp->update_iskey((unsigned int)wParam,true); 1.8445 + if (disp->key) cimg_std::memmove((void*)(disp->keys+1),(void*)disp->keys,512-1); 1.8446 + disp->key = (unsigned int)wParam; 1.8447 + if (disp->released_key) { cimg_std::memmove((void*)(disp->released_keys+1),(void*)disp->released_keys,512-1); disp->released_key = 0; } 1.8448 + disp->is_event = true; 1.8449 + SetEvent(cimg::Win32attr().wait_event); 1.8450 + break; 1.8451 + case WM_MOUSEMOVE : { 1.8452 + while (PeekMessage(&st_msg,window,WM_MOUSEMOVE,WM_MOUSEMOVE,PM_REMOVE)) {} 1.8453 + disp->mouse_x = LOWORD(lParam); 1.8454 + disp->mouse_y = HIWORD(lParam); 1.8455 +#if (_WIN32_WINNT>=0x0400) && !defined(NOTRACKMOUSEEVENT) 1.8456 + if (!disp->mouse_tracking) { 1.8457 + TRACKMOUSEEVENT tme; 1.8458 + tme.cbSize = sizeof(TRACKMOUSEEVENT); 1.8459 + tme.dwFlags = TME_LEAVE; 1.8460 + tme.hwndTrack = disp->window; 1.8461 + if (TrackMouseEvent(&tme)) disp->mouse_tracking = true; 1.8462 + } 1.8463 +#endif 1.8464 + if (disp->mouse_x<0 || disp->mouse_y<0 || disp->mouse_x>=disp->dimx() || disp->mouse_y>=disp->dimy()) 1.8465 + disp->mouse_x = disp->mouse_y = -1; 1.8466 + disp->is_event = true; 1.8467 + SetEvent(cimg::Win32attr().wait_event); 1.8468 + } break; 1.8469 + case WM_MOUSELEAVE : { 1.8470 + disp->mouse_x = disp->mouse_y = -1; 1.8471 + disp->mouse_tracking = false; 1.8472 + } break; 1.8473 + case WM_LBUTTONDOWN : 1.8474 + cimg_std::memmove((void*)(disp->buttons+1),(void*)disp->buttons,512-1); 1.8475 + disp->button|=1U; 1.8476 + disp->is_event = true; 1.8477 + SetEvent(cimg::Win32attr().wait_event); 1.8478 + break; 1.8479 + case WM_RBUTTONDOWN : 1.8480 + cimg_std::memmove((void*)(disp->buttons+1),(void*)disp->buttons,512-1); 1.8481 + disp->button|=2U; 1.8482 + disp->is_event = true; 1.8483 + SetEvent(cimg::Win32attr().wait_event); 1.8484 + break; 1.8485 + case WM_MBUTTONDOWN : 1.8486 + cimg_std::memmove((void*)(disp->buttons+1),(void*)disp->buttons,512-1); 1.8487 + disp->button|=4U; 1.8488 + disp->is_event = true; 1.8489 + SetEvent(cimg::Win32attr().wait_event); 1.8490 + break; 1.8491 + case 0x020A : // WM_MOUSEWHEEL: 1.8492 + disp->wheel+=(int)((short)HIWORD(wParam))/120; 1.8493 + disp->is_event = true; 1.8494 + SetEvent(cimg::Win32attr().wait_event); 1.8495 + case WM_KEYUP : 1.8496 + disp->update_iskey((unsigned int)wParam,false); 1.8497 + if (disp->key) { cimg_std::memmove((void*)(disp->keys+1),(void*)disp->keys,512-1); disp->key = 0; } 1.8498 + if (disp->released_key) cimg_std::memmove((void*)(disp->released_keys+1),(void*)disp->released_keys,512-1); 1.8499 + disp->released_key = (unsigned int)wParam; 1.8500 + disp->is_event = true; 1.8501 + SetEvent(cimg::Win32attr().wait_event); 1.8502 + break; 1.8503 + case WM_LBUTTONUP : 1.8504 + cimg_std::memmove((void*)(disp->buttons+1),(void*)disp->buttons,512-1); 1.8505 + disp->button&=~1U; 1.8506 + disp->is_event = true; 1.8507 + SetEvent(cimg::Win32attr().wait_event); 1.8508 + break; 1.8509 + case WM_RBUTTONUP : 1.8510 + cimg_std::memmove((void*)(disp->buttons+1),(void*)disp->buttons,512-1); 1.8511 + disp->button&=~2U; 1.8512 + disp->is_event = true; 1.8513 + SetEvent(cimg::Win32attr().wait_event); 1.8514 + break; 1.8515 + case WM_MBUTTONUP : 1.8516 + cimg_std::memmove((void*)(disp->buttons+1),(void*)disp->buttons,512-1); 1.8517 + disp->button&=~4U; 1.8518 + disp->is_event = true; 1.8519 + SetEvent(cimg::Win32attr().wait_event); 1.8520 + break; 1.8521 + case WM_SETCURSOR : 1.8522 + if (disp->visible_cursor) ShowCursor(TRUE); 1.8523 + else ShowCursor(FALSE); 1.8524 + break; 1.8525 + } 1.8526 + return DefWindowProc(window,msg,wParam,lParam); 1.8527 + } 1.8528 + 1.8529 + static DWORD WINAPI _events_thread(void* arg) { 1.8530 + CImgDisplay *disp = (CImgDisplay*)(((void**)arg)[0]); 1.8531 + const char *title = (const char*)(((void**)arg)[1]); 1.8532 + MSG msg; 1.8533 + delete[] (void**)arg; 1.8534 + disp->bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 1.8535 + disp->bmi.bmiHeader.biWidth = disp->width; 1.8536 + disp->bmi.bmiHeader.biHeight = -(int)disp->height; 1.8537 + disp->bmi.bmiHeader.biPlanes = 1; 1.8538 + disp->bmi.bmiHeader.biBitCount = 32; 1.8539 + disp->bmi.bmiHeader.biCompression = BI_RGB; 1.8540 + disp->bmi.bmiHeader.biSizeImage = 0; 1.8541 + disp->bmi.bmiHeader.biXPelsPerMeter = 1; 1.8542 + disp->bmi.bmiHeader.biYPelsPerMeter = 1; 1.8543 + disp->bmi.bmiHeader.biClrUsed = 0; 1.8544 + disp->bmi.bmiHeader.biClrImportant = 0; 1.8545 + disp->data = new unsigned int[disp->width*disp->height]; 1.8546 + if (!disp->is_fullscreen) { // Normal window 1.8547 + RECT rect; 1.8548 + rect.left = rect.top = 0; rect.right = disp->width-1; rect.bottom = disp->height-1; 1.8549 + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); 1.8550 + const int border1 = (rect.right-rect.left+1-disp->width)/2, border2 = rect.bottom-rect.top+1-disp->height-border1; 1.8551 + disp->window = CreateWindowA("MDICLIENT",title?title:" ", 1.8552 + WS_OVERLAPPEDWINDOW | (disp->is_closed?0:WS_VISIBLE), CW_USEDEFAULT,CW_USEDEFAULT, 1.8553 + disp->width + 2*border1, disp->height + border1 + border2, 1.8554 + 0,0,0,&(disp->ccs)); 1.8555 + if (!disp->is_closed) { 1.8556 + GetWindowRect(disp->window,&rect); 1.8557 + disp->window_x = rect.left + border1; 1.8558 + disp->window_y = rect.top + border2; 1.8559 + } else disp->window_x = disp->window_y = 0; 1.8560 + } else { // Fullscreen window 1.8561 + const unsigned int sx = screen_dimx(), sy = screen_dimy(); 1.8562 + disp->window = CreateWindowA("MDICLIENT",title?title:" ", 1.8563 + WS_POPUP | (disp->is_closed?0:WS_VISIBLE), (sx-disp->width)/2, (sy-disp->height)/2, 1.8564 + disp->width,disp->height,0,0,0,&(disp->ccs)); 1.8565 + disp->window_x = disp->window_y = 0; 1.8566 + } 1.8567 + SetForegroundWindow(disp->window); 1.8568 + disp->hdc = GetDC(disp->window); 1.8569 + disp->window_width = disp->width; 1.8570 + disp->window_height = disp->height; 1.8571 + disp->flush(); 1.8572 +#ifdef _WIN64 1.8573 + SetWindowLongPtr(disp->window,GWLP_USERDATA,(LONG_PTR)disp); 1.8574 + SetWindowLongPtr(disp->window,GWLP_WNDPROC,(LONG_PTR)_handle_events); 1.8575 +#else 1.8576 + SetWindowLong(disp->window,GWL_USERDATA,(LONG)disp); 1.8577 + SetWindowLong(disp->window,GWL_WNDPROC,(LONG)_handle_events); 1.8578 +#endif 1.8579 + SetEvent(disp->created); 1.8580 + while (GetMessage(&msg,0,0,0)) DispatchMessage(&msg); 1.8581 + return 0; 1.8582 + } 1.8583 + 1.8584 + CImgDisplay& _update_window_pos() { 1.8585 + if (!is_closed) { 1.8586 + RECT rect; 1.8587 + rect.left = rect.top = 0; rect.right = width-1; rect.bottom = height-1; 1.8588 + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); 1.8589 + const int border1 = (rect.right-rect.left+1-width)/2, border2 = rect.bottom-rect.top+1-height-border1; 1.8590 + GetWindowRect(window,&rect); 1.8591 + window_x = rect.left + border1; 1.8592 + window_y = rect.top + border2; 1.8593 + } else window_x = window_y = -1; 1.8594 + return *this; 1.8595 + } 1.8596 + 1.8597 + void _init_fullscreen() { 1.8598 + background_window = 0; 1.8599 + if (is_fullscreen && !is_closed) { 1.8600 + DEVMODE mode; 1.8601 + unsigned int imode = 0, ibest = 0, bestbpp = 0, bw = ~0U, bh = ~0U; 1.8602 + for (mode.dmSize = sizeof(DEVMODE), mode.dmDriverExtra = 0; EnumDisplaySettings(0,imode,&mode); ++imode) { 1.8603 + const unsigned int nw = mode.dmPelsWidth, nh = mode.dmPelsHeight; 1.8604 + if (nw>=width && nh>=height && mode.dmBitsPerPel>=bestbpp && nw<=bw && nh<=bh) { 1.8605 + bestbpp = mode.dmBitsPerPel; 1.8606 + ibest = imode; 1.8607 + bw = nw; bh = nh; 1.8608 + } 1.8609 + } 1.8610 + if (bestbpp) { 1.8611 + curr_mode.dmSize = sizeof(DEVMODE); curr_mode.dmDriverExtra = 0; 1.8612 + EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&curr_mode); 1.8613 + EnumDisplaySettings(0,ibest,&mode); 1.8614 + ChangeDisplaySettings(&mode,0); 1.8615 + } else curr_mode.dmSize = 0; 1.8616 + 1.8617 + const unsigned int sx = screen_dimx(), sy = screen_dimy(); 1.8618 + if (sx!=width || sy!=height) { 1.8619 + CLIENTCREATESTRUCT background_ccs; 1.8620 + background_window = CreateWindowA("MDICLIENT","",WS_POPUP | WS_VISIBLE, 0,0,sx,sy,0,0,0,&background_ccs); 1.8621 + SetForegroundWindow(background_window); 1.8622 + } 1.8623 + } else curr_mode.dmSize = 0; 1.8624 + } 1.8625 + 1.8626 + void _desinit_fullscreen() { 1.8627 + if (is_fullscreen) { 1.8628 + if (background_window) DestroyWindow(background_window); 1.8629 + background_window = 0; 1.8630 + if (curr_mode.dmSize) ChangeDisplaySettings(&curr_mode,0); 1.8631 + is_fullscreen = false; 1.8632 + } 1.8633 + } 1.8634 + 1.8635 + CImgDisplay& _assign(const unsigned int dimw, const unsigned int dimh, const char *ptitle=0, 1.8636 + const unsigned int normalization_type=3, 1.8637 + const bool fullscreen_flag=false, const bool closed_flag=false) { 1.8638 + 1.8639 + // Allocate space for window title 1.8640 + const int s = cimg::strlen(ptitle)+1; 1.8641 + char *tmp_title = s?new char[s]:0; 1.8642 + if (s) cimg_std::memcpy(tmp_title,ptitle,s*sizeof(char)); 1.8643 + 1.8644 + // Destroy previous window if existing 1.8645 + if (!is_empty()) assign(); 1.8646 + 1.8647 + // Set display variables 1.8648 + width = cimg::min(dimw,(unsigned int)screen_dimx()); 1.8649 + height = cimg::min(dimh,(unsigned int)screen_dimy()); 1.8650 + normalization = normalization_type<4?normalization_type:3; 1.8651 + is_fullscreen = fullscreen_flag; 1.8652 + window_x = window_y = 0; 1.8653 + is_closed = closed_flag; 1.8654 + visible_cursor = true; 1.8655 + mouse_tracking = false; 1.8656 + title = tmp_title; 1.8657 + flush(); 1.8658 + if (is_fullscreen) _init_fullscreen(); 1.8659 + 1.8660 + // Create event thread 1.8661 + void *arg = (void*)(new void*[2]); 1.8662 + ((void**)arg)[0]=(void*)this; 1.8663 + ((void**)arg)[1]=(void*)title; 1.8664 + unsigned long ThreadID = 0; 1.8665 + mutex = CreateMutex(0,FALSE,0); 1.8666 + created = CreateEvent(0,FALSE,FALSE,0); 1.8667 + thread = CreateThread(0,0,_events_thread,arg,0,&ThreadID); 1.8668 + WaitForSingleObject(created,INFINITE); 1.8669 + return *this; 1.8670 + } 1.8671 + 1.8672 + CImgDisplay& assign() { 1.8673 + if (is_empty()) return *this; 1.8674 + DestroyWindow(window); 1.8675 + TerminateThread(thread,0); 1.8676 + if (data) delete[] data; 1.8677 + if (title) delete[] title; 1.8678 + if (is_fullscreen) _desinit_fullscreen(); 1.8679 + width = height = normalization = window_width = window_height = 0; 1.8680 + window_x = window_y = 0; 1.8681 + is_fullscreen = false; 1.8682 + is_closed = true; 1.8683 + min = max = 0; 1.8684 + title = 0; 1.8685 + flush(); 1.8686 + return *this; 1.8687 + } 1.8688 + 1.8689 + CImgDisplay& assign(const unsigned int dimw, const unsigned int dimh, const char *title=0, 1.8690 + const unsigned int normalization_type=3, 1.8691 + const bool fullscreen_flag=false, const bool closed_flag=false) { 1.8692 + if (!dimw || !dimh) return assign(); 1.8693 + _assign(dimw,dimh,title,normalization_type,fullscreen_flag,closed_flag); 1.8694 + min = max = 0; 1.8695 + cimg_std::memset(data,0,sizeof(unsigned int)*width*height); 1.8696 + return paint(); 1.8697 + } 1.8698 + 1.8699 + template<typename T> 1.8700 + CImgDisplay& assign(const CImg<T>& img, const char *title=0, 1.8701 + const unsigned int normalization_type=3, 1.8702 + const bool fullscreen_flag=false, const bool closed_flag=false) { 1.8703 + if (!img) return assign(); 1.8704 + CImg<T> tmp; 1.8705 + const CImg<T>& nimg = (img.depth==1)?img:(tmp=img.get_projections2d(img.width/2,img.height/2,img.depth/2)); 1.8706 + _assign(nimg.width,nimg.height,title,normalization_type,fullscreen_flag,closed_flag); 1.8707 + if (normalization==2) min = (float)nimg.minmax(max); 1.8708 + return display(nimg); 1.8709 + } 1.8710 + 1.8711 + template<typename T> 1.8712 + CImgDisplay& assign(const CImgList<T>& list, const char *title=0, 1.8713 + const unsigned int normalization_type=3, 1.8714 + const bool fullscreen_flag=false, const bool closed_flag=false) { 1.8715 + if (!list) return assign(); 1.8716 + CImg<T> tmp; 1.8717 + const CImg<T> img = list.get_append('x','p'), 1.8718 + &nimg = (img.depth==1)?img:(tmp=img.get_projections2d(img.width/2,img.height/2,img.depth/2)); 1.8719 + _assign(nimg.width,nimg.height,title,normalization_type,fullscreen_flag,closed_flag); 1.8720 + if (normalization==2) min = (float)nimg.minmax(max); 1.8721 + return display(nimg); 1.8722 + } 1.8723 + 1.8724 + CImgDisplay& assign(const CImgDisplay& win) { 1.8725 + if (!win) return assign(); 1.8726 + _assign(win.width,win.height,win.title,win.normalization,win.is_fullscreen,win.is_closed); 1.8727 + cimg_std::memcpy(data,win.data,sizeof(unsigned int)*width*height); 1.8728 + return paint(); 1.8729 + } 1.8730 + 1.8731 + CImgDisplay& resize(const int nwidth, const int nheight, const bool redraw=true) { 1.8732 + if (!nwidth || !nheight || (is_empty() && (nwidth<0 || nheight<0))) return assign(); 1.8733 + if (is_empty()) return assign(nwidth,nheight); 1.8734 + const unsigned int 1.8735 + tmpdimx=(nwidth>0)?nwidth:(-nwidth*width/100), 1.8736 + tmpdimy=(nheight>0)?nheight:(-nheight*height/100), 1.8737 + dimx = tmpdimx?tmpdimx:1, 1.8738 + dimy = tmpdimy?tmpdimy:1; 1.8739 + if (window_width!=dimx || window_height!=dimy) { 1.8740 + RECT rect; rect.left = rect.top = 0; rect.right = dimx-1; rect.bottom = dimy-1; 1.8741 + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); 1.8742 + const int cwidth = rect.right-rect.left+1, cheight = rect.bottom-rect.top+1; 1.8743 + SetWindowPos(window,0,0,0,cwidth,cheight,SWP_NOMOVE | SWP_NOZORDER | SWP_NOCOPYBITS); 1.8744 + } 1.8745 + if (width!=dimx || height!=dimy) { 1.8746 + unsigned int *ndata = new unsigned int[dimx*dimy]; 1.8747 + if (redraw) _render_resize(data,width,height,ndata,dimx,dimy); 1.8748 + else cimg_std::memset(ndata,0x80,sizeof(unsigned int)*dimx*dimy); 1.8749 + delete[] data; 1.8750 + data = ndata; 1.8751 + bmi.bmiHeader.biWidth = dimx; 1.8752 + bmi.bmiHeader.biHeight = -(int)dimy; 1.8753 + width = dimx; 1.8754 + height = dimy; 1.8755 + } 1.8756 + window_width = dimx; window_height = dimy; 1.8757 + is_resized = false; 1.8758 + if (is_fullscreen) move((screen_dimx()-width)/2,(screen_dimy()-height)/2); 1.8759 + if (redraw) return paint(); 1.8760 + return *this; 1.8761 + } 1.8762 + 1.8763 + CImgDisplay& toggle_fullscreen(const bool redraw=true) { 1.8764 + if (is_empty()) return *this; 1.8765 + if (redraw) { 1.8766 + const unsigned int bufsize = width*height*4; 1.8767 + void *odata = cimg_std::malloc(bufsize); 1.8768 + cimg_std::memcpy(odata,data,bufsize); 1.8769 + assign(width,height,title,normalization,!is_fullscreen,false); 1.8770 + cimg_std::memcpy(data,odata,bufsize); 1.8771 + cimg_std::free(odata); 1.8772 + return paint(); 1.8773 + } 1.8774 + return assign(width,height,title,normalization,!is_fullscreen,false); 1.8775 + } 1.8776 + 1.8777 + CImgDisplay& show() { 1.8778 + if (is_empty()) return *this; 1.8779 + if (is_closed) { 1.8780 + is_closed = false; 1.8781 + if (is_fullscreen) _init_fullscreen(); 1.8782 + ShowWindow(window,SW_SHOW); 1.8783 + _update_window_pos(); 1.8784 + } 1.8785 + return paint(); 1.8786 + } 1.8787 + 1.8788 + CImgDisplay& close() { 1.8789 + if (is_empty()) return *this; 1.8790 + if (!is_closed && !is_fullscreen) { 1.8791 + if (is_fullscreen) _desinit_fullscreen(); 1.8792 + ShowWindow(window,SW_HIDE); 1.8793 + is_closed = true; 1.8794 + window_x = window_y = 0; 1.8795 + } 1.8796 + return *this; 1.8797 + } 1.8798 + 1.8799 + CImgDisplay& move(const int posx, const int posy) { 1.8800 + if (is_empty()) return *this; 1.8801 + if (!is_fullscreen) { 1.8802 + RECT rect; rect.left = rect.top = 0; rect.right=window_width-1; rect.bottom=window_height-1; 1.8803 + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); 1.8804 + const int border1 = (rect.right-rect.left+1-width)/2, border2 = rect.bottom-rect.top+1-height-border1; 1.8805 + SetWindowPos(window,0,posx-border1,posy-border2,0,0,SWP_NOSIZE | SWP_NOZORDER); 1.8806 + } else SetWindowPos(window,0,posx,posy,0,0,SWP_NOSIZE | SWP_NOZORDER); 1.8807 + window_x = posx; 1.8808 + window_y = posy; 1.8809 + is_moved = false; 1.8810 + return show(); 1.8811 + } 1.8812 + 1.8813 + CImgDisplay& show_mouse() { 1.8814 + if (is_empty()) return *this; 1.8815 + visible_cursor = true; 1.8816 + ShowCursor(TRUE); 1.8817 + SendMessage(window,WM_SETCURSOR,0,0); 1.8818 + return *this; 1.8819 + } 1.8820 + 1.8821 + CImgDisplay& hide_mouse() { 1.8822 + if (is_empty()) return *this; 1.8823 + visible_cursor = false; 1.8824 + ShowCursor(FALSE); 1.8825 + SendMessage(window,WM_SETCURSOR,0,0); 1.8826 + return *this; 1.8827 + } 1.8828 + 1.8829 + CImgDisplay& set_mouse(const int posx, const int posy) { 1.8830 + if (!is_closed && posx>=0 && posy>=0) { 1.8831 + _update_window_pos(); 1.8832 + const int res = (int)SetCursorPos(window_x+posx,window_y+posy); 1.8833 + if (res) { mouse_x = posx; mouse_y = posy; } 1.8834 + } 1.8835 + return *this; 1.8836 + } 1.8837 + 1.8838 + CImgDisplay& set_title(const char *format, ...) { 1.8839 + if (is_empty()) return *this; 1.8840 + char tmp[1024] = {0}; 1.8841 + va_list ap; 1.8842 + va_start(ap, format); 1.8843 + cimg_std::vsprintf(tmp,format,ap); 1.8844 + va_end(ap); 1.8845 + if (title) delete[] title; 1.8846 + const int s = cimg::strlen(tmp)+1; 1.8847 + title = new char[s]; 1.8848 + cimg_std::memcpy(title,tmp,s*sizeof(char)); 1.8849 + SetWindowTextA(window, tmp); 1.8850 + return *this; 1.8851 + } 1.8852 + 1.8853 + template<typename T> 1.8854 + CImgDisplay& display(const CImg<T>& img) { 1.8855 + if (img.is_empty()) 1.8856 + throw CImgArgumentException("CImgDisplay::display() : Cannot display empty image."); 1.8857 + if (is_empty()) assign(img.width,img.height); 1.8858 + return render(img).paint(); 1.8859 + } 1.8860 + 1.8861 + CImgDisplay& paint() { 1.8862 + if (!is_closed) { 1.8863 + WaitForSingleObject(mutex,INFINITE); 1.8864 + SetDIBitsToDevice(hdc,0,0,width,height,0,0,0,height,data,&bmi,DIB_RGB_COLORS); 1.8865 + ReleaseMutex(mutex); 1.8866 + } 1.8867 + return *this; 1.8868 + } 1.8869 + 1.8870 + template<typename T> 1.8871 + CImgDisplay& render(const CImg<T>& img) { 1.8872 + if (is_empty()) return *this; 1.8873 + if (!img) 1.8874 + throw CImgArgumentException("CImgDisplay::_render_image() : Specified input image (%u,%u,%u,%u,%p) is empty.", 1.8875 + img.width,img.height,img.depth,img.dim,img.data); 1.8876 + if (img.depth!=1) return render(img.get_projections2d(img.width/2,img.height/2,img.depth/2)); 1.8877 + 1.8878 + const T 1.8879 + *data1 = img.data, 1.8880 + *data2 = (img.dim>=2)?img.ptr(0,0,0,1):data1, 1.8881 + *data3 = (img.dim>=3)?img.ptr(0,0,0,2):data1; 1.8882 + 1.8883 + WaitForSingleObject(mutex,INFINITE); 1.8884 + unsigned int 1.8885 + *const ndata = (img.width==width && img.height==height)?data:new unsigned int[img.width*img.height], 1.8886 + *ptrd = ndata; 1.8887 + 1.8888 + if (!normalization || (normalization==3 && cimg::type<T>::string()==cimg::type<unsigned char>::string())) { 1.8889 + min = max = 0; 1.8890 + switch (img.dim) { 1.8891 + case 1 : { 1.8892 + for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8893 + const unsigned char val = (unsigned char)*(data1++); 1.8894 + *(ptrd++) = (val<<16) | (val<<8) | val; 1.8895 + }} break; 1.8896 + case 2 : { 1.8897 + for (unsigned int xy = img.width*img.height; xy>0; --xy) 1.8898 + *(ptrd++) = ((unsigned char)*(data1++)<<16) | ((unsigned char)*(data2++)<<8); 1.8899 + } break; 1.8900 + default : { 1.8901 + for (unsigned int xy = img.width*img.height; xy>0; --xy) 1.8902 + *(ptrd++) = ((unsigned char)*(data1++)<<16) | ((unsigned char)*(data2++)<<8) | (unsigned char)*(data3++); 1.8903 + } 1.8904 + } 1.8905 + } else { 1.8906 + if (normalization==3) { 1.8907 + if (cimg::type<T>::is_float()) min = (float)img.minmax(max); 1.8908 + else { min = (float)cimg::type<T>::min(); max = (float)cimg::type<T>::max(); } 1.8909 + } else if ((min>max) || normalization==1) min = (float)img.minmax(max); 1.8910 + const float delta = max-min, mm = delta?delta:1.0f; 1.8911 + switch (img.dim) { 1.8912 + case 1 : { 1.8913 + for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8914 + const unsigned char val = (unsigned char)(255*(*(data1++)-min)/mm); 1.8915 + *(ptrd++) = (val<<16) | (val<<8) | val; 1.8916 + }} break; 1.8917 + case 2 : { 1.8918 + for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8919 + const unsigned char 1.8920 + R = (unsigned char)(255*(*(data1++)-min)/mm), 1.8921 + G = (unsigned char)(255*(*(data2++)-min)/mm); 1.8922 + *(ptrd++) = (R<<16) | (G<<8); 1.8923 + }} break; 1.8924 + default : { 1.8925 + for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8926 + const unsigned char 1.8927 + R = (unsigned char)(255*(*(data1++)-min)/mm), 1.8928 + G = (unsigned char)(255*(*(data2++)-min)/mm), 1.8929 + B = (unsigned char)(255*(*(data3++)-min)/mm); 1.8930 + *(ptrd++) = (R<<16) | (G<<8) | B; 1.8931 + }} 1.8932 + } 1.8933 + } 1.8934 + if (ndata!=data) { _render_resize(ndata,img.width,img.height,data,width,height); delete[] ndata; } 1.8935 + ReleaseMutex(mutex); 1.8936 + return *this; 1.8937 + } 1.8938 + 1.8939 + template<typename T> 1.8940 + const CImgDisplay& snapshot(CImg<T>& img) const { 1.8941 + if (is_empty()) img.assign(); 1.8942 + else { 1.8943 + img.assign(width,height,1,3); 1.8944 + T 1.8945 + *data1 = img.ptr(0,0,0,0), 1.8946 + *data2 = img.ptr(0,0,0,1), 1.8947 + *data3 = img.ptr(0,0,0,2); 1.8948 + unsigned int *ptrs = data; 1.8949 + for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.8950 + const unsigned int val = *(ptrs++); 1.8951 + *(data1++) = (unsigned char)(val>>16); 1.8952 + *(data2++) = (unsigned char)((val>>8)&0xFF); 1.8953 + *(data3++) = (unsigned char)(val&0xFF); 1.8954 + } 1.8955 + } 1.8956 + return *this; 1.8957 + } 1.8958 + 1.8959 + // MacOSX - Carbon-based display 1.8960 + //------------------------------- 1.8961 + // (Code by Adrien Reboisson && Romain Blei, supervised by Jean-Marie Favreau) 1.8962 + // 1.8963 +#elif cimg_display==3 1.8964 + unsigned int *data; // The bits of the picture 1.8965 + WindowRef carbonWindow; // The opaque carbon window struct associated with the display 1.8966 + MPCriticalRegionID paintCriticalRegion; // Critical section used when drawing 1.8967 + CGColorSpaceRef csr; // Needed for painting 1.8968 + CGDataProviderRef dataProvider; // Needed for painting 1.8969 + CGImageRef imageRef; // The image 1.8970 + UInt32 lastKeyModifiers; // Buffer storing modifiers state 1.8971 + 1.8972 + // Define the kind of the queries which can be serialized using the event thread. 1.8973 + typedef enum { 1.8974 + COM_CREATEWINDOW = 0, // Create window query 1.8975 + COM_RELEASEWINDOW, // Release window query 1.8976 + COM_SHOWWINDOW, // Show window query 1.8977 + COM_HIDEWINDOW, // Hide window query 1.8978 + COM_SHOWMOUSE, // Show mouse query 1.8979 + COM_HIDEMOUSE, // Hide mouse query 1.8980 + COM_RESIZEWINDOW, // Resize window query 1.8981 + COM_MOVEWINDOW, // Move window query 1.8982 + COM_SETTITLE, // Set window title query 1.8983 + COM_SETMOUSEPOS // Set cursor position query 1.8984 + } CImgCarbonQueryKind; 1.8985 + 1.8986 + // The query destructor send to the event thread. 1.8987 + struct CbSerializedQuery { 1.8988 + CImgDisplay* sender; // Query's sender 1.8989 + CImgCarbonQueryKind kind; // The kind of the query sent to the background thread 1.8990 + short x, y; // X:Y values for move/resize operations 1.8991 + char *c; // Char values for window title 1.8992 + bool createFullScreenWindow; // Boolean value used for full-screen window creation 1.8993 + bool createClosedWindow; // Boolean value used for closed-window creation 1.8994 + bool update; // Boolean value used for resize 1.8995 + bool success; // Succes or failure of the message, used as return value 1.8996 + CbSerializedQuery(CImgDisplay *s, CImgCarbonQueryKind k):sender(s),kind(k),success(false) {}; 1.8997 + 1.8998 + inline static CbSerializedQuery BuildReleaseWindowQuery(CImgDisplay* sender) { 1.8999 + return CbSerializedQuery(sender, COM_RELEASEWINDOW); 1.9000 + } 1.9001 + inline static CbSerializedQuery BuildCreateWindowQuery(CImgDisplay* sender, const bool fullscreen, const bool closed) { 1.9002 + CbSerializedQuery q(sender, COM_CREATEWINDOW); 1.9003 + q.createFullScreenWindow = fullscreen; 1.9004 + q.createClosedWindow = closed; 1.9005 + return q; 1.9006 + } 1.9007 + inline static CbSerializedQuery BuildShowWindowQuery(CImgDisplay* sender) { 1.9008 + return CbSerializedQuery(sender, COM_SHOWWINDOW); 1.9009 + } 1.9010 + inline static CbSerializedQuery BuildHideWindowQuery(CImgDisplay* sender) { 1.9011 + return CbSerializedQuery(sender, COM_HIDEWINDOW); 1.9012 + } 1.9013 + inline static CbSerializedQuery BuildShowMouseQuery(CImgDisplay* sender) { 1.9014 + return CbSerializedQuery(sender, COM_SHOWMOUSE); 1.9015 + } 1.9016 + inline static CbSerializedQuery BuildHideMouseQuery(CImgDisplay* sender) { 1.9017 + return CbSerializedQuery(sender, COM_HIDEMOUSE); 1.9018 + } 1.9019 + inline static CbSerializedQuery BuildResizeWindowQuery(CImgDisplay* sender, const int x, const int y, bool update) { 1.9020 + CbSerializedQuery q(sender, COM_RESIZEWINDOW); 1.9021 + q.x = x, q.y = y; 1.9022 + q.update = update; 1.9023 + return q; 1.9024 + } 1.9025 + inline static CbSerializedQuery BuildMoveWindowQuery(CImgDisplay* sender, const int x, const int y) { 1.9026 + CbSerializedQuery q(sender, COM_MOVEWINDOW); 1.9027 + q.x = x, q.y = y; 1.9028 + return q; 1.9029 + } 1.9030 + inline static CbSerializedQuery BuildSetWindowTitleQuery(CImgDisplay* sender, char* c) { 1.9031 + CbSerializedQuery q(sender, COM_SETTITLE); 1.9032 + q.c = c; 1.9033 + return q; 1.9034 + } 1.9035 + inline static CbSerializedQuery BuildSetWindowPosQuery(CImgDisplay* sender, const int x, const int y) { 1.9036 + CbSerializedQuery q(sender, COM_SETMOUSEPOS); 1.9037 + q.x = x, q.y = y; 1.9038 + return q; 1.9039 + } 1.9040 + }; 1.9041 + 1.9042 + // Send a serialized query in a synchroneous way. 1.9043 + // @param c Application Carbon global settings. 1.9044 + // @param m The query to send. 1.9045 + // @result Success/failure of the operation returned by the event thread. 1.9046 + bool _CbSendMsg(cimg::CarbonInfo& c, CbSerializedQuery m) { 1.9047 + MPNotifyQueue(c.com_queue,&m,0,0); // Send the given message 1.9048 + MPWaitOnSemaphore(c.sync_event,kDurationForever); // Wait end of processing notification 1.9049 + return m.success; 1.9050 + } 1.9051 + 1.9052 + // Free the window attached to the current display. 1.9053 + // @param c Application Carbon global settings. 1.9054 + // @result Success/failure of the operation. 1.9055 + bool _CbFreeAttachedWindow(cimg::CarbonInfo& c) { 1.9056 + if (!_CbSendMsg(c, CbSerializedQuery::BuildReleaseWindowQuery(this))) // Ask the main thread to free the given window 1.9057 + throw CImgDisplayException("Cannot release window associated with the current display."); 1.9058 + // If a window existed, ask to release it 1.9059 + MPEnterCriticalRegion(c.windowListCR,kDurationForever); // Lock the list of the windows 1.9060 + --c.windowCount; //Decrement the window count 1.9061 + MPExitCriticalRegion(c.windowListCR); // Unlock the list 1.9062 + return c.windowCount == 0; 1.9063 + } 1.9064 + 1.9065 + // Create the window attached to the current display. 1.9066 + // @param c Application Carbon global settings. 1.9067 + // @param title The window title, if any. 1.9068 + // @param fullscreen Shoud we start in fullscreen mode ? 1.9069 + // @param create_closed If true, the window is created but not displayed. 1.9070 + // @result Success/failure of the operation. 1.9071 + void _CbCreateAttachedWindow(cimg::CarbonInfo& c, const char* title, const bool fullscreen, const bool create_closed) { 1.9072 + if (!_CbSendMsg(c,CbSerializedQuery::BuildCreateWindowQuery(this,fullscreen,create_closed))) // Ask the main thread to create the window 1.9073 + throw CImgDisplayException("Cannot create the window associated with the current display."); 1.9074 + if (title) set_title(title); // Set the title, if any 1.9075 + // Now we can register the window 1.9076 + MPEnterCriticalRegion(c.windowListCR,kDurationForever); // Lock the list of the windows 1.9077 + ++c.windowCount; //Increment the window count 1.9078 + MPExitCriticalRegion(c.windowListCR); // Unlock the list 1.9079 + } 1.9080 + 1.9081 + // Destroy graphic objects previously allocated. We free the image, the data provider, then the colorspace. 1.9082 + void _CbFinalizeGraphics() { 1.9083 + CGImageRelease (imageRef); // Release the picture 1.9084 + CGDataProviderRelease(dataProvider); // Release the DP 1.9085 + CGColorSpaceRelease(csr); // Free the cs 1.9086 + } 1.9087 + 1.9088 + // Create graphic objects associated to a display. We have to create a colormap, a data provider, and the image. 1.9089 + void _CbInitializeGraphics() { 1.9090 + csr = CGColorSpaceCreateDeviceRGB(); // Create the color space first 1.9091 + if (!csr) 1.9092 + throw CImgDisplayException("CGColorSpaceCreateDeviceRGB() failed."); 1.9093 + // Create the DP 1.9094 + dataProvider = CGDataProviderCreateWithData(0,data,height*width*sizeof(unsigned int),0); 1.9095 + if (!dataProvider) 1.9096 + throw CImgDisplayException("CGDataProviderCreateWithData() failed."); 1.9097 + // ... and finally the image. 1.9098 + if (cimg::endianness()) 1.9099 + imageRef = CGImageCreate(width,height,8,32,width*sizeof(unsigned int),csr, 1.9100 + kCGImageAlphaNoneSkipFirst,dataProvider,0,false,kCGRenderingIntentDefault); 1.9101 + else 1.9102 + imageRef = CGImageCreate(width,height,8,32,width*sizeof(unsigned int),csr, 1.9103 + kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host,dataProvider,0,false,kCGRenderingIntentDefault); 1.9104 + if (!imageRef) 1.9105 + throw CImgDisplayException("CGImageCreate() failed."); 1.9106 + } 1.9107 + 1.9108 + // Reinit graphic objects. Free them, then reallocate all. 1.9109 + // This is used when image bounds are changed or when data source get invalid. 1.9110 + void _CbReinitGraphics() { 1.9111 + MPEnterCriticalRegion(paintCriticalRegion, kDurationForever); 1.9112 + _CbFinalizeGraphics(); 1.9113 + _CbInitializeGraphics(); 1.9114 + MPExitCriticalRegion(paintCriticalRegion); 1.9115 + } 1.9116 + 1.9117 + // Convert a point having global coordonates into the window coordonates. 1.9118 + // We use this function to replace the deprecated GlobalToLocal QuickDraw API. 1.9119 + // @param mouseEvent The mouse event which triggered the event handler. 1.9120 + // @param window The window where the event occured. 1.9121 + // @param point The modified point struct. 1.9122 + // @result True if the point struct has been converted successfully. 1.9123 + static bool _CbToLocalPointFromMouseEvent(EventRef mouseEvent, WindowRef window, HIPoint* point) { 1.9124 + Rect bounds; 1.9125 + if (GetWindowBounds(window,kWindowStructureRgn,&bounds)==noErr) { 1.9126 + point->x -= bounds.left; 1.9127 + point->y -= bounds.top; 1.9128 + HIViewRef view = NULL; 1.9129 + if (HIViewGetViewForMouseEvent(HIViewGetRoot(window),mouseEvent,&view)==noErr) 1.9130 + return HIViewConvertPoint(point, NULL, view) == noErr; 1.9131 + } 1.9132 + return false; 1.9133 + } 1.9134 + 1.9135 + static int screen_dimx() { 1.9136 + return CGDisplayPixelsWide(kCGDirectMainDisplay); 1.9137 + } 1.9138 + 1.9139 + static int screen_dimy() { 1.9140 + return CGDisplayPixelsHigh(kCGDirectMainDisplay); 1.9141 + } 1.9142 + 1.9143 + CImgDisplay& assign(const unsigned int dimw, const unsigned int dimh, const char *title=0, 1.9144 + const unsigned int normalization_type=3, 1.9145 + const bool fullscreen_flag=false, const bool closed_flag=false) { 1.9146 + if (!dimw || !dimh) return assign(); 1.9147 + _assign(dimw,dimh,title,normalization_type,fullscreen_flag,closed_flag); 1.9148 + min = max = 0; 1.9149 + cimg_std::memset(data,0,sizeof(unsigned int)*width*height); 1.9150 + return paint(); 1.9151 + } 1.9152 + 1.9153 + template<typename T> 1.9154 + CImgDisplay& assign(const CImg<T>& img, const char *title=0, 1.9155 + const unsigned int normalization_type=3, 1.9156 + const bool fullscreen_flag=false, const bool closed_flag=false) { 1.9157 + if (!img) return assign(); 1.9158 + CImg<T> tmp; 1.9159 + const CImg<T>& nimg = (img.depth==1)?img:(tmp=img.get_projections2d(img.width/2,img.height/2,img.depth/2)); 1.9160 + _assign(nimg.width,nimg.height,title,normalization_type,fullscreen_flag,closed_flag); 1.9161 + if (normalization==2) min = (float)nimg.minmax(max); 1.9162 + return display(nimg); 1.9163 + } 1.9164 + 1.9165 + template<typename T> 1.9166 + CImgDisplay& assign(const CImgList<T>& list, const char *title=0, 1.9167 + const unsigned int normalization_type=3, 1.9168 + const bool fullscreen_flag=false, const bool closed_flag=false) { 1.9169 + if (!list) return assign(); 1.9170 + CImg<T> tmp; 1.9171 + const CImg<T> img = list.get_append('x','p'), 1.9172 + &nimg = (img.depth==1)?img:(tmp=img.get_projections2d(img.width/2,img.height/2,img.depth/2)); 1.9173 + _assign(nimg.width,nimg.height,title,normalization_type,fullscreen_flag,closed_flag); 1.9174 + if (normalization==2) min = (float)nimg.minmax(max); 1.9175 + return display(nimg); 1.9176 + } 1.9177 + 1.9178 + CImgDisplay& assign(const CImgDisplay &win) { 1.9179 + if (!win) return assign(); 1.9180 + _assign(win.width,win.height,win.title,win.normalization,win.is_fullscreen,win.is_closed); 1.9181 + cimg_std::memcpy(data,win.data,sizeof(unsigned int)*width*height); 1.9182 + return paint(); 1.9183 + } 1.9184 + 1.9185 + template<typename T> 1.9186 + CImgDisplay& display(const CImg<T>& img) { 1.9187 + if (is_empty()) assign(img.width,img.height); 1.9188 + return render(img).paint(); 1.9189 + } 1.9190 + 1.9191 + CImgDisplay& resize(const int nwidth, const int nheight, const bool redraw=true) { 1.9192 + if (!nwidth || !nheight || (is_empty() && (nwidth<0 || nheight<0))) return assign(); 1.9193 + if (is_empty()) return assign(nwidth,nheight); 1.9194 + const unsigned int 1.9195 + tmpdimx = (nwidth>0)?nwidth:(-nwidth*width/100), 1.9196 + tmpdimy = (nheight>0)?nheight:(-nheight*height/100), 1.9197 + dimx = tmpdimx?tmpdimx:1, 1.9198 + dimy = tmpdimy?tmpdimy:1; 1.9199 + cimg::CarbonInfo& c = cimg::CarbonAttr(); 1.9200 + 1.9201 + if ((window_width!=dimx || window_height!=dimy) && 1.9202 + !_CbSendMsg(c,CbSerializedQuery::BuildResizeWindowQuery(this,dimx,dimy,redraw))) 1.9203 + throw CImgDisplayException("CImgDisplay::resize() : Cannot resize the window associated to the current display."); 1.9204 + 1.9205 + if (width!=dimx || height!=dimy) { 1.9206 + unsigned int *ndata = new unsigned int[dimx*dimy]; 1.9207 + if (redraw) _render_resize(data,width,height,ndata,dimx,dimy); 1.9208 + else cimg_std::memset(ndata,0x80,sizeof(unsigned int)*dimx*dimy); 1.9209 + unsigned int const* old_data = data; 1.9210 + data = ndata; 1.9211 + delete[] old_data; 1.9212 + _CbReinitGraphics(); 1.9213 + } 1.9214 + window_width = width = dimx; window_height = height = dimy; 1.9215 + is_resized = false; 1.9216 + if (is_fullscreen) move((screen_dimx()-width)/2,(screen_dimy()-height)/2); 1.9217 + if (redraw) return paint(); 1.9218 + return *this; 1.9219 + } 1.9220 + 1.9221 + CImgDisplay& move(const int posx, const int posy) { 1.9222 + if (is_empty()) return *this; 1.9223 + if (!is_fullscreen) { 1.9224 + // If the operation succeeds, window_x and window_y are updated by the event thread 1.9225 + cimg::CarbonInfo& c = cimg::CarbonAttr(); 1.9226 + // Send the query 1.9227 + if (!_CbSendMsg(c,CbSerializedQuery::BuildMoveWindowQuery(this,posx,posy))) 1.9228 + throw CImgDisplayException("CImgDisplay::move() : Cannot move the window associated to the current display."); 1.9229 + } 1.9230 + return show(); 1.9231 + } 1.9232 + 1.9233 + CImgDisplay& set_mouse(const int posx, const int posy) { 1.9234 + if (!is_closed && posx>=0 && posy>=0) { 1.9235 + // If the operation succeeds, mouse_x and mouse_y are updated by the event thread 1.9236 + cimg::CarbonInfo& c = cimg::CarbonAttr(); 1.9237 + // Send the query 1.9238 + if (!_CbSendMsg(c,CbSerializedQuery::BuildSetWindowPosQuery(this,posx,posy))) 1.9239 + throw CImgDisplayException("CImgDisplay::set_mouse() : Cannot set the mouse position to the current display."); 1.9240 + } 1.9241 + return *this; 1.9242 + } 1.9243 + 1.9244 + CImgDisplay& hide_mouse() { 1.9245 + if (is_empty()) return *this; 1.9246 + cimg::CarbonInfo& c = cimg::CarbonAttr(); 1.9247 + // Send the query 1.9248 + if (!_CbSendMsg(c,CbSerializedQuery::BuildHideMouseQuery(this))) 1.9249 + throw CImgDisplayException("CImgDisplay::hide_mouse() : Cannot hide the mouse associated to the current display."); 1.9250 + return *this; 1.9251 + } 1.9252 + 1.9253 + CImgDisplay& show_mouse() { 1.9254 + if (is_empty()) return *this; 1.9255 + cimg::CarbonInfo& c = cimg::CarbonAttr(); 1.9256 + // Send the query 1.9257 + if (!_CbSendMsg(c,CbSerializedQuery::BuildShowMouseQuery(this))) 1.9258 + throw CImgDisplayException("CImgDisplay::show_mouse() : Cannot show the mouse associated to the current display."); 1.9259 + return *this; 1.9260 + } 1.9261 + 1.9262 + static void wait_all() { 1.9263 + cimg::CarbonInfo& c = cimg::CarbonAttr(); 1.9264 + MPWaitOnSemaphore(c.wait_event,kDurationForever); 1.9265 + } 1.9266 + 1.9267 + CImgDisplay& show() { 1.9268 + if (is_empty()) return *this; 1.9269 + if (is_closed) { 1.9270 + cimg::CarbonInfo& c = cimg::CarbonAttr(); 1.9271 + if (!_CbSendMsg(c,CbSerializedQuery::BuildShowWindowQuery(this))) 1.9272 + throw CImgDisplayException("CImgDisplay::show() : Cannot show the window associated to the current display."); 1.9273 + } 1.9274 + return paint(); 1.9275 + } 1.9276 + 1.9277 + CImgDisplay& close() { 1.9278 + if (is_empty()) return *this; 1.9279 + if (!is_closed && !is_fullscreen) { 1.9280 + cimg::CarbonInfo& c = cimg::CarbonAttr(); 1.9281 + // If the operation succeeds, window_x and window_y are updated on the event thread 1.9282 + if (!_CbSendMsg(c,CbSerializedQuery::BuildHideWindowQuery(this))) 1.9283 + throw CImgDisplayException("CImgDisplay::close() : Cannot hide the window associated to the current display."); 1.9284 + } 1.9285 + return *this; 1.9286 + } 1.9287 + 1.9288 + CImgDisplay& set_title(const char *format, ...) { 1.9289 + if (is_empty()) return *this; 1.9290 + char tmp[1024] = {0}; 1.9291 + va_list ap; 1.9292 + va_start(ap, format); 1.9293 + cimg_std::vsprintf(tmp,format,ap); 1.9294 + va_end(ap); 1.9295 + if (title) delete[] title; 1.9296 + const int s = cimg::strlen(tmp)+1; 1.9297 + title = new char[s]; 1.9298 + cimg_std::memcpy(title,tmp,s*sizeof(char)); 1.9299 + cimg::CarbonInfo& c = cimg::CarbonAttr(); 1.9300 + if (!_CbSendMsg(c,CbSerializedQuery::BuildSetWindowTitleQuery(this,tmp))) 1.9301 + throw CImgDisplayException("CImgDisplay::set_title() : Cannot set the window title associated to the current display."); 1.9302 + return *this; 1.9303 + } 1.9304 + 1.9305 + CImgDisplay& paint() { 1.9306 + if (!is_closed) { 1.9307 + MPEnterCriticalRegion(paintCriticalRegion,kDurationForever); 1.9308 + CGrafPtr portPtr = GetWindowPort(carbonWindow); 1.9309 + CGContextRef currentContext = 0; 1.9310 + QDBeginCGContext(portPtr,¤tContext); 1.9311 + CGContextSetRGBFillColor(currentContext,255,255,255,255); 1.9312 + CGContextFillRect(currentContext,CGRectMake(0,0,window_width,window_height)); 1.9313 + CGContextDrawImage(currentContext,CGRectMake(0,int(window_height-height)<0?0:window_height-height,width,height),imageRef); 1.9314 + CGContextFlush(currentContext); 1.9315 + QDEndCGContext(portPtr, ¤tContext); 1.9316 + MPExitCriticalRegion(paintCriticalRegion); 1.9317 + } 1.9318 + return *this; 1.9319 + } 1.9320 + 1.9321 + template<typename T> 1.9322 + CImgDisplay& render(const CImg<T>& img) { 1.9323 + if (is_empty()) return *this; 1.9324 + if (!img) 1.9325 + throw CImgArgumentException("CImgDisplay::_render_image() : Specified input image (%u,%u,%u,%u,%p) is empty.", 1.9326 + img.width,img.height,img.depth,img.dim,img.data); 1.9327 + if (img.depth!=1) return render(img.get_projections2d(img.width/2,img.height/2,img.depth/2)); 1.9328 + const T 1.9329 + *data1 = img.data, 1.9330 + *data2 = (img.dim>=2)?img.ptr(0,0,0,1):data1, 1.9331 + *data3 = (img.dim>=3)?img.ptr(0,0,0,2):data1; 1.9332 + MPEnterCriticalRegion(paintCriticalRegion, kDurationForever); 1.9333 + unsigned int 1.9334 + *const ndata = (img.width==width && img.height==height)?data:new unsigned int[img.width*img.height], 1.9335 + *ptrd = ndata; 1.9336 + if (!normalization || (normalization==3 && cimg::type<T>::string()==cimg::type<unsigned char>::string())) { 1.9337 + min = max = 0; 1.9338 + for (unsigned int xy = img.width*img.height; xy>0; --xy) 1.9339 + *(ptrd++) = ((unsigned char)*(data1++)<<16) | ((unsigned char)*(data2++)<<8) | (unsigned char)*(data3++); 1.9340 + } else { 1.9341 + if (normalization==3) { 1.9342 + if (cimg::type<T>::is_float()) min = (float)img.minmax(max); 1.9343 + else { 1.9344 + min = (float)cimg::type<T>::min(); 1.9345 + max = (float)cimg::type<T>::max(); 1.9346 + } 1.9347 + } else if ((min>max) || normalization==1) min = (float)img.minmax(max); 1.9348 + const float delta = max-min, mm = delta?delta:1.0f; 1.9349 + for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.9350 + const unsigned char 1.9351 + R = (unsigned char)(255*(*(data1++)-min)/mm), 1.9352 + G = (unsigned char)(255*(*(data2++)-min)/mm), 1.9353 + B = (unsigned char)(255*(*(data3++)-min)/mm); 1.9354 + *(ptrd++) = (R<<16) | (G<<8) | (B); 1.9355 + } 1.9356 + } 1.9357 + if (ndata!=data) { 1.9358 + _render_resize(ndata,img.width,img.height,data,width,height); 1.9359 + delete[] ndata; 1.9360 + } 1.9361 + MPExitCriticalRegion(paintCriticalRegion); 1.9362 + return *this; 1.9363 + } 1.9364 + 1.9365 + template<typename T> 1.9366 + const CImgDisplay& snapshot(CImg<T>& img) const { 1.9367 + if (is_empty()) img.assign(); 1.9368 + else { 1.9369 + img.assign(width,height,1,3); 1.9370 + T 1.9371 + *data1 = img.ptr(0,0,0,0), 1.9372 + *data2 = img.ptr(0,0,0,1), 1.9373 + *data3 = img.ptr(0,0,0,2); 1.9374 + unsigned int *ptrs = data; 1.9375 + for (unsigned int xy = img.width*img.height; xy>0; --xy) { 1.9376 + const unsigned int val = *(ptrs++); 1.9377 + *(data1++) = (unsigned char)(val>>16); 1.9378 + *(data2++) = (unsigned char)((val>>8)&0xFF); 1.9379 + *(data3++) = (unsigned char)(val&0xFF); 1.9380 + } 1.9381 + } 1.9382 + return *this; 1.9383 + } 1.9384 + 1.9385 + CImgDisplay& toggle_fullscreen(const bool redraw=true) { 1.9386 + if (is_empty()) return *this; 1.9387 + if (redraw) { 1.9388 + const unsigned int bufsize = width*height*4; 1.9389 + void *odata = cimg_std::malloc(bufsize); 1.9390 + cimg_std::memcpy(odata,data,bufsize); 1.9391 + assign(width,height,title,normalization,!is_fullscreen,false); 1.9392 + cimg_std::memcpy(data,odata,bufsize); 1.9393 + cimg_std::free(odata); 1.9394 + return paint(); 1.9395 + } 1.9396 + return assign(width,height,title,normalization,!is_fullscreen,false); 1.9397 + } 1.9398 + 1.9399 + static OSStatus CarbonEventHandler(EventHandlerCallRef myHandler, EventRef theEvent, void* userData) { 1.9400 + OSStatus result = eventNotHandledErr; 1.9401 + CImgDisplay* disp = (CImgDisplay*) userData; 1.9402 + (void)myHandler; // Avoid "unused parameter" 1.9403 + cimg::CarbonInfo& c = cimg::CarbonAttr(); 1.9404 + // Gets the associated display 1.9405 + if (disp) { 1.9406 + // Window events are always handled 1.9407 + if (GetEventClass(theEvent)==kEventClassWindow) switch (GetEventKind (theEvent)) { 1.9408 + case kEventWindowClose : 1.9409 + disp->mouse_x = disp->mouse_y = -1; 1.9410 + disp->window_x = disp->window_y = 0; 1.9411 + if (disp->button) { 1.9412 + cimg_std::memmove((void*)(disp->buttons+1),(void*)disp->buttons,512-1); 1.9413 + disp->button = 0; 1.9414 + } 1.9415 + if (disp->key) { 1.9416 + cimg_std::memmove((void*)(disp->keys+1),(void*)disp->keys,512-1); 1.9417 + disp->key = 0; 1.9418 + } 1.9419 + if (disp->released_key) { cimg_std::memmove((void*)(disp->released_keys+1),(void*)disp->released_keys,512-1); disp->released_key = 0; } 1.9420 + disp->is_closed = true; 1.9421 + HideWindow(disp->carbonWindow); 1.9422 + disp->is_event = true; 1.9423 + MPSignalSemaphore(c.wait_event); 1.9424 + result = noErr; 1.9425 + break; 1.9426 + // There is a lot of case where we have to redraw our window 1.9427 + case kEventWindowBoundsChanging : 1.9428 + case kEventWindowResizeStarted : 1.9429 + case kEventWindowCollapsed : //Not sure it's really needed :-) 1.9430 + break; 1.9431 + case kEventWindowZoomed : 1.9432 + case kEventWindowExpanded : 1.9433 + case kEventWindowResizeCompleted : { 1.9434 + MPEnterCriticalRegion(disp->paintCriticalRegion, kDurationForever); 1.9435 + // Now we retrieve the new size of the window 1.9436 + Rect newContentRect; 1.9437 + GetWindowBounds(disp->carbonWindow,kWindowContentRgn,&newContentRect); 1.9438 + const unsigned int 1.9439 + nw = (unsigned int)(newContentRect.right - newContentRect.left), 1.9440 + nh = (unsigned int)(newContentRect.bottom - newContentRect.top); 1.9441 + 1.9442 + // Then we update CImg internal settings 1.9443 + if (nw && nh && (nw!=disp->width || nh!=disp->height)) { 1.9444 + disp->window_width = nw; 1.9445 + disp->window_height = nh; 1.9446 + disp->mouse_x = disp->mouse_y = -1; 1.9447 + disp->is_resized = true; 1.9448 + } 1.9449 + disp->is_event = true; 1.9450 + MPExitCriticalRegion(disp->paintCriticalRegion); 1.9451 + disp->paint(); // Coords changed, must update the screen 1.9452 + MPSignalSemaphore(c.wait_event); 1.9453 + result = noErr; 1.9454 + } break; 1.9455 + case kEventWindowDragStarted : 1.9456 + case kEventWindowDragCompleted : { 1.9457 + MPEnterCriticalRegion(disp->paintCriticalRegion, kDurationForever); 1.9458 + // Now we retrieve the new size of the window 1.9459 + Rect newContentRect ; 1.9460 + GetWindowBounds(disp->carbonWindow,kWindowStructureRgn,&newContentRect); 1.9461 + const int nx = (int)(newContentRect.left), ny = (int)(newContentRect.top); 1.9462 + // Then we update CImg internal settings 1.9463 + if (nx!=disp->window_x || ny!=disp->window_y) { 1.9464 + disp->window_x = nx; 1.9465 + disp->window_y = ny; 1.9466 + disp->is_moved = true; 1.9467 + } 1.9468 + disp->is_event = true; 1.9469 + MPExitCriticalRegion(disp->paintCriticalRegion); 1.9470 + disp->paint(); // Coords changed, must update the screen 1.9471 + MPSignalSemaphore(c.wait_event); 1.9472 + result = noErr; 1.9473 + } break; 1.9474 + case kEventWindowPaint : 1.9475 + disp->paint(); 1.9476 + break; 1.9477 + } 1.9478 + 1.9479 + switch (GetEventClass(theEvent)) { 1.9480 + case kEventClassKeyboard : { 1.9481 + if (GetEventKind(theEvent)==kEventRawKeyModifiersChanged) { 1.9482 + // Apple has special keys named "notifiers", we have to convert this (exotic ?) key handling into the regular CImg processing. 1.9483 + UInt32 newModifiers; 1.9484 + if (GetEventParameter(theEvent,kEventParamKeyModifiers,typeUInt32,0,sizeof(UInt32),0,&newModifiers)==noErr) { 1.9485 + int newKeyCode = -1; 1.9486 + UInt32 changed = disp->lastKeyModifiers^newModifiers; 1.9487 + // Find what changed here 1.9488 + if ((changed & rightShiftKey)!=0) newKeyCode = cimg::keySHIFTRIGHT; 1.9489 + if ((changed & shiftKey)!=0) newKeyCode = cimg::keySHIFTLEFT; 1.9490 + 1.9491 + // On the Mac, the "option" key = the ALT key 1.9492 + if ((changed & (optionKey | rightOptionKey))!=0) newKeyCode = cimg::keyALTGR; 1.9493 + if ((changed & controlKey)!=0) newKeyCode = cimg::keyCTRLLEFT; 1.9494 + if ((changed & rightControlKey)!=0) newKeyCode = cimg::keyCTRLRIGHT; 1.9495 + if ((changed & cmdKey)!=0) newKeyCode = cimg::keyAPPLEFT; 1.9496 + if ((changed & alphaLock)!=0) newKeyCode = cimg::keyCAPSLOCK; 1.9497 + if (newKeyCode != -1) { // Simulate keystroke 1.9498 + if (disp->key) cimg_std::memmove((void*)(disp->keys+1),(void*)disp->keys,512-1); 1.9499 + disp->key = (int)newKeyCode; 1.9500 + } 1.9501 + disp->lastKeyModifiers = newModifiers; // Save current state 1.9502 + } 1.9503 + disp->is_event = true; 1.9504 + MPSignalSemaphore(c.wait_event); 1.9505 + } 1.9506 + if (GetEventKind(theEvent)==kEventRawKeyDown || GetEventKind(theEvent)==kEventRawKeyRepeat) { 1.9507 + char keyCode; 1.9508 + if (GetEventParameter(theEvent,kEventParamKeyMacCharCodes,typeChar,0,sizeof(keyCode),0,&keyCode)==noErr) { 1.9509 + disp->update_iskey((unsigned int)keyCode,true); 1.9510 + if (disp->key) cimg_std::memmove((void*)(disp->keys+1),(void*)disp->keys,512-1); 1.9511 + disp->key = (unsigned int)keyCode; 1.9512 + if (disp->released_key) { cimg_std::memmove((void*)(disp->released_keys+1),(void*)disp->released_keys,512-1); disp->released_key = 0; } 1.9513 + } 1.9514 + disp->is_event = true; 1.9515 + MPSignalSemaphore(c.wait_event); 1.9516 + } 1.9517 + } break; 1.9518 + 1.9519 + case kEventClassMouse : 1.9520 + switch (GetEventKind(theEvent)) { 1.9521 + case kEventMouseDragged : 1.9522 + // When you push the main button on the Apple mouse while moving it, you got NO kEventMouseMoved msg, 1.9523 + // but a kEventMouseDragged one. So we merge them here. 1.9524 + case kEventMouseMoved : 1.9525 + HIPoint point; 1.9526 + if (GetEventParameter(theEvent,kEventParamMouseLocation,typeHIPoint,0,sizeof(point),0,&point)==noErr) { 1.9527 + if (_CbToLocalPointFromMouseEvent(theEvent,disp->carbonWindow,&point)) { 1.9528 + disp->mouse_x = (int)point.x; 1.9529 + disp->mouse_y = (int)point.y; 1.9530 + if (disp->mouse_x<0 || disp->mouse_y<0 || disp->mouse_x>=disp->dimx() || disp->mouse_y>=disp->dimy()) 1.9531 + disp->mouse_x = disp->mouse_y = -1; 1.9532 + } else disp->mouse_x = disp->mouse_y = -1; 1.9533 + } 1.9534 + disp->is_event = true; 1.9535 + MPSignalSemaphore(c.wait_event); 1.9536 + break; 1.9537 + case kEventMouseDown : 1.9538 + UInt16 btn; 1.9539 + if (GetEventParameter(theEvent,kEventParamMouseButton,typeMouseButton,0,sizeof(btn),0,&btn)==noErr) { 1.9540 + cimg_std::memmove((void*)(disp->buttons+1),(void*)disp->buttons,512-1); 1.9541 + if (btn==kEventMouseButtonPrimary) disp->button|=1U; 1.9542 + // For those who don't have a multi-mouse button (as me), I think it's better to allow the user 1.9543 + // to emulate a right click by using the Control key 1.9544 + if ((disp->lastKeyModifiers & (controlKey | rightControlKey))!=0) 1.9545 + cimg::warn("CImgDisplay::CarbonEventHandler() : Will emulate right click now [Down]"); 1.9546 + if (btn==kEventMouseButtonSecondary || ((disp->lastKeyModifiers & (controlKey | rightControlKey))!=0)) disp->button|=2U; 1.9547 + if (btn==kEventMouseButtonTertiary) disp->button|=4U; 1.9548 + } 1.9549 + disp->is_event = true; 1.9550 + MPSignalSemaphore(c.wait_event); 1.9551 + break; 1.9552 + case kEventMouseWheelMoved : 1.9553 + EventMouseWheelAxis wheelax; 1.9554 + SInt32 delta; 1.9555 + if (GetEventParameter(theEvent,kEventParamMouseWheelAxis,typeMouseWheelAxis,0,sizeof(wheelax),0,&wheelax)==noErr) 1.9556 + if (wheelax==kEventMouseWheelAxisY) { 1.9557 + if (GetEventParameter(theEvent,kEventParamMouseWheelDelta,typeLongInteger,0,sizeof(delta),0,&delta)==noErr) 1.9558 + if (delta>0) disp->wheel+=delta/120; //FIXME: why 120 ? 1.9559 + disp->is_event = true; 1.9560 + MPSignalSemaphore(c.wait_event); 1.9561 + } 1.9562 + break; 1.9563 + } 1.9564 + } 1.9565 + 1.9566 + switch (GetEventClass(theEvent)) { 1.9567 + case kEventClassKeyboard : 1.9568 + if (GetEventKind(theEvent)==kEventRawKeyUp) { 1.9569 + UInt32 keyCode; 1.9570 + if (GetEventParameter(theEvent,kEventParamKeyCode,typeUInt32,0,sizeof(keyCode),0,&keyCode)==noErr) { 1.9571 + disp->update_iskey((unsigned int)keyCode,false); 1.9572 + if (disp->key) { cimg_std::memmove((void*)(disp->keys+1),(void*)disp->keys,512-1); disp->key = 0; } 1.9573 + if (disp->released_key) cimg_std::memmove((void*)(disp->released_keys+1),(void*)disp->released_keys,512-1); 1.9574 + disp->released_key = (int)keyCode; 1.9575 + } 1.9576 + disp->is_event = true; 1.9577 + MPSignalSemaphore(c.wait_event); 1.9578 + } 1.9579 + break; 1.9580 + 1.9581 + case kEventClassMouse : 1.9582 + switch (GetEventKind(theEvent)) { 1.9583 + case kEventMouseUp : 1.9584 + UInt16 btn; 1.9585 + if (GetEventParameter(theEvent,kEventParamMouseButton,typeMouseButton,0,sizeof(btn),0,&btn)==noErr) { 1.9586 + cimg_std::memmove((void*)(disp->buttons+1),(void*)disp->buttons,512-1); 1.9587 + if (btn==kEventMouseButtonPrimary) disp->button&=~1U; 1.9588 + // See note in kEventMouseDown handler. 1.9589 + if ((disp->lastKeyModifiers & (controlKey | rightControlKey))!=0) 1.9590 + cimg::warn("CImgDisplay::CarbonEventHandler() : Will emulate right click now [Up]"); 1.9591 + if (btn==kEventMouseButtonSecondary || ((disp->lastKeyModifiers & (controlKey | rightControlKey))!=0)) disp->button&=~2U; 1.9592 + if (btn==kEventMouseButtonTertiary) disp->button&=~2U; 1.9593 + } 1.9594 + disp->is_event = true; 1.9595 + MPSignalSemaphore(c.wait_event); 1.9596 + break; 1.9597 + } 1.9598 + } 1.9599 + } 1.9600 + return (result); 1.9601 + } 1.9602 + 1.9603 + static void* _events_thread(void* args) { 1.9604 + (void)args; // Make the compiler happy 1.9605 + cimg::CarbonInfo& c = cimg::CarbonAttr(); 1.9606 + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,0); 1.9607 + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,0); 1.9608 + MPSignalSemaphore(c.sync_event); // Notify the caller that all goes fine 1.9609 + EventRef theEvent; 1.9610 + EventTargetRef theTarget; 1.9611 + OSStatus err; 1.9612 + CbSerializedQuery* query; 1.9613 + theTarget = GetEventDispatcherTarget(); 1.9614 + 1.9615 + // Enter in the main loop 1.9616 + while (true) { 1.9617 + pthread_testcancel(); /* Check if cancelation happens */ 1.9618 + err = ReceiveNextEvent(0,0,kDurationImmediate,true,&theEvent); // Fetch new events 1.9619 + if (err==noErr) { // Received a carbon event, so process it ! 1.9620 + SendEventToEventTarget (theEvent, theTarget); 1.9621 + ReleaseEvent(theEvent); 1.9622 + } else if (err == eventLoopTimedOutErr) { // There is no event to process, so check if there is new messages to process 1.9623 + OSStatus r =MPWaitOnQueue(c.com_queue,(void**)&query,0,0,10*kDurationMillisecond); 1.9624 + if (r!=noErr) continue; //nothing in the queue or an error.., bye 1.9625 + // If we're here, we've something to do now. 1.9626 + if (query) { 1.9627 + switch (query->kind) { 1.9628 + case COM_SETMOUSEPOS : { // change the cursor position 1.9629 + query->success = CGDisplayMoveCursorToPoint(kCGDirectMainDisplay,CGPointMake(query->sender->window_x+query->x,query->sender->window_y+query->y)) 1.9630 + == kCGErrorSuccess; 1.9631 + if (query->success) { 1.9632 + query->sender->mouse_x = query->x; 1.9633 + query->sender->mouse_y = query->y; 1.9634 + } else cimg::warn("CImgDisplay::_events_thread() : CGDisplayMoveCursorToPoint failed."); 1.9635 + } break; 1.9636 + case COM_SETTITLE : { // change the title bar caption 1.9637 + CFStringRef windowTitle = CFStringCreateWithCString(0,query->c,kCFStringEncodingMacRoman); 1.9638 + query->success = SetWindowTitleWithCFString(query->sender->carbonWindow,windowTitle)==noErr; 1.9639 + if (!query->success) 1.9640 + cimg::warn("CImgDisplay::_events_thread() : SetWindowTitleWithCFString failed."); 1.9641 + CFRelease(windowTitle); 1.9642 + } break; 1.9643 + case COM_RESIZEWINDOW : { // Resize a window 1.9644 + SizeWindow(query->sender->carbonWindow,query->x,query->y,query->update); 1.9645 + // If the window has been resized successfully, update display informations 1.9646 + query->sender->window_width = query->x; 1.9647 + query->sender->window_height = query->y; 1.9648 + query->success = true; 1.9649 + } break; 1.9650 + case COM_MOVEWINDOW : { // Move a window 1.9651 + MoveWindow(query->sender->carbonWindow,query->x,query->y,false); 1.9652 + query->sender->window_x = query->x; 1.9653 + query->sender->window_y = query->y; 1.9654 + query->sender->is_moved = false; 1.9655 + query->success = true; 1.9656 + } break; 1.9657 + case COM_SHOWMOUSE : { // Show the mouse 1.9658 + query->success = CGDisplayShowCursor(kCGDirectMainDisplay)==noErr; 1.9659 + if (!query->success) 1.9660 + cimg::warn("CImgDisplay::_events_thread() : CGDisplayShowCursor failed."); 1.9661 + } break; 1.9662 + case COM_HIDEMOUSE : { // Hide the mouse 1.9663 + query->success = CGDisplayHideCursor(kCGDirectMainDisplay)==noErr; 1.9664 + if (!query->success) 1.9665 + cimg::warn("CImgDisplay::_events_thread() : CGDisplayHideCursor failed."); 1.9666 + } break; 1.9667 + case COM_SHOWWINDOW : { // We've to show a window 1.9668 + ShowWindow(query->sender->carbonWindow); 1.9669 + query->success = true; 1.9670 + query->sender->is_closed = false; 1.9671 + } break; 1.9672 + case COM_HIDEWINDOW : { // We've to show a window 1.9673 + HideWindow(query->sender->carbonWindow); 1.9674 + query->sender->is_closed = true; 1.9675 + query->sender->window_x = query->sender->window_y = 0; 1.9676 + query->success = true; 1.9677 + } break; 1.9678 + case COM_RELEASEWINDOW : { // We have to release a given window handle 1.9679 + query->success = true; 1.9680 + CFRelease(query->sender->carbonWindow); 1.9681 + } break; 1.9682 + case COM_CREATEWINDOW : { // We have to create a window 1.9683 + query->success = true; 1.9684 + WindowAttributes windowAttrs; 1.9685 + Rect contentRect; 1.9686 + if (query->createFullScreenWindow) { 1.9687 + // To simulate a "true" full screen, we remove menus and close boxes 1.9688 + windowAttrs = (1L << 9); //Why ? kWindowNoTitleBarAttribute seems to be not defined on 10.3 1.9689 + // Define a full screen bound rect 1.9690 + SetRect(&contentRect,0,0,CGDisplayPixelsWide(kCGDirectMainDisplay),CGDisplayPixelsHigh(kCGDirectMainDisplay)); 1.9691 + } else { // Set the window size 1.9692 + SetRect(&contentRect,0,0,query->sender->width,query->sender->height); // Window will be centered with RepositionWindow. 1.9693 + // Use default attributes 1.9694 + windowAttrs = kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute | kWindowInWindowMenuAttribute | kWindowLiveResizeAttribute; 1.9695 + } 1.9696 + // Update window position 1.9697 + if (query->createClosedWindow) query->sender->window_x = query->sender->window_y = 0; 1.9698 + else { 1.9699 + query->sender->window_x = contentRect.left; 1.9700 + query->sender->window_y = contentRect.top; 1.9701 + } 1.9702 + // Update window flags 1.9703 + query->sender->window_width = query->sender->width; 1.9704 + query->sender->window_height = query->sender->height; 1.9705 + query->sender->flush(); 1.9706 + // Create the window 1.9707 + if (CreateNewWindow(kDocumentWindowClass,windowAttrs,&contentRect,&query->sender->carbonWindow)!=noErr) { 1.9708 + query->success = false; 1.9709 + cimg::warn("CImgDisplay::_events_thread() : CreateNewWindow() failed."); 1.9710 + } 1.9711 + // Send it to the foreground 1.9712 + if (RepositionWindow(query->sender->carbonWindow,0,kWindowCenterOnMainScreen)!=noErr) query->success = false; 1.9713 + // Show it, if needed 1.9714 + if (!query->createClosedWindow) ShowWindow(query->sender->carbonWindow); 1.9715 + 1.9716 + // Associate a valid event handler 1.9717 + EventTypeSpec eventList[] = { 1.9718 + { kEventClassWindow, kEventWindowClose }, 1.9719 + { kEventClassWindow, kEventWindowResizeStarted }, 1.9720 + { kEventClassWindow, kEventWindowResizeCompleted }, 1.9721 + { kEventClassWindow, kEventWindowDragStarted}, 1.9722 + { kEventClassWindow, kEventWindowDragCompleted }, 1.9723 + { kEventClassWindow, kEventWindowPaint }, 1.9724 + { kEventClassWindow, kEventWindowBoundsChanging }, 1.9725 + { kEventClassWindow, kEventWindowCollapsed }, 1.9726 + { kEventClassWindow, kEventWindowExpanded }, 1.9727 + { kEventClassWindow, kEventWindowZoomed }, 1.9728 + { kEventClassKeyboard, kEventRawKeyDown }, 1.9729 + { kEventClassKeyboard, kEventRawKeyUp }, 1.9730 + { kEventClassKeyboard, kEventRawKeyRepeat }, 1.9731 + { kEventClassKeyboard, kEventRawKeyModifiersChanged }, 1.9732 + { kEventClassMouse, kEventMouseMoved }, 1.9733 + { kEventClassMouse, kEventMouseDown }, 1.9734 + { kEventClassMouse, kEventMouseUp }, 1.9735 + { kEventClassMouse, kEventMouseDragged } 1.9736 + }; 1.9737 + 1.9738 + // Set up the handler 1.9739 + if (InstallWindowEventHandler(query->sender->carbonWindow,NewEventHandlerUPP(CarbonEventHandler),GetEventTypeCount(eventList), 1.9740 + eventList,(void*)query->sender,0)!=noErr) { 1.9741 + query->success = false; 1.9742 + cimg::warn("CImgDisplay::_events_thread() : InstallWindowEventHandler failed."); 1.9743 + } 1.9744 + 1.9745 + // Paint 1.9746 + query->sender->paint(); 1.9747 + } break; 1.9748 + default : 1.9749 + cimg::warn("CImgDisplay::_events_thread() : Received unknow code %d.",query->kind); 1.9750 + } 1.9751 + // Signal that the message has been processed 1.9752 + MPSignalSemaphore(c.sync_event); 1.9753 + } 1.9754 + } 1.9755 + } 1.9756 + // If we are here, the application is now finished 1.9757 + pthread_exit(0); 1.9758 + } 1.9759 + 1.9760 + CImgDisplay& assign() { 1.9761 + if (is_empty()) return *this; 1.9762 + cimg::CarbonInfo& c = cimg::CarbonAttr(); 1.9763 + // Destroy the window associated to the display 1.9764 + _CbFreeAttachedWindow(c); 1.9765 + // Don't destroy the background thread here. 1.9766 + // If you check whether _CbFreeAttachedWindow() returned true, 1.9767 + // - saying that there were no window left on screen - and 1.9768 + // you destroy the background thread here, ReceiveNextEvent won't 1.9769 + // work anymore if you create a new window after. So the 1.9770 + // background thread must be killed (pthread_cancel() + pthread_join()) 1.9771 + // only on the application shutdown. 1.9772 + 1.9773 + // Finalize graphics 1.9774 + _CbFinalizeGraphics(); 1.9775 + 1.9776 + // Do some cleanup 1.9777 + if (data) delete[] data; 1.9778 + if (title) delete[] title; 1.9779 + width = height = normalization = window_width = window_height = 0; 1.9780 + window_x = window_y = 0; 1.9781 + is_fullscreen = false; 1.9782 + is_closed = true; 1.9783 + min = max = 0; 1.9784 + title = 0; 1.9785 + flush(); 1.9786 + if (MPDeleteCriticalRegion(paintCriticalRegion)!=noErr) 1.9787 + throw CImgDisplayException("CImgDisplay()::assign() : MPDeleteCriticalRegion failed."); 1.9788 + return *this; 1.9789 + } 1.9790 + 1.9791 + CImgDisplay& _assign(const unsigned int dimw, const unsigned int dimh, const char *ptitle=0, 1.9792 + const unsigned int normalization_type=3, 1.9793 + const bool fullscreen_flag=false, const bool closed_flag=false) { 1.9794 + cimg::CarbonInfo& c = cimg::CarbonAttr(); 1.9795 + 1.9796 + // Allocate space for window title 1.9797 + const int s = cimg::strlen(ptitle)+1; 1.9798 + char *tmp_title = s?new char[s]:0; 1.9799 + if (s) cimg_std::memcpy(tmp_title,ptitle,s*sizeof(char)); 1.9800 + 1.9801 + // Destroy previous window if existing 1.9802 + if (!is_empty()) assign(); 1.9803 + 1.9804 + // Set display variables 1.9805 + width = cimg::min(dimw,(unsigned int)screen_dimx()); 1.9806 + height = cimg::min(dimh,(unsigned int)screen_dimy()); 1.9807 + normalization = normalization_type<4?normalization_type:3; 1.9808 + is_fullscreen = fullscreen_flag; 1.9809 + is_closed = closed_flag; 1.9810 + lastKeyModifiers = 0; 1.9811 + title = tmp_title; 1.9812 + flush(); 1.9813 + 1.9814 + // Create the paint CR 1.9815 + if (MPCreateCriticalRegion(&paintCriticalRegion) != noErr) 1.9816 + throw CImgDisplayException("CImgDisplay::_assign() : MPCreateCriticalRegion() failed."); 1.9817 + 1.9818 + // Create the thread if it's not already created 1.9819 + if (c.event_thread==0) { 1.9820 + // Background thread does not exists, so create it ! 1.9821 + if (pthread_create(&c.event_thread,0,_events_thread,0)!=0) 1.9822 + throw CImgDisplayException("CImgDisplay::_assign() : pthread_create() failed."); 1.9823 + // Wait for thread initialization 1.9824 + MPWaitOnSemaphore(c.sync_event, kDurationForever); 1.9825 + } 1.9826 + 1.9827 + // Init disp. graphics 1.9828 + data = new unsigned int[width*height]; 1.9829 + _CbInitializeGraphics(); 1.9830 + 1.9831 + // Now ask the thread to create the window 1.9832 + _CbCreateAttachedWindow(c,ptitle,fullscreen_flag,closed_flag); 1.9833 + return *this; 1.9834 + } 1.9835 + 1.9836 +#endif 1.9837 + 1.9838 + }; 1.9839 + 1.9840 + /* 1.9841 + #-------------------------------------- 1.9842 + # 1.9843 + # 1.9844 + # 1.9845 + # Definition of the CImg<T> structure 1.9846 + # 1.9847 + # 1.9848 + # 1.9849 + #-------------------------------------- 1.9850 + */ 1.9851 + 1.9852 + //! Class representing an image (up to 4 dimensions wide), each pixel being of type \c T. 1.9853 + /** 1.9854 + This is the main class of the %CImg Library. It declares and constructs 1.9855 + an image, allows access to its pixel values, and is able to perform various image operations. 1.9856 + 1.9857 + \par Image representation 1.9858 + 1.9859 + A %CImg image is defined as an instance of the container \ref CImg<\c T>, which contains a regular grid of pixels, 1.9860 + each pixel value being of type \c T. The image grid can have up to 4 dimensions : width, height, depth 1.9861 + and number of channels. 1.9862 + Usually, the three first dimensions are used to describe spatial coordinates <tt>(x,y,z)</tt>, while the number of channels 1.9863 + is rather used as a vector-valued dimension (it may describe the R,G,B color channels for instance). 1.9864 + If you need a fifth dimension, you can use image lists \ref CImgList<\c T> rather than simple images \ref CImg<\c T>. 1.9865 + 1.9866 + Thus, the \ref CImg<\c T> class is able to represent volumetric images of vector-valued pixels, 1.9867 + as well as images with less dimensions (1D scalar signal, 2D color images, ...). 1.9868 + Most member functions of the class CImg<\c T> are designed to handle this maximum case of (3+1) dimensions. 1.9869 + 1.9870 + Concerning the pixel value type \c T : 1.9871 + fully supported template types are the basic C++ types : <tt>unsigned char, char, short, unsigned int, int, 1.9872 + unsigned long, long, float, double, ... </tt>. 1.9873 + Typically, fast image display can be done using <tt>CImg<unsigned char></tt> images, 1.9874 + while complex image processing algorithms may be rather coded using <tt>CImg<float></tt> or <tt>CImg<double></tt> 1.9875 + images that have floating-point pixel values. The default value for the template T is \c float. 1.9876 + Using your own template types may be possible. However, you will certainly have to define the complete set 1.9877 + of arithmetic and logical operators for your class. 1.9878 + 1.9879 + \par Image structure 1.9880 + 1.9881 + The \ref CImg<\c T> structure contains \a six fields : 1.9882 + - \ref width defines the number of \a columns of the image (size along the X-axis). 1.9883 + - \ref height defines the number of \a rows of the image (size along the Y-axis). 1.9884 + - \ref depth defines the number of \a slices of the image (size along the Z-axis). 1.9885 + - \ref dim defines the number of \a channels of the image (size along the V-axis). 1.9886 + - \ref data defines a \a pointer to the \a pixel \a data (of type \c T). 1.9887 + - \ref is_shared is a boolean that tells if the memory buffer \ref data is shared with 1.9888 + another image. 1.9889 + 1.9890 + You can access these fields publicly although it is recommended to use the dedicated functions 1.9891 + dimx(), dimy(), dimz(), dimv() and ptr() to do so. 1.9892 + Image dimensions are not limited to a specific range (as long as you got enough available memory). 1.9893 + A value of \e 1 usually means that the corresponding dimension is \a flat. 1.9894 + If one of the dimensions is \e 0, or if the data pointer is null, the image is considered as \e empty. 1.9895 + Empty images should not contain any pixel data and thus, will not be processed by CImg member functions 1.9896 + (a CImgInstanceException will be thrown instead). 1.9897 + Pixel data are stored in memory, in a non interlaced mode (See \ref cimg_storage). 1.9898 + 1.9899 + \par Image declaration and construction 1.9900 + 1.9901 + Declaring an image can be done by using one of the several available constructors. 1.9902 + Here is a list of the most used : 1.9903 + 1.9904 + - Construct images from arbitrary dimensions : 1.9905 + - <tt>CImg<char> img;</tt> declares an empty image. 1.9906 + - <tt>CImg<unsigned char> img(128,128);</tt> declares a 128x128 greyscale image with 1.9907 + \c unsigned \c char pixel values. 1.9908 + - <tt>CImg<double> img(3,3);</tt> declares a 3x3 matrix with \c double coefficients. 1.9909 + - <tt>CImg<unsigned char> img(256,256,1,3);</tt> declares a 256x256x1x3 (color) image 1.9910 + (colors are stored as an image with three channels). 1.9911 + - <tt>CImg<double> img(128,128,128);</tt> declares a 128x128x128 volumetric and greyscale image 1.9912 + (with \c double pixel values). 1.9913 + - <tt>CImg<> img(128,128,128,3);</tt> declares a 128x128x128 volumetric color image 1.9914 + (with \c float pixels, which is the default value of the template parameter \c T). 1.9915 + - \b Note : images pixels are <b>not automatically initialized to 0</b>. You may use the function \ref fill() to 1.9916 + do it, or use the specific constructor taking 5 parameters like this : 1.9917 + <tt>CImg<> img(128,128,128,3,0);</tt> declares a 128x128x128 volumetric color image with all pixel values to 0. 1.9918 + 1.9919 + - Construct images from filenames : 1.9920 + - <tt>CImg<unsigned char> img("image.jpg");</tt> reads a JPEG color image from the file "image.jpg". 1.9921 + - <tt>CImg<float> img("analyze.hdr");</tt> reads a volumetric image (ANALYZE7.5 format) from the file "analyze.hdr". 1.9922 + - \b Note : You need to install <a href="http://www.imagemagick.org">ImageMagick</a> 1.9923 + to be able to read common compressed image formats (JPG,PNG, ...) (See \ref cimg_files_io). 1.9924 + 1.9925 + - Construct images from C-style arrays : 1.9926 + - <tt>CImg<int> img(data_buffer,256,256);</tt> constructs a 256x256 greyscale image from a \c int* buffer 1.9927 + \c data_buffer (of size 256x256=65536). 1.9928 + - <tt>CImg<unsigned char> img(data_buffer,256,256,1,3,false);</tt> constructs a 256x256 color image 1.9929 + from a \c unsigned \c char* buffer \c data_buffer (where R,G,B channels follow each others). 1.9930 + - <tt>CImg<unsigned char> img(data_buffer,256,256,1,3,true);</tt> constructs a 256x256 color image 1.9931 + from a \c unsigned \c char* buffer \c data_buffer (where R,G,B channels are multiplexed). 1.9932 + 1.9933 + The complete list of constructors can be found <a href="#constructors">here</a>. 1.9934 + 1.9935 + \par Most useful functions 1.9936 + 1.9937 + The \ref CImg<\c T> class contains a lot of functions that operates on images. 1.9938 + Some of the most useful are : 1.9939 + 1.9940 + - operator()(), operator[]() : allows to access or write pixel values. 1.9941 + - display() : displays the image in a new window. 1.9942 + **/ 1.9943 + template<typename T> 1.9944 + struct CImg { 1.9945 + 1.9946 + //! Variable representing the width of the instance image (i.e. dimensions along the X-axis). 1.9947 + /** 1.9948 + \remark 1.9949 + - Prefer using the function CImg<T>::dimx() to get information about the width of an image. 1.9950 + - Use function CImg<T>::resize() to set a new width for an image. Setting directly the variable \c width would probably 1.9951 + result in a library crash. 1.9952 + - Empty images have \c width defined to \c 0. 1.9953 + **/ 1.9954 + unsigned int width; 1.9955 + 1.9956 + //! Variable representing the height of the instance image (i.e. dimensions along the Y-axis). 1.9957 + /** 1.9958 + \remark 1.9959 + - Prefer using the function CImg<T>::dimy() to get information about the height of an image. 1.9960 + - Use function CImg<T>::resize() to set a new height for an image. Setting directly the variable \c height would probably 1.9961 + result in a library crash. 1.9962 + - 1D signals have \c height defined to \c 1. 1.9963 + - Empty images have \c height defined to \c 0. 1.9964 + **/ 1.9965 + unsigned int height; 1.9966 + 1.9967 + //! Variable representing the depth of the instance image (i.e. dimensions along the Z-axis). 1.9968 + /** 1.9969 + \remark 1.9970 + - Prefer using the function CImg<T>::dimz() to get information about the depth of an image. 1.9971 + - Use function CImg<T>::resize() to set a new depth for an image. Setting directly the variable \c depth would probably 1.9972 + result in a library crash. 1.9973 + - Classical 2D images have \c depth defined to \c 1. 1.9974 + - Empty images have \c depth defined to \c 0. 1.9975 + **/ 1.9976 + unsigned int depth; 1.9977 + 1.9978 + //! Variable representing the number of channels of the instance image (i.e. dimensions along the V-axis). 1.9979 + /** 1.9980 + \remark 1.9981 + - Prefer using the function CImg<T>::dimv() to get information about the depth of an image. 1.9982 + - Use function CImg<T>::resize() to set a new vector dimension for an image. Setting directly the variable \c dim would probably 1.9983 + result in a library crash. 1.9984 + - Scalar-valued images (one value per pixel) have \c dim defined to \c 1. 1.9985 + - Empty images have \c depth defined to \c 0. 1.9986 + **/ 1.9987 + unsigned int dim; 1.9988 + 1.9989 + //! Variable telling if pixel buffer of the instance image is shared with another one. 1.9990 + bool is_shared; 1.9991 + 1.9992 + //! Pointer to the first pixel of the pixel buffer. 1.9993 + T *data; 1.9994 + 1.9995 + //! Iterator type for CImg<T>. 1.9996 + /** 1.9997 + \remark 1.9998 + - An \p iterator is a <tt>T*</tt> pointer (address of a pixel value in the pixel buffer). 1.9999 + - Iterators are not directly used in %CImg functions, they have been introduced for compatibility with the STL. 1.10000 + **/ 1.10001 + typedef T* iterator; 1.10002 + 1.10003 + //! Const iterator type for CImg<T>. 1.10004 + /** 1.10005 + \remark 1.10006 + - A \p const_iterator is a <tt>const T*</tt> pointer (address of a pixel value in the pixel buffer). 1.10007 + - Iterators are not directly used in %CImg functions, they have been introduced for compatibility with the STL. 1.10008 + **/ 1.10009 + typedef const T* const_iterator; 1.10010 + 1.10011 + //! Get value type 1.10012 + typedef T value_type; 1.10013 + 1.10014 + // Define common T-dependant types. 1.10015 + typedef typename cimg::superset<T,bool>::type Tbool; 1.10016 + typedef typename cimg::superset<T,unsigned char>::type Tuchar; 1.10017 + typedef typename cimg::superset<T,char>::type Tchar; 1.10018 + typedef typename cimg::superset<T,unsigned short>::type Tushort; 1.10019 + typedef typename cimg::superset<T,short>::type Tshort; 1.10020 + typedef typename cimg::superset<T,unsigned int>::type Tuint; 1.10021 + typedef typename cimg::superset<T,int>::type Tint; 1.10022 + typedef typename cimg::superset<T,unsigned long>::type Tulong; 1.10023 + typedef typename cimg::superset<T,long>::type Tlong; 1.10024 + typedef typename cimg::superset<T,float>::type Tfloat; 1.10025 + typedef typename cimg::superset<T,double>::type Tdouble; 1.10026 + typedef typename cimg::last<T,bool>::type boolT; 1.10027 + typedef typename cimg::last<T,unsigned char>::type ucharT; 1.10028 + typedef typename cimg::last<T,char>::type charT; 1.10029 + typedef typename cimg::last<T,unsigned short>::type ushortT; 1.10030 + typedef typename cimg::last<T,short>::type shortT; 1.10031 + typedef typename cimg::last<T,unsigned int>::type uintT; 1.10032 + typedef typename cimg::last<T,int>::type intT; 1.10033 + typedef typename cimg::last<T,unsigned long>::type ulongT; 1.10034 + typedef typename cimg::last<T,long>::type longT; 1.10035 + typedef typename cimg::last<T,float>::type floatT; 1.10036 + typedef typename cimg::last<T,double>::type doubleT; 1.10037 + 1.10038 + //@} 1.10039 + //--------------------------- 1.10040 + // 1.10041 + //! \name Plugins 1.10042 + //@{ 1.10043 + //--------------------------- 1.10044 +#ifdef cimg_plugin 1.10045 +#include cimg_plugin 1.10046 +#endif 1.10047 +#ifdef cimg_plugin1 1.10048 +#include cimg_plugin1 1.10049 +#endif 1.10050 +#ifdef cimg_plugin2 1.10051 +#include cimg_plugin2 1.10052 +#endif 1.10053 +#ifdef cimg_plugin3 1.10054 +#include cimg_plugin3 1.10055 +#endif 1.10056 +#ifdef cimg_plugin4 1.10057 +#include cimg_plugin4 1.10058 +#endif 1.10059 +#ifdef cimg_plugin5 1.10060 +#include cimg_plugin5 1.10061 +#endif 1.10062 +#ifdef cimg_plugin6 1.10063 +#include cimg_plugin6 1.10064 +#endif 1.10065 +#ifdef cimg_plugin7 1.10066 +#include cimg_plugin7 1.10067 +#endif 1.10068 +#ifdef cimg_plugin8 1.10069 +#include cimg_plugin8 1.10070 +#endif 1.10071 +#ifndef cimg_plugin_greycstoration 1.10072 +#define cimg_plugin_greycstoration_count 1.10073 +#endif 1.10074 +#ifndef cimg_plugin_greycstoration_lock 1.10075 +#define cimg_plugin_greycstoration_lock 1.10076 +#endif 1.10077 +#ifndef cimg_plugin_greycstoration_unlock 1.10078 +#define cimg_plugin_greycstoration_unlock 1.10079 +#endif 1.10080 + 1.10081 + //@} 1.10082 + 1.10083 + //-------------------------------------- 1.10084 + // 1.10085 + //! \name Constructors-Destructor-Copy 1.10086 + //@{ 1.10087 + //-------------------------------------- 1.10088 + 1.10089 + //! Destructor. 1.10090 + /** 1.10091 + The destructor destroys the instance image. 1.10092 + \remark 1.10093 + - Destructing an empty or shared image does nothing. 1.10094 + - Otherwise, all memory used to store the pixel data of the instance image is freed. 1.10095 + - When destroying a non-shared image, be sure that every shared instances of the same image are 1.10096 + also destroyed to avoid further access to desallocated memory buffers. 1.10097 + **/ 1.10098 + ~CImg() { 1.10099 + if (data && !is_shared) delete[] data; 1.10100 + } 1.10101 + 1.10102 + //! Default constructor. 1.10103 + /** 1.10104 + The default constructor creates an empty instance image. 1.10105 + \remark 1.10106 + - An empty image does not contain any data and has all of its dimensions \ref width, \ref height, \ref depth, \ref dim 1.10107 + set to 0 as well as its pointer to the pixel buffer \ref data. 1.10108 + - An empty image is non-shared. 1.10109 + **/ 1.10110 + CImg(): 1.10111 + width(0),height(0),depth(0),dim(0),is_shared(false),data(0) {} 1.10112 + 1.10113 + //! Constructs a new image with given size (\p dx,\p dy,\p dz,\p dv). 1.10114 + /** 1.10115 + This constructors create an instance image of size (\p dx,\p dy,\p dz,\p dv) with pixels of type \p T. 1.10116 + \param dx Desired size along the X-axis, i.e. the \ref width of the image. 1.10117 + \param dy Desired size along the Y-axis, i.e. the \ref height of the image. 1.10118 + \param dz Desired size along the Z-axis, i.e. the \ref depth of the image. 1.10119 + \param dv Desired size along the V-axis, i.e. the number of image channels \ref dim. 1.10120 + \remark 1.10121 + - If one of the input dimension \p dx,\p dy,\p dz or \p dv is set to 0, the created image is empty 1.10122 + and all has its dimensions set to 0. No memory for pixel data is then allocated. 1.10123 + - This constructor creates only non-shared images. 1.10124 + - Image pixels allocated by this constructor are \b not \b initialized. 1.10125 + Use the constructor CImg(const unsigned int,const unsigned int,const unsigned int,const unsigned int,const T) 1.10126 + to get an image of desired size with pixels set to a particular value. 1.10127 + **/ 1.10128 + explicit CImg(const unsigned int dx, const unsigned int dy=1, const unsigned int dz=1, const unsigned int dv=1): 1.10129 + is_shared(false) { 1.10130 + const unsigned long siz = dx*dy*dz*dv; 1.10131 + if (siz) { width = dx; height = dy; depth = dz; dim = dv; data = new T[siz]; } 1.10132 + else { width = height = depth = dim = 0; data = 0; } 1.10133 + } 1.10134 + 1.10135 + //! Construct an image with given size (\p dx,\p dy,\p dz,\p dv) and with pixel having a default value \p val. 1.10136 + /** 1.10137 + This constructor creates an instance image of size (\p dx,\p dy,\p dz,\p dv) with pixels of type \p T and sets all pixel 1.10138 + values of the created instance image to \p val. 1.10139 + \param dx Desired size along the X-axis, i.e. the \ref width of the image. 1.10140 + \param dy Desired size along the Y-axis, i.e. the \ref height of the image. 1.10141 + \param dz Desired size along the Z-axis, i.e. the \ref depth of the image. 1.10142 + \param dv Desired size along the V-axis, i.e. the number of image channels \p dim. 1.10143 + \param val Default value for image pixels. 1.10144 + \remark 1.10145 + - This constructor has the same properties as CImg(const unsigned int,const unsigned int,const unsigned int,const unsigned int). 1.10146 + **/ 1.10147 + CImg(const unsigned int dx, const unsigned int dy, const unsigned int dz, const unsigned int dv, const T val): 1.10148 + is_shared(false) { 1.10149 + const unsigned long siz = dx*dy*dz*dv; 1.10150 + if (siz) { width = dx; height = dy; depth = dz; dim = dv; data = new T[siz]; fill(val); } 1.10151 + else { width = height = depth = dim = 0; data = 0; } 1.10152 + } 1.10153 + 1.10154 + //! Construct an image with given size (\p dx,\p dy,\p dz,\p dv) and with specified pixel values (int version). 1.10155 + CImg(const unsigned int dx, const unsigned int dy, const unsigned int dz, const unsigned int dv, 1.10156 + const int val0, const int val1, ...):width(0),height(0),depth(0),dim(0),is_shared(false),data(0) { 1.10157 +#define _CImg_stdarg(img,a0,a1,N,t) { \ 1.10158 + unsigned int _siz = (unsigned int)N; \ 1.10159 + if (_siz--) { \ 1.10160 + va_list ap; \ 1.10161 + va_start(ap,a1); \ 1.10162 + T *ptrd = (img).data; \ 1.10163 + *(ptrd++) = (T)a0; \ 1.10164 + if (_siz--) { \ 1.10165 + *(ptrd++) = (T)a1; \ 1.10166 + for (; _siz; --_siz) *(ptrd++) = (T)va_arg(ap,t); \ 1.10167 + } \ 1.10168 + va_end(ap); \ 1.10169 + }} 1.10170 + assign(dx,dy,dz,dv); 1.10171 + _CImg_stdarg(*this,val0,val1,dx*dy*dz*dv,int); 1.10172 + } 1.10173 + 1.10174 + //! Construct an image with given size (\p dx,\p dy,\p dz,\p dv) and with specified pixel values (double version). 1.10175 + CImg(const unsigned int dx, const unsigned int dy, const unsigned int dz, const unsigned int dv, 1.10176 + const double val0, const double val1, ...):width(0),height(0),depth(0),dim(0),is_shared(false),data(0) { 1.10177 + assign(dx,dy,dz,dv); 1.10178 + _CImg_stdarg(*this,val0,val1,dx*dy*dz*dv,double); 1.10179 + } 1.10180 + 1.10181 + //! Construct an image with given size and with specified values given in a string. 1.10182 + CImg(const unsigned int dx, const unsigned int dy, const unsigned int dz, const unsigned int dv, 1.10183 + const char *const values, const bool repeat_pattern):is_shared(false) { 1.10184 + const unsigned long siz = dx*dy*dz*dv; 1.10185 + if (siz) { width = dx; height = dy; depth = dz; dim = dv; data = new T[siz]; fill(values,repeat_pattern); } 1.10186 + else { width = height = depth = dim = 0; data = 0; } 1.10187 + } 1.10188 + 1.10189 + //! Construct an image from a raw memory buffer. 1.10190 + /** 1.10191 + This constructor creates an instance image of size (\p dx,\p dy,\p dz,\p dv) and fill its pixel buffer by 1.10192 + copying data values from the input raw pixel buffer \p data_buffer. 1.10193 + **/ 1.10194 + template<typename t> 1.10195 + CImg(const t *const data_buffer, const unsigned int dx, const unsigned int dy=1, 1.10196 + const unsigned int dz=1, const unsigned int dv=1, const bool shared=false):is_shared(false) { 1.10197 + if (shared) 1.10198 + throw CImgArgumentException("CImg<%s>::CImg() : Cannot construct a shared instance image from a (%s*) buffer " 1.10199 + "(different pixel types).", 1.10200 + pixel_type(),CImg<t>::pixel_type()); 1.10201 + const unsigned long siz = dx*dy*dz*dv; 1.10202 + if (data_buffer && siz) { 1.10203 + width = dx; height = dy; depth = dz; dim = dv; data = new T[siz]; 1.10204 + const t *ptrs = data_buffer + siz; cimg_for(*this,ptrd,T) *ptrd = (T)*(--ptrs); 1.10205 + } else { width = height = depth = dim = 0; data = 0; } 1.10206 + } 1.10207 + 1.10208 +#ifndef cimg_use_visualcpp6 1.10209 + CImg(const T *const data_buffer, const unsigned int dx, const unsigned int dy=1, 1.10210 + const unsigned int dz=1, const unsigned int dv=1, const bool shared=false) 1.10211 +#else 1.10212 + CImg(const T *const data_buffer, const unsigned int dx, const unsigned int dy, 1.10213 + const unsigned int dz, const unsigned int dv, const bool shared) 1.10214 +#endif 1.10215 + { 1.10216 + const unsigned long siz = dx*dy*dz*dv; 1.10217 + if (data_buffer && siz) { 1.10218 + width = dx; height = dy; depth = dz; dim = dv; is_shared = shared; 1.10219 + if (is_shared) data = const_cast<T*>(data_buffer); 1.10220 + else { data = new T[siz]; cimg_std::memcpy(data,data_buffer,siz*sizeof(T)); } 1.10221 + } else { width = height = depth = dim = 0; is_shared = false; data = 0; } 1.10222 + } 1.10223 + 1.10224 + //! Default copy constructor. 1.10225 + /** 1.10226 + The default copy constructor creates a new instance image having same dimensions 1.10227 + (\ref width, \ref height, \ref depth, \ref dim) and same pixel values as the input image \p img. 1.10228 + \param img The input image to copy. 1.10229 + \remark 1.10230 + - If the input image \p img is non-shared or have a different template type \p t != \p T, 1.10231 + the default copy constructor allocates a new pixel buffer and copy the pixel data 1.10232 + of \p img into it. In this case, the pointers \ref data to the pixel buffers of the two images are different 1.10233 + and the resulting instance image is non-shared. 1.10234 + - If the input image \p img is shared and has the same template type \p t == \p T, 1.10235 + the default copy constructor does not allocate a new pixel buffer and the resulting instance image 1.10236 + shares its pixel buffer with the input image \p img, which means that modifying pixels of \p img also modifies 1.10237 + the created instance image. 1.10238 + - Copying an image having a different template type \p t != \p T performs a crude static cast conversion of each pixel value from 1.10239 + type \p t to type \p T. 1.10240 + - Copying an image having the same template type \p t == \p T is significantly faster. 1.10241 + **/ 1.10242 + template<typename t> 1.10243 + CImg(const CImg<t>& img):is_shared(false) { 1.10244 + const unsigned int siz = img.size(); 1.10245 + if (img.data && siz) { 1.10246 + width = img.width; height = img.height; depth = img.depth; dim = img.dim; data = new T[siz]; 1.10247 + const t *ptrs = img.data + siz; cimg_for(*this,ptrd,T) *ptrd = (T)*(--ptrs); 1.10248 + } else { width = height = depth = dim = 0; data = 0; } 1.10249 + } 1.10250 + 1.10251 + CImg(const CImg<T>& img) { 1.10252 + const unsigned int siz = img.size(); 1.10253 + if (img.data && siz) { 1.10254 + width = img.width; height = img.height; depth = img.depth; dim = img.dim; is_shared = img.is_shared; 1.10255 + if (is_shared) data = const_cast<T*>(img.data); 1.10256 + else { data = new T[siz]; cimg_std::memcpy(data,img.data,siz*sizeof(T)); } 1.10257 + } else { width = height = depth = dim = 0; is_shared = false; data = 0; } 1.10258 + } 1.10259 + 1.10260 + //! Advanced copy constructor. 1.10261 + /** 1.10262 + The advanced copy constructor - as the default constructor CImg(const CImg< t >&) - creates a new instance image having same dimensions 1.10263 + \ref width, \ref height, \ref depth, \ref dim and same pixel values as the input image \p img. 1.10264 + But it also decides if the created instance image shares its memory with the input image \p img (if the input parameter 1.10265 + \p shared is set to \p true) or not (if the input parameter \p shared is set to \p false). 1.10266 + \param img The input image to copy. 1.10267 + \param shared Boolean flag that decides if the copy is shared on non-shared. 1.10268 + \remark 1.10269 + - It is not possible to create a shared copy if the input image \p img is empty or has a different pixel type \p t != \p T. 1.10270 + - If a non-shared copy of the input image \p img is created, a new memory buffer is allocated for pixel data. 1.10271 + - If a shared copy of the input image \p img is created, no extra memory is allocated and the pixel buffer of the instance 1.10272 + image is the same as the one used by the input image \p img. 1.10273 + **/ 1.10274 + template<typename t> 1.10275 + CImg(const CImg<t>& img, const bool shared):is_shared(false) { 1.10276 + if (shared) 1.10277 + throw CImgArgumentException("CImg<%s>::CImg() : Cannot construct a shared instance image from a CImg<%s> instance " 1.10278 + "(different pixel types).", 1.10279 + pixel_type(),CImg<t>::pixel_type()); 1.10280 + const unsigned int siz = img.size(); 1.10281 + if (img.data && siz) { 1.10282 + width = img.width; height = img.height; depth = img.depth; dim = img.dim; data = new T[siz]; 1.10283 + const t *ptrs = img.data + siz; cimg_for(*this,ptrd,T) *ptrd = (T)*(--ptrs); 1.10284 + } else { width = height = depth = dim = 0; data = 0; } 1.10285 + } 1.10286 + 1.10287 + CImg(const CImg<T>& img, const bool shared) { 1.10288 + const unsigned int siz = img.size(); 1.10289 + if (img.data && siz) { 1.10290 + width = img.width; height = img.height; depth = img.depth; dim = img.dim; is_shared = shared; 1.10291 + if (is_shared) data = const_cast<T*>(img.data); 1.10292 + else { data = new T[siz]; cimg_std::memcpy(data,img.data,siz*sizeof(T)); } 1.10293 + } else { width = height = depth = dim = 0; is_shared = false; data = 0; } 1.10294 + } 1.10295 + 1.10296 + //! Construct an image using dimensions of another image 1.10297 + template<typename t> 1.10298 + CImg(const CImg<t>& img, const char *const dimensions):width(0),height(0),depth(0),dim(0),is_shared(false),data(0) { 1.10299 + assign(img,dimensions); 1.10300 + } 1.10301 + 1.10302 + //! Construct an image using dimensions of another image, and fill it with a default value 1.10303 + template<typename t> 1.10304 + CImg(const CImg<t>& img, const char *const dimensions, const T val): 1.10305 + width(0),height(0),depth(0),dim(0),is_shared(false),data(0) { 1.10306 + assign(img,dimensions).fill(val); 1.10307 + } 1.10308 + 1.10309 + //! Construct an image from an image file. 1.10310 + /** 1.10311 + This constructor creates an instance image by reading it from a file. 1.10312 + \param filename Filename of the image file. 1.10313 + \remark 1.10314 + - The image format is deduced from the filename only by looking for the filename extension i.e. without 1.10315 + analyzing the file itself. 1.10316 + - Recognized image formats depend on the tools installed on your system or the external libraries you use to link your code with. 1.10317 + More informations on this topic can be found in cimg_files_io. 1.10318 + - If the filename is not found, a CImgIOException is thrown by this constructor. 1.10319 + **/ 1.10320 + CImg(const char *const filename):width(0),height(0),depth(0),dim(0),is_shared(false),data(0) { 1.10321 + assign(filename); 1.10322 + } 1.10323 + 1.10324 + //! Construct an image from the content of a CImgDisplay instance. 1.10325 + CImg(const CImgDisplay &disp):width(0),height(0),depth(0),dim(0),is_shared(false),data(0) { 1.10326 + disp.snapshot(*this); 1.10327 + } 1.10328 + 1.10329 + //! In-place version of the default constructor/destructor. 1.10330 + /** 1.10331 + This function replaces the instance image by an empty image. 1.10332 + \remark 1.10333 + - Memory used by the previous content of the instance image is freed if necessary. 1.10334 + - If the instance image was initially shared, it is replaced by a (non-shared) empty image. 1.10335 + - This function is useful to free memory used by an image that is not of use, but which 1.10336 + has been created in the current code scope (i.e. not destroyed yet). 1.10337 + **/ 1.10338 + CImg<T>& assign() { 1.10339 + if (data && !is_shared) delete[] data; 1.10340 + width = height = depth = dim = 0; is_shared = false; data = 0; 1.10341 + return *this; 1.10342 + } 1.10343 + 1.10344 + //! In-place version of the default constructor. 1.10345 + /** 1.10346 + This function is strictly equivalent to \ref assign() and has been 1.10347 + introduced for having a STL-compliant function name. 1.10348 + **/ 1.10349 + CImg<T>& clear() { 1.10350 + return assign(); 1.10351 + } 1.10352 + 1.10353 + //! In-place version of the previous constructor. 1.10354 + /** 1.10355 + This function replaces the instance image by a new image of size (\p dx,\p dy,\p dz,\p dv) with pixels of type \p T. 1.10356 + \param dx Desired size along the X-axis, i.e. the \ref width of the image. 1.10357 + \param dy Desired size along the Y-axis, i.e. the \ref height of the image. 1.10358 + \param dz Desired size along the Z-axis, i.e. the \ref depth of the image. 1.10359 + \param dv Desired size along the V-axis, i.e. the number of image channels \p dim. 1.10360 + - If one of the input dimension \p dx,\p dy,\p dz or \p dv is set to 0, the instance image becomes empty 1.10361 + and all has its dimensions set to 0. No memory for pixel data is then allocated. 1.10362 + - Memory buffer used to store previous pixel values is freed if necessary. 1.10363 + - If the instance image is shared, this constructor actually does nothing more than verifying 1.10364 + that new and old image dimensions fit. 1.10365 + - Image pixels allocated by this function are \b not \b initialized. 1.10366 + Use the function assign(const unsigned int,const unsigned int,const unsigned int,const unsigned int,const T) 1.10367 + to assign an image of desired size with pixels set to a particular value. 1.10368 + **/ 1.10369 + CImg<T>& assign(const unsigned int dx, const unsigned int dy=1, const unsigned int dz=1, const unsigned int dv=1) { 1.10370 + const unsigned long siz = dx*dy*dz*dv; 1.10371 + if (!siz) return assign(); 1.10372 + const unsigned long curr_siz = size(); 1.10373 + if (siz!=curr_siz) { 1.10374 + if (is_shared) 1.10375 + throw CImgArgumentException("CImg<%s>::assign() : Cannot assign image (%u,%u,%u,%u) to shared instance image (%u,%u,%u,%u,%p).", 1.10376 + pixel_type(),dx,dy,dz,dv,width,height,depth,dim,data); 1.10377 + else { if (data) delete[] data; data = new T[siz]; } 1.10378 + } 1.10379 + width = dx; height = dy; depth = dz; dim = dv; 1.10380 + return *this; 1.10381 + } 1.10382 + 1.10383 + //! In-place version of the previous constructor. 1.10384 + /** 1.10385 + This function replaces the instance image by a new image of size (\p dx,\p dy,\p dz,\p dv) with pixels of type \p T 1.10386 + and sets all pixel values of the instance image to \p val. 1.10387 + \param dx Desired size along the X-axis, i.e. the \ref width of the image. 1.10388 + \param dy Desired size along the Y-axis, i.e. the \ref height of the image. 1.10389 + \param dz Desired size along the Z-axis, i.e. the \ref depth of the image. 1.10390 + \param dv Desired size along the V-axis, i.e. the number of image channels \p dim. 1.10391 + \param val Default value for image pixels. 1.10392 + \remark 1.10393 + - This function has the same properties as assign(const unsigned int,const unsigned int,const unsigned int,const unsigned int). 1.10394 + **/ 1.10395 + CImg<T>& assign(const unsigned int dx, const unsigned int dy, const unsigned int dz, const unsigned int dv, const T val) { 1.10396 + return assign(dx,dy,dz,dv).fill(val); 1.10397 + } 1.10398 + 1.10399 + //! In-place version of the previous constructor. 1.10400 + CImg<T>& assign(const unsigned int dx, const unsigned int dy, const unsigned int dz, const unsigned int dv, 1.10401 + const int val0, const int val1, ...) { 1.10402 + assign(dx,dy,dz,dv); 1.10403 + _CImg_stdarg(*this,val0,val1,dx*dy*dz*dv,int); 1.10404 + return *this; 1.10405 + } 1.10406 + 1.10407 + //! In-place version of the previous constructor. 1.10408 + CImg<T>& assign(const unsigned int dx, const unsigned int dy, const unsigned int dz, const unsigned int dv, 1.10409 + const double val0, const double val1, ...) { 1.10410 + assign(dx,dy,dz,dv); 1.10411 + _CImg_stdarg(*this,val0,val1,dx*dy*dz*dv,double); 1.10412 + return *this; 1.10413 + } 1.10414 + 1.10415 + //! In-place version of the previous constructor. 1.10416 + template<typename t> 1.10417 + CImg<T>& assign(const t *const data_buffer, const unsigned int dx, const unsigned int dy=1, 1.10418 + const unsigned int dz=1, const unsigned int dv=1) { 1.10419 + const unsigned long siz = dx*dy*dz*dv; 1.10420 + if (!data_buffer || !siz) return assign(); 1.10421 + assign(dx,dy,dz,dv); 1.10422 + const t *ptrs = data_buffer + siz; cimg_for(*this,ptrd,T) *ptrd = (T)*(--ptrs); 1.10423 + return *this; 1.10424 + } 1.10425 + 1.10426 +#ifndef cimg_use_visualcpp6 1.10427 + CImg<T>& assign(const T *const data_buffer, const unsigned int dx, const unsigned int dy=1, 1.10428 + const unsigned int dz=1, const unsigned int dv=1) 1.10429 +#else 1.10430 + CImg<T>& assign(const T *const data_buffer, const unsigned int dx, const unsigned int dy, 1.10431 + const unsigned int dz, const unsigned int dv) 1.10432 +#endif 1.10433 + { 1.10434 + const unsigned long siz = dx*dy*dz*dv; 1.10435 + if (!data_buffer || !siz) return assign(); 1.10436 + const unsigned long curr_siz = size(); 1.10437 + if (data_buffer==data && siz==curr_siz) return assign(dx,dy,dz,dv); 1.10438 + if (is_shared || data_buffer+siz<data || data_buffer>=data+size()) { 1.10439 + assign(dx,dy,dz,dv); 1.10440 + if (is_shared) cimg_std::memmove(data,data_buffer,siz*sizeof(T)); 1.10441 + else cimg_std::memcpy(data,data_buffer,siz*sizeof(T)); 1.10442 + } else { 1.10443 + T *new_data = new T[siz]; 1.10444 + cimg_std::memcpy(new_data,data_buffer,siz*sizeof(T)); 1.10445 + delete[] data; data = new_data; width = dx; height = dy; depth = dz; dim = dv; 1.10446 + } 1.10447 + return *this; 1.10448 + } 1.10449 + 1.10450 + //! In-place version of the previous constructor, allowing to force the shared state of the instance image. 1.10451 + template<typename t> 1.10452 + CImg<T>& assign(const t *const data_buffer, const unsigned int dx, const unsigned int dy, 1.10453 + const unsigned int dz, const unsigned int dv, const bool shared) { 1.10454 + if (shared) 1.10455 + throw CImgArgumentException("CImg<%s>::assign() : Cannot assign buffer (%s*) to shared instance image (%u,%u,%u,%u,%p)" 1.10456 + "(different pixel types).", 1.10457 + pixel_type(),CImg<t>::pixel_type(),width,height,depth,dim,data); 1.10458 + return assign(data_buffer,dx,dy,dz,dv); 1.10459 + } 1.10460 + 1.10461 + CImg<T>& assign(const T *const data_buffer, const unsigned int dx, const unsigned int dy, 1.10462 + const unsigned int dz, const unsigned int dv, const bool shared) { 1.10463 + const unsigned long siz = dx*dy*dz*dv; 1.10464 + if (!data_buffer || !siz) return assign(); 1.10465 + if (!shared) { if (is_shared) assign(); assign(data_buffer,dx,dy,dz,dv); } 1.10466 + else { 1.10467 + if (!is_shared) { 1.10468 + if (data_buffer+siz<data || data_buffer>=data+size()) assign(); 1.10469 + else cimg::warn("CImg<%s>::assign() : Shared instance image has overlapping memory !", 1.10470 + pixel_type()); 1.10471 + } 1.10472 + width = dx; height = dy; depth = dz; dim = dv; is_shared = true; 1.10473 + data = const_cast<T*>(data_buffer); 1.10474 + } 1.10475 + return *this; 1.10476 + } 1.10477 + 1.10478 + //! In-place version of the default copy constructor. 1.10479 + /** 1.10480 + This function assigns a copy of the input image \p img to the current instance image. 1.10481 + \param img The input image to copy. 1.10482 + \remark 1.10483 + - If the instance image is not shared, the content of the input image \p img is copied into a new buffer 1.10484 + becoming the new pixel buffer of the instance image, while the old pixel buffer is freed if necessary. 1.10485 + - If the instance image is shared, the content of the input image \p img is copied into the current (shared) pixel buffer 1.10486 + of the instance image, modifying then the image referenced by the shared instance image. The instance image still remains shared. 1.10487 + **/ 1.10488 + template<typename t> 1.10489 + CImg<T>& assign(const CImg<t>& img) { 1.10490 + return assign(img.data,img.width,img.height,img.depth,img.dim); 1.10491 + } 1.10492 + 1.10493 + //! In-place version of the advanced constructor. 1.10494 + /** 1.10495 + This function - as the simpler function assign(const CImg< t >&) - assigns a copy of the input image \p img to the 1.10496 + current instance image. But it also decides if the copy is shared (if the input parameter \p shared is set to \c true) 1.10497 + or non-shared (if the input parameter \p shared is set to \c false). 1.10498 + \param img The input image to copy. 1.10499 + \param shared Boolean flag that decides if the copy is shared or non-shared. 1.10500 + \remark 1.10501 + - It is not possible to assign a shared copy if the input image \p img is empty or has a different pixel type \p t != \p T. 1.10502 + - If a non-shared copy of the input image \p img is assigned, a new memory buffer is allocated for pixel data. 1.10503 + - If a shared copy of the input image \p img is assigned, no extra memory is allocated and the pixel buffer of the instance 1.10504 + image is the same as the one used by the input image \p img. 1.10505 + **/ 1.10506 + template<typename t> 1.10507 + CImg<T>& assign(const CImg<t>& img, const bool shared) { 1.10508 + return assign(img.data,img.width,img.height,img.depth,img.dim,shared); 1.10509 + } 1.10510 + 1.10511 + //! In-place version of the previous constructor. 1.10512 + template<typename t> 1.10513 + CImg<T>& assign(const CImg<t>& img, const char *const dimensions) { 1.10514 + if (dimensions) { 1.10515 + unsigned int siz[4] = { 0,1,1,1 }; 1.10516 + const char *s = dimensions; 1.10517 + char tmp[256] = { 0 }, c = 0; 1.10518 + int val = 0; 1.10519 + for (unsigned int k=0; k<4; ++k) { 1.10520 + const int err = cimg_std::sscanf(s,"%[-0-9]%c",tmp,&c); 1.10521 + if (err>=1) { 1.10522 + const int err = cimg_std::sscanf(s,"%d",&val); 1.10523 + if (err==1) { 1.10524 + int val2 = val<0?-val:(c=='%'?val:-1); 1.10525 + if (val2>=0) { 1.10526 + val = (int)((k==0?img.width:(k==1?img.height:(k==2?img.depth:img.dim)))*val2/100); 1.10527 + if (c!='%' && !val) val = 1; 1.10528 + } 1.10529 + siz[k] = val; 1.10530 + } 1.10531 + s+=cimg::strlen(tmp); 1.10532 + if (c=='%') ++s; 1.10533 + } 1.10534 + if (!err) { 1.10535 + if (!cimg::strncasecmp(s,"x",1)) { ++s; siz[k] = img.width; } 1.10536 + else if (!cimg::strncasecmp(s,"y",1)) { ++s; siz[k] = img.height; } 1.10537 + else if (!cimg::strncasecmp(s,"z",1)) { ++s; siz[k] = img.depth; } 1.10538 + else if (!cimg::strncasecmp(s,"v",1)) { ++s; siz[k] = img.dim; } 1.10539 + else if (!cimg::strncasecmp(s,"dx",2)) { s+=2; siz[k] = img.width; } 1.10540 + else if (!cimg::strncasecmp(s,"dy",2)) { s+=2; siz[k] = img.height; } 1.10541 + else if (!cimg::strncasecmp(s,"dz",2)) { s+=2; siz[k] = img.depth; } 1.10542 + else if (!cimg::strncasecmp(s,"dv",2)) { s+=2; siz[k] = img.dim; } 1.10543 + else if (!cimg::strncasecmp(s,"dimx",4)) { s+=4; siz[k] = img.width; } 1.10544 + else if (!cimg::strncasecmp(s,"dimy",4)) { s+=4; siz[k] = img.height; } 1.10545 + else if (!cimg::strncasecmp(s,"dimz",4)) { s+=4; siz[k] = img.depth; } 1.10546 + else if (!cimg::strncasecmp(s,"dimv",4)) { s+=4; siz[k] = img.dim; } 1.10547 + else if (!cimg::strncasecmp(s,"width",5)) { s+=5; siz[k] = img.width; } 1.10548 + else if (!cimg::strncasecmp(s,"height",6)) { s+=6; siz[k] = img.height; } 1.10549 + else if (!cimg::strncasecmp(s,"depth",5)) { s+=5; siz[k] = img.depth; } 1.10550 + else if (!cimg::strncasecmp(s,"dim",3)) { s+=3; siz[k] = img.dim; } 1.10551 + else { ++s; --k; } 1.10552 + } 1.10553 + } 1.10554 + return assign(siz[0],siz[1],siz[2],siz[3]); 1.10555 + } 1.10556 + return assign(); 1.10557 + } 1.10558 + 1.10559 + //! In-place version of the previous constructor. 1.10560 + template<typename t> 1.10561 + CImg<T>& assign(const CImg<t>& img, const char *const dimensions, const T val) { 1.10562 + return assign(img,dimensions).fill(val); 1.10563 + } 1.10564 + 1.10565 + //! In-place version of the previous constructor. 1.10566 + /** 1.10567 + This function replaces the instance image by the one that have been read from the given file. 1.10568 + \param filename Filename of the image file. 1.10569 + - The image format is deduced from the filename only by looking for the filename extension i.e. without 1.10570 + analyzing the file itself. 1.10571 + - Recognized image formats depend on the tools installed on your system or the external libraries you use to link your code with. 1.10572 + More informations on this topic can be found in cimg_files_io. 1.10573 + - If the filename is not found, a CImgIOException is thrown by this constructor. 1.10574 + **/ 1.10575 + CImg<T>& assign(const char *const filename) { 1.10576 + return load(filename); 1.10577 + } 1.10578 + 1.10579 + //! In-place version of the previous constructor. 1.10580 + CImg<T>& assign(const CImgDisplay &disp) { 1.10581 + disp.snapshot(*this); 1.10582 + return *this; 1.10583 + } 1.10584 + 1.10585 + //! Transfer the content of the instance image into another one in a way that memory copies are avoided if possible. 1.10586 + /** 1.10587 + The instance image is always empty after a call to this function. 1.10588 + **/ 1.10589 + template<typename t> 1.10590 + CImg<t>& transfer_to(CImg<t>& img) { 1.10591 + img.assign(*this); 1.10592 + assign(); 1.10593 + return img; 1.10594 + } 1.10595 + 1.10596 + CImg<T>& transfer_to(CImg<T>& img) { 1.10597 + if (is_shared || img.is_shared) { img.assign(*this); assign(); } else { img.assign(); swap(img); } 1.10598 + return img; 1.10599 + } 1.10600 + 1.10601 + //! Swap all fields of two images. Use with care ! 1.10602 + CImg<T>& swap(CImg<T>& img) { 1.10603 + cimg::swap(width,img.width); 1.10604 + cimg::swap(height,img.height); 1.10605 + cimg::swap(depth,img.depth); 1.10606 + cimg::swap(dim,img.dim); 1.10607 + cimg::swap(data,img.data); 1.10608 + cimg::swap(is_shared,img.is_shared); 1.10609 + return img; 1.10610 + } 1.10611 + 1.10612 + //@} 1.10613 + //------------------------------------- 1.10614 + // 1.10615 + //! \name Image Informations 1.10616 + //@{ 1.10617 + //------------------------------------- 1.10618 + 1.10619 + //! Return the type of the pixel values. 1.10620 + /** 1.10621 + \return a string describing the type of the image pixels (template parameter \p T). 1.10622 + - The string returned may contains spaces (<tt>"unsigned char"</tt>). 1.10623 + - If the template parameter T does not correspond to a registered type, the string <tt>"unknown"</tt> is returned. 1.10624 + **/ 1.10625 + static const char* pixel_type() { 1.10626 + return cimg::type<T>::string(); 1.10627 + } 1.10628 + 1.10629 + //! Return the total number of pixel values in an image. 1.10630 + /** 1.10631 + - Equivalent to : dimx() * dimy() * dimz() * dimv(). 1.10632 + 1.10633 + \par example: 1.10634 + \code 1.10635 + CImg<> img(100,100,1,3); 1.10636 + if (img.size()==100*100*3) std::fprintf(stderr,"This statement is true"); 1.10637 + \endcode 1.10638 + **/ 1.10639 + unsigned long size() const { 1.10640 + return width*height*depth*dim; 1.10641 + } 1.10642 + 1.10643 + //! Return the number of columns of the instance image (size along the X-axis, i.e image width). 1.10644 + int dimx() const { 1.10645 + return (int)width; 1.10646 + } 1.10647 + 1.10648 + //! Return the number of rows of the instance image (size along the Y-axis, i.e image height). 1.10649 + int dimy() const { 1.10650 + return (int)height; 1.10651 + } 1.10652 + 1.10653 + //! Return the number of slices of the instance image (size along the Z-axis). 1.10654 + int dimz() const { 1.10655 + return (int)depth; 1.10656 + } 1.10657 + 1.10658 + //! Return the number of vector channels of the instance image (size along the V-axis). 1.10659 + int dimv() const { 1.10660 + return (int)dim; 1.10661 + } 1.10662 + 1.10663 + //! Return \c true if image (*this) has the specified width. 1.10664 + bool is_sameX(const unsigned int dx) const { 1.10665 + return (width==dx); 1.10666 + } 1.10667 + 1.10668 + //! Return \c true if images \c (*this) and \c img have same width. 1.10669 + template<typename t> 1.10670 + bool is_sameX(const CImg<t>& img) const { 1.10671 + return is_sameX(img.width); 1.10672 + } 1.10673 + 1.10674 + //! Return \c true if images \c (*this) and the display \c disp have same width. 1.10675 + bool is_sameX(const CImgDisplay& disp) const { 1.10676 + return is_sameX(disp.width); 1.10677 + } 1.10678 + 1.10679 + //! Return \c true if image (*this) has the specified height. 1.10680 + bool is_sameY(const unsigned int dy) const { 1.10681 + return (height==dy); 1.10682 + } 1.10683 + 1.10684 + //! Return \c true if images \c (*this) and \c img have same height. 1.10685 + template<typename t> 1.10686 + bool is_sameY(const CImg<t>& img) const { 1.10687 + return is_sameY(img.height); 1.10688 + } 1.10689 + 1.10690 + //! Return \c true if images \c (*this) and the display \c disp have same height. 1.10691 + bool is_sameY(const CImgDisplay& disp) const { 1.10692 + return is_sameY(disp.height); 1.10693 + } 1.10694 + 1.10695 + //! Return \c true if image (*this) has the specified depth. 1.10696 + bool is_sameZ(const unsigned int dz) const { 1.10697 + return (depth==dz); 1.10698 + } 1.10699 + 1.10700 + //! Return \c true if images \c (*this) and \c img have same depth. 1.10701 + template<typename t> 1.10702 + bool is_sameZ(const CImg<t>& img) const { 1.10703 + return is_sameZ(img.depth); 1.10704 + } 1.10705 + 1.10706 + //! Return \c true if image (*this) has the specified number of channels. 1.10707 + bool is_sameV(const unsigned int dv) const { 1.10708 + return (dim==dv); 1.10709 + } 1.10710 + 1.10711 + //! Return \c true if images \c (*this) and \c img have same dim. 1.10712 + template<typename t> 1.10713 + bool is_sameV(const CImg<t>& img) const { 1.10714 + return is_sameV(img.dim); 1.10715 + } 1.10716 + 1.10717 + //! Return \c true if image (*this) has the specified width and height. 1.10718 + bool is_sameXY(const unsigned int dx, const unsigned int dy) const { 1.10719 + return (is_sameX(dx) && is_sameY(dy)); 1.10720 + } 1.10721 + 1.10722 + //! Return \c true if images have same width and same height. 1.10723 + template<typename t> 1.10724 + bool is_sameXY(const CImg<t>& img) const { 1.10725 + return (is_sameX(img) && is_sameY(img)); 1.10726 + } 1.10727 + 1.10728 + //! Return \c true if image \c (*this) and the display \c disp have same width and same height. 1.10729 + bool is_sameXY(const CImgDisplay& disp) const { 1.10730 + return (is_sameX(disp) && is_sameY(disp)); 1.10731 + } 1.10732 + 1.10733 + //! Return \c true if image (*this) has the specified width and depth. 1.10734 + bool is_sameXZ(const unsigned int dx, const unsigned int dz) const { 1.10735 + return (is_sameX(dx) && is_sameZ(dz)); 1.10736 + } 1.10737 + 1.10738 + //! Return \c true if images have same width and same depth. 1.10739 + template<typename t> 1.10740 + bool is_sameXZ(const CImg<t>& img) const { 1.10741 + return (is_sameX(img) && is_sameZ(img)); 1.10742 + } 1.10743 + 1.10744 + //! Return \c true if image (*this) has the specified width and number of channels. 1.10745 + bool is_sameXV(const unsigned int dx, const unsigned int dv) const { 1.10746 + return (is_sameX(dx) && is_sameV(dv)); 1.10747 + } 1.10748 + 1.10749 + //! Return \c true if images have same width and same number of channels. 1.10750 + template<typename t> 1.10751 + bool is_sameXV(const CImg<t>& img) const { 1.10752 + return (is_sameX(img) && is_sameV(img)); 1.10753 + } 1.10754 + 1.10755 + //! Return \c true if image (*this) has the specified height and depth. 1.10756 + bool is_sameYZ(const unsigned int dy, const unsigned int dz) const { 1.10757 + return (is_sameY(dy) && is_sameZ(dz)); 1.10758 + } 1.10759 + 1.10760 + //! Return \c true if images have same height and same depth. 1.10761 + template<typename t> 1.10762 + bool is_sameYZ(const CImg<t>& img) const { 1.10763 + return (is_sameY(img) && is_sameZ(img)); 1.10764 + } 1.10765 + 1.10766 + //! Return \c true if image (*this) has the specified height and number of channels. 1.10767 + bool is_sameYV(const unsigned int dy, const unsigned int dv) const { 1.10768 + return (is_sameY(dy) && is_sameV(dv)); 1.10769 + } 1.10770 + 1.10771 + //! Return \c true if images have same height and same number of channels. 1.10772 + template<typename t> 1.10773 + bool is_sameYV(const CImg<t>& img) const { 1.10774 + return (is_sameY(img) && is_sameV(img)); 1.10775 + } 1.10776 + 1.10777 + //! Return \c true if image (*this) has the specified depth and number of channels. 1.10778 + bool is_sameZV(const unsigned int dz, const unsigned int dv) const { 1.10779 + return (is_sameZ(dz) && is_sameV(dv)); 1.10780 + } 1.10781 + 1.10782 + //! Return \c true if images have same depth and same number of channels. 1.10783 + template<typename t> 1.10784 + bool is_sameZV(const CImg<t>& img) const { 1.10785 + return (is_sameZ(img) && is_sameV(img)); 1.10786 + } 1.10787 + 1.10788 + //! Return \c true if image (*this) has the specified width, height and depth. 1.10789 + bool is_sameXYZ(const unsigned int dx, const unsigned int dy, const unsigned int dz) const { 1.10790 + return (is_sameXY(dx,dy) && is_sameZ(dz)); 1.10791 + } 1.10792 + 1.10793 + //! Return \c true if images have same width, same height and same depth. 1.10794 + template<typename t> 1.10795 + bool is_sameXYZ(const CImg<t>& img) const { 1.10796 + return (is_sameXY(img) && is_sameZ(img)); 1.10797 + } 1.10798 + 1.10799 + //! Return \c true if image (*this) has the specified width, height and depth. 1.10800 + bool is_sameXYV(const unsigned int dx, const unsigned int dy, const unsigned int dv) const { 1.10801 + return (is_sameXY(dx,dy) && is_sameV(dv)); 1.10802 + } 1.10803 + 1.10804 + //! Return \c true if images have same width, same height and same number of channels. 1.10805 + template<typename t> 1.10806 + bool is_sameXYV(const CImg<t>& img) const { 1.10807 + return (is_sameXY(img) && is_sameV(img)); 1.10808 + } 1.10809 + 1.10810 + //! Return \c true if image (*this) has the specified width, height and number of channels. 1.10811 + bool is_sameXZV(const unsigned int dx, const unsigned int dz, const unsigned int dv) const { 1.10812 + return (is_sameXZ(dx,dz) && is_sameV(dv)); 1.10813 + } 1.10814 + 1.10815 + //! Return \c true if images have same width, same depth and same number of channels. 1.10816 + template<typename t> 1.10817 + bool is_sameXZV(const CImg<t>& img) const { 1.10818 + return (is_sameXZ(img) && is_sameV(img)); 1.10819 + } 1.10820 + 1.10821 + //! Return \c true if image (*this) has the specified height, depth and number of channels. 1.10822 + bool is_sameYZV(const unsigned int dy, const unsigned int dz, const unsigned int dv) const { 1.10823 + return (is_sameYZ(dy,dz) && is_sameV(dv)); 1.10824 + } 1.10825 + 1.10826 + //! Return \c true if images have same heigth, same depth and same number of channels. 1.10827 + template<typename t> 1.10828 + bool is_sameYZV(const CImg<t>& img) const { 1.10829 + return (is_sameYZ(img) && is_sameV(img)); 1.10830 + } 1.10831 + 1.10832 + //! Return \c true if image (*this) has the specified width, height, depth and number of channels. 1.10833 + bool is_sameXYZV(const unsigned int dx, const unsigned int dy, const unsigned int dz, const unsigned int dv) const { 1.10834 + return (is_sameXYZ(dx,dy,dz) && is_sameV(dv)); 1.10835 + } 1.10836 + 1.10837 + //! Return \c true if images \c (*this) and \c img have same width, same height, same depth and same number of channels. 1.10838 + template<typename t> 1.10839 + bool is_sameXYZV(const CImg<t>& img) const { 1.10840 + return (is_sameXYZ(img) && is_sameV(img)); 1.10841 + } 1.10842 + 1.10843 + //! Return \c true if current image is empty. 1.10844 + bool is_empty() const { 1.10845 + return !(data && width && height && depth && dim); 1.10846 + } 1.10847 + 1.10848 + //! Return \p true if image is not empty. 1.10849 + operator bool() const { 1.10850 + return !is_empty(); 1.10851 + } 1.10852 + 1.10853 + //! Return an iterator to the first image pixel 1.10854 + iterator begin() { 1.10855 + return data; 1.10856 + } 1.10857 + 1.10858 + const_iterator begin() const { 1.10859 + return data; 1.10860 + } 1.10861 + 1.10862 + //! Return reference to the first image pixel 1.10863 + const T& first() const { 1.10864 + return *data; 1.10865 + } 1.10866 + 1.10867 + T& first() { 1.10868 + return *data; 1.10869 + } 1.10870 + 1.10871 + //! Return an iterator pointing after the last image pixel 1.10872 + iterator end() { 1.10873 + return data + size(); 1.10874 + } 1.10875 + 1.10876 + const_iterator end() const { 1.10877 + return data + size(); 1.10878 + } 1.10879 + 1.10880 + //! Return a reference to the last image pixel 1.10881 + const T& last() const { 1.10882 + return data[size() - 1]; 1.10883 + } 1.10884 + 1.10885 + T& last() { 1.10886 + return data[size() - 1]; 1.10887 + } 1.10888 + 1.10889 + //! Return a pointer to the pixel buffer. 1.10890 + T* ptr() { 1.10891 + return data; 1.10892 + } 1.10893 + 1.10894 + const T* ptr() const { 1.10895 + return data; 1.10896 + } 1.10897 + 1.10898 + //! Return a pointer to the pixel value located at (\p x,\p y,\p z,\p v). 1.10899 + /** 1.10900 + \param x X-coordinate of the pixel. 1.10901 + \param y Y-coordinate of the pixel. 1.10902 + \param z Z-coordinate of the pixel. 1.10903 + \param v V-coordinate of the pixel. 1.10904 + 1.10905 + - When called without parameters, ptr() returns a pointer to the begining of the pixel buffer. 1.10906 + - If the macro \c 'cimg_debug'>=3, boundary checking is performed and warning messages may appear if 1.10907 + given coordinates are outside the image range (but function performances decrease). 1.10908 + 1.10909 + \par example: 1.10910 + \code 1.10911 + CImg<float> img(100,100,1,1,0); // Define a 100x100 greyscale image with float-valued pixels. 1.10912 + float *ptr = ptr(10,10); // Get a pointer to the pixel located at (10,10). 1.10913 + float val = *ptr; // Get the pixel value. 1.10914 + \endcode 1.10915 + **/ 1.10916 +#if cimg_debug>=3 1.10917 + T* ptr(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int v=0) { 1.10918 + const long off = offset(x,y,z,v); 1.10919 + if (off<0 || off>=(long)size()) { 1.10920 + cimg::warn("CImg<%s>::ptr() : Asked for a pointer at coordinates (%u,%u,%u,%u) (offset=%ld), " 1.10921 + "outside image range (%u,%u,%u,%u) (size=%lu)", 1.10922 + pixel_type(),x,y,z,v,off,width,height,depth,dim,size()); 1.10923 + return data; 1.10924 + } 1.10925 + return data + off; 1.10926 + } 1.10927 + 1.10928 + const T* ptr(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int v=0) const { 1.10929 + return const_cast<CImg<T>*>(this)->ptr(x,y,z,v); 1.10930 + } 1.10931 +#else 1.10932 + T* ptr(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int v=0) { 1.10933 + return data + (long)x + (long)y*width + (long)z*width*height + (long)v*width*height*depth; 1.10934 + } 1.10935 + 1.10936 + const T* ptr(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int v=0) const { 1.10937 + return data + (long)x + (long)y*width + (long)z*width*height + (long)v*width*height*depth; 1.10938 + } 1.10939 +#endif 1.10940 + 1.10941 + //! Return \c true if the memory buffers of the two images overlaps. 1.10942 + /** 1.10943 + May happen when using shared images. 1.10944 + **/ 1.10945 + template<typename t> 1.10946 + bool is_overlapped(const CImg<t>& img) const { 1.10947 + const unsigned long csiz = size(), isiz = img.size(); 1.10948 + return !((void*)(data+csiz)<=(void*)img.data || (void*)data>=(void*)(img.data+isiz)); 1.10949 + } 1.10950 + 1.10951 + //! Return the offset of the pixel coordinates (\p x,\p y,\p z,\p v) with respect to the data pointer \c data. 1.10952 + /** 1.10953 + \param x X-coordinate of the pixel. 1.10954 + \param y Y-coordinate of the pixel. 1.10955 + \param z Z-coordinate of the pixel. 1.10956 + \param v V-coordinate of the pixel. 1.10957 + 1.10958 + - No checking is done on the validity of the given coordinates. 1.10959 + 1.10960 + \par Example: 1.10961 + \code 1.10962 + CImg<float> img(100,100,1,3,0); // Define a 100x100 color image with float-valued black pixels. 1.10963 + long off = img.offset(10,10,0,2); // Get the offset of the blue value of the pixel located at (10,10). 1.10964 + float val = img[off]; // Get the blue value of the pixel. 1.10965 + \endcode 1.10966 + **/ 1.10967 + long offset(const int x, const int y=0, const int z=0, const int v=0) const { 1.10968 + return (long)x + (long)y*width + (long)z*width*height + (long)v*width*height*depth; 1.10969 + } 1.10970 + 1.10971 + //! Fast access to pixel value for reading or writing. 1.10972 + /** 1.10973 + \param x X-coordinate of the pixel. 1.10974 + \param y Y-coordinate of the pixel. 1.10975 + \param z Z-coordinate of the pixel. 1.10976 + \param v V-coordinate of the pixel. 1.10977 + 1.10978 + - If one image dimension is equal to 1, it can be omitted in the coordinate list (see example below). 1.10979 + - If the macro \c 'cimg_debug'>=3, boundary checking is performed and warning messages may appear 1.10980 + (but function performances decrease). 1.10981 + 1.10982 + \par example: 1.10983 + \code 1.10984 + CImg<float> img(100,100,1,3,0); // Define a 100x100 color image with float-valued black pixels. 1.10985 + const float valR = img(10,10,0,0); // Read the red component at coordinates (10,10). 1.10986 + const float valG = img(10,10,0,1); // Read the green component at coordinates (10,10) 1.10987 + const float valB = img(10,10,2); // Read the blue component at coordinates (10,10) (Z-coordinate omitted here). 1.10988 + const float avg = (valR + valG + valB)/3; // Compute average pixel value. 1.10989 + img(10,10,0) = img(10,10,1) = img(10,10,2) = avg; // Replace the pixel (10,10) by the average grey value. 1.10990 + \endcode 1.10991 + **/ 1.10992 +#if cimg_debug>=3 1.10993 + T& operator()(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int v=0) { 1.10994 + const long off = offset(x,y,z,v); 1.10995 + if (!data || off>=(long)size()) { 1.10996 + cimg::warn("CImg<%s>::operator() : Pixel access requested at (%u,%u,%u,%u) (offset=%ld) " 1.10997 + "outside the image range (%u,%u,%u,%u) (size=%lu)", 1.10998 + pixel_type(),x,y,z,v,off,width,height,depth,dim,size()); 1.10999 + return *data; 1.11000 + } 1.11001 + else return data[off]; 1.11002 + } 1.11003 + 1.11004 + const T& operator()(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int v=0) const { 1.11005 + return const_cast<CImg<T>*>(this)->operator()(x,y,z,v); 1.11006 + } 1.11007 +#else 1.11008 + T& operator()(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int v=0) { 1.11009 + return data[(long)x + (long)y*width + (long)z*width*height + (long)v*width*height*depth]; 1.11010 + } 1.11011 + 1.11012 + const T& operator()(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int v=0) const { 1.11013 + return data[(long)x + (long)y*width + (long)z*width*height + (long)v*width*height*depth]; 1.11014 + } 1.11015 +#endif 1.11016 + 1.11017 + //! Fast access to pixel value for reading or writing, using an offset to the image pixel. 1.11018 + /** 1.11019 + \param off Offset of the pixel according to the begining of the pixel buffer, given by ptr(). 1.11020 + 1.11021 + - If the macro \c 'cimg_debug'>=3, boundary checking is performed and warning messages may appear 1.11022 + (but function performances decrease). 1.11023 + - As pixel values are aligned in memory, this operator can sometime useful to access values easier than 1.11024 + with operator()() (see example below). 1.11025 + 1.11026 + \par example: 1.11027 + \code 1.11028 + CImg<float> vec(1,10); // Define a vector of float values (10 lines, 1 row). 1.11029 + const float val1 = vec(0,4); // Get the fifth element using operator()(). 1.11030 + const float val2 = vec[4]; // Get the fifth element using operator[]. Here, val2==val1. 1.11031 + \endcode 1.11032 + **/ 1.11033 +#if cimg_debug>=3 1.11034 + T& operator[](const unsigned long off) { 1.11035 + if (!data || off>=size()) { 1.11036 + cimg::warn("CImg<%s>::operator[] : Pixel access requested at offset=%lu " 1.11037 + "outside the image range (%u,%u,%u,%u) (size=%lu)", 1.11038 + pixel_type(),off,width,height,depth,dim,size()); 1.11039 + return *data; 1.11040 + } 1.11041 + else return data[off]; 1.11042 + } 1.11043 + 1.11044 + const T& operator[](const unsigned long off) const { 1.11045 + return const_cast<CImg<T>*>(this)->operator[](off); 1.11046 + } 1.11047 +#else 1.11048 + T& operator[](const unsigned long off) { 1.11049 + return data[off]; 1.11050 + } 1.11051 + 1.11052 + const T& operator[](const unsigned long off) const { 1.11053 + return data[off]; 1.11054 + } 1.11055 +#endif 1.11056 + 1.11057 + //! Return a reference to the last image value 1.11058 + T& back() { 1.11059 + return operator()(size()-1); 1.11060 + } 1.11061 + 1.11062 + const T& back() const { 1.11063 + return operator()(size()-1); 1.11064 + } 1.11065 + 1.11066 + //! Return a reference to the first image value 1.11067 + T& front() { 1.11068 + return *data; 1.11069 + } 1.11070 + 1.11071 + const T& front() const { 1.11072 + return *data; 1.11073 + } 1.11074 + 1.11075 + //! Return \c true if pixel (x,y,z,v) is inside image boundaries. 1.11076 + bool containsXYZV(const int x, const int y=0, const int z=0, const int v=0) const { 1.11077 + return !is_empty() && x>=0 && x<dimx() && y>=0 && y<dimy() && z>=0 && z<dimz() && v>=0 && v<dimv(); 1.11078 + } 1.11079 + 1.11080 + //! Return \c true if specified referenced value is inside image boundaries. If true, returns pixel coordinates in (x,y,z,v). 1.11081 + template<typename t> 1.11082 + bool contains(const T& pixel, t& x, t& y, t& z, t& v) const { 1.11083 + const unsigned long wh = width*height, whz = wh*depth, siz = whz*dim; 1.11084 + const T *const ppixel = &pixel; 1.11085 + if (is_empty() || ppixel<data || ppixel>=data+siz) return false; 1.11086 + unsigned long off = (unsigned long)(ppixel - data); 1.11087 + const unsigned long nv = off/whz; 1.11088 + off%=whz; 1.11089 + const unsigned long nz = off/wh; 1.11090 + off%=wh; 1.11091 + const unsigned long ny = off/width, nx = off%width; 1.11092 + x = (t)nx; y = (t)ny; z = (t)nz; v = (t)nv; 1.11093 + return true; 1.11094 + } 1.11095 + 1.11096 + //! Return \c true if specified referenced value is inside image boundaries. If true, returns pixel coordinates in (x,y,z). 1.11097 + template<typename t> 1.11098 + bool contains(const T& pixel, t& x, t& y, t& z) const { 1.11099 + const unsigned long wh = width*height, whz = wh*depth, siz = whz*dim; 1.11100 + const T *const ppixel = &pixel; 1.11101 + if (is_empty() || ppixel<data || ppixel>=data+siz) return false; 1.11102 + unsigned long off = ((unsigned long)(ppixel - data))%whz; 1.11103 + const unsigned long nz = off/wh; 1.11104 + off%=wh; 1.11105 + const unsigned long ny = off/width, nx = off%width; 1.11106 + x = (t)nx; y = (t)ny; z = (t)nz; 1.11107 + return true; 1.11108 + } 1.11109 + 1.11110 + //! Return \c true if specified referenced value is inside image boundaries. If true, returns pixel coordinates in (x,y). 1.11111 + template<typename t> 1.11112 + bool contains(const T& pixel, t& x, t& y) const { 1.11113 + const unsigned long wh = width*height, siz = wh*depth*dim; 1.11114 + const T *const ppixel = &pixel; 1.11115 + if (is_empty() || ppixel<data || ppixel>=data+siz) return false; 1.11116 + unsigned long off = ((unsigned long)(ppixel - data))%wh; 1.11117 + const unsigned long ny = off/width, nx = off%width; 1.11118 + x = (t)nx; y = (t)ny; 1.11119 + return true; 1.11120 + } 1.11121 + 1.11122 + //! Return \c true if specified referenced value is inside image boundaries. If true, returns pixel coordinates in (x). 1.11123 + template<typename t> 1.11124 + bool contains(const T& pixel, t& x) const { 1.11125 + const T *const ppixel = &pixel; 1.11126 + if (is_empty() || ppixel<data || ppixel>=data+size()) return false; 1.11127 + x = (t)(((unsigned long)(ppixel - data))%width); 1.11128 + return true; 1.11129 + } 1.11130 + 1.11131 + //! Return \c true if specified referenced value is inside the image boundaries. 1.11132 + bool contains(const T& pixel) const { 1.11133 + const T *const ppixel = &pixel; 1.11134 + return !is_empty() && ppixel>=data && ppixel<data+size(); 1.11135 + } 1.11136 + 1.11137 + //! Read a pixel value with Dirichlet boundary conditions. 1.11138 + T& at(const int off, const T out_val) { 1.11139 + return (off<0 || off>=(int)size())?(cimg::temporary(out_val)=out_val):(*this)[off]; 1.11140 + } 1.11141 + 1.11142 + T at(const int off, const T out_val) const { 1.11143 + return (off<0 || off>=(int)size())?out_val:(*this)[off]; 1.11144 + } 1.11145 + 1.11146 + //! Read a pixel value with Neumann boundary conditions. 1.11147 + T& at(const int off) { 1.11148 + if (!size()) 1.11149 + throw CImgInstanceException("CImg<%s>::at() : Instance image is empty.", 1.11150 + pixel_type()); 1.11151 + return _at(off); 1.11152 + } 1.11153 + 1.11154 + T at(const int off) const { 1.11155 + if (!size()) 1.11156 + throw CImgInstanceException("CImg<%s>::at() : Instance image is empty.", 1.11157 + pixel_type()); 1.11158 + return _at(off); 1.11159 + } 1.11160 + 1.11161 + T& _at(const int off) { 1.11162 + const unsigned int siz = (unsigned int)size(); 1.11163 + return (*this)[off<0?0:(unsigned int)off>=siz?siz-1:off]; 1.11164 + } 1.11165 + 1.11166 + T _at(const int off) const { 1.11167 + const unsigned int siz = (unsigned int)size(); 1.11168 + return (*this)[off<0?0:(unsigned int)off>=siz?siz-1:off]; 1.11169 + } 1.11170 + 1.11171 + //! Read a pixel value with Dirichlet boundary conditions. 1.11172 + T& atXYZV(const int x, const int y, const int z, const int v, const T out_val) { 1.11173 + return (x<0 || y<0 || z<0 || v<0 || x>=dimx() || y>=dimy() || z>=dimz() || v>=dimv())? 1.11174 + (cimg::temporary(out_val)=out_val):(*this)(x,y,z,v); 1.11175 + } 1.11176 + 1.11177 + T atXYZV(const int x, const int y, const int z, const int v, const T out_val) const { 1.11178 + return (x<0 || y<0 || z<0 || v<0 || x>=dimx() || y>=dimy() || z>=dimz() || v>=dimv())?out_val:(*this)(x,y,z,v); 1.11179 + } 1.11180 + 1.11181 + //! Read a pixel value with Neumann boundary conditions. 1.11182 + T& atXYZV(const int x, const int y, const int z, const int v) { 1.11183 + if (is_empty()) 1.11184 + throw CImgInstanceException("CImg<%s>::atXYZV() : Instance image is empty.", 1.11185 + pixel_type()); 1.11186 + return _atXYZV(x,y,z,v); 1.11187 + } 1.11188 + 1.11189 + T atXYZV(const int x, const int y, const int z, const int v) const { 1.11190 + if (is_empty()) 1.11191 + throw CImgInstanceException("CImg<%s>::atXYZV() : Instance image is empty.", 1.11192 + pixel_type()); 1.11193 + return _atXYZV(x,y,z,v); 1.11194 + } 1.11195 + 1.11196 + T& _atXYZV(const int x, const int y, const int z, const int v) { 1.11197 + return (*this)(x<0?0:(x>=dimx()?dimx()-1:x), y<0?0:(y>=dimy()?dimy()-1:y), 1.11198 + z<0?0:(z>=dimz()?dimz()-1:z), v<0?0:(v>=dimv()?dimv()-1:v)); 1.11199 + } 1.11200 + 1.11201 + T _atXYZV(const int x, const int y, const int z, const int v) const { 1.11202 + return (*this)(x<0?0:(x>=dimx()?dimx()-1:x), y<0?0:(y>=dimy()?dimy()-1:y), 1.11203 + z<0?0:(z>=dimz()?dimz()-1:z), v<0?0:(v>=dimv()?dimv()-1:v)); 1.11204 + } 1.11205 + 1.11206 + //! Read a pixel value with Dirichlet boundary conditions for the three first coordinates (\c x,\c y,\c z). 1.11207 + T& atXYZ(const int x, const int y, const int z, const int v, const T out_val) { 1.11208 + return (x<0 || y<0 || z<0 || x>=dimx() || y>=dimy() || z>=dimz())? 1.11209 + (cimg::temporary(out_val)=out_val):(*this)(x,y,z,v); 1.11210 + } 1.11211 + 1.11212 + T atXYZ(const int x, const int y, const int z, const int v, const T out_val) const { 1.11213 + return (x<0 || y<0 || z<0 || x>=dimx() || y>=dimy() || z>=dimz())?out_val:(*this)(x,y,z,v); 1.11214 + } 1.11215 + 1.11216 + //! Read a pixel value with Neumann boundary conditions for the three first coordinates (\c x,\c y,\c z). 1.11217 + T& atXYZ(const int x, const int y, const int z, const int v=0) { 1.11218 + if (is_empty()) 1.11219 + throw CImgInstanceException("CImg<%s>::atXYZ() : Instance image is empty.", 1.11220 + pixel_type()); 1.11221 + return _atXYZ(x,y,z,v); 1.11222 + } 1.11223 + 1.11224 + T atXYZ(const int x, const int y, const int z, const int v=0) const { 1.11225 + if (is_empty()) 1.11226 + throw CImgInstanceException("CImg<%s>::atXYZ() : Instance image is empty.", 1.11227 + pixel_type()); 1.11228 + return _atXYZ(x,y,z,v); 1.11229 + } 1.11230 + 1.11231 + T& _atXYZ(const int x, const int y, const int z, const int v=0) { 1.11232 + return (*this)(x<0?0:(x>=dimx()?dimx()-1:x),y<0?0:(y>=dimy()?dimy()-1:y), 1.11233 + z<0?0:(z>=dimz()?dimz()-1:z),v); 1.11234 + } 1.11235 + 1.11236 + T _atXYZ(const int x, const int y, const int z, const int v=0) const { 1.11237 + return (*this)(x<0?0:(x>=dimx()?dimx()-1:x),y<0?0:(y>=dimy()?dimy()-1:y), 1.11238 + z<0?0:(z>=dimz()?dimz()-1:z),v); 1.11239 + } 1.11240 + 1.11241 + //! Read a pixel value with Dirichlet boundary conditions for the two first coordinates (\c x,\c y). 1.11242 + T& atXY(const int x, const int y, const int z, const int v, const T out_val) { 1.11243 + return (x<0 || y<0 || x>=dimx() || y>=dimy())?(cimg::temporary(out_val)=out_val):(*this)(x,y,z,v); 1.11244 + } 1.11245 + 1.11246 + T atXY(const int x, const int y, const int z, const int v, const T out_val) const { 1.11247 + return (x<0 || y<0 || x>=dimx() || y>=dimy())?out_val:(*this)(x,y,z,v); 1.11248 + } 1.11249 + 1.11250 + //! Read a pixel value with Neumann boundary conditions for the two first coordinates (\c x,\c y). 1.11251 + T& atXY(const int x, const int y, const int z=0, const int v=0) { 1.11252 + if (is_empty()) 1.11253 + throw CImgInstanceException("CImg<%s>::atXY() : Instance image is empty.", 1.11254 + pixel_type()); 1.11255 + return _atXY(x,y,z,v); 1.11256 + } 1.11257 + 1.11258 + T atXY(const int x, const int y, const int z=0, const int v=0) const { 1.11259 + if (is_empty()) 1.11260 + throw CImgInstanceException("CImg<%s>::atXY() : Instance image is empty.", 1.11261 + pixel_type()); 1.11262 + return _atXY(x,y,z,v); 1.11263 + } 1.11264 + 1.11265 + T& _atXY(const int x, const int y, const int z=0, const int v=0) { 1.11266 + return (*this)(x<0?0:(x>=dimx()?dimx()-1:x), y<0?0:(y>=dimy()?dimy()-1:y),z,v); 1.11267 + } 1.11268 + 1.11269 + T _atXY(const int x, const int y, const int z=0, const int v=0) const { 1.11270 + return (*this)(x<0?0:(x>=dimx()?dimx()-1:x), y<0?0:(y>=dimy()?dimy()-1:y),z,v); 1.11271 + } 1.11272 + 1.11273 + //! Read a pixel value with Dirichlet boundary conditions for the first coordinates (\c x). 1.11274 + T& atX(const int x, const int y, const int z, const int v, const T out_val) { 1.11275 + return (x<0 || x>=dimx())?(cimg::temporary(out_val)=out_val):(*this)(x,y,z,v); 1.11276 + } 1.11277 + 1.11278 + T atX(const int x, const int y, const int z, const int v, const T out_val) const { 1.11279 + return (x<0 || x>=dimx())?out_val:(*this)(x,y,z,v); 1.11280 + } 1.11281 + 1.11282 + //! Read a pixel value with Neumann boundary conditions for the first coordinates (\c x). 1.11283 + T& atX(const int x, const int y=0, const int z=0, const int v=0) { 1.11284 + if (is_empty()) 1.11285 + throw CImgInstanceException("CImg<%s>::atX() : Instance image is empty.", 1.11286 + pixel_type()); 1.11287 + return _atX(x,y,z,v); 1.11288 + } 1.11289 + 1.11290 + T atX(const int x, const int y=0, const int z=0, const int v=0) const { 1.11291 + if (is_empty()) 1.11292 + throw CImgInstanceException("CImg<%s>::atX() : Instance image is empty.", 1.11293 + pixel_type()); 1.11294 + return _atX(x,y,z,v); 1.11295 + } 1.11296 + 1.11297 + T& _atX(const int x, const int y=0, const int z=0, const int v=0) { 1.11298 + return (*this)(x<0?0:(x>=dimx()?dimx()-1:x),y,z,v); 1.11299 + } 1.11300 + 1.11301 + T _atX(const int x, const int y=0, const int z=0, const int v=0) const { 1.11302 + return (*this)(x<0?0:(x>=dimx()?dimx()-1:x),y,z,v); 1.11303 + } 1.11304 + 1.11305 + //! Read a pixel value using linear interpolation and Dirichlet boundary conditions. 1.11306 + Tfloat linear_atXYZV(const float fx, const float fy, const float fz, const float fv, const T out_val) const { 1.11307 + const int 1.11308 + x = (int)fx-(fx>=0?0:1), nx = x+1, 1.11309 + y = (int)fy-(fy>=0?0:1), ny = y+1, 1.11310 + z = (int)fz-(fz>=0?0:1), nz = z+1, 1.11311 + v = (int)fv-(fv>=0?0:1), nv = v+1; 1.11312 + const float 1.11313 + dx = fx-x, 1.11314 + dy = fy-y, 1.11315 + dz = fz-z, 1.11316 + dv = fv-v; 1.11317 + const Tfloat 1.11318 + Icccc = (Tfloat)atXYZV(x,y,z,v,out_val), Inccc = (Tfloat)atXYZV(nx,y,z,v,out_val), 1.11319 + Icncc = (Tfloat)atXYZV(x,ny,z,v,out_val), Inncc = (Tfloat)atXYZV(nx,ny,z,v,out_val), 1.11320 + Iccnc = (Tfloat)atXYZV(x,y,nz,v,out_val), Incnc = (Tfloat)atXYZV(nx,y,nz,v,out_val), 1.11321 + Icnnc = (Tfloat)atXYZV(x,ny,nz,v,out_val), Innnc = (Tfloat)atXYZV(nx,ny,nz,v,out_val), 1.11322 + Icccn = (Tfloat)atXYZV(x,y,z,nv,out_val), Inccn = (Tfloat)atXYZV(nx,y,z,nv,out_val), 1.11323 + Icncn = (Tfloat)atXYZV(x,ny,z,nv,out_val), Inncn = (Tfloat)atXYZV(nx,ny,z,nv,out_val), 1.11324 + Iccnn = (Tfloat)atXYZV(x,y,nz,nv,out_val), Incnn = (Tfloat)atXYZV(nx,y,nz,nv,out_val), 1.11325 + Icnnn = (Tfloat)atXYZV(x,ny,nz,nv,out_val), Innnn = (Tfloat)atXYZV(nx,ny,nz,nv,out_val); 1.11326 + return Icccc + 1.11327 + dx*(Inccc-Icccc + 1.11328 + dy*(Icccc+Inncc-Icncc-Inccc + 1.11329 + dz*(Iccnc+Innnc+Icncc+Inccc-Icnnc-Incnc-Icccc-Inncc + 1.11330 + dv*(Iccnn+Innnn+Icncn+Inccn+Icnnc+Incnc+Icccc+Inncc-Icnnn-Incnn-Icccn-Inncn-Iccnc-Innnc-Icncc-Inccc)) + 1.11331 + dv*(Icccn+Inncn+Icncc+Inccc-Icncn-Inccn-Icccc-Inncc)) + 1.11332 + dz*(Icccc+Incnc-Iccnc-Inccc + 1.11333 + dv*(Icccn+Incnn+Iccnc+Inccc-Iccnn-Inccn-Icccc-Incnc)) + 1.11334 + dv*(Icccc+Inccn-Inccc-Icccn)) + 1.11335 + dy*(Icncc-Icccc + 1.11336 + dz*(Icccc+Icnnc-Iccnc-Icncc + 1.11337 + dv*(Icccn+Icnnn+Iccnc+Icncc-Iccnn-Icncn-Icccc-Icnnc)) + 1.11338 + dv*(Icccc+Icncn-Icncc-Icccn)) + 1.11339 + dz*(Iccnc-Icccc + 1.11340 + dv*(Icccc+Iccnn-Iccnc-Icccn)) + 1.11341 + dv*(Icccn-Icccc); 1.11342 + } 1.11343 + 1.11344 + //! Read a pixel value using linear interpolation and Neumann boundary conditions. 1.11345 + Tfloat linear_atXYZV(const float fx, const float fy=0, const float fz=0, const float fv=0) const { 1.11346 + if (is_empty()) 1.11347 + throw CImgInstanceException("CImg<%s>::linear_atXYZV() : Instance image is empty.", 1.11348 + pixel_type()); 1.11349 + return _linear_atXYZV(fx,fy,fz,fv); 1.11350 + } 1.11351 + 1.11352 + Tfloat _linear_atXYZV(const float fx, const float fy=0, const float fz=0, const float fv=0) const { 1.11353 + const float 1.11354 + nfx = fx<0?0:(fx>width-1?width-1:fx), 1.11355 + nfy = fy<0?0:(fy>height-1?height-1:fy), 1.11356 + nfz = fz<0?0:(fz>depth-1?depth-1:fz), 1.11357 + nfv = fv<0?0:(fv>dim-1?dim-1:fv); 1.11358 + const unsigned int 1.11359 + x = (unsigned int)nfx, 1.11360 + y = (unsigned int)nfy, 1.11361 + z = (unsigned int)nfz, 1.11362 + v = (unsigned int)nfv; 1.11363 + const float 1.11364 + dx = nfx-x, 1.11365 + dy = nfy-y, 1.11366 + dz = nfz-z, 1.11367 + dv = nfv-v; 1.11368 + const unsigned int 1.11369 + nx = dx>0?x+1:x, 1.11370 + ny = dy>0?y+1:y, 1.11371 + nz = dz>0?z+1:z, 1.11372 + nv = dv>0?v+1:v; 1.11373 + const Tfloat 1.11374 + Icccc = (Tfloat)(*this)(x,y,z,v), Inccc = (Tfloat)(*this)(nx,y,z,v), 1.11375 + Icncc = (Tfloat)(*this)(x,ny,z,v), Inncc = (Tfloat)(*this)(nx,ny,z,v), 1.11376 + Iccnc = (Tfloat)(*this)(x,y,nz,v), Incnc = (Tfloat)(*this)(nx,y,nz,v), 1.11377 + Icnnc = (Tfloat)(*this)(x,ny,nz,v), Innnc = (Tfloat)(*this)(nx,ny,nz,v), 1.11378 + Icccn = (Tfloat)(*this)(x,y,z,nv), Inccn = (Tfloat)(*this)(nx,y,z,nv), 1.11379 + Icncn = (Tfloat)(*this)(x,ny,z,nv), Inncn = (Tfloat)(*this)(nx,ny,z,nv), 1.11380 + Iccnn = (Tfloat)(*this)(x,y,nz,nv), Incnn = (Tfloat)(*this)(nx,y,nz,nv), 1.11381 + Icnnn = (Tfloat)(*this)(x,ny,nz,nv), Innnn = (Tfloat)(*this)(nx,ny,nz,nv); 1.11382 + return Icccc + 1.11383 + dx*(Inccc-Icccc + 1.11384 + dy*(Icccc+Inncc-Icncc-Inccc + 1.11385 + dz*(Iccnc+Innnc+Icncc+Inccc-Icnnc-Incnc-Icccc-Inncc + 1.11386 + dv*(Iccnn+Innnn+Icncn+Inccn+Icnnc+Incnc+Icccc+Inncc-Icnnn-Incnn-Icccn-Inncn-Iccnc-Innnc-Icncc-Inccc)) + 1.11387 + dv*(Icccn+Inncn+Icncc+Inccc-Icncn-Inccn-Icccc-Inncc)) + 1.11388 + dz*(Icccc+Incnc-Iccnc-Inccc + 1.11389 + dv*(Icccn+Incnn+Iccnc+Inccc-Iccnn-Inccn-Icccc-Incnc)) + 1.11390 + dv*(Icccc+Inccn-Inccc-Icccn)) + 1.11391 + dy*(Icncc-Icccc + 1.11392 + dz*(Icccc+Icnnc-Iccnc-Icncc + 1.11393 + dv*(Icccn+Icnnn+Iccnc+Icncc-Iccnn-Icncn-Icccc-Icnnc)) + 1.11394 + dv*(Icccc+Icncn-Icncc-Icccn)) + 1.11395 + dz*(Iccnc-Icccc + 1.11396 + dv*(Icccc+Iccnn-Iccnc-Icccn)) + 1.11397 + dv*(Icccn-Icccc); 1.11398 + } 1.11399 + 1.11400 + //! Read a pixel value using linear interpolation and Dirichlet boundary conditions (first three coordinates). 1.11401 + Tfloat linear_atXYZ(const float fx, const float fy, const float fz, const int v, const T out_val) const { 1.11402 + const int 1.11403 + x = (int)fx-(fx>=0?0:1), nx = x+1, 1.11404 + y = (int)fy-(fy>=0?0:1), ny = y+1, 1.11405 + z = (int)fz-(fz>=0?0:1), nz = z+1; 1.11406 + const float 1.11407 + dx = fx-x, 1.11408 + dy = fy-y, 1.11409 + dz = fz-z; 1.11410 + const Tfloat 1.11411 + Iccc = (Tfloat)atXYZ(x,y,z,v,out_val), Incc = (Tfloat)atXYZ(nx,y,z,v,out_val), 1.11412 + Icnc = (Tfloat)atXYZ(x,ny,z,v,out_val), Innc = (Tfloat)atXYZ(nx,ny,z,v,out_val), 1.11413 + Iccn = (Tfloat)atXYZ(x,y,nz,v,out_val), Incn = (Tfloat)atXYZ(nx,y,nz,v,out_val), 1.11414 + Icnn = (Tfloat)atXYZ(x,ny,nz,v,out_val), Innn = (Tfloat)atXYZ(nx,ny,nz,v,out_val); 1.11415 + return Iccc + 1.11416 + dx*(Incc-Iccc + 1.11417 + dy*(Iccc+Innc-Icnc-Incc + 1.11418 + dz*(Iccn+Innn+Icnc+Incc-Icnn-Incn-Iccc-Innc)) + 1.11419 + dz*(Iccc+Incn-Iccn-Incc)) + 1.11420 + dy*(Icnc-Iccc + 1.11421 + dz*(Iccc+Icnn-Iccn-Icnc)) + 1.11422 + dz*(Iccn-Iccc); 1.11423 + } 1.11424 + 1.11425 + //! Read a pixel value using linear interpolation and Neumann boundary conditions (first three coordinates). 1.11426 + Tfloat linear_atXYZ(const float fx, const float fy=0, const float fz=0, const int v=0) const { 1.11427 + if (is_empty()) 1.11428 + throw CImgInstanceException("CImg<%s>::linear_atXYZ() : Instance image is empty.", 1.11429 + pixel_type()); 1.11430 + return _linear_atXYZ(fx,fy,fz,v); 1.11431 + } 1.11432 + 1.11433 + Tfloat _linear_atXYZ(const float fx, const float fy=0, const float fz=0, const int v=0) const { 1.11434 + const float 1.11435 + nfx = fx<0?0:(fx>width-1?width-1:fx), 1.11436 + nfy = fy<0?0:(fy>height-1?height-1:fy), 1.11437 + nfz = fz<0?0:(fz>depth-1?depth-1:fz); 1.11438 + const unsigned int 1.11439 + x = (unsigned int)nfx, 1.11440 + y = (unsigned int)nfy, 1.11441 + z = (unsigned int)nfz; 1.11442 + const float 1.11443 + dx = nfx-x, 1.11444 + dy = nfy-y, 1.11445 + dz = nfz-z; 1.11446 + const unsigned int 1.11447 + nx = dx>0?x+1:x, 1.11448 + ny = dy>0?y+1:y, 1.11449 + nz = dz>0?z+1:z; 1.11450 + const Tfloat 1.11451 + Iccc = (Tfloat)(*this)(x,y,z,v), Incc = (Tfloat)(*this)(nx,y,z,v), 1.11452 + Icnc = (Tfloat)(*this)(x,ny,z,v), Innc = (Tfloat)(*this)(nx,ny,z,v), 1.11453 + Iccn = (Tfloat)(*this)(x,y,nz,v), Incn = (Tfloat)(*this)(nx,y,nz,v), 1.11454 + Icnn = (Tfloat)(*this)(x,ny,nz,v), Innn = (Tfloat)(*this)(nx,ny,nz,v); 1.11455 + return Iccc + 1.11456 + dx*(Incc-Iccc + 1.11457 + dy*(Iccc+Innc-Icnc-Incc + 1.11458 + dz*(Iccn+Innn+Icnc+Incc-Icnn-Incn-Iccc-Innc)) + 1.11459 + dz*(Iccc+Incn-Iccn-Incc)) + 1.11460 + dy*(Icnc-Iccc + 1.11461 + dz*(Iccc+Icnn-Iccn-Icnc)) + 1.11462 + dz*(Iccn-Iccc); 1.11463 + } 1.11464 + 1.11465 + //! Read a pixel value using linear interpolation and Dirichlet boundary conditions (first two coordinates). 1.11466 + Tfloat linear_atXY(const float fx, const float fy, const int z, const int v, const T out_val) const { 1.11467 + const int 1.11468 + x = (int)fx-(fx>=0?0:1), nx = x+1, 1.11469 + y = (int)fy-(fy>=0?0:1), ny = y+1; 1.11470 + const float 1.11471 + dx = fx-x, 1.11472 + dy = fy-y; 1.11473 + const Tfloat 1.11474 + Icc = (Tfloat)atXY(x,y,z,v,out_val), Inc = (Tfloat)atXY(nx,y,z,v,out_val), 1.11475 + Icn = (Tfloat)atXY(x,ny,z,v,out_val), Inn = (Tfloat)atXY(nx,ny,z,v,out_val); 1.11476 + return Icc + dx*(Inc-Icc + dy*(Icc+Inn-Icn-Inc)) + dy*(Icn-Icc); 1.11477 + } 1.11478 + 1.11479 + //! Read a pixel value using linear interpolation and Neumann boundary conditions (first two coordinates). 1.11480 + Tfloat linear_atXY(const float fx, const float fy, const int z=0, const int v=0) const { 1.11481 + if (is_empty()) 1.11482 + throw CImgInstanceException("CImg<%s>::linear_atXY() : Instance image is empty.", 1.11483 + pixel_type()); 1.11484 + return _linear_atXY(fx,fy,z,v); 1.11485 + } 1.11486 + 1.11487 + Tfloat _linear_atXY(const float fx, const float fy, const int z=0, const int v=0) const { 1.11488 + const float 1.11489 + nfx = fx<0?0:(fx>width-1?width-1:fx), 1.11490 + nfy = fy<0?0:(fy>height-1?height-1:fy); 1.11491 + const unsigned int 1.11492 + x = (unsigned int)nfx, 1.11493 + y = (unsigned int)nfy; 1.11494 + const float 1.11495 + dx = nfx-x, 1.11496 + dy = nfy-y; 1.11497 + const unsigned int 1.11498 + nx = dx>0?x+1:x, 1.11499 + ny = dy>0?y+1:y; 1.11500 + const Tfloat 1.11501 + Icc = (Tfloat)(*this)(x,y,z,v), Inc = (Tfloat)(*this)(nx,y,z,v), 1.11502 + Icn = (Tfloat)(*this)(x,ny,z,v), Inn = (Tfloat)(*this)(nx,ny,z,v); 1.11503 + return Icc + dx*(Inc-Icc + dy*(Icc+Inn-Icn-Inc)) + dy*(Icn-Icc); 1.11504 + } 1.11505 + 1.11506 + //! Read a pixel value using linear interpolation and Dirichlet boundary conditions (first coordinate). 1.11507 + Tfloat linear_atX(const float fx, const int y, const int z, const int v, const T out_val) const { 1.11508 + const int 1.11509 + x = (int)fx-(fx>=0?0:1), nx = x+1; 1.11510 + const float 1.11511 + dx = fx-x; 1.11512 + const Tfloat 1.11513 + Ic = (Tfloat)atX(x,y,z,v,out_val), In = (Tfloat)atXY(nx,y,z,v,out_val); 1.11514 + return Ic + dx*(In-Ic); 1.11515 + } 1.11516 + 1.11517 + //! Read a pixel value using linear interpolation and Neumann boundary conditions (first coordinate). 1.11518 + Tfloat linear_atX(const float fx, const int y=0, const int z=0, const int v=0) const { 1.11519 + if (is_empty()) 1.11520 + throw CImgInstanceException("CImg<%s>::linear_atX() : Instance image is empty.", 1.11521 + pixel_type()); 1.11522 + return _linear_atX(fx,y,z,v); 1.11523 + } 1.11524 + 1.11525 + Tfloat _linear_atX(const float fx, const int y=0, const int z=0, const int v=0) const { 1.11526 + const float 1.11527 + nfx = fx<0?0:(fx>width-1?width-1:fx); 1.11528 + const unsigned int 1.11529 + x = (unsigned int)nfx; 1.11530 + const float 1.11531 + dx = nfx-x; 1.11532 + const unsigned int 1.11533 + nx = dx>0?x+1:x; 1.11534 + const Tfloat 1.11535 + Ic = (Tfloat)(*this)(x,y,z,v), In = (Tfloat)(*this)(nx,y,z,v); 1.11536 + return Ic + dx*(In-Ic); 1.11537 + } 1.11538 + 1.11539 + //! Read a pixel value using cubic interpolation and Dirichlet boundary conditions. 1.11540 + Tfloat cubic_atXY(const float fx, const float fy, const int z, const int v, const T out_val) const { 1.11541 + const int 1.11542 + x = (int)fx-(fx>=0?0:1), px = x-1, nx = x+1, ax = x+2, 1.11543 + y = (int)fy-(fy>=0?0:1), py = y-1, ny = y+1, ay = y+2; 1.11544 + const float 1.11545 + dx = fx-x, dx2 = dx*dx, dx3 = dx2*dx, 1.11546 + dy = fy-y; 1.11547 + const Tfloat 1.11548 + Ipp = (Tfloat)atXY(px,py,z,v,out_val), Icp = (Tfloat)atXY(x,py,z,v,out_val), 1.11549 + Inp = (Tfloat)atXY(nx,py,z,v,out_val), Iap = (Tfloat)atXY(ax,py,z,v,out_val), 1.11550 + Ipc = (Tfloat)atXY(px,y,z,v,out_val), Icc = (Tfloat)atXY(x,y,z,v,out_val), 1.11551 + Inc = (Tfloat)atXY(nx,y,z,v,out_val), Iac = (Tfloat)atXY(ax,y,z,v,out_val), 1.11552 + Ipn = (Tfloat)atXY(px,ny,z,v,out_val), Icn = (Tfloat)atXY(x,ny,z,v,out_val), 1.11553 + Inn = (Tfloat)atXY(nx,ny,z,v,out_val), Ian = (Tfloat)atXY(ax,ny,z,v,out_val), 1.11554 + Ipa = (Tfloat)atXY(px,ay,z,v,out_val), Ica = (Tfloat)atXY(x,ay,z,v,out_val), 1.11555 + Ina = (Tfloat)atXY(nx,ay,z,v,out_val), Iaa = (Tfloat)atXY(ax,ay,z,v,out_val), 1.11556 + valm = cimg::min(cimg::min(Ipp,Icp,Inp,Iap),cimg::min(Ipc,Icc,Inc,Iac),cimg::min(Ipn,Icn,Inn,Ian),cimg::min(Ipa,Ica,Ina,Iaa)), 1.11557 + valM = cimg::max(cimg::max(Ipp,Icp,Inp,Iap),cimg::max(Ipc,Icc,Inc,Iac),cimg::max(Ipn,Icn,Inn,Ian),cimg::max(Ipa,Ica,Ina,Iaa)), 1.11558 + u0p = Icp - Ipp, 1.11559 + u1p = Iap - Inp, 1.11560 + ap = 2*(Icp-Inp) + u0p + u1p, 1.11561 + bp = 3*(Inp-Icp) - 2*u0p - u1p, 1.11562 + u0c = Icc - Ipc, 1.11563 + u1c = Iac - Inc, 1.11564 + ac = 2*(Icc-Inc) + u0c + u1c, 1.11565 + bc = 3*(Inc-Icc) - 2*u0c - u1c, 1.11566 + u0n = Icn - Ipn, 1.11567 + u1n = Ian - Inn, 1.11568 + an = 2*(Icn-Inn) + u0n + u1n, 1.11569 + bn = 3*(Inn-Icn) - 2*u0n - u1n, 1.11570 + u0a = Ica - Ipa, 1.11571 + u1a = Iaa - Ina, 1.11572 + aa = 2*(Ica-Ina) + u0a + u1a, 1.11573 + ba = 3*(Ina-Ica) - 2*u0a - u1a, 1.11574 + valp = ap*dx3 + bp*dx2 + u0p*dx + Icp, 1.11575 + valc = ac*dx3 + bc*dx2 + u0c*dx + Icc, 1.11576 + valn = an*dx3 + bn*dx2 + u0n*dx + Icn, 1.11577 + vala = aa*dx3 + ba*dx2 + u0a*dx + Ica, 1.11578 + u0 = valc - valp, 1.11579 + u1 = vala - valn, 1.11580 + a = 2*(valc-valn) + u0 + u1, 1.11581 + b = 3*(valn-valc) - 2*u0 - u1, 1.11582 + val = a*dy*dy*dy + b*dy*dy + u0*dy + valc; 1.11583 + return val<valm?valm:(val>valM?valM:val); 1.11584 + } 1.11585 + 1.11586 + //! Read a pixel value using cubic interpolation and Neumann boundary conditions. 1.11587 + Tfloat cubic_atXY(const float fx, const float fy, const int z=0, const int v=0) const { 1.11588 + if (is_empty()) 1.11589 + throw CImgInstanceException("CImg<%s>::cubic_atXY() : Instance image is empty.", 1.11590 + pixel_type()); 1.11591 + return _cubic_atXY(fx,fy,z,v); 1.11592 + } 1.11593 + 1.11594 + Tfloat _cubic_atXY(const float fx, const float fy, const int z=0, const int v=0) const { 1.11595 + const float 1.11596 + nfx = fx<0?0:(fx>width-1?width-1:fx), 1.11597 + nfy = fy<0?0:(fy>height-1?height-1:fy); 1.11598 + const int 1.11599 + x = (int)nfx, 1.11600 + y = (int)nfy; 1.11601 + const float 1.11602 + dx = nfx-x, dx2 = dx*dx, dx3 = dx2*dx, 1.11603 + dy = nfy-y; 1.11604 + const int 1.11605 + px = x-1<0?0:x-1, nx = dx>0?x+1:x, ax = x+2>=dimx()?dimx()-1:x+2, 1.11606 + py = y-1<0?0:y-1, ny = dy>0?y+1:y, ay = y+2>=dimy()?dimy()-1:y+2; 1.11607 + const Tfloat 1.11608 + Ipp = (Tfloat)(*this)(px,py,z,v), Icp = (Tfloat)(*this)(x,py,z,v), 1.11609 + Inp = (Tfloat)(*this)(nx,py,z,v), Iap = (Tfloat)(*this)(ax,py,z,v), 1.11610 + Ipc = (Tfloat)(*this)(px,y,z,v), Icc = (Tfloat)(*this)(x,y,z,v), 1.11611 + Inc = (Tfloat)(*this)(nx,y,z,v), Iac = (Tfloat)(*this)(ax,y,z,v), 1.11612 + Ipn = (Tfloat)(*this)(px,ny,z,v), Icn = (Tfloat)(*this)(x,ny,z,v), 1.11613 + Inn = (Tfloat)(*this)(nx,ny,z,v), Ian = (Tfloat)(*this)(ax,ny,z,v), 1.11614 + Ipa = (Tfloat)(*this)(px,ay,z,v), Ica = (Tfloat)(*this)(x,ay,z,v), 1.11615 + Ina = (Tfloat)(*this)(nx,ay,z,v), Iaa = (Tfloat)(*this)(ax,ay,z,v), 1.11616 + valm = cimg::min(cimg::min(Ipp,Icp,Inp,Iap),cimg::min(Ipc,Icc,Inc,Iac),cimg::min(Ipn,Icn,Inn,Ian),cimg::min(Ipa,Ica,Ina,Iaa)), 1.11617 + valM = cimg::max(cimg::max(Ipp,Icp,Inp,Iap),cimg::max(Ipc,Icc,Inc,Iac),cimg::max(Ipn,Icn,Inn,Ian),cimg::max(Ipa,Ica,Ina,Iaa)), 1.11618 + u0p = Icp - Ipp, 1.11619 + u1p = Iap - Inp, 1.11620 + ap = 2*(Icp-Inp) + u0p + u1p, 1.11621 + bp = 3*(Inp-Icp) - 2*u0p - u1p, 1.11622 + u0c = Icc - Ipc, 1.11623 + u1c = Iac - Inc, 1.11624 + ac = 2*(Icc-Inc) + u0c + u1c, 1.11625 + bc = 3*(Inc-Icc) - 2*u0c - u1c, 1.11626 + u0n = Icn - Ipn, 1.11627 + u1n = Ian - Inn, 1.11628 + an = 2*(Icn-Inn) + u0n + u1n, 1.11629 + bn = 3*(Inn-Icn) - 2*u0n - u1n, 1.11630 + u0a = Ica - Ipa, 1.11631 + u1a = Iaa - Ina, 1.11632 + aa = 2*(Ica-Ina) + u0a + u1a, 1.11633 + ba = 3*(Ina-Ica) - 2*u0a - u1a, 1.11634 + valp = ap*dx3 + bp*dx2 + u0p*dx + Icp, 1.11635 + valc = ac*dx3 + bc*dx2 + u0c*dx + Icc, 1.11636 + valn = an*dx3 + bn*dx2 + u0n*dx + Icn, 1.11637 + vala = aa*dx3 + ba*dx2 + u0a*dx + Ica, 1.11638 + u0 = valc - valp, 1.11639 + u1 = vala - valn, 1.11640 + a = 2*(valc-valn) + u0 + u1, 1.11641 + b = 3*(valn-valc) - 2*u0 - u1, 1.11642 + val = a*dy*dy*dy + b*dy*dy + u0*dy + valc; 1.11643 + return val<valm?valm:(val>valM?valM:val); 1.11644 + } 1.11645 + 1.11646 + //! Read a pixel value using cubic interpolation and Dirichlet boundary conditions (first coordinates). 1.11647 + Tfloat cubic_atX(const float fx, const int y, const int z, const int v, const T out_val) const { 1.11648 + const int 1.11649 + x = (int)fx-(fx>=0?0:1), px = x-1, nx = x+1, ax = x+2; 1.11650 + const float 1.11651 + dx = fx-x; 1.11652 + const Tfloat 1.11653 + Ip = (Tfloat)atX(px,y,z,v,out_val), Ic = (Tfloat)atX(x,y,z,v,out_val), 1.11654 + In = (Tfloat)atX(nx,y,z,v,out_val), Ia = (Tfloat)atX(ax,y,z,v,out_val), 1.11655 + valm = cimg::min(Ip,In,Ic,Ia), valM = cimg::max(Ip,In,Ic,Ia), 1.11656 + u0 = Ic - Ip, 1.11657 + u1 = Ia - In, 1.11658 + a = 2*(Ic-In) + u0 + u1, 1.11659 + b = 3*(In-Ic) - 2*u0 - u1, 1.11660 + val = a*dx*dx*dx + b*dx*dx + u0*dx + Ic; 1.11661 + return val<valm?valm:(val>valM?valM:val); 1.11662 + } 1.11663 + 1.11664 + //! Read a pixel value using cubic interpolation and Neumann boundary conditions (first coordinates). 1.11665 + Tfloat cubic_atX(const float fx, const int y=0, const int z=0, const int v=0) const { 1.11666 + if (is_empty()) 1.11667 + throw CImgInstanceException("CImg<%s>::cubic_atX() : Instance image is empty.", 1.11668 + pixel_type()); 1.11669 + return _cubic_atX(fx,y,z,v); 1.11670 + } 1.11671 + 1.11672 + Tfloat _cubic_atX(const float fx, const int y=0, const int z=0, const int v=0) const { 1.11673 + const float 1.11674 + nfx = fx<0?0:(fx>width-1?width-1:fx); 1.11675 + const int 1.11676 + x = (int)nfx; 1.11677 + const float 1.11678 + dx = nfx-x; 1.11679 + const int 1.11680 + px = x-1<0?0:x-1, nx = dx>0?x+1:x, ax = x+2>=dimx()?dimx()-1:x+2; 1.11681 + const Tfloat 1.11682 + Ip = (Tfloat)(*this)(px,y,z,v), Ic = (Tfloat)(*this)(x,y,z,v), 1.11683 + In = (Tfloat)(*this)(nx,y,z,v), Ia = (Tfloat)(*this)(ax,y,z,v), 1.11684 + valm = cimg::min(Ip,In,Ic,Ia), valM = cimg::max(Ip,In,Ic,Ia), 1.11685 + u0 = Ic - Ip, 1.11686 + u1 = Ia - In, 1.11687 + a = 2*(Ic-In) + u0 + u1, 1.11688 + b = 3*(In-Ic) - 2*u0 - u1, 1.11689 + val = a*dx*dx*dx + b*dx*dx + u0*dx + Ic; 1.11690 + return val<valm?valm:(val>valM?valM:val); 1.11691 + } 1.11692 + 1.11693 + //! Set a pixel value, with 3D float coordinates, using linear interpolation. 1.11694 + CImg& set_linear_atXYZ(const T& val, const float fx, const float fy=0, const float fz=0, const int v=0, 1.11695 + const bool add=false) { 1.11696 + const int 1.11697 + x = (int)fx-(fx>=0?0:1), nx = x+1, 1.11698 + y = (int)fy-(fy>=0?0:1), ny = y+1, 1.11699 + z = (int)fz-(fz>=0?0:1), nz = z+1; 1.11700 + const float 1.11701 + dx = fx-x, 1.11702 + dy = fy-y, 1.11703 + dz = fz-z; 1.11704 + if (v>=0 && v<dimv()) { 1.11705 + if (z>=0 && z<dimz()) { 1.11706 + if (y>=0 && y<dimy()) { 1.11707 + if (x>=0 && x<dimx()) { 1.11708 + const float w1 = (1-dx)*(1-dy)*(1-dz), w2 = add?1:(1-w1); 1.11709 + (*this)(x,y,z,v) = (T)(w1*val + w2*(*this)(x,y,z,v)); 1.11710 + } 1.11711 + if (nx>=0 && nx<dimx()) { 1.11712 + const float w1 = dx*(1-dy)*(1-dz), w2 = add?1:(1-w1); 1.11713 + (*this)(nx,y,z,v) = (T)(w1*val + w2*(*this)(nx,y,z,v)); 1.11714 + } 1.11715 + } 1.11716 + if (ny>=0 && ny<dimy()) { 1.11717 + if (x>=0 && x<dimx()) { 1.11718 + const float w1 = (1-dx)*dy*(1-dz), w2 = add?1:(1-w1); 1.11719 + (*this)(x,ny,z,v) = (T)(w1*val + w2*(*this)(x,ny,z,v)); 1.11720 + } 1.11721 + if (nx>=0 && nx<dimx()) { 1.11722 + const float w1 = dx*dy*(1-dz), w2 = add?1:(1-w1); 1.11723 + (*this)(nx,ny,z,v) = (T)(w1*val + w2*(*this)(nx,ny,z,v)); 1.11724 + } 1.11725 + } 1.11726 + } 1.11727 + if (nz>=0 && nz<dimz()) { 1.11728 + if (y>=0 && y<dimy()) { 1.11729 + if (x>=0 && x<dimx()) { 1.11730 + const float w1 = (1-dx)*(1-dy), w2 = add?1:(1-w1); 1.11731 + (*this)(x,y,nz,v) = (T)(w1*val + w2*(*this)(x,y,nz,v)); 1.11732 + } 1.11733 + if (nx>=0 && nx<dimx()) { 1.11734 + const float w1 = dx*(1-dy), w2 = add?1:(1-w1); 1.11735 + (*this)(nx,y,nz,v) = (T)(w1*val + w2*(*this)(nx,y,nz,v)); 1.11736 + } 1.11737 + } 1.11738 + if (ny>=0 && ny<dimy()) { 1.11739 + if (x>=0 && x<dimx()) { 1.11740 + const float w1 = (1-dx)*dy, w2 = add?1:(1-w1); 1.11741 + (*this)(x,ny,nz,v) = (T)(w1*val + w2*(*this)(x,ny,nz,v)); 1.11742 + } 1.11743 + if (nx>=0 && nx<dimx()) { 1.11744 + const float w1 = dx*dy, w2 = add?1:(1-w1); 1.11745 + (*this)(nx,ny,nz,v) = (T)(w1*val + w2*(*this)(nx,ny,nz,v)); 1.11746 + } 1.11747 + } 1.11748 + } 1.11749 + } 1.11750 + return *this; 1.11751 + } 1.11752 + 1.11753 + //! Set a pixel value, with 2D float coordinates, using linear interpolation. 1.11754 + CImg& set_linear_atXY(const T& val, const float fx, const float fy=0, const int z=0, const int v=0, 1.11755 + const bool add=false) { 1.11756 + const int 1.11757 + x = (int)fx-(fx>=0?0:1), nx = x+1, 1.11758 + y = (int)fy-(fy>=0?0:1), ny = y+1; 1.11759 + const float 1.11760 + dx = fx-x, 1.11761 + dy = fy-y; 1.11762 + if (z>=0 && z<dimz() && v>=0 && v<dimv()) { 1.11763 + if (y>=0 && y<dimy()) { 1.11764 + if (x>=0 && x<dimx()) { 1.11765 + const float w1 = (1-dx)*(1-dy), w2 = add?1:(1-w1); 1.11766 + (*this)(x,y,z,v) = (T)(w1*val + w2*(*this)(x,y,z,v)); 1.11767 + } 1.11768 + if (nx>=0 && nx<dimx()) { 1.11769 + const float w1 = dx*(1-dy), w2 = add?1:(1-w1); 1.11770 + (*this)(nx,y,z,v) = (T)(w1*val + w2*(*this)(nx,y,z,v)); 1.11771 + } 1.11772 + } 1.11773 + if (ny>=0 && ny<dimy()) { 1.11774 + if (x>=0 && x<dimx()) { 1.11775 + const float w1 = (1-dx)*dy, w2 = add?1:(1-w1); 1.11776 + (*this)(x,ny,z,v) = (T)(w1*val + w2*(*this)(x,ny,z,v)); 1.11777 + } 1.11778 + if (nx>=0 && nx<dimx()) { 1.11779 + const float w1 = dx*dy, w2 = add?1:(1-w1); 1.11780 + (*this)(nx,ny,z,v) = (T)(w1*val + w2*(*this)(nx,ny,z,v)); 1.11781 + } 1.11782 + } 1.11783 + } 1.11784 + return *this; 1.11785 + } 1.11786 + 1.11787 + //! Return a reference to the minimum pixel value of the instance image 1.11788 + const T& min() const { 1.11789 + if (is_empty()) 1.11790 + throw CImgInstanceException("CImg<%s>::min() : Instance image is empty.", 1.11791 + pixel_type()); 1.11792 + const T *ptrmin = data; 1.11793 + T min_value = *ptrmin; 1.11794 + cimg_for(*this,ptr,T) if ((*ptr)<min_value) min_value = *(ptrmin=ptr); 1.11795 + return *ptrmin; 1.11796 + } 1.11797 + 1.11798 + //! Return a reference to the minimum pixel value of the instance image 1.11799 + T& min() { 1.11800 + if (is_empty()) 1.11801 + throw CImgInstanceException("CImg<%s>::min() : Instance image is empty.", 1.11802 + pixel_type()); 1.11803 + T *ptrmin = data; 1.11804 + T min_value = *ptrmin; 1.11805 + cimg_for(*this,ptr,T) if ((*ptr)<min_value) min_value = *(ptrmin=ptr); 1.11806 + return *ptrmin; 1.11807 + } 1.11808 + 1.11809 + //! Return a reference to the maximum pixel value of the instance image 1.11810 + const T& max() const { 1.11811 + if (is_empty()) 1.11812 + throw CImgInstanceException("CImg<%s>::max() : Instance image is empty.", 1.11813 + pixel_type()); 1.11814 + const T *ptrmax = data; 1.11815 + T max_value = *ptrmax; 1.11816 + cimg_for(*this,ptr,T) if ((*ptr)>max_value) max_value = *(ptrmax=ptr); 1.11817 + return *ptrmax; 1.11818 + } 1.11819 + 1.11820 + //! Return a reference to the maximum pixel value of the instance image 1.11821 + T& max() { 1.11822 + if (is_empty()) 1.11823 + throw CImgInstanceException("CImg<%s>::max() : Instance image is empty.", 1.11824 + pixel_type()); 1.11825 + T *ptrmax = data; 1.11826 + T max_value = *ptrmax; 1.11827 + cimg_for(*this,ptr,T) if ((*ptr)>max_value) max_value = *(ptrmax=ptr); 1.11828 + return *ptrmax; 1.11829 + } 1.11830 + 1.11831 + //! Return a reference to the minimum pixel value and return also the maximum pixel value. 1.11832 + template<typename t> 1.11833 + const T& minmax(t& max_val) const { 1.11834 + if (is_empty()) 1.11835 + throw CImgInstanceException("CImg<%s>::minmax() : Instance image is empty.", 1.11836 + pixel_type()); 1.11837 + const T *ptrmin = data; 1.11838 + T min_value = *ptrmin, max_value = min_value; 1.11839 + cimg_for(*this,ptr,T) { 1.11840 + const T val = *ptr; 1.11841 + if (val<min_value) { min_value = val; ptrmin = ptr; } 1.11842 + if (val>max_value) max_value = val; 1.11843 + } 1.11844 + max_val = (t)max_value; 1.11845 + return *ptrmin; 1.11846 + } 1.11847 + 1.11848 + //! Return a reference to the minimum pixel value and return also the maximum pixel value. 1.11849 + template<typename t> 1.11850 + T& minmax(t& max_val) { 1.11851 + if (is_empty()) 1.11852 + throw CImgInstanceException("CImg<%s>::minmax() : Instance image is empty.", 1.11853 + pixel_type()); 1.11854 + T *ptrmin = data; 1.11855 + T min_value = *ptrmin, max_value = min_value; 1.11856 + cimg_for(*this,ptr,T) { 1.11857 + const T val = *ptr; 1.11858 + if (val<min_value) { min_value = val; ptrmin = ptr; } 1.11859 + if (val>max_value) max_value = val; 1.11860 + } 1.11861 + max_val = (t)max_value; 1.11862 + return *ptrmin; 1.11863 + } 1.11864 + 1.11865 + //! Return a reference to the maximum pixel value and return also the minimum pixel value. 1.11866 + template<typename t> 1.11867 + const T& maxmin(t& min_val) const { 1.11868 + if (is_empty()) 1.11869 + throw CImgInstanceException("CImg<%s>::maxmin() : Instance image is empty.", 1.11870 + pixel_type()); 1.11871 + const T *ptrmax = data; 1.11872 + T max_value = *ptrmax, min_value = max_value; 1.11873 + cimg_for(*this,ptr,T) { 1.11874 + const T val = *ptr; 1.11875 + if (val>max_value) { max_value = val; ptrmax = ptr; } 1.11876 + if (val<min_value) min_value = val; 1.11877 + } 1.11878 + min_val = (t)min_value; 1.11879 + return *ptrmax; 1.11880 + } 1.11881 + 1.11882 + //! Return a reference to the maximum pixel value and return also the minimum pixel value. 1.11883 + template<typename t> 1.11884 + T& maxmin(t& min_val) { 1.11885 + if (is_empty()) 1.11886 + throw CImgInstanceException("CImg<%s>::maxmin() : Instance image is empty.", 1.11887 + pixel_type()); 1.11888 + T *ptrmax = data; 1.11889 + T max_value = *ptrmax, min_value = max_value; 1.11890 + cimg_for(*this,ptr,T) { 1.11891 + const T val = *ptr; 1.11892 + if (val>max_value) { max_value = val; ptrmax = ptr; } 1.11893 + if (val<min_value) min_value = val; 1.11894 + } 1.11895 + min_val = (t)min_value; 1.11896 + return *ptrmax; 1.11897 + } 1.11898 + 1.11899 + //! Return the sum of all the pixel values in an image. 1.11900 + Tfloat sum() const { 1.11901 + if (is_empty()) 1.11902 + throw CImgInstanceException("CImg<%s>::sum() : Instance image (%u,%u,%u,%u,%p) is empty.", 1.11903 + pixel_type(),width,height,depth,dim,data); 1.11904 + Tfloat res = 0; 1.11905 + cimg_for(*this,ptr,T) res+=*ptr; 1.11906 + return res; 1.11907 + } 1.11908 + 1.11909 + //! Return the mean pixel value of the instance image. 1.11910 + Tfloat mean() const { 1.11911 + if (is_empty()) 1.11912 + throw CImgInstanceException("CImg<%s>::mean() : Instance image is empty.", 1.11913 + pixel_type()); 1.11914 + Tfloat val = 0; 1.11915 + cimg_for(*this,ptr,T) val+=*ptr; 1.11916 + return val/size(); 1.11917 + } 1.11918 + 1.11919 + //! Return the variance of the image. 1.11920 + /** 1.11921 + @param variance_method Determines how to calculate the variance 1.11922 + <table border="0"> 1.11923 + <tr><td>0</td> 1.11924 + <td>Second moment: 1.11925 + @f$ v = 1/N \sum\limits_{k=1}^{N} (x_k - \bar x)^2 1.11926 + = 1/N \left( \sum\limits_{k=1}^N x_k^2 - \left( \sum\limits_{k=1}^N x_k \right)^2 / N \right) @f$ 1.11927 + with @f$ \bar x = 1/N \sum\limits_{k=1}^N x_k \f$</td></tr> 1.11928 + <tr><td>1</td> 1.11929 + <td>Best unbiased estimator: @f$ v = \frac{1}{N-1} \sum\limits_{k=1}^{N} (x_k - \bar x)^2 @f$</td></tr> 1.11930 + <tr><td>2</td> 1.11931 + <td>Least median of squares</td></tr> 1.11932 + <tr><td>3</td> 1.11933 + <td>Least trimmed of squares</td></tr> 1.11934 + </table> 1.11935 + */ 1.11936 + Tfloat variance(const unsigned int variance_method=1) const { 1.11937 + Tfloat foo; 1.11938 + return variancemean(variance_method,foo); 1.11939 + } 1.11940 + 1.11941 + //! Return the variance and the mean of the image. 1.11942 + template<typename t> 1.11943 + Tfloat variancemean(const unsigned int variance_method, t& mean) const { 1.11944 + if (is_empty()) 1.11945 + throw CImgInstanceException("CImg<%s>::variance() : Instance image is empty.", 1.11946 + pixel_type()); 1.11947 + Tfloat variance = 0, average = 0; 1.11948 + const unsigned int siz = size(); 1.11949 + switch (variance_method) { 1.11950 + case 3 : { // Least trimmed of Squares 1.11951 + CImg<Tfloat> buf(*this); 1.11952 + const unsigned int siz2 = siz>>1; 1.11953 + { cimg_for(buf,ptrs,Tfloat) { const Tfloat val = *ptrs; (*ptrs)*=val; average+=val; }} 1.11954 + buf.sort(); 1.11955 + Tfloat a = 0; 1.11956 + const Tfloat *ptrs = buf.ptr(); 1.11957 + for (unsigned int j = 0; j<siz2; ++j) a+=*(ptrs++); 1.11958 + const Tfloat sig = (Tfloat)(2.6477*cimg_std::sqrt(a/siz2)); 1.11959 + variance = sig*sig; 1.11960 + } break; 1.11961 + case 2 : { // Least Median of Squares (MAD) 1.11962 + CImg<Tfloat> buf(*this); 1.11963 + buf.sort(); 1.11964 + const unsigned int siz2 = siz>>1; 1.11965 + const Tfloat med_i = buf[siz2]; 1.11966 + cimg_for(buf,ptrs,Tfloat) { const Tfloat val = *ptrs; *ptrs = cimg::abs(val - med_i); average+=val; } 1.11967 + buf.sort(); 1.11968 + const Tfloat sig = (Tfloat)(1.4828*buf[siz2]); 1.11969 + variance = sig*sig; 1.11970 + } break; 1.11971 + case 1 : { // Least mean square (robust definition) 1.11972 + Tfloat S = 0, S2 = 0; 1.11973 + cimg_for(*this,ptr,T) { const Tfloat val = (Tfloat)*ptr; S+=val; S2+=val*val; } 1.11974 + variance = siz>1?(S2 - S*S/siz)/(siz - 1):0; 1.11975 + average = S; 1.11976 + } break; 1.11977 + case 0 :{ // Least mean square (standard definition) 1.11978 + Tfloat S = 0, S2 = 0; 1.11979 + cimg_for(*this,ptr,T) { const Tfloat val = (Tfloat)*ptr; S+=val; S2+=val*val; } 1.11980 + variance = (S2 - S*S/siz)/siz; 1.11981 + average = S; 1.11982 + } break; 1.11983 + default : 1.11984 + throw CImgArgumentException("CImg<%s>::variancemean() : Incorrect parameter 'variance_method = %d' (correct values are 0,1,2 or 3).", 1.11985 + pixel_type(),variance_method); 1.11986 + } 1.11987 + mean = (t)(average/siz); 1.11988 + return variance>0?variance:0; 1.11989 + } 1.11990 + 1.11991 + //! Return the kth smallest element of the image. 1.11992 + // (Adapted from the numerical recipies for CImg) 1.11993 + T kth_smallest(const unsigned int k) const { 1.11994 + if (is_empty()) 1.11995 + throw CImgInstanceException("CImg<%s>::kth_smallest() : Instance image (%u,%u,%u,%u,%p) is empty.", 1.11996 + pixel_type(),width,height,depth,dim,data); 1.11997 + CImg<T> arr(*this); 1.11998 + unsigned long l = 0, ir = size()-1; 1.11999 + for (;;) { 1.12000 + if (ir<=l+1) { 1.12001 + if (ir==l+1 && arr[ir]<arr[l]) cimg::swap(arr[l],arr[ir]); 1.12002 + return arr[k]; 1.12003 + } else { 1.12004 + const unsigned long mid = (l+ir)>>1; 1.12005 + cimg::swap(arr[mid],arr[l+1]); 1.12006 + if (arr[l]>arr[ir]) cimg::swap(arr[l],arr[ir]); 1.12007 + if (arr[l+1]>arr[ir]) cimg::swap(arr[l+1],arr[ir]); 1.12008 + if (arr[l]>arr[l+1]) cimg::swap(arr[l],arr[l+1]); 1.12009 + unsigned long i = l+1, j = ir; 1.12010 + const T pivot = arr[l+1]; 1.12011 + for (;;) { 1.12012 + do ++i; while (arr[i]<pivot); 1.12013 + do --j; while (arr[j]>pivot); 1.12014 + if (j<i) break; 1.12015 + cimg::swap(arr[i],arr[j]); 1.12016 + } 1.12017 + arr[l+1] = arr[j]; 1.12018 + arr[j] = pivot; 1.12019 + if (j>=k) ir=j-1; 1.12020 + if (j<=k) l=i; 1.12021 + } 1.12022 + } 1.12023 + return 0; 1.12024 + } 1.12025 + 1.12026 + //! Compute a statistics vector (min,max,mean,variance,xmin,ymin,zmin,vmin,xmax,ymax,zmax,vmax). 1.12027 + CImg<T>& stats(const unsigned int variance_method=1) { 1.12028 + return get_stats(variance_method).transfer_to(*this); 1.12029 + } 1.12030 + 1.12031 + CImg<Tfloat> get_stats(const unsigned int variance_method=1) const { 1.12032 + if (is_empty()) return CImg<Tfloat>(); 1.12033 + const unsigned long siz = size(); 1.12034 + const T *const odata = data; 1.12035 + const T *pm = odata, *pM = odata; 1.12036 + Tfloat S = 0, S2 = 0; 1.12037 + T m = *pm, M = m; 1.12038 + cimg_for(*this,ptr,T) { 1.12039 + const T val = *ptr; 1.12040 + const Tfloat fval = (Tfloat)val; 1.12041 + if (val<m) { m = val; pm = ptr; } 1.12042 + if (val>M) { M = val; pM = ptr; } 1.12043 + S+=fval; 1.12044 + S2+=fval*fval; 1.12045 + } 1.12046 + const Tfloat 1.12047 + mean_value = S/siz, 1.12048 + _variance_value = variance_method==0?(S2 - S*S/siz)/siz: 1.12049 + (variance_method==1?(siz>1?(S2 - S*S/siz)/(siz - 1):0): 1.12050 + variance(variance_method)), 1.12051 + variance_value = _variance_value>0?_variance_value:0; 1.12052 + int 1.12053 + xm = 0, ym = 0, zm = 0, vm = 0, 1.12054 + xM = 0, yM = 0, zM = 0, vM = 0; 1.12055 + contains(*pm,xm,ym,zm,vm); 1.12056 + contains(*pM,xM,yM,zM,vM); 1.12057 + return CImg<Tfloat>(1,12).fill((Tfloat)m,(Tfloat)M,mean_value,variance_value, 1.12058 + (Tfloat)xm,(Tfloat)ym,(Tfloat)zm,(Tfloat)vm, 1.12059 + (Tfloat)xM,(Tfloat)yM,(Tfloat)zM,(Tfloat)vM); 1.12060 + } 1.12061 + 1.12062 + //! Return the median value of the image. 1.12063 + T median() const { 1.12064 + const unsigned int s = size(); 1.12065 + const T res = kth_smallest(s>>1); 1.12066 + return (s%2)?res:((res+kth_smallest((s>>1)-1))/2); 1.12067 + } 1.12068 + 1.12069 + //! Compute the MSE (Mean-Squared Error) between two images. 1.12070 + template<typename t> 1.12071 + Tfloat MSE(const CImg<t>& img) const { 1.12072 + if (img.size()!=size()) 1.12073 + throw CImgArgumentException("CImg<%s>::MSE() : Instance image (%u,%u,%u,%u) and given image (%u,%u,%u,%u) have different dimensions.", 1.12074 + pixel_type(),width,height,depth,dim,img.width,img.height,img.depth,img.dim); 1.12075 + 1.12076 + Tfloat vMSE = 0; 1.12077 + const t* ptr2 = img.end(); 1.12078 + cimg_for(*this,ptr1,T) { 1.12079 + const Tfloat diff = (Tfloat)*ptr1 - (Tfloat)*(--ptr2); 1.12080 + vMSE += diff*diff; 1.12081 + } 1.12082 + vMSE/=img.size(); 1.12083 + return vMSE; 1.12084 + } 1.12085 + 1.12086 + //! Compute the PSNR between two images. 1.12087 + template<typename t> 1.12088 + Tfloat PSNR(const CImg<t>& img, const Tfloat valmax=(Tfloat)255) const { 1.12089 + const Tfloat vMSE = (Tfloat)cimg_std::sqrt(MSE(img)); 1.12090 + return (vMSE!=0)?(Tfloat)(20*cimg_std::log10(valmax/vMSE)):(Tfloat)(cimg::type<Tfloat>::max()); 1.12091 + } 1.12092 + 1.12093 + //! Return the trace of the image, viewed as a matrix. 1.12094 + Tfloat trace() const { 1.12095 + if (is_empty()) 1.12096 + throw CImgInstanceException("CImg<%s>::trace() : Instance matrix (%u,%u,%u,%u,%p) is empty.", 1.12097 + pixel_type(),width,height,depth,dim,data); 1.12098 + Tfloat res = 0; 1.12099 + cimg_forX(*this,k) res+=(*this)(k,k); 1.12100 + return res; 1.12101 + } 1.12102 + 1.12103 + //! Return the dot product of the current vector/matrix with the vector/matrix \p img. 1.12104 + template<typename t> 1.12105 + Tfloat dot(const CImg<t>& img) const { 1.12106 + if (is_empty()) 1.12107 + throw CImgInstanceException("CImg<%s>::dot() : Instance object (%u,%u,%u,%u,%p) is empty.", 1.12108 + pixel_type(),width,height,depth,dim,data); 1.12109 + if (!img) 1.12110 + throw CImgArgumentException("CImg<%s>::trace() : Specified argument (%u,%u,%u,%u,%p) is empty.", 1.12111 + pixel_type(),img.width,img.height,img.depth,img.dim,img.data); 1.12112 + const unsigned long nb = cimg::min(size(),img.size()); 1.12113 + Tfloat res = 0; 1.12114 + for (unsigned long off = 0; off<nb; ++off) res+=(Tfloat)data[off]*(Tfloat)img[off]; 1.12115 + return res; 1.12116 + } 1.12117 + 1.12118 + //! Return the determinant of the image, viewed as a matrix. 1.12119 + Tfloat det() const { 1.12120 + if (is_empty() || width!=height || depth!=1 || dim!=1) 1.12121 + throw CImgInstanceException("CImg<%s>::det() : Instance matrix (%u,%u,%u,%u,%p) is not square or is empty.", 1.12122 + pixel_type(),width,height,depth,dim,data); 1.12123 + switch (width) { 1.12124 + case 1 : return (Tfloat)((*this)(0,0)); 1.12125 + case 2 : return (Tfloat)((*this)(0,0))*(Tfloat)((*this)(1,1)) - (Tfloat)((*this)(0,1))*(Tfloat)((*this)(1,0)); 1.12126 + case 3 : { 1.12127 + const Tfloat 1.12128 + a = (Tfloat)data[0], d = (Tfloat)data[1], g = (Tfloat)data[2], 1.12129 + b = (Tfloat)data[3], e = (Tfloat)data[4], h = (Tfloat)data[5], 1.12130 + c = (Tfloat)data[6], f = (Tfloat)data[7], i = (Tfloat)data[8]; 1.12131 + return i*a*e - a*h*f - i*b*d + b*g*f + c*d*h - c*g*e; 1.12132 + } 1.12133 + default : { 1.12134 + CImg<Tfloat> lu(*this); 1.12135 + CImg<uintT> indx; 1.12136 + bool d; 1.12137 + lu._LU(indx,d); 1.12138 + Tfloat res = d?(Tfloat)1:(Tfloat)-1; 1.12139 + cimg_forX(lu,i) res*=lu(i,i); 1.12140 + return res; 1.12141 + } 1.12142 + } 1.12143 + return 0; 1.12144 + } 1.12145 + 1.12146 + //! Return the norm of the current vector/matrix. \p ntype = norm type (0=L2, 1=L1, -1=Linf). 1.12147 + Tfloat norm(const int norm_type=2) const { 1.12148 + if (is_empty()) 1.12149 + throw CImgInstanceException("CImg<%s>::norm() : Instance object (%u,%u,%u,%u,%p) is empty.", 1.12150 + pixel_type(),width,height,depth,dim,data); 1.12151 + Tfloat res = 0; 1.12152 + switch (norm_type) { 1.12153 + case -1 : { 1.12154 + cimg_foroff(*this,off) { 1.12155 + const Tfloat tmp = cimg::abs((Tfloat)data[off]); 1.12156 + if (tmp>res) res = tmp; 1.12157 + } 1.12158 + return res; 1.12159 + } break; 1.12160 + case 1 : { 1.12161 + cimg_foroff(*this,off) res+=cimg::abs((Tfloat)data[off]); 1.12162 + return res; 1.12163 + } break; 1.12164 + case 2 : return (Tfloat)cimg_std::sqrt(dot(*this)); break; 1.12165 + default : 1.12166 + throw CImgArgumentException("CImg<%s>::norm() : Incorrect parameter 'norm_type=%d' (correct values are -1,1 or 2).", 1.12167 + pixel_type(),norm_type); 1.12168 + } 1.12169 + return 0; 1.12170 + } 1.12171 + 1.12172 + //! Return a C-string containing the values of the instance image. 1.12173 + CImg<charT> value_string(const char separator=',', const unsigned int max_size=0) const { 1.12174 + if (is_empty()) return CImg<charT>(1,1,1,1,0); 1.12175 + const unsigned int siz = (unsigned int)size(); 1.12176 + CImgList<charT> items; 1.12177 + char item[256] = { 0 }; 1.12178 + const T *ptrs = ptr(); 1.12179 + for (unsigned int off = 0; off<siz-1; ++off) { 1.12180 + cimg_std::sprintf(item,cimg::type<T>::format(),cimg::type<T>::format(*(ptrs++))); 1.12181 + const int l = cimg::strlen(item); 1.12182 + items.insert(CImg<charT>(item,l+1)); 1.12183 + items[items.size-1](l) = separator; 1.12184 + } 1.12185 + cimg_std::sprintf(item,cimg::type<T>::format(),cimg::type<T>::format(*ptrs)); 1.12186 + items.insert(CImg<charT>(item,cimg::strlen(item)+1)); 1.12187 + CImg<ucharT> res = items.get_append('x'); 1.12188 + if (max_size) { res.crop(0,max_size); res(max_size) = 0; } 1.12189 + return res; 1.12190 + } 1.12191 + 1.12192 + //! Display informations about the image on the standard error output. 1.12193 + /** 1.12194 + \param title Name for the considered image (optional). 1.12195 + \param display_stats Compute and display image statistics (optional). 1.12196 + **/ 1.12197 + const CImg<T>& print(const char *title=0, const bool display_stats=true) const { 1.12198 + int xm = 0, ym = 0, zm = 0, vm = 0, xM = 0, yM = 0, zM = 0, vM = 0; 1.12199 + static CImg<doubleT> st; 1.12200 + if (!is_empty() && display_stats) { 1.12201 + st = get_stats(); 1.12202 + xm = (int)st[4]; ym = (int)st[5], zm = (int)st[6], vm = (int)st[7]; 1.12203 + xM = (int)st[8]; yM = (int)st[9], zM = (int)st[10], vM = (int)st[11]; 1.12204 + } 1.12205 + const unsigned long siz = size(), msiz = siz*sizeof(T), siz1 = siz-1; 1.12206 + const unsigned int mdisp = msiz<8*1024?0:(msiz<8*1024*1024?1:2), width1 = width-1; 1.12207 + char ntitle[64] = { 0 }; 1.12208 + if (!title) cimg_std::sprintf(ntitle,"CImg<%s>",pixel_type()); 1.12209 + cimg_std::fprintf(cimg_stdout,"%s: this = %p, size = (%u,%u,%u,%u) [%lu %s], data = (%s*)%p (%s) = [ ", 1.12210 + title?title:ntitle,(void*)this,width,height,depth,dim, 1.12211 + mdisp==0?msiz:(mdisp==1?(msiz>>10):(msiz>>20)), 1.12212 + mdisp==0?"b":(mdisp==1?"Kb":"Mb"), 1.12213 + pixel_type(),(void*)data,is_shared?"shared":"not shared"); 1.12214 + if (!is_empty()) cimg_foroff(*this,off) { 1.12215 + cimg_std::fprintf(cimg_stdout,cimg::type<T>::format(),cimg::type<T>::format(data[off])); 1.12216 + if (off!=siz1) cimg_std::fprintf(cimg_stdout,"%s",off%width==width1?" ; ":" "); 1.12217 + if (off==7 && siz>16) { off = siz1-8; if (off!=7) cimg_std::fprintf(cimg_stdout,"... "); } 1.12218 + } 1.12219 + if (!is_empty() && display_stats) 1.12220 + cimg_std::fprintf(cimg_stdout," ], min = %g, max = %g, mean = %g, std = %g, coords(min) = (%u,%u,%u,%u), coords(max) = (%u,%u,%u,%u).\n", 1.12221 + st[0],st[1],st[2],cimg_std::sqrt(st[3]),xm,ym,zm,vm,xM,yM,zM,vM); 1.12222 + else cimg_std::fprintf(cimg_stdout,"%s].\n",is_empty()?"":" "); 1.12223 + return *this; 1.12224 + } 1.12225 + 1.12226 + //@} 1.12227 + //------------------------------------------ 1.12228 + // 1.12229 + //! \name Arithmetic and Boolean Operators 1.12230 + //@{ 1.12231 + //------------------------------------------ 1.12232 + 1.12233 + //! Assignment operator. 1.12234 + /** 1.12235 + This operator assigns a copy of the input image \p img to the current instance image. 1.12236 + \param img The input image to copy. 1.12237 + \remark 1.12238 + - This operator is strictly equivalent to the function assign(const CImg< t >&) and has exactly the same properties. 1.12239 + **/ 1.12240 + template<typename t> 1.12241 + CImg<T>& operator=(const CImg<t>& img) { 1.12242 + return assign(img); 1.12243 + } 1.12244 + 1.12245 + CImg<T>& operator=(const CImg<T>& img) { 1.12246 + return assign(img); 1.12247 + } 1.12248 + 1.12249 + //! Assign values of a C-array to the instance image. 1.12250 + /** 1.12251 + \param buf Pointer to a C-style array having a size of (at least) <tt>this->size()</tt>. 1.12252 + 1.12253 + - Replace pixel values by the content of the array \c buf. 1.12254 + - Warning : the value types in the array and in the image must be the same. 1.12255 + 1.12256 + \par example: 1.12257 + \code 1.12258 + float tab[4*4] = { 1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16 }; // Define a 4x4 matrix in C-style. 1.12259 + CImg<float> matrice(4,4); // Define a 4x4 greyscale image. 1.12260 + matrice = tab; // Fill the image by the values in tab. 1.12261 + \endcode 1.12262 + **/ 1.12263 + CImg<T>& operator=(const T *buf) { 1.12264 + return assign(buf,width,height,depth,dim); 1.12265 + } 1.12266 + 1.12267 + //! Assign a value to each image pixel of the instance image. 1.12268 + CImg<T>& operator=(const T val) { 1.12269 + return fill(val); 1.12270 + } 1.12271 + 1.12272 + //! Operator+ 1.12273 + /** 1.12274 + \remark 1.12275 + - This operator can be used to get a non-shared copy of an image. 1.12276 + **/ 1.12277 + CImg<T> operator+() const { 1.12278 + return CImg<T>(*this,false); 1.12279 + } 1.12280 + 1.12281 + //! Operator+=; 1.12282 +#ifdef cimg_use_visualcpp6 1.12283 + CImg<T>& operator+=(const T val) 1.12284 +#else 1.12285 + template<typename t> 1.12286 + CImg<T>& operator+=(const t val) 1.12287 +#endif 1.12288 + { 1.12289 + cimg_for(*this,ptr,T) (*ptr) = (T)((*ptr)+val); 1.12290 + return *this; 1.12291 + } 1.12292 + 1.12293 + //! Operator+= 1.12294 + template<typename t> 1.12295 + CImg<T>& operator+=(const CImg<t>& img) { 1.12296 + if (is_overlapped(img)) return *this+=+img; 1.12297 + const unsigned int smin = cimg::min(size(),img.size()); 1.12298 + t *ptrs = img.data + smin; 1.12299 + for (T *ptrd = data + smin; ptrd>data; --ptrd, (*ptrd)=(T)((*ptrd)+(*(--ptrs)))) {} 1.12300 + return *this; 1.12301 + } 1.12302 + 1.12303 + //! Operator++ (prefix) 1.12304 + CImg<T>& operator++() { 1.12305 + cimg_for(*this,ptr,T) ++(*ptr); 1.12306 + return *this; 1.12307 + } 1.12308 + 1.12309 + //! Operator++ (postfix) 1.12310 + CImg<T> operator++(int) { 1.12311 + const CImg<T> copy(*this,false); 1.12312 + ++*this; 1.12313 + return copy; 1.12314 + } 1.12315 + 1.12316 + //! Operator-. 1.12317 + CImg<T> operator-() const { 1.12318 + return CImg<T>(width,height,depth,dim,0)-=*this; 1.12319 + } 1.12320 + 1.12321 + //! Operator-=. 1.12322 +#ifdef cimg_use_visualcpp6 1.12323 + CImg<T>& operator-=(const T val) 1.12324 +#else 1.12325 + template<typename t> 1.12326 + CImg<T>& operator-=(const t val) 1.12327 +#endif 1.12328 + { 1.12329 + cimg_for(*this,ptr,T) (*ptr) = (T)((*ptr)-val); 1.12330 + return *this; 1.12331 + } 1.12332 + 1.12333 + //! Operator-=. 1.12334 + template<typename t> 1.12335 + CImg<T>& operator-=(const CImg<t>& img) { 1.12336 + if (is_overlapped(img)) return *this-=+img; 1.12337 + const unsigned int smin = cimg::min(size(),img.size()); 1.12338 + t *ptrs = img.data+smin; 1.12339 + for (T *ptrd = data+smin; ptrd>data; --ptrd, (*ptrd) = (T)((*ptrd)-(*(--ptrs)))) {} 1.12340 + return *this; 1.12341 + } 1.12342 + 1.12343 + //! Operator-- (prefix). 1.12344 + CImg<T>& operator--() { 1.12345 + cimg_for(*this,ptr,T) *ptr = *ptr-(T)1; 1.12346 + return *this; 1.12347 + } 1.12348 + 1.12349 + //! Operator-- (postfix). 1.12350 + CImg<T> operator--(int) { 1.12351 + CImg<T> copy(*this,false); 1.12352 + --*this; 1.12353 + return copy; 1.12354 + } 1.12355 + 1.12356 + //! Operator*=. 1.12357 +#ifdef cimg_use_visualcpp6 1.12358 + CImg<T>& operator*=(const double val) 1.12359 +#else 1.12360 + template<typename t> 1.12361 + CImg<T>& operator*=(const t val) 1.12362 +#endif 1.12363 + { 1.12364 + cimg_for(*this,ptr,T) (*ptr) = (T)((*ptr)*val); 1.12365 + return *this; 1.12366 + } 1.12367 + 1.12368 + //! Operator*=. 1.12369 + template<typename t> 1.12370 + CImg<T>& operator*=(const CImg<t>& img) { 1.12371 + return ((*this)*img).transfer_to(*this); 1.12372 + } 1.12373 + 1.12374 + //! Operator/=. 1.12375 +#ifdef cimg_use_visualcpp6 1.12376 + CImg<T>& operator/=(const double val) 1.12377 +#else 1.12378 + template<typename t> 1.12379 + CImg<T>& operator/=(const t val) 1.12380 +#endif 1.12381 + { 1.12382 + cimg_for(*this,ptr,T) (*ptr) = (T)((*ptr)/val); 1.12383 + return *this; 1.12384 + } 1.12385 + 1.12386 + //! Operator/=. 1.12387 + template<typename t> 1.12388 + CImg<T>& operator/=(const CImg<t>& img) { 1.12389 + return assign(*this*img.get_invert()); 1.12390 + } 1.12391 + 1.12392 + //! Modulo. 1.12393 + template<typename t> 1.12394 + CImg<typename cimg::superset<T,t>::type> operator%(const CImg<t>& img) const { 1.12395 + typedef typename cimg::superset<T,t>::type Tt; 1.12396 + return CImg<Tt>(*this,false)%=img; 1.12397 + } 1.12398 + 1.12399 + //! Modulo. 1.12400 + CImg<T> operator%(const T val) const { 1.12401 + return (+*this)%=val; 1.12402 + } 1.12403 + 1.12404 + //! In-place modulo. 1.12405 + CImg<T>& operator%=(const T val) { 1.12406 + cimg_for(*this,ptr,T) (*ptr) = (T)cimg::mod(*ptr,val); 1.12407 + return *this; 1.12408 + } 1.12409 + 1.12410 + //! In-place modulo. 1.12411 + template<typename t> 1.12412 + CImg<T>& operator%=(const CImg<t>& img) { 1.12413 + if (is_overlapped(img)) return *this%=+img; 1.12414 + typedef typename cimg::superset<T,t>::type Tt; 1.12415 + const unsigned int smin = cimg::min(size(),img.size()); 1.12416 + const t *ptrs = img.data + smin; 1.12417 + for (T *ptrd = data + smin; ptrd>data; ) { 1.12418 + T& val = *(--ptrd); 1.12419 + val = (T)cimg::mod((Tt)val,(Tt)*(--ptrs)); 1.12420 + } 1.12421 + return *this; 1.12422 + } 1.12423 + 1.12424 + //! Bitwise AND. 1.12425 + template<typename t> 1.12426 + CImg<typename cimg::superset<T,t>::type> operator&(const CImg<t>& img) const { 1.12427 + typedef typename cimg::superset<T,t>::type Tt; 1.12428 + return CImg<Tt>(*this,false)&=img; 1.12429 + } 1.12430 + 1.12431 + //! Bitwise AND. 1.12432 + CImg<T> operator&(const T val) const { 1.12433 + return (+*this)&=val; 1.12434 + } 1.12435 + 1.12436 + //! In-place bitwise AND. 1.12437 + template<typename t> 1.12438 + CImg<T>& operator&=(const CImg<t>& img) { 1.12439 + if (is_overlapped(img)) return *this&=+img; 1.12440 + const unsigned int smin = cimg::min(size(),img.size()); 1.12441 + const t *ptrs = img.data + smin; 1.12442 + for (T *ptrd = data + smin; ptrd>data; ) { 1.12443 + T& val = *(--ptrd); 1.12444 + val = (T)((unsigned long)val & (unsigned long)*(--ptrs)); 1.12445 + } 1.12446 + return *this; 1.12447 + } 1.12448 + 1.12449 + //! In-place bitwise AND. 1.12450 + CImg<T>& operator&=(const T val) { 1.12451 + cimg_for(*this,ptr,T) *ptr = (T)((unsigned long)*ptr & (unsigned long)val); 1.12452 + return *this; 1.12453 + } 1.12454 + 1.12455 + //! Bitwise OR. 1.12456 + template<typename t> 1.12457 + CImg<typename cimg::superset<T,t>::type> operator|(const CImg<t>& img) const { 1.12458 + typedef typename cimg::superset<T,t>::type Tt; 1.12459 + return CImg<Tt>(*this,false)|=img; 1.12460 + } 1.12461 + 1.12462 + //! Bitwise OR. 1.12463 + CImg<T> operator|(const T val) const { 1.12464 + return (+*this)|=val; 1.12465 + } 1.12466 + 1.12467 + //! In-place bitwise OR. 1.12468 + template<typename t> 1.12469 + CImg<T>& operator|=(const CImg<t>& img) { 1.12470 + if (is_overlapped(img)) return *this|=+img; 1.12471 + const unsigned int smin = cimg::min(size(),img.size()); 1.12472 + const t *ptrs = img.data + smin; 1.12473 + for (T *ptrd = data + smin; ptrd>data; ) { 1.12474 + T& val = *(--ptrd); 1.12475 + val = (T)((unsigned long)val | (unsigned long)*(--ptrs)); 1.12476 + } 1.12477 + return *this; 1.12478 + } 1.12479 + 1.12480 + //! In-place bitwise OR. 1.12481 + CImg<T>& operator|=(const T val) { 1.12482 + cimg_for(*this,ptr,T) *ptr = (T)((unsigned long)*ptr | (unsigned long)val); 1.12483 + return *this; 1.12484 + } 1.12485 + 1.12486 + //! Bitwise XOR. 1.12487 + template<typename t> 1.12488 + CImg<typename cimg::superset<T,t>::type> operator^(const CImg<t>& img) const { 1.12489 + typedef typename cimg::superset<T,t>::type Tt; 1.12490 + return CImg<Tt>(*this,false)^=img; 1.12491 + } 1.12492 + 1.12493 + //! Bitwise XOR. 1.12494 + CImg<T> operator^(const T val) const { 1.12495 + return (+*this)^=val; 1.12496 + } 1.12497 + 1.12498 + //! In-place bitwise XOR. 1.12499 + template<typename t> 1.12500 + CImg<T>& operator^=(const CImg<t>& img) { 1.12501 + if (is_overlapped(img)) return *this^=+img; 1.12502 + const unsigned int smin = cimg::min(size(),img.size()); 1.12503 + const t *ptrs = img.data + smin; 1.12504 + for (T *ptrd = data+smin; ptrd>data; ) { 1.12505 + T& val = *(--ptrd); 1.12506 + val =(T)((unsigned long)val ^ (unsigned long)*(--ptrs)); 1.12507 + } 1.12508 + return *this; 1.12509 + } 1.12510 + 1.12511 + //! In-place bitwise XOR. 1.12512 + CImg<T>& operator^=(const T val) { 1.12513 + cimg_for(*this,ptr,T) *ptr = (T)((unsigned long)*ptr ^ (unsigned long)val); 1.12514 + return *this; 1.12515 + } 1.12516 + 1.12517 + //! Bitwise NOT. 1.12518 + CImg<T> operator~() const { 1.12519 + CImg<T> res(width,height,depth,dim); 1.12520 + const T *ptrs = end(); 1.12521 + cimg_for(res,ptrd,T) { const unsigned long val = (unsigned long)*(--ptrs); *ptrd = (T)~val; } 1.12522 + return res; 1.12523 + } 1.12524 + 1.12525 + //! Bitwise left shift. 1.12526 + CImg<T>& operator<<=(const int n) { 1.12527 + cimg_for(*this,ptr,T) *ptr = (T)(((long)*ptr)<<n); 1.12528 + return *this; 1.12529 + } 1.12530 + 1.12531 + //! Bitwise left shift. 1.12532 + CImg<T> operator<<(const int n) const { 1.12533 + return (+*this)<<=n; 1.12534 + } 1.12535 + 1.12536 + //! Bitwise right shift. 1.12537 + CImg<T>& operator>>=(const int n) { 1.12538 + cimg_for(*this,ptr,T) *ptr = (T)(((long)*ptr)>>n); 1.12539 + return *this; 1.12540 + } 1.12541 + 1.12542 + //! Bitwise right shift. 1.12543 + CImg<T> operator>>(const int n) const { 1.12544 + return (+*this)>>=n; 1.12545 + } 1.12546 + 1.12547 + //! Boolean equality. 1.12548 + template<typename t> 1.12549 + bool operator==(const CImg<t>& img) const { 1.12550 + const unsigned int siz = size(); 1.12551 + bool vequal = true; 1.12552 + if (siz!=img.size()) return false; 1.12553 + t *ptrs = img.data + siz; 1.12554 + for (T *ptrd = data + siz; vequal && ptrd>data; vequal = vequal && ((*(--ptrd))==(*(--ptrs)))) {} 1.12555 + return vequal; 1.12556 + } 1.12557 + 1.12558 + //! Boolean difference. 1.12559 + template<typename t> 1.12560 + bool operator!=(const CImg<t>& img) const { 1.12561 + return !((*this)==img); 1.12562 + } 1.12563 + 1.12564 + //! Return a list of two images { *this, img }. 1.12565 + template<typename t> 1.12566 + CImgList<typename cimg::superset<T,t>::type> operator<<(const CImg<t>& img) const { 1.12567 + typedef typename cimg::superset<T,t>::type Tt; 1.12568 + return CImgList<Tt>(*this,img); 1.12569 + } 1.12570 + 1.12571 + //! Return a copy of \p list, where image *this has been inserted at first position. 1.12572 + template<typename t> 1.12573 + CImgList<typename cimg::superset<T,t>::type> operator<<(const CImgList<t>& list) const { 1.12574 + typedef typename cimg::superset<T,t>::type Tt; 1.12575 + return CImgList<Tt>(list).insert(*this,0); 1.12576 + } 1.12577 + 1.12578 + //! Return a list of two images { *this, img }. 1.12579 + template<typename t> 1.12580 + CImgList<typename cimg::superset<T,t>::type> operator>>(const CImg<t>& img) const { 1.12581 + return (*this)<<img; 1.12582 + } 1.12583 + 1.12584 + //! Insert an image into the begining of an image list. 1.12585 + template<typename t> 1.12586 + CImgList<t>& operator>>(const CImgList<t>& list) const { 1.12587 + return list.insert(*this,0); 1.12588 + } 1.12589 + 1.12590 + //! Display an image into a CImgDisplay. 1.12591 + const CImg<T>& operator>>(CImgDisplay& disp) const { 1.12592 + return display(disp); 1.12593 + } 1.12594 + 1.12595 + //@} 1.12596 + //--------------------------------------- 1.12597 + // 1.12598 + //! \name Usual Mathematics Functions 1.12599 + //@{ 1.12600 + //--------------------------------------- 1.12601 + 1.12602 + //! Apply a R->R function on all pixel values. 1.12603 + template<typename t> 1.12604 + CImg<T>& apply(t& func) { 1.12605 + cimg_for(*this,ptr,T) *ptr = func(*ptr); 1.12606 + return *this; 1.12607 + } 1.12608 + 1.12609 + template<typename t> 1.12610 + CImg<T> get_apply(t& func) const { 1.12611 + return (+*this).apply(func); 1.12612 + } 1.12613 + 1.12614 + //! Pointwise multiplication between two images. 1.12615 + template<typename t> 1.12616 + CImg<T>& mul(const CImg<t>& img) { 1.12617 + if (is_overlapped(img)) return mul(+img); 1.12618 + t *ptrs = img.data; 1.12619 + T *ptrf = data + cimg::min(size(),img.size()); 1.12620 + for (T* ptrd = data; ptrd<ptrf; ++ptrd) (*ptrd) = (T)(*ptrd*(*(ptrs++))); 1.12621 + return *this; 1.12622 + } 1.12623 + 1.12624 + template<typename t> 1.12625 + CImg<typename cimg::superset<T,t>::type> get_mul(const CImg<t>& img) const { 1.12626 + typedef typename cimg::superset<T,t>::type Tt; 1.12627 + return CImg<Tt>(*this,false).mul(img); 1.12628 + } 1.12629 + 1.12630 + //! Pointwise division between two images. 1.12631 + template<typename t> 1.12632 + CImg<T>& div(const CImg<t>& img) { 1.12633 + if (is_overlapped(img)) return div(+img); 1.12634 + t *ptrs = img.data; 1.12635 + T *ptrf = data + cimg::min(size(),img.size()); 1.12636 + for (T* ptrd = data; ptrd<ptrf; ++ptrd) (*ptrd) = (T)(*ptrd/(*(ptrs++))); 1.12637 + return *this; 1.12638 + } 1.12639 + 1.12640 + template<typename t> 1.12641 + CImg<typename cimg::superset<T,t>::type> get_div(const CImg<t>& img) const { 1.12642 + typedef typename cimg::superset<T,t>::type Tt; 1.12643 + return CImg<Tt>(*this,false).div(img); 1.12644 + } 1.12645 + 1.12646 + //! Pointwise max operator between two images. 1.12647 + template<typename t> 1.12648 + CImg<T>& max(const CImg<t>& img) { 1.12649 + if (is_overlapped(img)) return max(+img); 1.12650 + t *ptrs = img.data; 1.12651 + T *ptrf = data + cimg::min(size(),img.size()); 1.12652 + for (T* ptrd = data; ptrd<ptrf; ++ptrd) (*ptrd) = cimg::max((T)*(ptrs++),*ptrd); 1.12653 + return *this; 1.12654 + } 1.12655 + 1.12656 + template<typename t> 1.12657 + CImg<typename cimg::superset<T,t>::type> get_max(const CImg<t>& img) const { 1.12658 + typedef typename cimg::superset<T,t>::type Tt; 1.12659 + return CImg<Tt>(*this,false).max(img); 1.12660 + } 1.12661 + 1.12662 + //! Pointwise max operator between an image and a value. 1.12663 + CImg<T>& max(const T val) { 1.12664 + cimg_for(*this,ptr,T) (*ptr) = cimg::max(*ptr,val); 1.12665 + return *this; 1.12666 + } 1.12667 + 1.12668 + CImg<T> get_max(const T val) const { 1.12669 + return (+*this).max(val); 1.12670 + } 1.12671 + 1.12672 + //! Pointwise min operator between two images. 1.12673 + template<typename t> 1.12674 + CImg<T>& min(const CImg<t>& img) { 1.12675 + if (is_overlapped(img)) return min(+img); 1.12676 + t *ptrs = img.data; 1.12677 + T *ptrf = data + cimg::min(size(),img.size()); 1.12678 + for (T* ptrd = data; ptrd<ptrf; ++ptrd) (*ptrd) = cimg::min((T)*(ptrs++),*ptrd); 1.12679 + return *this; 1.12680 + } 1.12681 + 1.12682 + template<typename t> 1.12683 + CImg<typename cimg::superset<T,t>::type> get_min(const CImg<t>& img) const { 1.12684 + typedef typename cimg::superset<T,t>::type Tt; 1.12685 + return CImg<Tt>(*this,false).min(img); 1.12686 + } 1.12687 + 1.12688 + //! Pointwise min operator between an image and a value. 1.12689 + CImg<T>& min(const T val) { 1.12690 + cimg_for(*this,ptr,T) (*ptr) = cimg::min(*ptr,val); 1.12691 + return *this; 1.12692 + } 1.12693 + 1.12694 + CImg<T> get_min(const T val) const { 1.12695 + return (+*this).min(val); 1.12696 + } 1.12697 + 1.12698 + //! Compute the square value of each pixel. 1.12699 + CImg<T>& sqr() { 1.12700 + cimg_for(*this,ptr,T) { const T val = *ptr; *ptr = (T)(val*val); }; 1.12701 + return *this; 1.12702 + } 1.12703 + 1.12704 + CImg<Tfloat> get_sqr() const { 1.12705 + return CImg<Tfloat>(*this,false).sqr(); 1.12706 + } 1.12707 + 1.12708 + //! Compute the square root of each pixel value. 1.12709 + CImg<T>& sqrt() { 1.12710 + cimg_for(*this,ptr,T) (*ptr) = (T)cimg_std::sqrt((double)(*ptr)); 1.12711 + return *this; 1.12712 + } 1.12713 + 1.12714 + CImg<Tfloat> get_sqrt() const { 1.12715 + return CImg<Tfloat>(*this,false).sqrt(); 1.12716 + } 1.12717 + 1.12718 + //! Compute the exponential of each pixel value. 1.12719 + CImg<T>& exp() { 1.12720 + cimg_for(*this,ptr,T) (*ptr) = (T)cimg_std::exp((double)(*ptr)); 1.12721 + return *this; 1.12722 + } 1.12723 + 1.12724 + CImg<Tfloat> get_exp() const { 1.12725 + return CImg<Tfloat>(*this,false).exp(); 1.12726 + } 1.12727 + 1.12728 + //! Compute the log of each each pixel value. 1.12729 + CImg<T>& log() { 1.12730 + cimg_for(*this,ptr,T) (*ptr) = (T)cimg_std::log((double)(*ptr)); 1.12731 + return *this; 1.12732 + } 1.12733 + 1.12734 + CImg<Tfloat> get_log() const { 1.12735 + return CImg<Tfloat>(*this,false).log(); 1.12736 + } 1.12737 + 1.12738 + //! Compute the log10 of each each pixel value. 1.12739 + CImg<T>& log10() { 1.12740 + cimg_for(*this,ptr,T) (*ptr) = (T)cimg_std::log10((double)(*ptr)); 1.12741 + return *this; 1.12742 + } 1.12743 + 1.12744 + CImg<Tfloat> get_log10() const { 1.12745 + return CImg<Tfloat>(*this,false).log10(); 1.12746 + } 1.12747 + 1.12748 + //! Compute the power by p of each pixel value. 1.12749 + CImg<T>& pow(const double p) { 1.12750 + if (p==0) return fill(1); 1.12751 + if (p==0.5) { cimg_for(*this,ptr,T) { const T val = *ptr; *ptr = (T)cimg_std::sqrt((double)val); } return *this; } 1.12752 + if (p==1) return *this; 1.12753 + if (p==2) { cimg_for(*this,ptr,T) { const T val = *ptr; *ptr = val*val; } return *this; } 1.12754 + if (p==3) { cimg_for(*this,ptr,T) { const T val = *ptr; *ptr = val*val*val; } return *this; } 1.12755 + if (p==4) { cimg_for(*this,ptr,T) { const T val = *ptr; *ptr = val*val*val*val; } return *this; } 1.12756 + cimg_for(*this,ptr,T) (*ptr) = (T)cimg_std::pow((double)(*ptr),p); 1.12757 + return *this; 1.12758 + } 1.12759 + 1.12760 + CImg<Tfloat> get_pow(const double p) const { 1.12761 + return CImg<Tfloat>(*this,false).pow(p); 1.12762 + } 1.12763 + 1.12764 + //! Compute the power of each pixel value. 1.12765 + template<typename t> 1.12766 + CImg<T>& pow(const CImg<t>& img) { 1.12767 + if (is_overlapped(img)) return pow(+img); 1.12768 + t *ptrs = img.data; 1.12769 + T *ptrf = data + cimg::min(size(),img.size()); 1.12770 + for (T* ptrd = data; ptrd<ptrf; ++ptrd) (*ptrd) = (T)cimg_std::pow((double)*ptrd,(double)(*(ptrs++))); 1.12771 + return *this; 1.12772 + } 1.12773 + 1.12774 + template<typename t> 1.12775 + CImg<Tfloat> get_pow(const CImg<t>& img) const { 1.12776 + return CImg<Tfloat>(*this,false).pow(img); 1.12777 + } 1.12778 + 1.12779 + //! Compute the absolute value of each pixel value. 1.12780 + CImg<T>& abs() { 1.12781 + cimg_for(*this,ptr,T) (*ptr) = cimg::abs(*ptr); 1.12782 + return *this; 1.12783 + } 1.12784 + 1.12785 + CImg<Tfloat> get_abs() const { 1.12786 + return CImg<Tfloat>(*this,false).abs(); 1.12787 + } 1.12788 + 1.12789 + //! Compute the cosinus of each pixel value. 1.12790 + CImg<T>& cos() { 1.12791 + cimg_for(*this,ptr,T) (*ptr) = (T)cimg_std::cos((double)(*ptr)); 1.12792 + return *this; 1.12793 + } 1.12794 + 1.12795 + CImg<Tfloat> get_cos() const { 1.12796 + return CImg<Tfloat>(*this,false).cos(); 1.12797 + } 1.12798 + 1.12799 + //! Compute the sinus of each pixel value. 1.12800 + CImg<T>& sin() { 1.12801 + cimg_for(*this,ptr,T) (*ptr) = (T)cimg_std::sin((double)(*ptr)); 1.12802 + return *this; 1.12803 + } 1.12804 + 1.12805 + CImg<Tfloat> get_sin() const { 1.12806 + return CImg<Tfloat>(*this,false).sin(); 1.12807 + } 1.12808 + 1.12809 + //! Compute the tangent of each pixel. 1.12810 + CImg<T>& tan() { 1.12811 + cimg_for(*this,ptr,T) (*ptr) = (T)cimg_std::tan((double)(*ptr)); 1.12812 + return *this; 1.12813 + } 1.12814 + 1.12815 + CImg<Tfloat> get_tan() const { 1.12816 + return CImg<Tfloat>(*this,false).tan(); 1.12817 + } 1.12818 + 1.12819 + //! Compute the arc-cosine of each pixel value. 1.12820 + CImg<T>& acos() { 1.12821 + cimg_for(*this,ptr,T) (*ptr) = (T)cimg_std::acos((double)(*ptr)); 1.12822 + return *this; 1.12823 + } 1.12824 + 1.12825 + CImg<Tfloat> get_acos() const { 1.12826 + return CImg<Tfloat>(*this,false).acos(); 1.12827 + } 1.12828 + 1.12829 + //! Compute the arc-sinus of each pixel value. 1.12830 + CImg<T>& asin() { 1.12831 + cimg_for(*this,ptr,T) (*ptr) = (T)cimg_std::asin((double)(*ptr)); 1.12832 + return *this; 1.12833 + } 1.12834 + 1.12835 + CImg<Tfloat> get_asin() const { 1.12836 + return CImg<Tfloat>(*this,false).asin(); 1.12837 + } 1.12838 + 1.12839 + //! Compute the arc-tangent of each pixel. 1.12840 + CImg<T>& atan() { 1.12841 + cimg_for(*this,ptr,T) (*ptr) = (T)cimg_std::atan((double)(*ptr)); 1.12842 + return *this; 1.12843 + } 1.12844 + 1.12845 + CImg<Tfloat> get_atan() const { 1.12846 + return CImg<Tfloat>(*this,false).atan(); 1.12847 + } 1.12848 + 1.12849 + //! Compute image with rounded pixel values. 1.12850 + /** 1.12851 + \param x Rounding precision. 1.12852 + \param rounding_type Roundin type, can be 0 (nearest), 1 (forward), -1(backward). 1.12853 + **/ 1.12854 + CImg<T>& round(const float x, const int rounding_type=0) { 1.12855 + cimg_for(*this,ptr,T) (*ptr) = (T)cimg::round(*ptr,x,rounding_type); 1.12856 + return *this; 1.12857 + } 1.12858 + 1.12859 + CImg<T> get_round(const float x, const unsigned int rounding_type=0) const { 1.12860 + return (+*this).round(x,rounding_type); 1.12861 + } 1.12862 + 1.12863 + //! Fill the instance image with random values between specified range. 1.12864 + CImg<T>& rand(const T val_min, const T val_max) { 1.12865 + const float delta = (float)val_max - (float)val_min; 1.12866 + cimg_for(*this,ptr,T) *ptr = (T)(val_min + cimg::rand()*delta); 1.12867 + return *this; 1.12868 + } 1.12869 + 1.12870 + CImg<T> get_rand(const T val_min, const T val_max) const { 1.12871 + return (+*this).rand(val_min,val_max); 1.12872 + } 1.12873 + 1.12874 + //@} 1.12875 + //----------------------------------- 1.12876 + // 1.12877 + //! \name Usual Image Transformations 1.12878 + //@{ 1.12879 + //----------------------------------- 1.12880 + 1.12881 + //! Fill an image by a value \p val. 1.12882 + /** 1.12883 + \param val = fill value 1.12884 + \note All pixel values of the instance image will be initialized by \p val. 1.12885 + **/ 1.12886 + CImg<T>& fill(const T val) { 1.12887 + if (is_empty()) return *this; 1.12888 + if (val && sizeof(T)!=1) cimg_for(*this,ptr,T) *ptr = val; 1.12889 + else cimg_std::memset(data,(int)val,size()*sizeof(T)); 1.12890 + return *this; 1.12891 + } 1.12892 + 1.12893 + CImg<T> get_fill(const T val) const { 1.12894 + return CImg<T>(width,height,depth,dim).fill(val); 1.12895 + } 1.12896 + 1.12897 + //! Fill sequentially all pixel values with values \a val0 and \a val1 respectively. 1.12898 + CImg<T>& fill(const T val0, const T val1) { 1.12899 + if (is_empty()) return *this; 1.12900 + T *ptr, *ptr_end = end()-1; 1.12901 + for (ptr = data; ptr<ptr_end; ) { *(ptr++) = val0; *(ptr++) = val1; } 1.12902 + if (ptr!=ptr_end+1) *(ptr++) = val0; 1.12903 + return *this; 1.12904 + } 1.12905 + 1.12906 + CImg<T> get_fill(const T val0, const T val1) const { 1.12907 + return CImg<T>(width,height,depth,dim).fill(val0,val1); 1.12908 + } 1.12909 + 1.12910 + //! Fill sequentially all pixel values with values \a val0 and \a val1 and \a val2. 1.12911 + CImg<T>& fill(const T val0, const T val1, const T val2) { 1.12912 + if (is_empty()) return *this; 1.12913 + T *ptr, *ptr_end = end()-2; 1.12914 + for (ptr = data; ptr<ptr_end; ) { *(ptr++) = val0; *(ptr++) = val1; *(ptr++) = val2; } 1.12915 + ptr_end+=2; 1.12916 + switch (ptr_end-ptr) { 1.12917 + case 2 : *(--ptr_end) = val1; 1.12918 + case 1 : *(--ptr_end) = val0; 1.12919 + } 1.12920 + return *this; 1.12921 + } 1.12922 + 1.12923 + CImg<T> get_fill(const T val0, const T val1, const T val2) const { 1.12924 + return CImg<T>(width,height,depth,dim).fill(val0,val1,val2); 1.12925 + } 1.12926 + 1.12927 + //! Fill sequentially all pixel values with values \a val0 and \a val1 and \a val2 and \a val3. 1.12928 + CImg<T>& fill(const T val0, const T val1, const T val2, const T val3) { 1.12929 + if (is_empty()) return *this; 1.12930 + T *ptr, *ptr_end = end()-3; 1.12931 + for (ptr = data; ptr<ptr_end; ) { *(ptr++) = val0; *(ptr++) = val1; *(ptr++) = val2; *(ptr++) = val3; } 1.12932 + ptr_end+=3; 1.12933 + switch (ptr_end-ptr) { 1.12934 + case 3 : *(--ptr_end) = val2; 1.12935 + case 2 : *(--ptr_end) = val1; 1.12936 + case 1 : *(--ptr_end) = val0; 1.12937 + } 1.12938 + return *this; 1.12939 + } 1.12940 + 1.12941 + CImg<T> get_fill(const T val0, const T val1, const T val2, const T val3) const { 1.12942 + return CImg<T>(width,height,depth,dim).fill(val0,val1,val2,val3); 1.12943 + } 1.12944 + 1.12945 + //! Fill sequentially all pixel values with values \a val0 and \a val1 and \a val2 and \a val3 and \a val4. 1.12946 + CImg<T>& fill(const T val0, const T val1, const T val2, const T val3, const T val4) { 1.12947 + if (is_empty()) return *this; 1.12948 + T *ptr, *ptr_end = end()-4; 1.12949 + for (ptr = data; ptr<ptr_end; ) { *(ptr++) = val0; *(ptr++) = val1; *(ptr++) = val2; *(ptr++) = val3; *(ptr++) = val4; } 1.12950 + ptr_end+=4; 1.12951 + switch (ptr_end-ptr) { 1.12952 + case 4 : *(--ptr_end) = val3; 1.12953 + case 3 : *(--ptr_end) = val2; 1.12954 + case 2 : *(--ptr_end) = val1; 1.12955 + case 1 : *(--ptr_end) = val0; 1.12956 + } 1.12957 + return *this; 1.12958 + } 1.12959 + 1.12960 + CImg<T> get_fill(const T val0, const T val1, const T val2, const T val3, const T val4) const { 1.12961 + return CImg<T>(width,height,depth,dim).fill(val0,val1,val2,val3,val4); 1.12962 + } 1.12963 + 1.12964 + //! Fill sequentially all pixel values with values \a val0 and \a val1 and \a val2 and \a val3 and \a val4 and \a val5. 1.12965 + CImg<T>& fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5) { 1.12966 + if (is_empty()) return *this; 1.12967 + T *ptr, *ptr_end = end()-5; 1.12968 + for (ptr = data; ptr<ptr_end; ) { 1.12969 + *(ptr++) = val0; *(ptr++) = val1; *(ptr++) = val2; *(ptr++) = val3; *(ptr++) = val4; *(ptr++) = val5; 1.12970 + } 1.12971 + ptr_end+=5; 1.12972 + switch (ptr_end-ptr) { 1.12973 + case 5 : *(--ptr_end) = val4; 1.12974 + case 4 : *(--ptr_end) = val3; 1.12975 + case 3 : *(--ptr_end) = val2; 1.12976 + case 2 : *(--ptr_end) = val1; 1.12977 + case 1 : *(--ptr_end) = val0; 1.12978 + } 1.12979 + return *this; 1.12980 + } 1.12981 + 1.12982 + CImg<T> get_fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5) const { 1.12983 + return CImg<T>(width,height,depth,dim).fill(val0,val1,val2,val3,val4,val5); 1.12984 + } 1.12985 + 1.12986 + //! Fill sequentially pixel values. 1.12987 + CImg<T>& fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6) { 1.12988 + if (is_empty()) return *this; 1.12989 + T *ptr, *ptr_end = end()-6; 1.12990 + for (ptr = data; ptr<ptr_end; ) { 1.12991 + *(ptr++) = val0; *(ptr++) = val1; *(ptr++) = val2; *(ptr++) = val3; *(ptr++) = val4; *(ptr++) = val5; *(ptr++) = val6; 1.12992 + } 1.12993 + ptr_end+=6; 1.12994 + switch (ptr_end-ptr) { 1.12995 + case 6 : *(--ptr_end) = val5; 1.12996 + case 5 : *(--ptr_end) = val4; 1.12997 + case 4 : *(--ptr_end) = val3; 1.12998 + case 3 : *(--ptr_end) = val2; 1.12999 + case 2 : *(--ptr_end) = val1; 1.13000 + case 1 : *(--ptr_end) = val0; 1.13001 + } 1.13002 + return *this; 1.13003 + } 1.13004 + 1.13005 + CImg<T> get_fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6) const { 1.13006 + return CImg<T>(width,height,depth,dim).fill(val0,val1,val2,val3,val4,val5,val6); 1.13007 + } 1.13008 + 1.13009 + //! Fill sequentially pixel values. 1.13010 + CImg<T>& fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13011 + const T val7) { 1.13012 + if (is_empty()) return *this; 1.13013 + T *ptr, *ptr_end = end()-7; 1.13014 + for (ptr = data; ptr<ptr_end; ) { 1.13015 + *(ptr++) = val0; *(ptr++) = val1; *(ptr++) = val2; *(ptr++) = val3; 1.13016 + *(ptr++) = val4; *(ptr++) = val5; *(ptr++) = val6; *(ptr++) = val7; 1.13017 + } 1.13018 + ptr_end+=7; 1.13019 + switch (ptr_end-ptr) { 1.13020 + case 7 : *(--ptr_end) = val6; 1.13021 + case 6 : *(--ptr_end) = val5; 1.13022 + case 5 : *(--ptr_end) = val4; 1.13023 + case 4 : *(--ptr_end) = val3; 1.13024 + case 3 : *(--ptr_end) = val2; 1.13025 + case 2 : *(--ptr_end) = val1; 1.13026 + case 1 : *(--ptr_end) = val0; 1.13027 + } 1.13028 + return *this; 1.13029 + } 1.13030 + 1.13031 + CImg<T> get_fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13032 + const T val7) const { 1.13033 + return CImg<T>(width,height,depth,dim).fill(val0,val1,val2,val3,val4,val5,val6,val7); 1.13034 + } 1.13035 + 1.13036 + //! Fill sequentially pixel values. 1.13037 + CImg<T>& fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13038 + const T val7, const T val8) { 1.13039 + if (is_empty()) return *this; 1.13040 + T *ptr, *ptr_end = end()-8; 1.13041 + for (ptr = data; ptr<ptr_end; ) { 1.13042 + *(ptr++) = val0; *(ptr++) = val1; *(ptr++) = val2; 1.13043 + *(ptr++) = val3; *(ptr++) = val4; *(ptr++) = val5; 1.13044 + *(ptr++) = val6; *(ptr++) = val7; *(ptr++) = val8; 1.13045 + } 1.13046 + ptr_end+=8; 1.13047 + switch (ptr_end-ptr) { 1.13048 + case 8 : *(--ptr_end) = val7; 1.13049 + case 7 : *(--ptr_end) = val6; 1.13050 + case 6 : *(--ptr_end) = val5; 1.13051 + case 5 : *(--ptr_end) = val4; 1.13052 + case 4 : *(--ptr_end) = val3; 1.13053 + case 3 : *(--ptr_end) = val2; 1.13054 + case 2 : *(--ptr_end) = val1; 1.13055 + case 1 : *(--ptr_end) = val0; 1.13056 + } 1.13057 + return *this; 1.13058 + } 1.13059 + 1.13060 + CImg<T> get_fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13061 + const T val7, const T val8) const { 1.13062 + return CImg<T>(width,height,depth,dim).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8); 1.13063 + } 1.13064 + 1.13065 + //! Fill sequentially pixel values. 1.13066 + CImg<T>& fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13067 + const T val7, const T val8, const T val9) { 1.13068 + if (is_empty()) return *this; 1.13069 + T *ptr, *ptr_end = end()-9; 1.13070 + for (ptr = data; ptr<ptr_end; ) { 1.13071 + *(ptr++) = val0; *(ptr++) = val1; *(ptr++) = val2; *(ptr++) = val3; *(ptr++) = val4; 1.13072 + *(ptr++) = val5; *(ptr++) = val6; *(ptr++) = val7; *(ptr++) = val8; *(ptr++) = val9; 1.13073 + } 1.13074 + ptr_end+=9; 1.13075 + switch (ptr_end-ptr) { 1.13076 + case 9 : *(--ptr_end) = val8; 1.13077 + case 8 : *(--ptr_end) = val7; 1.13078 + case 7 : *(--ptr_end) = val6; 1.13079 + case 6 : *(--ptr_end) = val5; 1.13080 + case 5 : *(--ptr_end) = val4; 1.13081 + case 4 : *(--ptr_end) = val3; 1.13082 + case 3 : *(--ptr_end) = val2; 1.13083 + case 2 : *(--ptr_end) = val1; 1.13084 + case 1 : *(--ptr_end) = val0; 1.13085 + } 1.13086 + return *this; 1.13087 + } 1.13088 + 1.13089 + CImg<T> get_fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13090 + const T val7, const T val8, const T val9) const { 1.13091 + return CImg<T>(width,height,depth,dim).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9); 1.13092 + } 1.13093 + 1.13094 + //! Fill sequentially pixel values. 1.13095 + CImg<T>& fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13096 + const T val7, const T val8, const T val9, const T val10) { 1.13097 + if (is_empty()) return *this; 1.13098 + T *ptr, *ptr_end = end()-10; 1.13099 + for (ptr = data; ptr<ptr_end; ) { 1.13100 + *(ptr++) = val0; *(ptr++) = val1; *(ptr++) = val2; *(ptr++) = val3; *(ptr++) = val4; 1.13101 + *(ptr++) = val5; *(ptr++) = val6; *(ptr++) = val7; *(ptr++) = val8; *(ptr++) = val9; 1.13102 + *(ptr++) = val10; 1.13103 + } 1.13104 + ptr_end+=10; 1.13105 + switch (ptr_end-ptr) { 1.13106 + case 10 : *(--ptr_end) = val9; 1.13107 + case 9 : *(--ptr_end) = val8; 1.13108 + case 8 : *(--ptr_end) = val7; 1.13109 + case 7 : *(--ptr_end) = val6; 1.13110 + case 6 : *(--ptr_end) = val5; 1.13111 + case 5 : *(--ptr_end) = val4; 1.13112 + case 4 : *(--ptr_end) = val3; 1.13113 + case 3 : *(--ptr_end) = val2; 1.13114 + case 2 : *(--ptr_end) = val1; 1.13115 + case 1 : *(--ptr_end) = val0; 1.13116 + } 1.13117 + return *this; 1.13118 + } 1.13119 + 1.13120 + CImg<T> get_fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13121 + const T val7, const T val8, const T val9, const T val10) const { 1.13122 + return CImg<T>(width,height,depth,dim).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10); 1.13123 + } 1.13124 + 1.13125 + //! Fill sequentially pixel values. 1.13126 + CImg<T>& fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13127 + const T val7, const T val8, const T val9, const T val10, const T val11) { 1.13128 + if (is_empty()) return *this; 1.13129 + T *ptr, *ptr_end = end()-11; 1.13130 + for (ptr = data; ptr<ptr_end; ) { 1.13131 + *(ptr++) = val0; *(ptr++) = val1; *(ptr++) = val2; *(ptr++) = val3; *(ptr++) = val4; *(ptr++) = val5; 1.13132 + *(ptr++) = val6; *(ptr++) = val7; *(ptr++) = val8; *(ptr++) = val9; *(ptr++) = val10; *(ptr++) = val11; 1.13133 + } 1.13134 + ptr_end+=11; 1.13135 + switch (ptr_end-ptr) { 1.13136 + case 11 : *(--ptr_end) = val10; 1.13137 + case 10 : *(--ptr_end) = val9; 1.13138 + case 9 : *(--ptr_end) = val8; 1.13139 + case 8 : *(--ptr_end) = val7; 1.13140 + case 7 : *(--ptr_end) = val6; 1.13141 + case 6 : *(--ptr_end) = val5; 1.13142 + case 5 : *(--ptr_end) = val4; 1.13143 + case 4 : *(--ptr_end) = val3; 1.13144 + case 3 : *(--ptr_end) = val2; 1.13145 + case 2 : *(--ptr_end) = val1; 1.13146 + case 1 : *(--ptr_end) = val0; 1.13147 + } 1.13148 + return *this; 1.13149 + } 1.13150 + 1.13151 + CImg<T> get_fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13152 + const T val7, const T val8, const T val9, const T val10, const T val11) const { 1.13153 + return CImg<T>(width,height,depth,dim).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,val11); 1.13154 + } 1.13155 + 1.13156 + //! Fill sequentially pixel values. 1.13157 + CImg<T>& fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13158 + const T val7, const T val8, const T val9, const T val10, const T val11, const T val12) { 1.13159 + if (is_empty()) return *this; 1.13160 + T *ptr, *ptr_end = end()-12; 1.13161 + for (ptr = data; ptr<ptr_end; ) { 1.13162 + *(ptr++) = val0; *(ptr++) = val1; *(ptr++) = val2; *(ptr++) = val3; *(ptr++) = val4; *(ptr++) = val5; 1.13163 + *(ptr++) = val6; *(ptr++) = val7; *(ptr++) = val8; *(ptr++) = val9; *(ptr++) = val10; *(ptr++) = val11; 1.13164 + *(ptr++) = val12; 1.13165 + } 1.13166 + ptr_end+=12; 1.13167 + switch (ptr_end-ptr) { 1.13168 + case 12 : *(--ptr_end) = val11; 1.13169 + case 11 : *(--ptr_end) = val10; 1.13170 + case 10 : *(--ptr_end) = val9; 1.13171 + case 9 : *(--ptr_end) = val8; 1.13172 + case 8 : *(--ptr_end) = val7; 1.13173 + case 7 : *(--ptr_end) = val6; 1.13174 + case 6 : *(--ptr_end) = val5; 1.13175 + case 5 : *(--ptr_end) = val4; 1.13176 + case 4 : *(--ptr_end) = val3; 1.13177 + case 3 : *(--ptr_end) = val2; 1.13178 + case 2 : *(--ptr_end) = val1; 1.13179 + case 1 : *(--ptr_end) = val0; 1.13180 + } 1.13181 + return *this; 1.13182 + } 1.13183 + 1.13184 + CImg<T> get_fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13185 + const T val7, const T val8, const T val9, const T val10, const T val11, const T val12) const { 1.13186 + return CImg<T>(width,height,depth,dim).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,val11,val12); 1.13187 + } 1.13188 + 1.13189 + //! Fill sequentially pixel values. 1.13190 + CImg<T>& fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13191 + const T val7, const T val8, const T val9, const T val10, const T val11, const T val12, 1.13192 + const T val13) { 1.13193 + if (is_empty()) return *this; 1.13194 + T *ptr, *ptr_end = end()-13; 1.13195 + for (ptr = data; ptr<ptr_end; ) { 1.13196 + *(ptr++) = val0; *(ptr++) = val1; *(ptr++) = val2; *(ptr++) = val3; *(ptr++) = val4; *(ptr++) = val5; 1.13197 + *(ptr++) = val6; *(ptr++) = val7; *(ptr++) = val8; *(ptr++) = val9; *(ptr++) = val10; *(ptr++) = val11; 1.13198 + *(ptr++) = val12; *(ptr++) = val13; 1.13199 + } 1.13200 + ptr_end+=13; 1.13201 + switch (ptr_end-ptr) { 1.13202 + case 13 : *(--ptr_end) = val12; 1.13203 + case 12 : *(--ptr_end) = val11; 1.13204 + case 11 : *(--ptr_end) = val10; 1.13205 + case 10 : *(--ptr_end) = val9; 1.13206 + case 9 : *(--ptr_end) = val8; 1.13207 + case 8 : *(--ptr_end) = val7; 1.13208 + case 7 : *(--ptr_end) = val6; 1.13209 + case 6 : *(--ptr_end) = val5; 1.13210 + case 5 : *(--ptr_end) = val4; 1.13211 + case 4 : *(--ptr_end) = val3; 1.13212 + case 3 : *(--ptr_end) = val2; 1.13213 + case 2 : *(--ptr_end) = val1; 1.13214 + case 1 : *(--ptr_end) = val0; 1.13215 + } 1.13216 + return *this; 1.13217 + } 1.13218 + 1.13219 + CImg<T> get_fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13220 + const T val7, const T val8, const T val9, const T val10, const T val11, const T val12, 1.13221 + const T val13) const { 1.13222 + return CImg<T>(width,height,depth,dim).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,val11,val12, 1.13223 + val13); 1.13224 + } 1.13225 + 1.13226 + //! Fill sequentially pixel values. 1.13227 + CImg<T>& fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13228 + const T val7, const T val8, const T val9, const T val10, const T val11, const T val12, 1.13229 + const T val13, const T val14) { 1.13230 + if (is_empty()) return *this; 1.13231 + T *ptr, *ptr_end = end()-14; 1.13232 + for (ptr = data; ptr<ptr_end; ) { 1.13233 + *(ptr++) = val0; *(ptr++) = val1; *(ptr++) = val2; *(ptr++) = val3; *(ptr++) = val4; *(ptr++) = val5; 1.13234 + *(ptr++) = val6; *(ptr++) = val7; *(ptr++) = val8; *(ptr++) = val9; *(ptr++) = val10; *(ptr++) = val11; 1.13235 + *(ptr++) = val12; *(ptr++) = val13; *(ptr++) = val14; 1.13236 + } 1.13237 + ptr_end+=14; 1.13238 + switch (ptr_end-ptr) { 1.13239 + case 14 : *(--ptr_end) = val13; 1.13240 + case 13 : *(--ptr_end) = val12; 1.13241 + case 12 : *(--ptr_end) = val11; 1.13242 + case 11 : *(--ptr_end) = val10; 1.13243 + case 10 : *(--ptr_end) = val9; 1.13244 + case 9 : *(--ptr_end) = val8; 1.13245 + case 8 : *(--ptr_end) = val7; 1.13246 + case 7 : *(--ptr_end) = val6; 1.13247 + case 6 : *(--ptr_end) = val5; 1.13248 + case 5 : *(--ptr_end) = val4; 1.13249 + case 4 : *(--ptr_end) = val3; 1.13250 + case 3 : *(--ptr_end) = val2; 1.13251 + case 2 : *(--ptr_end) = val1; 1.13252 + case 1 : *(--ptr_end) = val0; 1.13253 + } 1.13254 + return *this; 1.13255 + } 1.13256 + 1.13257 + CImg<T> get_fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13258 + const T val7, const T val8, const T val9, const T val10, const T val11, const T val12, 1.13259 + const T val13, const T val14) const { 1.13260 + return CImg<T>(width,height,depth,dim).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,val11,val12, 1.13261 + val13,val14); 1.13262 + } 1.13263 + 1.13264 + //! Fill sequentially pixel values. 1.13265 + CImg<T>& fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13266 + const T val7, const T val8, const T val9, const T val10, const T val11, const T val12, 1.13267 + const T val13, const T val14, const T val15) { 1.13268 + if (is_empty()) return *this; 1.13269 + T *ptr, *ptr_end = end()-15; 1.13270 + for (ptr = data; ptr<ptr_end; ) { 1.13271 + *(ptr++) = val0; *(ptr++) = val1; *(ptr++) = val2; *(ptr++) = val3; *(ptr++) = val4; *(ptr++) = val5; 1.13272 + *(ptr++) = val6; *(ptr++) = val7; *(ptr++) = val8; *(ptr++) = val9; *(ptr++) = val10; *(ptr++) = val11; 1.13273 + *(ptr++) = val12; *(ptr++) = val13; *(ptr++) = val14; *(ptr++) = val15; 1.13274 + } 1.13275 + ptr_end+=15; 1.13276 + switch (ptr_end-ptr) { 1.13277 + case 15 : *(--ptr_end) = val14; 1.13278 + case 14 : *(--ptr_end) = val13; 1.13279 + case 13 : *(--ptr_end) = val12; 1.13280 + case 12 : *(--ptr_end) = val11; 1.13281 + case 11 : *(--ptr_end) = val10; 1.13282 + case 10 : *(--ptr_end) = val9; 1.13283 + case 9 : *(--ptr_end) = val8; 1.13284 + case 8 : *(--ptr_end) = val7; 1.13285 + case 7 : *(--ptr_end) = val6; 1.13286 + case 6 : *(--ptr_end) = val5; 1.13287 + case 5 : *(--ptr_end) = val4; 1.13288 + case 4 : *(--ptr_end) = val3; 1.13289 + case 3 : *(--ptr_end) = val2; 1.13290 + case 2 : *(--ptr_end) = val1; 1.13291 + case 1 : *(--ptr_end) = val0; 1.13292 + } 1.13293 + return *this; 1.13294 + } 1.13295 + 1.13296 + CImg<T> get_fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, 1.13297 + const T val7, const T val8, const T val9, const T val10, const T val11, const T val12, 1.13298 + const T val13, const T val14, const T val15) const { 1.13299 + return CImg<T>(width,height,depth,dim).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,val11,val12, 1.13300 + val13,val14,val15); 1.13301 + } 1.13302 + 1.13303 + //! Fill image values according to the values found in the specified string. 1.13304 + CImg<T>& fill(const char *const values, const bool repeat_pattern) { 1.13305 + if (is_empty() || !values) return *this; 1.13306 + T *ptrd = data, *ptr_end = data + size(); 1.13307 + const char *nvalues = values; 1.13308 + const unsigned int siz = size(); 1.13309 + char cval[64] = { 0 }, sep = 0; 1.13310 + int err = 0; double val = 0; unsigned int nb = 0; 1.13311 + while ((err=cimg_std::sscanf(nvalues,"%63[ \n\t0-9e.+-]%c",cval,&sep))>0 && 1.13312 + cimg_std::sscanf(cval,"%lf",&val)>0 && nb<siz) { 1.13313 + nvalues += cimg::strlen(cval); 1.13314 + *(ptrd++) = (T)val; 1.13315 + ++nb; 1.13316 + if (err!=2) break; else ++nvalues; 1.13317 + } 1.13318 + if (repeat_pattern && nb) for (T *ptrs = data; ptrd<ptr_end; ++ptrs) *(ptrd++) = *ptrs; 1.13319 + return *this; 1.13320 + } 1.13321 + 1.13322 + CImg<T> get_fill(const char *const values, const bool repeat_pattern) const { 1.13323 + return repeat_pattern?CImg<T>(width,height,depth,dim).fill(values,repeat_pattern):(+*this).fill(values,repeat_pattern); 1.13324 + } 1.13325 + 1.13326 + //! Fill image values according to the values found in the specified image. 1.13327 + template<typename t> 1.13328 + CImg<T>& fill(const CImg<t>& values, const bool repeat_pattern=true) { 1.13329 + if (is_empty() || !values) return *this; 1.13330 + T *ptrd = data, *ptrd_end = ptrd + size(); 1.13331 + for (t *ptrs = values.data, *ptrs_end = ptrs + values.size(); ptrs<ptrs_end && ptrd<ptrd_end; ++ptrs) *(ptrd++) = (T)*ptrs; 1.13332 + if (repeat_pattern && ptrd<ptrd_end) for (T *ptrs = data; ptrd<ptrd_end; ++ptrs) *(ptrd++) = *ptrs; 1.13333 + return *this; 1.13334 + } 1.13335 + 1.13336 + template<typename t> 1.13337 + CImg<T> get_fill(const CImg<t>& values, const bool repeat_pattern=true) const { 1.13338 + return repeat_pattern?CImg<T>(width,height,depth,dim).fill(values,repeat_pattern):(+*this).fill(values,repeat_pattern); 1.13339 + } 1.13340 + 1.13341 + //! Fill image values along the X-axis at the specified pixel position (y,z,v). 1.13342 + CImg<T>& fillX(const unsigned int y, const unsigned int z, const unsigned int v, const int a0, ...) { 1.13343 +#define _cimg_fill1(x,y,z,v,off,siz,t) { \ 1.13344 + va_list ap; va_start(ap,a0); T *ptrd = ptr(x,y,z,v); *ptrd = (T)a0; \ 1.13345 + for (unsigned int k = 1; k<siz; ++k) { ptrd+=off; *ptrd = (T)va_arg(ap,t); } \ 1.13346 + va_end(ap); } 1.13347 + if (y<height && z<depth && v<dim) _cimg_fill1(0,y,z,v,1,width,int); 1.13348 + return *this; 1.13349 + } 1.13350 + 1.13351 + CImg<T>& fillX(const unsigned int y, const unsigned int z, const unsigned int v, const double a0, ...) { 1.13352 + if (y<height && z<depth && v<dim) _cimg_fill1(0,y,z,v,1,width,double); 1.13353 + return *this; 1.13354 + } 1.13355 + 1.13356 + //! Fill image values along the Y-axis at the specified pixel position (x,z,v). 1.13357 + CImg<T>& fillY(const unsigned int x, const unsigned int z, const unsigned int v, const int a0, ...) { 1.13358 + if (x<width && z<depth && v<dim) _cimg_fill1(x,0,z,v,width,height,int); 1.13359 + return *this; 1.13360 + } 1.13361 + 1.13362 + CImg<T>& fillY(const unsigned int x, const unsigned int z, const unsigned int v, const double a0, ...) { 1.13363 + if (x<width && z<depth && v<dim) _cimg_fill1(x,0,z,v,width,height,double); 1.13364 + return *this; 1.13365 + } 1.13366 + 1.13367 + //! Fill image values along the Z-axis at the specified pixel position (x,y,v). 1.13368 + CImg<T>& fillZ(const unsigned int x, const unsigned int y, const unsigned int v, const int a0, ...) { 1.13369 + const unsigned int wh = width*height; 1.13370 + if (x<width && y<height && v<dim) _cimg_fill1(x,y,0,v,wh,depth,int); 1.13371 + return *this; 1.13372 + } 1.13373 + 1.13374 + CImg<T>& fillZ(const unsigned int x, const unsigned int y, const unsigned int v, const double a0, ...) { 1.13375 + const unsigned int wh = width*height; 1.13376 + if (x<width && y<height && v<dim) _cimg_fill1(x,y,0,v,wh,depth,double); 1.13377 + return *this; 1.13378 + } 1.13379 + 1.13380 + //! Fill image values along the V-axis at the specified pixel position (x,y,z). 1.13381 + CImg<T>& fillV(const unsigned int x, const unsigned int y, const unsigned int z, const int a0, ...) { 1.13382 + const unsigned int whz = width*height*depth; 1.13383 + if (x<width && y<height && z<depth) _cimg_fill1(x,y,z,0,whz,dim,int); 1.13384 + return *this; 1.13385 + } 1.13386 + 1.13387 + CImg<T>& fillV(const unsigned int x, const unsigned int y, const unsigned int z, const double a0, ...) { 1.13388 + const unsigned int whz = width*height*depth; 1.13389 + if (x<width && y<height && z<depth) _cimg_fill1(x,y,z,0,whz,dim,double); 1.13390 + return *this; 1.13391 + } 1.13392 + 1.13393 + //! Linear normalization of the pixel values between \a a and \a b. 1.13394 + CImg<T>& normalize(const T a, const T b) { 1.13395 + if (is_empty()) return *this; 1.13396 + const T na = a<b?a:b, nb = a<b?b:a; 1.13397 + T m, M = maxmin(m); 1.13398 + const Tfloat fm = (Tfloat)m, fM = (Tfloat)M; 1.13399 + if (m==M) return fill(0); 1.13400 + if (m!=na || M!=nb) cimg_for(*this,ptr,T) *ptr = (T)((*ptr-fm)/(fM-fm)*(nb-na)+na); 1.13401 + return *this; 1.13402 + } 1.13403 + 1.13404 + CImg<T> get_normalize(const T a, const T b) const { 1.13405 + return (+*this).normalize(a,b); 1.13406 + } 1.13407 + 1.13408 + //! Cut pixel values between \a a and \a b. 1.13409 + CImg<T>& cut(const T a, const T b) { 1.13410 + if (is_empty()) return *this; 1.13411 + const T na = a<b?a:b, nb = a<b?b:a; 1.13412 + cimg_for(*this,ptr,T) *ptr = (*ptr<na)?na:((*ptr>nb)?nb:*ptr); 1.13413 + return *this; 1.13414 + } 1.13415 + 1.13416 + CImg<T> get_cut(const T a, const T b) const { 1.13417 + return (+*this).cut(a,b); 1.13418 + } 1.13419 + 1.13420 + //! Quantize pixel values into \n levels. 1.13421 + CImg<T>& quantize(const unsigned int n, const bool keep_range=true) { 1.13422 + if (is_empty()) return *this; 1.13423 + if (!n) 1.13424 + throw CImgArgumentException("CImg<%s>::quantize() : Cannot quantize image to 0 values.", 1.13425 + pixel_type()); 1.13426 + Tfloat m, M = (Tfloat)maxmin(m), range = M - m; 1.13427 + if (range>0) { 1.13428 + if (keep_range) cimg_for(*this,ptr,T) { 1.13429 + const unsigned int val = (unsigned int)((*ptr-m)*n/range); 1.13430 + *ptr = (T)(m + cimg::min(val,n-1)*range/n); 1.13431 + } else cimg_for(*this,ptr,T) { 1.13432 + const unsigned int val = (unsigned int)((*ptr-m)*n/range); 1.13433 + *ptr = (T)cimg::min(val,n-1); 1.13434 + } 1.13435 + } 1.13436 + return *this; 1.13437 + } 1.13438 + 1.13439 + CImg<T> get_quantize(const unsigned int n, const bool keep_range=true) const { 1.13440 + return (+*this).quantize(n,keep_range); 1.13441 + } 1.13442 + 1.13443 + //! Threshold the image. 1.13444 + /** 1.13445 + \param value Threshold value. 1.13446 + \param soft Enable soft thresholding. 1.13447 + \param strict Tells if the threshold is strict. 1.13448 + **/ 1.13449 + CImg<T>& threshold(const T value, const bool soft=false, const bool strict=false) { 1.13450 + if (is_empty()) return *this; 1.13451 + if (strict) { 1.13452 + if (soft) cimg_for(*this,ptr,T) { const T v = *ptr; *ptr = v>value?(T)(v-value):v<-value?(T)(v+value):(T)0; } 1.13453 + else cimg_for(*this,ptr,T) *ptr = *ptr>value?(T)1:(T)0; 1.13454 + } else { 1.13455 + if (soft) cimg_for(*this,ptr,T) { const T v = *ptr; *ptr = v>=value?(T)(v-value):v<=-value?(T)(v+value):(T)0; } 1.13456 + else cimg_for(*this,ptr,T) *ptr = *ptr>=value?(T)1:(T)0; 1.13457 + } 1.13458 + return *this; 1.13459 + } 1.13460 + 1.13461 + CImg<T> get_threshold(const T value, const bool soft=false, const bool strict=false) const { 1.13462 + return (+*this).threshold(value,soft,strict); 1.13463 + } 1.13464 + 1.13465 + //! Rotate an image. 1.13466 + /** 1.13467 + \param angle = rotation angle (in degrees). 1.13468 + \param cond = rotation type. can be : 1.13469 + - 0 = zero-value at borders 1.13470 + - 1 = nearest pixel. 1.13471 + - 2 = Fourier style. 1.13472 + \note Returned image will probably have a different size than the instance image *this. 1.13473 + **/ 1.13474 + CImg<T>& rotate(const float angle, const unsigned int border_conditions=3, const unsigned int interpolation=1) { 1.13475 + return get_rotate(angle,border_conditions,interpolation).transfer_to(*this); 1.13476 + } 1.13477 + 1.13478 + CImg<T> get_rotate(const float angle, const unsigned int border_conditions=3, const unsigned int interpolation=1) const { 1.13479 + if (is_empty()) return *this; 1.13480 + CImg<T> dest; 1.13481 + const float nangle = cimg::mod(angle,360.0f); 1.13482 + if (border_conditions!=1 && cimg::mod(nangle,90.0f)==0) { // optimized version for orthogonal angles 1.13483 + const int wm1 = dimx()-1, hm1 = dimy()-1; 1.13484 + const int iangle = (int)nangle/90; 1.13485 + switch (iangle) { 1.13486 + case 1 : { 1.13487 + dest.assign(height,width,depth,dim); 1.13488 + cimg_forXYZV(dest,x,y,z,v) dest(x,y,z,v) = (*this)(y,hm1-x,z,v); 1.13489 + } break; 1.13490 + case 2 : { 1.13491 + dest.assign(width,height,depth,dim); 1.13492 + cimg_forXYZV(dest,x,y,z,v) dest(x,y,z,v) = (*this)(wm1-x,hm1-y,z,v); 1.13493 + } break; 1.13494 + case 3 : { 1.13495 + dest.assign(height,width,depth,dim); 1.13496 + cimg_forXYZV(dest,x,y,z,v) dest(x,y,z,v) = (*this)(wm1-y,x,z,v); 1.13497 + } break; 1.13498 + default : 1.13499 + return *this; 1.13500 + } 1.13501 + } else { // generic version 1.13502 + const float 1.13503 + rad = (float)(nangle*cimg::valuePI/180.0), 1.13504 + ca = (float)cimg_std::cos(rad), 1.13505 + sa = (float)cimg_std::sin(rad), 1.13506 + ux = cimg::abs(width*ca), uy = cimg::abs(width*sa), 1.13507 + vx = cimg::abs(height*sa), vy = cimg::abs(height*ca), 1.13508 + w2 = 0.5f*width, h2 = 0.5f*height, 1.13509 + dw2 = 0.5f*(ux+vx), dh2 = 0.5f*(uy+vy); 1.13510 + dest.assign((int)(ux+vx), (int)(uy+vy),depth,dim); 1.13511 + switch (border_conditions) { 1.13512 + case 0 : { 1.13513 + switch (interpolation) { 1.13514 + case 2 : { 1.13515 + cimg_forXY(dest,x,y) cimg_forZV(*this,z,v) 1.13516 + dest(x,y,z,v) = (T)cubic_atXY(w2 + (x-dw2)*ca + (y-dh2)*sa,h2 - (x-dw2)*sa + (y-dh2)*ca,z,v,0); 1.13517 + } break; 1.13518 + case 1 : { 1.13519 + cimg_forXY(dest,x,y) cimg_forZV(*this,z,v) 1.13520 + dest(x,y,z,v) = (T)linear_atXY(w2 + (x-dw2)*ca + (y-dh2)*sa,h2 - (x-dw2)*sa + (y-dh2)*ca,z,v,0); 1.13521 + } break; 1.13522 + default : { 1.13523 + cimg_forXY(dest,x,y) cimg_forZV(*this,z,v) 1.13524 + dest(x,y,z,v) = atXY((int)(w2 + (x-dw2)*ca + (y-dh2)*sa),(int)(h2 - (x-dw2)*sa + (y-dh2)*ca),z,v,0); 1.13525 + } 1.13526 + } 1.13527 + } break; 1.13528 + case 1 : { 1.13529 + switch (interpolation) { 1.13530 + case 2 : 1.13531 + cimg_forXY(dest,x,y) cimg_forZV(*this,z,v) 1.13532 + dest(x,y,z,v) = (T)cubic_atXY(w2 + (x-dw2)*ca + (y-dh2)*sa,h2 - (x-dw2)*sa + (y-dh2)*ca,z,v); 1.13533 + break; 1.13534 + case 1 : 1.13535 + cimg_forXY(dest,x,y) cimg_forZV(*this,z,v) 1.13536 + dest(x,y,z,v) = (T)linear_atXY(w2 + (x-dw2)*ca + (y-dh2)*sa,h2 - (x-dw2)*sa + (y-dh2)*ca,z,v); 1.13537 + break; 1.13538 + default : 1.13539 + cimg_forXY(dest,x,y) cimg_forZV(*this,z,v) 1.13540 + dest(x,y,z,v) = atXY((int)(w2 + (x-dw2)*ca + (y-dh2)*sa),(int)(h2 - (x-dw2)*sa + (y-dh2)*ca),z,v); 1.13541 + } 1.13542 + } break; 1.13543 + case 2 : { 1.13544 + switch (interpolation) { 1.13545 + case 2 : 1.13546 + cimg_forXY(dest,x,y) cimg_forZV(*this,z,v) 1.13547 + dest(x,y,z,v) = (T)cubic_atXY(cimg::mod(w2 + (x-dw2)*ca + (y-dh2)*sa,(float)dimx()), 1.13548 + cimg::mod(h2 - (x-dw2)*sa + (y-dh2)*ca,(float)dimy()),z,v); 1.13549 + break; 1.13550 + case 1 : 1.13551 + cimg_forXY(dest,x,y) cimg_forZV(*this,z,v) 1.13552 + dest(x,y,z,v) = (T)linear_atXY(cimg::mod(w2 + (x-dw2)*ca + (y-dh2)*sa,(float)dimx()), 1.13553 + cimg::mod(h2 - (x-dw2)*sa + (y-dh2)*ca,(float)dimy()),z,v); 1.13554 + break; 1.13555 + default : 1.13556 + cimg_forXY(dest,x,y) cimg_forZV(*this,z,v) 1.13557 + dest(x,y,z,v) = (*this)(cimg::mod((int)(w2 + (x-dw2)*ca + (y-dh2)*sa),dimx()), 1.13558 + cimg::mod((int)(h2 - (x-dw2)*sa + (y-dh2)*ca),dimy()),z,v); 1.13559 + } 1.13560 + } break; 1.13561 + default : 1.13562 + throw CImgArgumentException("CImg<%s>::get_rotate() : Invalid border conditions %d (should be 0,1 or 2).", 1.13563 + pixel_type(),border_conditions); 1.13564 + } 1.13565 + } 1.13566 + return dest; 1.13567 + } 1.13568 + 1.13569 + //! Rotate an image around a center point (\c cx,\c cy). 1.13570 + /** 1.13571 + \param angle = rotation angle (in degrees). 1.13572 + \param cx = X-coordinate of the rotation center. 1.13573 + \param cy = Y-coordinate of the rotation center. 1.13574 + \param zoom = zoom. 1.13575 + \param cond = rotation type. can be : 1.13576 + - 0 = zero-value at borders 1.13577 + - 1 = repeat image at borders 1.13578 + - 2 = zero-value at borders and linear interpolation 1.13579 + **/ 1.13580 + CImg<T>& rotate(const float angle, const float cx, const float cy, const float zoom, 1.13581 + const unsigned int border_conditions=3, const unsigned int interpolation=1) { 1.13582 + return get_rotate(angle,cx,cy,zoom,border_conditions,interpolation).transfer_to(*this); 1.13583 + } 1.13584 + 1.13585 + CImg<T> get_rotate(const float angle, const float cx, const float cy, const float zoom, 1.13586 + const unsigned int border_conditions=3, const unsigned int interpolation=1) const { 1.13587 + if (interpolation>2) 1.13588 + throw CImgArgumentException("CImg<%s>::get_rotate() : Invalid interpolation parameter %d (should be {0=none, 1=linear or 2=cubic}).", 1.13589 + pixel_type(),interpolation); 1.13590 + if (is_empty()) return *this; 1.13591 + CImg<T> dest(width,height,depth,dim); 1.13592 + const float nangle = cimg::mod(angle,360.0f); 1.13593 + if (border_conditions!=1 && zoom==1 && cimg::mod(nangle,90.0f)==0) { // optimized version for orthogonal angles 1.13594 + const int iangle = (int)nangle/90; 1.13595 + switch (iangle) { 1.13596 + case 1 : { 1.13597 + dest.fill(0); 1.13598 + const unsigned int 1.13599 + xmin = cimg::max(0,(dimx()-dimy())/2), xmax = cimg::min(width,xmin+height), 1.13600 + ymin = cimg::max(0,(dimy()-dimx())/2), ymax = cimg::min(height,ymin+width), 1.13601 + xoff = xmin + cimg::min(0,(dimx()-dimy())/2), 1.13602 + yoff = ymin + cimg::min(0,(dimy()-dimx())/2); 1.13603 + cimg_forZV(dest,z,v) for (unsigned int y = ymin; y<ymax; ++y) for (unsigned int x = xmin; x<xmax; ++x) 1.13604 + dest(x,y,z,v) = (*this)(y-yoff,height-1-x+xoff,z,v); 1.13605 + } break; 1.13606 + case 2 : { 1.13607 + cimg_forXYZV(dest,x,y,z,v) dest(x,y,z,v) = (*this)(width-1-x,height-1-y,z,v); 1.13608 + } break; 1.13609 + case 3 : { 1.13610 + dest.fill(0); 1.13611 + const unsigned int 1.13612 + xmin = cimg::max(0,(dimx()-dimy())/2), xmax = cimg::min(width,xmin+height), 1.13613 + ymin = cimg::max(0,(dimy()-dimx())/2), ymax = cimg::min(height,ymin+width), 1.13614 + xoff = xmin + cimg::min(0,(dimx()-dimy())/2), 1.13615 + yoff = ymin + cimg::min(0,(dimy()-dimx())/2); 1.13616 + cimg_forZV(dest,z,v) for (unsigned int y = ymin; y<ymax; ++y) for (unsigned int x = xmin; x<xmax; ++x) 1.13617 + dest(x,y,z,v) = (*this)(width-1-y+yoff,x-xoff,z,v); 1.13618 + } break; 1.13619 + default : 1.13620 + return *this; 1.13621 + } 1.13622 + } else { 1.13623 + const float 1.13624 + rad = (float)((nangle*cimg::valuePI)/180.0), 1.13625 + ca = (float)cimg_std::cos(rad)/zoom, 1.13626 + sa = (float)cimg_std::sin(rad)/zoom; 1.13627 + switch (border_conditions) { // generic version 1.13628 + case 0 : { 1.13629 + switch (interpolation) { 1.13630 + case 2 : { 1.13631 + cimg_forXY(dest,x,y) 1.13632 + cimg_forZV(*this,z,v) 1.13633 + dest(x,y,z,v) = (T)cubic_atXY(cx + (x-cx)*ca + (y-cy)*sa,cy - (x-cx)*sa + (y-cy)*ca,z,v,0); 1.13634 + } break; 1.13635 + case 1 : { 1.13636 + cimg_forXY(dest,x,y) 1.13637 + cimg_forZV(*this,z,v) 1.13638 + dest(x,y,z,v) = (T)linear_atXY(cx + (x-cx)*ca + (y-cy)*sa,cy - (x-cx)*sa + (y-cy)*ca,z,v,0); 1.13639 + } break; 1.13640 + default : { 1.13641 + cimg_forXY(dest,x,y) 1.13642 + cimg_forZV(*this,z,v) 1.13643 + dest(x,y,z,v) = atXY((int)(cx + (x-cx)*ca + (y-cy)*sa),(int)(cy - (x-cx)*sa + (y-cy)*ca),z,v,0); 1.13644 + } 1.13645 + } 1.13646 + } break; 1.13647 + case 1 : { 1.13648 + switch (interpolation) { 1.13649 + case 2 : { 1.13650 + cimg_forXY(dest,x,y) 1.13651 + cimg_forZV(*this,z,v) 1.13652 + dest(x,y,z,v) = (T)cubic_atXY(cx + (x-cx)*ca + (y-cy)*sa,cy - (x-cx)*sa + (y-cy)*ca,z,v); 1.13653 + } break; 1.13654 + case 1 : { 1.13655 + cimg_forXY(dest,x,y) 1.13656 + cimg_forZV(*this,z,v) 1.13657 + dest(x,y,z,v) = (T)linear_atXY(cx + (x-cx)*ca + (y-cy)*sa,cy - (x-cx)*sa + (y-cy)*ca,z,v); 1.13658 + } break; 1.13659 + default : { 1.13660 + cimg_forXY(dest,x,y) 1.13661 + cimg_forZV(*this,z,v) 1.13662 + dest(x,y,z,v) = atXY((int)(cx + (x-cx)*ca + (y-cy)*sa),(int)(cy - (x-cx)*sa + (y-cy)*ca),z,v); 1.13663 + } 1.13664 + } 1.13665 + } break; 1.13666 + case 2 : { 1.13667 + switch (interpolation) { 1.13668 + case 2 : { 1.13669 + cimg_forXY(dest,x,y) 1.13670 + cimg_forZV(*this,z,v) 1.13671 + dest(x,y,z,v) = (T)cubic_atXY(cimg::mod(cx + (x-cx)*ca + (y-cy)*sa,(float)dimx()), 1.13672 + cimg::mod(cy - (x-cx)*sa + (y-cy)*ca,(float)dimy()),z,v); 1.13673 + } break; 1.13674 + case 1 : { 1.13675 + cimg_forXY(dest,x,y) 1.13676 + cimg_forZV(*this,z,v) 1.13677 + dest(x,y,z,v) = (T)linear_atXY(cimg::mod(cx + (x-cx)*ca + (y-cy)*sa,(float)dimx()), 1.13678 + cimg::mod(cy - (x-cx)*sa + (y-cy)*ca,(float)dimy()),z,v); 1.13679 + } break; 1.13680 + default : { 1.13681 + cimg_forXY(dest,x,y) 1.13682 + cimg_forZV(*this,z,v) 1.13683 + dest(x,y,z,v) = (*this)(cimg::mod((int)(cx + (x-cx)*ca + (y-cy)*sa),dimx()), 1.13684 + cimg::mod((int)(cy - (x-cx)*sa + (y-cy)*ca),dimy()),z,v); 1.13685 + } 1.13686 + } 1.13687 + } break; 1.13688 + default : 1.13689 + throw CImgArgumentException("CImg<%s>::get_rotate() : Incorrect border conditions %d (should be 0,1 or 2).", 1.13690 + pixel_type(),border_conditions); 1.13691 + } 1.13692 + } 1.13693 + return dest; 1.13694 + } 1.13695 + 1.13696 + //! Resize an image. 1.13697 + /** 1.13698 + \param pdx Number of columns (new size along the X-axis). 1.13699 + \param pdy Number of rows (new size along the Y-axis). 1.13700 + \param pdz Number of slices (new size along the Z-axis). 1.13701 + \param pdv Number of vector-channels (new size along the V-axis). 1.13702 + \param interpolation_type Method of interpolation : 1.13703 + - -1 = no interpolation : raw memory resizing. 1.13704 + - 0 = no interpolation : additional space is filled according to \p border_condition. 1.13705 + - 1 = bloc interpolation (nearest point). 1.13706 + - 2 = moving average interpolation. 1.13707 + - 3 = linear interpolation. 1.13708 + - 4 = grid interpolation. 1.13709 + - 5 = bi-cubic interpolation. 1.13710 + \param border_condition Border condition type. 1.13711 + \param center Set centering type (only if \p interpolation_type=0). 1.13712 + \note If pd[x,y,z,v]<0, it corresponds to a percentage of the original size (the default value is -100). 1.13713 + **/ 1.13714 + CImg<T>& resize(const int pdx, const int pdy=-100, const int pdz=-100, const int pdv=-100, 1.13715 + const int interpolation_type=1, const int border_condition=-1, const bool center=false) { 1.13716 + if (!pdx || !pdy || !pdz || !pdv) return assign(); 1.13717 + const unsigned int 1.13718 + tdx = pdx<0?-pdx*width/100:pdx, 1.13719 + tdy = pdy<0?-pdy*height/100:pdy, 1.13720 + tdz = pdz<0?-pdz*depth/100:pdz, 1.13721 + tdv = pdv<0?-pdv*dim/100:pdv, 1.13722 + dx = tdx?tdx:1, 1.13723 + dy = tdy?tdy:1, 1.13724 + dz = tdz?tdz:1, 1.13725 + dv = tdv?tdv:1; 1.13726 + if (width==dx && height==dy && depth==dz && dim==dv) return *this; 1.13727 + if (interpolation_type==-1 && dx*dy*dz*dv==size()) { 1.13728 + width = dx; height = dy; depth = dz; dim = dv; 1.13729 + return *this; 1.13730 + } 1.13731 + return get_resize(dx,dy,dz,dv,interpolation_type,border_condition,center).transfer_to(*this); 1.13732 + } 1.13733 + 1.13734 + CImg<T> get_resize(const int pdx, const int pdy=-100, const int pdz=-100, const int pdv=-100, 1.13735 + const int interpolation_type=1, const int border_condition=-1, const bool center=false) const { 1.13736 + if (!pdx || !pdy || !pdz || !pdv) return CImg<T>(); 1.13737 + const unsigned int 1.13738 + tdx = pdx<0?-pdx*width/100:pdx, 1.13739 + tdy = pdy<0?-pdy*height/100:pdy, 1.13740 + tdz = pdz<0?-pdz*depth/100:pdz, 1.13741 + tdv = pdv<0?-pdv*dim/100:pdv, 1.13742 + dx = tdx?tdx:1, 1.13743 + dy = tdy?tdy:1, 1.13744 + dz = tdz?tdz:1, 1.13745 + dv = tdv?tdv:1; 1.13746 + if (width==dx && height==dy && depth==dz && dim==dv) return +*this; 1.13747 + if (is_empty()) return CImg<T>(dx,dy,dz,dv,0); 1.13748 + 1.13749 + CImg<T> res; 1.13750 + 1.13751 + switch (interpolation_type) { 1.13752 + case -1 : // Raw resizing 1.13753 + cimg_std::memcpy(res.assign(dx,dy,dz,dv,0).data,data,sizeof(T)*cimg::min(size(),(long unsigned int)dx*dy*dz*dv)); 1.13754 + break; 1.13755 + 1.13756 + case 0 : { // No interpolation 1.13757 + const unsigned int bx = width-1, by = height-1, bz = depth-1, bv = dim-1; 1.13758 + res.assign(dx,dy,dz,dv); 1.13759 + switch (border_condition) { 1.13760 + case 1 : { 1.13761 + if (center) { 1.13762 + const int 1.13763 + x0 = (res.dimx()-dimx())/2, 1.13764 + y0 = (res.dimy()-dimy())/2, 1.13765 + z0 = (res.dimz()-dimz())/2, 1.13766 + v0 = (res.dimv()-dimv())/2, 1.13767 + x1 = x0 + (int)bx, 1.13768 + y1 = y0 + (int)by, 1.13769 + z1 = z0 + (int)bz, 1.13770 + v1 = v0 + (int)bv; 1.13771 + res.draw_image(x0,y0,z0,v0,*this); 1.13772 + cimg_for_outXYZV(res,x0,y0,z0,v0,x1,y1,z1,v1,x,y,z,v) res(x,y,z,v) = _atXYZV(x-x0,y-y0,z-z0,v-v0); 1.13773 + } else { 1.13774 + res.draw_image(*this); 1.13775 + cimg_for_outXYZV(res,0,0,0,0,bx,by,bz,bv,x,y,z,v) res(x,y,z,v) = _atXYZV(x,y,z,v); 1.13776 + } 1.13777 + } break; 1.13778 + case 2 : { 1.13779 + int nx0 = 0, ny0 = 0, nz0 = 0, nv0 = 0; 1.13780 + if (center) { 1.13781 + const int 1.13782 + x0 = (res.dimx()-dimx())/2, 1.13783 + y0 = (res.dimy()-dimy())/2, 1.13784 + z0 = (res.dimz()-dimz())/2, 1.13785 + v0 = (res.dimv()-dimv())/2; 1.13786 + nx0 = x0>0?x0-(1+x0/width)*width:x0; 1.13787 + ny0 = y0>0?y0-(1+y0/height)*height:y0; 1.13788 + nz0 = z0>0?z0-(1+z0/depth)*depth:z0; 1.13789 + nv0 = v0>0?v0-(1+v0/dim)*dim:v0; 1.13790 + } 1.13791 + for (int k = nv0; k<(int)dv; k+=dimv()) 1.13792 + for (int z = nz0; z<(int)dz; z+=dimz()) 1.13793 + for (int y = ny0; y<(int)dy; y+=dimy()) 1.13794 + for (int x = nx0; x<(int)dx; x+=dimx()) res.draw_image(x,y,z,k,*this); 1.13795 + } break; 1.13796 + default : { 1.13797 + res.fill(0); 1.13798 + if (center) res.draw_image((res.dimx()-dimx())/2,(res.dimy()-dimy())/2,(res.dimz()-dimz())/2,(res.dimv()-dimv())/2,*this); 1.13799 + else res.draw_image(*this); 1.13800 + } 1.13801 + } 1.13802 + } break; 1.13803 + 1.13804 + case 1 : { // Nearest-neighbor interpolation 1.13805 + res.assign(dx,dy,dz,dv); 1.13806 + unsigned int 1.13807 + *const offx = new unsigned int[dx], 1.13808 + *const offy = new unsigned int[dy+1], 1.13809 + *const offz = new unsigned int[dz+1], 1.13810 + *const offv = new unsigned int[dv+1], 1.13811 + *poffx, *poffy, *poffz, *poffv, 1.13812 + curr, old; 1.13813 + const unsigned int wh = width*height, whd = width*height*depth, rwh = dx*dy, rwhd = dx*dy*dz; 1.13814 + poffx = offx; curr = 0; { cimg_forX(res,x) { old=curr; curr=(x+1)*width/dx; *(poffx++) = (unsigned int)curr-(unsigned int)old; }} 1.13815 + poffy = offy; curr = 0; { cimg_forY(res,y) { old=curr; curr=(y+1)*height/dy; *(poffy++) = width*((unsigned int)curr-(unsigned int)old); }} *poffy=0; 1.13816 + poffz = offz; curr = 0; { cimg_forZ(res,z) { old=curr; curr=(z+1)*depth/dz; *(poffz++) = wh*((unsigned int)curr-(unsigned int)old); }} *poffz=0; 1.13817 + poffv = offv; curr = 0; { cimg_forV(res,k) { old=curr; curr=(k+1)*dim/dv; *(poffv++) = whd*((unsigned int)curr-(unsigned int)old); }} *poffv=0; 1.13818 + T *ptrd = res.data; 1.13819 + const T* ptrv = data; 1.13820 + poffv = offv; 1.13821 + for (unsigned int k=0; k<dv; ) { 1.13822 + const T *ptrz = ptrv; 1.13823 + poffz = offz; 1.13824 + for (unsigned int z=0; z<dz; ) { 1.13825 + const T *ptry = ptrz; 1.13826 + poffy = offy; 1.13827 + for (unsigned int y=0; y<dy; ) { 1.13828 + const T *ptrx = ptry; 1.13829 + poffx = offx; 1.13830 + cimg_forX(res,x) { *(ptrd++) = *ptrx; ptrx+=*(poffx++); } 1.13831 + ++y; 1.13832 + unsigned int dy = *(poffy++); 1.13833 + for (;!dy && y<dy; cimg_std::memcpy(ptrd, ptrd-dx, sizeof(T)*dx), ++y, ptrd+=dx, dy=*(poffy++)) {} 1.13834 + ptry+=dy; 1.13835 + } 1.13836 + ++z; 1.13837 + unsigned int dz = *(poffz++); 1.13838 + for (;!dz && z<dz; cimg_std::memcpy(ptrd, ptrd-rwh, sizeof(T)*rwh), ++z, ptrd+=rwh, dz=*(poffz++)) {} 1.13839 + ptrz+=dz; 1.13840 + } 1.13841 + ++k; 1.13842 + unsigned int dv = *(poffv++); 1.13843 + for (;!dv && k<dv; cimg_std::memcpy(ptrd, ptrd-rwhd, sizeof(T)*rwhd), ++k, ptrd+=rwhd, dv=*(poffv++)) {} 1.13844 + ptrv+=dv; 1.13845 + } 1.13846 + delete[] offx; delete[] offy; delete[] offz; delete[] offv; 1.13847 + } break; 1.13848 + 1.13849 + case 2 : { // Moving average 1.13850 + bool instance_first = true; 1.13851 + if (dx!=width) { 1.13852 + CImg<Tfloat> tmp(dx,height,depth,dim,0); 1.13853 + for (unsigned int a = width*dx, b = width, c = dx, s = 0, t = 0; a; ) { 1.13854 + const unsigned int d = cimg::min(b,c); 1.13855 + a-=d; b-=d; c-=d; 1.13856 + cimg_forYZV(tmp,y,z,v) tmp(t,y,z,v)+=(Tfloat)(*this)(s,y,z,v)*d; 1.13857 + if (!b) { cimg_forYZV(tmp,y,z,v) tmp(t,y,z,v)/=width; ++t; b = width; } 1.13858 + if (!c) { ++s; c = dx; } 1.13859 + } 1.13860 + tmp.transfer_to(res); 1.13861 + instance_first = false; 1.13862 + } 1.13863 + if (dy!=height) { 1.13864 + CImg<Tfloat> tmp(dx,dy,depth,dim,0); 1.13865 + for (unsigned int a = height*dy, b = height, c = dy, s = 0, t = 0; a; ) { 1.13866 + const unsigned int d = cimg::min(b,c); 1.13867 + a-=d; b-=d; c-=d; 1.13868 + if (instance_first) cimg_forXZV(tmp,x,z,v) tmp(x,t,z,v)+=(Tfloat)(*this)(x,s,z,v)*d; 1.13869 + else cimg_forXZV(tmp,x,z,v) tmp(x,t,z,v)+=(Tfloat)res(x,s,z,v)*d; 1.13870 + if (!b) { cimg_forXZV(tmp,x,z,v) tmp(x,t,z,v)/=height; ++t; b = height; } 1.13871 + if (!c) { ++s; c = dy; } 1.13872 + } 1.13873 + tmp.transfer_to(res); 1.13874 + instance_first = false; 1.13875 + } 1.13876 + if (dz!=depth) { 1.13877 + CImg<Tfloat> tmp(dx,dy,dz,dim,0); 1.13878 + for (unsigned int a = depth*dz, b = depth, c = dz, s = 0, t = 0; a; ) { 1.13879 + const unsigned int d = cimg::min(b,c); 1.13880 + a-=d; b-=d; c-=d; 1.13881 + if (instance_first) cimg_forXYV(tmp,x,y,v) tmp(x,y,t,v)+=(Tfloat)(*this)(x,y,s,v)*d; 1.13882 + else cimg_forXYV(tmp,x,y,v) tmp(x,y,t,v)+=(Tfloat)res(x,y,s,v)*d; 1.13883 + if (!b) { cimg_forXYV(tmp,x,y,v) tmp(x,y,t,v)/=depth; ++t; b = depth; } 1.13884 + if (!c) { ++s; c = dz; } 1.13885 + } 1.13886 + tmp.transfer_to(res); 1.13887 + instance_first = false; 1.13888 + } 1.13889 + if (dv!=dim) { 1.13890 + CImg<Tfloat> tmp(dx,dy,dz,dv,0); 1.13891 + for (unsigned int a = dim*dv, b = dim, c = dv, s = 0, t = 0; a; ) { 1.13892 + const unsigned int d = cimg::min(b,c); 1.13893 + a-=d; b-=d; c-=d; 1.13894 + if (instance_first) cimg_forXYZ(tmp,x,y,z) tmp(x,y,z,t)+=(Tfloat)(*this)(x,y,z,s)*d; 1.13895 + else cimg_forXYZ(tmp,x,y,z) tmp(x,y,z,t)+=(Tfloat)res(x,y,z,s)*d; 1.13896 + if (!b) { cimg_forXYZ(tmp,x,y,z) tmp(x,y,z,t)/=dim; ++t; b = dim; } 1.13897 + if (!c) { ++s; c = dv; } 1.13898 + } 1.13899 + tmp.transfer_to(res); 1.13900 + instance_first = false; 1.13901 + } 1.13902 + } break; 1.13903 + 1.13904 + case 3 : { // Linear interpolation 1.13905 + const unsigned int dimmax = cimg::max(dx,dy,dz,dv); 1.13906 + const float 1.13907 + sx = (border_condition<0 && dx>width )?(dx>1?(width-1.0f)/(dx-1) :0):(float)width/dx, 1.13908 + sy = (border_condition<0 && dy>height)?(dy>1?(height-1.0f)/(dy-1):0):(float)height/dy, 1.13909 + sz = (border_condition<0 && dz>depth )?(dz>1?(depth-1.0f)/(dz-1) :0):(float)depth/dz, 1.13910 + sv = (border_condition<0 && dv>dim )?(dv>1?(dim-1.0f)/(dv-1) :0):(float)dim/dv; 1.13911 + 1.13912 + unsigned int *const off = new unsigned int[dimmax], *poff; 1.13913 + float *const foff = new float[dimmax], *pfoff, old, curr; 1.13914 + CImg<T> resx, resy, resz, resv; 1.13915 + T *ptrd; 1.13916 + 1.13917 + if (dx!=width) { 1.13918 + if (width==1) resx = get_resize(dx,height,depth,dim,1,0); 1.13919 + else { 1.13920 + resx.assign(dx,height,depth,dim); 1.13921 + curr = old = 0; poff = off; pfoff = foff; 1.13922 + cimg_forX(resx,x) { *(pfoff++) = curr-(unsigned int)curr; old = curr; curr+=sx; *(poff++) = (unsigned int)curr-(unsigned int)old; } 1.13923 + ptrd = resx.data; 1.13924 + const T *ptrs0 = data; 1.13925 + cimg_forYZV(resx,y,z,k) { 1.13926 + poff = off; pfoff = foff; 1.13927 + const T *ptrs = ptrs0, *const ptrsmax = ptrs0 + (width-1); 1.13928 + cimg_forX(resx,x) { 1.13929 + const float alpha = *(pfoff++); 1.13930 + const T val1 = *ptrs, val2 = ptrs<ptrsmax?*(ptrs+1):(border_condition?val1:(T)0); 1.13931 + *(ptrd++) = (T)((1-alpha)*val1 + alpha*val2); 1.13932 + ptrs+=*(poff++); 1.13933 + } 1.13934 + ptrs0+=width; 1.13935 + } 1.13936 + } 1.13937 + } else resx.assign(*this,true); 1.13938 + 1.13939 + if (dy!=height) { 1.13940 + if (height==1) resy = resx.get_resize(dx,dy,depth,dim,1,0); 1.13941 + else { 1.13942 + resy.assign(dx,dy,depth,dim); 1.13943 + curr = old = 0; poff = off; pfoff = foff; 1.13944 + cimg_forY(resy,y) { *(pfoff++) = curr-(unsigned int)curr; old = curr; curr+=sy; *(poff++) = dx*((unsigned int)curr-(unsigned int)old); } 1.13945 + cimg_forXZV(resy,x,z,k) { 1.13946 + ptrd = resy.ptr(x,0,z,k); 1.13947 + const T *ptrs = resx.ptr(x,0,z,k), *const ptrsmax = ptrs + (height-1)*dx; 1.13948 + poff = off; pfoff = foff; 1.13949 + cimg_forY(resy,y) { 1.13950 + const float alpha = *(pfoff++); 1.13951 + const T val1 = *ptrs, val2 = ptrs<ptrsmax?*(ptrs+dx):(border_condition?val1:(T)0); 1.13952 + *ptrd = (T)((1-alpha)*val1 + alpha*val2); 1.13953 + ptrd+=dx; 1.13954 + ptrs+=*(poff++); 1.13955 + } 1.13956 + } 1.13957 + } 1.13958 + resx.assign(); 1.13959 + } else resy.assign(resx,true); 1.13960 + 1.13961 + if (dz!=depth) { 1.13962 + if (depth==1) resz = resy.get_resize(dx,dy,dz,dim,1,0); 1.13963 + else { 1.13964 + const unsigned int wh = dx*dy; 1.13965 + resz.assign(dx,dy,dz,dim); 1.13966 + curr = old = 0; poff = off; pfoff = foff; 1.13967 + cimg_forZ(resz,z) { *(pfoff++) = curr-(unsigned int)curr; old = curr; curr+=sz; *(poff++) = wh*((unsigned int)curr-(unsigned int)old); } 1.13968 + cimg_forXYV(resz,x,y,k) { 1.13969 + ptrd = resz.ptr(x,y,0,k); 1.13970 + const T *ptrs = resy.ptr(x,y,0,k), *const ptrsmax = ptrs + (depth-1)*wh; 1.13971 + poff = off; pfoff = foff; 1.13972 + cimg_forZ(resz,z) { 1.13973 + const float alpha = *(pfoff++); 1.13974 + const T val1 = *ptrs, val2 = ptrs<ptrsmax?*(ptrs+wh):(border_condition?val1:(T)0); 1.13975 + *ptrd = (T)((1-alpha)*val1 + alpha*val2); 1.13976 + ptrd+=wh; 1.13977 + ptrs+=*(poff++); 1.13978 + } 1.13979 + } 1.13980 + } 1.13981 + resy.assign(); 1.13982 + } else resz.assign(resy,true); 1.13983 + 1.13984 + if (dv!=dim) { 1.13985 + if (dim==1) resv = resz.get_resize(dx,dy,dz,dv,1,0); 1.13986 + else { 1.13987 + const unsigned int whd = dx*dy*dz; 1.13988 + resv.assign(dx,dy,dz,dv); 1.13989 + curr = old = 0; poff = off; pfoff = foff; 1.13990 + cimg_forV(resv,k) { *(pfoff++) = curr-(unsigned int)curr; old = curr; curr+=sv; *(poff++) = whd*((unsigned int)curr-(unsigned int)old); } 1.13991 + cimg_forXYZ(resv,x,y,z) { 1.13992 + ptrd = resv.ptr(x,y,z,0); 1.13993 + const T *ptrs = resz.ptr(x,y,z,0), *const ptrsmax = ptrs + (dim-1)*whd; 1.13994 + poff = off; pfoff = foff; 1.13995 + cimg_forV(resv,k) { 1.13996 + const float alpha = *(pfoff++); 1.13997 + const T val1 = *ptrs, val2 = ptrs<ptrsmax?*(ptrs+whd):(border_condition?val1:(T)0); 1.13998 + *ptrd = (T)((1-alpha)*val1 + alpha*val2); 1.13999 + ptrd+=whd; 1.14000 + ptrs+=*(poff++); 1.14001 + } 1.14002 + } 1.14003 + } 1.14004 + resz.assign(); 1.14005 + } else resv.assign(resz,true); 1.14006 + 1.14007 + delete[] off; delete[] foff; 1.14008 + return resv.is_shared?(resz.is_shared?(resy.is_shared?(resx.is_shared?(+(*this)):resx):resy):resz):resv; 1.14009 + } break; 1.14010 + 1.14011 + case 4 : { // Grid filling 1.14012 + res.assign(dx,dy,dz,dv,0); 1.14013 + cimg_forXYZV(*this,x,y,z,k) res(x*dx/width,y*dy/height,z*dz/depth,k*dv/dim) = (*this)(x,y,z,k); 1.14014 + } break; 1.14015 + 1.14016 + case 5 : { // Cubic interpolation 1.14017 + const float 1.14018 + sx = (border_condition<0 && dx>width )?(dx>1?(width-1.0f)/(dx-1) :0):(float)width/dx, 1.14019 + sy = (border_condition<0 && dy>height)?(dy>1?(height-1.0f)/(dy-1):0):(float)height/dy, 1.14020 + sz = (border_condition<0 && dz>depth )?(dz>1?(depth-1.0f)/(dz-1) :0):(float)depth/dz, 1.14021 + sv = (border_condition<0 && dv>dim )?(dv>1?(dim-1.0f)/(dv-1) :0):(float)dim/dv; 1.14022 + res.assign(dx,dy,dz,dv); 1.14023 + T *ptrd = res.ptr(); 1.14024 + float cx, cy, cz, ck = 0; 1.14025 + cimg_forV(res,k) { cz = 0; 1.14026 + cimg_forZ(res,z) { cy = 0; 1.14027 + cimg_forY(res,y) { cx = 0; 1.14028 + cimg_forX(res,x) { 1.14029 + *(ptrd++) = (T)(border_condition?_cubic_atXY(cx,cy,(int)cz,(int)ck):cubic_atXY(cx,cy,(int)cz,(int)ck,0)); 1.14030 + cx+=sx; 1.14031 + } cy+=sy; 1.14032 + } cz+=sz; 1.14033 + } ck+=sv; 1.14034 + } 1.14035 + } break; 1.14036 + 1.14037 + default : // Invalid interpolation method 1.14038 + throw CImgArgumentException("CImg<%s>::resize() : Invalid interpolation_type %d " 1.14039 + "(should be { -1=raw, 0=zero, 1=nearest, 2=average, 3=linear, 4=grid, 5=bicubic}).", 1.14040 + pixel_type(),interpolation_type); 1.14041 + } 1.14042 + return res; 1.14043 + } 1.14044 + 1.14045 + //! Resize an image. 1.14046 + /** 1.14047 + \param src Image giving the geometry of the resize. 1.14048 + \param interpolation_type Interpolation method : 1.14049 + - 1 = raw memory 1.14050 + - 0 = no interpolation : additional space is filled with 0. 1.14051 + - 1 = bloc interpolation (nearest point). 1.14052 + - 2 = mosaic : image is repeated if necessary. 1.14053 + - 3 = linear interpolation. 1.14054 + - 4 = grid interpolation. 1.14055 + - 5 = bi-cubic interpolation. 1.14056 + \param border_condition Border condition type. 1.14057 + \note If pd[x,y,z,v]<0, it corresponds to a percentage of the original size (the default value is -100). 1.14058 + **/ 1.14059 + template<typename t> 1.14060 + CImg<T>& resize(const CImg<t>& src, const int interpolation_type=1, 1.14061 + const int border_condition=-1, const bool center=false) { 1.14062 + return resize(src.width,src.height,src.depth,src.dim,interpolation_type,border_condition,center); 1.14063 + } 1.14064 + 1.14065 + template<typename t> 1.14066 + CImg<T> get_resize(const CImg<t>& src, const int interpolation_type=1, 1.14067 + const int border_condition=-1, const bool center=false) const { 1.14068 + return get_resize(src.width,src.height,src.depth,src.dim,interpolation_type,border_condition,center); 1.14069 + } 1.14070 + 1.14071 + //! Resize an image. 1.14072 + /** 1.14073 + \param disp = Display giving the geometry of the resize. 1.14074 + \param interpolation_type = Resizing type : 1.14075 + - 0 = no interpolation : additional space is filled with 0. 1.14076 + - 1 = bloc interpolation (nearest point). 1.14077 + - 2 = mosaic : image is repeated if necessary. 1.14078 + - 3 = linear interpolation. 1.14079 + - 4 = grid interpolation. 1.14080 + - 5 = bi-cubic interpolation. 1.14081 + - 6 = moving average (best quality for photographs) 1.14082 + \param border_condition Border condition type. 1.14083 + \note If pd[x,y,z,v]<0, it corresponds to a percentage of the original size (the default value is -100). 1.14084 + **/ 1.14085 + CImg<T>& resize(const CImgDisplay& disp, const int interpolation_type=1, 1.14086 + const int border_condition=-1, const bool center=false) { 1.14087 + return resize(disp.width,disp.height,depth,dim,interpolation_type,border_condition,center); 1.14088 + } 1.14089 + 1.14090 + CImg<T> get_resize(const CImgDisplay& disp, const int interpolation_type=1, 1.14091 + const int border_condition=-1, const bool center=false) const { 1.14092 + return get_resize(disp.width,disp.height,depth,dim,interpolation_type,border_condition,center); 1.14093 + } 1.14094 + 1.14095 + //! Half-resize an image, using a special optimized filter. 1.14096 + CImg<T>& resize_halfXY() { 1.14097 + return get_resize_halfXY().transfer_to(*this); 1.14098 + } 1.14099 + 1.14100 + CImg<T> get_resize_halfXY() const { 1.14101 + if (is_empty()) return *this; 1.14102 + const Tfloat mask[9] = { 0.07842776544f, 0.1231940459f, 0.07842776544f, 1.14103 + 0.1231940459f, 0.1935127547f, 0.1231940459f, 1.14104 + 0.07842776544f, 0.1231940459f, 0.07842776544f }; 1.14105 + T I[9] = { 0 }; 1.14106 + CImg<T> dest(width/2,height/2,depth,dim); 1.14107 + cimg_forZV(*this,z,k) cimg_for3x3(*this,x,y,z,k,I) 1.14108 + if (x%2 && y%2) dest(x/2,y/2,z,k) = (T) 1.14109 + (I[0]*mask[0] + I[1]*mask[1] + I[2]*mask[2] + 1.14110 + I[3]*mask[3] + I[4]*mask[4] + I[5]*mask[5] + 1.14111 + I[6]*mask[6] + I[7]*mask[7] + I[8]*mask[8]); 1.14112 + return dest; 1.14113 + } 1.14114 + 1.14115 + //! Upscale an image by a factor 2x. 1.14116 + /** 1.14117 + Use anisotropic upscaling algorithm described at 1.14118 + http://scale2x.sourceforge.net/algorithm.html 1.14119 + **/ 1.14120 + CImg<T>& resize_doubleXY() { 1.14121 + return get_resize_doubleXY().transfer_to(*this); 1.14122 + } 1.14123 + 1.14124 + CImg<T> get_resize_doubleXY() const { 1.14125 +#define _cimg_gs2x_for3(bound,i) \ 1.14126 + for (int i = 0, _p1##i = 0, \ 1.14127 + _n1##i = 1>=(bound)?(int)(bound)-1:1; \ 1.14128 + _n1##i<(int)(bound) || i==--_n1##i; \ 1.14129 + _p1##i = i++, ++_n1##i, ptrd1+=(res).width, ptrd2+=(res).width) 1.14130 + 1.14131 +#define _cimg_gs2x_for3x3(img,x,y,z,v,I) \ 1.14132 + _cimg_gs2x_for3((img).height,y) for (int x = 0, \ 1.14133 + _p1##x = 0, \ 1.14134 + _n1##x = (int)( \ 1.14135 + (I[1] = (img)(0,_p1##y,z,v)), \ 1.14136 + (I[3] = I[4] = (img)(0,y,z,v)), \ 1.14137 + (I[7] = (img)(0,_n1##y,z,v)), \ 1.14138 + 1>=(img).width?(int)((img).width)-1:1); \ 1.14139 + (_n1##x<(int)((img).width) && ( \ 1.14140 + (I[2] = (img)(_n1##x,_p1##y,z,v)), \ 1.14141 + (I[5] = (img)(_n1##x,y,z,v)), \ 1.14142 + (I[8] = (img)(_n1##x,_n1##y,z,v)),1)) || \ 1.14143 + x==--_n1##x; \ 1.14144 + I[1] = I[2], \ 1.14145 + I[3] = I[4], I[4] = I[5], \ 1.14146 + I[7] = I[8], \ 1.14147 + _p1##x = x++, ++_n1##x) 1.14148 + 1.14149 + if (is_empty()) return *this; 1.14150 + CImg<T> res(2*width,2*height,depth,dim); 1.14151 + CImg_3x3(I,T); 1.14152 + cimg_forZV(*this,z,k) { 1.14153 + T 1.14154 + *ptrd1 = res.ptr(0,0,0,k), 1.14155 + *ptrd2 = ptrd1 + res.width; 1.14156 + _cimg_gs2x_for3x3(*this,x,y,0,k,I) { 1.14157 + if (Icp!=Icn && Ipc!=Inc) { 1.14158 + *(ptrd1++) = Ipc==Icp?Ipc:Icc; 1.14159 + *(ptrd1++) = Icp==Inc?Inc:Icc; 1.14160 + *(ptrd2++) = Ipc==Icn?Ipc:Icc; 1.14161 + *(ptrd2++) = Icn==Inc?Inc:Icc; 1.14162 + } else { *(ptrd1++) = Icc; *(ptrd1++) = Icc; *(ptrd2++) = Icc; *(ptrd2++) = Icc; } 1.14163 + } 1.14164 + } 1.14165 + return res; 1.14166 + } 1.14167 + 1.14168 + //! Upscale an image by a factor 3x. 1.14169 + /** 1.14170 + Use anisotropic upscaling algorithm described at 1.14171 + http://scale2x.sourceforge.net/algorithm.html 1.14172 + **/ 1.14173 + CImg<T>& resize_tripleXY() { 1.14174 + return get_resize_tripleXY().transfer_to(*this); 1.14175 + } 1.14176 + 1.14177 + CImg<T> get_resize_tripleXY() const { 1.14178 +#define _cimg_gs3x_for3(bound,i) \ 1.14179 + for (int i = 0, _p1##i = 0, \ 1.14180 + _n1##i = 1>=(bound)?(int)(bound)-1:1; \ 1.14181 + _n1##i<(int)(bound) || i==--_n1##i; \ 1.14182 + _p1##i = i++, ++_n1##i, ptrd1+=2*(res).width, ptrd2+=2*(res).width, ptrd3+=2*(res).width) 1.14183 + 1.14184 +#define _cimg_gs3x_for3x3(img,x,y,z,v,I) \ 1.14185 + _cimg_gs3x_for3((img).height,y) for (int x = 0, \ 1.14186 + _p1##x = 0, \ 1.14187 + _n1##x = (int)( \ 1.14188 + (I[0] = I[1] = (img)(0,_p1##y,z,v)), \ 1.14189 + (I[3] = I[4] = (img)(0,y,z,v)), \ 1.14190 + (I[6] = I[7] = (img)(0,_n1##y,z,v)), \ 1.14191 + 1>=(img).width?(int)((img).width)-1:1); \ 1.14192 + (_n1##x<(int)((img).width) && ( \ 1.14193 + (I[2] = (img)(_n1##x,_p1##y,z,v)), \ 1.14194 + (I[5] = (img)(_n1##x,y,z,v)), \ 1.14195 + (I[8] = (img)(_n1##x,_n1##y,z,v)),1)) || \ 1.14196 + x==--_n1##x; \ 1.14197 + I[0] = I[1], I[1] = I[2], \ 1.14198 + I[3] = I[4], I[4] = I[5], \ 1.14199 + I[6] = I[7], I[7] = I[8], \ 1.14200 + _p1##x = x++, ++_n1##x) 1.14201 + 1.14202 + if (is_empty()) return *this; 1.14203 + CImg<T> res(3*width,3*height,depth,dim); 1.14204 + CImg_3x3(I,T); 1.14205 + cimg_forZV(*this,z,k) { 1.14206 + T 1.14207 + *ptrd1 = res.ptr(0,0,0,k), 1.14208 + *ptrd2 = ptrd1 + res.width, 1.14209 + *ptrd3 = ptrd2 + res.width; 1.14210 + _cimg_gs3x_for3x3(*this,x,y,0,k,I) { 1.14211 + if (Icp != Icn && Ipc != Inc) { 1.14212 + *(ptrd1++) = Ipc==Icp?Ipc:Icc; 1.14213 + *(ptrd1++) = (Ipc==Icp && Icc!=Inp) || (Icp==Inc && Icc!=Ipp)?Icp:Icc; 1.14214 + *(ptrd1++) = Icp==Inc?Inc:Icc; 1.14215 + *(ptrd2++) = (Ipc==Icp && Icc!=Ipn) || (Ipc==Icn && Icc!=Ipp)?Ipc:Icc; 1.14216 + *(ptrd2++) = Icc; 1.14217 + *(ptrd2++) = (Icp==Inc && Icc!=Inn) || (Icn==Inc && Icc!=Inp)?Inc:Icc; 1.14218 + *(ptrd3++) = Ipc==Icn?Ipc:Icc; 1.14219 + *(ptrd3++) = (Ipc==Icn && Icc!=Inn) || (Icn==Inc && Icc!=Ipn)?Icn:Icc; 1.14220 + *(ptrd3++) = Icn==Inc?Inc:Icc; 1.14221 + } else { 1.14222 + *(ptrd1++) = Icc; *(ptrd1++) = Icc; *(ptrd1++) = Icc; 1.14223 + *(ptrd2++) = Icc; *(ptrd2++) = Icc; *(ptrd2++) = Icc; 1.14224 + *(ptrd3++) = Icc; *(ptrd3++) = Icc; *(ptrd3++) = Icc; 1.14225 + } 1.14226 + } 1.14227 + } 1.14228 + return res; 1.14229 + } 1.14230 + 1.14231 + // Warp an image. 1.14232 + template<typename t> 1.14233 + CImg<T>& warp(const CImg<t>& warp, const bool relative=false, 1.14234 + const bool interpolation=true, const unsigned int border_conditions=0) { 1.14235 + return get_warp(warp,relative,interpolation,border_conditions).transfer_to(*this); 1.14236 + } 1.14237 + 1.14238 + template<typename t> 1.14239 + CImg<T> get_warp(const CImg<t>& warp, const bool relative=false, 1.14240 + const bool interpolation=true, const unsigned int border_conditions=0) const { 1.14241 + if (is_empty() || !warp) return *this; 1.14242 + if (!is_sameXYZ(warp)) 1.14243 + throw CImgArgumentException("CImg<%s>::warp() : Instance image (%u,%u,%u,%u,%p) and warping field (%u,%u,%u,%u,%p) " 1.14244 + "have different XYZ dimensions.", 1.14245 + pixel_type(),width,height,depth,dim,data, 1.14246 + warp.width,warp.height,warp.depth,warp.dim,warp.data); 1.14247 + CImg<T> res(width,height,depth,dim); 1.14248 + switch (warp.dim) { 1.14249 + case 1 : // 1D warping. 1.14250 + if (relative) { // Relative warp coordinates 1.14251 + if (interpolation) switch (border_conditions) { 1.14252 + case 2 : { 1.14253 + cimg_forXYZV(*this,x,y,z,v) 1.14254 + res(x,y,z,v) = (T)_linear_atX(cimg::mod(x-(float)warp(x,y,z,0),(float)width),y,z,v); 1.14255 + } break; 1.14256 + case 1 : { 1.14257 + cimg_forXYZV(*this,x,y,z,v) 1.14258 + res(x,y,z,v) = (T)_linear_atX(x-(float)warp(x,y,z,0),y,z,v); 1.14259 + } break; 1.14260 + default : { 1.14261 + cimg_forXYZV(*this,x,y,z,v) 1.14262 + res(x,y,z,v) = (T)linear_atX(x-(float)warp(x,y,z,0),y,z,v,0); 1.14263 + } 1.14264 + } else switch (border_conditions) { 1.14265 + case 2 : { 1.14266 + cimg_forXYZV(*this,x,y,z,v) 1.14267 + res(x,y,z,v) = (*this)(cimg::mod(x-(int)warp(x,y,z,0),(int)width),y,z,v); 1.14268 + } break; 1.14269 + case 1 : { 1.14270 + cimg_forXYZV(*this,x,y,z,v) 1.14271 + res(x,y,z,v) = _atX(x-(int)warp(x,y,z,0),y,z,v); 1.14272 + } break; 1.14273 + default : { 1.14274 + cimg_forXYZV(*this,x,y,z,v) 1.14275 + res(x,y,z,v) = atX(x-(int)warp(x,y,z,0),y,z,v,0); 1.14276 + } 1.14277 + } 1.14278 + } else { // Absolute warp coordinates 1.14279 + if (interpolation) switch (border_conditions) { 1.14280 + case 2 : { 1.14281 + cimg_forXYZV(*this,x,y,z,v) 1.14282 + res(x,y,z,v) = (T)_linear_atX(cimg::mod((float)warp(x,y,z,0),(float)width),y,z,v); 1.14283 + } break; 1.14284 + case 1 : { 1.14285 + cimg_forXYZV(*this,x,y,z,v) 1.14286 + res(x,y,z,v) = (T)_linear_atX((float)warp(x,y,z,0),y,z,v); 1.14287 + } break; 1.14288 + default : { 1.14289 + cimg_forXYZV(*this,x,y,z,v) 1.14290 + res(x,y,z,v) = (T)linear_atX((float)warp(x,y,z,0),y,z,v,0); 1.14291 + } 1.14292 + } else switch (border_conditions) { 1.14293 + case 2 : { 1.14294 + cimg_forXYZV(*this,x,y,z,v) 1.14295 + res(x,y,z,v) = (*this)(cimg::mod((int)warp(x,y,z,0),(int)width),y,z,v); 1.14296 + } break; 1.14297 + case 1 : { 1.14298 + cimg_forXYZV(*this,x,y,z,v) 1.14299 + res(x,y,z,v) = _atX((int)warp(x,y,z,0),y,z,v); 1.14300 + } break; 1.14301 + default : { 1.14302 + cimg_forXYZV(*this,x,y,z,v) 1.14303 + res(x,y,z,v) = atX((int)warp(x,y,z,0),y,z,v,0); 1.14304 + } 1.14305 + } 1.14306 + } 1.14307 + break; 1.14308 + 1.14309 + case 2 : // 2D warping 1.14310 + if (relative) { // Relative warp coordinates 1.14311 + if (interpolation) switch (border_conditions) { 1.14312 + case 2 : { 1.14313 + cimg_forXYZV(*this,x,y,z,v) 1.14314 + res(x,y,z,v) = (T)_linear_atXY(cimg::mod(x-(float)warp(x,y,z,0),(float)width), 1.14315 + cimg::mod(y-(float)warp(x,y,z,1),(float)height),z,v); 1.14316 + } break; 1.14317 + case 1 : { 1.14318 + cimg_forXYZV(*this,x,y,z,v) 1.14319 + res(x,y,z,v) = (T)_linear_atXY(x-(float)warp(x,y,z,0),y-(float)warp(x,y,z,1),z,v); 1.14320 + } break; 1.14321 + default : { 1.14322 + cimg_forXYZV(*this,x,y,z,v) 1.14323 + res(x,y,z,v) = (T)linear_atXY(x-(float)warp(x,y,z,0),y-(float)warp(x,y,z,1),z,v,0); 1.14324 + } 1.14325 + } else switch (border_conditions) { 1.14326 + case 2 : { 1.14327 + cimg_forXYZV(*this,x,y,z,v) 1.14328 + res(x,y,z,v) = (*this)(cimg::mod(x-(int)warp(x,y,z,0),(int)width), 1.14329 + cimg::mod(y-(int)warp(x,y,z,1),(int)height),z,v); 1.14330 + } break; 1.14331 + case 1 : { 1.14332 + cimg_forXYZV(*this,x,y,z,v) 1.14333 + res(x,y,z,v) = _atXY(x-(int)warp(x,y,z,0),y-(int)warp(x,y,z,1),z,v); 1.14334 + } break; 1.14335 + default : { 1.14336 + cimg_forXYZV(*this,x,y,z,v) 1.14337 + res(x,y,z,v) = atXY(x-(int)warp(x,y,z,0),y-(int)warp(x,y,z,1),z,v,0); 1.14338 + } 1.14339 + } 1.14340 + } else { // Absolute warp coordinates 1.14341 + if (interpolation) switch (border_conditions) { 1.14342 + case 2 : { 1.14343 + cimg_forXYZV(*this,x,y,z,v) 1.14344 + res(x,y,z,v) = (T)_linear_atXY(cimg::mod((float)warp(x,y,z,0),(float)width), 1.14345 + cimg::mod((float)warp(x,y,z,1),(float)height),z,v); 1.14346 + } break; 1.14347 + case 1 : { 1.14348 + cimg_forXYZV(*this,x,y,z,v) 1.14349 + res(x,y,z,v) = (T)_linear_atXY((float)warp(x,y,z,0),(float)warp(x,y,z,1),z,v); 1.14350 + } break; 1.14351 + default : { 1.14352 + cimg_forXYZV(*this,x,y,z,v) 1.14353 + res(x,y,z,v) = (T)linear_atXY((float)warp(x,y,z,0),(float)warp(x,y,z,1),z,v,0); 1.14354 + } 1.14355 + } else switch (border_conditions) { 1.14356 + case 2 : { 1.14357 + cimg_forXYZV(*this,x,y,z,v) 1.14358 + res(x,y,z,v) = (*this)(cimg::mod((int)warp(x,y,z,0),(int)width), 1.14359 + cimg::mod((int)warp(x,y,z,1),(int)depth),z,v); 1.14360 + } break; 1.14361 + case 1 : { 1.14362 + cimg_forXYZV(*this,x,y,z,v) 1.14363 + res(x,y,z,v) = _atXY((int)warp(x,y,z,0),(int)warp(x,y,z,1),z,v); 1.14364 + } break; 1.14365 + default : { 1.14366 + cimg_forXYZV(*this,x,y,z,v) 1.14367 + res(x,y,z,v) = atXY((int)warp(x,y,z,0),(int)warp(x,y,z,1),z,v,0); 1.14368 + } 1.14369 + } 1.14370 + } 1.14371 + break; 1.14372 + 1.14373 + case 3 : // 3D warping 1.14374 + if (relative) { // Relative warp coordinates 1.14375 + if (interpolation) switch (border_conditions) { 1.14376 + case 2 : { 1.14377 + cimg_forXYZV(*this,x,y,z,v) 1.14378 + res(x,y,z,v) = (T)_linear_atXYZ(cimg::mod(x-(float)warp(x,y,z,0),(float)width), 1.14379 + cimg::mod(y-(float)warp(x,y,z,1),(float)height), 1.14380 + cimg::mod(z-(float)warp(x,y,z,2),(float)depth),v); 1.14381 + } break; 1.14382 + case 1 : { 1.14383 + cimg_forXYZV(*this,x,y,z,v) 1.14384 + res(x,y,z,v) = (T)_linear_atXYZ(x-(float)warp(x,y,z,0),y-(float)warp(x,y,z,1),z-(float)warp(x,y,z,2),v); 1.14385 + } break; 1.14386 + default : { 1.14387 + cimg_forXYZV(*this,x,y,z,v) 1.14388 + res(x,y,z,v) = (T)linear_atXYZ(x-(float)warp(x,y,z,0),y-(float)warp(x,y,z,1),z-(float)warp(x,y,z,2),v,0); 1.14389 + } 1.14390 + } else switch (border_conditions) { 1.14391 + case 2 : { 1.14392 + cimg_forXYZV(*this,x,y,z,v) 1.14393 + res(x,y,z,v) = (*this)(cimg::mod(x-(int)warp(x,y,z,0),(int)width), 1.14394 + cimg::mod(y-(int)warp(x,y,z,1),(int)height), 1.14395 + cimg::mod(z-(int)warp(x,y,z,2),(int)depth),v); 1.14396 + } break; 1.14397 + case 1 : { 1.14398 + cimg_forXYZV(*this,x,y,z,v) 1.14399 + res(x,y,z,v) = _atXYZ(x-(int)warp(x,y,z,0),y-(int)warp(x,y,z,1),z-(int)warp(x,y,z,2),v); 1.14400 + } break; 1.14401 + default : { 1.14402 + cimg_forXYZV(*this,x,y,z,v) 1.14403 + res(x,y,z,v) = atXYZ(x-(int)warp(x,y,z,0),y-(int)warp(x,y,z,1),z-(int)warp(x,y,z,2),v,0); 1.14404 + } 1.14405 + } 1.14406 + } else { // Absolute warp coordinates 1.14407 + if (interpolation) switch (border_conditions) { 1.14408 + case 2 : { 1.14409 + cimg_forXYZV(*this,x,y,z,v) 1.14410 + res(x,y,z,v) = (T)_linear_atXYZ(cimg::mod((float)warp(x,y,z,0),(float)width), 1.14411 + cimg::mod((float)warp(x,y,z,1),(float)height), 1.14412 + cimg::mod((float)warp(x,y,z,2),(float)depth),v); 1.14413 + } break; 1.14414 + case 1 : { 1.14415 + cimg_forXYZV(*this,x,y,z,v) 1.14416 + res(x,y,z,v) = (T)_linear_atXYZ((float)warp(x,y,z,0),(float)warp(x,y,z,1),(float)warp(x,y,z,2),v); 1.14417 + } break; 1.14418 + default : { 1.14419 + cimg_forXYZV(*this,x,y,z,v) 1.14420 + res(x,y,z,v) = (T)linear_atXYZ((float)warp(x,y,z,0),(float)warp(x,y,z,1),(float)warp(x,y,z,2),v,0); 1.14421 + } 1.14422 + } else switch (border_conditions) { 1.14423 + case 2 : { 1.14424 + cimg_forXYZV(*this,x,y,z,v) 1.14425 + res(x,y,z,v) = (*this)(cimg::mod((int)warp(x,y,z,0),(int)width), 1.14426 + cimg::mod((int)warp(x,y,z,1),(int)height), 1.14427 + cimg::mod((int)warp(x,y,z,2),(int)depth),v); 1.14428 + } break; 1.14429 + case 1 : { 1.14430 + cimg_forXYZV(*this,x,y,z,v) 1.14431 + res(x,y,z,v) = _atXYZ((int)warp(x,y,z,0),(int)warp(x,y,z,1),(int)warp(x,y,z,2),v); 1.14432 + } break; 1.14433 + default : { 1.14434 + cimg_forXYZV(*this,x,y,z,v) 1.14435 + res(x,y,z,v) = atXYZ((int)warp(x,y,z,0),(int)warp(x,y,z,1),(int)warp(x,y,z,2),v,0); 1.14436 + } 1.14437 + } 1.14438 + } 1.14439 + break; 1.14440 + 1.14441 + default : // 4D warping 1.14442 + if (relative) { // Relative warp coordinates 1.14443 + if (interpolation) switch (border_conditions) { 1.14444 + case 2 : { 1.14445 + cimg_forXYZV(*this,x,y,z,v) 1.14446 + res(x,y,z,v) = (T)_linear_atXYZV(cimg::mod(x-(float)warp(x,y,z,0),(float)width), 1.14447 + cimg::mod(y-(float)warp(x,y,z,1),(float)height), 1.14448 + cimg::mod(z-(float)warp(x,y,z,2),(float)depth), 1.14449 + cimg::mod(z-(float)warp(x,y,z,3),(float)dim)); 1.14450 + } break; 1.14451 + case 1 : { 1.14452 + cimg_forXYZV(*this,x,y,z,v) 1.14453 + res(x,y,z,v) = (T)_linear_atXYZV(x-(float)warp(x,y,z,0),y-(float)warp(x,y,z,1),z-(float)warp(x,y,z,2),v-(float)warp(x,y,z,3)); 1.14454 + } break; 1.14455 + default : { 1.14456 + cimg_forXYZV(*this,x,y,z,v) 1.14457 + res(x,y,z,v) = (T)linear_atXYZV(x-(float)warp(x,y,z,0),y-(float)warp(x,y,z,1),z-(float)warp(x,y,z,2),v-(float)warp(x,y,z,3),0); 1.14458 + } 1.14459 + } else switch (border_conditions) { 1.14460 + case 2 : { 1.14461 + cimg_forXYZV(*this,x,y,z,v) 1.14462 + res(x,y,z,v) = (*this)(cimg::mod(x-(int)warp(x,y,z,0),(int)width), 1.14463 + cimg::mod(y-(int)warp(x,y,z,1),(int)height), 1.14464 + cimg::mod(z-(int)warp(x,y,z,2),(int)depth), 1.14465 + cimg::mod(v-(int)warp(x,y,z,3),(int)dim)); 1.14466 + } break; 1.14467 + case 1 : { 1.14468 + cimg_forXYZV(*this,x,y,z,v) 1.14469 + res(x,y,z,v) = _atXYZV(x-(int)warp(x,y,z,0),y-(int)warp(x,y,z,1),z-(int)warp(x,y,z,2),v-(int)warp(x,y,z,3)); 1.14470 + } break; 1.14471 + default : { 1.14472 + cimg_forXYZV(*this,x,y,z,v) 1.14473 + res(x,y,z,v) = atXYZ(x-(int)warp(x,y,z,0),y-(int)warp(x,y,z,1),z-(int)warp(x,y,z,2),v-(int)warp(x,y,z,3),0); 1.14474 + } 1.14475 + } 1.14476 + } else { // Absolute warp coordinates 1.14477 + if (interpolation) switch (border_conditions) { 1.14478 + case 2 : { 1.14479 + cimg_forXYZV(*this,x,y,z,v) 1.14480 + res(x,y,z,v) = (T)_linear_atXYZV(cimg::mod((float)warp(x,y,z,0),(float)width), 1.14481 + cimg::mod((float)warp(x,y,z,1),(float)height), 1.14482 + cimg::mod((float)warp(x,y,z,2),(float)depth), 1.14483 + cimg::mod((float)warp(x,y,z,3),(float)dim)); 1.14484 + } break; 1.14485 + case 1 : { 1.14486 + cimg_forXYZV(*this,x,y,z,v) 1.14487 + res(x,y,z,v) = (T)_linear_atXYZV((float)warp(x,y,z,0),(float)warp(x,y,z,1),(float)warp(x,y,z,2),(float)warp(x,y,z,3)); 1.14488 + } break; 1.14489 + default : { 1.14490 + cimg_forXYZV(*this,x,y,z,v) 1.14491 + res(x,y,z,v) = (T)linear_atXYZV((float)warp(x,y,z,0),(float)warp(x,y,z,1),(float)warp(x,y,z,2),(float)warp(x,y,z,3),0); 1.14492 + } 1.14493 + } else switch (border_conditions) { 1.14494 + case 2 : { 1.14495 + cimg_forXYZV(*this,x,y,z,v) 1.14496 + res(x,y,z,v) = (*this)(cimg::mod((int)warp(x,y,z,0),(int)width), 1.14497 + cimg::mod((int)warp(x,y,z,1),(int)height), 1.14498 + cimg::mod((int)warp(x,y,z,2),(int)depth), 1.14499 + cimg::mod((int)warp(x,y,z,3),(int)dim)); 1.14500 + } break; 1.14501 + case 1 : { 1.14502 + cimg_forXYZV(*this,x,y,z,v) 1.14503 + res(x,y,z,v) = _atXYZV((int)warp(x,y,z,0),(int)warp(x,y,z,1),(int)warp(x,y,z,2),(int)warp(x,y,z,3)); 1.14504 + } break; 1.14505 + default : { 1.14506 + cimg_forXYZV(*this,x,y,z,v) 1.14507 + res(x,y,z,v) = atXYZV((int)warp(x,y,z,0),(int)warp(x,y,z,1),(int)warp(x,y,z,2),(int)warp(x,y,z,3),0); 1.14508 + } 1.14509 + } 1.14510 + } 1.14511 + } 1.14512 + return res; 1.14513 + } 1.14514 + 1.14515 + // Permute axes order (internal). 1.14516 + template<typename t> 1.14517 + CImg<t> _get_permute_axes(const char *permut, const t&) const { 1.14518 + if (is_empty() || !permut) return CImg<t>(*this,false); 1.14519 + CImg<t> res; 1.14520 + const T* ptrs = data; 1.14521 + if (!cimg::strncasecmp(permut,"xyzv",4)) return (+*this); 1.14522 + if (!cimg::strncasecmp(permut,"xyvz",4)) { 1.14523 + res.assign(width,height,dim,depth); 1.14524 + cimg_forXYZV(*this,x,y,z,v) res(x,y,v,z) = (t)*(ptrs++); 1.14525 + } 1.14526 + if (!cimg::strncasecmp(permut,"xzyv",4)) { 1.14527 + res.assign(width,depth,height,dim); 1.14528 + cimg_forXYZV(*this,x,y,z,v) res(x,z,y,v) = (t)*(ptrs++); 1.14529 + } 1.14530 + if (!cimg::strncasecmp(permut,"xzvy",4)) { 1.14531 + res.assign(width,depth,dim,height); 1.14532 + cimg_forXYZV(*this,x,y,z,v) res(x,z,v,y) = (t)*(ptrs++); 1.14533 + } 1.14534 + if (!cimg::strncasecmp(permut,"xvyz",4)) { 1.14535 + res.assign(width,dim,height,depth); 1.14536 + cimg_forXYZV(*this,x,y,z,v) res(x,v,y,z) = (t)*(ptrs++); 1.14537 + } 1.14538 + if (!cimg::strncasecmp(permut,"xvzy",4)) { 1.14539 + res.assign(width,dim,depth,height); 1.14540 + cimg_forXYZV(*this,x,y,z,v) res(x,v,z,y) = (t)*(ptrs++); 1.14541 + } 1.14542 + if (!cimg::strncasecmp(permut,"yxzv",4)) { 1.14543 + res.assign(height,width,depth,dim); 1.14544 + cimg_forXYZV(*this,x,y,z,v) res(y,x,z,v) = (t)*(ptrs++); 1.14545 + } 1.14546 + if (!cimg::strncasecmp(permut,"yxvz",4)) { 1.14547 + res.assign(height,width,dim,depth); 1.14548 + cimg_forXYZV(*this,x,y,z,v) res(y,x,v,z) = (t)*(ptrs++); 1.14549 + } 1.14550 + if (!cimg::strncasecmp(permut,"yzxv",4)) { 1.14551 + res.assign(height,depth,width,dim); 1.14552 + cimg_forXYZV(*this,x,y,z,v) res(y,z,x,v) = (t)*(ptrs++); 1.14553 + } 1.14554 + if (!cimg::strncasecmp(permut,"yzvx",4)) { 1.14555 + res.assign(height,depth,dim,width); 1.14556 + switch (width) { 1.14557 + case 1 : { 1.14558 + t *ptrR = res.ptr(0,0,0,0); 1.14559 + for (unsigned long siz = height*depth*dim; siz; --siz) { 1.14560 + *(ptrR++) = (t)*(ptrs++); 1.14561 + } 1.14562 + } break; 1.14563 + case 2 : { 1.14564 + t *ptrR = res.ptr(0,0,0,0), *ptrG = res.ptr(0,0,0,1); 1.14565 + for (unsigned long siz = height*depth*dim; siz; --siz) { 1.14566 + *(ptrR++) = (t)*(ptrs++); *(ptrG++) = (t)*(ptrs++); 1.14567 + } 1.14568 + } break; 1.14569 + case 3 : { // Optimization for the classical conversion from interleaved RGB to planar RGB 1.14570 + t *ptrR = res.ptr(0,0,0,0), *ptrG = res.ptr(0,0,0,1), *ptrB = res.ptr(0,0,0,2); 1.14571 + for (unsigned long siz = height*depth*dim; siz; --siz) { 1.14572 + *(ptrR++) = (t)*(ptrs++); *(ptrG++) = (t)*(ptrs++); *(ptrB++) = (t)*(ptrs++); 1.14573 + } 1.14574 + } break; 1.14575 + case 4 : { // Optimization for the classical conversion from interleaved RGBA to planar RGBA 1.14576 + t *ptrR = res.ptr(0,0,0,0), *ptrG = res.ptr(0,0,0,1), *ptrB = res.ptr(0,0,0,2), *ptrA = res.ptr(0,0,0,3); 1.14577 + for (unsigned long siz = height*depth*dim; siz; --siz) { 1.14578 + *(ptrR++) = (t)*(ptrs++); *(ptrG++) = (t)*(ptrs++); *(ptrB++) = (t)*(ptrs++); *(ptrA++) = (t)*(ptrs++); 1.14579 + } 1.14580 + } break; 1.14581 + default : { 1.14582 + cimg_forXYZV(*this,x,y,z,v) res(y,z,v,x) = *(ptrs++); 1.14583 + return res; 1.14584 + } 1.14585 + } 1.14586 + } 1.14587 + if (!cimg::strncasecmp(permut,"yvxz",4)) { 1.14588 + res.assign(height,dim,width,depth); 1.14589 + cimg_forXYZV(*this,x,y,z,v) res(y,v,x,z) = (t)*(ptrs++); 1.14590 + } 1.14591 + if (!cimg::strncasecmp(permut,"yvzx",4)) { 1.14592 + res.assign(height,dim,depth,width); 1.14593 + cimg_forXYZV(*this,x,y,z,v) res(y,v,z,x) = (t)*(ptrs++); 1.14594 + } 1.14595 + if (!cimg::strncasecmp(permut,"zxyv",4)) { 1.14596 + res.assign(depth,width,height,dim); 1.14597 + cimg_forXYZV(*this,x,y,z,v) res(z,x,y,v) = (t)*(ptrs++); 1.14598 + } 1.14599 + if (!cimg::strncasecmp(permut,"zxvy",4)) { 1.14600 + res.assign(depth,width,dim,height); 1.14601 + cimg_forXYZV(*this,x,y,z,v) res(z,x,v,y) = (t)*(ptrs++); 1.14602 + } 1.14603 + if (!cimg::strncasecmp(permut,"zyxv",4)) { 1.14604 + res.assign(depth,height,width,dim); 1.14605 + cimg_forXYZV(*this,x,y,z,v) res(z,y,x,v) = (t)*(ptrs++); 1.14606 + } 1.14607 + if (!cimg::strncasecmp(permut,"zyvx",4)) { 1.14608 + res.assign(depth,height,dim,width); 1.14609 + cimg_forXYZV(*this,x,y,z,v) res(z,y,v,x) = (t)*(ptrs++); 1.14610 + } 1.14611 + if (!cimg::strncasecmp(permut,"zvxy",4)) { 1.14612 + res.assign(depth,dim,width,height); 1.14613 + cimg_forXYZV(*this,x,y,z,v) res(z,v,x,y) = (t)*(ptrs++); 1.14614 + } 1.14615 + if (!cimg::strncasecmp(permut,"zvyx",4)) { 1.14616 + res.assign(depth,dim,height,width); 1.14617 + cimg_forXYZV(*this,x,y,z,v) res(z,v,y,x) = (t)*(ptrs++); 1.14618 + } 1.14619 + if (!cimg::strncasecmp(permut,"vxyz",4)) { 1.14620 + res.assign(dim,width,height,depth); 1.14621 + switch (dim) { 1.14622 + case 1 : { 1.14623 + const T *ptrR = ptr(0,0,0,0); 1.14624 + t *ptrd = res.ptr(); 1.14625 + for (unsigned long siz = width*height*depth; siz; --siz) { 1.14626 + *(ptrd++) = (t)*(ptrR++); 1.14627 + } 1.14628 + } break; 1.14629 + case 2 : { 1.14630 + const T *ptrR = ptr(0,0,0,0), *ptrG = ptr(0,0,0,1); 1.14631 + t *ptrd = res.ptr(); 1.14632 + for (unsigned long siz = width*height*depth; siz; --siz) { 1.14633 + *(ptrd++) = (t)*(ptrR++); *(ptrd++) = (t)*(ptrG++); 1.14634 + } 1.14635 + } break; 1.14636 + case 3 : { // Optimization for the classical conversion from planar RGB to interleaved RGB 1.14637 + const T *ptrR = ptr(0,0,0,0), *ptrG = ptr(0,0,0,1), *ptrB = ptr(0,0,0,2); 1.14638 + t *ptrd = res.ptr(); 1.14639 + for (unsigned long siz = width*height*depth; siz; --siz) { 1.14640 + *(ptrd++) = (t)*(ptrR++); *(ptrd++) = (t)*(ptrG++); *(ptrd++) = (t)*(ptrB++); 1.14641 + } 1.14642 + } break; 1.14643 + case 4 : { // Optimization for the classical conversion from planar RGBA to interleaved RGBA 1.14644 + const T *ptrR = ptr(0,0,0,0), *ptrG = ptr(0,0,0,1), *ptrB = ptr(0,0,0,2), *ptrA = ptr(0,0,0,3); 1.14645 + t *ptrd = res.ptr(); 1.14646 + for (unsigned long siz = width*height*depth; siz; --siz) { 1.14647 + *(ptrd++) = (t)*(ptrR++); *(ptrd++) = (t)*(ptrG++); *(ptrd++) = (t)*(ptrB++); *(ptrd++) = (t)*(ptrA++); 1.14648 + } 1.14649 + } break; 1.14650 + default : { 1.14651 + cimg_forXYZV(*this,x,y,z,v) res(v,x,y,z) = (t)*(ptrs++); 1.14652 + } 1.14653 + } 1.14654 + } 1.14655 + if (!cimg::strncasecmp(permut,"vxzy",4)) { 1.14656 + res.assign(dim,width,depth,height); 1.14657 + cimg_forXYZV(*this,x,y,z,v) res(v,x,z,y) = (t)*(ptrs++); 1.14658 + } 1.14659 + if (!cimg::strncasecmp(permut,"vyxz",4)) { 1.14660 + res.assign(dim,height,width,depth); 1.14661 + cimg_forXYZV(*this,x,y,z,v) res(v,y,x,z) = (t)*(ptrs++); 1.14662 + } 1.14663 + if (!cimg::strncasecmp(permut,"vyzx",4)) { 1.14664 + res.assign(dim,height,depth,width); 1.14665 + cimg_forXYZV(*this,x,y,z,v) res(v,y,z,x) = (t)*(ptrs++); 1.14666 + } 1.14667 + if (!cimg::strncasecmp(permut,"vzxy",4)) { 1.14668 + res.assign(dim,depth,width,height); 1.14669 + cimg_forXYZV(*this,x,y,z,v) res(v,z,x,y) = (t)*(ptrs++); 1.14670 + } 1.14671 + if (!cimg::strncasecmp(permut,"vzyx",4)) { 1.14672 + res.assign(dim,depth,height,width); 1.14673 + cimg_forXYZV(*this,x,y,z,v) res(v,z,y,x) = (t)*(ptrs++); 1.14674 + } 1.14675 + if (!res) 1.14676 + throw CImgArgumentException("CImg<%s>::permute_axes() : Invalid input permutation '%s'.", 1.14677 + pixel_type(),permut); 1.14678 + return res; 1.14679 + } 1.14680 + 1.14681 + //! Permute axes order. 1.14682 + /** 1.14683 + This function permutes image axes. 1.14684 + \param permut = String describing the permutation (4 characters). 1.14685 + **/ 1.14686 + CImg<T>& permute_axes(const char *order) { 1.14687 + return get_permute_axes(order).transfer_to(*this); 1.14688 + } 1.14689 + 1.14690 + CImg<T> get_permute_axes(const char *order) const { 1.14691 + const T foo = (T)0; 1.14692 + return _get_permute_axes(order,foo); 1.14693 + } 1.14694 + 1.14695 + //! Invert endianness. 1.14696 + CImg<T>& invert_endianness() { 1.14697 + cimg::invert_endianness(data,size()); 1.14698 + return *this; 1.14699 + } 1.14700 + 1.14701 + CImg<T> get_invert_endianness() const { 1.14702 + return (+*this).invert_endianness(); 1.14703 + } 1.14704 + 1.14705 + //! Mirror an image along the specified axis. 1.14706 + CImg<T>& mirror(const char axis) { 1.14707 + if (is_empty()) return *this; 1.14708 + T *pf, *pb, *buf = 0; 1.14709 + switch (cimg::uncase(axis)) { 1.14710 + case 'x' : { 1.14711 + pf = data; pb = ptr(width-1); 1.14712 + const unsigned int width2 = width/2; 1.14713 + for (unsigned int yzv = 0; yzv<height*depth*dim; ++yzv) { 1.14714 + for (unsigned int x = 0; x<width2; ++x) { const T val = *pf; *(pf++) = *pb; *(pb--) = val; } 1.14715 + pf+=width - width2; 1.14716 + pb+=width + width2; 1.14717 + } 1.14718 + } break; 1.14719 + case 'y' : { 1.14720 + buf = new T[width]; 1.14721 + pf = data; pb = ptr(0,height-1); 1.14722 + const unsigned int height2 = height/2; 1.14723 + for (unsigned int zv=0; zv<depth*dim; ++zv) { 1.14724 + for (unsigned int y=0; y<height2; ++y) { 1.14725 + cimg_std::memcpy(buf,pf,width*sizeof(T)); 1.14726 + cimg_std::memcpy(pf,pb,width*sizeof(T)); 1.14727 + cimg_std::memcpy(pb,buf,width*sizeof(T)); 1.14728 + pf+=width; 1.14729 + pb-=width; 1.14730 + } 1.14731 + pf+=width*(height - height2); 1.14732 + pb+=width*(height + height2); 1.14733 + } 1.14734 + } break; 1.14735 + case 'z' : { 1.14736 + buf = new T[width*height]; 1.14737 + pf = data; pb = ptr(0,0,depth-1); 1.14738 + const unsigned int depth2 = depth/2; 1.14739 + cimg_forV(*this,v) { 1.14740 + for (unsigned int z=0; z<depth2; ++z) { 1.14741 + cimg_std::memcpy(buf,pf,width*height*sizeof(T)); 1.14742 + cimg_std::memcpy(pf,pb,width*height*sizeof(T)); 1.14743 + cimg_std::memcpy(pb,buf,width*height*sizeof(T)); 1.14744 + pf+=width*height; 1.14745 + pb-=width*height; 1.14746 + } 1.14747 + pf+=width*height*(depth - depth2); 1.14748 + pb+=width*height*(depth + depth2); 1.14749 + } 1.14750 + } break; 1.14751 + case 'v' : { 1.14752 + buf = new T[width*height*depth]; 1.14753 + pf = data; pb = ptr(0,0,0,dim-1); 1.14754 + const unsigned int dim2 = dim/2; 1.14755 + for (unsigned int v=0; v<dim2; ++v) { 1.14756 + cimg_std::memcpy(buf,pf,width*height*depth*sizeof(T)); 1.14757 + cimg_std::memcpy(pf,pb,width*height*depth*sizeof(T)); 1.14758 + cimg_std::memcpy(pb,buf,width*height*depth*sizeof(T)); 1.14759 + pf+=width*height*depth; 1.14760 + pb-=width*height*depth; 1.14761 + } 1.14762 + } break; 1.14763 + default : 1.14764 + throw CImgArgumentException("CImg<%s>::mirror() : unknow axis '%c', must be 'x','y','z' or 'v'.", 1.14765 + pixel_type(),axis); 1.14766 + } 1.14767 + if (buf) delete[] buf; 1.14768 + return *this; 1.14769 + } 1.14770 + 1.14771 + CImg<T> get_mirror(const char axis) const { 1.14772 + return (+*this).mirror(axis); 1.14773 + } 1.14774 + 1.14775 + //! Translate the image. 1.14776 + /** 1.14777 + \param deltax Amount of displacement along the X-axis. 1.14778 + \param deltay Amount of displacement along the Y-axis. 1.14779 + \param deltaz Amount of displacement along the Z-axis. 1.14780 + \param deltav Amount of displacement along the V-axis. 1.14781 + \param border_condition Border condition. 1.14782 + 1.14783 + - \c border_condition can be : 1.14784 + - 0 : Zero border condition (Dirichlet). 1.14785 + - 1 : Nearest neighbors (Neumann). 1.14786 + - 2 : Repeat Pattern (Fourier style). 1.14787 + **/ 1.14788 + CImg<T>& translate(const int deltax, const int deltay=0, const int deltaz=0, const int deltav=0, 1.14789 + const int border_condition=0) { 1.14790 + if (is_empty()) return *this; 1.14791 + if (deltax) // Translate along X-axis 1.14792 + switch (border_condition) { 1.14793 + case 0 : 1.14794 + if (cimg::abs(deltax)>=dimx()) return fill(0); 1.14795 + if (deltax>0) cimg_forYZV(*this,y,z,k) { 1.14796 + cimg_std::memmove(ptr(0,y,z,k),ptr(deltax,y,z,k),(width-deltax)*sizeof(T)); 1.14797 + cimg_std::memset(ptr(width-deltax,y,z,k),0,deltax*sizeof(T)); 1.14798 + } else cimg_forYZV(*this,y,z,k) { 1.14799 + cimg_std::memmove(ptr(-deltax,y,z,k),ptr(0,y,z,k),(width+deltax)*sizeof(T)); 1.14800 + cimg_std::memset(ptr(0,y,z,k),0,-deltax*sizeof(T)); 1.14801 + } 1.14802 + break; 1.14803 + case 1 : 1.14804 + if (deltax>0) { 1.14805 + const int ndeltax = (deltax>=dimx())?width-1:deltax; 1.14806 + if (!ndeltax) return *this; 1.14807 + cimg_forYZV(*this,y,z,k) { 1.14808 + cimg_std::memmove(ptr(0,y,z,k),ptr(ndeltax,y,z,k),(width-ndeltax)*sizeof(T)); 1.14809 + T *ptrd = ptr(width-1,y,z,k); 1.14810 + const T val = *ptrd; 1.14811 + for (int l = 0; l<ndeltax-1; ++l) *(--ptrd) = val; 1.14812 + } 1.14813 + } else { 1.14814 + const int ndeltax = (-deltax>=dimx())?width-1:-deltax; 1.14815 + if (!ndeltax) return *this; 1.14816 + cimg_forYZV(*this,y,z,k) { 1.14817 + cimg_std::memmove(ptr(ndeltax,y,z,k),ptr(0,y,z,k),(width-ndeltax)*sizeof(T)); 1.14818 + T *ptrd = ptr(0,y,z,k); 1.14819 + const T val = *ptrd; 1.14820 + for (int l = 0; l<ndeltax-1; ++l) *(++ptrd) = val; 1.14821 + } 1.14822 + } 1.14823 + break; 1.14824 + case 2 : { 1.14825 + const int ml = cimg::mod(deltax,dimx()), ndeltax = (ml<=dimx()/2)?ml:(ml-dimx()); 1.14826 + if (!ndeltax) return *this; 1.14827 + T* buf = new T[cimg::abs(ndeltax)]; 1.14828 + if (ndeltax>0) cimg_forYZV(*this,y,z,k) { 1.14829 + cimg_std::memcpy(buf,ptr(0,y,z,k),ndeltax*sizeof(T)); 1.14830 + cimg_std::memmove(ptr(0,y,z,k),ptr(ndeltax,y,z,k),(width-ndeltax)*sizeof(T)); 1.14831 + cimg_std::memcpy(ptr(width-ndeltax,y,z,k),buf,ndeltax*sizeof(T)); 1.14832 + } else cimg_forYZV(*this,y,z,k) { 1.14833 + cimg_std::memcpy(buf,ptr(width+ndeltax,y,z,k),-ndeltax*sizeof(T)); 1.14834 + cimg_std::memmove(ptr(-ndeltax,y,z,k),ptr(0,y,z,k),(width+ndeltax)*sizeof(T)); 1.14835 + cimg_std::memcpy(ptr(0,y,z,k),buf,-ndeltax*sizeof(T)); 1.14836 + } 1.14837 + delete[] buf; 1.14838 + } break; 1.14839 + } 1.14840 + 1.14841 + if (deltay) // Translate along Y-axis 1.14842 + switch (border_condition) { 1.14843 + case 0 : 1.14844 + if (cimg::abs(deltay)>=dimy()) return fill(0); 1.14845 + if (deltay>0) cimg_forZV(*this,z,k) { 1.14846 + cimg_std::memmove(ptr(0,0,z,k),ptr(0,deltay,z,k),width*(height-deltay)*sizeof(T)); 1.14847 + cimg_std::memset(ptr(0,height-deltay,z,k),0,width*deltay*sizeof(T)); 1.14848 + } else cimg_forZV(*this,z,k) { 1.14849 + cimg_std::memmove(ptr(0,-deltay,z,k),ptr(0,0,z,k),width*(height+deltay)*sizeof(T)); 1.14850 + cimg_std::memset(ptr(0,0,z,k),0,-deltay*width*sizeof(T)); 1.14851 + } 1.14852 + break; 1.14853 + case 1 : 1.14854 + if (deltay>0) { 1.14855 + const int ndeltay = (deltay>=dimy())?height-1:deltay; 1.14856 + if (!ndeltay) return *this; 1.14857 + cimg_forZV(*this,z,k) { 1.14858 + cimg_std::memmove(ptr(0,0,z,k),ptr(0,ndeltay,z,k),width*(height-ndeltay)*sizeof(T)); 1.14859 + T *ptrd = ptr(0,height-ndeltay,z,k), *ptrs = ptr(0,height-1,z,k); 1.14860 + for (int l = 0; l<ndeltay-1; ++l) { cimg_std::memcpy(ptrd,ptrs,width*sizeof(T)); ptrd+=width; } 1.14861 + } 1.14862 + } else { 1.14863 + const int ndeltay = (-deltay>=dimy())?height-1:-deltay; 1.14864 + if (!ndeltay) return *this; 1.14865 + cimg_forZV(*this,z,k) { 1.14866 + cimg_std::memmove(ptr(0,ndeltay,z,k),ptr(0,0,z,k),width*(height-ndeltay)*sizeof(T)); 1.14867 + T *ptrd = ptr(0,1,z,k), *ptrs = ptr(0,0,z,k); 1.14868 + for (int l = 0; l<ndeltay-1; ++l) { cimg_std::memcpy(ptrd,ptrs,width*sizeof(T)); ptrd+=width; } 1.14869 + } 1.14870 + } 1.14871 + break; 1.14872 + case 2 : { 1.14873 + const int ml = cimg::mod(deltay,dimy()), ndeltay = (ml<=dimy()/2)?ml:(ml-dimy()); 1.14874 + if (!ndeltay) return *this; 1.14875 + T* buf = new T[width*cimg::abs(ndeltay)]; 1.14876 + if (ndeltay>0) cimg_forZV(*this,z,k) { 1.14877 + cimg_std::memcpy(buf,ptr(0,0,z,k),width*ndeltay*sizeof(T)); 1.14878 + cimg_std::memmove(ptr(0,0,z,k),ptr(0,ndeltay,z,k),width*(height-ndeltay)*sizeof(T)); 1.14879 + cimg_std::memcpy(ptr(0,height-ndeltay,z,k),buf,width*ndeltay*sizeof(T)); 1.14880 + } else cimg_forZV(*this,z,k) { 1.14881 + cimg_std::memcpy(buf,ptr(0,height+ndeltay,z,k),-ndeltay*width*sizeof(T)); 1.14882 + cimg_std::memmove(ptr(0,-ndeltay,z,k),ptr(0,0,z,k),width*(height+ndeltay)*sizeof(T)); 1.14883 + cimg_std::memcpy(ptr(0,0,z,k),buf,-ndeltay*width*sizeof(T)); 1.14884 + } 1.14885 + delete[] buf; 1.14886 + } break; 1.14887 + } 1.14888 + 1.14889 + if (deltaz) // Translate along Z-axis 1.14890 + switch (border_condition) { 1.14891 + case 0 : 1.14892 + if (cimg::abs(deltaz)>=dimz()) return fill(0); 1.14893 + if (deltaz>0) cimg_forV(*this,k) { 1.14894 + cimg_std::memmove(ptr(0,0,0,k),ptr(0,0,deltaz,k),width*height*(depth-deltaz)*sizeof(T)); 1.14895 + cimg_std::memset(ptr(0,0,depth-deltaz,k),0,width*height*deltaz*sizeof(T)); 1.14896 + } else cimg_forV(*this,k) { 1.14897 + cimg_std::memmove(ptr(0,0,-deltaz,k),ptr(0,0,0,k),width*height*(depth+deltaz)*sizeof(T)); 1.14898 + cimg_std::memset(ptr(0,0,0,k),0,-deltaz*width*height*sizeof(T)); 1.14899 + } 1.14900 + break; 1.14901 + case 1 : 1.14902 + if (deltaz>0) { 1.14903 + const int ndeltaz = (deltaz>=dimz())?depth-1:deltaz; 1.14904 + if (!ndeltaz) return *this; 1.14905 + cimg_forV(*this,k) { 1.14906 + cimg_std::memmove(ptr(0,0,0,k),ptr(0,0,ndeltaz,k),width*height*(depth-ndeltaz)*sizeof(T)); 1.14907 + T *ptrd = ptr(0,0,depth-ndeltaz,k), *ptrs = ptr(0,0,depth-1,k); 1.14908 + for (int l = 0; l<ndeltaz-1; ++l) { cimg_std::memcpy(ptrd,ptrs,width*height*sizeof(T)); ptrd+=width*height; } 1.14909 + } 1.14910 + } else { 1.14911 + const int ndeltaz = (-deltaz>=dimz())?depth-1:-deltaz; 1.14912 + if (!ndeltaz) return *this; 1.14913 + cimg_forV(*this,k) { 1.14914 + cimg_std::memmove(ptr(0,0,ndeltaz,k),ptr(0,0,0,k),width*height*(depth-ndeltaz)*sizeof(T)); 1.14915 + T *ptrd = ptr(0,0,1,k), *ptrs = ptr(0,0,0,k); 1.14916 + for (int l = 0; l<ndeltaz-1; ++l) { cimg_std::memcpy(ptrd,ptrs,width*height*sizeof(T)); ptrd+=width*height; } 1.14917 + } 1.14918 + } 1.14919 + break; 1.14920 + case 2 : { 1.14921 + const int ml = cimg::mod(deltaz,dimz()), ndeltaz = (ml<=dimz()/2)?ml:(ml-dimz()); 1.14922 + if (!ndeltaz) return *this; 1.14923 + T* buf = new T[width*height*cimg::abs(ndeltaz)]; 1.14924 + if (ndeltaz>0) cimg_forV(*this,k) { 1.14925 + cimg_std::memcpy(buf,ptr(0,0,0,k),width*height*ndeltaz*sizeof(T)); 1.14926 + cimg_std::memmove(ptr(0,0,0,k),ptr(0,0,ndeltaz,k),width*height*(depth-ndeltaz)*sizeof(T)); 1.14927 + cimg_std::memcpy(ptr(0,0,depth-ndeltaz,k),buf,width*height*ndeltaz*sizeof(T)); 1.14928 + } else cimg_forV(*this,k) { 1.14929 + cimg_std::memcpy(buf,ptr(0,0,depth+ndeltaz,k),-ndeltaz*width*height*sizeof(T)); 1.14930 + cimg_std::memmove(ptr(0,0,-ndeltaz,k),ptr(0,0,0,k),width*height*(depth+ndeltaz)*sizeof(T)); 1.14931 + cimg_std::memcpy(ptr(0,0,0,k),buf,-ndeltaz*width*height*sizeof(T)); 1.14932 + } 1.14933 + delete[] buf; 1.14934 + } break; 1.14935 + } 1.14936 + 1.14937 + if (deltav) // Translate along V-axis 1.14938 + switch (border_condition) { 1.14939 + case 0 : 1.14940 + if (cimg::abs(deltav)>=dimv()) return fill(0); 1.14941 + if (deltav>0) { 1.14942 + cimg_std::memmove(data,ptr(0,0,0,deltav),width*height*depth*(dim-deltav)*sizeof(T)); 1.14943 + cimg_std::memset(ptr(0,0,0,dim-deltav),0,width*height*depth*deltav*sizeof(T)); 1.14944 + } else cimg_forV(*this,k) { 1.14945 + cimg_std::memmove(ptr(0,0,0,-deltav),data,width*height*depth*(dim+deltav)*sizeof(T)); 1.14946 + cimg_std::memset(data,0,-deltav*width*height*depth*sizeof(T)); 1.14947 + } 1.14948 + break; 1.14949 + case 1 : 1.14950 + if (deltav>0) { 1.14951 + const int ndeltav = (deltav>=dimv())?dim-1:deltav; 1.14952 + if (!ndeltav) return *this; 1.14953 + cimg_std::memmove(data,ptr(0,0,0,ndeltav),width*height*depth*(dim-ndeltav)*sizeof(T)); 1.14954 + T *ptrd = ptr(0,0,0,dim-ndeltav), *ptrs = ptr(0,0,0,dim-1); 1.14955 + for (int l = 0; l<ndeltav-1; ++l) { cimg_std::memcpy(ptrd,ptrs,width*height*depth*sizeof(T)); ptrd+=width*height*depth; } 1.14956 + } else { 1.14957 + const int ndeltav = (-deltav>=dimv())?dim-1:-deltav; 1.14958 + if (!ndeltav) return *this; 1.14959 + cimg_std::memmove(ptr(0,0,0,ndeltav),data,width*height*depth*(dim-ndeltav)*sizeof(T)); 1.14960 + T *ptrd = ptr(0,0,0,1); 1.14961 + for (int l = 0; l<ndeltav-1; ++l) { cimg_std::memcpy(ptrd,data,width*height*depth*sizeof(T)); ptrd+=width*height*depth; } 1.14962 + } 1.14963 + break; 1.14964 + case 2 : { 1.14965 + const int ml = cimg::mod(deltav,dimv()), ndeltav = (ml<=dimv()/2)?ml:(ml-dimv()); 1.14966 + if (!ndeltav) return *this; 1.14967 + T* buf = new T[width*height*depth*cimg::abs(ndeltav)]; 1.14968 + if (ndeltav>0) { 1.14969 + cimg_std::memcpy(buf,data,width*height*depth*ndeltav*sizeof(T)); 1.14970 + cimg_std::memmove(data,ptr(0,0,0,ndeltav),width*height*depth*(dim-ndeltav)*sizeof(T)); 1.14971 + cimg_std::memcpy(ptr(0,0,0,dim-ndeltav),buf,width*height*depth*ndeltav*sizeof(T)); 1.14972 + } else { 1.14973 + cimg_std::memcpy(buf,ptr(0,0,0,dim+ndeltav),-ndeltav*width*height*depth*sizeof(T)); 1.14974 + cimg_std::memmove(ptr(0,0,0,-ndeltav),data,width*height*depth*(dim+ndeltav)*sizeof(T)); 1.14975 + cimg_std::memcpy(data,buf,-ndeltav*width*height*depth*sizeof(T)); 1.14976 + } 1.14977 + delete[] buf; 1.14978 + } break; 1.14979 + } 1.14980 + return *this; 1.14981 + } 1.14982 + 1.14983 + CImg<T> get_translate(const int deltax, const int deltay=0, const int deltaz=0, const int deltav=0, 1.14984 + const int border_condition=0) const { 1.14985 + return (+*this).translate(deltax,deltay,deltaz,deltav,border_condition); 1.14986 + } 1.14987 + 1.14988 + //! Get a square region of the image. 1.14989 + /** 1.14990 + \param x0 = X-coordinate of the upper-left crop rectangle corner. 1.14991 + \param y0 = Y-coordinate of the upper-left crop rectangle corner. 1.14992 + \param z0 = Z-coordinate of the upper-left crop rectangle corner. 1.14993 + \param v0 = V-coordinate of the upper-left crop rectangle corner. 1.14994 + \param x1 = X-coordinate of the lower-right crop rectangle corner. 1.14995 + \param y1 = Y-coordinate of the lower-right crop rectangle corner. 1.14996 + \param z1 = Z-coordinate of the lower-right crop rectangle corner. 1.14997 + \param v1 = V-coordinate of the lower-right crop rectangle corner. 1.14998 + \param border_condition = Dirichlet (false) or Neumann border conditions. 1.14999 + **/ 1.15000 + CImg<T>& crop(const int x0, const int y0, const int z0, const int v0, 1.15001 + const int x1, const int y1, const int z1, const int v1, 1.15002 + const bool border_condition=false) { 1.15003 + return get_crop(x0,y0,z0,v0,x1,y1,z1,v1,border_condition).transfer_to(*this); 1.15004 + } 1.15005 + 1.15006 + CImg<T> get_crop(const int x0, const int y0, const int z0, const int v0, 1.15007 + const int x1, const int y1, const int z1, const int v1, 1.15008 + const bool border_condition=false) const { 1.15009 + if (is_empty()) return *this; 1.15010 + const int 1.15011 + nx0 = x0<x1?x0:x1, nx1 = x0^x1^nx0, 1.15012 + ny0 = y0<y1?y0:y1, ny1 = y0^y1^ny0, 1.15013 + nz0 = z0<z1?z0:z1, nz1 = z0^z1^nz0, 1.15014 + nv0 = v0<v1?v0:v1, nv1 = v0^v1^nv0; 1.15015 + CImg<T> dest(1U+nx1-nx0,1U+ny1-ny0,1U+nz1-nz0,1U+nv1-nv0); 1.15016 + if (nx0<0 || nx1>=dimx() || ny0<0 || ny1>=dimy() || nz0<0 || nz1>=dimz() || nv0<0 || nv1>=dimv()) { 1.15017 + if (border_condition) cimg_forXYZV(dest,x,y,z,v) dest(x,y,z,v) = _atXYZV(nx0+x,ny0+y,nz0+z,nv0+v); 1.15018 + else dest.fill(0).draw_image(-nx0,-ny0,-nz0,-nv0,*this); 1.15019 + } else dest.draw_image(-nx0,-ny0,-nz0,-nv0,*this); 1.15020 + return dest; 1.15021 + } 1.15022 + 1.15023 + //! Get a rectangular part of the instance image. 1.15024 + /** 1.15025 + \param x0 = X-coordinate of the upper-left crop rectangle corner. 1.15026 + \param y0 = Y-coordinate of the upper-left crop rectangle corner. 1.15027 + \param z0 = Z-coordinate of the upper-left crop rectangle corner. 1.15028 + \param x1 = X-coordinate of the lower-right crop rectangle corner. 1.15029 + \param y1 = Y-coordinate of the lower-right crop rectangle corner. 1.15030 + \param z1 = Z-coordinate of the lower-right crop rectangle corner. 1.15031 + \param border_condition = determine the type of border condition if 1.15032 + some of the desired region is outside the image. 1.15033 + **/ 1.15034 + CImg<T>& crop(const int x0, const int y0, const int z0, 1.15035 + const int x1, const int y1, const int z1, 1.15036 + const bool border_condition=false) { 1.15037 + return crop(x0,y0,z0,0,x1,y1,z1,dim-1,border_condition); 1.15038 + } 1.15039 + 1.15040 + CImg<T> get_crop(const int x0, const int y0, const int z0, 1.15041 + const int x1, const int y1, const int z1, 1.15042 + const bool border_condition=false) const { 1.15043 + return get_crop(x0,y0,z0,0,x1,y1,z1,dim-1,border_condition); 1.15044 + } 1.15045 + 1.15046 + //! Get a rectangular part of the instance image. 1.15047 + /** 1.15048 + \param x0 = X-coordinate of the upper-left crop rectangle corner. 1.15049 + \param y0 = Y-coordinate of the upper-left crop rectangle corner. 1.15050 + \param x1 = X-coordinate of the lower-right crop rectangle corner. 1.15051 + \param y1 = Y-coordinate of the lower-right crop rectangle corner. 1.15052 + \param border_condition = determine the type of border condition if 1.15053 + some of the desired region is outside the image. 1.15054 + **/ 1.15055 + CImg<T>& crop(const int x0, const int y0, 1.15056 + const int x1, const int y1, 1.15057 + const bool border_condition=false) { 1.15058 + return crop(x0,y0,0,0,x1,y1,depth-1,dim-1,border_condition); 1.15059 + } 1.15060 + 1.15061 + CImg<T> get_crop(const int x0, const int y0, 1.15062 + const int x1, const int y1, 1.15063 + const bool border_condition=false) const { 1.15064 + return get_crop(x0,y0,0,0,x1,y1,depth-1,dim-1,border_condition); 1.15065 + } 1.15066 + 1.15067 + //! Get a rectangular part of the instance image. 1.15068 + /** 1.15069 + \param x0 = X-coordinate of the upper-left crop rectangle corner. 1.15070 + \param x1 = X-coordinate of the lower-right crop rectangle corner. 1.15071 + \param border_condition = determine the type of border condition if 1.15072 + some of the desired region is outside the image. 1.15073 + **/ 1.15074 + CImg<T>& crop(const int x0, const int x1, const bool border_condition=false) { 1.15075 + return crop(x0,0,0,0,x1,height-1,depth-1,dim-1,border_condition); 1.15076 + } 1.15077 + 1.15078 + CImg<T> get_crop(const int x0, const int x1, const bool border_condition=false) const { 1.15079 + return get_crop(x0,0,0,0,x1,height-1,depth-1,dim-1,border_condition); 1.15080 + } 1.15081 + 1.15082 + //! Autocrop an image, regarding of the specified backround value. 1.15083 + CImg<T>& autocrop(const T value, const char *const axes="vzyx") { 1.15084 + if (is_empty()) return *this; 1.15085 + const int lmax = cimg::strlen(axes); 1.15086 + for (int l = 0; l<lmax; ++l) autocrop(value,axes[l]); 1.15087 + return *this; 1.15088 + } 1.15089 + 1.15090 + CImg<T> get_autocrop(const T value, const char *const axes="vzyx") const { 1.15091 + return (+*this).autocrop(value,axes); 1.15092 + } 1.15093 + 1.15094 + //! Autocrop an image, regarding of the specified backround color. 1.15095 + CImg<T>& autocrop(const T *const color, const char *const axes="zyx") { 1.15096 + if (is_empty()) return *this; 1.15097 + const int lmax = cimg::strlen(axes); 1.15098 + for (int l = 0; l<lmax; ++l) autocrop(color,axes[l]); 1.15099 + return *this; 1.15100 + } 1.15101 + 1.15102 + CImg<T> get_autocrop(const T *const color, const char *const axes="zyx") const { 1.15103 + return (+*this).autocrop(color,axes); 1.15104 + } 1.15105 + 1.15106 + //! Autocrop an image, regarding of the specified backround color. 1.15107 + template<typename t> CImg<T>& autocrop(const CImg<t>& color, const char *const axes="zyx") { 1.15108 + return get_autocrop(color,axes).transfer_to(*this); 1.15109 + } 1.15110 + 1.15111 + template<typename t> CImg<T> get_autocrop(const CImg<t>& color, const char *const axes="zyx") const { 1.15112 + return get_autocrop(color.data,axes); 1.15113 + } 1.15114 + 1.15115 + //! Autocrop an image along specified axis, regarding of the specified backround value. 1.15116 + CImg<T>& autocrop(const T value, const char axis) { 1.15117 + return get_autocrop(value,axis).transfer_to(*this); 1.15118 + } 1.15119 + 1.15120 + CImg<T> get_autocrop(const T value, const char axis) const { 1.15121 + if (is_empty()) return *this; 1.15122 + CImg<T> res; 1.15123 + const CImg<intT> coords = _get_autocrop(value,axis); 1.15124 + switch (cimg::uncase(axis)) { 1.15125 + case 'x' : { 1.15126 + const int x0 = coords[0], x1 = coords[1]; 1.15127 + if (x0>=0 && x1>=0) res = get_crop(x0,x1); 1.15128 + } break; 1.15129 + case 'y' : { 1.15130 + const int y0 = coords[0], y1 = coords[1]; 1.15131 + if (y0>=0 && y1>=0) res = get_crop(0,y0,width-1,y1); 1.15132 + } break; 1.15133 + case 'z' : { 1.15134 + const int z0 = coords[0], z1 = coords[1]; 1.15135 + if (z0>=0 && z1>=0) res = get_crop(0,0,z0,width-1,height-1,z1); 1.15136 + } break; 1.15137 + case 'v' : { 1.15138 + const int v0 = coords[0], v1 = coords[1]; 1.15139 + if (v0>=0 && v1>=0) res = get_crop(0,0,0,v0,width-1,height-1,depth-1,v1); 1.15140 + } break; 1.15141 + } 1.15142 + return res; 1.15143 + } 1.15144 + 1.15145 + //! Autocrop an image along specified axis, regarding of the specified backround color. 1.15146 + CImg<T>& autocrop(const T *const color, const char axis) { 1.15147 + return get_autocrop(color,axis).transfer_to(*this); 1.15148 + } 1.15149 + 1.15150 + CImg<T> get_autocrop(const T *const color, const char axis) const { 1.15151 + if (is_empty()) return *this; 1.15152 + CImg<T> res; 1.15153 + switch (cimg::uncase(axis)) { 1.15154 + case 'x' : { 1.15155 + int x0 = width, x1 = -1; 1.15156 + cimg_forV(*this,k) { 1.15157 + const CImg<intT> coords = get_shared_channel(k)._get_autocrop(color[k],axis); 1.15158 + const int nx0 = coords[0], nx1 = coords[1]; 1.15159 + if (nx0>=0 && nx1>=0) { x0 = cimg::min(x0,nx0); x1 = cimg::max(x1,nx1); } 1.15160 + } 1.15161 + if (x0<=x1) res = get_crop(x0,x1); 1.15162 + } break; 1.15163 + case 'y' : { 1.15164 + int y0 = height, y1 = -1; 1.15165 + cimg_forV(*this,k) { 1.15166 + const CImg<intT> coords = get_shared_channel(k)._get_autocrop(color[k],axis); 1.15167 + const int ny0 = coords[0], ny1 = coords[1]; 1.15168 + if (ny0>=0 && ny1>=0) { y0 = cimg::min(y0,ny0); y1 = cimg::max(y1,ny1); } 1.15169 + } 1.15170 + if (y0<=y1) res = get_crop(0,y0,width-1,y1); 1.15171 + } break; 1.15172 + case 'z' : { 1.15173 + int z0 = depth, z1 = -1; 1.15174 + cimg_forV(*this,k) { 1.15175 + const CImg<intT> coords = get_shared_channel(k)._get_autocrop(color[k],axis); 1.15176 + const int nz0 = coords[0], nz1 = coords[1]; 1.15177 + if (nz0>=0 && nz1>=0) { z0 = cimg::min(z0,nz0); z1 = cimg::max(z1,nz1); } 1.15178 + } 1.15179 + if (z0<=z1) res = get_crop(0,0,z0,width-1,height-1,z1); 1.15180 + } break; 1.15181 + default : 1.15182 + throw CImgArgumentException("CImg<%s>::autocrop() : Invalid axis '%c', must be 'x','y' or 'z'.", 1.15183 + pixel_type(),axis); 1.15184 + } 1.15185 + return res; 1.15186 + } 1.15187 + 1.15188 + //! Autocrop an image along specified axis, regarding of the specified backround color. 1.15189 + template<typename t> CImg<T>& autocrop(const CImg<t>& color, const char axis) { 1.15190 + return get_autocrop(color,axis).transfer_to(*this); 1.15191 + } 1.15192 + 1.15193 + template<typename t> CImg<T> get_autocrop(const CImg<t>& color, const char axis) const { 1.15194 + return get_autocrop(color.data,axis); 1.15195 + } 1.15196 + 1.15197 + CImg<intT> _get_autocrop(const T value, const char axis) const { 1.15198 + CImg<intT> res; 1.15199 + int x0 = -1, y0 = -1, z0 = -1, v0 = -1, x1 = -1, y1 = -1, z1 = -1, v1 = -1; 1.15200 + switch (cimg::uncase(axis)) { 1.15201 + case 'x' : { 1.15202 + cimg_forX(*this,x) cimg_forYZV(*this,y,z,v) 1.15203 + if ((*this)(x,y,z,v)!=value) { x0 = x; x = dimx(); y = dimy(); z = dimz(); v = dimv(); } 1.15204 + if (x0>=0) { 1.15205 + for (int x = dimx()-1; x>=0; --x) cimg_forYZV(*this,y,z,v) 1.15206 + if ((*this)(x,y,z,v)!=value) { x1 = x; x = 0; y = dimy(); z = dimz(); v = dimv(); } 1.15207 + } 1.15208 + res = CImg<intT>::vector(x0,x1); 1.15209 + } break; 1.15210 + case 'y' : { 1.15211 + cimg_forY(*this,y) cimg_forXZV(*this,x,z,v) 1.15212 + if ((*this)(x,y,z,v)!=value) { y0 = y; x = dimx(); y = dimy(); z = dimz(); v = dimv(); } 1.15213 + if (y0>=0) { 1.15214 + for (int y = dimy()-1; y>=0; --y) cimg_forXZV(*this,x,z,v) 1.15215 + if ((*this)(x,y,z,v)!=value) { y1 = y; x = dimx(); y = 0; z = dimz(); v = dimv(); } 1.15216 + } 1.15217 + res = CImg<intT>::vector(y0,y1); 1.15218 + } break; 1.15219 + case 'z' : { 1.15220 + cimg_forZ(*this,z) cimg_forXYV(*this,x,y,v) 1.15221 + if ((*this)(x,y,z,v)!=value) { z0 = z; x = dimx(); y = dimy(); z = dimz(); v = dimv(); } 1.15222 + if (z0>=0) { 1.15223 + for (int z = dimz()-1; z>=0; --z) cimg_forXYV(*this,x,y,v) 1.15224 + if ((*this)(x,y,z,v)!=value) { z1 = z; x = dimx(); y = dimy(); z = 0; v = dimv(); } 1.15225 + } 1.15226 + res = CImg<intT>::vector(z0,z1); 1.15227 + } break; 1.15228 + case 'v' : { 1.15229 + cimg_forV(*this,v) cimg_forXYZ(*this,x,y,z) 1.15230 + if ((*this)(x,y,z,v)!=value) { v0 = v; x = dimx(); y = dimy(); z = dimz(); v = dimv(); } 1.15231 + if (v0>=0) { 1.15232 + for (int v = dimv()-1; v>=0; --v) cimg_forXYZ(*this,x,y,z) 1.15233 + if ((*this)(x,y,z,v)!=value) { v1 = v; x = dimx(); y = dimy(); z = dimz(); v = 0; } 1.15234 + } 1.15235 + res = CImg<intT>::vector(v0,v1); 1.15236 + } break; 1.15237 + default : 1.15238 + throw CImgArgumentException("CImg<%s>::autocrop() : unknow axis '%c', must be 'x','y','z' or 'v'", 1.15239 + pixel_type(),axis); 1.15240 + } 1.15241 + return res; 1.15242 + } 1.15243 + 1.15244 + //! Get a set of columns. 1.15245 + CImg<T>& columns(const unsigned int x0, const unsigned int x1) { 1.15246 + return get_columns(x0,x1).transfer_to(*this); 1.15247 + } 1.15248 + 1.15249 + CImg<T> get_columns(const unsigned int x0, const unsigned int x1) const { 1.15250 + return get_crop((int)x0,0,0,0,(int)x1,dimy()-1,dimz()-1,dimv()-1); 1.15251 + } 1.15252 + 1.15253 + //! Get one column. 1.15254 + CImg<T>& column(const unsigned int x0) { 1.15255 + return columns(x0,x0); 1.15256 + } 1.15257 + 1.15258 + CImg<T> get_column(const unsigned int x0) const { 1.15259 + return get_columns(x0,x0); 1.15260 + } 1.15261 + 1.15262 + //! Get a set of lines. 1.15263 + CImg<T>& lines(const unsigned int y0, const unsigned int y1) { 1.15264 + return get_lines(y0,y1).transfer_to(*this); 1.15265 + } 1.15266 + 1.15267 + CImg<T> get_lines(const unsigned int y0, const unsigned int y1) const { 1.15268 + return get_crop(0,(int)y0,0,0,dimx()-1,(int)y1,dimz()-1,dimv()-1); 1.15269 + } 1.15270 + 1.15271 + //! Get a line. 1.15272 + CImg<T>& line(const unsigned int y0) { 1.15273 + return lines(y0,y0); 1.15274 + } 1.15275 + 1.15276 + CImg<T> get_line(const unsigned int y0) const { 1.15277 + return get_lines(y0,y0); 1.15278 + } 1.15279 + 1.15280 + //! Get a set of slices. 1.15281 + CImg<T>& slices(const unsigned int z0, const unsigned int z1) { 1.15282 + return get_slices(z0,z1).transfer_to(*this); 1.15283 + } 1.15284 + 1.15285 + CImg<T> get_slices(const unsigned int z0, const unsigned int z1) const { 1.15286 + return get_crop(0,0,(int)z0,0,dimx()-1,dimy()-1,(int)z1,dimv()-1); 1.15287 + } 1.15288 + 1.15289 + //! Get a slice. 1.15290 + CImg<T>& slice(const unsigned int z0) { 1.15291 + return slices(z0,z0); 1.15292 + } 1.15293 + 1.15294 + CImg<T> get_slice(const unsigned int z0) const { 1.15295 + return get_slices(z0,z0); 1.15296 + } 1.15297 + 1.15298 + //! Get a set of channels. 1.15299 + CImg<T>& channels(const unsigned int v0, const unsigned int v1) { 1.15300 + return get_channels(v0,v1).transfer_to(*this); 1.15301 + } 1.15302 + 1.15303 + CImg<T> get_channels(const unsigned int v0, const unsigned int v1) const { 1.15304 + return get_crop(0,0,0,(int)v0,dimx()-1,dimy()-1,dimz()-1,(int)v1); 1.15305 + } 1.15306 + 1.15307 + //! Get a channel. 1.15308 + CImg<T>& channel(const unsigned int v0) { 1.15309 + return channels(v0,v0); 1.15310 + } 1.15311 + 1.15312 + CImg<T> get_channel(const unsigned int v0) const { 1.15313 + return get_channels(v0,v0); 1.15314 + } 1.15315 + 1.15316 + //! Get a shared-memory image referencing a set of points of the instance image. 1.15317 + CImg<T> get_shared_points(const unsigned int x0, const unsigned int x1, 1.15318 + const unsigned int y0=0, const unsigned int z0=0, const unsigned int v0=0) { 1.15319 + const unsigned long beg = offset(x0,y0,z0,v0), end = offset(x1,y0,z0,v0); 1.15320 + if (beg>end || beg>=size() || end>=size()) 1.15321 + throw CImgArgumentException("CImg<%s>::get_shared_points() : Cannot return a shared-memory subset (%u->%u,%u,%u,%u) from " 1.15322 + "a (%u,%u,%u,%u) image.", 1.15323 + pixel_type(),x0,x1,y0,z0,v0,width,height,depth,dim); 1.15324 + return CImg<T>(data+beg,x1-x0+1,1,1,1,true); 1.15325 + } 1.15326 + 1.15327 + const CImg<T> get_shared_points(const unsigned int x0, const unsigned int x1, 1.15328 + const unsigned int y0=0, const unsigned int z0=0, const unsigned int v0=0) const { 1.15329 + const unsigned long beg = offset(x0,y0,z0,v0), end = offset(x1,y0,z0,v0); 1.15330 + if (beg>end || beg>=size() || end>=size()) 1.15331 + throw CImgArgumentException("CImg<%s>::get_shared_points() : Cannot return a shared-memory subset (%u->%u,%u,%u,%u) from " 1.15332 + "a (%u,%u,%u,%u) image.", 1.15333 + pixel_type(),x0,x1,y0,z0,v0,width,height,depth,dim); 1.15334 + return CImg<T>(data+beg,x1-x0+1,1,1,1,true); 1.15335 + } 1.15336 + 1.15337 + //! Return a shared-memory image referencing a set of lines of the instance image. 1.15338 + CImg<T> get_shared_lines(const unsigned int y0, const unsigned int y1, 1.15339 + const unsigned int z0=0, const unsigned int v0=0) { 1.15340 + const unsigned long beg = offset(0,y0,z0,v0), end = offset(0,y1,z0,v0); 1.15341 + if (beg>end || beg>=size() || end>=size()) 1.15342 + throw CImgArgumentException("CImg<%s>::get_shared_lines() : Cannot return a shared-memory subset (0->%u,%u->%u,%u,%u) from " 1.15343 + "a (%u,%u,%u,%u) image.", 1.15344 + pixel_type(),width-1,y0,y1,z0,v0,width,height,depth,dim); 1.15345 + return CImg<T>(data+beg,width,y1-y0+1,1,1,true); 1.15346 + } 1.15347 + 1.15348 + const CImg<T> get_shared_lines(const unsigned int y0, const unsigned int y1, 1.15349 + const unsigned int z0=0, const unsigned int v0=0) const { 1.15350 + const unsigned long beg = offset(0,y0,z0,v0), end = offset(0,y1,z0,v0); 1.15351 + if (beg>end || beg>=size() || end>=size()) 1.15352 + throw CImgArgumentException("CImg<%s>::get_shared_lines() : Cannot return a shared-memory subset (0->%u,%u->%u,%u,%u) from " 1.15353 + "a (%u,%u,%u,%u) image.", 1.15354 + pixel_type(),width-1,y0,y1,z0,v0,width,height,depth,dim); 1.15355 + return CImg<T>(data+beg,width,y1-y0+1,1,1,true); 1.15356 + } 1.15357 + 1.15358 + //! Return a shared-memory image referencing one particular line (y0,z0,v0) of the instance image. 1.15359 + CImg<T> get_shared_line(const unsigned int y0, const unsigned int z0=0, const unsigned int v0=0) { 1.15360 + return get_shared_lines(y0,y0,z0,v0); 1.15361 + } 1.15362 + 1.15363 + const CImg<T> get_shared_line(const unsigned int y0, const unsigned int z0=0, const unsigned int v0=0) const { 1.15364 + return get_shared_lines(y0,y0,z0,v0); 1.15365 + } 1.15366 + 1.15367 + //! Return a shared memory image referencing a set of planes (z0->z1,v0) of the instance image. 1.15368 + CImg<T> get_shared_planes(const unsigned int z0, const unsigned int z1, const unsigned int v0=0) { 1.15369 + const unsigned long beg = offset(0,0,z0,v0), end = offset(0,0,z1,v0); 1.15370 + if (beg>end || beg>=size() || end>=size()) 1.15371 + throw CImgArgumentException("CImg<%s>::get_shared_planes() : Cannot return a shared-memory subset (0->%u,0->%u,%u->%u,%u) from " 1.15372 + "a (%u,%u,%u,%u) image.", 1.15373 + pixel_type(),width-1,height-1,z0,z1,v0,width,height,depth,dim); 1.15374 + return CImg<T>(data+beg,width,height,z1-z0+1,1,true); 1.15375 + } 1.15376 + 1.15377 + const CImg<T> get_shared_planes(const unsigned int z0, const unsigned int z1, const unsigned int v0=0) const { 1.15378 + const unsigned long beg = offset(0,0,z0,v0), end = offset(0,0,z1,v0); 1.15379 + if (beg>end || beg>=size() || end>=size()) 1.15380 + throw CImgArgumentException("CImg<%s>::get_shared_planes() : Cannot return a shared-memory subset (0->%u,0->%u,%u->%u,%u) from " 1.15381 + "a (%u,%u,%u,%u) image.", 1.15382 + pixel_type(),width-1,height-1,z0,z1,v0,width,height,depth,dim); 1.15383 + return CImg<T>(data+beg,width,height,z1-z0+1,1,true); 1.15384 + } 1.15385 + 1.15386 + //! Return a shared-memory image referencing one plane (z0,v0) of the instance image. 1.15387 + CImg<T> get_shared_plane(const unsigned int z0, const unsigned int v0=0) { 1.15388 + return get_shared_planes(z0,z0,v0); 1.15389 + } 1.15390 + 1.15391 + const CImg<T> get_shared_plane(const unsigned int z0, const unsigned int v0=0) const { 1.15392 + return get_shared_planes(z0,z0,v0); 1.15393 + } 1.15394 + 1.15395 + //! Return a shared-memory image referencing a set of channels (v0->v1) of the instance image. 1.15396 + CImg<T> get_shared_channels(const unsigned int v0, const unsigned int v1) { 1.15397 + const unsigned long beg = offset(0,0,0,v0), end = offset(0,0,0,v1); 1.15398 + if (beg>end || beg>=size() || end>=size()) 1.15399 + throw CImgArgumentException("CImg<%s>::get_shared_channels() : Cannot return a shared-memory subset (0->%u,0->%u,0->%u,%u->%u) from " 1.15400 + "a (%u,%u,%u,%u) image.", 1.15401 + pixel_type(),width-1,height-1,depth-1,v0,v1,width,height,depth,dim); 1.15402 + return CImg<T>(data+beg,width,height,depth,v1-v0+1,true); 1.15403 + } 1.15404 + 1.15405 + const CImg<T> get_shared_channels(const unsigned int v0, const unsigned int v1) const { 1.15406 + const unsigned long beg = offset(0,0,0,v0), end = offset(0,0,0,v1); 1.15407 + if (beg>end || beg>=size() || end>=size()) 1.15408 + throw CImgArgumentException("CImg<%s>::get_shared_channels() : Cannot return a shared-memory subset (0->%u,0->%u,0->%u,%u->%u) from " 1.15409 + "a (%u,%u,%u,%u) image.", 1.15410 + pixel_type(),width-1,height-1,depth-1,v0,v1,width,height,depth,dim); 1.15411 + return CImg<T>(data+beg,width,height,depth,v1-v0+1,true); 1.15412 + } 1.15413 + 1.15414 + //! Return a shared-memory image referencing one channel v0 of the instance image. 1.15415 + CImg<T> get_shared_channel(const unsigned int v0) { 1.15416 + return get_shared_channels(v0,v0); 1.15417 + } 1.15418 + 1.15419 + const CImg<T> get_shared_channel(const unsigned int v0) const { 1.15420 + return get_shared_channels(v0,v0); 1.15421 + } 1.15422 + 1.15423 + //! Return a shared version of the instance image. 1.15424 + CImg<T> get_shared() { 1.15425 + return CImg<T>(data,width,height,depth,dim,true); 1.15426 + } 1.15427 + 1.15428 + const CImg<T> get_shared() const { 1.15429 + return CImg<T>(data,width,height,depth,dim,true); 1.15430 + } 1.15431 + 1.15432 + //! Return a 2D representation of a 3D image, with three slices. 1.15433 + CImg<T>& projections2d(const unsigned int x0, const unsigned int y0, const unsigned int z0, 1.15434 + const int dx=-100, const int dy=-100, const int dz=-100) { 1.15435 + return get_projections2d(x0,y0,z0,dx,dy,dz).transfer_to(*this); 1.15436 + } 1.15437 + 1.15438 + CImg<T> get_projections2d(const unsigned int x0, const unsigned int y0, const unsigned int z0, 1.15439 + const int dx=-100, const int dy=-100, const int dz=-100) const { 1.15440 + if (is_empty()) return *this; 1.15441 + const unsigned int 1.15442 + nx0 = (x0>=width)?width-1:x0, 1.15443 + ny0 = (y0>=height)?height-1:y0, 1.15444 + nz0 = (z0>=depth)?depth-1:z0; 1.15445 + CImg<T> 1.15446 + imgxy(width,height,1,dim), 1.15447 + imgzy(depth,height,1,dim), 1.15448 + imgxz(width,depth,1,dim); 1.15449 + { cimg_forXYV(*this,x,y,k) imgxy(x,y,k) = (*this)(x,y,nz0,k); } 1.15450 + { cimg_forYZV(*this,y,z,k) imgzy(z,y,k) = (*this)(nx0,y,z,k); } 1.15451 + { cimg_forXZV(*this,x,z,k) imgxz(x,z,k) = (*this)(x,ny0,z,k); } 1.15452 + imgxy.resize(dx,dy,1,dim,1); 1.15453 + imgzy.resize(dz,dy,1,dim,1); 1.15454 + imgxz.resize(dx,dz,1,dim,1); 1.15455 + return CImg<T>(imgxy.width+imgzy.width,imgxy.height+imgxz.height,1,dim,0). 1.15456 + draw_image(imgxy).draw_image(imgxy.width,imgzy).draw_image(0,imgxy.height,imgxz); 1.15457 + } 1.15458 + 1.15459 + //! Compute the image histogram. 1.15460 + /** 1.15461 + The histogram H of an image I is a 1D-function where H(x) is the number of 1.15462 + occurences of the value x in I. 1.15463 + \param nblevels = Number of different levels of the computed histogram. 1.15464 + For classical images, this value is 256. You should specify more levels 1.15465 + if you are working with CImg<float> or images with high range of pixel values. 1.15466 + \param val_min = Minimum value considered for the histogram computation. All pixel values lower than val_min 1.15467 + won't be counted. 1.15468 + \param val_max = Maximum value considered for the histogram computation. All pixel values higher than val_max 1.15469 + won't be counted. 1.15470 + \note If val_min==val_max==0 (default values), the function first estimates the minimum and maximum 1.15471 + pixel values of the current image, then uses these values for the histogram computation. 1.15472 + \result The histogram is returned as a 1D CImg<float> image H, having a size of (nblevels,1,1,1) such that 1.15473 + H(0) and H(nblevels-1) are respectively equal to the number of occurences of the values val_min and val_max in I. 1.15474 + \note Histogram computation always returns a 1D function. Histogram of multi-valued (such as color) images 1.15475 + are not multi-dimensional. 1.15476 + **/ 1.15477 + CImg<T>& histogram(const unsigned int nblevels, const T val_min=(T)0, const T val_max=(T)0) { 1.15478 + return get_histogram(nblevels,val_min,val_max).transfer_to(*this); 1.15479 + } 1.15480 + 1.15481 + CImg<floatT> get_histogram(const unsigned int nblevels, const T val_min=(T)0, const T val_max=(T)0) const { 1.15482 + if (is_empty()) return CImg<floatT>(); 1.15483 + if (!nblevels) 1.15484 + throw CImgArgumentException("CImg<%s>::get_histogram() : Can't compute an histogram with 0 levels", 1.15485 + pixel_type()); 1.15486 + T vmin = val_min, vmax = val_max; 1.15487 + CImg<floatT> res(nblevels,1,1,1,0); 1.15488 + if (vmin>=vmax && vmin==0) vmin = minmax(vmax); 1.15489 + if (vmin<vmax) cimg_for(*this,ptr,T) { 1.15490 + const int pos = (int)((*ptr-vmin)*(nblevels-1)/(vmax-vmin)); 1.15491 + if (pos>=0 && pos<(int)nblevels) ++res[pos]; 1.15492 + } else res[0]+=size(); 1.15493 + return res; 1.15494 + } 1.15495 + 1.15496 + //! Compute the histogram-equalized version of the instance image. 1.15497 + /** 1.15498 + The histogram equalization is a classical image processing algorithm that enhances the image contrast 1.15499 + by expanding its histogram. 1.15500 + \param nblevels = Number of different levels of the computed histogram. 1.15501 + For classical images, this value is 256. You should specify more levels 1.15502 + if you are working with CImg<float> or images with high range of pixel values. 1.15503 + \param val_min = Minimum value considered for the histogram computation. All pixel values lower than val_min 1.15504 + won't be changed. 1.15505 + \param val_max = Maximum value considered for the histogram computation. All pixel values higher than val_max 1.15506 + won't be changed. 1.15507 + \note If val_min==val_max==0 (default values), the function acts on all pixel values of the image. 1.15508 + \return A new image with same size is returned, where pixels have been equalized. 1.15509 + **/ 1.15510 + CImg<T>& equalize(const unsigned int nblevels, const T val_min=(T)0, const T val_max=(T)0) { 1.15511 + if (is_empty()) return *this; 1.15512 + T vmin = val_min, vmax = val_max; 1.15513 + if (vmin==vmax && vmin==0) vmin = minmax(vmax); 1.15514 + if (vmin<vmax) { 1.15515 + CImg<floatT> hist = get_histogram(nblevels,vmin,vmax); 1.15516 + float cumul = 0; 1.15517 + cimg_forX(hist,pos) { cumul+=hist[pos]; hist[pos]=cumul; } 1.15518 + cimg_for(*this,ptr,T) { 1.15519 + const int pos = (unsigned int)((*ptr-vmin)*(nblevels-1)/(vmax-vmin)); 1.15520 + if (pos>=0 && pos<(int)nblevels) *ptr = (T)(vmin + (vmax-vmin)*hist[pos]/size()); 1.15521 + } 1.15522 + } 1.15523 + return *this; 1.15524 + } 1.15525 + 1.15526 + CImg<T> get_equalize(const unsigned int nblevels, const T val_min=(T)0, const T val_max=(T)0) const { 1.15527 + return (+*this).equalize(nblevels,val_min,val_max); 1.15528 + } 1.15529 + 1.15530 + //! Get a label map of disconnected regions with same intensities. 1.15531 + CImg<T>& label_regions() { 1.15532 + return get_label_regions().transfer_to(*this); 1.15533 + } 1.15534 + 1.15535 + CImg<uintT> get_label_regions() const { 1.15536 +#define _cimg_get_label_test(p,q) { \ 1.15537 + flag = true; \ 1.15538 + const T *ptr1 = ptr(x,y) + siz, *ptr2 = ptr(p,q) + siz; \ 1.15539 + for (unsigned int i = dim; flag && i; --i) { ptr1-=wh; ptr2-=wh; flag = (*ptr1==*ptr2); } \ 1.15540 +} 1.15541 + if (depth>1) 1.15542 + throw CImgInstanceException("CImg<%s>::label_regions() : Instance image must be a 2D image"); 1.15543 + CImg<uintT> res(width,height,depth,1,0); 1.15544 + unsigned int label = 1; 1.15545 + const unsigned int wh = width*height, siz = width*height*dim; 1.15546 + const int W1 = dimx()-1, H1 = dimy()-1; 1.15547 + bool flag; 1.15548 + cimg_forXY(*this,x,y) { 1.15549 + bool done = false; 1.15550 + if (y) { 1.15551 + _cimg_get_label_test(x,y-1); 1.15552 + if (flag) { 1.15553 + const unsigned int lab = (res(x,y) = res(x,y-1)); 1.15554 + done = true; 1.15555 + if (x && res(x-1,y)!=lab) { 1.15556 + _cimg_get_label_test(x-1,y); 1.15557 + if (flag) { 1.15558 + const unsigned int lold = res(x-1,y), *const cptr = res.ptr(x,y); 1.15559 + for (unsigned int *ptr = res.ptr(); ptr<cptr; ++ptr) if (*ptr==lold) *ptr = lab; 1.15560 + } 1.15561 + } 1.15562 + } 1.15563 + } 1.15564 + if (x && !done) { _cimg_get_label_test(x-1,y); if (flag) { res(x,y) = res(x-1,y); done = true; }} 1.15565 + if (!done) res(x,y) = label++; 1.15566 + } 1.15567 + { for (int y = H1; y>=0; --y) for (int x=W1; x>=0; --x) { 1.15568 + bool done = false; 1.15569 + if (y<H1) { 1.15570 + _cimg_get_label_test(x,y+1); 1.15571 + if (flag) { 1.15572 + const unsigned int lab = (res(x,y) = res(x,y+1)); 1.15573 + done = true; 1.15574 + if (x<W1 && res(x+1,y)!=lab) { 1.15575 + _cimg_get_label_test(x+1,y); 1.15576 + if (flag) { 1.15577 + const unsigned int lold = res(x+1,y), *const cptr = res.ptr(x,y); 1.15578 + for (unsigned int *ptr = res.ptr()+res.size()-1; ptr>cptr; --ptr) if (*ptr==lold) *ptr = lab; 1.15579 + } 1.15580 + } 1.15581 + } 1.15582 + } 1.15583 + if (x<W1 && !done) { _cimg_get_label_test(x+1,y); if (flag) res(x,y) = res(x+1,y); done = true; } 1.15584 + }} 1.15585 + const unsigned int lab0 = res.max()+1; 1.15586 + label = lab0; 1.15587 + cimg_foroff(res,off) { // Relabel regions 1.15588 + const unsigned int lab = res[off]; 1.15589 + if (lab<lab0) { cimg_for(res,ptr,unsigned int) if (*ptr==lab) *ptr = label; ++label; } 1.15590 + } 1.15591 + return (res-=lab0); 1.15592 + } 1.15593 + 1.15594 + //! Compute the scalar image of vector norms. 1.15595 + /** 1.15596 + When dealing with vector-valued images (i.e images with dimv()>1), this function computes the L1,L2 or Linf norm of each 1.15597 + vector-valued pixel. 1.15598 + \param norm_type = Type of the norm being computed (1 = L1, 2 = L2, -1 = Linf). 1.15599 + \return A scalar-valued image CImg<float> with size (dimx(),dimy(),dimz(),1), where each pixel is the norm 1.15600 + of the corresponding pixels in the original vector-valued image. 1.15601 + **/ 1.15602 + CImg<T>& pointwise_norm(int norm_type=2) { 1.15603 + return get_pointwise_norm(norm_type).transfer_to(*this); 1.15604 + } 1.15605 + 1.15606 + CImg<Tfloat> get_pointwise_norm(int norm_type=2) const { 1.15607 + if (is_empty()) return *this; 1.15608 + if (dim==1) return get_abs(); 1.15609 + CImg<Tfloat> res(width,height,depth); 1.15610 + switch (norm_type) { 1.15611 + case -1 : { // Linf norm 1.15612 + cimg_forXYZ(*this,x,y,z) { 1.15613 + Tfloat n = 0; cimg_forV(*this,v) { 1.15614 + const Tfloat tmp = (Tfloat)cimg::abs((*this)(x,y,z,v)); 1.15615 + if (tmp>n) n=tmp; res(x,y,z) = n; 1.15616 + } 1.15617 + } 1.15618 + } break; 1.15619 + case 1 : { // L1 norm 1.15620 + cimg_forXYZ(*this,x,y,z) { 1.15621 + Tfloat n = 0; cimg_forV(*this,v) n+=cimg::abs((*this)(x,y,z,v)); res(x,y,z) = n; 1.15622 + } 1.15623 + } break; 1.15624 + default : { // L2 norm 1.15625 + cimg_forXYZ(*this,x,y,z) { 1.15626 + Tfloat n = 0; cimg_forV(*this,v) n+=(*this)(x,y,z,v)*(*this)(x,y,z,v); res(x,y,z) = (Tfloat)cimg_std::sqrt((double)n); 1.15627 + } 1.15628 + } 1.15629 + } 1.15630 + return res; 1.15631 + } 1.15632 + 1.15633 + //! Compute the image of normalized vectors. 1.15634 + /** 1.15635 + When dealing with vector-valued images (i.e images with dimv()>1), this function return the image of normalized vectors 1.15636 + (unit vectors). Null vectors are unchanged. The L2-norm is computed for the normalization. 1.15637 + \return A new vector-valued image with same size, where each vector-valued pixels have been normalized. 1.15638 + **/ 1.15639 + CImg<T>& pointwise_orientation() { 1.15640 + cimg_forXYZ(*this,x,y,z) { 1.15641 + float n = 0; 1.15642 + cimg_forV(*this,v) n+=(float)((*this)(x,y,z,v)*(*this)(x,y,z,v)); 1.15643 + n = (float)cimg_std::sqrt(n); 1.15644 + if (n>0) cimg_forV(*this,v) (*this)(x,y,z,v) = (T)((*this)(x,y,z,v)/n); 1.15645 + else cimg_forV(*this,v) (*this)(x,y,z,v) = 0; 1.15646 + } 1.15647 + return *this; 1.15648 + } 1.15649 + 1.15650 + CImg<Tfloat> get_pointwise_orientation() const { 1.15651 + if (is_empty()) return *this; 1.15652 + return CImg<Tfloat>(*this,false).pointwise_orientation(); 1.15653 + } 1.15654 + 1.15655 + //! Split image into a list. 1.15656 + CImgList<T> get_split(const char axis, const unsigned int nb=0) const { 1.15657 + if (is_empty()) return CImgList<T>(); 1.15658 + CImgList<T> res; 1.15659 + switch (cimg::uncase(axis)) { 1.15660 + case 'x' : { 1.15661 + if (nb>width) 1.15662 + throw CImgArgumentException("CImg<%s>::get_split() : Cannot split instance image (%u,%u,%u,%u,%p) along 'x' into %u images.", 1.15663 + pixel_type(),width,height,depth,dim,data,nb); 1.15664 + res.assign(nb?nb:width); 1.15665 + const unsigned int delta = (unsigned int)cimg::round((float)width/res.size,1); 1.15666 + unsigned int l, x; 1.15667 + for (l = 0, x = 0; l<res.size-1; ++l, x+=delta) res[l] = get_crop(x,0,0,0,x+delta-1,height-1,depth-1,dim-1); 1.15668 + res[res.size-1] = get_crop(x,0,0,0,width-1,height-1,depth-1,dim-1); 1.15669 + } break; 1.15670 + case 'y' : { 1.15671 + if (nb>height) 1.15672 + throw CImgArgumentException("CImg<%s>::get_split() : Cannot split instance image (%u,%u,%u,%u,%p) along 'y' into %u images.", 1.15673 + pixel_type(),width,height,depth,dim,data,nb); 1.15674 + res.assign(nb?nb:height); 1.15675 + const unsigned int delta = (unsigned int)cimg::round((float)height/res.size,1); 1.15676 + unsigned int l, y; 1.15677 + for (l = 0, y = 0; l<res.size-1; ++l, y+=delta) res[l] = get_crop(0,y,0,0,width-1,y+delta-1,depth-1,dim-1); 1.15678 + res[res.size-1] = get_crop(0,y,0,0,width-1,height-1,depth-1,dim-1); 1.15679 + } break; 1.15680 + case 'z' : { 1.15681 + if (nb>depth) 1.15682 + throw CImgArgumentException("CImg<%s>::get_split() : Cannot split instance image (%u,%u,%u,%u,%p) along 'z' into %u images.", 1.15683 + pixel_type(),width,height,depth,dim,data,nb); 1.15684 + res.assign(nb?nb:depth); 1.15685 + const unsigned int delta = (unsigned int)cimg::round((float)depth/res.size,1); 1.15686 + unsigned int l, z; 1.15687 + for (l = 0, z = 0; l<res.size-1; ++l, z+=delta) res[l] = get_crop(0,0,z,0,width-1,height-1,z+delta-1,dim-1); 1.15688 + res[res.size-1] = get_crop(0,0,z,0,width-1,height-1,depth-1,dim-1); 1.15689 + } break; 1.15690 + case 'v' : { 1.15691 + if (nb>dim) 1.15692 + throw CImgArgumentException("CImg<%s>::get_split() : Cannot split instance image (%u,%u,%u,%u,%p) along 'v' into %u images.", 1.15693 + pixel_type(),width,height,depth,dim,data,nb); 1.15694 + res.assign(nb?nb:dim); 1.15695 + const unsigned int delta = (unsigned int)cimg::round((float)dim/res.size,1); 1.15696 + unsigned int l, v; 1.15697 + for (l = 0, v = 0; l<res.size-1; ++l, v+=delta) res[l] = get_crop(0,0,0,v,width-1,height-1,depth-1,v+delta-1); 1.15698 + res[res.size-1] = get_crop(0,0,0,v,width-1,height-1,depth-1,dim-1); 1.15699 + } break; 1.15700 + default : 1.15701 + throw CImgArgumentException("CImg<%s>::get_split() : Unknow axis '%c', must be 'x','y','z' or 'v'", 1.15702 + pixel_type(),axis); 1.15703 + } 1.15704 + return res; 1.15705 + } 1.15706 + 1.15707 + // Split image into a list of vectors, according to a given splitting value. 1.15708 + CImgList<T> get_split(const T value, const bool keep_values, const bool shared) const { 1.15709 + CImgList<T> res; 1.15710 + const T *ptr0 = data, *const ptr_end = data + size(); 1.15711 + while (ptr0<ptr_end) { 1.15712 + const T *ptr1 = ptr0; 1.15713 + while (ptr1<ptr_end && *ptr1==value) ++ptr1; 1.15714 + const unsigned int siz0 = ptr1 - ptr0; 1.15715 + if (siz0 && keep_values) res.insert(CImg<T>(ptr0,1,siz0,1,1,shared)); 1.15716 + ptr0 = ptr1; 1.15717 + while (ptr1<ptr_end && *ptr1!=value) ++ptr1; 1.15718 + const unsigned int siz1 = ptr1 - ptr0; 1.15719 + if (siz1) res.insert(CImg<T>(ptr0,1,siz1,1,1,shared),~0U,shared); 1.15720 + ptr0 = ptr1; 1.15721 + } 1.15722 + return res; 1.15723 + } 1.15724 + 1.15725 + //! Append an image to another one. 1.15726 + CImg<T>& append(const CImg<T>& img, const char axis, const char align='p') { 1.15727 + if (!img) return *this; 1.15728 + if (is_empty()) return (*this=img); 1.15729 + return get_append(img,axis,align).transfer_to(*this); 1.15730 + } 1.15731 + 1.15732 + CImg<T> get_append(const CImg<T>& img, const char axis, const char align='p') const { 1.15733 + if (!img) return *this; 1.15734 + if (is_empty()) return img; 1.15735 + CImgList<T> temp(2); 1.15736 + temp[0].width = width; temp[0].height = height; temp[0].depth = depth; 1.15737 + temp[0].dim = dim; temp[0].data = data; 1.15738 + temp[1].width = img.width; temp[1].height = img.height; temp[1].depth = img.depth; 1.15739 + temp[1].dim = img.dim; temp[1].data = img.data; 1.15740 + const CImg<T> res = temp.get_append(axis,align); 1.15741 + temp[0].width = temp[0].height = temp[0].depth = temp[0].dim = 0; temp[0].data = 0; 1.15742 + temp[1].width = temp[1].height = temp[1].depth = temp[1].dim = 0; temp[1].data = 0; 1.15743 + return res; 1.15744 + } 1.15745 + 1.15746 + //! Compute the list of images, corresponding to the XY-gradients of an image. 1.15747 + /** 1.15748 + \param scheme = Numerical scheme used for the gradient computation : 1.15749 + - -1 = Backward finite differences 1.15750 + - 0 = Centered finite differences 1.15751 + - 1 = Forward finite differences 1.15752 + - 2 = Using Sobel masks 1.15753 + - 3 = Using rotation invariant masks 1.15754 + - 4 = Using Deriche recusrsive filter. 1.15755 + **/ 1.15756 + CImgList<Tfloat> get_gradient(const char *const axes=0, const int scheme=3) const { 1.15757 + CImgList<Tfloat> grad(2,width,height,depth,dim); 1.15758 + bool threed = false; 1.15759 + if (axes) { 1.15760 + for (unsigned int a = 0; axes[a]; ++a) { 1.15761 + const char axis = cimg::uncase(axes[a]); 1.15762 + switch (axis) { 1.15763 + case 'x' : case 'y' : break; 1.15764 + case 'z' : threed = true; break; 1.15765 + default : 1.15766 + throw CImgArgumentException("CImg<%s>::get_gradient() : Unknown specified axis '%c'.", 1.15767 + pixel_type(),axis); 1.15768 + } 1.15769 + } 1.15770 + } else threed = (depth>1); 1.15771 + if (threed) { 1.15772 + grad.insert(1); grad[2].assign(width,height,depth,dim); 1.15773 + switch (scheme) { // Compute 3D gradient 1.15774 + case -1 : { // backward finite differences 1.15775 + CImg_3x3x3(I,T); 1.15776 + cimg_forV(*this,k) cimg_for3x3x3(*this,x,y,z,k,I) { 1.15777 + grad[0](x,y,z,k) = (Tfloat)Iccc - Ipcc; 1.15778 + grad[1](x,y,z,k) = (Tfloat)Iccc - Icpc; 1.15779 + grad[2](x,y,z,k) = (Tfloat)Iccc - Iccp; 1.15780 + } 1.15781 + } break; 1.15782 + case 1 : { // forward finite differences 1.15783 + CImg_2x2x2(I,T); 1.15784 + cimg_forV(*this,k) cimg_for2x2x2(*this,x,y,z,k,I) { 1.15785 + grad[0](x,y,z,k) = (Tfloat)Incc - Iccc; 1.15786 + grad[1](x,y,z,k) = (Tfloat)Icnc - Iccc; 1.15787 + grad[2](x,y,z,k) = (Tfloat)Iccn - Iccc; 1.15788 + } 1.15789 + } break; 1.15790 + case 4 : { // using Deriche filter with low standard variation 1.15791 + grad[0] = get_deriche(0,1,'x'); 1.15792 + grad[1] = get_deriche(0,1,'y'); 1.15793 + grad[2] = get_deriche(0,1,'z'); 1.15794 + } break; 1.15795 + default : { // central finite differences 1.15796 + CImg_3x3x3(I,T); 1.15797 + cimg_forV(*this,k) cimg_for3x3x3(*this,x,y,z,k,I) { 1.15798 + grad[0](x,y,z,k) = 0.5f*((Tfloat)Incc - Ipcc); 1.15799 + grad[1](x,y,z,k) = 0.5f*((Tfloat)Icnc - Icpc); 1.15800 + grad[2](x,y,z,k) = 0.5f*((Tfloat)Iccn - Iccp); 1.15801 + } 1.15802 + } 1.15803 + } 1.15804 + } else switch (scheme) { // Compute 2D-gradient 1.15805 + case -1 : { // backward finite differences 1.15806 + CImg_3x3(I,T); 1.15807 + cimg_forZV(*this,z,k) cimg_for3x3(*this,x,y,z,k,I) { 1.15808 + grad[0](x,y,z,k) = (Tfloat)Icc - Ipc; 1.15809 + grad[1](x,y,z,k) = (Tfloat)Icc - Icp; 1.15810 + } 1.15811 + } break; 1.15812 + case 1 : { // forward finite differences 1.15813 + CImg_2x2(I,T); 1.15814 + cimg_forZV(*this,z,k) cimg_for2x2(*this,x,y,z,k,I) { 1.15815 + grad[0](x,y,0,k) = (Tfloat)Inc - Icc; 1.15816 + grad[1](x,y,z,k) = (Tfloat)Icn - Icc; 1.15817 + } 1.15818 + } break; 1.15819 + case 2 : { // using Sobel mask 1.15820 + CImg_3x3(I,T); 1.15821 + const Tfloat a = 1, b = 2; 1.15822 + cimg_forZV(*this,z,k) cimg_for3x3(*this,x,y,z,k,I) { 1.15823 + grad[0](x,y,z,k) = -a*Ipp - b*Ipc - a*Ipn + a*Inp + b*Inc + a*Inn; 1.15824 + grad[1](x,y,z,k) = -a*Ipp - b*Icp - a*Inp + a*Ipn + b*Icn + a*Inn; 1.15825 + } 1.15826 + } break; 1.15827 + case 3 : { // using rotation invariant mask 1.15828 + CImg_3x3(I,T); 1.15829 + const Tfloat a = (Tfloat)(0.25f*(2-cimg_std::sqrt(2.0f))), b = (Tfloat)(0.5f*(cimg_std::sqrt(2.0f)-1)); 1.15830 + cimg_forZV(*this,z,k) cimg_for3x3(*this,x,y,z,k,I) { 1.15831 + grad[0](x,y,z,k) = -a*Ipp - b*Ipc - a*Ipn + a*Inp + b*Inc + a*Inn; 1.15832 + grad[1](x,y,z,k) = -a*Ipp - b*Icp - a*Inp + a*Ipn + b*Icn + a*Inn; 1.15833 + } 1.15834 + } break; 1.15835 + case 4 : { // using Deriche filter with low standard variation 1.15836 + grad[0] = get_deriche(0,1,'x'); 1.15837 + grad[1] = get_deriche(0,1,'y'); 1.15838 + } break; 1.15839 + default : { // central finite differences 1.15840 + CImg_3x3(I,T); 1.15841 + cimg_forZV(*this,z,k) cimg_for3x3(*this,x,y,z,k,I) { 1.15842 + grad[0](x,y,z,k) = 0.5f*((Tfloat)Inc - Ipc); 1.15843 + grad[1](x,y,z,k) = 0.5f*((Tfloat)Icn - Icp); 1.15844 + } 1.15845 + } 1.15846 + } 1.15847 + if (!axes) return grad; 1.15848 + CImgList<Tfloat> res; 1.15849 + for (unsigned int l = 0; axes[l]; ++l) { 1.15850 + const char axis = cimg::uncase(axes[l]); 1.15851 + switch (axis) { 1.15852 + case 'x' : res.insert(grad[0]); break; 1.15853 + case 'y' : res.insert(grad[1]); break; 1.15854 + case 'z' : res.insert(grad[2]); break; 1.15855 + } 1.15856 + } 1.15857 + grad.assign(); 1.15858 + return res; 1.15859 + } 1.15860 + 1.15861 + //! Compute the structure tensor field of an image. 1.15862 + CImg<T>& structure_tensor(const bool central_scheme=false) { 1.15863 + return get_structure_tensor(central_scheme).transfer_to(*this); 1.15864 + } 1.15865 + 1.15866 + CImg<Tfloat> get_structure_tensor(const bool central_scheme=false) const { 1.15867 + if (is_empty()) return *this; 1.15868 + CImg<Tfloat> res; 1.15869 + if (depth>1) { // 3D version 1.15870 + res.assign(width,height,depth,6,0); 1.15871 + CImg_3x3x3(I,T); 1.15872 + if (central_scheme) cimg_forV(*this,k) cimg_for3x3x3(*this,x,y,z,k,I) { // classical central finite differences 1.15873 + const Tfloat 1.15874 + ix = 0.5f*((Tfloat)Incc - Ipcc), 1.15875 + iy = 0.5f*((Tfloat)Icnc - Icpc), 1.15876 + iz = 0.5f*((Tfloat)Iccn - Iccp); 1.15877 + res(x,y,z,0)+=ix*ix; 1.15878 + res(x,y,z,1)+=ix*iy; 1.15879 + res(x,y,z,2)+=ix*iz; 1.15880 + res(x,y,z,3)+=iy*iy; 1.15881 + res(x,y,z,4)+=iy*iz; 1.15882 + res(x,y,z,5)+=iz*iz; 1.15883 + } else cimg_forV(*this,k) cimg_for3x3x3(*this,x,y,z,k,I) { // Precise forward/backward finite differences 1.15884 + const Tfloat 1.15885 + ixf = (Tfloat)Incc - Iccc, ixb = (Tfloat)Iccc - Ipcc, 1.15886 + iyf = (Tfloat)Icnc - Iccc, iyb = (Tfloat)Iccc - Icpc, 1.15887 + izf = (Tfloat)Iccn - Iccc, izb = (Tfloat)Iccc - Iccp; 1.15888 + res(x,y,z,0) += 0.5f*(ixf*ixf + ixb*ixb); 1.15889 + res(x,y,z,1) += 0.25f*(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb); 1.15890 + res(x,y,z,2) += 0.25f*(ixf*izf + ixf*izb + ixb*izf + ixb*izb); 1.15891 + res(x,y,z,3) += 0.5f*(iyf*iyf + iyb*iyb); 1.15892 + res(x,y,z,4) += 0.25f*(iyf*izf + iyf*izb + iyb*izf + iyb*izb); 1.15893 + res(x,y,z,5) += 0.5f*(izf*izf + izb*izb); 1.15894 + } 1.15895 + } else { // 2D version 1.15896 + res.assign(width,height,depth,3,0); 1.15897 + CImg_3x3(I,T); 1.15898 + if (central_scheme) cimg_forV(*this,k) cimg_for3x3(*this,x,y,0,k,I) { // classical central finite differences 1.15899 + const Tfloat 1.15900 + ix = 0.5f*((Tfloat)Inc - Ipc), 1.15901 + iy = 0.5f*((Tfloat)Icn - Icp); 1.15902 + res(x,y,0,0)+=ix*ix; 1.15903 + res(x,y,0,1)+=ix*iy; 1.15904 + res(x,y,0,2)+=iy*iy; 1.15905 + } else cimg_forV(*this,k) cimg_for3x3(*this,x,y,0,k,I) { // Precise forward/backward finite differences 1.15906 + const Tfloat 1.15907 + ixf = (Tfloat)Inc - Icc, ixb = (Tfloat)Icc - Ipc, 1.15908 + iyf = (Tfloat)Icn - Icc, iyb = (Tfloat)Icc - Icp; 1.15909 + res(x,y,0,0) += 0.5f*(ixf*ixf+ixb*ixb); 1.15910 + res(x,y,0,1) += 0.25f*(ixf*iyf+ixf*iyb+ixb*iyf+ixb*iyb); 1.15911 + res(x,y,0,2) += 0.5f*(iyf*iyf+iyb*iyb); 1.15912 + } 1.15913 + } 1.15914 + return res; 1.15915 + } 1.15916 + 1.15917 + //! Get components of the Hessian matrix of an image. 1.15918 + CImgList<Tfloat> get_hessian(const char *const axes=0) const { 1.15919 + const char *naxes = axes, *const def_axes2d = "xxxyyy", *const def_axes3d = "xxxyxzyyyzzz"; 1.15920 + if (!axes) naxes = depth>1?def_axes3d:def_axes2d; 1.15921 + CImgList<Tfloat> res; 1.15922 + const int lmax = cimg::strlen(naxes); 1.15923 + if (lmax%2) 1.15924 + throw CImgArgumentException("CImg<%s>::get_hessian() : Incomplete parameter axes = '%s'.", 1.15925 + pixel_type(),naxes); 1.15926 + res.assign(lmax/2,width,height,depth,dim); 1.15927 + if (!cimg::strcasecmp(naxes,def_axes3d)) { // Default 3D version 1.15928 + CImg_3x3x3(I,T); 1.15929 + cimg_forV(*this,k) cimg_for3x3x3(*this,x,y,z,k,I) { 1.15930 + res[0](x,y,z,k) = (Tfloat)Ipcc + Incc - 2*Iccc; // Ixx 1.15931 + res[1](x,y,z,k) = 0.25f*((Tfloat)Ippc + Innc - Ipnc - Inpc); // Ixy 1.15932 + res[2](x,y,z,k) = 0.25f*((Tfloat)Ipcp + Incn - Ipcn - Incp); // Ixz 1.15933 + res[3](x,y,z,k) = (Tfloat)Icpc + Icnc - 2*Iccc; // Iyy 1.15934 + res[4](x,y,z,k) = 0.25f*((Tfloat)Icpp + Icnn - Icpn - Icnp); // Iyz 1.15935 + res[5](x,y,z,k) = (Tfloat)Iccn + Iccp - 2*Iccc; // Izz 1.15936 + } 1.15937 + } else if (!cimg::strcasecmp(naxes,def_axes2d)) { // Default 2D version 1.15938 + CImg_3x3(I,T); 1.15939 + cimg_forV(*this,k) cimg_for3x3(*this,x,y,0,k,I) { 1.15940 + res[0](x,y,0,k) = (Tfloat)Ipc + Inc - 2*Icc; // Ixx 1.15941 + res[1](x,y,0,k) = 0.25f*((Tfloat)Ipp + Inn - Ipn - Inp); // Ixy 1.15942 + res[2](x,y,0,k) = (Tfloat)Icp + Icn - 2*Icc; // Iyy 1.15943 + } 1.15944 + } else for (int l = 0; l<lmax; ) { // Version with custom axes. 1.15945 + const int l2 = l/2; 1.15946 + char axis1 = naxes[l++], axis2 = naxes[l++]; 1.15947 + if (axis1>axis2) cimg::swap(axis1,axis2); 1.15948 + bool valid_axis = false; 1.15949 + if (axis1=='x' && axis2=='x') { // Ixx 1.15950 + valid_axis = true; CImg_3x3(I,T); 1.15951 + cimg_forZV(*this,z,k) cimg_for3x3(*this,x,y,z,k,I) res[l2](x,y,z,k) = (Tfloat)Ipc + Inc - 2*Icc; 1.15952 + } 1.15953 + else if (axis1=='x' && axis2=='y') { // Ixy 1.15954 + valid_axis = true; CImg_3x3(I,T); 1.15955 + cimg_forZV(*this,z,k) cimg_for3x3(*this,x,y,z,k,I) res[l2](x,y,z,k) = 0.25f*((Tfloat)Ipp + Inn - Ipn - Inp); 1.15956 + } 1.15957 + else if (axis1=='x' && axis2=='z') { // Ixz 1.15958 + valid_axis = true; CImg_3x3x3(I,T); 1.15959 + cimg_forV(*this,k) cimg_for3x3x3(*this,x,y,z,k,I) res[l2](x,y,z,k) = 0.25f*((Tfloat)Ipcp + Incn - Ipcn - Incp); 1.15960 + } 1.15961 + else if (axis1=='y' && axis2=='y') { // Iyy 1.15962 + valid_axis = true; CImg_3x3(I,T); 1.15963 + cimg_forZV(*this,z,k) cimg_for3x3(*this,x,y,z,k,I) res[l2](x,y,z,k) = (Tfloat)Icp + Icn - 2*Icc; 1.15964 + } 1.15965 + else if (axis1=='y' && axis2=='z') { // Iyz 1.15966 + valid_axis = true; CImg_3x3x3(I,T); 1.15967 + cimg_forV(*this,k) cimg_for3x3x3(*this,x,y,z,k,I) res[l2](x,y,z,k) = 0.25f*((Tfloat)Icpp + Icnn - Icpn - Icnp); 1.15968 + } 1.15969 + else if (axis1=='z' && axis2=='z') { // Izz 1.15970 + valid_axis = true; CImg_3x3x3(I,T); 1.15971 + cimg_forV(*this,k) cimg_for3x3x3(*this,x,y,z,k,I) res[l2](x,y,z,k) = (Tfloat)Iccn + Iccp - 2*Iccc; 1.15972 + } 1.15973 + else if (!valid_axis) throw CImgArgumentException("CImg<%s>::get_hessian() : Invalid parameter axes = '%s'.", 1.15974 + pixel_type(),naxes); 1.15975 + } 1.15976 + return res; 1.15977 + } 1.15978 + 1.15979 + //! Compute distance function from 0-valued isophotes by the application of an Hamilton-Jacobi PDE. 1.15980 + CImg<T>& distance_hamilton(const unsigned int nb_iter, const float band_size=0, const float precision=0.5f) { 1.15981 + if (is_empty()) return *this; 1.15982 + CImg<Tfloat> veloc(*this); 1.15983 + for (unsigned int iter = 0; iter<nb_iter; ++iter) { 1.15984 + veloc.fill(0); 1.15985 + if (depth>1) { // 3D version 1.15986 + CImg_3x3x3(I,T); 1.15987 + cimg_forV(*this,k) cimg_for3x3x3(*this,x,y,z,k,I) if (band_size<=0 || cimg::abs(Iccc)<band_size) { 1.15988 + const Tfloat 1.15989 + gx = 0.5f*((Tfloat)Incc - Ipcc), 1.15990 + gy = 0.5f*((Tfloat)Icnc - Icpc), 1.15991 + gz = 0.5f*((Tfloat)Iccn - Iccp), 1.15992 + sgn = -cimg::sign((Tfloat)Iccc), 1.15993 + ix = gx*sgn>0?(Tfloat)Incc - Iccc:(Tfloat)Iccc - Ipcc, 1.15994 + iy = gy*sgn>0?(Tfloat)Icnc - Iccc:(Tfloat)Iccc - Icpc, 1.15995 + iz = gz*sgn>0?(Tfloat)Iccn - Iccc:(Tfloat)Iccc - Iccp, 1.15996 + ng = 1e-5f + (Tfloat)cimg_std::sqrt(gx*gx + gy*gy + gz*gz), 1.15997 + ngx = gx/ng, 1.15998 + ngy = gy/ng, 1.15999 + ngz = gz/ng; 1.16000 + veloc(x,y,z,k) = sgn*(ngx*ix + ngy*iy + ngz*iz - 1); 1.16001 + } 1.16002 + } else { // 2D version 1.16003 + CImg_3x3(I,T); 1.16004 + cimg_forV(*this,k) cimg_for3x3(*this,x,y,0,k,I) if (band_size<=0 || cimg::abs(Icc)<band_size) { 1.16005 + const Tfloat 1.16006 + gx = 0.5f*((Tfloat)Inc - Ipc), 1.16007 + gy = 0.5f*((Tfloat)Icn - Icp), 1.16008 + sgn = -cimg::sign((Tfloat)Icc), 1.16009 + ix = gx*sgn>0?(Tfloat)Inc - Icc:(Tfloat)Icc - Ipc, 1.16010 + iy = gy*sgn>0?(Tfloat)Icn - Icc:(Tfloat)Icc - Icp, 1.16011 + ng = 1e-5f + (Tfloat)cimg_std::sqrt(gx*gx + gy*gy), 1.16012 + ngx = gx/ng, 1.16013 + ngy = gy/ng; 1.16014 + veloc(x,y,k) = sgn*(ngx*ix + ngy*iy - 1); 1.16015 + } 1.16016 + } 1.16017 + float m, M = (float)veloc.maxmin(m), xdt = precision/(float)cimg::max(cimg::abs(m),cimg::abs(M)); 1.16018 + *this+=(veloc*=xdt); 1.16019 + } 1.16020 + return *this; 1.16021 + } 1.16022 + 1.16023 + CImg<Tfloat> get_distance_hamilton(const unsigned int nb_iter, const float band_size=0, const float precision=0.5f) const { 1.16024 + return CImg<Tfloat>(*this,false).distance_hamilton(nb_iter,band_size,precision); 1.16025 + } 1.16026 + 1.16027 + //! Compute the Euclidean distance map to a shape of specified isovalue. 1.16028 + CImg<T>& distance(const T isovalue, 1.16029 + const float sizex=1, const float sizey=1, const float sizez=1, 1.16030 + const bool compute_sqrt=true) { 1.16031 + return get_distance(isovalue,sizex,sizey,sizez,compute_sqrt).transfer_to(*this); 1.16032 + } 1.16033 + 1.16034 + CImg<floatT> get_distance(const T isovalue, 1.16035 + const float sizex=1, const float sizey=1, const float sizez=1, 1.16036 + const bool compute_sqrt=true) const { 1.16037 + if (is_empty()) return *this; 1.16038 + const int dx = dimx(), dy = dimy(), dz = dimz(); 1.16039 + CImg<floatT> res(dx,dy,dz,dim); 1.16040 + const float maxdist = (float)cimg_std::sqrt((float)dx*dx + dy*dy + dz*dz); 1.16041 + cimg_forV(*this,k) { 1.16042 + bool is_isophote = false; 1.16043 + 1.16044 + if (depth>1) { // 3D version 1.16045 + { cimg_forYZ(*this,y,z) { 1.16046 + if ((*this)(0,y,z,k)==isovalue) { is_isophote = true; res(0,y,z,k) = 0; } else res(0,y,z,k) = maxdist; 1.16047 + for (int x = 1; x<dx; ++x) if ((*this)(x,y,z,k)==isovalue) { is_isophote = true; res(x,y,z,k) = 0; } 1.16048 + else res(x,y,z,k) = res(x-1,y,z,k) + sizex; 1.16049 + { for (int x = dx-2; x>=0; --x) if (res(x+1,y,z,k)<res(x,y,z,k)) res(x,y,z,k) = res(x+1,y,z,k) + sizex; } 1.16050 + }} 1.16051 + if (!is_isophote) { res.get_shared_channel(k).fill(cimg::type<float>::max()); continue; } 1.16052 + CImg<floatT> tmp(cimg::max(dy,dz)); 1.16053 + CImg<intT> s(tmp.width), t(s.width); 1.16054 + { cimg_forXZ(*this,x,z) { 1.16055 + { cimg_forY(*this,y) tmp[y] = res(x,y,z,k); } 1.16056 + int q = s[0] = t[0] = 0; 1.16057 + { for (int y = 1; y<dy; ++y) { 1.16058 + const float val = tmp[y], val2 = val*val; 1.16059 + while (q>=0 && _distance_f(t[q],s[q],cimg::sqr(tmp[s[q]]),sizey)>_distance_f(t[q],y,val2,sizey)) --q; 1.16060 + if (q<0) { q = 0; s[0] = y; } 1.16061 + else { 1.16062 + const int w = 1 + _distance_sep(s[q],y,(int)cimg::sqr(tmp[s[q]]),(int)val2,sizey); 1.16063 + if (w<dy) { s[++q] = y; t[q] = w; } 1.16064 + } 1.16065 + }} 1.16066 + { for (int y = dy - 1; y>=0; --y) { 1.16067 + res(x,y,z,k) = _distance_f(y,s[q],cimg::sqr(tmp[s[q]]),sizey); 1.16068 + if (y==t[q]) --q; 1.16069 + }} 1.16070 + }} 1.16071 + { cimg_forXY(*this,x,y) { 1.16072 + { cimg_forZ(*this,z) tmp[z] = res(x,y,z,k); } 1.16073 + int q = s[0] = t[0] = 0; 1.16074 + { for (int z = 1; z<dz; ++z) { 1.16075 + const float val = tmp[z]; 1.16076 + while (q>=0 && _distance_f(t(q),s[q],tmp[s[q]],sizez)>_distance_f(t[q],z,tmp[z],sizez)) --q; 1.16077 + if (q<0) { q = 0; s[0] = z; } 1.16078 + else { 1.16079 + const int w = 1 + _distance_sep(s[q],z,(int)tmp[s[q]],(int)val,sizez); 1.16080 + if (w<dz) { s[++q] = z; t[q] = w; } 1.16081 + } 1.16082 + }} 1.16083 + { for (int z = dz - 1; z>=0; --z) { 1.16084 + const float val = _distance_f(z,s[q],tmp[s[q]],sizez); 1.16085 + res(x,y,z,k) = compute_sqrt?(float)cimg_std::sqrt(val):val; 1.16086 + if (z==t[q]) --q; 1.16087 + }} 1.16088 + }} 1.16089 + } else { // 2D version (with small optimizations) 1.16090 + cimg_forX(*this,x) { 1.16091 + const T *ptrs = ptr(x,0,0,k); 1.16092 + float *ptrd = res.ptr(x,0,0,k), d = *ptrd = *ptrs==isovalue?(is_isophote=true),0:maxdist; 1.16093 + for (int y = 1; y<dy; ++y) { ptrs+=width; ptrd+=width; d = *ptrd = *ptrs==isovalue?(is_isophote=true),0:d+sizey; } 1.16094 + { for (int y = dy - 2; y>=0; --y) { ptrd-=width; if (d<*ptrd) *ptrd = (d+=sizey); else d = *ptrd; }} 1.16095 + } 1.16096 + if (!is_isophote) { res.get_shared_channel(k).fill(cimg::type<float>::max()); continue; } 1.16097 + CImg<floatT> tmp(dx); 1.16098 + CImg<intT> s(dx), t(dx); 1.16099 + cimg_forY(*this,y) { 1.16100 + float *ptmp = tmp.ptr(); 1.16101 + cimg_std::memcpy(ptmp,res.ptr(0,y,0,k),sizeof(float)*dx); 1.16102 + int q = s[0] = t[0] = 0; 1.16103 + for (int x = 1; x<dx; ++x) { 1.16104 + const float val = *(++ptmp), val2 = val*val; 1.16105 + while (q>=0 && _distance_f(t[q],s[q],cimg::sqr(tmp[s[q]]),sizex)>_distance_f(t[q],x,val2,sizex)) --q; 1.16106 + if (q<0) { q = 0; s[0] = x; } 1.16107 + else { 1.16108 + const int w = 1 + _distance_sep(s[q],x,(int)cimg::sqr(tmp[s[q]]),(int)val2,sizex); 1.16109 + if (w<dx) { q++; s[q] = x; t[q] = w; } 1.16110 + } 1.16111 + } 1.16112 + float *pres = res.ptr(0,y,0,k) + width; 1.16113 + { for (int x = dx - 1; x>=0; --x) { 1.16114 + const float val = _distance_f(x,s[q],cimg::sqr(tmp[s[q]]),sizex); 1.16115 + *(--pres) = compute_sqrt?(float)cimg_std::sqrt(val):val; 1.16116 + if (x==t[q]) --q; 1.16117 + }} 1.16118 + } 1.16119 + } 1.16120 + } 1.16121 + return res; 1.16122 + } 1.16123 + 1.16124 + static float _distance_f(const int x, const int i, const float gi2, const float fact) { 1.16125 + const float xmi = fact*((float)x - i); 1.16126 + return xmi*xmi + gi2; 1.16127 + } 1.16128 + static int _distance_sep(const int i, const int u, const int gi2, const int gu2, const float fact) { 1.16129 + const float fact2 = fact*fact; 1.16130 + return (int)(fact2*(u*u - i*i) + gu2 - gi2)/(int)(2*fact2*(u - i)); 1.16131 + } 1.16132 + 1.16133 + //! Compute minimal path in a graph, using the Dijkstra algorithm. 1.16134 + /** 1.16135 + \param distance An object having operator()(unsigned int i, unsigned int j) which returns distance between two nodes (i,j). 1.16136 + \param nb_nodes Number of graph nodes. 1.16137 + \param starting_node Indice of the starting node. 1.16138 + \param ending_node Indice of the ending node (set to ~0U to ignore ending node). 1.16139 + \param previous Array that gives the previous node indice in the path to the starting node (optional parameter). 1.16140 + \return Array of distances of each node to the starting node. 1.16141 + **/ 1.16142 + template<typename tf, typename t> 1.16143 + static CImg<T> dijkstra(const tf& distance, const unsigned int nb_nodes, 1.16144 + const unsigned int starting_node, const unsigned int ending_node, 1.16145 + CImg<t>& previous) { 1.16146 + 1.16147 + CImg<T> dist(1,nb_nodes,1,1,cimg::type<T>::max()); 1.16148 + dist(starting_node) = 0; 1.16149 + previous.assign(1,nb_nodes,1,1,(t)-1); 1.16150 + previous(starting_node) = (t)starting_node; 1.16151 + CImg<uintT> Q(nb_nodes); 1.16152 + cimg_forX(Q,u) Q(u) = u; 1.16153 + cimg::swap(Q(starting_node),Q(0)); 1.16154 + unsigned int sizeQ = nb_nodes; 1.16155 + while (sizeQ) { 1.16156 + // Update neighbors from minimal vertex 1.16157 + const unsigned int umin = Q(0); 1.16158 + if (umin==ending_node) sizeQ = 0; 1.16159 + else { 1.16160 + const T dmin = dist(umin); 1.16161 + const T infty = cimg::type<T>::max(); 1.16162 + for (unsigned int q=1; q<sizeQ; ++q) { 1.16163 + const unsigned int v = Q(q); 1.16164 + const T d = (T)distance(v,umin); 1.16165 + if (d<infty) { 1.16166 + const T alt = dmin + d; 1.16167 + if (alt<dist(v)) { 1.16168 + dist(v) = alt; 1.16169 + previous(v) = (t)umin; 1.16170 + const T distpos = dist(Q(q)); 1.16171 + for (unsigned int pos = q, par = 0; pos && distpos<dist(Q(par=(pos+1)/2-1)); pos=par) cimg::swap(Q(pos),Q(par)); 1.16172 + } 1.16173 + } 1.16174 + } 1.16175 + // Remove minimal vertex from queue 1.16176 + Q(0) = Q(--sizeQ); 1.16177 + const T distpos = dist(Q(0)); 1.16178 + for (unsigned int pos = 0, left = 0, right = 0; 1.16179 + ((right=2*(pos+1),(left=right-1))<sizeQ && distpos>dist(Q(left))) || (right<sizeQ && distpos>dist(Q(right)));) { 1.16180 + if (right<sizeQ) { 1.16181 + if (dist(Q(left))<dist(Q(right))) { cimg::swap(Q(pos),Q(left)); pos = left; } 1.16182 + else { cimg::swap(Q(pos),Q(right)); pos = right; } 1.16183 + } else { cimg::swap(Q(pos),Q(left)); pos = left; } 1.16184 + } 1.16185 + } 1.16186 + } 1.16187 + return dist; 1.16188 + } 1.16189 + 1.16190 + //! Return minimal path in a graph, using the Dijkstra algorithm. 1.16191 + template<typename tf, typename t> 1.16192 + static CImg<T> dijkstra(const tf& distance, const unsigned int nb_nodes, 1.16193 + const unsigned int starting_node, const unsigned int ending_node=~0U) { 1.16194 + CImg<uintT> foo; 1.16195 + return dijkstra(distance,nb_nodes,starting_node,ending_node,foo); 1.16196 + } 1.16197 + 1.16198 + //! Return minimal path in a graph, using the Dijkstra algorithm. 1.16199 + /** 1.16200 + Instance image corresponds to the adjacency matrix of the graph. 1.16201 + \param starting_node Indice of the starting node. 1.16202 + \param previous Array that gives the previous node indice in the path to the starting node (optional parameter). 1.16203 + \return Array of distances of each node to the starting node. 1.16204 + **/ 1.16205 + template<typename t> 1.16206 + CImg<T>& dijkstra(const unsigned int starting_node, const unsigned int ending_node, CImg<t>& previous) { 1.16207 + return get_dijkstra(starting_node,ending_node,previous).transfer_to(*this); 1.16208 + } 1.16209 + 1.16210 + template<typename t> 1.16211 + CImg<T> get_dijkstra(const unsigned int starting_node, const unsigned int ending_node, CImg<t>& previous) const { 1.16212 + if (width!=height || depth!=1 || dim!=1) 1.16213 + throw CImgInstanceException("CImg<%s>::dijkstra() : Instance image (%u,%u,%u,%u,%p) is not a graph adjacency matrix", 1.16214 + pixel_type(),width,height,depth,dim,data); 1.16215 + return dijkstra(*this,width,starting_node,ending_node,previous); 1.16216 + } 1.16217 + 1.16218 + //! Return minimal path in a graph, using the Dijkstra algorithm. 1.16219 + CImg<T>& dijkstra(const unsigned int starting_node, const unsigned int ending_node=~0U) { 1.16220 + return get_dijkstra(starting_node,ending_node).transfer_to(*this); 1.16221 + } 1.16222 + 1.16223 + CImg<Tfloat> get_dijkstra(const unsigned int starting_node, const unsigned int ending_node=~0U) const { 1.16224 + CImg<uintT> foo; 1.16225 + return get_dijkstra(starting_node,ending_node,foo); 1.16226 + } 1.16227 + 1.16228 + //@} 1.16229 + //------------------------------------- 1.16230 + // 1.16231 + //! \name Meshes and Triangulations 1.16232 + //@{ 1.16233 + //------------------------------------- 1.16234 + 1.16235 + //! Return a 3D centered cube. 1.16236 + template<typename tf> 1.16237 + static CImg<floatT> cube3d(CImgList<tf>& primitives, const float size=100) { 1.16238 + const double s = size/2.0; 1.16239 + 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); 1.16240 + return CImg<floatT>(8,3,1,1, 1.16241 + -s,s,s,-s,-s,s,s,-s, 1.16242 + -s,-s,s,s,-s,-s,s,s, 1.16243 + -s,-s,-s,-s,s,s,s,s); 1.16244 + } 1.16245 + 1.16246 + //! Return a 3D centered cuboid. 1.16247 + template<typename tf> 1.16248 + static CImg<floatT> cuboid3d(CImgList<tf>& primitives, const float sizex=200, 1.16249 + const float sizey=100, const float sizez=100) { 1.16250 + const double sx = sizex/2.0, sy = sizey/2.0, sz = sizez/2.0; 1.16251 + 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); 1.16252 + return CImg<floatT>(8,3,1,1, 1.16253 + -sx,sx,sx,-sx,-sx,sx,sx,-sx, 1.16254 + -sy,-sy,sy,sy,-sy,-sy,sy,sy, 1.16255 + -sz,-sz,-sz,-sz,sz,sz,sz,sz); 1.16256 + } 1.16257 + 1.16258 + //! Return a 3D centered cone. 1.16259 + template<typename tf> 1.16260 + static CImg<floatT> cone3d(CImgList<tf>& primitives, const float radius=50, const float height=100, 1.16261 + const unsigned int subdivisions=24, const bool symetrize=false) { 1.16262 + primitives.assign(); 1.16263 + if (!subdivisions) return CImg<floatT>(); 1.16264 + const double r = (double)radius, h = (double)height/2; 1.16265 + CImgList<floatT> points(2,1,3,1,1, 1.16266 + 0.0,0.0,h, 1.16267 + 0.0,0.0,-h); 1.16268 + const float delta = 360.0f/subdivisions, nh = symetrize?0:-(float)h; 1.16269 + for (float angle = 0; angle<360; angle+=delta) { 1.16270 + const float a = (float)(angle*cimg::valuePI/180); 1.16271 + points.insert(CImg<floatT>::vector((float)(r*cimg_std::cos(a)),(float)(r*cimg_std::sin(a)),nh)); 1.16272 + } 1.16273 + const unsigned int nbr = points.size-2; 1.16274 + for (unsigned int p = 0; p<nbr; ++p) { 1.16275 + const unsigned int curr = 2+p, next = 2+((p+1)%nbr); 1.16276 + primitives.insert(CImg<tf>::vector(1,next,curr)). 1.16277 + insert(CImg<tf>::vector(0,curr,next)); 1.16278 + } 1.16279 + return points.get_append('x'); 1.16280 + } 1.16281 + 1.16282 + //! Return a 3D centered cylinder. 1.16283 + template<typename tf> 1.16284 + static CImg<floatT> cylinder3d(CImgList<tf>& primitives, const float radius=50, const float height=100, 1.16285 + const unsigned int subdivisions=24) { 1.16286 + primitives.assign(); 1.16287 + if (!subdivisions) return CImg<floatT>(); 1.16288 + const double r = (double)radius, h = (double)height/2; 1.16289 + CImgList<floatT> points(2,1,3,1,1, 1.16290 + 0.0,0.0,-h, 1.16291 + 0.0,0.0,h); 1.16292 + 1.16293 + const float delta = 360.0f/subdivisions; 1.16294 + for (float angle = 0; angle<360; angle+=delta) { 1.16295 + const float a = (float)(angle*cimg::valuePI/180); 1.16296 + points.insert(CImg<floatT>::vector((float)(r*cimg_std::cos(a)),(float)(r*cimg_std::sin(a)),-(float)h)); 1.16297 + points.insert(CImg<floatT>::vector((float)(r*cimg_std::cos(a)),(float)(r*cimg_std::sin(a)),(float)h)); 1.16298 + } 1.16299 + const unsigned int nbr = (points.size-2)/2; 1.16300 + for (unsigned int p = 0; p<nbr; ++p) { 1.16301 + const unsigned int curr = 2+2*p, next = 2+(2*((p+1)%nbr)); 1.16302 + primitives.insert(CImg<tf>::vector(0,next,curr)). 1.16303 + insert(CImg<tf>::vector(1,curr+1,next+1)). 1.16304 + insert(CImg<tf>::vector(curr,next,next+1,curr+1)); 1.16305 + } 1.16306 + return points.get_append('x'); 1.16307 + } 1.16308 + 1.16309 + //! Return a 3D centered torus. 1.16310 + template<typename tf> 1.16311 + static CImg<floatT> torus3d(CImgList<tf>& primitives, const float radius1=100, const float radius2=30, 1.16312 + const unsigned int subdivisions1=24, const unsigned int subdivisions2=12) { 1.16313 + primitives.assign(); 1.16314 + if (!subdivisions1 || !subdivisions2) return CImg<floatT>(); 1.16315 + CImgList<floatT> points; 1.16316 + for (unsigned int v = 0; v<subdivisions1; ++v) { 1.16317 + const float 1.16318 + beta = (float)(v*2*cimg::valuePI/subdivisions1), 1.16319 + xc = radius1*(float)cimg_std::cos(beta), 1.16320 + yc = radius1*(float)cimg_std::sin(beta); 1.16321 + for (unsigned int u=0; u<subdivisions2; ++u) { 1.16322 + const float 1.16323 + alpha = (float)(u*2*cimg::valuePI/subdivisions2), 1.16324 + x = xc + radius2*(float)(cimg_std::cos(alpha)*cimg_std::cos(beta)), 1.16325 + y = yc + radius2*(float)(cimg_std::cos(alpha)*cimg_std::sin(beta)), 1.16326 + z = radius2*(float)cimg_std::sin(alpha); 1.16327 + points.insert(CImg<floatT>::vector(x,y,z)); 1.16328 + } 1.16329 + } 1.16330 + for (unsigned int vv = 0; vv<subdivisions1; ++vv) { 1.16331 + const unsigned int nv = (vv+1)%subdivisions1; 1.16332 + for (unsigned int uu = 0; uu<subdivisions2; ++uu) { 1.16333 + const unsigned int nu = (uu+1)%subdivisions2, svv = subdivisions2*vv, snv = subdivisions2*nv; 1.16334 + primitives.insert(CImg<tf>::vector(svv+nu,svv+uu,snv+uu)); 1.16335 + primitives.insert(CImg<tf>::vector(svv+nu,snv+uu,snv+nu)); 1.16336 + } 1.16337 + } 1.16338 + return points.get_append('x'); 1.16339 + } 1.16340 + 1.16341 + //! Return a 3D centered XY plane. 1.16342 + template<typename tf> 1.16343 + static CImg<floatT> plane3d(CImgList<tf>& primitives, const float sizex=100, const float sizey=100, 1.16344 + const unsigned int subdivisionsx=3, const unsigned int subdivisionsy=3, 1.16345 + const bool double_sided=false) { 1.16346 + primitives.assign(); 1.16347 + if (!subdivisionsx || !subdivisionsy) return CImg<floatT>(); 1.16348 + CImgList<floatT> points; 1.16349 + const unsigned int w = subdivisionsx + 1, h = subdivisionsy + 1; 1.16350 + const float w2 = subdivisionsx/2.0f, h2 = subdivisionsy/2.0f, fx = (float)sizex/w, fy = (float)sizey/h; 1.16351 + for (unsigned int yy = 0; yy<h; ++yy) 1.16352 + for (unsigned int xx = 0; xx<w; ++xx) 1.16353 + points.insert(CImg<floatT>::vector(fx*(xx-w2),fy*(yy-h2),0)); 1.16354 + for (unsigned int y = 0; y<subdivisionsy; ++y) for (unsigned int x = 0; x<subdivisionsx; ++x) { 1.16355 + const int off1 = x+y*w, off2 = x+1+y*w, off3 = x+1+(y+1)*w, off4 = x+(y+1)*w; 1.16356 + primitives.insert(CImg<tf>::vector(off1,off4,off3,off2)); 1.16357 + if (double_sided) primitives.insert(CImg<tf>::vector(off1,off2,off3,off4)); 1.16358 + } 1.16359 + return points.get_append('x'); 1.16360 + } 1.16361 + 1.16362 + //! Return a 3D centered sphere. 1.16363 + template<typename tf> 1.16364 + static CImg<floatT> sphere3d(CImgList<tf>& primitives, const float radius=50, const unsigned int subdivisions=3) { 1.16365 + 1.16366 + // Create initial icosahedron 1.16367 + primitives.assign(); 1.16368 + if (!subdivisions) return CImg<floatT>(); 1.16369 + const double tmp = (1+cimg_std::sqrt(5.0f))/2, a = 1.0/cimg_std::sqrt(1+tmp*tmp), b = tmp*a; 1.16370 + CImgList<floatT> points(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, 1.16371 + -a,0.0,-b, -a,0.0,b, 0.0,b,a, 0.0,-b,a, 0.0,-b,-a, 0.0,b,-a); 1.16372 + 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, 1.16373 + 8,0,11, 8,11,1, 9,10,3, 9,2,10, 8,4,0, 11,0,5, 4,9,3, 1.16374 + 5,3,10, 7,8,1, 6,1,11, 7,2,9, 6,10,2); 1.16375 + 1.16376 + // Recurse subdivisions 1.16377 + for (unsigned int i = 0; i<subdivisions; ++i) { 1.16378 + const unsigned int L = primitives.size; 1.16379 + for (unsigned int l = 0; l<L; ++l) { 1.16380 + const unsigned int 1.16381 + p0 = (unsigned int)primitives(0,0), p1 = (unsigned int)primitives(0,1), p2 = (unsigned int)primitives(0,2); 1.16382 + const float 1.16383 + x0 = points(p0,0), y0 = points(p0,1), z0 = points(p0,2), 1.16384 + x1 = points(p1,0), y1 = points(p1,1), z1 = points(p1,2), 1.16385 + x2 = points(p2,0), y2 = points(p2,1), z2 = points(p2,2), 1.16386 + tnx0 = (x0+x1)/2, tny0 = (y0+y1)/2, tnz0 = (z0+z1)/2, nn0 = (float)cimg_std::sqrt(tnx0*tnx0+tny0*tny0+tnz0*tnz0), 1.16387 + tnx1 = (x0+x2)/2, tny1 = (y0+y2)/2, tnz1 = (z0+z2)/2, nn1 = (float)cimg_std::sqrt(tnx1*tnx1+tny1*tny1+tnz1*tnz1), 1.16388 + tnx2 = (x1+x2)/2, tny2 = (y1+y2)/2, tnz2 = (z1+z2)/2, nn2 = (float)cimg_std::sqrt(tnx2*tnx2+tny2*tny2+tnz2*tnz2), 1.16389 + nx0 = tnx0/nn0, ny0 = tny0/nn0, nz0 = tnz0/nn0, 1.16390 + nx1 = tnx1/nn1, ny1 = tny1/nn1, nz1 = tnz1/nn1, 1.16391 + nx2 = tnx2/nn2, ny2 = tny2/nn2, nz2 = tnz2/nn2; 1.16392 + int i0 = -1, i1 = -1, i2 = -1; 1.16393 + cimglist_for(points,p) { 1.16394 + const float x = (float)points(p,0), y = (float)points(p,1), z = (float)points(p,2); 1.16395 + if (x==nx0 && y==ny0 && z==nz0) i0 = p; 1.16396 + if (x==nx1 && y==ny1 && z==nz1) i1 = p; 1.16397 + if (x==nx2 && y==ny2 && z==nz2) i2 = p; 1.16398 + } 1.16399 + if (i0<0) { points.insert(CImg<floatT>::vector(nx0,ny0,nz0)); i0 = points.size-1; } 1.16400 + if (i1<0) { points.insert(CImg<floatT>::vector(nx1,ny1,nz1)); i1 = points.size-1; } 1.16401 + if (i2<0) { points.insert(CImg<floatT>::vector(nx2,ny2,nz2)); i2 = points.size-1; } 1.16402 + primitives.remove(0); 1.16403 + primitives.insert(CImg<tf>::vector(p0,i0,i1)). 1.16404 + insert(CImg<tf>::vector((tf)i0,(tf)p1,(tf)i2)). 1.16405 + insert(CImg<tf>::vector((tf)i1,(tf)i2,(tf)p2)). 1.16406 + insert(CImg<tf>::vector((tf)i1,(tf)i0,(tf)i2)); 1.16407 + } 1.16408 + } 1.16409 + return points.get_append('x')*=radius; 1.16410 + } 1.16411 + 1.16412 + //! Return a 3D centered ellipsoid. 1.16413 + template<typename tf, typename t> 1.16414 + static CImg<floatT> ellipsoid3d(CImgList<tf>& primitives, const CImg<t>& tensor, 1.16415 + const unsigned int subdivisions=3) { 1.16416 + primitives.assign(); 1.16417 + if (!subdivisions) return CImg<floatT>(); 1.16418 + typedef typename cimg::superset<t,float>::type tfloat; 1.16419 + CImg<tfloat> S,V; 1.16420 + tensor.symmetric_eigen(S,V); 1.16421 + const tfloat l0 = S[0], l1 = S[1], l2 = S[2]; 1.16422 + CImg<floatT> points = sphere(primitives,subdivisions); 1.16423 + cimg_forX(points,p) { 1.16424 + points(p,0) = (float)(points(p,0)*l0); 1.16425 + points(p,1) = (float)(points(p,1)*l1); 1.16426 + points(p,2) = (float)(points(p,2)*l2); 1.16427 + } 1.16428 + V.transpose(); 1.16429 + points = V*points; 1.16430 + return points; 1.16431 + } 1.16432 + 1.16433 + //! Return a 3D elevation object of the instance image. 1.16434 + template<typename tf, typename tc, typename te> 1.16435 + CImg<floatT> get_elevation3d(CImgList<tf>& primitives, CImgList<tc>& colors, const CImg<te>& elevation) const { 1.16436 + primitives.assign(); 1.16437 + colors.assign(); 1.16438 + if (is_empty()) return *this; 1.16439 + if (depth>1) 1.16440 + throw CImgInstanceException("CImg<%s>::get_elevation3d() : Instance image (%u,%u,%u,%u,%p) is not a 2D image.", 1.16441 + pixel_type(),width,height,depth,dim,data); 1.16442 + if (!is_sameXY(elevation)) 1.16443 + throw CImgArgumentException("CImg<%s>::get_elevation3d() : Elevation image (%u,%u,%u,%u,%p) and instance image (%u,%u,%u,%u,%p) " 1.16444 + "have different sizes.",pixel_type(), 1.16445 + elevation.width,elevation.height,elevation.depth,elevation.dim,elevation.data, 1.16446 + width,height,depth,dim,data,pixel_type()); 1.16447 + float m, M = (float)maxmin(m); 1.16448 + if (M==m) ++M; 1.16449 + const unsigned int w = width + 1, h = height + 1; 1.16450 + CImg<floatT> points(w*h,3); 1.16451 + cimg_forXY(*this,x,y) { 1.16452 + const int yw = y*w, xpyw = x + yw, xpyww = xpyw + w; 1.16453 + points(xpyw,0) = points(xpyw+1,0) = points(xpyww+1,0) = points(xpyww,0) = (float)x; 1.16454 + points(xpyw,1) = points(xpyw+1,1) = points(xpyww+1,1) = points(xpyww,1) = (float)y; 1.16455 + points(xpyw,2) = points(xpyw+1,2) = points(xpyww+1,2) = points(xpyww,2) = (float)elevation(x,y); 1.16456 + primitives.insert(CImg<tf>::vector(xpyw,xpyw+1,xpyww+1,xpyww)); 1.16457 + const unsigned char 1.16458 + r = (unsigned char)(((*this)(x,y,0) - m)*255/(M-m)), 1.16459 + g = dim>1?(unsigned char)(((*this)(x,y,1) - m)*255/(M-m)):r, 1.16460 + b = dim>2?(unsigned char)(((*this)(x,y,2) - m)*255/(M-m)):(dim>1?0:r); 1.16461 + colors.insert(CImg<tc>::vector((tc)r,(tc)g,(tc)b)); 1.16462 + } 1.16463 + return points; 1.16464 + } 1.16465 + 1.16466 + // Inner routine used by the Marching square algorithm. 1.16467 + template<typename t> 1.16468 + static int _marching_squares_indice(const unsigned int edge, const CImg<t>& indices1, const CImg<t>& indices2, 1.16469 + const unsigned int x, const unsigned int nx) { 1.16470 + switch (edge) { 1.16471 + case 0 : return (int)indices1(x,0); 1.16472 + case 1 : return (int)indices1(nx,1); 1.16473 + case 2 : return (int)indices2(x,0); 1.16474 + case 3 : return (int)indices1(x,1); 1.16475 + } 1.16476 + return 0; 1.16477 + } 1.16478 + 1.16479 + //! Polygonize an implicit 2D function by the marching squares algorithm. 1.16480 + template<typename tf, typename tfunc> 1.16481 + static CImg<floatT> marching_squares(CImgList<tf>& primitives, const tfunc& func, const float isovalue, 1.16482 + const float x0, const float y0, 1.16483 + const float x1, const float y1, 1.16484 + const float resx, const float resy) { 1.16485 + static unsigned int edges[16] = { 0x0, 0x9, 0x3, 0xa, 0x6, 0xf, 0x5, 0xc, 0xc, 0x5, 0xf, 0x6, 0xa, 0x3, 0x9, 0x0 }; 1.16486 + static int segments[16][4] = { { -1,-1,-1,-1 }, { 0,3,-1,-1 }, { 0,1,-1,-1 }, { 1,3,-1,-1 }, 1.16487 + { 1,2,-1,-1 }, { 0,1,2,3 }, { 0,2,-1,-1 }, { 2,3,-1,-1 }, 1.16488 + { 2,3,-1,-1 }, { 0,2,-1,-1}, { 0,3,1,2 }, { 1,2,-1,-1 }, 1.16489 + { 1,3,-1,-1 }, { 0,1,-1,-1}, { 0,3,-1,-1}, { -1,-1,-1,-1 } }; 1.16490 + const unsigned int 1.16491 + nx = (unsigned int)((x1-x0+1)/resx), nxm1 = nx-1, 1.16492 + ny = (unsigned int)((y1-y0+1)/resy), nym1 = ny-1; 1.16493 + if (!nxm1 || !nym1) return CImg<floatT>(); 1.16494 + 1.16495 + primitives.assign(); 1.16496 + CImgList<floatT> points; 1.16497 + CImg<intT> indices1(nx,1,1,2,-1), indices2(nx,1,1,2); 1.16498 + CImg<floatT> values1(nx), values2(nx); 1.16499 + float X = 0, Y = 0, nX = 0, nY = 0; 1.16500 + 1.16501 + // Fill first line with values 1.16502 + cimg_forX(values1,x) { values1(x) = (float)func(X,Y); X+=resx; } 1.16503 + 1.16504 + // Run the marching squares algorithm 1.16505 + Y = y0; nY = Y + resy; 1.16506 + for (unsigned int yi = 0, nyi = 1; yi<nym1; ++yi, ++nyi, Y=nY, nY+=resy) { 1.16507 + X = x0; nX = X + resx; 1.16508 + indices2.fill(-1); 1.16509 + for (unsigned int xi = 0, nxi = 1; xi<nxm1; ++xi, ++nxi, X=nX, nX+=resx) { 1.16510 + 1.16511 + // Determine cube configuration 1.16512 + const float 1.16513 + val0 = values1(xi), val1 = values1(nxi), 1.16514 + val2 = values2(nxi) = (float)func(nX,nY), 1.16515 + val3 = values2(xi) = (float)func(X,nY); 1.16516 + 1.16517 + const unsigned int configuration = (val0<isovalue?1:0) | (val1<isovalue?2:0) | (val2<isovalue?4:0) | (val3<isovalue?8:0), 1.16518 + edge = edges[configuration]; 1.16519 + 1.16520 + // Compute intersection points 1.16521 + if (edge) { 1.16522 + if ((edge&1) && indices1(xi,0)<0) { 1.16523 + const float Xi = X + (isovalue-val0)*resx/(val1-val0); 1.16524 + indices1(xi,0) = points.size; 1.16525 + points.insert(CImg<floatT>::vector(Xi,Y)); 1.16526 + } 1.16527 + if ((edge&2) && indices1(nxi,1)<0) { 1.16528 + const float Yi = Y + (isovalue-val1)*resy/(val2-val1); 1.16529 + indices1(nxi,1) = points.size; 1.16530 + points.insert(CImg<floatT>::vector(nX,Yi)); 1.16531 + } 1.16532 + if ((edge&4) && indices2(xi,0)<0) { 1.16533 + const float Xi = X + (isovalue-val3)*resx/(val2-val3); 1.16534 + indices2(xi,0) = points.size; 1.16535 + points.insert(CImg<floatT>::vector(Xi,nY)); 1.16536 + } 1.16537 + if ((edge&8) && indices1(xi,1)<0) { 1.16538 + const float Yi = Y + (isovalue-val0)*resy/(val3-val0); 1.16539 + indices1(xi,1) = points.size; 1.16540 + points.insert(CImg<floatT>::vector(X,Yi)); 1.16541 + } 1.16542 + 1.16543 + // Create segments 1.16544 + for (int *segment = segments[configuration]; *segment!=-1; ) { 1.16545 + const unsigned int p0 = *(segment++), p1 = *(segment++); 1.16546 + const tf 1.16547 + i0 = (tf)(_marching_squares_indice(p0,indices1,indices2,xi,nxi)), 1.16548 + i1 = (tf)(_marching_squares_indice(p1,indices1,indices2,xi,nxi)); 1.16549 + primitives.insert(CImg<tf>::vector(i0,i1)); 1.16550 + } 1.16551 + } 1.16552 + } 1.16553 + values1.swap(values2); 1.16554 + indices1.swap(indices2); 1.16555 + } 1.16556 + return points.get_append('x'); 1.16557 + } 1.16558 + 1.16559 + // Inner routine used by the Marching cube algorithm. 1.16560 + template<typename t> 1.16561 + static int _marching_cubes_indice(const unsigned int edge, const CImg<t>& indices1, const CImg<t>& indices2, 1.16562 + const unsigned int x, const unsigned int y, const unsigned int nx, const unsigned int ny) { 1.16563 + switch (edge) { 1.16564 + case 0 : return indices1(x,y,0); 1.16565 + case 1 : return indices1(nx,y,1); 1.16566 + case 2 : return indices1(x,ny,0); 1.16567 + case 3 : return indices1(x,y,1); 1.16568 + case 4 : return indices2(x,y,0); 1.16569 + case 5 : return indices2(nx,y,1); 1.16570 + case 6 : return indices2(x,ny,0); 1.16571 + case 7 : return indices2(x,y,1); 1.16572 + case 8 : return indices1(x,y,2); 1.16573 + case 9 : return indices1(nx,y,2); 1.16574 + case 10 : return indices1(nx,ny,2); 1.16575 + case 11 : return indices1(x,ny,2); 1.16576 + } 1.16577 + return 0; 1.16578 + } 1.16579 + 1.16580 + //! Polygonize an implicit function 1.16581 + // This function uses the Marching Cubes Tables published on the web page : 1.16582 + // http://astronomy.swin.edu.au/~pbourke/modelling/polygonise/ 1.16583 + template<typename tf, typename tfunc> 1.16584 + static CImg<floatT> marching_cubes(CImgList<tf>& primitives, 1.16585 + const tfunc& func, const float isovalue, 1.16586 + const float x0, const float y0, const float z0, 1.16587 + const float x1, const float y1, const float z1, 1.16588 + const float resx, const float resy, const float resz, 1.16589 + const bool invert_faces=false) { 1.16590 + 1.16591 + static unsigned int edges[256] = { 1.16592 + 0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 1.16593 + 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, 1.16594 + 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, 1.16595 + 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, 1.16596 + 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, 1.16597 + 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, 1.16598 + 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, 1.16599 + 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 1.16600 + 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, 1.16601 + 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, 1.16602 + 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, 1.16603 + 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, 1.16604 + 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, 1.16605 + 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, 1.16606 + 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, 1.16607 + 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000 }; 1.16608 + 1.16609 + static int triangles[256][16] = 1.16610 + {{ -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 }, 1.16611 + { 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.16612 + { 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 }, 1.16613 + { 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 }, 1.16614 + { 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.16615 + { 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 }, 1.16616 + { 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 }, 1.16617 + { 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 }, 1.16618 + { 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 }, 1.16619 + { 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.16620 + { 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 }, 1.16621 + { 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 }, 1.16622 + { 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 }, 1.16623 + { 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 }, 1.16624 + { 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 }, 1.16625 + { 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 }, 1.16626 + { 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 }, 1.16627 + { 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.16628 + { 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 }, 1.16629 + { 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 }, 1.16630 + { 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 }, 1.16631 + { 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 }, 1.16632 + { 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 }, 1.16633 + { 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 }, 1.16634 + { 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 }, 1.16635 + { 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 }, 1.16636 + { 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 }, 1.16637 + { 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 }, 1.16638 + { 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 }, 1.16639 + { 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 }, 1.16640 + { 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 }, 1.16641 + { 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 }, 1.16642 + { 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 }, 1.16643 + { 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.16644 + { 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 }, 1.16645 + { 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 }, 1.16646 + { 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 }, 1.16647 + { 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 }, 1.16648 + { 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 }, 1.16649 + { 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 }, 1.16650 + { 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.16651 + { 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 }, 1.16652 + { 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 }, 1.16653 + { 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 }, 1.16654 + { 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 }, 1.16655 + { 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 }, 1.16656 + { 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 }, 1.16657 + { 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 }, 1.16658 + { 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 }, 1.16659 + { 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.16660 + { 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 }, 1.16661 + { 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 }, 1.16662 + { 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 }, 1.16663 + { 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 }, 1.16664 + { 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 }, 1.16665 + { 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 }, 1.16666 + { 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 }, 1.16667 + { 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.16668 + { 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 }, 1.16669 + { 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 }, 1.16670 + { 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.16671 + { 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 }, 1.16672 + { 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 }, 1.16673 + { 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 }, 1.16674 + { 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 }, 1.16675 + { 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 }, 1.16676 + { 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 }, 1.16677 + { 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 }, 1.16678 + { 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 }, 1.16679 + { 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 }, 1.16680 + { 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 }, 1.16681 + { 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 }, 1.16682 + { 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 }, 1.16683 + { 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 }, 1.16684 + { 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 }, 1.16685 + { 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 }, 1.16686 + { 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.16687 + { 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 }, 1.16688 + { 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 }, 1.16689 + { 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 }, 1.16690 + { 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 }, 1.16691 + { 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 }, 1.16692 + { 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 }, 1.16693 + { 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 }, 1.16694 + { 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 }, 1.16695 + { 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 }, 1.16696 + { 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 }, 1.16697 + { 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 }, 1.16698 + { 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 }, 1.16699 + { 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.16700 + { 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 }, 1.16701 + { 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 }, 1.16702 + { 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.16703 + { 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.16704 + { 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 }, 1.16705 + { 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 }, 1.16706 + { 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 }, 1.16707 + { 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 }, 1.16708 + { 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 }, 1.16709 + { 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 }, 1.16710 + { 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 }, 1.16711 + { 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.16712 + { 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 }, 1.16713 + { 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 }, 1.16714 + { 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 }, 1.16715 + { 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 }, 1.16716 + { 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 }, 1.16717 + { 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 }, 1.16718 + { 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 }, 1.16719 + { 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 }, 1.16720 + { 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 }, 1.16721 + { 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 }, 1.16722 + { 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.16723 + { 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 }, 1.16724 + { 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 }, 1.16725 + { 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 }, 1.16726 + { 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 }, 1.16727 + { 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 }, 1.16728 + { 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 }, 1.16729 + { 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 }, 1.16730 + { 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 }, 1.16731 + { 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.16732 + { 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 }, 1.16733 + { 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 }, 1.16734 + { 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 }, 1.16735 + { 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.16736 + { 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 }, 1.16737 + { 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 }}; 1.16738 + 1.16739 + const unsigned int 1.16740 + nx = (unsigned int)((x1-x0+1)/resx), nxm1 = nx-1, 1.16741 + ny = (unsigned int)((y1-y0+1)/resy), nym1 = ny-1, 1.16742 + nz = (unsigned int)((z1-z0+1)/resz), nzm1 = nz-1; 1.16743 + if (!nxm1 || !nym1 || !nzm1) return CImg<floatT>(); 1.16744 + 1.16745 + primitives.assign(); 1.16746 + CImgList<floatT> points; 1.16747 + CImg<intT> indices1(nx,ny,1,3,-1), indices2(indices1); 1.16748 + CImg<floatT> values1(nx,ny), values2(nx,ny); 1.16749 + float X = 0, Y = 0, Z = 0, nX = 0, nY = 0, nZ = 0; 1.16750 + 1.16751 + // Fill the first plane with function values 1.16752 + Y = y0; 1.16753 + cimg_forY(values1,y) { 1.16754 + X = x0; 1.16755 + cimg_forX(values1,x) { values1(x,y) = (float)func(X,Y,z0); X+=resx; } 1.16756 + Y+=resy; 1.16757 + } 1.16758 + 1.16759 + // Run Marching Cubes algorithm 1.16760 + Z = z0; nZ = Z + resz; 1.16761 + for (unsigned int zi = 0; zi<nzm1; ++zi, Z = nZ, nZ+=resz) { 1.16762 + Y = y0; nY = Y + resy; 1.16763 + indices2.fill(-1); 1.16764 + for (unsigned int yi = 0, nyi = 1; yi<nym1; ++yi, ++nyi, Y = nY, nY+=resy) { 1.16765 + X = x0; nX = X + resx; 1.16766 + for (unsigned int xi = 0, nxi = 1; xi<nxm1; ++xi, ++nxi, X = nX, nX+=resx) { 1.16767 + 1.16768 + // Determine cube configuration 1.16769 + const float 1.16770 + val0 = values1(xi,yi), val1 = values1(nxi,yi), val2 = values1(nxi,nyi), val3 = values1(xi,nyi), 1.16771 + val4 = values2(xi,yi) = (float)func(X,Y,nZ), 1.16772 + val5 = values2(nxi,yi) = (float)func(nX,Y,nZ), 1.16773 + val6 = values2(nxi,nyi) = (float)func(nX,nY,nZ), 1.16774 + val7 = values2(xi,nyi) = (float)func(X,nY,nZ); 1.16775 + 1.16776 + const unsigned int configuration = 1.16777 + (val0<isovalue?1:0) | (val1<isovalue?2:0) | (val2<isovalue?4:0) | (val3<isovalue?8:0) | 1.16778 + (val4<isovalue?16:0) | (val5<isovalue?32:0) | (val6<isovalue?64:0) | (val7<isovalue?128:0), 1.16779 + edge = edges[configuration]; 1.16780 + 1.16781 + // Compute intersection points 1.16782 + if (edge) { 1.16783 + if ((edge&1) && indices1(xi,yi,0)<0) { 1.16784 + const float Xi = X + (isovalue-val0)*resx/(val1-val0); 1.16785 + indices1(xi,yi,0) = points.size; 1.16786 + points.insert(CImg<floatT>::vector(Xi,Y,Z)); 1.16787 + } 1.16788 + if ((edge&2) && indices1(nxi,yi,1)<0) { 1.16789 + const float Yi = Y + (isovalue-val1)*resy/(val2-val1); 1.16790 + indices1(nxi,yi,1) = points.size; 1.16791 + points.insert(CImg<floatT>::vector(nX,Yi,Z)); 1.16792 + } 1.16793 + if ((edge&4) && indices1(xi,nyi,0)<0) { 1.16794 + const float Xi = X + (isovalue-val3)*resx/(val2-val3); 1.16795 + indices1(xi,nyi,0) = points.size; 1.16796 + points.insert(CImg<floatT>::vector(Xi,nY,Z)); 1.16797 + } 1.16798 + if ((edge&8) && indices1(xi,yi,1)<0) { 1.16799 + const float Yi = Y + (isovalue-val0)*resy/(val3-val0); 1.16800 + indices1(xi,yi,1) = points.size; 1.16801 + points.insert(CImg<floatT>::vector(X,Yi,Z)); 1.16802 + } 1.16803 + if ((edge&16) && indices2(xi,yi,0)<0) { 1.16804 + const float Xi = X + (isovalue-val4)*resx/(val5-val4); 1.16805 + indices2(xi,yi,0) = points.size; 1.16806 + points.insert(CImg<floatT>::vector(Xi,Y,nZ)); 1.16807 + } 1.16808 + if ((edge&32) && indices2(nxi,yi,1)<0) { 1.16809 + const float Yi = Y + (isovalue-val5)*resy/(val6-val5); 1.16810 + indices2(nxi,yi,1) = points.size; 1.16811 + points.insert(CImg<floatT>::vector(nX,Yi,nZ)); 1.16812 + } 1.16813 + if ((edge&64) && indices2(xi,nyi,0)<0) { 1.16814 + const float Xi = X + (isovalue-val7)*resx/(val6-val7); 1.16815 + indices2(xi,nyi,0) = points.size; 1.16816 + points.insert(CImg<floatT>::vector(Xi,nY,nZ)); 1.16817 + } 1.16818 + if ((edge&128) && indices2(xi,yi,1)<0) { 1.16819 + const float Yi = Y + (isovalue-val4)*resy/(val7-val4); 1.16820 + indices2(xi,yi,1) = points.size; 1.16821 + points.insert(CImg<floatT>::vector(X,Yi,nZ)); 1.16822 + } 1.16823 + if ((edge&256) && indices1(xi,yi,2)<0) { 1.16824 + const float Zi = Z+ (isovalue-val0)*resz/(val4-val0); 1.16825 + indices1(xi,yi,2) = points.size; 1.16826 + points.insert(CImg<floatT>::vector(X,Y,Zi)); 1.16827 + } 1.16828 + if ((edge&512) && indices1(nxi,yi,2)<0) { 1.16829 + const float Zi = Z + (isovalue-val1)*resz/(val5-val1); 1.16830 + indices1(nxi,yi,2) = points.size; 1.16831 + points.insert(CImg<floatT>::vector(nX,Y,Zi)); 1.16832 + } 1.16833 + if ((edge&1024) && indices1(nxi,nyi,2)<0) { 1.16834 + const float Zi = Z + (isovalue-val2)*resz/(val6-val2); 1.16835 + indices1(nxi,nyi,2) = points.size; 1.16836 + points.insert(CImg<floatT>::vector(nX,nY,Zi)); 1.16837 + } 1.16838 + if ((edge&2048) && indices1(xi,nyi,2)<0) { 1.16839 + const float Zi = Z + (isovalue-val3)*resz/(val7-val3); 1.16840 + indices1(xi,nyi,2) = points.size; 1.16841 + points.insert(CImg<floatT>::vector(X,nY,Zi)); 1.16842 + } 1.16843 + 1.16844 + // Create triangles 1.16845 + for (int *triangle = triangles[configuration]; *triangle!=-1; ) { 1.16846 + const unsigned int p0 = *(triangle++), p1 = *(triangle++), p2 = *(triangle++); 1.16847 + const tf 1.16848 + i0 = (tf)(_marching_cubes_indice(p0,indices1,indices2,xi,yi,nxi,nyi)), 1.16849 + i1 = (tf)(_marching_cubes_indice(p1,indices1,indices2,xi,yi,nxi,nyi)), 1.16850 + i2 = (tf)(_marching_cubes_indice(p2,indices1,indices2,xi,yi,nxi,nyi)); 1.16851 + if (invert_faces) primitives.insert(CImg<tf>::vector(i0,i1,i2)); 1.16852 + else primitives.insert(CImg<tf>::vector(i0,i2,i1)); 1.16853 + } 1.16854 + } 1.16855 + } 1.16856 + } 1.16857 + cimg::swap(values1,values2); 1.16858 + cimg::swap(indices1,indices2); 1.16859 + } 1.16860 + return points.get_append('x'); 1.16861 + } 1.16862 + 1.16863 + struct _marching_squares_func { 1.16864 + const CImg<T>& ref; 1.16865 + _marching_squares_func(const CImg<T>& pref):ref(pref) {} 1.16866 + float operator()(const float x, const float y) const { 1.16867 + return (float)ref((int)x,(int)y); 1.16868 + } 1.16869 + }; 1.16870 + 1.16871 + struct _marching_cubes_func { 1.16872 + const CImg<T>& ref; 1.16873 + _marching_cubes_func(const CImg<T>& pref):ref(pref) {} 1.16874 + float operator()(const float x, const float y, const float z) const { 1.16875 + return (float)ref((int)x,(int)y,(int)z); 1.16876 + } 1.16877 + }; 1.16878 + 1.16879 + struct _marching_squares_func_float { 1.16880 + const CImg<T>& ref; 1.16881 + _marching_squares_func_float(const CImg<T>& pref):ref(pref) {} 1.16882 + float operator()(const float x, const float y) const { 1.16883 + return (float)ref._linear_atXY(x,y); 1.16884 + } 1.16885 + }; 1.16886 + 1.16887 + struct _marching_cubes_func_float { 1.16888 + const CImg<T>& ref; 1.16889 + _marching_cubes_func_float(const CImg<T>& pref):ref(pref) {} 1.16890 + float operator()(const float x, const float y, const float z) const { 1.16891 + return (float)ref._linear_atXYZ(x,y,z); 1.16892 + } 1.16893 + }; 1.16894 + 1.16895 + //! Compute a vectorization of an implicit function. 1.16896 + template<typename tf> 1.16897 + CImg<floatT> get_isovalue3d(CImgList<tf>& primitives, const float isovalue, 1.16898 + const float resx=1, const float resy=1, const float resz=1, 1.16899 + const bool invert_faces=false) const { 1.16900 + primitives.assign(); 1.16901 + if (is_empty()) return *this; 1.16902 + if (dim>1) 1.16903 + throw CImgInstanceException("CImg<%s>::get_isovalue3d() : Instance image (%u,%u,%u,%u,%p) is not a scalar image.", 1.16904 + pixel_type(),width,height,depth,dim,data); 1.16905 + CImg<floatT> points; 1.16906 + if (depth>1) { 1.16907 + if (resx==1 && resy==1 && resz==1) { 1.16908 + const _marching_cubes_func func(*this); 1.16909 + points = marching_cubes(primitives,func,isovalue,0,0,0,dimx()-1.0f,dimy()-1.0f,dimz()-1.0f,resx,resy,resz,invert_faces); 1.16910 + } else { 1.16911 + const _marching_cubes_func_float func(*this); 1.16912 + points = marching_cubes(primitives,func,isovalue,0,0,0,dimx()-1.0f,dimy()-1.0f,dimz()-1.0f,resx,resy,resz,invert_faces); 1.16913 + } 1.16914 + } else { 1.16915 + if (resx==1 && resy==1) { 1.16916 + const _marching_squares_func func(*this); 1.16917 + points = marching_squares(primitives,func,isovalue,0,0,dimx()-1.0f,dimy()-1.0f,resx,resy); 1.16918 + } else { 1.16919 + const _marching_squares_func_float func(*this); 1.16920 + points = marching_squares(primitives,func,isovalue,0,0,dimx()-1.0f,dimy()-1.0f,resx,resy); 1.16921 + } 1.16922 + if (points) points.resize(-100,3,1,1,0); 1.16923 + } 1.16924 + return points; 1.16925 + } 1.16926 + 1.16927 + //! Translate a 3D object. 1.16928 + CImg<T>& translate_object3d(const float tx, const float ty=0, const float tz=0) { 1.16929 + get_shared_line(0)+=tx; get_shared_line(1)+=ty; get_shared_line(2)+=tz; 1.16930 + return *this; 1.16931 + } 1.16932 + 1.16933 + CImg<Tfloat> get_translate_object3d(const float tx, const float ty=0, const float tz=0) const { 1.16934 + return CImg<Tfloat>(*this,false).translate_object3d(tx,ty,tz); 1.16935 + } 1.16936 + 1.16937 + //! Translate a 3D object so that it becomes centered. 1.16938 + CImg<T>& translate_object3d() { 1.16939 + CImg<T> xcoords = get_shared_line(0), ycoords = get_shared_line(1), zcoords = get_shared_line(2); 1.16940 + float xm, xM = (float)xcoords.maxmin(xm), ym, yM = (float)ycoords.maxmin(ym), zm, zM = (float)zcoords.maxmin(zm); 1.16941 + xcoords-=(xm + xM)/2; ycoords-=(ym + yM)/2; zcoords-=(zm + zM)/2; 1.16942 + return *this; 1.16943 + } 1.16944 + 1.16945 + CImg<Tfloat> get_translate_object3d() const { 1.16946 + return CImg<Tfloat>(*this,false).translate_object3d(); 1.16947 + } 1.16948 + 1.16949 + //! Resize a 3D object. 1.16950 + CImg<T>& resize_object3d(const float sx, const float sy=-100, const float sz=-100) { 1.16951 + CImg<T> xcoords = get_shared_line(0), ycoords = get_shared_line(1), zcoords = get_shared_line(2); 1.16952 + float xm, xM = (float)xcoords.maxmin(xm), ym, yM = (float)ycoords.maxmin(ym), zm, zM = (float)zcoords.maxmin(zm); 1.16953 + if (xm<xM) { if (sx>0) xcoords*=sx/(xM-xm); else xcoords*=-sx/100; } 1.16954 + if (ym<yM) { if (sy>0) ycoords*=sy/(yM-ym); else ycoords*=-sy/100; } 1.16955 + if (zm<zM) { if (sz>0) zcoords*=sz/(zM-zm); else zcoords*=-sz/100; } 1.16956 + return *this; 1.16957 + } 1.16958 + 1.16959 + CImg<Tfloat> get_resize_object3d(const float sx, const float sy=-100, const float sz=-100) const { 1.16960 + return CImg<Tfloat>(*this,false).resize_object3d(sx,sy,sz); 1.16961 + } 1.16962 + 1.16963 + // Resize a 3D object so that its max dimension if one. 1.16964 + CImg<T> resize_object3d() const { 1.16965 + CImg<T> xcoords = get_shared_line(0), ycoords = get_shared_line(1), zcoords = get_shared_line(2); 1.16966 + float xm, xM = (float)xcoords.maxmin(xm), ym, yM = (float)ycoords.maxmin(ym), zm, zM = (float)zcoords.maxmin(zm); 1.16967 + const float dx = xM - xm, dy = yM - ym, dz = zM - zm, dmax = cimg::max(dx,dy,dz); 1.16968 + if (dmax>0) { xcoords/=dmax; ycoords/=dmax; zcoords/=dmax; } 1.16969 + return *this; 1.16970 + } 1.16971 + 1.16972 + CImg<Tfloat> get_resize_object3d() const { 1.16973 + return CImg<Tfloat>(*this,false).resize_object3d(); 1.16974 + } 1.16975 + 1.16976 + //! Append a 3D object to another one. 1.16977 + template<typename tf, typename tp, typename tff> 1.16978 + CImg<T>& append_object3d(CImgList<tf>& primitives, const CImg<tp>& obj_points, const CImgList<tff>& obj_primitives) { 1.16979 + const unsigned int P = width; 1.16980 + append(obj_points,'x'); 1.16981 + const unsigned int N = primitives.size; 1.16982 + primitives.insert(obj_primitives); 1.16983 + for (unsigned int i = N; i<primitives.size; ++i) { 1.16984 + CImg<tf> &p = primitives[i]; 1.16985 + if (p.size()!=5) p+=P; 1.16986 + else { p[0]+=P; if (p[2]==0) p[1]+=P; } 1.16987 + } 1.16988 + return *this; 1.16989 + } 1.16990 + 1.16991 + //@} 1.16992 + //---------------------------- 1.16993 + // 1.16994 + //! \name Color bases 1.16995 + //@{ 1.16996 + //---------------------------- 1.16997 + 1.16998 + //! Return a default indexed color palette with 256 (R,G,B) entries. 1.16999 + /** 1.17000 + The default color palette is used by %CImg when displaying images on 256 colors displays. 1.17001 + It consists in the quantification of the (R,G,B) color space using 3:3:2 bits for color coding 1.17002 + (i.e 8 levels for the Red and Green and 4 levels for the Blue). 1.17003 + \return a 1x256x1x3 color image defining the palette entries. 1.17004 + **/ 1.17005 + static CImg<Tuchar> default_LUT8() { 1.17006 + static CImg<Tuchar> palette; 1.17007 + if (!palette) { 1.17008 + palette.assign(1,256,1,3); 1.17009 + for (unsigned int index = 0, r = 16; r<256; r+=32) 1.17010 + for (unsigned int g = 16; g<256; g+=32) 1.17011 + for (unsigned int b = 32; b<256; b+=64) { 1.17012 + palette(0,index,0) = (Tuchar)r; 1.17013 + palette(0,index,1) = (Tuchar)g; 1.17014 + palette(0,index++,2) = (Tuchar)b; 1.17015 + } 1.17016 + } 1.17017 + return palette; 1.17018 + } 1.17019 + 1.17020 + //! Return a rainbow color palette with 256 (R,G,B) entries. 1.17021 + static CImg<Tuchar> rainbow_LUT8() { 1.17022 + static CImg<Tuchar> palette; 1.17023 + if (!palette) { 1.17024 + CImg<Tint> tmp(1,256,1,3,1); 1.17025 + tmp.get_shared_channel(0).sequence(0,359); 1.17026 + palette = tmp.HSVtoRGB(); 1.17027 + } 1.17028 + return palette; 1.17029 + } 1.17030 + 1.17031 + //! Return a contrasted color palette with 256 (R,G,B) entries. 1.17032 + static CImg<Tuchar> contrast_LUT8() { 1.17033 + static const unsigned char pal[] = { 1.17034 + 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, 1.17035 + 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, 1.17036 + 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, 1.17037 + 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, 1.17038 + 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.17039 + 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, 1.17040 + 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, 1.17041 + 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, 1.17042 + 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, 1.17043 + 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, 1.17044 + 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, 1.17045 + 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, 1.17046 + 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, 1.17047 + 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, 1.17048 + 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, 1.17049 + 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, 1.17050 + 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, 1.17051 + 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, 1.17052 + 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, 1.17053 + 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, 1.17054 + 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, 1.17055 + 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, 1.17056 + 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, 1.17057 + 23,168,19,50,240,244,185,0,1,144,10,168,31,82,1,13 }; 1.17058 + static const CImg<Tuchar> palette(pal,1,256,1,3,false); 1.17059 + return palette; 1.17060 + } 1.17061 + 1.17062 + //! Convert (R,G,B) color image to indexed color image. 1.17063 + template<typename t> 1.17064 + CImg<T>& RGBtoLUT(const CImg<t>& palette, const bool dithering=true, const bool indexing=false) { 1.17065 + return get_RGBtoLUT(palette,dithering,indexing).transfer_to(*this); 1.17066 + } 1.17067 + 1.17068 + template<typename t> 1.17069 + CImg<t> get_RGBtoLUT(const CImg<t>& palette, const bool dithering=true, const bool indexing=false) const { 1.17070 + if (is_empty()) return CImg<t>(); 1.17071 + if (dim!=3) 1.17072 + throw CImgInstanceException("CImg<%s>::RGBtoLUT() : Input image dimension is dim=%u, " 1.17073 + "should be a (R,G,B) image.", 1.17074 + pixel_type(),dim); 1.17075 + if (palette.data && palette.dim!=3) 1.17076 + throw CImgArgumentException("CImg<%s>::RGBtoLUT() : Given palette dimension is dim=%u, " 1.17077 + "should be a (R,G,B) palette", 1.17078 + pixel_type(),palette.dim); 1.17079 + CImg<t> res(width,height,depth,indexing?1:3); 1.17080 + float *line1 = new float[3*width], *line2 = new float[3*width]; 1.17081 + t *pRd = res.ptr(0,0,0,0), *pGd = indexing?pRd:res.ptr(0,0,0,1), *pBd = indexing?pRd:res.ptr(0,0,0,2); 1.17082 + cimg_forZ(*this,z) { 1.17083 + const T *pRs = ptr(0,0,z,0), *pGs = ptr(0,0,z,1), *pBs = ptr(0,0,z,2); 1.17084 + float *ptrd = line2; cimg_forX(*this,x) { *(ptrd++) = (float)*(pRs++); *(ptrd++) = (float)*(pGs++); *(ptrd++) = (float)*(pBs++); } 1.17085 + cimg_forY(*this,y) { 1.17086 + cimg::swap(line1,line2); 1.17087 + if (y<dimy()-1) { 1.17088 + const int ny = y + 1; 1.17089 + const T *pRs = ptr(0,ny,z,0), *pGs = ptr(0,ny,z,1), *pBs = ptr(0,ny,z,2); 1.17090 + float *ptrd = line2; cimg_forX(*this,x) { *(ptrd++) = (float)*(pRs++); *(ptrd++) = (float)*(pGs++); *(ptrd++) = (float)*(pBs++); } 1.17091 + } 1.17092 + float *ptr1 = line1, *ptr2 = line2; 1.17093 + cimg_forX(*this,x) { 1.17094 + float R = *(ptr1++), G = *(ptr1++), B = *(ptr1++); 1.17095 + R = R<0?0:(R>255?255:R); G = G<0?0:(G>255?255:G); B = B<0?0:(B>255?255:B); 1.17096 + t Rbest = 0, Gbest = 0, Bbest = 0; 1.17097 + int best_index = 0; 1.17098 + if (palette) { // find best match in given color palette 1.17099 + const t *pRs = palette.ptr(0,0,0,0), *pGs = palette.ptr(0,0,0,1), *pBs = palette.ptr(0,0,0,2); 1.17100 + const unsigned int Npal = palette.width*palette.height*palette.depth; 1.17101 + float min = cimg::type<float>::max(); 1.17102 + for (unsigned int off = 0; off<Npal; ++off) { 1.17103 + const t Rp = *(pRs++), Gp = *(pGs++), Bp = *(pBs++); 1.17104 + const float error = cimg::sqr((float)Rp-(float)R) + cimg::sqr((float)Gp-(float)G) + cimg::sqr((float)Bp-(float)B); 1.17105 + if (error<min) { min = error; best_index = off; Rbest = Rp; Gbest = Gp; Bbest = Bp; } 1.17106 + } 1.17107 + } else { 1.17108 + Rbest = (t)((unsigned char)R&0xe0); Gbest = (t)((unsigned char)G&0xe0); Bbest = (t)((unsigned char)B&0xc0); 1.17109 + best_index = (unsigned char)Rbest | ((unsigned char)Gbest>>3) | ((unsigned char)Bbest>>6); 1.17110 + } 1.17111 + if (indexing) *(pRd++) = (t)best_index; else { *(pRd++) = Rbest; *(pGd++) = Gbest; *(pBd++) = Bbest; } 1.17112 + if (dithering) { // apply dithering to neighborhood pixels if needed 1.17113 + const float dR = (float)(R-Rbest), dG = (float)(G-Gbest), dB = (float)(B-Bbest); 1.17114 + if (x<dimx()-1) { *(ptr1++)+= dR*7/16; *(ptr1++)+= dG*7/16; *(ptr1++)+= dB*7/16; ptr1-=3; } 1.17115 + if (y<dimy()-1) { 1.17116 + *(ptr2++)+= dR*5/16; *(ptr2++)+= dG*5/16; *ptr2+= dB*5/16; ptr2-=2; 1.17117 + if (x>0) { *(--ptr2)+= dB*3/16; *(--ptr2)+= dG*3/16; *(--ptr2)+= dR*3/16; ptr2+=3; } 1.17118 + if (x<dimx()-1) { ptr2+=3; *(ptr2++)+= dR/16; *(ptr2++)+= dG/16; *ptr2+= dB/16; ptr2-=5; } 1.17119 + } 1.17120 + } 1.17121 + ptr2+=3; 1.17122 + } 1.17123 + } 1.17124 + } 1.17125 + delete[] line1; delete[] line2; 1.17126 + return res; 1.17127 + } 1.17128 + 1.17129 + //! Convert color pixels from (R,G,B) to match the default palette. 1.17130 + CImg<T>& RGBtoLUT(const bool dithering=true, const bool indexing=false) { 1.17131 + return get_RGBtoLUT(dithering,indexing).transfer_to(*this); 1.17132 + } 1.17133 + 1.17134 + CImg<Tuchar> get_RGBtoLUT(const bool dithering=true, const bool indexing=false) const { 1.17135 + static const CImg<Tuchar> empty; 1.17136 + return get_RGBtoLUT(empty,dithering,indexing); 1.17137 + } 1.17138 + 1.17139 + //! Convert an indexed image to a (R,G,B) image using the specified color palette. 1.17140 + CImg<T>& LUTtoRGB(const CImg<T>& palette) { 1.17141 + return get_LUTtoRGB(palette).transfer_to(*this); 1.17142 + } 1.17143 + 1.17144 + template<typename t> 1.17145 + CImg<t> get_LUTtoRGB(const CImg<t>& palette) const { 1.17146 + if (is_empty()) return CImg<t>(); 1.17147 + if (dim!=1) 1.17148 + throw CImgInstanceException("CImg<%s>::LUTtoRGB() : Input image dimension is dim=%u, " 1.17149 + "should be a LUT image", 1.17150 + pixel_type(),dim); 1.17151 + if (palette.data && palette.dim!=3) 1.17152 + throw CImgArgumentException("CImg<%s>::LUTtoRGB() : Given palette dimension is dim=%u, " 1.17153 + "should be a (R,G,B) palette", 1.17154 + pixel_type(),palette.dim); 1.17155 + const CImg<t> pal = palette.data?palette:CImg<t>(default_LUT8()); 1.17156 + CImg<t> res(width,height,depth,3); 1.17157 + const t *pRs = pal.ptr(0,0,0,0), *pGs = pal.ptr(0,0,0,1), *pBs = pal.ptr(0,0,0,2); 1.17158 + t *pRd = res.ptr(0,0,0,1), *pGd = pRd + width*height*depth, *pBd = pGd + width*height*depth; 1.17159 + const unsigned int Npal = palette.width*palette.height*palette.depth; 1.17160 + cimg_for(*this,ptr,T) { 1.17161 + const unsigned int index = ((unsigned int)*ptr)%Npal; 1.17162 + *(--pRd) = pRs[index]; *(--pGd) = pGs[index]; *(--pBd) = pBs[index]; 1.17163 + } 1.17164 + return res; 1.17165 + } 1.17166 + 1.17167 + //! Convert an indexed image (with the default palette) to a (R,G,B) image. 1.17168 + CImg<T>& LUTtoRGB() { 1.17169 + return get_LUTtoRGB().transfer_to(*this); 1.17170 + } 1.17171 + 1.17172 + CImg<Tuchar> get_LUTtoRGB() const { 1.17173 + static const CImg<Tuchar> empty; 1.17174 + return get_LUTtoRGB(empty); 1.17175 + } 1.17176 + 1.17177 + //! Convert color pixels from (R,G,B) to (H,S,V). 1.17178 + CImg<T>& RGBtoHSV() { 1.17179 + if (is_empty()) return *this; 1.17180 + if (dim!=3) 1.17181 + throw CImgInstanceException("CImg<%s>::RGBtoHSV() : Input image dimension is dim=%u, " 1.17182 + "should be a (R,G,B) image.", 1.17183 + pixel_type(),dim); 1.17184 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17185 + for (unsigned long N = width*height*depth; N; --N) { 1.17186 + const Tfloat 1.17187 + R = (Tfloat)*p1, 1.17188 + G = (Tfloat)*p2, 1.17189 + B = (Tfloat)*p3, 1.17190 + nR = (R<0?0:(R>255?255:R))/255, 1.17191 + nG = (G<0?0:(G>255?255:G))/255, 1.17192 + nB = (B<0?0:(B>255?255:B))/255, 1.17193 + m = cimg::min(nR,nG,nB), 1.17194 + M = cimg::max(nR,nG,nB); 1.17195 + Tfloat H = 0, S = 0; 1.17196 + if (M!=m) { 1.17197 + const Tfloat 1.17198 + f = (nR==m)?(nG-nB):((nG==m)?(nB-nR):(nR-nG)), 1.17199 + i = (Tfloat)((nR==m)?3:((nG==m)?5:1)); 1.17200 + H = (i-f/(M-m)); 1.17201 + if (H>=6) H-=6; 1.17202 + H*=60; 1.17203 + S = (M-m)/M; 1.17204 + } 1.17205 + *(p1++) = (T)H; 1.17206 + *(p2++) = (T)S; 1.17207 + *(p3++) = (T)M; 1.17208 + } 1.17209 + return *this; 1.17210 + } 1.17211 + 1.17212 + CImg<Tfloat> get_RGBtoHSV() const { 1.17213 + return CImg<Tfloat>(*this,false).RGBtoHSV(); 1.17214 + } 1.17215 + 1.17216 + //! Convert color pixels from (H,S,V) to (R,G,B). 1.17217 + CImg<T>& HSVtoRGB() { 1.17218 + if (is_empty()) return *this; 1.17219 + if (dim!=3) 1.17220 + throw CImgInstanceException("CImg<%s>::HSVtoRGB() : Input image dimension is dim=%u, " 1.17221 + "should be a (H,S,V) image", 1.17222 + pixel_type(),dim); 1.17223 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17224 + for (unsigned long N = width*height*depth; N; --N) { 1.17225 + Tfloat 1.17226 + H = (Tfloat)*p1, 1.17227 + S = (Tfloat)*p2, 1.17228 + V = (Tfloat)*p3, 1.17229 + R = 0, G = 0, B = 0; 1.17230 + if (H==0 && S==0) R = G = B = V; 1.17231 + else { 1.17232 + H/=60; 1.17233 + const int i = (int)cimg_std::floor(H); 1.17234 + const Tfloat 1.17235 + f = (i&1)?(H-i):(1-H+i), 1.17236 + m = V*(1-S), 1.17237 + n = V*(1-S*f); 1.17238 + switch (i) { 1.17239 + case 6 : 1.17240 + case 0 : R = V; G = n; B = m; break; 1.17241 + case 1 : R = n; G = V; B = m; break; 1.17242 + case 2 : R = m; G = V; B = n; break; 1.17243 + case 3 : R = m; G = n; B = V; break; 1.17244 + case 4 : R = n; G = m; B = V; break; 1.17245 + case 5 : R = V; G = m; B = n; break; 1.17246 + } 1.17247 + } 1.17248 + R*=255; G*=255; B*=255; 1.17249 + *(p1++) = (T)(R<0?0:(R>255?255:R)); 1.17250 + *(p2++) = (T)(G<0?0:(G>255?255:G)); 1.17251 + *(p3++) = (T)(B<0?0:(B>255?255:B)); 1.17252 + } 1.17253 + return *this; 1.17254 + } 1.17255 + 1.17256 + CImg<Tuchar> get_HSVtoRGB() const { 1.17257 + return CImg<Tuchar>(*this,false).HSVtoRGB(); 1.17258 + } 1.17259 + 1.17260 + //! Convert color pixels from (R,G,B) to (H,S,L). 1.17261 + CImg<T>& RGBtoHSL() { 1.17262 + if (is_empty()) return *this; 1.17263 + if (dim!=3) 1.17264 + throw CImgInstanceException("CImg<%s>::RGBtoHSL() : Input image dimension is dim=%u, " 1.17265 + "should be a (R,G,B) image.", 1.17266 + pixel_type(),dim); 1.17267 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17268 + for (unsigned long N = width*height*depth; N; --N) { 1.17269 + const Tfloat 1.17270 + R = (Tfloat)*p1, 1.17271 + G = (Tfloat)*p2, 1.17272 + B = (Tfloat)*p3, 1.17273 + nR = (R<0?0:(R>255?255:R))/255, 1.17274 + nG = (G<0?0:(G>255?255:G))/255, 1.17275 + nB = (B<0?0:(B>255?255:B))/255, 1.17276 + m = cimg::min(nR,nG,nB), 1.17277 + M = cimg::max(nR,nG,nB), 1.17278 + L = (m+M)/2; 1.17279 + Tfloat H = 0, S = 0; 1.17280 + if (M==m) H = S = 0; 1.17281 + else { 1.17282 + const Tfloat 1.17283 + f = (nR==m)?(nG-nB):((nG==m)?(nB-nR):(nR-nG)), 1.17284 + i = (nR==m)?3.0f:((nG==m)?5.0f:1.0f); 1.17285 + H = (i-f/(M-m)); 1.17286 + if (H>=6) H-=6; 1.17287 + H*=60; 1.17288 + S = (2*L<=1)?((M-m)/(M+m)):((M-m)/(2-M-m)); 1.17289 + } 1.17290 + *(p1++) = (T)H; 1.17291 + *(p2++) = (T)S; 1.17292 + *(p3++) = (T)L; 1.17293 + } 1.17294 + return *this; 1.17295 + } 1.17296 + 1.17297 + CImg<Tfloat> get_RGBtoHSL() const { 1.17298 + return CImg< Tfloat>(*this,false).RGBtoHSL(); 1.17299 + } 1.17300 + 1.17301 + //! Convert color pixels from (H,S,L) to (R,G,B). 1.17302 + CImg<T>& HSLtoRGB() { 1.17303 + if (is_empty()) return *this; 1.17304 + if (dim!=3) 1.17305 + throw CImgInstanceException("CImg<%s>::HSLtoRGB() : Input image dimension is dim=%u, " 1.17306 + "should be a (H,S,V) image", 1.17307 + pixel_type(),dim); 1.17308 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17309 + for (unsigned long N = width*height*depth; N; --N) { 1.17310 + const Tfloat 1.17311 + H = (Tfloat)*p1, 1.17312 + S = (Tfloat)*p2, 1.17313 + L = (Tfloat)*p3, 1.17314 + q = 2*L<1?L*(1+S):(L+S-L*S), 1.17315 + p = 2*L-q, 1.17316 + h = H/360, 1.17317 + tr = h + 1.0f/3, 1.17318 + tg = h, 1.17319 + tb = h - 1.0f/3, 1.17320 + ntr = tr<0?tr+1:(tr>1?tr-1:tr), 1.17321 + ntg = tg<0?tg+1:(tg>1?tg-1:tg), 1.17322 + ntb = tb<0?tb+1:(tb>1?tb-1:tb), 1.17323 + R = 255*(6*ntr<1?p+(q-p)*6*ntr:(2*ntr<1?q:(3*ntr<2?p+(q-p)*6*(2.0f/3-ntr):p))), 1.17324 + G = 255*(6*ntg<1?p+(q-p)*6*ntg:(2*ntg<1?q:(3*ntg<2?p+(q-p)*6*(2.0f/3-ntg):p))), 1.17325 + B = 255*(6*ntb<1?p+(q-p)*6*ntb:(2*ntb<1?q:(3*ntb<2?p+(q-p)*6*(2.0f/3-ntb):p))); 1.17326 + *(p1++) = (T)(R<0?0:(R>255?255:R)); 1.17327 + *(p2++) = (T)(G<0?0:(G>255?255:G)); 1.17328 + *(p3++) = (T)(B<0?0:(B>255?255:B)); 1.17329 + } 1.17330 + return *this; 1.17331 + } 1.17332 + 1.17333 + CImg<Tuchar> get_HSLtoRGB() const { 1.17334 + return CImg<Tuchar>(*this,false).HSLtoRGB(); 1.17335 + } 1.17336 + 1.17337 + //! Convert color pixels from (R,G,B) to (H,S,I). 1.17338 + //! Reference: "Digital Image Processing, 2nd. edition", R. Gonzalez and R. Woods. Prentice Hall, 2002. 1.17339 + CImg<T>& RGBtoHSI() { 1.17340 + if (is_empty()) return *this; 1.17341 + if (dim!=3) 1.17342 + throw CImgInstanceException("CImg<%s>::RGBtoHSI() : Input image dimension is dim=%u, " 1.17343 + "should be a (R,G,B) image.", 1.17344 + pixel_type(),dim); 1.17345 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17346 + for (unsigned long N = width*height*depth; N; --N) { 1.17347 + const Tfloat 1.17348 + R = (Tfloat)*p1, 1.17349 + G = (Tfloat)*p2, 1.17350 + B = (Tfloat)*p3, 1.17351 + nR = (R<0?0:(R>255?255:R))/255, 1.17352 + nG = (G<0?0:(G>255?255:G))/255, 1.17353 + nB = (B<0?0:(B>255?255:B))/255, 1.17354 + m = cimg::min(nR,nG,nB), 1.17355 + theta = (Tfloat)(cimg_std::acos(0.5f*((nR-nG)+(nR-nB))/cimg_std::sqrt(cimg_std::pow(nR-nG,2)+(nR-nB)*(nG-nB)))*180/cimg::valuePI), 1.17356 + sum = nR + nG + nB; 1.17357 + Tfloat H = 0, S = 0, I = 0; 1.17358 + if (theta>0) H = (nB<=nG)?theta:360-theta; 1.17359 + if (sum>0) S = 1 - 3/sum*m; 1.17360 + I = sum/3; 1.17361 + *(p1++) = (T)H; 1.17362 + *(p2++) = (T)S; 1.17363 + *(p3++) = (T)I; 1.17364 + } 1.17365 + return *this; 1.17366 + } 1.17367 + 1.17368 + CImg<Tfloat> get_RGBtoHSI() const { 1.17369 + return CImg<Tfloat>(*this,false).RGBtoHSI(); 1.17370 + } 1.17371 + 1.17372 + //! Convert color pixels from (H,S,I) to (R,G,B). 1.17373 + CImg<T>& HSItoRGB() { 1.17374 + if (is_empty()) return *this; 1.17375 + if (dim!=3) 1.17376 + throw CImgInstanceException("CImg<%s>::HSItoRGB() : Input image dimension is dim=%u, " 1.17377 + "should be a (H,S,I) image", 1.17378 + pixel_type(),dim); 1.17379 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17380 + for (unsigned long N = width*height*depth; N; --N) { 1.17381 + Tfloat 1.17382 + H = (Tfloat)*p1, 1.17383 + S = (Tfloat)*p2, 1.17384 + I = (Tfloat)*p3, 1.17385 + a = I*(1-S), 1.17386 + R = 0, G = 0, B = 0; 1.17387 + if (H<120) { 1.17388 + B = a; 1.17389 + R = (Tfloat)(I*(1+S*cimg_std::cos(H*cimg::valuePI/180)/cimg_std::cos((60-H)*cimg::valuePI/180))); 1.17390 + G = 3*I-(R+B); 1.17391 + } else if (H<240) { 1.17392 + H-=120; 1.17393 + R = a; 1.17394 + G = (Tfloat)(I*(1+S*cimg_std::cos(H*cimg::valuePI/180)/cimg_std::cos((60-H)*cimg::valuePI/180))); 1.17395 + B = 3*I-(R+G); 1.17396 + } else { 1.17397 + H-=240; 1.17398 + G = a; 1.17399 + B = (Tfloat)(I*(1+S*cimg_std::cos(H*cimg::valuePI/180)/cimg_std::cos((60-H)*cimg::valuePI/180))); 1.17400 + R = 3*I-(G+B); 1.17401 + } 1.17402 + R*=255; G*=255; B*=255; 1.17403 + *(p1++) = (T)(R<0?0:(R>255?255:R)); 1.17404 + *(p2++) = (T)(G<0?0:(G>255?255:G)); 1.17405 + *(p3++) = (T)(B<0?0:(B>255?255:B)); 1.17406 + } 1.17407 + return *this; 1.17408 + } 1.17409 + 1.17410 + CImg<Tfloat> get_HSItoRGB() const { 1.17411 + return CImg< Tuchar>(*this,false).HSItoRGB(); 1.17412 + } 1.17413 + 1.17414 + //! Convert color pixels from (R,G,B) to (Y,Cb,Cr)_8. 1.17415 + CImg<T>& RGBtoYCbCr() { 1.17416 + if (is_empty()) return *this; 1.17417 + if (dim!=3) 1.17418 + throw CImgInstanceException("CImg<%s>::RGBtoYCbCr() : Input image dimension is dim=%u, " 1.17419 + "should be a (R,G,B) image (dim=3)", 1.17420 + pixel_type(),dim); 1.17421 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17422 + for (unsigned long N = width*height*depth; N; --N) { 1.17423 + const Tfloat 1.17424 + R = (Tfloat)*p1, 1.17425 + G = (Tfloat)*p2, 1.17426 + B = (Tfloat)*p3, 1.17427 + Y = (66*R + 129*G + 25*B + 128)/256 + 16, 1.17428 + Cb = (-38*R - 74*G + 112*B + 128)/256 + 128, 1.17429 + Cr = (112*R - 94*G - 18*B + 128)/256 + 128; 1.17430 + *(p1++) = (T)(Y<0?0:(Y>255?255:Y)); 1.17431 + *(p2++) = (T)(Cb<0?0:(Cb>255?255:Cb)); 1.17432 + *(p3++) = (T)(Cr<0?0:(Cr>255?255:Cr)); 1.17433 + } 1.17434 + return *this; 1.17435 + } 1.17436 + 1.17437 + CImg<Tuchar> get_RGBtoYCbCr() const { 1.17438 + return CImg<Tuchar>(*this,false).RGBtoYCbCr(); 1.17439 + } 1.17440 + 1.17441 + //! Convert color pixels from (R,G,B) to (Y,Cb,Cr)_8. 1.17442 + CImg<T>& YCbCrtoRGB() { 1.17443 + if (is_empty()) return *this; 1.17444 + if (dim!=3) 1.17445 + throw CImgInstanceException("CImg<%s>::YCbCrtoRGB() : Input image dimension is dim=%u, " 1.17446 + "should be a (Y,Cb,Cr)_8 image (dim=3)", 1.17447 + pixel_type(),dim); 1.17448 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17449 + for (unsigned long N = width*height*depth; N; --N) { 1.17450 + const Tfloat 1.17451 + Y = (Tfloat)*p1 - 16, 1.17452 + Cb = (Tfloat)*p2 - 128, 1.17453 + Cr = (Tfloat)*p3 - 128, 1.17454 + R = (298*Y + 409*Cr + 128)/256, 1.17455 + G = (298*Y - 100*Cb - 208*Cr + 128)/256, 1.17456 + B = (298*Y + 516*Cb + 128)/256; 1.17457 + *(p1++) = (T)(R<0?0:(R>255?255:R)); 1.17458 + *(p2++) = (T)(G<0?0:(G>255?255:G)); 1.17459 + *(p3++) = (T)(B<0?0:(B>255?255:B)); 1.17460 + } 1.17461 + return *this; 1.17462 + } 1.17463 + 1.17464 + CImg<Tuchar> get_YCbCrtoRGB() const { 1.17465 + return CImg<Tuchar>(*this,false).YCbCrtoRGB(); 1.17466 + } 1.17467 + 1.17468 + //! Convert color pixels from (R,G,B) to (Y,U,V). 1.17469 + CImg<T>& RGBtoYUV() { 1.17470 + if (is_empty()) return *this; 1.17471 + if (dim!=3) 1.17472 + throw CImgInstanceException("CImg<%s>::RGBtoYUV() : Input image dimension is dim=%u, " 1.17473 + "should be a (R,G,B) image (dim=3)", 1.17474 + pixel_type(),dim); 1.17475 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17476 + for (unsigned long N = width*height*depth; N; --N) { 1.17477 + const Tfloat 1.17478 + R = (Tfloat)*p1/255, 1.17479 + G = (Tfloat)*p2/255, 1.17480 + B = (Tfloat)*p3/255, 1.17481 + Y = 0.299f*R + 0.587f*G + 0.114f*B; 1.17482 + *(p1++) = (T)Y; 1.17483 + *(p2++) = (T)(0.492f*(B-Y)); 1.17484 + *(p3++) = (T)(0.877*(R-Y)); 1.17485 + } 1.17486 + return *this; 1.17487 + } 1.17488 + 1.17489 + CImg<Tfloat> get_RGBtoYUV() const { 1.17490 + return CImg<Tfloat>(*this,false).RGBtoYUV(); 1.17491 + } 1.17492 + 1.17493 + //! Convert color pixels from (Y,U,V) to (R,G,B). 1.17494 + CImg<T>& YUVtoRGB() { 1.17495 + if (is_empty()) return *this; 1.17496 + if (dim!=3) 1.17497 + throw CImgInstanceException("CImg<%s>::YUVtoRGB() : Input image dimension is dim=%u, " 1.17498 + "should be a (Y,U,V) image (dim=3)", 1.17499 + pixel_type(),dim); 1.17500 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17501 + for (unsigned long N = width*height*depth; N; --N) { 1.17502 + const Tfloat 1.17503 + Y = (Tfloat)*p1, 1.17504 + U = (Tfloat)*p2, 1.17505 + V = (Tfloat)*p3, 1.17506 + R = (Y + 1.140f*V)*255, 1.17507 + G = (Y - 0.395f*U - 0.581f*V)*255, 1.17508 + B = (Y + 2.032f*U)*255; 1.17509 + *(p1++) = (T)(R<0?0:(R>255?255:R)); 1.17510 + *(p2++) = (T)(G<0?0:(G>255?255:G)); 1.17511 + *(p3++) = (T)(B<0?0:(B>255?255:B)); 1.17512 + } 1.17513 + return *this; 1.17514 + } 1.17515 + 1.17516 + CImg<Tuchar> get_YUVtoRGB() const { 1.17517 + return CImg< Tuchar>(*this,false).YUVtoRGB(); 1.17518 + } 1.17519 + 1.17520 + //! Convert color pixels from (R,G,B) to (C,M,Y). 1.17521 + CImg<T>& RGBtoCMY() { 1.17522 + if (is_empty()) return *this; 1.17523 + if (dim!=3) 1.17524 + throw CImgInstanceException("CImg<%s>::RGBtoCMY() : Input image dimension is dim=%u, " 1.17525 + "should be a (R,G,B) image (dim=3)", 1.17526 + pixel_type(),dim); 1.17527 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17528 + for (unsigned long N = width*height*depth; N; --N) { 1.17529 + const Tfloat 1.17530 + R = (Tfloat)*p1/255, 1.17531 + G = (Tfloat)*p2/255, 1.17532 + B = (Tfloat)*p3/255; 1.17533 + *(p1++) = (T)(1 - R); 1.17534 + *(p2++) = (T)(1 - G); 1.17535 + *(p3++) = (T)(1 - B); 1.17536 + } 1.17537 + return *this; 1.17538 + } 1.17539 + 1.17540 + CImg<Tfloat> get_RGBtoCMY() const { 1.17541 + return CImg<Tfloat>(*this,false).RGBtoCMY(); 1.17542 + } 1.17543 + 1.17544 + //! Convert (C,M,Y) pixels of a color image into the (R,G,B) color space. 1.17545 + CImg<T>& CMYtoRGB() { 1.17546 + if (is_empty()) return *this; 1.17547 + if (dim!=3) 1.17548 + throw CImgInstanceException("CImg<%s>::CMYtoRGB() : Input image dimension is dim=%u, " 1.17549 + "should be a (C,M,Y) image (dim=3)", 1.17550 + pixel_type(),dim); 1.17551 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17552 + for (unsigned long N = width*height*depth; N; --N) { 1.17553 + const Tfloat 1.17554 + C = (Tfloat)*p1, 1.17555 + M = (Tfloat)*p2, 1.17556 + Y = (Tfloat)*p3, 1.17557 + R = 255*(1 - C), 1.17558 + G = 255*(1 - M), 1.17559 + B = 255*(1 - Y); 1.17560 + *(p1++) = (T)(R<0?0:(R>255?255:R)); 1.17561 + *(p2++) = (T)(G<0?0:(G>255?255:G)); 1.17562 + *(p3++) = (T)(B<0?0:(B>255?255:B)); 1.17563 + } 1.17564 + return *this; 1.17565 + } 1.17566 + 1.17567 + CImg<Tuchar> get_CMYtoRGB() const { 1.17568 + return CImg<Tuchar>(*this,false).CMYtoRGB(); 1.17569 + } 1.17570 + 1.17571 + //! Convert color pixels from (C,M,Y) to (C,M,Y,K). 1.17572 + CImg<T>& CMYtoCMYK() { 1.17573 + return get_CMYtoCMYK().transfer_to(*this); 1.17574 + } 1.17575 + 1.17576 + CImg<Tfloat> get_CMYtoCMYK() const { 1.17577 + if (is_empty()) return *this; 1.17578 + if (dim!=3) 1.17579 + throw CImgInstanceException("CImg<%s>::CMYtoCMYK() : Input image dimension is dim=%u, " 1.17580 + "should be a (C,M,Y) image (dim=3)", 1.17581 + pixel_type(),dim); 1.17582 + CImg<Tfloat> res(width,height,depth,4); 1.17583 + const T *ps1 = ptr(0,0,0,0), *ps2 = ptr(0,0,0,1), *ps3 = ptr(0,0,0,2); 1.17584 + Tfloat *pd1 = res.ptr(0,0,0,0), *pd2 = res.ptr(0,0,0,1), *pd3 = res.ptr(0,0,0,2), *pd4 = res.ptr(0,0,0,3); 1.17585 + for (unsigned long N = width*height*depth; N; --N) { 1.17586 + Tfloat 1.17587 + C = (Tfloat)*(ps1++), 1.17588 + M = (Tfloat)*(ps2++), 1.17589 + Y = (Tfloat)*(ps3++), 1.17590 + K = cimg::min(C,M,Y); 1.17591 + if (K==1) C = M = Y = 0; 1.17592 + else { const Tfloat K1 = 1 - K; C = (C - K)/K1; M = (M - K)/K1; Y = (Y - K)/K1; } 1.17593 + *(pd1++) = C; 1.17594 + *(pd2++) = M; 1.17595 + *(pd3++) = Y; 1.17596 + *(pd4++) = K; 1.17597 + } 1.17598 + return res; 1.17599 + } 1.17600 + 1.17601 + //! Convert (C,M,Y,K) pixels of a color image into the (C,M,Y) color space. 1.17602 + CImg<T>& CMYKtoCMY() { 1.17603 + return get_CMYKtoCMY().transfer_to(*this); 1.17604 + } 1.17605 + 1.17606 + CImg<Tfloat> get_CMYKtoCMY() const { 1.17607 + if (is_empty()) return *this; 1.17608 + if (dim!=4) 1.17609 + throw CImgInstanceException("CImg<%s>::CMYKtoCMY() : Input image dimension is dim=%u, " 1.17610 + "should be a (C,M,Y,K) image (dim=4)", 1.17611 + pixel_type(),dim); 1.17612 + CImg<Tfloat> res(width,height,depth,3); 1.17613 + const T *ps1 = ptr(0,0,0,0), *ps2 = ptr(0,0,0,1), *ps3 = ptr(0,0,0,2), *ps4 = ptr(0,0,0,3); 1.17614 + Tfloat *pd1 = res.ptr(0,0,0,0), *pd2 = res.ptr(0,0,0,1), *pd3 = res.ptr(0,0,0,2); 1.17615 + for (unsigned long N = width*height*depth; N; --N) { 1.17616 + const Tfloat 1.17617 + C = (Tfloat)*ps1, 1.17618 + M = (Tfloat)*ps2, 1.17619 + Y = (Tfloat)*ps3, 1.17620 + K = (Tfloat)*ps4, 1.17621 + K1 = 1 - K; 1.17622 + *(pd1++) = C*K1 + K; 1.17623 + *(pd2++) = M*K1 + K; 1.17624 + *(pd3++) = Y*K1 + K; 1.17625 + } 1.17626 + return res; 1.17627 + } 1.17628 + 1.17629 + //! Convert color pixels from (R,G,B) to (X,Y,Z)_709. 1.17630 + CImg<T>& RGBtoXYZ() { 1.17631 + if (is_empty()) return *this; 1.17632 + if (dim!=3) 1.17633 + throw CImgInstanceException("CImg<%s>::RGBtoXYZ() : Input image dimension is dim=%u, " 1.17634 + "should be a (R,G,B) image (dim=3)", 1.17635 + pixel_type(),dim); 1.17636 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17637 + for (unsigned long N = width*height*depth; N; --N) { 1.17638 + const Tfloat 1.17639 + R = (Tfloat)*p1/255, 1.17640 + G = (Tfloat)*p2/255, 1.17641 + B = (Tfloat)*p3/255; 1.17642 + *(p1++) = (T)(0.412453f*R + 0.357580f*G + 0.180423f*B); 1.17643 + *(p2++) = (T)(0.212671f*R + 0.715160f*G + 0.072169f*B); 1.17644 + *(p3++) = (T)(0.019334f*R + 0.119193f*G + 0.950227f*B); 1.17645 + } 1.17646 + return *this; 1.17647 + } 1.17648 + 1.17649 + CImg<Tfloat> get_RGBtoXYZ() const { 1.17650 + return CImg<Tfloat>(*this,false).RGBtoXYZ(); 1.17651 + } 1.17652 + 1.17653 + //! Convert (X,Y,Z)_709 pixels of a color image into the (R,G,B) color space. 1.17654 + CImg<T>& XYZtoRGB() { 1.17655 + if (is_empty()) return *this; 1.17656 + if (dim!=3) 1.17657 + throw CImgInstanceException("CImg<%s>::XYZtoRGB() : Input image dimension is dim=%u, " 1.17658 + "should be a (X,Y,Z) image (dim=3)", 1.17659 + pixel_type(),dim); 1.17660 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17661 + for (unsigned long N = width*height*depth; N; --N) { 1.17662 + const Tfloat 1.17663 + X = (Tfloat)*p1*255, 1.17664 + Y = (Tfloat)*p2*255, 1.17665 + Z = (Tfloat)*p3*255, 1.17666 + R = 3.240479f*X - 1.537150f*Y - 0.498535f*Z, 1.17667 + G = -0.969256f*X + 1.875992f*Y + 0.041556f*Z, 1.17668 + B = 0.055648f*X - 0.204043f*Y + 1.057311f*Z; 1.17669 + *(p1++) = (T)(R<0?0:(R>255?255:R)); 1.17670 + *(p2++) = (T)(G<0?0:(G>255?255:G)); 1.17671 + *(p3++) = (T)(B<0?0:(B>255?255:B)); 1.17672 + } 1.17673 + return *this; 1.17674 + } 1.17675 + 1.17676 + CImg<Tuchar> get_XYZtoRGB() const { 1.17677 + return CImg<Tuchar>(*this,false).XYZtoRGB(); 1.17678 + } 1.17679 + 1.17680 + //! Convert (X,Y,Z)_709 pixels of a color image into the (L*,a*,b*) color space. 1.17681 + CImg<T>& XYZtoLab() { 1.17682 +#define _cimg_Labf(x) ((x)>=0.008856f?(cimg_std::pow(x,(Tfloat)1/3)):(7.787f*(x)+16.0f/116)) 1.17683 + if (is_empty()) return *this; 1.17684 + if (dim!=3) 1.17685 + throw CImgInstanceException("CImg<%s>::XYZtoLab() : Input image dimension is dim=%u, " 1.17686 + "should be a (X,Y,Z) image (dim=3)", 1.17687 + pixel_type(),dim); 1.17688 + const Tfloat 1.17689 + Xn = (Tfloat)(0.412453f + 0.357580f + 0.180423f), 1.17690 + Yn = (Tfloat)(0.212671f + 0.715160f + 0.072169f), 1.17691 + Zn = (Tfloat)(0.019334f + 0.119193f + 0.950227f); 1.17692 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17693 + for (unsigned long N = width*height*depth; N; --N) { 1.17694 + const Tfloat 1.17695 + X = (Tfloat)*p1, 1.17696 + Y = (Tfloat)*p2, 1.17697 + Z = (Tfloat)*p3, 1.17698 + XXn = X/Xn, YYn = Y/Yn, ZZn = Z/Zn, 1.17699 + fX = (Tfloat)_cimg_Labf(XXn), 1.17700 + fY = (Tfloat)_cimg_Labf(YYn), 1.17701 + fZ = (Tfloat)_cimg_Labf(ZZn); 1.17702 + *(p1++) = (T)(116*fY - 16); 1.17703 + *(p2++) = (T)(500*(fX - fY)); 1.17704 + *(p3++) = (T)(200*(fY - fZ)); 1.17705 + } 1.17706 + return *this; 1.17707 + } 1.17708 + 1.17709 + CImg<Tfloat> get_XYZtoLab() const { 1.17710 + return CImg<Tfloat>(*this,false).XYZtoLab(); 1.17711 + } 1.17712 + 1.17713 + //! Convert (L,a,b) pixels of a color image into the (X,Y,Z) color space. 1.17714 + CImg<T>& LabtoXYZ() { 1.17715 +#define _cimg_Labfi(x) ((x)>=0.206893f?((x)*(x)*(x)):(((x)-16.0f/116)/7.787f)) 1.17716 + if (is_empty()) return *this; 1.17717 + if (dim!=3) 1.17718 + throw CImgInstanceException("CImg<%s>::LabtoXYZ() : Input image dimension is dim=%u, " 1.17719 + "should be a (X,Y,Z) image (dim=3)", 1.17720 + pixel_type(),dim); 1.17721 + const Tfloat 1.17722 + Xn = (Tfloat)(0.412453f + 0.357580f + 0.180423f), 1.17723 + Yn = (Tfloat)(0.212671f + 0.715160f + 0.072169f), 1.17724 + Zn = (Tfloat)(0.019334f + 0.119193f + 0.950227f); 1.17725 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17726 + for (unsigned long N = width*height*depth; N; --N) { 1.17727 + const Tfloat 1.17728 + L = (Tfloat)*p1, 1.17729 + a = (Tfloat)*p2, 1.17730 + b = (Tfloat)*p3, 1.17731 + cY = (L + 16)/116, 1.17732 + Y = (Tfloat)(Yn*_cimg_Labfi(cY)), 1.17733 + pY = (Tfloat)cimg_std::pow(Y/Yn,(Tfloat)1/3), 1.17734 + cX = a/500 + pY, 1.17735 + X = Xn*cX*cX*cX, 1.17736 + cZ = pY - b/200, 1.17737 + Z = Zn*cZ*cZ*cZ; 1.17738 + *(p1++) = (T)(X); 1.17739 + *(p2++) = (T)(Y); 1.17740 + *(p3++) = (T)(Z); 1.17741 + } 1.17742 + return *this; 1.17743 + } 1.17744 + 1.17745 + CImg<Tfloat> get_LabtoXYZ() const { 1.17746 + return CImg<Tfloat>(*this,false).LabtoXYZ(); 1.17747 + } 1.17748 + 1.17749 + //! Convert (X,Y,Z)_709 pixels of a color image into the (x,y,Y) color space. 1.17750 + CImg<T>& XYZtoxyY() { 1.17751 + if (is_empty()) return *this; 1.17752 + if (dim!=3) 1.17753 + throw CImgInstanceException("CImg<%s>::XYZtoxyY() : Input image dimension is dim=%u, " 1.17754 + "should be a (X,Y,Z) image (dim=3)", 1.17755 + pixel_type(),dim); 1.17756 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17757 + for (unsigned long N = width*height*depth; N; --N) { 1.17758 + const Tfloat 1.17759 + X = (Tfloat)*p1, 1.17760 + Y = (Tfloat)*p2, 1.17761 + Z = (Tfloat)*p3, 1.17762 + sum = (X+Y+Z), 1.17763 + nsum = sum>0?sum:1; 1.17764 + *(p1++) = (T)(X/nsum); 1.17765 + *(p2++) = (T)(Y/nsum); 1.17766 + *(p3++) = (T)Y; 1.17767 + } 1.17768 + return *this; 1.17769 + } 1.17770 + 1.17771 + CImg<Tfloat> get_XYZtoxyY() const { 1.17772 + return CImg<Tfloat>(*this,false).XYZtoxyY(); 1.17773 + } 1.17774 + 1.17775 + //! Convert (x,y,Y) pixels of a color image into the (X,Y,Z)_709 color space. 1.17776 + CImg<T>& xyYtoXYZ() { 1.17777 + if (is_empty()) return *this; 1.17778 + if (dim!=3) 1.17779 + throw CImgInstanceException("CImg<%s>::xyYtoXYZ() : Input image dimension is dim=%u, " 1.17780 + "should be a (x,y,Y) image (dim=3)", 1.17781 + pixel_type(),dim); 1.17782 + T *p1 = ptr(0,0,0,0), *p2 = ptr(0,0,0,1), *p3 = ptr(0,0,0,2); 1.17783 + for (unsigned long N = width*height*depth; N; --N) { 1.17784 + const Tfloat 1.17785 + px = (Tfloat)*p1, 1.17786 + py = (Tfloat)*p2, 1.17787 + Y = (Tfloat)*p3, 1.17788 + ny = py>0?py:1; 1.17789 + *(p1++) = (T)(px*Y/ny); 1.17790 + *(p2++) = (T)Y; 1.17791 + *(p3++) = (T)((1-px-py)*Y/ny); 1.17792 + } 1.17793 + return *this; 1.17794 + } 1.17795 + 1.17796 + CImg<Tfloat> get_xyYtoXYZ() const { 1.17797 + return CImg<Tfloat>(*this,false).xyYtoXYZ(); 1.17798 + } 1.17799 + 1.17800 + //! Convert a (R,G,B) image to a (L,a,b) one. 1.17801 + CImg<T>& RGBtoLab() { 1.17802 + return RGBtoXYZ().XYZtoLab(); 1.17803 + } 1.17804 + 1.17805 + CImg<Tfloat> get_RGBtoLab() const { 1.17806 + return CImg<Tfloat>(*this,false).RGBtoLab(); 1.17807 + } 1.17808 + 1.17809 + //! Convert a (L,a,b) image to a (R,G,B) one. 1.17810 + CImg<T>& LabtoRGB() { 1.17811 + return LabtoXYZ().XYZtoRGB(); 1.17812 + } 1.17813 + 1.17814 + CImg<Tuchar> get_LabtoRGB() const { 1.17815 + return CImg<Tuchar>(*this,false).LabtoRGB(); 1.17816 + } 1.17817 + 1.17818 + //! Convert a (R,G,B) image to a (x,y,Y) one. 1.17819 + CImg<T>& RGBtoxyY() { 1.17820 + return RGBtoXYZ().XYZtoxyY(); 1.17821 + } 1.17822 + 1.17823 + CImg<Tfloat> get_RGBtoxyY() const { 1.17824 + return CImg<Tfloat>(*this,false).RGBtoxyY(); 1.17825 + } 1.17826 + 1.17827 + //! Convert a (x,y,Y) image to a (R,G,B) one. 1.17828 + CImg<T>& xyYtoRGB() { 1.17829 + return xyYtoXYZ().XYZtoRGB(); 1.17830 + } 1.17831 + 1.17832 + CImg<Tuchar> get_xyYtoRGB() const { 1.17833 + return CImg<Tuchar>(*this,false).xyYtoRGB(); 1.17834 + } 1.17835 + 1.17836 + //! Convert a (R,G,B) image to a (C,M,Y,K) one. 1.17837 + CImg<T>& RGBtoCMYK() { 1.17838 + return RGBtoCMY().CMYtoCMYK(); 1.17839 + } 1.17840 + 1.17841 + CImg<Tfloat> get_RGBtoCMYK() const { 1.17842 + return CImg<Tfloat>(*this,false).RGBtoCMYK(); 1.17843 + } 1.17844 + 1.17845 + //! Convert a (C,M,Y,K) image to a (R,G,B) one. 1.17846 + CImg<T>& CMYKtoRGB() { 1.17847 + return CMYKtoCMY().CMYtoRGB(); 1.17848 + } 1.17849 + 1.17850 + CImg<Tuchar> get_CMYKtoRGB() const { 1.17851 + return CImg<Tuchar>(*this,false).CMYKtoRGB(); 1.17852 + } 1.17853 + 1.17854 + //! Convert a (R,G,B) image to a Bayer-coded representation. 1.17855 + /** 1.17856 + \note First (upper-left) pixel if the red component of the pixel color. 1.17857 + **/ 1.17858 + CImg<T>& RGBtoBayer() { 1.17859 + return get_RGBtoBayer().transfer_to(*this); 1.17860 + } 1.17861 + 1.17862 + CImg<T> get_RGBtoBayer() const { 1.17863 + if (is_empty()) return *this; 1.17864 + if (dim!=3) 1.17865 + throw CImgInstanceException("CImg<%s>::RGBtoBayer() : Input image dimension is dim=%u, " 1.17866 + "should be a (R,G,B) image (dim=3)", 1.17867 + pixel_type(),dim); 1.17868 + CImg<T> res(width,height,depth,1); 1.17869 + const T *pR = ptr(0,0,0,0), *pG = ptr(0,0,0,1), *pB = ptr(0,0,0,2); 1.17870 + T *ptrd = res.data; 1.17871 + cimg_forXYZ(*this,x,y,z) { 1.17872 + if (y%2) { 1.17873 + if (x%2) *(ptrd++) = *pB; 1.17874 + else *(ptrd++) = *pG; 1.17875 + } else { 1.17876 + if (x%2) *(ptrd++) = *pG; 1.17877 + else *(ptrd++) = *pR; 1.17878 + } 1.17879 + ++pR; ++pG; ++pB; 1.17880 + } 1.17881 + return res; 1.17882 + } 1.17883 + 1.17884 + //! Convert a Bayer-coded image to a (R,G,B) color image. 1.17885 + CImg<T>& BayertoRGB(const unsigned int interpolation_type=3) { 1.17886 + return get_BayertoRGB(interpolation_type).transfer_to(*this); 1.17887 + } 1.17888 + 1.17889 + CImg<Tuchar> get_BayertoRGB(const unsigned int interpolation_type=3) const { 1.17890 + if (is_empty()) return *this; 1.17891 + if (dim!=1) 1.17892 + throw CImgInstanceException("CImg<%s>::BayertoRGB() : Input image dimension is dim=%u, " 1.17893 + "should be a Bayer image (dim=1)", 1.17894 + pixel_type(),dim); 1.17895 + CImg<Tuchar> res(width,height,depth,3); 1.17896 + CImg_3x3(I,T); 1.17897 + Tuchar *pR = res.ptr(0,0,0,0), *pG = res.ptr(0,0,0,1), *pB = res.ptr(0,0,0,2); 1.17898 + switch (interpolation_type) { 1.17899 + case 3 : { // Edge-directed 1.17900 + CImg_3x3(R,T); 1.17901 + CImg_3x3(G,T); 1.17902 + CImg_3x3(B,T); 1.17903 + cimg_forXYZ(*this,x,y,z) { 1.17904 + const int _p1x = x?x-1:1, _p1y = y?y-1:1, _n1x = x<dimx()-1?x+1:x-1, _n1y = y<dimy()-1?y+1:y-1; 1.17905 + cimg_get3x3(*this,x,y,z,0,I); 1.17906 + if (y%2) { 1.17907 + if (x%2) { 1.17908 + const Tfloat alpha = cimg::sqr((Tfloat)Inc - Ipc), beta = cimg::sqr((Tfloat)Icn - Icp), cx = 1/(1+alpha), cy = 1/(1+beta); 1.17909 + *pG = (Tuchar)((cx*(Inc+Ipc) + cy*(Icn+Icp))/(2*(cx+cy))); 1.17910 + } else *pG = (Tuchar)Icc; 1.17911 + } else { 1.17912 + if (x%2) *pG = (Tuchar)Icc; 1.17913 + else { 1.17914 + const Tfloat alpha = cimg::sqr((Tfloat)Inc - Ipc), beta = cimg::sqr((Tfloat)Icn - Icp), cx = 1/(1+alpha), cy = 1/(1+beta); 1.17915 + *pG = (Tuchar)((cx*(Inc+Ipc) + cy*(Icn+Icp))/(2*(cx+cy))); 1.17916 + } 1.17917 + } 1.17918 + ++pG; 1.17919 + } 1.17920 + cimg_forXYZ(*this,x,y,z) { 1.17921 + const int _p1x = x?x-1:1, _p1y = y?y-1:1, _n1x = x<dimx()-1?x+1:x-1, _n1y = y<dimy()-1?y+1:y-1; 1.17922 + cimg_get3x3(*this,x,y,z,0,I); 1.17923 + cimg_get3x3(res,x,y,z,1,G); 1.17924 + if (y%2) { 1.17925 + if (x%2) *pB = (Tuchar)Icc; 1.17926 + else { *pR = (Tuchar)((Icn+Icp)/2); *pB = (Tuchar)((Inc+Ipc)/2); } 1.17927 + } else { 1.17928 + if (x%2) { *pR = (Tuchar)((Inc+Ipc)/2); *pB = (Tuchar)((Icn+Icp)/2); } 1.17929 + else *pR = (Tuchar)Icc; 1.17930 + } 1.17931 + ++pR; ++pB; 1.17932 + } 1.17933 + pR = res.ptr(0,0,0,0); 1.17934 + pG = res.ptr(0,0,0,1); 1.17935 + pB = res.ptr(0,0,0,2); 1.17936 + cimg_forXYZ(*this,x,y,z) { 1.17937 + const int _p1x = x?x-1:1, _p1y = y?y-1:1, _n1x = x<dimx()-1?x+1:x-1, _n1y = y<dimy()-1?y+1:y-1; 1.17938 + cimg_get3x3(res,x,y,z,0,R); 1.17939 + cimg_get3x3(res,x,y,z,1,G); 1.17940 + cimg_get3x3(res,x,y,z,2,B); 1.17941 + if (y%2) { 1.17942 + if (x%2) { 1.17943 + const float alpha = (float)cimg::sqr(Rnc-Rpc), beta = (float)cimg::sqr(Rcn-Rcp), cx = 1/(1+alpha), cy = 1/(1+beta); 1.17944 + *pR = (Tuchar)((cx*(Rnc+Rpc) + cy*(Rcn+Rcp))/(2*(cx+cy))); 1.17945 + } 1.17946 + } else { 1.17947 + if (!(x%2)) { 1.17948 + const float alpha = (float)cimg::sqr(Bnc-Bpc), beta = (float)cimg::sqr(Bcn-Bcp), cx = 1/(1+alpha), cy = 1/(1+beta); 1.17949 + *pB = (Tuchar)((cx*(Bnc+Bpc) + cy*(Bcn+Bcp))/(2*(cx+cy))); 1.17950 + } 1.17951 + } 1.17952 + ++pR; ++pG; ++pB; 1.17953 + } 1.17954 + } break; 1.17955 + case 2 : { // Linear interpolation 1.17956 + cimg_forXYZ(*this,x,y,z) { 1.17957 + const int _p1x = x?x-1:1, _p1y = y?y-1:1, _n1x = x<dimx()-1?x+1:x-1, _n1y = y<dimy()-1?y+1:y-1; 1.17958 + cimg_get3x3(*this,x,y,z,0,I); 1.17959 + if (y%2) { 1.17960 + if (x%2) { *pR = (Tuchar)((Ipp+Inn+Ipn+Inp)/4); *pG = (Tuchar)((Inc+Ipc+Icn+Icp)/4); *pB = (Tuchar)Icc; } 1.17961 + else { *pR = (Tuchar)((Icp+Icn)/2); *pG = (Tuchar)Icc; *pB = (Tuchar)((Inc+Ipc)/2); } 1.17962 + } else { 1.17963 + if (x%2) { *pR = (Tuchar)((Ipc+Inc)/2); *pG = (Tuchar)Icc; *pB = (Tuchar)((Icn+Icp)/2); } 1.17964 + else { *pR = (Tuchar)Icc; *pG = (Tuchar)((Inc+Ipc+Icn+Icp)/4); *pB = (Tuchar)((Ipp+Inn+Ipn+Inp)/4); } 1.17965 + } 1.17966 + ++pR; ++pG; ++pB; 1.17967 + } 1.17968 + } break; 1.17969 + case 1 : { // Nearest neighbor interpolation 1.17970 + cimg_forXYZ(*this,x,y,z) { 1.17971 + const int _p1x = x?x-1:1, _p1y = y?y-1:1, _n1x = x<dimx()-1?x+1:x-1, _n1y = y<dimy()-1?y+1:y-1; 1.17972 + cimg_get3x3(*this,x,y,z,0,I); 1.17973 + if (y%2) { 1.17974 + if (x%2) { *pR = (Tuchar)cimg::min(Ipp,Inn,Ipn,Inp); *pG = (Tuchar)cimg::min(Inc,Ipc,Icn,Icp); *pB = (Tuchar)Icc; } 1.17975 + else { *pR = (Tuchar)cimg::min(Icn,Icp); *pG = (Tuchar)Icc; *pB = (Tuchar)cimg::min(Inc,Ipc); } 1.17976 + } else { 1.17977 + if (x%2) { *pR = (Tuchar)cimg::min(Inc,Ipc); *pG = (Tuchar)Icc; *pB = (Tuchar)cimg::min(Icn,Icp); } 1.17978 + else { *pR = (Tuchar)Icc; *pG = (Tuchar)cimg::min(Inc,Ipc,Icn,Icp); *pB = (Tuchar)cimg::min(Ipp,Inn,Ipn,Inp); } 1.17979 + } 1.17980 + ++pR; ++pG; ++pB; 1.17981 + } 1.17982 + } break; 1.17983 + default : { // 0-filling interpolation 1.17984 + const T *ptrs = data; 1.17985 + res.fill(0); 1.17986 + cimg_forXYZ(*this,x,y,z) { 1.17987 + const T val = *(ptrs++); 1.17988 + if (y%2) { if (x%2) *pB = val; else *pG = val; } else { if (x%2) *pG = val; else *pR = val; } 1.17989 + ++pR; ++pG; ++pB; 1.17990 + } 1.17991 + } 1.17992 + } 1.17993 + return res; 1.17994 + } 1.17995 + 1.17996 + //@} 1.17997 + //------------------- 1.17998 + // 1.17999 + //! \name Drawing 1.18000 + //@{ 1.18001 + //------------------- 1.18002 + 1.18003 + // The following _draw_scanline() routines are *non user-friendly functions*, used only for internal purpose. 1.18004 + // Pre-requisites : x0<x1, y-coordinate is valid, col is valid. 1.18005 + template<typename tc> 1.18006 + CImg<T>& _draw_scanline(const int x0, const int x1, const int y, 1.18007 + const tc *const color, const float opacity=1, 1.18008 + const float brightness=1, const bool init=false) { 1.18009 + static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max()); 1.18010 + static float nopacity = 0, copacity = 0; 1.18011 + static unsigned int whz = 0; 1.18012 + static const tc *col = 0; 1.18013 + if (init) { 1.18014 + nopacity = cimg::abs(opacity); 1.18015 + copacity = 1 - cimg::max(opacity,0); 1.18016 + whz = width*height*depth; 1.18017 + } else { 1.18018 + const int nx0 = x0>0?x0:0, nx1 = x1<dimx()?x1:dimx()-1, dx = nx1 - nx0; 1.18019 + if (dx>=0) { 1.18020 + col = color; 1.18021 + const unsigned int off = whz-dx-1; 1.18022 + T *ptrd = ptr(nx0,y); 1.18023 + if (opacity>=1) { // ** Opaque drawing ** 1.18024 + if (brightness==1) { // Brightness==1 1.18025 + if (sizeof(T)!=1) cimg_forV(*this,k) { 1.18026 + const T val = (T)*(col++); 1.18027 + for (int x = dx; x>=0; --x) *(ptrd++) = val; 1.18028 + ptrd+=off; 1.18029 + } else cimg_forV(*this,k) { 1.18030 + const T val = (T)*(col++); 1.18031 + cimg_std::memset(ptrd,(int)val,dx+1); 1.18032 + ptrd+=whz; 1.18033 + } 1.18034 + } else if (brightness<1) { // Brightness<1 1.18035 + if (sizeof(T)!=1) cimg_forV(*this,k) { 1.18036 + const T val = (T)(*(col++)*brightness); 1.18037 + for (int x = dx; x>=0; --x) *(ptrd++) = val; 1.18038 + ptrd+=off; 1.18039 + } else cimg_forV(*this,k) { 1.18040 + const T val = (T)(*(col++)*brightness); 1.18041 + cimg_std::memset(ptrd,(int)val,dx+1); 1.18042 + ptrd+=whz; 1.18043 + } 1.18044 + } else { // Brightness>1 1.18045 + if (sizeof(T)!=1) cimg_forV(*this,k) { 1.18046 + const T val = (T)((2-brightness)**(col++) + (brightness-1)*maxval); 1.18047 + for (int x = dx; x>=0; --x) *(ptrd++) = val; 1.18048 + ptrd+=off; 1.18049 + } else cimg_forV(*this,k) { 1.18050 + const T val = (T)((2-brightness)**(col++) + (brightness-1)*maxval); 1.18051 + cimg_std::memset(ptrd,(int)val,dx+1); 1.18052 + ptrd+=whz; 1.18053 + } 1.18054 + } 1.18055 + } else { // ** Transparent drawing ** 1.18056 + if (brightness==1) { // Brightness==1 1.18057 + cimg_forV(*this,k) { 1.18058 + const T val = (T)*(col++); 1.18059 + for (int x = dx; x>=0; --x) { *ptrd = (T)(val*nopacity + *ptrd*copacity); ++ptrd; } 1.18060 + ptrd+=off; 1.18061 + } 1.18062 + } else if (brightness<=1) { // Brightness<1 1.18063 + cimg_forV(*this,k) { 1.18064 + const T val = (T)(*(col++)*brightness); 1.18065 + for (int x = dx; x>=0; --x) { *ptrd = (T)(val*nopacity + *ptrd*copacity); ++ptrd; } 1.18066 + ptrd+=off; 1.18067 + } 1.18068 + } else { // Brightness>1 1.18069 + cimg_forV(*this,k) { 1.18070 + const T val = (T)((2-brightness)**(col++) + (brightness-1)*maxval); 1.18071 + for (int x = dx; x>=0; --x) { *ptrd = (T)(val*nopacity + *ptrd*copacity); ++ptrd; } 1.18072 + ptrd+=off; 1.18073 + } 1.18074 + } 1.18075 + } 1.18076 + } 1.18077 + } 1.18078 + return *this; 1.18079 + } 1.18080 + 1.18081 + template<typename tc> 1.18082 + CImg<T>& _draw_scanline(const tc *const color, const float opacity=1) { 1.18083 + return _draw_scanline(0,0,0,color,opacity,0,true); 1.18084 + } 1.18085 + 1.18086 + //! Draw a 2D colored point (pixel). 1.18087 + /** 1.18088 + \param x0 X-coordinate of the point. 1.18089 + \param y0 Y-coordinate of the point. 1.18090 + \param color Pointer to \c dimv() consecutive values, defining the color values. 1.18091 + \param opacity Drawing opacity (optional). 1.18092 + \note 1.18093 + - Clipping is supported. 1.18094 + - To set pixel values without clipping needs, you should use the faster CImg::operator()() function. 1.18095 + \par Example: 1.18096 + \code 1.18097 + CImg<unsigned char> img(100,100,1,3,0); 1.18098 + const unsigned char color[] = { 255,128,64 }; 1.18099 + img.draw_point(50,50,color); 1.18100 + \endcode 1.18101 + **/ 1.18102 + template<typename tc> 1.18103 + CImg<T>& draw_point(const int x0, const int y0, 1.18104 + const tc *const color, const float opacity=1) { 1.18105 + return draw_point(x0,y0,0,color,opacity); 1.18106 + } 1.18107 + 1.18108 + //! Draw a 2D colored point (pixel). 1.18109 + template<typename tc> 1.18110 + CImg<T>& draw_point(const int x0, const int y0, 1.18111 + const CImg<tc>& color, const float opacity=1) { 1.18112 + return draw_point(x0,y0,color.data,opacity); 1.18113 + } 1.18114 + 1.18115 + //! Draw a 3D colored point (voxel). 1.18116 + template<typename tc> 1.18117 + CImg<T>& draw_point(const int x0, const int y0, const int z0, 1.18118 + const tc *const color, const float opacity=1) { 1.18119 + if (is_empty()) return *this; 1.18120 + if (!color) 1.18121 + throw CImgArgumentException("CImg<%s>::draw_point() : Specified color is (null)", 1.18122 + pixel_type()); 1.18123 + if (x0>=0 && y0>=0 && z0>=0 && x0<dimx() && y0<dimy() && z0<dimz()) { 1.18124 + const unsigned int whz = width*height*depth; 1.18125 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.18126 + T *ptrd = ptr(x0,y0,z0,0); 1.18127 + const tc *col = color; 1.18128 + if (opacity>=1) cimg_forV(*this,k) { *ptrd = (T)*(col++); ptrd+=whz; } 1.18129 + else cimg_forV(*this,k) { *ptrd = (T)(*(col++)*nopacity + *ptrd*copacity); ptrd+=whz; } 1.18130 + } 1.18131 + return *this; 1.18132 + } 1.18133 + 1.18134 + //! Draw a 3D colored point (voxel). 1.18135 + template<typename tc> 1.18136 + CImg<T>& draw_point(const int x0, const int y0, const int z0, 1.18137 + const CImg<tc>& color, const float opacity=1) { 1.18138 + return draw_point(x0,y0,z0,color.data,opacity); 1.18139 + } 1.18140 + 1.18141 + // Draw a cloud of colored point (internal). 1.18142 + template<typename t, typename tc> 1.18143 + CImg<T>& _draw_point(const t& points, const unsigned int W, const unsigned int H, 1.18144 + const tc *const color, const float opacity) { 1.18145 + if (is_empty() || !points || !W) return *this; 1.18146 + switch (H) { 1.18147 + case 0 : case 1 : 1.18148 + throw CImgArgumentException("CImg<%s>::draw_point() : Given list of points is not valid.", 1.18149 + pixel_type()); 1.18150 + case 2 : { 1.18151 + for (unsigned int i = 0; i<W; ++i) { 1.18152 + const int x = (int)points(i,0), y = (int)points(i,1); 1.18153 + draw_point(x,y,color,opacity); 1.18154 + } 1.18155 + } break; 1.18156 + default : { 1.18157 + for (unsigned int i = 0; i<W; ++i) { 1.18158 + const int x = (int)points(i,0), y = (int)points(i,1), z = (int)points(i,2); 1.18159 + draw_point(x,y,z,color,opacity); 1.18160 + } 1.18161 + } 1.18162 + } 1.18163 + return *this; 1.18164 + } 1.18165 + 1.18166 + //! Draw a cloud of colored points. 1.18167 + /** 1.18168 + \param points Coordinates of vertices, stored as a list of vectors. 1.18169 + \param color Pointer to \c dimv() consecutive values of type \c T, defining the drawing color. 1.18170 + \param opacity Drawing opacity (optional). 1.18171 + \note 1.18172 + - This function uses several call to the single CImg::draw_point() procedure, 1.18173 + depending on the vectors size in \p points. 1.18174 + \par Example: 1.18175 + \code 1.18176 + CImg<unsigned char> img(100,100,1,3,0); 1.18177 + const unsigned char color[] = { 255,128,64 }; 1.18178 + CImgList<int> points; 1.18179 + points.insert(CImg<int>::vector(0,0)). 1.18180 + .insert(CImg<int>::vector(70,10)). 1.18181 + .insert(CImg<int>::vector(80,60)). 1.18182 + .insert(CImg<int>::vector(10,90)); 1.18183 + img.draw_point(points,color); 1.18184 + \endcode 1.18185 + **/ 1.18186 + template<typename t, typename tc> 1.18187 + CImg<T>& draw_point(const CImgList<t>& points, 1.18188 + const tc *const color, const float opacity=1) { 1.18189 + unsigned int H = ~0U; cimglist_for(points,p) H = cimg::min(H,(unsigned int)(points[p].size())); 1.18190 + return _draw_point(points,points.size,H,color,opacity); 1.18191 + } 1.18192 + 1.18193 + //! Draw a cloud of colored points. 1.18194 + template<typename t, typename tc> 1.18195 + CImg<T>& draw_point(const CImgList<t>& points, 1.18196 + const CImg<tc>& color, const float opacity=1) { 1.18197 + return draw_point(points,color.data,opacity); 1.18198 + } 1.18199 + 1.18200 + //! Draw a cloud of colored points. 1.18201 + /** 1.18202 + \note 1.18203 + - Similar to the previous function, where the N vertex coordinates are stored as a Nx2 or Nx3 image 1.18204 + (sequence of vectors aligned along the x-axis). 1.18205 + **/ 1.18206 + template<typename t, typename tc> 1.18207 + CImg<T>& draw_point(const CImg<t>& points, 1.18208 + const tc *const color, const float opacity=1) { 1.18209 + return _draw_point(points,points.width,points.height,color,opacity); 1.18210 + } 1.18211 + 1.18212 + //! Draw a cloud of colored points. 1.18213 + template<typename t, typename tc> 1.18214 + CImg<T>& draw_point(const CImg<t>& points, 1.18215 + const CImg<tc>& color, const float opacity=1) { 1.18216 + return draw_point(points,color.data,opacity); 1.18217 + } 1.18218 + 1.18219 + //! Draw a 2D colored line. 1.18220 + /** 1.18221 + \param x0 X-coordinate of the starting line point. 1.18222 + \param y0 Y-coordinate of the starting line point. 1.18223 + \param x1 X-coordinate of the ending line point. 1.18224 + \param y1 Y-coordinate of the ending line point. 1.18225 + \param color Pointer to \c dimv() consecutive values of type \c T, defining the drawing color. 1.18226 + \param opacity Drawing opacity (optional). 1.18227 + \param pattern An integer whose bits describe the line pattern (optional). 1.18228 + \param init_hatch Flag telling if a reinitialization of the hash state must be done (optional). 1.18229 + \note 1.18230 + - Clipping is supported. 1.18231 + - Line routine uses Bresenham's algorithm. 1.18232 + - Set \p init_hatch = false to draw consecutive hatched segments without breaking the line pattern. 1.18233 + \par Example: 1.18234 + \code 1.18235 + CImg<unsigned char> img(100,100,1,3,0); 1.18236 + const unsigned char color[] = { 255,128,64 }; 1.18237 + img.draw_line(40,40,80,70,color); 1.18238 + \endcode 1.18239 + **/ 1.18240 + template<typename tc> 1.18241 + CImg<T>& draw_line(const int x0, const int y0, 1.18242 + const int x1, const int y1, 1.18243 + const tc *const color, const float opacity=1, 1.18244 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.18245 + if (is_empty()) return *this; 1.18246 + if (!color) 1.18247 + throw CImgArgumentException("CImg<%s>::draw_line() : Specified color is (null)", 1.18248 + pixel_type()); 1.18249 + static unsigned int hatch = ~0U - (~0U>>1); 1.18250 + if (init_hatch) hatch = ~0U - (~0U>>1); 1.18251 + const bool xdir = x0<x1, ydir = y0<y1; 1.18252 + int 1.18253 + nx0 = x0, nx1 = x1, ny0 = y0, ny1 = y1, 1.18254 + &xleft = xdir?nx0:nx1, &yleft = xdir?ny0:ny1, 1.18255 + &xright = xdir?nx1:nx0, &yright = xdir?ny1:ny0, 1.18256 + &xup = ydir?nx0:nx1, &yup = ydir?ny0:ny1, 1.18257 + &xdown = ydir?nx1:nx0, &ydown = ydir?ny1:ny0; 1.18258 + if (xright<0 || xleft>=dimx()) return *this; 1.18259 + if (xleft<0) { yleft-=xleft*(yright - yleft)/(xright - xleft); xleft = 0; } 1.18260 + if (xright>=dimx()) { yright-=(xright - dimx())*(yright - yleft)/(xright - xleft); xright = dimx()-1; } 1.18261 + if (ydown<0 || yup>=dimy()) return *this; 1.18262 + if (yup<0) { xup-=yup*(xdown - xup)/(ydown - yup); yup = 0; } 1.18263 + if (ydown>=dimy()) { xdown-=(ydown - dimy())*(xdown - xup)/(ydown - yup); ydown = dimy()-1; } 1.18264 + T *ptrd0 = ptr(nx0,ny0); 1.18265 + int dx = xright - xleft, dy = ydown - yup; 1.18266 + const bool steep = dy>dx; 1.18267 + if (steep) cimg::swap(nx0,ny0,nx1,ny1,dx,dy); 1.18268 + const int 1.18269 + offx = (nx0<nx1?1:-1)*(steep?width:1), 1.18270 + offy = (ny0<ny1?1:-1)*(steep?1:width), 1.18271 + wh = width*height; 1.18272 + if (opacity>=1) { 1.18273 + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18274 + if (pattern&hatch) { T *ptrd = ptrd0; const tc* col = color; cimg_forV(*this,k) { *ptrd = (T)*(col++); ptrd+=wh; }} 1.18275 + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); 1.18276 + ptrd0+=offx; 1.18277 + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } 1.18278 + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18279 + T *ptrd = ptrd0; const tc* col = color; cimg_forV(*this,k) { *ptrd = (T)*(col++); ptrd+=wh; } 1.18280 + ptrd0+=offx; 1.18281 + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } 1.18282 + } 1.18283 + } else { 1.18284 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.18285 + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18286 + if (pattern&hatch) { 1.18287 + T *ptrd = ptrd0; const tc* col = color; 1.18288 + cimg_forV(*this,k) { *ptrd = (T)(nopacity**(col++) + *ptrd*copacity); ptrd+=wh; } 1.18289 + } 1.18290 + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); 1.18291 + ptrd0+=offx; 1.18292 + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } 1.18293 + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18294 + T *ptrd = ptrd0; const tc* col = color; cimg_forV(*this,k) { *ptrd = (T)(nopacity**(col++) + *ptrd*copacity); ptrd+=wh; } 1.18295 + ptrd0+=offx; 1.18296 + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } 1.18297 + } 1.18298 + } 1.18299 + return *this; 1.18300 + } 1.18301 + 1.18302 + //! Draw a 2D colored line. 1.18303 + template<typename tc> 1.18304 + CImg<T>& draw_line(const int x0, const int y0, 1.18305 + const int x1, const int y1, 1.18306 + const CImg<tc>& color, const float opacity=1, 1.18307 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.18308 + return draw_line(x0,y0,x1,y1,color.data,opacity,pattern,init_hatch); 1.18309 + } 1.18310 + 1.18311 + //! Draw a 2D colored line, with z-buffering. 1.18312 + template<typename tc> 1.18313 + CImg<T>& draw_line(float *const zbuffer, 1.18314 + const int x0, const int y0, const float z0, 1.18315 + const int x1, const int y1, const float z1, 1.18316 + const tc *const color, const float opacity=1, 1.18317 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.18318 + if (!is_empty() && z0>0 && z1>0) { 1.18319 + if (!color) 1.18320 + throw CImgArgumentException("CImg<%s>::draw_line() : Specified color is (null).", 1.18321 + pixel_type()); 1.18322 + static unsigned int hatch = ~0U - (~0U>>1); 1.18323 + if (init_hatch) hatch = ~0U - (~0U>>1); 1.18324 + const bool xdir = x0<x1, ydir = y0<y1; 1.18325 + int 1.18326 + nx0 = x0, nx1 = x1, ny0 = y0, ny1 = y1, 1.18327 + &xleft = xdir?nx0:nx1, &yleft = xdir?ny0:ny1, 1.18328 + &xright = xdir?nx1:nx0, &yright = xdir?ny1:ny0, 1.18329 + &xup = ydir?nx0:nx1, &yup = ydir?ny0:ny1, 1.18330 + &xdown = ydir?nx1:nx0, &ydown = ydir?ny1:ny0; 1.18331 + float 1.18332 + Z0 = 1/z0, Z1 = 1/z1, nz0 = Z0, nz1 = Z1, dz = Z1 - Z0, 1.18333 + &zleft = xdir?nz0:nz1, 1.18334 + &zright = xdir?nz1:nz0, 1.18335 + &zup = ydir?nz0:nz1, 1.18336 + &zdown = ydir?nz1:nz0; 1.18337 + if (xright<0 || xleft>=dimx()) return *this; 1.18338 + if (xleft<0) { 1.18339 + const int D = xright - xleft; 1.18340 + yleft-=xleft*(yright - yleft)/D; 1.18341 + zleft-=xleft*(zright - zleft)/D; 1.18342 + xleft = 0; 1.18343 + } 1.18344 + if (xright>=dimx()) { 1.18345 + const int d = xright - dimx(), D = xright - xleft; 1.18346 + yright-=d*(yright - yleft)/D; 1.18347 + zright-=d*(zright - zleft)/D; 1.18348 + xright = dimx()-1; 1.18349 + } 1.18350 + if (ydown<0 || yup>=dimy()) return *this; 1.18351 + if (yup<0) { 1.18352 + const int D = ydown - yup; 1.18353 + xup-=yup*(xdown - xup)/D; 1.18354 + zup-=yup*(zdown - zup)/D; 1.18355 + yup = 0; 1.18356 + } 1.18357 + if (ydown>=dimy()) { 1.18358 + const int d = ydown - dimy(), D = ydown - yup; 1.18359 + xdown-=d*(xdown - xup)/D; 1.18360 + zdown-=d*(zdown - zup)/D; 1.18361 + ydown = dimy()-1; 1.18362 + } 1.18363 + T *ptrd0 = ptr(nx0,ny0); 1.18364 + float *ptrz = zbuffer + nx0 + ny0*width; 1.18365 + int dx = xright - xleft, dy = ydown - yup; 1.18366 + const bool steep = dy>dx; 1.18367 + if (steep) cimg::swap(nx0,ny0,nx1,ny1,dx,dy); 1.18368 + const int 1.18369 + offx = (nx0<nx1?1:-1)*(steep?width:1), 1.18370 + offy = (ny0<ny1?1:-1)*(steep?1:width), 1.18371 + wh = width*height, 1.18372 + ndx = dx>0?dx:1; 1.18373 + if (opacity>=1) { 1.18374 + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18375 + const float z = Z0 + x*dz/ndx; 1.18376 + if (z>*ptrz && pattern&hatch) { 1.18377 + *ptrz = z; 1.18378 + T *ptrd = ptrd0; const tc *col = color; 1.18379 + cimg_forV(*this,k) { *ptrd = (T)*(col++); ptrd+=wh; } 1.18380 + } 1.18381 + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); 1.18382 + ptrd0+=offx; ptrz+=offx; 1.18383 + if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; } 1.18384 + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18385 + const float z = Z0 + x*dz/ndx; 1.18386 + if (z>*ptrz) { 1.18387 + *ptrz = z; 1.18388 + T *ptrd = ptrd0; const tc *col = color; 1.18389 + cimg_forV(*this,k) { *ptrd = (T)*(col++); ptrd+=wh; } 1.18390 + } 1.18391 + ptrd0+=offx; ptrz+=offx; 1.18392 + if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; } 1.18393 + } 1.18394 + } else { 1.18395 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.18396 + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18397 + const float z = Z0 + x*dz/ndx; 1.18398 + if (z>*ptrz && pattern&hatch) { 1.18399 + *ptrz = z; 1.18400 + T *ptrd = ptrd0; const tc *col = color; 1.18401 + cimg_forV(*this,k) { *ptrd = (T)(nopacity**(col++) + *ptrd*copacity); ptrd+=wh; } 1.18402 + } 1.18403 + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); 1.18404 + ptrd0+=offx; ptrz+=offx; 1.18405 + if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; } 1.18406 + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18407 + const float z = Z0 + x*dz/ndx; 1.18408 + if (z>*ptrz) { 1.18409 + *ptrz = z; 1.18410 + T *ptrd = ptrd0; const tc *col = color; 1.18411 + cimg_forV(*this,k) { *ptrd = (T)(nopacity**(col++) + *ptrd*copacity); ptrd+=wh; } 1.18412 + } 1.18413 + ptrd0+=offx; ptrz+=offx; 1.18414 + if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; } 1.18415 + } 1.18416 + } 1.18417 + } 1.18418 + return *this; 1.18419 + } 1.18420 + 1.18421 + //! Draw a 2D colored line, with z-buffering. 1.18422 + template<typename tc> 1.18423 + CImg<T>& draw_line(float *const zbuffer, 1.18424 + const int x0, const int y0, const float z0, 1.18425 + const int x1, const int y1, const float z1, 1.18426 + const CImg<tc>& color, const float opacity=1, 1.18427 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.18428 + return draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color.data,opacity,pattern,init_hatch); 1.18429 + } 1.18430 + 1.18431 + //! Draw a 3D colored line. 1.18432 + template<typename tc> 1.18433 + CImg<T>& draw_line(const int x0, const int y0, const int z0, 1.18434 + const int x1, const int y1, const int z1, 1.18435 + const tc *const color, const float opacity=1, 1.18436 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.18437 + if (is_empty()) return *this; 1.18438 + if (!color) 1.18439 + throw CImgArgumentException("CImg<%s>::draw_line() : Specified color is (null)", 1.18440 + pixel_type()); 1.18441 + static unsigned int hatch = ~0U - (~0U>>1); 1.18442 + if (init_hatch) hatch = ~0U - (~0U>>1); 1.18443 + int nx0 = x0, ny0 = y0, nz0 = z0, nx1 = x1, ny1 = y1, nz1 = z1; 1.18444 + if (nx0>nx1) cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1); 1.18445 + if (nx1<0 || nx0>=dimx()) return *this; 1.18446 + if (nx0<0) { const int D = 1 + nx1 - nx0; ny0-=nx0*(1 + ny1 - ny0)/D; nz0-=nx0*(1 + nz1 - nz0)/D; nx0 = 0; } 1.18447 + if (nx1>=dimx()) { const int d = nx1-dimx(), D = 1 + nx1 - nx0; ny1+=d*(1 + ny0 - ny1)/D; nz1+=d*(1 + nz0 - nz1)/D; nx1 = dimx()-1; } 1.18448 + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1); 1.18449 + if (ny1<0 || ny0>=dimy()) return *this; 1.18450 + if (ny0<0) { const int D = 1 + ny1 - ny0; nx0-=ny0*(1 + nx1 - nx0)/D; nz0-=ny0*(1 + nz1 - nz0)/D; ny0 = 0; } 1.18451 + if (ny1>=dimy()) { const int d = ny1-dimy(), D = 1 + ny1 - ny0; nx1+=d*(1 + nx0 - nx1)/D; nz1+=d*(1 + nz0 - nz1)/D; ny1 = dimy()-1; } 1.18452 + if (nz0>nz1) cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1); 1.18453 + if (nz1<0 || nz0>=dimz()) return *this; 1.18454 + if (nz0<0) { const int D = 1 + nz1 - nz0; nx0-=nz0*(1 + nx1 - nx0)/D; ny0-=nz0*(1 + ny1 - ny0)/D; nz0 = 0; } 1.18455 + if (nz1>=dimz()) { const int d = nz1-dimz(), D = 1 + nz1 - nz0; nx1+=d*(1 + nx0 - nx1)/D; ny1+=d*(1 + ny0 - ny1)/D; nz1 = dimz()-1; } 1.18456 + const unsigned int dmax = cimg::max(cimg::abs(nx1 - nx0),cimg::abs(ny1 - ny0),nz1 - nz0), whz = width*height*depth; 1.18457 + const float px = (nx1 - nx0)/(float)dmax, py = (ny1 - ny0)/(float)dmax, pz = (nz1 - nz0)/(float)dmax; 1.18458 + float x = (float)nx0, y = (float)ny0, z = (float)nz0; 1.18459 + if (opacity>=1) for (unsigned int t = 0; t<=dmax; ++t) { 1.18460 + if (!(~pattern) || (~pattern && pattern&hatch)) { 1.18461 + T* ptrd = ptr((unsigned int)x,(unsigned int)y,(unsigned int)z); 1.18462 + const tc *col = color; cimg_forV(*this,k) { *ptrd = (T)*(col++); ptrd+=whz; } 1.18463 + } 1.18464 + x+=px; y+=py; z+=pz; if (pattern) { hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); } 1.18465 + } else { 1.18466 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.18467 + for (unsigned int t = 0; t<=dmax; ++t) { 1.18468 + if (!(~pattern) || (~pattern && pattern&hatch)) { 1.18469 + T* ptrd = ptr((unsigned int)x,(unsigned int)y,(unsigned int)z); 1.18470 + const tc *col = color; cimg_forV(*this,k) { *ptrd = (T)(*(col++)*nopacity + *ptrd*copacity); ptrd+=whz; } 1.18471 + } 1.18472 + x+=px; y+=py; z+=pz; if (pattern) { hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); } 1.18473 + } 1.18474 + } 1.18475 + return *this; 1.18476 + } 1.18477 + 1.18478 + //! Draw a 3D colored line. 1.18479 + template<typename tc> 1.18480 + CImg<T>& draw_line(const int x0, const int y0, const int z0, 1.18481 + const int x1, const int y1, const int z1, 1.18482 + const CImg<tc>& color, const float opacity=1, 1.18483 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.18484 + return draw_line(x0,y0,z0,x1,y1,z1,color.data,opacity,pattern,init_hatch); 1.18485 + } 1.18486 + 1.18487 + //! Draw a 2D textured line. 1.18488 + /** 1.18489 + \param x0 X-coordinate of the starting line point. 1.18490 + \param y0 Y-coordinate of the starting line point. 1.18491 + \param x1 X-coordinate of the ending line point. 1.18492 + \param y1 Y-coordinate of the ending line point. 1.18493 + \param texture Texture image defining the pixel colors. 1.18494 + \param tx0 X-coordinate of the starting texture point. 1.18495 + \param ty0 Y-coordinate of the starting texture point. 1.18496 + \param tx1 X-coordinate of the ending texture point. 1.18497 + \param ty1 Y-coordinate of the ending texture point. 1.18498 + \param opacity Drawing opacity (optional). 1.18499 + \param pattern An integer whose bits describe the line pattern (optional). 1.18500 + \param init_hatch Flag telling if the hash variable must be reinitialized (optional). 1.18501 + \note 1.18502 + - Clipping is supported but not for texture coordinates. 1.18503 + - Line routine uses the well known Bresenham's algorithm. 1.18504 + \par Example: 1.18505 + \code 1.18506 + CImg<unsigned char> img(100,100,1,3,0), texture("texture256x256.ppm"); 1.18507 + const unsigned char color[] = { 255,128,64 }; 1.18508 + img.draw_line(40,40,80,70,texture,0,0,255,255); 1.18509 + \endcode 1.18510 + **/ 1.18511 + template<typename tc> 1.18512 + CImg<T>& draw_line(const int x0, const int y0, 1.18513 + const int x1, const int y1, 1.18514 + const CImg<tc>& texture, 1.18515 + const int tx0, const int ty0, 1.18516 + const int tx1, const int ty1, 1.18517 + const float opacity=1, 1.18518 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.18519 + if (is_empty()) return *this; 1.18520 + if (!texture || texture.dim<dim) 1.18521 + throw CImgArgumentException("CImg<%s>::draw_line() : Specified texture (%u,%u,%u,%u,%p) is not a valid argument.", 1.18522 + pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data); 1.18523 + if (is_overlapped(texture)) return draw_line(x0,y0,x1,y1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch); 1.18524 + static unsigned int hatch = ~0U - (~0U>>1); 1.18525 + if (init_hatch) hatch = ~0U - (~0U>>1); 1.18526 + const bool xdir = x0<x1, ydir = y0<y1; 1.18527 + int 1.18528 + dtx = tx1-tx0, dty = ty1-ty0, 1.18529 + nx0 = x0, nx1 = x1, ny0 = y0, ny1 = y1, 1.18530 + tnx0 = tx0, tnx1 = tx1, tny0 = ty0, tny1 = ty1, 1.18531 + &xleft = xdir?nx0:nx1, &yleft = xdir?ny0:ny1, &xright = xdir?nx1:nx0, &yright = xdir?ny1:ny0, 1.18532 + &txleft = xdir?tnx0:tnx1, &tyleft = xdir?tny0:tny1, &txright = xdir?tnx1:tnx0, &tyright = xdir?tny1:tny0, 1.18533 + &xup = ydir?nx0:nx1, &yup = ydir?ny0:ny1, &xdown = ydir?nx1:nx0, &ydown = ydir?ny1:ny0, 1.18534 + &txup = ydir?tnx0:tnx1, &tyup = ydir?tny0:tny1, &txdown = ydir?tnx1:tnx0, &tydown = ydir?tny1:tny0; 1.18535 + if (xright<0 || xleft>=dimx()) return *this; 1.18536 + if (xleft<0) { 1.18537 + const int D = xright - xleft; 1.18538 + yleft-=xleft*(yright - yleft)/D; 1.18539 + txleft-=xleft*(txright - txleft)/D; 1.18540 + tyleft-=xleft*(tyright - tyleft)/D; 1.18541 + xleft = 0; 1.18542 + } 1.18543 + if (xright>=dimx()) { 1.18544 + const int d = xright - dimx(), D = xright - xleft; 1.18545 + yright-=d*(yright - yleft)/D; 1.18546 + txright-=d*(txright - txleft)/D; 1.18547 + tyright-=d*(tyright - tyleft)/D; 1.18548 + xright = dimx()-1; 1.18549 + } 1.18550 + if (ydown<0 || yup>=dimy()) return *this; 1.18551 + if (yup<0) { 1.18552 + const int D = ydown - yup; 1.18553 + xup-=yup*(xdown - xup)/D; 1.18554 + txup-=yup*(txdown - txup)/D; 1.18555 + tyup-=yup*(tydown - tyup)/D; 1.18556 + yup = 0; 1.18557 + } 1.18558 + if (ydown>=dimy()) { 1.18559 + const int d = ydown - dimy(), D = ydown - yup; 1.18560 + xdown-=d*(xdown - xup)/D; 1.18561 + txdown-=d*(txdown - txup)/D; 1.18562 + tydown-=d*(tydown - tyup)/D; 1.18563 + ydown = dimy()-1; 1.18564 + } 1.18565 + T *ptrd0 = ptr(nx0,ny0); 1.18566 + int dx = xright - xleft, dy = ydown - yup; 1.18567 + const bool steep = dy>dx; 1.18568 + if (steep) cimg::swap(nx0,ny0,nx1,ny1,dx,dy); 1.18569 + const int 1.18570 + offx = (nx0<nx1?1:-1)*(steep?width:1), 1.18571 + offy = (ny0<ny1?1:-1)*(steep?1:width), 1.18572 + wh = width*height, 1.18573 + ndx = dx>0?dx:1; 1.18574 + if (opacity>=1) { 1.18575 + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18576 + if (pattern&hatch) { 1.18577 + T *ptrd = ptrd0; 1.18578 + const int tx = tx0 + x*dtx/ndx, ty = ty0 + x*dty/ndx; 1.18579 + cimg_forV(*this,k) { *ptrd = (T)texture(tx,ty,0,k); ptrd+=wh; } 1.18580 + } 1.18581 + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); 1.18582 + ptrd0+=offx; 1.18583 + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } 1.18584 + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18585 + T *ptrd = ptrd0; 1.18586 + const int tx = tx0 + x*dtx/ndx, ty = ty0 + x*dty/ndx; 1.18587 + cimg_forV(*this,k) { *ptrd = (T)texture(tx,ty,0,k); ptrd+=wh; } 1.18588 + ptrd0+=offx; 1.18589 + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } 1.18590 + } 1.18591 + } else { 1.18592 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.18593 + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18594 + T *ptrd = ptrd0; 1.18595 + if (pattern&hatch) { 1.18596 + const int tx = tx0 + x*dtx/ndx, ty = ty0 + x*dty/ndx; 1.18597 + cimg_forV(*this,k) { *ptrd = (T)(nopacity*texture(tx,ty,0,k) + *ptrd*copacity); ptrd+=wh; } 1.18598 + } 1.18599 + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); 1.18600 + ptrd0+=offx; 1.18601 + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } 1.18602 + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18603 + T *ptrd = ptrd0; 1.18604 + const int tx = tx0 + x*dtx/ndx, ty = ty0 + x*dty/ndx; 1.18605 + cimg_forV(*this,k) { *ptrd = (T)(nopacity*texture(tx,ty,0,k) + *ptrd*copacity); ptrd+=wh; } 1.18606 + ptrd0+=offx; 1.18607 + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } 1.18608 + } 1.18609 + } 1.18610 + return *this; 1.18611 + } 1.18612 + 1.18613 + //! Draw a 2D textured line, with perspective correction. 1.18614 + template<typename tc> 1.18615 + CImg<T>& draw_line(const int x0, const int y0, const float z0, 1.18616 + const int x1, const int y1, const float z1, 1.18617 + const CImg<tc>& texture, 1.18618 + const int tx0, const int ty0, 1.18619 + const int tx1, const int ty1, 1.18620 + const float opacity=1, 1.18621 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.18622 + if (is_empty() && z0<=0 && z1<=0) return *this; 1.18623 + if (!texture || texture.dim<dim) 1.18624 + throw CImgArgumentException("CImg<%s>::draw_line() : Specified texture (%u,%u,%u,%u,%p) is not a valid argument.", 1.18625 + pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data); 1.18626 + if (is_overlapped(texture)) return draw_line(x0,y0,z0,x1,y1,z1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch); 1.18627 + static unsigned int hatch = ~0U - (~0U>>1); 1.18628 + if (init_hatch) hatch = ~0U - (~0U>>1); 1.18629 + const bool xdir = x0<x1, ydir = y0<y1; 1.18630 + int 1.18631 + nx0 = x0, nx1 = x1, ny0 = y0, ny1 = y1, 1.18632 + &xleft = xdir?nx0:nx1, &yleft = xdir?ny0:ny1, 1.18633 + &xright = xdir?nx1:nx0, &yright = xdir?ny1:ny0, 1.18634 + &xup = ydir?nx0:nx1, &yup = ydir?ny0:ny1, 1.18635 + &xdown = ydir?nx1:nx0, &ydown = ydir?ny1:ny0; 1.18636 + float 1.18637 + Tx0 = tx0/z0, Tx1 = tx1/z1, 1.18638 + Ty0 = ty0/z0, Ty1 = ty1/z1, 1.18639 + Z0 = 1/z0, Z1 = 1/z1, 1.18640 + dz = Z1 - Z0, dtx = Tx1 - Tx0, dty = Ty1 - Ty0, 1.18641 + tnx0 = Tx0, tnx1 = Tx1, tny0 = Ty0, tny1 = Ty1, nz0 = Z0, nz1 = Z1, 1.18642 + &zleft = xdir?nz0:nz1, &txleft = xdir?tnx0:tnx1, &tyleft = xdir?tny0:tny1, 1.18643 + &zright = xdir?nz1:nz0, &txright = xdir?tnx1:tnx0, &tyright = xdir?tny1:tny0, 1.18644 + &zup = ydir?nz0:nz1, &txup = ydir?tnx0:tnx1, &tyup = ydir?tny0:tny1, 1.18645 + &zdown = ydir?nz1:nz0, &txdown = ydir?tnx1:tnx0, &tydown = ydir?tny1:tny0; 1.18646 + if (xright<0 || xleft>=dimx()) return *this; 1.18647 + if (xleft<0) { 1.18648 + const int D = xright - xleft; 1.18649 + yleft-=xleft*(yright - yleft)/D; 1.18650 + zleft-=xleft*(zright - zleft)/D; 1.18651 + txleft-=xleft*(txright - txleft)/D; 1.18652 + tyleft-=xleft*(tyright - tyleft)/D; 1.18653 + xleft = 0; 1.18654 + } 1.18655 + if (xright>=dimx()) { 1.18656 + const int d = xright - dimx(), D = xright - xleft; 1.18657 + yright-=d*(yright - yleft)/D; 1.18658 + zright-=d*(zright - zleft)/D; 1.18659 + txright-=d*(txright - txleft)/D; 1.18660 + tyright-=d*(tyright - tyleft)/D; 1.18661 + xright = dimx()-1; 1.18662 + } 1.18663 + if (ydown<0 || yup>=dimy()) return *this; 1.18664 + if (yup<0) { 1.18665 + const int D = ydown - yup; 1.18666 + xup-=yup*(xdown - xup)/D; 1.18667 + zup-=yup*(zdown - zup)/D; 1.18668 + txup-=yup*(txdown - txup)/D; 1.18669 + tyup-=yup*(tydown - tyup)/D; 1.18670 + yup = 0; 1.18671 + } 1.18672 + if (ydown>=dimy()) { 1.18673 + const int d = ydown - dimy(), D = ydown - yup; 1.18674 + xdown-=d*(xdown - xup)/D; 1.18675 + zdown-=d*(zdown - zup)/D; 1.18676 + txdown-=d*(txdown - txup)/D; 1.18677 + tydown-=d*(tydown - tyup)/D; 1.18678 + ydown = dimy()-1; 1.18679 + } 1.18680 + T *ptrd0 = ptr(nx0,ny0); 1.18681 + int dx = xright - xleft, dy = ydown - yup; 1.18682 + const bool steep = dy>dx; 1.18683 + if (steep) cimg::swap(nx0,ny0,nx1,ny1,dx,dy); 1.18684 + const int 1.18685 + offx = (nx0<nx1?1:-1)*(steep?width:1), 1.18686 + offy = (ny0<ny1?1:-1)*(steep?1:width), 1.18687 + wh = width*height, 1.18688 + ndx = dx>0?dx:1; 1.18689 + if (opacity>=1) { 1.18690 + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18691 + if (pattern&hatch) { 1.18692 + const float z = Z0 + x*dz/ndx, tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx; 1.18693 + T *ptrd = ptrd0; cimg_forV(*this,k) { *ptrd = (T)texture((int)(tx/z),(int)(ty/z),0,k); ptrd+=wh; } 1.18694 + } 1.18695 + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); 1.18696 + ptrd0+=offx; 1.18697 + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } 1.18698 + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18699 + const float z = Z0 + x*dz/ndx, tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx; 1.18700 + T *ptrd = ptrd0; cimg_forV(*this,k) { *ptrd = (T)texture((int)(tx/z),(int)(ty/z),0,k); ptrd+=wh; } 1.18701 + ptrd0+=offx; 1.18702 + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } 1.18703 + } 1.18704 + } else { 1.18705 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.18706 + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18707 + if (pattern&hatch) { 1.18708 + const float z = Z0 + x*dz/ndx, tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx; 1.18709 + T *ptrd = ptrd0; cimg_forV(*this,k) { *ptrd = (T)(nopacity*texture((int)(tx/z),(int)(ty/z),0,k) + *ptrd*copacity); ptrd+=wh; } 1.18710 + } 1.18711 + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); 1.18712 + ptrd0+=offx; 1.18713 + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } 1.18714 + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18715 + const float z = Z0 + x*dz/ndx, tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx; 1.18716 + T *ptrd = ptrd0; 1.18717 + cimg_forV(*this,k) { *ptrd = (T)(nopacity*texture((int)(tx/z),(int)(ty/z),0,k) + *ptrd*copacity); ptrd+=wh; } 1.18718 + ptrd0+=offx; 1.18719 + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } 1.18720 + } 1.18721 + } 1.18722 + return *this; 1.18723 + } 1.18724 + 1.18725 + //! Draw a 2D textured line, with z-buffering and perspective correction. 1.18726 + template<typename tc> 1.18727 + CImg<T>& draw_line(float *const zbuffer, 1.18728 + const int x0, const int y0, const float z0, 1.18729 + const int x1, const int y1, const float z1, 1.18730 + const CImg<tc>& texture, 1.18731 + const int tx0, const int ty0, 1.18732 + const int tx1, const int ty1, 1.18733 + const float opacity=1, 1.18734 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.18735 + if (!is_empty() && z0>0 && z1>0) { 1.18736 + if (!texture || texture.dim<dim) 1.18737 + throw CImgArgumentException("CImg<%s>::draw_line() : Specified texture (%u,%u,%u,%u,%p) is not a valid argument.", 1.18738 + pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data); 1.18739 + if (is_overlapped(texture)) return draw_line(zbuffer,x0,y0,z0,x1,y1,z1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch); 1.18740 + static unsigned int hatch = ~0U - (~0U>>1); 1.18741 + if (init_hatch) hatch = ~0U - (~0U>>1); 1.18742 + const bool xdir = x0<x1, ydir = y0<y1; 1.18743 + int 1.18744 + nx0 = x0, nx1 = x1, ny0 = y0, ny1 = y1, 1.18745 + &xleft = xdir?nx0:nx1, &yleft = xdir?ny0:ny1, 1.18746 + &xright = xdir?nx1:nx0, &yright = xdir?ny1:ny0, 1.18747 + &xup = ydir?nx0:nx1, &yup = ydir?ny0:ny1, 1.18748 + &xdown = ydir?nx1:nx0, &ydown = ydir?ny1:ny0; 1.18749 + float 1.18750 + Tx0 = tx0/z0, Tx1 = tx1/z1, 1.18751 + Ty0 = ty0/z0, Ty1 = ty1/z1, 1.18752 + Z0 = 1/z0, Z1 = 1/z1, 1.18753 + dz = Z1 - Z0, dtx = Tx1 - Tx0, dty = Ty1 - Ty0, 1.18754 + tnx0 = Tx0, tnx1 = Tx1, tny0 = Ty0, tny1 = Ty1, nz0 = Z0, nz1 = Z1, 1.18755 + &zleft = xdir?nz0:nz1, &txleft = xdir?tnx0:tnx1, &tyleft = xdir?tny0:tny1, 1.18756 + &zright = xdir?nz1:nz0, &txright = xdir?tnx1:tnx0, &tyright = xdir?tny1:tny0, 1.18757 + &zup = ydir?nz0:nz1, &txup = ydir?tnx0:tnx1, &tyup = ydir?tny0:tny1, 1.18758 + &zdown = ydir?nz1:nz0, &txdown = ydir?tnx1:tnx0, &tydown = ydir?tny1:tny0; 1.18759 + if (xright<0 || xleft>=dimx()) return *this; 1.18760 + if (xleft<0) { 1.18761 + const int D = xright - xleft; 1.18762 + yleft-=xleft*(yright - yleft)/D; 1.18763 + zleft-=xleft*(zright - zleft)/D; 1.18764 + txleft-=xleft*(txright - txleft)/D; 1.18765 + tyleft-=xleft*(tyright - tyleft)/D; 1.18766 + xleft = 0; 1.18767 + } 1.18768 + if (xright>=dimx()) { 1.18769 + const int d = xright - dimx(), D = xright - xleft; 1.18770 + yright-=d*(yright - yleft)/D; 1.18771 + zright-=d*(zright - zleft)/D; 1.18772 + txright-=d*(txright - txleft)/D; 1.18773 + tyright-=d*(tyright - tyleft)/D; 1.18774 + xright = dimx()-1; 1.18775 + } 1.18776 + if (ydown<0 || yup>=dimy()) return *this; 1.18777 + if (yup<0) { 1.18778 + const int D = ydown - yup; 1.18779 + xup-=yup*(xdown - xup)/D; 1.18780 + zup-=yup*(zdown - zup)/D; 1.18781 + txup-=yup*(txdown - txup)/D; 1.18782 + tyup-=yup*(tydown - tyup)/D; 1.18783 + yup = 0; 1.18784 + } 1.18785 + if (ydown>=dimy()) { 1.18786 + const int d = ydown - dimy(), D = ydown - yup; 1.18787 + xdown-=d*(xdown - xup)/D; 1.18788 + zdown-=d*(zdown - zup)/D; 1.18789 + txdown-=d*(txdown - txup)/D; 1.18790 + tydown-=d*(tydown - tyup)/D; 1.18791 + ydown = dimy()-1; 1.18792 + } 1.18793 + T *ptrd0 = ptr(nx0,ny0); 1.18794 + float *ptrz = zbuffer + nx0 + ny0*width; 1.18795 + int dx = xright - xleft, dy = ydown - yup; 1.18796 + const bool steep = dy>dx; 1.18797 + if (steep) cimg::swap(nx0,ny0,nx1,ny1,dx,dy); 1.18798 + const int 1.18799 + offx = (nx0<nx1?1:-1)*(steep?width:1), 1.18800 + offy = (ny0<ny1?1:-1)*(steep?1:width), 1.18801 + wh = width*height, 1.18802 + ndx = dx>0?dx:1; 1.18803 + if (opacity>=1) { 1.18804 + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18805 + if (pattern&hatch) { 1.18806 + const float z = Z0 + x*dz/ndx; 1.18807 + if (z>*ptrz) { 1.18808 + *ptrz = z; 1.18809 + const float tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx; 1.18810 + T *ptrd = ptrd0; cimg_forV(*this,k) { *ptrd = (T)texture((int)(tx/z),(int)(ty/z),0,k); ptrd+=wh; } 1.18811 + } 1.18812 + } 1.18813 + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); 1.18814 + ptrd0+=offx; ptrz+=offx; 1.18815 + if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; } 1.18816 + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18817 + const float z = Z0 + x*dz/ndx; 1.18818 + if (z>*ptrz) { 1.18819 + *ptrz = z; 1.18820 + const float tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx; 1.18821 + T *ptrd = ptrd0; cimg_forV(*this,k) { *ptrd = (T)texture((int)(tx/z),(int)(ty/z),0,k); ptrd+=wh; } 1.18822 + } 1.18823 + ptrd0+=offx; ptrz+=offx; 1.18824 + if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; } 1.18825 + } 1.18826 + } else { 1.18827 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.18828 + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18829 + if (pattern&hatch) { 1.18830 + const float z = Z0 + x*dz/ndx; 1.18831 + if (z>*ptrz) { 1.18832 + *ptrz = z; 1.18833 + const float tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx; 1.18834 + T *ptrd = ptrd0; cimg_forV(*this,k) { *ptrd = (T)(nopacity*texture((int)(tx/z),(int)(ty/z),0,k) + *ptrd*copacity); ptrd+=wh; } 1.18835 + } 1.18836 + } 1.18837 + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); 1.18838 + ptrd0+=offx; ptrz+=offx; 1.18839 + if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; } 1.18840 + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { 1.18841 + const float z = Z0 + x*dz/ndx; 1.18842 + if (z>*ptrz) { 1.18843 + *ptrz = z; 1.18844 + const float tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx; 1.18845 + T *ptrd = ptrd0; cimg_forV(*this,k) { *ptrd = (T)(nopacity*texture((int)(tx/z),(int)(ty/z),0,k) + *ptrd*copacity); ptrd+=wh; } 1.18846 + } 1.18847 + ptrd0+=offx; ptrz+=offx; 1.18848 + if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offx; error+=dx; } 1.18849 + } 1.18850 + } 1.18851 + } 1.18852 + return *this; 1.18853 + } 1.18854 + 1.18855 + // Inner routine for drawing set of consecutive lines with generic type for coordinates. 1.18856 + template<typename t, typename tc> 1.18857 + CImg<T>& _draw_line(const t& points, const unsigned int W, const unsigned int H, 1.18858 + const tc *const color, const float opacity, 1.18859 + const unsigned int pattern, const bool init_hatch) { 1.18860 + if (is_empty() || !points || W<2) return *this; 1.18861 + bool ninit_hatch = init_hatch; 1.18862 + switch (H) { 1.18863 + case 0 : case 1 : 1.18864 + throw CImgArgumentException("CImg<%s>::draw_line() : Given list of points is not valid.", 1.18865 + pixel_type()); 1.18866 + case 2 : { 1.18867 + const int x0 = (int)points(0,0), y0 = (int)points(0,1); 1.18868 + int ox = x0, oy = y0; 1.18869 + for (unsigned int i = 1; i<W; ++i) { 1.18870 + const int x = (int)points(i,0), y = (int)points(i,1); 1.18871 + draw_line(ox,oy,x,y,color,opacity,pattern,ninit_hatch); 1.18872 + ninit_hatch = false; 1.18873 + ox = x; oy = y; 1.18874 + } 1.18875 + } break; 1.18876 + default : { 1.18877 + const int x0 = (int)points(0,0), y0 = (int)points(0,1), z0 = (int)points(0,2); 1.18878 + int ox = x0, oy = y0, oz = z0; 1.18879 + for (unsigned int i = 1; i<W; ++i) { 1.18880 + const int x = (int)points(i,0), y = (int)points(i,1), z = (int)points(i,2); 1.18881 + draw_line(ox,oy,oz,x,y,z,color,opacity,pattern,ninit_hatch); 1.18882 + ninit_hatch = false; 1.18883 + ox = x; oy = y; oz = z; 1.18884 + } 1.18885 + } 1.18886 + } 1.18887 + return *this; 1.18888 + } 1.18889 + 1.18890 + //! Draw a set of consecutive colored lines in the instance image. 1.18891 + /** 1.18892 + \param points Coordinates of vertices, stored as a list of vectors. 1.18893 + \param color Pointer to \c dimv() consecutive values of type \c T, defining the drawing color. 1.18894 + \param opacity Drawing opacity (optional). 1.18895 + \param pattern An integer whose bits describe the line pattern (optional). 1.18896 + \param init_hatch If set to true, init hatch motif. 1.18897 + \note 1.18898 + - This function uses several call to the single CImg::draw_line() procedure, 1.18899 + depending on the vectors size in \p points. 1.18900 + \par Example: 1.18901 + \code 1.18902 + CImg<unsigned char> img(100,100,1,3,0); 1.18903 + const unsigned char color[] = { 255,128,64 }; 1.18904 + CImgList<int> points; 1.18905 + points.insert(CImg<int>::vector(0,0)). 1.18906 + .insert(CImg<int>::vector(70,10)). 1.18907 + .insert(CImg<int>::vector(80,60)). 1.18908 + .insert(CImg<int>::vector(10,90)); 1.18909 + img.draw_line(points,color); 1.18910 + \endcode 1.18911 + **/ 1.18912 + template<typename t, typename tc> 1.18913 + CImg<T>& draw_line(const CImgList<t>& points, 1.18914 + const tc *const color, const float opacity=1, 1.18915 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.18916 + unsigned int H = ~0U; cimglist_for(points,p) H = cimg::min(H,(unsigned int)(points[p].size())); 1.18917 + return _draw_line(points,points.size,H,color,opacity,pattern,init_hatch); 1.18918 + } 1.18919 + 1.18920 + //! Draw a set of consecutive colored lines in the instance image. 1.18921 + template<typename t, typename tc> 1.18922 + CImg<T>& draw_line(const CImgList<t>& points, 1.18923 + const CImg<tc>& color, const float opacity=1, 1.18924 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.18925 + return draw_line(points,color.data,opacity,pattern,init_hatch); 1.18926 + } 1.18927 + 1.18928 + //! Draw a set of consecutive colored lines in the instance image. 1.18929 + /** 1.18930 + \note 1.18931 + - Similar to the previous function, where the N vertex coordinates are stored as a Nx2 or Nx3 image 1.18932 + (sequence of vectors aligned along the x-axis). 1.18933 + **/ 1.18934 + template<typename t, typename tc> 1.18935 + CImg<T>& draw_line(const CImg<t>& points, 1.18936 + const tc *const color, const float opacity=1, 1.18937 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.18938 + return _draw_line(points,points.width,points.height,color,opacity,pattern,init_hatch); 1.18939 + } 1.18940 + 1.18941 + //! Draw a set of consecutive colored lines in the instance image. 1.18942 + template<typename t, typename tc> 1.18943 + CImg<T>& draw_line(const CImg<t>& points, 1.18944 + const CImg<tc>& color, const float opacity=1, 1.18945 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.18946 + return draw_line(points,color.data,opacity,pattern,init_hatch); 1.18947 + } 1.18948 + 1.18949 + // Inner routine for a drawing filled polygon with generic type for coordinates. 1.18950 + template<typename t, typename tc> 1.18951 + CImg<T>& _draw_polygon(const t& points, const unsigned int N, 1.18952 + const tc *const color, const float opacity) { 1.18953 + if (is_empty() || !points || N<3) return *this; 1.18954 + if (!color) 1.18955 + throw CImgArgumentException("CImg<%s>::draw_polygon() : Specified color is (null).", 1.18956 + pixel_type()); 1.18957 + _draw_scanline(color,opacity); 1.18958 + int xmin = (int)(~0U>>1), xmax = 0, ymin = (int)(~0U>>1), ymax = 0; 1.18959 + { for (unsigned int p = 0; p<N; ++p) { 1.18960 + const int x = (int)points(p,0), y = (int)points(p,1); 1.18961 + if (x<xmin) xmin = x; 1.18962 + if (x>xmax) xmax = x; 1.18963 + if (y<ymin) ymin = y; 1.18964 + if (y>ymax) ymax = y; 1.18965 + }} 1.18966 + if (xmax<0 || xmin>=dimx() || ymax<0 || ymin>=dimy()) return *this; 1.18967 + const unsigned int 1.18968 + nymin = ymin<0?0:(unsigned int)ymin, 1.18969 + nymax = ymax>=dimy()?height-1:(unsigned int)ymax, 1.18970 + dy = 1 + nymax - nymin; 1.18971 + CImg<intT> X(1+2*N,dy,1,1,0), tmp; 1.18972 + int cx = (int)points(0,0), cy = (int)points(0,1); 1.18973 + for (unsigned int cp = 0, p = 0; p<N; ++p) { 1.18974 + const unsigned int np = (p!=N-1)?p+1:0, ap = (np!=N-1)?np+1:0; 1.18975 + const int 1.18976 + nx = (int)points(np,0), ny = (int)points(np,1), ay = (int)points(ap,1), 1.18977 + y0 = cy - nymin, y1 = ny - nymin; 1.18978 + if (y0!=y1) { 1.18979 + const int countermin = ((ny<ay && cy<ny) || (ny>ay && cy>ny))?1:0; 1.18980 + for (int x = cx, y = y0, _sx = 1, _sy = 1, 1.18981 + _dx = nx>cx?nx-cx:((_sx=-1),cx-nx), 1.18982 + _dy = y1>y0?y1-y0:((_sy=-1),y0-y1), 1.18983 + _counter = ((_dx-=_dy?_dy*(_dx/_dy):0),_dy), 1.18984 + _err = _dx>>1, 1.18985 + _rx = _dy?(nx-cx)/_dy:0; 1.18986 + _counter>=countermin; 1.18987 + --_counter, y+=_sy, x+=_rx + ((_err-=_dx)<0?_err+=_dy,_sx:0)) 1.18988 + if (y>=0 && y<(int)dy) X(++X(0,y),y) = x; 1.18989 + cp = np; cx = nx; cy = ny; 1.18990 + } else { 1.18991 + const int pp = (cp?cp-1:N-1), py = (int)points(pp,1); 1.18992 + if ((cy>py && ay>cy) || (cy<py && ay<cy)) X(++X(0,y0),y0) = nx; 1.18993 + if (cy!=ay) { cp = np; cx = nx; cy = ny; } 1.18994 + } 1.18995 + } 1.18996 + for (int y = 0; y<(int)dy; ++y) { 1.18997 + tmp.assign(X.ptr(1,y),X(0,y),1,1,1,true).sort(); 1.18998 + for (int i = 1; i<=X(0,y); ) { 1.18999 + const int xb = X(i++,y), xe = X(i++,y); 1.19000 + _draw_scanline(xb,xe,nymin+y,color,opacity); 1.19001 + } 1.19002 + } 1.19003 + return *this; 1.19004 + } 1.19005 + 1.19006 + //! Draw a filled polygon in the instance image. 1.19007 + template<typename t, typename tc> 1.19008 + CImg<T>& draw_polygon(const CImgList<t>& points, 1.19009 + const tc *const color, const float opacity=1) { 1.19010 + if (!points.is_sameY(2)) 1.19011 + throw CImgArgumentException("CImg<%s>::draw_polygon() : Given list of points is not valid.", 1.19012 + pixel_type()); 1.19013 + return _draw_polygon(points,points.size,color,opacity); 1.19014 + } 1.19015 + 1.19016 + //! Draw a filled polygon in the instance image. 1.19017 + template<typename t, typename tc> 1.19018 + CImg<T>& draw_polygon(const CImgList<t>& points, 1.19019 + const CImg<tc>& color, const float opacity=1) { 1.19020 + return draw_polygon(points,color.data,opacity); 1.19021 + } 1.19022 + 1.19023 + //! Draw a filled polygon in the instance image. 1.19024 + template<typename t, typename tc> 1.19025 + CImg<T>& draw_polygon(const CImg<t>& points, 1.19026 + const tc *const color, const float opacity=1) { 1.19027 + if (points.height<2) 1.19028 + throw CImgArgumentException("CImg<%s>::draw_polygon() : Given list of points is not valid.", 1.19029 + pixel_type()); 1.19030 + return _draw_polygon(points,points.width,color,opacity); 1.19031 + } 1.19032 + 1.19033 + //! Draw a filled polygon in the instance image. 1.19034 + template<typename t, typename tc> 1.19035 + CImg<T>& draw_polygon(const CImg<t>& points, 1.19036 + const CImg<tc>& color, const float opacity=1) { 1.19037 + return draw_polygon(points,color.data,opacity); 1.19038 + } 1.19039 + 1.19040 + // Inner routine for drawing an outlined polygon with generic point coordinates. 1.19041 + template<typename t, typename tc> 1.19042 + CImg<T>& _draw_polygon(const t& points, const unsigned int W, const unsigned int H, 1.19043 + const tc *const color, const float opacity, 1.19044 + const unsigned int pattern) { 1.19045 + if (is_empty() || !points || W<3) return *this; 1.19046 + bool ninit_hatch = true; 1.19047 + switch (H) { 1.19048 + case 0 : case 1 : 1.19049 + throw CImgArgumentException("CImg<%s>::draw_polygon() : Given list of points is not valid.", 1.19050 + pixel_type()); 1.19051 + case 2 : { 1.19052 + const int x0 = (int)points(0,0), y0 = (int)points(0,1); 1.19053 + int ox = x0, oy = y0; 1.19054 + for (unsigned int i = 1; i<W; ++i) { 1.19055 + const int x = (int)points(i,0), y = (int)points(i,1); 1.19056 + draw_line(ox,oy,x,y,color,opacity,pattern,ninit_hatch); 1.19057 + ninit_hatch = false; 1.19058 + ox = x; oy = y; 1.19059 + } 1.19060 + draw_line(ox,oy,x0,y0,color,opacity,pattern,false); 1.19061 + } break; 1.19062 + default : { 1.19063 + const int x0 = (int)points(0,0), y0 = (int)points(0,1), z0 = (int)points(0,2); 1.19064 + int ox = x0, oy = y0, oz = z0; 1.19065 + for (unsigned int i = 1; i<W; ++i) { 1.19066 + const int x = (int)points(i,0), y = (int)points(i,1), z = (int)points(i,2); 1.19067 + draw_line(ox,oy,oz,x,y,z,color,opacity,pattern,ninit_hatch); 1.19068 + ninit_hatch = false; 1.19069 + ox = x; oy = y; oz = z; 1.19070 + } 1.19071 + draw_line(ox,oy,oz,x0,y0,z0,color,opacity,pattern,false); 1.19072 + } 1.19073 + } 1.19074 + return *this; 1.19075 + } 1.19076 + 1.19077 + //! Draw a polygon outline. 1.19078 + template<typename t, typename tc> 1.19079 + CImg<T>& draw_polygon(const CImgList<t>& points, 1.19080 + const tc *const color, const float opacity, 1.19081 + const unsigned int pattern) { 1.19082 + unsigned int H = ~0U; cimglist_for(points,p) H = cimg::min(H,(unsigned int)(points[p].size())); 1.19083 + return _draw_polygon(points,points.size,H,color,opacity,pattern); 1.19084 + } 1.19085 + 1.19086 + //! Draw a polygon outline. 1.19087 + template<typename t, typename tc> 1.19088 + CImg<T>& draw_polygon(const CImgList<t>& points, 1.19089 + const CImg<tc>& color, const float opacity, 1.19090 + const unsigned int pattern) { 1.19091 + return draw_polygon(points,color.data,opacity,pattern); 1.19092 + } 1.19093 + 1.19094 + //! Draw a polygon outline. 1.19095 + template<typename t, typename tc> 1.19096 + CImg<T>& draw_polygon(const CImg<t>& points, 1.19097 + const tc *const color, const float opacity, 1.19098 + const unsigned int pattern) { 1.19099 + return _draw_polygon(points,points.width,points.height,color,opacity,pattern); 1.19100 + } 1.19101 + 1.19102 + //! Draw a polygon outline. 1.19103 + template<typename t, typename tc> 1.19104 + CImg<T>& draw_polygon(const CImg<t>& points, 1.19105 + const CImg<tc>& color, const float opacity, 1.19106 + const unsigned int pattern) { 1.19107 + return draw_polygon(points,color.data,opacity,pattern); 1.19108 + } 1.19109 + 1.19110 + //! Draw a cubic spline curve in the instance image. 1.19111 + /** 1.19112 + \param x0 X-coordinate of the starting curve point 1.19113 + \param y0 Y-coordinate of the starting curve point 1.19114 + \param u0 X-coordinate of the starting velocity 1.19115 + \param v0 Y-coordinate of the starting velocity 1.19116 + \param x1 X-coordinate of the ending curve point 1.19117 + \param y1 Y-coordinate of the ending curve point 1.19118 + \param u1 X-coordinate of the ending velocity 1.19119 + \param v1 Y-coordinate of the ending velocity 1.19120 + \param color Pointer to \c dimv() consecutive values of type \c T, defining the drawing color. 1.19121 + \param precision Curve drawing precision (optional). 1.19122 + \param opacity Drawing opacity (optional). 1.19123 + \param pattern An integer whose bits describe the line pattern (optional). 1.19124 + \param init_hatch If \c true, init hatch motif. 1.19125 + \note 1.19126 + - The curve is a 2D cubic Bezier spline, from the set of specified starting/ending points 1.19127 + and corresponding velocity vectors. 1.19128 + - The spline is drawn as a serie of connected segments. The \p precision parameter sets the 1.19129 + average number of pixels in each drawn segment. 1.19130 + - 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) } 1.19131 + 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 1.19132 + \e control points. 1.19133 + The starting and ending velocities (\p u0,\p v0) and (\p u1,\p v1) can be deduced easily from the control points as 1.19134 + \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). 1.19135 + \par Example: 1.19136 + \code 1.19137 + CImg<unsigned char> img(100,100,1,3,0); 1.19138 + const unsigned char color[] = { 255,255,255 }; 1.19139 + img.draw_spline(30,30,0,100,90,40,0,-100,color); 1.19140 + \endcode 1.19141 + **/ 1.19142 + template<typename tc> 1.19143 + CImg<T>& draw_spline(const int x0, const int y0, const float u0, const float v0, 1.19144 + const int x1, const int y1, const float u1, const float v1, 1.19145 + const tc *const color, const float opacity=1, 1.19146 + const float precision=4, const unsigned int pattern=~0U, 1.19147 + const bool init_hatch=true) { 1.19148 + if (is_empty()) return *this; 1.19149 + if (!color) 1.19150 + throw CImgArgumentException("CImg<%s>::draw_spline() : Specified color is (null)", 1.19151 + pixel_type()); 1.19152 + bool ninit_hatch = init_hatch; 1.19153 + const float 1.19154 + dx = (float)(x1 - x0), 1.19155 + dy = (float)(y1 - y0), 1.19156 + dmax = cimg::max(cimg::abs(dx),cimg::abs(dy)), 1.19157 + ax = -2*dx + u0 + u1, 1.19158 + bx = 3*dx - 2*u0 - u1, 1.19159 + ay = -2*dy + v0 + v1, 1.19160 + by = 3*dy - 2*v0 - v1, 1.19161 + xprecision = dmax>0?precision/dmax:1.0f, 1.19162 + tmax = 1 + (dmax>0?xprecision:0.0f); 1.19163 + int ox = x0, oy = y0; 1.19164 + for (float t = 0; t<tmax; t+=xprecision) { 1.19165 + const float 1.19166 + t2 = t*t, 1.19167 + t3 = t2*t; 1.19168 + const int 1.19169 + nx = (int)(ax*t3 + bx*t2 + u0*t + x0), 1.19170 + ny = (int)(ay*t3 + by*t2 + v0*t + y0); 1.19171 + draw_line(ox,oy,nx,ny,color,opacity,pattern,ninit_hatch); 1.19172 + ninit_hatch = false; 1.19173 + ox = nx; oy = ny; 1.19174 + } 1.19175 + return *this; 1.19176 + } 1.19177 + 1.19178 + //! Draw a cubic spline curve in the instance image. 1.19179 + template<typename tc> 1.19180 + CImg<T>& draw_spline(const int x0, const int y0, const float u0, const float v0, 1.19181 + const int x1, const int y1, const float u1, const float v1, 1.19182 + const CImg<tc>& color, const float opacity=1, 1.19183 + const float precision=4, const unsigned int pattern=~0U, 1.19184 + const bool init_hatch=true) { 1.19185 + return draw_spline(x0,y0,u0,v0,x1,y1,u1,v1,color.data,opacity,precision,pattern,init_hatch); 1.19186 + } 1.19187 + 1.19188 + //! Draw a cubic spline curve in the instance image (for volumetric images). 1.19189 + /** 1.19190 + \note 1.19191 + - Similar to CImg::draw_spline() for a 3D spline in a volumetric image. 1.19192 + **/ 1.19193 + template<typename tc> 1.19194 + CImg<T>& draw_spline(const int x0, const int y0, const int z0, const float u0, const float v0, const float w0, 1.19195 + const int x1, const int y1, const int z1, const float u1, const float v1, const float w1, 1.19196 + const tc *const color, const float opacity=1, 1.19197 + const float precision=4, const unsigned int pattern=~0U, 1.19198 + const bool init_hatch=true) { 1.19199 + if (is_empty()) return *this; 1.19200 + if (!color) 1.19201 + throw CImgArgumentException("CImg<%s>::draw_spline() : Specified color is (null)", 1.19202 + pixel_type()); 1.19203 + bool ninit_hatch = init_hatch; 1.19204 + const float 1.19205 + dx = (float)(x1 - x0), 1.19206 + dy = (float)(y1 - y0), 1.19207 + dz = (float)(z1 - z0), 1.19208 + dmax = cimg::max(cimg::abs(dx),cimg::abs(dy),cimg::abs(dz)), 1.19209 + ax = -2*dx + u0 + u1, 1.19210 + bx = 3*dx - 2*u0 - u1, 1.19211 + ay = -2*dy + v0 + v1, 1.19212 + by = 3*dy - 2*v0 - v1, 1.19213 + az = -2*dz + w0 + w1, 1.19214 + bz = 3*dz - 2*w0 - w1, 1.19215 + xprecision = dmax>0?precision/dmax:1.0f, 1.19216 + tmax = 1 + (dmax>0?xprecision:0.0f); 1.19217 + int ox = x0, oy = y0, oz = z0; 1.19218 + for (float t = 0; t<tmax; t+=xprecision) { 1.19219 + const float 1.19220 + t2 = t*t, 1.19221 + t3 = t2*t; 1.19222 + const int 1.19223 + nx = (int)(ax*t3 + bx*t2 + u0*t + x0), 1.19224 + ny = (int)(ay*t3 + by*t2 + v0*t + y0), 1.19225 + nz = (int)(az*t3 + bz*t2 + w0*t + z0); 1.19226 + draw_line(ox,oy,oz,nx,ny,nz,color,opacity,pattern,ninit_hatch); 1.19227 + ninit_hatch = false; 1.19228 + ox = nx; oy = ny; oz = nz; 1.19229 + } 1.19230 + return *this; 1.19231 + } 1.19232 + 1.19233 + //! Draw a cubic spline curve in the instance image (for volumetric images). 1.19234 + template<typename tc> 1.19235 + CImg<T>& draw_spline(const int x0, const int y0, const int z0, const float u0, const float v0, const float w0, 1.19236 + const int x1, const int y1, const int z1, const float u1, const float v1, const float w1, 1.19237 + const CImg<tc>& color, const float opacity=1, 1.19238 + const float precision=4, const unsigned int pattern=~0U, 1.19239 + const bool init_hatch=true) { 1.19240 + return draw_spline(x0,y0,z0,u0,v0,w0,x1,y1,z1,u1,v1,w1,color.data,opacity,precision,pattern,init_hatch); 1.19241 + } 1.19242 + 1.19243 + //! Draw a cubic spline curve in the instance image. 1.19244 + /** 1.19245 + \param x0 X-coordinate of the starting curve point 1.19246 + \param y0 Y-coordinate of the starting curve point 1.19247 + \param u0 X-coordinate of the starting velocity 1.19248 + \param v0 Y-coordinate of the starting velocity 1.19249 + \param x1 X-coordinate of the ending curve point 1.19250 + \param y1 Y-coordinate of the ending curve point 1.19251 + \param u1 X-coordinate of the ending velocity 1.19252 + \param v1 Y-coordinate of the ending velocity 1.19253 + \param texture Texture image defining line pixel colors. 1.19254 + \param tx0 X-coordinate of the starting texture point. 1.19255 + \param ty0 Y-coordinate of the starting texture point. 1.19256 + \param tx1 X-coordinate of the ending texture point. 1.19257 + \param ty1 Y-coordinate of the ending texture point. 1.19258 + \param precision Curve drawing precision (optional). 1.19259 + \param opacity Drawing opacity (optional). 1.19260 + \param pattern An integer whose bits describe the line pattern (optional). 1.19261 + \param init_hatch if \c true, reinit hatch motif. 1.19262 + **/ 1.19263 + template<typename t> 1.19264 + CImg<T>& draw_spline(const int x0, const int y0, const float u0, const float v0, 1.19265 + const int x1, const int y1, const float u1, const float v1, 1.19266 + const CImg<t>& texture, 1.19267 + const int tx0, const int ty0, const int tx1, const int ty1, 1.19268 + const float opacity=1, 1.19269 + const float precision=4, const unsigned int pattern=~0U, 1.19270 + const bool init_hatch=true) { 1.19271 + if (is_empty()) return *this; 1.19272 + if (!texture || texture.dim<dim) 1.19273 + throw CImgArgumentException("CImg<%s>::draw_line() : Specified texture (%u,%u,%u,%u,%p) is not a valid argument.", 1.19274 + pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data); 1.19275 + 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); 1.19276 + bool ninit_hatch = true; 1.19277 + const float 1.19278 + dx = (float)(x1 - x0), 1.19279 + dy = (float)(y1 - y0), 1.19280 + dmax = cimg::max(cimg::abs(dx),cimg::abs(dy)), 1.19281 + ax = -2*dx + u0 + u1, 1.19282 + bx = 3*dx - 2*u0 - u1, 1.19283 + ay = -2*dy + v0 + v1, 1.19284 + by = 3*dy - 2*v0 - v1, 1.19285 + xprecision = dmax>0?precision/dmax:1.0f, 1.19286 + tmax = 1 + (dmax>0?xprecision:0.0f); 1.19287 + int ox = x0, oy = y0, otx = tx0, oty = ty0; 1.19288 + for (float t1 = 0; t1<tmax; t1+=xprecision) { 1.19289 + const float 1.19290 + t2 = t1*t1, 1.19291 + t3 = t2*t1; 1.19292 + const int 1.19293 + nx = (int)(ax*t3 + bx*t2 + u0*t1 + x0), 1.19294 + ny = (int)(ay*t3 + by*t2 + v0*t1 + y0), 1.19295 + ntx = tx0 + (int)((tx1-tx0)*t1/tmax), 1.19296 + nty = ty0 + (int)((ty1-ty0)*t1/tmax); 1.19297 + draw_line(ox,oy,nx,ny,texture,otx,oty,ntx,nty,opacity,pattern,ninit_hatch); 1.19298 + ninit_hatch = false; 1.19299 + ox = nx; oy = ny; otx = ntx; oty = nty; 1.19300 + } 1.19301 + return *this; 1.19302 + } 1.19303 + 1.19304 + // Draw a set of connected spline curves in the instance image (internal). 1.19305 + template<typename tp, typename tt, typename tc> 1.19306 + CImg<T>& _draw_spline(const tp& points, const tt& tangents, const unsigned int W, const unsigned int H, 1.19307 + const tc *const color, const float opacity, 1.19308 + const bool close_set, const float precision, 1.19309 + const unsigned int pattern, const bool init_hatch) { 1.19310 + if (is_empty() || !points || !tangents || W<2) return *this; 1.19311 + bool ninit_hatch = init_hatch; 1.19312 + switch (H) { 1.19313 + case 0 : case 1 : 1.19314 + throw CImgArgumentException("CImg<%s>::draw_spline() : Given list of points or tangents is not valid.", 1.19315 + pixel_type()); 1.19316 + case 2 : { 1.19317 + const int x0 = (int)points(0,0), y0 = (int)points(0,1); 1.19318 + const float u0 = (float)tangents(0,0), v0 = (float)tangents(0,1); 1.19319 + int ox = x0, oy = y0; 1.19320 + float ou = u0, ov = v0; 1.19321 + for (unsigned int i = 1; i<W; ++i) { 1.19322 + const int x = (int)points(i,0), y = (int)points(i,1); 1.19323 + const float u = (float)tangents(i,0), v = (float)tangents(i,1); 1.19324 + draw_spline(ox,oy,ou,ov,x,y,u,v,color,precision,opacity,pattern,ninit_hatch); 1.19325 + ninit_hatch = false; 1.19326 + ox = x; oy = y; ou = u; ov = v; 1.19327 + } 1.19328 + if (close_set) draw_spline(ox,oy,ou,ov,x0,y0,u0,v0,color,precision,opacity,pattern,false); 1.19329 + } break; 1.19330 + default : { 1.19331 + const int x0 = (int)points(0,0), y0 = (int)points(0,1), z0 = (int)points(0,2); 1.19332 + const float u0 = (float)tangents(0,0), v0 = (float)tangents(0,1), w0 = (float)tangents(0,2); 1.19333 + int ox = x0, oy = y0, oz = z0; 1.19334 + float ou = u0, ov = v0, ow = w0; 1.19335 + for (unsigned int i = 1; i<W; ++i) { 1.19336 + const int x = (int)points(i,0), y = (int)points(i,1), z = (int)points(i,2); 1.19337 + const float u = (float)tangents(i,0), v = (float)tangents(i,1), w = (float)tangents(i,2); 1.19338 + draw_spline(ox,oy,oz,ou,ov,ow,x,y,z,u,v,w,color,opacity,pattern,ninit_hatch); 1.19339 + ninit_hatch = false; 1.19340 + ox = x; oy = y; oz = z; ou = u; ov = v; ow = w; 1.19341 + } 1.19342 + if (close_set) draw_spline(ox,oy,oz,ou,ov,ow,x0,y0,z0,u0,v0,w0,color,precision,opacity,pattern,false); 1.19343 + } 1.19344 + } 1.19345 + return *this; 1.19346 + } 1.19347 + 1.19348 + // Draw a set of connected spline curves in the instance image (internal). 1.19349 + template<typename tp, typename tc> 1.19350 + CImg<T>& _draw_spline(const tp& points, const unsigned int W, const unsigned int H, 1.19351 + const tc *const color, const float opacity, 1.19352 + const bool close_set, const float precision, 1.19353 + const unsigned int pattern, const bool init_hatch) { 1.19354 + if (is_empty() || !points || W<2) return *this; 1.19355 + CImg<Tfloat> tangents; 1.19356 + switch (H) { 1.19357 + case 0 : case 1 : 1.19358 + throw CImgArgumentException("CImg<%s>::draw_spline() : Given list of points or tangents is not valid.", 1.19359 + pixel_type()); 1.19360 + case 2 : { 1.19361 + tangents.assign(W,H); 1.19362 + for (unsigned int p = 0; p<W; ++p) { 1.19363 + const unsigned int 1.19364 + p0 = close_set?(p+W-1)%W:(p?p-1:0), 1.19365 + p1 = close_set?(p+1)%W:(p+1<W?p+1:p); 1.19366 + const float 1.19367 + x = (float)points(p,0), 1.19368 + y = (float)points(p,1), 1.19369 + x0 = (float)points(p0,0), 1.19370 + y0 = (float)points(p0,1), 1.19371 + x1 = (float)points(p1,0), 1.19372 + y1 = (float)points(p1,1), 1.19373 + u0 = x - x0, 1.19374 + v0 = y - y0, 1.19375 + n0 = 1e-8f + (float)cimg_std::sqrt(u0*u0 + v0*v0), 1.19376 + u1 = x1 - x, 1.19377 + v1 = y1 - y, 1.19378 + n1 = 1e-8f + (float)cimg_std::sqrt(u1*u1 + v1*v1), 1.19379 + u = u0/n0 + u1/n1, 1.19380 + v = v0/n0 + v1/n1, 1.19381 + n = 1e-8f + (float)cimg_std::sqrt(u*u + v*v), 1.19382 + fact = 0.5f*(n0 + n1); 1.19383 + tangents(p,0) = (Tfloat)(fact*u/n); 1.19384 + tangents(p,1) = (Tfloat)(fact*v/n); 1.19385 + } 1.19386 + } break; 1.19387 + default : { 1.19388 + tangents.assign(W,H); 1.19389 + for (unsigned int p = 0; p<W; ++p) { 1.19390 + const unsigned int 1.19391 + p0 = close_set?(p+W-1)%W:(p?p-1:0), 1.19392 + p1 = close_set?(p+1)%W:(p+1<W?p+1:p); 1.19393 + const float 1.19394 + x = (float)points(p,0), 1.19395 + y = (float)points(p,1), 1.19396 + z = (float)points(p,2), 1.19397 + x0 = (float)points(p0,0), 1.19398 + y0 = (float)points(p0,1), 1.19399 + z0 = (float)points(p0,2), 1.19400 + x1 = (float)points(p1,0), 1.19401 + y1 = (float)points(p1,1), 1.19402 + z1 = (float)points(p1,2), 1.19403 + u0 = x - x0, 1.19404 + v0 = y - y0, 1.19405 + w0 = z - z0, 1.19406 + n0 = 1e-8f + (float)cimg_std::sqrt(u0*u0 + v0*v0 + w0*w0), 1.19407 + u1 = x1 - x, 1.19408 + v1 = y1 - y, 1.19409 + w1 = z1 - z, 1.19410 + n1 = 1e-8f + (float)cimg_std::sqrt(u1*u1 + v1*v1 + w1*w1), 1.19411 + u = u0/n0 + u1/n1, 1.19412 + v = v0/n0 + v1/n1, 1.19413 + w = w0/n0 + w1/n1, 1.19414 + n = 1e-8f + (float)cimg_std::sqrt(u*u + v*v + w*w), 1.19415 + fact = 0.5f*(n0 + n1); 1.19416 + tangents(p,0) = (Tfloat)(fact*u/n); 1.19417 + tangents(p,1) = (Tfloat)(fact*v/n); 1.19418 + tangents(p,2) = (Tfloat)(fact*w/n); 1.19419 + } 1.19420 + } 1.19421 + } 1.19422 + return _draw_spline(points,tangents,W,H,color,opacity,close_set,precision,pattern,init_hatch); 1.19423 + } 1.19424 + 1.19425 + //! Draw a set of consecutive colored splines in the instance image. 1.19426 + template<typename tp, typename tt, typename tc> 1.19427 + CImg<T>& draw_spline(const CImgList<tp>& points, const CImgList<tt>& tangents, 1.19428 + const tc *const color, const float opacity=1, 1.19429 + const bool close_set=false, const float precision=4, 1.19430 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.19431 + unsigned int H = ~0U; cimglist_for(points,p) H = cimg::min(H,(unsigned int)(points[p].size()),(unsigned int)(tangents[p].size())); 1.19432 + return _draw_spline(points,tangents,color,opacity,close_set,precision,pattern,init_hatch,points.size,H); 1.19433 + } 1.19434 + 1.19435 + //! Draw a set of consecutive colored splines in the instance image. 1.19436 + template<typename tp, typename tt, typename tc> 1.19437 + CImg<T>& draw_spline(const CImgList<tp>& points, const CImgList<tt>& tangents, 1.19438 + const CImg<tc>& color, const float opacity=1, 1.19439 + const bool close_set=false, const float precision=4, 1.19440 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.19441 + return draw_spline(points,tangents,color.data,opacity,close_set,precision,pattern,init_hatch); 1.19442 + } 1.19443 + 1.19444 + //! Draw a set of consecutive colored splines in the instance image. 1.19445 + template<typename tp, typename tt, typename tc> 1.19446 + CImg<T>& draw_spline(const CImg<tp>& points, const CImg<tt>& tangents, 1.19447 + const tc *const color, const float opacity=1, 1.19448 + const bool close_set=false, const float precision=4, 1.19449 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.19450 + return _draw_spline(points,tangents,color,opacity,close_set,precision,pattern,init_hatch,points.width,points.height); 1.19451 + } 1.19452 + 1.19453 + //! Draw a set of consecutive colored splines in the instance image. 1.19454 + template<typename tp, typename tt, typename tc> 1.19455 + CImg<T>& draw_spline(const CImg<tp>& points, const CImg<tt>& tangents, 1.19456 + const CImg<tc>& color, const float opacity=1, 1.19457 + const bool close_set=false, const float precision=4, 1.19458 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.19459 + return draw_spline(points,tangents,color.data,opacity,close_set,precision,pattern,init_hatch); 1.19460 + } 1.19461 + 1.19462 + //! Draw a set of consecutive colored splines in the instance image. 1.19463 + template<typename t, typename tc> 1.19464 + CImg<T>& draw_spline(const CImgList<t>& points, 1.19465 + const tc *const color, const float opacity=1, 1.19466 + const bool close_set=false, const float precision=4, 1.19467 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.19468 + unsigned int H = ~0U; 1.19469 + cimglist_for(points,p) { const unsigned int s = points[p].size(); if (s<H) H = s; } 1.19470 + return _draw_spline(points,color,opacity,close_set,precision,pattern,init_hatch,points.size,H); 1.19471 + } 1.19472 + 1.19473 + //! Draw a set of consecutive colored splines in the instance image. 1.19474 + template<typename t, typename tc> 1.19475 + CImg<T>& draw_spline(const CImgList<t>& points, 1.19476 + CImg<tc>& color, const float opacity=1, 1.19477 + const bool close_set=false, const float precision=4, 1.19478 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.19479 + return draw_spline(points,color.data,opacity,close_set,precision,pattern,init_hatch); 1.19480 + } 1.19481 + 1.19482 + //! Draw a set of consecutive colored lines in the instance image. 1.19483 + template<typename t, typename tc> 1.19484 + CImg<T>& draw_spline(const CImg<t>& points, 1.19485 + const tc *const color, const float opacity=1, 1.19486 + const bool close_set=false, const float precision=4, 1.19487 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.19488 + return _draw_spline(points,color,opacity,close_set,precision,pattern,init_hatch,points.width,points.height); 1.19489 + } 1.19490 + 1.19491 + //! Draw a set of consecutive colored lines in the instance image. 1.19492 + template<typename t, typename tc> 1.19493 + CImg<T>& draw_spline(const CImg<t>& points, 1.19494 + const CImg<tc>& color, const float opacity=1, 1.19495 + const bool close_set=false, const float precision=4, 1.19496 + const unsigned int pattern=~0U, const bool init_hatch=true) { 1.19497 + return draw_spline(points,color.data,opacity,close_set,precision,pattern,init_hatch); 1.19498 + } 1.19499 + 1.19500 + //! Draw a colored arrow in the instance image. 1.19501 + /** 1.19502 + \param x0 X-coordinate of the starting arrow point (tail). 1.19503 + \param y0 Y-coordinate of the starting arrow point (tail). 1.19504 + \param x1 X-coordinate of the ending arrow point (head). 1.19505 + \param y1 Y-coordinate of the ending arrow point (head). 1.19506 + \param color Pointer to \c dimv() consecutive values of type \c T, defining the drawing color. 1.19507 + \param angle Aperture angle of the arrow head (optional). 1.19508 + \param length Length of the arrow head. If negative, describes a percentage of the arrow length (optional). 1.19509 + \param opacity Drawing opacity (optional). 1.19510 + \param pattern An integer whose bits describe the line pattern (optional). 1.19511 + \note 1.19512 + - Clipping is supported. 1.19513 + **/ 1.19514 + template<typename tc> 1.19515 + CImg<T>& draw_arrow(const int x0, const int y0, 1.19516 + const int x1, const int y1, 1.19517 + const tc *const color, const float opacity=1, 1.19518 + const float angle=30, const float length=-10, 1.19519 + const unsigned int pattern=~0U) { 1.19520 + if (is_empty()) return *this; 1.19521 + const float u = (float)(x0 - x1), v = (float)(y0 - y1), sq = u*u + v*v, 1.19522 + deg = (float)(angle*cimg::valuePI/180), ang = (sq>0)?(float)cimg_std::atan2(v,u):0.0f, 1.19523 + l = (length>=0)?length:-length*(float)cimg_std::sqrt(sq)/100; 1.19524 + if (sq>0) { 1.19525 + const float 1.19526 + cl = (float)cimg_std::cos(ang - deg), sl = (float)cimg_std::sin(ang - deg), 1.19527 + cr = (float)cimg_std::cos(ang + deg), sr = (float)cimg_std::sin(ang + deg); 1.19528 + const int 1.19529 + xl = x1 + (int)(l*cl), yl = y1 + (int)(l*sl), 1.19530 + xr = x1 + (int)(l*cr), yr = y1 + (int)(l*sr), 1.19531 + xc = x1 + (int)((l+1)*(cl+cr))/2, yc = y1 + (int)((l+1)*(sl+sr))/2; 1.19532 + draw_line(x0,y0,xc,yc,color,opacity,pattern).draw_triangle(x1,y1,xl,yl,xr,yr,color,opacity); 1.19533 + } else draw_point(x0,y0,color,opacity); 1.19534 + return *this; 1.19535 + } 1.19536 + 1.19537 + //! Draw a colored arrow in the instance image. 1.19538 + template<typename tc> 1.19539 + CImg<T>& draw_arrow(const int x0, const int y0, 1.19540 + const int x1, const int y1, 1.19541 + const CImg<tc>& color, const float opacity=1, 1.19542 + const float angle=30, const float length=-10, 1.19543 + const unsigned int pattern=~0U) { 1.19544 + return draw_arrow(x0,y0,x1,y1,color.data,opacity,angle,length,pattern); 1.19545 + } 1.19546 + 1.19547 + //! Draw an image. 1.19548 + /** 1.19549 + \param sprite Sprite image. 1.19550 + \param x0 X-coordinate of the sprite position. 1.19551 + \param y0 Y-coordinate of the sprite position. 1.19552 + \param z0 Z-coordinate of the sprite position. 1.19553 + \param v0 V-coordinate of the sprite position. 1.19554 + \param opacity Drawing opacity (optional). 1.19555 + \note 1.19556 + - Clipping is supported. 1.19557 + **/ 1.19558 + template<typename t> 1.19559 + CImg<T>& draw_image(const int x0, const int y0, const int z0, const int v0, 1.19560 + const CImg<t>& sprite, const float opacity=1) { 1.19561 + if (is_empty()) return *this; 1.19562 + if (!sprite) 1.19563 + throw CImgArgumentException("CImg<%s>::draw_image() : Specified sprite image (%u,%u,%u,%u,%p) is empty.", 1.19564 + pixel_type(),sprite.width,sprite.height,sprite.depth,sprite.dim,sprite.data); 1.19565 + if (is_overlapped(sprite)) return draw_image(x0,y0,z0,v0,+sprite,opacity); 1.19566 + const bool bx = (x0<0), by = (y0<0), bz = (z0<0), bv = (v0<0); 1.19567 + const int 1.19568 + lX = sprite.dimx() - (x0 + sprite.dimx()>dimx()?x0 + sprite.dimx() - dimx():0) + (bx?x0:0), 1.19569 + lY = sprite.dimy() - (y0 + sprite.dimy()>dimy()?y0 + sprite.dimy() - dimy():0) + (by?y0:0), 1.19570 + lZ = sprite.dimz() - (z0 + sprite.dimz()>dimz()?z0 + sprite.dimz() - dimz():0) + (bz?z0:0), 1.19571 + lV = sprite.dimv() - (v0 + sprite.dimv()>dimv()?v0 + sprite.dimv() - dimv():0) + (bv?v0:0); 1.19572 + const t 1.19573 + *ptrs = sprite.data - 1.19574 + (bx?x0:0) - 1.19575 + (by?y0*sprite.dimx():0) - 1.19576 + (bz?z0*sprite.dimx()*sprite.dimy():0) - 1.19577 + (bv?v0*sprite.dimx()*sprite.dimy()*sprite.dimz():0); 1.19578 + const unsigned int 1.19579 + offX = width - lX, soffX = sprite.width - lX, 1.19580 + offY = width*(height - lY), soffY = sprite.width*(sprite.height - lY), 1.19581 + offZ = width*height*(depth - lZ), soffZ = sprite.width*sprite.height*(sprite.depth - lZ); 1.19582 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.19583 + if (lX>0 && lY>0 && lZ>0 && lV>0) { 1.19584 + T *ptrd = ptr(x0<0?0:x0,y0<0?0:y0,z0<0?0:z0,v0<0?0:v0); 1.19585 + for (int v = 0; v<lV; ++v) { 1.19586 + for (int z = 0; z<lZ; ++z) { 1.19587 + for (int y = 0; y<lY; ++y) { 1.19588 + if (opacity>=1) for (int x = 0; x<lX; ++x) *(ptrd++) = (T)*(ptrs++); 1.19589 + else for (int x = 0; x<lX; ++x) { *ptrd = (T)(nopacity*(*(ptrs++)) + *ptrd*copacity); ++ptrd; } 1.19590 + ptrd+=offX; ptrs+=soffX; 1.19591 + } 1.19592 + ptrd+=offY; ptrs+=soffY; 1.19593 + } 1.19594 + ptrd+=offZ; ptrs+=soffZ; 1.19595 + } 1.19596 + } 1.19597 + return *this; 1.19598 + } 1.19599 + 1.19600 +#ifndef cimg_use_visualcpp6 1.19601 + // Otimized version (internal). 1.19602 + CImg<T>& draw_image(const int x0, const int y0, const int z0, const int v0, 1.19603 + const CImg<T>& sprite, const float opacity=1) { 1.19604 + if (is_empty()) return *this; 1.19605 + if (!sprite) 1.19606 + throw CImgArgumentException("CImg<%s>::draw_image() : Specified sprite image (%u,%u,%u,%u,%p) is empty.", 1.19607 + pixel_type(),sprite.width,sprite.height,sprite.depth,sprite.dim,sprite.data); 1.19608 + if (is_overlapped(sprite)) return draw_image(x0,y0,z0,v0,+sprite,opacity); 1.19609 + const bool bx = (x0<0), by = (y0<0), bz = (z0<0), bv = (v0<0); 1.19610 + const int 1.19611 + lX = sprite.dimx() - (x0 + sprite.dimx()>dimx()?x0 + sprite.dimx() - dimx():0) + (bx?x0:0), 1.19612 + lY = sprite.dimy() - (y0 + sprite.dimy()>dimy()?y0 + sprite.dimy() - dimy():0) + (by?y0:0), 1.19613 + lZ = sprite.dimz() - (z0 + sprite.dimz()>dimz()?z0 + sprite.dimz() - dimz():0) + (bz?z0:0), 1.19614 + lV = sprite.dimv() - (v0 + sprite.dimv()>dimv()?v0 + sprite.dimv() - dimv():0) + (bv?v0:0); 1.19615 + const T 1.19616 + *ptrs = sprite.data - 1.19617 + (bx?x0:0) - 1.19618 + (by?y0*sprite.dimx():0) - 1.19619 + (bz?z0*sprite.dimx()*sprite.dimy():0) - 1.19620 + (bv?v0*sprite.dimx()*sprite.dimy()*sprite.dimz():0); 1.19621 + const unsigned int 1.19622 + offX = width - lX, soffX = sprite.width - lX, 1.19623 + offY = width*(height - lY), soffY = sprite.width*(sprite.height - lY), 1.19624 + offZ = width*height*(depth - lZ), soffZ = sprite.width*sprite.height*(sprite.depth - lZ), 1.19625 + slX = lX*sizeof(T); 1.19626 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.19627 + if (lX>0 && lY>0 && lZ>0 && lV>0) { 1.19628 + T *ptrd = ptr(x0<0?0:x0,y0<0?0:y0,z0<0?0:z0,v0<0?0:v0); 1.19629 + for (int v = 0; v<lV; ++v) { 1.19630 + for (int z = 0; z<lZ; ++z) { 1.19631 + if (opacity>=1) for (int y = 0; y<lY; ++y) { cimg_std::memcpy(ptrd,ptrs,slX); ptrd+=width; ptrs+=sprite.width; } 1.19632 + else for (int y = 0; y<lY; ++y) { 1.19633 + for (int x = 0; x<lX; ++x) { *ptrd = (T)(nopacity*(*(ptrs++)) + *ptrd*copacity); ++ptrd; } 1.19634 + ptrd+=offX; ptrs+=soffX; 1.19635 + } 1.19636 + ptrd+=offY; ptrs+=soffY; 1.19637 + } 1.19638 + ptrd+=offZ; ptrs+=soffZ; 1.19639 + } 1.19640 + } 1.19641 + return *this; 1.19642 + } 1.19643 +#endif 1.19644 + 1.19645 + //! Draw an image. 1.19646 + template<typename t> 1.19647 + CImg<T>& draw_image(const int x0, const int y0, const int z0, 1.19648 + const CImg<t>& sprite, const float opacity=1) { 1.19649 + return draw_image(x0,y0,z0,0,sprite,opacity); 1.19650 + } 1.19651 + 1.19652 + //! Draw an image. 1.19653 + template<typename t> 1.19654 + CImg<T>& draw_image(const int x0, const int y0, 1.19655 + const CImg<t>& sprite, const float opacity=1) { 1.19656 + return draw_image(x0,y0,0,sprite,opacity); 1.19657 + } 1.19658 + 1.19659 + //! Draw an image. 1.19660 + template<typename t> 1.19661 + CImg<T>& draw_image(const int x0, 1.19662 + const CImg<t>& sprite, const float opacity=1) { 1.19663 + return draw_image(x0,0,sprite,opacity); 1.19664 + } 1.19665 + 1.19666 + //! Draw an image. 1.19667 + template<typename t> 1.19668 + CImg<T>& draw_image(const CImg<t>& sprite, const float opacity=1) { 1.19669 + return draw_image(0,sprite,opacity); 1.19670 + } 1.19671 + 1.19672 + //! Draw a sprite image in the instance image (masked version). 1.19673 + /** 1.19674 + \param sprite Sprite image. 1.19675 + \param mask Mask image. 1.19676 + \param x0 X-coordinate of the sprite position in the instance image. 1.19677 + \param y0 Y-coordinate of the sprite position in the instance image. 1.19678 + \param z0 Z-coordinate of the sprite position in the instance image. 1.19679 + \param v0 V-coordinate of the sprite position in the instance image. 1.19680 + \param mask_valmax Maximum pixel value of the mask image \c mask (optional). 1.19681 + \param opacity Drawing opacity. 1.19682 + \note 1.19683 + - Pixel values of \c mask set the opacity of the corresponding pixels in \c sprite. 1.19684 + - Clipping is supported. 1.19685 + - Dimensions along x,y and z of \p sprite and \p mask must be the same. 1.19686 + **/ 1.19687 + template<typename ti, typename tm> 1.19688 + CImg<T>& draw_image(const int x0, const int y0, const int z0, const int v0, 1.19689 + const CImg<ti>& sprite, const CImg<tm>& mask, const float opacity=1, 1.19690 + const float mask_valmax=1) { 1.19691 + if (is_empty()) return *this; 1.19692 + if (!sprite) 1.19693 + throw CImgArgumentException("CImg<%s>::draw_image() : Specified sprite image (%u,%u,%u,%u,%p) is empty.", 1.19694 + pixel_type(),sprite.width,sprite.height,sprite.depth,sprite.dim,sprite.data); 1.19695 + if (!mask) 1.19696 + throw CImgArgumentException("CImg<%s>::draw_image() : Specified mask image (%u,%u,%u,%u,%p) is empty.", 1.19697 + pixel_type(),mask.width,mask.height,mask.depth,mask.dim,mask.data); 1.19698 + if (is_overlapped(sprite)) return draw_image(x0,y0,z0,v0,+sprite,mask,opacity,mask_valmax); 1.19699 + if (is_overlapped(mask)) return draw_image(x0,y0,z0,v0,sprite,+mask,opacity,mask_valmax); 1.19700 + if (mask.width!=sprite.width || mask.height!=sprite.height || mask.depth!=sprite.depth) 1.19701 + throw CImgArgumentException("CImg<%s>::draw_image() : Mask dimension is (%u,%u,%u,%u), while sprite is (%u,%u,%u,%u)", 1.19702 + pixel_type(),mask.width,mask.height,mask.depth,mask.dim,sprite.width,sprite.height,sprite.depth,sprite.dim); 1.19703 + const bool bx = (x0<0), by = (y0<0), bz = (z0<0), bv = (v0<0); 1.19704 + const int 1.19705 + lX = sprite.dimx() - (x0 + sprite.dimx()>dimx()?x0 + sprite.dimx() - dimx():0) + (bx?x0:0), 1.19706 + lY = sprite.dimy() - (y0 + sprite.dimy()>dimy()?y0 + sprite.dimy() - dimy():0) + (by?y0:0), 1.19707 + lZ = sprite.dimz() - (z0 + sprite.dimz()>dimz()?z0 + sprite.dimz() - dimz():0) + (bz?z0:0), 1.19708 + lV = sprite.dimv() - (v0 + sprite.dimv()>dimv()?v0 + sprite.dimv() - dimv():0) + (bv?v0:0); 1.19709 + const int 1.19710 + coff = -(bx?x0:0)-(by?y0*mask.dimx():0)-(bz?z0*mask.dimx()*mask.dimy():0)-(bv?v0*mask.dimx()*mask.dimy()*mask.dimz():0), 1.19711 + ssize = mask.dimx()*mask.dimy()*mask.dimz(); 1.19712 + const ti *ptrs = sprite.data + coff; 1.19713 + const tm *ptrm = mask.data + coff; 1.19714 + const unsigned int 1.19715 + offX = width - lX, soffX = sprite.width - lX, 1.19716 + offY = width*(height - lY), soffY = sprite.width*(sprite.height - lY), 1.19717 + offZ = width*height*(depth - lZ), soffZ = sprite.width*sprite.height*(sprite.depth - lZ); 1.19718 + if (lX>0 && lY>0 && lZ>0 && lV>0) { 1.19719 + T *ptrd = ptr(x0<0?0:x0,y0<0?0:y0,z0<0?0:z0,v0<0?0:v0); 1.19720 + for (int v = 0; v<lV; ++v) { 1.19721 + ptrm = mask.data + (ptrm - mask.data)%ssize; 1.19722 + for (int z = 0; z<lZ; ++z) { 1.19723 + for (int y = 0; y<lY; ++y) { 1.19724 + for (int x=0; x<lX; ++x) { 1.19725 + const float mopacity = (float)(*(ptrm++)*opacity), 1.19726 + nopacity = cimg::abs(mopacity), copacity = mask_valmax - cimg::max(mopacity,0); 1.19727 + *ptrd = (T)((nopacity*(*(ptrs++)) + *ptrd*copacity)/mask_valmax); 1.19728 + ++ptrd; 1.19729 + } 1.19730 + ptrd+=offX; ptrs+=soffX; ptrm+=soffX; 1.19731 + } 1.19732 + ptrd+=offY; ptrs+=soffY; ptrm+=soffY; 1.19733 + } 1.19734 + ptrd+=offZ; ptrs+=soffZ; ptrm+=soffZ; 1.19735 + } 1.19736 + } 1.19737 + return *this; 1.19738 + } 1.19739 + 1.19740 + //! Draw an image. 1.19741 + template<typename ti, typename tm> 1.19742 + CImg<T>& draw_image(const int x0, const int y0, const int z0, 1.19743 + const CImg<ti>& sprite, const CImg<tm>& mask, const float opacity=1, 1.19744 + const float mask_valmax=1) { 1.19745 + return draw_image(x0,y0,z0,0,sprite,mask,opacity,mask_valmax); 1.19746 + } 1.19747 + 1.19748 + //! Draw an image. 1.19749 + template<typename ti, typename tm> 1.19750 + CImg<T>& draw_image(const int x0, const int y0, 1.19751 + const CImg<ti>& sprite, const CImg<tm>& mask, const float opacity=1, 1.19752 + const float mask_valmax=1) { 1.19753 + return draw_image(x0,y0,0,sprite,mask,opacity,mask_valmax); 1.19754 + } 1.19755 + 1.19756 + //! Draw an image. 1.19757 + template<typename ti, typename tm> 1.19758 + CImg<T>& draw_image(const int x0, 1.19759 + const CImg<ti>& sprite, const CImg<tm>& mask, const float opacity=1, 1.19760 + const float mask_valmax=1) { 1.19761 + return draw_image(x0,0,sprite,mask,opacity,mask_valmax); 1.19762 + } 1.19763 + 1.19764 + //! Draw an image. 1.19765 + template<typename ti, typename tm> 1.19766 + CImg<T>& draw_image(const CImg<ti>& sprite, const CImg<tm>& mask, const float opacity=1, 1.19767 + const float mask_valmax=1) { 1.19768 + return draw_image(0,sprite,mask,opacity,mask_valmax); 1.19769 + } 1.19770 + 1.19771 + //! Draw a 4D filled rectangle in the instance image, at coordinates (\c x0,\c y0,\c z0,\c v0)-(\c x1,\c y1,\c z1,\c v1). 1.19772 + /** 1.19773 + \param x0 X-coordinate of the upper-left rectangle corner. 1.19774 + \param y0 Y-coordinate of the upper-left rectangle corner. 1.19775 + \param z0 Z-coordinate of the upper-left rectangle corner. 1.19776 + \param v0 V-coordinate of the upper-left rectangle corner. 1.19777 + \param x1 X-coordinate of the lower-right rectangle corner. 1.19778 + \param y1 Y-coordinate of the lower-right rectangle corner. 1.19779 + \param z1 Z-coordinate of the lower-right rectangle corner. 1.19780 + \param v1 V-coordinate of the lower-right rectangle corner. 1.19781 + \param val Scalar value used to fill the rectangle area. 1.19782 + \param opacity Drawing opacity (optional). 1.19783 + \note 1.19784 + - Clipping is supported. 1.19785 + **/ 1.19786 + CImg<T>& draw_rectangle(const int x0, const int y0, const int z0, const int v0, 1.19787 + const int x1, const int y1, const int z1, const int v1, 1.19788 + const T val, const float opacity=1) { 1.19789 + if (is_empty()) return *this; 1.19790 + const bool bx = (x0<x1), by = (y0<y1), bz = (z0<z1), bv = (v0<v1); 1.19791 + const int 1.19792 + nx0 = bx?x0:x1, nx1 = bx?x1:x0, 1.19793 + ny0 = by?y0:y1, ny1 = by?y1:y0, 1.19794 + nz0 = bz?z0:z1, nz1 = bz?z1:z0, 1.19795 + nv0 = bv?v0:v1, nv1 = bv?v1:v0; 1.19796 + const int 1.19797 + lX = (1 + nx1 - nx0) + (nx1>=dimx()?dimx() - 1 - nx1:0) + (nx0<0?nx0:0), 1.19798 + lY = (1 + ny1 - ny0) + (ny1>=dimy()?dimy() - 1 - ny1:0) + (ny0<0?ny0:0), 1.19799 + lZ = (1 + nz1 - nz0) + (nz1>=dimz()?dimz() - 1 - nz1:0) + (nz0<0?nz0:0), 1.19800 + lV = (1 + nv1 - nv0) + (nv1>=dimv()?dimv() - 1 - nv1:0) + (nv0<0?nv0:0); 1.19801 + const unsigned int offX = width - lX, offY = width*(height - lY), offZ = width*height*(depth - lZ); 1.19802 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.19803 + T *ptrd = ptr(nx0<0?0:nx0,ny0<0?0:ny0,nz0<0?0:nz0,nv0<0?0:nv0); 1.19804 + if (lX>0 && lY>0 && lZ>0 && lV>0) 1.19805 + for (int v = 0; v<lV; ++v) { 1.19806 + for (int z = 0; z<lZ; ++z) { 1.19807 + for (int y = 0; y<lY; ++y) { 1.19808 + if (opacity>=1) { 1.19809 + if (sizeof(T)!=1) { for (int x = 0; x<lX; ++x) *(ptrd++) = val; ptrd+=offX; } 1.19810 + else { cimg_std::memset(ptrd,(int)val,lX); ptrd+=width; } 1.19811 + } else { for (int x = 0; x<lX; ++x) { *ptrd = (T)(nopacity*val + *ptrd*copacity); ++ptrd; } ptrd+=offX; } 1.19812 + } 1.19813 + ptrd+=offY; 1.19814 + } 1.19815 + ptrd+=offZ; 1.19816 + } 1.19817 + return *this; 1.19818 + } 1.19819 + 1.19820 + //! Draw a 3D filled colored rectangle in the instance image, at coordinates (\c x0,\c y0,\c z0)-(\c x1,\c y1,\c z1). 1.19821 + /** 1.19822 + \param x0 X-coordinate of the upper-left rectangle corner. 1.19823 + \param y0 Y-coordinate of the upper-left rectangle corner. 1.19824 + \param z0 Z-coordinate of the upper-left rectangle corner. 1.19825 + \param x1 X-coordinate of the lower-right rectangle corner. 1.19826 + \param y1 Y-coordinate of the lower-right rectangle corner. 1.19827 + \param z1 Z-coordinate of the lower-right rectangle corner. 1.19828 + \param color Pointer to \c dimv() consecutive values of type \c T, defining the drawing color. 1.19829 + \param opacity Drawing opacity (optional). 1.19830 + \note 1.19831 + - Clipping is supported. 1.19832 + **/ 1.19833 + template<typename tc> 1.19834 + CImg<T>& draw_rectangle(const int x0, const int y0, const int z0, 1.19835 + const int x1, const int y1, const int z1, 1.19836 + const tc *const color, const float opacity=1) { 1.19837 + if (!color) 1.19838 + throw CImgArgumentException("CImg<%s>::draw_rectangle : specified color is (null)", 1.19839 + pixel_type()); 1.19840 + cimg_forV(*this,k) draw_rectangle(x0,y0,z0,k,x1,y1,z1,k,color[k],opacity); 1.19841 + return *this; 1.19842 + } 1.19843 + 1.19844 + //! Draw a 3D filled colored rectangle in the instance image, at coordinates (\c x0,\c y0,\c z0)-(\c x1,\c y1,\c z1). 1.19845 + template<typename tc> 1.19846 + CImg<T>& draw_rectangle(const int x0, const int y0, const int z0, 1.19847 + const int x1, const int y1, const int z1, 1.19848 + const CImg<tc>& color, const float opacity=1) { 1.19849 + return draw_rectangle(x0,y0,z0,x1,y1,z1,color.data,opacity); 1.19850 + } 1.19851 + 1.19852 + //! Draw a 3D outlined colored rectangle in the instance image. 1.19853 + template<typename tc> 1.19854 + CImg<T>& draw_rectangle(const int x0, const int y0, const int z0, 1.19855 + const int x1, const int y1, const int z1, 1.19856 + const tc *const color, const float opacity, 1.19857 + const unsigned int pattern) { 1.19858 + return draw_line(x0,y0,z0,x1,y0,z0,color,opacity,pattern,true). 1.19859 + draw_line(x1,y0,z0,x1,y1,z0,color,opacity,pattern,false). 1.19860 + draw_line(x1,y1,z0,x0,y1,z0,color,opacity,pattern,false). 1.19861 + draw_line(x0,y1,z0,x0,y0,z0,color,opacity,pattern,false). 1.19862 + draw_line(x0,y0,z1,x1,y0,z1,color,opacity,pattern,true). 1.19863 + draw_line(x1,y0,z1,x1,y1,z1,color,opacity,pattern,false). 1.19864 + draw_line(x1,y1,z1,x0,y1,z1,color,opacity,pattern,false). 1.19865 + draw_line(x0,y1,z1,x0,y0,z1,color,opacity,pattern,false). 1.19866 + draw_line(x0,y0,z0,x0,y0,z1,color,opacity,pattern,true). 1.19867 + draw_line(x1,y0,z0,x1,y0,z1,color,opacity,pattern,true). 1.19868 + draw_line(x1,y1,z0,x1,y1,z1,color,opacity,pattern,true). 1.19869 + draw_line(x0,y1,z0,x0,y1,z1,color,opacity,pattern,true); 1.19870 + } 1.19871 + 1.19872 + //! Draw a 3D outlined colored rectangle in the instance image. 1.19873 + template<typename tc> 1.19874 + CImg<T>& draw_rectangle(const int x0, const int y0, const int z0, 1.19875 + const int x1, const int y1, const int z1, 1.19876 + const CImg<tc>& color, const float opacity, 1.19877 + const unsigned int pattern) { 1.19878 + return draw_rectangle(x0,y0,z0,x1,y1,z1,color.data,opacity,pattern); 1.19879 + } 1.19880 + 1.19881 + //! Draw a 2D filled colored rectangle in the instance image, at coordinates (\c x0,\c y0)-(\c x1,\c y1). 1.19882 + /** 1.19883 + \param x0 X-coordinate of the upper-left rectangle corner. 1.19884 + \param y0 Y-coordinate of the upper-left rectangle corner. 1.19885 + \param x1 X-coordinate of the lower-right rectangle corner. 1.19886 + \param y1 Y-coordinate of the lower-right rectangle corner. 1.19887 + \param color Pointer to \c dimv() consecutive values of type \c T, defining the drawing color. 1.19888 + \param opacity Drawing opacity (optional). 1.19889 + \note 1.19890 + - Clipping is supported. 1.19891 + **/ 1.19892 + template<typename tc> 1.19893 + CImg<T>& draw_rectangle(const int x0, const int y0, 1.19894 + const int x1, const int y1, 1.19895 + const tc *const color, const float opacity=1) { 1.19896 + return draw_rectangle(x0,y0,0,x1,y1,depth-1,color,opacity); 1.19897 + } 1.19898 + 1.19899 + //! Draw a 2D filled colored rectangle in the instance image, at coordinates (\c x0,\c y0)-(\c x1,\c y1). 1.19900 + template<typename tc> 1.19901 + CImg<T>& draw_rectangle(const int x0, const int y0, 1.19902 + const int x1, const int y1, 1.19903 + const CImg<tc>& color, const float opacity=1) { 1.19904 + return draw_rectangle(x0,y0,x1,y1,color.data,opacity); 1.19905 + } 1.19906 + 1.19907 + //! Draw a 2D outlined colored rectangle. 1.19908 + template<typename tc> 1.19909 + CImg<T>& draw_rectangle(const int x0, const int y0, 1.19910 + const int x1, const int y1, 1.19911 + const tc *const color, const float opacity, 1.19912 + const unsigned int pattern) { 1.19913 + if (is_empty()) return *this; 1.19914 + if (y0==y1) return draw_line(x0,y0,x1,y0,color,opacity,pattern,true); 1.19915 + if (x0==x1) return draw_line(x0,y0,x0,y1,color,opacity,pattern,true); 1.19916 + const bool bx = (x0<x1), by = (y0<y1); 1.19917 + const int 1.19918 + nx0 = bx?x0:x1, nx1 = bx?x1:x0, 1.19919 + ny0 = by?y0:y1, ny1 = by?y1:y0; 1.19920 + if (ny1==ny0+1) return draw_line(nx0,ny0,nx1,ny0,color,opacity,pattern,true). 1.19921 + draw_line(nx1,ny1,nx0,ny1,color,opacity,pattern,false); 1.19922 + return draw_line(nx0,ny0,nx1,ny0,color,opacity,pattern,true). 1.19923 + draw_line(nx1,ny0+1,nx1,ny1-1,color,opacity,pattern,false). 1.19924 + draw_line(nx1,ny1,nx0,ny1,color,opacity,pattern,false). 1.19925 + draw_line(nx0,ny1-1,nx0,ny0+1,color,opacity,pattern,false); 1.19926 + } 1.19927 + 1.19928 + //! Draw a 2D outlined colored rectangle. 1.19929 + template<typename tc> 1.19930 + CImg<T>& draw_rectangle(const int x0, const int y0, 1.19931 + const int x1, const int y1, 1.19932 + const CImg<tc>& color, const float opacity, 1.19933 + const unsigned int pattern) { 1.19934 + return draw_rectangle(x0,y0,x1,y1,color.data,opacity,pattern); 1.19935 + } 1.19936 + 1.19937 + // Inner macro for drawing triangles. 1.19938 +#define _cimg_for_triangle1(img,xl,xr,y,x0,y0,x1,y1,x2,y2) \ 1.19939 + for (int y = y0<0?0:y0, \ 1.19940 + xr = y0>=0?x0:(x0-y0*(x2-x0)/(y2-y0)), \ 1.19941 + xl = y1>=0?(y0>=0?(y0==y1?x1:x0):(x0-y0*(x1-x0)/(y1-y0))):(x1-y1*(x2-x1)/(y2-y1)), \ 1.19942 + _sxn=1, \ 1.19943 + _sxr=1, \ 1.19944 + _sxl=1, \ 1.19945 + _dxn = x2>x1?x2-x1:(_sxn=-1,x1-x2), \ 1.19946 + _dxr = x2>x0?x2-x0:(_sxr=-1,x0-x2), \ 1.19947 + _dxl = x1>x0?x1-x0:(_sxl=-1,x0-x1), \ 1.19948 + _dyn = y2-y1, \ 1.19949 + _dyr = y2-y0, \ 1.19950 + _dyl = y1-y0, \ 1.19951 + _counter = (_dxn-=_dyn?_dyn*(_dxn/_dyn):0, \ 1.19952 + _dxr-=_dyr?_dyr*(_dxr/_dyr):0, \ 1.19953 + _dxl-=_dyl?_dyl*(_dxl/_dyl):0, \ 1.19954 + cimg::min((int)(img).height-y-1,y2-y)), \ 1.19955 + _errn = _dyn/2, \ 1.19956 + _errr = _dyr/2, \ 1.19957 + _errl = _dyl/2, \ 1.19958 + _rxn = _dyn?(x2-x1)/_dyn:0, \ 1.19959 + _rxr = _dyr?(x2-x0)/_dyr:0, \ 1.19960 + _rxl = (y0!=y1 && y1>0)?(_dyl?(x1-x0)/_dyl:0): \ 1.19961 + (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxn); \ 1.19962 + _counter>=0; --_counter, ++y, \ 1.19963 + xr+=_rxr+((_errr-=_dxr)<0?_errr+=_dyr,_sxr:0), \ 1.19964 + xl+=(y!=y1)?_rxl+((_errl-=_dxl)<0?(_errl+=_dyl,_sxl):0): \ 1.19965 + (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxl=_rxn, x1-xl)) 1.19966 + 1.19967 +#define _cimg_for_triangle2(img,xl,cl,xr,cr,y,x0,y0,c0,x1,y1,c1,x2,y2,c2) \ 1.19968 + for (int y = y0<0?0:y0, \ 1.19969 + xr = y0>=0?x0:(x0-y0*(x2-x0)/(y2-y0)), \ 1.19970 + cr = y0>=0?c0:(c0-y0*(c2-c0)/(y2-y0)), \ 1.19971 + xl = y1>=0?(y0>=0?(y0==y1?x1:x0):(x0-y0*(x1-x0)/(y1-y0))):(x1-y1*(x2-x1)/(y2-y1)), \ 1.19972 + cl = y1>=0?(y0>=0?(y0==y1?c1:c0):(c0-y0*(c1-c0)/(y1-y0))):(c1-y1*(c2-c1)/(y2-y1)), \ 1.19973 + _sxn=1, _scn=1, \ 1.19974 + _sxr=1, _scr=1, \ 1.19975 + _sxl=1, _scl=1, \ 1.19976 + _dxn = x2>x1?x2-x1:(_sxn=-1,x1-x2), \ 1.19977 + _dxr = x2>x0?x2-x0:(_sxr=-1,x0-x2), \ 1.19978 + _dxl = x1>x0?x1-x0:(_sxl=-1,x0-x1), \ 1.19979 + _dcn = c2>c1?c2-c1:(_scn=-1,c1-c2), \ 1.19980 + _dcr = c2>c0?c2-c0:(_scr=-1,c0-c2), \ 1.19981 + _dcl = c1>c0?c1-c0:(_scl=-1,c0-c1), \ 1.19982 + _dyn = y2-y1, \ 1.19983 + _dyr = y2-y0, \ 1.19984 + _dyl = y1-y0, \ 1.19985 + _counter =(_dxn-=_dyn?_dyn*(_dxn/_dyn):0, \ 1.19986 + _dxr-=_dyr?_dyr*(_dxr/_dyr):0, \ 1.19987 + _dxl-=_dyl?_dyl*(_dxl/_dyl):0, \ 1.19988 + _dcn-=_dyn?_dyn*(_dcn/_dyn):0, \ 1.19989 + _dcr-=_dyr?_dyr*(_dcr/_dyr):0, \ 1.19990 + _dcl-=_dyl?_dyl*(_dcl/_dyl):0, \ 1.19991 + cimg::min((int)(img).height-y-1,y2-y)), \ 1.19992 + _errn = _dyn/2, _errcn = _errn, \ 1.19993 + _errr = _dyr/2, _errcr = _errr, \ 1.19994 + _errl = _dyl/2, _errcl = _errl, \ 1.19995 + _rxn = _dyn?(x2-x1)/_dyn:0, \ 1.19996 + _rcn = _dyn?(c2-c1)/_dyn:0, \ 1.19997 + _rxr = _dyr?(x2-x0)/_dyr:0, \ 1.19998 + _rcr = _dyr?(c2-c0)/_dyr:0, \ 1.19999 + _rxl = (y0!=y1 && y1>0)?(_dyl?(x1-x0)/_dyl:0): \ 1.20000 + (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxn), \ 1.20001 + _rcl = (y0!=y1 && y1>0)?(_dyl?(c1-c0)/_dyl:0): \ 1.20002 + (_errcl=_errcn, _dcl=_dcn, _dyl=_dyn, _scl=_scn, _rcn ); \ 1.20003 + _counter>=0; --_counter, ++y, \ 1.20004 + xr+=_rxr+((_errr-=_dxr)<0?_errr+=_dyr,_sxr:0), \ 1.20005 + cr+=_rcr+((_errcr-=_dcr)<0?_errcr+=_dyr,_scr:0), \ 1.20006 + xl+=(y!=y1)?(cl+=_rcl+((_errcl-=_dcl)<0?(_errcl+=_dyl,_scl):0), \ 1.20007 + _rxl+((_errl-=_dxl)<0?(_errl+=_dyl,_sxl):0)): \ 1.20008 + (_errcl=_errcn, _dcl=_dcn, _dyl=_dyn, _scl=_scn, _rcl=_rcn, cl=c1, \ 1.20009 + _errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxl=_rxn, x1-xl)) 1.20010 + 1.20011 +#define _cimg_for_triangle3(img,xl,txl,tyl,xr,txr,tyr,y,x0,y0,tx0,ty0,x1,y1,tx1,ty1,x2,y2,tx2,ty2) \ 1.20012 + for (int y = y0<0?0:y0, \ 1.20013 + xr = y0>=0?x0:(x0-y0*(x2-x0)/(y2-y0)), \ 1.20014 + txr = y0>=0?tx0:(tx0-y0*(tx2-tx0)/(y2-y0)), \ 1.20015 + tyr = y0>=0?ty0:(ty0-y0*(ty2-ty0)/(y2-y0)), \ 1.20016 + xl = y1>=0?(y0>=0?(y0==y1?x1:x0):(x0-y0*(x1-x0)/(y1-y0))):(x1-y1*(x2-x1)/(y2-y1)), \ 1.20017 + txl = y1>=0?(y0>=0?(y0==y1?tx1:tx0):(tx0-y0*(tx1-tx0)/(y1-y0))):(tx1-y1*(tx2-tx1)/(y2-y1)), \ 1.20018 + tyl = y1>=0?(y0>=0?(y0==y1?ty1:ty0):(ty0-y0*(ty1-ty0)/(y1-y0))):(ty1-y1*(ty2-ty1)/(y2-y1)), \ 1.20019 + _sxn=1, _stxn=1, _styn=1, \ 1.20020 + _sxr=1, _stxr=1, _styr=1, \ 1.20021 + _sxl=1, _stxl=1, _styl=1, \ 1.20022 + _dxn = x2>x1?x2-x1:(_sxn=-1,x1-x2), \ 1.20023 + _dxr = x2>x0?x2-x0:(_sxr=-1,x0-x2), \ 1.20024 + _dxl = x1>x0?x1-x0:(_sxl=-1,x0-x1), \ 1.20025 + _dtxn = tx2>tx1?tx2-tx1:(_stxn=-1,tx1-tx2), \ 1.20026 + _dtxr = tx2>tx0?tx2-tx0:(_stxr=-1,tx0-tx2), \ 1.20027 + _dtxl = tx1>tx0?tx1-tx0:(_stxl=-1,tx0-tx1), \ 1.20028 + _dtyn = ty2>ty1?ty2-ty1:(_styn=-1,ty1-ty2), \ 1.20029 + _dtyr = ty2>ty0?ty2-ty0:(_styr=-1,ty0-ty2), \ 1.20030 + _dtyl = ty1>ty0?ty1-ty0:(_styl=-1,ty0-ty1), \ 1.20031 + _dyn = y2-y1, \ 1.20032 + _dyr = y2-y0, \ 1.20033 + _dyl = y1-y0, \ 1.20034 + _counter =(_dxn-=_dyn?_dyn*(_dxn/_dyn):0, \ 1.20035 + _dxr-=_dyr?_dyr*(_dxr/_dyr):0, \ 1.20036 + _dxl-=_dyl?_dyl*(_dxl/_dyl):0, \ 1.20037 + _dtxn-=_dyn?_dyn*(_dtxn/_dyn):0, \ 1.20038 + _dtxr-=_dyr?_dyr*(_dtxr/_dyr):0, \ 1.20039 + _dtxl-=_dyl?_dyl*(_dtxl/_dyl):0, \ 1.20040 + _dtyn-=_dyn?_dyn*(_dtyn/_dyn):0, \ 1.20041 + _dtyr-=_dyr?_dyr*(_dtyr/_dyr):0, \ 1.20042 + _dtyl-=_dyl?_dyl*(_dtyl/_dyl):0, \ 1.20043 + cimg::min((int)(img).height-y-1,y2-y)), \ 1.20044 + _errn = _dyn/2, _errtxn = _errn, _errtyn = _errn, \ 1.20045 + _errr = _dyr/2, _errtxr = _errr, _errtyr = _errr, \ 1.20046 + _errl = _dyl/2, _errtxl = _errl, _errtyl = _errl, \ 1.20047 + _rxn = _dyn?(x2-x1)/_dyn:0, \ 1.20048 + _rtxn = _dyn?(tx2-tx1)/_dyn:0, \ 1.20049 + _rtyn = _dyn?(ty2-ty1)/_dyn:0, \ 1.20050 + _rxr = _dyr?(x2-x0)/_dyr:0, \ 1.20051 + _rtxr = _dyr?(tx2-tx0)/_dyr:0, \ 1.20052 + _rtyr = _dyr?(ty2-ty0)/_dyr:0, \ 1.20053 + _rxl = (y0!=y1 && y1>0)?(_dyl?(x1-x0)/_dyl:0): \ 1.20054 + (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxn), \ 1.20055 + _rtxl = (y0!=y1 && y1>0)?(_dyl?(tx1-tx0)/_dyl:0): \ 1.20056 + (_errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxn ), \ 1.20057 + _rtyl = (y0!=y1 && y1>0)?(_dyl?(ty1-ty0)/_dyl:0): \ 1.20058 + (_errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyn ); \ 1.20059 + _counter>=0; --_counter, ++y, \ 1.20060 + xr+=_rxr+((_errr-=_dxr)<0?_errr+=_dyr,_sxr:0), \ 1.20061 + txr+=_rtxr+((_errtxr-=_dtxr)<0?_errtxr+=_dyr,_stxr:0), \ 1.20062 + tyr+=_rtyr+((_errtyr-=_dtyr)<0?_errtyr+=_dyr,_styr:0), \ 1.20063 + xl+=(y!=y1)?(txl+=_rtxl+((_errtxl-=_dtxl)<0?(_errtxl+=_dyl,_stxl):0), \ 1.20064 + tyl+=_rtyl+((_errtyl-=_dtyl)<0?(_errtyl+=_dyl,_styl):0), \ 1.20065 + _rxl+((_errl-=_dxl)<0?(_errl+=_dyl,_sxl):0)): \ 1.20066 + (_errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxl=_rtxn, txl=tx1, \ 1.20067 + _errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyl=_rtyn, tyl=ty1,\ 1.20068 + _errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxl=_rxn, x1-xl)) 1.20069 + 1.20070 +#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) \ 1.20071 + for (int y = y0<0?0:y0, \ 1.20072 + xr = y0>=0?x0:(x0-y0*(x2-x0)/(y2-y0)), \ 1.20073 + cr = y0>=0?c0:(c0-y0*(c2-c0)/(y2-y0)), \ 1.20074 + txr = y0>=0?tx0:(tx0-y0*(tx2-tx0)/(y2-y0)), \ 1.20075 + tyr = y0>=0?ty0:(ty0-y0*(ty2-ty0)/(y2-y0)), \ 1.20076 + xl = y1>=0?(y0>=0?(y0==y1?x1:x0):(x0-y0*(x1-x0)/(y1-y0))):(x1-y1*(x2-x1)/(y2-y1)), \ 1.20077 + cl = y1>=0?(y0>=0?(y0==y1?c1:c0):(c0-y0*(c1-c0)/(y1-y0))):(c1-y1*(c2-c1)/(y2-y1)), \ 1.20078 + txl = y1>=0?(y0>=0?(y0==y1?tx1:tx0):(tx0-y0*(tx1-tx0)/(y1-y0))):(tx1-y1*(tx2-tx1)/(y2-y1)), \ 1.20079 + tyl = y1>=0?(y0>=0?(y0==y1?ty1:ty0):(ty0-y0*(ty1-ty0)/(y1-y0))):(ty1-y1*(ty2-ty1)/(y2-y1)), \ 1.20080 + _sxn=1, _scn=1, _stxn=1, _styn=1, \ 1.20081 + _sxr=1, _scr=1, _stxr=1, _styr=1, \ 1.20082 + _sxl=1, _scl=1, _stxl=1, _styl=1, \ 1.20083 + _dxn = x2>x1?x2-x1:(_sxn=-1,x1-x2), \ 1.20084 + _dxr = x2>x0?x2-x0:(_sxr=-1,x0-x2), \ 1.20085 + _dxl = x1>x0?x1-x0:(_sxl=-1,x0-x1), \ 1.20086 + _dcn = c2>c1?c2-c1:(_scn=-1,c1-c2), \ 1.20087 + _dcr = c2>c0?c2-c0:(_scr=-1,c0-c2), \ 1.20088 + _dcl = c1>c0?c1-c0:(_scl=-1,c0-c1), \ 1.20089 + _dtxn = tx2>tx1?tx2-tx1:(_stxn=-1,tx1-tx2), \ 1.20090 + _dtxr = tx2>tx0?tx2-tx0:(_stxr=-1,tx0-tx2), \ 1.20091 + _dtxl = tx1>tx0?tx1-tx0:(_stxl=-1,tx0-tx1), \ 1.20092 + _dtyn = ty2>ty1?ty2-ty1:(_styn=-1,ty1-ty2), \ 1.20093 + _dtyr = ty2>ty0?ty2-ty0:(_styr=-1,ty0-ty2), \ 1.20094 + _dtyl = ty1>ty0?ty1-ty0:(_styl=-1,ty0-ty1), \ 1.20095 + _dyn = y2-y1, \ 1.20096 + _dyr = y2-y0, \ 1.20097 + _dyl = y1-y0, \ 1.20098 + _counter =(_dxn-=_dyn?_dyn*(_dxn/_dyn):0, \ 1.20099 + _dxr-=_dyr?_dyr*(_dxr/_dyr):0, \ 1.20100 + _dxl-=_dyl?_dyl*(_dxl/_dyl):0, \ 1.20101 + _dcn-=_dyn?_dyn*(_dcn/_dyn):0, \ 1.20102 + _dcr-=_dyr?_dyr*(_dcr/_dyr):0, \ 1.20103 + _dcl-=_dyl?_dyl*(_dcl/_dyl):0, \ 1.20104 + _dtxn-=_dyn?_dyn*(_dtxn/_dyn):0, \ 1.20105 + _dtxr-=_dyr?_dyr*(_dtxr/_dyr):0, \ 1.20106 + _dtxl-=_dyl?_dyl*(_dtxl/_dyl):0, \ 1.20107 + _dtyn-=_dyn?_dyn*(_dtyn/_dyn):0, \ 1.20108 + _dtyr-=_dyr?_dyr*(_dtyr/_dyr):0, \ 1.20109 + _dtyl-=_dyl?_dyl*(_dtyl/_dyl):0, \ 1.20110 + cimg::min((int)(img).height-y-1,y2-y)), \ 1.20111 + _errn = _dyn/2, _errcn = _errn, _errtxn = _errn, _errtyn = _errn, \ 1.20112 + _errr = _dyr/2, _errcr = _errr, _errtxr = _errr, _errtyr = _errr, \ 1.20113 + _errl = _dyl/2, _errcl = _errl, _errtxl = _errl, _errtyl = _errl, \ 1.20114 + _rxn = _dyn?(x2-x1)/_dyn:0, \ 1.20115 + _rcn = _dyn?(c2-c1)/_dyn:0, \ 1.20116 + _rtxn = _dyn?(tx2-tx1)/_dyn:0, \ 1.20117 + _rtyn = _dyn?(ty2-ty1)/_dyn:0, \ 1.20118 + _rxr = _dyr?(x2-x0)/_dyr:0, \ 1.20119 + _rcr = _dyr?(c2-c0)/_dyr:0, \ 1.20120 + _rtxr = _dyr?(tx2-tx0)/_dyr:0, \ 1.20121 + _rtyr = _dyr?(ty2-ty0)/_dyr:0, \ 1.20122 + _rxl = (y0!=y1 && y1>0)?(_dyl?(x1-x0)/_dyl:0): \ 1.20123 + (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxn), \ 1.20124 + _rcl = (y0!=y1 && y1>0)?(_dyl?(c1-c0)/_dyl:0): \ 1.20125 + (_errcl=_errcn, _dcl=_dcn, _dyl=_dyn, _scl=_scn, _rcn ), \ 1.20126 + _rtxl = (y0!=y1 && y1>0)?(_dyl?(tx1-tx0)/_dyl:0): \ 1.20127 + (_errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxn ), \ 1.20128 + _rtyl = (y0!=y1 && y1>0)?(_dyl?(ty1-ty0)/_dyl:0): \ 1.20129 + (_errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyn ); \ 1.20130 + _counter>=0; --_counter, ++y, \ 1.20131 + xr+=_rxr+((_errr-=_dxr)<0?_errr+=_dyr,_sxr:0), \ 1.20132 + cr+=_rcr+((_errcr-=_dcr)<0?_errcr+=_dyr,_scr:0), \ 1.20133 + txr+=_rtxr+((_errtxr-=_dtxr)<0?_errtxr+=_dyr,_stxr:0), \ 1.20134 + tyr+=_rtyr+((_errtyr-=_dtyr)<0?_errtyr+=_dyr,_styr:0), \ 1.20135 + xl+=(y!=y1)?(cl+=_rcl+((_errcl-=_dcl)<0?(_errcl+=_dyl,_scl):0), \ 1.20136 + txl+=_rtxl+((_errtxl-=_dtxl)<0?(_errtxl+=_dyl,_stxl):0), \ 1.20137 + tyl+=_rtyl+((_errtyl-=_dtyl)<0?(_errtyl+=_dyl,_styl):0), \ 1.20138 + _rxl+((_errl-=_dxl)<0?(_errl+=_dyl,_sxl):0)): \ 1.20139 + (_errcl=_errcn, _dcl=_dcn, _dyl=_dyn, _scl=_scn, _rcl=_rcn, cl=c1, \ 1.20140 + _errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxl=_rtxn, txl=tx1, \ 1.20141 + _errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyl=_rtyn, tyl=ty1, \ 1.20142 + _errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxl=_rxn, x1-xl)) 1.20143 + 1.20144 +#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) \ 1.20145 + for (int y = y0<0?0:y0, \ 1.20146 + xr = y0>=0?x0:(x0-y0*(x2-x0)/(y2-y0)), \ 1.20147 + txr = y0>=0?tx0:(tx0-y0*(tx2-tx0)/(y2-y0)), \ 1.20148 + tyr = y0>=0?ty0:(ty0-y0*(ty2-ty0)/(y2-y0)), \ 1.20149 + lxr = y0>=0?lx0:(lx0-y0*(lx2-lx0)/(y2-y0)), \ 1.20150 + lyr = y0>=0?ly0:(ly0-y0*(ly2-ly0)/(y2-y0)), \ 1.20151 + xl = y1>=0?(y0>=0?(y0==y1?x1:x0):(x0-y0*(x1-x0)/(y1-y0))):(x1-y1*(x2-x1)/(y2-y1)), \ 1.20152 + txl = y1>=0?(y0>=0?(y0==y1?tx1:tx0):(tx0-y0*(tx1-tx0)/(y1-y0))):(tx1-y1*(tx2-tx1)/(y2-y1)), \ 1.20153 + tyl = y1>=0?(y0>=0?(y0==y1?ty1:ty0):(ty0-y0*(ty1-ty0)/(y1-y0))):(ty1-y1*(ty2-ty1)/(y2-y1)), \ 1.20154 + lxl = y1>=0?(y0>=0?(y0==y1?lx1:lx0):(lx0-y0*(lx1-lx0)/(y1-y0))):(lx1-y1*(lx2-lx1)/(y2-y1)), \ 1.20155 + lyl = y1>=0?(y0>=0?(y0==y1?ly1:ly0):(ly0-y0*(ly1-ly0)/(y1-y0))):(ly1-y1*(ly2-ly1)/(y2-y1)), \ 1.20156 + _sxn=1, _stxn=1, _styn=1, _slxn=1, _slyn=1, \ 1.20157 + _sxr=1, _stxr=1, _styr=1, _slxr=1, _slyr=1, \ 1.20158 + _sxl=1, _stxl=1, _styl=1, _slxl=1, _slyl=1, \ 1.20159 + _dxn = x2>x1?x2-x1:(_sxn=-1,x1-x2), _dyn = y2-y1, \ 1.20160 + _dxr = x2>x0?x2-x0:(_sxr=-1,x0-x2), _dyr = y2-y0, \ 1.20161 + _dxl = x1>x0?x1-x0:(_sxl=-1,x0-x1), _dyl = y1-y0, \ 1.20162 + _dtxn = tx2>tx1?tx2-tx1:(_stxn=-1,tx1-tx2), \ 1.20163 + _dtxr = tx2>tx0?tx2-tx0:(_stxr=-1,tx0-tx2), \ 1.20164 + _dtxl = tx1>tx0?tx1-tx0:(_stxl=-1,tx0-tx1), \ 1.20165 + _dtyn = ty2>ty1?ty2-ty1:(_styn=-1,ty1-ty2), \ 1.20166 + _dtyr = ty2>ty0?ty2-ty0:(_styr=-1,ty0-ty2), \ 1.20167 + _dtyl = ty1>ty0?ty1-ty0:(_styl=-1,ty0-ty1), \ 1.20168 + _dlxn = lx2>lx1?lx2-lx1:(_slxn=-1,lx1-lx2), \ 1.20169 + _dlxr = lx2>lx0?lx2-lx0:(_slxr=-1,lx0-lx2), \ 1.20170 + _dlxl = lx1>lx0?lx1-lx0:(_slxl=-1,lx0-lx1), \ 1.20171 + _dlyn = ly2>ly1?ly2-ly1:(_slyn=-1,ly1-ly2), \ 1.20172 + _dlyr = ly2>ly0?ly2-ly0:(_slyr=-1,ly0-ly2), \ 1.20173 + _dlyl = ly1>ly0?ly1-ly0:(_slyl=-1,ly0-ly1), \ 1.20174 + _counter =(_dxn-=_dyn?_dyn*(_dxn/_dyn):0, \ 1.20175 + _dxr-=_dyr?_dyr*(_dxr/_dyr):0, \ 1.20176 + _dxl-=_dyl?_dyl*(_dxl/_dyl):0, \ 1.20177 + _dtxn-=_dyn?_dyn*(_dtxn/_dyn):0, \ 1.20178 + _dtxr-=_dyr?_dyr*(_dtxr/_dyr):0, \ 1.20179 + _dtxl-=_dyl?_dyl*(_dtxl/_dyl):0, \ 1.20180 + _dtyn-=_dyn?_dyn*(_dtyn/_dyn):0, \ 1.20181 + _dtyr-=_dyr?_dyr*(_dtyr/_dyr):0, \ 1.20182 + _dtyl-=_dyl?_dyl*(_dtyl/_dyl):0, \ 1.20183 + _dlxn-=_dyn?_dyn*(_dlxn/_dyn):0, \ 1.20184 + _dlxr-=_dyr?_dyr*(_dlxr/_dyr):0, \ 1.20185 + _dlxl-=_dyl?_dyl*(_dlxl/_dyl):0, \ 1.20186 + _dlyn-=_dyn?_dyn*(_dlyn/_dyn):0, \ 1.20187 + _dlyr-=_dyr?_dyr*(_dlyr/_dyr):0, \ 1.20188 + _dlyl-=_dyl?_dyl*(_dlyl/_dyl):0, \ 1.20189 + cimg::min((int)(img).height-y-1,y2-y)), \ 1.20190 + _errn = _dyn/2, _errtxn = _errn, _errtyn = _errn, _errlxn = _errn, _errlyn = _errn, \ 1.20191 + _errr = _dyr/2, _errtxr = _errr, _errtyr = _errr, _errlxr = _errr, _errlyr = _errr, \ 1.20192 + _errl = _dyl/2, _errtxl = _errl, _errtyl = _errl, _errlxl = _errl, _errlyl = _errl, \ 1.20193 + _rxn = _dyn?(x2-x1)/_dyn:0, \ 1.20194 + _rtxn = _dyn?(tx2-tx1)/_dyn:0, \ 1.20195 + _rtyn = _dyn?(ty2-ty1)/_dyn:0, \ 1.20196 + _rlxn = _dyn?(lx2-lx1)/_dyn:0, \ 1.20197 + _rlyn = _dyn?(ly2-ly1)/_dyn:0, \ 1.20198 + _rxr = _dyr?(x2-x0)/_dyr:0, \ 1.20199 + _rtxr = _dyr?(tx2-tx0)/_dyr:0, \ 1.20200 + _rtyr = _dyr?(ty2-ty0)/_dyr:0, \ 1.20201 + _rlxr = _dyr?(lx2-lx0)/_dyr:0, \ 1.20202 + _rlyr = _dyr?(ly2-ly0)/_dyr:0, \ 1.20203 + _rxl = (y0!=y1 && y1>0)?(_dyl?(x1-x0)/_dyl:0): \ 1.20204 + (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxn), \ 1.20205 + _rtxl = (y0!=y1 && y1>0)?(_dyl?(tx1-tx0)/_dyl:0): \ 1.20206 + (_errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxn ), \ 1.20207 + _rtyl = (y0!=y1 && y1>0)?(_dyl?(ty1-ty0)/_dyl:0): \ 1.20208 + (_errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyn ), \ 1.20209 + _rlxl = (y0!=y1 && y1>0)?(_dyl?(lx1-lx0)/_dyl:0): \ 1.20210 + (_errlxl=_errlxn, _dlxl=_dlxn, _dyl=_dyn, _slxl=_slxn, _rlxn ), \ 1.20211 + _rlyl = (y0!=y1 && y1>0)?(_dyl?(ly1-ly0)/_dyl:0): \ 1.20212 + (_errlyl=_errlyn, _dlyl=_dlyn, _dyl=_dyn, _slyl=_slyn, _rlyn ); \ 1.20213 + _counter>=0; --_counter, ++y, \ 1.20214 + xr+=_rxr+((_errr-=_dxr)<0?_errr+=_dyr,_sxr:0), \ 1.20215 + txr+=_rtxr+((_errtxr-=_dtxr)<0?_errtxr+=_dyr,_stxr:0), \ 1.20216 + tyr+=_rtyr+((_errtyr-=_dtyr)<0?_errtyr+=_dyr,_styr:0), \ 1.20217 + lxr+=_rlxr+((_errlxr-=_dlxr)<0?_errlxr+=_dyr,_slxr:0), \ 1.20218 + lyr+=_rlyr+((_errlyr-=_dlyr)<0?_errlyr+=_dyr,_slyr:0), \ 1.20219 + xl+=(y!=y1)?(txl+=_rtxl+((_errtxl-=_dtxl)<0?(_errtxl+=_dyl,_stxl):0), \ 1.20220 + tyl+=_rtyl+((_errtyl-=_dtyl)<0?(_errtyl+=_dyl,_styl):0), \ 1.20221 + lxl+=_rlxl+((_errlxl-=_dlxl)<0?(_errlxl+=_dyl,_slxl):0), \ 1.20222 + lyl+=_rlyl+((_errlyl-=_dlyl)<0?(_errlyl+=_dyl,_slyl):0), \ 1.20223 + _rxl+((_errl-=_dxl)<0?(_errl+=_dyl,_sxl):0)): \ 1.20224 + (_errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxl=_rtxn, txl=tx1, \ 1.20225 + _errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyl=_rtyn, tyl=ty1, \ 1.20226 + _errlxl=_errlxn, _dlxl=_dlxn, _dyl=_dyn, _slxl=_slxn, _rlxl=_rlxn, lxl=lx1, \ 1.20227 + _errlyl=_errlyn, _dlyl=_dlyn, _dyl=_dyn, _slyl=_slyn, _rlyl=_rlyn, lyl=ly1, \ 1.20228 + _errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxl=_rxn, x1-xl)) 1.20229 + 1.20230 + // Draw a colored triangle (inner routine, uses bresenham's algorithm). 1.20231 + template<typename tc> 1.20232 + CImg<T>& _draw_triangle(const int x0, const int y0, 1.20233 + const int x1, const int y1, 1.20234 + const int x2, const int y2, 1.20235 + const tc *const color, const float opacity, 1.20236 + const float brightness) { 1.20237 + _draw_scanline(color,opacity); 1.20238 + const float nbrightness = brightness<0?0:(brightness>2?2:brightness); 1.20239 + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2; 1.20240 + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1); 1.20241 + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2); 1.20242 + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2); 1.20243 + if (ny0<dimy() && ny2>=0) { 1.20244 + if ((nx1 - nx0)*(ny2 - ny0) - (nx2 - nx0)*(ny1 - ny0)<0) 1.20245 + _cimg_for_triangle1(*this,xl,xr,y,nx0,ny0,nx1,ny1,nx2,ny2) _draw_scanline(xl,xr,y,color,opacity,nbrightness); 1.20246 + else 1.20247 + _cimg_for_triangle1(*this,xl,xr,y,nx0,ny0,nx1,ny1,nx2,ny2) _draw_scanline(xr,xl,y,color,opacity,nbrightness); 1.20248 + } 1.20249 + return *this; 1.20250 + } 1.20251 + 1.20252 + //! Draw a 2D filled colored triangle. 1.20253 + template<typename tc> 1.20254 + CImg<T>& draw_triangle(const int x0, const int y0, 1.20255 + const int x1, const int y1, 1.20256 + const int x2, const int y2, 1.20257 + const tc *const color, const float opacity=1) { 1.20258 + if (is_empty()) return *this; 1.20259 + if (!color) 1.20260 + throw CImgArgumentException("CImg<%s>::draw_triangle : Specified color is (null).", 1.20261 + pixel_type()); 1.20262 + _draw_triangle(x0,y0,x1,y1,x2,y2,color,opacity,1); 1.20263 + return *this; 1.20264 + } 1.20265 + 1.20266 + //! Draw a 2D filled colored triangle. 1.20267 + template<typename tc> 1.20268 + CImg<T>& draw_triangle(const int x0, const int y0, 1.20269 + const int x1, const int y1, 1.20270 + const int x2, const int y2, 1.20271 + const CImg<tc>& color, const float opacity=1) { 1.20272 + return draw_triangle(x0,y0,x1,y1,x2,y2,color.data,opacity); 1.20273 + } 1.20274 + 1.20275 + //! Draw a 2D outlined colored triangle. 1.20276 + template<typename tc> 1.20277 + CImg<T>& draw_triangle(const int x0, const int y0, 1.20278 + const int x1, const int y1, 1.20279 + const int x2, const int y2, 1.20280 + const tc *const color, const float opacity, 1.20281 + const unsigned int pattern) { 1.20282 + if (is_empty()) return *this; 1.20283 + if (!color) 1.20284 + throw CImgArgumentException("CImg<%s>::draw_triangle : Specified color is (null).", 1.20285 + pixel_type()); 1.20286 + draw_line(x0,y0,x1,y1,color,opacity,pattern,true). 1.20287 + draw_line(x1,y1,x2,y2,color,opacity,pattern,false). 1.20288 + draw_line(x2,y2,x0,y0,color,opacity,pattern,false); 1.20289 + return *this; 1.20290 + } 1.20291 + 1.20292 + //! Draw a 2D outlined colored triangle. 1.20293 + template<typename tc> 1.20294 + CImg<T>& draw_triangle(const int x0, const int y0, 1.20295 + const int x1, const int y1, 1.20296 + const int x2, const int y2, 1.20297 + const CImg<tc>& color, const float opacity, 1.20298 + const unsigned int pattern) { 1.20299 + return draw_triangle(x0,y0,x1,y1,x2,y2,color.data,opacity,pattern); 1.20300 + } 1.20301 + 1.20302 + //! Draw a 2D filled colored triangle, with z-buffering. 1.20303 + template<typename tc> 1.20304 + CImg<T>& draw_triangle(float *const zbuffer, 1.20305 + const int x0, const int y0, const float z0, 1.20306 + const int x1, const int y1, const float z1, 1.20307 + const int x2, const int y2, const float z2, 1.20308 + const tc *const color, const float opacity=1, 1.20309 + const float brightness=1) { 1.20310 + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; 1.20311 + if (!color) 1.20312 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified color is (null).", 1.20313 + pixel_type()); 1.20314 + static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max()); 1.20315 + const float 1.20316 + nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0), 1.20317 + nbrightness = brightness<0?0:(brightness>2?2:brightness); 1.20318 + const int whz = width*height*depth, offx = dim*whz; 1.20319 + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2; 1.20320 + float nz0 = 1/z0, nz1 = 1/z1, nz2 = 1/z2; 1.20321 + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1); 1.20322 + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,nz0,nz2); 1.20323 + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,nz1,nz2); 1.20324 + if (ny0>=dimy() || ny2<0) return *this; 1.20325 + float 1.20326 + pzl = (nz1 - nz0)/(ny1 - ny0), 1.20327 + pzr = (nz2 - nz0)/(ny2 - ny0), 1.20328 + pzn = (nz2 - nz1)/(ny2 - ny1), 1.20329 + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), 1.20330 + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))); 1.20331 + _cimg_for_triangle1(*this,xleft0,xright0,y,nx0,ny0,nx1,ny1,nx2,ny2) { 1.20332 + if (y==ny1) { zl = nz1; pzl = pzn; } 1.20333 + int xleft = xleft0, xright = xright0; 1.20334 + float zleft = zl, zright = zr; 1.20335 + if (xright<xleft) cimg::swap(xleft,xright,zleft,zright); 1.20336 + const int dx = xright - xleft; 1.20337 + const float pentez = (zright - zleft)/dx; 1.20338 + if (xleft<0 && dx) zleft-=xleft*(zright - zleft)/dx; 1.20339 + if (xleft<0) xleft = 0; 1.20340 + if (xright>=dimx()-1) xright = dimx()-1; 1.20341 + T* ptrd = ptr(xleft,y,0,0); 1.20342 + float *ptrz = zbuffer + xleft + y*width; 1.20343 + if (opacity>=1) { 1.20344 + if (nbrightness==1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { 1.20345 + if (zleft>*ptrz) { 1.20346 + *ptrz = zleft; 1.20347 + const tc *col = color; cimg_forV(*this,k) { *ptrd = (T)*(col++); ptrd+=whz; } 1.20348 + ptrd-=offx; 1.20349 + } 1.20350 + zleft+=pentez; 1.20351 + } else if (nbrightness<1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { 1.20352 + if (zleft>*ptrz) { 1.20353 + *ptrz = zleft; 1.20354 + const tc *col = color; cimg_forV(*this,k) { *ptrd = (T)(nbrightness*(*col++)); ptrd+=whz; } 1.20355 + ptrd-=offx; 1.20356 + } 1.20357 + zleft+=pentez; 1.20358 + } else for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { 1.20359 + if (zleft>*ptrz) { 1.20360 + *ptrz = zleft; 1.20361 + const tc *col = color; cimg_forV(*this,k) { *ptrd = (T)((2-nbrightness)**(col++) + (nbrightness-1)*maxval); ptrd+=whz; } 1.20362 + ptrd-=offx; 1.20363 + } 1.20364 + zleft+=pentez; 1.20365 + } 1.20366 + } else { 1.20367 + if (nbrightness==1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { 1.20368 + if (zleft>*ptrz) { 1.20369 + *ptrz = zleft; 1.20370 + const tc *col = color; cimg_forV(*this,k) { *ptrd = (T)(nopacity**(col++) + *ptrd*copacity); ptrd+=whz; } 1.20371 + ptrd-=offx; 1.20372 + } 1.20373 + zleft+=pentez; 1.20374 + } else if (nbrightness<1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { 1.20375 + if (zleft>*ptrz) { 1.20376 + *ptrz = zleft; 1.20377 + const tc *col = color; cimg_forV(*this,k) { *ptrd = (T)(nopacity*nbrightness**(col++) + *ptrd*copacity); ptrd+=whz; } 1.20378 + ptrd-=offx; 1.20379 + } 1.20380 + zleft+=pentez; 1.20381 + } else for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { 1.20382 + if (zleft>*ptrz) { 1.20383 + *ptrz = zleft; 1.20384 + const tc *col = color; 1.20385 + cimg_forV(*this,k) { 1.20386 + const T val = (T)((2-nbrightness)**(col++) + (nbrightness-1)*maxval); 1.20387 + *ptrd = (T)(nopacity*val + *ptrd*copacity); 1.20388 + ptrd+=whz; 1.20389 + } 1.20390 + ptrd-=offx; 1.20391 + } 1.20392 + zleft+=pentez; 1.20393 + } 1.20394 + } 1.20395 + zr+=pzr; zl+=pzl; 1.20396 + } 1.20397 + return *this; 1.20398 + } 1.20399 + 1.20400 + //! Draw a 2D filled colored triangle, with z-buffering. 1.20401 + template<typename tc> 1.20402 + CImg<T>& draw_triangle(float *const zbuffer, 1.20403 + const int x0, const int y0, const float z0, 1.20404 + const int x1, const int y1, const float z1, 1.20405 + const int x2, const int y2, const float z2, 1.20406 + const CImg<tc>& color, const float opacity=1, 1.20407 + const float brightness=1) { 1.20408 + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color.data,opacity,brightness); 1.20409 + } 1.20410 + 1.20411 + //! Draw a 2D Gouraud-shaded colored triangle. 1.20412 + /** 1.20413 + \param x0 = X-coordinate of the first corner in the instance image. 1.20414 + \param y0 = Y-coordinate of the first corner in the instance image. 1.20415 + \param x1 = X-coordinate of the second corner in the instance image. 1.20416 + \param y1 = Y-coordinate of the second corner in the instance image. 1.20417 + \param x2 = X-coordinate of the third corner in the instance image. 1.20418 + \param y2 = Y-coordinate of the third corner in the instance image. 1.20419 + \param color = array of dimv() values of type \c T, defining the global drawing color. 1.20420 + \param brightness0 = brightness of the first corner (in [0,2]). 1.20421 + \param brightness1 = brightness of the second corner (in [0,2]). 1.20422 + \param brightness2 = brightness of the third corner (in [0,2]). 1.20423 + \param opacity = opacity of the drawing. 1.20424 + \note Clipping is supported. 1.20425 + **/ 1.20426 + template<typename tc> 1.20427 + CImg<T>& draw_triangle(const int x0, const int y0, 1.20428 + const int x1, const int y1, 1.20429 + const int x2, const int y2, 1.20430 + const tc *const color, 1.20431 + const float brightness0, 1.20432 + const float brightness1, 1.20433 + const float brightness2, 1.20434 + const float opacity=1) { 1.20435 + if (is_empty()) return *this; 1.20436 + if (!color) 1.20437 + throw CImgArgumentException("CImg<%s>::draw_triangle : Specified color is (null).", 1.20438 + pixel_type()); 1.20439 + static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max()); 1.20440 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.20441 + const int whz = width*height*depth, offx = dim*whz-1; 1.20442 + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, 1.20443 + nc0 = (int)((brightness0<0?0:(brightness0>2?2:brightness0))*256), 1.20444 + nc1 = (int)((brightness1<0?0:(brightness1>2?2:brightness1))*256), 1.20445 + nc2 = (int)((brightness2<0?0:(brightness2>2?2:brightness2))*256); 1.20446 + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nc0,nc1); 1.20447 + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,nc0,nc2); 1.20448 + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,nc1,nc2); 1.20449 + if (ny0>=dimy() || ny2<0) return *this; 1.20450 + _cimg_for_triangle2(*this,xleft0,cleft0,xright0,cright0,y,nx0,ny0,nc0,nx1,ny1,nc1,nx2,ny2,nc2) { 1.20451 + int xleft = xleft0, xright = xright0, cleft = cleft0, cright = cright0; 1.20452 + if (xright<xleft) cimg::swap(xleft,xright,cleft,cright); 1.20453 + const int 1.20454 + dx = xright - xleft, 1.20455 + dc = cright>cleft?cright - cleft:cleft - cright, 1.20456 + rc = dx?(cright - cleft)/dx:0, 1.20457 + sc = cright>cleft?1:-1, 1.20458 + ndc = dc-(dx?dx*(dc/dx):0); 1.20459 + int errc = dx>>1; 1.20460 + if (xleft<0 && dx) cleft-=xleft*(cright - cleft)/dx; 1.20461 + if (xleft<0) xleft = 0; 1.20462 + if (xright>=dimx()-1) xright = dimx()-1; 1.20463 + T* ptrd = ptr(xleft,y); 1.20464 + if (opacity>=1) for (int x = xleft; x<=xright; ++x) { 1.20465 + const tc *col = color; 1.20466 + cimg_forV(*this,k) { 1.20467 + *ptrd = (T)(cleft<256?cleft**(col++)/256:((512-cleft)**(col++)+(cleft-256)*maxval)/256); 1.20468 + ptrd+=whz; 1.20469 + } 1.20470 + ptrd-=offx; 1.20471 + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); 1.20472 + } else for (int x = xleft; x<=xright; ++x) { 1.20473 + const tc *col = color; 1.20474 + cimg_forV(*this,k) { 1.20475 + const T val = (T)(cleft<256?cleft**(col++)/256:((512-cleft)**(col++)+(cleft-256)*maxval)/256); 1.20476 + *ptrd = (T)(nopacity*val + *ptrd*copacity); 1.20477 + ptrd+=whz; 1.20478 + } 1.20479 + ptrd-=offx; 1.20480 + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); 1.20481 + } 1.20482 + } 1.20483 + return *this; 1.20484 + } 1.20485 + 1.20486 + //! Draw a 2D Gouraud-shaded colored triangle. 1.20487 + template<typename tc> 1.20488 + CImg<T>& draw_triangle(const int x0, const int y0, 1.20489 + const int x1, const int y1, 1.20490 + const int x2, const int y2, 1.20491 + const CImg<tc>& color, 1.20492 + const float brightness0, 1.20493 + const float brightness1, 1.20494 + const float brightness2, 1.20495 + const float opacity=1) { 1.20496 + return draw_triangle(x0,y0,x1,y1,x2,y2,color.data,brightness0,brightness1,brightness2,opacity); 1.20497 + } 1.20498 + 1.20499 + //! Draw a 2D Gouraud-shaded colored triangle, with z-buffering. 1.20500 + template<typename tc> 1.20501 + CImg<T>& draw_triangle(float *const zbuffer, 1.20502 + const int x0, const int y0, const float z0, 1.20503 + const int x1, const int y1, const float z1, 1.20504 + const int x2, const int y2, const float z2, 1.20505 + const tc *const color, 1.20506 + const float brightness0, 1.20507 + const float brightness1, 1.20508 + const float brightness2, 1.20509 + const float opacity=1) { 1.20510 + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; 1.20511 + if (!color) 1.20512 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified color is (null).", 1.20513 + pixel_type()); 1.20514 + static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max()); 1.20515 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.20516 + const int whz = width*height*depth, offx = dim*whz; 1.20517 + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, 1.20518 + nc0 = (int)((brightness0<0?0:(brightness0>2?2:brightness0))*256), 1.20519 + nc1 = (int)((brightness1<0?0:(brightness1>2?2:brightness1))*256), 1.20520 + nc2 = (int)((brightness2<0?0:(brightness2>2?2:brightness2))*256); 1.20521 + float nz0 = 1/z0, nz1 = 1/z1, nz2 = 1/z2; 1.20522 + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1,nc0,nc1); 1.20523 + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,nz0,nz2,nc0,nc2); 1.20524 + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,nz1,nz2,nc1,nc2); 1.20525 + if (ny0>=dimy() || ny2<0) return *this; 1.20526 + float 1.20527 + pzl = (nz1 - nz0)/(ny1 - ny0), 1.20528 + pzr = (nz2 - nz0)/(ny2 - ny0), 1.20529 + pzn = (nz2 - nz1)/(ny2 - ny1), 1.20530 + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), 1.20531 + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))); 1.20532 + _cimg_for_triangle2(*this,xleft0,cleft0,xright0,cright0,y,nx0,ny0,nc0,nx1,ny1,nc1,nx2,ny2,nc2) { 1.20533 + if (y==ny1) { zl = nz1; pzl = pzn; } 1.20534 + int xleft = xleft0, xright = xright0, cleft = cleft0, cright = cright0; 1.20535 + float zleft = zl, zright = zr; 1.20536 + if (xright<xleft) cimg::swap(xleft,xright,zleft,zright,cleft,cright); 1.20537 + const int 1.20538 + dx = xright - xleft, 1.20539 + dc = cright>cleft?cright - cleft:cleft - cright, 1.20540 + rc = dx?(cright-cleft)/dx:0, 1.20541 + sc = cright>cleft?1:-1, 1.20542 + ndc = dc-(dx?dx*(dc/dx):0); 1.20543 + const float pentez = (zright - zleft)/dx; 1.20544 + int errc = dx>>1; 1.20545 + if (xleft<0 && dx) { 1.20546 + cleft-=xleft*(cright - cleft)/dx; 1.20547 + zleft-=xleft*(zright - zleft)/dx; 1.20548 + } 1.20549 + if (xleft<0) xleft = 0; 1.20550 + if (xright>=dimx()-1) xright = dimx()-1; 1.20551 + T *ptrd = ptr(xleft,y); 1.20552 + float *ptrz = zbuffer + xleft + y*width; 1.20553 + if (opacity>=1) for (int x = xleft; x<=xright; ++x, ++ptrd, ++ptrz) { 1.20554 + if (zleft>*ptrz) { 1.20555 + *ptrz = zleft; 1.20556 + const tc *col = color; 1.20557 + cimg_forV(*this,k) { 1.20558 + *ptrd = (T)(cleft<256?cleft**(col++)/256:((512-cleft)**(col++)+(cleft-256)*maxval)/256); 1.20559 + ptrd+=whz; 1.20560 + } 1.20561 + ptrd-=offx; 1.20562 + } 1.20563 + zleft+=pentez; 1.20564 + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); 1.20565 + } else for (int x = xleft; x<=xright; ++x, ++ptrd, ++ptrz) { 1.20566 + if (zleft>*ptrz) { 1.20567 + *ptrz = zleft; 1.20568 + const tc *col = color; 1.20569 + cimg_forV(*this,k) { 1.20570 + const T val = (T)(cleft<256?cleft**(col++)/256:((512-cleft)**(col++)+(cleft-256)*maxval)/256); 1.20571 + *ptrd = (T)(nopacity*val + *ptrd*copacity); 1.20572 + ptrd+=whz; 1.20573 + } 1.20574 + ptrd-=offx; 1.20575 + } 1.20576 + zleft+=pentez; 1.20577 + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); 1.20578 + } 1.20579 + zr+=pzr; zl+=pzl; 1.20580 + } 1.20581 + return *this; 1.20582 + } 1.20583 + 1.20584 + //! Draw a Gouraud triangle with z-buffer consideration. 1.20585 + template<typename tc> 1.20586 + CImg<T>& draw_triangle(float *const zbuffer, 1.20587 + const int x0, const int y0, const float z0, 1.20588 + const int x1, const int y1, const float z1, 1.20589 + const int x2, const int y2, const float z2, 1.20590 + const CImg<tc>& color, 1.20591 + const float brightness0, 1.20592 + const float brightness1, 1.20593 + const float brightness2, 1.20594 + const float opacity=1) { 1.20595 + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color.data,brightness0,brightness1,brightness2,opacity); 1.20596 + } 1.20597 + 1.20598 + //! Draw a 2D textured triangle. 1.20599 + /** 1.20600 + \param x0 = X-coordinate of the first corner in the instance image. 1.20601 + \param y0 = Y-coordinate of the first corner in the instance image. 1.20602 + \param x1 = X-coordinate of the second corner in the instance image. 1.20603 + \param y1 = Y-coordinate of the second corner in the instance image. 1.20604 + \param x2 = X-coordinate of the third corner in the instance image. 1.20605 + \param y2 = Y-coordinate of the third corner in the instance image. 1.20606 + \param texture = texture image used to fill the triangle. 1.20607 + \param tx0 = X-coordinate of the first corner in the texture image. 1.20608 + \param ty0 = Y-coordinate of the first corner in the texture image. 1.20609 + \param tx1 = X-coordinate of the second corner in the texture image. 1.20610 + \param ty1 = Y-coordinate of the second corner in the texture image. 1.20611 + \param tx2 = X-coordinate of the third corner in the texture image. 1.20612 + \param ty2 = Y-coordinate of the third corner in the texture image. 1.20613 + \param opacity = opacity of the drawing. 1.20614 + \param brightness = brightness of the drawing (in [0,2]). 1.20615 + \note Clipping is supported, but texture coordinates do not support clipping. 1.20616 + **/ 1.20617 + template<typename tc> 1.20618 + CImg<T>& draw_triangle(const int x0, const int y0, 1.20619 + const int x1, const int y1, 1.20620 + const int x2, const int y2, 1.20621 + const CImg<tc>& texture, 1.20622 + const int tx0, const int ty0, 1.20623 + const int tx1, const int ty1, 1.20624 + const int tx2, const int ty2, 1.20625 + const float opacity=1, 1.20626 + const float brightness=1) { 1.20627 + if (is_empty()) return *this; 1.20628 + if (!texture || texture.dim<dim) 1.20629 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified texture (%u,%u,%u,%u,%p) is not a valid argument.", 1.20630 + pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data); 1.20631 + if (is_overlapped(texture)) return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness); 1.20632 + static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max()); 1.20633 + const float 1.20634 + nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0), 1.20635 + nbrightness = brightness<0?0:(brightness>2?2:brightness); 1.20636 + const int whz = width*height*depth, twhz = texture.width*texture.height*texture.depth, offx = dim*whz-1; 1.20637 + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, 1.20638 + ntx0 = tx0, nty0 = ty0, ntx1 = tx1, nty1 = ty1, ntx2 = tx2, nty2 = ty2; 1.20639 + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1); 1.20640 + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2); 1.20641 + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2); 1.20642 + if (ny0>=dimy() || ny2<0) return *this; 1.20643 + _cimg_for_triangle3(*this,xleft0,txleft0,tyleft0,xright0,txright0,tyright0,y, 1.20644 + nx0,ny0,ntx0,nty0,nx1,ny1,ntx1,nty1,nx2,ny2,ntx2,nty2) { 1.20645 + int 1.20646 + xleft = xleft0, xright = xright0, 1.20647 + txleft = txleft0, txright = txright0, 1.20648 + tyleft = tyleft0, tyright = tyright0; 1.20649 + if (xright<xleft) cimg::swap(xleft,xright,txleft,txright,tyleft,tyright); 1.20650 + const int 1.20651 + dx = xright - xleft, 1.20652 + dtx = txright>txleft?txright - txleft:txleft - txright, 1.20653 + dty = tyright>tyleft?tyright - tyleft:tyleft - tyright, 1.20654 + rtx = dx?(txright - txleft)/dx:0, 1.20655 + rty = dx?(tyright - tyleft)/dx:0, 1.20656 + stx = txright>txleft?1:-1, 1.20657 + sty = tyright>tyleft?1:-1, 1.20658 + ndtx = dtx - (dx?dx*(dtx/dx):0), 1.20659 + ndty = dty - (dx?dx*(dty/dx):0); 1.20660 + int errtx = dx>>1, errty = errtx; 1.20661 + if (xleft<0 && dx) { 1.20662 + txleft-=xleft*(txright - txleft)/dx; 1.20663 + tyleft-=xleft*(tyright - tyleft)/dx; 1.20664 + } 1.20665 + if (xleft<0) xleft = 0; 1.20666 + if (xright>=dimx()-1) xright = dimx()-1; 1.20667 + T* ptrd = ptr(xleft,y,0,0); 1.20668 + if (opacity>=1) { 1.20669 + if (nbrightness==1) for (int x = xleft; x<=xright; ++x) { 1.20670 + const tc *col = texture.ptr(txleft,tyleft); 1.20671 + cimg_forV(*this,k) { 1.20672 + *ptrd = (T)*col; 1.20673 + ptrd+=whz; col+=twhz; 1.20674 + } 1.20675 + ptrd-=offx; 1.20676 + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); 1.20677 + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); 1.20678 + } else if (nbrightness<1) for (int x = xleft; x<=xright; ++x) { 1.20679 + const tc *col = texture.ptr(txleft,tyleft); 1.20680 + cimg_forV(*this,k) { 1.20681 + *ptrd = (T)(nbrightness**col); 1.20682 + ptrd+=whz; col+=twhz; 1.20683 + } 1.20684 + ptrd-=offx; 1.20685 + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); 1.20686 + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); 1.20687 + } else for (int x = xleft; x<=xright; ++x) { 1.20688 + const tc *col = texture.ptr(txleft,tyleft); 1.20689 + cimg_forV(*this,k) { 1.20690 + *ptrd = (T)((2-nbrightness)**(col++) + (nbrightness-1)*maxval); 1.20691 + ptrd+=whz; col+=twhz; 1.20692 + } 1.20693 + ptrd-=offx; 1.20694 + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); 1.20695 + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); 1.20696 + } 1.20697 + } else { 1.20698 + if (nbrightness==1) for (int x = xleft; x<=xright; ++x) { 1.20699 + const tc *col = texture.ptr(txleft,tyleft); 1.20700 + cimg_forV(*this,k) { 1.20701 + *ptrd = (T)(nopacity**col + *ptrd*copacity); 1.20702 + ptrd+=whz; col+=twhz; 1.20703 + } 1.20704 + ptrd-=offx; 1.20705 + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); 1.20706 + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); 1.20707 + } else if (nbrightness<1) for (int x = xleft; x<=xright; ++x) { 1.20708 + const tc *col = texture.ptr(txleft,tyleft); 1.20709 + cimg_forV(*this,k) { 1.20710 + *ptrd = (T)(nopacity*nbrightness**col + *ptrd*copacity); 1.20711 + ptrd+=whz; col+=twhz; 1.20712 + } 1.20713 + ptrd-=offx; 1.20714 + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); 1.20715 + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); 1.20716 + } else for (int x = xleft; x<=xright; ++x) { 1.20717 + const tc *col = texture.ptr(txleft,tyleft); 1.20718 + cimg_forV(*this,k) { 1.20719 + const T val = (T)((2-nbrightness)**(col++) + (nbrightness-1)*maxval); 1.20720 + *ptrd = (T)(nopacity*val + *ptrd*copacity); 1.20721 + ptrd+=whz; col+=twhz; 1.20722 + } 1.20723 + ptrd-=offx; 1.20724 + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); 1.20725 + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); 1.20726 + } 1.20727 + } 1.20728 + } 1.20729 + return *this; 1.20730 + } 1.20731 + 1.20732 + //! Draw a 2D textured triangle, with perspective correction. 1.20733 + template<typename tc> 1.20734 + CImg<T>& draw_triangle(const int x0, const int y0, const float z0, 1.20735 + const int x1, const int y1, const float z1, 1.20736 + const int x2, const int y2, const float z2, 1.20737 + const CImg<tc>& texture, 1.20738 + const int tx0, const int ty0, 1.20739 + const int tx1, const int ty1, 1.20740 + const int tx2, const int ty2, 1.20741 + const float opacity=1, 1.20742 + const float brightness=1) { 1.20743 + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; 1.20744 + if (!texture || texture.dim<dim) 1.20745 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified texture (%u,%u,%u,%u,%p) is not a valid argument.", 1.20746 + pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data); 1.20747 + 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); 1.20748 + static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max()); 1.20749 + const float 1.20750 + nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0), 1.20751 + nbrightness = brightness<0?0:(brightness>2?2:brightness); 1.20752 + const int whz = width*height*depth, twhz = texture.width*texture.height*texture.depth, offx = dim*whz-1; 1.20753 + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2; 1.20754 + float 1.20755 + ntx0 = tx0/z0, nty0 = ty0/z0, 1.20756 + ntx1 = tx1/z1, nty1 = ty1/z1, 1.20757 + ntx2 = tx2/z2, nty2 = ty2/z2, 1.20758 + nz0 = 1/z0, nz1 = 1/z1, nz2 = 1/z2; 1.20759 + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nz0,nz1); 1.20760 + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nz0,nz2); 1.20761 + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nz1,nz2); 1.20762 + if (ny0>=dimy() || ny2<0) return *this; 1.20763 + float 1.20764 + ptxl = (ntx1 - ntx0)/(ny1 - ny0), 1.20765 + ptxr = (ntx2 - ntx0)/(ny2 - ny0), 1.20766 + ptxn = (ntx2 - ntx1)/(ny2 - ny1), 1.20767 + ptyl = (nty1 - nty0)/(ny1 - ny0), 1.20768 + ptyr = (nty2 - nty0)/(ny2 - ny0), 1.20769 + ptyn = (nty2 - nty1)/(ny2 - ny1), 1.20770 + pzl = (nz1 - nz0)/(ny1 - ny0), 1.20771 + pzr = (nz2 - nz0)/(ny2 - ny0), 1.20772 + pzn = (nz2 - nz1)/(ny2 - ny1), 1.20773 + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), 1.20774 + txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)), 1.20775 + tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)), 1.20776 + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))), 1.20777 + txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))):(ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))), 1.20778 + tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))):(ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1))); 1.20779 + _cimg_for_triangle1(*this,xleft0,xright0,y,nx0,ny0,nx1,ny1,nx2,ny2) { 1.20780 + if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; } 1.20781 + int xleft = xleft0, xright = xright0; 1.20782 + float 1.20783 + zleft = zl, zright = zr, 1.20784 + txleft = txl, txright = txr, 1.20785 + tyleft = tyl, tyright = tyr; 1.20786 + if (xright<xleft) cimg::swap(xleft,xright,zleft,zright,txleft,txright,tyleft,tyright); 1.20787 + const int dx = xright - xleft; 1.20788 + const float 1.20789 + pentez = (zright - zleft)/dx, 1.20790 + pentetx = (txright - txleft)/dx, 1.20791 + pentety = (tyright - tyleft)/dx; 1.20792 + if (xleft<0 && dx) { 1.20793 + zleft-=xleft*(zright - zleft)/dx; 1.20794 + txleft-=xleft*(txright - txleft)/dx; 1.20795 + tyleft-=xleft*(tyright - tyleft)/dx; 1.20796 + } 1.20797 + if (xleft<0) xleft = 0; 1.20798 + if (xright>=dimx()-1) xright = dimx()-1; 1.20799 + T* ptrd = ptr(xleft,y,0,0); 1.20800 + if (opacity>=1) { 1.20801 + if (nbrightness==1) for (int x = xleft; x<=xright; ++x) { 1.20802 + const float invz = 1/zleft; 1.20803 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.20804 + cimg_forV(*this,k) { 1.20805 + *ptrd = (T)*col; 1.20806 + ptrd+=whz; col+=twhz; 1.20807 + } 1.20808 + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.20809 + } else if (nbrightness<1) for (int x=xleft; x<=xright; ++x) { 1.20810 + const float invz = 1/zleft; 1.20811 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.20812 + cimg_forV(*this,k) { 1.20813 + *ptrd = (T)(nbrightness**col); 1.20814 + ptrd+=whz; col+=twhz; 1.20815 + } 1.20816 + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.20817 + } else for (int x = xleft; x<=xright; ++x) { 1.20818 + const float invz = 1/zleft; 1.20819 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.20820 + cimg_forV(*this,k) { 1.20821 + *ptrd = (T)((2-nbrightness)**col + (nbrightness-1)*maxval); 1.20822 + ptrd+=whz; col+=twhz; 1.20823 + } 1.20824 + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.20825 + } 1.20826 + } else { 1.20827 + if (nbrightness==1) for (int x = xleft; x<=xright; ++x) { 1.20828 + const float invz = 1/zleft; 1.20829 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.20830 + cimg_forV(*this,k) { 1.20831 + *ptrd = (T)(nopacity**col + *ptrd*copacity); 1.20832 + ptrd+=whz; col+=twhz; 1.20833 + } 1.20834 + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.20835 + } else if (nbrightness<1) for (int x = xleft; x<=xright; ++x) { 1.20836 + const float invz = 1/zleft; 1.20837 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.20838 + cimg_forV(*this,k) { 1.20839 + *ptrd = (T)(nopacity*nbrightness**col + *ptrd*copacity); 1.20840 + ptrd+=whz; col+=twhz; 1.20841 + } 1.20842 + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.20843 + } else for (int x = xleft; x<=xright; ++x) { 1.20844 + const float invz = 1/zleft; 1.20845 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.20846 + cimg_forV(*this,k) { 1.20847 + const T val = (T)((2-nbrightness)**col + (nbrightness-1)*maxval); 1.20848 + *ptrd = (T)(nopacity*val + *ptrd*copacity); 1.20849 + ptrd+=whz; col+=twhz; 1.20850 + } 1.20851 + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.20852 + } 1.20853 + } 1.20854 + zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl; 1.20855 + } 1.20856 + return *this; 1.20857 + } 1.20858 + 1.20859 + //! Draw a 2D textured triangle, with z-buffering and perspective correction. 1.20860 + template<typename tc> 1.20861 + CImg<T>& draw_triangle(float *const zbuffer, 1.20862 + const int x0, const int y0, const float z0, 1.20863 + const int x1, const int y1, const float z1, 1.20864 + const int x2, const int y2, const float z2, 1.20865 + const CImg<tc>& texture, 1.20866 + const int tx0, const int ty0, 1.20867 + const int tx1, const int ty1, 1.20868 + const int tx2, const int ty2, 1.20869 + const float opacity=1, 1.20870 + const float brightness=1) { 1.20871 + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; 1.20872 + if (!texture || texture.dim<dim) 1.20873 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified texture (%u,%u,%u,%u,%p) is not a valid argument.", 1.20874 + pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data); 1.20875 + 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); 1.20876 + static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max()); 1.20877 + const float 1.20878 + nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0), 1.20879 + nbrightness = brightness<0?0:(brightness>2?2:brightness); 1.20880 + const int whz = width*height*depth, twhz = texture.width*texture.height*texture.depth, offx = dim*whz; 1.20881 + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2; 1.20882 + float 1.20883 + ntx0 = tx0/z0, nty0 = ty0/z0, 1.20884 + ntx1 = tx1/z1, nty1 = ty1/z1, 1.20885 + ntx2 = tx2/z2, nty2 = ty2/z2, 1.20886 + nz0 = 1/z0, nz1 = 1/z1, nz2 = 1/z2; 1.20887 + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nz0,nz1); 1.20888 + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nz0,nz2); 1.20889 + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nz1,nz2); 1.20890 + if (ny0>=dimy() || ny2<0) return *this; 1.20891 + float 1.20892 + ptxl = (ntx1 - ntx0)/(ny1 - ny0), 1.20893 + ptxr = (ntx2 - ntx0)/(ny2 - ny0), 1.20894 + ptxn = (ntx2 - ntx1)/(ny2 - ny1), 1.20895 + ptyl = (nty1 - nty0)/(ny1 - ny0), 1.20896 + ptyr = (nty2 - nty0)/(ny2 - ny0), 1.20897 + ptyn = (nty2 - nty1)/(ny2 - ny1), 1.20898 + pzl = (nz1 - nz0)/(ny1 - ny0), 1.20899 + pzr = (nz2 - nz0)/(ny2 - ny0), 1.20900 + pzn = (nz2 - nz1)/(ny2 - ny1), 1.20901 + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), 1.20902 + txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)), 1.20903 + tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)), 1.20904 + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))), 1.20905 + txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))):(ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))), 1.20906 + tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))):(ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1))); 1.20907 + _cimg_for_triangle1(*this,xleft0,xright0,y,nx0,ny0,nx1,ny1,nx2,ny2) { 1.20908 + if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; } 1.20909 + int xleft = xleft0, xright = xright0; 1.20910 + float 1.20911 + zleft = zl, zright = zr, 1.20912 + txleft = txl, txright = txr, 1.20913 + tyleft = tyl, tyright = tyr; 1.20914 + if (xright<xleft) cimg::swap(xleft,xright,zleft,zright,txleft,txright,tyleft,tyright); 1.20915 + const int dx = xright - xleft; 1.20916 + const float 1.20917 + pentez = (zright - zleft)/dx, 1.20918 + pentetx = (txright - txleft)/dx, 1.20919 + pentety = (tyright - tyleft)/dx; 1.20920 + if (xleft<0 && dx) { 1.20921 + zleft-=xleft*(zright - zleft)/dx; 1.20922 + txleft-=xleft*(txright - txleft)/dx; 1.20923 + tyleft-=xleft*(tyright - tyleft)/dx; 1.20924 + } 1.20925 + if (xleft<0) xleft = 0; 1.20926 + if (xright>=dimx()-1) xright = dimx()-1; 1.20927 + T *ptrd = ptr(xleft,y,0,0); 1.20928 + float *ptrz = zbuffer + xleft + y*width; 1.20929 + if (opacity>=1) { 1.20930 + if (nbrightness==1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { 1.20931 + if (zleft>*ptrz) { 1.20932 + *ptrz = zleft; 1.20933 + const float invz = 1/zleft; 1.20934 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.20935 + cimg_forV(*this,k) { 1.20936 + *ptrd = (T)*col; 1.20937 + ptrd+=whz; col+=twhz; 1.20938 + } 1.20939 + ptrd-=offx; 1.20940 + } 1.20941 + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.20942 + } else if (nbrightness<1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { 1.20943 + if (zleft>*ptrz) { 1.20944 + *ptrz = zleft; 1.20945 + const float invz = 1/zleft; 1.20946 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.20947 + cimg_forV(*this,k) { 1.20948 + *ptrd = (T)(nbrightness**col); 1.20949 + ptrd+=whz; col+=twhz; 1.20950 + } 1.20951 + ptrd-=offx; 1.20952 + } 1.20953 + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.20954 + } else for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { 1.20955 + if (zleft>*ptrz) { 1.20956 + *ptrz = zleft; 1.20957 + const float invz = 1/zleft; 1.20958 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.20959 + cimg_forV(*this,k) { 1.20960 + *ptrd = (T)((2-nbrightness)**col + (nbrightness-1)*maxval); 1.20961 + ptrd+=whz; col+=twhz; 1.20962 + } 1.20963 + ptrd-=offx; 1.20964 + } 1.20965 + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.20966 + } 1.20967 + } else { 1.20968 + if (nbrightness==1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { 1.20969 + if (zleft>*ptrz) { 1.20970 + *ptrz = zleft; 1.20971 + const float invz = 1/zleft; 1.20972 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.20973 + cimg_forV(*this,k) { 1.20974 + *ptrd = (T)(nopacity**col + *ptrd*copacity); 1.20975 + ptrd+=whz; col+=twhz; 1.20976 + } 1.20977 + ptrd-=offx; 1.20978 + } 1.20979 + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.20980 + } else if (nbrightness<1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { 1.20981 + if (zleft>*ptrz) { 1.20982 + *ptrz = zleft; 1.20983 + const float invz = 1/zleft; 1.20984 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.20985 + cimg_forV(*this,k) { 1.20986 + *ptrd = (T)(nopacity*nbrightness**col + *ptrd*copacity); 1.20987 + ptrd+=whz; col+=twhz; 1.20988 + } 1.20989 + ptrd-=offx; 1.20990 + } 1.20991 + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.20992 + } else for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { 1.20993 + if (zleft>*ptrz) { 1.20994 + *ptrz = zleft; 1.20995 + const float invz = 1/zleft; 1.20996 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.20997 + cimg_forV(*this,k) { 1.20998 + const T val = (T)((2-nbrightness)**col + (nbrightness-1)*maxval); 1.20999 + *ptrd = (T)(nopacity*val + *ptrd*copacity); 1.21000 + ptrd+=whz; col+=twhz; 1.21001 + } 1.21002 + ptrd-=offx; 1.21003 + } 1.21004 + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.21005 + } 1.21006 + } 1.21007 + zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl; 1.21008 + } 1.21009 + return *this; 1.21010 + } 1.21011 + 1.21012 + //! Draw a 2D Pseudo-Phong-shaded triangle. 1.21013 + /** 1.21014 + \param x0 = X-coordinate of the first corner in the instance image. 1.21015 + \param y0 = Y-coordinate of the first corner in the instance image. 1.21016 + \param x1 = X-coordinate of the second corner in the instance image. 1.21017 + \param y1 = Y-coordinate of the second corner in the instance image. 1.21018 + \param x2 = X-coordinate of the third corner in the instance image. 1.21019 + \param y2 = Y-coordinate of the third corner in the instance image. 1.21020 + \param color = array of dimv() values of type \c T, defining the global drawing color. 1.21021 + \param light = light image. 1.21022 + \param lx0 = X-coordinate of the first corner in the light image. 1.21023 + \param ly0 = Y-coordinate of the first corner in the light image. 1.21024 + \param lx1 = X-coordinate of the second corner in the light image. 1.21025 + \param ly1 = Y-coordinate of the second corner in the light image. 1.21026 + \param lx2 = X-coordinate of the third corner in the light image. 1.21027 + \param ly2 = Y-coordinate of the third corner in the light image. 1.21028 + \param opacity = opacity of the drawing. 1.21029 + \note Clipping is supported, but texture coordinates do not support clipping. 1.21030 + **/ 1.21031 + template<typename tc, typename tl> 1.21032 + CImg<T>& draw_triangle(const int x0, const int y0, 1.21033 + const int x1, const int y1, 1.21034 + const int x2, const int y2, 1.21035 + const tc *const color, 1.21036 + const CImg<tl>& light, 1.21037 + const int lx0, const int ly0, 1.21038 + const int lx1, const int ly1, 1.21039 + const int lx2, const int ly2, 1.21040 + const float opacity=1) { 1.21041 + if (is_empty()) return *this; 1.21042 + if (!color) 1.21043 + throw CImgArgumentException("CImg<%s>::draw_triangle : Specified color is (null).", 1.21044 + pixel_type()); 1.21045 + if (!light) 1.21046 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified light texture (%u,%u,%u,%u,%p) is empty.", 1.21047 + pixel_type(),light.width,light.height,light.depth,light.dim,light.data); 1.21048 + if (is_overlapped(light)) return draw_triangle(x0,y0,x1,y1,x2,y2,color,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); 1.21049 + static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max()); 1.21050 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.21051 + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, 1.21052 + nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2; 1.21053 + const int whz = width*height*depth, offx = dim*whz-1; 1.21054 + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nlx0,nlx1,nly0,nly1); 1.21055 + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,nlx0,nlx2,nly0,nly2); 1.21056 + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,nlx1,nlx2,nly1,nly2); 1.21057 + if (ny0>=dimy() || ny2<0) return *this; 1.21058 + _cimg_for_triangle3(*this,xleft0,lxleft0,lyleft0,xright0,lxright0,lyright0,y, 1.21059 + nx0,ny0,nlx0,nly0,nx1,ny1,nlx1,nly1,nx2,ny2,nlx2,nly2) { 1.21060 + int 1.21061 + xleft = xleft0, xright = xright0, 1.21062 + lxleft = lxleft0, lxright = lxright0, 1.21063 + lyleft = lyleft0, lyright = lyright0; 1.21064 + if (xright<xleft) cimg::swap(xleft,xright,lxleft,lxright,lyleft,lyright); 1.21065 + const int 1.21066 + dx = xright - xleft, 1.21067 + dlx = lxright>lxleft?lxright - lxleft:lxleft - lxright, 1.21068 + dly = lyright>lyleft?lyright - lyleft:lyleft - lyright, 1.21069 + rlx = dx?(lxright - lxleft)/dx:0, 1.21070 + rly = dx?(lyright - lyleft)/dx:0, 1.21071 + slx = lxright>lxleft?1:-1, 1.21072 + sly = lyright>lyleft?1:-1, 1.21073 + ndlx = dlx - (dx?dx*(dlx/dx):0), 1.21074 + ndly = dly - (dx?dx*(dly/dx):0); 1.21075 + int errlx = dx>>1, errly = errlx; 1.21076 + if (xleft<0 && dx) { 1.21077 + lxleft-=xleft*(lxright - lxleft)/dx; 1.21078 + lyleft-=xleft*(lyright - lyleft)/dx; 1.21079 + } 1.21080 + if (xleft<0) xleft = 0; 1.21081 + if (xright>=dimx()-1) xright = dimx()-1; 1.21082 + T* ptrd = ptr(xleft,y,0,0); 1.21083 + if (opacity>=1) for (int x = xleft; x<=xright; ++x) { 1.21084 + const tl l = light(lxleft,lyleft); 1.21085 + const tc *col = color; 1.21086 + cimg_forV(*this,k) { 1.21087 + *ptrd = (T)(l<1?l**(col++):((2-l)**(col++)+(l-1)*maxval)); 1.21088 + ptrd+=whz; 1.21089 + } 1.21090 + ptrd-=offx; 1.21091 + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); 1.21092 + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); 1.21093 + } else for (int x = xleft; x<=xright; ++x) { 1.21094 + const tl l = light(lxleft,lyleft); 1.21095 + const tc *col = color; 1.21096 + cimg_forV(*this,k) { 1.21097 + const T val = (T)(l<1?l**(col++):((2-l)**(col++)+(l-1)*maxval)); 1.21098 + *ptrd = (T)(nopacity*val + *ptrd*copacity); 1.21099 + ptrd+=whz; 1.21100 + } 1.21101 + ptrd-=offx; 1.21102 + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); 1.21103 + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); 1.21104 + } 1.21105 + } 1.21106 + return *this; 1.21107 + } 1.21108 + 1.21109 + //! Draw a 2D Pseudo-Phong-shaded triangle. 1.21110 + template<typename tc, typename tl> 1.21111 + CImg<T>& draw_triangle(const int x0, const int y0, 1.21112 + const int x1, const int y1, 1.21113 + const int x2, const int y2, 1.21114 + const CImg<tc>& color, 1.21115 + const CImg<tl>& light, 1.21116 + const int lx0, const int ly0, 1.21117 + const int lx1, const int ly1, 1.21118 + const int lx2, const int ly2, 1.21119 + const float opacity=1) { 1.21120 + return draw_triangle(x0,y0,x1,y1,x2,y2,color.data,light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); 1.21121 + } 1.21122 + 1.21123 + //! Draw a 2D Pseudo-Phong-shaded triangle, with z-buffering. 1.21124 + template<typename tc, typename tl> 1.21125 + CImg<T>& draw_triangle(float *const zbuffer, 1.21126 + const int x0, const int y0, const float z0, 1.21127 + const int x1, const int y1, const float z1, 1.21128 + const int x2, const int y2, const float z2, 1.21129 + const tc *const color, 1.21130 + const CImg<tl>& light, 1.21131 + const int lx0, const int ly0, 1.21132 + const int lx1, const int ly1, 1.21133 + const int lx2, const int ly2, 1.21134 + const float opacity=1) { 1.21135 + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; 1.21136 + if (!color) 1.21137 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified color is (null).", 1.21138 + pixel_type()); 1.21139 + if (!light) 1.21140 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified light texture (%u,%u,%u,%u,%p) is empty.", 1.21141 + pixel_type(),light.width,light.height,light.depth,light.dim,light.data); 1.21142 + if (is_overlapped(light)) return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color, 1.21143 + +light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); 1.21144 + static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max()); 1.21145 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.21146 + const int whz = width*height*depth, offx = dim*whz; 1.21147 + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, 1.21148 + nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2; 1.21149 + float nz0 = 1/z0, nz1 = 1/z1, nz2 = 1/z2; 1.21150 + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nlx0,nlx1,nly0,nly1,nz0,nz1); 1.21151 + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,nlx0,nlx2,nly0,nly2,nz0,nz2); 1.21152 + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,nlx1,nlx2,nly1,nly2,nz1,nz2); 1.21153 + if (ny0>=dimy() || ny2<0) return *this; 1.21154 + float 1.21155 + pzl = (nz1 - nz0)/(ny1 - ny0), 1.21156 + pzr = (nz2 - nz0)/(ny2 - ny0), 1.21157 + pzn = (nz2 - nz1)/(ny2 - ny1), 1.21158 + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), 1.21159 + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))); 1.21160 + _cimg_for_triangle3(*this,xleft0,lxleft0,lyleft0,xright0,lxright0,lyright0,y, 1.21161 + nx0,ny0,nlx0,nly0,nx1,ny1,nlx1,nly1,nx2,ny2,nlx2,nly2) { 1.21162 + if (y==ny1) { zl = nz1; pzl = pzn; } 1.21163 + int 1.21164 + xleft = xleft0, xright = xright0, 1.21165 + lxleft = lxleft0, lxright = lxright0, 1.21166 + lyleft = lyleft0, lyright = lyright0; 1.21167 + float zleft = zl, zright = zr; 1.21168 + if (xright<xleft) cimg::swap(xleft,xright,zleft,zright,lxleft,lxright,lyleft,lyright); 1.21169 + const int 1.21170 + dx = xright - xleft, 1.21171 + dlx = lxright>lxleft?lxright - lxleft:lxleft - lxright, 1.21172 + dly = lyright>lyleft?lyright - lyleft:lyleft - lyright, 1.21173 + rlx = dx?(lxright - lxleft)/dx:0, 1.21174 + rly = dx?(lyright - lyleft)/dx:0, 1.21175 + slx = lxright>lxleft?1:-1, 1.21176 + sly = lyright>lyleft?1:-1, 1.21177 + ndlx = dlx - (dx?dx*(dlx/dx):0), 1.21178 + ndly = dly - (dx?dx*(dly/dx):0); 1.21179 + const float pentez = (zright - zleft)/dx; 1.21180 + int errlx = dx>>1, errly = errlx; 1.21181 + if (xleft<0 && dx) { 1.21182 + zleft-=xleft*(zright - zleft)/dx; 1.21183 + lxleft-=xleft*(lxright - lxleft)/dx; 1.21184 + lyleft-=xleft*(lyright - lyleft)/dx; 1.21185 + } 1.21186 + if (xleft<0) xleft = 0; 1.21187 + if (xright>=dimx()-1) xright = dimx()-1; 1.21188 + T *ptrd = ptr(xleft,y,0,0); 1.21189 + float *ptrz = zbuffer + xleft + y*width; 1.21190 + if (opacity>=1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { 1.21191 + if (zleft>*ptrz) { 1.21192 + *ptrz = zleft; 1.21193 + const tl l = light(lxleft,lyleft); 1.21194 + const tc *col = color; 1.21195 + cimg_forV(*this,k) { 1.21196 + const tc cval = *(col++); 1.21197 + *ptrd = (T)(l<1?l*cval:(2-l)*cval+(l-1)*maxval); 1.21198 + ptrd+=whz; 1.21199 + } 1.21200 + ptrd-=offx; 1.21201 + } 1.21202 + zleft+=pentez; 1.21203 + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); 1.21204 + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); 1.21205 + } else for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { 1.21206 + if (zleft>*ptrz) { 1.21207 + *ptrz = zleft; 1.21208 + const tl l = light(lxleft,lyleft); 1.21209 + const tc *col = color; 1.21210 + cimg_forV(*this,k) { 1.21211 + const tc cval = *(col++); 1.21212 + const T val = (T)(l<1?l*cval:(2-l)*cval+(l-1)*maxval); 1.21213 + *ptrd = (T)(nopacity*val + *ptrd*copacity); 1.21214 + ptrd+=whz; 1.21215 + } 1.21216 + ptrd-=offx; 1.21217 + } 1.21218 + zleft+=pentez; 1.21219 + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); 1.21220 + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); 1.21221 + } 1.21222 + zr+=pzr; zl+=pzl; 1.21223 + } 1.21224 + return *this; 1.21225 + } 1.21226 + 1.21227 + //! Draw a 2D Pseudo-Phong-shaded triangle, with z-buffering. 1.21228 + template<typename tc, typename tl> 1.21229 + CImg<T>& draw_triangle(float *const zbuffer, 1.21230 + const int x0, const int y0, const float z0, 1.21231 + const int x1, const int y1, const float z1, 1.21232 + const int x2, const int y2, const float z2, 1.21233 + const CImg<tc>& color, 1.21234 + const CImg<tl>& light, 1.21235 + const int lx0, const int ly0, 1.21236 + const int lx1, const int ly1, 1.21237 + const int lx2, const int ly2, 1.21238 + const float opacity=1) { 1.21239 + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color.data,light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); 1.21240 + } 1.21241 + 1.21242 + //! Draw a 2D Gouraud-shaded textured triangle. 1.21243 + /** 1.21244 + \param x0 = X-coordinate of the first corner in the instance image. 1.21245 + \param y0 = Y-coordinate of the first corner in the instance image. 1.21246 + \param x1 = X-coordinate of the second corner in the instance image. 1.21247 + \param y1 = Y-coordinate of the second corner in the instance image. 1.21248 + \param x2 = X-coordinate of the third corner in the instance image. 1.21249 + \param y2 = Y-coordinate of the third corner in the instance image. 1.21250 + \param texture = texture image used to fill the triangle. 1.21251 + \param tx0 = X-coordinate of the first corner in the texture image. 1.21252 + \param ty0 = Y-coordinate of the first corner in the texture image. 1.21253 + \param tx1 = X-coordinate of the second corner in the texture image. 1.21254 + \param ty1 = Y-coordinate of the second corner in the texture image. 1.21255 + \param tx2 = X-coordinate of the third corner in the texture image. 1.21256 + \param ty2 = Y-coordinate of the third corner in the texture image. 1.21257 + \param brightness0 = brightness value of the first corner. 1.21258 + \param brightness1 = brightness value of the second corner. 1.21259 + \param brightness2 = brightness value of the third corner. 1.21260 + \param opacity = opacity of the drawing. 1.21261 + \note Clipping is supported, but texture coordinates do not support clipping. 1.21262 + **/ 1.21263 + template<typename tc> 1.21264 + CImg<T>& draw_triangle(const int x0, const int y0, 1.21265 + const int x1, const int y1, 1.21266 + const int x2, const int y2, 1.21267 + const CImg<tc>& texture, 1.21268 + const int tx0, const int ty0, 1.21269 + const int tx1, const int ty1, 1.21270 + const int tx2, const int ty2, 1.21271 + const float brightness0, 1.21272 + const float brightness1, 1.21273 + const float brightness2, 1.21274 + const float opacity=1) { 1.21275 + if (is_empty()) return *this; 1.21276 + if (!texture || texture.dim<dim) 1.21277 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified texture (%u,%u,%u,%u,%p) is not a valid argument.", 1.21278 + pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data); 1.21279 + if (is_overlapped(texture)) 1.21280 + return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,brightness0,brightness1,brightness2,opacity); 1.21281 + static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max()); 1.21282 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.21283 + const int whz = width*height*depth, twhz = texture.width*texture.height*texture.depth, offx = dim*whz-1; 1.21284 + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, 1.21285 + ntx0 = tx0, nty0 = ty0, ntx1 = tx1, nty1 = ty1, ntx2 = tx2, nty2 = ty2, 1.21286 + nc0 = (int)((brightness0<0?0:(brightness0>2?2:brightness0))*256), 1.21287 + nc1 = (int)((brightness1<0?0:(brightness1>2?2:brightness1))*256), 1.21288 + nc2 = (int)((brightness2<0?0:(brightness2>2?2:brightness2))*256); 1.21289 + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nc0,nc1); 1.21290 + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nc0,nc2); 1.21291 + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nc1,nc2); 1.21292 + if (ny0>=dimy() || ny2<0) return *this; 1.21293 + _cimg_for_triangle4(*this,xleft0,cleft0,txleft0,tyleft0,xright0,cright0,txright0,tyright0,y, 1.21294 + nx0,ny0,nc0,ntx0,nty0,nx1,ny1,nc1,ntx1,nty1,nx2,ny2,nc2,ntx2,nty2) { 1.21295 + int 1.21296 + xleft = xleft0, xright = xright0, 1.21297 + cleft = cleft0, cright = cright0, 1.21298 + txleft = txleft0, txright = txright0, 1.21299 + tyleft = tyleft0, tyright = tyright0; 1.21300 + if (xright<xleft) cimg::swap(xleft,xright,cleft,cright,txleft,txright,tyleft,tyright); 1.21301 + const int 1.21302 + dx = xright - xleft, 1.21303 + dc = cright>cleft?cright - cleft:cleft - cright, 1.21304 + dtx = txright>txleft?txright - txleft:txleft - txright, 1.21305 + dty = tyright>tyleft?tyright - tyleft:tyleft - tyright, 1.21306 + rc = dx?(cright - cleft)/dx:0, 1.21307 + rtx = dx?(txright - txleft)/dx:0, 1.21308 + rty = dx?(tyright - tyleft)/dx:0, 1.21309 + sc = cright>cleft?1:-1, 1.21310 + stx = txright>txleft?1:-1, 1.21311 + sty = tyright>tyleft?1:-1, 1.21312 + ndc = dc - (dx?dx*(dc/dx):0), 1.21313 + ndtx = dtx - (dx?dx*(dtx/dx):0), 1.21314 + ndty = dty - (dx?dx*(dty/dx):0); 1.21315 + int errc = dx>>1, errtx = errc, errty = errc; 1.21316 + if (xleft<0 && dx) { 1.21317 + cleft-=xleft*(cright - cleft)/dx; 1.21318 + txleft-=xleft*(txright - txleft)/dx; 1.21319 + tyleft-=xleft*(tyright - tyleft)/dx; 1.21320 + } 1.21321 + if (xleft<0) xleft = 0; 1.21322 + if (xright>=dimx()-1) xright = dimx()-1; 1.21323 + T* ptrd = ptr(xleft,y,0,0); 1.21324 + if (opacity>=1) for (int x = xleft; x<=xright; ++x) { 1.21325 + const tc *col = texture.ptr(txleft,tyleft); 1.21326 + cimg_forV(*this,k) { 1.21327 + *ptrd = (T)(cleft<256?cleft**col/256:((512-cleft)**col+(cleft-256)*maxval)/256); 1.21328 + ptrd+=whz; col+=twhz; 1.21329 + } 1.21330 + ptrd-=offx; 1.21331 + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); 1.21332 + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); 1.21333 + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); 1.21334 + } else for (int x = xleft; x<=xright; ++x) { 1.21335 + const tc *col = texture.ptr(txleft,tyleft); 1.21336 + cimg_forV(*this,k) { 1.21337 + const T val = (T)(cleft<256?cleft**col/256:((512-cleft)**col+(cleft-256)*maxval)/256); 1.21338 + *ptrd = (T)(nopacity*val + *ptrd*copacity); 1.21339 + ptrd+=whz; col+=twhz; 1.21340 + } 1.21341 + ptrd-=offx; 1.21342 + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); 1.21343 + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); 1.21344 + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); 1.21345 + } 1.21346 + } 1.21347 + return *this; 1.21348 + } 1.21349 + 1.21350 + //! Draw a 2D Gouraud-shaded textured triangle, with perspective correction. 1.21351 + template<typename tc> 1.21352 + CImg<T>& draw_triangle(const int x0, const int y0, const float z0, 1.21353 + const int x1, const int y1, const float z1, 1.21354 + const int x2, const int y2, const float z2, 1.21355 + const CImg<tc>& texture, 1.21356 + const int tx0, const int ty0, 1.21357 + const int tx1, const int ty1, 1.21358 + const int tx2, const int ty2, 1.21359 + const float brightness0, 1.21360 + const float brightness1, 1.21361 + const float brightness2, 1.21362 + const float opacity=1) { 1.21363 + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; 1.21364 + if (!texture || texture.dim<dim) 1.21365 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified texture (%u,%u,%u,%u,%p) is not a valid argument.", 1.21366 + pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data); 1.21367 + if (is_overlapped(texture)) return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2, 1.21368 + brightness0,brightness1,brightness2,opacity); 1.21369 + static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max()); 1.21370 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.21371 + const int whz = width*height*depth, twhz = texture.width*texture.height*texture.depth, offx = dim*whz-1; 1.21372 + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, 1.21373 + nc0 = (int)((brightness0<0?0:(brightness0>2?2:brightness0))*256), 1.21374 + nc1 = (int)((brightness1<0?0:(brightness1>2?2:brightness1))*256), 1.21375 + nc2 = (int)((brightness2<0?0:(brightness2>2?2:brightness2))*256); 1.21376 + float 1.21377 + ntx0 = tx0/z0, nty0 = ty0/z0, 1.21378 + ntx1 = tx1/z1, nty1 = ty1/z1, 1.21379 + ntx2 = tx2/z2, nty2 = ty2/z2, 1.21380 + nz0 = 1/z0, nz1 = 1/z1, nz2 = 1/z2; 1.21381 + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nz0,nz1,nc0,nc1); 1.21382 + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nz0,nz2,nc0,nc2); 1.21383 + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nz1,nz2,nc1,nc2); 1.21384 + if (ny0>=dimy() || ny2<0) return *this; 1.21385 + float 1.21386 + ptxl = (ntx1 - ntx0)/(ny1 - ny0), 1.21387 + ptxr = (ntx2 - ntx0)/(ny2 - ny0), 1.21388 + ptxn = (ntx2 - ntx1)/(ny2 - ny1), 1.21389 + ptyl = (nty1 - nty0)/(ny1 - ny0), 1.21390 + ptyr = (nty2 - nty0)/(ny2 - ny0), 1.21391 + ptyn = (nty2 - nty1)/(ny2 - ny1), 1.21392 + pzl = (nz1 - nz0)/(ny1 - ny0), 1.21393 + pzr = (nz2 - nz0)/(ny2 - ny0), 1.21394 + pzn = (nz2 - nz1)/(ny2 - ny1), 1.21395 + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), 1.21396 + txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)), 1.21397 + tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)), 1.21398 + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))), 1.21399 + txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))):(ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))), 1.21400 + tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))):(ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1))); 1.21401 + _cimg_for_triangle2(*this,xleft0,cleft0,xright0,cright0,y,nx0,ny0,nc0,nx1,ny1,nc1,nx2,ny2,nc2) { 1.21402 + if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; } 1.21403 + int 1.21404 + xleft = xleft0, xright = xright0, 1.21405 + cleft = cleft0, cright = cright0; 1.21406 + float 1.21407 + zleft = zl, zright = zr, 1.21408 + txleft = txl, txright = txr, 1.21409 + tyleft = tyl, tyright = tyr; 1.21410 + if (xright<xleft) cimg::swap(xleft,xright,zleft,zright,txleft,txright,tyleft,tyright,cleft,cright); 1.21411 + const int 1.21412 + dx = xright - xleft, 1.21413 + dc = cright>cleft?cright - cleft:cleft - cright, 1.21414 + rc = dx?(cright - cleft)/dx:0, 1.21415 + sc = cright>cleft?1:-1, 1.21416 + ndc = dc - (dx?dx*(dc/dx):0); 1.21417 + const float 1.21418 + pentez = (zright - zleft)/dx, 1.21419 + pentetx = (txright - txleft)/dx, 1.21420 + pentety = (tyright - tyleft)/dx; 1.21421 + int errc = dx>>1; 1.21422 + if (xleft<0 && dx) { 1.21423 + cleft-=xleft*(cright - cleft)/dx; 1.21424 + zleft-=xleft*(zright - zleft)/dx; 1.21425 + txleft-=xleft*(txright - txleft)/dx; 1.21426 + tyleft-=xleft*(tyright - tyleft)/dx; 1.21427 + } 1.21428 + if (xleft<0) xleft = 0; 1.21429 + if (xright>=dimx()-1) xright = dimx()-1; 1.21430 + T* ptrd = ptr(xleft,y,0,0); 1.21431 + if (opacity>=1) for (int x = xleft; x<=xright; ++x) { 1.21432 + const float invz = 1/zleft; 1.21433 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.21434 + cimg_forV(*this,k) { 1.21435 + *ptrd = (T)(cleft<256?cleft**col/256:((512-cleft)**col+(cleft-256)*maxval)/256); 1.21436 + ptrd+=whz; col+=twhz; 1.21437 + } 1.21438 + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.21439 + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); 1.21440 + } else for (int x = xleft; x<=xright; ++x) { 1.21441 + const float invz = 1/zleft; 1.21442 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.21443 + cimg_forV(*this,k) { 1.21444 + const T val = (T)(cleft<256?cleft**col/256:((512-cleft)**col+(cleft-256)*maxval)/256); 1.21445 + *ptrd = (T)(nopacity*val + *ptrd*copacity); 1.21446 + ptrd+=whz; col+=twhz; 1.21447 + } 1.21448 + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.21449 + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); 1.21450 + } 1.21451 + zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl; 1.21452 + } 1.21453 + return *this; 1.21454 + } 1.21455 + 1.21456 + //! Draw a 2D Gouraud-shaded textured triangle, with z-buffering and perspective correction. 1.21457 + template<typename tc> 1.21458 + CImg<T>& draw_triangle(float *const zbuffer, 1.21459 + const int x0, const int y0, const float z0, 1.21460 + const int x1, const int y1, const float z1, 1.21461 + const int x2, const int y2, const float z2, 1.21462 + const CImg<tc>& texture, 1.21463 + const int tx0, const int ty0, 1.21464 + const int tx1, const int ty1, 1.21465 + const int tx2, const int ty2, 1.21466 + const float brightness0, 1.21467 + const float brightness1, 1.21468 + const float brightness2, 1.21469 + const float opacity=1) { 1.21470 + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; 1.21471 + if (!texture || texture.dim<dim) 1.21472 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified texture (%u,%u,%u,%u,%p) is not a valid argument.", 1.21473 + pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data); 1.21474 + if (is_overlapped(texture)) return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2, 1.21475 + brightness0,brightness1,brightness2,opacity); 1.21476 + static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max()); 1.21477 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.21478 + const int whz = width*height*depth, twhz = texture.width*texture.height*texture.depth, offx = dim*whz; 1.21479 + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, 1.21480 + nc0 = (int)((brightness0<0?0:(brightness0>2?2:brightness0))*256), 1.21481 + nc1 = (int)((brightness1<0?0:(brightness1>2?2:brightness1))*256), 1.21482 + nc2 = (int)((brightness2<0?0:(brightness2>2?2:brightness2))*256); 1.21483 + float 1.21484 + ntx0 = tx0/z0, nty0 = ty0/z0, 1.21485 + ntx1 = tx1/z1, nty1 = ty1/z1, 1.21486 + ntx2 = tx2/z2, nty2 = ty2/z2, 1.21487 + nz0 = 1/z0, nz1 = 1/z1, nz2 = 1/z2; 1.21488 + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nz0,nz1,nc0,nc1); 1.21489 + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nz0,nz2,nc0,nc2); 1.21490 + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nz1,nz2,nc1,nc2); 1.21491 + if (ny0>=dimy() || ny2<0) return *this; 1.21492 + float 1.21493 + ptxl = (ntx1 - ntx0)/(ny1 - ny0), 1.21494 + ptxr = (ntx2 - ntx0)/(ny2 - ny0), 1.21495 + ptxn = (ntx2 - ntx1)/(ny2 - ny1), 1.21496 + ptyl = (nty1 - nty0)/(ny1 - ny0), 1.21497 + ptyr = (nty2 - nty0)/(ny2 - ny0), 1.21498 + ptyn = (nty2 - nty1)/(ny2 - ny1), 1.21499 + pzl = (nz1 - nz0)/(ny1 - ny0), 1.21500 + pzr = (nz2 - nz0)/(ny2 - ny0), 1.21501 + pzn = (nz2 - nz1)/(ny2 - ny1), 1.21502 + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), 1.21503 + txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)), 1.21504 + tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)), 1.21505 + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))), 1.21506 + txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))):(ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))), 1.21507 + tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))):(ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1))); 1.21508 + _cimg_for_triangle2(*this,xleft0,cleft0,xright0,cright0,y,nx0,ny0,nc0,nx1,ny1,nc1,nx2,ny2,nc2) { 1.21509 + if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; } 1.21510 + int 1.21511 + xleft = xleft0, xright = xright0, 1.21512 + cleft = cleft0, cright = cright0; 1.21513 + float 1.21514 + zleft = zl, zright = zr, 1.21515 + txleft = txl, txright = txr, 1.21516 + tyleft = tyl, tyright = tyr; 1.21517 + if (xright<xleft) cimg::swap(xleft,xright,zleft,zright,txleft,txright,tyleft,tyright,cleft,cright); 1.21518 + const int 1.21519 + dx = xright - xleft, 1.21520 + dc = cright>cleft?cright - cleft:cleft - cright, 1.21521 + rc = dx?(cright - cleft)/dx:0, 1.21522 + sc = cright>cleft?1:-1, 1.21523 + ndc = dc - (dx?dx*(dc/dx):0); 1.21524 + const float 1.21525 + pentez = (zright - zleft)/dx, 1.21526 + pentetx = (txright - txleft)/dx, 1.21527 + pentety = (tyright - tyleft)/dx; 1.21528 + int errc = dx>>1; 1.21529 + if (xleft<0 && dx) { 1.21530 + cleft-=xleft*(cright - cleft)/dx; 1.21531 + zleft-=xleft*(zright - zleft)/dx; 1.21532 + txleft-=xleft*(txright - txleft)/dx; 1.21533 + tyleft-=xleft*(tyright - tyleft)/dx; 1.21534 + } 1.21535 + if (xleft<0) xleft = 0; 1.21536 + if (xright>=dimx()-1) xright = dimx()-1; 1.21537 + T* ptrd = ptr(xleft,y); 1.21538 + float *ptrz = zbuffer + xleft + y*width; 1.21539 + if (opacity>=1) for (int x = xleft; x<=xright; ++x, ++ptrd, ++ptrz) { 1.21540 + if (zleft>*ptrz) { 1.21541 + *ptrz = zleft; 1.21542 + const float invz = 1/zleft; 1.21543 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.21544 + cimg_forV(*this,k) { 1.21545 + *ptrd = (T)(cleft<256?cleft**col/256:((512-cleft)**col+(cleft-256)*maxval)/256); 1.21546 + ptrd+=whz; col+=twhz; 1.21547 + } 1.21548 + ptrd-=offx; 1.21549 + } 1.21550 + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.21551 + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); 1.21552 + } else for (int x = xleft; x<=xright; ++x, ++ptrd, ++ptrz) { 1.21553 + if (zleft>*ptrz) { 1.21554 + *ptrz = zleft; 1.21555 + const float invz = 1/zleft; 1.21556 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.21557 + cimg_forV(*this,k) { 1.21558 + const T val = (T)(cleft<256?cleft**col/256:((512-cleft)**col+(cleft-256)*maxval)/256); 1.21559 + *ptrd = (T)(nopacity*val + *ptrd*copacity); 1.21560 + ptrd+=whz; col+=twhz; 1.21561 + } 1.21562 + ptrd-=offx; 1.21563 + } 1.21564 + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.21565 + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); 1.21566 + } 1.21567 + zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl; 1.21568 + } 1.21569 + return *this; 1.21570 + } 1.21571 + 1.21572 + //! Draw a 2D Pseudo-Phong-shaded textured triangle. 1.21573 + /** 1.21574 + \param x0 = X-coordinate of the first corner in the instance image. 1.21575 + \param y0 = Y-coordinate of the first corner in the instance image. 1.21576 + \param x1 = X-coordinate of the second corner in the instance image. 1.21577 + \param y1 = Y-coordinate of the second corner in the instance image. 1.21578 + \param x2 = X-coordinate of the third corner in the instance image. 1.21579 + \param y2 = Y-coordinate of the third corner in the instance image. 1.21580 + \param texture = texture image used to fill the triangle. 1.21581 + \param tx0 = X-coordinate of the first corner in the texture image. 1.21582 + \param ty0 = Y-coordinate of the first corner in the texture image. 1.21583 + \param tx1 = X-coordinate of the second corner in the texture image. 1.21584 + \param ty1 = Y-coordinate of the second corner in the texture image. 1.21585 + \param tx2 = X-coordinate of the third corner in the texture image. 1.21586 + \param ty2 = Y-coordinate of the third corner in the texture image. 1.21587 + \param light = light image. 1.21588 + \param lx0 = X-coordinate of the first corner in the light image. 1.21589 + \param ly0 = Y-coordinate of the first corner in the light image. 1.21590 + \param lx1 = X-coordinate of the second corner in the light image. 1.21591 + \param ly1 = Y-coordinate of the second corner in the light image. 1.21592 + \param lx2 = X-coordinate of the third corner in the light image. 1.21593 + \param ly2 = Y-coordinate of the third corner in the light image. 1.21594 + \param opacity = opacity of the drawing. 1.21595 + \note Clipping is supported, but texture coordinates do not support clipping. 1.21596 + **/ 1.21597 + template<typename tc, typename tl> 1.21598 + CImg<T>& draw_triangle(const int x0, const int y0, 1.21599 + const int x1, const int y1, 1.21600 + const int x2, const int y2, 1.21601 + const CImg<tc>& texture, 1.21602 + const int tx0, const int ty0, 1.21603 + const int tx1, const int ty1, 1.21604 + const int tx2, const int ty2, 1.21605 + const CImg<tl>& light, 1.21606 + const int lx0, const int ly0, 1.21607 + const int lx1, const int ly1, 1.21608 + const int lx2, const int ly2, 1.21609 + const float opacity=1) { 1.21610 + if (is_empty()) return *this; 1.21611 + if (!texture || texture.dim<dim) 1.21612 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified texture (%u,%u,%u,%u,%p) is not a valid argument.", 1.21613 + pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data); 1.21614 + if (!light) 1.21615 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified light texture (%u,%u,%u,%u,%p) is empty.", 1.21616 + pixel_type(),light.width,light.height,light.depth,light.dim,light.data); 1.21617 + 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); 1.21618 + 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); 1.21619 + static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max()); 1.21620 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.21621 + const int whz = width*height*depth, twhz = texture.width*texture.height*texture.depth, offx = dim*whz-1; 1.21622 + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, 1.21623 + ntx0 = tx0, nty0 = ty0, ntx1 = tx1, nty1 = ty1, ntx2 = tx2, nty2 = ty2, 1.21624 + nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2; 1.21625 + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nlx0,nlx1,nly0,nly1); 1.21626 + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nlx0,nlx2,nly0,nly2); 1.21627 + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nlx1,nlx2,nly1,nly2); 1.21628 + if (ny0>=dimy() || ny2<0) return *this; 1.21629 + _cimg_for_triangle5(*this,xleft0,lxleft0,lyleft0,txleft0,tyleft0,xright0,lxright0,lyright0,txright0,tyright0,y, 1.21630 + nx0,ny0,nlx0,nly0,ntx0,nty0,nx1,ny1,nlx1,nly1,ntx1,nty1,nx2,ny2,nlx2,nly2,ntx2,nty2) { 1.21631 + int 1.21632 + xleft = xleft0, xright = xright0, 1.21633 + lxleft = lxleft0, lxright = lxright0, 1.21634 + lyleft = lyleft0, lyright = lyright0, 1.21635 + txleft = txleft0, txright = txright0, 1.21636 + tyleft = tyleft0, tyright = tyright0; 1.21637 + if (xright<xleft) cimg::swap(xleft,xright,lxleft,lxright,lyleft,lyright,txleft,txright,tyleft,tyright); 1.21638 + const int 1.21639 + dx = xright - xleft, 1.21640 + dlx = lxright>lxleft?lxright - lxleft:lxleft - lxright, 1.21641 + dly = lyright>lyleft?lyright - lyleft:lyleft - lyright, 1.21642 + dtx = txright>txleft?txright - txleft:txleft - txright, 1.21643 + dty = tyright>tyleft?tyright - tyleft:tyleft - tyright, 1.21644 + rlx = dx?(lxright - lxleft)/dx:0, 1.21645 + rly = dx?(lyright - lyleft)/dx:0, 1.21646 + rtx = dx?(txright - txleft)/dx:0, 1.21647 + rty = dx?(tyright - tyleft)/dx:0, 1.21648 + slx = lxright>lxleft?1:-1, 1.21649 + sly = lyright>lyleft?1:-1, 1.21650 + stx = txright>txleft?1:-1, 1.21651 + sty = tyright>tyleft?1:-1, 1.21652 + ndlx = dlx - (dx?dx*(dlx/dx):0), 1.21653 + ndly = dly - (dx?dx*(dly/dx):0), 1.21654 + ndtx = dtx - (dx?dx*(dtx/dx):0), 1.21655 + ndty = dty - (dx?dx*(dty/dx):0); 1.21656 + int errlx = dx>>1, errly = errlx, errtx = errlx, errty = errlx; 1.21657 + if (xleft<0 && dx) { 1.21658 + lxleft-=xleft*(lxright - lxleft)/dx; 1.21659 + lyleft-=xleft*(lyright - lyleft)/dx; 1.21660 + txleft-=xleft*(txright - txleft)/dx; 1.21661 + tyleft-=xleft*(tyright - tyleft)/dx; 1.21662 + } 1.21663 + if (xleft<0) xleft = 0; 1.21664 + if (xright>=dimx()-1) xright = dimx()-1; 1.21665 + T* ptrd = ptr(xleft,y,0,0); 1.21666 + if (opacity>=1) for (int x = xleft; x<=xright; ++x) { 1.21667 + const tl l = light(lxleft,lyleft); 1.21668 + const tc *col = texture.ptr(txleft,tyleft); 1.21669 + cimg_forV(*this,k) { 1.21670 + *ptrd = (T)(l<1?l**col:(2-l)**col+(l-1)*maxval); 1.21671 + ptrd+=whz; col+=twhz; 1.21672 + } 1.21673 + ptrd-=offx; 1.21674 + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); 1.21675 + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); 1.21676 + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); 1.21677 + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); 1.21678 + } else for (int x = xleft; x<=xright; ++x) { 1.21679 + const tl l = light(lxleft,lyleft); 1.21680 + const tc *col = texture.ptr(txleft,tyleft); 1.21681 + cimg_forV(*this,k) { 1.21682 + const T val = (T)(l<1?l**col:(2-l)**col+(l-1)*maxval); 1.21683 + *ptrd = (T)(nopacity*val + *ptrd*copacity); 1.21684 + ptrd+=whz; col+=twhz; 1.21685 + } 1.21686 + ptrd-=offx; 1.21687 + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); 1.21688 + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); 1.21689 + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); 1.21690 + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); 1.21691 + } 1.21692 + } 1.21693 + return *this; 1.21694 + } 1.21695 + 1.21696 + //! Draw a 2D Pseudo-Phong-shaded textured triangle, with perspective correction. 1.21697 + template<typename tc, typename tl> 1.21698 + CImg<T>& draw_triangle(const int x0, const int y0, const float z0, 1.21699 + const int x1, const int y1, const float z1, 1.21700 + const int x2, const int y2, const float z2, 1.21701 + const CImg<tc>& texture, 1.21702 + const int tx0, const int ty0, 1.21703 + const int tx1, const int ty1, 1.21704 + const int tx2, const int ty2, 1.21705 + const CImg<tl>& light, 1.21706 + const int lx0, const int ly0, 1.21707 + const int lx1, const int ly1, 1.21708 + const int lx2, const int ly2, 1.21709 + const float opacity=1) { 1.21710 + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; 1.21711 + if (!texture || texture.dim<dim) 1.21712 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified texture (%u,%u,%u,%u,%p) is not a valid argument.", 1.21713 + pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data); 1.21714 + if (!light) 1.21715 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified light texture (%u,%u,%u,%u,%p) is empty.", 1.21716 + pixel_type(),light.width,light.height,light.depth,light.dim,light.data); 1.21717 + 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); 1.21718 + 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); 1.21719 + static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max()); 1.21720 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.21721 + const int whz = width*height*depth, twhz = texture.width*texture.height*texture.depth, offx = dim*whz-1; 1.21722 + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, 1.21723 + nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2; 1.21724 + float 1.21725 + ntx0 = tx0/z0, nty0 = ty0/z0, 1.21726 + ntx1 = tx1/z1, nty1 = ty1/z1, 1.21727 + ntx2 = tx2/z2, nty2 = ty2/z2, 1.21728 + nz0 = 1/z0, nz1 = 1/z1, nz2 = 1/z2; 1.21729 + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nlx0,nlx1,nly0,nly1,nz0,nz1); 1.21730 + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nlx0,nlx2,nly0,nly2,nz0,nz2); 1.21731 + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nlx1,nlx2,nly1,nly2,nz1,nz2); 1.21732 + if (ny0>=dimy() || ny2<0) return *this; 1.21733 + float 1.21734 + ptxl = (ntx1 - ntx0)/(ny1 - ny0), 1.21735 + ptxr = (ntx2 - ntx0)/(ny2 - ny0), 1.21736 + ptxn = (ntx2 - ntx1)/(ny2 - ny1), 1.21737 + ptyl = (nty1 - nty0)/(ny1 - ny0), 1.21738 + ptyr = (nty2 - nty0)/(ny2 - ny0), 1.21739 + ptyn = (nty2 - nty1)/(ny2 - ny1), 1.21740 + pzl = (nz1 - nz0)/(ny1 - ny0), 1.21741 + pzr = (nz2 - nz0)/(ny2 - ny0), 1.21742 + pzn = (nz2 - nz1)/(ny2 - ny1), 1.21743 + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), 1.21744 + txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)), 1.21745 + tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)), 1.21746 + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))), 1.21747 + txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))):(ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))), 1.21748 + tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))):(ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1))); 1.21749 + _cimg_for_triangle3(*this,xleft0,lxleft0,lyleft0,xright0,lxright0,lyright0,y, 1.21750 + nx0,ny0,nlx0,nly0,nx1,ny1,nlx1,nly1,nx2,ny2,nlx2,nly2) { 1.21751 + if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; } 1.21752 + int 1.21753 + xleft = xleft0, xright = xright0, 1.21754 + lxleft = lxleft0, lxright = lxright0, 1.21755 + lyleft = lyleft0, lyright = lyright0; 1.21756 + float 1.21757 + zleft = zl, zright = zr, 1.21758 + txleft = txl, txright = txr, 1.21759 + tyleft = tyl, tyright = tyr; 1.21760 + if (xright<xleft) cimg::swap(xleft,xright,zleft,zright,txleft,txright,tyleft,tyright,lxleft,lxright,lyleft,lyright); 1.21761 + const int 1.21762 + dx = xright - xleft, 1.21763 + dlx = lxright>lxleft?lxright - lxleft:lxleft - lxright, 1.21764 + dly = lyright>lyleft?lyright - lyleft:lyleft - lyright, 1.21765 + rlx = dx?(lxright - lxleft)/dx:0, 1.21766 + rly = dx?(lyright - lyleft)/dx:0, 1.21767 + slx = lxright>lxleft?1:-1, 1.21768 + sly = lyright>lyleft?1:-1, 1.21769 + ndlx = dlx - (dx?dx*(dlx/dx):0), 1.21770 + ndly = dly - (dx?dx*(dly/dx):0); 1.21771 + const float 1.21772 + pentez = (zright - zleft)/dx, 1.21773 + pentetx = (txright - txleft)/dx, 1.21774 + pentety = (tyright - tyleft)/dx; 1.21775 + int errlx = dx>>1, errly = errlx; 1.21776 + if (xleft<0 && dx) { 1.21777 + zleft-=xleft*(zright - zleft)/dx; 1.21778 + lxleft-=xleft*(lxright - lxleft)/dx; 1.21779 + lyleft-=xleft*(lyright - lyleft)/dx; 1.21780 + txleft-=xleft*(txright - txleft)/dx; 1.21781 + tyleft-=xleft*(tyright - tyleft)/dx; 1.21782 + } 1.21783 + if (xleft<0) xleft = 0; 1.21784 + if (xright>=dimx()-1) xright = dimx()-1; 1.21785 + T* ptrd = ptr(xleft,y,0,0); 1.21786 + if (opacity>=1) for (int x = xleft; x<=xright; ++x) { 1.21787 + const float invz = 1/zleft; 1.21788 + const tl l = light(lxleft,lyleft); 1.21789 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.21790 + cimg_forV(*this,k) { 1.21791 + *ptrd = (T)(l<1?l**col:(2-l)**col+(l-1)*maxval); 1.21792 + ptrd+=whz; col+=twhz; 1.21793 + } 1.21794 + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.21795 + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); 1.21796 + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); 1.21797 + } else for (int x = xleft; x<=xright; ++x) { 1.21798 + const float invz = 1/zleft; 1.21799 + const tl l = light(lxleft,lyleft); 1.21800 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.21801 + cimg_forV(*this,k) { 1.21802 + const T val = (T)(l<1?l**col:(2-l)**col+(l-1)*maxval); 1.21803 + *ptrd = (T)(nopacity*val + *ptrd*copacity); 1.21804 + ptrd+=whz; col+=twhz; 1.21805 + } 1.21806 + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.21807 + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); 1.21808 + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); 1.21809 + } 1.21810 + zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl; 1.21811 + } 1.21812 + return *this; 1.21813 + } 1.21814 + 1.21815 + //! Draw a 2D Pseudo-Phong-shaded textured triangle, with z-buffering and perspective correction. 1.21816 + template<typename tc, typename tl> 1.21817 + CImg<T>& draw_triangle(float *const zbuffer, 1.21818 + const int x0, const int y0, const float z0, 1.21819 + const int x1, const int y1, const float z1, 1.21820 + const int x2, const int y2, const float z2, 1.21821 + const CImg<tc>& texture, 1.21822 + const int tx0, const int ty0, 1.21823 + const int tx1, const int ty1, 1.21824 + const int tx2, const int ty2, 1.21825 + const CImg<tl>& light, 1.21826 + const int lx0, const int ly0, 1.21827 + const int lx1, const int ly1, 1.21828 + const int lx2, const int ly2, 1.21829 + const float opacity=1) { 1.21830 + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; 1.21831 + if (!texture || texture.dim<dim) 1.21832 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified texture (%u,%u,%u,%u,%p) is not a valid argument.", 1.21833 + pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data); 1.21834 + if (!light) 1.21835 + throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified light texture (%u,%u,%u,%u,%p) is empty.", 1.21836 + pixel_type(),light.width,light.height,light.depth,light.dim,light.data); 1.21837 + if (is_overlapped(texture)) return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2, 1.21838 + +texture,tx0,ty0,tx1,ty1,tx2,ty2,light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); 1.21839 + if (is_overlapped(light)) return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2, 1.21840 + texture,tx0,ty0,tx1,ty1,tx2,ty2,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); 1.21841 + static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max()); 1.21842 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.21843 + const int whz = width*height*depth, twhz = texture.width*texture.height*texture.depth, offx = dim*whz; 1.21844 + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, 1.21845 + nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2; 1.21846 + float 1.21847 + ntx0 = tx0/z0, nty0 = ty0/z0, 1.21848 + ntx1 = tx1/z1, nty1 = ty1/z1, 1.21849 + ntx2 = tx2/z2, nty2 = ty2/z2, 1.21850 + nz0 = 1/z0, nz1 = 1/z1, nz2 = 1/z2; 1.21851 + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nlx0,nlx1,nly0,nly1,nz0,nz1); 1.21852 + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nlx0,nlx2,nly0,nly2,nz0,nz2); 1.21853 + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nlx1,nlx2,nly1,nly2,nz1,nz2); 1.21854 + if (ny0>=dimy() || ny2<0) return *this; 1.21855 + float 1.21856 + ptxl = (ntx1 - ntx0)/(ny1 - ny0), 1.21857 + ptxr = (ntx2 - ntx0)/(ny2 - ny0), 1.21858 + ptxn = (ntx2 - ntx1)/(ny2 - ny1), 1.21859 + ptyl = (nty1 - nty0)/(ny1 - ny0), 1.21860 + ptyr = (nty2 - nty0)/(ny2 - ny0), 1.21861 + ptyn = (nty2 - nty1)/(ny2 - ny1), 1.21862 + pzl = (nz1 - nz0)/(ny1 - ny0), 1.21863 + pzr = (nz2 - nz0)/(ny2 - ny0), 1.21864 + pzn = (nz2 - nz1)/(ny2 - ny1), 1.21865 + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), 1.21866 + txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)), 1.21867 + tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)), 1.21868 + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))), 1.21869 + txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))):(ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))), 1.21870 + tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))):(ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1))); 1.21871 + _cimg_for_triangle3(*this,xleft0,lxleft0,lyleft0,xright0,lxright0,lyright0,y, 1.21872 + nx0,ny0,nlx0,nly0,nx1,ny1,nlx1,nly1,nx2,ny2,nlx2,nly2) { 1.21873 + if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; } 1.21874 + int 1.21875 + xleft = xleft0, xright = xright0, 1.21876 + lxleft = lxleft0, lxright = lxright0, 1.21877 + lyleft = lyleft0, lyright = lyright0; 1.21878 + float 1.21879 + zleft = zl, zright = zr, 1.21880 + txleft = txl, txright = txr, 1.21881 + tyleft = tyl, tyright = tyr; 1.21882 + if (xright<xleft) cimg::swap(xleft,xright,zleft,zright,txleft,txright,tyleft,tyright,lxleft,lxright,lyleft,lyright); 1.21883 + const int 1.21884 + dx = xright - xleft, 1.21885 + dlx = lxright>lxleft?lxright - lxleft:lxleft - lxright, 1.21886 + dly = lyright>lyleft?lyright - lyleft:lyleft - lyright, 1.21887 + rlx = dx?(lxright - lxleft)/dx:0, 1.21888 + rly = dx?(lyright - lyleft)/dx:0, 1.21889 + slx = lxright>lxleft?1:-1, 1.21890 + sly = lyright>lyleft?1:-1, 1.21891 + ndlx = dlx - (dx?dx*(dlx/dx):0), 1.21892 + ndly = dly - (dx?dx*(dly/dx):0); 1.21893 + const float 1.21894 + pentez = (zright - zleft)/dx, 1.21895 + pentetx = (txright - txleft)/dx, 1.21896 + pentety = (tyright - tyleft)/dx; 1.21897 + int errlx = dx>>1, errly = errlx; 1.21898 + if (xleft<0 && dx) { 1.21899 + zleft-=xleft*(zright - zleft)/dx; 1.21900 + lxleft-=xleft*(lxright - lxleft)/dx; 1.21901 + lyleft-=xleft*(lyright - lyleft)/dx; 1.21902 + txleft-=xleft*(txright - txleft)/dx; 1.21903 + tyleft-=xleft*(tyright - tyleft)/dx; 1.21904 + } 1.21905 + if (xleft<0) xleft = 0; 1.21906 + if (xright>=dimx()-1) xright = dimx()-1; 1.21907 + T* ptrd = ptr(xleft,y); 1.21908 + float *ptrz = zbuffer + xleft + y*width; 1.21909 + if (opacity>=1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { 1.21910 + if (zleft>*ptrz) { 1.21911 + *ptrz = zleft; 1.21912 + const float invz = 1/zleft; 1.21913 + const tl l = light(lxleft,lyleft); 1.21914 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.21915 + cimg_forV(*this,k) { 1.21916 + *ptrd = (T)(l<1?l**col:(2-l)**col+(l-1)*maxval); 1.21917 + ptrd+=whz; col+=twhz; 1.21918 + } 1.21919 + ptrd-=offx; 1.21920 + } 1.21921 + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.21922 + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); 1.21923 + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); 1.21924 + } else for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { 1.21925 + if (zleft>*ptrz) { 1.21926 + *ptrz = zleft; 1.21927 + const float invz = 1/zleft; 1.21928 + const tl l = light(lxleft,lyleft); 1.21929 + const tc *col = texture.ptr((int)(txleft*invz),(int)(tyleft*invz)); 1.21930 + cimg_forV(*this,k) { 1.21931 + const T val = (T)(l<1?l**col:(2-l)**col+(l-1)*maxval); 1.21932 + *ptrd = (T)(nopacity*val + *ptrd*copacity); 1.21933 + ptrd+=whz; col+=twhz; 1.21934 + } 1.21935 + ptrd-=offx; 1.21936 + } 1.21937 + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; 1.21938 + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); 1.21939 + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); 1.21940 + } 1.21941 + zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl; 1.21942 + } 1.21943 + return *this; 1.21944 + } 1.21945 + 1.21946 + // Draw a 2D ellipse (inner routine). 1.21947 + template<typename tc> 1.21948 + CImg<T>& _draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float ru, const float rv, 1.21949 + const tc *const color, const float opacity, 1.21950 + const unsigned int pattern) { 1.21951 + if (is_empty()) return *this; 1.21952 + if (!color) 1.21953 + throw CImgArgumentException("CImg<%s>::draw_ellipse : Specified color is (null).", 1.21954 + pixel_type()); 1.21955 + _draw_scanline(color,opacity); 1.21956 + const float 1.21957 + nr1 = cimg::abs(r1), nr2 = cimg::abs(r2), 1.21958 + norm = (float)cimg_std::sqrt(ru*ru+rv*rv), 1.21959 + u = norm>0?ru/norm:1, 1.21960 + v = norm>0?rv/norm:0, 1.21961 + rmax = cimg::max(nr1,nr2), 1.21962 + l1 = (float)cimg_std::pow(rmax/(nr1>0?nr1:1e-6),2), 1.21963 + l2 = (float)cimg_std::pow(rmax/(nr2>0?nr2:1e-6),2), 1.21964 + a = l1*u*u + l2*v*v, 1.21965 + b = u*v*(l1-l2), 1.21966 + c = l1*v*v + l2*u*u; 1.21967 + const int 1.21968 + yb = (int)cimg_std::sqrt(a*rmax*rmax/(a*c-b*b)), 1.21969 + tymin = y0 - yb - 1, 1.21970 + tymax = y0 + yb + 1, 1.21971 + ymin = tymin<0?0:tymin, 1.21972 + ymax = tymax>=dimy()?height-1:tymax; 1.21973 + int oxmin = 0, oxmax = 0; 1.21974 + bool first_line = true; 1.21975 + for (int y = ymin; y<=ymax; ++y) { 1.21976 + const float 1.21977 + Y = y-y0 + (y<y0?0.5f:-0.5f), 1.21978 + delta = b*b*Y*Y-a*(c*Y*Y-rmax*rmax), 1.21979 + sdelta = delta>0?(float)cimg_std::sqrt(delta)/a:0.0f, 1.21980 + bY = b*Y/a, 1.21981 + fxmin = x0-0.5f-bY-sdelta, 1.21982 + fxmax = x0+0.5f-bY+sdelta; 1.21983 + const int xmin = (int)fxmin, xmax = (int)fxmax; 1.21984 + if (!pattern) _draw_scanline(xmin,xmax,y,color,opacity); 1.21985 + else { 1.21986 + if (first_line) { 1.21987 + if (y0-yb>=0) _draw_scanline(xmin,xmax,y,color,opacity); 1.21988 + else draw_point(xmin,y,color,opacity).draw_point(xmax,y,color,opacity); 1.21989 + first_line = false; 1.21990 + } else { 1.21991 + if (xmin<oxmin) _draw_scanline(xmin,oxmin-1,y,color,opacity); 1.21992 + else _draw_scanline(oxmin+(oxmin==xmin?0:1),xmin,y,color,opacity); 1.21993 + if (xmax<oxmax) _draw_scanline(xmax,oxmax-1,y,color,opacity); 1.21994 + else _draw_scanline(oxmax+(oxmax==xmax?0:1),xmax,y,color,opacity); 1.21995 + if (y==tymax) _draw_scanline(xmin+1,xmax-1,y,color,opacity); 1.21996 + } 1.21997 + } 1.21998 + oxmin = xmin; oxmax = xmax; 1.21999 + } 1.22000 + return *this; 1.22001 + } 1.22002 + 1.22003 + //! Draw a filled ellipse. 1.22004 + /** 1.22005 + \param x0 = X-coordinate of the ellipse center. 1.22006 + \param y0 = Y-coordinate of the ellipse center. 1.22007 + \param r1 = First radius of the ellipse. 1.22008 + \param r2 = Second radius of the ellipse. 1.22009 + \param ru = X-coordinate of the orientation vector related to the first radius. 1.22010 + \param rv = Y-coordinate of the orientation vector related to the first radius. 1.22011 + \param color = array of dimv() values of type \c T, defining the drawing color. 1.22012 + \param opacity = opacity of the drawing. 1.22013 + **/ 1.22014 + template<typename tc> 1.22015 + CImg<T>& draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float ru, const float rv, 1.22016 + const tc *const color, const float opacity=1) { 1.22017 + return _draw_ellipse(x0,y0,r1,r2,ru,rv,color,opacity,0U); 1.22018 + } 1.22019 + 1.22020 + //! Draw a filled ellipse. 1.22021 + template<typename tc> 1.22022 + CImg<T>& draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float ru, const float rv, 1.22023 + const CImg<tc>& color, const float opacity=1) { 1.22024 + return draw_ellipse(x0,y0,r1,r2,ru,rv,color.data,opacity); 1.22025 + } 1.22026 + 1.22027 + //! Draw a filled ellipse. 1.22028 + /** 1.22029 + \param x0 = X-coordinate of the ellipse center. 1.22030 + \param y0 = Y-coordinate of the ellipse center. 1.22031 + \param tensor = Diffusion tensor describing the ellipse. 1.22032 + \param color = array of dimv() values of type \c T, defining the drawing color. 1.22033 + \param opacity = opacity of the drawing. 1.22034 + **/ 1.22035 + template<typename t, typename tc> 1.22036 + CImg<T>& draw_ellipse(const int x0, const int y0, const CImg<t> &tensor, 1.22037 + const tc *const color, const float opacity=1) { 1.22038 + CImgList<t> eig = tensor.get_symmetric_eigen(); 1.22039 + const CImg<t> &val = eig[0], &vec = eig[1]; 1.22040 + return draw_ellipse(x0,y0,val(0),val(1),vec(0,0),vec(0,1),color,opacity); 1.22041 + } 1.22042 + 1.22043 + //! Draw a filled ellipse. 1.22044 + template<typename t, typename tc> 1.22045 + CImg<T>& draw_ellipse(const int x0, const int y0, const CImg<t> &tensor, 1.22046 + const CImg<tc>& color, const float opacity=1) { 1.22047 + return draw_ellipse(x0,y0,tensor,color.data,opacity); 1.22048 + } 1.22049 + 1.22050 + //! Draw an outlined ellipse. 1.22051 + /** 1.22052 + \param x0 = X-coordinate of the ellipse center. 1.22053 + \param y0 = Y-coordinate of the ellipse center. 1.22054 + \param r1 = First radius of the ellipse. 1.22055 + \param r2 = Second radius of the ellipse. 1.22056 + \param ru = X-coordinate of the orientation vector related to the first radius. 1.22057 + \param rv = Y-coordinate of the orientation vector related to the first radius. 1.22058 + \param color = array of dimv() values of type \c T, defining the drawing color. 1.22059 + \param pattern = If zero, the ellipse is filled, else pattern is an integer whose bits describe the outline pattern. 1.22060 + \param opacity = opacity of the drawing. 1.22061 + **/ 1.22062 + template<typename tc> 1.22063 + CImg<T>& draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float ru, const float rv, 1.22064 + const tc *const color, const float opacity, 1.22065 + const unsigned int pattern) { 1.22066 + if (pattern) _draw_ellipse(x0,y0,r1,r2,ru,rv,color,opacity,pattern); 1.22067 + return *this; 1.22068 + } 1.22069 + 1.22070 + //! Draw an outlined ellipse. 1.22071 + template<typename tc> 1.22072 + CImg<T>& draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float ru, const float rv, 1.22073 + const CImg<tc>& color, const float opacity, 1.22074 + const unsigned int pattern) { 1.22075 + return draw_ellipse(x0,y0,r1,r2,ru,rv,color.data,opacity,pattern); 1.22076 + } 1.22077 + 1.22078 + //! Draw an outlined ellipse. 1.22079 + /** 1.22080 + \param x0 = X-coordinate of the ellipse center. 1.22081 + \param y0 = Y-coordinate of the ellipse center. 1.22082 + \param tensor = Diffusion tensor describing the ellipse. 1.22083 + \param color = array of dimv() values of type \c T, defining the drawing color. 1.22084 + \param pattern = If zero, the ellipse is filled, else pattern is an integer whose bits describe the outline pattern. 1.22085 + \param opacity = opacity of the drawing. 1.22086 + **/ 1.22087 + template<typename t, typename tc> 1.22088 + CImg<T>& draw_ellipse(const int x0, const int y0, const CImg<t> &tensor, 1.22089 + const tc *const color, const float opacity, 1.22090 + const unsigned int pattern) { 1.22091 + CImgList<t> eig = tensor.get_symmetric_eigen(); 1.22092 + const CImg<t> &val = eig[0], &vec = eig[1]; 1.22093 + return draw_ellipse(x0,y0,val(0),val(1),vec(0,0),vec(0,1),color,opacity,pattern); 1.22094 + } 1.22095 + 1.22096 + //! Draw an outlined ellipse. 1.22097 + template<typename t, typename tc> 1.22098 + CImg<T>& draw_ellipse(const int x0, const int y0, const CImg<t> &tensor, 1.22099 + const CImg<tc>& color, const float opacity, 1.22100 + const unsigned int pattern) { 1.22101 + return draw_ellipse(x0,y0,tensor,color.data,opacity,pattern); 1.22102 + } 1.22103 + 1.22104 + //! Draw a filled circle. 1.22105 + /** 1.22106 + \param x0 X-coordinate of the circle center. 1.22107 + \param y0 Y-coordinate of the circle center. 1.22108 + \param radius Circle radius. 1.22109 + \param color Array of dimv() values of type \c T, defining the drawing color. 1.22110 + \param opacity Drawing opacity. 1.22111 + \note 1.22112 + - Circle version of the Bresenham's algorithm is used. 1.22113 + **/ 1.22114 + template<typename tc> 1.22115 + CImg<T>& draw_circle(const int x0, const int y0, int radius, 1.22116 + const tc *const color, const float opacity=1) { 1.22117 + if (!is_empty()) { 1.22118 + if (!color) 1.22119 + throw CImgArgumentException("CImg<%s>::draw_circle : Specified color is (null).", 1.22120 + pixel_type()); 1.22121 + _draw_scanline(color,opacity); 1.22122 + if (radius<0 || x0-radius>=dimx() || y0+radius<0 || y0-radius>=dimy()) return *this; 1.22123 + if (y0>=0 && y0<dimy()) _draw_scanline(x0-radius,x0+radius,y0,color,opacity); 1.22124 + for (int f=1-radius, ddFx=0, ddFy=-(radius<<1), x=0, y=radius; x<y; ) { 1.22125 + if (f>=0) { 1.22126 + const int x1 = x0-x, x2 = x0+x, y1 = y0-y, y2 = y0+y; 1.22127 + if (y1>=0 && y1<dimy()) _draw_scanline(x1,x2,y1,color,opacity); 1.22128 + if (y2>=0 && y2<dimy()) _draw_scanline(x1,x2,y2,color,opacity); 1.22129 + f+=(ddFy+=2); --y; 1.22130 + } 1.22131 + const bool no_diag = y!=(x++); 1.22132 + ++(f+=(ddFx+=2)); 1.22133 + const int x1 = x0-y, x2 = x0+y, y1 = y0-x, y2 = y0+x; 1.22134 + if (no_diag) { 1.22135 + if (y1>=0 && y1<dimy()) _draw_scanline(x1,x2,y1,color,opacity); 1.22136 + if (y2>=0 && y2<dimy()) _draw_scanline(x1,x2,y2,color,opacity); 1.22137 + } 1.22138 + } 1.22139 + } 1.22140 + return *this; 1.22141 + } 1.22142 + 1.22143 + //! Draw a filled circle. 1.22144 + template<typename tc> 1.22145 + CImg<T>& draw_circle(const int x0, const int y0, int radius, 1.22146 + const CImg<tc>& color, const float opacity=1) { 1.22147 + return draw_circle(x0,y0,radius,color.data,opacity); 1.22148 + } 1.22149 + 1.22150 + //! Draw an outlined circle. 1.22151 + /** 1.22152 + \param x0 X-coordinate of the circle center. 1.22153 + \param y0 Y-coordinate of the circle center. 1.22154 + \param radius Circle radius. 1.22155 + \param color Array of dimv() values of type \c T, defining the drawing color. 1.22156 + \param opacity Drawing opacity. 1.22157 + **/ 1.22158 + template<typename tc> 1.22159 + CImg<T>& draw_circle(const int x0, const int y0, int radius, 1.22160 + const tc *const color, const float opacity, 1.22161 + const unsigned int) { 1.22162 + if (!is_empty()) { 1.22163 + if (!color) 1.22164 + throw CImgArgumentException("CImg<%s>::draw_circle : Specified color is (null).", 1.22165 + pixel_type()); 1.22166 + if (radius<0 || x0-radius>=dimx() || y0+radius<0 || y0-radius>=dimy()) return *this; 1.22167 + if (!radius) return draw_point(x0,y0,color,opacity); 1.22168 + draw_point(x0-radius,y0,color,opacity).draw_point(x0+radius,y0,color,opacity). 1.22169 + draw_point(x0,y0-radius,color,opacity).draw_point(x0,y0+radius,color,opacity); 1.22170 + if (radius==1) return *this; 1.22171 + for (int f=1-radius, ddFx=0, ddFy=-(radius<<1), x=0, y=radius; x<y; ) { 1.22172 + if (f>=0) { f+=(ddFy+=2); --y; } 1.22173 + ++x; ++(f+=(ddFx+=2)); 1.22174 + if (x!=y+1) { 1.22175 + 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; 1.22176 + draw_point(x1,y1,color,opacity).draw_point(x1,y2,color,opacity). 1.22177 + draw_point(x2,y1,color,opacity).draw_point(x2,y2,color,opacity); 1.22178 + if (x!=y) 1.22179 + draw_point(x3,y3,color,opacity).draw_point(x4,y4,color,opacity). 1.22180 + draw_point(x4,y3,color,opacity).draw_point(x3,y4,color,opacity); 1.22181 + } 1.22182 + } 1.22183 + } 1.22184 + return *this; 1.22185 + } 1.22186 + 1.22187 + //! Draw an outlined circle. 1.22188 + template<typename tc> 1.22189 + CImg<T>& draw_circle(const int x0, const int y0, int radius, const CImg<tc>& color, 1.22190 + const float opacity, 1.22191 + const unsigned int pattern) { 1.22192 + return draw_circle(x0,y0,radius,color.data,opacity,pattern); 1.22193 + } 1.22194 + 1.22195 + // Draw a text (internal). 1.22196 + template<typename tc1, typename tc2, typename t> 1.22197 + CImg<T>& _draw_text(const int x0, const int y0, const char *const text, 1.22198 + const tc1 *const foreground_color, const tc2 *const background_color, 1.22199 + const float opacity, const CImgList<t>& font) { 1.22200 + if (!text) return *this; 1.22201 + if (!font) 1.22202 + throw CImgArgumentException("CImg<%s>::draw_text() : Specified font (%u,%p) is empty.", 1.22203 + pixel_type(),font.size,font.data); 1.22204 + const int text_length = cimg::strlen(text); 1.22205 + 1.22206 + if (is_empty()) { 1.22207 + // If needed, pre-compute necessary size of the image 1.22208 + int x = 0, y = 0, w = 0; 1.22209 + unsigned char c = 0; 1.22210 + for (int i = 0; i<text_length; ++i) { 1.22211 + c = text[i]; 1.22212 + switch (c) { 1.22213 + case '\n' : y+=font[' '].height; if (x>w) w = x; x = 0; break; 1.22214 + case '\t' : x+=4*font[' '].width; break; 1.22215 + default : if (c<font.size) x+=font[c].width; 1.22216 + } 1.22217 + } 1.22218 + if (x!=0 || c=='\n') { 1.22219 + if (x>w) w=x; 1.22220 + y+=font[' '].height; 1.22221 + } 1.22222 + assign(x0+w,y0+y,1,font[' '].dim,0); 1.22223 + if (background_color) cimg_forV(*this,k) get_shared_channel(k).fill((T)background_color[k]); 1.22224 + } 1.22225 + 1.22226 + int x = x0, y = y0; 1.22227 + CImg<T> letter; 1.22228 + for (int i = 0; i<text_length; ++i) { 1.22229 + const unsigned char c = text[i]; 1.22230 + switch (c) { 1.22231 + case '\n' : y+=font[' '].height; x = x0; break; 1.22232 + case '\t' : x+=4*font[' '].width; break; 1.22233 + default : if (c<font.size) { 1.22234 + letter = font[c]; 1.22235 + const CImg<T>& mask = (c+256)<(int)font.size?font[c+256]:font[c]; 1.22236 + if (foreground_color) for (unsigned int p = 0; p<letter.width*letter.height; ++p) 1.22237 + if (mask(p)) cimg_forV(*this,k) letter(p,0,0,k) = (T)(letter(p,0,0,k)*foreground_color[k]); 1.22238 + if (background_color) for (unsigned int p = 0; p<letter.width*letter.height; ++p) 1.22239 + if (!mask(p)) cimg_forV(*this,k) letter(p,0,0,k) = (T)background_color[k]; 1.22240 + if (!background_color && font.size>=512) draw_image(x,y,letter,mask,opacity,(T)1); 1.22241 + else draw_image(x,y,letter,opacity); 1.22242 + x+=letter.width; 1.22243 + } 1.22244 + } 1.22245 + } 1.22246 + return *this; 1.22247 + } 1.22248 + 1.22249 + //! Draw a text. 1.22250 + /** 1.22251 + \param x0 X-coordinate of the text in the instance image. 1.22252 + \param y0 Y-coordinate of the text in the instance image. 1.22253 + \param foreground_color Array of dimv() values of type \c T, defining the foreground color (0 means 'transparent'). 1.22254 + \param background_color Array of dimv() values of type \c T, defining the background color (0 means 'transparent'). 1.22255 + \param font Font used for drawing text. 1.22256 + \param opacity Drawing opacity. 1.22257 + \param format 'printf'-style format string, followed by arguments. 1.22258 + \note Clipping is supported. 1.22259 + **/ 1.22260 + template<typename tc1, typename tc2, typename t> 1.22261 + CImg<T>& draw_text(const int x0, const int y0, const char *const text, 1.22262 + const tc1 *const foreground_color, const tc2 *const background_color, 1.22263 + const float opacity, const CImgList<t>& font, ...) { 1.22264 + char tmp[2048] = { 0 }; cimg_std::va_list ap; va_start(ap,font); 1.22265 + cimg_std::vsprintf(tmp,text,ap); va_end(ap); 1.22266 + return _draw_text(x0,y0,tmp,foreground_color,background_color,opacity,font); 1.22267 + } 1.22268 + 1.22269 + //! Draw a text. 1.22270 + template<typename tc1, typename tc2, typename t> 1.22271 + CImg<T>& draw_text(const int x0, const int y0, const char *const text, 1.22272 + const CImg<tc1>& foreground_color, const CImg<tc2>& background_color, 1.22273 + const float opacity, const CImgList<t>& font, ...) { 1.22274 + char tmp[2048] = { 0 }; cimg_std::va_list ap; va_start(ap,font); 1.22275 + cimg_std::vsprintf(tmp,text,ap); va_end(ap); 1.22276 + return _draw_text(x0,y0,tmp,foreground_color,background_color,opacity,font); 1.22277 + } 1.22278 + 1.22279 + //! Draw a text. 1.22280 + template<typename tc, typename t> 1.22281 + CImg<T>& draw_text(const int x0, const int y0, const char *const text, 1.22282 + const tc *const foreground_color, const int background_color, 1.22283 + const float opacity, const CImgList<t>& font, ...) { 1.22284 + char tmp[2048] = { 0 }; cimg_std::va_list ap; va_start(ap,font); 1.22285 + cimg_std::vsprintf(tmp,text,ap); va_end(ap); 1.22286 + return _draw_text(x0,y0,tmp,foreground_color,(tc*)background_color,opacity,font); 1.22287 + } 1.22288 + 1.22289 + //! Draw a text. 1.22290 + template<typename tc, typename t> 1.22291 + CImg<T>& draw_text(const int x0, const int y0, const char *const text, 1.22292 + const int foreground_color, const tc *const background_color, 1.22293 + const float opacity, const CImgList<t>& font, ...) { 1.22294 + char tmp[2048] = { 0 }; cimg_std::va_list ap; va_start(ap,font); 1.22295 + cimg_std::vsprintf(tmp,text,ap); va_end(ap); 1.22296 + return _draw_text(x0,y0,tmp,(tc*)foreground_color,background_color,opacity,font); 1.22297 + } 1.22298 + 1.22299 + //! Draw a text. 1.22300 + /** 1.22301 + \param x0 X-coordinate of the text in the instance image. 1.22302 + \param y0 Y-coordinate of the text in the instance image. 1.22303 + \param foreground_color Array of dimv() values of type \c T, defining the foreground color (0 means 'transparent'). 1.22304 + \param background_color Array of dimv() values of type \c T, defining the background color (0 means 'transparent'). 1.22305 + \param font_size Size of the font (nearest match). 1.22306 + \param opacity Drawing opacity. 1.22307 + \param format 'printf'-style format string, followed by arguments. 1.22308 + \note Clipping is supported. 1.22309 + **/ 1.22310 + template<typename tc1, typename tc2> 1.22311 + CImg<T>& draw_text(const int x0, const int y0, const char *const text, 1.22312 + const tc1 *const foreground_color, const tc2 *const background_color, 1.22313 + const float opacity=1, const unsigned int font_size=11, ...) { 1.22314 + static CImgList<T> font; 1.22315 + static unsigned int fsize = 0; 1.22316 + if (fsize!=font_size) { font = CImgList<T>::font(font_size); fsize = font_size; } 1.22317 + char tmp[2048] = { 0 }; cimg_std::va_list ap; va_start(ap,font_size); cimg_std::vsprintf(tmp,text,ap); va_end(ap); 1.22318 + return _draw_text(x0,y0,tmp,foreground_color,background_color,opacity,font); 1.22319 + } 1.22320 + 1.22321 + //! Draw a text. 1.22322 + template<typename tc1, typename tc2> 1.22323 + CImg<T>& draw_text(const int x0, const int y0, const char *const text, 1.22324 + const CImg<tc1>& foreground_color, const CImg<tc2>& background_color, 1.22325 + const float opacity=1, const unsigned int font_size=11, ...) { 1.22326 + static CImgList<T> font; 1.22327 + static unsigned int fsize = 0; 1.22328 + if (fsize!=font_size) { font = CImgList<T>::font(font_size); fsize = font_size; } 1.22329 + char tmp[2048] = { 0 }; cimg_std::va_list ap; va_start(ap,font_size); cimg_std::vsprintf(tmp,text,ap); va_end(ap); 1.22330 + return _draw_text(x0,y0,tmp,foreground_color.data,background_color.data,opacity,font); 1.22331 + } 1.22332 + 1.22333 + //! Draw a text. 1.22334 + template<typename tc> 1.22335 + CImg<T>& draw_text(const int x0, const int y0, const char *const text, 1.22336 + const tc *const foreground_color, const int background_color=0, 1.22337 + const float opacity=1, const unsigned int font_size=11, ...) { 1.22338 + static CImgList<T> font; 1.22339 + static unsigned int fsize = 0; 1.22340 + if (fsize!=font_size) { font = CImgList<T>::font(font_size); fsize = font_size; } 1.22341 + char tmp[2048] = { 0 }; cimg_std::va_list ap; va_start(ap,font_size); cimg_std::vsprintf(tmp,text,ap); va_end(ap); 1.22342 + return _draw_text(x0,y0,tmp,foreground_color,(const tc*)background_color,opacity,font); 1.22343 + } 1.22344 + 1.22345 + //! Draw a text. 1.22346 + template<typename tc> 1.22347 + CImg<T>& draw_text(const int x0, const int y0, const char *const text, 1.22348 + const int foreground_color, const tc *const background_color, 1.22349 + const float opacity=1, const unsigned int font_size=11, ...) { 1.22350 + static CImgList<T> font; 1.22351 + static unsigned int fsize = 0; 1.22352 + if (fsize!=font_size) { font = CImgList<T>::font(font_size); fsize = font_size; } 1.22353 + char tmp[2048] = { 0 }; cimg_std::va_list ap; va_start(ap,font_size); cimg_std::vsprintf(tmp,text,ap); va_end(ap); 1.22354 + return _draw_text(x0,y0,tmp,(tc*)foreground_color,background_color,opacity,font); 1.22355 + } 1.22356 + 1.22357 + //! Draw a vector field in the instance image, using a colormap. 1.22358 + /** 1.22359 + \param flow Image of 2d vectors used as input data. 1.22360 + \param color Image of dimv()-D vectors corresponding to the color of each arrow. 1.22361 + \param sampling Length (in pixels) between each arrow. 1.22362 + \param factor Length factor of each arrow (if <0, computed as a percentage of the maximum length). 1.22363 + \param quiver_type Type of plot. Can be 0 (arrows) or 1 (segments). 1.22364 + \param opacity Opacity of the drawing. 1.22365 + \param pattern Used pattern to draw lines. 1.22366 + \note Clipping is supported. 1.22367 + **/ 1.22368 + template<typename t1, typename t2> 1.22369 + CImg<T>& draw_quiver(const CImg<t1>& flow, 1.22370 + const t2 *const color, const float opacity=1, 1.22371 + const unsigned int sampling=25, const float factor=-20, 1.22372 + const int quiver_type=0, const unsigned int pattern=~0U) { 1.22373 + return draw_quiver(flow,CImg<t2>(color,dim,1,1,1,true),opacity,sampling,factor,quiver_type,pattern); 1.22374 + } 1.22375 + 1.22376 + //! Draw a vector field in the instance image, using a colormap. 1.22377 + /** 1.22378 + \param flow Image of 2d vectors used as input data. 1.22379 + \param color Image of dimv()-D vectors corresponding to the color of each arrow. 1.22380 + \param sampling Length (in pixels) between each arrow. 1.22381 + \param factor Length factor of each arrow (if <0, computed as a percentage of the maximum length). 1.22382 + \param quiver_type Type of plot. Can be 0 (arrows) or 1 (segments). 1.22383 + \param opacity Opacity of the drawing. 1.22384 + \param pattern Used pattern to draw lines. 1.22385 + \note Clipping is supported. 1.22386 + **/ 1.22387 + template<typename t1, typename t2> 1.22388 + CImg<T>& draw_quiver(const CImg<t1>& flow, 1.22389 + const CImg<t2>& color, const float opacity=1, 1.22390 + const unsigned int sampling=25, const float factor=-20, 1.22391 + const int quiver_type=0, const unsigned int pattern=~0U) { 1.22392 + if (!is_empty()) { 1.22393 + if (!flow || flow.dim!=2) 1.22394 + throw CImgArgumentException("CImg<%s>::draw_quiver() : Specified flow (%u,%u,%u,%u,%p) has wrong dimensions.", 1.22395 + pixel_type(),flow.width,flow.height,flow.depth,flow.dim,flow.data); 1.22396 + if (sampling<=0) 1.22397 + throw CImgArgumentException("CImg<%s>::draw_quiver() : Incorrect sampling value = %g", 1.22398 + pixel_type(),sampling); 1.22399 + const bool colorfield = (color.width==flow.width && color.height==flow.height && color.depth==1 && color.dim==dim); 1.22400 + if (is_overlapped(flow)) return draw_quiver(+flow,color,opacity,sampling,factor,quiver_type,pattern); 1.22401 + 1.22402 + float vmax,fact; 1.22403 + if (factor<=0) { 1.22404 + float m, M = (float)flow.get_pointwise_norm(2).maxmin(m); 1.22405 + vmax = (float)cimg::max(cimg::abs(m),cimg::abs(M)); 1.22406 + fact = -factor; 1.22407 + } else { fact = factor; vmax = 1; } 1.22408 + 1.22409 + for (unsigned int y=sampling/2; y<height; y+=sampling) 1.22410 + for (unsigned int x=sampling/2; x<width; x+=sampling) { 1.22411 + const unsigned int X = x*flow.width/width, Y = y*flow.height/height; 1.22412 + float u = (float)flow(X,Y,0,0)*fact/vmax, v = (float)flow(X,Y,0,1)*fact/vmax; 1.22413 + if (!quiver_type) { 1.22414 + const int xx = x+(int)u, yy = y+(int)v; 1.22415 + if (colorfield) draw_arrow(x,y,xx,yy,color.get_vector_at(X,Y).data,opacity,45,sampling/5.0f,pattern); 1.22416 + else draw_arrow(x,y,xx,yy,color,opacity,45,sampling/5.0f,pattern); 1.22417 + } else { 1.22418 + 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),opacity,pattern); 1.22419 + else draw_line((int)(x-0.5*u),(int)(y-0.5*v),(int)(x+0.5*u),(int)(y+0.5*v),color,opacity,pattern); 1.22420 + } 1.22421 + } 1.22422 + } 1.22423 + return *this; 1.22424 + } 1.22425 + 1.22426 + //! Draw a 1D graph on the instance image. 1.22427 + /** 1.22428 + \param data Image containing the graph values I = f(x). 1.22429 + \param color Array of dimv() values of type \c T, defining the drawing color. 1.22430 + \param gtype Define the type of the plot : 1.22431 + - 0 = Plot using points clouds. 1.22432 + - 1 = Plot using linear interpolation (segments). 1.22433 + - 2 = Plot with bars. 1.22434 + - 3 = Plot using cubic interpolation (3-polynomials). 1.22435 + - 4 = Plot using cross clouds. 1.22436 + \param ymin Lower bound of the y-range. 1.22437 + \param ymax Upper bound of the y-range. 1.22438 + \param opacity Drawing opacity. 1.22439 + \param pattern Drawing pattern. 1.22440 + \note 1.22441 + - if \c ymin==ymax==0, the y-range is computed automatically from the input sample. 1.22442 + **/ 1.22443 + template<typename t, typename tc> 1.22444 + CImg<T>& draw_graph(const CImg<t>& data, 1.22445 + const tc *const color, const float opacity=1, 1.22446 + const unsigned int plot_type=1, const unsigned int vertex_type=1, 1.22447 + const double ymin=0, const double ymax=0, 1.22448 + const unsigned int pattern=~0U) { 1.22449 + if (is_empty() || height<=1) return *this;; 1.22450 + const unsigned long siz = data.size(); 1.22451 + if (!color) 1.22452 + throw CImgArgumentException("CImg<%s>::draw_graph() : Specified color is (null)", 1.22453 + pixel_type()); 1.22454 + tc *color1 = 0, *color2 = 0; 1.22455 + if (plot_type==3) { 1.22456 + color1 = new tc[dim]; color2 = new tc[dim]; 1.22457 + cimg_forV(*this,k) { color1[k] = (tc)(color[k]*0.6f); color2[k] = (tc)(color[k]*0.3f); } 1.22458 + } 1.22459 + 1.22460 + double m = ymin, M = ymax; 1.22461 + if (ymin==ymax) m = (double)data.maxmin(M); 1.22462 + if (m==M) { --m; ++M; } 1.22463 + const float ca = (float)(M-m)/(height-1); 1.22464 + bool init_hatch = true; 1.22465 + 1.22466 + // Draw graph edges 1.22467 + switch (plot_type%4) { 1.22468 + case 1 : { // Segments 1.22469 + int oX = 0, oY = (int)((data[0]-m)/ca); 1.22470 + for (unsigned long off = 1; off<siz; ++off) { 1.22471 + const int 1.22472 + X = (int)(off*width/siz), 1.22473 + Y = (int)((data[off]-m)/ca); 1.22474 + draw_line(oX,oY,X,Y,color,opacity,pattern,init_hatch); 1.22475 + oX = X; oY = Y; 1.22476 + init_hatch = false; 1.22477 + } 1.22478 + } break; 1.22479 + case 2 : { // Spline 1.22480 + const CImg<t> ndata = data.get_shared_points(0,siz-1); 1.22481 + int oY = (int)((data[0]-m)/ca); 1.22482 + cimg_forX(*this,x) { 1.22483 + const int Y = (int)((ndata._cubic_atX((float)x*ndata.width/width)-m)/ca); 1.22484 + if (x>0) draw_line(x,oY,x+1,Y,color,opacity,pattern,init_hatch); 1.22485 + init_hatch = false; 1.22486 + oY = Y; 1.22487 + } 1.22488 + } break; 1.22489 + case 3 : { // Bars 1.22490 + const int Y0 = (int)(-m/ca); 1.22491 + int oX = 0; 1.22492 + cimg_foroff(data,off) { 1.22493 + const int 1.22494 + X = (off+1)*width/siz-1, 1.22495 + Y = (int)((data[off]-m)/ca); 1.22496 + draw_rectangle(oX,Y0,X,Y,color1,opacity). 1.22497 + draw_line(oX,Y,oX,Y0,color2,opacity). 1.22498 + draw_line(oX,Y0,X,Y0,Y<=Y0?color2:color,opacity). 1.22499 + draw_line(X,Y,X,Y0,color,opacity). 1.22500 + draw_line(oX,Y,X,Y,Y<=Y0?color:color2,opacity); 1.22501 + oX = X+1; 1.22502 + } 1.22503 + } break; 1.22504 + default : break; // No edges 1.22505 + } 1.22506 + 1.22507 + // Draw graph points 1.22508 + switch (vertex_type%8) { 1.22509 + case 1 : { // Point 1.22510 + cimg_foroff(data,off) { 1.22511 + const int X = off*width/siz, Y = (int)((data[off]-m)/ca); 1.22512 + draw_point(X,Y,color,opacity); 1.22513 + } 1.22514 + } break; 1.22515 + case 2 : { // Standard Cross 1.22516 + cimg_foroff(data,off) { 1.22517 + const int X = off*width/siz, Y = (int)((data[off]-m)/ca); 1.22518 + draw_line(X-3,Y,X+3,Y,color,opacity).draw_line(X,Y-3,X,Y+3,color,opacity); 1.22519 + } 1.22520 + } break; 1.22521 + case 3 : { // Rotated Cross 1.22522 + cimg_foroff(data,off) { 1.22523 + const int X = off*width/siz, Y = (int)((data[off]-m)/ca); 1.22524 + draw_line(X-3,Y-3,X+3,Y+3,color,opacity).draw_line(X-3,Y+3,X+3,Y-3,color,opacity); 1.22525 + } 1.22526 + } break; 1.22527 + case 4 : { // Filled Circle 1.22528 + cimg_foroff(data,off) { 1.22529 + const int X = off*width/siz, Y = (int)((data[off]-m)/ca); 1.22530 + draw_circle(X,Y,3,color,opacity); 1.22531 + } 1.22532 + } break; 1.22533 + case 5 : { // Outlined circle 1.22534 + cimg_foroff(data,off) { 1.22535 + const int X = off*width/siz, Y = (int)((data[off]-m)/ca); 1.22536 + draw_circle(X,Y,3,color,opacity,0U); 1.22537 + } 1.22538 + } break; 1.22539 + case 6 : { // Square 1.22540 + cimg_foroff(data,off) { 1.22541 + const int X = off*width/siz, Y = (int)((data[off]-m)/ca); 1.22542 + draw_rectangle(X-3,Y-3,X+3,Y+3,color,opacity,~0U); 1.22543 + } 1.22544 + } break; 1.22545 + case 7 : { // Diamond 1.22546 + cimg_foroff(data,off) { 1.22547 + const int X = off*width/siz, Y = (int)((data[off]-m)/ca); 1.22548 + draw_line(X,Y-4,X+4,Y,color,opacity). 1.22549 + draw_line(X+4,Y,X,Y+4,color,opacity). 1.22550 + draw_line(X,Y+4,X-4,Y,color,opacity). 1.22551 + draw_line(X-4,Y,X,Y-4,color,opacity); 1.22552 + } 1.22553 + } break; 1.22554 + default : break; // No vertices 1.22555 + } 1.22556 + 1.22557 + if (color1) delete[] color1; if (color2) delete[] color2; 1.22558 + return *this; 1.22559 + } 1.22560 + 1.22561 + //! Draw a 1D graph on the instance image. 1.22562 + template<typename t, typename tc> 1.22563 + CImg<T>& draw_graph(const CImg<t>& data, 1.22564 + const CImg<tc>& color, const float opacity=1, 1.22565 + const unsigned int plot_type=1, const unsigned int vertex_type=1, 1.22566 + const double ymin=0, const double ymax=0, 1.22567 + const unsigned int pattern=~0U) { 1.22568 + return draw_graph(data,color.data,opacity,plot_type,vertex_type,ymin,ymax,pattern); 1.22569 + } 1.22570 + 1.22571 + //! Draw a labeled horizontal axis on the instance image. 1.22572 + /** 1.22573 + \param xvalues Lower bound of the x-range. 1.22574 + \param y Y-coordinate of the horizontal axis in the instance image. 1.22575 + \param color Array of dimv() values of type \c T, defining the drawing color. 1.22576 + \param opacity Drawing opacity. 1.22577 + \param pattern Drawing pattern. 1.22578 + \param opacity_out Drawing opacity of 'outside' axes. 1.22579 + \note if \c precision==0, precision of the labels is automatically computed. 1.22580 + **/ 1.22581 + template<typename t, typename tc> 1.22582 + CImg<T>& draw_axis(const CImg<t>& xvalues, const int y, 1.22583 + const tc *const color, const float opacity=1, 1.22584 + const unsigned int pattern=~0U) { 1.22585 + if (!is_empty()) { 1.22586 + int siz = (int)xvalues.size()-1; 1.22587 + if (siz<=0) draw_line(0,y,width-1,y,color,opacity,pattern); 1.22588 + else { 1.22589 + if (xvalues[0]<xvalues[siz]) draw_arrow(0,y,width-1,y,color,opacity,30,5,pattern); 1.22590 + else draw_arrow(width-1,y,0,y,color,opacity,30,5,pattern); 1.22591 + const int yt = (y+14)<dimy()?(y+3):(y-14); 1.22592 + char txt[32]; 1.22593 + cimg_foroff(xvalues,x) { 1.22594 + cimg_std::sprintf(txt,"%g",(double)xvalues(x)); 1.22595 + const int xi = (int)(x*(width-1)/siz), xt = xi-(int)cimg::strlen(txt)*3; 1.22596 + draw_point(xi,y-1,color,opacity).draw_point(xi,y+1,color,opacity). 1.22597 + draw_text(xt<0?0:xt,yt,txt,color,(tc*)0,opacity,11); 1.22598 + } 1.22599 + } 1.22600 + } 1.22601 + return *this; 1.22602 + } 1.22603 + 1.22604 + //! Draw a labeled horizontal axis on the instance image. 1.22605 + template<typename t, typename tc> 1.22606 + CImg<T>& draw_axis(const CImg<t>& xvalues, const int y, 1.22607 + const CImg<tc>& color, const float opacity=1, 1.22608 + const unsigned int pattern=~0U) { 1.22609 + return draw_axis(xvalues,y,color.data,opacity,pattern); 1.22610 + } 1.22611 + 1.22612 + //! Draw a labeled vertical axis on the instance image. 1.22613 + template<typename t, typename tc> 1.22614 + CImg<T>& draw_axis(const int x, const CImg<t>& yvalues, 1.22615 + const tc *const color, const float opacity=1, 1.22616 + const unsigned int pattern=~0U) { 1.22617 + if (!is_empty()) { 1.22618 + int siz = (int)yvalues.size()-1; 1.22619 + if (siz<=0) draw_line(x,0,x,height-1,color,opacity,pattern); 1.22620 + else { 1.22621 + if (yvalues[0]<yvalues[siz]) draw_arrow(x,0,x,height-1,color,opacity,30,5,pattern); 1.22622 + else draw_arrow(x,height-1,x,0,color,opacity,30,5,pattern); 1.22623 + char txt[32]; 1.22624 + cimg_foroff(yvalues,y) { 1.22625 + cimg_std::sprintf(txt,"%g",(double)yvalues(y)); 1.22626 + const int 1.22627 + yi = (int)(y*(height-1)/siz), 1.22628 + tmp = yi-5, 1.22629 + nyi = tmp<0?0:(tmp>=dimy()-11?dimy()-11:tmp), 1.22630 + xt = x-(int)cimg::strlen(txt)*7; 1.22631 + draw_point(x-1,yi,color,opacity).draw_point(x+1,yi,color,opacity); 1.22632 + if (xt>0) draw_text(xt,nyi,txt,color,(tc*)0,opacity,11); 1.22633 + else draw_text(x+3,nyi,txt,color,(tc*)0,opacity,11); 1.22634 + } 1.22635 + } 1.22636 + } 1.22637 + return *this; 1.22638 + } 1.22639 + 1.22640 + //! Draw a labeled vertical axis on the instance image. 1.22641 + template<typename t, typename tc> 1.22642 + CImg<T>& draw_axis(const int x, const CImg<t>& yvalues, 1.22643 + const CImg<tc>& color, const float opacity=1, 1.22644 + const unsigned int pattern=~0U) { 1.22645 + return draw_axis(x,yvalues,color.data,opacity,pattern); 1.22646 + } 1.22647 + 1.22648 + //! Draw a labeled horizontal+vertical axis on the instance image. 1.22649 + template<typename tx, typename ty, typename tc> 1.22650 + CImg<T>& draw_axis(const CImg<tx>& xvalues, const CImg<ty>& yvalues, 1.22651 + const tc *const color, const float opacity=1, 1.22652 + const unsigned int patternx=~0U, const unsigned int patterny=~0U) { 1.22653 + if (!is_empty()) { 1.22654 + const CImg<tx> nxvalues(xvalues.data,xvalues.size(),1,1,1,true); 1.22655 + const int sizx = (int)xvalues.size()-1, wm1 = (int)(width)-1; 1.22656 + if (sizx>0) { 1.22657 + float ox = (float)nxvalues[0]; 1.22658 + for (unsigned int x = 1; x<width; ++x) { 1.22659 + const float nx = (float)nxvalues._linear_atX((float)x*sizx/wm1); 1.22660 + if (nx*ox<=0) { draw_axis(nx==0?x:x-1,yvalues,color,opacity,patterny); break; } 1.22661 + ox = nx; 1.22662 + } 1.22663 + } 1.22664 + const CImg<ty> nyvalues(yvalues.data,yvalues.size(),1,1,1,true); 1.22665 + const int sizy = (int)yvalues.size()-1, hm1 = (int)(height)-1; 1.22666 + if (sizy>0) { 1.22667 + float oy = (float)nyvalues[0]; 1.22668 + for (unsigned int y = 1; y<height; ++y) { 1.22669 + const float ny = (float)nyvalues._linear_atX((float)y*sizy/hm1); 1.22670 + if (ny*oy<=0) { draw_axis(xvalues,ny==0?y:y-1,color,opacity,patternx); break; } 1.22671 + oy = ny; 1.22672 + } 1.22673 + } 1.22674 + } 1.22675 + return *this; 1.22676 + } 1.22677 + 1.22678 + //! Draw a labeled horizontal+vertical axis on the instance image. 1.22679 + template<typename tx, typename ty, typename tc> 1.22680 + CImg<T>& draw_axis(const CImg<tx>& xvalues, const CImg<ty>& yvalues, 1.22681 + const CImg<tc>& color, const float opacity=1, 1.22682 + const unsigned int patternx=~0U, const unsigned int patterny=~0U) { 1.22683 + return draw_axis(xvalues,yvalues,color.data,opacity,patternx,patterny); 1.22684 + } 1.22685 + 1.22686 + //! Draw a labeled horizontal+vertical axis on the instance image. 1.22687 + template<typename tc> 1.22688 + CImg<T>& draw_axis(const float x0, const float x1, const float y0, const float y1, 1.22689 + const tc *const color, const float opacity=1, 1.22690 + const int subdivisionx=-60, const int subdivisiony=-60, 1.22691 + const float precisionx=0, const float precisiony=0, 1.22692 + const unsigned int patternx=~0U, const unsigned int patterny=~0U) { 1.22693 + if (!is_empty()) { 1.22694 + const float 1.22695 + dx = cimg::abs(x1-x0), dy = cimg::abs(y1-y0), 1.22696 + px = (precisionx==0)?(float)cimg_std::pow(10.0,(int)cimg_std::log10(dx)-2.0):precisionx, 1.22697 + py = (precisiony==0)?(float)cimg_std::pow(10.0,(int)cimg_std::log10(dy)-2.0):precisiony; 1.22698 + draw_axis(CImg<floatT>::sequence(subdivisionx>0?subdivisionx:1-dimx()/subdivisionx,x0,x1).round(px), 1.22699 + CImg<floatT>::sequence(subdivisiony>0?subdivisiony:1-dimy()/subdivisiony,y0,y1).round(py), 1.22700 + color,opacity,patternx,patterny); 1.22701 + } 1.22702 + return *this; 1.22703 + } 1.22704 + 1.22705 + //! Draw a labeled horizontal+vertical axis on the instance image. 1.22706 + template<typename tc> 1.22707 + CImg<T>& draw_axis(const float x0, const float x1, const float y0, const float y1, 1.22708 + const CImg<tc>& color, const float opacity=1, 1.22709 + const int subdivisionx=-60, const int subdivisiony=-60, 1.22710 + const float precisionx=0, const float precisiony=0, 1.22711 + const unsigned int patternx=~0U, const unsigned int patterny=~0U) { 1.22712 + return draw_axis(x0,x1,y0,y1,color.data,opacity,subdivisionx,subdivisiony,precisionx,precisiony,patternx,patterny); 1.22713 + } 1.22714 + 1.22715 + //! Draw grid. 1.22716 + template<typename tx, typename ty, typename tc> 1.22717 + CImg<T>& draw_grid(const CImg<tx>& xvalues, const CImg<ty>& yvalues, 1.22718 + const tc *const color, const float opacity=1, 1.22719 + const unsigned int patternx=~0U, const unsigned int patterny=~0U) { 1.22720 + if (!is_empty()) { 1.22721 + if (xvalues) cimg_foroff(xvalues,x) { 1.22722 + const int xi = (int)xvalues[x]; 1.22723 + if (xi>=0 && xi<dimx()) draw_line(xi,0,xi,height-1,color,opacity,patternx); 1.22724 + } 1.22725 + if (yvalues) cimg_foroff(yvalues,y) { 1.22726 + const int yi = (int)yvalues[y]; 1.22727 + if (yi>=0 && yi<dimy()) draw_line(0,yi,width-1,yi,color,opacity,patterny); 1.22728 + } 1.22729 + } 1.22730 + return *this; 1.22731 + } 1.22732 + 1.22733 + //! Draw grid. 1.22734 + template<typename tx, typename ty, typename tc> 1.22735 + CImg<T>& draw_grid(const CImg<tx>& xvalues, const CImg<ty>& yvalues, 1.22736 + const CImg<tc>& color, const float opacity=1, 1.22737 + const unsigned int patternx=~0U, const unsigned int patterny=~0U) { 1.22738 + return draw_grid(xvalues,yvalues,color.data,opacity,patternx,patterny); 1.22739 + } 1.22740 + 1.22741 + //! Draw grid. 1.22742 + template<typename tc> 1.22743 + CImg<T>& draw_grid(const float deltax, const float deltay, 1.22744 + const float offsetx, const float offsety, 1.22745 + const bool invertx, const bool inverty, 1.22746 + const tc *const color, const float opacity=1, 1.22747 + const unsigned int patternx=~0U, const unsigned int patterny=~0U) { 1.22748 + CImg<uintT> seqx, seqy; 1.22749 + if (deltax!=0) { 1.22750 + const float dx = deltax>0?deltax:width*-deltax/100; 1.22751 + const unsigned int nx = (unsigned int)(width/dx); 1.22752 + seqx = CImg<uintT>::sequence(1+nx,0,(unsigned int)(dx*nx)); 1.22753 + if (offsetx) cimg_foroff(seqx,x) seqx(x) = (unsigned int)cimg::mod(seqx(x)+offsetx,(float)width); 1.22754 + if (invertx) cimg_foroff(seqx,x) seqx(x) = width-1-seqx(x); 1.22755 + } 1.22756 + 1.22757 + if (deltay!=0) { 1.22758 + const float dy = deltay>0?deltay:height*-deltay/100; 1.22759 + const unsigned int ny = (unsigned int)(height/dy); 1.22760 + seqy = CImg<uintT>::sequence(1+ny,0,(unsigned int)(dy*ny)); 1.22761 + if (offsety) cimg_foroff(seqy,y) seqy(y) = (unsigned int)cimg::mod(seqy(y)+offsety,(float)height); 1.22762 + if (inverty) cimg_foroff(seqy,y) seqy(y) = height-1-seqy(y); 1.22763 + } 1.22764 + return draw_grid(seqx,seqy,color,opacity,patternx,patterny); 1.22765 + } 1.22766 + 1.22767 + //! Draw grid. 1.22768 + template<typename tc> 1.22769 + CImg<T>& draw_grid(const float deltax, const float deltay, 1.22770 + const float offsetx, const float offsety, 1.22771 + const bool invertx, const bool inverty, 1.22772 + const CImg<tc>& color, const float opacity=1, 1.22773 + const unsigned int patternx=~0U, const unsigned int patterny=~0U) { 1.22774 + return draw_grid(deltax,deltay,offsetx,offsety,invertx,inverty,color.data,opacity,patternx,patterny); 1.22775 + } 1.22776 + 1.22777 + //! Draw a 3D filled region starting from a point (\c x,\c y,\ z) in the instance image. 1.22778 + /** 1.22779 + \param x X-coordinate of the starting point of the region to fill. 1.22780 + \param y Y-coordinate of the starting point of the region to fill. 1.22781 + \param z Z-coordinate of the starting point of the region to fill. 1.22782 + \param color An array of dimv() values of type \c T, defining the drawing color. 1.22783 + \param region Image that will contain the mask of the filled region mask, as an output. 1.22784 + \param sigma Tolerance concerning neighborhood values. 1.22785 + \param opacity Opacity of the drawing. 1.22786 + \param high_connexity Tells if 8-connexity must be used (only for 2D images). 1.22787 + \return \p region is initialized with the binary mask of the filled region. 1.22788 + **/ 1.22789 + template<typename tc, typename t> 1.22790 + CImg<T>& draw_fill(const int x, const int y, const int z, 1.22791 + const tc *const color, const float opacity, 1.22792 + CImg<t>& region, const float sigma=0, 1.22793 + const bool high_connexity=false) { 1.22794 + 1.22795 +#define _cimg_draw_fill_test(x,y,z,res) if (region(x,y,z)) res = false; else { \ 1.22796 + res = true; \ 1.22797 + const T *reference_col = reference_color.ptr() + dim, *ptrs = ptr(x,y,z) + siz; \ 1.22798 + for (unsigned int i = dim; res && i; --i) { ptrs-=whz; res = (cimg::abs(*ptrs - *(--reference_col))<=sigma); } \ 1.22799 + region(x,y,z) = (t)(res?1:noregion); \ 1.22800 +} 1.22801 + 1.22802 +#define _cimg_draw_fill_set(x,y,z) { \ 1.22803 + const tc *col = color; \ 1.22804 + T *ptrd = ptr(x,y,z); \ 1.22805 + if (opacity>=1) cimg_forV(*this,k) { *ptrd = (T)*(col++); ptrd+=whz; } \ 1.22806 + else cimg_forV(*this,k) { *ptrd = (T)(*(col++)*nopacity + *ptrd*copacity); ptrd+=whz; } \ 1.22807 +} 1.22808 + 1.22809 +#define _cimg_draw_fill_insert(x,y,z) { \ 1.22810 + if (posr1>=remaining.height) remaining.resize(3,remaining.height<<1,1,1,0); \ 1.22811 + unsigned int *ptrr = remaining.ptr(0,posr1); \ 1.22812 + *(ptrr++) = x; *(ptrr++) = y; *(ptrr++) = z; ++posr1; \ 1.22813 +} 1.22814 + 1.22815 +#define _cimg_draw_fill_test_neighbor(x,y,z,cond) if (cond) { \ 1.22816 + const unsigned int tx = x, ty = y, tz = z; \ 1.22817 + _cimg_draw_fill_test(tx,ty,tz,res); if (res) _cimg_draw_fill_insert(tx,ty,tz); \ 1.22818 +} 1.22819 + 1.22820 + if (!color) 1.22821 + throw CImgArgumentException("CImg<%s>::draw_fill() : Specified color is (null).", 1.22822 + pixel_type()); 1.22823 + region.assign(width,height,depth,1,(t)0); 1.22824 + if (x>=0 && x<dimx() && y>=0 && y<dimy() && z>=0 && z<dimz()) { 1.22825 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.22826 + const unsigned int whz = width*height*depth, siz = dim*whz, W1 = width-1, H1 = height-1, D1 = depth-1; 1.22827 + const bool threed = depth>1; 1.22828 + const CImg<T> reference_color = get_vector_at(x,y,z); 1.22829 + CImg<uintT> remaining(3,512,1,1,0); 1.22830 + remaining(0,0) = x; remaining(1,0) = y; remaining(2,0) = z; 1.22831 + unsigned int posr0 = 0, posr1 = 1; 1.22832 + region(x,y,z) = (t)1; 1.22833 + const t noregion = ((t)1==(t)2)?(t)0:(t)(-1); 1.22834 + if (threed) do { // 3D version of the filling algorithm 1.22835 + const unsigned int *pcurr = remaining.ptr(0,posr0++), xc = *(pcurr++), yc = *(pcurr++), zc = *(pcurr++); 1.22836 + if (posr0>=512) { remaining.translate(0,posr0); posr1-=posr0; posr0 = 0; } 1.22837 + bool cont, res; 1.22838 + unsigned int nxc = xc; 1.22839 + do { // X-backward 1.22840 + _cimg_draw_fill_set(nxc,yc,zc); 1.22841 + _cimg_draw_fill_test_neighbor(nxc,yc-1,zc,yc!=0); 1.22842 + _cimg_draw_fill_test_neighbor(nxc,yc+1,zc,yc<H1); 1.22843 + _cimg_draw_fill_test_neighbor(nxc,yc,zc-1,zc!=0); 1.22844 + _cimg_draw_fill_test_neighbor(nxc,yc,zc+1,zc<D1); 1.22845 + if (nxc) { --nxc; _cimg_draw_fill_test(nxc,yc,zc,cont); } else cont = false; 1.22846 + } while (cont); 1.22847 + nxc = xc; 1.22848 + do { // X-forward 1.22849 + if ((++nxc)<=W1) { _cimg_draw_fill_test(nxc,yc,zc,cont); } else cont = false; 1.22850 + if (cont) { 1.22851 + _cimg_draw_fill_set(nxc,yc,zc); 1.22852 + _cimg_draw_fill_test_neighbor(nxc,yc-1,zc,yc!=0); 1.22853 + _cimg_draw_fill_test_neighbor(nxc,yc+1,zc,yc<H1); 1.22854 + _cimg_draw_fill_test_neighbor(nxc,yc,zc-1,zc!=0); 1.22855 + _cimg_draw_fill_test_neighbor(nxc,yc,zc+1,zc<D1); 1.22856 + } 1.22857 + } while (cont); 1.22858 + unsigned int nyc = yc; 1.22859 + do { // Y-backward 1.22860 + if (nyc) { --nyc; _cimg_draw_fill_test(xc,nyc,zc,cont); } else cont = false; 1.22861 + if (cont) { 1.22862 + _cimg_draw_fill_set(xc,nyc,zc); 1.22863 + _cimg_draw_fill_test_neighbor(xc-1,nyc,zc,xc!=0); 1.22864 + _cimg_draw_fill_test_neighbor(xc+1,nyc,zc,xc<W1); 1.22865 + _cimg_draw_fill_test_neighbor(xc,nyc,zc-1,zc!=0); 1.22866 + _cimg_draw_fill_test_neighbor(xc,nyc,zc+1,zc<D1); 1.22867 + } 1.22868 + } while (cont); 1.22869 + nyc = yc; 1.22870 + do { // Y-forward 1.22871 + if ((++nyc)<=H1) { _cimg_draw_fill_test(xc,nyc,zc,cont); } else cont = false; 1.22872 + if (cont) { 1.22873 + _cimg_draw_fill_set(xc,nyc,zc); 1.22874 + _cimg_draw_fill_test_neighbor(xc-1,nyc,zc,xc!=0); 1.22875 + _cimg_draw_fill_test_neighbor(xc+1,nyc,zc,xc<W1); 1.22876 + _cimg_draw_fill_test_neighbor(xc,nyc,zc-1,zc!=0); 1.22877 + _cimg_draw_fill_test_neighbor(xc,nyc,zc+1,zc<D1); 1.22878 + } 1.22879 + } while (cont); 1.22880 + unsigned int nzc = zc; 1.22881 + do { // Z-backward 1.22882 + if (nzc) { --nzc; _cimg_draw_fill_test(xc,yc,nzc,cont); } else cont = false; 1.22883 + if (cont) { 1.22884 + _cimg_draw_fill_set(xc,yc,nzc); 1.22885 + _cimg_draw_fill_test_neighbor(xc-1,yc,nzc,xc!=0); 1.22886 + _cimg_draw_fill_test_neighbor(xc+1,yc,nzc,xc<W1); 1.22887 + _cimg_draw_fill_test_neighbor(xc,yc-1,nzc,yc!=0); 1.22888 + _cimg_draw_fill_test_neighbor(xc,yc+1,nzc,yc<H1); 1.22889 + } 1.22890 + } while (cont); 1.22891 + nzc = zc; 1.22892 + do { // Z-forward 1.22893 + if ((++nzc)<=D1) { _cimg_draw_fill_test(xc,yc,nzc,cont); } else cont = false; 1.22894 + if (cont) { 1.22895 + _cimg_draw_fill_set(xc,nyc,zc); 1.22896 + _cimg_draw_fill_test_neighbor(xc-1,yc,nzc,xc!=0); 1.22897 + _cimg_draw_fill_test_neighbor(xc+1,yc,nzc,xc<W1); 1.22898 + _cimg_draw_fill_test_neighbor(xc,yc-1,nzc,yc!=0); 1.22899 + _cimg_draw_fill_test_neighbor(xc,yc+1,nzc,yc<H1); 1.22900 + } 1.22901 + } while (cont); 1.22902 + } while (posr1>posr0); 1.22903 + else do { // 2D version of the filling algorithm 1.22904 + const unsigned int *pcurr = remaining.ptr(0,posr0++), xc = *(pcurr++), yc = *(pcurr++); 1.22905 + if (posr0>=512) { remaining.translate(0,posr0); posr1-=posr0; posr0 = 0; } 1.22906 + bool cont, res; 1.22907 + unsigned int nxc = xc; 1.22908 + do { // X-backward 1.22909 + _cimg_draw_fill_set(nxc,yc,0); 1.22910 + _cimg_draw_fill_test_neighbor(nxc,yc-1,0,yc!=0); 1.22911 + _cimg_draw_fill_test_neighbor(nxc,yc+1,0,yc<H1); 1.22912 + if (high_connexity) { 1.22913 + _cimg_draw_fill_test_neighbor(nxc-1,yc-1,0,(nxc!=0 && yc!=0)); 1.22914 + _cimg_draw_fill_test_neighbor(nxc+1,yc-1,0,(nxc<W1 && yc!=0)); 1.22915 + _cimg_draw_fill_test_neighbor(nxc-1,yc+1,0,(nxc!=0 && yc<H1)); 1.22916 + _cimg_draw_fill_test_neighbor(nxc+1,yc+1,0,(nxc<W1 && yc<H1)); 1.22917 + } 1.22918 + if (nxc) { --nxc; _cimg_draw_fill_test(nxc,yc,0,cont); } else cont = false; 1.22919 + } while (cont); 1.22920 + nxc = xc; 1.22921 + do { // X-forward 1.22922 + if ((++nxc)<=W1) { _cimg_draw_fill_test(nxc,yc,0,cont); } else cont = false; 1.22923 + if (cont) { 1.22924 + _cimg_draw_fill_set(nxc,yc,0); 1.22925 + _cimg_draw_fill_test_neighbor(nxc,yc-1,0,yc!=0); 1.22926 + _cimg_draw_fill_test_neighbor(nxc,yc+1,0,yc<H1); 1.22927 + if (high_connexity) { 1.22928 + _cimg_draw_fill_test_neighbor(nxc-1,yc-1,0,(nxc!=0 && yc!=0)); 1.22929 + _cimg_draw_fill_test_neighbor(nxc+1,yc-1,0,(nxc<W1 && yc!=0)); 1.22930 + _cimg_draw_fill_test_neighbor(nxc-1,yc+1,0,(nxc!=0 && yc<H1)); 1.22931 + _cimg_draw_fill_test_neighbor(nxc+1,yc+1,0,(nxc<W1 && yc<H1)); 1.22932 + } 1.22933 + } 1.22934 + } while (cont); 1.22935 + unsigned int nyc = yc; 1.22936 + do { // Y-backward 1.22937 + if (nyc) { --nyc; _cimg_draw_fill_test(xc,nyc,0,cont); } else cont = false; 1.22938 + if (cont) { 1.22939 + _cimg_draw_fill_set(xc,nyc,0); 1.22940 + _cimg_draw_fill_test_neighbor(xc-1,nyc,0,xc!=0); 1.22941 + _cimg_draw_fill_test_neighbor(xc+1,nyc,0,xc<W1); 1.22942 + if (high_connexity) { 1.22943 + _cimg_draw_fill_test_neighbor(xc-1,nyc-1,0,(xc!=0 && nyc!=0)); 1.22944 + _cimg_draw_fill_test_neighbor(xc+1,nyc-1,0,(xc<W1 && nyc!=0)); 1.22945 + _cimg_draw_fill_test_neighbor(xc-1,nyc+1,0,(xc!=0 && nyc<H1)); 1.22946 + _cimg_draw_fill_test_neighbor(xc+1,nyc+1,0,(xc<W1 && nyc<H1)); 1.22947 + } 1.22948 + } 1.22949 + } while (cont); 1.22950 + nyc = yc; 1.22951 + do { // Y-forward 1.22952 + if ((++nyc)<=H1) { _cimg_draw_fill_test(xc,nyc,0,cont); } else cont = false; 1.22953 + if (cont) { 1.22954 + _cimg_draw_fill_set(xc,nyc,0); 1.22955 + _cimg_draw_fill_test_neighbor(xc-1,nyc,0,xc!=0); 1.22956 + _cimg_draw_fill_test_neighbor(xc+1,nyc,0,xc<W1); 1.22957 + if (high_connexity) { 1.22958 + _cimg_draw_fill_test_neighbor(xc-1,nyc-1,0,(xc!=0 && nyc!=0)); 1.22959 + _cimg_draw_fill_test_neighbor(xc+1,nyc-1,0,(xc<W1 && nyc!=0)); 1.22960 + _cimg_draw_fill_test_neighbor(xc-1,nyc+1,0,(xc!=0 && nyc<H1)); 1.22961 + _cimg_draw_fill_test_neighbor(xc+1,nyc+1,0,(xc<W1 && nyc<H1)); 1.22962 + } 1.22963 + } 1.22964 + } while (cont); 1.22965 + } while (posr1>posr0); 1.22966 + if (noregion) cimg_for(region,ptr,t) if (*ptr==noregion) *ptr = (t)0; 1.22967 + } 1.22968 + return *this; 1.22969 + } 1.22970 + 1.22971 + //! Draw a 3D filled region starting from a point (\c x,\c y,\ z) in the instance image. 1.22972 + template<typename tc, typename t> 1.22973 + CImg<T>& draw_fill(const int x, const int y, const int z, 1.22974 + const CImg<tc>& color, const float opacity, 1.22975 + CImg<t>& region, const float sigma=0, const bool high_connexity=false) { 1.22976 + return draw_fill(x,y,z,color.data,opacity,region,sigma,high_connexity); 1.22977 + } 1.22978 + 1.22979 + //! Draw a 3D filled region starting from a point (\c x,\c y,\ z) in the instance image. 1.22980 + /** 1.22981 + \param x = X-coordinate of the starting point of the region to fill. 1.22982 + \param y = Y-coordinate of the starting point of the region to fill. 1.22983 + \param z = Z-coordinate of the starting point of the region to fill. 1.22984 + \param color = an array of dimv() values of type \c T, defining the drawing color. 1.22985 + \param sigma = tolerance concerning neighborhood values. 1.22986 + \param opacity = opacity of the drawing. 1.22987 + **/ 1.22988 + template<typename tc> 1.22989 + CImg<T>& draw_fill(const int x, const int y, const int z, 1.22990 + const tc *const color, const float opacity=1, 1.22991 + const float sigma=0, const bool high_connexity=false) { 1.22992 + CImg<boolT> tmp; 1.22993 + return draw_fill(x,y,z,color,opacity,tmp,sigma,high_connexity); 1.22994 + } 1.22995 + 1.22996 + //! Draw a 3D filled region starting from a point (\c x,\c y,\ z) in the instance image. 1.22997 + template<typename tc> 1.22998 + CImg<T>& draw_fill(const int x, const int y, const int z, 1.22999 + const CImg<tc>& color, const float opacity=1, 1.23000 + const float sigma=0, const bool high_connexity=false) { 1.23001 + return draw_fill(x,y,z,color.data,opacity,sigma,high_connexity); 1.23002 + } 1.23003 + 1.23004 + //! Draw a 2D filled region starting from a point (\c x,\c y) in the instance image. 1.23005 + /** 1.23006 + \param x = X-coordinate of the starting point of the region to fill. 1.23007 + \param y = Y-coordinate of the starting point of the region to fill. 1.23008 + \param color = an array of dimv() values of type \c T, defining the drawing color. 1.23009 + \param sigma = tolerance concerning neighborhood values. 1.23010 + \param opacity = opacity of the drawing. 1.23011 + **/ 1.23012 + template<typename tc> 1.23013 + CImg<T>& draw_fill(const int x, const int y, 1.23014 + const tc *const color, const float opacity=1, 1.23015 + const float sigma=0, const bool high_connexity=false) { 1.23016 + CImg<boolT> tmp; 1.23017 + return draw_fill(x,y,0,color,opacity,tmp,sigma,high_connexity); 1.23018 + } 1.23019 + 1.23020 + //! Draw a 2D filled region starting from a point (\c x,\c y) in the instance image. 1.23021 + template<typename tc> 1.23022 + CImg<T>& draw_fill(const int x, const int y, 1.23023 + const CImg<tc>& color, const float opacity=1, 1.23024 + const float sigma=0, const bool high_connexity=false) { 1.23025 + return draw_fill(x,y,color.data,opacity,sigma,high_connexity); 1.23026 + } 1.23027 + 1.23028 + //! Draw a plasma random texture. 1.23029 + /** 1.23030 + \param x0 = X-coordinate of the upper-left corner of the plasma. 1.23031 + \param y0 = Y-coordinate of the upper-left corner of the plasma. 1.23032 + \param x1 = X-coordinate of the lower-right corner of the plasma. 1.23033 + \param y1 = Y-coordinate of the lower-right corner of the plasma. 1.23034 + \param alpha = Alpha-parameter of the plasma. 1.23035 + \param beta = Beta-parameter of the plasma. 1.23036 + \param opacity = opacity of the drawing. 1.23037 + **/ 1.23038 + CImg<T>& draw_plasma(const int x0, const int y0, const int x1, const int y1, 1.23039 + const float alpha=1, const float beta=1, 1.23040 + const float opacity=1) { 1.23041 + if (!is_empty()) { 1.23042 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.23043 + int nx0 = x0, nx1 = x1, ny0 = y0, ny1 = y1; 1.23044 + if (nx1<nx0) cimg::swap(nx0,nx1); 1.23045 + if (ny1<ny0) cimg::swap(ny0,ny1); 1.23046 + if (nx0<0) nx0 = 0; 1.23047 + if (nx1>=dimx()) nx1 = width-1; 1.23048 + if (ny0<0) ny0 = 0; 1.23049 + if (ny1>=dimy()) ny1 = height-1; 1.23050 + const int xc = (nx0+nx1)/2, yc = (ny0+ny1)/2, dx = (xc-nx0), dy = (yc-ny0); 1.23051 + const Tfloat dc = (Tfloat)(cimg_std::sqrt((float)(dx*dx+dy*dy))*alpha + beta); 1.23052 + Tfloat val = 0; 1.23053 + cimg_forV(*this,k) { 1.23054 + if (opacity>=1) { 1.23055 + const Tfloat 1.23056 + val0 = (Tfloat)((*this)(nx0,ny0,0,k)), val1 = (Tfloat)((*this)(nx1,ny0,0,k)), 1.23057 + val2 = (Tfloat)((*this)(nx0,ny1,0,k)), val3 = (Tfloat)((*this)(nx1,ny1,0,k)); 1.23058 + (*this)(xc,ny0,0,k) = (T)((val0+val1)/2); 1.23059 + (*this)(xc,ny1,0,k) = (T)((val2+val3)/2); 1.23060 + (*this)(nx0,yc,0,k) = (T)((val0+val2)/2); 1.23061 + (*this)(nx1,yc,0,k) = (T)((val1+val3)/2); 1.23062 + do { 1.23063 + val = (Tfloat)(0.25f*((Tfloat)((*this)(nx0,ny0,0,k)) + 1.23064 + (Tfloat)((*this)(nx1,ny0,0,k)) + 1.23065 + (Tfloat)((*this)(nx1,ny1,0,k)) + 1.23066 + (Tfloat)((*this)(nx0,ny1,0,k))) + 1.23067 + dc*cimg::grand()); 1.23068 + } while (val<(Tfloat)cimg::type<T>::min() || val>(Tfloat)cimg::type<T>::max()); 1.23069 + (*this)(xc,yc,0,k) = (T)val; 1.23070 + } else { 1.23071 + const Tfloat 1.23072 + val0 = (Tfloat)((*this)(nx0,ny0,0,k)), val1 = (Tfloat)((*this)(nx1,ny0,0,k)), 1.23073 + val2 = (Tfloat)((*this)(nx0,ny1,0,k)), val3 = (Tfloat)((*this)(nx1,ny1,0,k)); 1.23074 + (*this)(xc,ny0,0,k) = (T)(((val0+val1)*nopacity + copacity*(*this)(xc,ny0,0,k))/2); 1.23075 + (*this)(xc,ny1,0,k) = (T)(((val2+val3)*nopacity + copacity*(*this)(xc,ny1,0,k))/2); 1.23076 + (*this)(nx0,yc,0,k) = (T)(((val0+val2)*nopacity + copacity*(*this)(nx0,yc,0,k))/2); 1.23077 + (*this)(nx1,yc,0,k) = (T)(((val1+val3)*nopacity + copacity*(*this)(nx1,yc,0,k))/2); 1.23078 + do { 1.23079 + val = (Tfloat)(0.25f*(((Tfloat)((*this)(nx0,ny0,0,k)) + 1.23080 + (Tfloat)((*this)(nx1,ny0,0,k)) + 1.23081 + (Tfloat)((*this)(nx1,ny1,0,k)) + 1.23082 + (Tfloat)((*this)(nx0,ny1,0,k))) + 1.23083 + dc*cimg::grand())*nopacity + copacity*(*this)(xc,yc,0,k)); 1.23084 + } while (val<(Tfloat)cimg::type<T>::min() || val>(Tfloat)cimg::type<T>::max()); 1.23085 + (*this)(xc,yc,0,k) = (T)val; 1.23086 + } 1.23087 + } 1.23088 + if (xc!=nx0 || yc!=ny0) { 1.23089 + draw_plasma(nx0,ny0,xc,yc,alpha,beta,opacity); 1.23090 + draw_plasma(xc,ny0,nx1,yc,alpha,beta,opacity); 1.23091 + draw_plasma(nx0,yc,xc,ny1,alpha,beta,opacity); 1.23092 + draw_plasma(xc,yc,nx1,ny1,alpha,beta,opacity); 1.23093 + } 1.23094 + } 1.23095 + return *this; 1.23096 + } 1.23097 + 1.23098 + //! Draw a plasma random texture. 1.23099 + /** 1.23100 + \param alpha = Alpha-parameter of the plasma. 1.23101 + \param beta = Beta-parameter of the plasma. 1.23102 + \param opacity = opacity of the drawing. 1.23103 + **/ 1.23104 + CImg<T>& draw_plasma(const float alpha=1, const float beta=1, 1.23105 + const float opacity=1) { 1.23106 + return draw_plasma(0,0,width-1,height-1,alpha,beta,opacity); 1.23107 + } 1.23108 + 1.23109 + //! Draw a quadratic Mandelbrot or Julia fractal set, computed using the Escape Time Algorithm. 1.23110 + template<typename tc> 1.23111 + CImg<T>& draw_mandelbrot(const int x0, const int y0, const int x1, const int y1, 1.23112 + const CImg<tc>& color_palette, const float opacity=1, 1.23113 + const double z0r=-2, const double z0i=-2, const double z1r=2, const double z1i=2, 1.23114 + const unsigned int itermax=255, 1.23115 + const bool normalized_iteration=false, 1.23116 + const bool julia_set=false, 1.23117 + const double paramr=0, const double parami=0) { 1.23118 + if (is_empty()) return *this; 1.23119 + CImg<tc> palette; 1.23120 + if (color_palette) palette.assign(color_palette.data,color_palette.size()/color_palette.dim,1,1,color_palette.dim,true); 1.23121 + if (palette && palette.dim!=dim) 1.23122 + throw CImgArgumentException("CImg<%s>::draw_mandelbrot() : Specified color palette (%u,%u,%u,%u,%p) is not \n" 1.23123 + "compatible with instance image (%u,%u,%u,%u,%p).", 1.23124 + pixel_type(),color_palette.width,color_palette.height,color_palette.depth,color_palette.dim, 1.23125 + color_palette.data,width,height,depth,dim,data); 1.23126 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0), ln2 = (float)cimg_std::log(2.0); 1.23127 + unsigned int iter = 0; 1.23128 + cimg_for_inXY(*this,x0,y0,x1,y1,p,q) { 1.23129 + const double x = z0r + p*(z1r-z0r)/width, y = z0i + q*(z1i-z0i)/height; 1.23130 + double zr, zi, cr, ci; 1.23131 + if (julia_set) { zr = x; zi = y; cr = paramr; ci = parami; } 1.23132 + else { zr = paramr; zi = parami; cr = x; ci = y; } 1.23133 + for (iter=1; zr*zr + zi*zi<=4 && iter<=itermax; ++iter) { 1.23134 + const double temp = zr*zr - zi*zi + cr; 1.23135 + zi = 2*zr*zi + ci; 1.23136 + zr = temp; 1.23137 + } 1.23138 + if (iter>itermax) { 1.23139 + if (palette) { 1.23140 + if (opacity>=1) cimg_forV(*this,k) (*this)(p,q,0,k) = (T)palette(0,k); 1.23141 + else cimg_forV(*this,k) (*this)(p,q,0,k) = (T)(palette(0,k)*nopacity + (*this)(p,q,0,k)*copacity); 1.23142 + } else { 1.23143 + if (opacity>=1) cimg_forV(*this,k) (*this)(p,q,0,k) = (T)0; 1.23144 + else cimg_forV(*this,k) (*this)(p,q,0,k) = (T)((*this)(p,q,0,k)*copacity); 1.23145 + } 1.23146 + } else if (normalized_iteration) { 1.23147 + const float 1.23148 + normz = (float)cimg::abs(zr*zr+zi*zi), 1.23149 + niter = (float)(iter + 1 - cimg_std::log(cimg_std::log(normz))/ln2); 1.23150 + if (palette) { 1.23151 + if (opacity>=1) cimg_forV(*this,k) (*this)(p,q,0,k) = (T)palette._linear_atX(niter,k); 1.23152 + else cimg_forV(*this,k) (*this)(p,q,0,k) = (T)(palette._linear_atX(niter,k)*nopacity + (*this)(p,q,0,k)*copacity); 1.23153 + } else { 1.23154 + if (opacity>=1) cimg_forV(*this,k) (*this)(p,q,0,k) = (T)niter; 1.23155 + else cimg_forV(*this,k) (*this)(p,q,0,k) = (T)(niter*nopacity + (*this)(p,q,0,k)*copacity); 1.23156 + } 1.23157 + } else { 1.23158 + if (palette) { 1.23159 + if (opacity>=1) cimg_forV(*this,k) (*this)(p,q,0,k) = (T)palette._atX(iter,k); 1.23160 + else cimg_forV(*this,k) (*this)(p,q,0,k) = (T)(palette(iter,k)*nopacity + (*this)(p,q,0,k)*copacity); 1.23161 + } else { 1.23162 + if (opacity>=1) cimg_forV(*this,k) (*this)(p,q,0,k) = (T)iter; 1.23163 + else cimg_forV(*this,k) (*this)(p,q,0,k) = (T)(iter*nopacity + (*this)(p,q,0,k)*copacity); 1.23164 + } 1.23165 + } 1.23166 + } 1.23167 + return *this; 1.23168 + } 1.23169 + 1.23170 + //! Draw a quadratic Mandelbrot or Julia fractal set, computed using the Escape Time Algorithm. 1.23171 + template<typename tc> 1.23172 + CImg<T>& draw_mandelbrot(const CImg<tc>& color_palette, const float opacity=1, 1.23173 + const double z0r=-2, const double z0i=-2, const double z1r=2, const double z1i=2, 1.23174 + const unsigned int itermax=255, 1.23175 + const bool normalized_iteration=false, 1.23176 + const bool julia_set=false, 1.23177 + const double paramr=0, const double parami=0) { 1.23178 + return draw_mandelbrot(0,0,width-1,height-1,color_palette,opacity,z0r,z0i,z1r,z1i,itermax,normalized_iteration,julia_set,paramr,parami); 1.23179 + } 1.23180 + 1.23181 + //! Draw a 1D gaussian function in the instance image. 1.23182 + /** 1.23183 + \param xc = X-coordinate of the gaussian center. 1.23184 + \param sigma = Standard variation of the gaussian distribution. 1.23185 + \param color = array of dimv() values of type \c T, defining the drawing color. 1.23186 + \param opacity = opacity of the drawing. 1.23187 + **/ 1.23188 + template<typename tc> 1.23189 + CImg<T>& draw_gaussian(const float xc, const float sigma, 1.23190 + const tc *const color, const float opacity=1) { 1.23191 + if (is_empty()) return *this; 1.23192 + if (!color) 1.23193 + throw CImgArgumentException("CImg<%s>::draw_gaussian() : Specified color is (null)", 1.23194 + pixel_type()); 1.23195 + const float sigma2 = 2*sigma*sigma, nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.23196 + const unsigned int whz = width*height*depth; 1.23197 + const tc *col = color; 1.23198 + cimg_forX(*this,x) { 1.23199 + const float dx = (x - xc), val = (float)cimg_std::exp(-dx*dx/sigma2); 1.23200 + T *ptrd = ptr(x,0,0,0); 1.23201 + if (opacity>=1) cimg_forV(*this,k) { *ptrd = (T)(val*(*col++)); ptrd+=whz; } 1.23202 + else cimg_forV(*this,k) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whz; } 1.23203 + col-=dim; 1.23204 + } 1.23205 + return *this; 1.23206 + } 1.23207 + 1.23208 + //! Draw a 1D gaussian function in the instance image. 1.23209 + template<typename tc> 1.23210 + CImg<T>& draw_gaussian(const float xc, const float sigma, 1.23211 + const CImg<tc>& color, const float opacity=1) { 1.23212 + return draw_gaussian(xc,sigma,color.data,opacity); 1.23213 + } 1.23214 + 1.23215 + //! Draw an anisotropic 2D gaussian function. 1.23216 + /** 1.23217 + \param xc = X-coordinate of the gaussian center. 1.23218 + \param yc = Y-coordinate of the gaussian center. 1.23219 + \param tensor = 2x2 covariance matrix. 1.23220 + \param color = array of dimv() values of type \c T, defining the drawing color. 1.23221 + \param opacity = opacity of the drawing. 1.23222 + **/ 1.23223 + template<typename t, typename tc> 1.23224 + CImg<T>& draw_gaussian(const float xc, const float yc, const CImg<t>& tensor, 1.23225 + const tc *const color, const float opacity=1) { 1.23226 + if (is_empty()) return *this; 1.23227 + typedef typename cimg::superset<t,float>::type tfloat; 1.23228 + if (tensor.width!=2 || tensor.height!=2 || tensor.depth!=1 || tensor.dim!=1) 1.23229 + throw CImgArgumentException("CImg<%s>::draw_gaussian() : Tensor parameter (%u,%u,%u,%u,%p) is not a 2x2 matrix.", 1.23230 + pixel_type(),tensor.width,tensor.height,tensor.depth,tensor.dim,tensor.data); 1.23231 + if (!color) 1.23232 + throw CImgArgumentException("CImg<%s>::draw_gaussian() : Specified color is (null)", 1.23233 + pixel_type()); 1.23234 + const CImg<tfloat> invT = tensor.get_invert(), invT2 = (invT*invT)/(-2.0); 1.23235 + const tfloat a = invT2(0,0), b = 2*invT2(1,0), c = invT2(1,1); 1.23236 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.23237 + const unsigned int whz = width*height*depth; 1.23238 + const tc *col = color; 1.23239 + float dy = -yc; 1.23240 + cimg_forY(*this,y) { 1.23241 + float dx = -xc; 1.23242 + cimg_forX(*this,x) { 1.23243 + const float val = (float)cimg_std::exp(a*dx*dx + b*dx*dy + c*dy*dy); 1.23244 + T *ptrd = ptr(x,y,0,0); 1.23245 + if (opacity>=1) cimg_forV(*this,k) { *ptrd = (T)(val*(*col++)); ptrd+=whz; } 1.23246 + else cimg_forV(*this,k) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whz; } 1.23247 + col-=dim; 1.23248 + ++dx; 1.23249 + } 1.23250 + ++dy; 1.23251 + } 1.23252 + return *this; 1.23253 + } 1.23254 + 1.23255 + //! Draw an anisotropic 2D gaussian function. 1.23256 + template<typename t, typename tc> 1.23257 + CImg<T>& draw_gaussian(const float xc, const float yc, const CImg<t>& tensor, 1.23258 + const CImg<tc>& color, const float opacity=1) { 1.23259 + return draw_gaussian(xc,yc,tensor,color.data,opacity); 1.23260 + } 1.23261 + 1.23262 + //! Draw an anisotropic 2D gaussian function. 1.23263 + template<typename tc> 1.23264 + CImg<T>& draw_gaussian(const int xc, const int yc, const float r1, const float r2, const float ru, const float rv, 1.23265 + const tc *const color, const float opacity=1) { 1.23266 + const double 1.23267 + a = r1*ru*ru + r2*rv*rv, 1.23268 + b = (r1-r2)*ru*rv, 1.23269 + c = r1*rv*rv + r2*ru*ru; 1.23270 + const CImg<Tfloat> tensor(2,2,1,1, a,b,b,c); 1.23271 + return draw_gaussian(xc,yc,tensor,color,opacity); 1.23272 + } 1.23273 + 1.23274 + //! Draw an anisotropic 2D gaussian function. 1.23275 + template<typename tc> 1.23276 + CImg<T>& draw_gaussian(const int xc, const int yc, const float r1, const float r2, const float ru, const float rv, 1.23277 + const CImg<tc>& color, const float opacity=1) { 1.23278 + return draw_gaussian(xc,yc,r1,r2,ru,rv,color.data,opacity); 1.23279 + } 1.23280 + 1.23281 + //! Draw an isotropic 2D gaussian function. 1.23282 + /** 1.23283 + \param xc = X-coordinate of the gaussian center. 1.23284 + \param yc = Y-coordinate of the gaussian center. 1.23285 + \param sigma = standard variation of the gaussian distribution. 1.23286 + \param color = array of dimv() values of type \c T, defining the drawing color. 1.23287 + \param opacity = opacity of the drawing. 1.23288 + **/ 1.23289 + template<typename tc> 1.23290 + CImg<T>& draw_gaussian(const float xc, const float yc, const float sigma, 1.23291 + const tc *const color, const float opacity=1) { 1.23292 + return draw_gaussian(xc,yc,CImg<floatT>::diagonal(sigma,sigma),color,opacity); 1.23293 + } 1.23294 + 1.23295 + //! Draw an isotropic 2D gaussian function. 1.23296 + template<typename tc> 1.23297 + CImg<T>& draw_gaussian(const float xc, const float yc, const float sigma, 1.23298 + const CImg<tc>& color, const float opacity=1) { 1.23299 + return draw_gaussian(xc,yc,sigma,color.data,opacity); 1.23300 + } 1.23301 + 1.23302 + //! Draw an anisotropic 3D gaussian function. 1.23303 + /** 1.23304 + \param xc = X-coordinate of the gaussian center. 1.23305 + \param yc = Y-coordinate of the gaussian center. 1.23306 + \param zc = Z-coordinate of the gaussian center. 1.23307 + \param tensor = 3x3 covariance matrix. 1.23308 + \param color = array of dimv() values of type \c T, defining the drawing color. 1.23309 + \param opacity = opacity of the drawing. 1.23310 + **/ 1.23311 + template<typename t, typename tc> 1.23312 + CImg<T>& draw_gaussian(const float xc, const float yc, const float zc, const CImg<t>& tensor, 1.23313 + const tc *const color, const float opacity=1) { 1.23314 + if (is_empty()) return *this; 1.23315 + typedef typename cimg::superset<t,float>::type tfloat; 1.23316 + if (tensor.width!=3 || tensor.height!=3 || tensor.depth!=1 || tensor.dim!=1) 1.23317 + throw CImgArgumentException("CImg<%s>::draw_gaussian() : Tensor parameter (%u,%u,%u,%u,%p) is not a 3x3 matrix.", 1.23318 + pixel_type(),tensor.width,tensor.height,tensor.depth,tensor.dim,tensor.data); 1.23319 + const CImg<tfloat> invT = tensor.get_invert(), invT2 = (invT*invT)/(-2.0); 1.23320 + const tfloat a = invT(0,0), b = 2*invT(1,0), c = 2*invT(2,0), d = invT(1,1), e = 2*invT(2,1), f = invT(2,2); 1.23321 + const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0); 1.23322 + const unsigned int whz = width*height*depth; 1.23323 + const tc *col = color; 1.23324 + cimg_forXYZ(*this,x,y,z) { 1.23325 + const float 1.23326 + dx = (x - xc), dy = (y - yc), dz = (z - zc), 1.23327 + val = (float)cimg_std::exp(a*dx*dx + b*dx*dy + c*dx*dz + d*dy*dy + e*dy*dz + f*dz*dz); 1.23328 + T *ptrd = ptr(x,y,z,0); 1.23329 + if (opacity>=1) cimg_forV(*this,k) { *ptrd = (T)(val*(*col++)); ptrd+=whz; } 1.23330 + else cimg_forV(*this,k) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whz; } 1.23331 + col-=dim; 1.23332 + } 1.23333 + return *this; 1.23334 + } 1.23335 + 1.23336 + //! Draw an anisotropic 3D gaussian function. 1.23337 + template<typename t, typename tc> 1.23338 + CImg<T>& draw_gaussian(const float xc, const float yc, const float zc, const CImg<t>& tensor, 1.23339 + const CImg<tc>& color, const float opacity=1) { 1.23340 + return draw_gaussian(xc,yc,zc,tensor,color.data,opacity); 1.23341 + } 1.23342 + 1.23343 + //! Draw an isotropic 3D gaussian function. 1.23344 + /** 1.23345 + \param xc = X-coordinate of the gaussian center. 1.23346 + \param yc = Y-coordinate of the gaussian center. 1.23347 + \param zc = Z-coordinate of the gaussian center. 1.23348 + \param sigma = standard variation of the gaussian distribution. 1.23349 + \param color = array of dimv() values of type \c T, defining the drawing color. 1.23350 + \param opacity = opacity of the drawing. 1.23351 + **/ 1.23352 + template<typename tc> 1.23353 + CImg<T>& draw_gaussian(const float xc, const float yc, const float zc, const float sigma, 1.23354 + const tc *const color, const float opacity=1) { 1.23355 + return draw_gaussian(xc,yc,zc,CImg<floatT>::diagonal(sigma,sigma,sigma),color,opacity); 1.23356 + } 1.23357 + 1.23358 + //! Draw an isotropic 3D gaussian function. 1.23359 + template<typename tc> 1.23360 + CImg<T>& draw_gaussian(const float xc, const float yc, const float zc, const float sigma, 1.23361 + const CImg<tc>& color, const float opacity=1) { 1.23362 + return draw_gaussian(xc,yc,zc,sigma,color.data,opacity); 1.23363 + } 1.23364 + 1.23365 + // Draw a 3D object (internal) 1.23366 + template<typename tc, typename to> 1.23367 + void _draw_object3d_sprite(const int x, const int y, 1.23368 + const CImg<tc>& color, const CImg<to>& opacity, const CImg<T>& sprite) { 1.23369 + if (opacity.width==color.width && opacity.height==color.height) 1.23370 + draw_image(x,y,sprite,opacity.get_resize(sprite.width,sprite.height,1,sprite.dim,1)); 1.23371 + else 1.23372 + draw_image(x,y,sprite,opacity(0)); 1.23373 + } 1.23374 + 1.23375 + template<typename tc> 1.23376 + void _draw_object3d_sprite(const int x, const int y, 1.23377 + const CImg<tc>& color, const float opacity, const CImg<T>& sprite) { 1.23378 + if (color) draw_image(x,y,sprite,opacity); 1.23379 + } 1.23380 + 1.23381 + template<typename tp, typename tf, typename tc, typename to> 1.23382 + CImg<T>& _draw_object3d(void *const pboard, float *const zbuffer, 1.23383 + const float X, const float Y, const float Z, 1.23384 + const tp& points, const unsigned int nb_points, 1.23385 + const CImgList<tf>& primitives, 1.23386 + const CImgList<tc>& colors, 1.23387 + const to& opacities, const unsigned int nb_opacities, 1.23388 + const unsigned int render_type, 1.23389 + const bool double_sided, const float focale, 1.23390 + const float lightx, const float lighty, const float lightz, 1.23391 + const float specular_light, const float specular_shine) { 1.23392 + if (is_empty()) return *this; 1.23393 +#ifndef cimg_use_board 1.23394 + if (pboard) return *this; 1.23395 +#endif 1.23396 + const float 1.23397 + nspec = 1-(specular_light<0?0:(specular_light>1?1:specular_light)), 1.23398 + nspec2 = 1+(specular_shine<0?0:specular_shine), 1.23399 + nsl1 = (nspec2-1)/cimg::sqr(nspec-1), 1.23400 + nsl2 = (1-2*nsl1*nspec), 1.23401 + nsl3 = nspec2-nsl1-nsl2; 1.23402 + 1.23403 + // Create light texture for phong-like rendering 1.23404 + static CImg<floatT> light_texture; 1.23405 + if (render_type==5) { 1.23406 + if (colors.size>primitives.size) light_texture.assign(colors[primitives.size])/=255; 1.23407 + else { 1.23408 + static float olightx = 0, olighty = 0, olightz = 0, ospecular_shine = 0; 1.23409 + if (!light_texture || lightx!=olightx || lighty!=olighty || lightz!=olightz || specular_shine!=ospecular_shine) { 1.23410 + light_texture.assign(512,512); 1.23411 + const float white[] = { 1 }, 1.23412 + dlx = lightx-X, dly = lighty-Y, dlz = lightz-Z, 1.23413 + nl = (float)cimg_std::sqrt(dlx*dlx+dly*dly+dlz*dlz), 1.23414 + nlx = light_texture.width/2*(1+dlx/nl), 1.23415 + nly = light_texture.height/2*(1+dly/nl); 1.23416 + light_texture.draw_gaussian(nlx,nly,light_texture.width/3.0f,white); 1.23417 + cimg_forXY(light_texture,x,y) { 1.23418 + const float factor = light_texture(x,y); 1.23419 + if (factor>nspec) light_texture(x,y) = cimg::min(2,nsl1*factor*factor+nsl2*factor+nsl3); 1.23420 + } 1.23421 + olightx = lightx; olighty = lighty; olightz = lightz; ospecular_shine = specular_shine; 1.23422 + } 1.23423 + } 1.23424 + } 1.23425 + 1.23426 + // Compute 3D to 2D projection 1.23427 + CImg<floatT> projections(nb_points,2); 1.23428 + cimg_forX(projections,l) { 1.23429 + const float 1.23430 + x = (float)points(l,0), 1.23431 + y = (float)points(l,1), 1.23432 + z = (float)points(l,2); 1.23433 + const float projectedz = z + Z + focale; 1.23434 + projections(l,1) = Y + focale*y/projectedz; 1.23435 + projections(l,0) = X + focale*x/projectedz; 1.23436 + } 1.23437 + 1.23438 + // Compute and sort visible primitives 1.23439 + CImg<uintT> visibles(primitives.size); 1.23440 + CImg<floatT> zrange(primitives.size); 1.23441 + unsigned int nb_visibles = 0; 1.23442 + const float zmin = -focale+1.5f; 1.23443 + { cimglist_for(primitives,l) { 1.23444 + const CImg<tf>& primitive = primitives[l]; 1.23445 + switch (primitive.size()) { 1.23446 + 1.23447 + case 1 : { // Point 1.23448 + const unsigned int i0 = (unsigned int)primitive(0); 1.23449 + const float x0 = projections(i0,0), y0 = projections(i0,1), z0 = (float)(Z+points(i0,2)); 1.23450 + if (z0>zmin && x0>=0 && x0<width && y0>=0 && y0<height) { 1.23451 + visibles(nb_visibles) = (unsigned int)l; 1.23452 + zrange(nb_visibles++) = z0; 1.23453 + } 1.23454 + } break; 1.23455 + case 5 : { // Sphere 1.23456 + const unsigned int 1.23457 + i0 = (unsigned int)primitive(0), 1.23458 + i1 = (unsigned int)primitive(1), 1.23459 + i2 = (unsigned int)primitive(2); 1.23460 + const float x0 = projections(i0,0), y0 = projections(i0,1), z0 = (float)(Z+points(i0,2)); 1.23461 + int radius; 1.23462 + if (i2) radius = (int)(i2*focale/(z0+focale)); 1.23463 + else { 1.23464 + const float x1 = projections(i1,0), y1 = projections(i1,1); 1.23465 + const int deltax = (int)(x1-x0), deltay = (int)(y1-y0); 1.23466 + radius = (int)cimg_std::sqrt((float)(deltax*deltax + deltay*deltay)); 1.23467 + } 1.23468 + if (z0>zmin && x0+radius>=0 && x0-radius<width && y0+radius>=0 && y0-radius<height) { 1.23469 + visibles(nb_visibles) = (unsigned int)l; 1.23470 + zrange(nb_visibles++) = z0; 1.23471 + } 1.23472 + } break; 1.23473 + case 2 : // Line 1.23474 + case 6 : { 1.23475 + const unsigned int 1.23476 + i0 = (unsigned int)primitive(0), 1.23477 + i1 = (unsigned int)primitive(1); 1.23478 + const float 1.23479 + x0 = projections(i0,0), y0 = projections(i0,1), z0 = (float)(Z+points(i0,2)), 1.23480 + x1 = projections(i1,0), y1 = projections(i1,1), z1 = (float)(Z+points(i1,2)); 1.23481 + float xm, xM, ym, yM; 1.23482 + if (x0<x1) { xm = x0; xM = x1; } else { xm = x1; xM = x0; } 1.23483 + if (y0<y1) { ym = y0; yM = y1; } else { ym = y1; yM = y0; } 1.23484 + if (z0>zmin && z1>zmin && xM>=0 && xm<width && yM>=0 && ym<height) { 1.23485 + visibles(nb_visibles) = (unsigned int)l; 1.23486 + zrange(nb_visibles++) = 0.5f*(z0+z1); 1.23487 + } 1.23488 + } break; 1.23489 + case 3 : // Triangle 1.23490 + case 9 : { 1.23491 + const unsigned int 1.23492 + i0 = (unsigned int)primitive(0), 1.23493 + i1 = (unsigned int)primitive(1), 1.23494 + i2 = (unsigned int)primitive(2); 1.23495 + const float 1.23496 + x0 = projections(i0,0), y0 = projections(i0,1), z0 = (float)(Z+points(i0,2)), 1.23497 + x1 = projections(i1,0), y1 = projections(i1,1), z1 = (float)(Z+points(i1,2)), 1.23498 + x2 = projections(i2,0), y2 = projections(i2,1), z2 = (float)(Z+points(i2,2)); 1.23499 + float xm, xM, ym, yM; 1.23500 + if (x0<x1) { xm = x0; xM = x1; } else { xm = x1; xM = x0; } 1.23501 + if (x2<xm) xm = x2; 1.23502 + if (x2>xM) xM = x2; 1.23503 + if (y0<y1) { ym = y0; yM = y1; } else { ym = y1; yM = y0; } 1.23504 + if (y2<ym) ym = y2; 1.23505 + if (y2>yM) yM = y2; 1.23506 + if (z0>zmin && z1>zmin && z2>zmin && xM>=0 && xm<width && yM>=0 && ym<height) { 1.23507 + const float d = (x1-x0)*(y2-y0)-(x2-x0)*(y1-y0); 1.23508 + if (double_sided || d<0) { 1.23509 + visibles(nb_visibles) = (unsigned int)l; 1.23510 + zrange(nb_visibles++) = (z0+z1+z2)/3; 1.23511 + } 1.23512 + } 1.23513 + } break; 1.23514 + case 4 : // Rectangle 1.23515 + case 12 : { 1.23516 + const unsigned int 1.23517 + i0 = (unsigned int)primitive(0), 1.23518 + i1 = (unsigned int)primitive(1), 1.23519 + i2 = (unsigned int)primitive(2), 1.23520 + i3 = (unsigned int)primitive(3); 1.23521 + const float 1.23522 + x0 = projections(i0,0), y0 = projections(i0,1), z0 = (float)(Z+points(i0,2)), 1.23523 + x1 = projections(i1,0), y1 = projections(i1,1), z1 = (float)(Z+points(i1,2)), 1.23524 + x2 = projections(i2,0), y2 = projections(i2,1), z2 = (float)(Z+points(i2,2)), 1.23525 + x3 = projections(i3,0), y3 = projections(i3,1), z3 = (float)(Z+points(i3,2)); 1.23526 + float xm, xM, ym, yM; 1.23527 + if (x0<x1) { xm = x0; xM = x1; } else { xm = x1; xM = x0; } 1.23528 + if (x2<xm) xm = x2; 1.23529 + if (x2>xM) xM = x2; 1.23530 + if (x3<xm) xm = x3; 1.23531 + if (x3>xM) xM = x3; 1.23532 + if (y0<y1) { ym = y0; yM = y1; } else { ym = y1; yM = y0; } 1.23533 + if (y2<ym) ym = y2; 1.23534 + if (y2>yM) yM = y2; 1.23535 + if (y3<ym) ym = y3; 1.23536 + if (y3>yM) yM = y3; 1.23537 + if (z0>zmin && z1>zmin && z2>zmin && z3>zmin && xM>=0 && xm<width && yM>=0 && ym<height) { 1.23538 + const float d = (x1 - x0)*(y2 - y0) - (x2 - x0)*(y1 - y0); 1.23539 + if (double_sided || d<0) { 1.23540 + visibles(nb_visibles) = (unsigned int)l; 1.23541 + zrange(nb_visibles++) = (z0 + z1 + z2 + z3)/4; 1.23542 + } 1.23543 + } 1.23544 + } break; 1.23545 + default : 1.23546 + throw CImgArgumentException("CImg<%s>::draw_object3d() : Primitive %u is invalid (size = %u, can be 1,2,3,4,5,6,9 or 12)", 1.23547 + pixel_type(),l,primitive.size()); 1.23548 + }} 1.23549 + } 1.23550 + if (nb_visibles<=0) return *this; 1.23551 + CImg<uintT> permutations; 1.23552 + CImg<floatT>(zrange.data,nb_visibles,1,1,1,true).sort(permutations,false); 1.23553 + 1.23554 + // Compute light properties 1.23555 + CImg<floatT> lightprops; 1.23556 + switch (render_type) { 1.23557 + case 3 : { // Flat Shading 1.23558 + lightprops.assign(nb_visibles); 1.23559 + cimg_forX(lightprops,l) { 1.23560 + const CImg<tf>& primitive = primitives(visibles(permutations(l))); 1.23561 + const unsigned int psize = primitive.size(); 1.23562 + if (psize==3 || psize==4 || psize==9 || psize==12) { 1.23563 + const unsigned int 1.23564 + i0 = (unsigned int)primitive(0), 1.23565 + i1 = (unsigned int)primitive(1), 1.23566 + i2 = (unsigned int)primitive(2); 1.23567 + const float 1.23568 + x0 = (float)points(i0,0), y0 = (float)points(i0,1), z0 = (float)points(i0,2), 1.23569 + x1 = (float)points(i1,0), y1 = (float)points(i1,1), z1 = (float)points(i1,2), 1.23570 + x2 = (float)points(i2,0), y2 = (float)points(i2,1), z2 = (float)points(i2,2), 1.23571 + dx1 = x1 - x0, dy1 = y1 - y0, dz1 = z1 - z0, 1.23572 + dx2 = x2 - x0, dy2 = y2 - y0, dz2 = z2 - z0, 1.23573 + nx = dy1*dz2 - dz1*dy2, 1.23574 + ny = dz1*dx2 - dx1*dz2, 1.23575 + nz = dx1*dy2 - dy1*dx2, 1.23576 + norm = (float)cimg_std::sqrt(1e-5f + nx*nx + ny*ny + nz*nz), 1.23577 + lx = X + (x0 + x1 + x2)/3 - lightx, 1.23578 + ly = Y + (y0 + y1 + y2)/3 - lighty, 1.23579 + lz = Z + (z0 + z1 + z2)/3 - lightz, 1.23580 + nl = (float)cimg_std::sqrt(1e-5f + lx*lx + ly*ly + lz*lz), 1.23581 + factor = cimg::max(cimg::abs(-lx*nx-ly*ny-lz*nz)/(norm*nl),0); 1.23582 + lightprops[l] = factor<=nspec?factor:(nsl1*factor*factor + nsl2*factor + nsl3); 1.23583 + } else lightprops[l] = 1; 1.23584 + } 1.23585 + } break; 1.23586 + 1.23587 + case 4 : // Gouraud Shading 1.23588 + case 5 : { // Phong-Shading 1.23589 + CImg<floatT> points_normals(nb_points,3,1,1,0); 1.23590 + for (unsigned int l=0; l<nb_visibles; ++l) { 1.23591 + const CImg<tf>& primitive = primitives[visibles(l)]; 1.23592 + const unsigned int psize = primitive.size(); 1.23593 + const bool 1.23594 + triangle_flag = (psize==3) || (psize==9), 1.23595 + rectangle_flag = (psize==4) || (psize==12); 1.23596 + if (triangle_flag || rectangle_flag) { 1.23597 + const unsigned int 1.23598 + i0 = (unsigned int)primitive(0), 1.23599 + i1 = (unsigned int)primitive(1), 1.23600 + i2 = (unsigned int)primitive(2), 1.23601 + i3 = rectangle_flag?(unsigned int)primitive(3):0; 1.23602 + const float 1.23603 + x0 = (float)points(i0,0), y0 = (float)points(i0,1), z0 = (float)points(i0,2), 1.23604 + x1 = (float)points(i1,0), y1 = (float)points(i1,1), z1 = (float)points(i1,2), 1.23605 + x2 = (float)points(i2,0), y2 = (float)points(i2,1), z2 = (float)points(i2,2), 1.23606 + dx1 = x1 - x0, dy1 = y1 - y0, dz1 = z1 - z0, 1.23607 + dx2 = x2 - x0, dy2 = y2 - y0, dz2 = z2 - z0, 1.23608 + nnx = dy1*dz2 - dz1*dy2, 1.23609 + nny = dz1*dx2 - dx1*dz2, 1.23610 + nnz = dx1*dy2 - dy1*dx2, 1.23611 + norm = 1e-5f + (float)cimg_std::sqrt(nnx*nnx + nny*nny + nnz*nnz), 1.23612 + nx = nnx/norm, 1.23613 + ny = nny/norm, 1.23614 + nz = nnz/norm; 1.23615 + points_normals(i0,0)+=nx; points_normals(i0,1)+=ny; points_normals(i0,2)+=nz; 1.23616 + points_normals(i1,0)+=nx; points_normals(i1,1)+=ny; points_normals(i1,2)+=nz; 1.23617 + points_normals(i2,0)+=nx; points_normals(i2,1)+=ny; points_normals(i2,2)+=nz; 1.23618 + if (rectangle_flag) { points_normals(i3,0)+=nx; points_normals(i3,1)+=ny; points_normals(i3,2)+=nz; } 1.23619 + } 1.23620 + } 1.23621 + 1.23622 + if (double_sided) cimg_forX(points_normals,p) if (points_normals(p,2)>0) { 1.23623 + points_normals(p,0) = -points_normals(p,0); 1.23624 + points_normals(p,1) = -points_normals(p,1); 1.23625 + points_normals(p,2) = -points_normals(p,2); 1.23626 + } 1.23627 + 1.23628 + if (render_type==4) { 1.23629 + lightprops.assign(nb_points); 1.23630 + cimg_forX(lightprops,ll) { 1.23631 + const float 1.23632 + nx = points_normals(ll,0), 1.23633 + ny = points_normals(ll,1), 1.23634 + nz = points_normals(ll,2), 1.23635 + norm = (float)cimg_std::sqrt(1e-5f + nx*nx + ny*ny + nz*nz), 1.23636 + lx = (float)(X + points(ll,0) - lightx), 1.23637 + ly = (float)(Y + points(ll,1) - lighty), 1.23638 + lz = (float)(Z + points(ll,2) - lightz), 1.23639 + nl = (float)cimg_std::sqrt(1e-5f + lx*lx + ly*ly + lz*lz), 1.23640 + factor = cimg::max((-lx*nx-ly*ny-lz*nz)/(norm*nl),0); 1.23641 + lightprops[ll] = factor<=nspec?factor:(nsl1*factor*factor + nsl2*factor + nsl3); 1.23642 + } 1.23643 + } else { 1.23644 + const unsigned int 1.23645 + lw2 = light_texture.width/2 - 1, 1.23646 + lh2 = light_texture.height/2 - 1; 1.23647 + lightprops.assign(nb_points,2); 1.23648 + cimg_forX(lightprops,ll) { 1.23649 + const float 1.23650 + nx = points_normals(ll,0), 1.23651 + ny = points_normals(ll,1), 1.23652 + nz = points_normals(ll,2), 1.23653 + norm = (float)cimg_std::sqrt(1e-5f + nx*nx + ny*ny + nz*nz), 1.23654 + nnx = nx/norm, 1.23655 + nny = ny/norm; 1.23656 + lightprops(ll,0) = lw2*(1 + nnx); 1.23657 + lightprops(ll,1) = lh2*(1 + nny); 1.23658 + } 1.23659 + } 1.23660 + } break; 1.23661 + } 1.23662 + 1.23663 + // Draw visible primitives 1.23664 + const CImg<tc> default_color(1,dim,1,1,(tc)200); 1.23665 + { for (unsigned int l = 0; l<nb_visibles; ++l) { 1.23666 + const unsigned int n_primitive = visibles(permutations(l)); 1.23667 + const CImg<tf>& primitive = primitives[n_primitive]; 1.23668 + const CImg<tc>& color = n_primitive<colors.size?colors[n_primitive]:default_color; 1.23669 + const float opac = n_primitive<nb_opacities?opacities(n_primitive,0):1.0f; 1.23670 +#ifdef cimg_use_board 1.23671 + BoardLib::Board &board = *(BoardLib::Board*)pboard; 1.23672 +#endif 1.23673 + 1.23674 + switch (primitive.size()) { 1.23675 + case 1 : { // Colored point or sprite 1.23676 + const unsigned int n0 = (unsigned int)primitive[0]; 1.23677 + const int x0 = (int)projections(n0,0), y0 = (int)projections(n0,1); 1.23678 + if (color.size()==dim) { 1.23679 + draw_point(x0,y0,color,opac); 1.23680 +#ifdef cimg_use_board 1.23681 + if (pboard) { 1.23682 + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opac*255)); 1.23683 + board.fillCircle((float)x0,dimy()-(float)y0,0); 1.23684 + } 1.23685 +#endif 1.23686 + } else { 1.23687 + const float z = Z + points(n0,2); 1.23688 + const int 1.23689 + factor = (int)(focale*100/(z+focale)), 1.23690 + sw = color.width*factor/200, 1.23691 + sh = color.height*factor/200; 1.23692 + if (x0+sw>=0 && x0-sw<dimx() && y0+sh>=0 && y0-sh<dimy()) { 1.23693 + const CImg<T> sprite = color.get_resize(-factor,-factor,1,-100,render_type<=3?1:3); 1.23694 + _draw_object3d_sprite(x0-sw,y0-sh,color,opacities[n_primitive%nb_opacities],sprite); 1.23695 +#ifdef cimg_use_board 1.23696 + if (pboard) { 1.23697 + board.setPenColorRGBi(128,128,128); 1.23698 + board.setFillColor(BoardLib::Color::none); 1.23699 + board.drawRectangle((float)x0-sw,dimy()-(float)y0+sh,sw,sh); 1.23700 + } 1.23701 +#endif 1.23702 + } 1.23703 + } 1.23704 + } break; 1.23705 + case 2 : { // Colored line 1.23706 + const unsigned int 1.23707 + n0 = (unsigned int)primitive[0], 1.23708 + n1 = (unsigned int)primitive[1]; 1.23709 + const int 1.23710 + x0 = (int)projections(n0,0), y0 = (int)projections(n0,1), 1.23711 + x1 = (int)projections(n1,0), y1 = (int)projections(n1,1); 1.23712 + const float 1.23713 + z0 = points(n0,2) + Z + focale, 1.23714 + z1 = points(n1,2) + Z + focale; 1.23715 + if (render_type) { 1.23716 + if (zbuffer) draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,opac); 1.23717 + else draw_line(x0,y0,x1,y1,color,opac); 1.23718 +#ifdef cimg_use_board 1.23719 + if (pboard) { 1.23720 + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opac*255)); 1.23721 + board.drawLine((float)x0,dimy()-(float)y0,x1,dimy()-(float)y1); 1.23722 + } 1.23723 +#endif 1.23724 + } else { 1.23725 + draw_point(x0,y0,color,opac).draw_point(x1,y1,color,opac); 1.23726 +#ifdef cimg_use_board 1.23727 + if (pboard) { 1.23728 + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opac*255)); 1.23729 + board.drawCircle((float)x0,dimy()-(float)y0,0); 1.23730 + board.drawCircle((float)x1,dimy()-(float)y1,0); 1.23731 + } 1.23732 +#endif 1.23733 + } 1.23734 + } break; 1.23735 + case 5 : { // Colored sphere 1.23736 + const unsigned int 1.23737 + n0 = (unsigned int)primitive[0], 1.23738 + n1 = (unsigned int)primitive[1], 1.23739 + n2 = (unsigned int)primitive[2]; 1.23740 + const int 1.23741 + x0 = (int)projections(n0,0), y0 = (int)projections(n0,1); 1.23742 + int radius; 1.23743 + if (n2) radius = (int)(n2*focale/(Z+points(n0,2)+focale)); 1.23744 + else { 1.23745 + const int 1.23746 + x1 = (int)projections(n1,0), y1 = (int)projections(n1,1), 1.23747 + deltax = x1-x0, deltay = y1-y0; 1.23748 + radius = (int)cimg_std::sqrt((float)(deltax*deltax + deltay*deltay)); 1.23749 + } 1.23750 + switch (render_type) { 1.23751 + case 0 : 1.23752 + draw_point(x0,y0,color,opac); 1.23753 +#ifdef cimg_use_board 1.23754 + if (pboard) { 1.23755 + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opac*255)); 1.23756 + board.fillCircle((float)x0,dimy()-(float)y0,0); 1.23757 + } 1.23758 +#endif 1.23759 + break; 1.23760 + case 1 : 1.23761 + draw_circle(x0,y0,radius,color,opac,~0U); 1.23762 +#ifdef cimg_use_board 1.23763 + if (pboard) { 1.23764 + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opac*255)); 1.23765 + board.setFillColor(BoardLib::Color::none); 1.23766 + board.drawCircle((float)x0,dimy()-(float)y0,(float)radius); 1.23767 + } 1.23768 +#endif 1.23769 + break; 1.23770 + default : 1.23771 + draw_circle(x0,y0,radius,color,opac); 1.23772 +#ifdef cimg_use_board 1.23773 + if (pboard) { 1.23774 + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opac*255)); 1.23775 + board.fillCircle((float)x0,dimy()-(float)y0,(float)radius); 1.23776 + } 1.23777 +#endif 1.23778 + break; 1.23779 + } 1.23780 + } break; 1.23781 + case 6 : { // Textured line 1.23782 + const unsigned int 1.23783 + n0 = (unsigned int)primitive[0], 1.23784 + n1 = (unsigned int)primitive[1], 1.23785 + tx0 = (unsigned int)primitive[2], 1.23786 + ty0 = (unsigned int)primitive[3], 1.23787 + tx1 = (unsigned int)primitive[4], 1.23788 + ty1 = (unsigned int)primitive[5]; 1.23789 + const int 1.23790 + x0 = (int)projections(n0,0), y0 = (int)projections(n0,1), 1.23791 + x1 = (int)projections(n1,0), y1 = (int)projections(n1,1); 1.23792 + const float 1.23793 + z0 = points(n0,2) + Z + focale, 1.23794 + z1 = points(n1,2) + Z + focale; 1.23795 + if (render_type) { 1.23796 + if (zbuffer) draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opac); 1.23797 + else draw_line(x0,y0,x1,y1,color,tx0,ty0,tx1,ty1,opac); 1.23798 +#ifdef cimg_use_board 1.23799 + if (pboard) { 1.23800 + board.setPenColorRGBi(128,128,128,(unsigned char)(opac*255)); 1.23801 + board.drawLine((float)x0,dimy()-(float)y0,(float)x1,dimy()-(float)y1); 1.23802 + } 1.23803 +#endif 1.23804 + } else { 1.23805 + draw_point(x0,y0,color.get_vector_at(tx0,ty0),opac). 1.23806 + draw_point(x1,y1,color.get_vector_at(tx1,ty1),opac); 1.23807 +#ifdef cimg_use_board 1.23808 + if (pboard) { 1.23809 + board.setPenColorRGBi(128,128,128,(unsigned char)(opac*255)); 1.23810 + board.drawCircle((float)x0,dimy()-(float)y0,0); 1.23811 + board.drawCircle((float)x1,dimy()-(float)y1,0); 1.23812 + } 1.23813 +#endif 1.23814 + } 1.23815 + } break; 1.23816 + case 3 : { // Colored triangle 1.23817 + const unsigned int 1.23818 + n0 = (unsigned int)primitive[0], 1.23819 + n1 = (unsigned int)primitive[1], 1.23820 + n2 = (unsigned int)primitive[2]; 1.23821 + const int 1.23822 + x0 = (int)projections(n0,0), y0 = (int)projections(n0,1), 1.23823 + x1 = (int)projections(n1,0), y1 = (int)projections(n1,1), 1.23824 + x2 = (int)projections(n2,0), y2 = (int)projections(n2,1); 1.23825 + const float 1.23826 + z0 = points(n0,2) + Z + focale, 1.23827 + z1 = points(n1,2) + Z + focale, 1.23828 + z2 = points(n2,2) + Z + focale; 1.23829 + switch (render_type) { 1.23830 + case 0 : 1.23831 + draw_point(x0,y0,color,opac).draw_point(x1,y1,color,opac).draw_point(x2,y2,color,opac); 1.23832 +#ifdef cimg_use_board 1.23833 + if (pboard) { 1.23834 + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opac*255)); 1.23835 + board.drawCircle((float)x0,dimy()-(float)y0,0); 1.23836 + board.drawCircle((float)x1,dimy()-(float)y1,0); 1.23837 + board.drawCircle((float)x2,dimy()-(float)y2,0); 1.23838 + } 1.23839 +#endif 1.23840 + break; 1.23841 + case 1 : 1.23842 + if (zbuffer) 1.23843 + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,opac).draw_line(zbuffer,x0,y0,z0,x2,y2,z2,color,opac). 1.23844 + draw_line(zbuffer,x1,y1,z1,x2,y2,z2,color,opac); 1.23845 + else 1.23846 + draw_line(x0,y0,x1,y1,color,opac).draw_line(x0,y0,x2,y2,color,opac). 1.23847 + draw_line(x1,y1,x2,y2,color,opac); 1.23848 +#ifdef cimg_use_board 1.23849 + if (pboard) { 1.23850 + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opac*255)); 1.23851 + board.drawLine((float)x0,dimy()-(float)y0,(float)x1,dimy()-(float)y1); 1.23852 + board.drawLine((float)x0,dimy()-(float)y0,(float)x2,dimy()-(float)y2); 1.23853 + board.drawLine((float)x1,dimy()-(float)y1,(float)x2,dimy()-(float)y2); 1.23854 + } 1.23855 +#endif 1.23856 + break; 1.23857 + case 2 : 1.23858 + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,opac); 1.23859 + else draw_triangle(x0,y0,x1,y1,x2,y2,color,opac); 1.23860 +#ifdef cimg_use_board 1.23861 + if (pboard) { 1.23862 + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opac*255)); 1.23863 + board.fillTriangle((float)x0,dimy()-(float)y0,(float)x1,dimy()-(float)y1,(float)x2,dimy()-(float)y2); 1.23864 + } 1.23865 +#endif 1.23866 + break; 1.23867 + case 3 : 1.23868 + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color.data,opac,lightprops(l)); 1.23869 + else _draw_triangle(x0,y0,x1,y1,x2,y2,color.data,opac,lightprops(l)); 1.23870 +#ifdef cimg_use_board 1.23871 + if (pboard) { 1.23872 + const float lp = cimg::min(lightprops(l),1); 1.23873 + board.setPenColorRGBi((unsigned char)(color[0]*lp), 1.23874 + (unsigned char)(color[1]*lp), 1.23875 + (unsigned char)(color[2]*lp), 1.23876 + (unsigned char)(opac*255)); 1.23877 + board.fillTriangle((float)x0,dimy()-(float)y0,(float)x1,dimy()-(float)y1,(float)x2,dimy()-(float)y2); 1.23878 + } 1.23879 +#endif 1.23880 + break; 1.23881 + case 4 : 1.23882 + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,lightprops(n0),lightprops(n1),lightprops(n2),opac); 1.23883 + else draw_triangle(x0,y0,x1,y1,x2,y2,color,lightprops(n0),lightprops(n1),lightprops(n2),opac); 1.23884 +#ifdef cimg_use_board 1.23885 + if (pboard) { 1.23886 + board.setPenColorRGBi((unsigned char)(color[0]), 1.23887 + (unsigned char)(color[1]), 1.23888 + (unsigned char)(color[2]), 1.23889 + (unsigned char)(opac*255)); 1.23890 + board.fillGouraudTriangle((float)x0,dimy()-(float)y0,lightprops(n0), 1.23891 + (float)x1,dimy()-(float)y1,lightprops(n1), 1.23892 + (float)x2,dimy()-(float)y2,lightprops(n2)); 1.23893 + } 1.23894 +#endif 1.23895 + break; 1.23896 + case 5 : { 1.23897 + const unsigned int 1.23898 + lx0 = (unsigned int)lightprops(n0,0), ly0 = (unsigned int)lightprops(n0,1), 1.23899 + lx1 = (unsigned int)lightprops(n1,0), ly1 = (unsigned int)lightprops(n1,1), 1.23900 + lx2 = (unsigned int)lightprops(n2,0), ly2 = (unsigned int)lightprops(n2,1); 1.23901 + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opac); 1.23902 + else draw_triangle(x0,y0,x1,y1,x2,y2,color,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opac); 1.23903 +#ifdef cimg_use_board 1.23904 + if (pboard) { 1.23905 + const float 1.23906 + l0 = light_texture((int)(light_texture.dimx()/2*(1+lightprops(n0,0))), (int)(light_texture.dimy()/2*(1+lightprops(n0,1)))), 1.23907 + l1 = light_texture((int)(light_texture.dimx()/2*(1+lightprops(n1,0))), (int)(light_texture.dimy()/2*(1+lightprops(n1,1)))), 1.23908 + l2 = light_texture((int)(light_texture.dimx()/2*(1+lightprops(n2,0))), (int)(light_texture.dimy()/2*(1+lightprops(n2,1)))); 1.23909 + board.setPenColorRGBi((unsigned char)(color[0]), 1.23910 + (unsigned char)(color[1]), 1.23911 + (unsigned char)(color[2]), 1.23912 + (unsigned char)(opac*255)); 1.23913 + board.fillGouraudTriangle((float)x0,dimy()-(float)y0,l0, 1.23914 + (float)x1,dimy()-(float)y1,l1, 1.23915 + (float)x2,dimy()-(float)y2,l2); 1.23916 + } 1.23917 +#endif 1.23918 + } break; 1.23919 + } 1.23920 + } break; 1.23921 + case 4 : { // Colored rectangle 1.23922 + const unsigned int 1.23923 + n0 = (unsigned int)primitive[0], 1.23924 + n1 = (unsigned int)primitive[1], 1.23925 + n2 = (unsigned int)primitive[2], 1.23926 + n3 = (unsigned int)primitive[3]; 1.23927 + const int 1.23928 + x0 = (int)projections(n0,0), y0 = (int)projections(n0,1), 1.23929 + x1 = (int)projections(n1,0), y1 = (int)projections(n1,1), 1.23930 + x2 = (int)projections(n2,0), y2 = (int)projections(n2,1), 1.23931 + x3 = (int)projections(n3,0), y3 = (int)projections(n3,1); 1.23932 + const float 1.23933 + z0 = points(n0,2) + Z + focale, 1.23934 + z1 = points(n1,2) + Z + focale, 1.23935 + z2 = points(n2,2) + Z + focale, 1.23936 + z3 = points(n3,2) + Z + focale; 1.23937 + switch (render_type) { 1.23938 + case 0 : 1.23939 + draw_point(x0,y0,color,opac).draw_point(x1,y1,color,opac). 1.23940 + draw_point(x2,y2,color,opac).draw_point(x3,y3,color,opac); 1.23941 +#ifdef cimg_use_board 1.23942 + if (pboard) { 1.23943 + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opac*255)); 1.23944 + board.drawCircle((float)x0,dimy()-(float)y0,0); 1.23945 + board.drawCircle((float)x1,dimy()-(float)y1,0); 1.23946 + board.drawCircle((float)x2,dimy()-(float)y2,0); 1.23947 + board.drawCircle((float)x3,dimy()-(float)y3,0); 1.23948 + } 1.23949 +#endif 1.23950 + break; 1.23951 + case 1 : 1.23952 + if (zbuffer) 1.23953 + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,opac).draw_line(zbuffer,x1,y1,z1,x2,y2,z2,color,opac). 1.23954 + draw_line(zbuffer,x2,y2,z2,x3,y3,z3,color,opac).draw_line(zbuffer,x3,y3,z3,x0,y0,z0,color,opac); 1.23955 + else 1.23956 + draw_line(x0,y0,x1,y1,color,opac).draw_line(x1,y1,x2,y2,color,opac). 1.23957 + draw_line(x2,y2,x3,y3,color,opac).draw_line(x3,y3,x0,y0,color,opac); 1.23958 +#ifdef cimg_use_board 1.23959 + if (pboard) { 1.23960 + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opac*255)); 1.23961 + board.drawLine((float)x0,dimy()-(float)y0,(float)x1,dimy()-(float)y1); 1.23962 + board.drawLine((float)x1,dimy()-(float)y1,(float)x2,dimy()-(float)y2); 1.23963 + board.drawLine((float)x2,dimy()-(float)y2,(float)x3,dimy()-(float)y3); 1.23964 + board.drawLine((float)x3,dimy()-(float)y3,(float)x0,dimy()-(float)y0); 1.23965 + } 1.23966 +#endif 1.23967 + break; 1.23968 + case 2 : 1.23969 + if (zbuffer) 1.23970 + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,opac).draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,opac); 1.23971 + else 1.23972 + draw_triangle(x0,y0,x1,y1,x2,y2,color,opac).draw_triangle(x0,y0,x2,y2,x3,y3,color,opac); 1.23973 +#ifdef cimg_use_board 1.23974 + if (pboard) { 1.23975 + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opac*255)); 1.23976 + board.fillTriangle((float)x0,dimy()-(float)y0,(float)x1,dimy()-(float)y1,(float)x2,dimy()-(float)y2); 1.23977 + board.fillTriangle((float)x0,dimy()-(float)y0,(float)x2,dimy()-(float)y2,(float)x3,dimy()-(float)y3); 1.23978 + } 1.23979 +#endif 1.23980 + break; 1.23981 + case 3 : 1.23982 + if (zbuffer) 1.23983 + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color.data,opac,lightprops(l)). 1.23984 + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color.data,opac,lightprops(l)); 1.23985 + else 1.23986 + _draw_triangle(x0,y0,x1,y1,x2,y2,color.data,opac,lightprops(l)). 1.23987 + _draw_triangle(x0,y0,x2,y2,x3,y3,color.data,opac,lightprops(l)); 1.23988 +#ifdef cimg_use_board 1.23989 + if (pboard) { 1.23990 + const float lp = cimg::min(lightprops(l),1); 1.23991 + board.setPenColorRGBi((unsigned char)(color[0]*lp), 1.23992 + (unsigned char)(color[1]*lp), 1.23993 + (unsigned char)(color[2]*lp),(unsigned char)(opac*255)); 1.23994 + board.fillTriangle((float)x0,dimy()-(float)y0,(float)x1,dimy()-(float)y1,(float)x2,dimy()-(float)y2); 1.23995 + board.fillTriangle((float)x0,dimy()-(float)y0,(float)x2,dimy()-(float)y2,(float)x3,dimy()-(float)y3); 1.23996 + } 1.23997 +#endif 1.23998 + break; 1.23999 + case 4 : { 1.24000 + const float 1.24001 + lightprop0 = lightprops(n0), lightprop1 = lightprops(n1), 1.24002 + lightprop2 = lightprops(n2), lightprop3 = lightprops(n3); 1.24003 + if (zbuffer) 1.24004 + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,lightprop0,lightprop1,lightprop2,opac). 1.24005 + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,lightprop0,lightprop2,lightprop3,opac); 1.24006 + else 1.24007 + draw_triangle(x0,y0,x1,y1,x2,y2,color,lightprop0,lightprop1,lightprop2,opac). 1.24008 + draw_triangle(x0,y0,x2,y2,x3,y3,color,lightprop0,lightprop2,lightprop3,opac); 1.24009 +#ifdef cimg_use_board 1.24010 + if (pboard) { 1.24011 + board.setPenColorRGBi((unsigned char)(color[0]), 1.24012 + (unsigned char)(color[1]), 1.24013 + (unsigned char)(color[2]), 1.24014 + (unsigned char)(opac*255)); 1.24015 + board.fillGouraudTriangle((float)x0,dimy()-(float)y0,lightprop0, 1.24016 + (float)x1,dimy()-(float)y1,lightprop1, 1.24017 + (float)x2,dimy()-(float)y2,lightprop2); 1.24018 + board.fillGouraudTriangle((float)x0,dimy()-(float)y0,lightprop0, 1.24019 + (float)x2,dimy()-(float)y2,lightprop2, 1.24020 + (float)x3,dimy()-(float)y3,lightprop3); 1.24021 + } 1.24022 +#endif 1.24023 + } break; 1.24024 + case 5 : { 1.24025 + const unsigned int 1.24026 + lx0 = (unsigned int)lightprops(n0,0), ly0 = (unsigned int)lightprops(n0,1), 1.24027 + lx1 = (unsigned int)lightprops(n1,0), ly1 = (unsigned int)lightprops(n1,1), 1.24028 + lx2 = (unsigned int)lightprops(n2,0), ly2 = (unsigned int)lightprops(n2,1), 1.24029 + lx3 = (unsigned int)lightprops(n3,0), ly3 = (unsigned int)lightprops(n3,1); 1.24030 + if (zbuffer) 1.24031 + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opac). 1.24032 + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opac); 1.24033 + else 1.24034 + draw_triangle(x0,y0,x1,y1,x2,y2,color,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opac). 1.24035 + draw_triangle(x0,y0,x2,y2,x3,y3,color,light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opac); 1.24036 +#ifdef cimg_use_board 1.24037 + if (pboard) { 1.24038 + const float 1.24039 + l0 = light_texture((int)(light_texture.dimx()/2*(1+lx0)), (int)(light_texture.dimy()/2*(1+ly0))), 1.24040 + l1 = light_texture((int)(light_texture.dimx()/2*(1+lx1)), (int)(light_texture.dimy()/2*(1+ly1))), 1.24041 + l2 = light_texture((int)(light_texture.dimx()/2*(1+lx2)), (int)(light_texture.dimy()/2*(1+ly2))), 1.24042 + l3 = light_texture((int)(light_texture.dimx()/2*(1+lx3)), (int)(light_texture.dimy()/2*(1+ly3))); 1.24043 + board.setPenColorRGBi((unsigned char)(color[0]), 1.24044 + (unsigned char)(color[1]), 1.24045 + (unsigned char)(color[2]), 1.24046 + (unsigned char)(opac*255)); 1.24047 + board.fillGouraudTriangle((float)x0,dimy()-(float)y0,l0, 1.24048 + (float)x1,dimy()-(float)y1,l1, 1.24049 + (float)x2,dimy()-(float)y2,l2); 1.24050 + board.fillGouraudTriangle((float)x0,dimy()-(float)y0,l0, 1.24051 + (float)x2,dimy()-(float)y2,l2, 1.24052 + (float)x3,dimy()-(float)y3,l3); 1.24053 + } 1.24054 +#endif 1.24055 + } break; 1.24056 + } 1.24057 + } break; 1.24058 + case 9 : { // Textured triangle 1.24059 + const unsigned int 1.24060 + n0 = (unsigned int)primitive[0], 1.24061 + n1 = (unsigned int)primitive[1], 1.24062 + n2 = (unsigned int)primitive[2], 1.24063 + tx0 = (unsigned int)primitive[3], 1.24064 + ty0 = (unsigned int)primitive[4], 1.24065 + tx1 = (unsigned int)primitive[5], 1.24066 + ty1 = (unsigned int)primitive[6], 1.24067 + tx2 = (unsigned int)primitive[7], 1.24068 + ty2 = (unsigned int)primitive[8]; 1.24069 + const int 1.24070 + x0 = (int)projections(n0,0), y0 = (int)projections(n0,1), 1.24071 + x1 = (int)projections(n1,0), y1 = (int)projections(n1,1), 1.24072 + x2 = (int)projections(n2,0), y2 = (int)projections(n2,1); 1.24073 + const float 1.24074 + z0 = points(n0,2) + Z + focale, 1.24075 + z1 = points(n1,2) + Z + focale, 1.24076 + z2 = points(n2,2) + Z + focale; 1.24077 + switch (render_type) { 1.24078 + case 0 : 1.24079 + draw_point(x0,y0,color.get_vector_at(tx0,ty0),opac). 1.24080 + draw_point(x1,y1,color.get_vector_at(tx1,ty1),opac). 1.24081 + draw_point(x2,y2,color.get_vector_at(tx2,ty2),opac); 1.24082 +#ifdef cimg_use_board 1.24083 + if (pboard) { 1.24084 + board.setPenColorRGBi(128,128,128,(unsigned char)(opac*255)); 1.24085 + board.drawCircle((float)x0,dimy()-(float)y0,0); 1.24086 + board.drawCircle((float)x1,dimy()-(float)y1,0); 1.24087 + board.drawCircle((float)x2,dimy()-(float)y2,0); 1.24088 + } 1.24089 +#endif 1.24090 + break; 1.24091 + case 1 : 1.24092 + if (zbuffer) 1.24093 + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opac). 1.24094 + draw_line(zbuffer,x0,y0,z0,x2,y2,z2,color,tx0,ty0,tx2,ty2,opac). 1.24095 + draw_line(zbuffer,x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opac); 1.24096 + else 1.24097 + draw_line(x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opac). 1.24098 + draw_line(x0,y0,z0,x2,y2,z2,color,tx0,ty0,tx2,ty2,opac). 1.24099 + draw_line(x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opac); 1.24100 +#ifdef cimg_use_board 1.24101 + if (pboard) { 1.24102 + board.setPenColorRGBi(128,128,128,(unsigned char)(opac*255)); 1.24103 + board.drawLine((float)x0,dimy()-(float)y0,(float)x1,dimy()-(float)y1); 1.24104 + board.drawLine((float)x0,dimy()-(float)y0,(float)x2,dimy()-(float)y2); 1.24105 + board.drawLine((float)x1,dimy()-(float)y1,(float)x2,dimy()-(float)y2); 1.24106 + } 1.24107 +#endif 1.24108 + break; 1.24109 + case 2 : 1.24110 + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opac); 1.24111 + else draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opac); 1.24112 +#ifdef cimg_use_board 1.24113 + if (pboard) { 1.24114 + board.setPenColorRGBi(128,128,128,(unsigned char)(opac*255)); 1.24115 + board.fillTriangle((float)x0,dimy()-(float)y0,(float)x1,dimy()-(float)y1,(float)x2,dimy()-(float)y2); 1.24116 + } 1.24117 +#endif 1.24118 + break; 1.24119 + case 3 : 1.24120 + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opac,lightprops(l)); 1.24121 + else draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opac,lightprops(l)); 1.24122 +#ifdef cimg_use_board 1.24123 + if (pboard) { 1.24124 + const float lp = cimg::min(lightprops(l),1); 1.24125 + board.setPenColorRGBi((unsigned char)(128*lp), 1.24126 + (unsigned char)(128*lp), 1.24127 + (unsigned char)(128*lp), 1.24128 + (unsigned char)(opac*255)); 1.24129 + board.fillTriangle((float)x0,dimy()-(float)y0,(float)x1,dimy()-(float)y1,(float)x2,dimy()-(float)y2); 1.24130 + } 1.24131 +#endif 1.24132 + break; 1.24133 + case 4 : 1.24134 + if (zbuffer) 1.24135 + 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),opac); 1.24136 + else 1.24137 + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,lightprops(n0),lightprops(n1),lightprops(n2),opac); 1.24138 +#ifdef cimg_use_board 1.24139 + if (pboard) { 1.24140 + board.setPenColorRGBi(128,128,128,(unsigned char)(opac*255)); 1.24141 + board.fillGouraudTriangle((float)x0,dimy()-(float)y0,lightprops(n0), 1.24142 + (float)x1,dimy()-(float)y1,lightprops(n1), 1.24143 + (float)x2,dimy()-(float)y2,lightprops(n2)); 1.24144 + } 1.24145 +#endif 1.24146 + break; 1.24147 + case 5 : 1.24148 + if (zbuffer) 1.24149 + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,light_texture, 1.24150 + (unsigned int)lightprops(n0,0), (unsigned int)lightprops(n0,1), 1.24151 + (unsigned int)lightprops(n1,0), (unsigned int)lightprops(n1,1), 1.24152 + (unsigned int)lightprops(n2,0), (unsigned int)lightprops(n2,1), 1.24153 + opac); 1.24154 + else 1.24155 + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,light_texture, 1.24156 + (unsigned int)lightprops(n0,0), (unsigned int)lightprops(n0,1), 1.24157 + (unsigned int)lightprops(n1,0), (unsigned int)lightprops(n1,1), 1.24158 + (unsigned int)lightprops(n2,0), (unsigned int)lightprops(n2,1), 1.24159 + opac); 1.24160 +#ifdef cimg_use_board 1.24161 + if (pboard) { 1.24162 + const float 1.24163 + l0 = light_texture((int)(light_texture.dimx()/2*(1+lightprops(n0,0))), (int)(light_texture.dimy()/2*(1+lightprops(n0,1)))), 1.24164 + l1 = light_texture((int)(light_texture.dimx()/2*(1+lightprops(n1,0))), (int)(light_texture.dimy()/2*(1+lightprops(n1,1)))), 1.24165 + l2 = light_texture((int)(light_texture.dimx()/2*(1+lightprops(n2,0))), (int)(light_texture.dimy()/2*(1+lightprops(n2,1)))); 1.24166 + board.setPenColorRGBi(128,128,128,(unsigned char)(opac*255)); 1.24167 + board.fillGouraudTriangle((float)x0,dimy()-(float)y0,l0,(float)x1,dimy()-(float)y1,l1,(float)x2,dimy()-(float)y2,l2); 1.24168 + } 1.24169 +#endif 1.24170 + break; 1.24171 + } 1.24172 + } break; 1.24173 + case 12 : { // Textured rectangle 1.24174 + const unsigned int 1.24175 + n0 = (unsigned int)primitive[0], 1.24176 + n1 = (unsigned int)primitive[1], 1.24177 + n2 = (unsigned int)primitive[2], 1.24178 + n3 = (unsigned int)primitive[3], 1.24179 + tx0 = (unsigned int)primitive[4], 1.24180 + ty0 = (unsigned int)primitive[5], 1.24181 + tx1 = (unsigned int)primitive[6], 1.24182 + ty1 = (unsigned int)primitive[7], 1.24183 + tx2 = (unsigned int)primitive[8], 1.24184 + ty2 = (unsigned int)primitive[9], 1.24185 + tx3 = (unsigned int)primitive[10], 1.24186 + ty3 = (unsigned int)primitive[11]; 1.24187 + const int 1.24188 + x0 = (int)projections(n0,0), y0 = (int)projections(n0,1), 1.24189 + x1 = (int)projections(n1,0), y1 = (int)projections(n1,1), 1.24190 + x2 = (int)projections(n2,0), y2 = (int)projections(n2,1), 1.24191 + x3 = (int)projections(n3,0), y3 = (int)projections(n3,1); 1.24192 + const float 1.24193 + z0 = points(n0,2) + Z + focale, 1.24194 + z1 = points(n1,2) + Z + focale, 1.24195 + z2 = points(n2,2) + Z + focale, 1.24196 + z3 = points(n3,2) + Z + focale; 1.24197 + switch (render_type) { 1.24198 + case 0 : 1.24199 + draw_point(x0,y0,color.get_vector_at(tx0,ty0),opac). 1.24200 + draw_point(x1,y1,color.get_vector_at(tx1,ty1),opac). 1.24201 + draw_point(x2,y2,color.get_vector_at(tx2,ty2),opac). 1.24202 + draw_point(x3,y3,color.get_vector_at(tx3,ty3),opac); 1.24203 +#ifdef cimg_use_board 1.24204 + if (pboard) { 1.24205 + board.setPenColorRGBi(128,128,128,(unsigned char)(opac*255)); 1.24206 + board.drawCircle((float)x0,dimy()-(float)y0,0); 1.24207 + board.drawCircle((float)x1,dimy()-(float)y1,0); 1.24208 + board.drawCircle((float)x2,dimy()-(float)y2,0); 1.24209 + board.drawCircle((float)x3,dimy()-(float)y3,0); 1.24210 + } 1.24211 +#endif 1.24212 + break; 1.24213 + case 1 : 1.24214 + if (zbuffer) 1.24215 + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opac). 1.24216 + draw_line(zbuffer,x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opac). 1.24217 + draw_line(zbuffer,x2,y2,z2,x3,y3,z3,color,tx2,ty2,tx3,ty3,opac). 1.24218 + draw_line(zbuffer,x3,y3,z3,x0,y0,z0,color,tx3,ty3,tx0,ty0,opac); 1.24219 + else 1.24220 + draw_line(x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opac). 1.24221 + draw_line(x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opac). 1.24222 + draw_line(x2,y2,z2,x3,y3,z3,color,tx2,ty2,tx3,ty3,opac). 1.24223 + draw_line(x3,y3,z3,x0,y0,z0,color,tx3,ty3,tx0,ty0,opac); 1.24224 +#ifdef cimg_use_board 1.24225 + if (pboard) { 1.24226 + board.setPenColorRGBi(128,128,128,(unsigned char)(opac*255)); 1.24227 + board.drawLine((float)x0,dimy()-(float)y0,(float)x1,dimy()-(float)y1); 1.24228 + board.drawLine((float)x1,dimy()-(float)y1,(float)x2,dimy()-(float)y2); 1.24229 + board.drawLine((float)x2,dimy()-(float)y2,(float)x3,dimy()-(float)y3); 1.24230 + board.drawLine((float)x3,dimy()-(float)y3,(float)x0,dimy()-(float)y0); 1.24231 + } 1.24232 +#endif 1.24233 + break; 1.24234 + case 2 : 1.24235 + if (zbuffer) 1.24236 + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opac). 1.24237 + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opac); 1.24238 + else 1.24239 + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opac). 1.24240 + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opac); 1.24241 +#ifdef cimg_use_board 1.24242 + if (pboard) { 1.24243 + board.setPenColorRGBi(128,128,128,(unsigned char)(opac*255)); 1.24244 + board.fillTriangle((float)x0,dimy()-(float)y0,(float)x1,dimy()-(float)y1,(float)x2,dimy()-(float)y2); 1.24245 + board.fillTriangle((float)x0,dimy()-(float)y0,(float)x2,dimy()-(float)y2,(float)x3,dimy()-(float)y3); 1.24246 + } 1.24247 +#endif 1.24248 + break; 1.24249 + case 3 : 1.24250 + if (zbuffer) 1.24251 + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opac,lightprops(l)). 1.24252 + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opac,lightprops(l)); 1.24253 + else 1.24254 + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opac,lightprops(l)). 1.24255 + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opac,lightprops(l)); 1.24256 +#ifdef cimg_use_board 1.24257 + if (pboard) { 1.24258 + const float lp = cimg::min(lightprops(l),1); 1.24259 + board.setPenColorRGBi((unsigned char)(128*lp), 1.24260 + (unsigned char)(128*lp), 1.24261 + (unsigned char)(128*lp), 1.24262 + (unsigned char)(opac*255)); 1.24263 + board.fillTriangle((float)x0,dimy()-(float)y0,(float)x1,dimy()-(float)y1,(float)x2,dimy()-(float)y2); 1.24264 + board.fillTriangle((float)x0,dimy()-(float)y0,(float)x2,dimy()-(float)y2,(float)x3,dimy()-(float)y3); 1.24265 + } 1.24266 +#endif 1.24267 + break; 1.24268 + case 4 : { 1.24269 + const float 1.24270 + lightprop0 = lightprops(n0), lightprop1 = lightprops(n1), 1.24271 + lightprop2 = lightprops(n2), lightprop3 = lightprops(n3); 1.24272 + if (zbuffer) 1.24273 + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,lightprop0,lightprop1,lightprop2,opac). 1.24274 + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,lightprop0,lightprop2,lightprop3,opac); 1.24275 + else 1.24276 + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,lightprop0,lightprop1,lightprop2,opac). 1.24277 + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,lightprop0,lightprop2,lightprop3,opac); 1.24278 +#ifdef cimg_use_board 1.24279 + if (pboard) { 1.24280 + board.setPenColorRGBi(128,128,128,(unsigned char)(opac*255)); 1.24281 + board.fillGouraudTriangle((float)x0,dimy()-(float)y0,lightprop0, 1.24282 + (float)x1,dimy()-(float)y1,lightprop1, 1.24283 + (float)x2,dimy()-(float)y2,lightprop2); 1.24284 + board.fillGouraudTriangle((float)x0,dimy()-(float)y0,lightprop0, 1.24285 + (float)x2,dimy()-(float)y2,lightprop2, 1.24286 + (float)x3,dimy()-(float)y3,lightprop3); 1.24287 + } 1.24288 +#endif 1.24289 + } break; 1.24290 + case 5 : { 1.24291 + const unsigned int 1.24292 + lx0 = (unsigned int)lightprops(n0,0), ly0 = (unsigned int)lightprops(n0,1), 1.24293 + lx1 = (unsigned int)lightprops(n1,0), ly1 = (unsigned int)lightprops(n1,1), 1.24294 + lx2 = (unsigned int)lightprops(n2,0), ly2 = (unsigned int)lightprops(n2,1), 1.24295 + lx3 = (unsigned int)lightprops(n3,0), ly3 = (unsigned int)lightprops(n3,1); 1.24296 + if (zbuffer) 1.24297 + 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,opac). 1.24298 + 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,opac); 1.24299 + else 1.24300 + 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,opac). 1.24301 + 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,opac); 1.24302 +#ifdef cimg_use_board 1.24303 + if (pboard) { 1.24304 + const float 1.24305 + l0 = light_texture((int)(light_texture.dimx()/2*(1+lx0)), (int)(light_texture.dimy()/2*(1+ly0))), 1.24306 + l1 = light_texture((int)(light_texture.dimx()/2*(1+lx1)), (int)(light_texture.dimy()/2*(1+ly1))), 1.24307 + l2 = light_texture((int)(light_texture.dimx()/2*(1+lx2)), (int)(light_texture.dimy()/2*(1+ly2))), 1.24308 + l3 = light_texture((int)(light_texture.dimx()/2*(1+lx3)), (int)(light_texture.dimy()/2*(1+ly3))); 1.24309 + board.setPenColorRGBi(128,128,128,(unsigned char)(opac*255)); 1.24310 + board.fillGouraudTriangle((float)x0,dimy()-(float)y0,l0, 1.24311 + (float)x1,dimy()-(float)y1,l1, 1.24312 + (float)x2,dimy()-(float)y2,l2); 1.24313 + board.fillGouraudTriangle((float)x0,dimy()-(float)y0,l0, 1.24314 + (float)x2,dimy()-(float)y2,l2, 1.24315 + (float)x3,dimy()-(float)y3,l3); 1.24316 + } 1.24317 +#endif 1.24318 + } break; 1.24319 + } 1.24320 + } break; 1.24321 + } 1.24322 + } 1.24323 + } 1.24324 + return *this; 1.24325 + } 1.24326 + 1.24327 + //! Draw a 3D object. 1.24328 + /** 1.24329 + \param X = X-coordinate of the 3d object position 1.24330 + \param Y = Y-coordinate of the 3d object position 1.24331 + \param Z = Z-coordinate of the 3d object position 1.24332 + \param points = Image N*3 describing 3D point coordinates 1.24333 + \param primitives = List of P primitives 1.24334 + \param colors = List of P color (or textures) 1.24335 + \param opacities = Image of P opacities 1.24336 + \param render_type = Render type (0=Points, 1=Lines, 2=Faces (no light), 3=Faces (flat), 4=Faces(Gouraud) 1.24337 + \param double_sided = Tell if object faces have two sides or are oriented. 1.24338 + \param focale = length of the focale 1.24339 + \param lightx = X-coordinate of the light 1.24340 + \param lighty = Y-coordinate of the light 1.24341 + \param lightz = Z-coordinate of the light 1.24342 + \param specular_shine = Shininess of the object 1.24343 + **/ 1.24344 + template<typename tp, typename tf, typename tc, typename to> 1.24345 + CImg<T>& draw_object3d(const float x0, const float y0, const float z0, 1.24346 + const CImg<tp>& points, const CImgList<tf>& primitives, 1.24347 + const CImgList<tc>& colors, const CImgList<to>& opacities, 1.24348 + const unsigned int render_type=4, 1.24349 + const bool double_sided=false, const float focale=500, 1.24350 + const float lightx=0, const float lighty=0, const float lightz=-5000, 1.24351 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.24352 + float *const zbuffer=0) { 1.24353 + if (!points) return *this; 1.24354 + return _draw_object3d(0,zbuffer,x0,y0,z0,points.height<3?points:points.get_resize(-100,3,1,1,0),points.width, 1.24355 + primitives,colors,opacities,opacities.size, 1.24356 + render_type,double_sided,focale,lightx,lighty,lightz,specular_light,specular_shine); 1.24357 + } 1.24358 + 1.24359 +#ifdef cimg_use_board 1.24360 + template<typename tp, typename tf, typename tc, typename to> 1.24361 + CImg<T>& draw_object3d(BoardLib::Board& board, 1.24362 + const float x0, const float y0, const float z0, 1.24363 + const CImg<tp>& points, const CImgList<tf>& primitives, 1.24364 + const CImgList<tc>& colors, const CImgList<to>& opacities, 1.24365 + const unsigned int render_type=4, 1.24366 + const bool double_sided=false, const float focale=500, 1.24367 + const float lightx=0, const float lighty=0, const float lightz=-5000, 1.24368 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.24369 + float *const zbuffer=0) { 1.24370 + if (!points) return *this; 1.24371 + return _draw_object3d((void*)&board,zbuffer,x0,y0,z0,points.height<3?points:points.get_resize(-100,3,1,1,0),points.width, 1.24372 + primitives,colors,opacities,opacities.size, 1.24373 + render_type,double_sided,focale,lightx,lighty,lightz,specular_light,specular_shine); 1.24374 + } 1.24375 +#endif 1.24376 + 1.24377 + //! Draw a 3D object. 1.24378 + template<typename tp, typename tf, typename tc, typename to> 1.24379 + CImg<T>& draw_object3d(const float x0, const float y0, const float z0, 1.24380 + const CImgList<tp>& points, const CImgList<tf>& primitives, 1.24381 + const CImgList<tc>& colors, const CImgList<to>& opacities, 1.24382 + const unsigned int render_type=4, 1.24383 + const bool double_sided=false, const float focale=500, 1.24384 + const float lightx=0, const float lighty=0, const float lightz=-5000, 1.24385 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.24386 + float *const zbuffer=0) { 1.24387 + if (!points) return *this; 1.24388 + return _draw_object3d(0,zbuffer,x0,y0,z0,points,points.size,primitives,colors,opacities,opacities.size, 1.24389 + render_type,double_sided,focale,lightx,lighty,lightz,specular_light,specular_shine); 1.24390 + } 1.24391 + 1.24392 +#ifdef cimg_use_board 1.24393 + template<typename tp, typename tf, typename tc, typename to> 1.24394 + CImg<T>& draw_object3d(BoardLib::Board& board, 1.24395 + const float x0, const float y0, const float z0, 1.24396 + const CImgList<tp>& points, const CImgList<tf>& primitives, 1.24397 + const CImgList<tc>& colors, const CImgList<to>& opacities, 1.24398 + const unsigned int render_type=4, 1.24399 + const bool double_sided=false, const float focale=500, 1.24400 + const float lightx=0, const float lighty=0, const float lightz=-5000, 1.24401 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.24402 + float *const zbuffer=0) { 1.24403 + if (!points) return *this; 1.24404 + return _draw_object3d((void*)&board,zbuffer,x0,y0,z0,points,points.size,primitives,colors,opacities,opacities.size, 1.24405 + render_type,double_sided,focale,lightx,lighty,lightz,specular_light,specular_shine); 1.24406 + } 1.24407 +#endif 1.24408 + 1.24409 + //! Draw a 3D object. 1.24410 + template<typename tp, typename tf, typename tc, typename to> 1.24411 + CImg<T>& draw_object3d(const float x0, const float y0, const float z0, 1.24412 + const CImg<tp>& points, const CImgList<tf>& primitives, 1.24413 + const CImgList<tc>& colors, const CImg<to>& opacities, 1.24414 + const unsigned int render_type=4, 1.24415 + const bool double_sided=false, const float focale=500, 1.24416 + const float lightx=0, const float lighty=0, const float lightz=-5000, 1.24417 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.24418 + float *const zbuffer=0) { 1.24419 + if (!points) return *this; 1.24420 + return _draw_object3d(0,zbuffer,x0,y0,z0,points.height<3?points:points.get_resize(-100,3,1,1,0),points.width, 1.24421 + primitives,colors,opacities,opacities.size(), 1.24422 + render_type,double_sided,focale,lightx,lighty,lightz,specular_light,specular_shine); 1.24423 + } 1.24424 + 1.24425 +#ifdef cimg_use_board 1.24426 + template<typename tp, typename tf, typename tc, typename to> 1.24427 + CImg<T>& draw_object3d(BoardLib::Board& board, 1.24428 + const float x0, const float y0, const float z0, 1.24429 + const CImg<tp>& points, const CImgList<tf>& primitives, 1.24430 + const CImgList<tc>& colors, const CImg<to>& opacities, 1.24431 + const unsigned int render_type=4, 1.24432 + const bool double_sided=false, const float focale=500, 1.24433 + const float lightx=0, const float lighty=0, const float lightz=-5000, 1.24434 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.24435 + float *const zbuffer=0) { 1.24436 + if (!points) return *this; 1.24437 + return _draw_object3d((void*)&board,zbuffer,x0,y0,z0,points.height<3?points:points.get_resize(-100,3,1,1,0),points.width 1.24438 + ,primitives,colors,opacities,opacities.size(), 1.24439 + render_type,double_sided,focale,lightx,lighty,lightz,specular_light,specular_shine); 1.24440 + } 1.24441 +#endif 1.24442 + 1.24443 + //! Draw a 3D object. 1.24444 + template<typename tp, typename tf, typename tc, typename to> 1.24445 + CImg<T>& draw_object3d(const float x0, const float y0, const float z0, 1.24446 + const CImgList<tp>& points, const CImgList<tf>& primitives, 1.24447 + const CImgList<tc>& colors, const CImg<to>& opacities, 1.24448 + const unsigned int render_type=4, 1.24449 + const bool double_sided=false, const float focale=500, 1.24450 + const float lightx=0, const float lighty=0, const float lightz=-5000, 1.24451 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.24452 + float *const zbuffer=0) { 1.24453 + if (!points) return *this; 1.24454 + return _draw_object3d(0,zbuffer,x0,y0,z0,points,points.size,primitives,colors,opacities,opacities.size(), 1.24455 + render_type,double_sided,focale,lightx,lighty,lightz,specular_light,specular_shine); 1.24456 + } 1.24457 + 1.24458 +#ifdef cimg_use_board 1.24459 + template<typename tp, typename tf, typename tc, typename to> 1.24460 + CImg<T>& draw_object3d(BoardLib::Board& board, 1.24461 + const float x0, const float y0, const float z0, 1.24462 + const CImgList<tp>& points, const CImgList<tf>& primitives, 1.24463 + const CImgList<tc>& colors, const CImg<to>& opacities, 1.24464 + const unsigned int render_type=4, 1.24465 + const bool double_sided=false, const float focale=500, 1.24466 + const float lightx=0, const float lighty=0, const float lightz=-5000, 1.24467 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.24468 + float *const zbuffer=0) { 1.24469 + if (!points) return *this; 1.24470 + return _draw_object3d((void*)&board,zbuffer,x0,y0,z0,points,points.size,primitives,colors,opacities,opacities.size(), 1.24471 + render_type,double_sided,focale,lightx,lighty,lightz,specular_light,specular_shine); 1.24472 + } 1.24473 +#endif 1.24474 + 1.24475 + //! Draw a 3D object. 1.24476 + template<typename tp, typename tf, typename tc> 1.24477 + CImg<T>& draw_object3d(const float x0, const float y0, const float z0, 1.24478 + const tp& points, const CImgList<tf>& primitives, 1.24479 + const CImgList<tc>& colors, 1.24480 + const unsigned int render_type=4, 1.24481 + const bool double_sided=false, const float focale=500, 1.24482 + const float lightx=0, const float lighty=0, const float lightz=-5000, 1.24483 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.24484 + float *const zbuffer=0) { 1.24485 + static const CImg<floatT> opacities; 1.24486 + return draw_object3d(x0,y0,z0,points,primitives,colors,opacities, 1.24487 + render_type,double_sided,focale,lightx,lighty,lightz,specular_light,specular_shine,zbuffer); 1.24488 + } 1.24489 + 1.24490 +#ifdef cimg_use_board 1.24491 + template<typename tp, typename tf, typename tc, typename to> 1.24492 + CImg<T>& draw_object3d(BoardLib::Board& board, 1.24493 + const float x0, const float y0, const float z0, 1.24494 + const tp& points, const CImgList<tf>& primitives, 1.24495 + const CImgList<tc>& colors, 1.24496 + const unsigned int render_type=4, 1.24497 + const bool double_sided=false, const float focale=500, 1.24498 + const float lightx=0, const float lighty=0, const float lightz=-5000, 1.24499 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.24500 + float *const zbuffer=0) { 1.24501 + static const CImg<floatT> opacities; 1.24502 + return draw_object3d(x0,y0,z0,points,primitives,colors,opacities, 1.24503 + render_type,double_sided,focale,lightx,lighty,lightz,specular_light,specular_shine,zbuffer); 1.24504 + } 1.24505 +#endif 1.24506 + 1.24507 + //@} 1.24508 + //---------------------------- 1.24509 + // 1.24510 + //! \name Image Filtering 1.24511 + //@{ 1.24512 + //---------------------------- 1.24513 + 1.24514 + //! Compute the correlation of the instance image by a mask. 1.24515 + /** 1.24516 + The correlation of the instance image \p *this by the mask \p mask is defined to be : 1.24517 + 1.24518 + res(x,y,z) = sum_{i,j,k} (*this)(x+i,y+j,z+k)*mask(i,j,k) 1.24519 + 1.24520 + \param mask = the correlation kernel. 1.24521 + \param cond = the border condition type (0=zero, 1=dirichlet) 1.24522 + \param weighted_correl = enable local normalization. 1.24523 + **/ 1.24524 + template<typename t> 1.24525 + CImg<T>& correlate(const CImg<t>& mask, const unsigned int cond=1, const bool weighted_correl=false) { 1.24526 + return get_correlate(mask,cond,weighted_correl).transfer_to(*this); 1.24527 + } 1.24528 + 1.24529 + template<typename t> 1.24530 + CImg<typename cimg::superset2<T,t,float>::type> get_correlate(const CImg<t>& mask, const unsigned int cond=1, 1.24531 + const bool weighted_correl=false) const { 1.24532 + typedef typename cimg::superset2<T,t,float>::type Ttfloat; 1.24533 + if (is_empty()) return *this; 1.24534 + if (!mask || mask.dim!=1) 1.24535 + throw CImgArgumentException("CImg<%s>::correlate() : Specified mask (%u,%u,%u,%u,%p) is not scalar.", 1.24536 + pixel_type(),mask.width,mask.height,mask.depth,mask.dim,mask.data); 1.24537 + CImg<Ttfloat> dest(width,height,depth,dim); 1.24538 + if (cond && mask.width==mask.height && ((mask.depth==1 && mask.width<=5) || (mask.depth==mask.width && mask.width<=3))) { 1.24539 + // A special optimization is done for 2x2, 3x3, 4x4, 5x5, 2x2x2 and 3x3x3 mask (with cond=1) 1.24540 + switch (mask.depth) { 1.24541 + case 3 : { 1.24542 + T I[27] = { 0 }; 1.24543 + cimg_forZV(*this,z,v) cimg_for3x3x3(*this,x,y,z,v,I) dest(x,y,z,v) = (Ttfloat) 1.24544 + (I[ 0]*mask[ 0] + I[ 1]*mask[ 1] + I[ 2]*mask[ 2] + 1.24545 + I[ 3]*mask[ 3] + I[ 4]*mask[ 4] + I[ 5]*mask[ 5] + 1.24546 + I[ 6]*mask[ 6] + I[ 7]*mask[ 7] + I[ 8]*mask[ 8] + 1.24547 + I[ 9]*mask[ 9] + I[10]*mask[10] + I[11]*mask[11] + 1.24548 + I[12]*mask[12] + I[13]*mask[13] + I[14]*mask[14] + 1.24549 + I[15]*mask[15] + I[16]*mask[16] + I[17]*mask[17] + 1.24550 + I[18]*mask[18] + I[19]*mask[19] + I[20]*mask[20] + 1.24551 + I[21]*mask[21] + I[22]*mask[22] + I[23]*mask[23] + 1.24552 + I[24]*mask[24] + I[25]*mask[25] + I[26]*mask[26]); 1.24553 + if (weighted_correl) cimg_forZV(*this,z,v) cimg_for3x3x3(*this,x,y,z,v,I) { 1.24554 + const double weight = (double)(I[ 0]*I[ 0] + I[ 1]*I[ 1] + I[ 2]*I[ 2] + 1.24555 + I[ 3]*I[ 3] + I[ 4]*I[ 4] + I[ 5]*I[ 5] + 1.24556 + I[ 6]*I[ 6] + I[ 7]*I[ 7] + I[ 8]*I[ 8] + 1.24557 + I[ 9]*I[ 9] + I[10]*I[10] + I[11]*I[11] + 1.24558 + I[12]*I[12] + I[13]*I[13] + I[14]*I[14] + 1.24559 + I[15]*I[15] + I[16]*I[16] + I[17]*I[17] + 1.24560 + I[18]*I[18] + I[19]*I[19] + I[20]*I[20] + 1.24561 + I[21]*I[21] + I[22]*I[22] + I[23]*I[23] + 1.24562 + I[24]*I[24] + I[25]*I[25] + I[26]*I[26]); 1.24563 + if (weight>0) dest(x,y,z,v)/=(Ttfloat)cimg_std::sqrt(weight); 1.24564 + } 1.24565 + } break; 1.24566 + case 2 : { 1.24567 + T I[8] = { 0 }; 1.24568 + cimg_forZV(*this,z,v) cimg_for2x2x2(*this,x,y,z,v,I) dest(x,y,z,v) = (Ttfloat) 1.24569 + (I[0]*mask[0] + I[1]*mask[1] + 1.24570 + I[2]*mask[2] + I[3]*mask[3] + 1.24571 + I[4]*mask[4] + I[5]*mask[5] + 1.24572 + I[6]*mask[6] + I[7]*mask[7]); 1.24573 + if (weighted_correl) cimg_forZV(*this,z,v) cimg_for2x2x2(*this,x,y,z,v,I) { 1.24574 + const double weight = (double)(I[0]*I[0] + I[1]*I[1] + 1.24575 + I[2]*I[2] + I[3]*I[3] + 1.24576 + I[4]*I[4] + I[5]*I[5] + 1.24577 + I[6]*I[6] + I[7]*I[7]); 1.24578 + if (weight>0) dest(x,y,z,v)/=(Ttfloat)cimg_std::sqrt(weight); 1.24579 + } 1.24580 + } break; 1.24581 + default : 1.24582 + case 1 : 1.24583 + switch (mask.width) { 1.24584 + case 6 : { 1.24585 + T I[36] = { 0 }; 1.24586 + cimg_forZV(*this,z,v) cimg_for6x6(*this,x,y,z,v,I) dest(x,y,z,v) = (Ttfloat) 1.24587 + (I[ 0]*mask[ 0] + I[ 1]*mask[ 1] + I[ 2]*mask[ 2] + I[ 3]*mask[ 3] + I[ 4]*mask[ 4] + I[ 5]*mask[ 5] + 1.24588 + I[ 6]*mask[ 6] + I[ 7]*mask[ 7] + I[ 8]*mask[ 8] + I[ 9]*mask[ 9] + I[10]*mask[10] + I[11]*mask[11] + 1.24589 + I[12]*mask[12] + I[13]*mask[13] + I[14]*mask[14] + I[15]*mask[15] + I[16]*mask[16] + I[17]*mask[17] + 1.24590 + I[18]*mask[18] + I[19]*mask[19] + I[20]*mask[20] + I[21]*mask[21] + I[22]*mask[22] + I[23]*mask[23] + 1.24591 + I[24]*mask[24] + I[25]*mask[25] + I[26]*mask[26] + I[27]*mask[27] + I[28]*mask[28] + I[29]*mask[29] + 1.24592 + I[30]*mask[30] + I[31]*mask[31] + I[32]*mask[32] + I[33]*mask[33] + I[34]*mask[34] + I[35]*mask[35]); 1.24593 + if (weighted_correl) cimg_forZV(*this,z,v) cimg_for5x5(*this,x,y,z,v,I) { 1.24594 + const double weight = (double)(I[ 0]*I[ 0] + I[ 1]*I[ 1] + I[ 2]*I[ 2] + I[ 3]*I[ 3] + I[ 4]*I[ 4] + I[ 5]*I[ 5] + 1.24595 + I[ 6]*I[ 6] + I[ 7]*I[ 7] + I[ 8]*I[ 8] + I[ 9]*I[ 9] + I[10]*I[10] + I[11]*I[11] + 1.24596 + I[12]*I[12] + I[13]*I[13] + I[14]*I[14] + I[15]*I[15] + I[16]*I[16] + I[17]*I[17] + 1.24597 + I[18]*I[18] + I[19]*I[19] + I[20]*I[20] + I[21]*I[21] + I[22]*I[22] + I[23]*I[23] + 1.24598 + I[24]*I[24] + I[25]*I[25] + I[26]*I[26] + I[27]*I[27] + I[28]*I[28] + I[29]*I[29] + 1.24599 + I[30]*I[30] + I[31]*I[31] + I[32]*I[32] + I[33]*I[33] + I[34]*I[34] + I[35]*I[35]); 1.24600 + if (weight>0) dest(x,y,z,v)/=(Ttfloat)cimg_std::sqrt(weight); 1.24601 + } 1.24602 + } break; 1.24603 + case 5 : { 1.24604 + T I[25] = { 0 }; 1.24605 + cimg_forZV(*this,z,v) cimg_for5x5(*this,x,y,z,v,I) dest(x,y,z,v) = (Ttfloat) 1.24606 + (I[ 0]*mask[ 0] + I[ 1]*mask[ 1] + I[ 2]*mask[ 2] + I[ 3]*mask[ 3] + I[ 4]*mask[ 4] + 1.24607 + I[ 5]*mask[ 5] + I[ 6]*mask[ 6] + I[ 7]*mask[ 7] + I[ 8]*mask[ 8] + I[ 9]*mask[ 9] + 1.24608 + I[10]*mask[10] + I[11]*mask[11] + I[12]*mask[12] + I[13]*mask[13] + I[14]*mask[14] + 1.24609 + I[15]*mask[15] + I[16]*mask[16] + I[17]*mask[17] + I[18]*mask[18] + I[19]*mask[19] + 1.24610 + I[20]*mask[20] + I[21]*mask[21] + I[22]*mask[22] + I[23]*mask[23] + I[24]*mask[24]); 1.24611 + if (weighted_correl) cimg_forZV(*this,z,v) cimg_for5x5(*this,x,y,z,v,I) { 1.24612 + const double weight = (double)(I[ 0]*I[ 0] + I[ 1]*I[ 1] + I[ 2]*I[ 2] + I[ 3]*I[ 3] + I[ 4]*I[ 4] + 1.24613 + I[ 5]*I[ 5] + I[ 6]*I[ 6] + I[ 7]*I[ 7] + I[ 8]*I[ 8] + I[ 9]*I[ 9] + 1.24614 + I[10]*I[10] + I[11]*I[11] + I[12]*I[12] + I[13]*I[13] + I[14]*I[14] + 1.24615 + I[15]*I[15] + I[16]*I[16] + I[17]*I[17] + I[18]*I[18] + I[19]*I[19] + 1.24616 + I[20]*I[20] + I[21]*I[21] + I[22]*I[22] + I[23]*I[23] + I[24]*I[24]); 1.24617 + if (weight>0) dest(x,y,z,v)/=(Ttfloat)cimg_std::sqrt(weight); 1.24618 + } 1.24619 + } break; 1.24620 + case 4 : { 1.24621 + T I[16] = { 0 }; 1.24622 + cimg_forZV(*this,z,v) cimg_for4x4(*this,x,y,z,v,I) dest(x,y,z,v) = (Ttfloat) 1.24623 + (I[ 0]*mask[ 0] + I[ 1]*mask[ 1] + I[ 2]*mask[ 2] + I[ 3]*mask[ 3] + 1.24624 + I[ 4]*mask[ 4] + I[ 5]*mask[ 5] + I[ 6]*mask[ 6] + I[ 7]*mask[ 7] + 1.24625 + I[ 8]*mask[ 8] + I[ 9]*mask[ 9] + I[10]*mask[10] + I[11]*mask[11] + 1.24626 + I[12]*mask[12] + I[13]*mask[13] + I[14]*mask[14] + I[15]*mask[15]); 1.24627 + if (weighted_correl) cimg_forZV(*this,z,v) cimg_for4x4(*this,x,y,z,v,I) { 1.24628 + const double weight = (double)(I[ 0]*I[ 0] + I[ 1]*I[ 1] + I[ 2]*I[ 2] + I[ 3]*I[ 3] + 1.24629 + I[ 4]*I[ 4] + I[ 5]*I[ 5] + I[ 6]*I[ 6] + I[ 7]*I[ 7] + 1.24630 + I[ 8]*I[ 8] + I[ 9]*I[ 9] + I[10]*I[10] + I[11]*I[11] + 1.24631 + I[12]*I[12] + I[13]*I[13] + I[14]*I[14] + I[15]*I[15]); 1.24632 + if (weight>0) dest(x,y,z,v)/=(Ttfloat)cimg_std::sqrt(weight); 1.24633 + } 1.24634 + } break; 1.24635 + case 3 : { 1.24636 + T I[9] = { 0 }; 1.24637 + cimg_forZV(*this,z,v) cimg_for3x3(*this,x,y,z,v,I) dest(x,y,z,v) = (Ttfloat) 1.24638 + (I[0]*mask[0] + I[1]*mask[1] + I[2]*mask[2] + 1.24639 + I[3]*mask[3] + I[4]*mask[4] + I[5]*mask[5] + 1.24640 + I[6]*mask[6] + I[7]*mask[7] + I[8]*mask[8]); 1.24641 + if (weighted_correl) cimg_forZV(*this,z,v) cimg_for3x3(*this,x,y,z,v,I) { 1.24642 + const double weight = (double)(I[0]*I[0] + I[1]*I[1] + I[2]*I[2] + 1.24643 + I[3]*I[3] + I[4]*I[4] + I[5]*I[5] + 1.24644 + I[6]*I[6] + I[7]*I[7] + I[8]*I[8]); 1.24645 + if (weight>0) dest(x,y,z,v)/=(Ttfloat)cimg_std::sqrt(weight); 1.24646 + } 1.24647 + } break; 1.24648 + case 2 : { 1.24649 + T I[4] = { 0 }; 1.24650 + cimg_forZV(*this,z,v) cimg_for2x2(*this,x,y,z,v,I) dest(x,y,z,v) = (Ttfloat) 1.24651 + (I[0]*mask[0] + I[1]*mask[1] + 1.24652 + I[2]*mask[2] + I[3]*mask[3]); 1.24653 + if (weighted_correl) cimg_forZV(*this,z,v) cimg_for2x2(*this,x,y,z,v,I) { 1.24654 + const double weight = (double)(I[0]*I[0] + I[1]*I[1] + 1.24655 + I[2]*I[2] + I[3]*I[3]); 1.24656 + if (weight>0) dest(x,y,z,v)/=(Ttfloat)cimg_std::sqrt(weight); 1.24657 + } 1.24658 + } break; 1.24659 + case 1 : (dest.assign(*this))*=mask(0); break; 1.24660 + } 1.24661 + } 1.24662 + } else { // Generic version for other masks 1.24663 + const int 1.24664 + mx2 = mask.dimx()/2, my2 = mask.dimy()/2, mz2 = mask.dimz()/2, 1.24665 + mx1 = mx2 - 1 + (mask.dimx()%2), my1 = my2 - 1 + (mask.dimy()%2), mz1 = mz2 - 1 + (mask.dimz()%2), 1.24666 + mxe = dimx() - mx2, mye = dimy() - my2, mze = dimz() - mz2; 1.24667 + cimg_forV(*this,v) 1.24668 + if (!weighted_correl) { // Classical correlation 1.24669 + for (int z = mz1; z<mze; ++z) for (int y = my1; y<mye; ++y) for (int x = mx1; x<mxe; ++x) { 1.24670 + Ttfloat val = 0; 1.24671 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) 1.24672 + val+=(*this)(x+xm,y+ym,z+zm,v)*mask(mx1+xm,my1+ym,mz1+zm); 1.24673 + dest(x,y,z,v) = (Ttfloat)val; 1.24674 + } 1.24675 + if (cond) 1.24676 + cimg_forYZV(*this,y,z,v) 1.24677 + for (int x = 0; x<dimx(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) { 1.24678 + Ttfloat val = 0; 1.24679 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) 1.24680 + val+=_atXYZ(x+xm,y+ym,z+zm,v)*mask(mx1+xm,my1+ym,mz1+zm); 1.24681 + dest(x,y,z,v) = (Ttfloat)val; 1.24682 + } 1.24683 + else 1.24684 + cimg_forYZV(*this,y,z,v) 1.24685 + for (int x = 0; x<dimx(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) { 1.24686 + Ttfloat val = 0; 1.24687 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) 1.24688 + val+=atXYZ(x+xm,y+ym,z+zm,v,0)*mask(mx1+xm,my1+ym,mz1+zm); 1.24689 + dest(x,y,z,v) = (Ttfloat)val; 1.24690 + } 1.24691 + } else { // Weighted correlation 1.24692 + for (int z = mz1; z<mze; ++z) for (int y = my1; y<mye; ++y) for (int x = mx1; x<mxe; ++x) { 1.24693 + Ttfloat val = 0, weight = 0; 1.24694 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) { 1.24695 + const Ttfloat cval = (Ttfloat)(*this)(x+xm,y+ym,z+zm,v); 1.24696 + val+=cval*mask(mx1+xm,my1+ym,mz1+zm); 1.24697 + weight+=cval*cval; 1.24698 + } 1.24699 + dest(x,y,z,v) = (weight>(Ttfloat)0)?(Ttfloat)(val/cimg_std::sqrt((double)weight)):(Ttfloat)0; 1.24700 + } 1.24701 + if (cond) 1.24702 + cimg_forYZV(*this,y,z,v) 1.24703 + for (int x = 0; x<dimx(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) { 1.24704 + Ttfloat val = 0, weight = 0; 1.24705 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) { 1.24706 + const Ttfloat cval = (Ttfloat)_atXYZ(x+xm,y+ym,z+zm,v); 1.24707 + val+=cval*mask(mx1+xm,my1+ym,mz1+zm); 1.24708 + weight+=cval*cval; 1.24709 + } 1.24710 + dest(x,y,z,v) = (weight>(Ttfloat)0)?(Ttfloat)(val/cimg_std::sqrt((double)weight)):(Ttfloat)0; 1.24711 + } 1.24712 + else 1.24713 + cimg_forYZV(*this,y,z,v) 1.24714 + for (int x = 0; x<dimx(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) { 1.24715 + Ttfloat val = 0, weight = 0; 1.24716 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) { 1.24717 + const Ttfloat cval = (Ttfloat)atXYZ(x+xm,y+ym,z+zm,v,0); 1.24718 + val+=cval*mask(mx1+xm,my1+ym,mz1+zm); 1.24719 + weight+=cval*cval; 1.24720 + } 1.24721 + dest(x,y,z,v) = (weight>(Ttfloat)0)?(Ttfloat)(val/cimg_std::sqrt((double)weight)):(Ttfloat)0; 1.24722 + } 1.24723 + } 1.24724 + } 1.24725 + return dest; 1.24726 + } 1.24727 + 1.24728 + //! Compute the convolution of the image by a mask. 1.24729 + /** 1.24730 + The result \p res of the convolution of an image \p img by a mask \p mask is defined to be : 1.24731 + 1.24732 + res(x,y,z) = sum_{i,j,k} img(x-i,y-j,z-k)*mask(i,j,k) 1.24733 + 1.24734 + \param mask = the correlation kernel. 1.24735 + \param cond = the border condition type (0=zero, 1=dirichlet) 1.24736 + \param weighted_convol = enable local normalization. 1.24737 + **/ 1.24738 + template<typename t> 1.24739 + CImg<T>& convolve(const CImg<t>& mask, const unsigned int cond=1, const bool weighted_convol=false) { 1.24740 + return get_convolve(mask,cond,weighted_convol).transfer_to(*this); 1.24741 + } 1.24742 + 1.24743 + template<typename t> 1.24744 + CImg<typename cimg::superset2<T,t,float>::type> get_convolve(const CImg<t>& mask, const unsigned int cond=1, 1.24745 + const bool weighted_convol=false) const { 1.24746 + typedef typename cimg::superset2<T,t,float>::type Ttfloat; 1.24747 + if (is_empty()) return *this; 1.24748 + if (!mask || mask.dim!=1) 1.24749 + throw CImgArgumentException("CImg<%s>::convolve() : Specified mask (%u,%u,%u,%u,%p) is not scalar.", 1.24750 + pixel_type(),mask.width,mask.height,mask.depth,mask.dim,mask.data); 1.24751 + return get_correlate(CImg<t>(mask.ptr(),mask.size(),1,1,1,true).get_mirror('x').resize(mask,-1),cond,weighted_convol); 1.24752 + } 1.24753 + 1.24754 + //! Return the erosion of the image by a structuring element. 1.24755 + template<typename t> 1.24756 + CImg<T>& erode(const CImg<t>& mask, const unsigned int cond=1, const bool weighted_erosion=false) { 1.24757 + return get_erode(mask,cond,weighted_erosion).transfer_to(*this); 1.24758 + } 1.24759 + 1.24760 + template<typename t> 1.24761 + CImg<typename cimg::superset<T,t>::type> get_erode(const CImg<t>& mask, const unsigned int cond=1, 1.24762 + const bool weighted_erosion=false) const { 1.24763 + typedef typename cimg::superset<T,t>::type Tt; 1.24764 + if (is_empty()) return *this; 1.24765 + if (!mask || mask.dim!=1) 1.24766 + throw CImgArgumentException("CImg<%s>::erode() : Specified mask (%u,%u,%u,%u,%p) is not a scalar image.", 1.24767 + pixel_type(),mask.width,mask.height,mask.depth,mask.dim,mask.data); 1.24768 + CImg<Tt> dest(width,height,depth,dim); 1.24769 + const int 1.24770 + mx2 = mask.dimx()/2, my2 = mask.dimy()/2, mz2 = mask.dimz()/2, 1.24771 + mx1 = mx2 - 1 + (mask.dimx()%2), my1 = my2 - 1 + (mask.dimy()%2), mz1 = mz2 - 1 + (mask.dimz()%2), 1.24772 + mxe = dimx() - mx2, mye = dimy() - my2, mze = dimz() - mz2; 1.24773 + cimg_forV(*this,v) 1.24774 + if (!weighted_erosion) { // Classical erosion 1.24775 + for (int z = mz1; z<mze; ++z) for (int y = my1; y<mye; ++y) for (int x = mx1; x<mxe; ++x) { 1.24776 + Tt min_val = cimg::type<Tt>::max(); 1.24777 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) { 1.24778 + const Tt cval = (Tt)(*this)(x+xm,y+ym,z+zm,v); 1.24779 + if (mask(mx1+xm,my1+ym,mz1+zm) && cval<min_val) min_val = cval; 1.24780 + } 1.24781 + dest(x,y,z,v) = min_val; 1.24782 + } 1.24783 + if (cond) 1.24784 + cimg_forYZV(*this,y,z,v) 1.24785 + for (int x = 0; x<dimx(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) { 1.24786 + Tt min_val = cimg::type<Tt>::max(); 1.24787 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) { 1.24788 + const T cval = (Tt)_atXYZ(x+xm,y+ym,z+zm,v); 1.24789 + if (mask(mx1+xm,my1+ym,mz1+zm) && cval<min_val) min_val = cval; 1.24790 + } 1.24791 + dest(x,y,z,v) = min_val; 1.24792 + } 1.24793 + else 1.24794 + cimg_forYZV(*this,y,z,v) 1.24795 + for (int x = 0; x<dimx(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) { 1.24796 + Tt min_val = cimg::type<Tt>::max(); 1.24797 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) { 1.24798 + const T cval = (Tt)atXYZ(x+xm,y+ym,z+zm,v,0); 1.24799 + if (mask(mx1+xm,my1+ym,mz1+zm) && cval<min_val) min_val = cval; 1.24800 + } 1.24801 + dest(x,y,z,v) = min_val; 1.24802 + } 1.24803 + } else { // Weighted erosion 1.24804 + for (int z = mz1; z<mze; ++z) for (int y = my1; y<mye; ++y) for (int x = mx1; x<mxe; ++x) { 1.24805 + Tt min_val = cimg::type<Tt>::max(); 1.24806 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) { 1.24807 + const t mval = mask(mx1+xm,my1+ym,mz1+zm); 1.24808 + const Tt cval = (Tt)((*this)(x+xm,y+ym,z+zm,v) + mval); 1.24809 + if (mval && cval<min_val) min_val = cval; 1.24810 + } 1.24811 + dest(x,y,z,v) = min_val; 1.24812 + } 1.24813 + if (cond) 1.24814 + cimg_forYZV(*this,y,z,v) 1.24815 + for (int x = 0; x<dimx(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) { 1.24816 + Tt min_val = cimg::type<Tt>::max(); 1.24817 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) { 1.24818 + const t mval = mask(mx1+xm,my1+ym,mz1+zm); 1.24819 + const Tt cval = (Tt)(_atXYZ(x+xm,y+ym,z+zm,v) + mval); 1.24820 + if (mval && cval<min_val) min_val = cval; 1.24821 + } 1.24822 + dest(x,y,z,v) = min_val; 1.24823 + } 1.24824 + else 1.24825 + cimg_forYZV(*this,y,z,v) 1.24826 + for (int x = 0; x<dimx(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) { 1.24827 + Tt min_val = cimg::type<Tt>::max(); 1.24828 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) { 1.24829 + const t mval = mask(mx1+xm,my1+ym,mz1+zm); 1.24830 + const Tt cval = (Tt)(atXYZ(x+xm,y+ym,z+zm,v,0) + mval); 1.24831 + if (mval && cval<min_val) min_val = cval; 1.24832 + } 1.24833 + dest(x,y,z,v) = min_val; 1.24834 + } 1.24835 + } 1.24836 + return dest; 1.24837 + } 1.24838 + 1.24839 + //! Erode the image by a square structuring element of size n. 1.24840 + CImg<T>& erode(const unsigned int n, const unsigned int cond=1) { 1.24841 + if (n<2) return *this; 1.24842 + return get_erode(n,cond).transfer_to(*this); 1.24843 + } 1.24844 + 1.24845 + CImg<T> get_erode(const unsigned int n, const unsigned int cond=1) const { 1.24846 + static CImg<T> mask; 1.24847 + if (n<2) return *this; 1.24848 + if (mask.width!=n) mask.assign(n,n,1,1,1); 1.24849 + const CImg<T> res = get_erode(mask,cond,false); 1.24850 + if (n>20) mask.assign(); 1.24851 + return res; 1.24852 + } 1.24853 + 1.24854 + //! Dilate the image by a structuring element. 1.24855 + template<typename t> 1.24856 + CImg<T>& dilate(const CImg<t>& mask, const unsigned int cond=1, const bool weighted_dilatation=false) { 1.24857 + return get_dilate(mask,cond,weighted_dilatation).transfer_to(*this); 1.24858 + } 1.24859 + 1.24860 + template<typename t> 1.24861 + CImg<typename cimg::superset<T,t>::type> get_dilate(const CImg<t>& mask, const unsigned int cond=1, 1.24862 + const bool weighted_dilatation=false) const { 1.24863 + typedef typename cimg::superset<T,t>::type Tt; 1.24864 + if (is_empty()) return *this; 1.24865 + if (!mask || mask.dim!=1) 1.24866 + throw CImgArgumentException("CImg<%s>::dilate() : Specified mask (%u,%u,%u,%u,%p) is not a scalar image.", 1.24867 + pixel_type(),mask.width,mask.height,mask.depth,mask.dim,mask.data); 1.24868 + CImg<Tt> dest(width,height,depth,dim); 1.24869 + const int 1.24870 + mx2 = mask.dimx()/2, my2 = mask.dimy()/2, mz2 = mask.dimz()/2, 1.24871 + mx1 = mx2 - 1 + (mask.dimx()%2), my1 = my2 - 1 + (mask.dimy()%2), mz1 = mz2 - 1 + (mask.dimz()%2), 1.24872 + mxe = dimx() - mx2, mye = dimy() - my2, mze = dimz() - mz2; 1.24873 + cimg_forV(*this,v) 1.24874 + if (!weighted_dilatation) { // Classical dilatation 1.24875 + for (int z = mz1; z<mze; ++z) for (int y = my1; y<mye; ++y) for (int x = mx1; x<mxe; ++x) { 1.24876 + Tt max_val = cimg::type<Tt>::min(); 1.24877 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) { 1.24878 + const Tt cval = (Tt)(*this)(x+xm,y+ym,z+zm,v); 1.24879 + if (mask(mx1+xm,my1+ym,mz1+zm) && cval>max_val) max_val = cval; 1.24880 + } 1.24881 + dest(x,y,z,v) = max_val; 1.24882 + } 1.24883 + if (cond) 1.24884 + cimg_forYZV(*this,y,z,v) 1.24885 + for (int x = 0; x<dimx(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) { 1.24886 + Tt max_val = cimg::type<Tt>::min(); 1.24887 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) { 1.24888 + const T cval = (Tt)_atXYZ(x+xm,y+ym,z+zm,v); 1.24889 + if (mask(mx1+xm,my1+ym,mz1+zm) && cval>max_val) max_val = cval; 1.24890 + } 1.24891 + dest(x,y,z,v) = max_val; 1.24892 + } 1.24893 + else 1.24894 + cimg_forYZV(*this,y,z,v) 1.24895 + for (int x = 0; x<dimx(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) { 1.24896 + Tt max_val = cimg::type<Tt>::min(); 1.24897 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) { 1.24898 + const T cval = (Tt)atXYZ(x+xm,y+ym,z+zm,v,0); 1.24899 + if (mask(mx1+xm,my1+ym,mz1+zm) && cval>max_val) max_val = cval; 1.24900 + } 1.24901 + dest(x,y,z,v) = max_val; 1.24902 + } 1.24903 + } else { // Weighted dilatation 1.24904 + for (int z = mz1; z<mze; ++z) for (int y = my1; y<mye; ++y) for (int x = mx1; x<mxe; ++x) { 1.24905 + Tt max_val = cimg::type<Tt>::min(); 1.24906 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) { 1.24907 + const t mval = mask(mx1+xm,my1+ym,mz1+zm); 1.24908 + const Tt cval = (Tt)((*this)(x+xm,y+ym,z+zm,v) - mval); 1.24909 + if (mval && cval>max_val) max_val = cval; 1.24910 + } 1.24911 + dest(x,y,z,v) = max_val; 1.24912 + } 1.24913 + if (cond) 1.24914 + cimg_forYZV(*this,y,z,v) 1.24915 + for (int x = 0; x<dimx(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) { 1.24916 + Tt max_val = cimg::type<Tt>::min(); 1.24917 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) { 1.24918 + const t mval = mask(mx1+xm,my1+ym,mz1+zm); 1.24919 + const Tt cval = (Tt)(_atXYZ(x+xm,y+ym,z+zm,v) - mval); 1.24920 + if (mval && cval>max_val) max_val = cval; 1.24921 + } 1.24922 + dest(x,y,z,v) = max_val; 1.24923 + } 1.24924 + else 1.24925 + cimg_forYZV(*this,y,z,v) 1.24926 + for (int x = 0; x<dimx(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) { 1.24927 + Tt max_val = cimg::type<Tt>::min(); 1.24928 + for (int zm = -mz1; zm<=mz2; ++zm) for (int ym = -my1; ym<=my2; ++ym) for (int xm = -mx1; xm<=mx2; ++xm) { 1.24929 + const t mval = mask(mx1+xm,my1+ym,mz1+zm); 1.24930 + const Tt cval = (Tt)(atXYZ(x+xm,y+ym,z+zm,v,0) - mval); 1.24931 + if (mval && cval>max_val) max_val = cval; 1.24932 + } 1.24933 + dest(x,y,z,v) = max_val; 1.24934 + } 1.24935 + } 1.24936 + return dest; 1.24937 + } 1.24938 + 1.24939 + //! Dilate the image by a square structuring element of size n. 1.24940 + CImg<T>& dilate(const unsigned int n, const unsigned int cond=1) { 1.24941 + if (n<2) return *this; 1.24942 + return get_dilate(n,cond).transfer_to(*this); 1.24943 + } 1.24944 + 1.24945 + CImg<T> get_dilate(const unsigned int n, const unsigned int cond=1) const { 1.24946 + static CImg<T> mask; 1.24947 + if (n<2) return *this; 1.24948 + if (mask.width!=n) mask.assign(n,n,1,1,1); 1.24949 + const CImg<T> res = get_dilate(mask,cond,false); 1.24950 + if (n>20) mask.assign(); 1.24951 + return res; 1.24952 + } 1.24953 + 1.24954 + //! Add noise to the image. 1.24955 + /** 1.24956 + \param sigma = power of the noise. if sigma<0, it corresponds to the percentage of the maximum image value. 1.24957 + \param ntype = noise type. can be 0=gaussian, 1=uniform or 2=Salt and Pepper, 3=Poisson, 4=Rician. 1.24958 + \return A noisy version of the instance image. 1.24959 + **/ 1.24960 + CImg<T>& noise(const double sigma, const unsigned int noise_type=0) { 1.24961 + if (!is_empty()) { 1.24962 + double nsigma = sigma, max = (double)cimg::type<T>::max(), min = (double)cimg::type<T>::min(); 1.24963 + Tfloat m = 0, M = 0; 1.24964 + if (nsigma==0 && noise_type!=3) return *this; 1.24965 + if (nsigma<0 || noise_type==2) m = (Tfloat)minmax(M); 1.24966 + if (nsigma<0) nsigma = -nsigma*(M-m)/100.0; 1.24967 + switch (noise_type) { 1.24968 + case 0 : { // Gaussian noise 1.24969 + cimg_for(*this,ptr,T) { 1.24970 + double val = *ptr + nsigma*cimg::grand(); 1.24971 + if (val>max) val = max; 1.24972 + if (val<min) val = min; 1.24973 + *ptr = (T)val; 1.24974 + } 1.24975 + } break; 1.24976 + case 1 : { // Uniform noise 1.24977 + cimg_for(*this,ptr,T) { 1.24978 + double val = *ptr + nsigma*cimg::crand(); 1.24979 + if (val>max) val = max; 1.24980 + if (val<min) val = min; 1.24981 + *ptr = (T)val; 1.24982 + } 1.24983 + } break; 1.24984 + case 2 : { // Salt & Pepper noise 1.24985 + if (nsigma<0) nsigma = -nsigma; 1.24986 + if (M==m) { m = 0; M = (float)(cimg::type<T>::is_float()?1:cimg::type<T>::max()); } 1.24987 + cimg_for(*this,ptr,T) if (cimg::rand()*100<nsigma) *ptr = (T)(cimg::rand()<0.5?M:m); 1.24988 + } break; 1.24989 + 1.24990 + case 3 : { // Poisson Noise 1.24991 + cimg_for(*this,ptr,T) *ptr = (T)cimg::prand(*ptr); 1.24992 + } break; 1.24993 + 1.24994 + case 4 : { // Rice noise 1.24995 + const double sqrt2 = (double)cimg_std::sqrt(2.0); 1.24996 + cimg_for(*this,ptr,T) { 1.24997 + const double 1.24998 + val0 = (double)*ptr/sqrt2, 1.24999 + re = val0 + nsigma*cimg::grand(), 1.25000 + im = val0 + nsigma*cimg::grand(); 1.25001 + double val = cimg_std::sqrt(re*re + im*im); 1.25002 + if (val>max) val = max; 1.25003 + if (val<min) val = min; 1.25004 + *ptr = (T)val; 1.25005 + } 1.25006 + } break; 1.25007 + default : 1.25008 + throw CImgArgumentException("CImg<%s>::noise() : Invalid noise type %d " 1.25009 + "(should be {0=Gaussian, 1=Uniform, 2=Salt&Pepper, 3=Poisson}).",pixel_type(),noise_type); 1.25010 + } 1.25011 + } 1.25012 + return *this; 1.25013 + } 1.25014 + 1.25015 + CImg<T> get_noise(const double sigma, const unsigned int noise_type=0) const { 1.25016 + return (+*this).noise(sigma,noise_type); 1.25017 + } 1.25018 + 1.25019 + //! Compute the result of the Deriche filter. 1.25020 + /** 1.25021 + The Canny-Deriche filter is a recursive algorithm allowing to compute blurred derivatives of 1.25022 + order 0,1 or 2 of an image. 1.25023 + **/ 1.25024 + CImg<T>& deriche(const float sigma, const int order=0, const char axis='x', const bool cond=true) { 1.25025 +#define _cimg_deriche2_apply \ 1.25026 + Tfloat *ptrY = Y.data, yb = 0, yp = 0; \ 1.25027 + T xp = (T)0; \ 1.25028 + if (cond) { xp = *ptrX; yb = yp = (Tfloat)(coefp*xp); } \ 1.25029 + for (int m=0; m<N; ++m) { \ 1.25030 + const T xc = *ptrX; ptrX+=off; \ 1.25031 + const Tfloat yc = *(ptrY++) = (Tfloat)(a0*xc + a1*xp - b1*yp - b2*yb); \ 1.25032 + xp = xc; yb = yp; yp = yc; \ 1.25033 + } \ 1.25034 + T xn = (T)0, xa = (T)0; \ 1.25035 + Tfloat yn = 0, ya = 0; \ 1.25036 + if (cond) { xn = xa = *(ptrX-off); yn = ya = (Tfloat)coefn*xn; } \ 1.25037 + for (int n=N-1; n>=0; --n) { \ 1.25038 + const T xc = *(ptrX-=off); \ 1.25039 + const Tfloat yc = (Tfloat)(a2*xn + a3*xa - b1*yn - b2*ya); \ 1.25040 + xa = xn; xn = xc; ya = yn; yn = yc; \ 1.25041 + *ptrX = (T)(*(--ptrY)+yc); \ 1.25042 + } 1.25043 + if (sigma<0) 1.25044 + throw CImgArgumentException("CImg<%s>::deriche() : Given filter variance (sigma = %g) is negative", 1.25045 + pixel_type(),sigma); 1.25046 + if (is_empty() || (sigma<0.1 && !order)) return *this; 1.25047 + const float 1.25048 + nsigma = sigma<0.1f?0.1f:sigma, 1.25049 + alpha = 1.695f/nsigma, 1.25050 + ema = (float)cimg_std::exp(-alpha), 1.25051 + ema2 = (float)cimg_std::exp(-2*alpha), 1.25052 + b1 = -2*ema, 1.25053 + b2 = ema2; 1.25054 + float a0 = 0, a1 = 0, a2 = 0, a3 = 0, coefp = 0, coefn = 0; 1.25055 + switch (order) { 1.25056 + case 0 : { 1.25057 + const float k = (1-ema)*(1-ema)/(1+2*alpha*ema-ema2); 1.25058 + a0 = k; 1.25059 + a1 = k*(alpha-1)*ema; 1.25060 + a2 = k*(alpha+1)*ema; 1.25061 + a3 = -k*ema2; 1.25062 + } break; 1.25063 + case 1 : { 1.25064 + const float k = (1-ema)*(1-ema)/ema; 1.25065 + a0 = k*ema; 1.25066 + a1 = a3 = 0; 1.25067 + a2 = -a0; 1.25068 + } break; 1.25069 + case 2 : { 1.25070 + const float 1.25071 + ea = (float)cimg_std::exp(-alpha), 1.25072 + k = -(ema2-1)/(2*alpha*ema), 1.25073 + kn = (-2*(-1+3*ea-3*ea*ea+ea*ea*ea)/(3*ea+1+3*ea*ea+ea*ea*ea)); 1.25074 + a0 = kn; 1.25075 + a1 = -kn*(1+k*alpha)*ema; 1.25076 + a2 = kn*(1-k*alpha)*ema; 1.25077 + a3 = -kn*ema2; 1.25078 + } break; 1.25079 + default : 1.25080 + throw CImgArgumentException("CImg<%s>::deriche() : Given filter order (order = %u) must be 0,1 or 2", 1.25081 + pixel_type(),order); 1.25082 + } 1.25083 + coefp = (a0+a1)/(1+b1+b2); 1.25084 + coefn = (a2+a3)/(1+b1+b2); 1.25085 + switch (cimg::uncase(axis)) { 1.25086 + case 'x' : { 1.25087 + const int N = width, off = 1; 1.25088 + CImg<Tfloat> Y(N); 1.25089 + cimg_forYZV(*this,y,z,v) { T *ptrX = ptr(0,y,z,v); _cimg_deriche2_apply; } 1.25090 + } break; 1.25091 + case 'y' : { 1.25092 + const int N = height, off = width; 1.25093 + CImg<Tfloat> Y(N); 1.25094 + cimg_forXZV(*this,x,z,v) { T *ptrX = ptr(x,0,z,v); _cimg_deriche2_apply; } 1.25095 + } break; 1.25096 + case 'z' : { 1.25097 + const int N = depth, off = width*height; 1.25098 + CImg<Tfloat> Y(N); 1.25099 + cimg_forXYV(*this,x,y,v) { T *ptrX = ptr(x,y,0,v); _cimg_deriche2_apply; } 1.25100 + } break; 1.25101 + case 'v' : { 1.25102 + const int N = dim, off = width*height*depth; 1.25103 + CImg<Tfloat> Y(N); 1.25104 + cimg_forXYZ(*this,x,y,z) { T *ptrX = ptr(x,y,z,0); _cimg_deriche2_apply; } 1.25105 + } break; 1.25106 + } 1.25107 + return *this; 1.25108 + } 1.25109 + 1.25110 + CImg<Tfloat> get_deriche(const float sigma, const int order=0, const char axis='x', const bool cond=true) const { 1.25111 + return CImg<Tfloat>(*this,false).deriche(sigma,order,axis,cond); 1.25112 + } 1.25113 + 1.25114 + //! Return a blurred version of the image, using a Canny-Deriche filter. 1.25115 + /** 1.25116 + Blur the image with an anisotropic exponential filter (Deriche filter of order 0). 1.25117 + **/ 1.25118 + CImg<T>& blur(const float sigmax, const float sigmay, const float sigmaz, const bool cond=true) { 1.25119 + if (!is_empty()) { 1.25120 + if (width>1 && sigmax>0) deriche(sigmax,0,'x',cond); 1.25121 + if (height>1 && sigmay>0) deriche(sigmay,0,'y',cond); 1.25122 + if (depth>1 && sigmaz>0) deriche(sigmaz,0,'z',cond); 1.25123 + } 1.25124 + return *this; 1.25125 + } 1.25126 + 1.25127 + CImg<Tfloat> get_blur(const float sigmax, const float sigmay, const float sigmaz, 1.25128 + const bool cond=true) const { 1.25129 + return CImg<Tfloat>(*this,false).blur(sigmax,sigmay,sigmaz,cond); 1.25130 + } 1.25131 + 1.25132 + //! Return a blurred version of the image, using a Canny-Deriche filter. 1.25133 + CImg<T>& blur(const float sigma, const bool cond=true) { 1.25134 + return blur(sigma,sigma,sigma,cond); 1.25135 + } 1.25136 + 1.25137 + CImg<Tfloat> get_blur(const float sigma, const bool cond=true) const { 1.25138 + return CImg<Tfloat>(*this,false).blur(sigma,cond); 1.25139 + } 1.25140 + 1.25141 + //! Blur the image anisotropically following a field of diffusion tensors. 1.25142 + /** 1.25143 + \param G = Field of square roots of diffusion tensors used to drive the smoothing. 1.25144 + \param amplitude = amplitude of the smoothing. 1.25145 + \param dl = spatial discretization. 1.25146 + \param da = angular discretization. 1.25147 + \param gauss_prec = precision of the gaussian function. 1.25148 + \param interpolation Used interpolation scheme (0 = nearest-neighbor, 1 = linear, 2 = Runge-Kutta) 1.25149 + \param fast_approx = Tell to use the fast approximation or not. 1.25150 + **/ 1.25151 + template<typename t> 1.25152 + CImg<T>& blur_anisotropic(const CImg<t>& G, const float amplitude=60, const float dl=0.8f, const float da=30, 1.25153 + const float gauss_prec=2, const unsigned int interpolation_type=0, const bool fast_approx=true) { 1.25154 +#define _cimg_valign2d(i,j) \ 1.25155 + { Tfloat &u = W(i,j,0,0), &v = W(i,j,0,1); \ 1.25156 + if (u*curru + v*currv<0) { u=-u; v=-v; }} 1.25157 +#define _cimg_valign3d(i,j,k) \ 1.25158 + { Tfloat &u = W(i,j,k,0), &v = W(i,j,k,1), &w = W(i,j,k,2); \ 1.25159 + if (u*curru + v*currv + w*currw<0) { u=-u; v=-v; w=-w; }} 1.25160 + 1.25161 + // Check arguments and init variables 1.25162 + if (!is_empty() && amplitude>0) { 1.25163 + if (!G || (G.dim!=3 && G.dim!=6) || G.width!=width || G.height!=height || G.depth!=depth) 1.25164 + throw CImgArgumentException("CImg<%s>::blur_anisotropic() : Specified tensor field (%u,%u,%u,%u) is not valid.", 1.25165 + pixel_type(),G.width,G.height,G.depth,G.dim); 1.25166 + 1.25167 + const float sqrt2amplitude = (float)cimg_std::sqrt(2*amplitude); 1.25168 + const bool threed = (G.dim>=6); 1.25169 + const int 1.25170 + dx1 = dimx()-1, 1.25171 + dy1 = dimy()-1, 1.25172 + dz1 = dimz()-1; 1.25173 + CImg<Tfloat> 1.25174 + dest(width,height,depth,dim,0), 1.25175 + W(width,height,depth,threed?4:3), 1.25176 + tmp(dim); 1.25177 + int N = 0; 1.25178 + 1.25179 + if (threed) 1.25180 + // 3D version of the algorithm 1.25181 + for (float phi=(180%(int)da)/2.0f; phi<=180; phi+=da) { 1.25182 + const float 1.25183 + phir = (float)(phi*cimg::valuePI/180), 1.25184 + datmp = (float)(da/cimg_std::cos(phir)), 1.25185 + da2 = datmp<1?360.0f:datmp; 1.25186 + 1.25187 + for (float theta=0; theta<360; (theta+=da2),++N) { 1.25188 + const float 1.25189 + thetar = (float)(theta*cimg::valuePI/180), 1.25190 + vx = (float)(cimg_std::cos(thetar)*cimg_std::cos(phir)), 1.25191 + vy = (float)(cimg_std::sin(thetar)*cimg_std::cos(phir)), 1.25192 + vz = (float)cimg_std::sin(phir); 1.25193 + const t 1.25194 + *pa = G.ptr(0,0,0,0), 1.25195 + *pb = G.ptr(0,0,0,1), 1.25196 + *pc = G.ptr(0,0,0,2), 1.25197 + *pd = G.ptr(0,0,0,3), 1.25198 + *pe = G.ptr(0,0,0,4), 1.25199 + *pf = G.ptr(0,0,0,5); 1.25200 + Tfloat 1.25201 + *pd0 = W.ptr(0,0,0,0), 1.25202 + *pd1 = W.ptr(0,0,0,1), 1.25203 + *pd2 = W.ptr(0,0,0,2), 1.25204 + *pd3 = W.ptr(0,0,0,3); 1.25205 + cimg_forXYZ(G,xg,yg,zg) { 1.25206 + const t 1.25207 + a = *(pa++), b = *(pb++), c = *(pc++), 1.25208 + d = *(pd++), e = *(pe++), f = *(pf++); 1.25209 + const float 1.25210 + u = (float)(a*vx + b*vy + c*vz), 1.25211 + v = (float)(b*vx + d*vy + e*vz), 1.25212 + w = (float)(c*vx + e*vy + f*vz), 1.25213 + n = (float)cimg_std::sqrt(1e-5+u*u+v*v+w*w), 1.25214 + dln = dl/n; 1.25215 + *(pd0++) = (Tfloat)(u*dln); 1.25216 + *(pd1++) = (Tfloat)(v*dln); 1.25217 + *(pd2++) = (Tfloat)(w*dln); 1.25218 + *(pd3++) = (Tfloat)n; 1.25219 + } 1.25220 + 1.25221 + cimg_forXYZ(*this,x,y,z) { 1.25222 + tmp.fill(0); 1.25223 + const float 1.25224 + cu = (float)W(x,y,z,0), 1.25225 + cv = (float)W(x,y,z,1), 1.25226 + cw = (float)W(x,y,z,2), 1.25227 + n = (float)W(x,y,z,3), 1.25228 + fsigma = (float)(n*sqrt2amplitude), 1.25229 + length = gauss_prec*fsigma, 1.25230 + fsigma2 = 2*fsigma*fsigma; 1.25231 + float 1.25232 + S = 0, 1.25233 + pu = cu, 1.25234 + pv = cv, 1.25235 + pw = cw, 1.25236 + X = (float)x, 1.25237 + Y = (float)y, 1.25238 + Z = (float)z; 1.25239 + 1.25240 + switch (interpolation_type) { 1.25241 + case 0 : { 1.25242 + // Nearest neighbor 1.25243 + for (float l=0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) { 1.25244 + const int 1.25245 + cx = (int)(X+0.5f), 1.25246 + cy = (int)(Y+0.5f), 1.25247 + cz = (int)(Z+0.5f); 1.25248 + float 1.25249 + u = (float)W(cx,cy,cz,0), 1.25250 + v = (float)W(cx,cy,cz,1), 1.25251 + w = (float)W(cx,cy,cz,2); 1.25252 + if ((pu*u + pv*v + pw*w)<0) { u=-u; v=-v; w=-w; } 1.25253 + if (fast_approx) { cimg_forV(*this,k) tmp[k]+=(Tfloat)(*this)(cx,cy,cz,k); ++S; } 1.25254 + else { 1.25255 + const float coef = (float)cimg_std::exp(-l*l/fsigma2); 1.25256 + cimg_forV(*this,k) tmp[k]+=(Tfloat)(coef*(*this)(cx,cy,cz,k)); 1.25257 + S+=coef; 1.25258 + } 1.25259 + X+=(pu=u); Y+=(pv=v); Z+=(pw=w); 1.25260 + } 1.25261 + } break; 1.25262 + 1.25263 + case 1 : { 1.25264 + // Linear interpolation 1.25265 + for (float l=0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) { 1.25266 + const int 1.25267 + cx = (int)X, px = (cx-1<0)?0:cx-1, nx = (cx+1>dx1)?dx1:cx+1, 1.25268 + cy = (int)Y, py = (cy-1<0)?0:cy-1, ny = (cy+1>dy1)?dy1:cy+1, 1.25269 + cz = (int)Z, pz = (cz-1<0)?0:cz-1, nz = (cz+1>dz1)?dz1:cz+1; 1.25270 + const float 1.25271 + curru = (float)W(cx,cy,cz,0), 1.25272 + currv = (float)W(cx,cy,cz,1), 1.25273 + currw = (float)W(cx,cy,cz,2); 1.25274 + _cimg_valign3d(px,py,pz); _cimg_valign3d(cx,py,pz); _cimg_valign3d(nx,py,pz); 1.25275 + _cimg_valign3d(px,cy,pz); _cimg_valign3d(cx,cy,pz); _cimg_valign3d(nx,cy,pz); 1.25276 + _cimg_valign3d(px,ny,pz); _cimg_valign3d(cx,ny,pz); _cimg_valign3d(nx,ny,pz); 1.25277 + _cimg_valign3d(px,py,cz); _cimg_valign3d(cx,py,cz); _cimg_valign3d(nx,py,cz); 1.25278 + _cimg_valign3d(px,cy,cz); _cimg_valign3d(nx,cy,cz); 1.25279 + _cimg_valign3d(px,ny,cz); _cimg_valign3d(cx,ny,cz); _cimg_valign3d(nx,ny,cz); 1.25280 + _cimg_valign3d(px,py,nz); _cimg_valign3d(cx,py,nz); _cimg_valign3d(nx,py,nz); 1.25281 + _cimg_valign3d(px,cy,nz); _cimg_valign3d(cx,cy,nz); _cimg_valign3d(nx,cy,nz); 1.25282 + _cimg_valign3d(px,ny,nz); _cimg_valign3d(cx,ny,nz); _cimg_valign3d(nx,ny,nz); 1.25283 + float 1.25284 + u = (float)(W._linear_atXYZ(X,Y,Z,0)), 1.25285 + v = (float)(W._linear_atXYZ(X,Y,Z,1)), 1.25286 + w = (float)(W._linear_atXYZ(X,Y,Z,2)); 1.25287 + if ((pu*u + pv*v + pw*w)<0) { u=-u; v=-v; w=-w; } 1.25288 + if (fast_approx) { cimg_forV(*this,k) tmp[k]+=(Tfloat)_linear_atXYZ(X,Y,Z,k); ++S; } 1.25289 + else { 1.25290 + const float coef = (float)cimg_std::exp(-l*l/fsigma2); 1.25291 + cimg_forV(*this,k) tmp[k]+=(Tfloat)(coef*_linear_atXYZ(X,Y,Z,k)); 1.25292 + S+=coef; 1.25293 + } 1.25294 + X+=(pu=u); Y+=(pv=v); Z+=(pw=w); 1.25295 + } 1.25296 + } break; 1.25297 + 1.25298 + default : { 1.25299 + // 2nd order Runge Kutta 1.25300 + for (float l=0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) { 1.25301 + const int 1.25302 + cx = (int)X, px = (cx-1<0)?0:cx-1, nx = (cx+1>dx1)?dx1:cx+1, 1.25303 + cy = (int)Y, py = (cy-1<0)?0:cy-1, ny = (cy+1>dy1)?dy1:cy+1, 1.25304 + cz = (int)Z, pz = (cz-1<0)?0:cz-1, nz = (cz+1>dz1)?dz1:cz+1; 1.25305 + const float 1.25306 + curru = (float)W(cx,cy,cz,0), 1.25307 + currv = (float)W(cx,cy,cz,1), 1.25308 + currw = (float)W(cx,cy,cz,2); 1.25309 + _cimg_valign3d(px,py,pz); _cimg_valign3d(cx,py,pz); _cimg_valign3d(nx,py,pz); 1.25310 + _cimg_valign3d(px,cy,pz); _cimg_valign3d(cx,cy,pz); _cimg_valign3d(nx,cy,pz); 1.25311 + _cimg_valign3d(px,ny,pz); _cimg_valign3d(cx,ny,pz); _cimg_valign3d(nx,ny,pz); 1.25312 + _cimg_valign3d(px,py,cz); _cimg_valign3d(cx,py,cz); _cimg_valign3d(nx,py,cz); 1.25313 + _cimg_valign3d(px,cy,cz); _cimg_valign3d(nx,cy,cz); 1.25314 + _cimg_valign3d(px,ny,cz); _cimg_valign3d(cx,ny,cz); _cimg_valign3d(nx,ny,cz); 1.25315 + _cimg_valign3d(px,py,nz); _cimg_valign3d(cx,py,nz); _cimg_valign3d(nx,py,nz); 1.25316 + _cimg_valign3d(px,cy,nz); _cimg_valign3d(cx,cy,nz); _cimg_valign3d(nx,cy,nz); 1.25317 + _cimg_valign3d(px,ny,nz); _cimg_valign3d(cx,ny,nz); _cimg_valign3d(nx,ny,nz); 1.25318 + const float 1.25319 + u0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,0)), 1.25320 + v0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,1)), 1.25321 + w0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,2)); 1.25322 + float 1.25323 + u = (float)(W._linear_atXYZ(X+u0,Y+v0,Z+w0,0)), 1.25324 + v = (float)(W._linear_atXYZ(X+u0,Y+v0,Z+w0,1)), 1.25325 + w = (float)(W._linear_atXYZ(X+u0,Y+v0,Z+w0,2)); 1.25326 + if ((pu*u + pv*v + pw*w)<0) { u=-u; v=-v; w=-w; } 1.25327 + if (fast_approx) { cimg_forV(*this,k) tmp[k]+=(Tfloat)_linear_atXYZ(X,Y,Z,k); ++S; } 1.25328 + else { 1.25329 + const float coef = (float)cimg_std::exp(-l*l/fsigma2); 1.25330 + cimg_forV(*this,k) tmp[k]+=(Tfloat)(coef*_linear_atXYZ(X,Y,Z,k)); 1.25331 + S+=coef; 1.25332 + } 1.25333 + X+=(pu=u); Y+=(pv=v); Z+=(pw=w); 1.25334 + } 1.25335 + } break; 1.25336 + } 1.25337 + if (S>0) cimg_forV(dest,k) dest(x,y,z,k)+=tmp[k]/S; 1.25338 + else cimg_forV(dest,k) dest(x,y,z,k)+=(Tfloat)((*this)(x,y,z,k)); 1.25339 + cimg_plugin_greycstoration_count; 1.25340 + } 1.25341 + } 1.25342 + } else 1.25343 + // 2D version of the algorithm 1.25344 + for (float theta=(360%(int)da)/2.0f; theta<360; (theta+=da),++N) { 1.25345 + const float 1.25346 + thetar = (float)(theta*cimg::valuePI/180), 1.25347 + vx = (float)(cimg_std::cos(thetar)), 1.25348 + vy = (float)(cimg_std::sin(thetar)); 1.25349 + const t 1.25350 + *pa = G.ptr(0,0,0,0), 1.25351 + *pb = G.ptr(0,0,0,1), 1.25352 + *pc = G.ptr(0,0,0,2); 1.25353 + Tfloat 1.25354 + *pd0 = W.ptr(0,0,0,0), 1.25355 + *pd1 = W.ptr(0,0,0,1), 1.25356 + *pd2 = W.ptr(0,0,0,2); 1.25357 + cimg_forXY(G,xg,yg) { 1.25358 + const t a = *(pa++), b = *(pb++), c = *(pc++); 1.25359 + const float 1.25360 + u = (float)(a*vx + b*vy), 1.25361 + v = (float)(b*vx + c*vy), 1.25362 + n = (float)cimg_std::sqrt(1e-5+u*u+v*v), 1.25363 + dln = dl/n; 1.25364 + *(pd0++) = (Tfloat)(u*dln); 1.25365 + *(pd1++) = (Tfloat)(v*dln); 1.25366 + *(pd2++) = (Tfloat)n; 1.25367 + } 1.25368 + 1.25369 + cimg_forXY(*this,x,y) { 1.25370 + tmp.fill(0); 1.25371 + const float 1.25372 + cu = (float)W(x,y,0,0), 1.25373 + cv = (float)W(x,y,0,1), 1.25374 + n = (float)W(x,y,0,2), 1.25375 + fsigma = (float)(n*sqrt2amplitude), 1.25376 + length = gauss_prec*fsigma, 1.25377 + fsigma2 = 2*fsigma*fsigma; 1.25378 + float 1.25379 + S = 0, 1.25380 + pu = cu, 1.25381 + pv = cv, 1.25382 + X = (float)x, 1.25383 + Y = (float)y; 1.25384 + 1.25385 + switch (interpolation_type) { 1.25386 + 1.25387 + case 0 : { 1.25388 + // Nearest-neighbor interpolation for 2D images 1.25389 + for (float l=0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) { 1.25390 + const int 1.25391 + cx = (int)(X+0.5f), 1.25392 + cy = (int)(Y+0.5f); 1.25393 + float 1.25394 + u = (float)W(cx,cy,0,0), 1.25395 + v = (float)W(cx,cy,0,1); 1.25396 + if ((pu*u + pv*v)<0) { u=-u; v=-v; } 1.25397 + if (fast_approx) { cimg_forV(*this,k) tmp[k]+=(Tfloat)(*this)(cx,cy,0,k); ++S; } 1.25398 + else { 1.25399 + const float coef = (float)cimg_std::exp(-l*l/fsigma2); 1.25400 + cimg_forV(*this,k) tmp[k]+=(Tfloat)(coef*(*this)(cx,cy,0,k)); 1.25401 + S+=coef; 1.25402 + } 1.25403 + X+=(pu=u); Y+=(pv=v); 1.25404 + } 1.25405 + } break; 1.25406 + 1.25407 + case 1 : { 1.25408 + // Linear interpolation for 2D images 1.25409 + for (float l=0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) { 1.25410 + const int 1.25411 + cx = (int)X, px = (cx-1<0)?0:cx-1, nx = (cx+1>dx1)?dx1:cx+1, 1.25412 + cy = (int)Y, py = (cy-1<0)?0:cy-1, ny = (cy+1>dy1)?dy1:cy+1; 1.25413 + const float 1.25414 + curru = (float)W(cx,cy,0,0), 1.25415 + currv = (float)W(cx,cy,0,1); 1.25416 + _cimg_valign2d(px,py); _cimg_valign2d(cx,py); _cimg_valign2d(nx,py); 1.25417 + _cimg_valign2d(px,cy); _cimg_valign2d(nx,cy); 1.25418 + _cimg_valign2d(px,ny); _cimg_valign2d(cx,ny); _cimg_valign2d(nx,ny); 1.25419 + float 1.25420 + u = (float)(W._linear_atXY(X,Y,0,0)), 1.25421 + v = (float)(W._linear_atXY(X,Y,0,1)); 1.25422 + if ((pu*u + pv*v)<0) { u=-u; v=-v; } 1.25423 + if (fast_approx) { cimg_forV(*this,k) tmp[k]+=(Tfloat)_linear_atXY(X,Y,0,k); ++S; } 1.25424 + else { 1.25425 + const float coef = (float)cimg_std::exp(-l*l/fsigma2); 1.25426 + cimg_forV(*this,k) tmp[k]+=(Tfloat)(coef*_linear_atXY(X,Y,0,k)); 1.25427 + S+=coef; 1.25428 + } 1.25429 + X+=(pu=u); Y+=(pv=v); 1.25430 + } 1.25431 + } break; 1.25432 + 1.25433 + default : { 1.25434 + // 2nd-order Runge-kutta interpolation for 2D images 1.25435 + for (float l=0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) { 1.25436 + const int 1.25437 + cx = (int)X, px = (cx-1<0)?0:cx-1, nx = (cx+1>dx1)?dx1:cx+1, 1.25438 + cy = (int)Y, py = (cy-1<0)?0:cy-1, ny = (cy+1>dy1)?dy1:cy+1; 1.25439 + const float 1.25440 + curru = (float)W(cx,cy,0,0), 1.25441 + currv = (float)W(cx,cy,0,1); 1.25442 + _cimg_valign2d(px,py); _cimg_valign2d(cx,py); _cimg_valign2d(nx,py); 1.25443 + _cimg_valign2d(px,cy); _cimg_valign2d(nx,cy); 1.25444 + _cimg_valign2d(px,ny); _cimg_valign2d(cx,ny); _cimg_valign2d(nx,ny); 1.25445 + const float 1.25446 + u0 = (float)(0.5f*W._linear_atXY(X,Y,0,0)), 1.25447 + v0 = (float)(0.5f*W._linear_atXY(X,Y,0,1)); 1.25448 + float 1.25449 + u = (float)(W._linear_atXY(X+u0,Y+v0,0,0)), 1.25450 + v = (float)(W._linear_atXY(X+u0,Y+v0,0,1)); 1.25451 + if ((pu*u + pv*v)<0) { u=-u; v=-v; } 1.25452 + if (fast_approx) { cimg_forV(*this,k) tmp[k]+=(Tfloat)_linear_atXY(X,Y,0,k); ++S; } 1.25453 + else { 1.25454 + const float coef = (float)cimg_std::exp(-l*l/fsigma2); 1.25455 + cimg_forV(*this,k) tmp[k]+=(Tfloat)(coef*_linear_atXY(X,Y,0,k)); 1.25456 + S+=coef; 1.25457 + } 1.25458 + X+=(pu=u); Y+=(pv=v); 1.25459 + } 1.25460 + } 1.25461 + } 1.25462 + if (S>0) cimg_forV(dest,k) dest(x,y,0,k)+=tmp[k]/S; 1.25463 + else cimg_forV(dest,k) dest(x,y,0,k)+=(Tfloat)((*this)(x,y,0,k)); 1.25464 + cimg_plugin_greycstoration_count; 1.25465 + } 1.25466 + } 1.25467 + const Tfloat *ptrs = dest.data+dest.size(); 1.25468 + const T m = cimg::type<T>::min(), M = cimg::type<T>::max(); 1.25469 + cimg_for(*this,ptrd,T) { const Tfloat val = *(--ptrs)/N; *ptrd = val<m?m:(val>M?M:(T)val); } 1.25470 + } 1.25471 + return *this; 1.25472 + } 1.25473 + 1.25474 + template<typename t> 1.25475 + CImg<T> get_blur_anisotropic(const CImg<t>& G, const float amplitude=60, const float dl=0.8f, const float da=30, 1.25476 + const float gauss_prec=2, const unsigned int interpolation_type=0, const bool fast_approx=true) const { 1.25477 + return (+*this).blur_anisotropic(G,amplitude,dl,da,gauss_prec,interpolation_type,fast_approx); 1.25478 + } 1.25479 + 1.25480 + //! Blur an image in an anisotropic way. 1.25481 + /** 1.25482 + \param mask Binary mask. 1.25483 + \param amplitude Amplitude of the anisotropic blur. 1.25484 + \param sharpness Contour preservation. 1.25485 + \param anisotropy Smoothing anisotropy. 1.25486 + \param alpha Image pre-blurring (gaussian). 1.25487 + \param sigma Regularity of the tensor-valued geometry. 1.25488 + \param dl Spatial discretization. 1.25489 + \param da Angular discretization. 1.25490 + \param gauss_prec Precision of the gaussian function. 1.25491 + \param interpolation_type Used interpolation scheme (0 = nearest-neighbor, 1 = linear, 2 = Runge-Kutta) 1.25492 + \param fast_approx Tell to use the fast approximation or not 1.25493 + \param geom_factor Geometry factor. 1.25494 + **/ 1.25495 + template<typename tm> 1.25496 + CImg<T>& blur_anisotropic(const CImg<tm>& mask, const float amplitude, const float sharpness=0.7f, const float anisotropy=0.3f, 1.25497 + const float alpha=0.6f, const float sigma=1.1f, const float dl=0.8f, const float da=30, 1.25498 + const float gauss_prec=2, const unsigned int interpolation_type=0, const bool fast_approx=true, 1.25499 + const float geom_factor=1) { 1.25500 + if (!is_empty() && amplitude>0) { 1.25501 + if (amplitude==0) return *this; 1.25502 + if (amplitude<0 || sharpness<0 || anisotropy<0 || anisotropy>1 || alpha<0 || sigma<0 || dl<0 || da<0 || gauss_prec<0) 1.25503 + throw CImgArgumentException("CImg<%s>::blur_anisotropic() : Given parameters are amplitude(%g), sharpness(%g), " 1.25504 + "anisotropy(%g), alpha(%g), sigma(%g), dl(%g), da(%g), gauss_prec(%g).\n" 1.25505 + "Admissible parameters are in the range : amplitude>0, sharpness>0, anisotropy in [0,1], " 1.25506 + "alpha>0, sigma>0, dl>0, da>0, gauss_prec>0.", 1.25507 + pixel_type(),amplitude,sharpness,anisotropy,alpha,sigma,dl,da,gauss_prec); 1.25508 + const bool threed = (depth>1), no_mask = mask.is_empty(); 1.25509 + const float nsharpness = cimg::max(sharpness,1e-5f), power1 = 0.5f*nsharpness, power2 = power1/(1e-7f+1-anisotropy); 1.25510 + CImg<floatT> blurred = CImg<floatT>(*this,false).blur(alpha); 1.25511 + if (geom_factor>0) blurred*=geom_factor; 1.25512 + else blurred.normalize(0,-geom_factor); 1.25513 + 1.25514 + if (threed) { // Field for 3D volumes 1.25515 + cimg_plugin_greycstoration_lock; 1.25516 + CImg<floatT> val(3), vec(3,3), G(blurred.get_structure_tensor()); 1.25517 + if (sigma>0) G.blur(sigma); 1.25518 + cimg_forXYZ(*this,x,y,z) { 1.25519 + if (no_mask || mask(x,y,z)) { 1.25520 + G.get_tensor_at(x,y,z).symmetric_eigen(val,vec); 1.25521 + const float l1 = val[2], l2 = val[1], l3 = val[0], 1.25522 + ux = vec(0,0), uy = vec(0,1), uz = vec(0,2), 1.25523 + vx = vec(1,0), vy = vec(1,1), vz = vec(1,2), 1.25524 + wx = vec(2,0), wy = vec(2,1), wz = vec(2,2), 1.25525 + n1 = (float)cimg_std::pow(1+l1+l2+l3,-power1), 1.25526 + n2 = (float)cimg_std::pow(1+l1+l2+l3,-power2); 1.25527 + G(x,y,z,0) = n1*(ux*ux + vx*vx) + n2*wx*wx; 1.25528 + G(x,y,z,1) = n1*(ux*uy + vx*vy) + n2*wx*wy; 1.25529 + G(x,y,z,2) = n1*(ux*uz + vx*vz) + n2*wx*wz; 1.25530 + G(x,y,z,3) = n1*(uy*uy + vy*vy) + n2*wy*wy; 1.25531 + G(x,y,z,4) = n1*(uy*uz + vy*vz) + n2*wy*wz; 1.25532 + G(x,y,z,5) = n1*(uz*uz + vz*vz) + n2*wz*wz; 1.25533 + } else G(x,y,z,0) = G(x,y,z,1) = G(x,y,z,2) = G(x,y,z,3) = G(x,y,z,4) = G(x,y,z,5) = 0; 1.25534 + cimg_plugin_greycstoration_count; 1.25535 + } 1.25536 + cimg_plugin_greycstoration_unlock; 1.25537 + blur_anisotropic(G,amplitude,dl,da,gauss_prec,interpolation_type,fast_approx); 1.25538 + } else { // Field for 2D images 1.25539 + cimg_plugin_greycstoration_lock; 1.25540 + CImg<floatT> val(2), vec(2,2), G(blurred.get_structure_tensor()); 1.25541 + if (sigma>0) G.blur(sigma); 1.25542 + cimg_forXY(*this,x,y) { 1.25543 + if (no_mask || mask(x,y)) { 1.25544 + G.get_tensor_at(x,y).symmetric_eigen(val,vec); 1.25545 + const float l1 = val[1], l2 = val[0], 1.25546 + ux = vec(1,0), uy = vec(1,1), 1.25547 + vx = vec(0,0), vy = vec(0,1), 1.25548 + n1 = (float)cimg_std::pow(1+l1+l2,-power1), 1.25549 + n2 = (float)cimg_std::pow(1+l1+l2,-power2); 1.25550 + G(x,y,0,0) = n1*ux*ux + n2*vx*vx; 1.25551 + G(x,y,0,1) = n1*ux*uy + n2*vx*vy; 1.25552 + G(x,y,0,2) = n1*uy*uy + n2*vy*vy; 1.25553 + } else G(x,y,0,0) = G(x,y,0,1) = G(x,y,0,2) = 0; 1.25554 + cimg_plugin_greycstoration_count; 1.25555 + } 1.25556 + cimg_plugin_greycstoration_unlock; 1.25557 + blur_anisotropic(G,amplitude,dl,da,gauss_prec,interpolation_type,fast_approx); 1.25558 + } 1.25559 + } 1.25560 + return *this; 1.25561 + } 1.25562 + 1.25563 + template<typename tm> 1.25564 + CImg<T> get_blur_anisotropic(const CImg<tm>& mask, const float amplitude, const float sharpness=0.7f, const float anisotropy=0.3f, 1.25565 + const float alpha=0.6f, const float sigma=1.1f, const float dl=0.8f, 1.25566 + const float da=30, const float gauss_prec=2, const unsigned int interpolation_type=0, 1.25567 + const bool fast_approx=true, const float geom_factor=1) const { 1.25568 + return (+*this).blur_anisotropic(mask,amplitude,sharpness,anisotropy,alpha,sigma,dl,da,gauss_prec,interpolation_type,fast_approx,geom_factor); 1.25569 + } 1.25570 + 1.25571 + //! Blur an image following in an anisotropic way. 1.25572 + CImg<T>& blur_anisotropic(const float amplitude, const float sharpness=0.7f, const float anisotropy=0.3f, 1.25573 + const float alpha=0.6f, const float sigma=1.1f, const float dl=0.8f, const float da=30, 1.25574 + const float gauss_prec=2, const unsigned int interpolation_type=0, const bool fast_approx=true, 1.25575 + const float geom_factor=1) { 1.25576 + return blur_anisotropic(CImg<T>(),amplitude,sharpness,anisotropy,alpha,sigma,dl,da,gauss_prec,interpolation_type,fast_approx,geom_factor); 1.25577 + } 1.25578 + 1.25579 + CImg<T> get_blur_anisotropic(const float amplitude, const float sharpness=0.7f, const float anisotropy=0.3f, 1.25580 + const float alpha=0.6f, const float sigma=1.1f, const float dl=0.8f, 1.25581 + const float da=30, const float gauss_prec=2, const unsigned int interpolation_type=0, 1.25582 + const bool fast_approx=true, const float geom_factor=1) const { 1.25583 + return (+*this).blur_anisotropic(amplitude,sharpness,anisotropy,alpha,sigma,dl,da,gauss_prec,interpolation_type,fast_approx,geom_factor); 1.25584 + } 1.25585 + 1.25586 + //! Blur an image using the bilateral filter. 1.25587 + /** 1.25588 + \param sigmax Amount of blur along the X-axis. 1.25589 + \param sigmay Amount of blur along the Y-axis. 1.25590 + \param sigmaz Amount of blur along the Z-axis. 1.25591 + \param sigmar Amount of blur along the range axis. 1.25592 + \param bgridx Size of the bilateral grid along the X-axis. 1.25593 + \param bgridy Size of the bilateral grid along the Y-axis. 1.25594 + \param bgridz Size of the bilateral grid along the Z-axis. 1.25595 + \param bgridr Size of the bilateral grid along the range axis. 1.25596 + \param interpolation_type Use interpolation for image slicing. 1.25597 + \note This algorithm uses the optimisation technique proposed by S. Paris and F. Durand, in ECCV'2006 1.25598 + (extended for 3D volumetric images). 1.25599 + **/ 1.25600 + CImg<T>& blur_bilateral(const float sigmax, const float sigmay, const float sigmaz, const float sigmar, 1.25601 + const int bgridx, const int bgridy, const int bgridz, const int bgridr, 1.25602 + const bool interpolation_type=true) { 1.25603 + T m, M = maxmin(m); 1.25604 + const float range = (float)(1.0f+M-m); 1.25605 + const unsigned int 1.25606 + bx0 = bgridx>=0?bgridx:width*(-bgridx)/100, 1.25607 + by0 = bgridy>=0?bgridy:height*(-bgridy)/100, 1.25608 + bz0 = bgridz>=0?bgridz:depth*(-bgridz)/100, 1.25609 + br0 = bgridr>=0?bgridr:(int)(-range*bgridr/100), 1.25610 + bx = bx0>0?bx0:1, 1.25611 + by = by0>0?by0:1, 1.25612 + bz = bz0>0?bz0:1, 1.25613 + br = br0>0?br0:1; 1.25614 + const float 1.25615 + nsigmax = sigmax*bx/width, 1.25616 + nsigmay = sigmay*by/height, 1.25617 + nsigmaz = sigmaz*bz/depth, 1.25618 + nsigmar = sigmar*br/range; 1.25619 + if (nsigmax>0 || nsigmay>0 || nsigmaz>0 || nsigmar>0) { 1.25620 + const bool threed = depth>1; 1.25621 + if (threed) { // 3d version of the algorithm 1.25622 + CImg<floatT> bgrid(bx,by,bz,br), bgridw(bx,by,bz,br); 1.25623 + cimg_forV(*this,k) { 1.25624 + bgrid.fill(0); bgridw.fill(0); 1.25625 + cimg_forXYZ(*this,x,y,z) { 1.25626 + const T val = (*this)(x,y,z,k); 1.25627 + const int X = x*bx/width, Y = y*by/height, Z = z*bz/depth, R = (int)((val-m)*br/range); 1.25628 + bgrid(X,Y,Z,R) = (float)val; 1.25629 + bgridw(X,Y,Z,R) = 1; 1.25630 + } 1.25631 + bgrid.blur(nsigmax,nsigmay,nsigmaz,true).deriche(nsigmar,0,'v',false); 1.25632 + bgridw.blur(nsigmax,nsigmay,nsigmaz,true).deriche(nsigmar,0,'v',false); 1.25633 + if (interpolation_type) cimg_forXYZ(*this,x,y,z) { 1.25634 + const T val = (*this)(x,y,z,k); 1.25635 + const float X = (float)x*bx/width, Y = (float)y*by/height, Z = (float)z*bz/depth, R = (float)((val-m)*br/range), 1.25636 + bval0 = bgrid._linear_atXYZV(X,Y,Z,R), bval1 = bgridw._linear_atXYZV(X,Y,Z,R); 1.25637 + (*this)(x,y,z,k) = (T)(bval0/bval1); 1.25638 + } else cimg_forXYZ(*this,x,y,z) { 1.25639 + const T val = (*this)(x,y,z,k); 1.25640 + const int X = x*bx/width, Y = y*by/height, Z = z*bz/depth, R = (int)((val-m)*br/range); 1.25641 + const float bval0 = bgrid(X,Y,Z,R), bval1 = bgridw(X,Y,Z,R); 1.25642 + (*this)(x,y,z,k) = (T)(bval0/bval1); 1.25643 + } 1.25644 + } 1.25645 + } else { // 2d version of the algorithm 1.25646 + CImg<floatT> bgrid(bx,by,br,2); 1.25647 + cimg_forV(*this,k) { 1.25648 + bgrid.fill(0); 1.25649 + cimg_forXY(*this,x,y) { 1.25650 + const T val = (*this)(x,y,k); 1.25651 + const int X = x*bx/width, Y = y*by/height, R = (int)((val-m)*br/range); 1.25652 + bgrid(X,Y,R,0) = (float)val; 1.25653 + bgrid(X,Y,R,1) = 1; 1.25654 + } 1.25655 + bgrid.blur(nsigmax,nsigmay,0,true).blur(0,0,nsigmar,false); 1.25656 + if (interpolation_type) cimg_forXY(*this,x,y) { 1.25657 + const T val = (*this)(x,y,k); 1.25658 + const float X = (float)x*bx/width, Y = (float)y*by/height, R = (float)((val-m)*br/range), 1.25659 + bval0 = bgrid._linear_atXYZ(X,Y,R,0), bval1 = bgrid._linear_atXYZ(X,Y,R,1); 1.25660 + (*this)(x,y,k) = (T)(bval0/bval1); 1.25661 + } else cimg_forXY(*this,x,y) { 1.25662 + const T val = (*this)(x,y,k); 1.25663 + const int X = x*bx/width, Y = y*by/height, R = (int)((val-m)*br/range); 1.25664 + const float bval0 = bgrid(X,Y,R,0), bval1 = bgrid(X,Y,R,1); 1.25665 + (*this)(x,y,k) = (T)(bval0/bval1); 1.25666 + } 1.25667 + } 1.25668 + } 1.25669 + } 1.25670 + return *this; 1.25671 + } 1.25672 + 1.25673 + CImg<T> get_blur_bilateral(const float sigmax, const float sigmay, const float sigmaz, const float sigmar, 1.25674 + const int bgridx, const int bgridy, const int bgridz, const int bgridr, 1.25675 + const bool interpolation_type=true) const { 1.25676 + return (+*this).blur_bilateral(sigmax,sigmay,sigmaz,sigmar,bgridx,bgridy,bgridz,bgridr,interpolation_type); 1.25677 + } 1.25678 + 1.25679 + //! Blur an image using the bilateral filter. 1.25680 + CImg<T>& blur_bilateral(const float sigmas, const float sigmar, const int bgrids=-33, const int bgridr=32, 1.25681 + const bool interpolation_type=true) { 1.25682 + return blur_bilateral(sigmas,sigmas,sigmas,sigmar,bgrids,bgrids,bgrids,bgridr,interpolation_type); 1.25683 + } 1.25684 + 1.25685 + CImg<T> get_blur_bilateral(const float sigmas, const float sigmar, const int bgrids=-33, const int bgridr=32, 1.25686 + const bool interpolation_type=true) const { 1.25687 + return (+*this).blur_bilateral(sigmas,sigmas,sigmas,sigmar,bgrids,bgrids,bgrids,bgridr,interpolation_type); 1.25688 + } 1.25689 + 1.25690 + //! Blur an image in its patch-based space. 1.25691 + CImg<T>& blur_patch(const unsigned int patch_size, const float sigma_p, const float sigma_s=10, 1.25692 + const unsigned int lookup_size=4, const bool fast_approx=true) { 1.25693 + 1.25694 +#define _cimg_blur_patch_fastfunc(x) ((x)>3?0:1) 1.25695 +#define _cimg_blur_patch_slowfunc(x) cimg_std::exp(-(x)) 1.25696 +#define _cimg_blur_patch3d(N,func) { \ 1.25697 + const unsigned int N3 = N*N*N; \ 1.25698 + cimg_for##N##XYZ(*this,x,y,z) { \ 1.25699 + cimg_plugin_greycstoration_count; \ 1.25700 + cimg_forV(*this,k) cimg_get##N##x##N##x##N(*this,x,y,z,k,P.ptr(N3*k)); \ 1.25701 + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; \ 1.25702 + float sum_weights = 0; \ 1.25703 + cimg_for_in##N##XYZ(*this,x0,y0,z0,x1,y1,z1,p,q,r) { \ 1.25704 + cimg_forV(*this,k) cimg_get##N##x##N##x##N(*this,p,q,r,k,Q.ptr(N3*k)); \ 1.25705 + float distance2 = 0; \ 1.25706 + const T *pQ = Q.end(); \ 1.25707 + cimg_for(P,pP,T) { const float dI = (float)*pP - (float)*(--pQ); distance2+=dI*dI; } \ 1.25708 + distance2/=Pnorm; \ 1.25709 + const float dx = (float)p - x, dy = (float)q - y, dz = (float)r - z, \ 1.25710 + alldist = distance2 + (dx*dx + dy*dy + dz*dz)/sigma_s2, weight = (float)func(alldist); \ 1.25711 + sum_weights+=weight; \ 1.25712 + { cimg_forV(*this,k) res(x,y,z,k)+=weight*(*this)(p,q,r,k); } \ 1.25713 + } \ 1.25714 + if (sum_weights>0) cimg_forV(*this,k) res(x,y,z,k)/=sum_weights; else cimg_forV(*this,k) res(x,y,z,k) = (Tfloat)((*this)(x,y,z,k)); \ 1.25715 + }} 1.25716 +#define _cimg_blur_patch2d(N,func) { \ 1.25717 + const unsigned int N2 = N*N; \ 1.25718 + cimg_for##N##XY(*this,x,y) { \ 1.25719 + cimg_plugin_greycstoration_count; \ 1.25720 + cimg_forV(*this,k) cimg_get##N##x##N(*this,x,y,0,k,P.ptr(N2*k)); \ 1.25721 + const int x0 = x-rsize1, y0 = y-rsize1, x1 = x+rsize2, y1 = y+rsize2; \ 1.25722 + float sum_weights = 0; \ 1.25723 + cimg_for_in##N##XY(*this,x0,y0,x1,y1,p,q) { \ 1.25724 + cimg_forV(*this,k) cimg_get##N##x##N(*this,p,q,0,k,Q.ptr(N2*k)); \ 1.25725 + float distance2 = 0; \ 1.25726 + const T *pQ = Q.end(); \ 1.25727 + cimg_for(P,pP,T) { const float dI = (float)*pP-(float)*(--pQ); distance2+=dI*dI; } \ 1.25728 + distance2/=Pnorm; \ 1.25729 + const float dx = (float)p-x, dy = (float)q-y, \ 1.25730 + alldist = distance2 + (dx*dx+dy*dy)/sigma_s2, weight = (float)func(alldist); \ 1.25731 + sum_weights+=weight; \ 1.25732 + { cimg_forV(*this,k) res(x,y,k)+=weight*(*this)(p,q,k); } \ 1.25733 + } \ 1.25734 + if (sum_weights>0) cimg_forV(*this,k) res(x,y,k)/=sum_weights; else cimg_forV(*this,k) res(x,y,k) = (Tfloat)((*this)(x,y,k)); \ 1.25735 + }} 1.25736 + 1.25737 + CImg<Tfloat> res(width,height,depth,dim,0); 1.25738 + CImg<T> P(patch_size*patch_size*dim), Q(P); 1.25739 + const float sigma_s2 = sigma_s*sigma_s, sigma_p2 = sigma_p*sigma_p, Pnorm = P.size()*sigma_p2; 1.25740 + const int rsize2 = (int)lookup_size/2, rsize1 = rsize2-1+(lookup_size%2); 1.25741 + if (depth>1) switch (patch_size) { // 3D version 1.25742 + case 2 : 1.25743 + if (fast_approx) { _cimg_blur_patch3d(2,_cimg_blur_patch_fastfunc); } 1.25744 + else { _cimg_blur_patch3d(2,_cimg_blur_patch_slowfunc); } 1.25745 + break; 1.25746 + case 3 : 1.25747 + if (fast_approx) { _cimg_blur_patch3d(3,_cimg_blur_patch_fastfunc); } 1.25748 + else { _cimg_blur_patch3d(3,_cimg_blur_patch_slowfunc); } 1.25749 + break; 1.25750 + default : { 1.25751 + const int psize1 = (int)patch_size/2, psize0 = psize1-1+(patch_size%2); 1.25752 + cimg_forXYZ(*this,x,y,z) { 1.25753 + cimg_plugin_greycstoration_count; 1.25754 + P = get_crop(x - psize0,y - psize0,z - psize0,x + psize1,y + psize1,z + psize1,true); 1.25755 + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; 1.25756 + float sum_weights = 0; 1.25757 + cimg_for_inXYZ(*this,x0,y0,z0,x1,y1,z1,p,q,r) { 1.25758 + (Q = get_crop(p - psize0,q - psize0,r - psize0,p + psize1,q + psize1,r + psize1,true))-=P; 1.25759 + const float 1.25760 + dx = (float)x - p, dy = (float)y - q, dz = (float)z - r, 1.25761 + distance2 = (float)(Q.pow(2).sum()/Pnorm + (dx*dx + dy*dy + dz*dz)/sigma_s2), 1.25762 + weight = (float)cimg_std::exp(-distance2); 1.25763 + sum_weights+=weight; 1.25764 + cimg_forV(*this,k) res(x,y,z,k)+=weight*(*this)(p,q,r,k); 1.25765 + } 1.25766 + if (sum_weights>0) cimg_forV(*this,k) res(x,y,z,k)/=sum_weights; else cimg_forV(*this,k) res(x,y,z,k) = (Tfloat)((*this)(x,y,z,k)); 1.25767 + } 1.25768 + } 1.25769 + } else switch (patch_size) { // 2D version 1.25770 + case 2 : 1.25771 + if (fast_approx) { _cimg_blur_patch2d(2,_cimg_blur_patch_fastfunc); } 1.25772 + else { _cimg_blur_patch2d(2,_cimg_blur_patch_slowfunc); } 1.25773 + break; 1.25774 + case 3 : 1.25775 + if (fast_approx) { _cimg_blur_patch2d(3,_cimg_blur_patch_fastfunc); } 1.25776 + else { _cimg_blur_patch2d(3,_cimg_blur_patch_slowfunc); } 1.25777 + break; 1.25778 + case 4 : 1.25779 + if (fast_approx) { _cimg_blur_patch2d(4,_cimg_blur_patch_fastfunc); } 1.25780 + else { _cimg_blur_patch2d(4,_cimg_blur_patch_slowfunc); } 1.25781 + break; 1.25782 + case 5 : 1.25783 + if (fast_approx) { _cimg_blur_patch2d(5,_cimg_blur_patch_fastfunc); } 1.25784 + else { _cimg_blur_patch2d(5,_cimg_blur_patch_slowfunc); } 1.25785 + break; 1.25786 + case 6 : 1.25787 + if (fast_approx) { _cimg_blur_patch2d(6,_cimg_blur_patch_fastfunc); } 1.25788 + else { _cimg_blur_patch2d(6,_cimg_blur_patch_slowfunc); } 1.25789 + break; 1.25790 + case 7 : 1.25791 + if (fast_approx) { _cimg_blur_patch2d(7,_cimg_blur_patch_fastfunc); } 1.25792 + else { _cimg_blur_patch2d(7,_cimg_blur_patch_slowfunc); } 1.25793 + break; 1.25794 + case 8 : 1.25795 + if (fast_approx) { _cimg_blur_patch2d(8,_cimg_blur_patch_fastfunc); } 1.25796 + else { _cimg_blur_patch2d(8,_cimg_blur_patch_slowfunc); } 1.25797 + break; 1.25798 + case 9 : 1.25799 + if (fast_approx) { _cimg_blur_patch2d(9,_cimg_blur_patch_fastfunc); } 1.25800 + else { _cimg_blur_patch2d(9,_cimg_blur_patch_slowfunc); } 1.25801 + break; 1.25802 + default : { 1.25803 + const int psize1 = (int)patch_size/2, psize0 = psize1-1+(patch_size%2); 1.25804 + cimg_forXY(*this,x,y) { 1.25805 + cimg_plugin_greycstoration_count; 1.25806 + P = get_crop(x - psize0,y - psize0,x + psize1,y + psize1,true); 1.25807 + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; 1.25808 + float sum_weights = 0; 1.25809 + cimg_for_inXY(*this,x0,y0,x1,y1,p,q) { 1.25810 + (Q = get_crop(p - psize0,q - psize0,p + psize1,q + psize1,true))-=P; 1.25811 + const float 1.25812 + dx = (float)x - p, dy = (float)y - q, 1.25813 + distance2 = (float)(Q.pow(2).sum()/Pnorm + (dx*dx + dy*dy)/sigma_s2), 1.25814 + weight = (float)cimg_std::exp(-distance2); 1.25815 + sum_weights+=weight; 1.25816 + cimg_forV(*this,k) res(x,y,0,k)+=weight*(*this)(p,q,0,k); 1.25817 + } 1.25818 + if (sum_weights>0) cimg_forV(*this,k) res(x,y,0,k)/=sum_weights; else cimg_forV(*this,k) res(x,y,0,k) = (Tfloat)((*this)(x,y,0,k)); 1.25819 + } 1.25820 + } 1.25821 + } 1.25822 + return res.transfer_to(*this); 1.25823 + } 1.25824 + 1.25825 + CImg<T> get_blur_patch(const unsigned int patch_size, const float sigma_p, const float sigma_s=10, 1.25826 + const unsigned int lookup_size=4, const bool fast_approx=true) const { 1.25827 + return (+*this).blur_patch(patch_size,sigma_p,sigma_s,lookup_size,fast_approx); 1.25828 + } 1.25829 + 1.25830 + //! Compute the Fast Fourier Transform of an image (along a specified axis). 1.25831 + CImgList<Tfloat> get_FFT(const char axis, const bool invert=false) const { 1.25832 + return CImgList<Tfloat>(*this).FFT(axis,invert); 1.25833 + } 1.25834 + 1.25835 + //! Compute the Fast Fourier Transform on an image. 1.25836 + CImgList<Tfloat> get_FFT(const bool invert=false) const { 1.25837 + return CImgList<Tfloat>(*this).FFT(invert); 1.25838 + } 1.25839 + 1.25840 + //! Apply a median filter. 1.25841 + CImg<T>& blur_median(const unsigned int n) { 1.25842 + return get_blur_median(n).transfer_to(*this); 1.25843 + } 1.25844 + 1.25845 + CImg<T> get_blur_median(const unsigned int n) { 1.25846 + CImg<T> res(width,height,depth,dim); 1.25847 + if (!n || n==1) return *this; 1.25848 + const int hl=n/2, hr=hl-1+n%2; 1.25849 + if (res.depth!=1) { // 3D median filter 1.25850 + CImg<T> vois; 1.25851 + cimg_forXYZV(*this,x,y,z,k) { 1.25852 + const int 1.25853 + x0 = x - hl, y0 = y - hl, z0 = z-hl, x1 = x + hr, y1 = y + hr, z1 = z+hr, 1.25854 + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, nz0 = z0<0?0:z0, 1.25855 + nx1 = x1>=dimx()?dimx()-1:x1, ny1 = y1>=dimy()?dimy()-1:y1, nz1 = z1>=dimz()?dimz()-1:z1; 1.25856 + vois = get_crop(nx0,ny0,nz0,k,nx1,ny1,nz1,k); 1.25857 + res(x,y,z,k) = vois.median(); 1.25858 + } 1.25859 + } else { 1.25860 +#define _cimg_median_sort(a,b) if ((a)>(b)) cimg::swap(a,b) 1.25861 + if (res.height!=1) switch (n) { // 2D median filter 1.25862 + case 3 : { 1.25863 + T I[9] = { 0 }; 1.25864 + CImg_3x3(J,T); 1.25865 + cimg_forV(*this,k) cimg_for3x3(*this,x,y,0,k,I) { 1.25866 + cimg_std::memcpy(J,I,9*sizeof(T)); 1.25867 + _cimg_median_sort(Jcp, Jnp); _cimg_median_sort(Jcc, Jnc); _cimg_median_sort(Jcn, Jnn); 1.25868 + _cimg_median_sort(Jpp, Jcp); _cimg_median_sort(Jpc, Jcc); _cimg_median_sort(Jpn, Jcn); 1.25869 + _cimg_median_sort(Jcp, Jnp); _cimg_median_sort(Jcc, Jnc); _cimg_median_sort(Jcn, Jnn); 1.25870 + _cimg_median_sort(Jpp, Jpc); _cimg_median_sort(Jnc, Jnn); _cimg_median_sort(Jcc, Jcn); 1.25871 + _cimg_median_sort(Jpc, Jpn); _cimg_median_sort(Jcp, Jcc); _cimg_median_sort(Jnp, Jnc); 1.25872 + _cimg_median_sort(Jcc, Jcn); _cimg_median_sort(Jcc, Jnp); _cimg_median_sort(Jpn, Jcc); 1.25873 + _cimg_median_sort(Jcc, Jnp); 1.25874 + res(x,y,0,k) = Jcc; 1.25875 + } 1.25876 + } break; 1.25877 + case 5 : { 1.25878 + T I[25] = { 0 }; 1.25879 + CImg_5x5(J,T); 1.25880 + cimg_forV(*this,k) cimg_for5x5(*this,x,y,0,k,I) { 1.25881 + cimg_std::memcpy(J,I,25*sizeof(T)); 1.25882 + _cimg_median_sort(Jbb, Jpb); _cimg_median_sort(Jnb, Jab); _cimg_median_sort(Jcb, Jab); _cimg_median_sort(Jcb, Jnb); 1.25883 + _cimg_median_sort(Jpp, Jcp); _cimg_median_sort(Jbp, Jcp); _cimg_median_sort(Jbp, Jpp); _cimg_median_sort(Jap, Jbc); 1.25884 + _cimg_median_sort(Jnp, Jbc); _cimg_median_sort(Jnp, Jap); _cimg_median_sort(Jcc, Jnc); _cimg_median_sort(Jpc, Jnc); 1.25885 + _cimg_median_sort(Jpc, Jcc); _cimg_median_sort(Jbn, Jpn); _cimg_median_sort(Jac, Jpn); _cimg_median_sort(Jac, Jbn); 1.25886 + _cimg_median_sort(Jnn, Jan); _cimg_median_sort(Jcn, Jan); _cimg_median_sort(Jcn, Jnn); _cimg_median_sort(Jpa, Jca); 1.25887 + _cimg_median_sort(Jba, Jca); _cimg_median_sort(Jba, Jpa); _cimg_median_sort(Jna, Jaa); _cimg_median_sort(Jcb, Jbp); 1.25888 + _cimg_median_sort(Jnb, Jpp); _cimg_median_sort(Jbb, Jpp); _cimg_median_sort(Jbb, Jnb); _cimg_median_sort(Jab, Jcp); 1.25889 + _cimg_median_sort(Jpb, Jcp); _cimg_median_sort(Jpb, Jab); _cimg_median_sort(Jpc, Jac); _cimg_median_sort(Jnp, Jac); 1.25890 + _cimg_median_sort(Jnp, Jpc); _cimg_median_sort(Jcc, Jbn); _cimg_median_sort(Jap, Jbn); _cimg_median_sort(Jap, Jcc); 1.25891 + _cimg_median_sort(Jnc, Jpn); _cimg_median_sort(Jbc, Jpn); _cimg_median_sort(Jbc, Jnc); _cimg_median_sort(Jba, Jna); 1.25892 + _cimg_median_sort(Jcn, Jna); _cimg_median_sort(Jcn, Jba); _cimg_median_sort(Jpa, Jaa); _cimg_median_sort(Jnn, Jaa); 1.25893 + _cimg_median_sort(Jnn, Jpa); _cimg_median_sort(Jan, Jca); _cimg_median_sort(Jnp, Jcn); _cimg_median_sort(Jap, Jnn); 1.25894 + _cimg_median_sort(Jbb, Jnn); _cimg_median_sort(Jbb, Jap); _cimg_median_sort(Jbc, Jan); _cimg_median_sort(Jpb, Jan); 1.25895 + _cimg_median_sort(Jpb, Jbc); _cimg_median_sort(Jpc, Jba); _cimg_median_sort(Jcb, Jba); _cimg_median_sort(Jcb, Jpc); 1.25896 + _cimg_median_sort(Jcc, Jpa); _cimg_median_sort(Jnb, Jpa); _cimg_median_sort(Jnb, Jcc); _cimg_median_sort(Jnc, Jca); 1.25897 + _cimg_median_sort(Jab, Jca); _cimg_median_sort(Jab, Jnc); _cimg_median_sort(Jac, Jna); _cimg_median_sort(Jbp, Jna); 1.25898 + _cimg_median_sort(Jbp, Jac); _cimg_median_sort(Jbn, Jaa); _cimg_median_sort(Jpp, Jaa); _cimg_median_sort(Jpp, Jbn); 1.25899 + _cimg_median_sort(Jcp, Jpn); _cimg_median_sort(Jcp, Jan); _cimg_median_sort(Jnc, Jpa); _cimg_median_sort(Jbn, Jna); 1.25900 + _cimg_median_sort(Jcp, Jnc); _cimg_median_sort(Jcp, Jbn); _cimg_median_sort(Jpb, Jap); _cimg_median_sort(Jnb, Jpc); 1.25901 + _cimg_median_sort(Jbp, Jcn); _cimg_median_sort(Jpc, Jcn); _cimg_median_sort(Jap, Jcn); _cimg_median_sort(Jab, Jbc); 1.25902 + _cimg_median_sort(Jpp, Jcc); _cimg_median_sort(Jcp, Jac); _cimg_median_sort(Jab, Jpp); _cimg_median_sort(Jab, Jcp); 1.25903 + _cimg_median_sort(Jcc, Jac); _cimg_median_sort(Jbc, Jac); _cimg_median_sort(Jpp, Jcp); _cimg_median_sort(Jbc, Jcc); 1.25904 + _cimg_median_sort(Jpp, Jbc); _cimg_median_sort(Jpp, Jcn); _cimg_median_sort(Jcc, Jcn); _cimg_median_sort(Jcp, Jcn); 1.25905 + _cimg_median_sort(Jcp, Jbc); _cimg_median_sort(Jcc, Jnn); _cimg_median_sort(Jcp, Jcc); _cimg_median_sort(Jbc, Jnn); 1.25906 + _cimg_median_sort(Jcc, Jba); _cimg_median_sort(Jbc, Jba); _cimg_median_sort(Jbc, Jcc); 1.25907 + res(x,y,0,k) = Jcc; 1.25908 + } 1.25909 + } break; 1.25910 + default : { 1.25911 + CImg<T> vois; 1.25912 + cimg_forXYV(*this,x,y,k) { 1.25913 + const int 1.25914 + x0 = x - hl, y0 = y - hl, x1 = x + hr, y1 = y + hr, 1.25915 + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, 1.25916 + nx1 = x1>=dimx()?dimx()-1:x1, ny1 = y1>=dimy()?dimy()-1:y1; 1.25917 + vois = get_crop(nx0,ny0,0,k,nx1,ny1,0,k); 1.25918 + res(x,y,0,k) = vois.median(); 1.25919 + } 1.25920 + } 1.25921 + } else switch (n) { // 1D median filter 1.25922 + case 2 : { 1.25923 + T I[4] = { 0 }; 1.25924 + cimg_forV(*this,k) cimg_for2x2(*this,x,y,0,k,I) res(x,0,0,k) = (T)(0.5f*(I[0]+I[1])); 1.25925 + } break; 1.25926 + case 3 : { 1.25927 + T I[9] = { 0 }; 1.25928 + cimg_forV(*this,k) cimg_for3x3(*this,x,y,0,k,I) { 1.25929 + res(x,0,0,k) = I[3]<I[4]? 1.25930 + (I[4]<I[5]?I[4]: 1.25931 + (I[3]<I[5]?I[5]:I[3])): 1.25932 + (I[3]<I[5]?I[3]: 1.25933 + (I[4]<I[5]?I[5]:I[4])); 1.25934 + } 1.25935 + } break; 1.25936 + default : { 1.25937 + CImg<T> vois; 1.25938 + cimg_forXV(*this,x,k) { 1.25939 + const int 1.25940 + x0 = x - hl, x1 = x + hr, 1.25941 + nx0 = x0<0?0:x0, nx1 = x1>=dimx()?dimx()-1:x1; 1.25942 + vois = get_crop(nx0,0,0,k,nx1,0,0,k); 1.25943 + res(x,0,0,k) = vois.median(); 1.25944 + } 1.25945 + } 1.25946 + } 1.25947 + } 1.25948 + return res; 1.25949 + } 1.25950 + 1.25951 + //! Sharpen image using anisotropic shock filters or inverse diffusion. 1.25952 + CImg<T>& sharpen(const float amplitude, const bool sharpen_type=false, const float edge=1, const float alpha=0, const float sigma=0) { 1.25953 + if (is_empty()) return *this; 1.25954 + T valm, valM = maxmin(valm); 1.25955 + const bool threed = (depth>1); 1.25956 + const float nedge = 0.5f*edge; 1.25957 + CImg<Tfloat> val, vec, veloc(width,height,depth,dim); 1.25958 + 1.25959 + if (threed) { 1.25960 + CImg_3x3x3(I,T); 1.25961 + if (sharpen_type) { // 3D Shock filter. 1.25962 + CImg<Tfloat> G = (alpha>0?get_blur(alpha).get_structure_tensor():get_structure_tensor()); 1.25963 + if (sigma>0) G.blur(sigma); 1.25964 + 1.25965 + cimg_forXYZ(G,x,y,z) { 1.25966 + G.get_tensor_at(x,y,z).symmetric_eigen(val,vec); 1.25967 + G(x,y,z,0) = vec(0,0); 1.25968 + G(x,y,z,1) = vec(0,1); 1.25969 + G(x,y,z,2) = vec(0,2); 1.25970 + G(x,y,z,3) = 1 - (Tfloat)cimg_std::pow(1+val[0]+val[1]+val[2],-(Tfloat)nedge); 1.25971 + } 1.25972 + cimg_forV(*this,k) cimg_for3x3x3(*this,x,y,z,k,I) { 1.25973 + const Tfloat 1.25974 + u = G(x,y,z,0), 1.25975 + v = G(x,y,z,1), 1.25976 + w = G(x,y,z,2), 1.25977 + amp = G(x,y,z,3), 1.25978 + ixx = (Tfloat)Incc + Ipcc - 2*Iccc, 1.25979 + ixy = 0.25f*((Tfloat)Innc + Ippc - Inpc - Ipnc), 1.25980 + ixz = 0.25f*((Tfloat)Incn + Ipcp - Incp - Ipcn), 1.25981 + iyy = (Tfloat)Icnc + Icpc - 2*Iccc, 1.25982 + iyz = 0.25f*((Tfloat)Icnn + Icpp - Icnp - Icpn), 1.25983 + izz = (Tfloat)Iccn + Iccp - 2*Iccc, 1.25984 + ixf = (Tfloat)Incc - Iccc, 1.25985 + ixb = (Tfloat)Iccc - Ipcc, 1.25986 + iyf = (Tfloat)Icnc - Iccc, 1.25987 + iyb = (Tfloat)Iccc - Icpc, 1.25988 + izf = (Tfloat)Iccn - Iccc, 1.25989 + izb = (Tfloat)Iccc - Iccp, 1.25990 + itt = u*u*ixx + v*v*iyy + w*w*izz + 2*u*v*ixy + 2*u*w*ixz + 2*v*w*iyz, 1.25991 + it = u*cimg::minmod(ixf,ixb) + v*cimg::minmod(iyf,iyb) + w*cimg::minmod(izf,izb); 1.25992 + veloc(x,y,z,k) = -amp*cimg::sign(itt)*cimg::abs(it); 1.25993 + } 1.25994 + } else cimg_forV(*this,k) cimg_for3x3x3(*this,x,y,z,k,I) veloc(x,y,z,k) = -(Tfloat)Ipcc-Incc-Icpc-Icnc-Iccp-Iccn+6*Iccc; // 3D Inverse diffusion. 1.25995 + } else { 1.25996 + CImg_3x3(I,T); 1.25997 + if (sharpen_type) { // 2D Shock filter. 1.25998 + CImg<Tfloat> G = (alpha>0?get_blur(alpha).get_structure_tensor():get_structure_tensor()); 1.25999 + if (sigma>0) G.blur(sigma); 1.26000 + cimg_forXY(G,x,y) { 1.26001 + G.get_tensor_at(x,y).symmetric_eigen(val,vec); 1.26002 + G(x,y,0) = vec(0,0); 1.26003 + G(x,y,1) = vec(0,1); 1.26004 + G(x,y,2) = 1 - (Tfloat)cimg_std::pow(1+val[0]+val[1],-(Tfloat)nedge); 1.26005 + } 1.26006 + cimg_forV(*this,k) cimg_for3x3(*this,x,y,0,k,I) { 1.26007 + const Tfloat 1.26008 + u = G(x,y,0), 1.26009 + v = G(x,y,1), 1.26010 + amp = G(x,y,2), 1.26011 + ixx = (Tfloat)Inc + Ipc - 2*Icc, 1.26012 + ixy = 0.25f*((Tfloat)Inn + Ipp - Inp - Ipn), 1.26013 + iyy = (Tfloat)Icn + Icp - 2*Icc, 1.26014 + ixf = (Tfloat)Inc - Icc, 1.26015 + ixb = (Tfloat)Icc - Ipc, 1.26016 + iyf = (Tfloat)Icn - Icc, 1.26017 + iyb = (Tfloat)Icc - Icp, 1.26018 + itt = u*u*ixx + v*v*iyy + 2*u*v*ixy, 1.26019 + it = u*cimg::minmod(ixf,ixb) + v*cimg::minmod(iyf,iyb); 1.26020 + veloc(x,y,k) = -amp*cimg::sign(itt)*cimg::abs(it); 1.26021 + } 1.26022 + } else cimg_forV(*this,k) cimg_for3x3(*this,x,y,0,k,I) veloc(x,y,k) = -(Tfloat)Ipc-Inc-Icp-Icn+4*Icc; // 3D Inverse diffusion. 1.26023 + } 1.26024 + float m, M = (float)veloc.maxmin(m); 1.26025 + const float vmax = (float)cimg::max(cimg::abs(m),cimg::abs(M)); 1.26026 + if (vmax!=0) { veloc*=amplitude/vmax; (*this)+=veloc; } 1.26027 + return cut(valm,valM); 1.26028 + } 1.26029 + 1.26030 + CImg<T> get_sharpen(const float amplitude, const bool sharpen_type=false, const float edge=1, const float alpha=0, const float sigma=0) const { 1.26031 + return (+*this).sharpen(amplitude,sharpen_type,edge,alpha,sigma); 1.26032 + } 1.26033 + 1.26034 + //! Compute the Haar multiscale wavelet transform (monodimensional version). 1.26035 + /** 1.26036 + \param axis Axis considered for the transform. 1.26037 + \param invert Set inverse of direct transform. 1.26038 + \param nb_scales Number of scales used for the transform. 1.26039 + **/ 1.26040 + CImg<T>& haar(const char axis, const bool invert=false, const unsigned int nb_scales=1) { 1.26041 + return get_haar(axis,invert,nb_scales).transfer_to(*this); 1.26042 + } 1.26043 + 1.26044 + CImg<Tfloat> get_haar(const char axis, const bool invert=false, const unsigned int nb_scales=1) const { 1.26045 + if (is_empty() || !nb_scales) return *this; 1.26046 + CImg<Tfloat> res; 1.26047 + 1.26048 + if (nb_scales==1) { 1.26049 + switch (cimg::uncase(axis)) { // Single scale transform 1.26050 + case 'x' : { 1.26051 + const unsigned int w = width/2; 1.26052 + if (w) { 1.26053 + if (w%2) 1.26054 + throw CImgInstanceException("CImg<%s>::haar() : Sub-image width = %u is not even at a particular scale (=%u).", 1.26055 + pixel_type(),w); 1.26056 + res.assign(width,height,depth,dim); 1.26057 + if (invert) cimg_forYZV(*this,y,z,v) { // Inverse transform along X 1.26058 + for (unsigned int x=0, xw=w, x2=0; x<w; ++x, ++xw) { 1.26059 + const Tfloat val0 = (Tfloat)(*this)(x,y,z,v), val1 = (Tfloat)(*this)(xw,y,z,v); 1.26060 + res(x2++,y,z,v) = val0 - val1; 1.26061 + res(x2++,y,z,v) = val0 + val1; 1.26062 + } 1.26063 + } else cimg_forYZV(*this,y,z,v) { // Direct transform along X 1.26064 + for (unsigned int x=0, xw=w, x2=0; x<w; ++x, ++xw) { 1.26065 + const Tfloat val0 = (Tfloat)(*this)(x2++,y,z,v), val1 = (Tfloat)(*this)(x2++,y,z,v); 1.26066 + res(x,y,z,v) = (val0 + val1)/2; 1.26067 + res(xw,y,z,v) = (val1 - val0)/2; 1.26068 + } 1.26069 + } 1.26070 + } else return *this; 1.26071 + } break; 1.26072 + case 'y' : { 1.26073 + const unsigned int h = height/2; 1.26074 + if (h) { 1.26075 + if (h%2) 1.26076 + throw CImgInstanceException("CImg<%s>::haar() : Sub-image height = %u is not even at a particular scale.", 1.26077 + pixel_type(),h); 1.26078 + res.assign(width,height,depth,dim); 1.26079 + if (invert) cimg_forXZV(*this,x,z,v) { // Inverse transform along Y 1.26080 + for (unsigned int y=0, yh=h, y2=0; y<h; ++y, ++yh) { 1.26081 + const Tfloat val0 = (Tfloat)(*this)(x,y,z,v), val1 = (Tfloat)(*this)(x,yh,z,v); 1.26082 + res(x,y2++,z,v) = val0 - val1; 1.26083 + res(x,y2++,z,v) = val0 + val1; 1.26084 + } 1.26085 + } else cimg_forXZV(*this,x,z,v) { 1.26086 + for (unsigned int y=0, yh=h, y2=0; y<h; ++y, ++yh) { // Direct transform along Y 1.26087 + const Tfloat val0 = (Tfloat)(*this)(x,y2++,z,v), val1 = (Tfloat)(*this)(x,y2++,z,v); 1.26088 + res(x,y,z,v) = (val0 + val1)/2; 1.26089 + res(x,yh,z,v) = (val1 - val0)/2; 1.26090 + } 1.26091 + } 1.26092 + } else return *this; 1.26093 + } break; 1.26094 + case 'z' : { 1.26095 + const unsigned int d = depth/2; 1.26096 + if (d) { 1.26097 + if (d%2) 1.26098 + throw CImgInstanceException("CImg<%s>::haar() : Sub-image depth = %u is not even at a particular scale.", 1.26099 + pixel_type(),d); 1.26100 + res.assign(width,height,depth,dim); 1.26101 + if (invert) cimg_forXYV(*this,x,y,v) { // Inverse transform along Z 1.26102 + for (unsigned int z=0, zd=d, z2=0; z<d; ++z, ++zd) { 1.26103 + const Tfloat val0 = (Tfloat)(*this)(x,y,z,v), val1 = (Tfloat)(*this)(x,y,zd,v); 1.26104 + res(x,y,z2++,v) = val0 - val1; 1.26105 + res(x,y,z2++,v) = val0 + val1; 1.26106 + } 1.26107 + } else cimg_forXYV(*this,x,y,v) { 1.26108 + for (unsigned int z=0, zd=d, z2=0; z<d; ++z, ++zd) { // Direct transform along Z 1.26109 + const Tfloat val0 = (Tfloat)(*this)(x,y,z2++,v), val1 = (Tfloat)(*this)(x,y,z2++,v); 1.26110 + res(x,y,z,v) = (val0 + val1)/2; 1.26111 + res(x,y,zd,v) = (val1 - val0)/2; 1.26112 + } 1.26113 + } 1.26114 + } else return *this; 1.26115 + } break; 1.26116 + default : 1.26117 + throw CImgArgumentException("CImg<%s>::haar() : Invalid axis '%c', must be 'x','y' or 'z'.", 1.26118 + pixel_type(),axis); 1.26119 + } 1.26120 + } else { // Multi-scale version 1.26121 + if (invert) { 1.26122 + res.assign(*this); 1.26123 + switch (cimg::uncase(axis)) { 1.26124 + case 'x' : { 1.26125 + unsigned int w = width; 1.26126 + for (unsigned int s=1; w && s<nb_scales; ++s) w/=2; 1.26127 + for (w=w?w:1; w<=width; w*=2) res.draw_image(res.get_crop(0,w-1).get_haar('x',true,1)); 1.26128 + } break; 1.26129 + case 'y' : { 1.26130 + unsigned int h = width; 1.26131 + for (unsigned int s=1; h && s<nb_scales; ++s) h/=2; 1.26132 + for (h=h?h:1; h<=height; h*=2) res.draw_image(res.get_crop(0,0,width-1,h-1).get_haar('y',true,1)); 1.26133 + } break; 1.26134 + case 'z' : { 1.26135 + unsigned int d = depth; 1.26136 + for (unsigned int s=1; d && s<nb_scales; ++s) d/=2; 1.26137 + for (d=d?d:1; d<=depth; d*=2) res.draw_image(res.get_crop(0,0,0,width-1,height-1,d-1).get_haar('z',true,1)); 1.26138 + } break; 1.26139 + default : 1.26140 + throw CImgArgumentException("CImg<%s>::haar() : Invalid axis '%c', must be 'x','y' or 'z'.", 1.26141 + pixel_type(),axis); 1.26142 + } 1.26143 + } else { // Direct transform 1.26144 + res = get_haar(axis,false,1); 1.26145 + switch (cimg::uncase(axis)) { 1.26146 + case 'x' : { 1.26147 + for (unsigned int s=1, w=width/2; w && s<nb_scales; ++s, w/=2) res.draw_image(res.get_crop(0,w-1).get_haar('x',false,1)); 1.26148 + } break; 1.26149 + case 'y' : { 1.26150 + for (unsigned int s=1, h=height/2; h && s<nb_scales; ++s, h/=2) res.draw_image(res.get_crop(0,0,width-1,h-1).get_haar('y',false,1)); 1.26151 + } break; 1.26152 + case 'z' : { 1.26153 + for (unsigned int s=1, d=depth/2; d && s<nb_scales; ++s, d/=2) res.draw_image(res.get_crop(0,0,0,width-1,height-1,d-1).get_haar('z',false,1)); 1.26154 + } break; 1.26155 + default : 1.26156 + throw CImgArgumentException("CImg<%s>::haar() : Invalid axis '%c', must be 'x','y' or 'z'.", 1.26157 + pixel_type(),axis); 1.26158 + } 1.26159 + } 1.26160 + } 1.26161 + return res; 1.26162 + } 1.26163 + 1.26164 + //! Compute the Haar multiscale wavelet transform. 1.26165 + /** 1.26166 + \param invert Set inverse of direct transform. 1.26167 + \param nb_scales Number of scales used for the transform. 1.26168 + **/ 1.26169 + CImg<T>& haar(const bool invert=false, const unsigned int nb_scales=1) { 1.26170 + return get_haar(invert,nb_scales).transfer_to(*this); 1.26171 + } 1.26172 + 1.26173 + CImg<Tfloat> get_haar(const bool invert=false, const unsigned int nb_scales=1) const { 1.26174 + CImg<Tfloat> res; 1.26175 + 1.26176 + if (nb_scales==1) { // Single scale transform 1.26177 + if (width>1) get_haar('x',invert,1).transfer_to(res); 1.26178 + if (height>1) { if (res) res.get_haar('y',invert,1).transfer_to(res); else get_haar('y',invert,1).transfer_to(res); } 1.26179 + if (depth>1) { if (res) res.get_haar('z',invert,1).transfer_to(res); else get_haar('z',invert,1).transfer_to(res); } 1.26180 + if (res) return res; 1.26181 + } else { // Multi-scale transform 1.26182 + if (invert) { // Inverse transform 1.26183 + res.assign(*this); 1.26184 + if (width>1) { 1.26185 + if (height>1) { 1.26186 + if (depth>1) { 1.26187 + unsigned int w = width, h = height, d = depth; for (unsigned int s=1; w && h && d && s<nb_scales; ++s) { w/=2; h/=2; d/=2; } 1.26188 + for (w=w?w:1, h=h?h:1, d=d?d:1; w<=width && h<=height && d<=depth; w*=2, h*=2, d*=2) 1.26189 + res.draw_image(res.get_crop(0,0,0,w-1,h-1,d-1).get_haar(true,1)); 1.26190 + } else { 1.26191 + unsigned int w = width, h = height; for (unsigned int s=1; w && h && s<nb_scales; ++s) { w/=2; h/=2; } 1.26192 + for (w=w?w:1, h=h?h:1; w<=width && h<=height; w*=2, h*=2) 1.26193 + res.draw_image(res.get_crop(0,0,0,w-1,h-1,0).get_haar(true,1)); 1.26194 + } 1.26195 + } else { 1.26196 + if (depth>1) { 1.26197 + unsigned int w = width, d = depth; for (unsigned int s=1; w && d && s<nb_scales; ++s) { w/=2; d/=2; } 1.26198 + for (w=w?w:1, d=d?d:1; w<=width && d<=depth; w*=2, d*=2) 1.26199 + res.draw_image(res.get_crop(0,0,0,w-1,0,d-1).get_haar(true,1)); 1.26200 + } else { 1.26201 + unsigned int w = width; for (unsigned int s=1; w && s<nb_scales; ++s) w/=2; 1.26202 + for (w=w?w:1; w<=width; w*=2) 1.26203 + res.draw_image(res.get_crop(0,0,0,w-1,0,0).get_haar(true,1)); 1.26204 + } 1.26205 + } 1.26206 + } else { 1.26207 + if (height>1) { 1.26208 + if (depth>1) { 1.26209 + unsigned int h = height, d = depth; for (unsigned int s=1; h && d && s<nb_scales; ++s) { h/=2; d/=2; } 1.26210 + for (h=h?h:1, d=d?d:1; h<=height && d<=depth; h*=2, d*=2) 1.26211 + res.draw_image(res.get_crop(0,0,0,0,h-1,d-1).get_haar(true,1)); 1.26212 + } else { 1.26213 + unsigned int h = height; for (unsigned int s=1; h && s<nb_scales; ++s) h/=2; 1.26214 + for (h=h?h:1; h<=height; h*=2) 1.26215 + res.draw_image(res.get_crop(0,0,0,0,h-1,0).get_haar(true,1)); 1.26216 + } 1.26217 + } else { 1.26218 + if (depth>1) { 1.26219 + unsigned int d = depth; for (unsigned int s=1; d && s<nb_scales; ++s) d/=2; 1.26220 + for (d=d?d:1; d<=depth; d*=2) 1.26221 + res.draw_image(res.get_crop(0,0,0,0,0,d-1).get_haar(true,1)); 1.26222 + } else return *this; 1.26223 + } 1.26224 + } 1.26225 + } else { // Direct transform 1.26226 + res = get_haar(false,1); 1.26227 + if (width>1) { 1.26228 + if (height>1) { 1.26229 + if (depth>1) for (unsigned int s=1, w=width/2, h=height/2, d=depth/2; w && h && d && s<nb_scales; ++s, w/=2, h/=2, d/=2) 1.26230 + res.draw_image(res.get_crop(0,0,0,w-1,h-1,d-1).haar(false,1)); 1.26231 + else for (unsigned int s=1, w=width/2, h=height/2; w && h && s<nb_scales; ++s, w/=2, h/=2) 1.26232 + res.draw_image(res.get_crop(0,0,0,w-1,h-1,0).haar(false,1)); 1.26233 + } else { 1.26234 + if (depth>1) for (unsigned int s=1, w=width/2, d=depth/2; w && d && s<nb_scales; ++s, w/=2, d/=2) 1.26235 + res.draw_image(res.get_crop(0,0,0,w-1,0,d-1).haar(false,1)); 1.26236 + else for (unsigned int s=1, w=width/2; w && s<nb_scales; ++s, w/=2) 1.26237 + res.draw_image(res.get_crop(0,0,0,w-1,0,0).haar(false,1)); 1.26238 + } 1.26239 + } else { 1.26240 + if (height>1) { 1.26241 + if (depth>1) for (unsigned int s=1, h=height/2, d=depth/2; h && d && s<nb_scales; ++s, h/=2, d/=2) 1.26242 + res.draw_image(res.get_crop(0,0,0,0,h-1,d-1).haar(false,1)); 1.26243 + else for (unsigned int s=1, h=height/2; h && s<nb_scales; ++s, h/=2) 1.26244 + res.draw_image(res.get_crop(0,0,0,0,h-1,0).haar(false,1)); 1.26245 + } else { 1.26246 + if (depth>1) for (unsigned int s=1, d=depth/2; d && s<nb_scales; ++s, d/=2) 1.26247 + res.draw_image(res.get_crop(0,0,0,0,0,d-1).haar(false,1)); 1.26248 + else return *this; 1.26249 + } 1.26250 + } 1.26251 + } 1.26252 + return res; 1.26253 + } 1.26254 + return *this; 1.26255 + } 1.26256 + 1.26257 + //! Estimate a displacement field between instance image and given target image. 1.26258 + CImg<T>& displacement_field(const CImg<T>& target, const float smooth=0.1f, const float precision=0.1f, 1.26259 + const unsigned int nb_scales=0, const unsigned int itermax=10000) { 1.26260 + return get_displacement_field(target,smooth,precision,nb_scales,itermax).transfer_to(*this); 1.26261 + } 1.26262 + 1.26263 + CImg<Tfloat> get_displacement_field(const CImg<T>& target, 1.26264 + const float smoothness=0.1f, const float precision=0.1f, 1.26265 + const unsigned int nb_scales=0, const unsigned int itermax=10000) const { 1.26266 + if (is_empty() || !target) return *this; 1.26267 + if (!is_sameXYZV(target)) 1.26268 + throw CImgArgumentException("CImg<%s>::displacement_field() : Instance image (%u,%u,%u,%u,%p) and target image (%u,%u,%u,%u,%p) " 1.26269 + "have different size.", 1.26270 + pixel_type(),width,height,depth,dim,data, 1.26271 + target.width,target.height,target.depth,target.dim,target.data); 1.26272 + if (smoothness<0) 1.26273 + throw CImgArgumentException("CImg<%s>::displacement_field() : Smoothness parameter %g is negative.", 1.26274 + pixel_type(),smoothness); 1.26275 + if (precision<0) 1.26276 + throw CImgArgumentException("CImg<%s>::displacement_field() : Precision parameter %g is negative.", 1.26277 + pixel_type(),precision); 1.26278 + 1.26279 + const unsigned int nscales = nb_scales>0?nb_scales:(unsigned int)(2*cimg_std::log((double)(cimg::max(width,height,depth)))); 1.26280 + Tfloat m1, M1 = (Tfloat)maxmin(m1), m2, M2 = (Tfloat)target.maxmin(m2); 1.26281 + const Tfloat factor = cimg::max(cimg::abs(m1),cimg::abs(M1),cimg::abs(m2),cimg::abs(M2)); 1.26282 + CImg<Tfloat> U0; 1.26283 + const bool threed = (depth>1); 1.26284 + 1.26285 + // Begin multi-scale motion estimation 1.26286 + for (int scale = (int)nscales-1; scale>=0; --scale) { 1.26287 + const float sfactor = (float)cimg_std::pow(1.5f,(float)scale), sprecision = (float)(precision/cimg_std::pow(2.25,1+scale)); 1.26288 + const int 1.26289 + sw = (int)(width/sfactor), sh = (int)(height/sfactor), sd = (int)(depth/sfactor), 1.26290 + swidth = sw?sw:1, sheight = sh?sh:1, sdepth = sd?sd:1; 1.26291 + CImg<Tfloat> 1.26292 + I1 = get_resize(swidth,sheight,sdepth,-100,2), 1.26293 + I2 = target.get_resize(swidth,sheight,sdepth,-100,2); 1.26294 + I1/=factor; I2/=factor; 1.26295 + CImg<Tfloat> U; 1.26296 + if (U0) U = (U0*=1.5f).get_resize(I1.dimx(),I1.dimy(),I1.dimz(),-100,3); 1.26297 + else U.assign(I1.dimx(),I1.dimy(),I1.dimz(),threed?3:2,0); 1.26298 + 1.26299 + // Begin single-scale motion estimation 1.26300 + CImg<Tfloat> veloc(U); 1.26301 + float dt = 2, Energy = cimg::type<float>::max(); 1.26302 + const CImgList<Tfloat> dI = I2.get_gradient(); 1.26303 + for (unsigned int iter=0; iter<itermax; iter++) { 1.26304 + veloc.fill(0); 1.26305 + float nEnergy = 0; 1.26306 + if (threed) { 1.26307 + cimg_for3XYZ(U,x,y,z) { 1.26308 + const float X = (float)(x + U(x,y,z,0)), Y = (float)(y + U(x,y,z,1)), Z = (float)(z + U(x,y,z,2)); 1.26309 + cimg_forV(U,k) { 1.26310 + const Tfloat 1.26311 + Ux = 0.5f*(U(_n1x,y,z,k) - U(_p1x,y,z,k)), 1.26312 + Uy = 0.5f*(U(x,_n1y,z,k) - U(x,_p1y,z,k)), 1.26313 + Uz = 0.5f*(U(x,y,_n1z,k) - U(x,y,_p1z,k)), 1.26314 + Uxx = U(_n1x,y,z,k) + U(_p1x,y,z,k) - 2*U(x,y,z,k), 1.26315 + Uyy = U(x,_n1y,z,k) + U(x,_p1y,z,k) - 2*U(x,y,z,k), 1.26316 + Uzz = U(x,y,_n1z,k) + U(x,y,_n1z,k) - 2*U(x,y,z,k); 1.26317 + nEnergy += (float)(smoothness*(Ux*Ux + Uy*Uy + Uz*Uz)); 1.26318 + Tfloat deltaIgrad = 0; 1.26319 + cimg_forV(I1,i) { 1.26320 + const Tfloat deltaIi = (float)(I2._linear_atXYZ(X,Y,Z,i) - I1(x,y,z,i)); 1.26321 + nEnergy += (float)(deltaIi*deltaIi/2); 1.26322 + deltaIgrad+=-deltaIi*dI[k]._linear_atXYZ(X,Y,Z,i); 1.26323 + } 1.26324 + veloc(x,y,z,k) = deltaIgrad + smoothness*(Uxx + Uyy + Uzz); 1.26325 + } 1.26326 + } 1.26327 + } else { 1.26328 + cimg_for3XY(U,x,y) { 1.26329 + const float X = (float)(x + U(x,y,0)), Y = (float)(y + U(x,y,1)); 1.26330 + cimg_forV(U,k) { 1.26331 + const Tfloat 1.26332 + Ux = 0.5f*(U(_n1x,y,k) - U(_p1x,y,k)), 1.26333 + Uy = 0.5f*(U(x,_n1y,k) - U(x,_p1y,k)), 1.26334 + Uxx = U(_n1x,y,k) + U(_p1x,y,k) - 2*U(x,y,k), 1.26335 + Uyy = U(x,_n1y,k) + U(x,_p1y,k) - 2*U(x,y,k); 1.26336 + nEnergy += (float)(smoothness*(Ux*Ux + Uy*Uy)); 1.26337 + Tfloat deltaIgrad = 0; 1.26338 + cimg_forV(I1,i) { 1.26339 + const Tfloat deltaIi = (float)(I2._linear_atXY(X,Y,i) - I1(x,y,i)); 1.26340 + nEnergy += (float)(deltaIi*deltaIi/2); 1.26341 + deltaIgrad+=-deltaIi*dI[k]._linear_atXY(X,Y,i); 1.26342 + } 1.26343 + veloc(x,y,k) = deltaIgrad + smoothness*(Uxx + Uyy); 1.26344 + } 1.26345 + } 1.26346 + } 1.26347 + const Tfloat vmax = cimg::max(cimg::abs(veloc.min()), cimg::abs(veloc.max())); 1.26348 + U+=(veloc*=dt/vmax); 1.26349 + if (cimg::abs(nEnergy-Energy)<sprecision) break; 1.26350 + if (nEnergy<Energy) dt*=0.5f; 1.26351 + Energy = nEnergy; 1.26352 + } 1.26353 + U.transfer_to(U0); 1.26354 + } 1.26355 + return U0; 1.26356 + } 1.26357 + 1.26358 + //@} 1.26359 + //----------------------------- 1.26360 + // 1.26361 + //! \name Matrix and Vectors 1.26362 + //@{ 1.26363 + //----------------------------- 1.26364 + 1.26365 + //! Return a vector with specified coefficients. 1.26366 + static CImg<T> vector(const T& a0) { 1.26367 + static CImg<T> r(1,1); r[0] = a0; 1.26368 + return r; 1.26369 + } 1.26370 + 1.26371 + //! Return a vector with specified coefficients. 1.26372 + static CImg<T> vector(const T& a0, const T& a1) { 1.26373 + static CImg<T> r(1,2); T *ptr = r.data; 1.26374 + *(ptr++) = a0; *(ptr++) = a1; 1.26375 + return r; 1.26376 + } 1.26377 + 1.26378 + //! Return a vector with specified coefficients. 1.26379 + static CImg<T> vector(const T& a0, const T& a1, const T& a2) { 1.26380 + static CImg<T> r(1,3); T *ptr = r.data; 1.26381 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; 1.26382 + return r; 1.26383 + } 1.26384 + 1.26385 + //! Return a vector with specified coefficients. 1.26386 + static CImg<T> vector(const T& a0, const T& a1, const T& a2, const T& a3) { 1.26387 + static CImg<T> r(1,4); T *ptr = r.data; 1.26388 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; 1.26389 + return r; 1.26390 + } 1.26391 + 1.26392 + //! Return a vector with specified coefficients. 1.26393 + static CImg<T> vector(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4) { 1.26394 + static CImg<T> r(1,5); T *ptr = r.data; 1.26395 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; *(ptr++) = a4; 1.26396 + return r; 1.26397 + } 1.26398 + 1.26399 + //! Return a vector with specified coefficients. 1.26400 + static CImg<T> vector(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, const T& a5) { 1.26401 + static CImg<T> r(1,6); T *ptr = r.data; 1.26402 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; *(ptr++) = a4; *(ptr++) = a5; 1.26403 + return r; 1.26404 + } 1.26405 + 1.26406 + //! Return a vector with specified coefficients. 1.26407 + static CImg<T> vector(const T& a0, const T& a1, const T& a2, const T& a3, 1.26408 + const T& a4, const T& a5, const T& a6) { 1.26409 + static CImg<T> r(1,7); T *ptr = r.data; 1.26410 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; 1.26411 + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; 1.26412 + return r; 1.26413 + } 1.26414 + 1.26415 + //! Return a vector with specified coefficients. 1.26416 + static CImg<T> vector(const T& a0, const T& a1, const T& a2, const T& a3, 1.26417 + const T& a4, const T& a5, const T& a6, const T& a7) { 1.26418 + static CImg<T> r(1,8); T *ptr = r.data; 1.26419 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; 1.26420 + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; 1.26421 + return r; 1.26422 + } 1.26423 + 1.26424 + //! Return a vector with specified coefficients. 1.26425 + static CImg<T> vector(const T& a0, const T& a1, const T& a2, const T& a3, 1.26426 + const T& a4, const T& a5, const T& a6, const T& a7, 1.26427 + const T& a8) { 1.26428 + static CImg<T> r(1,9); T *ptr = r.data; 1.26429 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; 1.26430 + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; 1.26431 + *(ptr++) = a8; 1.26432 + return r; 1.26433 + } 1.26434 + 1.26435 + //! Return a vector with specified coefficients. 1.26436 + static CImg<T> vector(const T& a0, const T& a1, const T& a2, const T& a3, 1.26437 + const T& a4, const T& a5, const T& a6, const T& a7, 1.26438 + const T& a8, const T& a9) { 1.26439 + static CImg<T> r(1,10); T *ptr = r.data; 1.26440 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; 1.26441 + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; 1.26442 + *(ptr++) = a8; *(ptr++) = a9; 1.26443 + return r; 1.26444 + } 1.26445 + 1.26446 + //! Return a vector with specified coefficients. 1.26447 + static CImg<T> vector(const T& a0, const T& a1, const T& a2, const T& a3, 1.26448 + const T& a4, const T& a5, const T& a6, const T& a7, 1.26449 + const T& a8, const T& a9, const T& a10) { 1.26450 + static CImg<T> r(1,11); T *ptr = r.data; 1.26451 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; 1.26452 + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; 1.26453 + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; 1.26454 + return r; 1.26455 + } 1.26456 + 1.26457 + //! Return a vector with specified coefficients. 1.26458 + static CImg<T> vector(const T& a0, const T& a1, const T& a2, const T& a3, 1.26459 + const T& a4, const T& a5, const T& a6, const T& a7, 1.26460 + const T& a8, const T& a9, const T& a10, const T& a11) { 1.26461 + static CImg<T> r(1,12); T *ptr = r.data; 1.26462 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; 1.26463 + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; 1.26464 + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11; 1.26465 + return r; 1.26466 + } 1.26467 + 1.26468 + //! Return a vector with specified coefficients. 1.26469 + static CImg<T> vector(const T& a0, const T& a1, const T& a2, const T& a3, 1.26470 + const T& a4, const T& a5, const T& a6, const T& a7, 1.26471 + const T& a8, const T& a9, const T& a10, const T& a11, 1.26472 + const T& a12) { 1.26473 + static CImg<T> r(1,13); T *ptr = r.data; 1.26474 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; 1.26475 + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; 1.26476 + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11; 1.26477 + *(ptr++) = a12; 1.26478 + return r; 1.26479 + } 1.26480 + 1.26481 + //! Return a vector with specified coefficients. 1.26482 + static CImg<T> vector(const T& a0, const T& a1, const T& a2, const T& a3, 1.26483 + const T& a4, const T& a5, const T& a6, const T& a7, 1.26484 + const T& a8, const T& a9, const T& a10, const T& a11, 1.26485 + const T& a12, const T& a13) { 1.26486 + static CImg<T> r(1,14); T *ptr = r.data; 1.26487 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; 1.26488 + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; 1.26489 + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11; 1.26490 + *(ptr++) = a12; *(ptr++) = a13; 1.26491 + return r; 1.26492 + } 1.26493 + 1.26494 + //! Return a vector with specified coefficients. 1.26495 + static CImg<T> vector(const T& a0, const T& a1, const T& a2, const T& a3, 1.26496 + const T& a4, const T& a5, const T& a6, const T& a7, 1.26497 + const T& a8, const T& a9, const T& a10, const T& a11, 1.26498 + const T& a12, const T& a13, const T& a14) { 1.26499 + static CImg<T> r(1,15); T *ptr = r.data; 1.26500 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; 1.26501 + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; 1.26502 + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11; 1.26503 + *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14; 1.26504 + return r; 1.26505 + } 1.26506 + 1.26507 + //! Return a vector with specified coefficients. 1.26508 + static CImg<T> vector(const T& a0, const T& a1, const T& a2, const T& a3, 1.26509 + const T& a4, const T& a5, const T& a6, const T& a7, 1.26510 + const T& a8, const T& a9, const T& a10, const T& a11, 1.26511 + const T& a12, const T& a13, const T& a14, const T& a15) { 1.26512 + static CImg<T> r(1,16); T *ptr = r.data; 1.26513 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; 1.26514 + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; 1.26515 + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11; 1.26516 + *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14; *(ptr++) = a15; 1.26517 + return r; 1.26518 + } 1.26519 + 1.26520 + //! Return a 1x1 square matrix with specified coefficients. 1.26521 + static CImg<T> matrix(const T& a0) { 1.26522 + return vector(a0); 1.26523 + } 1.26524 + 1.26525 + //! Return a 2x2 square matrix with specified coefficients. 1.26526 + static CImg<T> matrix(const T& a0, const T& a1, 1.26527 + const T& a2, const T& a3) { 1.26528 + static CImg<T> r(2,2); T *ptr = r.data; 1.26529 + *(ptr++) = a0; *(ptr++) = a1; 1.26530 + *(ptr++) = a2; *(ptr++) = a3; 1.26531 + return r; 1.26532 + } 1.26533 + 1.26534 + //! Return a 3x3 square matrix with specified coefficients. 1.26535 + static CImg<T> matrix(const T& a0, const T& a1, const T& a2, 1.26536 + const T& a3, const T& a4, const T& a5, 1.26537 + const T& a6, const T& a7, const T& a8) { 1.26538 + static CImg<T> r(3,3); T *ptr = r.data; 1.26539 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; 1.26540 + *(ptr++) = a3; *(ptr++) = a4; *(ptr++) = a5; 1.26541 + *(ptr++) = a6; *(ptr++) = a7; *(ptr++) = a8; 1.26542 + return r; 1.26543 + } 1.26544 + 1.26545 + //! Return a 4x4 square matrix with specified coefficients. 1.26546 + static CImg<T> matrix(const T& a0, const T& a1, const T& a2, const T& a3, 1.26547 + const T& a4, const T& a5, const T& a6, const T& a7, 1.26548 + const T& a8, const T& a9, const T& a10, const T& a11, 1.26549 + const T& a12, const T& a13, const T& a14, const T& a15) { 1.26550 + static CImg<T> r(4,4); T *ptr = r.data; 1.26551 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; 1.26552 + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; 1.26553 + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11; 1.26554 + *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14; *(ptr++) = a15; 1.26555 + return r; 1.26556 + } 1.26557 + 1.26558 + //! Return a 5x5 square matrix with specified coefficients. 1.26559 + static CImg<T> matrix(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, 1.26560 + const T& a5, const T& a6, const T& a7, const T& a8, const T& a9, 1.26561 + const T& a10, const T& a11, const T& a12, const T& a13, const T& a14, 1.26562 + const T& a15, const T& a16, const T& a17, const T& a18, const T& a19, 1.26563 + const T& a20, const T& a21, const T& a22, const T& a23, const T& a24) { 1.26564 + static CImg<T> r(5,5); T *ptr = r.data; 1.26565 + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; *(ptr++) = a4; 1.26566 + *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; *(ptr++) = a8; *(ptr++) = a9; 1.26567 + *(ptr++) = a10; *(ptr++) = a11; *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14; 1.26568 + *(ptr++) = a15; *(ptr++) = a16; *(ptr++) = a17; *(ptr++) = a18; *(ptr++) = a19; 1.26569 + *(ptr++) = a20; *(ptr++) = a21; *(ptr++) = a22; *(ptr++) = a23; *(ptr++) = a24; 1.26570 + return r; 1.26571 + } 1.26572 + 1.26573 + //! Return a 1x1 symmetric matrix with specified coefficients. 1.26574 + static CImg<T> tensor(const T& a1) { 1.26575 + return matrix(a1); 1.26576 + } 1.26577 + 1.26578 + //! Return a 2x2 symmetric matrix tensor with specified coefficients. 1.26579 + static CImg<T> tensor(const T& a1, const T& a2, const T& a3) { 1.26580 + return matrix(a1,a2,a2,a3); 1.26581 + } 1.26582 + 1.26583 + //! Return a 3x3 symmetric matrix with specified coefficients. 1.26584 + static CImg<T> tensor(const T& a1, const T& a2, const T& a3, const T& a4, const T& a5, const T& a6) { 1.26585 + return matrix(a1,a2,a3,a2,a4,a5,a3,a5,a6); 1.26586 + } 1.26587 + 1.26588 + //! Return a 1x1 diagonal matrix with specified coefficients. 1.26589 + static CImg<T> diagonal(const T& a0) { 1.26590 + return matrix(a0); 1.26591 + } 1.26592 + 1.26593 + //! Return a 2x2 diagonal matrix with specified coefficients. 1.26594 + static CImg<T> diagonal(const T& a0, const T& a1) { 1.26595 + return matrix(a0,0,0,a1); 1.26596 + } 1.26597 + 1.26598 + //! Return a 3x3 diagonal matrix with specified coefficients. 1.26599 + static CImg<T> diagonal(const T& a0, const T& a1, const T& a2) { 1.26600 + return matrix(a0,0,0,0,a1,0,0,0,a2); 1.26601 + } 1.26602 + 1.26603 + //! Return a 4x4 diagonal matrix with specified coefficients. 1.26604 + static CImg<T> diagonal(const T& a0, const T& a1, const T& a2, const T& a3) { 1.26605 + return matrix(a0,0,0,0,0,a1,0,0,0,0,a2,0,0,0,0,a3); 1.26606 + } 1.26607 + 1.26608 + //! Return a 5x5 diagonal matrix with specified coefficients. 1.26609 + static CImg<T> diagonal(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4) { 1.26610 + 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); 1.26611 + } 1.26612 + 1.26613 + //! Return a NxN identity matrix. 1.26614 + static CImg<T> identity_matrix(const unsigned int N) { 1.26615 + CImg<T> res(N,N,1,1,0); 1.26616 + cimg_forX(res,x) res(x,x) = 1; 1.26617 + return res; 1.26618 + } 1.26619 + 1.26620 + //! Return a N-numbered sequence vector from \p a0 to \p a1. 1.26621 + static CImg<T> sequence(const unsigned int N, const T a0, const T a1) { 1.26622 + if (N) return CImg<T>(1,N).sequence(a0,a1); 1.26623 + return CImg<T>(); 1.26624 + } 1.26625 + 1.26626 + //! Return a 3x3 rotation matrix along the (x,y,z)-axis with an angle w. 1.26627 + static CImg<T> rotation_matrix(const float x, const float y, const float z, const float w, const bool quaternion_data=false) { 1.26628 + float X,Y,Z,W; 1.26629 + if (!quaternion_data) { 1.26630 + const float norm = (float)cimg_std::sqrt(x*x + y*y + z*z), 1.26631 + nx = norm>0?x/norm:0, 1.26632 + ny = norm>0?y/norm:0, 1.26633 + nz = norm>0?z/norm:1, 1.26634 + nw = norm>0?w:0, 1.26635 + sina = (float)cimg_std::sin(nw/2), 1.26636 + cosa = (float)cimg_std::cos(nw/2); 1.26637 + X = nx*sina; 1.26638 + Y = ny*sina; 1.26639 + Z = nz*sina; 1.26640 + W = cosa; 1.26641 + } else { 1.26642 + const float norm = (float)cimg_std::sqrt(x*x + y*y + z*z + w*w); 1.26643 + if (norm>0) { X = x/norm; Y = y/norm; Z = z/norm; W = w/norm; } 1.26644 + else { X = Y = Z = 0; W = 1; } 1.26645 + } 1.26646 + const float xx = X*X, xy = X*Y, xz = X*Z, xw = X*W, yy = Y*Y, yz = Y*Z, yw = Y*W, zz = Z*Z, zw = Z*W; 1.26647 + return CImg<T>::matrix((T)(1-2*(yy+zz)), (T)(2*(xy+zw)), (T)(2*(xz-yw)), 1.26648 + (T)(2*(xy-zw)), (T)(1-2*(xx+zz)), (T)(2*(yz+xw)), 1.26649 + (T)(2*(xz+yw)), (T)(2*(yz-xw)), (T)(1-2*(xx+yy))); 1.26650 + } 1.26651 + 1.26652 + //! Return a new image corresponding to the vector located at (\p x,\p y,\p z) of the current vector-valued image. 1.26653 + CImg<T> get_vector_at(const unsigned int x, const unsigned int y=0, const unsigned int z=0) const { 1.26654 + static CImg<T> dest; 1.26655 + if (dest.height!=dim) dest.assign(1,dim); 1.26656 + const unsigned int whz = width*height*depth; 1.26657 + const T *ptrs = ptr(x,y,z); 1.26658 + T *ptrd = dest.data; 1.26659 + cimg_forV(*this,k) { *(ptrd++) = *ptrs; ptrs+=whz; } 1.26660 + return dest; 1.26661 + } 1.26662 + 1.26663 + //! Set the image \p vec as the \a vector \a valued pixel located at (\p x,\p y,\p z) of the current vector-valued image. 1.26664 + template<typename t> 1.26665 + CImg<T>& set_vector_at(const CImg<t>& vec, const unsigned int x, const unsigned int y=0, const unsigned int z=0) { 1.26666 + if (x<width && y<height && z<depth) { 1.26667 + const unsigned int whz = width*height*depth; 1.26668 + const t *ptrs = vec.data; 1.26669 + T *ptrd = ptr(x,y,z); 1.26670 + for (unsigned int k=cimg::min((unsigned int)vec.size(),dim); k; --k) { *ptrd = (T)*(ptrs++); ptrd+=whz; } 1.26671 + } 1.26672 + return *this; 1.26673 + } 1.26674 + 1.26675 + //! Return a new image corresponding to the \a square \a matrix located at (\p x,\p y,\p z) of the current vector-valued image. 1.26676 + CImg<T> get_matrix_at(const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) const { 1.26677 + const int n = (int)cimg_std::sqrt((double)dim); 1.26678 + CImg<T> dest(n,n); 1.26679 + cimg_forV(*this,k) dest[k]=(*this)(x,y,z,k); 1.26680 + return dest; 1.26681 + } 1.26682 + 1.26683 + //! Set the image \p vec as the \a square \a matrix-valued pixel located at (\p x,\p y,\p z) of the current vector-valued image. 1.26684 + template<typename t> 1.26685 + CImg<T>& set_matrix_at(const CImg<t>& mat, const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) { 1.26686 + return set_vector_at(mat,x,y,z); 1.26687 + } 1.26688 + 1.26689 + //! Return a new image corresponding to the \a diffusion \a tensor located at (\p x,\p y,\p z) of the current vector-valued image. 1.26690 + CImg<T> get_tensor_at(const unsigned int x, const unsigned int y=0, const unsigned int z=0) const { 1.26691 + if (dim==6) return tensor((*this)(x,y,z,0),(*this)(x,y,z,1),(*this)(x,y,z,2), 1.26692 + (*this)(x,y,z,3),(*this)(x,y,z,4),(*this)(x,y,z,5)); 1.26693 + if (dim==3) return tensor((*this)(x,y,z,0),(*this)(x,y,z,1),(*this)(x,y,z,2)); 1.26694 + return tensor((*this)(x,y,z,0)); 1.26695 + } 1.26696 + 1.26697 + //! Set the image \p vec as the \a tensor \a valued pixel located at (\p x,\p y,\p z) of the current vector-valued image. 1.26698 + template<typename t> 1.26699 + CImg<T>& set_tensor_at(const CImg<t>& ten, const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) { 1.26700 + if (ten.height==2) { 1.26701 + (*this)(x,y,z,0) = (T)ten[0]; 1.26702 + (*this)(x,y,z,1) = (T)ten[1]; 1.26703 + (*this)(x,y,z,2) = (T)ten[3]; 1.26704 + } 1.26705 + else { 1.26706 + (*this)(x,y,z,0) = (T)ten[0]; 1.26707 + (*this)(x,y,z,1) = (T)ten[1]; 1.26708 + (*this)(x,y,z,2) = (T)ten[2]; 1.26709 + (*this)(x,y,z,3) = (T)ten[4]; 1.26710 + (*this)(x,y,z,4) = (T)ten[5]; 1.26711 + (*this)(x,y,z,5) = (T)ten[8]; 1.26712 + } 1.26713 + return *this; 1.26714 + } 1.26715 + 1.26716 + //! Unroll all images values into a one-column vector. 1.26717 + CImg<T>& vector() { 1.26718 + return unroll('y'); 1.26719 + } 1.26720 + 1.26721 + CImg<T> get_vector() const { 1.26722 + return get_unroll('y'); 1.26723 + } 1.26724 + 1.26725 + //! Realign pixel values of the instance image as a square matrix 1.26726 + CImg<T>& matrix() { 1.26727 + const unsigned int siz = size(); 1.26728 + switch (siz) { 1.26729 + case 1 : break; 1.26730 + case 4 : width = height = 2; break; 1.26731 + case 9 : width = height = 3; break; 1.26732 + case 16 : width = height = 4; break; 1.26733 + case 25 : width = height = 5; break; 1.26734 + case 36 : width = height = 6; break; 1.26735 + case 49 : width = height = 7; break; 1.26736 + case 64 : width = height = 8; break; 1.26737 + case 81 : width = height = 9; break; 1.26738 + case 100 : width = height = 10; break; 1.26739 + default : { 1.26740 + unsigned int i = 11, i2 = i*i; 1.26741 + while (i2<siz) { i2+=2*i+1; ++i; } 1.26742 + if (i2==siz) width = height = i; 1.26743 + else throw CImgInstanceException("CImg<%s>::matrix() : Image size = %u is not a square number", 1.26744 + pixel_type(),siz); 1.26745 + } 1.26746 + } 1.26747 + return *this; 1.26748 + } 1.26749 + 1.26750 + CImg<T> get_matrix() const { 1.26751 + return (+*this).matrix(); 1.26752 + } 1.26753 + 1.26754 + //! Realign pixel values of the instance image as a symmetric tensor. 1.26755 + CImg<T>& tensor() { 1.26756 + return get_tensor().transfer_to(*this); 1.26757 + } 1.26758 + 1.26759 + CImg<T> get_tensor() const { 1.26760 + CImg<T> res; 1.26761 + const unsigned int siz = size(); 1.26762 + switch (siz) { 1.26763 + case 1 : break; 1.26764 + case 3 : 1.26765 + res.assign(2,2); 1.26766 + res(0,0) = (*this)(0); 1.26767 + res(1,0) = res(0,1) = (*this)(1); 1.26768 + res(1,1) = (*this)(2); 1.26769 + break; 1.26770 + case 6 : 1.26771 + res.assign(3,3); 1.26772 + res(0,0) = (*this)(0); 1.26773 + res(1,0) = res(0,1) = (*this)(1); 1.26774 + res(2,0) = res(0,2) = (*this)(2); 1.26775 + res(1,1) = (*this)(3); 1.26776 + res(2,1) = res(1,2) = (*this)(4); 1.26777 + res(2,2) = (*this)(5); 1.26778 + break; 1.26779 + default : 1.26780 + throw CImgInstanceException("CImg<%s>::tensor() : Wrong vector dimension = %u in instance image.", 1.26781 + pixel_type(), dim); 1.26782 + } 1.26783 + return res; 1.26784 + } 1.26785 + 1.26786 + //! Unroll all images values into specified axis. 1.26787 + CImg<T>& unroll(const char axis) { 1.26788 + const unsigned int siz = size(); 1.26789 + if (siz) switch (axis) { 1.26790 + case 'x' : width = siz; height=depth=dim=1; break; 1.26791 + case 'y' : height = siz; width=depth=dim=1; break; 1.26792 + case 'z' : depth = siz; width=height=dim=1; break; 1.26793 + case 'v' : dim = siz; width=height=depth=1; break; 1.26794 + default : 1.26795 + throw CImgArgumentException("CImg<%s>::unroll() : Given axis is '%c' which is not 'x','y','z' or 'v'", 1.26796 + pixel_type(),axis); 1.26797 + } 1.26798 + return *this; 1.26799 + } 1.26800 + 1.26801 + CImg<T> get_unroll(const char axis) const { 1.26802 + return (+*this).unroll(axis); 1.26803 + } 1.26804 + 1.26805 + //! Get a diagonal matrix, whose diagonal coefficients are the coefficients of the input image. 1.26806 + CImg<T>& diagonal() { 1.26807 + return get_diagonal().transfer_to(*this); 1.26808 + } 1.26809 + 1.26810 + CImg<T> get_diagonal() const { 1.26811 + if (is_empty()) return *this; 1.26812 + CImg<T> res(size(),size(),1,1,0); 1.26813 + cimg_foroff(*this,off) res(off,off) = (*this)(off); 1.26814 + return res; 1.26815 + } 1.26816 + 1.26817 + //! Get an identity matrix having same dimension than instance image. 1.26818 + CImg<T>& identity_matrix() { 1.26819 + return identity_matrix(cimg::max(width,height)).transfer_to(*this); 1.26820 + } 1.26821 + 1.26822 + CImg<T> get_identity_matrix() const { 1.26823 + return identity_matrix(cimg::max(width,height)); 1.26824 + } 1.26825 + 1.26826 + //! Return a N-numbered sequence vector from \p a0 to \p a1. 1.26827 + CImg<T>& sequence(const T a0, const T a1) { 1.26828 + if (is_empty()) return *this; 1.26829 + const unsigned int siz = size() - 1; 1.26830 + T* ptr = data; 1.26831 + if (siz) { 1.26832 + const Tfloat delta = (Tfloat)a1 - a0; 1.26833 + cimg_foroff(*this,l) *(ptr++) = (T)(a0 + delta*l/siz); 1.26834 + } else *ptr = a0; 1.26835 + return *this; 1.26836 + } 1.26837 + 1.26838 + CImg<T> get_sequence(const T a0, const T a1) const { 1.26839 + return (+*this).sequence(a0,a1); 1.26840 + } 1.26841 + 1.26842 + //! Transpose the current matrix. 1.26843 + CImg<T>& transpose() { 1.26844 + if (width==1) { width=height; height=1; return *this; } 1.26845 + if (height==1) { height=width; width=1; return *this; } 1.26846 + if (width==height) { 1.26847 + cimg_forYZV(*this,y,z,v) for (int x=y; x<dimx(); ++x) cimg::swap((*this)(x,y,z,v),(*this)(y,x,z,v)); 1.26848 + return *this; 1.26849 + } 1.26850 + return get_transpose().transfer_to(*this); 1.26851 + } 1.26852 + 1.26853 + CImg<T> get_transpose() const { 1.26854 + return get_permute_axes("yxzv"); 1.26855 + } 1.26856 + 1.26857 + //! Invert the current matrix. 1.26858 + CImg<T>& invert(const bool use_LU=true) { 1.26859 + if (!is_empty()) { 1.26860 + if (width!=height || depth!=1 || dim!=1) 1.26861 + throw CImgInstanceException("CImg<%s>::invert() : Instance matrix (%u,%u,%u,%u,%p) is not square.", 1.26862 + pixel_type(),width,height,depth,dim,data); 1.26863 +#ifdef cimg_use_lapack 1.26864 + int INFO = (int)use_LU, N = width, LWORK = 4*N, *IPIV = new int[N]; 1.26865 + Tfloat 1.26866 + *lapA = new Tfloat[N*N], 1.26867 + *WORK = new Tfloat[LWORK]; 1.26868 + cimg_forXY(*this,k,l) lapA[k*N+l] = (Tfloat)((*this)(k,l)); 1.26869 + cimg::getrf(N,lapA,IPIV,INFO); 1.26870 + if (INFO) 1.26871 + cimg::warn("CImg<%s>::invert() : LAPACK library function dgetrf_() returned error code %d.", 1.26872 + pixel_type(),INFO); 1.26873 + else { 1.26874 + cimg::getri(N,lapA,IPIV,WORK,LWORK,INFO); 1.26875 + if (INFO) 1.26876 + cimg::warn("CImg<%s>::invert() : LAPACK library function dgetri_() returned Error code %d", 1.26877 + pixel_type(),INFO); 1.26878 + } 1.26879 + if (!INFO) cimg_forXY(*this,k,l) (*this)(k,l) = (T)(lapA[k*N+l]); else fill(0); 1.26880 + delete[] IPIV; delete[] lapA; delete[] WORK; 1.26881 +#else 1.26882 + const double dete = width>3?-1.0:det(); 1.26883 + if (dete!=0.0 && width==2) { 1.26884 + const double 1.26885 + a = data[0], c = data[1], 1.26886 + b = data[2], d = data[3]; 1.26887 + data[0] = (T)(d/dete); data[1] = (T)(-c/dete); 1.26888 + data[2] = (T)(-b/dete); data[3] = (T)(a/dete); 1.26889 + } else if (dete!=0.0 && width==3) { 1.26890 + const double 1.26891 + a = data[0], d = data[1], g = data[2], 1.26892 + b = data[3], e = data[4], h = data[5], 1.26893 + c = data[6], f = data[7], i = data[8]; 1.26894 + data[0] = (T)((i*e-f*h)/dete), data[1] = (T)((g*f-i*d)/dete), data[2] = (T)((d*h-g*e)/dete); 1.26895 + data[3] = (T)((h*c-i*b)/dete), data[4] = (T)((i*a-c*g)/dete), data[5] = (T)((g*b-a*h)/dete); 1.26896 + data[6] = (T)((b*f-e*c)/dete), data[7] = (T)((d*c-a*f)/dete), data[8] = (T)((a*e-d*b)/dete); 1.26897 + } else { 1.26898 + if (use_LU) { // LU-based inverse computation 1.26899 + CImg<Tfloat> A(*this), indx, col(1,width); 1.26900 + bool d; 1.26901 + A._LU(indx,d); 1.26902 + cimg_forX(*this,j) { 1.26903 + col.fill(0); 1.26904 + col(j) = 1; 1.26905 + col._solve(A,indx); 1.26906 + cimg_forX(*this,i) (*this)(j,i) = (T)col(i); 1.26907 + } 1.26908 + } else { // SVD-based inverse computation 1.26909 + CImg<Tfloat> U(width,width), S(1,width), V(width,width); 1.26910 + SVD(U,S,V,false); 1.26911 + U.transpose(); 1.26912 + cimg_forY(S,k) if (S[k]!=0) S[k]=1/S[k]; 1.26913 + S.diagonal(); 1.26914 + *this = V*S*U; 1.26915 + } 1.26916 + } 1.26917 +#endif 1.26918 + } 1.26919 + return *this; 1.26920 + } 1.26921 + 1.26922 + CImg<Tfloat> get_invert(const bool use_LU=true) const { 1.26923 + return CImg<Tfloat>(*this,false).invert(use_LU); 1.26924 + } 1.26925 + 1.26926 + //! Compute the pseudo-inverse (Moore-Penrose) of the matrix. 1.26927 + CImg<T>& pseudoinvert() { 1.26928 + return get_pseudoinvert().transfer_to(*this); 1.26929 + } 1.26930 + 1.26931 + CImg<Tfloat> get_pseudoinvert() const { 1.26932 + CImg<Tfloat> U, S, V; 1.26933 + SVD(U,S,V); 1.26934 + cimg_forX(V,x) { 1.26935 + const Tfloat s = S(x), invs = s!=0?1/s:(Tfloat)0; 1.26936 + cimg_forY(V,y) V(x,y)*=invs; 1.26937 + } 1.26938 + return V*U.transpose(); 1.26939 + } 1.26940 + 1.26941 + //! Compute the cross product between two 3d vectors. 1.26942 + template<typename t> 1.26943 + CImg<T>& cross(const CImg<t>& img) { 1.26944 + if (width!=1 || height<3 || img.width!=1 || img.height<3) 1.26945 + throw CImgInstanceException("CImg<%s>::cross() : Arguments (%u,%u,%u,%u,%p) and (%u,%u,%u,%u,%p) must be both 3d vectors.", 1.26946 + pixel_type(),width,height,depth,dim,data,img.width,img.height,img.depth,img.dim,img.data); 1.26947 + const T x = (*this)[0], y = (*this)[1], z = (*this)[2]; 1.26948 + (*this)[0] = (T)(y*img[2]-z*img[1]); 1.26949 + (*this)[1] = (T)(z*img[0]-x*img[2]); 1.26950 + (*this)[2] = (T)(x*img[1]-y*img[0]); 1.26951 + return *this; 1.26952 + } 1.26953 + 1.26954 + template<typename t> 1.26955 + CImg<typename cimg::superset<T,t>::type> get_cross(const CImg<t>& img) const { 1.26956 + typedef typename cimg::superset<T,t>::type Tt; 1.26957 + return CImg<Tt>(*this).cross(img); 1.26958 + } 1.26959 + 1.26960 + //! Solve a linear system AX=B where B=*this. 1.26961 + template<typename t> 1.26962 + CImg<T>& solve(const CImg<t>& A) { 1.26963 + if (width!=1 || depth!=1 || dim!=1 || height!=A.height || A.depth!=1 || A.dim!=1) 1.26964 + throw CImgArgumentException("CImg<%s>::solve() : Instance matrix size is (%u,%u,%u,%u) while " 1.26965 + "size of given matrix A is (%u,%u,%u,%u).", 1.26966 + pixel_type(),width,height,depth,dim,A.width,A.height,A.depth,A.dim); 1.26967 + 1.26968 + typedef typename cimg::superset2<T,t,float>::type Ttfloat; 1.26969 + if (A.width==A.height) { 1.26970 +#ifdef cimg_use_lapack 1.26971 + char TRANS='N'; 1.26972 + int INFO, N = height, LWORK = 4*N, one = 1, *IPIV = new int[N]; 1.26973 + Ttfloat 1.26974 + *lapA = new Ttfloat[N*N], 1.26975 + *lapB = new Ttfloat[N], 1.26976 + *WORK = new Ttfloat[LWORK]; 1.26977 + cimg_forXY(A,k,l) lapA[k*N+l] = (Ttfloat)(A(k,l)); 1.26978 + cimg_forY(*this,i) lapB[i] = (Ttfloat)((*this)(i)); 1.26979 + cimg::getrf(N,lapA,IPIV,INFO); 1.26980 + if (INFO) 1.26981 + cimg::warn("CImg<%s>::solve() : LAPACK library function dgetrf_() returned error code %d.", 1.26982 + pixel_type(),INFO); 1.26983 + if (!INFO) { 1.26984 + cimg::getrs(TRANS,N,lapA,IPIV,lapB,INFO); 1.26985 + if (INFO) 1.26986 + cimg::warn("CImg<%s>::solve() : LAPACK library function dgetrs_() returned Error code %d", 1.26987 + pixel_type(),INFO); 1.26988 + } 1.26989 + if (!INFO) cimg_forY(*this,i) (*this)(i) = (T)(lapB[i]); else fill(0); 1.26990 + delete[] IPIV; delete[] lapA; delete[] lapB; delete[] WORK; 1.26991 +#else 1.26992 + CImg<Ttfloat> lu(A); 1.26993 + CImg<Ttfloat> indx; 1.26994 + bool d; 1.26995 + lu._LU(indx,d); 1.26996 + _solve(lu,indx); 1.26997 +#endif 1.26998 + } else assign(A.get_pseudoinvert()*(*this)); 1.26999 + return *this; 1.27000 + } 1.27001 + 1.27002 + template<typename t> 1.27003 + CImg<typename cimg::superset2<T,t,float>::type> get_solve(const CImg<t>& A) const { 1.27004 + typedef typename cimg::superset2<T,t,float>::type Ttfloat; 1.27005 + return CImg<Ttfloat>(*this,false).solve(A); 1.27006 + } 1.27007 + 1.27008 + template<typename t, typename ti> 1.27009 + CImg<T>& _solve(const CImg<t>& A, const CImg<ti>& indx) { 1.27010 + typedef typename cimg::superset2<T,t,float>::type Ttfloat; 1.27011 + const int N = size(); 1.27012 + int ii = -1; 1.27013 + Ttfloat sum; 1.27014 + for (int i=0; i<N; ++i) { 1.27015 + const int ip = (int)indx[i]; 1.27016 + Ttfloat sum = (*this)(ip); 1.27017 + (*this)(ip) = (*this)(i); 1.27018 + if (ii>=0) for (int j=ii; j<=i-1; ++j) sum-=A(j,i)*(*this)(j); 1.27019 + else if (sum!=0) ii=i; 1.27020 + (*this)(i) = (T)sum; 1.27021 + } 1.27022 + { for (int i=N-1; i>=0; --i) { 1.27023 + sum = (*this)(i); 1.27024 + for (int j=i+1; j<N; ++j) sum-=A(j,i)*(*this)(j); 1.27025 + (*this)(i) = (T)(sum/A(i,i)); 1.27026 + }} 1.27027 + return *this; 1.27028 + } 1.27029 + 1.27030 + //! Solve a linear system AX=B where B=*this and A is a tridiagonal matrix A = [ b0,c0,0,...; a1,b1,c1,0,... ; ... ; ...,0,aN,bN ]. 1.27031 + // (Use the Thomas Algorithm). 1.27032 + template<typename t> 1.27033 + CImg<T>& solve_tridiagonal(const CImg<t>& a, const CImg<t>& b, const CImg<t>& c) { 1.27034 + const int siz = (int)size(); 1.27035 + if ((int)a.size()!=siz || (int)b.size()!=siz || (int)c.size()!=siz) 1.27036 + throw CImgArgumentException("CImg<%s>::solve_tridiagonal() : arrays of triagonal coefficients have different size.",pixel_type); 1.27037 + typedef typename cimg::superset2<T,t,float>::type Ttfloat; 1.27038 + CImg<Ttfloat> nc(siz); 1.27039 + const T *ptra = a.data, *ptrb = b.data, *ptrc = c.data; 1.27040 + T *ptrnc = nc.data, *ptrd = data; 1.27041 + const Ttfloat valb0 = (Ttfloat)*(ptrb++); 1.27042 + *ptrnc = *(ptrc++)/valb0; 1.27043 + Ttfloat vald = (Ttfloat)(*(ptrd++)/=valb0); 1.27044 + for (int i = 1; i<siz; ++i) { 1.27045 + const Ttfloat 1.27046 + vala = (Tfloat)*(ptra++), 1.27047 + id = 1/(*(ptrb++) - *(ptrnc++)*vala); 1.27048 + *ptrnc = *(ptrc++)*id; 1.27049 + vald = ((*ptrd-=vala*vald)*=id); 1.27050 + ++ptrd; 1.27051 + } 1.27052 + vald = *(--ptrd); 1.27053 + for (int i = siz-2; i>=0; --i) vald = (*(--ptrd)-=*(--ptrnc)*vald); 1.27054 + return *this; 1.27055 + } 1.27056 + 1.27057 + template<typename t> 1.27058 + CImg<typename cimg::superset2<T,t,float>::type> get_solve_tridiagonal(const CImg<t>& a, const CImg<t>& b, const CImg<t>& c) const { 1.27059 + typedef typename cimg::superset2<T,t,float>::type Ttfloat; 1.27060 + return CImg<Ttfloat>(*this,false).solve_tridiagonal(a,b,c); 1.27061 + } 1.27062 + 1.27063 + //! Sort values of a vector and get permutations. 1.27064 + template<typename t> 1.27065 + CImg<T>& sort(CImg<t>& permutations, const bool increasing=true) { 1.27066 + if (is_empty()) permutations.assign(); 1.27067 + else { 1.27068 + if (permutations.size()!=size()) permutations.assign(size()); 1.27069 + cimg_foroff(permutations,off) permutations[off] = (t)off; 1.27070 + _quicksort(0,size()-1,permutations,increasing); 1.27071 + } 1.27072 + return *this; 1.27073 + } 1.27074 + 1.27075 + template<typename t> 1.27076 + CImg<T> get_sort(CImg<t>& permutations, const bool increasing=true) const { 1.27077 + return (+*this).sort(permutations,increasing); 1.27078 + } 1.27079 + 1.27080 + // Sort image values. 1.27081 + CImg<T>& sort(const bool increasing=true) { 1.27082 + CImg<T> foo; 1.27083 + return sort(foo,increasing); 1.27084 + } 1.27085 + 1.27086 + CImg<T> get_sort(const bool increasing=true) const { 1.27087 + return (+*this).sort(increasing); 1.27088 + } 1.27089 + 1.27090 + template<typename t> 1.27091 + CImg<T>& _quicksort(const int min, const int max, CImg<t>& permutations, const bool increasing) { 1.27092 + if (min<max) { 1.27093 + const int mid = (min+max)/2; 1.27094 + if (increasing) { 1.27095 + if ((*this)[min]>(*this)[mid]) { 1.27096 + cimg::swap((*this)[min],(*this)[mid]); cimg::swap(permutations[min],permutations[mid]); } 1.27097 + if ((*this)[mid]>(*this)[max]) { 1.27098 + cimg::swap((*this)[max],(*this)[mid]); cimg::swap(permutations[max],permutations[mid]); } 1.27099 + if ((*this)[min]>(*this)[mid]) { 1.27100 + cimg::swap((*this)[min],(*this)[mid]); cimg::swap(permutations[min],permutations[mid]); } 1.27101 + } else { 1.27102 + if ((*this)[min]<(*this)[mid]) { 1.27103 + cimg::swap((*this)[min],(*this)[mid]); cimg::swap(permutations[min],permutations[mid]); } 1.27104 + if ((*this)[mid]<(*this)[max]) { 1.27105 + cimg::swap((*this)[max],(*this)[mid]); cimg::swap(permutations[max],permutations[mid]); } 1.27106 + if ((*this)[min]<(*this)[mid]) { 1.27107 + cimg::swap((*this)[min],(*this)[mid]); cimg::swap(permutations[min],permutations[mid]); } 1.27108 + } 1.27109 + if (max-min>=3) { 1.27110 + const T pivot = (*this)[mid]; 1.27111 + int i = min, j = max; 1.27112 + if (increasing) { 1.27113 + do { 1.27114 + while ((*this)[i]<pivot) ++i; 1.27115 + while ((*this)[j]>pivot) --j; 1.27116 + if (i<=j) { 1.27117 + cimg::swap((*this)[i],(*this)[j]); 1.27118 + cimg::swap(permutations[i++],permutations[j--]); 1.27119 + } 1.27120 + } while (i<=j); 1.27121 + } else { 1.27122 + do { 1.27123 + while ((*this)[i]>pivot) ++i; 1.27124 + while ((*this)[j]<pivot) --j; 1.27125 + if (i<=j) { 1.27126 + cimg::swap((*this)[i],(*this)[j]); 1.27127 + cimg::swap(permutations[i++],permutations[j--]); 1.27128 + } 1.27129 + } while (i<=j); 1.27130 + } 1.27131 + if (min<j) _quicksort(min,j,permutations,increasing); 1.27132 + if (i<max) _quicksort(i,max,permutations,increasing); 1.27133 + } 1.27134 + } 1.27135 + return *this; 1.27136 + } 1.27137 + 1.27138 + //! Get a permutation of the pixels. 1.27139 + template<typename t> 1.27140 + CImg<T>& permute(const CImg<t>& permutation) { 1.27141 + return get_permute(permutation).transfer_to(*this); 1.27142 + } 1.27143 + 1.27144 + template<typename t> 1.27145 + CImg<T> get_permute(const CImg<t>& permutation) const { 1.27146 + if (permutation.size()!=size()) 1.27147 + throw CImgArgumentException("CImg<%s>::permute() : Instance image (%u,%u,%u,%u,%p) and permutation (%u,%u,%u,%u,%p)" 1.27148 + "have different sizes.", 1.27149 + pixel_type(),width,height,depth,dim,data, 1.27150 + permutation.width,permutation.height,permutation.depth,permutation.dim,permutation.data); 1.27151 + CImg<T> res(width,height,depth,dim); 1.27152 + const t *p = permutation.ptr(permutation.size()); 1.27153 + cimg_for(res,ptr,T) *ptr = (*this)[*(--p)]; 1.27154 + return res; 1.27155 + } 1.27156 + 1.27157 + //! Compute the SVD of a general matrix. 1.27158 + template<typename t> 1.27159 + const CImg<T>& SVD(CImg<t>& U, CImg<t>& S, CImg<t>& V, 1.27160 + const bool sorting=true, const unsigned int max_iter=40, const float lambda=0) const { 1.27161 + if (is_empty()) { U.assign(); S.assign(); V.assign(); } 1.27162 + else { 1.27163 + U = *this; 1.27164 + if (lambda!=0) { 1.27165 + const unsigned int delta = cimg::min(U.width,U.height); 1.27166 + for (unsigned int i=0; i<delta; ++i) U(i,i) = (t)(U(i,i) + lambda); 1.27167 + } 1.27168 + if (S.size()<width) S.assign(1,width); 1.27169 + if (V.width<width || V.height<height) V.assign(width,width); 1.27170 + CImg<t> rv1(width); 1.27171 + t anorm = 0, c, f, g = 0, h, s, scale = 0; 1.27172 + int l = 0, nm = 0; 1.27173 + 1.27174 + cimg_forX(U,i) { 1.27175 + l = i+1; rv1[i] = scale*g; g = s = scale = 0; 1.27176 + if (i<dimy()) { 1.27177 + for (int k=i; k<dimy(); ++k) scale+= cimg::abs(U(i,k)); 1.27178 + if (scale) { 1.27179 + for (int k=i; k<dimy(); ++k) { U(i,k)/=scale; s+= U(i,k)*U(i,k); } 1.27180 + f = U(i,i); g = (t)((f>=0?-1:1)*cimg_std::sqrt(s)); h=f*g-s; U(i,i) = f-g; 1.27181 + for (int j=l; j<dimx(); ++j) { 1.27182 + s = 0; for (int k=i; k<dimy(); ++k) s+= U(i,k)*U(j,k); 1.27183 + f = s/h; 1.27184 + { for (int k=i; k<dimy(); ++k) U(j,k)+= f*U(i,k); } 1.27185 + } 1.27186 + { for (int k=i; k<dimy(); ++k) U(i,k)*= scale; } 1.27187 + } 1.27188 + } 1.27189 + S[i]=scale*g; 1.27190 + 1.27191 + g = s = scale = 0; 1.27192 + if (i<dimy() && i!=dimx()-1) { 1.27193 + for (int k=l; k<dimx(); ++k) scale += cimg::abs(U(k,i)); 1.27194 + if (scale) { 1.27195 + for (int k=l; k<dimx(); ++k) { U(k,i)/= scale; s+= U(k,i)*U(k,i); } 1.27196 + f = U(l,i); g = (t)((f>=0?-1:1)*cimg_std::sqrt(s)); h = f*g-s; U(l,i) = f-g; 1.27197 + { for (int k=l; k<dimx(); ++k) rv1[k]=U(k,i)/h; } 1.27198 + for (int j=l; j<dimy(); ++j) { 1.27199 + s = 0; for (int k=l; k<dimx(); ++k) s+= U(k,j)*U(k,i); 1.27200 + { for (int k=l; k<dimx(); ++k) U(k,j)+= s*rv1[k]; } 1.27201 + } 1.27202 + { for (int k=l; k<dimx(); ++k) U(k,i)*= scale; } 1.27203 + } 1.27204 + } 1.27205 + anorm = (t)cimg::max((float)anorm,(float)(cimg::abs(S[i])+cimg::abs(rv1[i]))); 1.27206 + } 1.27207 + 1.27208 + { for (int i=dimx()-1; i>=0; --i) { 1.27209 + if (i<dimx()-1) { 1.27210 + if (g) { 1.27211 + { for (int j=l; j<dimx(); ++j) V(i,j) =(U(j,i)/U(l,i))/g; } 1.27212 + for (int j=l; j<dimx(); ++j) { 1.27213 + s = 0; for (int k=l; k<dimx(); ++k) s+= U(k,i)*V(j,k); 1.27214 + { for (int k=l; k<dimx(); ++k) V(j,k)+= s*V(i,k); } 1.27215 + } 1.27216 + } 1.27217 + for (int j=l; j<dimx(); ++j) V(j,i) = V(i,j) = (t)0.0; 1.27218 + } 1.27219 + V(i,i) = (t)1.0; g = rv1[i]; l = i; 1.27220 + } 1.27221 + } 1.27222 + 1.27223 + { for (int i=cimg::min(dimx(),dimy())-1; i>=0; --i) { 1.27224 + l = i+1; g = S[i]; 1.27225 + for (int j=l; j<dimx(); ++j) U(j,i) = 0; 1.27226 + if (g) { 1.27227 + g = 1/g; 1.27228 + for (int j=l; j<dimx(); ++j) { 1.27229 + s = 0; for (int k=l; k<dimy(); ++k) s+= U(i,k)*U(j,k); 1.27230 + f = (s/U(i,i))*g; 1.27231 + { for (int k=i; k<dimy(); ++k) U(j,k)+= f*U(i,k); } 1.27232 + } 1.27233 + { for (int j=i; j<dimy(); ++j) U(i,j)*= g; } 1.27234 + } else for (int j=i; j<dimy(); ++j) U(i,j) = 0; 1.27235 + ++U(i,i); 1.27236 + } 1.27237 + } 1.27238 + 1.27239 + for (int k=dimx()-1; k>=0; --k) { 1.27240 + for (unsigned int its=0; its<max_iter; ++its) { 1.27241 + bool flag = true; 1.27242 + for (l=k; l>=1; --l) { 1.27243 + nm = l-1; 1.27244 + if ((cimg::abs(rv1[l])+anorm)==anorm) { flag = false; break; } 1.27245 + if ((cimg::abs(S[nm])+anorm)==anorm) break; 1.27246 + } 1.27247 + if (flag) { 1.27248 + c = 0; s = 1; 1.27249 + for (int i=l; i<=k; ++i) { 1.27250 + f = s*rv1[i]; rv1[i] = c*rv1[i]; 1.27251 + if ((cimg::abs(f)+anorm)==anorm) break; 1.27252 + g = S[i]; h = (t)cimg::_pythagore(f,g); S[i] = h; h = 1/h; c = g*h; s = -f*h; 1.27253 + 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; } 1.27254 + } 1.27255 + } 1.27256 + const t z = S[k]; 1.27257 + if (l==k) { if (z<0) { S[k] = -z; cimg_forX(U,j) V(k,j) = -V(k,j); } break; } 1.27258 + nm = k-1; 1.27259 + t x = S[l], y = S[nm]; 1.27260 + g = rv1[nm]; h = rv1[k]; 1.27261 + f = ((y-z)*(y+z)+(g-h)*(g+h))/(2*h*y); 1.27262 + g = (t)cimg::_pythagore(f,1.0); 1.27263 + f = ((x-z)*(x+z)+h*((y/(f+ (f>=0?g:-g)))-h))/x; 1.27264 + c = s = 1; 1.27265 + for (int j=l; j<=nm; ++j) { 1.27266 + const int i = j+1; 1.27267 + g = rv1[i]; h = s*g; g = c*g; 1.27268 + t y = S[i]; 1.27269 + t z = (t)cimg::_pythagore(f,h); 1.27270 + rv1[j] = z; c = f/z; s = h/z; 1.27271 + f = x*c+g*s; g = g*c-x*s; h = y*s; y*=c; 1.27272 + 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; } 1.27273 + z = (t)cimg::_pythagore(f,h); S[j] = z; 1.27274 + if (z) { z = 1/z; c = f*z; s = h*z; } 1.27275 + f = c*g+s*y; x = c*y-s*g; 1.27276 + { 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; }} 1.27277 + } 1.27278 + rv1[l] = 0; rv1[k]=f; S[k]=x; 1.27279 + } 1.27280 + } 1.27281 + 1.27282 + if (sorting) { 1.27283 + CImg<intT> permutations(width); 1.27284 + CImg<t> tmp(width); 1.27285 + S.sort(permutations,false); 1.27286 + cimg_forY(U,k) { 1.27287 + cimg_forX(permutations,x) tmp(x) = U(permutations(x),k); 1.27288 + cimg_std::memcpy(U.ptr(0,k),tmp.data,sizeof(t)*width); 1.27289 + } 1.27290 + { cimg_forY(V,k) { 1.27291 + cimg_forX(permutations,x) tmp(x) = V(permutations(x),k); 1.27292 + cimg_std::memcpy(V.ptr(0,k),tmp.data,sizeof(t)*width); 1.27293 + }} 1.27294 + } 1.27295 + } 1.27296 + return *this; 1.27297 + } 1.27298 + 1.27299 + //! Compute the SVD of a general matrix. 1.27300 + template<typename t> 1.27301 + const CImg<T>& SVD(CImgList<t>& USV) const { 1.27302 + if (USV.size<3) USV.assign(3); 1.27303 + return SVD(USV[0],USV[1],USV[2]); 1.27304 + } 1.27305 + 1.27306 + //! Compute the SVD of a general matrix. 1.27307 + CImgList<Tfloat> get_SVD(const bool sorting=true) const { 1.27308 + CImgList<Tfloat> res(3); 1.27309 + SVD(res[0],res[1],res[2],sorting); 1.27310 + return res; 1.27311 + } 1.27312 + 1.27313 + // INNER ROUTINE : Compute the LU decomposition of a permuted matrix (c.f. numerical recipies) 1.27314 + template<typename t> 1.27315 + CImg<T>& _LU(CImg<t>& indx, bool& d) { 1.27316 + const int N = dimx(); 1.27317 + int imax = 0; 1.27318 + CImg<Tfloat> vv(N); 1.27319 + indx.assign(N); 1.27320 + d = true; 1.27321 + cimg_forX(*this,i) { 1.27322 + Tfloat vmax = 0; 1.27323 + cimg_forX(*this,j) { 1.27324 + const Tfloat tmp = cimg::abs((*this)(j,i)); 1.27325 + if (tmp>vmax) vmax = tmp; 1.27326 + } 1.27327 + if (vmax==0) { indx.fill(0); return fill(0); } 1.27328 + vv[i] = 1/vmax; 1.27329 + } 1.27330 + cimg_forX(*this,j) { 1.27331 + for (int i=0; i<j; ++i) { 1.27332 + Tfloat sum=(*this)(j,i); 1.27333 + for (int k=0; k<i; ++k) sum-=(*this)(k,i)*(*this)(j,k); 1.27334 + (*this)(j,i) = (T)sum; 1.27335 + } 1.27336 + Tfloat vmax = 0; 1.27337 + { for (int i=j; i<dimx(); ++i) { 1.27338 + Tfloat sum=(*this)(j,i); 1.27339 + for (int k=0; k<j; ++k) sum-=(*this)(k,i)*(*this)(j,k); 1.27340 + (*this)(j,i) = (T)sum; 1.27341 + const Tfloat tmp = vv[i]*cimg::abs(sum); 1.27342 + if (tmp>=vmax) { vmax=tmp; imax=i; } 1.27343 + }} 1.27344 + if (j!=imax) { 1.27345 + cimg_forX(*this,k) cimg::swap((*this)(k,imax),(*this)(k,j)); 1.27346 + d =!d; 1.27347 + vv[imax] = vv[j]; 1.27348 + } 1.27349 + indx[j] = (t)imax; 1.27350 + if ((*this)(j,j)==0) (*this)(j,j) = (T)1e-20; 1.27351 + if (j<N) { 1.27352 + const Tfloat tmp = 1/(Tfloat)(*this)(j,j); 1.27353 + for (int i=j+1; i<N; ++i) (*this)(j,i) = (T)((*this)(j,i)*tmp); 1.27354 + } 1.27355 + } 1.27356 + return *this; 1.27357 + } 1.27358 + 1.27359 + //! Compute the eigenvalues and eigenvectors of a matrix. 1.27360 + template<typename t> 1.27361 + const CImg<T>& eigen(CImg<t>& val, CImg<t> &vec) const { 1.27362 + if (is_empty()) { val.assign(); vec.assign(); } 1.27363 + else { 1.27364 + if (width!=height || depth>1 || dim>1) 1.27365 + throw CImgInstanceException("CImg<%s>::eigen() : Instance object (%u,%u,%u,%u,%p) is empty.", 1.27366 + pixel_type(),width,height,depth,dim,data); 1.27367 + if (val.size()<width) val.assign(1,width); 1.27368 + if (vec.size()<width*width) vec.assign(width,width); 1.27369 + switch (width) { 1.27370 + case 1 : { val[0]=(t)(*this)[0]; vec[0]=(t)1; } break; 1.27371 + case 2 : { 1.27372 + const double a = (*this)[0], b = (*this)[1], c = (*this)[2], d = (*this)[3], e = a+d; 1.27373 + double f = e*e-4*(a*d-b*c); 1.27374 + if (f<0) 1.27375 + cimg::warn("CImg<%s>::eigen() : Complex eigenvalues", 1.27376 + pixel_type()); 1.27377 + f = cimg_std::sqrt(f); 1.27378 + const double l1 = 0.5*(e-f), l2 = 0.5*(e+f); 1.27379 + const double theta1 = cimg_std::atan2(l2-a,b), theta2 = cimg_std::atan2(l1-a,b); 1.27380 + val[0]=(t)l2; 1.27381 + val[1]=(t)l1; 1.27382 + vec(0,0) = (t)cimg_std::cos(theta1); 1.27383 + vec(0,1) = (t)cimg_std::sin(theta1); 1.27384 + vec(1,0) = (t)cimg_std::cos(theta2); 1.27385 + vec(1,1) = (t)cimg_std::sin(theta2); 1.27386 + } break; 1.27387 + default : 1.27388 + throw CImgInstanceException("CImg<%s>::eigen() : Eigenvalues computation of general matrices is limited" 1.27389 + "to 2x2 matrices (given is %ux%u)", 1.27390 + pixel_type(),width,height); 1.27391 + } 1.27392 + } 1.27393 + return *this; 1.27394 + } 1.27395 + 1.27396 + //! Compute the eigenvalues and eigenvectors of a matrix. 1.27397 + CImgList<Tfloat> get_eigen() const { 1.27398 + CImgList<Tfloat> res(2); 1.27399 + eigen(res[0],res[1]); 1.27400 + return res; 1.27401 + } 1.27402 + 1.27403 + //! Compute the eigenvalues and eigenvectors of a symmetric matrix. 1.27404 + template<typename t> 1.27405 + const CImg<T>& symmetric_eigen(CImg<t>& val, CImg<t>& vec) const { 1.27406 + if (is_empty()) { val.assign(); vec.assign(); } 1.27407 + else { 1.27408 +#ifdef cimg_use_lapack 1.27409 + char JOB = 'V', UPLO = 'U'; 1.27410 + int N = width, LWORK = 4*N, INFO; 1.27411 + Tfloat 1.27412 + *lapA = new Tfloat[N*N], 1.27413 + *lapW = new Tfloat[N], 1.27414 + *WORK = new Tfloat[LWORK]; 1.27415 + cimg_forXY(*this,k,l) lapA[k*N+l] = (Tfloat)((*this)(k,l)); 1.27416 + cimg::syev(JOB,UPLO,N,lapA,lapW,WORK,LWORK,INFO); 1.27417 + if (INFO) 1.27418 + cimg::warn("CImg<%s>::symmetric_eigen() : LAPACK library function dsyev_() returned error code %d.", 1.27419 + pixel_type(),INFO); 1.27420 + val.assign(1,N); 1.27421 + vec.assign(N,N); 1.27422 + if (!INFO) { 1.27423 + cimg_forY(val,i) val(i) = (T)lapW[N-1-i]; 1.27424 + cimg_forXY(vec,k,l) vec(k,l) = (T)(lapA[(N-1-k)*N+l]); 1.27425 + } else { val.fill(0); vec.fill(0); } 1.27426 + delete[] lapA; delete[] lapW; delete[] WORK; 1.27427 +#else 1.27428 + if (width!=height || depth>1 || dim>1) 1.27429 + throw CImgInstanceException("CImg<%s>::eigen() : Instance object (%u,%u,%u,%u,%p) is empty.", 1.27430 + pixel_type(),width,height,depth,dim,data); 1.27431 + val.assign(1,width); 1.27432 + if (vec.data) vec.assign(width,width); 1.27433 + if (width<3) return eigen(val,vec); 1.27434 + CImg<t> V(width,width); 1.27435 + SVD(vec,val,V,false); 1.27436 + bool ambiguous = false; 1.27437 + float eig = 0; 1.27438 + cimg_forY(val,p) { // check for ambiguous cases. 1.27439 + if (val[p]>eig) eig = (float)val[p]; 1.27440 + t scal = 0; 1.27441 + cimg_forY(vec,y) scal+=vec(p,y)*V(p,y); 1.27442 + if (cimg::abs(scal)<0.9f) ambiguous = true; 1.27443 + if (scal<0) val[p] = -val[p]; 1.27444 + } 1.27445 + if (ambiguous) { 1.27446 + (eig*=2)++; 1.27447 + SVD(vec,val,V,false,40,eig); 1.27448 + val-=eig; 1.27449 + } 1.27450 + CImg<intT> permutations(width); // sort eigenvalues in decreasing order 1.27451 + CImg<t> tmp(width); 1.27452 + val.sort(permutations,false); 1.27453 + cimg_forY(vec,k) { 1.27454 + cimg_forX(permutations,x) tmp(x) = vec(permutations(x),k); 1.27455 + cimg_std::memcpy(vec.ptr(0,k),tmp.data,sizeof(t)*width); 1.27456 + } 1.27457 +#endif 1.27458 + } 1.27459 + return *this; 1.27460 + } 1.27461 + 1.27462 + //! Compute the eigenvalues and eigenvectors of a symmetric matrix. 1.27463 + CImgList<Tfloat> get_symmetric_eigen() const { 1.27464 + CImgList<Tfloat> res(2); 1.27465 + symmetric_eigen(res[0],res[1]); 1.27466 + return res; 1.27467 + } 1.27468 + 1.27469 + //@} 1.27470 + //------------------- 1.27471 + // 1.27472 + //! \name Display 1.27473 + //@{ 1.27474 + //------------------- 1.27475 + 1.27476 + //! Display an image into a CImgDisplay window. 1.27477 + const CImg<T>& display(CImgDisplay& disp) const { 1.27478 + disp.display(*this); 1.27479 + return *this; 1.27480 + } 1.27481 + 1.27482 + //! Display an image in a window with a title \p title, and wait a 'is_closed' or 'keyboard' event.\n 1.27483 + const CImg<T>& display(CImgDisplay &disp, const bool display_info) const { 1.27484 + return _display(disp,0,display_info); 1.27485 + } 1.27486 + 1.27487 + //! Display an image in a window with a title \p title, and wait a 'is_closed' or 'keyboard' event.\n 1.27488 + const CImg<T>& display(const char *const title=0, const bool display_info=true) const { 1.27489 + CImgDisplay disp; 1.27490 + return _display(disp,title,display_info); 1.27491 + } 1.27492 + 1.27493 + const CImg<T>& _display(CImgDisplay &disp, const char *const title, const bool display_info) const { 1.27494 + if (is_empty()) 1.27495 + throw CImgInstanceException("CImg<%s>::display() : Instance image (%u,%u,%u,%u,%p) is empty.", 1.27496 + pixel_type(),width,height,depth,dim,data); 1.27497 + unsigned int oldw = 0, oldh = 0, XYZ[3], key = 0, mkey = 0; 1.27498 + int x0 = 0, y0 = 0, z0 = 0, x1 = dimx()-1, y1 = dimy()-1, z1 = dimz()-1; 1.27499 + float frametiming = 5; 1.27500 + 1.27501 + char ntitle[256] = { 0 }; 1.27502 + if (!disp) { 1.27503 + if (!title) cimg_std::sprintf(ntitle,"CImg<%s>",pixel_type()); 1.27504 + disp.assign(cimg_fitscreen(width,height,depth),title?title:ntitle,1); 1.27505 + } 1.27506 + cimg_std::strncpy(ntitle,disp.title,255); 1.27507 + if (display_info) print(ntitle); 1.27508 + 1.27509 + CImg<T> zoom; 1.27510 + for (bool reset_view = true, resize_disp = false; !key && !disp.is_closed; ) { 1.27511 + if (reset_view) { 1.27512 + XYZ[0] = (x0 + x1)/2; XYZ[1] = (y0 + y1)/2; XYZ[2] = (z0 + z1)/2; 1.27513 + x0 = 0; y0 = 0; z0 = 0; x1 = width-1; y1 = height-1; z1 = depth-1; 1.27514 + oldw = disp.width; oldh = disp.height; 1.27515 + reset_view = false; 1.27516 + } 1.27517 + if (!x0 && !y0 && !z0 && x1==dimx()-1 && y1==dimy()-1 && z1==dimz()-1) zoom.assign(); 1.27518 + else zoom = get_crop(x0,y0,z0,x1,y1,z1); 1.27519 + 1.27520 + const unsigned int 1.27521 + dx = 1 + x1 - x0, dy = 1 + y1 - y0, dz = 1 + z1 - z0, 1.27522 + tw = dx + (dz>1?dz:0), th = dy + (dz>1?dz:0); 1.27523 + if (resize_disp) { 1.27524 + const unsigned int 1.27525 + ttw = tw*disp.width/oldw, tth = th*disp.height/oldh, 1.27526 + dM = cimg::max(ttw,tth), diM = cimg::max(disp.width,disp.height), 1.27527 + imgw = cimg::max(16U,ttw*diM/dM), imgh = cimg::max(16U,tth*diM/dM); 1.27528 + disp.normalscreen().resize(cimg_fitscreen(imgw,imgh,1),false); 1.27529 + resize_disp = false; 1.27530 + } 1.27531 + oldw = tw; oldh = th; 1.27532 + 1.27533 + bool 1.27534 + go_up = false, go_down = false, go_left = false, go_right = false, 1.27535 + go_inc = false, go_dec = false, go_in = false, go_out = false, 1.27536 + go_in_center = false; 1.27537 + const CImg<T>& visu = zoom?zoom:*this; 1.27538 + const CImg<intT> selection = visu._get_select(disp,0,2,XYZ,0,x0,y0,z0); 1.27539 + if (disp.wheel) { 1.27540 + if (disp.is_keyCTRLLEFT) { if (!mkey || mkey==1) go_out = !(go_in = disp.wheel>0); go_in_center = false; mkey = 1; } 1.27541 + else if (disp.is_keySHIFTLEFT) { if (!mkey || mkey==2) go_right = !(go_left = disp.wheel>0); mkey = 2; } 1.27542 + else if (disp.is_keyALT || depth==1) { if (!mkey || mkey==3) go_down = !(go_up = disp.wheel>0); mkey = 3; } 1.27543 + else mkey = 0; 1.27544 + disp.wheel = 0; 1.27545 + } else mkey = 0; 1.27546 + const int 1.27547 + sx0 = selection(0), sy0 = selection(1), sz0 = selection(2), 1.27548 + sx1 = selection(3), sy1 = selection(4), sz1 = selection(5); 1.27549 + if (sx0>=0 && sy0>=0 && sz0>=0 && sx1>=0 && sy1>=0 && sz1>=0) { 1.27550 + x1 = x0 + sx1; y1 = y0 + sy1; z1 = z0 + sz1; x0+=sx0; y0+=sy0; z0+=sz0; 1.27551 + if (sx0==sx1 && sy0==sy1 && sz0==sz1) reset_view = true; 1.27552 + resize_disp = true; 1.27553 + } else switch (key = disp.key) { 1.27554 + case 0 : case cimg::keyCTRLLEFT : case cimg::keyPAD5 : case cimg::keySHIFTLEFT : case cimg::keyALT : disp.key = key = 0; break; 1.27555 + case cimg::keyP : if (visu.depth>1 && disp.is_keyCTRLLEFT) { // Special mode : play stack of frames 1.27556 + const unsigned int 1.27557 + w1 = visu.width*disp.width/(visu.width+(visu.depth>1?visu.depth:0)), 1.27558 + h1 = visu.height*disp.height/(visu.height+(visu.depth>1?visu.depth:0)); 1.27559 + disp.resize(cimg_fitscreen(w1,h1,1),false).key = disp.wheel = key = 0; 1.27560 + for (unsigned int timer = 0; !key && !disp.is_closed && !disp.button; ) { 1.27561 + if (disp.is_resized) disp.resize(); 1.27562 + if (!timer) { 1.27563 + visu.get_slice(XYZ[2]).display(disp.set_title("%s | z=%d",ntitle,XYZ[2])); 1.27564 + if (++XYZ[2]>=visu.depth) XYZ[2] = 0; 1.27565 + } 1.27566 + if (++timer>(unsigned int)frametiming) timer = 0; 1.27567 + if (disp.wheel) { frametiming-=disp.wheel/3.0f; disp.wheel = 0; } 1.27568 + switch (key = disp.key) { 1.27569 + case 0 : case cimg::keyCTRLLEFT : disp.key = key = 0; break; 1.27570 + case cimg::keyPAGEUP : frametiming-=0.3f; key = 0; break; 1.27571 + case cimg::keyPAGEDOWN : frametiming+=0.3f; key = 0; break; 1.27572 + case cimg::keyD : if (disp.is_keyCTRLLEFT) { 1.27573 + disp.normalscreen().resize(CImgDisplay::_fitscreen(3*disp.width/2,3*disp.height/2,1,128,-100,false), 1.27574 + CImgDisplay::_fitscreen(3*disp.width/2,3*disp.height/2,1,128,-100,true),false); 1.27575 + disp.key = key = 0; 1.27576 + } break; 1.27577 + case cimg::keyC : if (disp.is_keyCTRLLEFT) { 1.27578 + disp.normalscreen().resize(cimg_fitscreen(2*disp.width/3,2*disp.height/3,1),false); 1.27579 + disp.key = key = 0; 1.27580 + } break; 1.27581 + case cimg::keyR : if (disp.is_keyCTRLLEFT) { 1.27582 + disp.normalscreen().resize(cimg_fitscreen(width,height,depth),false); 1.27583 + disp.key = key = 0; 1.27584 + } break; 1.27585 + case cimg::keyF : if (disp.is_keyCTRLLEFT) { 1.27586 + disp.resize(disp.screen_dimx(),disp.screen_dimy()).toggle_fullscreen(); 1.27587 + disp.key = key = 0; 1.27588 + } break; 1.27589 + } 1.27590 + frametiming = frametiming<1?1:(frametiming>39?39:frametiming); 1.27591 + disp.wait(20); 1.27592 + } 1.27593 + const unsigned int 1.27594 + w2 = (visu.width + (visu.depth>1?visu.depth:0))*disp.width/visu.width, 1.27595 + h2 = (visu.height + (visu.depth>1?visu.depth:0))*disp.height/visu.height; 1.27596 + disp.resize(cimg_fitscreen(w2,h2,1),false).set_title(ntitle); 1.27597 + key = disp.key = disp.button = disp.wheel = 0; 1.27598 + } break; 1.27599 + case cimg::keyHOME : case cimg::keyBACKSPACE : reset_view = resize_disp = true; key = 0; break; 1.27600 + case cimg::keyPADADD : go_in = true; go_in_center = true; key = 0; break; 1.27601 + case cimg::keyPADSUB : go_out = true; key = 0; break; 1.27602 + case cimg::keyARROWLEFT : case cimg::keyPAD4: go_left = true; key = 0; break; 1.27603 + case cimg::keyARROWRIGHT : case cimg::keyPAD6: go_right = true; key = 0; break; 1.27604 + case cimg::keyARROWUP : case cimg::keyPAD8: go_up = true; key = 0; break; 1.27605 + case cimg::keyARROWDOWN : case cimg::keyPAD2: go_down = true; key = 0; break; 1.27606 + case cimg::keyPAD7 : go_up = go_left = true; key = 0; break; 1.27607 + case cimg::keyPAD9 : go_up = go_right = true; key = 0; break; 1.27608 + case cimg::keyPAD1 : go_down = go_left = true; key = 0; break; 1.27609 + case cimg::keyPAD3 : go_down = go_right = true; key = 0; break; 1.27610 + case cimg::keyPAGEUP : go_inc = true; key = 0; break; 1.27611 + case cimg::keyPAGEDOWN : go_dec = true; key = 0; break; 1.27612 + } 1.27613 + if (go_in) { 1.27614 + const int 1.27615 + mx = go_in_center?disp.dimx()/2:disp.mouse_x, 1.27616 + my = go_in_center?disp.dimy()/2:disp.mouse_y, 1.27617 + mX = mx*(width+(depth>1?depth:0))/disp.width, 1.27618 + mY = my*(height+(depth>1?depth:0))/disp.height; 1.27619 + int X = XYZ[0], Y = XYZ[1], Z = XYZ[2]; 1.27620 + if (mX<dimx() && mY<dimy()) { X = x0 + mX*(1+x1-x0)/width; Y = y0 + mY*(1+y1-y0)/height; Z = XYZ[2]; } 1.27621 + if (mX<dimx() && mY>=dimy()) { X = x0 + mX*(1+x1-x0)/width; Z = z0 + (mY-height)*(1+z1-z0)/depth; Y = XYZ[1]; } 1.27622 + if (mX>=dimx() && mY<dimy()) { Y = y0 + mY*(1+y1-y0)/height; Z = z0 + (mX-width)*(1+z1-z0)/depth; X = XYZ[0]; } 1.27623 + if (x1-x0>4) { x0 = X - 7*(X-x0)/8; x1 = X + 7*(x1-X)/8; } 1.27624 + if (y1-y0>4) { y0 = Y - 7*(Y-y0)/8; y1 = Y + 7*(y1-Y)/8; } 1.27625 + if (z1-z0>4) { z0 = Z - 7*(Z-z0)/8; z1 = Z + 7*(z1-Z)/8; } 1.27626 + } 1.27627 + if (go_out) { 1.27628 + const int 1.27629 + deltax = (x1-x0)/8, deltay = (y1-y0)/8, deltaz = (z1-z0)/8, 1.27630 + ndeltax = deltax?deltax:(width>1?1:0), 1.27631 + ndeltay = deltay?deltay:(height>1?1:0), 1.27632 + ndeltaz = deltaz?deltaz:(depth>1?1:0); 1.27633 + x0-=ndeltax; y0-=ndeltay; z0-=ndeltaz; 1.27634 + x1+=ndeltax; y1+=ndeltay; z1+=ndeltaz; 1.27635 + if (x0<0) { x1-=x0; x0 = 0; if (x1>=dimx()) x1 = dimx()-1; } 1.27636 + if (y0<0) { y1-=y0; y0 = 0; if (y1>=dimy()) y1 = dimy()-1; } 1.27637 + if (z0<0) { z1-=z0; z0 = 0; if (z1>=dimz()) z1 = dimz()-1; } 1.27638 + if (x1>=dimx()) { x0-=(x1-dimx()+1); x1 = dimx()-1; if (x0<0) x0 = 0; } 1.27639 + if (y1>=dimy()) { y0-=(y1-dimy()+1); y1 = dimy()-1; if (y0<0) y0 = 0; } 1.27640 + if (z1>=dimz()) { z0-=(z1-dimz()+1); z1 = dimz()-1; if (z0<0) z0 = 0; } 1.27641 + } 1.27642 + if (go_left) { 1.27643 + const int delta = (x1-x0)/5, ndelta = delta?delta:(width>1?1:0); 1.27644 + if (x0-ndelta>=0) { x0-=ndelta; x1-=ndelta; } 1.27645 + else { x1-=x0; x0 = 0; } 1.27646 + } 1.27647 + if (go_right) { 1.27648 + const int delta = (x1-x0)/5, ndelta = delta?delta:(width>1?1:0); 1.27649 + if (x1+ndelta<dimx()) { x0+=ndelta; x1+=ndelta; } 1.27650 + else { x0+=(dimx()-1-x1); x1 = dimx()-1; } 1.27651 + } 1.27652 + if (go_up) { 1.27653 + const int delta = (y1-y0)/5, ndelta = delta?delta:(height>1?1:0); 1.27654 + if (y0-ndelta>=0) { y0-=ndelta; y1-=ndelta; } 1.27655 + else { y1-=y0; y0 = 0; } 1.27656 + } 1.27657 + if (go_down) { 1.27658 + const int delta = (y1-y0)/5, ndelta = delta?delta:(height>1?1:0); 1.27659 + if (y1+ndelta<dimy()) { y0+=ndelta; y1+=ndelta; } 1.27660 + else { y0+=(dimy()-1-y1); y1 = dimy()-1; } 1.27661 + } 1.27662 + if (go_inc) { 1.27663 + const int delta = (z1-z0)/5, ndelta = delta?delta:(depth>1?1:0); 1.27664 + if (z0-ndelta>=0) { z0-=ndelta; z1-=ndelta; } 1.27665 + else { z1-=z0; z0 = 0; } 1.27666 + } 1.27667 + if (go_dec) { 1.27668 + const int delta = (z1-z0)/5, ndelta = delta?delta:(depth>1?1:0); 1.27669 + if (z1+ndelta<dimz()) { z0+=ndelta; z1+=ndelta; } 1.27670 + else { z0+=(depth-1-z1); z1 = depth-1; } 1.27671 + } 1.27672 + } 1.27673 + disp.key = key; 1.27674 + return *this; 1.27675 + } 1.27676 + 1.27677 + //! Simple interface to select a shape from an image. 1.27678 + /** 1.27679 + \param selection Array of 6 values containing the selection result 1.27680 + \param coords_type Determine shape type to select (0=point, 1=vector, 2=rectangle, 3=circle) 1.27681 + \param disp Display window used to make the selection 1.27682 + \param XYZ Initial XYZ position (for volumetric images only) 1.27683 + \param color Color of the shape selector. 1.27684 + **/ 1.27685 + CImg<T>& select(CImgDisplay &disp, 1.27686 + const int select_type=2, unsigned int *const XYZ=0, 1.27687 + const unsigned char *const color=0) { 1.27688 + return get_select(disp,select_type,XYZ,color).transfer_to(*this); 1.27689 + } 1.27690 + 1.27691 + //! Simple interface to select a shape from an image. 1.27692 + CImg<T>& select(const char *const title, 1.27693 + const int select_type=2, unsigned int *const XYZ=0, 1.27694 + const unsigned char *const color=0) { 1.27695 + return get_select(title,select_type,XYZ,color).transfer_to(*this); 1.27696 + } 1.27697 + 1.27698 + //! Simple interface to select a shape from an image. 1.27699 + CImg<intT> get_select(CImgDisplay &disp, 1.27700 + const int select_type=2, unsigned int *const XYZ=0, 1.27701 + const unsigned char *const color=0) const { 1.27702 + return _get_select(disp,0,select_type,XYZ,color,0,0,0); 1.27703 + } 1.27704 + 1.27705 + //! Simple interface to select a shape from an image. 1.27706 + CImg<intT> get_select(const char *const title, 1.27707 + const int select_type=2, unsigned int *const XYZ=0, 1.27708 + const unsigned char *const color=0) const { 1.27709 + CImgDisplay disp; 1.27710 + return _get_select(disp,title,select_type,XYZ,color,0,0,0); 1.27711 + } 1.27712 + 1.27713 + CImg<intT> _get_select(CImgDisplay &disp, const char *const title, 1.27714 + const int coords_type, unsigned int *const XYZ, 1.27715 + const unsigned char *const color, 1.27716 + const int origX, const int origY, const int origZ) const { 1.27717 + if (is_empty()) 1.27718 + throw CImgInstanceException("CImg<%s>::select() : Instance image (%u,%u,%u,%u,%p) is empty.", 1.27719 + pixel_type(),width,height,depth,dim,data); 1.27720 + if (!disp) { 1.27721 + char ntitle[64] = { 0 }; if (!title) { cimg_std::sprintf(ntitle,"CImg<%s>",pixel_type()); } 1.27722 + disp.assign(cimg_fitscreen(width,height,depth),title?title:ntitle,1); 1.27723 + } 1.27724 + 1.27725 + const unsigned int 1.27726 + old_normalization = disp.normalization, 1.27727 + hatch = 0x55555555; 1.27728 + 1.27729 + bool old_is_resized = disp.is_resized; 1.27730 + disp.normalization = 0; 1.27731 + disp.show().key = 0; 1.27732 + 1.27733 + unsigned char foreground_color[] = { 255,255,105 }, background_color[] = { 0,0,0 }; 1.27734 + if (color) cimg_std::memcpy(foreground_color,color,sizeof(unsigned char)*cimg::min(3,dimv())); 1.27735 + 1.27736 + int area = 0, clicked_area = 0, phase = 0, 1.27737 + X0 = (int)((XYZ?XYZ[0]:width/2)%width), Y0 = (int)((XYZ?XYZ[1]:height/2)%height), Z0 = (int)((XYZ?XYZ[2]:depth/2)%depth), 1.27738 + X1 =-1, Y1 = -1, Z1 = -1, 1.27739 + X = -1, Y = -1, Z = -1, 1.27740 + oX = X, oY = Y, oZ = Z; 1.27741 + unsigned int old_button = 0, key = 0; 1.27742 + 1.27743 + bool shape_selected = false, text_down = false; 1.27744 + CImg<ucharT> visu, visu0; 1.27745 + char text[1024] = { 0 }; 1.27746 + 1.27747 + while (!key && !disp.is_closed && !shape_selected) { 1.27748 + 1.27749 + // Handle mouse motion and selection 1.27750 + oX = X; oY = Y; oZ = Z; 1.27751 + int mx = disp.mouse_x, my = disp.mouse_y; 1.27752 + const int mX = mx*(width+(depth>1?depth:0))/disp.width, mY = my*(height+(depth>1?depth:0))/disp.height; 1.27753 + 1.27754 + area = 0; 1.27755 + if (mX<dimx() && mY<dimy()) { area = 1; X = mX; Y = mY; Z = phase?Z1:Z0; } 1.27756 + if (mX<dimx() && mY>=dimy()) { area = 2; X = mX; Z = mY-height; Y = phase?Y1:Y0; } 1.27757 + if (mX>=dimx() && mY<dimy()) { area = 3; Y = mY; Z = mX-width; X = phase?X1:X0; } 1.27758 + 1.27759 + switch (key = disp.key) { 1.27760 + case 0 : case cimg::keyCTRLLEFT : disp.key = key = 0; break; 1.27761 + case cimg::keyPAGEUP : if (disp.is_keyCTRLLEFT) { ++disp.wheel; key = 0; } break; 1.27762 + case cimg::keyPAGEDOWN : if (disp.is_keyCTRLLEFT) { --disp.wheel; key = 0; } break; 1.27763 + case cimg::keyD : if (disp.is_keyCTRLLEFT) { 1.27764 + disp.normalscreen().resize(CImgDisplay::_fitscreen(3*disp.width/2,3*disp.height/2,1,128,-100,false), 1.27765 + CImgDisplay::_fitscreen(3*disp.width/2,3*disp.height/2,1,128,-100,true),false).is_resized = true; 1.27766 + disp.key = key = 0; 1.27767 + } break; 1.27768 + case cimg::keyC : if (disp.is_keyCTRLLEFT) { 1.27769 + disp.normalscreen().resize(cimg_fitscreen(2*disp.width/3,2*disp.height/3,1),false).is_resized = true; 1.27770 + disp.key = key = 0; visu0.assign(); 1.27771 + } break; 1.27772 + case cimg::keyR : if (disp.is_keyCTRLLEFT) { 1.27773 + disp.normalscreen().resize(cimg_fitscreen(width,height,depth),false).is_resized = true; 1.27774 + disp.key = key = 0; visu0.assign(); 1.27775 + } break; 1.27776 + case cimg::keyF : if (disp.is_keyCTRLLEFT) { 1.27777 + disp.resize(disp.screen_dimx(),disp.screen_dimy(),false).toggle_fullscreen().is_resized = true; 1.27778 + disp.key = key = 0; visu0.assign(); 1.27779 + } break; 1.27780 + case cimg::keyS : if (disp.is_keyCTRLLEFT) { 1.27781 + static unsigned int snap_number = 0; 1.27782 + char filename[32] = { 0 }; 1.27783 + cimg_std::FILE *file; 1.27784 + do { 1.27785 + cimg_std::sprintf(filename,"CImg_%.4u.bmp",snap_number++); 1.27786 + if ((file=cimg_std::fopen(filename,"r"))!=0) cimg_std::fclose(file); 1.27787 + } while (file); 1.27788 + if (visu0) { 1.27789 + visu.draw_text(2,2,"Saving snapshot...",foreground_color,background_color,0.8f,11).display(disp); 1.27790 + visu0.save(filename); 1.27791 + visu.draw_text(2,2,"Snapshot '%s' saved.",foreground_color,background_color,0.8f,11,filename).display(disp); 1.27792 + } 1.27793 + disp.key = key = 0; 1.27794 + } break; 1.27795 + case cimg::keyO : if (disp.is_keyCTRLLEFT) { 1.27796 + static unsigned int snap_number = 0; 1.27797 + char filename[32] = { 0 }; 1.27798 + cimg_std::FILE *file; 1.27799 + do { 1.27800 + cimg_std::sprintf(filename,"CImg_%.4u.cimg",snap_number++); 1.27801 + if ((file=cimg_std::fopen(filename,"r"))!=0) cimg_std::fclose(file); 1.27802 + } while (file); 1.27803 + visu.draw_text(2,2,"Saving instance...",foreground_color,background_color,0.8f,11).display(disp); 1.27804 + save(filename); 1.27805 + visu.draw_text(2,2,"Instance '%s' saved.",foreground_color,background_color,0.8f,11,filename).display(disp); 1.27806 + disp.key = key = 0; 1.27807 + } break; 1.27808 + } 1.27809 + 1.27810 + if (!area) mx = my = X = Y = Z = -1; 1.27811 + else { 1.27812 + if (disp.button&1 && phase<2) { X1 = X; Y1 = Y; Z1 = Z; } 1.27813 + if (!(disp.button&1) && phase>=2) { 1.27814 + switch (clicked_area) { 1.27815 + case 1 : Z1 = Z; break; 1.27816 + case 2 : Y1 = Y; break; 1.27817 + case 3 : X1 = X; break; 1.27818 + } 1.27819 + } 1.27820 + if (disp.button&2) { if (phase) { X1 = X; Y1 = Y; Z1 = Z; } else { X0 = X; Y0 = Y; Z0 = Z; } } 1.27821 + if (disp.button&4) { oX = X = X0; oY = Y = Y0; oZ = Z = Z0; phase = 0; visu.assign(); } 1.27822 + if (disp.wheel) { 1.27823 + if (depth>1 && !disp.is_keyCTRLLEFT && !disp.is_keySHIFTLEFT && !disp.is_keyALT) { 1.27824 + switch (area) { 1.27825 + case 1 : if (phase) Z = (Z1+=disp.wheel); else Z = (Z0+=disp.wheel); break; 1.27826 + case 2 : if (phase) Y = (Y1+=disp.wheel); else Y = (Y0+=disp.wheel); break; 1.27827 + case 3 : if (phase) X = (X1+=disp.wheel); else X = (X0+=disp.wheel); break; 1.27828 + } 1.27829 + disp.wheel = 0; 1.27830 + } else key = ~0U; 1.27831 + } 1.27832 + if ((disp.button&1)!=old_button) { 1.27833 + switch (phase++) { 1.27834 + case 0 : X0 = X1 = X; Y0 = Y1 = Y; Z0 = Z1 = Z; clicked_area = area; break; 1.27835 + case 1 : X1 = X; Y1 = Y; Z1 = Z; break; 1.27836 + } 1.27837 + old_button = disp.button&1; 1.27838 + } 1.27839 + if (depth>1 && (X!=oX || Y!=oY || Z!=oZ)) visu0.assign(); 1.27840 + } 1.27841 + 1.27842 + if (phase) { 1.27843 + if (!coords_type) shape_selected = phase?true:false; 1.27844 + else { 1.27845 + if (depth>1) shape_selected = (phase==3)?true:false; 1.27846 + else shape_selected = (phase==2)?true:false; 1.27847 + } 1.27848 + } 1.27849 + 1.27850 + if (X0<0) X0 = 0; if (X0>=dimx()) X0 = dimx()-1; if (Y0<0) Y0 = 0; if (Y0>=dimy()) Y0 = dimy()-1; 1.27851 + if (Z0<0) Z0 = 0; if (Z0>=dimz()) Z0 = dimz()-1; 1.27852 + if (X1<1) X1 = 0; if (X1>=dimx()) X1 = dimx()-1; if (Y1<0) Y1 = 0; if (Y1>=dimy()) Y1 = dimy()-1; 1.27853 + if (Z1<0) Z1 = 0; if (Z1>=dimz()) Z1 = dimz()-1; 1.27854 + 1.27855 + // Draw visualization image on the display 1.27856 + if (oX!=X || oY!=Y || oZ!=Z || !visu0) { 1.27857 + if (!visu0) { 1.27858 + CImg<Tuchar> tmp, tmp0; 1.27859 + if (depth!=1) { 1.27860 + tmp0 = (!phase)?get_projections2d(X0,Y0,Z0):get_projections2d(X1,Y1,Z1); 1.27861 + tmp = tmp0.get_channels(0,cimg::min(2U,dim-1)); 1.27862 + } else tmp = get_channels(0,cimg::min(2U,dim-1)); 1.27863 + switch (old_normalization) { 1.27864 + case 0 : visu0 = tmp; break; 1.27865 + case 3 : 1.27866 + if (cimg::type<T>::is_float()) visu0 = tmp.normalize(0,(T)255); 1.27867 + else { 1.27868 + const float m = (float)cimg::type<T>::min(), M = (float)cimg::type<T>::max(); 1.27869 + visu0.assign(tmp.width,tmp.height,1,tmp.dim); 1.27870 + unsigned char *ptrd = visu0.end(); 1.27871 + cimg_for(tmp,ptrs,Tuchar) *(--ptrd) = (unsigned char)((*ptrs-m)*255.0f/(M-m)); 1.27872 + } break; 1.27873 + default : visu0 = tmp.normalize(0,255); 1.27874 + } 1.27875 + visu0.resize(disp); 1.27876 + } 1.27877 + visu = visu0; 1.27878 + if (!color) { 1.27879 + if (visu.mean()<200) { 1.27880 + foreground_color[0] = foreground_color[1] = foreground_color[2] = 255; 1.27881 + background_color[0] = background_color[1] = background_color[2] = 0; 1.27882 + } else { 1.27883 + foreground_color[0] = foreground_color[1] = foreground_color[2] = 0; 1.27884 + background_color[0] = background_color[1] = background_color[2] = 255; 1.27885 + } 1.27886 + } 1.27887 + 1.27888 + const int d = (depth>1)?depth:0; 1.27889 + if (phase) switch (coords_type) { 1.27890 + case 1 : { 1.27891 + const int 1.27892 + x0 = (int)((X0+0.5f)*disp.width/(width+d)), 1.27893 + y0 = (int)((Y0+0.5f)*disp.height/(height+d)), 1.27894 + x1 = (int)((X1+0.5f)*disp.width/(width+d)), 1.27895 + y1 = (int)((Y1+0.5f)*disp.height/(height+d)); 1.27896 + visu.draw_arrow(x0,y0,x1,y1,foreground_color,0.6f,30,5,hatch); 1.27897 + if (d) { 1.27898 + const int 1.27899 + zx0 = (int)((width+Z0+0.5f)*disp.width/(width+d)), 1.27900 + zx1 = (int)((width+Z1+0.5f)*disp.width/(width+d)), 1.27901 + zy0 = (int)((height+Z0+0.5f)*disp.height/(height+d)), 1.27902 + zy1 = (int)((height+Z1+0.5f)*disp.height/(height+d)); 1.27903 + visu.draw_arrow(zx0,y0,zx1,y1,foreground_color,0.6f,30,5,hatch). 1.27904 + draw_arrow(x0,zy0,x1,zy1,foreground_color,0.6f,30,5,hatch); 1.27905 + } 1.27906 + } break; 1.27907 + case 2 : { 1.27908 + const int 1.27909 + x0 = (X0<X1?X0:X1)*disp.width/(width+d), y0 = (Y0<Y1?Y0:Y1)*disp.height/(height+d), 1.27910 + x1 = ((X0<X1?X1:X0)+1)*disp.width/(width+d)-1, y1 = ((Y0<Y1?Y1:Y0)+1)*disp.height/(height+d)-1; 1.27911 + visu.draw_rectangle(x0,y0,x1,y1,foreground_color,0.2f).draw_rectangle(x0,y0,x1,y1,foreground_color,0.6f,hatch); 1.27912 + if (d) { 1.27913 + const int 1.27914 + zx0 = (int)((width+(Z0<Z1?Z0:Z1))*disp.width/(width+d)), 1.27915 + zy0 = (int)((height+(Z0<Z1?Z0:Z1))*disp.height/(height+d)), 1.27916 + zx1 = (int)((width+(Z0<Z1?Z1:Z0)+1)*disp.width/(width+d))-1, 1.27917 + zy1 = (int)((height+(Z0<Z1?Z1:Z0)+1)*disp.height/(height+d))-1; 1.27918 + visu.draw_rectangle(zx0,y0,zx1,y1,foreground_color,0.2f).draw_rectangle(zx0,y0,zx1,y1,foreground_color,0.6f,hatch); 1.27919 + visu.draw_rectangle(x0,zy0,x1,zy1,foreground_color,0.2f).draw_rectangle(x0,zy0,x1,zy1,foreground_color,0.6f,hatch); 1.27920 + } 1.27921 + } break; 1.27922 + case 3 : { 1.27923 + const int 1.27924 + x0 = X0*disp.width/(width+d), 1.27925 + y0 = Y0*disp.height/(height+d), 1.27926 + x1 = X1*disp.width/(width+d)-1, 1.27927 + y1 = Y1*disp.height/(height+d)-1; 1.27928 + visu.draw_ellipse(x0,y0,(float)(x1-x0),(float)(y1-y0),1,0,foreground_color,0.2f). 1.27929 + draw_ellipse(x0,y0,(float)(x1-x0),(float)(y1-y0),1,0,foreground_color,0.6f,hatch); 1.27930 + if (d) { 1.27931 + const int 1.27932 + zx0 = (int)((width+Z0)*disp.width/(width+d)), 1.27933 + zy0 = (int)((height+Z0)*disp.height/(height+d)), 1.27934 + zx1 = (int)((width+Z1+1)*disp.width/(width+d))-1, 1.27935 + zy1 = (int)((height+Z1+1)*disp.height/(height+d))-1; 1.27936 + visu.draw_ellipse(zx0,y0,(float)(zx1-zx0),(float)(y1-y0),1,0,foreground_color,0.2f). 1.27937 + draw_ellipse(zx0,y0,(float)(zx1-zx0),(float)(y1-y0),1,0,foreground_color,0.6f,hatch). 1.27938 + draw_ellipse(x0,zy0,(float)(x1-x0),(float)(zy1-zy0),1,0,foreground_color,0.2f). 1.27939 + draw_ellipse(x0,zy0,(float)(x1-x0),(float)(zy1-zy0),1,0,foreground_color,0.6f,hatch); 1.27940 + } 1.27941 + } break; 1.27942 + } else { 1.27943 + const int 1.27944 + x0 = X*disp.width/(width+d), 1.27945 + y0 = Y*disp.height/(height+d), 1.27946 + x1 = (X+1)*disp.width/(width+d)-1, 1.27947 + y1 = (Y+1)*disp.height/(height+d)-1; 1.27948 + if (x1-x0>=4 && y1-y0>=4) visu.draw_rectangle(x0,y0,x1,y1,foreground_color,0.4f,~0U); 1.27949 + } 1.27950 + 1.27951 + if (my<12) text_down = true; 1.27952 + if (my>=visu.dimy()-11) text_down = false; 1.27953 + if (!coords_type || !phase) { 1.27954 + if (X>=0 && Y>=0 && Z>=0 && X<dimx() && Y<dimy() && Z<dimz()) { 1.27955 + if (depth>1) cimg_std::sprintf(text,"Point (%d,%d,%d) = [ ",origX+X,origY+Y,origZ+Z); 1.27956 + else cimg_std::sprintf(text,"Point (%d,%d) = [ ",origX+X,origY+Y); 1.27957 + char *ctext = text + cimg::strlen(text), *const ltext = text + 512; 1.27958 + for (unsigned int k=0; k<dim && ctext<ltext; ++k) { 1.27959 + cimg_std::sprintf(ctext,cimg::type<T>::format(),cimg::type<T>::format((*this)(X,Y,Z,k))); 1.27960 + ctext = text + cimg::strlen(text); 1.27961 + *(ctext++) = ' '; *ctext = '\0'; 1.27962 + } 1.27963 + cimg_std::sprintf(text + cimg::strlen(text),"]"); 1.27964 + } 1.27965 + } else switch (coords_type) { 1.27966 + case 1 : { 1.27967 + const double dX = (double)(X0 - X1), dY = (double)(Y0 - Y1), dZ = (double)(Z0 - Z1), norm = cimg_std::sqrt(dX*dX+dY*dY+dZ*dZ); 1.27968 + if (depth>1) cimg_std::sprintf(text,"Vect (%d,%d,%d)-(%d,%d,%d), Norm = %g", 1.27969 + origX+X0,origY+Y0,origZ+Z0,origX+X1,origY+Y1,origZ+Z1,norm); 1.27970 + else cimg_std::sprintf(text,"Vect (%d,%d)-(%d,%d), Norm = %g", 1.27971 + origX+X0,origY+Y0,origX+X1,origY+Y1,norm); 1.27972 + } break; 1.27973 + case 2 : 1.27974 + if (depth>1) cimg_std::sprintf(text,"Box (%d,%d,%d)-(%d,%d,%d), Size = (%d,%d,%d)", 1.27975 + origX+(X0<X1?X0:X1),origY+(Y0<Y1?Y0:Y1),origZ+(Z0<Z1?Z0:Z1), 1.27976 + origX+(X0<X1?X1:X0),origY+(Y0<Y1?Y1:Y0),origZ+(Z0<Z1?Z1:Z0), 1.27977 + 1+cimg::abs(X0-X1),1+cimg::abs(Y0-Y1),1+cimg::abs(Z0-Z1)); 1.27978 + else cimg_std::sprintf(text,"Box (%d,%d)-(%d,%d), Size = (%d,%d)", 1.27979 + origX+(X0<X1?X0:X1),origY+(Y0<Y1?Y0:Y1),origX+(X0<X1?X1:X0),origY+(Y0<Y1?Y1:Y0), 1.27980 + 1+cimg::abs(X0-X1),1+cimg::abs(Y0-Y1)); 1.27981 + break; 1.27982 + default : 1.27983 + if (depth>1) cimg_std::sprintf(text,"Ellipse (%d,%d,%d)-(%d,%d,%d), Radii = (%d,%d,%d)", 1.27984 + origX+X0,origY+Y0,origZ+Z0,origX+X1,origY+Y1,origZ+Z1, 1.27985 + 1+cimg::abs(X0-X1),1+cimg::abs(Y0-Y1),1+cimg::abs(Z0-Z1)); 1.27986 + else cimg_std::sprintf(text,"Ellipse (%d,%d)-(%d,%d), Radii = (%d,%d)", 1.27987 + origX+X0,origY+Y0,origX+X1,origY+Y1,1+cimg::abs(X0-X1),1+cimg::abs(Y0-Y1)); 1.27988 + 1.27989 + } 1.27990 + if (phase || (mx>=0 && my>=0)) visu.draw_text(0,text_down?visu.dimy()-11:0,text,foreground_color,background_color,0.7f,11); 1.27991 + disp.display(visu).wait(25); 1.27992 + } else if (!shape_selected) disp.wait(); 1.27993 + 1.27994 + if (disp.is_resized) { disp.resize(false); old_is_resized = true; disp.is_resized = false; visu0.assign(); } 1.27995 + } 1.27996 + 1.27997 + // Return result 1.27998 + CImg<intT> res(1,6,1,1,-1); 1.27999 + if (XYZ) { XYZ[0] = (unsigned int)X0; XYZ[1] = (unsigned int)Y0; XYZ[2] = (unsigned int)Z0; } 1.28000 + if (shape_selected) { 1.28001 + if (coords_type==2) { 1.28002 + if (X0>X1) cimg::swap(X0,X1); 1.28003 + if (Y0>Y1) cimg::swap(Y0,Y1); 1.28004 + if (Z0>Z1) cimg::swap(Z0,Z1); 1.28005 + } 1.28006 + if (X1<0 || Y1<0 || Z1<0) X0 = Y0 = Z0 = X1 = Y1 = Z1 = -1; 1.28007 + switch (coords_type) { 1.28008 + case 1 : 1.28009 + case 2 : res[3] = X1; res[4] = Y1; res[5] = Z1; 1.28010 + default : res[0] = X0; res[1] = Y0; res[2] = Z0; 1.28011 + } 1.28012 + } 1.28013 + disp.button = 0; 1.28014 + disp.normalization = old_normalization; 1.28015 + disp.is_resized = old_is_resized; 1.28016 + if (key!=~0U) disp.key = key; 1.28017 + return res; 1.28018 + } 1.28019 + 1.28020 + //! High-level interface for displaying a 3d object. 1.28021 + template<typename tp, typename tf, typename tc, typename to> 1.28022 + const CImg<T>& display_object3d(CImgDisplay& disp, 1.28023 + const CImg<tp>& points, const CImgList<tf>& primitives, 1.28024 + const CImgList<tc>& colors, const to& opacities, 1.28025 + const bool centering=true, 1.28026 + const int render_static=4, const int render_motion=1, 1.28027 + const bool double_sided=false, const float focale=500, 1.28028 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.28029 + const bool display_axes=true, float *const pose_matrix=0) const { 1.28030 + return _display_object3d(disp,0,points,points.width,primitives,colors,opacities,centering,render_static, 1.28031 + render_motion,double_sided,focale,specular_light,specular_shine, 1.28032 + display_axes,pose_matrix); 1.28033 + } 1.28034 + 1.28035 + //! High-level interface for displaying a 3d object. 1.28036 + template<typename tp, typename tf, typename tc, typename to> 1.28037 + const CImg<T>& display_object3d(const char *const title, 1.28038 + const CImg<tp>& points, const CImgList<tf>& primitives, 1.28039 + const CImgList<tc>& colors, const to& opacities, 1.28040 + const bool centering=true, 1.28041 + const int render_static=4, const int render_motion=1, 1.28042 + const bool double_sided=false, const float focale=500, 1.28043 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.28044 + const bool display_axes=true, float *const pose_matrix=0) const { 1.28045 + CImgDisplay disp; 1.28046 + return _display_object3d(disp,title,points,points.width,primitives,colors,opacities,centering,render_static, 1.28047 + render_motion,double_sided,focale,specular_light,specular_shine, 1.28048 + display_axes,pose_matrix); 1.28049 + } 1.28050 + 1.28051 + //! High-level interface for displaying a 3d object. 1.28052 + template<typename tp, typename tf, typename tc, typename to> 1.28053 + const CImg<T>& display_object3d(CImgDisplay& disp, 1.28054 + const CImgList<tp>& points, const CImgList<tf>& primitives, 1.28055 + const CImgList<tc>& colors, const to& opacities, 1.28056 + const bool centering=true, 1.28057 + const int render_static=4, const int render_motion=1, 1.28058 + const bool double_sided=false, const float focale=500, 1.28059 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.28060 + const bool display_axes=true, float *const pose_matrix=0) const { 1.28061 + return _display_object3d(disp,0,points,points.size,primitives,colors,opacities,centering,render_static, 1.28062 + render_motion,double_sided,focale,specular_light,specular_shine, 1.28063 + display_axes,pose_matrix); 1.28064 + } 1.28065 + 1.28066 + //! High-level interface for displaying a 3d object. 1.28067 + template<typename tp, typename tf, typename tc, typename to> 1.28068 + const CImg<T>& display_object3d(const char *const title, 1.28069 + const CImgList<tp>& points, const CImgList<tf>& primitives, 1.28070 + const CImgList<tc>& colors, const to& opacities, 1.28071 + const bool centering=true, 1.28072 + const int render_static=4, const int render_motion=1, 1.28073 + const bool double_sided=false, const float focale=500, 1.28074 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.28075 + const bool display_axes=true, float *const pose_matrix=0) const { 1.28076 + CImgDisplay disp; 1.28077 + return _display_object3d(disp,title,points,points.size,primitives,colors,opacities,centering,render_static, 1.28078 + render_motion,double_sided,focale,specular_light,specular_shine, 1.28079 + display_axes,pose_matrix); 1.28080 + } 1.28081 + 1.28082 + //! High-level interface for displaying a 3d object. 1.28083 + template<typename tp, typename tf, typename tc> 1.28084 + const CImg<T>& display_object3d(CImgDisplay &disp, 1.28085 + const tp& points, const CImgList<tf>& primitives, 1.28086 + const CImgList<tc>& colors, 1.28087 + const bool centering=true, 1.28088 + const int render_static=4, const int render_motion=1, 1.28089 + const bool double_sided=false, const float focale=500, 1.28090 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.28091 + const bool display_axes=true, float *const pose_matrix=0) const { 1.28092 + return display_object3d(disp,points,primitives,colors,CImg<floatT>(),centering, 1.28093 + render_static,render_motion,double_sided,focale,specular_light,specular_shine, 1.28094 + display_axes,pose_matrix); 1.28095 + } 1.28096 + 1.28097 + //! High-level interface for displaying a 3d object. 1.28098 + template<typename tp, typename tf, typename tc> 1.28099 + const CImg<T>& display_object3d(const char *const title, 1.28100 + const tp& points, const CImgList<tf>& primitives, 1.28101 + const CImgList<tc>& colors, 1.28102 + const bool centering=true, 1.28103 + const int render_static=4, const int render_motion=1, 1.28104 + const bool double_sided=false, const float focale=500, 1.28105 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.28106 + const bool display_axes=true, float *const pose_matrix=0) const { 1.28107 + return display_object3d(title,points,primitives,colors,CImg<floatT>(),centering, 1.28108 + render_static,render_motion,double_sided,focale,specular_light,specular_shine, 1.28109 + display_axes,pose_matrix); 1.28110 + } 1.28111 + 1.28112 + //! High-level interface for displaying a 3d object. 1.28113 + template<typename tp, typename tf> 1.28114 + const CImg<T>& display_object3d(CImgDisplay &disp, 1.28115 + const tp& points, const CImgList<tf>& primitives, 1.28116 + const bool centering=true, 1.28117 + const int render_static=4, const int render_motion=1, 1.28118 + const bool double_sided=false, const float focale=500, 1.28119 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.28120 + const bool display_axes=true, float *const pose_matrix=0) const { 1.28121 + return display_object3d(disp,points,primitives,CImgList<T>(),centering, 1.28122 + render_static,render_motion,double_sided,focale,specular_light,specular_shine, 1.28123 + display_axes,pose_matrix); 1.28124 + } 1.28125 + 1.28126 + //! High-level interface for displaying a 3d object. 1.28127 + template<typename tp, typename tf> 1.28128 + const CImg<T>& display_object3d(const char *const title, 1.28129 + const tp& points, const CImgList<tf>& primitives, 1.28130 + const bool centering=true, 1.28131 + const int render_static=4, const int render_motion=1, 1.28132 + const bool double_sided=false, const float focale=500, 1.28133 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.28134 + const bool display_axes=true, float *const pose_matrix=0) const { 1.28135 + return display_object3d(title,points,primitives,CImgList<T>(),centering, 1.28136 + render_static,render_motion,double_sided,focale,specular_light,specular_shine, 1.28137 + display_axes,pose_matrix); 1.28138 + } 1.28139 + 1.28140 + //! High-level interface for displaying a 3d object. 1.28141 + template<typename tp> 1.28142 + const CImg<T>& display_object3d(CImgDisplay &disp, 1.28143 + const tp& points, 1.28144 + const bool centering=true, 1.28145 + const int render_static=4, const int render_motion=1, 1.28146 + const bool double_sided=false, const float focale=500, 1.28147 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.28148 + const bool display_axes=true, float *const pose_matrix=0) const { 1.28149 + return display_object3d(disp,points,CImgList<uintT>(),centering, 1.28150 + render_static,render_motion,double_sided,focale,specular_light,specular_shine, 1.28151 + display_axes,pose_matrix); 1.28152 + } 1.28153 + 1.28154 + //! High-level interface for displaying a 3d object. 1.28155 + template<typename tp> 1.28156 + const CImg<T>& display_object3d(const char *const title, 1.28157 + const tp& points, 1.28158 + const bool centering=true, 1.28159 + const int render_static=4, const int render_motion=1, 1.28160 + const bool double_sided=false, const float focale=500, 1.28161 + const float specular_light=0.2f, const float specular_shine=0.1f, 1.28162 + const bool display_axes=true, float *const pose_matrix=0) const { 1.28163 + return display_object3d(title,points,CImgList<uintT>(),centering, 1.28164 + render_static,render_motion,double_sided,focale,specular_light,specular_shine, 1.28165 + display_axes,pose_matrix); 1.28166 + } 1.28167 + 1.28168 + T _display_object3d_at2(const int i, const int j) const { 1.28169 + return atXY(i,j,0,0,0); 1.28170 + } 1.28171 + 1.28172 + template<typename tp, typename tf, typename tc, typename to> 1.28173 + const CImg<T>& _display_object3d(CImgDisplay& disp, const char *const title, 1.28174 + const tp& points, const unsigned int Npoints, 1.28175 + const CImgList<tf>& primitives, 1.28176 + const CImgList<tc>& colors, const to& opacities, 1.28177 + const bool centering, 1.28178 + const int render_static, const int render_motion, 1.28179 + const bool double_sided, const float focale, 1.28180 + const float specular_light, const float specular_shine, 1.28181 + const bool display_axes, float *const pose_matrix) const { 1.28182 + 1.28183 + // Check input arguments 1.28184 + if (!points || !Npoints) 1.28185 + throw CImgArgumentException("CImg<%s>::display_object3d() : Given points are empty.", 1.28186 + pixel_type()); 1.28187 + if (is_empty()) { 1.28188 + if (disp) return CImg<T>(disp.width,disp.height,1,colors[0].size(),0). 1.28189 + _display_object3d(disp,title,points,Npoints,primitives,colors,opacities,centering, 1.28190 + render_static,render_motion,double_sided,focale,specular_light,specular_shine, 1.28191 + display_axes,pose_matrix); 1.28192 + else return CImg<T>(cimg_fitscreen(640,480,1),1,colors[0].size(),0). 1.28193 + _display_object3d(disp,title,points,Npoints,primitives,colors,opacities,centering, 1.28194 + render_static,render_motion,double_sided,focale,specular_light,specular_shine, 1.28195 + display_axes,pose_matrix); 1.28196 + } 1.28197 + if (!primitives) { 1.28198 + CImgList<tf> nprimitives(Npoints,1,1,1,1); 1.28199 + cimglist_for(nprimitives,l) nprimitives(l,0) = l; 1.28200 + return _display_object3d(disp,title,points,Npoints,nprimitives,colors,opacities, 1.28201 + centering,render_static,render_motion,double_sided,focale,specular_light,specular_shine, 1.28202 + display_axes,pose_matrix); 1.28203 + } 1.28204 + if (!disp) { 1.28205 + char ntitle[64] = { 0 }; if (!title) { cimg_std::sprintf(ntitle,"CImg<%s>",pixel_type()); } 1.28206 + disp.assign(cimg_fitscreen(width,height,depth),title?title:ntitle,1); 1.28207 + } 1.28208 + 1.28209 + CImgList<tc> _colors; 1.28210 + if (!colors) _colors.insert(primitives.size,CImg<tc>::vector(200,200,200)); 1.28211 + const CImgList<tc> &ncolors = colors?colors:_colors; 1.28212 + 1.28213 + // Init 3D objects and compute object statistics 1.28214 + CImg<floatT> 1.28215 + pose, rot_mat, zbuffer, 1.28216 + centered_points = centering?CImg<floatT>(Npoints,3):CImg<floatT>(), 1.28217 + rotated_points(Npoints,3), 1.28218 + bbox_points, rotated_bbox_points, 1.28219 + axes_points, rotated_axes_points, 1.28220 + bbox_opacities, axes_opacities; 1.28221 + CImgList<uintT> bbox_primitives, axes_primitives; 1.28222 + CImgList<T> bbox_colors, bbox_colors2, axes_colors; 1.28223 + float dx = 0, dy = 0, dz = 0, ratio = 1; 1.28224 + 1.28225 + T minval = (T)0, maxval = (T)255; 1.28226 + if (disp.normalization && colors) { 1.28227 + minval = colors.minmax(maxval); 1.28228 + if (minval==maxval) { minval = (T)0; maxval = (T)255; } 1.28229 + } 1.28230 + const float meanval = (float)mean(); 1.28231 + bool color_model = true; 1.28232 + if (cimg::abs(meanval-minval)>cimg::abs(meanval-maxval)) color_model = false; 1.28233 + const CImg<T> 1.28234 + background_color(1,1,1,dim,color_model?minval:maxval), 1.28235 + foreground_color(1,1,1,dim,color_model?maxval:minval); 1.28236 + 1.28237 + float xm = cimg::type<float>::max(), xM = 0, ym = xm, yM = 0, zm = xm, zM = 0; 1.28238 + for (unsigned int i = 0; i<Npoints; ++i) { 1.28239 + const float 1.28240 + x = points._display_object3d_at2(i,0), 1.28241 + y = points._display_object3d_at2(i,1), 1.28242 + z = points._display_object3d_at2(i,2); 1.28243 + if (x<xm) xm = x; 1.28244 + if (x>xM) xM = x; 1.28245 + if (y<ym) ym = y; 1.28246 + if (y>yM) yM = y; 1.28247 + if (z<zm) zm = z; 1.28248 + if (z>zM) zM = z; 1.28249 + } 1.28250 + const float delta = cimg::max(xM-xm,yM-ym,zM-zm); 1.28251 + 1.28252 + if (display_axes) { 1.28253 + rotated_axes_points = axes_points.assign(7,3,1,1, 1.28254 + 0,20,0,0,22,-6,-6, 1.28255 + 0,0,20,0,-6,22,-6, 1.28256 + 0,0,0,20,0,0,22); 1.28257 + axes_opacities.assign(3,1,1,1,1); 1.28258 + axes_colors.assign(3,dim,1,1,1,foreground_color[0]); 1.28259 + axes_primitives.assign(3,1,2,1,1, 0,1, 0,2, 0,3); 1.28260 + } 1.28261 + 1.28262 + // Begin user interaction loop 1.28263 + CImg<T> visu0(*this), visu; 1.28264 + bool init = true, clicked = false, redraw = true; 1.28265 + unsigned int key = 0; 1.28266 + int x0 = 0, y0 = 0, x1 = 0, y1 = 0; 1.28267 + disp.show().flush(); 1.28268 + 1.28269 + while (!disp.is_closed && !key) { 1.28270 + 1.28271 + // Init object position and scale if necessary 1.28272 + if (init) { 1.28273 + ratio = delta>0?(2.0f*cimg::min(disp.width,disp.height)/(3.0f*delta)):0; 1.28274 + dx = 0.5f*(xM + xm); dy = 0.5f*(yM + ym); dz = 0.5f*(zM + zm); 1.28275 + if (centering) { 1.28276 + cimg_forX(centered_points,l) { 1.28277 + centered_points(l,0) = (float)((points(l,0) - dx)*ratio); 1.28278 + centered_points(l,1) = (float)((points(l,1) - dy)*ratio); 1.28279 + centered_points(l,2) = (float)((points(l,2) - dz)*ratio); 1.28280 + } 1.28281 + } 1.28282 + 1.28283 + if (render_static<0 || render_motion<0) { 1.28284 + rotated_bbox_points = bbox_points.assign(8,3,1,1, 1.28285 + xm,xM,xM,xm,xm,xM,xM,xm, 1.28286 + ym,ym,yM,yM,ym,ym,yM,yM, 1.28287 + zm,zm,zm,zm,zM,zM,zM,zM); 1.28288 + 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); 1.28289 + bbox_colors.assign(6,dim,1,1,1,background_color[0]); 1.28290 + bbox_colors2.assign(6,dim,1,1,1,foreground_color[0]); 1.28291 + bbox_opacities.assign(bbox_colors.size,1,1,1,0.3f); 1.28292 + } 1.28293 + 1.28294 + if (!pose) { 1.28295 + if (pose_matrix) pose = CImg<floatT>(pose_matrix,4,4,1,1,false); 1.28296 + else pose = CImg<floatT>::identity_matrix(4); 1.28297 + } 1.28298 + init = false; 1.28299 + redraw = true; 1.28300 + } 1.28301 + 1.28302 + // Rotate and Draw 3D object 1.28303 + if (redraw) { 1.28304 + const float 1.28305 + r00 = pose(0,0), r10 = pose(1,0), r20 = pose(2,0), r30 = pose(3,0), 1.28306 + r01 = pose(0,1), r11 = pose(1,1), r21 = pose(2,1), r31 = pose(3,1), 1.28307 + r02 = pose(0,2), r12 = pose(1,2), r22 = pose(2,2), r32 = pose(3,2); 1.28308 + if ((clicked && render_motion>=0) || (!clicked && render_static>=0)) { 1.28309 + if (centering) cimg_forX(centered_points,l) { 1.28310 + const float x = centered_points(l,0), y = centered_points(l,1), z = centered_points(l,2); 1.28311 + rotated_points(l,0) = r00*x + r10*y + r20*z + r30; 1.28312 + rotated_points(l,1) = r01*x + r11*y + r21*z + r31; 1.28313 + rotated_points(l,2) = r02*x + r12*y + r22*z + r32; 1.28314 + } else for (unsigned int l = 0; l<Npoints; ++l) { 1.28315 + const float 1.28316 + x = (float)points._display_object3d_at2(l,0), 1.28317 + y = (float)points._display_object3d_at2(l,1), 1.28318 + z = (float)points._display_object3d_at2(l,2); 1.28319 + rotated_points(l,0) = r00*x + r10*y + r20*z + r30; 1.28320 + rotated_points(l,1) = r01*x + r11*y + r21*z + r31; 1.28321 + rotated_points(l,2) = r02*x + r12*y + r22*z + r32; 1.28322 + } 1.28323 + } else { 1.28324 + if (!centering) cimg_forX(bbox_points,l) { 1.28325 + const float x = bbox_points(l,0), y = bbox_points(l,1), z = bbox_points(l,2); 1.28326 + rotated_bbox_points(l,0) = r00*x + r10*y + r20*z + r30; 1.28327 + rotated_bbox_points(l,1) = r01*x + r11*y + r21*z + r31; 1.28328 + rotated_bbox_points(l,2) = r02*x + r12*y + r22*z + r32; 1.28329 + } else cimg_forX(bbox_points,l) { 1.28330 + const float x = (bbox_points(l,0)-dx)*ratio, y = (bbox_points(l,1)-dy)*ratio, z = (bbox_points(l,2)-dz)*ratio; 1.28331 + rotated_bbox_points(l,0) = r00*x + r10*y + r20*z + r30; 1.28332 + rotated_bbox_points(l,1) = r01*x + r11*y + r21*z + r31; 1.28333 + rotated_bbox_points(l,2) = r02*x + r12*y + r22*z + r32; 1.28334 + } 1.28335 + } 1.28336 + 1.28337 + // Draw object 1.28338 + visu = visu0; 1.28339 + if ((clicked && render_motion<0) || (!clicked && render_static<0)) 1.28340 + visu.draw_object3d(visu.width/2.0f,visu.height/2.0f,0,rotated_bbox_points,bbox_primitives,bbox_colors,bbox_opacities,2,false,focale). 1.28341 + draw_object3d(visu.width/2.0f,visu.height/2.0f,0,rotated_bbox_points,bbox_primitives,bbox_colors2,1,false,focale); 1.28342 + else visu.draw_object3d(visu.width/2.0f,visu.height/2.0f,0, 1.28343 + rotated_points,primitives,ncolors,opacities,clicked?render_motion:render_static, 1.28344 + double_sided,focale,visu.dimx()/2.0f,visu.dimy()/2.0f,-5000,specular_light,specular_shine, 1.28345 + (!clicked && render_static>0)?zbuffer.fill(0).ptr():0); 1.28346 + 1.28347 + // Draw axes 1.28348 + if (display_axes) { 1.28349 + const float Xaxes = 25, Yaxes = visu.height - 35.0f; 1.28350 + cimg_forX(axes_points,l) { 1.28351 + const float x = axes_points(l,0), y = axes_points(l,1), z = axes_points(l,2); 1.28352 + rotated_axes_points(l,0) = r00*x + r10*y + r20*z; 1.28353 + rotated_axes_points(l,1) = r01*x + r11*y + r21*z; 1.28354 + rotated_axes_points(l,2) = r02*x + r12*y + r22*z; 1.28355 + } 1.28356 + axes_opacities(0,0) = (rotated_axes_points(1,2)>0)?0.5f:1.0f; 1.28357 + axes_opacities(1,0) = (rotated_axes_points(2,2)>0)?0.5f:1.0f; 1.28358 + axes_opacities(2,0) = (rotated_axes_points(3,2)>0)?0.5f:1.0f; 1.28359 + visu.draw_object3d(Xaxes,Yaxes,0,rotated_axes_points,axes_primitives,axes_colors,axes_opacities,1,false,focale). 1.28360 + draw_text((int)(Xaxes+rotated_axes_points(4,0)), 1.28361 + (int)(Yaxes+rotated_axes_points(4,1)), 1.28362 + "X",axes_colors[0].data,0,axes_opacities(0,0),11). 1.28363 + draw_text((int)(Xaxes+rotated_axes_points(5,0)), 1.28364 + (int)(Yaxes+rotated_axes_points(5,1)), 1.28365 + "Y",axes_colors[1].data,0,axes_opacities(1,0),11). 1.28366 + draw_text((int)(Xaxes+rotated_axes_points(6,0)), 1.28367 + (int)(Yaxes+rotated_axes_points(6,1)), 1.28368 + "Z",axes_colors[2].data,0,axes_opacities(2,0),11); 1.28369 + } 1.28370 + visu.display(disp); 1.28371 + if (!clicked || render_motion==render_static) redraw = false; 1.28372 + } 1.28373 + 1.28374 + // Handle user interaction 1.28375 + disp.wait(); 1.28376 + if ((disp.button || disp.wheel) && disp.mouse_x>=0 && disp.mouse_y>=0) { 1.28377 + redraw = true; 1.28378 + if (!clicked) { x0 = x1 = disp.mouse_x; y0 = y1 = disp.mouse_y; if (!disp.wheel) clicked = true; } 1.28379 + else { x1 = disp.mouse_x; y1 = disp.mouse_y; } 1.28380 + if (disp.button&1) { 1.28381 + const float 1.28382 + R = 0.45f*cimg::min(disp.width,disp.height), 1.28383 + R2 = R*R, 1.28384 + u0 = (float)(x0-disp.dimx()/2), 1.28385 + v0 = (float)(y0-disp.dimy()/2), 1.28386 + u1 = (float)(x1-disp.dimx()/2), 1.28387 + v1 = (float)(y1-disp.dimy()/2), 1.28388 + n0 = (float)cimg_std::sqrt(u0*u0+v0*v0), 1.28389 + n1 = (float)cimg_std::sqrt(u1*u1+v1*v1), 1.28390 + nu0 = n0>R?(u0*R/n0):u0, 1.28391 + nv0 = n0>R?(v0*R/n0):v0, 1.28392 + nw0 = (float)cimg_std::sqrt(cimg::max(0,R2-nu0*nu0-nv0*nv0)), 1.28393 + nu1 = n1>R?(u1*R/n1):u1, 1.28394 + nv1 = n1>R?(v1*R/n1):v1, 1.28395 + nw1 = (float)cimg_std::sqrt(cimg::max(0,R2-nu1*nu1-nv1*nv1)), 1.28396 + u = nv0*nw1-nw0*nv1, 1.28397 + v = nw0*nu1-nu0*nw1, 1.28398 + w = nv0*nu1-nu0*nv1, 1.28399 + n = (float)cimg_std::sqrt(u*u+v*v+w*w), 1.28400 + alpha = (float)cimg_std::asin(n/R2); 1.28401 + rot_mat = CImg<floatT>::rotation_matrix(u,v,w,alpha); 1.28402 + rot_mat *= pose.get_crop(0,0,2,2); 1.28403 + pose.draw_image(rot_mat); 1.28404 + x0=x1; y0=y1; 1.28405 + } 1.28406 + if (disp.button&2) { pose(3,2)+=(y1-y0); x0 = x1; y0 = y1; } 1.28407 + if (disp.wheel) { pose(3,2)-=focale*disp.wheel/10; disp.wheel = 0; } 1.28408 + if (disp.button&4) { pose(3,0)+=(x1-x0); pose(3,1)+=(y1-y0); x0 = x1; y0 = y1; } 1.28409 + if ((disp.button&1) && (disp.button&2)) { init = true; disp.button = 0; x0 = x1; y0 = y1; pose = CImg<floatT>::identity_matrix(4); } 1.28410 + } else if (clicked) { x0 = x1; y0 = y1; clicked = false; redraw = true; } 1.28411 + 1.28412 + switch (key = disp.key) { 1.28413 + case 0 : case cimg::keyCTRLLEFT : disp.key = key = 0; break; 1.28414 + case cimg::keyD: if (disp.is_keyCTRLLEFT) { 1.28415 + disp.normalscreen().resize(CImgDisplay::_fitscreen(3*disp.width/2,3*disp.height/2,1,128,-100,false), 1.28416 + CImgDisplay::_fitscreen(3*disp.width/2,3*disp.height/2,1,128,-100,true),false).is_resized = true; 1.28417 + disp.key = key = 0; 1.28418 + } break; 1.28419 + case cimg::keyC : if (disp.is_keyCTRLLEFT) { 1.28420 + disp.normalscreen().resize(cimg_fitscreen(2*disp.width/3,2*disp.height/3,1),false).is_resized = true; 1.28421 + disp.key = key = 0; 1.28422 + } break; 1.28423 + case cimg::keyR : if (disp.is_keyCTRLLEFT) { 1.28424 + disp.normalscreen().resize(cimg_fitscreen(width,height,depth),false).is_resized = true; 1.28425 + disp.key = key = 0; 1.28426 + } break; 1.28427 + case cimg::keyF : if (disp.is_keyCTRLLEFT) { 1.28428 + disp.resize(disp.screen_dimx(),disp.screen_dimy()).toggle_fullscreen().is_resized = true; 1.28429 + disp.key = key = 0; 1.28430 + } break; 1.28431 + case cimg::keyZ : if (disp.is_keyCTRLLEFT) { // Enable/Disable Z-buffer 1.28432 + if (zbuffer) zbuffer.assign(); 1.28433 + else zbuffer.assign(disp.width,disp.height); 1.28434 + disp.key = key = 0; redraw = true; 1.28435 + } break; 1.28436 + case cimg::keyS : if (disp.is_keyCTRLLEFT) { // Save snapshot 1.28437 + static unsigned int snap_number = 0; 1.28438 + char filename[32] = { 0 }; 1.28439 + cimg_std::FILE *file; 1.28440 + do { 1.28441 + cimg_std::sprintf(filename,"CImg_%.4u.bmp",snap_number++); 1.28442 + if ((file=cimg_std::fopen(filename,"r"))!=0) cimg_std::fclose(file); 1.28443 + } while (file); 1.28444 + (+visu).draw_text(2,2,"Saving BMP snapshot...",foreground_color,background_color,1,11).display(disp); 1.28445 + visu.save(filename); 1.28446 + visu.draw_text(2,2,"Snapshot '%s' saved.",foreground_color,background_color,1,11,filename).display(disp); 1.28447 + disp.key = key = 0; 1.28448 + } break; 1.28449 + case cimg::keyO : if (disp.is_keyCTRLLEFT) { // Save object as an .OFF file 1.28450 + static unsigned int snap_number = 0; 1.28451 + char filename[32] = { 0 }; 1.28452 + cimg_std::FILE *file; 1.28453 + do { 1.28454 + cimg_std::sprintf(filename,"CImg_%.4u.off",snap_number++); 1.28455 + if ((file=cimg_std::fopen(filename,"r"))!=0) cimg_std::fclose(file); 1.28456 + } while (file); 1.28457 + visu.draw_text(2,2,"Saving object...",foreground_color,background_color,1,11).display(disp); 1.28458 + points.save_off(filename,primitives,ncolors); 1.28459 + visu.draw_text(2,2,"Object '%s' saved.",foreground_color,background_color,1,11,filename).display(disp); 1.28460 + disp.key = key = 0; 1.28461 + } break; 1.28462 +#ifdef cimg_use_board 1.28463 + case cimg::keyP : if (disp.is_keyCTRLLEFT) { // Save object as a .EPS file 1.28464 + static unsigned int snap_number = 0; 1.28465 + char filename[32] = { 0 }; 1.28466 + cimg_std::FILE *file; 1.28467 + do { 1.28468 + cimg_std::sprintf(filename,"CImg_%.4u.eps",snap_number++); 1.28469 + if ((file=cimg_std::fopen(filename,"r"))!=0) cimg_std::fclose(file); 1.28470 + } while (file); 1.28471 + visu.draw_text(2,2,"Saving EPS snapshot...",foreground_color,background_color,1,11).display(disp); 1.28472 + BoardLib::Board board; 1.28473 + (+visu).draw_object3d(board,visu.width/2.0f, visu.height/2.0f, 0, 1.28474 + rotated_points,primitives,ncolors,opacities,clicked?render_motion:render_static, 1.28475 + double_sided,focale,visu.dimx()/2.0f,visu.dimy()/2.0f,-5000,specular_light,specular_shine, 1.28476 + zbuffer.fill(0).ptr()); 1.28477 + board.saveEPS(filename); 1.28478 + visu.draw_text(2,2,"Object '%s' saved.",foreground_color,background_color,1,11,filename).display(disp); 1.28479 + disp.key = key = 0; 1.28480 + } break; 1.28481 + case cimg::keyV : if (disp.is_keyCTRLLEFT) { // Save object as a .SVG file 1.28482 + static unsigned int snap_number = 0; 1.28483 + char filename[32] = { 0 }; 1.28484 + cimg_std::FILE *file; 1.28485 + do { 1.28486 + cimg_std::sprintf(filename,"CImg_%.4u.svg",snap_number++); 1.28487 + if ((file=cimg_std::fopen(filename,"r"))!=0) cimg_std::fclose(file); 1.28488 + } while (file); 1.28489 + visu.draw_text(2,2,"Saving SVG snapshot...",foreground_color,background_color,1,11).display(disp); 1.28490 + BoardLib::Board board; 1.28491 + (+visu).draw_object3d(board,visu.width/2.0f, visu.height/2.0f, 0, 1.28492 + rotated_points,primitives,ncolors,opacities,clicked?render_motion:render_static, 1.28493 + double_sided,focale,visu.dimx()/2.0f,visu.dimy()/2.0f,-5000,specular_light,specular_shine, 1.28494 + zbuffer.fill(0).ptr()); 1.28495 + board.saveSVG(filename); 1.28496 + visu.draw_text(2,2,"Object '%s' saved.",foreground_color,background_color,1,11,filename).display(disp); 1.28497 + disp.key = key = 0; 1.28498 + } break; 1.28499 +#endif 1.28500 + } 1.28501 + if (disp.is_resized) { disp.resize(false); visu0 = get_resize(disp,1); if (zbuffer) zbuffer.assign(disp.width,disp.height); redraw = true; } 1.28502 + } 1.28503 + if (pose_matrix) cimg_std::memcpy(pose_matrix,pose.data,16*sizeof(float)); 1.28504 + disp.button = 0; 1.28505 + disp.key = key; 1.28506 + return *this; 1.28507 + } 1.28508 + 1.28509 + //! High-level interface for displaying a graph. 1.28510 + const CImg<T>& display_graph(CImgDisplay &disp, 1.28511 + const unsigned int plot_type=1, const unsigned int vertex_type=1, 1.28512 + const char *const labelx=0, const double xmin=0, const double xmax=0, 1.28513 + const char *const labely=0, const double ymin=0, const double ymax=0) const { 1.28514 + if (is_empty()) 1.28515 + throw CImgInstanceException("CImg<%s>::display_graph() : Instance image (%u,%u,%u,%u,%p) is empty.", 1.28516 + pixel_type(),width,height,depth,dim,data); 1.28517 + const unsigned int siz = width*height*depth, onormalization = disp.normalization; 1.28518 + if (!disp) { char ntitle[64] = { 0 }; cimg_std::sprintf(ntitle,"CImg<%s>",pixel_type()); disp.assign(640,480,ntitle,0); } 1.28519 + disp.show().flush().normalization = 0; 1.28520 + double y0 = ymin, y1 = ymax, nxmin = xmin, nxmax = xmax; 1.28521 + if (nxmin==nxmax) { nxmin = 0; nxmax = siz - 1.0; } 1.28522 + int x0 = 0, x1 = size()/dimv()-1, key = 0; 1.28523 + 1.28524 + for (bool reset_view = true, resize_disp = false; !key && !disp.is_closed; ) { 1.28525 + if (reset_view) { x0 = 0; x1 = size()/dimv()-1; y0 = ymin; y1 = ymax; reset_view = false; } 1.28526 + CImg<T> zoom(x1-x0+1,1,1,dimv()); 1.28527 + cimg_forV(*this,k) zoom.get_shared_channel(k) = CImg<T>(ptr(x0,0,0,k),x1-x0+1,1,1,1,true); 1.28528 + 1.28529 + if (y0==y1) y0 = zoom.minmax(y1); 1.28530 + if (y0==y1) { --y0; ++y1; } 1.28531 + const CImg<intT> selection = zoom.get_select_graph(disp,plot_type,vertex_type, 1.28532 + labelx,nxmin + x0*(nxmax-nxmin)/siz,nxmin + x1*(nxmax-nxmin)/siz, 1.28533 + labely,y0,y1); 1.28534 + 1.28535 + const int mouse_x = disp.mouse_x, mouse_y = disp.mouse_y; 1.28536 + if (selection[0]>=0 && selection[2]>=0) { 1.28537 + x1 = x0 + selection[2]; 1.28538 + x0 += selection[0]; 1.28539 + if (x0==x1) reset_view = true; 1.28540 + if (selection[1]>=0 && selection[3]>=0) { 1.28541 + y0 = y1 - selection[3]*(y1-y0)/(disp.dimy()-32); 1.28542 + y1 -= selection[1]*(y1-y0)/(disp.dimy()-32); 1.28543 + } 1.28544 + } else { 1.28545 + bool go_in = false, go_out = false, go_left = false, go_right = false, go_up = false, go_down = false; 1.28546 + switch (key = disp.key) { 1.28547 + case cimg::keyHOME : case cimg::keyBACKSPACE : reset_view = resize_disp = true; key = 0; break; 1.28548 + case cimg::keyPADADD : go_in = true; key = 0; break; 1.28549 + case cimg::keyPADSUB : go_out = true; key = 0; break; 1.28550 + case cimg::keyARROWLEFT : case cimg::keyPAD4 : go_left = true; key = 0; break; 1.28551 + case cimg::keyARROWRIGHT : case cimg::keyPAD6 : go_right = true; key = 0; break; 1.28552 + case cimg::keyARROWUP : case cimg::keyPAD8 : go_up = true; key = 0; break; 1.28553 + case cimg::keyARROWDOWN : case cimg::keyPAD2 : go_down = true; key = 0; break; 1.28554 + case cimg::keyPAD7 : go_left = true; go_up = true; key = 0; break; 1.28555 + case cimg::keyPAD9 : go_right = true; go_up = true; key = 0; break; 1.28556 + case cimg::keyPAD1 : go_left = true; go_down = true; key = 0; break; 1.28557 + case cimg::keyPAD3 : go_right = true; go_down = true; key = 0; break; 1.28558 + } 1.28559 + if (disp.wheel) go_out = !(go_in = disp.wheel>0); 1.28560 + 1.28561 + if (go_in) { 1.28562 + const int 1.28563 + xsiz = x1 - x0, 1.28564 + mx = (mouse_x-16)*xsiz/(disp.dimx()-32), 1.28565 + cx = x0 + (mx<0?0:(mx>=xsiz?xsiz:mx)); 1.28566 + if (x1-x0>4) { 1.28567 + x0 = cx - 7*(cx-x0)/8; x1 = cx + 7*(x1-cx)/8; 1.28568 + if (disp.is_keyCTRLLEFT) { 1.28569 + const double 1.28570 + ysiz = y1 - y0, 1.28571 + my = (mouse_y-16)*ysiz/(disp.dimy()-32), 1.28572 + cy = y1 - (my<0?0:(my>=ysiz?ysiz:my)); 1.28573 + y0 = cy - 7*(cy-y0)/8; y1 = cy + 7*(y1-cy)/8; 1.28574 + } else y0 = y1 = 0; 1.28575 + } 1.28576 + } 1.28577 + if (go_out) { 1.28578 + const int deltax = (x1-x0)/8, ndeltax = deltax?deltax:(siz>1?1:0); 1.28579 + x0-=ndeltax; x1+=ndeltax; 1.28580 + if (x0<0) { x1-=x0; x0 = 0; if (x1>=(int)siz) x1 = (int)siz-1; } 1.28581 + if (x1>=(int)siz) { x0-=(x1-siz+1); x1 = (int)siz-1; if (x0<0) x0 = 0; } 1.28582 + if (disp.is_keyCTRLLEFT) { 1.28583 + const double deltay = (y1-y0)/8, ndeltay = deltay?deltay:0.01; 1.28584 + y0-=ndeltay; y1+=ndeltay; 1.28585 + } 1.28586 + } 1.28587 + if (go_left) { 1.28588 + const int delta = (x1-x0)/5, ndelta = delta?delta:1; 1.28589 + if (x0-ndelta>=0) { x0-=ndelta; x1-=ndelta; } 1.28590 + else { x1-=x0; x0 = 0; } 1.28591 + go_left = false; 1.28592 + } 1.28593 + if (go_right) { 1.28594 + const int delta = (x1-x0)/5, ndelta = delta?delta:1; 1.28595 + if (x1+ndelta<(int)siz) { x0+=ndelta; x1+=ndelta; } 1.28596 + else { x0+=(siz-1-x1); x1 = siz-1; } 1.28597 + go_right = false; 1.28598 + } 1.28599 + if (go_up) { 1.28600 + const double delta = (y1-y0)/10, ndelta = delta?delta:1; 1.28601 + y0+=ndelta; y1+=ndelta; 1.28602 + go_up = false; 1.28603 + } 1.28604 + if (go_down) { 1.28605 + const double delta = (y1-y0)/10, ndelta = delta?delta:1; 1.28606 + y0-=ndelta; y1-=ndelta; 1.28607 + go_down = false; 1.28608 + } 1.28609 + } 1.28610 + } 1.28611 + disp.normalization = onormalization; 1.28612 + return *this; 1.28613 + } 1.28614 + 1.28615 + //! High-level interface for displaying a graph. 1.28616 + const CImg<T>& display_graph(const char *const title=0, 1.28617 + const unsigned int plot_type=1, const unsigned int vertex_type=1, 1.28618 + const char *const labelx=0, const double xmin=0, const double xmax=0, 1.28619 + const char *const labely=0, const double ymin=0, const double ymax=0) const { 1.28620 + if (is_empty()) 1.28621 + throw CImgInstanceException("CImg<%s>::display_graph() : Instance image (%u,%u,%u,%u,%p) is empty.", 1.28622 + pixel_type(),width,height,depth,dim,data); 1.28623 + char ntitle[64] = { 0 }; if (!title) cimg_std::sprintf(ntitle,"CImg<%s>",pixel_type()); 1.28624 + CImgDisplay disp(cimg_fitscreen(640,480,1),title?title:ntitle,0); 1.28625 + return display_graph(disp,plot_type,vertex_type,labelx,xmin,xmax,labely,ymin,ymax); 1.28626 + } 1.28627 + 1.28628 + //! Select sub-graph in a graph. 1.28629 + CImg<intT> get_select_graph(CImgDisplay &disp, 1.28630 + const unsigned int plot_type=1, const unsigned int vertex_type=1, 1.28631 + const char *const labelx=0, const double xmin=0, const double xmax=0, 1.28632 + const char *const labely=0, const double ymin=0, const double ymax=0) const { 1.28633 + if (is_empty()) 1.28634 + throw CImgInstanceException("CImg<%s>::display_graph() : Instance image (%u,%u,%u,%u,%p) is empty.", 1.28635 + pixel_type(),width,height,depth,dim,data); 1.28636 + const unsigned int siz = width*height*depth, onormalization = disp.normalization; 1.28637 + if (!disp) { char ntitle[64] = { 0 }; cimg_std::sprintf(ntitle,"CImg<%s>",pixel_type()); disp.assign(640,480,ntitle,0); } 1.28638 + disp.show().key = disp.normalization = disp.button = disp.wheel = 0; // Must keep 'key' field unchanged. 1.28639 + double nymin = ymin, nymax = ymax, nxmin = xmin, nxmax = xmax; 1.28640 + if (nymin==nymax) nymin = (Tfloat)minmax(nymax); 1.28641 + if (nymin==nymax) { --nymin; ++nymax; } 1.28642 + if (nxmin==nxmax && nxmin==0) { nxmin = 0; nxmax = siz - 1.0; } 1.28643 + 1.28644 + const unsigned char black[] = { 0,0,0 }, white[] = { 255,255,255 }, gray[] = { 220,220,220 }; 1.28645 + const unsigned char gray2[] = { 110,110,110 }, ngray[] = { 35,35,35 }; 1.28646 + static unsigned int odimv = 0; 1.28647 + static CImg<ucharT> palette; 1.28648 + if (odimv!=dim) { 1.28649 + odimv = dim; 1.28650 + palette = CImg<ucharT>(3,dim,1,1,120).noise(70,1); 1.28651 + if (dim==1) { palette[0] = palette[1] = 120; palette[2] = 200; } 1.28652 + else { 1.28653 + palette(0,0) = 220; palette(1,0) = 10; palette(2,0) = 10; 1.28654 + if (dim>1) { palette(0,1) = 10; palette(1,1) = 220; palette(2,1) = 10; } 1.28655 + if (dim>2) { palette(0,2) = 10; palette(1,2) = 10; palette(2,2) = 220; } 1.28656 + } 1.28657 + } 1.28658 + 1.28659 + CImg<ucharT> visu0, visu, graph, text, axes; 1.28660 + const unsigned int whz = width*height*depth; 1.28661 + int x0 = -1, x1 = -1, y0 = -1, y1 = -1, omouse_x = -2, omouse_y = -2; 1.28662 + char message[1024] = { 0 }; 1.28663 + unsigned int okey = 0, obutton = 0; 1.28664 + CImg_3x3(I,unsigned char); 1.28665 + 1.28666 + for (bool selected = false; !selected && !disp.is_closed && !okey && !disp.wheel; ) { 1.28667 + const int mouse_x = disp.mouse_x, mouse_y = disp.mouse_y; 1.28668 + const unsigned int key = disp.key, button = disp.button; 1.28669 + 1.28670 + // Generate graph representation. 1.28671 + if (!visu0) { 1.28672 + visu0.assign(disp.dimx(),disp.dimy(),1,3,220); 1.28673 + const int gdimx = disp.dimx() - 32, gdimy = disp.dimy() - 32; 1.28674 + if (gdimx>0 && gdimy>0) { 1.28675 + graph.assign(gdimx,gdimy,1,3,255); 1.28676 + graph.draw_grid(-10,-10,0,0,false,true,black,0.2f,0x33333333,0x33333333); 1.28677 + cimg_forV(*this,k) graph.draw_graph(get_shared_channel(k),&palette(0,k),(plot_type!=3 || dim==1)?1:0.6f, 1.28678 + plot_type,vertex_type,nymax,nymin); 1.28679 + 1.28680 + axes.assign(gdimx,gdimy,1,1,0); 1.28681 + const float 1.28682 + dx = (float)cimg::abs(nxmax-nxmin), dy = (float)cimg::abs(nymax-nymin), 1.28683 + px = (float)cimg_std::pow(10.0,(int)cimg_std::log10(dx)-2.0), 1.28684 + py = (float)cimg_std::pow(10.0,(int)cimg_std::log10(dy)-2.0); 1.28685 + const CImg<Tdouble> 1.28686 + seqx = CImg<Tdouble>::sequence(1 + gdimx/60,nxmin,nxmax).round(px), 1.28687 + seqy = CImg<Tdouble>::sequence(1 + gdimy/60,nymax,nymin).round(py); 1.28688 + axes.draw_axis(seqx,seqy,white); 1.28689 + if (nymin>0) axes.draw_axis(seqx,gdimy-1,gray); 1.28690 + if (nymax<0) axes.draw_axis(seqx,0,gray); 1.28691 + if (nxmin>0) axes.draw_axis(0,seqy,gray); 1.28692 + if (nxmax<0) axes.draw_axis(gdimx-1,seqy,gray); 1.28693 + 1.28694 + cimg_for3x3(axes,x,y,0,0,I) 1.28695 + if (Icc) { 1.28696 + if (Icc==255) cimg_forV(graph,k) graph(x,y,k) = 0; 1.28697 + else cimg_forV(graph,k) graph(x,y,k) = (unsigned char)(2*graph(x,y,k)/3); 1.28698 + } 1.28699 + else if (Ipc || Inc || Icp || Icn || Ipp || Inn || Ipn || Inp) cimg_forV(graph,k) graph(x,y,k) = (graph(x,y,k)+255)/2; 1.28700 + 1.28701 + visu0.draw_image(16,16,graph); 1.28702 + visu0.draw_line(15,15,16+gdimx,15,gray2).draw_line(16+gdimx,15,16+gdimx,16+gdimy,gray2). 1.28703 + draw_line(16+gdimx,16+gdimy,15,16+gdimy,white).draw_line(15,16+gdimy,15,15,white); 1.28704 + } else graph.assign(); 1.28705 + text.assign().draw_text(0,0,labelx?labelx:"X-axis",white,ngray,1); 1.28706 + visu0.draw_image((visu0.dimx()-text.dimx())/2,visu0.dimy()-14,~text); 1.28707 + text.assign().draw_text(0,0,labely?labely:"Y-axis",white,ngray,1).rotate(-90); 1.28708 + visu0.draw_image(2,(visu0.dimy()-text.dimy())/2,~text); 1.28709 + visu.assign(); 1.28710 + } 1.28711 + 1.28712 + // Generate and display current view. 1.28713 + if (!visu) { 1.28714 + visu.assign(visu0); 1.28715 + if (graph && x0>=0 && x1>=0) { 1.28716 + const int 1.28717 + nx0 = x0<=x1?x0:x1, 1.28718 + nx1 = x0<=x1?x1:x0, 1.28719 + ny0 = y0<=y1?y0:y1, 1.28720 + ny1 = y0<=y1?y1:y0, 1.28721 + sx0 = 16 + nx0*(visu.dimx()-32)/whz, 1.28722 + sx1 = 15 + (nx1+1)*(visu.dimx()-32)/whz, 1.28723 + sy0 = 16 + ny0, 1.28724 + sy1 = 16 + ny1; 1.28725 + 1.28726 + if (y0>=0 && y1>=0) 1.28727 + visu.draw_rectangle(sx0,sy0,sx1,sy1,gray,0.5f).draw_rectangle(sx0,sy0,sx1,sy1,black,0.5f,0xCCCCCCCCU); 1.28728 + else visu.draw_rectangle(sx0,0,sx1,visu.dimy()-17,gray,0.5f). 1.28729 + draw_line(sx0,16,sx0,visu.dimy()-17,black,0.5f,0xCCCCCCCCU). 1.28730 + draw_line(sx1,16,sx1,visu.dimy()-17,black,0.5f,0xCCCCCCCCU); 1.28731 + } 1.28732 + if (mouse_x>=16 && mouse_y>=16 && mouse_x<visu.dimx()-16 && mouse_y<visu.dimy()-16) { 1.28733 + if (graph) visu.draw_line(mouse_x,16,mouse_x,visu.dimy()-17,black,0.5f,0x55555555U); 1.28734 + const unsigned x = (mouse_x-16)*whz/(disp.dimx()-32); 1.28735 + const double cx = nxmin + x*(nxmax-nxmin)/whz; 1.28736 + if (dim>=7) 1.28737 + cimg_std::sprintf(message,"Value[%g] = ( %g %g %g ... %g %g %g )",cx, 1.28738 + (double)(*this)(x,0,0,0),(double)(*this)(x,0,0,1),(double)(*this)(x,0,0,2), 1.28739 + (double)(*this)(x,0,0,dim-4),(double)(*this)(x,0,0,dim-3),(double)(*this)(x,0,0,dim-1)); 1.28740 + else { 1.28741 + cimg_std::sprintf(message,"Value[%g] = ( ",cx); 1.28742 + cimg_forV(*this,k) cimg_std::sprintf(message+cimg::strlen(message),"%g ",(double)(*this)(x,0,0,k)); 1.28743 + cimg_std::sprintf(message+cimg::strlen(message),")"); 1.28744 + } 1.28745 + if (x0>=0 && x1>=0) { 1.28746 + const int 1.28747 + nx0 = x0<=x1?x0:x1, 1.28748 + nx1 = x0<=x1?x1:x0, 1.28749 + ny0 = y0<=y1?y0:y1, 1.28750 + ny1 = y0<=y1?y1:y0; 1.28751 + const double 1.28752 + cx0 = nxmin + nx0*(nxmax-nxmin)/(visu.dimx()-32), 1.28753 + cx1 = nxmin + nx1*(nxmax-nxmin)/(visu.dimx()-32), 1.28754 + cy0 = nymax - ny0*(nymax-nymin)/(visu.dimy()-32), 1.28755 + cy1 = nymax - ny1*(nymax-nymin)/(visu.dimy()-32); 1.28756 + if (y0>=0 && y1>=0) 1.28757 + cimg_std::sprintf(message+cimg::strlen(message)," - Range ( %g, %g ) - ( %g, %g )",cx0,cy0,cx1,cy1); 1.28758 + else 1.28759 + cimg_std::sprintf(message+cimg::strlen(message)," - Range [ %g - %g ]",cx0,cx1); 1.28760 + } 1.28761 + text.assign().draw_text(0,0,message,white,ngray,1); 1.28762 + visu.draw_image((visu.dimx()-text.dimx())/2,2,~text); 1.28763 + } 1.28764 + visu.display(disp); 1.28765 + } 1.28766 + 1.28767 + // Test keys. 1.28768 + switch (okey = key) { 1.28769 + case cimg::keyCTRLLEFT : okey = 0; break; 1.28770 + case cimg::keyD : if (disp.is_keyCTRLLEFT) { 1.28771 + disp.normalscreen().resize(CImgDisplay::_fitscreen(3*disp.width/2,3*disp.height/2,1,128,-100,false), 1.28772 + CImgDisplay::_fitscreen(3*disp.width/2,3*disp.height/2,1,128,-100,true),false).is_resized = true; 1.28773 + disp.key = okey = 0; 1.28774 + } break; 1.28775 + case cimg::keyC : if (disp.is_keyCTRLLEFT) { 1.28776 + disp.normalscreen().resize(cimg_fitscreen(2*disp.width/3,2*disp.height/3,1),false).is_resized = true; 1.28777 + disp.key = okey = 0; 1.28778 + } break; 1.28779 + case cimg::keyR : if (disp.is_keyCTRLLEFT) { 1.28780 + disp.normalscreen().resize(cimg_fitscreen(640,480,1),false).is_resized = true; 1.28781 + disp.key = okey = 0; 1.28782 + } break; 1.28783 + case cimg::keyF : if (disp.is_keyCTRLLEFT) { 1.28784 + disp.resize(disp.screen_dimx(),disp.screen_dimy()).toggle_fullscreen().is_resized = true; 1.28785 + disp.key = okey = 0; 1.28786 + } break; 1.28787 + case cimg::keyS : if (disp.is_keyCTRLLEFT) { 1.28788 + static unsigned int snap_number = 0; 1.28789 + if (visu || visu0) { 1.28790 + CImg<ucharT> &screen = visu?visu:visu0; 1.28791 + char filename[32] = { 0 }; 1.28792 + cimg_std::FILE *file; 1.28793 + do { 1.28794 + cimg_std::sprintf(filename,"CImg_%.4u.bmp",snap_number++); 1.28795 + if ((file=cimg_std::fopen(filename,"r"))!=0) cimg_std::fclose(file); 1.28796 + } while (file); 1.28797 + (+screen).draw_text(2,2,"Saving BMP snapshot...",black,gray,1,11).display(disp); 1.28798 + screen.save(filename); 1.28799 + screen.draw_text(2,2,"Snapshot '%s' saved.",black,gray,1,11,filename).display(disp); 1.28800 + } 1.28801 + disp.key = okey = 0; 1.28802 + } break; 1.28803 + } 1.28804 + 1.28805 + // Handle mouse motion and mouse buttons 1.28806 + if (obutton!=button || omouse_x!=mouse_x || omouse_y!=mouse_y) { 1.28807 + visu.assign(); 1.28808 + if (disp.mouse_x>=0 && disp.mouse_y>=0) { 1.28809 + const int 1.28810 + mx = (mouse_x-16)*(int)whz/(disp.dimx()-32), 1.28811 + cx = mx<0?0:(mx>=(int)whz?whz-1:mx), 1.28812 + my = mouse_y-16, 1.28813 + cy = my<=0?0:(my>=(disp.dimy()-32)?(disp.dimy()-32):my); 1.28814 + if (button&1) { if (!obutton) { x0 = cx; y0 = -1; } else { x1 = cx; y1 = -1; }} 1.28815 + else if (button&2) { if (!obutton) { x0 = cx; y0 = cy; } else { x1 = cx; y1 = cy; }} 1.28816 + else if (obutton) { x1 = cx; y1 = y1>=0?cy:-1; selected = true; } 1.28817 + } else if (!button && obutton) selected = true; 1.28818 + obutton = button; omouse_x = mouse_x; omouse_y = mouse_y; 1.28819 + } 1.28820 + if (disp.is_resized) { disp.resize(false); visu0.assign(); } 1.28821 + if (visu && visu0) disp.wait(); 1.28822 + } 1.28823 + disp.normalization = onormalization; 1.28824 + if (x1<x0) cimg::swap(x0,x1); 1.28825 + if (y1<y0) cimg::swap(y0,y1); 1.28826 + disp.key = okey; 1.28827 + return CImg<intT>(4,1,1,1,x0,y0,x1,y1); 1.28828 + } 1.28829 + 1.28830 + //@} 1.28831 + //--------------------------- 1.28832 + // 1.28833 + //! \name Image File Loading 1.28834 + //@{ 1.28835 + //--------------------------- 1.28836 + 1.28837 + //! Load an image from a file. 1.28838 + /** 1.28839 + \param filename is the name of the image file to load. 1.28840 + \note The extension of \c filename defines the file format. If no filename 1.28841 + extension is provided, CImg<T>::get_load() will try to load a .cimg file. 1.28842 + **/ 1.28843 + CImg<T>& load(const char *const filename) { 1.28844 + if (!filename) 1.28845 + throw CImgArgumentException("CImg<%s>::load() : Cannot load (null) filename.", 1.28846 + pixel_type()); 1.28847 + const char *ext = cimg::split_filename(filename); 1.28848 + const unsigned int odebug = cimg::exception_mode(); 1.28849 + cimg::exception_mode() = 0; 1.28850 + assign(); 1.28851 + try { 1.28852 +#ifdef cimg_load_plugin 1.28853 + cimg_load_plugin(filename); 1.28854 +#endif 1.28855 +#ifdef cimg_load_plugin1 1.28856 + cimg_load_plugin1(filename); 1.28857 +#endif 1.28858 +#ifdef cimg_load_plugin2 1.28859 + cimg_load_plugin2(filename); 1.28860 +#endif 1.28861 +#ifdef cimg_load_plugin3 1.28862 + cimg_load_plugin3(filename); 1.28863 +#endif 1.28864 +#ifdef cimg_load_plugin4 1.28865 + cimg_load_plugin4(filename); 1.28866 +#endif 1.28867 +#ifdef cimg_load_plugin5 1.28868 + cimg_load_plugin5(filename); 1.28869 +#endif 1.28870 +#ifdef cimg_load_plugin6 1.28871 + cimg_load_plugin6(filename); 1.28872 +#endif 1.28873 +#ifdef cimg_load_plugin7 1.28874 + cimg_load_plugin7(filename); 1.28875 +#endif 1.28876 +#ifdef cimg_load_plugin8 1.28877 + cimg_load_plugin8(filename); 1.28878 +#endif 1.28879 + // ASCII formats 1.28880 + if (!cimg::strcasecmp(ext,"asc")) load_ascii(filename); 1.28881 + if (!cimg::strcasecmp(ext,"dlm") || 1.28882 + !cimg::strcasecmp(ext,"txt")) load_dlm(filename); 1.28883 + 1.28884 + // 2D binary formats 1.28885 + if (!cimg::strcasecmp(ext,"bmp")) load_bmp(filename); 1.28886 + if (!cimg::strcasecmp(ext,"jpg") || 1.28887 + !cimg::strcasecmp(ext,"jpeg") || 1.28888 + !cimg::strcasecmp(ext,"jpe") || 1.28889 + !cimg::strcasecmp(ext,"jfif") || 1.28890 + !cimg::strcasecmp(ext,"jif")) load_jpeg(filename); 1.28891 + if (!cimg::strcasecmp(ext,"png")) load_png(filename); 1.28892 + if (!cimg::strcasecmp(ext,"ppm") || 1.28893 + !cimg::strcasecmp(ext,"pgm") || 1.28894 + !cimg::strcasecmp(ext,"pnm")) load_pnm(filename); 1.28895 + if (!cimg::strcasecmp(ext,"tif") || 1.28896 + !cimg::strcasecmp(ext,"tiff")) load_tiff(filename); 1.28897 + if (!cimg::strcasecmp(ext,"cr2") || 1.28898 + !cimg::strcasecmp(ext,"crw") || 1.28899 + !cimg::strcasecmp(ext,"dcr") || 1.28900 + !cimg::strcasecmp(ext,"mrw") || 1.28901 + !cimg::strcasecmp(ext,"nef") || 1.28902 + !cimg::strcasecmp(ext,"orf") || 1.28903 + !cimg::strcasecmp(ext,"pix") || 1.28904 + !cimg::strcasecmp(ext,"ptx") || 1.28905 + !cimg::strcasecmp(ext,"raf") || 1.28906 + !cimg::strcasecmp(ext,"srf")) load_dcraw_external(filename); 1.28907 + 1.28908 + // 3D binary formats 1.28909 + if (!cimg::strcasecmp(ext,"dcm") || 1.28910 + !cimg::strcasecmp(ext,"dicom")) load_medcon_external(filename); 1.28911 + if (!cimg::strcasecmp(ext,"hdr") || 1.28912 + !cimg::strcasecmp(ext,"nii")) load_analyze(filename); 1.28913 + if (!cimg::strcasecmp(ext,"par") || 1.28914 + !cimg::strcasecmp(ext,"rec")) load_parrec(filename); 1.28915 + if (!cimg::strcasecmp(ext,"inr")) load_inr(filename); 1.28916 + if (!cimg::strcasecmp(ext,"pan")) load_pandore(filename); 1.28917 + if (!cimg::strcasecmp(ext,"cimg") || 1.28918 + !cimg::strcasecmp(ext,"cimgz") || 1.28919 + *ext=='\0') return load_cimg(filename); 1.28920 + 1.28921 + // Archive files 1.28922 + if (!cimg::strcasecmp(ext,"gz")) load_gzip_external(filename); 1.28923 + 1.28924 + // Image sequences 1.28925 + if (!cimg::strcasecmp(ext,"avi") || 1.28926 + !cimg::strcasecmp(ext,"mov") || 1.28927 + !cimg::strcasecmp(ext,"asf") || 1.28928 + !cimg::strcasecmp(ext,"divx") || 1.28929 + !cimg::strcasecmp(ext,"flv") || 1.28930 + !cimg::strcasecmp(ext,"mpg") || 1.28931 + !cimg::strcasecmp(ext,"m1v") || 1.28932 + !cimg::strcasecmp(ext,"m2v") || 1.28933 + !cimg::strcasecmp(ext,"m4v") || 1.28934 + !cimg::strcasecmp(ext,"mjp") || 1.28935 + !cimg::strcasecmp(ext,"mkv") || 1.28936 + !cimg::strcasecmp(ext,"mpe") || 1.28937 + !cimg::strcasecmp(ext,"movie") || 1.28938 + !cimg::strcasecmp(ext,"ogm") || 1.28939 + !cimg::strcasecmp(ext,"qt") || 1.28940 + !cimg::strcasecmp(ext,"rm") || 1.28941 + !cimg::strcasecmp(ext,"vob") || 1.28942 + !cimg::strcasecmp(ext,"wmv") || 1.28943 + !cimg::strcasecmp(ext,"xvid") || 1.28944 + !cimg::strcasecmp(ext,"mpeg")) load_ffmpeg(filename); 1.28945 + if (is_empty()) throw CImgIOException("CImg<%s>::load()",pixel_type()); 1.28946 + } catch (CImgException& e) { 1.28947 + if (!cimg::strncasecmp(e.message,"cimg::fopen()",13)) { 1.28948 + cimg::exception_mode() = odebug; 1.28949 + throw CImgIOException("CImg<%s>::load() : File '%s' cannot be opened.",pixel_type(),filename); 1.28950 + } else try { 1.28951 + const char *const ftype = cimg::file_type(0,filename); 1.28952 + assign(); 1.28953 + if (!cimg::strcmp(ftype,"pnm")) load_pnm(filename); 1.28954 + if (!cimg::strcmp(ftype,"bmp")) load_bmp(filename); 1.28955 + if (!cimg::strcmp(ftype,"jpeg")) load_jpeg(filename); 1.28956 + if (!cimg::strcmp(ftype,"pan")) load_pandore(filename); 1.28957 + if (!cimg::strcmp(ftype,"png")) load_png(filename); 1.28958 + if (!cimg::strcmp(ftype,"tiff")) load_tiff(filename); 1.28959 + if (is_empty()) throw CImgIOException("CImg<%s>::load()",pixel_type()); 1.28960 + } catch (CImgException&) { 1.28961 + try { 1.28962 + load_other(filename); 1.28963 + } catch (CImgException&) { 1.28964 + assign(); 1.28965 + } 1.28966 + } 1.28967 + } 1.28968 + cimg::exception_mode() = odebug; 1.28969 + if (is_empty()) 1.28970 + throw CImgIOException("CImg<%s>::load() : File '%s', format not recognized.",pixel_type(),filename); 1.28971 + return *this; 1.28972 + } 1.28973 + 1.28974 + static CImg<T> get_load(const char *const filename) { 1.28975 + return CImg<T>().load(filename); 1.28976 + } 1.28977 + 1.28978 + //! Load an image from an ASCII file. 1.28979 + CImg<T>& load_ascii(const char *const filename) { 1.28980 + return _load_ascii(0,filename); 1.28981 + } 1.28982 + 1.28983 + static CImg<T> get_load_ascii(const char *const filename) { 1.28984 + return CImg<T>().load_ascii(filename); 1.28985 + } 1.28986 + 1.28987 + //! Load an image from an ASCII file. 1.28988 + CImg<T>& load_ascii(cimg_std::FILE *const file) { 1.28989 + return _load_ascii(file,0); 1.28990 + } 1.28991 + 1.28992 + static CImg<T> get_load_ascii(cimg_std::FILE *const file) { 1.28993 + return CImg<T>().load_ascii(file); 1.28994 + } 1.28995 + 1.28996 + CImg<T>& _load_ascii(cimg_std::FILE *const file, const char *const filename) { 1.28997 + if (!filename && !file) 1.28998 + throw CImgArgumentException("CImg<%s>::load_ascii() : Cannot load (null) filename.", 1.28999 + pixel_type()); 1.29000 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); 1.29001 + char line[256] = { 0 }; 1.29002 + int err = cimg_std::fscanf(nfile,"%*[^0-9]%255[^\n]",line); 1.29003 + unsigned int off, dx = 0, dy = 1, dz = 1, dv = 1; 1.29004 + cimg_std::sscanf(line,"%u%*c%u%*c%u%*c%u",&dx,&dy,&dz,&dv); 1.29005 + err = cimg_std::fscanf(nfile,"%*[^0-9.+-]"); 1.29006 + if (!dx || !dy || !dz || !dv) { 1.29007 + if (!file) cimg::fclose(nfile); 1.29008 + throw CImgIOException("CImg<%s>::load_ascii() : File '%s', invalid .ASC header, specified image dimensions are (%u,%u,%u,%u).", 1.29009 + pixel_type(),filename?filename:"(FILE*)",dx,dy,dz,dv); 1.29010 + } 1.29011 + assign(dx,dy,dz,dv); 1.29012 + const unsigned long siz = size(); 1.29013 + double val; 1.29014 + T *ptr = data; 1.29015 + for (err = 1, off = 0; off<siz && err==1; ++off) { 1.29016 + err = cimg_std::fscanf(nfile,"%lf%*[^0-9.+-]",&val); 1.29017 + *(ptr++) = (T)val; 1.29018 + } 1.29019 + if (err!=1) 1.29020 + cimg::warn("CImg<%s>::load_ascii() : File '%s', only %u/%lu values read.", 1.29021 + pixel_type(),filename?filename:"(FILE*)",off-1,siz); 1.29022 + if (!file) cimg::fclose(nfile); 1.29023 + return *this; 1.29024 + } 1.29025 + 1.29026 + //! Load an image from a DLM file. 1.29027 + CImg<T>& load_dlm(const char *const filename) { 1.29028 + return _load_dlm(0,filename); 1.29029 + } 1.29030 + 1.29031 + static CImg<T> get_load_dlm(const char *const filename) { 1.29032 + return CImg<T>().load_dlm(filename); 1.29033 + } 1.29034 + 1.29035 + //! Load an image from a DLM file. 1.29036 + CImg<T>& load_dlm(cimg_std::FILE *const file) { 1.29037 + return _load_dlm(file,0); 1.29038 + } 1.29039 + 1.29040 + static CImg<T> get_load_dlm(cimg_std::FILE *const file) { 1.29041 + return CImg<T>().load_dlm(file); 1.29042 + } 1.29043 + 1.29044 + CImg<T>& _load_dlm(cimg_std::FILE *const file, const char *const filename) { 1.29045 + if (!filename && !file) 1.29046 + throw CImgArgumentException("CImg<%s>::load_dlm() : Cannot load (null) filename.", 1.29047 + pixel_type()); 1.29048 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"r"); 1.29049 + assign(256,256); 1.29050 + char c, delimiter[256] = { 0 }, tmp[256]; 1.29051 + unsigned int cdx = 0, dx = 0, dy = 0; 1.29052 + int oerr = 0, err; 1.29053 + double val; 1.29054 + while ((err = cimg_std::fscanf(nfile,"%lf%255[^0-9.+-]",&val,delimiter))!=EOF) { 1.29055 + oerr = err; 1.29056 + if (err>0) (*this)(cdx++,dy) = (T)val; 1.29057 + if (cdx>=width) resize(width+256,1,1,1,0); 1.29058 + c = 0; if (!cimg_std::sscanf(delimiter,"%255[^\n]%c",tmp,&c) || c=='\n') { 1.29059 + dx = cimg::max(cdx,dx); 1.29060 + ++dy; 1.29061 + if (dy>=height) resize(width,height+256,1,1,0); 1.29062 + cdx = 0; 1.29063 + } 1.29064 + } 1.29065 + if (cdx && oerr==1) { dx=cdx; ++dy; } 1.29066 + if (!dx || !dy) { 1.29067 + if (!file) cimg::fclose(nfile); 1.29068 + throw CImgIOException("CImg<%s>::load_dlm() : File '%s', invalid DLM file, specified image dimensions are (%u,%u).", 1.29069 + pixel_type(),filename?filename:"(FILE*)",dx,dy); 1.29070 + } 1.29071 + resize(dx,dy,1,1,0); 1.29072 + if (!file) cimg::fclose(nfile); 1.29073 + return *this; 1.29074 + } 1.29075 + 1.29076 + //! Load an image from a BMP file. 1.29077 + CImg<T>& load_bmp(const char *const filename) { 1.29078 + return _load_bmp(0,filename); 1.29079 + } 1.29080 + 1.29081 + static CImg<T> get_load_bmp(const char *const filename) { 1.29082 + return CImg<T>().load_bmp(filename); 1.29083 + } 1.29084 + 1.29085 + //! Load an image from a BMP file. 1.29086 + CImg<T>& load_bmp(cimg_std::FILE *const file) { 1.29087 + return _load_bmp(file,0); 1.29088 + } 1.29089 + 1.29090 + static CImg<T> get_load_bmp(cimg_std::FILE *const file) { 1.29091 + return CImg<T>().load_bmp(file); 1.29092 + } 1.29093 + 1.29094 + CImg<T>& _load_bmp(cimg_std::FILE *const file, const char *const filename) { 1.29095 + if (!filename && !file) 1.29096 + throw CImgArgumentException("CImg<%s>::load_bmp() : Cannot load (null) filename.", 1.29097 + pixel_type()); 1.29098 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); 1.29099 + unsigned char header[64]; 1.29100 + cimg::fread(header,54,nfile); 1.29101 + if (header[0]!='B' || header[1]!='M') { 1.29102 + if (!file) cimg::fclose(nfile); 1.29103 + throw CImgIOException("CImg<%s>::load_bmp() : Invalid valid BMP file (filename '%s').", 1.29104 + pixel_type(),filename?filename:"(FILE*)"); 1.29105 + } 1.29106 + assign(); 1.29107 + 1.29108 + // Read header and pixel buffer 1.29109 + int 1.29110 + file_size = header[0x02] + (header[0x03]<<8) + (header[0x04]<<16) + (header[0x05]<<24), 1.29111 + offset = header[0x0A] + (header[0x0B]<<8) + (header[0x0C]<<16) + (header[0x0D]<<24), 1.29112 + dx = header[0x12] + (header[0x13]<<8) + (header[0x14]<<16) + (header[0x15]<<24), 1.29113 + dy = header[0x16] + (header[0x17]<<8) + (header[0x18]<<16) + (header[0x19]<<24), 1.29114 + compression = header[0x1E] + (header[0x1F]<<8) + (header[0x20]<<16) + (header[0x21]<<24), 1.29115 + nb_colors = header[0x2E] + (header[0x2F]<<8) + (header[0x30]<<16) + (header[0x31]<<24), 1.29116 + bpp = header[0x1C] + (header[0x1D]<<8), 1.29117 + *palette = 0; 1.29118 + const int 1.29119 + dx_bytes = (bpp==1)?(dx/8+(dx%8?1:0)):((bpp==4)?(dx/2+(dx%2?1:0)):(dx*bpp/8)), 1.29120 + align = (4-dx_bytes%4)%4, 1.29121 + buf_size = cimg::min(cimg::abs(dy)*(dx_bytes+align),file_size-offset); 1.29122 + 1.29123 + if (bpp<16) { if (!nb_colors) nb_colors=1<<bpp; } else nb_colors = 0; 1.29124 + if (nb_colors) { palette = new int[nb_colors]; cimg::fread(palette,nb_colors,nfile); } 1.29125 + const int xoffset = offset-54-4*nb_colors; 1.29126 + if (xoffset>0) cimg_std::fseek(nfile,xoffset,SEEK_CUR); 1.29127 + unsigned char *buffer = new unsigned char[buf_size], *ptrs = buffer; 1.29128 + cimg::fread(buffer,buf_size,nfile); 1.29129 + if (!file) cimg::fclose(nfile); 1.29130 + 1.29131 + // Decompress buffer (if necessary) 1.29132 + if (compression) { 1.29133 + delete[] buffer; 1.29134 + if (file) { 1.29135 + throw CImgIOException("CImg<%s>::load_bmp() : Not able to read a compressed BMP file using a *FILE input", 1.29136 + pixel_type()); 1.29137 + } else return load_other(filename); 1.29138 + } 1.29139 + 1.29140 + // Read pixel data 1.29141 + assign(dx,cimg::abs(dy),1,3); 1.29142 + switch (bpp) { 1.29143 + case 1 : { // Monochrome 1.29144 + for (int y=height-1; y>=0; --y) { 1.29145 + unsigned char mask = 0x80, val = 0; 1.29146 + cimg_forX(*this,x) { 1.29147 + if (mask==0x80) val = *(ptrs++); 1.29148 + const unsigned char *col = (unsigned char*)(palette+(val&mask?1:0)); 1.29149 + (*this)(x,y,2) = (T)*(col++); 1.29150 + (*this)(x,y,1) = (T)*(col++); 1.29151 + (*this)(x,y,0) = (T)*(col++); 1.29152 + mask = cimg::ror(mask); 1.29153 + } ptrs+=align; } 1.29154 + } break; 1.29155 + case 4 : { // 16 colors 1.29156 + for (int y=height-1; y>=0; --y) { 1.29157 + unsigned char mask = 0xF0, val = 0; 1.29158 + cimg_forX(*this,x) { 1.29159 + if (mask==0xF0) val = *(ptrs++); 1.29160 + const unsigned char color = (unsigned char)((mask<16)?(val&mask):((val&mask)>>4)); 1.29161 + unsigned char *col = (unsigned char*)(palette+color); 1.29162 + (*this)(x,y,2) = (T)*(col++); 1.29163 + (*this)(x,y,1) = (T)*(col++); 1.29164 + (*this)(x,y,0) = (T)*(col++); 1.29165 + mask = cimg::ror(mask,4); 1.29166 + } ptrs+=align; } 1.29167 + } break; 1.29168 + case 8 : { // 256 colors 1.29169 + for (int y=height-1; y>=0; --y) { cimg_forX(*this,x) { 1.29170 + const unsigned char *col = (unsigned char*)(palette+*(ptrs++)); 1.29171 + (*this)(x,y,2) = (T)*(col++); 1.29172 + (*this)(x,y,1) = (T)*(col++); 1.29173 + (*this)(x,y,0) = (T)*(col++); 1.29174 + } ptrs+=align; } 1.29175 + } break; 1.29176 + case 16 : { // 16 bits colors 1.29177 + for (int y=height-1; y>=0; --y) { cimg_forX(*this,x) { 1.29178 + const unsigned char c1 = *(ptrs++), c2 = *(ptrs++); 1.29179 + const unsigned short col = (unsigned short)(c1|(c2<<8)); 1.29180 + (*this)(x,y,2) = (T)(col&0x1F); 1.29181 + (*this)(x,y,1) = (T)((col>>5)&0x1F); 1.29182 + (*this)(x,y,0) = (T)((col>>10)&0x1F); 1.29183 + } ptrs+=align; } 1.29184 + } break; 1.29185 + case 24 : { // 24 bits colors 1.29186 + for (int y=height-1; y>=0; --y) { cimg_forX(*this,x) { 1.29187 + (*this)(x,y,2) = (T)*(ptrs++); 1.29188 + (*this)(x,y,1) = (T)*(ptrs++); 1.29189 + (*this)(x,y,0) = (T)*(ptrs++); 1.29190 + } ptrs+=align; } 1.29191 + } break; 1.29192 + case 32 : { // 32 bits colors 1.29193 + for (int y=height-1; y>=0; --y) { cimg_forX(*this,x) { 1.29194 + (*this)(x,y,2) = (T)*(ptrs++); 1.29195 + (*this)(x,y,1) = (T)*(ptrs++); 1.29196 + (*this)(x,y,0) = (T)*(ptrs++); 1.29197 + ++ptrs; 1.29198 + } ptrs+=align; } 1.29199 + } break; 1.29200 + } 1.29201 + if (palette) delete[] palette; 1.29202 + delete[] buffer; 1.29203 + if (dy<0) mirror('y'); 1.29204 + return *this; 1.29205 + } 1.29206 + 1.29207 + //! Load an image from a JPEG file. 1.29208 + CImg<T>& load_jpeg(const char *const filename) { 1.29209 + return _load_jpeg(0,filename); 1.29210 + } 1.29211 + 1.29212 + static CImg<T> get_load_jpeg(const char *const filename) { 1.29213 + return CImg<T>().load_jpeg(filename); 1.29214 + } 1.29215 + 1.29216 + //! Load an image from a JPEG file. 1.29217 + CImg<T>& load_jpeg(cimg_std::FILE *const file) { 1.29218 + return _load_jpeg(file,0); 1.29219 + } 1.29220 + 1.29221 + static CImg<T> get_load_jpeg(cimg_std::FILE *const file) { 1.29222 + return CImg<T>().load_jpeg(file); 1.29223 + } 1.29224 + 1.29225 + CImg<T>& _load_jpeg(cimg_std::FILE *const file, const char *const filename) { 1.29226 + if (!filename && !file) 1.29227 + throw CImgArgumentException("CImg<%s>::load_jpeg() : Cannot load (null) filename.", 1.29228 + pixel_type()); 1.29229 +#ifndef cimg_use_jpeg 1.29230 + if (file) 1.29231 + throw CImgIOException("CImg<%s>::load_jpeg() : File '(FILE*)' cannot be read without using libjpeg.", 1.29232 + pixel_type()); 1.29233 + else return load_other(filename); 1.29234 +#else 1.29235 + struct jpeg_decompress_struct cinfo; 1.29236 + struct jpeg_error_mgr jerr; 1.29237 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); 1.29238 + 1.29239 + cinfo.err = jpeg_std_error(&jerr); 1.29240 + jpeg_create_decompress(&cinfo); 1.29241 + jpeg_stdio_src(&cinfo,nfile); 1.29242 + jpeg_read_header(&cinfo,TRUE); 1.29243 + jpeg_start_decompress(&cinfo); 1.29244 + 1.29245 + if (cinfo.output_components!=1 && cinfo.output_components!=3 && cinfo.output_components!=4) { 1.29246 + cimg::warn("CImg<%s>::load_jpeg() : Don't know how to read image '%s' with libpeg, trying ImageMagick's convert", 1.29247 + pixel_type(),filename?filename:"(FILE*)"); 1.29248 + if (!file) return load_other(filename); 1.29249 + else { 1.29250 + if (!file) cimg::fclose(nfile); 1.29251 + throw CImgIOException("CImg<%s>::load_jpeg() : Cannot read JPEG image '%s' using a *FILE input.", 1.29252 + pixel_type(),filename?filename:"(FILE*)"); 1.29253 + } 1.29254 + } 1.29255 + 1.29256 + const unsigned int row_stride = cinfo.output_width * cinfo.output_components; 1.29257 + unsigned char *buf = new unsigned char[cinfo.output_width*cinfo.output_height*cinfo.output_components], *buf2 = buf; 1.29258 + JSAMPROW row_pointer[1]; 1.29259 + while (cinfo.output_scanline < cinfo.output_height) { 1.29260 + row_pointer[0] = &buf[cinfo.output_scanline*row_stride]; 1.29261 + jpeg_read_scanlines(&cinfo,row_pointer,1); 1.29262 + } 1.29263 + jpeg_finish_decompress(&cinfo); 1.29264 + jpeg_destroy_decompress(&cinfo); 1.29265 + if (!file) cimg::fclose(nfile); 1.29266 + 1.29267 + assign(cinfo.output_width,cinfo.output_height,1,cinfo.output_components); 1.29268 + switch (dim) { 1.29269 + case 1 : { 1.29270 + T *ptr_g = data; 1.29271 + cimg_forXY(*this,x,y) *(ptr_g++) = (T)*(buf2++); 1.29272 + } break; 1.29273 + case 3 : { 1.29274 + T *ptr_r = ptr(0,0,0,0), *ptr_g = ptr(0,0,0,1), *ptr_b = ptr(0,0,0,2); 1.29275 + cimg_forXY(*this,x,y) { 1.29276 + *(ptr_r++) = (T)*(buf2++); 1.29277 + *(ptr_g++) = (T)*(buf2++); 1.29278 + *(ptr_b++) = (T)*(buf2++); 1.29279 + } 1.29280 + } break; 1.29281 + case 4 : { 1.29282 + T *ptr_r = ptr(0,0,0,0), *ptr_g = ptr(0,0,0,1), 1.29283 + *ptr_b = ptr(0,0,0,2), *ptr_a = ptr(0,0,0,3); 1.29284 + cimg_forXY(*this,x,y) { 1.29285 + *(ptr_r++) = (T)*(buf2++); 1.29286 + *(ptr_g++) = (T)*(buf2++); 1.29287 + *(ptr_b++) = (T)*(buf2++); 1.29288 + *(ptr_a++) = (T)*(buf2++); 1.29289 + } 1.29290 + } break; 1.29291 + } 1.29292 + delete[] buf; 1.29293 + return *this; 1.29294 +#endif 1.29295 + } 1.29296 + 1.29297 + //! Load an image from a file, using Magick++ library. 1.29298 + // Added April/may 2006 by Christoph Hormann <chris_hormann@gmx.de> 1.29299 + // This is experimental code, not much tested, use with care. 1.29300 + CImg<T>& load_magick(const char *const filename) { 1.29301 + if (!filename) 1.29302 + throw CImgArgumentException("CImg<%s>::load_magick() : Cannot load (null) filename.", 1.29303 + pixel_type()); 1.29304 +#ifdef cimg_use_magick 1.29305 + Magick::Image image(filename); 1.29306 + const unsigned int W = image.size().width(), H = image.size().height(); 1.29307 + switch (image.type()) { 1.29308 + case Magick::PaletteMatteType : 1.29309 + case Magick::TrueColorMatteType : 1.29310 + case Magick::ColorSeparationType : { 1.29311 + assign(W,H,1,4); 1.29312 + T *rdata = ptr(0,0,0,0), *gdata = ptr(0,0,0,1), *bdata = ptr(0,0,0,2), *adata = ptr(0,0,0,3); 1.29313 + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); 1.29314 + for (unsigned int off = W*H; off; --off) { 1.29315 + *(rdata++) = (T)(pixels->red); 1.29316 + *(gdata++) = (T)(pixels->green); 1.29317 + *(bdata++) = (T)(pixels->blue); 1.29318 + *(adata++) = (T)(pixels->opacity); 1.29319 + ++pixels; 1.29320 + } 1.29321 + } break; 1.29322 + case Magick::PaletteType : 1.29323 + case Magick::TrueColorType : { 1.29324 + assign(W,H,1,3); 1.29325 + T *rdata = ptr(0,0,0,0), *gdata = ptr(0,0,0,1), *bdata = ptr(0,0,0,2); 1.29326 + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); 1.29327 + for (unsigned int off = W*H; off; --off) { 1.29328 + *(rdata++) = (T)(pixels->red); 1.29329 + *(gdata++) = (T)(pixels->green); 1.29330 + *(bdata++) = (T)(pixels->blue); 1.29331 + ++pixels; 1.29332 + } 1.29333 + } break; 1.29334 + case Magick::GrayscaleMatteType : { 1.29335 + assign(W,H,1,2); 1.29336 + T *data = ptr(0,0,0,0), *adata = ptr(0,0,0,1); 1.29337 + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); 1.29338 + for (unsigned int off = W*H; off; --off) { 1.29339 + *(data++) = (T)(pixels->red); 1.29340 + *(adata++) = (T)(pixels->opacity); 1.29341 + ++pixels; 1.29342 + } 1.29343 + } break; 1.29344 + default : { 1.29345 + assign(W,H,1,1); 1.29346 + T *data = ptr(0,0,0,0); 1.29347 + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); 1.29348 + for (unsigned int off = W*H; off; --off) { 1.29349 + *(data++) = (T)(pixels->red); 1.29350 + ++pixels; 1.29351 + } 1.29352 + } 1.29353 + } 1.29354 +#else 1.29355 + throw CImgIOException("CImg<%s>::load_magick() : File '%s', Magick++ library has not been linked.", 1.29356 + pixel_type(),filename); 1.29357 +#endif 1.29358 + return *this; 1.29359 + } 1.29360 + 1.29361 + static CImg<T> get_load_magick(const char *const filename) { 1.29362 + return CImg<T>().load_magick(filename); 1.29363 + } 1.29364 + 1.29365 + //! Load an image from a PNG file. 1.29366 + CImg<T>& load_png(const char *const filename) { 1.29367 + return _load_png(0,filename); 1.29368 + } 1.29369 + 1.29370 + static CImg<T> get_load_png(const char *const filename) { 1.29371 + return CImg<T>().load_png(filename); 1.29372 + } 1.29373 + 1.29374 + //! Load an image from a PNG file. 1.29375 + CImg<T>& load_png(cimg_std::FILE *const file) { 1.29376 + return _load_png(file,0); 1.29377 + } 1.29378 + 1.29379 + static CImg<T> get_load_png(cimg_std::FILE *const file) { 1.29380 + return CImg<T>().load_png(file); 1.29381 + } 1.29382 + 1.29383 + // (Note : Most of this function has been written by Eric Fausett) 1.29384 + CImg<T>& _load_png(cimg_std::FILE *const file, const char *const filename) { 1.29385 + if (!filename && !file) 1.29386 + throw CImgArgumentException("CImg<%s>::load_png() : Cannot load (null) filename.", 1.29387 + pixel_type()); 1.29388 +#ifndef cimg_use_png 1.29389 + if (file) 1.29390 + throw CImgIOException("CImg<%s>::load_png() : File '(FILE*)' cannot be read without using libpng.", 1.29391 + pixel_type()); 1.29392 + else return load_other(filename); 1.29393 +#else 1.29394 + // Open file and check for PNG validity 1.29395 + const char *volatile nfilename = filename; // two 'volatile' here to remove a g++ warning due to 'setjmp'. 1.29396 + cimg_std::FILE *volatile nfile = file?file:cimg::fopen(nfilename,"rb"); 1.29397 + 1.29398 + unsigned char pngCheck[8]; 1.29399 + cimg::fread(pngCheck,8,(cimg_std::FILE*)nfile); 1.29400 + if (png_sig_cmp(pngCheck,0,8)) { 1.29401 + if (!file) cimg::fclose(nfile); 1.29402 + throw CImgIOException("CImg<%s>::load_png() : File '%s' is not a valid PNG file.", 1.29403 + pixel_type(),nfilename?nfilename:"(FILE*)"); 1.29404 + } 1.29405 + 1.29406 + // Setup PNG structures for read 1.29407 + png_voidp user_error_ptr = 0; 1.29408 + png_error_ptr user_error_fn = 0, user_warning_fn = 0; 1.29409 + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,user_error_ptr,user_error_fn,user_warning_fn); 1.29410 + if (!png_ptr) { 1.29411 + if (!file) cimg::fclose(nfile); 1.29412 + throw CImgIOException("CImg<%s>::load_png() : File '%s', trouble initializing 'png_ptr' data structure.", 1.29413 + pixel_type(),nfilename?nfilename:"(FILE*)"); 1.29414 + } 1.29415 + png_infop info_ptr = png_create_info_struct(png_ptr); 1.29416 + if (!info_ptr) { 1.29417 + if (!file) cimg::fclose(nfile); 1.29418 + png_destroy_read_struct(&png_ptr,(png_infopp)0,(png_infopp)0); 1.29419 + throw CImgIOException("CImg<%s>::load_png() : File '%s', trouble initializing 'info_ptr' data structure.", 1.29420 + pixel_type(),nfilename?nfilename:"(FILE*)"); 1.29421 + } 1.29422 + png_infop end_info = png_create_info_struct(png_ptr); 1.29423 + if (!end_info) { 1.29424 + if (!file) cimg::fclose(nfile); 1.29425 + png_destroy_read_struct(&png_ptr,&info_ptr,(png_infopp)0); 1.29426 + throw CImgIOException("CImg<%s>::load_png() : File '%s', trouble initializing 'end_info' data structure.", 1.29427 + pixel_type(),nfilename?nfilename:"(FILE*)"); 1.29428 + } 1.29429 + 1.29430 + // Error handling callback for png file reading 1.29431 + if (setjmp(png_jmpbuf(png_ptr))) { 1.29432 + if (!file) cimg::fclose((cimg_std::FILE*)nfile); 1.29433 + png_destroy_read_struct(&png_ptr, &end_info, (png_infopp)0); 1.29434 + throw CImgIOException("CImg<%s>::load_png() : File '%s', unknown fatal error.", 1.29435 + pixel_type(),nfilename?nfilename:"(FILE*)"); 1.29436 + } 1.29437 + png_init_io(png_ptr, nfile); 1.29438 + png_set_sig_bytes(png_ptr, 8); 1.29439 + 1.29440 + // Get PNG Header Info up to data block 1.29441 + png_read_info(png_ptr,info_ptr); 1.29442 + png_uint_32 W, H; 1.29443 + int bit_depth, color_type, interlace_type; 1.29444 + png_get_IHDR(png_ptr,info_ptr,&W,&H,&bit_depth,&color_type,&interlace_type,int_p_NULL,int_p_NULL); 1.29445 + int new_bit_depth = bit_depth; 1.29446 + int new_color_type = color_type; 1.29447 + 1.29448 + // Transforms to unify image data 1.29449 + if (new_color_type == PNG_COLOR_TYPE_PALETTE){ 1.29450 + png_set_palette_to_rgb(png_ptr); 1.29451 + new_color_type -= PNG_COLOR_MASK_PALETTE; 1.29452 + new_bit_depth = 8; 1.29453 + } 1.29454 + if (new_color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8){ 1.29455 + png_set_gray_1_2_4_to_8(png_ptr); 1.29456 + new_bit_depth = 8; 1.29457 + } 1.29458 + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) 1.29459 + png_set_tRNS_to_alpha(png_ptr); 1.29460 + if (new_color_type == PNG_COLOR_TYPE_GRAY || new_color_type == PNG_COLOR_TYPE_GRAY_ALPHA){ 1.29461 + png_set_gray_to_rgb(png_ptr); 1.29462 + new_color_type |= PNG_COLOR_MASK_COLOR; 1.29463 + } 1.29464 + if (new_color_type == PNG_COLOR_TYPE_RGB) 1.29465 + png_set_filler(png_ptr, 0xffffU, PNG_FILLER_AFTER); 1.29466 + png_read_update_info(png_ptr,info_ptr); 1.29467 + if (!(new_bit_depth==8 || new_bit_depth==16)) { 1.29468 + if (!file) cimg::fclose(nfile); 1.29469 + png_destroy_read_struct(&png_ptr, &end_info, (png_infopp)0); 1.29470 + throw CImgIOException("CImg<%s>::load_png() : File '%s', wrong bit coding (bit_depth=%u)", 1.29471 + pixel_type(),nfilename?nfilename:"(FILE*)",new_bit_depth); 1.29472 + } 1.29473 + const int byte_depth = new_bit_depth>>3; 1.29474 + 1.29475 + // Allocate Memory for Image Read 1.29476 + png_bytep *imgData = new png_bytep[H]; 1.29477 + for (unsigned int row = 0; row<H; ++row) imgData[row] = new png_byte[byte_depth*4*W]; 1.29478 + png_read_image(png_ptr,imgData); 1.29479 + png_read_end(png_ptr,end_info); 1.29480 + 1.29481 + // Read pixel data 1.29482 + if (!(new_color_type==PNG_COLOR_TYPE_RGB || new_color_type==PNG_COLOR_TYPE_RGB_ALPHA)) { 1.29483 + if (!file) cimg::fclose(nfile); 1.29484 + png_destroy_read_struct(&png_ptr,&end_info,(png_infopp)0); 1.29485 + throw CImgIOException("CImg<%s>::load_png() : File '%s', wrong color coding (new_color_type=%u)", 1.29486 + pixel_type(),nfilename?nfilename:"(FILE*)",new_color_type); 1.29487 + } 1.29488 + const bool no_alpha_channel = (new_color_type==PNG_COLOR_TYPE_RGB); 1.29489 + assign(W,H,1,no_alpha_channel?3:4); 1.29490 + T *ptr1 = ptr(0,0,0,0), *ptr2 = ptr(0,0,0,1), *ptr3 = ptr(0,0,0,2), *ptr4 = ptr(0,0,0,3); 1.29491 + switch (new_bit_depth) { 1.29492 + case 8 : { 1.29493 + cimg_forY(*this,y){ 1.29494 + const unsigned char *ptrs = (unsigned char*)imgData[y]; 1.29495 + cimg_forX(*this,x){ 1.29496 + *(ptr1++) = (T)*(ptrs++); 1.29497 + *(ptr2++) = (T)*(ptrs++); 1.29498 + *(ptr3++) = (T)*(ptrs++); 1.29499 + if (no_alpha_channel) ++ptrs; else *(ptr4++) = (T)*(ptrs++); 1.29500 + } 1.29501 + } 1.29502 + } break; 1.29503 + case 16 : { 1.29504 + cimg_forY(*this,y){ 1.29505 + const unsigned short *ptrs = (unsigned short*)(imgData[y]); 1.29506 + if (!cimg::endianness()) cimg::invert_endianness(ptrs,4*width); 1.29507 + cimg_forX(*this,x){ 1.29508 + *(ptr1++) = (T)*(ptrs++); 1.29509 + *(ptr2++) = (T)*(ptrs++); 1.29510 + *(ptr3++) = (T)*(ptrs++); 1.29511 + if (no_alpha_channel) ++ptrs; else *(ptr4++) = (T)*(ptrs++); 1.29512 + } 1.29513 + } 1.29514 + } break; 1.29515 + } 1.29516 + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); 1.29517 + 1.29518 + // Deallocate Image Read Memory 1.29519 + cimg_forY(*this,n) delete[] imgData[n]; 1.29520 + delete[] imgData; 1.29521 + if (!file) cimg::fclose(nfile); 1.29522 + return *this; 1.29523 +#endif 1.29524 + } 1.29525 + 1.29526 + //! Load an image from a PNM file. 1.29527 + CImg<T>& load_pnm(const char *const filename) { 1.29528 + return _load_pnm(0,filename); 1.29529 + } 1.29530 + 1.29531 + static CImg<T> get_load_pnm(const char *const filename) { 1.29532 + return CImg<T>().load_pnm(filename); 1.29533 + } 1.29534 + 1.29535 + //! Load an image from a PNM file. 1.29536 + CImg<T>& load_pnm(cimg_std::FILE *const file) { 1.29537 + return _load_pnm(file,0); 1.29538 + } 1.29539 + 1.29540 + static CImg<T> get_load_pnm(cimg_std::FILE *const file) { 1.29541 + return CImg<T>().load_pnm(file); 1.29542 + } 1.29543 + 1.29544 + CImg<T>& _load_pnm(cimg_std::FILE *const file, const char *const filename) { 1.29545 + if (!filename && !file) 1.29546 + throw CImgArgumentException("CImg<%s>::load_pnm() : Cannot load (null) filename.", 1.29547 + pixel_type()); 1.29548 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); 1.29549 + unsigned int ppm_type, W, H, colormax = 255; 1.29550 + char item[1024] = { 0 }; 1.29551 + int err, rval, gval, bval; 1.29552 + const int cimg_iobuffer = 12*1024*1024; 1.29553 + while ((err=cimg_std::fscanf(nfile,"%1023[^\n]",item))!=EOF && (item[0]=='#' || !err)) cimg_std::fgetc(nfile); 1.29554 + if (cimg_std::sscanf(item," P%u",&ppm_type)!=1) { 1.29555 + if (!file) cimg::fclose(nfile); 1.29556 + throw CImgIOException("CImg<%s>::load_pnm() : File '%s', PNM header 'P?' not found.", 1.29557 + pixel_type(),filename?filename:"(FILE*)"); 1.29558 + } 1.29559 + while ((err=cimg_std::fscanf(nfile," %1023[^\n]",item))!=EOF && (item[0]=='#' || !err)) cimg_std::fgetc(nfile); 1.29560 + if ((err=cimg_std::sscanf(item," %u %u %u",&W,&H,&colormax))<2) { 1.29561 + if (!file) cimg::fclose(nfile); 1.29562 + throw CImgIOException("CImg<%s>::load_pnm() : File '%s', WIDTH and HEIGHT fields are not defined in PNM header.", 1.29563 + pixel_type(),filename?filename:"(FILE*)"); 1.29564 + } 1.29565 + if (err==2) { 1.29566 + while ((err=cimg_std::fscanf(nfile," %1023[^\n]",item))!=EOF && (item[0]=='#' || !err)) cimg_std::fgetc(nfile); 1.29567 + if (cimg_std::sscanf(item,"%u",&colormax)!=1) 1.29568 + cimg::warn("CImg<%s>::load_pnm() : File '%s', COLORMAX field is not defined in PNM header.", 1.29569 + pixel_type(),filename?filename:"(FILE*)"); 1.29570 + } 1.29571 + cimg_std::fgetc(nfile); 1.29572 + assign(); 1.29573 + 1.29574 + switch (ppm_type) { 1.29575 + case 2 : { // Grey Ascii 1.29576 + assign(W,H,1,1); 1.29577 + T* rdata = data; 1.29578 + cimg_foroff(*this,off) { if (cimg_std::fscanf(nfile,"%d",&rval)>0) *(rdata++) = (T)rval; else break; } 1.29579 + } break; 1.29580 + case 3 : { // Color Ascii 1.29581 + assign(W,H,1,3); 1.29582 + T *rdata = ptr(0,0,0,0), *gdata = ptr(0,0,0,1), *bdata = ptr(0,0,0,2); 1.29583 + cimg_forXY(*this,x,y) { 1.29584 + if (cimg_std::fscanf(nfile,"%d %d %d",&rval,&gval,&bval)==3) { *(rdata++) = (T)rval; *(gdata++) = (T)gval; *(bdata++) = (T)bval; } 1.29585 + else break; 1.29586 + } 1.29587 + } break; 1.29588 + case 5 : { // Grey Binary 1.29589 + if (colormax<256) { // 8 bits 1.29590 + CImg<ucharT> raw; 1.29591 + assign(W,H,1,1); 1.29592 + T *ptrd = ptr(0,0,0,0); 1.29593 + for (int toread = (int)size(); toread>0; ) { 1.29594 + raw.assign(cimg::min(toread,cimg_iobuffer)); 1.29595 + cimg::fread(raw.data,raw.width,nfile); 1.29596 + toread-=raw.width; 1.29597 + const unsigned char *ptrs = raw.data; 1.29598 + for (unsigned int off = raw.width; off; --off) *(ptrd++) = (T)*(ptrs++); 1.29599 + } 1.29600 + } else { // 16 bits 1.29601 + CImg<ushortT> raw; 1.29602 + assign(W,H,1,1); 1.29603 + T *ptrd = ptr(0,0,0,0); 1.29604 + for (int toread = (int)size(); toread>0; ) { 1.29605 + raw.assign(cimg::min(toread,cimg_iobuffer/2)); 1.29606 + cimg::fread(raw.data,raw.width,nfile); 1.29607 + if (!cimg::endianness()) cimg::invert_endianness(raw.data,raw.width); 1.29608 + toread-=raw.width; 1.29609 + const unsigned short *ptrs = raw.data; 1.29610 + for (unsigned int off = raw.width; off; --off) *(ptrd++) = (T)*(ptrs++); 1.29611 + } 1.29612 + } 1.29613 + } break; 1.29614 + case 6 : { // Color Binary 1.29615 + if (colormax<256) { // 8 bits 1.29616 + CImg<ucharT> raw; 1.29617 + assign(W,H,1,3); 1.29618 + T 1.29619 + *ptr_r = ptr(0,0,0,0), 1.29620 + *ptr_g = ptr(0,0,0,1), 1.29621 + *ptr_b = ptr(0,0,0,2); 1.29622 + for (int toread = (int)size(); toread>0; ) { 1.29623 + raw.assign(cimg::min(toread,cimg_iobuffer)); 1.29624 + cimg::fread(raw.data,raw.width,nfile); 1.29625 + toread-=raw.width; 1.29626 + const unsigned char *ptrs = raw.data; 1.29627 + for (unsigned int off = raw.width/3; off; --off) { 1.29628 + *(ptr_r++) = (T)*(ptrs++); 1.29629 + *(ptr_g++) = (T)*(ptrs++); 1.29630 + *(ptr_b++) = (T)*(ptrs++); 1.29631 + } 1.29632 + } 1.29633 + } else { // 16 bits 1.29634 + CImg<ushortT> raw; 1.29635 + assign(W,H,1,3); 1.29636 + T 1.29637 + *ptr_r = ptr(0,0,0,0), 1.29638 + *ptr_g = ptr(0,0,0,1), 1.29639 + *ptr_b = ptr(0,0,0,2); 1.29640 + for (int toread = (int)size(); toread>0; ) { 1.29641 + raw.assign(cimg::min(toread,cimg_iobuffer/2)); 1.29642 + cimg::fread(raw.data,raw.width,nfile); 1.29643 + if (!cimg::endianness()) cimg::invert_endianness(raw.data,raw.width); 1.29644 + toread-=raw.width; 1.29645 + const unsigned short *ptrs = raw.data; 1.29646 + for (unsigned int off = raw.width/3; off; --off) { 1.29647 + *(ptr_r++) = (T)*(ptrs++); 1.29648 + *(ptr_g++) = (T)*(ptrs++); 1.29649 + *(ptr_b++) = (T)*(ptrs++); 1.29650 + } 1.29651 + } 1.29652 + } 1.29653 + } break; 1.29654 + default : 1.29655 + if (!file) cimg::fclose(nfile); 1.29656 + throw CImgIOException("CImg<%s>::load_pnm() : File '%s', PPM type 'P%d' not supported.", 1.29657 + pixel_type(),filename?filename:"(FILE*)",ppm_type); 1.29658 + } 1.29659 + if (!file) cimg::fclose(nfile); 1.29660 + return *this; 1.29661 + } 1.29662 + 1.29663 + //! Load an image from a RGB file. 1.29664 + CImg<T>& load_rgb(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { 1.29665 + return _load_rgb(0,filename,dimw,dimh); 1.29666 + } 1.29667 + 1.29668 + static CImg<T> get_load_rgb(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { 1.29669 + return CImg<T>().load_rgb(filename,dimw,dimh); 1.29670 + } 1.29671 + 1.29672 + //! Load an image from a RGB file. 1.29673 + CImg<T>& load_rgb(cimg_std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { 1.29674 + return _load_rgb(file,0,dimw,dimh); 1.29675 + } 1.29676 + 1.29677 + static CImg<T> get_load_rgb(cimg_std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { 1.29678 + return CImg<T>().load_rgb(file,dimw,dimh); 1.29679 + } 1.29680 + 1.29681 + CImg<T>& _load_rgb(cimg_std::FILE *const file, const char *const filename, const unsigned int dimw, const unsigned int dimh) { 1.29682 + if (!filename && !file) 1.29683 + throw CImgArgumentException("CImg<%s>::load_rgb() : Cannot load (null) filename.", 1.29684 + pixel_type()); 1.29685 + if (!dimw || !dimh) return assign(); 1.29686 + const int cimg_iobuffer = 12*1024*1024; 1.29687 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); 1.29688 + CImg<ucharT> raw; 1.29689 + assign(dimw,dimh,1,3); 1.29690 + T 1.29691 + *ptr_r = ptr(0,0,0,0), 1.29692 + *ptr_g = ptr(0,0,0,1), 1.29693 + *ptr_b = ptr(0,0,0,2); 1.29694 + for (int toread = (int)size(); toread>0; ) { 1.29695 + raw.assign(cimg::min(toread,cimg_iobuffer)); 1.29696 + cimg::fread(raw.data,raw.width,nfile); 1.29697 + toread-=raw.width; 1.29698 + const unsigned char *ptrs = raw.data; 1.29699 + for (unsigned int off = raw.width/3; off; --off) { 1.29700 + *(ptr_r++) = (T)*(ptrs++); 1.29701 + *(ptr_g++) = (T)*(ptrs++); 1.29702 + *(ptr_b++) = (T)*(ptrs++); 1.29703 + } 1.29704 + } 1.29705 + if (!file) cimg::fclose(nfile); 1.29706 + return *this; 1.29707 + } 1.29708 + 1.29709 + //! Load an image from a RGBA file. 1.29710 + CImg<T>& load_rgba(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { 1.29711 + return _load_rgba(0,filename,dimw,dimh); 1.29712 + } 1.29713 + 1.29714 + static CImg<T> get_load_rgba(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { 1.29715 + return CImg<T>().load_rgba(filename,dimw,dimh); 1.29716 + } 1.29717 + 1.29718 + //! Load an image from a RGBA file. 1.29719 + CImg<T>& load_rgba(cimg_std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { 1.29720 + return _load_rgba(file,0,dimw,dimh); 1.29721 + } 1.29722 + 1.29723 + static CImg<T> get_load_rgba(cimg_std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { 1.29724 + return CImg<T>().load_rgba(file,dimw,dimh); 1.29725 + } 1.29726 + 1.29727 + CImg<T>& _load_rgba(cimg_std::FILE *const file, const char *const filename, const unsigned int dimw, const unsigned int dimh) { 1.29728 + if (!filename && !file) 1.29729 + throw CImgArgumentException("CImg<%s>::load_rgba() : Cannot load (null) filename.", 1.29730 + pixel_type()); 1.29731 + if (!dimw || !dimh) return assign(); 1.29732 + const int cimg_iobuffer = 12*1024*1024; 1.29733 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); 1.29734 + CImg<ucharT> raw; 1.29735 + assign(dimw,dimh,1,4); 1.29736 + T 1.29737 + *ptr_r = ptr(0,0,0,0), 1.29738 + *ptr_g = ptr(0,0,0,1), 1.29739 + *ptr_b = ptr(0,0,0,2), 1.29740 + *ptr_a = ptr(0,0,0,3); 1.29741 + for (int toread = (int)size(); toread>0; ) { 1.29742 + raw.assign(cimg::min(toread,cimg_iobuffer)); 1.29743 + cimg::fread(raw.data,raw.width,nfile); 1.29744 + toread-=raw.width; 1.29745 + const unsigned char *ptrs = raw.data; 1.29746 + for (unsigned int off = raw.width/4; off; --off) { 1.29747 + *(ptr_r++) = (T)*(ptrs++); 1.29748 + *(ptr_g++) = (T)*(ptrs++); 1.29749 + *(ptr_b++) = (T)*(ptrs++); 1.29750 + *(ptr_a++) = (T)*(ptrs++); 1.29751 + } 1.29752 + } 1.29753 + if (!file) cimg::fclose(nfile); 1.29754 + return *this; 1.29755 + } 1.29756 + 1.29757 + //! Load an image from a TIFF file. 1.29758 + CImg<T>& load_tiff(const char *const filename, 1.29759 + const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.29760 + const unsigned int step_frame=1) { 1.29761 + if (!filename) 1.29762 + throw CImgArgumentException("CImg<%s>::load_tiff() : Cannot load (null) filename.", 1.29763 + pixel_type()); 1.29764 + const unsigned int 1.29765 + nfirst_frame = first_frame<last_frame?first_frame:last_frame, 1.29766 + nstep_frame = step_frame?step_frame:1; 1.29767 + unsigned int nlast_frame = first_frame<last_frame?last_frame:first_frame; 1.29768 + 1.29769 +#ifndef cimg_use_tiff 1.29770 + if (nfirst_frame || nlast_frame!=~0U || nstep_frame>1) 1.29771 + throw CImgArgumentException("CImg<%s>::load_tiff() : File '%s', reading sub-images from a tiff file requires the use of libtiff.\n" 1.29772 + "('cimg_use_tiff' must be defined).", 1.29773 + pixel_type(),filename); 1.29774 + return load_other(filename); 1.29775 +#else 1.29776 + TIFF *tif = TIFFOpen(filename,"r"); 1.29777 + if (tif) { 1.29778 + unsigned int nb_images = 0; 1.29779 + do ++nb_images; while (TIFFReadDirectory(tif)); 1.29780 + if (nfirst_frame>=nb_images || (nlast_frame!=~0U && nlast_frame>=nb_images)) 1.29781 + cimg::warn("CImg<%s>::load_tiff() : File '%s' contains %u image(s), specified frame range is [%u,%u] (step %u).", 1.29782 + pixel_type(),filename,nb_images,nfirst_frame,nlast_frame,nstep_frame); 1.29783 + if (nfirst_frame>=nb_images) return assign(); 1.29784 + if (nlast_frame>=nb_images) nlast_frame = nb_images-1; 1.29785 + TIFFSetDirectory(tif,0); 1.29786 + CImg<T> frame; 1.29787 + for (unsigned int l = nfirst_frame; l<=nlast_frame; l+=nstep_frame) { 1.29788 + frame._load_tiff(tif,l); 1.29789 + if (l==nfirst_frame) assign(frame.width,frame.height,1+(nlast_frame-nfirst_frame)/nstep_frame,frame.dim); 1.29790 + if (frame.width>width || frame.height>height || frame.dim>dim) 1.29791 + resize(cimg::max(frame.width,width),cimg::max(frame.height,height),-100,cimg::max(frame.dim,dim),0); 1.29792 + draw_image(0,0,(l-nfirst_frame)/nstep_frame,frame); 1.29793 + } 1.29794 + TIFFClose(tif); 1.29795 + } else throw CImgException("CImg<%s>::load_tiff() : File '%s' cannot be opened.", 1.29796 + pixel_type(),filename); 1.29797 + return *this; 1.29798 +#endif 1.29799 + } 1.29800 + 1.29801 + static CImg<T> get_load_tiff(const char *const filename, 1.29802 + const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.29803 + const unsigned int step_frame=1) { 1.29804 + return CImg<T>().load_tiff(filename,first_frame,last_frame,step_frame); 1.29805 + } 1.29806 + 1.29807 + // (Original contribution by Jerome Boulanger). 1.29808 +#ifdef cimg_use_tiff 1.29809 + CImg<T>& _load_tiff(TIFF *tif, const unsigned int directory) { 1.29810 + if (!TIFFSetDirectory(tif,directory)) return assign(); 1.29811 + uint16 samplesperpixel, bitspersample; 1.29812 + uint32 nx,ny; 1.29813 + const char *const filename = TIFFFileName(tif); 1.29814 + TIFFGetField(tif,TIFFTAG_IMAGEWIDTH,&nx); 1.29815 + TIFFGetField(tif,TIFFTAG_IMAGELENGTH,&ny); 1.29816 + TIFFGetField(tif,TIFFTAG_SAMPLESPERPIXEL,&samplesperpixel); 1.29817 + if (samplesperpixel!=1 && samplesperpixel!=3 && samplesperpixel!=4) { 1.29818 + cimg::warn("CImg<%s>::load_tiff() : File '%s', unknow value for tag : TIFFTAG_SAMPLESPERPIXEL, will force it to 1.", 1.29819 + pixel_type(),filename); 1.29820 + samplesperpixel = 1; 1.29821 + } 1.29822 + TIFFGetFieldDefaulted(tif,TIFFTAG_BITSPERSAMPLE,&bitspersample); 1.29823 + assign(nx,ny,1,samplesperpixel); 1.29824 + if (bitspersample!=8 || !(samplesperpixel==3 || samplesperpixel==4)) { 1.29825 + uint16 photo, config; 1.29826 + TIFFGetField(tif,TIFFTAG_PLANARCONFIG,&config); 1.29827 + TIFFGetField(tif,TIFFTAG_PHOTOMETRIC,&photo); 1.29828 + if (TIFFIsTiled(tif)) { 1.29829 + uint32 tw, th; 1.29830 + TIFFGetField(tif,TIFFTAG_TILEWIDTH,&tw); 1.29831 + TIFFGetField(tif,TIFFTAG_TILELENGTH,&th); 1.29832 + if (config==PLANARCONFIG_CONTIG) switch (bitspersample) { 1.29833 + case 8 : { 1.29834 + unsigned char *buf = (unsigned char*)_TIFFmalloc(TIFFTileSize(tif)); 1.29835 + if (buf) { 1.29836 + for (unsigned int row = 0; row<ny; row+=th) 1.29837 + for (unsigned int col = 0; col<nx; col+=tw) { 1.29838 + if (TIFFReadTile(tif,buf,col,row,0,0)<0) { 1.29839 + _TIFFfree(buf); TIFFClose(tif); 1.29840 + throw CImgException("CImg<%s>::load_tiff() : File '%s', an error occure while reading a tile.", 1.29841 + pixel_type(),filename); 1.29842 + } else { 1.29843 + unsigned char *ptr = buf; 1.29844 + for (unsigned int rr = row; rr<cimg::min((unsigned int)(row+th),(unsigned int)ny); ++rr) 1.29845 + for (unsigned int cc = col; cc<cimg::min((unsigned int)(col+tw),(unsigned int)nx); ++cc) 1.29846 + for (unsigned int vv = 0; vv<samplesperpixel; ++vv) 1.29847 + (*this)(cc,rr,vv) = (T)(float)(ptr[(rr-row)*th*samplesperpixel + (cc-col)*samplesperpixel + vv]); 1.29848 + } 1.29849 + } 1.29850 + _TIFFfree(buf); 1.29851 + } 1.29852 + } break; 1.29853 + case 16 : { 1.29854 + unsigned short *buf = (unsigned short*)_TIFFmalloc(TIFFTileSize(tif)); 1.29855 + if (buf) { 1.29856 + for (unsigned int row = 0; row<ny; row+=th) 1.29857 + for (unsigned int col = 0; col<nx; col+=tw) { 1.29858 + if (TIFFReadTile(tif,buf,col,row,0,0)<0) { 1.29859 + _TIFFfree(buf); TIFFClose(tif); 1.29860 + throw CImgException("CImg<%s>::load_tiff() : File '%s', an error occure while reading a tile.", 1.29861 + pixel_type(),filename); 1.29862 + } else { 1.29863 + unsigned short *ptr = buf; 1.29864 + for (unsigned int rr = row; rr<cimg::min((unsigned int)(row+th),(unsigned int)ny); ++rr) 1.29865 + for (unsigned int cc = col; cc<cimg::min((unsigned int)(col+tw),(unsigned int)nx); ++cc) 1.29866 + for (unsigned int vv = 0; vv<samplesperpixel; ++vv) 1.29867 + (*this)(cc,rr,vv) = (T)(float)(ptr[(rr-row)*th*samplesperpixel + (cc-col)*samplesperpixel + vv]); 1.29868 + } 1.29869 + } 1.29870 + _TIFFfree(buf); 1.29871 + } 1.29872 + } break; 1.29873 + case 32 : { 1.29874 + float *buf = (float*)_TIFFmalloc(TIFFTileSize(tif)); 1.29875 + if (buf) { 1.29876 + for (unsigned int row = 0; row<ny; row+=th) 1.29877 + for (unsigned int col = 0; col<nx; col+=tw) { 1.29878 + if (TIFFReadTile(tif,buf,col,row,0,0)<0) { 1.29879 + _TIFFfree(buf); TIFFClose(tif); 1.29880 + throw CImgException("CImg<%s>::load_tiff() : File '%s', an error occure while reading a tile.", 1.29881 + pixel_type(),filename); 1.29882 + } else { 1.29883 + float *ptr = buf; 1.29884 + for (unsigned int rr = row; rr<cimg::min((unsigned int)(row+th),(unsigned int)ny); ++rr) 1.29885 + for (unsigned int cc = col; cc<cimg::min((unsigned int)(col+tw),(unsigned int)nx); ++cc) 1.29886 + for (unsigned int vv = 0; vv<samplesperpixel; ++vv) 1.29887 + (*this)(cc,rr,vv) = (T)(float)(ptr[(rr-row)*th*samplesperpixel + (cc-col)*samplesperpixel + vv]); 1.29888 + } 1.29889 + } 1.29890 + _TIFFfree(buf); 1.29891 + } 1.29892 + } break; 1.29893 + } else switch (bitspersample) { 1.29894 + case 8 : { 1.29895 + unsigned char *buf = (unsigned char*)_TIFFmalloc(TIFFTileSize(tif)); 1.29896 + if (buf) { 1.29897 + for (unsigned int vv = 0; vv<samplesperpixel; ++vv) 1.29898 + for (unsigned int row = 0; row<ny; row+=th) 1.29899 + for (unsigned int col = 0; col<nx; col+=tw) { 1.29900 + if (TIFFReadTile(tif,buf,col,row,0,vv)<0) { 1.29901 + _TIFFfree(buf); TIFFClose(tif); 1.29902 + throw CImgException("CImg<%s>::load_tiff() : File '%s', an error occure while reading a tile.", 1.29903 + pixel_type(),filename); 1.29904 + } else { 1.29905 + unsigned char *ptr = buf; 1.29906 + for (unsigned int rr = row; rr<cimg::min((unsigned int)(row+th),(unsigned int)ny); ++rr) 1.29907 + for (unsigned int cc = col; cc<cimg::min((unsigned int)(col+tw),(unsigned int)nx); ++cc) 1.29908 + (*this)(cc,rr,vv) = (T)(float)*(ptr++); 1.29909 + } 1.29910 + } 1.29911 + _TIFFfree(buf); 1.29912 + } 1.29913 + } break; 1.29914 + case 16 : { 1.29915 + unsigned short *buf = (unsigned short*)_TIFFmalloc(TIFFTileSize(tif)); 1.29916 + if (buf) { 1.29917 + for (unsigned int vv = 0; vv<samplesperpixel; ++vv) 1.29918 + for (unsigned int row = 0; row<ny; row+=th) 1.29919 + for (unsigned int col = 0; col<nx; col+=tw) { 1.29920 + if (TIFFReadTile(tif,buf,col,row,0,vv)<0) { 1.29921 + _TIFFfree(buf); TIFFClose(tif); 1.29922 + throw CImgException("CImg<%s>::load_tiff() : File '%s', an error occure while reading a tile.", 1.29923 + pixel_type(),filename); 1.29924 + } else { 1.29925 + unsigned short *ptr = buf; 1.29926 + for (unsigned int rr = row; rr<cimg::min((unsigned int)(row+th),(unsigned int)ny); ++rr) 1.29927 + for (unsigned int cc = col; cc<cimg::min((unsigned int)(col+tw),(unsigned int)nx); ++cc) 1.29928 + (*this)(cc,rr,vv) = (T)(float)*(ptr++); 1.29929 + } 1.29930 + } 1.29931 + _TIFFfree(buf); 1.29932 + } 1.29933 + } break; 1.29934 + case 32 : { 1.29935 + float *buf = (float*)_TIFFmalloc(TIFFTileSize(tif)); 1.29936 + if (buf) { 1.29937 + for (unsigned int vv = 0; vv<samplesperpixel; ++vv) 1.29938 + for (unsigned int row = 0; row<ny; row+=th) 1.29939 + for (unsigned int col = 0; col<nx; col+=tw) { 1.29940 + if (TIFFReadTile(tif,buf,col,row,0,vv)<0) { 1.29941 + _TIFFfree(buf); TIFFClose(tif); 1.29942 + throw CImgException("CImg<%s>::load_tiff() : File '%s', an error occure while reading a tile.", 1.29943 + pixel_type(),filename); 1.29944 + } else { 1.29945 + float *ptr = buf; 1.29946 + for (unsigned int rr = row; rr<cimg::min((unsigned int)(row+th),(unsigned int)ny); ++rr) 1.29947 + for (unsigned int cc = col; cc<cimg::min((unsigned int)(col+tw),(unsigned int)nx); ++cc) 1.29948 + (*this)(cc,rr,vv) = (T)(float)*(ptr++); 1.29949 + } 1.29950 + } 1.29951 + _TIFFfree(buf); 1.29952 + } 1.29953 + } break; 1.29954 + } 1.29955 + } else { 1.29956 + if (config==PLANARCONFIG_CONTIG) switch (bitspersample) { 1.29957 + case 8 : { 1.29958 + unsigned char *buf = (unsigned char*)_TIFFmalloc(TIFFStripSize(tif)); 1.29959 + if (buf) { 1.29960 + uint32 row, rowsperstrip = (uint32)-1; 1.29961 + TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rowsperstrip); 1.29962 + for (row = 0; row<ny; row+= rowsperstrip) { 1.29963 + uint32 nrow = (row+rowsperstrip>ny?ny-row:rowsperstrip); 1.29964 + tstrip_t strip = TIFFComputeStrip(tif, row, 0); 1.29965 + if ((TIFFReadEncodedStrip(tif,strip,buf,-1))<0) { 1.29966 + _TIFFfree(buf); TIFFClose(tif); 1.29967 + throw CImgException("CImg<%s>::load_tiff() : File '%s', an error occure while reading a strip.", 1.29968 + pixel_type(),filename); 1.29969 + } 1.29970 + unsigned char *ptr = buf; 1.29971 + for (unsigned int rr = 0; rr<nrow; ++rr) 1.29972 + for (unsigned int cc = 0; cc<nx; ++cc) 1.29973 + for (unsigned int vv = 0; vv<samplesperpixel; ++vv) (*this)(cc,row+rr,vv) = (T)(float)*(ptr++); 1.29974 + } 1.29975 + _TIFFfree(buf); 1.29976 + } 1.29977 + } break; 1.29978 + case 16 : { 1.29979 + unsigned short *buf = (unsigned short*)_TIFFmalloc(TIFFStripSize(tif)); 1.29980 + if (buf) { 1.29981 + uint32 row, rowsperstrip = (uint32)-1; 1.29982 + TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rowsperstrip); 1.29983 + for (row = 0; row<ny; row+= rowsperstrip) { 1.29984 + uint32 nrow = (row+rowsperstrip>ny?ny-row:rowsperstrip); 1.29985 + tstrip_t strip = TIFFComputeStrip(tif, row, 0); 1.29986 + if ((TIFFReadEncodedStrip(tif,strip,buf,-1))<0) { 1.29987 + _TIFFfree(buf); TIFFClose(tif); 1.29988 + throw CImgException("CImg<%s>::load_tiff() : File '%s', error while reading a strip.", 1.29989 + pixel_type(),filename); 1.29990 + } 1.29991 + unsigned short *ptr = buf; 1.29992 + for (unsigned int rr = 0; rr<nrow; ++rr) 1.29993 + for (unsigned int cc = 0; cc<nx; ++cc) 1.29994 + for (unsigned int vv = 0; vv<samplesperpixel; ++vv) (*this)(cc,row+rr,vv) = (T)(float)*(ptr++); 1.29995 + } 1.29996 + _TIFFfree(buf); 1.29997 + } 1.29998 + } break; 1.29999 + case 32 : { 1.30000 + float *buf = (float*)_TIFFmalloc(TIFFStripSize(tif)); 1.30001 + if (buf) { 1.30002 + uint32 row, rowsperstrip = (uint32)-1; 1.30003 + TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rowsperstrip); 1.30004 + for (row = 0; row<ny; row+= rowsperstrip) { 1.30005 + uint32 nrow = (row+rowsperstrip>ny?ny-row:rowsperstrip); 1.30006 + tstrip_t strip = TIFFComputeStrip(tif, row, 0); 1.30007 + if ((TIFFReadEncodedStrip(tif,strip,buf,-1))<0) { 1.30008 + _TIFFfree(buf); TIFFClose(tif); 1.30009 + throw CImgException("CImg<%s>::load_tiff() : File '%s', error while reading a strip.", 1.30010 + pixel_type(),filename); 1.30011 + } 1.30012 + float *ptr = buf; 1.30013 + for (unsigned int rr = 0; rr<nrow; ++rr) 1.30014 + for (unsigned int cc = 0; cc<nx; ++cc) 1.30015 + for (unsigned int vv = 0; vv<samplesperpixel; ++vv) (*this)(cc,row+rr,vv) = (T)(float)*(ptr++); 1.30016 + } 1.30017 + _TIFFfree(buf); 1.30018 + } 1.30019 + } break; 1.30020 + } else switch (bitspersample){ 1.30021 + case 8 : { 1.30022 + unsigned char *buf = (unsigned char*)_TIFFmalloc(TIFFStripSize(tif)); 1.30023 + if (buf) { 1.30024 + uint32 row, rowsperstrip = (uint32)-1; 1.30025 + TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rowsperstrip); 1.30026 + for (unsigned int vv=0; vv<samplesperpixel; ++vv) 1.30027 + for (row = 0; row<ny; row+= rowsperstrip) { 1.30028 + uint32 nrow = (row+rowsperstrip>ny?ny-row:rowsperstrip); 1.30029 + tstrip_t strip = TIFFComputeStrip(tif, row, vv); 1.30030 + if ((TIFFReadEncodedStrip(tif,strip,buf,-1))<0) { 1.30031 + _TIFFfree(buf); TIFFClose(tif); 1.30032 + throw CImgException("CImg<%s>::load_tiff() : File '%s', an error occure while reading a strip.", 1.30033 + pixel_type(),filename); 1.30034 + } 1.30035 + unsigned char *ptr = buf; 1.30036 + for (unsigned int rr = 0;rr<nrow; ++rr) 1.30037 + for (unsigned int cc = 0; cc<nx; ++cc) 1.30038 + (*this)(cc,row+rr,vv) = (T)(float)*(ptr++); 1.30039 + } 1.30040 + _TIFFfree(buf); 1.30041 + } 1.30042 + } break; 1.30043 + case 16 : { 1.30044 + unsigned short *buf = (unsigned short*)_TIFFmalloc(TIFFStripSize(tif)); 1.30045 + if (buf) { 1.30046 + uint32 row, rowsperstrip = (uint32)-1; 1.30047 + TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rowsperstrip); 1.30048 + for (unsigned int vv = 0; vv<samplesperpixel; ++vv) 1.30049 + for (row = 0; row<ny; row+= rowsperstrip) { 1.30050 + uint32 nrow = (row+rowsperstrip>ny?ny-row:rowsperstrip); 1.30051 + tstrip_t strip = TIFFComputeStrip(tif, row, vv); 1.30052 + if ((TIFFReadEncodedStrip(tif,strip,buf,-1))<0) { 1.30053 + _TIFFfree(buf); TIFFClose(tif); 1.30054 + throw CImgException("CImg<%s>::load_tiff() : File '%s', error while reading a strip.", 1.30055 + pixel_type(),filename); 1.30056 + } 1.30057 + unsigned short *ptr = buf; 1.30058 + for (unsigned int rr = 0; rr<nrow; ++rr) 1.30059 + for (unsigned int cc = 0; cc<nx; ++cc) 1.30060 + (*this)(cc,row+rr,vv) = (T)(float)*(ptr++); 1.30061 + } 1.30062 + _TIFFfree(buf); 1.30063 + } 1.30064 + } break; 1.30065 + case 32 : { 1.30066 + float *buf = (float*)_TIFFmalloc(TIFFStripSize(tif)); 1.30067 + if (buf) { 1.30068 + uint32 row, rowsperstrip = (uint32)-1; 1.30069 + TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rowsperstrip); 1.30070 + for (unsigned int vv = 0; vv<samplesperpixel; ++vv) 1.30071 + for (row = 0; row<ny; row+= rowsperstrip) { 1.30072 + uint32 nrow = (row+rowsperstrip>ny?ny-row:rowsperstrip); 1.30073 + tstrip_t strip = TIFFComputeStrip(tif, row, vv); 1.30074 + if ((TIFFReadEncodedStrip(tif,strip,buf,-1))<0) { 1.30075 + _TIFFfree(buf); TIFFClose(tif); 1.30076 + throw CImgException("CImg<%s>::load_tiff() : File '%s', error while reading a strip.", 1.30077 + pixel_type(),filename); 1.30078 + } 1.30079 + float *ptr = buf; 1.30080 + for (unsigned int rr = 0; rr<nrow; ++rr) for (unsigned int cc = 0; cc<nx; ++cc) 1.30081 + (*this)(cc,row+rr,vv) = (T)(float)*(ptr++); 1.30082 + } 1.30083 + _TIFFfree(buf); 1.30084 + } 1.30085 + } break; 1.30086 + } 1.30087 + } 1.30088 + } else { 1.30089 + uint32* raster = (uint32*)_TIFFmalloc(nx * ny * sizeof (uint32)); 1.30090 + if (!raster) { 1.30091 + _TIFFfree(raster); TIFFClose(tif); 1.30092 + throw CImgException("CImg<%s>::load_tiff() : File '%s', not enough memory for buffer allocation.", 1.30093 + pixel_type(),filename); 1.30094 + } 1.30095 + TIFFReadRGBAImage(tif,nx,ny,raster,0); 1.30096 + switch (samplesperpixel) { 1.30097 + case 1 : { 1.30098 + cimg_forXY(*this,x,y) (*this)(x,y) = (T)(float)((raster[nx*(ny-1-y)+x]+ 128) / 257); 1.30099 + } break; 1.30100 + case 3 : { 1.30101 + cimg_forXY(*this,x,y) { 1.30102 + (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny-1-y)+x]); 1.30103 + (*this)(x,y,1) = (T)(float)TIFFGetG(raster[nx*(ny-1-y)+x]); 1.30104 + (*this)(x,y,2) = (T)(float)TIFFGetB(raster[nx*(ny-1-y)+x]); 1.30105 + } 1.30106 + } break; 1.30107 + case 4 : { 1.30108 + cimg_forXY(*this,x,y) { 1.30109 + (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny-1-y)+x]); 1.30110 + (*this)(x,y,1) = (T)(float)TIFFGetG(raster[nx*(ny-1-y)+x]); 1.30111 + (*this)(x,y,2) = (T)(float)TIFFGetB(raster[nx*(ny-1-y)+x]); 1.30112 + (*this)(x,y,3) = (T)(float)TIFFGetA(raster[nx*(ny-1-y)+x]); 1.30113 + } 1.30114 + } break; 1.30115 + } 1.30116 + _TIFFfree(raster); 1.30117 + } 1.30118 + return *this; 1.30119 + } 1.30120 +#endif 1.30121 + 1.30122 + //! Load an image from an ANALYZE7.5/NIFTI file. 1.30123 + CImg<T>& load_analyze(const char *const filename, float *const voxsize=0) { 1.30124 + return _load_analyze(0,filename,voxsize); 1.30125 + } 1.30126 + 1.30127 + static CImg<T> get_load_analyze(const char *const filename, float *const voxsize=0) { 1.30128 + return CImg<T>().load_analyze(filename,voxsize); 1.30129 + } 1.30130 + 1.30131 + //! Load an image from an ANALYZE7.5/NIFTI file. 1.30132 + CImg<T>& load_analyze(cimg_std::FILE *const file, float *const voxsize=0) { 1.30133 + return _load_analyze(file,0,voxsize); 1.30134 + } 1.30135 + 1.30136 + static CImg<T> get_load_analyze(cimg_std::FILE *const file, float *const voxsize=0) { 1.30137 + return CImg<T>().load_analyze(file,voxsize); 1.30138 + } 1.30139 + 1.30140 + CImg<T>& _load_analyze(cimg_std::FILE *const file, const char *const filename, float *const voxsize=0) { 1.30141 + if (!filename && !file) 1.30142 + throw CImgArgumentException("CImg<%s>::load_analyze() : Cannot load (null) filename.", 1.30143 + pixel_type()); 1.30144 + cimg_std::FILE *nfile_header = 0, *nfile = 0; 1.30145 + if (!file) { 1.30146 + char body[1024]; 1.30147 + const char *ext = cimg::split_filename(filename,body); 1.30148 + if (!cimg::strcasecmp(ext,"hdr")) { // File is an Analyze header file. 1.30149 + nfile_header = cimg::fopen(filename,"rb"); 1.30150 + cimg_std::sprintf(body+cimg::strlen(body),".img"); 1.30151 + nfile = cimg::fopen(body,"rb"); 1.30152 + } else if (!cimg::strcasecmp(ext,"img")) { // File is an Analyze data file. 1.30153 + nfile = cimg::fopen(filename,"rb"); 1.30154 + cimg_std::sprintf(body+cimg::strlen(body),".hdr"); 1.30155 + nfile_header = cimg::fopen(body,"rb"); 1.30156 + } else nfile_header = nfile = cimg::fopen(filename,"rb"); // File is a Niftii file. 1.30157 + } else nfile_header = nfile = file; // File is a Niftii file. 1.30158 + if (!nfile || !nfile_header) 1.30159 + throw CImgIOException("CImg<%s>::load_analyze() : File '%s', not recognized as an Analyze7.5 or NIFTI file.", 1.30160 + pixel_type(),filename?filename:"(FILE*)"); 1.30161 + 1.30162 + // Read header. 1.30163 + bool endian = false; 1.30164 + unsigned int header_size; 1.30165 + cimg::fread(&header_size,1,nfile_header); 1.30166 + if (!header_size) 1.30167 + throw CImgIOException("CImg<%s>::load_analyze() : File '%s', zero-sized header found.", 1.30168 + pixel_type(),filename?filename:"(FILE*)"); 1.30169 + if (header_size>=4096) { endian = true; cimg::invert_endianness(header_size); } 1.30170 + unsigned char *header = new unsigned char[header_size]; 1.30171 + cimg::fread(header+4,header_size-4,nfile_header); 1.30172 + if (!file && nfile_header!=nfile) cimg::fclose(nfile_header); 1.30173 + if (endian) { 1.30174 + cimg::invert_endianness((short*)(header+40),5); 1.30175 + cimg::invert_endianness((short*)(header+70),1); 1.30176 + cimg::invert_endianness((short*)(header+72),1); 1.30177 + cimg::invert_endianness((float*)(header+76),4); 1.30178 + cimg::invert_endianness((float*)(header+112),1); 1.30179 + } 1.30180 + unsigned short *dim = (unsigned short*)(header+40), dimx = 1, dimy = 1, dimz = 1, dimv = 1; 1.30181 + if (!dim[0]) 1.30182 + cimg::warn("CImg<%s>::load_analyze() : File '%s', tells that image has zero dimensions.", 1.30183 + pixel_type(),filename?filename:"(FILE*)"); 1.30184 + if (dim[0]>4) 1.30185 + cimg::warn("CImg<%s>::load_analyze() : File '%s', number of image dimension is %u, reading only the 4 first dimensions", 1.30186 + pixel_type(),filename?filename:"(FILE*)",dim[0]); 1.30187 + if (dim[0]>=1) dimx = dim[1]; 1.30188 + if (dim[0]>=2) dimy = dim[2]; 1.30189 + if (dim[0]>=3) dimz = dim[3]; 1.30190 + if (dim[0]>=4) dimv = dim[4]; 1.30191 + float scalefactor = *(float*)(header+112); if (scalefactor==0) scalefactor=1; 1.30192 + const unsigned short datatype = *(short*)(header+70); 1.30193 + if (voxsize) { 1.30194 + const float *vsize = (float*)(header+76); 1.30195 + voxsize[0] = vsize[1]; voxsize[1] = vsize[2]; voxsize[2] = vsize[3]; 1.30196 + } 1.30197 + delete[] header; 1.30198 + 1.30199 + // Read pixel data. 1.30200 + assign(dimx,dimy,dimz,dimv); 1.30201 + switch (datatype) { 1.30202 + case 2 : { 1.30203 + unsigned char *buffer = new unsigned char[dimx*dimy*dimz*dimv]; 1.30204 + cimg::fread(buffer,dimx*dimy*dimz*dimv,nfile); 1.30205 + cimg_foroff(*this,off) data[off] = (T)(buffer[off]*scalefactor); 1.30206 + delete[] buffer; 1.30207 + } break; 1.30208 + case 4 : { 1.30209 + short *buffer = new short[dimx*dimy*dimz*dimv]; 1.30210 + cimg::fread(buffer,dimx*dimy*dimz*dimv,nfile); 1.30211 + if (endian) cimg::invert_endianness(buffer,dimx*dimy*dimz*dimv); 1.30212 + cimg_foroff(*this,off) data[off] = (T)(buffer[off]*scalefactor); 1.30213 + delete[] buffer; 1.30214 + } break; 1.30215 + case 8 : { 1.30216 + int *buffer = new int[dimx*dimy*dimz*dimv]; 1.30217 + cimg::fread(buffer,dimx*dimy*dimz*dimv,nfile); 1.30218 + if (endian) cimg::invert_endianness(buffer,dimx*dimy*dimz*dimv); 1.30219 + cimg_foroff(*this,off) data[off] = (T)(buffer[off]*scalefactor); 1.30220 + delete[] buffer; 1.30221 + } break; 1.30222 + case 16 : { 1.30223 + float *buffer = new float[dimx*dimy*dimz*dimv]; 1.30224 + cimg::fread(buffer,dimx*dimy*dimz*dimv,nfile); 1.30225 + if (endian) cimg::invert_endianness(buffer,dimx*dimy*dimz*dimv); 1.30226 + cimg_foroff(*this,off) data[off] = (T)(buffer[off]*scalefactor); 1.30227 + delete[] buffer; 1.30228 + } break; 1.30229 + case 64 : { 1.30230 + double *buffer = new double[dimx*dimy*dimz*dimv]; 1.30231 + cimg::fread(buffer,dimx*dimy*dimz*dimv,nfile); 1.30232 + if (endian) cimg::invert_endianness(buffer,dimx*dimy*dimz*dimv); 1.30233 + cimg_foroff(*this,off) data[off] = (T)(buffer[off]*scalefactor); 1.30234 + delete[] buffer; 1.30235 + } break; 1.30236 + default : 1.30237 + if (!file) cimg::fclose(nfile); 1.30238 + throw CImgIOException("CImg<%s>::load_analyze() : File '%s', cannot read images with 'datatype = %d'", 1.30239 + pixel_type(),filename?filename:"(FILE*)",datatype); 1.30240 + } 1.30241 + if (!file) cimg::fclose(nfile); 1.30242 + return *this; 1.30243 + } 1.30244 + 1.30245 + //! Load an image (list) from a .cimg file. 1.30246 + CImg<T>& load_cimg(const char *const filename, const char axis='z', const char align='p') { 1.30247 + CImgList<T> list; 1.30248 + list.load_cimg(filename); 1.30249 + if (list.size==1) return list[0].transfer_to(*this); 1.30250 + return assign(list.get_append(axis,align)); 1.30251 + } 1.30252 + 1.30253 + static CImg<T> get_load_cimg(const char *const filename, const char axis='z', const char align='p') { 1.30254 + return CImg<T>().load_cimg(filename,axis,align); 1.30255 + } 1.30256 + 1.30257 + //! Load an image (list) from a .cimg file. 1.30258 + CImg<T>& load_cimg(cimg_std::FILE *const file, const char axis='z', const char align='p') { 1.30259 + CImgList<T> list; 1.30260 + list.load_cimg(file); 1.30261 + if (list.size==1) return list[0].transfer_to(*this); 1.30262 + return assign(list.get_append(axis,align)); 1.30263 + } 1.30264 + 1.30265 + static CImg<T> get_load_cimg(cimg_std::FILE *const file, const char axis='z', const char align='p') { 1.30266 + return CImg<T>().load_cimg(file,axis,align); 1.30267 + } 1.30268 + 1.30269 + //! Load a sub-image (list) from a .cimg file. 1.30270 + CImg<T>& load_cimg(const char *const filename, 1.30271 + const unsigned int n0, const unsigned int n1, 1.30272 + const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int v0, 1.30273 + const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int v1, 1.30274 + const char axis='z', const char align='p') { 1.30275 + CImgList<T> list; 1.30276 + list.load_cimg(filename,n0,n1,x0,y0,z0,v0,x1,y1,z1,v1); 1.30277 + if (list.size==1) return list[0].transfer_to(*this); 1.30278 + return assign(list.get_append(axis,align)); 1.30279 + } 1.30280 + 1.30281 + static CImg<T> get_load_cimg(const char *const filename, 1.30282 + const unsigned int n0, const unsigned int n1, 1.30283 + const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int v0, 1.30284 + const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int v1, 1.30285 + const char axis='z', const char align='p') { 1.30286 + return CImg<T>().load_cimg(filename,n0,n1,x0,y0,z0,v0,x1,y1,z1,v1,axis,align); 1.30287 + } 1.30288 + 1.30289 + //! Load a sub-image (list) from a non-compressed .cimg file. 1.30290 + CImg<T>& load_cimg(cimg_std::FILE *const file, 1.30291 + const unsigned int n0, const unsigned int n1, 1.30292 + const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int v0, 1.30293 + const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int v1, 1.30294 + const char axis='z', const char align='p') { 1.30295 + CImgList<T> list; 1.30296 + list.load_cimg(file,n0,n1,x0,y0,z0,v0,x1,y1,z1,v1); 1.30297 + if (list.size==1) return list[0].transfer_to(*this); 1.30298 + return assign(list.get_append(axis,align)); 1.30299 + } 1.30300 + 1.30301 + static CImg<T> get_load_cimg(cimg_std::FILE *const file, 1.30302 + const unsigned int n0, const unsigned int n1, 1.30303 + const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int v0, 1.30304 + const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int v1, 1.30305 + const char axis='z', const char align='p') { 1.30306 + return CImg<T>().load_cimg(file,n0,n1,x0,y0,z0,v0,x1,y1,z1,v1,axis,align); 1.30307 + } 1.30308 + 1.30309 + //! Load an image from an INRIMAGE-4 file. 1.30310 + CImg<T>& load_inr(const char *const filename, float *const voxsize=0) { 1.30311 + return _load_inr(0,filename,voxsize); 1.30312 + } 1.30313 + 1.30314 + static CImg<T> get_load_inr(const char *const filename, float *const voxsize=0) { 1.30315 + return CImg<T>().load_inr(filename,voxsize); 1.30316 + } 1.30317 + 1.30318 + //! Load an image from an INRIMAGE-4 file. 1.30319 + CImg<T>& load_inr(cimg_std::FILE *const file, float *const voxsize=0) { 1.30320 + return _load_inr(file,0,voxsize); 1.30321 + } 1.30322 + 1.30323 + static CImg<T> get_load_inr(cimg_std::FILE *const file, float *voxsize=0) { 1.30324 + return CImg<T>().load_inr(file,voxsize); 1.30325 + } 1.30326 + 1.30327 + // Load an image from an INRIMAGE-4 file (internal). 1.30328 + static void _load_inr_header(cimg_std::FILE *file, int out[8], float *const voxsize) { 1.30329 + char item[1024], tmp1[64], tmp2[64]; 1.30330 + out[0] = cimg_std::fscanf(file,"%63s",item); 1.30331 + out[0] = out[1] = out[2] = out[3] = out[5] = 1; out[4] = out[6] = out[7] = -1; 1.30332 + if(cimg::strncasecmp(item,"#INRIMAGE-4#{",13)!=0) 1.30333 + throw CImgIOException("CImg<%s>::load_inr() : File does not appear to be a valid INR file.\n" 1.30334 + "(INRIMAGE-4 identifier not found)", 1.30335 + pixel_type()); 1.30336 + while (cimg_std::fscanf(file," %63[^\n]%*c",item)!=EOF && cimg::strncmp(item,"##}",3)) { 1.30337 + cimg_std::sscanf(item," XDIM%*[^0-9]%d",out); 1.30338 + cimg_std::sscanf(item," YDIM%*[^0-9]%d",out+1); 1.30339 + cimg_std::sscanf(item," ZDIM%*[^0-9]%d",out+2); 1.30340 + cimg_std::sscanf(item," VDIM%*[^0-9]%d",out+3); 1.30341 + cimg_std::sscanf(item," PIXSIZE%*[^0-9]%d",out+6); 1.30342 + if (voxsize) { 1.30343 + cimg_std::sscanf(item," VX%*[^0-9.+-]%f",voxsize); 1.30344 + cimg_std::sscanf(item," VY%*[^0-9.+-]%f",voxsize+1); 1.30345 + cimg_std::sscanf(item," VZ%*[^0-9.+-]%f",voxsize+2); 1.30346 + } 1.30347 + if (cimg_std::sscanf(item," CPU%*[ =]%s",tmp1)) out[7]=cimg::strncasecmp(tmp1,"sun",3)?0:1; 1.30348 + switch (cimg_std::sscanf(item," TYPE%*[ =]%s %s",tmp1,tmp2)) { 1.30349 + case 0 : break; 1.30350 + case 2 : out[5] = cimg::strncasecmp(tmp1,"unsigned",8)?1:0; cimg_std::strcpy(tmp1,tmp2); 1.30351 + case 1 : 1.30352 + if (!cimg::strncasecmp(tmp1,"int",3) || !cimg::strncasecmp(tmp1,"fixed",5)) out[4] = 0; 1.30353 + if (!cimg::strncasecmp(tmp1,"float",5) || !cimg::strncasecmp(tmp1,"double",6)) out[4] = 1; 1.30354 + if (!cimg::strncasecmp(tmp1,"packed",6)) out[4] = 2; 1.30355 + if (out[4]>=0) break; 1.30356 + default : 1.30357 + throw CImgIOException("cimg::inr_header_read() : Invalid TYPE '%s'",tmp2); 1.30358 + } 1.30359 + } 1.30360 + if(out[0]<0 || out[1]<0 || out[2]<0 || out[3]<0) 1.30361 + throw CImgIOException("CImg<%s>::load_inr() : Bad dimensions in .inr file = ( %d , %d , %d , %d )", 1.30362 + pixel_type(),out[0],out[1],out[2],out[3]); 1.30363 + if(out[4]<0 || out[5]<0) 1.30364 + throw CImgIOException("CImg<%s>::load_inr() : TYPE is not fully defined", 1.30365 + pixel_type()); 1.30366 + if(out[6]<0) 1.30367 + throw CImgIOException("CImg<%s>::load_inr() : PIXSIZE is not fully defined", 1.30368 + pixel_type()); 1.30369 + if(out[7]<0) 1.30370 + throw CImgIOException("CImg<%s>::load_inr() : Big/Little Endian coding type is not defined", 1.30371 + pixel_type()); 1.30372 + } 1.30373 + 1.30374 + CImg<T>& _load_inr(cimg_std::FILE *const file, const char *const filename, float *const voxsize) { 1.30375 +#define _cimg_load_inr_case(Tf,sign,pixsize,Ts) \ 1.30376 + if (!loaded && fopt[6]==pixsize && fopt[4]==Tf && fopt[5]==sign) { \ 1.30377 + Ts *xval, *val = new Ts[fopt[0]*fopt[3]]; \ 1.30378 + cimg_forYZ(*this,y,z) { \ 1.30379 + cimg::fread(val,fopt[0]*fopt[3],nfile); \ 1.30380 + if (fopt[7]!=endian) cimg::invert_endianness(val,fopt[0]*fopt[3]); \ 1.30381 + xval = val; cimg_forX(*this,x) cimg_forV(*this,k) (*this)(x,y,z,k) = (T)*(xval++); \ 1.30382 + } \ 1.30383 + delete[] val; \ 1.30384 + loaded = true; \ 1.30385 + } 1.30386 + 1.30387 + if (!filename && !file) 1.30388 + throw CImgArgumentException("CImg<%s>::load_inr() : Cannot load (null) filename.", 1.30389 + pixel_type()); 1.30390 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); 1.30391 + int fopt[8], endian=cimg::endianness()?1:0; 1.30392 + bool loaded = false; 1.30393 + if (voxsize) voxsize[0]=voxsize[1]=voxsize[2]=1; 1.30394 + _load_inr_header(nfile,fopt,voxsize); 1.30395 + assign(fopt[0],fopt[1],fopt[2],fopt[3]); 1.30396 + _cimg_load_inr_case(0,0,8, unsigned char); 1.30397 + _cimg_load_inr_case(0,1,8, char); 1.30398 + _cimg_load_inr_case(0,0,16,unsigned short); 1.30399 + _cimg_load_inr_case(0,1,16,short); 1.30400 + _cimg_load_inr_case(0,0,32,unsigned int); 1.30401 + _cimg_load_inr_case(0,1,32,int); 1.30402 + _cimg_load_inr_case(1,0,32,float); 1.30403 + _cimg_load_inr_case(1,1,32,float); 1.30404 + _cimg_load_inr_case(1,0,64,double); 1.30405 + _cimg_load_inr_case(1,1,64,double); 1.30406 + if (!loaded) { 1.30407 + if (!file) cimg::fclose(nfile); 1.30408 + throw CImgIOException("CImg<%s>::load_inr() : File '%s', cannot read images of the type specified in the file", 1.30409 + pixel_type(),filename?filename:"(FILE*)"); 1.30410 + } 1.30411 + if (!file) cimg::fclose(nfile); 1.30412 + return *this; 1.30413 + } 1.30414 + 1.30415 + //! Load an image from a PANDORE file. 1.30416 + CImg<T>& load_pandore(const char *const filename) { 1.30417 + return _load_pandore(0,filename); 1.30418 + } 1.30419 + 1.30420 + static CImg<T> get_load_pandore(const char *const filename) { 1.30421 + return CImg<T>().load_pandore(filename); 1.30422 + } 1.30423 + 1.30424 + //! Load an image from a PANDORE file. 1.30425 + CImg<T>& load_pandore(cimg_std::FILE *const file) { 1.30426 + return _load_pandore(file,0); 1.30427 + } 1.30428 + 1.30429 + static CImg<T> get_load_pandore(cimg_std::FILE *const file) { 1.30430 + return CImg<T>().load_pandore(file); 1.30431 + } 1.30432 + 1.30433 + CImg<T>& _load_pandore(cimg_std::FILE *const file, const char *const filename) { 1.30434 +#define __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,ndim,stype) \ 1.30435 + cimg::fread(dims,nbdim,nfile); \ 1.30436 + if (endian) cimg::invert_endianness(dims,nbdim); \ 1.30437 + assign(nwidth,nheight,ndepth,ndim); \ 1.30438 + const unsigned int siz = size(); \ 1.30439 + stype *buffer = new stype[siz]; \ 1.30440 + cimg::fread(buffer,siz,nfile); \ 1.30441 + if (endian) cimg::invert_endianness(buffer,siz); \ 1.30442 + T *ptrd = data; \ 1.30443 + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); \ 1.30444 + buffer-=siz; \ 1.30445 + delete[] buffer 1.30446 + 1.30447 +#define _cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype1,stype2,stype3,ltype) { \ 1.30448 + if (sizeof(stype1)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype1); } \ 1.30449 + else if (sizeof(stype2)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype2); } \ 1.30450 + else if (sizeof(stype3)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype3); } \ 1.30451 + else throw CImgIOException("CImg<%s>::load_pandore() : File '%s' cannot be read, datatype not supported on this architecture.", \ 1.30452 + pixel_type(),filename?filename:"(FILE*)"); } 1.30453 + 1.30454 + if (!filename && !file) 1.30455 + throw CImgArgumentException("CImg<%s>::load_pandore() : Cannot load (null) filename.", 1.30456 + pixel_type()); 1.30457 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); 1.30458 + typedef unsigned char uchar; 1.30459 + typedef unsigned short ushort; 1.30460 + typedef unsigned int uint; 1.30461 + typedef unsigned long ulong; 1.30462 + char header[32]; 1.30463 + cimg::fread(header,12,nfile); 1.30464 + if (cimg::strncasecmp("PANDORE",header,7)) { 1.30465 + if (!file) cimg::fclose(nfile); 1.30466 + throw CImgIOException("CImg<%s>::load_pandore() : File '%s' is not a valid PANDORE file, " 1.30467 + "(PANDORE identifier not found).", 1.30468 + pixel_type(),filename?filename:"(FILE*)"); 1.30469 + } 1.30470 + unsigned int imageid, dims[8]; 1.30471 + cimg::fread(&imageid,1,nfile); 1.30472 + const bool endian = (imageid>255); 1.30473 + if (endian) cimg::invert_endianness(imageid); 1.30474 + cimg::fread(header,20,nfile); 1.30475 + 1.30476 + switch (imageid) { 1.30477 + case 2: _cimg_load_pandore_case(2,dims[1],1,1,1,uchar,uchar,uchar,1); break; 1.30478 + case 3: _cimg_load_pandore_case(2,dims[1],1,1,1,long,int,short,4); break; 1.30479 + case 4: _cimg_load_pandore_case(2,dims[1],1,1,1,double,float,float,4); break; 1.30480 + case 5: _cimg_load_pandore_case(3,dims[2],dims[1],1,1,uchar,uchar,uchar,1); break; 1.30481 + case 6: _cimg_load_pandore_case(3,dims[2],dims[1],1,1,long,int,short,4); break; 1.30482 + case 7: _cimg_load_pandore_case(3,dims[2],dims[1],1,1,double,float,float,4); break; 1.30483 + case 8: _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,uchar,uchar,uchar,1); break; 1.30484 + case 9: _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,long,int,short,4); break; 1.30485 + case 10: _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,double,float,float,4); break; 1.30486 + case 11 : { // Region 1D 1.30487 + cimg::fread(dims,3,nfile); 1.30488 + if (endian) cimg::invert_endianness(dims,3); 1.30489 + assign(dims[1],1,1,1); 1.30490 + const unsigned siz = size(); 1.30491 + if (dims[2]<256) { 1.30492 + unsigned char *buffer = new unsigned char[siz]; 1.30493 + cimg::fread(buffer,siz,nfile); 1.30494 + T *ptrd = data; 1.30495 + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); 1.30496 + buffer-=siz; 1.30497 + delete[] buffer; 1.30498 + } else { 1.30499 + if (dims[2]<65536) { 1.30500 + unsigned short *buffer = new unsigned short[siz]; 1.30501 + cimg::fread(buffer,siz,nfile); 1.30502 + if (endian) cimg::invert_endianness(buffer,siz); 1.30503 + T *ptrd = data; 1.30504 + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); 1.30505 + buffer-=siz; 1.30506 + delete[] buffer; 1.30507 + } else { 1.30508 + unsigned int *buffer = new unsigned int[siz]; 1.30509 + cimg::fread(buffer,siz,nfile); 1.30510 + if (endian) cimg::invert_endianness(buffer,siz); 1.30511 + T *ptrd = data; 1.30512 + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); 1.30513 + buffer-=siz; 1.30514 + delete[] buffer; 1.30515 + } 1.30516 + } 1.30517 + } 1.30518 + break; 1.30519 + case 12 : { // Region 2D 1.30520 + cimg::fread(dims,4,nfile); 1.30521 + if (endian) cimg::invert_endianness(dims,4); 1.30522 + assign(dims[2],dims[1],1,1); 1.30523 + const unsigned int siz = size(); 1.30524 + if (dims[3]<256) { 1.30525 + unsigned char *buffer = new unsigned char[siz]; 1.30526 + cimg::fread(buffer,siz,nfile); 1.30527 + T *ptrd = data; 1.30528 + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); 1.30529 + buffer-=siz; 1.30530 + delete[] buffer; 1.30531 + } else { 1.30532 + if (dims[3]<65536) { 1.30533 + unsigned short *buffer = new unsigned short[siz]; 1.30534 + cimg::fread(buffer,siz,nfile); 1.30535 + if (endian) cimg::invert_endianness(buffer,siz); 1.30536 + T *ptrd = data; 1.30537 + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); 1.30538 + buffer-=siz; 1.30539 + delete[] buffer; 1.30540 + } else { 1.30541 + unsigned long *buffer = new unsigned long[siz]; 1.30542 + cimg::fread(buffer,siz,nfile); 1.30543 + if (endian) cimg::invert_endianness(buffer,siz); 1.30544 + T *ptrd = data; 1.30545 + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); 1.30546 + buffer-=siz; 1.30547 + delete[] buffer; 1.30548 + } 1.30549 + } 1.30550 + } 1.30551 + break; 1.30552 + case 13 : { // Region 3D 1.30553 + cimg::fread(dims,5,nfile); 1.30554 + if (endian) cimg::invert_endianness(dims,5); 1.30555 + assign(dims[3],dims[2],dims[1],1); 1.30556 + const unsigned int siz = size(); 1.30557 + if (dims[4]<256) { 1.30558 + unsigned char *buffer = new unsigned char[siz]; 1.30559 + cimg::fread(buffer,siz,nfile); 1.30560 + T *ptrd = data; 1.30561 + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); 1.30562 + buffer-=siz; 1.30563 + delete[] buffer; 1.30564 + } else { 1.30565 + if (dims[4]<65536) { 1.30566 + unsigned short *buffer = new unsigned short[siz]; 1.30567 + cimg::fread(buffer,siz,nfile); 1.30568 + if (endian) cimg::invert_endianness(buffer,siz); 1.30569 + T *ptrd = data; 1.30570 + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); 1.30571 + buffer-=siz; 1.30572 + delete[] buffer; 1.30573 + } else { 1.30574 + unsigned int *buffer = new unsigned int[siz]; 1.30575 + cimg::fread(buffer,siz,nfile); 1.30576 + if (endian) cimg::invert_endianness(buffer,siz); 1.30577 + T *ptrd = data; 1.30578 + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); 1.30579 + buffer-=siz; 1.30580 + delete[] buffer; 1.30581 + } 1.30582 + } 1.30583 + } 1.30584 + break; 1.30585 + case 16: _cimg_load_pandore_case(4,dims[2],dims[1],1,3,uchar,uchar,uchar,1); break; 1.30586 + case 17: _cimg_load_pandore_case(4,dims[2],dims[1],1,3,long,int,short,4); break; 1.30587 + case 18: _cimg_load_pandore_case(4,dims[2],dims[1],1,3,double,float,float,4); break; 1.30588 + case 19: _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,uchar,uchar,uchar,1); break; 1.30589 + case 20: _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,long,int,short,4); break; 1.30590 + case 21: _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,double,float,float,4); break; 1.30591 + case 22: _cimg_load_pandore_case(2,dims[1],1,1,dims[0],uchar,uchar,uchar,1); break; 1.30592 + case 23: _cimg_load_pandore_case(2,dims[1],1,1,dims[0],long,int,short,4); 1.30593 + case 24: _cimg_load_pandore_case(2,dims[1],1,1,dims[0],ulong,uint,ushort,4); break; 1.30594 + case 25: _cimg_load_pandore_case(2,dims[1],1,1,dims[0],double,float,float,4); break; 1.30595 + case 26: _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],uchar,uchar,uchar,1); break; 1.30596 + case 27: _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],long,int,short,4); break; 1.30597 + case 28: _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],ulong,uint,ushort,4); break; 1.30598 + case 29: _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],double,float,float,4); break; 1.30599 + case 30: _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],uchar,uchar,uchar,1); break; 1.30600 + case 31: _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],long,int,short,4); break; 1.30601 + case 32: _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],ulong,uint,ushort,4); break; 1.30602 + case 33: _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],double,float,float,4); break; 1.30603 + case 34 : { // Points 1D 1.30604 + int ptbuf[4]; 1.30605 + cimg::fread(ptbuf,1,nfile); 1.30606 + if (endian) cimg::invert_endianness(ptbuf,1); 1.30607 + assign(1); (*this)(0) = (T)ptbuf[0]; 1.30608 + } break; 1.30609 + case 35 : { // Points 2D 1.30610 + int ptbuf[4]; 1.30611 + cimg::fread(ptbuf,2,nfile); 1.30612 + if (endian) cimg::invert_endianness(ptbuf,2); 1.30613 + assign(2); (*this)(0) = (T)ptbuf[1]; (*this)(1) = (T)ptbuf[0]; 1.30614 + } break; 1.30615 + case 36 : { // Points 3D 1.30616 + int ptbuf[4]; 1.30617 + cimg::fread(ptbuf,3,nfile); 1.30618 + if (endian) cimg::invert_endianness(ptbuf,3); 1.30619 + assign(3); (*this)(0) = (T)ptbuf[2]; (*this)(1) = (T)ptbuf[1]; (*this)(2) = (T)ptbuf[0]; 1.30620 + } break; 1.30621 + default : 1.30622 + if (!file) cimg::fclose(nfile); 1.30623 + throw CImgIOException("CImg<%s>::load_pandore() : File '%s', cannot read images with ID_type = %u", 1.30624 + pixel_type(),filename?filename:"(FILE*)",imageid); 1.30625 + } 1.30626 + if (!file) cimg::fclose(nfile); 1.30627 + return *this; 1.30628 + } 1.30629 + 1.30630 + //! Load an image from a PAR-REC (Philips) file. 1.30631 + CImg<T>& load_parrec(const char *const filename, const char axis='v', const char align='p') { 1.30632 + CImgList<T> list; 1.30633 + list.load_parrec(filename); 1.30634 + if (list.size==1) return list[0].transfer_to(*this); 1.30635 + return assign(list.get_append(axis,align)); 1.30636 + } 1.30637 + 1.30638 + static CImg<T> get_load_parrec(const char *const filename, const char axis='v', const char align='p') { 1.30639 + return CImg<T>().load_parrec(filename,axis,align); 1.30640 + } 1.30641 + 1.30642 + //! Load an image from a .RAW file. 1.30643 + CImg<T>& load_raw(const char *const filename, 1.30644 + const unsigned int sizex, const unsigned int sizey=1, 1.30645 + const unsigned int sizez=1, const unsigned int sizev=1, 1.30646 + const bool multiplexed=false, const bool invert_endianness=false) { 1.30647 + return _load_raw(0,filename,sizex,sizey,sizez,sizev,multiplexed,invert_endianness); 1.30648 + } 1.30649 + 1.30650 + static CImg<T> get_load_raw(const char *const filename, 1.30651 + const unsigned int sizex, const unsigned int sizey=1, 1.30652 + const unsigned int sizez=1, const unsigned int sizev=1, 1.30653 + const bool multiplexed=false, const bool invert_endianness=false) { 1.30654 + return CImg<T>().load_raw(filename,sizex,sizey,sizez,sizev,multiplexed,invert_endianness); 1.30655 + } 1.30656 + 1.30657 + //! Load an image from a .RAW file. 1.30658 + CImg<T>& load_raw(cimg_std::FILE *const file, 1.30659 + const unsigned int sizex, const unsigned int sizey=1, 1.30660 + const unsigned int sizez=1, const unsigned int sizev=1, 1.30661 + const bool multiplexed=false, const bool invert_endianness=false) { 1.30662 + return _load_raw(file,0,sizex,sizey,sizez,sizev,multiplexed,invert_endianness); 1.30663 + } 1.30664 + 1.30665 + static CImg<T> get_load_raw(cimg_std::FILE *const file, 1.30666 + const unsigned int sizex, const unsigned int sizey=1, 1.30667 + const unsigned int sizez=1, const unsigned int sizev=1, 1.30668 + const bool multiplexed=false, const bool invert_endianness=false) { 1.30669 + return CImg<T>().load_raw(file,sizex,sizey,sizez,sizev,multiplexed,invert_endianness); 1.30670 + } 1.30671 + 1.30672 + CImg<T>& _load_raw(cimg_std::FILE *const file, const char *const filename, 1.30673 + const unsigned int sizex, const unsigned int sizey, 1.30674 + const unsigned int sizez, const unsigned int sizev, 1.30675 + const bool multiplexed, const bool invert_endianness) { 1.30676 + if (!filename && !file) 1.30677 + throw CImgArgumentException("CImg<%s>::load_raw() : Cannot load (null) filename.", 1.30678 + pixel_type()); 1.30679 + assign(sizex,sizey,sizez,sizev,0); 1.30680 + const unsigned int siz = size(); 1.30681 + if (siz) { 1.30682 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); 1.30683 + if (!multiplexed) { 1.30684 + cimg::fread(data,siz,nfile); 1.30685 + if (invert_endianness) cimg::invert_endianness(data,siz); 1.30686 + } 1.30687 + else { 1.30688 + CImg<T> buf(1,1,1,sizev); 1.30689 + cimg_forXYZ(*this,x,y,z) { 1.30690 + cimg::fread(buf.data,sizev,nfile); 1.30691 + if (invert_endianness) cimg::invert_endianness(buf.data,sizev); 1.30692 + set_vector_at(buf,x,y,z); } 1.30693 + } 1.30694 + if (!file) cimg::fclose(nfile); 1.30695 + } 1.30696 + return *this; 1.30697 + } 1.30698 + 1.30699 + //! Load a video sequence using FFMPEG av's libraries. 1.30700 + CImg<T>& load_ffmpeg(const char *const filename, const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.30701 + const unsigned int step_frame=1, const bool pixel_format=true, const bool resume=false, 1.30702 + const char axis='z', const char align='p') { 1.30703 + return get_load_ffmpeg(filename,first_frame,last_frame,step_frame,pixel_format,resume,axis,align).transfer_to(*this); 1.30704 + } 1.30705 + 1.30706 + static CImg<T> get_load_ffmpeg(const char *const filename, const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.30707 + const unsigned int step_frame=1, const bool pixel_format=true, const bool resume=false, 1.30708 + const char axis='z', const char align='p') { 1.30709 + return CImgList<T>().load_ffmpeg(filename,first_frame,last_frame,step_frame,pixel_format,resume).get_append(axis,align); 1.30710 + } 1.30711 + 1.30712 + //! Load an image sequence from a YUV file. 1.30713 + CImg<T>& load_yuv(const char *const filename, 1.30714 + const unsigned int sizex, const unsigned int sizey=1, 1.30715 + const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.30716 + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z', const char align='p') { 1.30717 + return get_load_yuv(filename,sizex,sizey,first_frame,last_frame,step_frame,yuv2rgb,axis,align).transfer_to(*this); 1.30718 + } 1.30719 + 1.30720 + static CImg<T> get_load_yuv(const char *const filename, 1.30721 + const unsigned int sizex, const unsigned int sizey=1, 1.30722 + const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.30723 + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z', const char align='p') { 1.30724 + return CImgList<T>().load_yuv(filename,sizex,sizey,first_frame,last_frame,step_frame,yuv2rgb).get_append(axis,align); 1.30725 + } 1.30726 + 1.30727 + //! Load an image sequence from a YUV file. 1.30728 + CImg<T>& load_yuv(cimg_std::FILE *const file, 1.30729 + const unsigned int sizex, const unsigned int sizey=1, 1.30730 + const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.30731 + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z', const char align='p') { 1.30732 + return get_load_yuv(file,sizex,sizey,first_frame,last_frame,step_frame,yuv2rgb,axis,align).transfer_to(*this); 1.30733 + } 1.30734 + 1.30735 + static CImg<T> get_load_yuv(cimg_std::FILE *const file, 1.30736 + const unsigned int sizex, const unsigned int sizey=1, 1.30737 + const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.30738 + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z', const char align='p') { 1.30739 + return CImgList<T>().load_yuv(file,sizex,sizey,first_frame,last_frame,step_frame,yuv2rgb).get_append(axis,align); 1.30740 + } 1.30741 + 1.30742 + //! Load a 3D object from a .OFF file. 1.30743 + template<typename tf, typename tc> 1.30744 + CImg<T>& load_off(const char *const filename, CImgList<tf>& primitives, CImgList<tc>& colors, const bool invert_faces=false) { 1.30745 + return _load_off(0,filename,primitives,colors,invert_faces); 1.30746 + } 1.30747 + 1.30748 + template<typename tf, typename tc> 1.30749 + static CImg<T> get_load_off(const char *const filename, CImgList<tf>& primitives, CImgList<tc>& colors, 1.30750 + const bool invert_faces=false) { 1.30751 + return CImg<T>().load_off(filename,primitives,colors,invert_faces); 1.30752 + } 1.30753 + 1.30754 + //! Load a 3D object from a .OFF file. 1.30755 + template<typename tf, typename tc> 1.30756 + CImg<T>& load_off(cimg_std::FILE *const file, CImgList<tf>& primitives, CImgList<tc>& colors, const bool invert_faces=false) { 1.30757 + return _load_off(file,0,primitives,colors,invert_faces); 1.30758 + } 1.30759 + 1.30760 + template<typename tf, typename tc> 1.30761 + static CImg<T> get_load_off(cimg_std::FILE *const file, CImgList<tf>& primitives, CImgList<tc>& colors, 1.30762 + const bool invert_faces=false) { 1.30763 + return CImg<T>().load_off(file,primitives,colors,invert_faces); 1.30764 + } 1.30765 + 1.30766 + template<typename tf, typename tc> 1.30767 + CImg<T>& _load_off(cimg_std::FILE *const file, const char *const filename, 1.30768 + CImgList<tf>& primitives, CImgList<tc>& colors, const bool invert_faces) { 1.30769 + if (!filename && !file) 1.30770 + throw CImgArgumentException("CImg<%s>::load_off() : Cannot load (null) filename.", 1.30771 + pixel_type()); 1.30772 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"r"); 1.30773 + unsigned int nb_points = 0, nb_primitives = 0, nb_read = 0; 1.30774 + char line[256] = { 0 }; 1.30775 + int err; 1.30776 + 1.30777 + // Skip comments, and read magic string OFF 1.30778 + do { err = cimg_std::fscanf(nfile,"%255[^\n] ",line); } while (!err || (err==1 && line[0]=='#')); 1.30779 + if (cimg::strncasecmp(line,"OFF",3) && cimg::strncasecmp(line,"COFF",4)) { 1.30780 + if (!file) cimg::fclose(nfile); 1.30781 + throw CImgIOException("CImg<%s>::load_off() : File '%s', keyword 'OFF' not found.", 1.30782 + pixel_type(),filename?filename:"(FILE*)"); 1.30783 + } 1.30784 + do { err = cimg_std::fscanf(nfile,"%255[^\n] ",line); } while (!err || (err==1 && line[0]=='#')); 1.30785 + if ((err = cimg_std::sscanf(line,"%u%u%*[^\n] ",&nb_points,&nb_primitives))!=2) { 1.30786 + if (!file) cimg::fclose(nfile); 1.30787 + throw CImgIOException("CImg<%s>::load_off() : File '%s', invalid vertices/primitives numbers.", 1.30788 + pixel_type(),filename?filename:"(FILE*)"); 1.30789 + } 1.30790 + 1.30791 + // Read points data 1.30792 + assign(nb_points,3); 1.30793 + float X = 0, Y = 0, Z = 0; 1.30794 + cimg_forX(*this,l) { 1.30795 + do { err = cimg_std::fscanf(nfile,"%255[^\n] ",line); } while (!err || (err==1 && line[0]=='#')); 1.30796 + if ((err = cimg_std::sscanf(line,"%f%f%f%*[^\n] ",&X,&Y,&Z))!=3) { 1.30797 + if (!file) cimg::fclose(nfile); 1.30798 + throw CImgIOException("CImg<%s>::load_off() : File '%s', cannot read point %u/%u.\n", 1.30799 + pixel_type(),filename?filename:"(FILE*)",l+1,nb_points); 1.30800 + } 1.30801 + (*this)(l,0) = (T)X; (*this)(l,1) = (T)Y; (*this)(l,2) = (T)Z; 1.30802 + } 1.30803 + 1.30804 + // Read primitive data 1.30805 + primitives.assign(); 1.30806 + colors.assign(); 1.30807 + bool stopflag = false; 1.30808 + while (!stopflag) { 1.30809 + float c0 = 0.7f, c1 = 0.7f, c2 = 0.7f; 1.30810 + unsigned int prim = 0, i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, i6 = 0, i7 = 0; 1.30811 + line[0]='\0'; 1.30812 + if ((err = cimg_std::fscanf(nfile,"%u",&prim))!=1) stopflag=true; 1.30813 + else { 1.30814 + ++nb_read; 1.30815 + switch (prim) { 1.30816 + case 1 : { 1.30817 + if ((err = cimg_std::fscanf(nfile,"%u%255[^\n] ",&i0,line))<2) { 1.30818 + cimg::warn("CImg<%s>::load_off() : File '%s', invalid primitive %u/%u.", 1.30819 + pixel_type(),filename?filename:"(FILE*)",nb_read,nb_primitives); 1.30820 + err = cimg_std::fscanf(nfile,"%*[^\n] "); 1.30821 + } else { 1.30822 + err = cimg_std::sscanf(line,"%f%f%f",&c0,&c1,&c2); 1.30823 + primitives.insert(CImg<tf>::vector(i0)); 1.30824 + colors.insert(CImg<tc>::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); 1.30825 + } 1.30826 + } break; 1.30827 + case 2 : { 1.30828 + if ((err = cimg_std::fscanf(nfile,"%u%u%255[^\n] ",&i0,&i1,line))<2) { 1.30829 + cimg::warn("CImg<%s>::load_off() : File '%s', invalid primitive %u/%u.", 1.30830 + pixel_type(),filename?filename:"(FILE*)",nb_read,nb_primitives); 1.30831 + err = cimg_std::fscanf(nfile,"%*[^\n] "); 1.30832 + } else { 1.30833 + err = cimg_std::sscanf(line,"%f%f%f",&c0,&c1,&c2); 1.30834 + primitives.insert(CImg<tf>::vector(i0,i1)); 1.30835 + colors.insert(CImg<tc>::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); 1.30836 + } 1.30837 + } break; 1.30838 + case 3 : { 1.30839 + if ((err = cimg_std::fscanf(nfile,"%u%u%u%255[^\n] ",&i0,&i1,&i2,line))<3) { 1.30840 + cimg::warn("CImg<%s>::load_off() : File '%s', invalid primitive %u/%u.", 1.30841 + pixel_type(),filename?filename:"(FILE*)",nb_read,nb_primitives); 1.30842 + err = cimg_std::fscanf(nfile,"%*[^\n] "); 1.30843 + } else { 1.30844 + err = cimg_std::sscanf(line,"%f%f%f",&c0,&c1,&c2); 1.30845 + if (invert_faces) primitives.insert(CImg<tf>::vector(i0,i1,i2)); 1.30846 + else primitives.insert(CImg<tf>::vector(i0,i2,i1)); 1.30847 + colors.insert(CImg<tc>::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); 1.30848 + } 1.30849 + } break; 1.30850 + case 4 : { 1.30851 + if ((err = cimg_std::fscanf(nfile,"%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,line))<4) { 1.30852 + cimg::warn("CImg<%s>::load_off() : File '%s', invalid primitive %u/%u.", 1.30853 + pixel_type(),filename?filename:"(FILE*)",nb_read,nb_primitives); 1.30854 + err = cimg_std::fscanf(nfile,"%*[^\n] "); 1.30855 + } else { 1.30856 + err = cimg_std::sscanf(line,"%f%f%f",&c0,&c1,&c2); 1.30857 + if (invert_faces) primitives.insert(CImg<tf>::vector(i0,i1,i2,i3)); 1.30858 + else primitives.insert(CImg<tf>::vector(i0,i3,i2,i1)); 1.30859 + colors.insert(CImg<tc>::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255),(tc)(c2*255))); 1.30860 + } 1.30861 + } break; 1.30862 + case 5 : { 1.30863 + if ((err = cimg_std::fscanf(nfile,"%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,line))<5) { 1.30864 + cimg::warn("CImg<%s>::load_off() : File '%s', invalid primitive %u/%u.", 1.30865 + pixel_type(),filename?filename:"(FILE*)",nb_read,nb_primitives); 1.30866 + err = cimg_std::fscanf(nfile,"%*[^\n] "); 1.30867 + } else { 1.30868 + err = cimg_std::sscanf(line,"%f%f%f",&c0,&c1,&c2); 1.30869 + if (invert_faces) { 1.30870 + primitives.insert(CImg<tf>::vector(i0,i1,i2,i3)); 1.30871 + primitives.insert(CImg<tf>::vector(i0,i3,i4)); 1.30872 + } 1.30873 + else { 1.30874 + primitives.insert(CImg<tf>::vector(i0,i3,i2,i1)); 1.30875 + primitives.insert(CImg<tf>::vector(i0,i4,i3)); 1.30876 + } 1.30877 + colors.insert(2,CImg<tc>::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255),(tc)(c2*255))); 1.30878 + ++nb_primitives; 1.30879 + } 1.30880 + } break; 1.30881 + case 6 : { 1.30882 + if ((err = cimg_std::fscanf(nfile,"%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,line))<6) { 1.30883 + cimg::warn("CImg<%s>::load_off() : File '%s', invalid primitive %u/%u.", 1.30884 + pixel_type(),filename?filename:"(FILE*)",nb_read,nb_primitives); 1.30885 + err = cimg_std::fscanf(nfile,"%*[^\n] "); 1.30886 + } else { 1.30887 + err = cimg_std::sscanf(line,"%f%f%f",&c0,&c1,&c2); 1.30888 + if (invert_faces) { 1.30889 + primitives.insert(CImg<tf>::vector(i0,i1,i2,i3)); 1.30890 + primitives.insert(CImg<tf>::vector(i0,i3,i4,i5)); 1.30891 + } 1.30892 + else { 1.30893 + primitives.insert(CImg<tf>::vector(i0,i3,i2,i1)); 1.30894 + primitives.insert(CImg<tf>::vector(i0,i5,i4,i3)); 1.30895 + } 1.30896 + colors.insert(2,CImg<tc>::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255),(tc)(c2*255))); 1.30897 + ++nb_primitives; 1.30898 + } 1.30899 + } break; 1.30900 + case 7 : { 1.30901 + if ((err = cimg_std::fscanf(nfile,"%u%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,&i6,line))<7) { 1.30902 + cimg::warn("CImg<%s>::load_off() : File '%s', invalid primitive %u/%u.", 1.30903 + pixel_type(),filename?filename:"(FILE*)",nb_read,nb_primitives); 1.30904 + err = cimg_std::fscanf(nfile,"%*[^\n] "); 1.30905 + } else { 1.30906 + err = cimg_std::sscanf(line,"%f%f%f",&c0,&c1,&c2); 1.30907 + if (invert_faces) { 1.30908 + primitives.insert(CImg<tf>::vector(i0,i1,i3,i4)); 1.30909 + primitives.insert(CImg<tf>::vector(i0,i4,i5,i6)); 1.30910 + primitives.insert(CImg<tf>::vector(i1,i2,i3)); 1.30911 + } 1.30912 + else { 1.30913 + primitives.insert(CImg<tf>::vector(i0,i4,i3,i1)); 1.30914 + primitives.insert(CImg<tf>::vector(i0,i6,i5,i4)); 1.30915 + primitives.insert(CImg<tf>::vector(i3,i2,i1)); 1.30916 + } 1.30917 + colors.insert(2,CImg<tc>::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255),(tc)(c2*255))); 1.30918 + ++(++nb_primitives); 1.30919 + } 1.30920 + } break; 1.30921 + case 8 : { 1.30922 + if ((err = cimg_std::fscanf(nfile,"%u%u%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,&i6,&i7,line))<7) { 1.30923 + cimg::warn("CImg<%s>::load_off() : File '%s', invalid primitive %u/%u.", 1.30924 + pixel_type(),filename?filename:"(FILE*)",nb_read,nb_primitives); 1.30925 + err = cimg_std::fscanf(nfile,"%*[^\n] "); 1.30926 + } else { 1.30927 + err = cimg_std::sscanf(line,"%f%f%f",&c0,&c1,&c2); 1.30928 + if (invert_faces) { 1.30929 + primitives.insert(CImg<tf>::vector(i0,i1,i2,i3)); 1.30930 + primitives.insert(CImg<tf>::vector(i0,i3,i4,i5)); 1.30931 + primitives.insert(CImg<tf>::vector(i0,i5,i6,i7)); 1.30932 + } 1.30933 + else { 1.30934 + primitives.insert(CImg<tf>::vector(i0,i3,i2,i1)); 1.30935 + primitives.insert(CImg<tf>::vector(i0,i5,i4,i3)); 1.30936 + primitives.insert(CImg<tf>::vector(i0,i7,i6,i5)); 1.30937 + } 1.30938 + colors.insert(2,CImg<tc>::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255),(tc)(c2*255))); 1.30939 + ++(++nb_primitives); 1.30940 + } 1.30941 + } break; 1.30942 + default : 1.30943 + cimg::warn("CImg<%s>::load_off() : File '%s', invalid primitive %u/%u (%u vertices).", 1.30944 + pixel_type(),filename?filename:"(FILE*)",nb_read,nb_primitives,prim); 1.30945 + err = cimg_std::fscanf(nfile,"%*[^\n] "); 1.30946 + } 1.30947 + } 1.30948 + } 1.30949 + if (!file) cimg::fclose(nfile); 1.30950 + if (primitives.size!=nb_primitives) 1.30951 + cimg::warn("CImg<%s>::load_off() : File '%s', read only %u primitives instead of %u as claimed in the header.", 1.30952 + pixel_type(),filename?filename:"(FILE*)",primitives.size,nb_primitives); 1.30953 + return *this; 1.30954 + } 1.30955 + 1.30956 + //! Load a video sequence using FFMPEG's external tool 'ffmpeg'. 1.30957 + CImg<T>& load_ffmpeg_external(const char *const filename, const char axis='z', const char align='p') { 1.30958 + return get_load_ffmpeg_external(filename,axis,align).transfer_to(*this); 1.30959 + } 1.30960 + 1.30961 + static CImg<T> get_load_ffmpeg_external(const char *const filename, const char axis='z', const char align='p') { 1.30962 + return CImgList<T>().load_ffmpeg_external(filename).get_append(axis,align); 1.30963 + } 1.30964 + 1.30965 + //! Load an image using GraphicsMagick's external tool 'gm'. 1.30966 + CImg<T>& load_graphicsmagick_external(const char *const filename) { 1.30967 + if (!filename) 1.30968 + throw CImgArgumentException("CImg<%s>::load_graphicsmagick_external() : Cannot load (null) filename.", 1.30969 + pixel_type()); 1.30970 + char command[1024], filetmp[512]; 1.30971 + cimg_std::FILE *file = 0; 1.30972 +#if cimg_OS==1 1.30973 + cimg_std::sprintf(command,"%s convert \"%s\" ppm:-",cimg::graphicsmagick_path(),filename); 1.30974 + file = popen(command,"r"); 1.30975 + if (file) { load_pnm(file); pclose(file); return *this; } 1.30976 +#endif 1.30977 + do { 1.30978 + cimg_std::sprintf(filetmp,"%s%s%s.ppm",cimg::temporary_path(),cimg_OS==2?"\\":"/",cimg::filenamerand()); 1.30979 + if ((file=cimg_std::fopen(filetmp,"rb"))!=0) cimg_std::fclose(file); 1.30980 + } while (file); 1.30981 + cimg_std::sprintf(command,"%s convert \"%s\" %s",cimg::graphicsmagick_path(),filename,filetmp); 1.30982 + cimg::system(command,cimg::graphicsmagick_path()); 1.30983 + if (!(file = cimg_std::fopen(filetmp,"rb"))) { 1.30984 + cimg::fclose(cimg::fopen(filename,"r")); 1.30985 + throw CImgIOException("CImg<%s>::load_graphicsmagick_external() : Failed to open image '%s'.\n\n" 1.30986 + "Path of 'GraphicsMagick's gm' : \"%s\"\n" 1.30987 + "Path of temporary filename : \"%s\"", 1.30988 + pixel_type(),filename,cimg::graphicsmagick_path(),filetmp); 1.30989 + } else cimg::fclose(file); 1.30990 + load_pnm(filetmp); 1.30991 + cimg_std::remove(filetmp); 1.30992 + return *this; 1.30993 + } 1.30994 + 1.30995 + static CImg<T> get_load_graphicsmagick_external(const char *const filename) { 1.30996 + return CImg<T>().load_graphicsmagick_external(filename); 1.30997 + } 1.30998 + 1.30999 + //! Load a gzipped image file, using external tool 'gunzip'. 1.31000 + CImg<T>& load_gzip_external(const char *const filename) { 1.31001 + if (!filename) 1.31002 + throw CImgIOException("CImg<%s>::load_gzip_external() : Cannot load (null) filename.", 1.31003 + pixel_type()); 1.31004 + char command[1024], filetmp[512], body[512]; 1.31005 + const char 1.31006 + *ext = cimg::split_filename(filename,body), 1.31007 + *ext2 = cimg::split_filename(body,0); 1.31008 + cimg_std::FILE *file = 0; 1.31009 + do { 1.31010 + if (!cimg::strcasecmp(ext,"gz")) { 1.31011 + if (*ext2) cimg_std::sprintf(filetmp,"%s%s%s.%s",cimg::temporary_path(),cimg_OS==2?"\\":"/", 1.31012 + cimg::filenamerand(),ext2); 1.31013 + else cimg_std::sprintf(filetmp,"%s%s%s",cimg::temporary_path(),cimg_OS==2?"\\":"/", 1.31014 + cimg::filenamerand()); 1.31015 + } else { 1.31016 + if (*ext) cimg_std::sprintf(filetmp,"%s%s%s.%s",cimg::temporary_path(),cimg_OS==2?"\\":"/", 1.31017 + cimg::filenamerand(),ext); 1.31018 + else cimg_std::sprintf(filetmp,"%s%s%s",cimg::temporary_path(),cimg_OS==2?"\\":"/", 1.31019 + cimg::filenamerand()); 1.31020 + } 1.31021 + if ((file=cimg_std::fopen(filetmp,"rb"))!=0) cimg_std::fclose(file); 1.31022 + } while (file); 1.31023 + cimg_std::sprintf(command,"%s -c \"%s\" > %s",cimg::gunzip_path(),filename,filetmp); 1.31024 + cimg::system(command); 1.31025 + if (!(file = cimg_std::fopen(filetmp,"rb"))) { 1.31026 + cimg::fclose(cimg::fopen(filename,"r")); 1.31027 + throw CImgIOException("CImg<%s>::load_gzip_external() : File '%s' cannot be opened.", 1.31028 + pixel_type(),filename); 1.31029 + } else cimg::fclose(file); 1.31030 + load(filetmp); 1.31031 + cimg_std::remove(filetmp); 1.31032 + return *this; 1.31033 + } 1.31034 + 1.31035 + static CImg<T> get_load_gzip_external(const char *const filename) { 1.31036 + return CImg<T>().load_gzip_external(filename); 1.31037 + } 1.31038 + 1.31039 + //! Load an image using ImageMagick's external tool 'convert'. 1.31040 + CImg<T>& load_imagemagick_external(const char *const filename) { 1.31041 + if (!filename) 1.31042 + throw CImgArgumentException("CImg<%s>::load_imagemagick_external() : Cannot load (null) filename.", 1.31043 + pixel_type()); 1.31044 + char command[1024], filetmp[512]; 1.31045 + cimg_std::FILE *file = 0; 1.31046 +#if cimg_OS==1 1.31047 + cimg_std::sprintf(command,"%s \"%s\" ppm:-",cimg::imagemagick_path(),filename); 1.31048 + file = popen(command,"r"); 1.31049 + if (file) { load_pnm(file); pclose(file); return *this; } 1.31050 +#endif 1.31051 + do { 1.31052 + cimg_std::sprintf(filetmp,"%s%s%s.ppm",cimg::temporary_path(),cimg_OS==2?"\\":"/",cimg::filenamerand()); 1.31053 + if ((file=cimg_std::fopen(filetmp,"rb"))!=0) cimg_std::fclose(file); 1.31054 + } while (file); 1.31055 + cimg_std::sprintf(command,"%s \"%s\" %s",cimg::imagemagick_path(),filename,filetmp); 1.31056 + cimg::system(command,cimg::imagemagick_path()); 1.31057 + if (!(file = cimg_std::fopen(filetmp,"rb"))) { 1.31058 + cimg::fclose(cimg::fopen(filename,"r")); 1.31059 + throw CImgIOException("CImg<%s>::load_imagemagick_external() : Failed to open image '%s'.\n\n" 1.31060 + "Path of 'ImageMagick's convert' : \"%s\"\n" 1.31061 + "Path of temporary filename : \"%s\"", 1.31062 + pixel_type(),filename,cimg::imagemagick_path(),filetmp); 1.31063 + } else cimg::fclose(file); 1.31064 + load_pnm(filetmp); 1.31065 + cimg_std::remove(filetmp); 1.31066 + return *this; 1.31067 + } 1.31068 + 1.31069 + static CImg<T> get_load_imagemagick_external(const char *const filename) { 1.31070 + return CImg<T>().load_imagemagick_external(filename); 1.31071 + } 1.31072 + 1.31073 + //! Load a DICOM image file, using XMedcon's external tool 'medcon'. 1.31074 + CImg<T>& load_medcon_external(const char *const filename) { 1.31075 + if (!filename) 1.31076 + throw CImgArgumentException("CImg<%s>::load_medcon_external() : Cannot load (null) filename.", 1.31077 + pixel_type()); 1.31078 + char command[1024], filetmp[512], body[512]; 1.31079 + cimg::fclose(cimg::fopen(filename,"r")); 1.31080 + cimg_std::FILE *file = 0; 1.31081 + do { 1.31082 + cimg_std::sprintf(filetmp,"%s.hdr",cimg::filenamerand()); 1.31083 + if ((file=cimg_std::fopen(filetmp,"rb"))!=0) cimg_std::fclose(file); 1.31084 + } while (file); 1.31085 + cimg_std::sprintf(command,"%s -w -c anlz -o %s -f %s",cimg::medcon_path(),filetmp,filename); 1.31086 + cimg::system(command); 1.31087 + cimg::split_filename(filetmp,body); 1.31088 + cimg_std::sprintf(command,"m000-%s.hdr",body); 1.31089 + file = cimg_std::fopen(command,"rb"); 1.31090 + if (!file) { 1.31091 + throw CImgIOException("CImg<%s>::load_medcon_external() : Failed to open image '%s'.\n\n" 1.31092 + "Path of 'medcon' : \"%s\"\n" 1.31093 + "Path of temporary filename : \"%s\"", 1.31094 + pixel_type(),filename,cimg::medcon_path(),filetmp); 1.31095 + } else cimg::fclose(file); 1.31096 + load_analyze(command); 1.31097 + cimg_std::remove(command); 1.31098 + cimg_std::sprintf(command,"m000-%s.img",body); 1.31099 + cimg_std::remove(command); 1.31100 + return *this; 1.31101 + } 1.31102 + 1.31103 + static CImg<T> get_load_medcon_external(const char *const filename) { 1.31104 + return CImg<T>().load_medcon_external(filename); 1.31105 + } 1.31106 + 1.31107 + //! Load a RAW Color Camera image file, using external tool 'dcraw'. 1.31108 + CImg<T>& load_dcraw_external(const char *const filename) { 1.31109 + if (!filename) 1.31110 + throw CImgArgumentException("CImg<%s>::load_dcraw_external() : Cannot load (null) filename.", 1.31111 + pixel_type()); 1.31112 + char command[1024], filetmp[512]; 1.31113 + cimg_std::FILE *file = 0; 1.31114 +#if cimg_OS==1 1.31115 + cimg_std::sprintf(command,"%s -4 -c \"%s\"",cimg::dcraw_path(),filename); 1.31116 + file = popen(command,"r"); 1.31117 + if (file) { load_pnm(file); pclose(file); return *this; } 1.31118 +#endif 1.31119 + do { 1.31120 + cimg_std::sprintf(filetmp,"%s%s%s.ppm",cimg::temporary_path(),cimg_OS==2?"\\":"/",cimg::filenamerand()); 1.31121 + if ((file=cimg_std::fopen(filetmp,"rb"))!=0) cimg_std::fclose(file); 1.31122 + } while (file); 1.31123 + cimg_std::sprintf(command,"%s -4 -c \"%s\" > %s",cimg::dcraw_path(),filename,filetmp); 1.31124 + cimg::system(command,cimg::dcraw_path()); 1.31125 + if (!(file = cimg_std::fopen(filetmp,"rb"))) { 1.31126 + cimg::fclose(cimg::fopen(filename,"r")); 1.31127 + throw CImgIOException("CImg<%s>::load_dcraw_external() : Failed to open image '%s'.\n\n" 1.31128 + "Path of 'dcraw' : \"%s\"\n" 1.31129 + "Path of temporary filename : \"%s\"", 1.31130 + pixel_type(),filename,cimg::dcraw_path(),filetmp); 1.31131 + } else cimg::fclose(file); 1.31132 + load_pnm(filetmp); 1.31133 + cimg_std::remove(filetmp); 1.31134 + return *this; 1.31135 + } 1.31136 + 1.31137 + static CImg<T> get_load_dcraw_external(const char *const filename) { 1.31138 + return CImg<T>().load_dcraw_external(filename); 1.31139 + } 1.31140 + 1.31141 + //! Load an image using ImageMagick's or GraphicsMagick's executables. 1.31142 + CImg<T>& load_other(const char *const filename) { 1.31143 + if (!filename) 1.31144 + throw CImgArgumentException("CImg<%s>::load_other() : Cannot load (null) filename.", 1.31145 + pixel_type()); 1.31146 + const unsigned int odebug = cimg::exception_mode(); 1.31147 + cimg::exception_mode() = 0; 1.31148 + try { load_magick(filename); } 1.31149 + catch (CImgException&) { 1.31150 + try { load_imagemagick_external(filename); } 1.31151 + catch (CImgException&) { 1.31152 + try { load_graphicsmagick_external(filename); } 1.31153 + catch (CImgException&) { 1.31154 + assign(); 1.31155 + } 1.31156 + } 1.31157 + } 1.31158 + cimg::exception_mode() = odebug; 1.31159 + if (is_empty()) 1.31160 + throw CImgIOException("CImg<%s>::load_other() : File '%s' cannot be opened.", 1.31161 + pixel_type(),filename); 1.31162 + return *this; 1.31163 + } 1.31164 + 1.31165 + static CImg<T> get_load_other(const char *const filename) { 1.31166 + return CImg<T>().load_other(filename); 1.31167 + } 1.31168 + 1.31169 + //@} 1.31170 + //--------------------------- 1.31171 + // 1.31172 + //! \name Image File Saving 1.31173 + //@{ 1.31174 + //--------------------------- 1.31175 + 1.31176 + //! Save the image as a file. 1.31177 + /** 1.31178 + The used file format is defined by the file extension in the filename \p filename. 1.31179 + Parameter \p number can be used to add a 6-digit number to the filename before saving. 1.31180 + **/ 1.31181 + const CImg<T>& save(const char *const filename, const int number=-1) const { 1.31182 + if (is_empty()) 1.31183 + throw CImgInstanceException("CImg<%s>::save() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.31184 + pixel_type(),filename?filename:"(null)",width,height,depth,dim,data); 1.31185 + if (!filename) 1.31186 + throw CImgArgumentException("CImg<%s>::save() : Instance image (%u,%u,%u,%u,%p) cannot be saved as a (null) filename.", 1.31187 + pixel_type(),width,height,depth,dim,data); 1.31188 + const char *ext = cimg::split_filename(filename); 1.31189 + char nfilename[1024]; 1.31190 + const char *const fn = (number>=0)?cimg::number_filename(filename,number,6,nfilename):filename; 1.31191 +#ifdef cimg_save_plugin 1.31192 + cimg_save_plugin(fn); 1.31193 +#endif 1.31194 +#ifdef cimg_save_plugin1 1.31195 + cimg_save_plugin1(fn); 1.31196 +#endif 1.31197 +#ifdef cimg_save_plugin2 1.31198 + cimg_save_plugin2(fn); 1.31199 +#endif 1.31200 +#ifdef cimg_save_plugin3 1.31201 + cimg_save_plugin3(fn); 1.31202 +#endif 1.31203 +#ifdef cimg_save_plugin4 1.31204 + cimg_save_plugin4(fn); 1.31205 +#endif 1.31206 +#ifdef cimg_save_plugin5 1.31207 + cimg_save_plugin5(fn); 1.31208 +#endif 1.31209 +#ifdef cimg_save_plugin6 1.31210 + cimg_save_plugin6(fn); 1.31211 +#endif 1.31212 +#ifdef cimg_save_plugin7 1.31213 + cimg_save_plugin7(fn); 1.31214 +#endif 1.31215 +#ifdef cimg_save_plugin8 1.31216 + cimg_save_plugin8(fn); 1.31217 +#endif 1.31218 + // ASCII formats 1.31219 + if (!cimg::strcasecmp(ext,"asc")) return save_ascii(fn); 1.31220 + if (!cimg::strcasecmp(ext,"dlm") || 1.31221 + !cimg::strcasecmp(ext,"txt")) return save_dlm(fn); 1.31222 + if (!cimg::strcasecmp(ext,"cpp") || 1.31223 + !cimg::strcasecmp(ext,"hpp") || 1.31224 + !cimg::strcasecmp(ext,"h") || 1.31225 + !cimg::strcasecmp(ext,"c")) return save_cpp(fn); 1.31226 + 1.31227 + // 2D binary formats 1.31228 + if (!cimg::strcasecmp(ext,"bmp")) return save_bmp(fn); 1.31229 + if (!cimg::strcasecmp(ext,"jpg") || 1.31230 + !cimg::strcasecmp(ext,"jpeg") || 1.31231 + !cimg::strcasecmp(ext,"jpe") || 1.31232 + !cimg::strcasecmp(ext,"jfif") || 1.31233 + !cimg::strcasecmp(ext,"jif")) return save_jpeg(fn); 1.31234 + if (!cimg::strcasecmp(ext,"rgb")) return save_rgb(fn); 1.31235 + if (!cimg::strcasecmp(ext,"rgba")) return save_rgba(fn); 1.31236 + if (!cimg::strcasecmp(ext,"png")) return save_png(fn); 1.31237 + if (!cimg::strcasecmp(ext,"pgm") || 1.31238 + !cimg::strcasecmp(ext,"ppm") || 1.31239 + !cimg::strcasecmp(ext,"pnm")) return save_pnm(fn); 1.31240 + if (!cimg::strcasecmp(ext,"tif") || 1.31241 + !cimg::strcasecmp(ext,"tiff")) return save_tiff(fn); 1.31242 + 1.31243 + // 3D binary formats 1.31244 + if (!cimg::strcasecmp(ext,"cimgz")) return save_cimg(fn,true); 1.31245 + if (!cimg::strcasecmp(ext,"cimg") || ext[0]=='\0') return save_cimg(fn,false); 1.31246 + if (!cimg::strcasecmp(ext,"dcm")) return save_medcon_external(fn); 1.31247 + if (!cimg::strcasecmp(ext,"hdr") || 1.31248 + !cimg::strcasecmp(ext,"nii")) return save_analyze(fn); 1.31249 + if (!cimg::strcasecmp(ext,"inr")) return save_inr(fn); 1.31250 + if (!cimg::strcasecmp(ext,"pan")) return save_pandore(fn); 1.31251 + if (!cimg::strcasecmp(ext,"raw")) return save_raw(fn); 1.31252 + 1.31253 + // Archive files 1.31254 + if (!cimg::strcasecmp(ext,"gz")) return save_gzip_external(fn); 1.31255 + 1.31256 + // Image sequences 1.31257 + if (!cimg::strcasecmp(ext,"yuv")) return save_yuv(fn,true); 1.31258 + if (!cimg::strcasecmp(ext,"avi") || 1.31259 + !cimg::strcasecmp(ext,"mov") || 1.31260 + !cimg::strcasecmp(ext,"asf") || 1.31261 + !cimg::strcasecmp(ext,"divx") || 1.31262 + !cimg::strcasecmp(ext,"flv") || 1.31263 + !cimg::strcasecmp(ext,"mpg") || 1.31264 + !cimg::strcasecmp(ext,"m1v") || 1.31265 + !cimg::strcasecmp(ext,"m2v") || 1.31266 + !cimg::strcasecmp(ext,"m4v") || 1.31267 + !cimg::strcasecmp(ext,"mjp") || 1.31268 + !cimg::strcasecmp(ext,"mkv") || 1.31269 + !cimg::strcasecmp(ext,"mpe") || 1.31270 + !cimg::strcasecmp(ext,"movie") || 1.31271 + !cimg::strcasecmp(ext,"ogm") || 1.31272 + !cimg::strcasecmp(ext,"qt") || 1.31273 + !cimg::strcasecmp(ext,"rm") || 1.31274 + !cimg::strcasecmp(ext,"vob") || 1.31275 + !cimg::strcasecmp(ext,"wmv") || 1.31276 + !cimg::strcasecmp(ext,"xvid") || 1.31277 + !cimg::strcasecmp(ext,"mpeg")) return save_ffmpeg(fn); 1.31278 + return save_other(fn); 1.31279 + } 1.31280 + 1.31281 + // Save the image as an ASCII file (ASCII Raw + simple header) (internal). 1.31282 + const CImg<T>& _save_ascii(cimg_std::FILE *const file, const char *const filename) const { 1.31283 + if (is_empty()) 1.31284 + throw CImgInstanceException("CImg<%s>::save_ascii() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.31285 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31286 + if (!file && !filename) 1.31287 + throw CImgArgumentException("CImg<%s>::save_ascii() : Instance image (%u,%u,%u,%u,%p), specified file is (null).", 1.31288 + pixel_type(),width,height,depth,dim,data); 1.31289 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); 1.31290 + cimg_std::fprintf(nfile,"%u %u %u %u\n",width,height,depth,dim); 1.31291 + const T* ptrs = data; 1.31292 + cimg_forYZV(*this,y,z,v) { 1.31293 + cimg_forX(*this,x) cimg_std::fprintf(nfile,"%g ",(double)*(ptrs++)); 1.31294 + cimg_std::fputc('\n',nfile); 1.31295 + } 1.31296 + if (!file) cimg::fclose(nfile); 1.31297 + return *this; 1.31298 + } 1.31299 + 1.31300 + //! Save the image as an ASCII file (ASCII Raw + simple header). 1.31301 + const CImg<T>& save_ascii(const char *const filename) const { 1.31302 + return _save_ascii(0,filename); 1.31303 + } 1.31304 + 1.31305 + //! Save the image as an ASCII file (ASCII Raw + simple header). 1.31306 + const CImg<T>& save_ascii(cimg_std::FILE *const file) const { 1.31307 + return _save_ascii(file,0); 1.31308 + } 1.31309 + 1.31310 + // Save the image as a C or CPP source file (internal). 1.31311 + const CImg<T>& _save_cpp(cimg_std::FILE *const file, const char *const filename) const { 1.31312 + if (!file && !filename) 1.31313 + throw CImgArgumentException("CImg<%s>::save_cpp() : Instance image (%u,%u,%u,%u,%p), specified file is (null).", 1.31314 + pixel_type(),width,height,depth,dim,data); 1.31315 + if (is_empty()) 1.31316 + throw CImgInstanceException("CImg<%s>::save_cpp() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.31317 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31318 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); 1.31319 + char varname[1024] = { 0 }; 1.31320 + if (filename) cimg_std::sscanf(cimg::basename(filename),"%1023[a-zA-Z0-9_]",varname); 1.31321 + if (varname[0]=='\0') cimg_std::sprintf(varname,"unnamed"); 1.31322 + cimg_std::fprintf(nfile, 1.31323 + "/* Define image '%s' of size %ux%ux%ux%u and type '%s' */\n" 1.31324 + "%s data_%s[] = { \n ", 1.31325 + varname,width,height,depth,dim,pixel_type(),pixel_type(),varname); 1.31326 + for (unsigned long off = 0, siz = size()-1; off<=siz; ++off) { 1.31327 + cimg_std::fprintf(nfile,cimg::type<T>::format(),cimg::type<T>::format((*this)[off])); 1.31328 + if (off==siz) cimg_std::fprintf(nfile," };\n"); 1.31329 + else if (!((off+1)%16)) cimg_std::fprintf(nfile,",\n "); 1.31330 + else cimg_std::fprintf(nfile,", "); 1.31331 + } 1.31332 + if (!file) cimg::fclose(nfile); 1.31333 + return *this; 1.31334 + } 1.31335 + 1.31336 + //! Save the image as a CPP source file. 1.31337 + const CImg<T>& save_cpp(const char *const filename) const { 1.31338 + return _save_cpp(0,filename); 1.31339 + } 1.31340 + 1.31341 + //! Save the image as a CPP source file. 1.31342 + const CImg<T>& save_cpp(cimg_std::FILE *const file) const { 1.31343 + return _save_cpp(file,0); 1.31344 + } 1.31345 + 1.31346 + // Save the image as a DLM file (internal). 1.31347 + const CImg<T>& _save_dlm(cimg_std::FILE *const file, const char *const filename) const { 1.31348 + if (is_empty()) 1.31349 + throw CImgInstanceException("CImg<%s>::save_dlm() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.31350 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31351 + if (!file && !filename) 1.31352 + throw CImgArgumentException("CImg<%s>::save_dlm() : Instance image (%u,%u,%u,%u,%p), specified file is (null).", 1.31353 + pixel_type(),width,height,depth,dim,data); 1.31354 + if (depth>1) 1.31355 + cimg::warn("CImg<%s>::save_dlm() : File '%s', instance image (%u,%u,%u,%u,%p) is volumetric. Pixel values along Z will be unrolled.", 1.31356 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31357 + if (dim>1) 1.31358 + cimg::warn("CImg<%s>::save_dlm() : File '%s', instance image (%u,%u,%u,%u,%p) is multispectral. " 1.31359 + "Pixel values along V will be unrolled.", 1.31360 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31361 + 1.31362 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); 1.31363 + const T* ptrs = data; 1.31364 + cimg_forYZV(*this,y,z,v) { 1.31365 + cimg_forX(*this,x) cimg_std::fprintf(nfile,"%g%s",(double)*(ptrs++),(x==dimx()-1)?"":","); 1.31366 + cimg_std::fputc('\n',nfile); 1.31367 + } 1.31368 + if (!file) cimg::fclose(nfile); 1.31369 + return *this; 1.31370 + } 1.31371 + 1.31372 + //! Save the image as a DLM file. 1.31373 + const CImg<T>& save_dlm(const char *const filename) const { 1.31374 + return _save_dlm(0,filename); 1.31375 + } 1.31376 + 1.31377 + //! Save the image as a DLM file. 1.31378 + const CImg<T>& save_dlm(cimg_std::FILE *const file) const { 1.31379 + return _save_dlm(file,0); 1.31380 + } 1.31381 + 1.31382 + // Save the image as a BMP file (internal). 1.31383 + const CImg<T>& _save_bmp(cimg_std::FILE *const file, const char *const filename) const { 1.31384 + if (is_empty()) 1.31385 + throw CImgInstanceException("CImg<%s>::save_bmp() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.31386 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31387 + if (!file && !filename) 1.31388 + throw CImgArgumentException("CImg<%s>::save_bmp() : Instance image (%u,%u,%u,%u,%p), specified file is (null).", 1.31389 + pixel_type(),width,height,depth,dim,data); 1.31390 + if (depth>1) 1.31391 + cimg::warn("CImg<%s>::save_bmp() : File '%s', instance image (%u,%u,%u,%u,%p) is volumetric. Only the first slice will be saved.", 1.31392 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31393 + if (dim>3) 1.31394 + cimg::warn("CImg<%s>::save_bmp() : File '%s', instance image (%u,%u,%u,%u,%p) is multispectral. Only the three first channels will be saved.", 1.31395 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31396 + 1.31397 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); 1.31398 + unsigned char header[54] = { 0 }, align_buf[4] = { 0 }; 1.31399 + const unsigned int 1.31400 + align = (4 - (3*width)%4)%4, 1.31401 + buf_size = (3*width+align)*dimy(), 1.31402 + file_size = 54 + buf_size; 1.31403 + header[0] = 'B'; header[1] = 'M'; 1.31404 + header[0x02] = file_size&0xFF; 1.31405 + header[0x03] = (file_size>>8)&0xFF; 1.31406 + header[0x04] = (file_size>>16)&0xFF; 1.31407 + header[0x05] = (file_size>>24)&0xFF; 1.31408 + header[0x0A] = 0x36; 1.31409 + header[0x0E] = 0x28; 1.31410 + header[0x12] = width&0xFF; 1.31411 + header[0x13] = (width>>8)&0xFF; 1.31412 + header[0x14] = (width>>16)&0xFF; 1.31413 + header[0x15] = (width>>24)&0xFF; 1.31414 + header[0x16] = height&0xFF; 1.31415 + header[0x17] = (height>>8)&0xFF; 1.31416 + header[0x18] = (height>>16)&0xFF; 1.31417 + header[0x19] = (height>>24)&0xFF; 1.31418 + header[0x1A] = 1; 1.31419 + header[0x1B] = 0; 1.31420 + header[0x1C] = 24; 1.31421 + header[0x1D] = 0; 1.31422 + header[0x22] = buf_size&0xFF; 1.31423 + header[0x23] = (buf_size>>8)&0xFF; 1.31424 + header[0x24] = (buf_size>>16)&0xFF; 1.31425 + header[0x25] = (buf_size>>24)&0xFF; 1.31426 + header[0x27] = 0x1; 1.31427 + header[0x2B] = 0x1; 1.31428 + cimg::fwrite(header,54,nfile); 1.31429 + 1.31430 + const T 1.31431 + *pR = ptr(0,height-1,0,0), 1.31432 + *pG = (dim>=2)?ptr(0,height-1,0,1):0, 1.31433 + *pB = (dim>=3)?ptr(0,height-1,0,2):0; 1.31434 + 1.31435 + switch (dim) { 1.31436 + case 1 : { 1.31437 + cimg_forY(*this,y) { cimg_forX(*this,x) { 1.31438 + const unsigned char val = (unsigned char)*(pR++); 1.31439 + cimg_std::fputc(val,nfile); cimg_std::fputc(val,nfile); cimg_std::fputc(val,nfile); 1.31440 + } 1.31441 + cimg::fwrite(align_buf,align,nfile); 1.31442 + pR-=2*width; 1.31443 + }} break; 1.31444 + case 2 : { 1.31445 + cimg_forY(*this,y) { cimg_forX(*this,x) { 1.31446 + cimg_std::fputc(0,nfile); 1.31447 + cimg_std::fputc((unsigned char)(*(pG++)),nfile); 1.31448 + cimg_std::fputc((unsigned char)(*(pR++)),nfile); 1.31449 + } 1.31450 + cimg::fwrite(align_buf,align,nfile); 1.31451 + pR-=2*width; pG-=2*width; 1.31452 + }} break; 1.31453 + default : { 1.31454 + cimg_forY(*this,y) { cimg_forX(*this,x) { 1.31455 + cimg_std::fputc((unsigned char)(*(pB++)),nfile); 1.31456 + cimg_std::fputc((unsigned char)(*(pG++)),nfile); 1.31457 + cimg_std::fputc((unsigned char)(*(pR++)),nfile); 1.31458 + } 1.31459 + cimg::fwrite(align_buf,align,nfile); 1.31460 + pR-=2*width; pG-=2*width; pB-=2*width; 1.31461 + } 1.31462 + } 1.31463 + } 1.31464 + if (!file) cimg::fclose(nfile); 1.31465 + return *this; 1.31466 + } 1.31467 + 1.31468 + //! Save the image as a BMP file. 1.31469 + const CImg<T>& save_bmp(const char *const filename) const { 1.31470 + return _save_bmp(0,filename); 1.31471 + } 1.31472 + 1.31473 + //! Save the image as a BMP file. 1.31474 + const CImg<T>& save_bmp(cimg_std::FILE *const file) const { 1.31475 + return _save_bmp(file,0); 1.31476 + } 1.31477 + 1.31478 + // Save a file in JPEG format (internal). 1.31479 + const CImg<T>& _save_jpeg(cimg_std::FILE *const file, const char *const filename, const unsigned int quality) const { 1.31480 + if (is_empty()) 1.31481 + throw CImgInstanceException("CImg<%s>::save_jpeg() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.31482 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31483 + if (!file && !filename) 1.31484 + throw CImgArgumentException("CImg<%s>::save_jpeg() : Instance image (%u,%u,%u,%u,%p), specified filename is (null).", 1.31485 + pixel_type(),width,height,depth,dim,data); 1.31486 + if (depth>1) 1.31487 + cimg::warn("CImg<%s>::save_jpeg() : File '%s, instance image (%u,%u,%u,%u,%p) is volumetric. Only the first slice will be saved.", 1.31488 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31489 +#ifndef cimg_use_jpeg 1.31490 + if (!file) return save_other(filename,quality); 1.31491 + else throw CImgIOException("CImg<%s>::save_jpeg() : Cannot save a JPEG image in a *FILE output. Use libjpeg instead.", 1.31492 + pixel_type()); 1.31493 +#else 1.31494 + // Fill pixel buffer 1.31495 + unsigned char *buf; 1.31496 + unsigned int dimbuf = 0; 1.31497 + J_COLOR_SPACE colortype = JCS_RGB; 1.31498 + switch (dim) { 1.31499 + case 1 : { // Greyscale images 1.31500 + unsigned char *buf2 = buf = new unsigned char[width*height*(dimbuf=1)]; 1.31501 + colortype = JCS_GRAYSCALE; 1.31502 + const T *ptr_g = data; 1.31503 + cimg_forXY(*this,x,y) *(buf2++) = (unsigned char)*(ptr_g++); 1.31504 + } break; 1.31505 + case 2 : { // RG images 1.31506 + unsigned char *buf2 = buf = new unsigned char[width*height*(dimbuf=3)]; 1.31507 + const T *ptr_r = ptr(0,0,0,0), *ptr_g = ptr(0,0,0,1); 1.31508 + colortype = JCS_RGB; 1.31509 + cimg_forXY(*this,x,y) { 1.31510 + *(buf2++) = (unsigned char)*(ptr_r++); 1.31511 + *(buf2++) = (unsigned char)*(ptr_g++); 1.31512 + *(buf2++) = 0; 1.31513 + } 1.31514 + } break; 1.31515 + case 3 : { // RGB images 1.31516 + unsigned char *buf2 = buf = new unsigned char[width*height*(dimbuf=3)]; 1.31517 + const T *ptr_r = ptr(0,0,0,0), *ptr_g = ptr(0,0,0,1), *ptr_b = ptr(0,0,0,2); 1.31518 + colortype = JCS_RGB; 1.31519 + cimg_forXY(*this,x,y) { 1.31520 + *(buf2++) = (unsigned char)*(ptr_r++); 1.31521 + *(buf2++) = (unsigned char)*(ptr_g++); 1.31522 + *(buf2++) = (unsigned char)*(ptr_b++); 1.31523 + } 1.31524 + } break; 1.31525 + default : { // CMYK images 1.31526 + unsigned char *buf2 = buf = new unsigned char[width*height*(dimbuf=4)]; 1.31527 + const T *ptr_r = ptr(0,0,0,0), *ptr_g = ptr(0,0,0,1), *ptr_b = ptr(0,0,0,2), *ptr_a = ptr(0,0,0,3); 1.31528 + colortype = JCS_CMYK; 1.31529 + cimg_forXY(*this,x,y) { 1.31530 + *(buf2++) = (unsigned char)*(ptr_r++); 1.31531 + *(buf2++) = (unsigned char)*(ptr_g++); 1.31532 + *(buf2++) = (unsigned char)*(ptr_b++); 1.31533 + *(buf2++) = (unsigned char)*(ptr_a++); 1.31534 + } 1.31535 + } 1.31536 + } 1.31537 + 1.31538 + // Call libjpeg functions 1.31539 + struct jpeg_compress_struct cinfo; 1.31540 + struct jpeg_error_mgr jerr; 1.31541 + cinfo.err = jpeg_std_error(&jerr); 1.31542 + jpeg_create_compress(&cinfo); 1.31543 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); 1.31544 + jpeg_stdio_dest(&cinfo,nfile); 1.31545 + cinfo.image_width = width; 1.31546 + cinfo.image_height = height; 1.31547 + cinfo.input_components = dimbuf; 1.31548 + cinfo.in_color_space = colortype; 1.31549 + jpeg_set_defaults(&cinfo); 1.31550 + jpeg_set_quality(&cinfo,quality<100?quality:100,TRUE); 1.31551 + jpeg_start_compress(&cinfo,TRUE); 1.31552 + 1.31553 + const unsigned int row_stride = width*dimbuf; 1.31554 + JSAMPROW row_pointer[1]; 1.31555 + while (cinfo.next_scanline < cinfo.image_height) { 1.31556 + row_pointer[0] = &buf[cinfo.next_scanline*row_stride]; 1.31557 + jpeg_write_scanlines(&cinfo,row_pointer,1); 1.31558 + } 1.31559 + jpeg_finish_compress(&cinfo); 1.31560 + 1.31561 + delete[] buf; 1.31562 + if (!file) cimg::fclose(nfile); 1.31563 + jpeg_destroy_compress(&cinfo); 1.31564 + return *this; 1.31565 +#endif 1.31566 + } 1.31567 + 1.31568 + //! Save a file in JPEG format. 1.31569 + const CImg<T>& save_jpeg(const char *const filename, const unsigned int quality=100) const { 1.31570 + return _save_jpeg(0,filename,quality); 1.31571 + } 1.31572 + 1.31573 + //! Save a file in JPEG format. 1.31574 + const CImg<T>& save_jpeg(cimg_std::FILE *const file, const unsigned int quality=100) const { 1.31575 + return _save_jpeg(file,0,quality); 1.31576 + } 1.31577 + 1.31578 + //! Save the image using built-in ImageMagick++ library. 1.31579 + const CImg<T>& save_magick(const char *const filename) const { 1.31580 + if (is_empty()) 1.31581 + throw CImgInstanceException("CImg<%s>::save_magick() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.31582 + pixel_type(),filename?filename:"(null)",width,height,depth,dim,data); 1.31583 + if (!filename) 1.31584 + throw CImgArgumentException("CImg<%s>::save_magick() : Instance image (%u,%u,%u,%u,%p), specified file is (null).", 1.31585 + pixel_type(),width,height,depth,dim,data); 1.31586 +#ifdef cimg_use_magick 1.31587 + Magick::Image image(Magick::Geometry(width,height),"black"); 1.31588 + image.type(Magick::TrueColorType); 1.31589 + const T 1.31590 + *rdata = ptr(0,0,0,0), 1.31591 + *gdata = dim>1?ptr(0,0,0,1):0, 1.31592 + *bdata = dim>2?ptr(0,0,0,2):0; 1.31593 + Magick::PixelPacket *pixels = image.getPixels(0,0,width,height); 1.31594 + switch (dim) { 1.31595 + case 1 : // Scalar images 1.31596 + for (unsigned int off = width*height; off; --off) { 1.31597 + pixels->red = pixels->green = pixels->blue = Magick::Color::scaleDoubleToQuantum(*(rdata++)/255.0); 1.31598 + ++pixels; 1.31599 + } 1.31600 + break; 1.31601 + case 2 : // RG images 1.31602 + for (unsigned int off = width*height; off; --off) { 1.31603 + pixels->red = Magick::Color::scaleDoubleToQuantum(*(rdata++)/255.0); 1.31604 + pixels->green = Magick::Color::scaleDoubleToQuantum(*(gdata++)/255.0); 1.31605 + pixels->blue = 0; 1.31606 + ++pixels; 1.31607 + } 1.31608 + break; 1.31609 + default : // RGB images 1.31610 + for (unsigned int off = width*height; off; --off) { 1.31611 + pixels->red = Magick::Color::scaleDoubleToQuantum(*(rdata++)/255.0); 1.31612 + pixels->green = Magick::Color::scaleDoubleToQuantum(*(gdata++)/255.0); 1.31613 + pixels->blue = Magick::Color::scaleDoubleToQuantum(*(bdata++)/255.0); 1.31614 + ++pixels; 1.31615 + } 1.31616 + } 1.31617 + image.syncPixels(); 1.31618 + image.write(filename); 1.31619 +#else 1.31620 + throw CImgIOException("CImg<%s>::save_magick() : File '%s', Magick++ library has not been linked.", 1.31621 + pixel_type(),filename); 1.31622 +#endif 1.31623 + return *this; 1.31624 + } 1.31625 + 1.31626 + // Save an image to a PNG file (internal). 1.31627 + // Most of this function has been written by Eric Fausett 1.31628 + const CImg<T>& _save_png(cimg_std::FILE *const file, const char *const filename) const { 1.31629 + if (is_empty()) 1.31630 + throw CImgInstanceException("CImg<%s>::save_png() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.31631 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31632 + if (!filename) 1.31633 + throw CImgArgumentException("CImg<%s>::save_png() : Instance image (%u,%u,%u,%u,%p), specified filename is (null).", 1.31634 + pixel_type(),width,height,depth,dim,data); 1.31635 + if (depth>1) 1.31636 + cimg::warn("CImg<%s>::save_png() : File '%s', instance image (%u,%u,%u,%u,%p) is volumetric. Only the first slice will be saved.", 1.31637 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31638 +#ifndef cimg_use_png 1.31639 + if (!file) return save_other(filename); 1.31640 + else throw CImgIOException("CImg<%s>::save_png() : Cannot save a PNG image in a *FILE output. You must use 'libpng' to do this instead.", 1.31641 + pixel_type()); 1.31642 +#else 1.31643 + const char *volatile nfilename = filename; // two 'volatile' here to remove a g++ warning due to 'setjmp'. 1.31644 + cimg_std::FILE *volatile nfile = file?file:cimg::fopen(nfilename,"wb"); 1.31645 + 1.31646 + // Setup PNG structures for write 1.31647 + png_voidp user_error_ptr = 0; 1.31648 + png_error_ptr user_error_fn = 0, user_warning_fn = 0; 1.31649 + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,user_error_ptr, user_error_fn, user_warning_fn); 1.31650 + if(!png_ptr){ 1.31651 + if (!file) cimg::fclose(nfile); 1.31652 + throw CImgIOException("CImg<%s>::save_png() : File '%s', error when initializing 'png_ptr' data structure.", 1.31653 + pixel_type(),nfilename?nfilename:"(FILE*)"); 1.31654 + } 1.31655 + png_infop info_ptr = png_create_info_struct(png_ptr); 1.31656 + if (!info_ptr) { 1.31657 + png_destroy_write_struct(&png_ptr,(png_infopp)0); 1.31658 + if (!file) cimg::fclose(nfile); 1.31659 + throw CImgIOException("CImg<%s>::save_png() : File '%s', error when initializing 'info_ptr' data structure.", 1.31660 + pixel_type(),nfilename?nfilename:"(FILE*)"); 1.31661 + } 1.31662 + if (setjmp(png_jmpbuf(png_ptr))) { 1.31663 + png_destroy_write_struct(&png_ptr, &info_ptr); 1.31664 + if (!file) cimg::fclose(nfile); 1.31665 + throw CImgIOException("CImg<%s>::save_png() : File '%s', unknown fatal error.", 1.31666 + pixel_type(),nfilename?nfilename:"(FILE*)"); 1.31667 + } 1.31668 + png_init_io(png_ptr, nfile); 1.31669 + png_uint_32 width = dimx(), height = dimy(); 1.31670 + float vmin, vmax = (float)maxmin(vmin); 1.31671 + const int bit_depth = (vmin<0 || vmax>=256)?16:8; 1.31672 + int color_type; 1.31673 + switch (dimv()) { 1.31674 + case 1 : color_type = PNG_COLOR_TYPE_GRAY; break; 1.31675 + case 2 : color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break; 1.31676 + case 3 : color_type = PNG_COLOR_TYPE_RGB; break; 1.31677 + default : color_type = PNG_COLOR_TYPE_RGB_ALPHA; 1.31678 + } 1.31679 + const int interlace_type = PNG_INTERLACE_NONE; 1.31680 + const int compression_type = PNG_COMPRESSION_TYPE_DEFAULT; 1.31681 + const int filter_method = PNG_FILTER_TYPE_DEFAULT; 1.31682 + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, interlace_type,compression_type, filter_method); 1.31683 + png_write_info(png_ptr, info_ptr); 1.31684 + const int byte_depth = bit_depth>>3; 1.31685 + const int numChan = dimv()>4?4:dimv(); 1.31686 + const int pixel_bit_depth_flag = numChan * (bit_depth-1); 1.31687 + 1.31688 + // Allocate Memory for Image Save and Fill pixel data 1.31689 + png_bytep *imgData = new png_byte*[height]; 1.31690 + for (unsigned int row = 0; row<height; ++row) imgData[row] = new png_byte[byte_depth*numChan*width]; 1.31691 + const T *pC0 = ptr(0,0,0,0); 1.31692 + switch (pixel_bit_depth_flag) { 1.31693 + case 7 : { // Gray 8-bit 1.31694 + cimg_forY(*this,y) { 1.31695 + unsigned char *ptrd = imgData[y]; 1.31696 + cimg_forX(*this,x) *(ptrd++) = (unsigned char)*(pC0++); 1.31697 + } 1.31698 + } break; 1.31699 + case 14 : { // Gray w/ Alpha 8-bit 1.31700 + const T *pC1 = ptr(0,0,0,1); 1.31701 + cimg_forY(*this,y) { 1.31702 + unsigned char *ptrd = imgData[y]; 1.31703 + cimg_forX(*this,x) { 1.31704 + *(ptrd++) = (unsigned char)*(pC0++); 1.31705 + *(ptrd++) = (unsigned char)*(pC1++); 1.31706 + } 1.31707 + } 1.31708 + } break; 1.31709 + case 21 : { // RGB 8-bit 1.31710 + const T *pC1 = ptr(0,0,0,1), *pC2 = ptr(0,0,0,2); 1.31711 + cimg_forY(*this,y) { 1.31712 + unsigned char *ptrd = imgData[y]; 1.31713 + cimg_forX(*this,x) { 1.31714 + *(ptrd++) = (unsigned char)*(pC0++); 1.31715 + *(ptrd++) = (unsigned char)*(pC1++); 1.31716 + *(ptrd++) = (unsigned char)*(pC2++); 1.31717 + } 1.31718 + } 1.31719 + } break; 1.31720 + case 28 : { // RGB x/ Alpha 8-bit 1.31721 + const T *pC1 = ptr(0,0,0,1), *pC2 = ptr(0,0,0,2), *pC3 = ptr(0,0,0,3); 1.31722 + cimg_forY(*this,y){ 1.31723 + unsigned char *ptrd = imgData[y]; 1.31724 + cimg_forX(*this,x){ 1.31725 + *(ptrd++) = (unsigned char)*(pC0++); 1.31726 + *(ptrd++) = (unsigned char)*(pC1++); 1.31727 + *(ptrd++) = (unsigned char)*(pC2++); 1.31728 + *(ptrd++) = (unsigned char)*(pC3++); 1.31729 + } 1.31730 + } 1.31731 + } break; 1.31732 + case 15 : { // Gray 16-bit 1.31733 + cimg_forY(*this,y){ 1.31734 + unsigned short *ptrd = (unsigned short*)(imgData[y]); 1.31735 + cimg_forX(*this,x) *(ptrd++) = (unsigned short)*(pC0++); 1.31736 + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],width); 1.31737 + } 1.31738 + } break; 1.31739 + case 30 : { // Gray w/ Alpha 16-bit 1.31740 + const T *pC1 = ptr(0,0,0,1); 1.31741 + cimg_forY(*this,y){ 1.31742 + unsigned short *ptrd = (unsigned short*)(imgData[y]); 1.31743 + cimg_forX(*this,x) { 1.31744 + *(ptrd++) = (unsigned short)*(pC0++); 1.31745 + *(ptrd++) = (unsigned short)*(pC1++); 1.31746 + } 1.31747 + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],2*width); 1.31748 + } 1.31749 + } break; 1.31750 + case 45 : { // RGB 16-bit 1.31751 + const T *pC1 = ptr(0,0,0,1), *pC2 = ptr(0,0,0,2); 1.31752 + cimg_forY(*this,y) { 1.31753 + unsigned short *ptrd = (unsigned short*)(imgData[y]); 1.31754 + cimg_forX(*this,x) { 1.31755 + *(ptrd++) = (unsigned short)*(pC0++); 1.31756 + *(ptrd++) = (unsigned short)*(pC1++); 1.31757 + *(ptrd++) = (unsigned short)*(pC2++); 1.31758 + } 1.31759 + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],3*width); 1.31760 + } 1.31761 + } break; 1.31762 + case 60 : { // RGB w/ Alpha 16-bit 1.31763 + const T *pC1 = ptr(0,0,0,1), *pC2 = ptr(0,0,0,2), *pC3 = ptr(0,0,0,3); 1.31764 + cimg_forY(*this,y) { 1.31765 + unsigned short *ptrd = (unsigned short*)(imgData[y]); 1.31766 + cimg_forX(*this,x) { 1.31767 + *(ptrd++) = (unsigned short)*(pC0++); 1.31768 + *(ptrd++) = (unsigned short)*(pC1++); 1.31769 + *(ptrd++) = (unsigned short)*(pC2++); 1.31770 + *(ptrd++) = (unsigned short)*(pC3++); 1.31771 + } 1.31772 + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],4*width); 1.31773 + } 1.31774 + } break; 1.31775 + default : 1.31776 + if (!file) cimg::fclose(nfile); 1.31777 + throw CImgIOException("CImg<%s>::save_png() : File '%s', unknown fatal error.", 1.31778 + pixel_type(),nfilename?nfilename:"(FILE*)"); 1.31779 + } 1.31780 + png_write_image(png_ptr, imgData); 1.31781 + png_write_end(png_ptr, info_ptr); 1.31782 + png_destroy_write_struct(&png_ptr, &info_ptr); 1.31783 + 1.31784 + // Deallocate Image Write Memory 1.31785 + cimg_forY(*this,n) delete[] imgData[n]; 1.31786 + delete[] imgData; 1.31787 + if (!file) cimg::fclose(nfile); 1.31788 + return *this; 1.31789 +#endif 1.31790 + } 1.31791 + 1.31792 + //! Save a file in PNG format 1.31793 + const CImg<T>& save_png(const char *const filename) const { 1.31794 + return _save_png(0,filename); 1.31795 + } 1.31796 + 1.31797 + //! Save a file in PNG format 1.31798 + const CImg<T>& save_png(cimg_std::FILE *const file) const { 1.31799 + return _save_png(file,0); 1.31800 + } 1.31801 + 1.31802 + // Save the image as a PNM file (internal function). 1.31803 + const CImg<T>& _save_pnm(cimg_std::FILE *const file, const char *const filename) const { 1.31804 + if (!file && !filename) 1.31805 + throw CImgArgumentException("CImg<%s>::save_pnm() : Instance image (%u,%u,%u,%u,%p), specified file is (null).", 1.31806 + pixel_type(),width,height,depth,dim,data); 1.31807 + if (is_empty()) 1.31808 + throw CImgInstanceException("CImg<%s>::save_pnm() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.31809 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31810 + double stmin, stmax = (double)maxmin(stmin); 1.31811 + if (depth>1) 1.31812 + cimg::warn("CImg<%s>::save_pnm() : File '%s', instance image (%u,%u,%u,%u,%p) is volumetric. Only the first slice will be saved.", 1.31813 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31814 + if (dim>3) 1.31815 + cimg::warn("CImg<%s>::save_pnm() : File '%s', instance image (%u,%u,%u,%u,%p) is multispectral. Only the three first channels will be saved.", 1.31816 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31817 + if (stmin<0 || stmax>65535) 1.31818 + cimg::warn("CImg<%s>::save_pnm() : File '%s', instance image (%u,%u,%u,%u,%p) has pixel values in [%g,%g]. Probable type overflow.", 1.31819 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data,stmin,stmax); 1.31820 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); 1.31821 + const T 1.31822 + *ptrR = ptr(0,0,0,0), 1.31823 + *ptrG = (dim>=2)?ptr(0,0,0,1):0, 1.31824 + *ptrB = (dim>=3)?ptr(0,0,0,2):0; 1.31825 + const unsigned int buf_size = width*height*(dim==1?1:3); 1.31826 + 1.31827 + cimg_std::fprintf(nfile,"P%c\n# CREATOR: CImg Library (original size = %ux%ux%ux%u)\n%u %u\n%u\n", 1.31828 + (dim==1?'5':'6'),width,height,depth,dim,width,height,stmax<256?255:(stmax<4096?4095:65535)); 1.31829 + 1.31830 + switch (dim) { 1.31831 + case 1 : { // Scalar image 1.31832 + if (stmax<256) { // Binary PGM 8 bits 1.31833 + unsigned char *ptrd = new unsigned char[buf_size], *xptrd = ptrd; 1.31834 + cimg_forXY(*this,x,y) *(xptrd++) = (unsigned char)*(ptrR++); 1.31835 + cimg::fwrite(ptrd,buf_size,nfile); 1.31836 + delete[] ptrd; 1.31837 + } else { // Binary PGM 16 bits 1.31838 + unsigned short *ptrd = new unsigned short[buf_size], *xptrd = ptrd; 1.31839 + cimg_forXY(*this,x,y) *(xptrd++) = (unsigned short)*(ptrR++); 1.31840 + if (!cimg::endianness()) cimg::invert_endianness(ptrd,buf_size); 1.31841 + cimg::fwrite(ptrd,buf_size,nfile); 1.31842 + delete[] ptrd; 1.31843 + } 1.31844 + } break; 1.31845 + case 2 : { // RG image 1.31846 + if (stmax<256) { // Binary PPM 8 bits 1.31847 + unsigned char *ptrd = new unsigned char[buf_size], *xptrd = ptrd; 1.31848 + cimg_forXY(*this,x,y) { 1.31849 + *(xptrd++) = (unsigned char)*(ptrR++); 1.31850 + *(xptrd++) = (unsigned char)*(ptrG++); 1.31851 + *(xptrd++) = 0; 1.31852 + } 1.31853 + cimg::fwrite(ptrd,buf_size,nfile); 1.31854 + delete[] ptrd; 1.31855 + } else { // Binary PPM 16 bits 1.31856 + unsigned short *ptrd = new unsigned short[buf_size], *xptrd = ptrd; 1.31857 + cimg_forXY(*this,x,y) { 1.31858 + *(xptrd++) = (unsigned short)*(ptrR++); 1.31859 + *(xptrd++) = (unsigned short)*(ptrG++); 1.31860 + *(xptrd++) = 0; 1.31861 + } 1.31862 + if (!cimg::endianness()) cimg::invert_endianness(ptrd,buf_size); 1.31863 + cimg::fwrite(ptrd,buf_size,nfile); 1.31864 + delete[] ptrd; 1.31865 + } 1.31866 + } break; 1.31867 + default : { // RGB image 1.31868 + if (stmax<256) { // Binary PPM 8 bits 1.31869 + unsigned char *ptrd = new unsigned char[buf_size], *xptrd = ptrd; 1.31870 + cimg_forXY(*this,x,y) { 1.31871 + *(xptrd++) = (unsigned char)*(ptrR++); 1.31872 + *(xptrd++) = (unsigned char)*(ptrG++); 1.31873 + *(xptrd++) = (unsigned char)*(ptrB++); 1.31874 + } 1.31875 + cimg::fwrite(ptrd,buf_size,nfile); 1.31876 + delete[] ptrd; 1.31877 + } else { // Binary PPM 16 bits 1.31878 + unsigned short *ptrd = new unsigned short[buf_size], *xptrd = ptrd; 1.31879 + cimg_forXY(*this,x,y) { 1.31880 + *(xptrd++) = (unsigned short)*(ptrR++); 1.31881 + *(xptrd++) = (unsigned short)*(ptrG++); 1.31882 + *(xptrd++) = (unsigned short)*(ptrB++); 1.31883 + } 1.31884 + if (!cimg::endianness()) cimg::invert_endianness(ptrd,buf_size); 1.31885 + cimg::fwrite(ptrd,buf_size,nfile); 1.31886 + delete[] ptrd; 1.31887 + } 1.31888 + } 1.31889 + } 1.31890 + if (!file) cimg::fclose(nfile); 1.31891 + return *this; 1.31892 + } 1.31893 + 1.31894 + //! Save the image as a PNM file. 1.31895 + const CImg<T>& save_pnm(const char *const filename) const { 1.31896 + return _save_pnm(0,filename); 1.31897 + } 1.31898 + 1.31899 + //! Save the image as a PNM file. 1.31900 + const CImg<T>& save_pnm(cimg_std::FILE *const file) const { 1.31901 + return _save_pnm(file,0); 1.31902 + } 1.31903 + 1.31904 + // Save the image as a RGB file (internal). 1.31905 + const CImg<T>& _save_rgb(cimg_std::FILE *const file, const char *const filename) const { 1.31906 + if (is_empty()) 1.31907 + throw CImgInstanceException("CImg<%s>::save_rgb() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.31908 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31909 + if (!file && !filename) 1.31910 + throw CImgArgumentException("CImg<%s>::save_rgb() : Instance image (%u,%u,%u,%u,%p), specified file is (null).", 1.31911 + pixel_type(),width,height,depth,dim,data); 1.31912 + if (dim!=3) 1.31913 + cimg::warn("CImg<%s>::save_rgb() : File '%s', instance image (%u,%u,%u,%u,%p) has not exactly 3 channels.", 1.31914 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31915 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); 1.31916 + const unsigned int wh = width*height; 1.31917 + unsigned char *buffer = new unsigned char[3*wh], *nbuffer=buffer; 1.31918 + const T 1.31919 + *ptr1 = ptr(0,0,0,0), 1.31920 + *ptr2 = dim>1?ptr(0,0,0,1):0, 1.31921 + *ptr3 = dim>2?ptr(0,0,0,2):0; 1.31922 + switch (dim) { 1.31923 + case 1 : { // Scalar image 1.31924 + for (unsigned int k=0; k<wh; ++k) { 1.31925 + const unsigned char val = (unsigned char)*(ptr1++); 1.31926 + *(nbuffer++) = val; 1.31927 + *(nbuffer++) = val; 1.31928 + *(nbuffer++) = val; 1.31929 + }} break; 1.31930 + case 2 : { // RG image 1.31931 + for (unsigned int k=0; k<wh; ++k) { 1.31932 + *(nbuffer++) = (unsigned char)(*(ptr1++)); 1.31933 + *(nbuffer++) = (unsigned char)(*(ptr2++)); 1.31934 + *(nbuffer++) = 0; 1.31935 + }} break; 1.31936 + default : { // RGB image 1.31937 + for (unsigned int k=0; k<wh; ++k) { 1.31938 + *(nbuffer++) = (unsigned char)(*(ptr1++)); 1.31939 + *(nbuffer++) = (unsigned char)(*(ptr2++)); 1.31940 + *(nbuffer++) = (unsigned char)(*(ptr3++)); 1.31941 + } 1.31942 + } 1.31943 + } 1.31944 + cimg::fwrite(buffer,3*wh,nfile); 1.31945 + if (!file) cimg::fclose(nfile); 1.31946 + delete[] buffer; 1.31947 + return *this; 1.31948 + } 1.31949 + 1.31950 + //! Save the image as a RGB file. 1.31951 + const CImg<T>& save_rgb(const char *const filename) const { 1.31952 + return _save_rgb(0,filename); 1.31953 + } 1.31954 + 1.31955 + //! Save the image as a RGB file. 1.31956 + const CImg<T>& save_rgb(cimg_std::FILE *const file) const { 1.31957 + return _save_rgb(file,0); 1.31958 + } 1.31959 + 1.31960 + // Save the image as a RGBA file (internal). 1.31961 + const CImg<T>& _save_rgba(cimg_std::FILE *const file, const char *const filename) const { 1.31962 + if (is_empty()) 1.31963 + throw CImgInstanceException("CImg<%s>::save_rgba() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.31964 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31965 + if (!file && !filename) 1.31966 + throw CImgArgumentException("CImg<%s>::save_rgba() : Instance image (%u,%u,%u,%u,%p), specified file is (null).", 1.31967 + pixel_type(),width,height,depth,dim,data); 1.31968 + if (dim!=4) 1.31969 + cimg::warn("CImg<%s>::save_rgba() : File '%s, instance image (%u,%u,%u,%u,%p) has not exactly 4 channels.", 1.31970 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.31971 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); 1.31972 + const unsigned int wh = width*height; 1.31973 + unsigned char *buffer = new unsigned char[4*wh], *nbuffer=buffer; 1.31974 + const T 1.31975 + *ptr1 = ptr(0,0,0,0), 1.31976 + *ptr2 = dim>1?ptr(0,0,0,1):0, 1.31977 + *ptr3 = dim>2?ptr(0,0,0,2):0, 1.31978 + *ptr4 = dim>3?ptr(0,0,0,3):0; 1.31979 + switch (dim) { 1.31980 + case 1 : { // Scalar images 1.31981 + for (unsigned int k=0; k<wh; ++k) { 1.31982 + const unsigned char val = (unsigned char)*(ptr1++); 1.31983 + *(nbuffer++) = val; 1.31984 + *(nbuffer++) = val; 1.31985 + *(nbuffer++) = val; 1.31986 + *(nbuffer++) = 255; 1.31987 + }} break; 1.31988 + case 2 : { // RG images 1.31989 + for (unsigned int k=0; k<wh; ++k) { 1.31990 + *(nbuffer++) = (unsigned char)(*(ptr1++)); 1.31991 + *(nbuffer++) = (unsigned char)(*(ptr2++)); 1.31992 + *(nbuffer++) = 0; 1.31993 + *(nbuffer++) = 255; 1.31994 + }} break; 1.31995 + case 3 : { // RGB images 1.31996 + for (unsigned int k=0; k<wh; ++k) { 1.31997 + *(nbuffer++) = (unsigned char)(*(ptr1++)); 1.31998 + *(nbuffer++) = (unsigned char)(*(ptr2++)); 1.31999 + *(nbuffer++) = (unsigned char)(*(ptr3++)); 1.32000 + *(nbuffer++) = 255; 1.32001 + }} break; 1.32002 + default : { // RGBA images 1.32003 + for (unsigned int k=0; k<wh; ++k) { 1.32004 + *(nbuffer++) = (unsigned char)(*(ptr1++)); 1.32005 + *(nbuffer++) = (unsigned char)(*(ptr2++)); 1.32006 + *(nbuffer++) = (unsigned char)(*(ptr3++)); 1.32007 + *(nbuffer++) = (unsigned char)(*(ptr4++)); 1.32008 + } 1.32009 + } 1.32010 + } 1.32011 + cimg::fwrite(buffer,4*wh,nfile); 1.32012 + if (!file) cimg::fclose(nfile); 1.32013 + delete[] buffer; 1.32014 + return *this; 1.32015 + } 1.32016 + 1.32017 + //! Save the image as a RGBA file. 1.32018 + const CImg<T>& save_rgba(const char *const filename) const { 1.32019 + return _save_rgba(0,filename); 1.32020 + } 1.32021 + 1.32022 + //! Save the image as a RGBA file. 1.32023 + const CImg<T>& save_rgba(cimg_std::FILE *const file) const { 1.32024 + return _save_rgba(file,0); 1.32025 + } 1.32026 + 1.32027 + // Save a plane into a tiff file 1.32028 +#ifdef cimg_use_tiff 1.32029 + const CImg<T>& _save_tiff(TIFF *tif, const unsigned int directory) const { 1.32030 + if (is_empty() || !tif) return *this; 1.32031 + const char *const filename = TIFFFileName(tif); 1.32032 + uint32 rowsperstrip = (uint32)-1; 1.32033 + uint16 spp = dim, bpp = sizeof(T)*8, photometric, compression = COMPRESSION_NONE; 1.32034 + if (spp==3 || spp==4) photometric = PHOTOMETRIC_RGB; 1.32035 + else photometric = PHOTOMETRIC_MINISBLACK; 1.32036 + TIFFSetDirectory(tif,directory); 1.32037 + TIFFSetField(tif,TIFFTAG_IMAGEWIDTH,width); 1.32038 + TIFFSetField(tif,TIFFTAG_IMAGELENGTH,height); 1.32039 + TIFFSetField(tif,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT); 1.32040 + TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,spp); 1.32041 + if (cimg::type<T>::is_float()) TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,3); 1.32042 + else if (cimg::type<T>::min()==0) TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,1); 1.32043 + else TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,2); 1.32044 + TIFFSetField(tif,TIFFTAG_BITSPERSAMPLE,bpp); 1.32045 + TIFFSetField(tif,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG); 1.32046 + TIFFSetField(tif,TIFFTAG_PHOTOMETRIC,photometric); 1.32047 + TIFFSetField(tif,TIFFTAG_COMPRESSION,compression); 1.32048 + rowsperstrip = TIFFDefaultStripSize(tif,rowsperstrip); 1.32049 + TIFFSetField(tif,TIFFTAG_ROWSPERSTRIP,rowsperstrip); 1.32050 + TIFFSetField(tif,TIFFTAG_FILLORDER,FILLORDER_MSB2LSB); 1.32051 + TIFFSetField(tif,TIFFTAG_SOFTWARE,"CImg"); 1.32052 + T *buf = (T*)_TIFFmalloc(TIFFStripSize(tif)); 1.32053 + if (buf){ 1.32054 + for (unsigned int row = 0; row<height; row+=rowsperstrip) { 1.32055 + uint32 nrow = (row+rowsperstrip>height?height-row:rowsperstrip); 1.32056 + tstrip_t strip = TIFFComputeStrip(tif,row,0); 1.32057 + tsize_t i = 0; 1.32058 + for (unsigned int rr = 0; rr<nrow; ++rr) 1.32059 + for (unsigned int cc = 0; cc<width; ++cc) 1.32060 + for (unsigned int vv = 0; vv<spp; ++vv) 1.32061 + buf[i++] = (*this)(cc,row+rr,vv); 1.32062 + if (TIFFWriteEncodedStrip(tif,strip,buf,i*sizeof(T))<0) 1.32063 + throw CImgException("CImg<%s>::save_tiff() : File '%s', an error has occured while writing a strip.", 1.32064 + pixel_type(),filename?filename:"(FILE*)"); 1.32065 + } 1.32066 + _TIFFfree(buf); 1.32067 + } 1.32068 + TIFFWriteDirectory(tif); 1.32069 + return (*this); 1.32070 + } 1.32071 +#endif 1.32072 + 1.32073 + //! Save a file in TIFF format. 1.32074 + const CImg<T>& save_tiff(const char *const filename) const { 1.32075 + if (is_empty()) 1.32076 + throw CImgInstanceException("CImg<%s>::save_tiff() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.32077 + pixel_type(),filename?filename:"(null)",width,height,depth,dim,data); 1.32078 + if (!filename) 1.32079 + throw CImgArgumentException("CImg<%s>::save_tiff() : Specified filename is (null) for instance image (%u,%u,%u,%u,%p).", 1.32080 + pixel_type(),width,height,depth,dim,data); 1.32081 +#ifdef cimg_use_tiff 1.32082 + TIFF *tif = TIFFOpen(filename,"w"); 1.32083 + if (tif) { 1.32084 + cimg_forZ(*this,z) get_slice(z)._save_tiff(tif,z); 1.32085 + TIFFClose(tif); 1.32086 + } else throw CImgException("CImg<%s>::save_tiff() : File '%s', error while opening file stream for writing.", 1.32087 + pixel_type(),filename); 1.32088 +#else 1.32089 + return save_other(filename); 1.32090 +#endif 1.32091 + return *this; 1.32092 + } 1.32093 + 1.32094 + //! Save the image as an ANALYZE7.5 or NIFTI file. 1.32095 + const CImg<T>& save_analyze(const char *const filename, const float *const voxsize=0) const { 1.32096 + if (is_empty()) 1.32097 + throw CImgInstanceException("CImg<%s>::save_analyze() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.32098 + pixel_type(),filename?filename:"(null)",width,height,depth,dim,data); 1.32099 + if (!filename) 1.32100 + throw CImgArgumentException("CImg<%s>::save_analyze() : Instance image (%u,%u,%u,%u,%p), specified filename is (null).", 1.32101 + pixel_type(),width,height,depth,dim,data); 1.32102 + cimg_std::FILE *file; 1.32103 + char header[348], hname[1024], iname[1024]; 1.32104 + const char *ext = cimg::split_filename(filename); 1.32105 + short datatype=-1; 1.32106 + cimg_std::memset(header,0,348); 1.32107 + if (!ext[0]) { cimg_std::sprintf(hname,"%s.hdr",filename); cimg_std::sprintf(iname,"%s.img",filename); } 1.32108 + if (!cimg::strncasecmp(ext,"hdr",3)) { 1.32109 + cimg_std::strcpy(hname,filename); cimg_std::strcpy(iname,filename); cimg_std::sprintf(iname+cimg::strlen(iname)-3,"img"); 1.32110 + } 1.32111 + if (!cimg::strncasecmp(ext,"img",3)) { 1.32112 + cimg_std::strcpy(hname,filename); cimg_std::strcpy(iname,filename); cimg_std::sprintf(hname+cimg::strlen(iname)-3,"hdr"); 1.32113 + } 1.32114 + if (!cimg::strncasecmp(ext,"nii",3)) { 1.32115 + cimg_std::strcpy(hname,filename); iname[0] = 0; 1.32116 + } 1.32117 + ((int*)(header))[0] = 348; 1.32118 + cimg_std::sprintf(header+4,"CImg"); 1.32119 + cimg_std::sprintf(header+14," "); 1.32120 + ((short*)(header+36))[0] = 4096; 1.32121 + ((char*)(header+38))[0] = 114; 1.32122 + ((short*)(header+40))[0] = 4; 1.32123 + ((short*)(header+40))[1] = width; 1.32124 + ((short*)(header+40))[2] = height; 1.32125 + ((short*)(header+40))[3] = depth; 1.32126 + ((short*)(header+40))[4] = dim; 1.32127 + if (!cimg::strcasecmp(pixel_type(),"bool")) datatype = 2; 1.32128 + if (!cimg::strcasecmp(pixel_type(),"unsigned char")) datatype = 2; 1.32129 + if (!cimg::strcasecmp(pixel_type(),"char")) datatype = 2; 1.32130 + if (!cimg::strcasecmp(pixel_type(),"unsigned short")) datatype = 4; 1.32131 + if (!cimg::strcasecmp(pixel_type(),"short")) datatype = 4; 1.32132 + if (!cimg::strcasecmp(pixel_type(),"unsigned int")) datatype = 8; 1.32133 + if (!cimg::strcasecmp(pixel_type(),"int")) datatype = 8; 1.32134 + if (!cimg::strcasecmp(pixel_type(),"unsigned long")) datatype = 8; 1.32135 + if (!cimg::strcasecmp(pixel_type(),"long")) datatype = 8; 1.32136 + if (!cimg::strcasecmp(pixel_type(),"float")) datatype = 16; 1.32137 + if (!cimg::strcasecmp(pixel_type(),"double")) datatype = 64; 1.32138 + if (datatype<0) 1.32139 + throw CImgIOException("CImg<%s>::save_analyze() : Cannot save image '%s' since pixel type (%s)" 1.32140 + "is not handled in Analyze7.5 specifications.\n", 1.32141 + pixel_type(),filename,pixel_type()); 1.32142 + ((short*)(header+70))[0] = datatype; 1.32143 + ((short*)(header+72))[0] = sizeof(T); 1.32144 + ((float*)(header+112))[0] = 1; 1.32145 + ((float*)(header+76))[0] = 0; 1.32146 + if (voxsize) { 1.32147 + ((float*)(header+76))[1] = voxsize[0]; 1.32148 + ((float*)(header+76))[2] = voxsize[1]; 1.32149 + ((float*)(header+76))[3] = voxsize[2]; 1.32150 + } else ((float*)(header+76))[1] = ((float*)(header+76))[2] = ((float*)(header+76))[3] = 1; 1.32151 + file = cimg::fopen(hname,"wb"); 1.32152 + cimg::fwrite(header,348,file); 1.32153 + if (iname[0]) { cimg::fclose(file); file = cimg::fopen(iname,"wb"); } 1.32154 + cimg::fwrite(data,size(),file); 1.32155 + cimg::fclose(file); 1.32156 + return *this; 1.32157 + } 1.32158 + 1.32159 + //! Save the image as a .cimg file. 1.32160 + const CImg<T>& save_cimg(const char *const filename, const bool compress=false) const { 1.32161 + CImgList<T>(*this,true).save_cimg(filename,compress); 1.32162 + return *this; 1.32163 + } 1.32164 + 1.32165 + // Save the image as a .cimg file. 1.32166 + const CImg<T>& save_cimg(cimg_std::FILE *const file, const bool compress=false) const { 1.32167 + CImgList<T>(*this,true).save_cimg(file,compress); 1.32168 + return *this; 1.32169 + } 1.32170 + 1.32171 + //! Insert the image into an existing .cimg file, at specified coordinates. 1.32172 + const CImg<T>& save_cimg(const char *const filename, 1.32173 + const unsigned int n0, 1.32174 + const unsigned int x0, const unsigned int y0, 1.32175 + const unsigned int z0, const unsigned int v0) const { 1.32176 + CImgList<T>(*this,true).save_cimg(filename,n0,x0,y0,z0,v0); 1.32177 + return *this; 1.32178 + } 1.32179 + 1.32180 + //! Insert the image into an existing .cimg file, at specified coordinates. 1.32181 + const CImg<T>& save_cimg(cimg_std::FILE *const file, 1.32182 + const unsigned int n0, 1.32183 + const unsigned int x0, const unsigned int y0, 1.32184 + const unsigned int z0, const unsigned int v0) const { 1.32185 + CImgList<T>(*this,true).save_cimg(file,n0,x0,y0,z0,v0); 1.32186 + return *this; 1.32187 + } 1.32188 + 1.32189 + //! Save an empty .cimg file with specified dimensions. 1.32190 + static void save_empty_cimg(const char *const filename, 1.32191 + const unsigned int dx, const unsigned int dy=1, 1.32192 + const unsigned int dz=1, const unsigned int dv=1) { 1.32193 + return CImgList<T>::save_empty_cimg(filename,1,dx,dy,dz,dv); 1.32194 + } 1.32195 + 1.32196 + //! Save an empty .cimg file with specified dimensions. 1.32197 + static void save_empty_cimg(cimg_std::FILE *const file, 1.32198 + const unsigned int dx, const unsigned int dy=1, 1.32199 + const unsigned int dz=1, const unsigned int dv=1) { 1.32200 + return CImgList<T>::save_empty_cimg(file,1,dx,dy,dz,dv); 1.32201 + } 1.32202 + 1.32203 + // Save the image as an INRIMAGE-4 file (internal). 1.32204 + const CImg<T>& _save_inr(cimg_std::FILE *const file, const char *const filename, const float *const voxsize) const { 1.32205 + if (is_empty()) 1.32206 + throw CImgInstanceException("CImg<%s>::save_inr() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.32207 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.32208 + if (!filename) 1.32209 + throw CImgArgumentException("CImg<%s>::save_inr() : Instance image (%u,%u,%u,%u,%p), specified file is (null).", 1.32210 + pixel_type(),width,height,depth,dim,data); 1.32211 + int inrpixsize=-1; 1.32212 + const char *inrtype = "unsigned fixed\nPIXSIZE=8 bits\nSCALE=2**0"; 1.32213 + if (!cimg::strcasecmp(pixel_type(),"unsigned char")) { inrtype = "unsigned fixed\nPIXSIZE=8 bits\nSCALE=2**0"; inrpixsize = 1; } 1.32214 + if (!cimg::strcasecmp(pixel_type(),"char")) { inrtype = "fixed\nPIXSIZE=8 bits\nSCALE=2**0"; inrpixsize = 1; } 1.32215 + if (!cimg::strcasecmp(pixel_type(),"unsigned short")) { inrtype = "unsigned fixed\nPIXSIZE=16 bits\nSCALE=2**0";inrpixsize = 2; } 1.32216 + if (!cimg::strcasecmp(pixel_type(),"short")) { inrtype = "fixed\nPIXSIZE=16 bits\nSCALE=2**0"; inrpixsize = 2; } 1.32217 + if (!cimg::strcasecmp(pixel_type(),"unsigned int")) { inrtype = "unsigned fixed\nPIXSIZE=32 bits\nSCALE=2**0";inrpixsize = 4; } 1.32218 + if (!cimg::strcasecmp(pixel_type(),"int")) { inrtype = "fixed\nPIXSIZE=32 bits\nSCALE=2**0"; inrpixsize = 4; } 1.32219 + if (!cimg::strcasecmp(pixel_type(),"float")) { inrtype = "float\nPIXSIZE=32 bits"; inrpixsize = 4; } 1.32220 + if (!cimg::strcasecmp(pixel_type(),"double")) { inrtype = "float\nPIXSIZE=64 bits"; inrpixsize = 8; } 1.32221 + if (inrpixsize<=0) 1.32222 + throw CImgIOException("CImg<%s>::save_inr() : Don't know how to save images of '%s'", 1.32223 + pixel_type(),pixel_type()); 1.32224 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); 1.32225 + char header[257]; 1.32226 + int err = cimg_std::sprintf(header,"#INRIMAGE-4#{\nXDIM=%u\nYDIM=%u\nZDIM=%u\nVDIM=%u\n",width,height,depth,dim); 1.32227 + if (voxsize) err += cimg_std::sprintf(header+err,"VX=%g\nVY=%g\nVZ=%g\n",voxsize[0],voxsize[1],voxsize[2]); 1.32228 + err += cimg_std::sprintf(header+err,"TYPE=%s\nCPU=%s\n",inrtype,cimg::endianness()?"sun":"decm"); 1.32229 + cimg_std::memset(header+err,'\n',252-err); 1.32230 + cimg_std::memcpy(header+252,"##}\n",4); 1.32231 + cimg::fwrite(header,256,nfile); 1.32232 + cimg_forXYZ(*this,x,y,z) cimg_forV(*this,k) cimg::fwrite(&((*this)(x,y,z,k)),1,nfile); 1.32233 + if (!file) cimg::fclose(nfile); 1.32234 + return *this; 1.32235 + } 1.32236 + 1.32237 + //! Save the image as an INRIMAGE-4 file. 1.32238 + const CImg<T>& save_inr(const char *const filename, const float *const voxsize=0) const { 1.32239 + return _save_inr(0,filename,voxsize); 1.32240 + } 1.32241 + 1.32242 + //! Save the image as an INRIMAGE-4 file. 1.32243 + const CImg<T>& save_inr(cimg_std::FILE *const file, const float *const voxsize=0) const { 1.32244 + return _save_inr(file,0,voxsize); 1.32245 + } 1.32246 + 1.32247 + // Save the image as a PANDORE-5 file (internal). 1.32248 + unsigned int _save_pandore_header_length(unsigned int id, unsigned int *dims, const unsigned int colorspace) const { 1.32249 + unsigned int nbdims = 0; 1.32250 + if (id==2 || id==3 || id==4) { dims[0] = 1; dims[1] = width; nbdims = 2; } 1.32251 + if (id==5 || id==6 || id==7) { dims[0] = 1; dims[1] = height; dims[2] = width; nbdims=3; } 1.32252 + if (id==8 || id==9 || id==10) { dims[0] = dim; dims[1] = depth; dims[2] = height; dims[3] = width; nbdims = 4; } 1.32253 + if (id==16 || id==17 || id==18) { dims[0] = 3; dims[1] = height; dims[2] = width; dims[3] = colorspace; nbdims = 4; } 1.32254 + if (id==19 || id==20 || id==21) { dims[0] = 3; dims[1] = depth; dims[2] = height; dims[3] = width; dims[4] = colorspace; nbdims = 5; } 1.32255 + if (id==22 || id==23 || id==25) { dims[0] = dim; dims[1] = width; nbdims = 2; } 1.32256 + if (id==26 || id==27 || id==29) { dims[0] = dim; dims[1] = height; dims[2] = width; nbdims=3; } 1.32257 + if (id==30 || id==31 || id==33) { dims[0] = dim; dims[1] = depth; dims[2] = height; dims[3] = width; nbdims = 4; } 1.32258 + return nbdims; 1.32259 + } 1.32260 + 1.32261 + const CImg<T>& _save_pandore(cimg_std::FILE *const file, const char *const filename, const unsigned int colorspace) const { 1.32262 + typedef unsigned char uchar; 1.32263 + typedef unsigned short ushort; 1.32264 + typedef unsigned int uint; 1.32265 + typedef unsigned long ulong; 1.32266 + 1.32267 +#define __cimg_save_pandore_case(dtype) \ 1.32268 + dtype *buffer = new dtype[size()]; \ 1.32269 + const T *ptrs = data; \ 1.32270 + cimg_foroff(*this,off) *(buffer++) = (dtype)(*(ptrs++)); \ 1.32271 + buffer-=size(); \ 1.32272 + cimg::fwrite(buffer,size(),nfile); \ 1.32273 + delete[] buffer 1.32274 + 1.32275 +#define _cimg_save_pandore_case(sy,sz,sv,stype,id) \ 1.32276 + if (!saved && (sy?(sy==height):true) && (sz?(sz==depth):true) && (sv?(sv==dim):true) && !cimg::strcmp(stype,pixel_type())) { \ 1.32277 + unsigned int *iheader = (unsigned int*)(header+12); \ 1.32278 + nbdims = _save_pandore_header_length((*iheader=id),dims,colorspace); \ 1.32279 + cimg::fwrite(header,36,nfile); \ 1.32280 + if (sizeof(ulong)==4) { ulong ndims[5]; for (int d = 0; d<5; ++d) ndims[d] = (ulong)dims[d]; cimg::fwrite(ndims,nbdims,nfile); } \ 1.32281 + else if (sizeof(uint)==4) { uint ndims[5]; for (int d = 0; d<5; ++d) ndims[d] = (uint)dims[d]; cimg::fwrite(ndims,nbdims,nfile); } \ 1.32282 + else if (sizeof(ushort)==4) { ushort ndims[5]; for (int d = 0; d<5; ++d) ndims[d] = (ushort)dims[d]; cimg::fwrite(ndims,nbdims,nfile); } \ 1.32283 + else throw CImgIOException("CImg<%s>::save_pandore() : File '%s', instance image (%u,%u,%u,%u,%p), output type is not" \ 1.32284 + "supported on this architecture.",pixel_type(),filename?filename:"(FILE*)",width,height, \ 1.32285 + depth,dim,data); \ 1.32286 + if (id==2 || id==5 || id==8 || id==16 || id==19 || id==22 || id==26 || id==30) { \ 1.32287 + __cimg_save_pandore_case(uchar); \ 1.32288 + } else if (id==3 || id==6 || id==9 || id==17 || id==20 || id==23 || id==27 || id==31) { \ 1.32289 + if (sizeof(ulong)==4) { __cimg_save_pandore_case(ulong); } \ 1.32290 + else if (sizeof(uint)==4) { __cimg_save_pandore_case(uint); } \ 1.32291 + else if (sizeof(ushort)==4) { __cimg_save_pandore_case(ushort); } \ 1.32292 + else throw CImgIOException("CImg<%s>::save_pandore() : File '%s', instance image (%u,%u,%u,%u,%p), output type is not" \ 1.32293 + "supported on this architecture.",pixel_type(),filename?filename:"(FILE*)",width,height, \ 1.32294 + depth,dim,data); \ 1.32295 + } else if (id==4 || id==7 || id==10 || id==18 || id==21 || id==25 || id==29 || id==33) { \ 1.32296 + if (sizeof(double)==4) { __cimg_save_pandore_case(double); } \ 1.32297 + else if (sizeof(float)==4) { __cimg_save_pandore_case(float); } \ 1.32298 + else throw CImgIOException("CImg<%s>::save_pandore() : File '%s', instance image (%u,%u,%u,%u,%p), output type is not" \ 1.32299 + "supported on this architecture.",pixel_type(),filename?filename:"(FILE*)",width,height, \ 1.32300 + depth,dim,data); \ 1.32301 + } \ 1.32302 + saved = true; \ 1.32303 + } 1.32304 + 1.32305 + if (is_empty()) 1.32306 + throw CImgInstanceException("CImg<%s>::save_pandore() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.32307 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.32308 + if (!file && !filename) 1.32309 + throw CImgArgumentException("CImg<%s>::save_pandore() : Instance image (%u,%u,%u,%u,%p), specified file is (null).", 1.32310 + pixel_type(),width,height,depth,dim,data); 1.32311 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); 1.32312 + unsigned char header[36] = { 'P','A','N','D','O','R','E','0','4',0,0,0, 1.32313 + 0,0,0,0,'C','I','m','g',0,0,0,0,0,'N','o',' ','d','a','t','e',0,0,0,0 }; 1.32314 + unsigned int nbdims, dims[5]; 1.32315 + bool saved = false; 1.32316 + _cimg_save_pandore_case(1,1,1,"unsigned char",2); 1.32317 + _cimg_save_pandore_case(1,1,1,"char",3); 1.32318 + _cimg_save_pandore_case(1,1,1,"short",3); 1.32319 + _cimg_save_pandore_case(1,1,1,"unsigned short",3); 1.32320 + _cimg_save_pandore_case(1,1,1,"unsigned int",3); 1.32321 + _cimg_save_pandore_case(1,1,1,"int",3); 1.32322 + _cimg_save_pandore_case(1,1,1,"unsigned long",4); 1.32323 + _cimg_save_pandore_case(1,1,1,"long",3); 1.32324 + _cimg_save_pandore_case(1,1,1,"float",4); 1.32325 + _cimg_save_pandore_case(1,1,1,"double",4); 1.32326 + 1.32327 + _cimg_save_pandore_case(0,1,1,"unsigned char",5); 1.32328 + _cimg_save_pandore_case(0,1,1,"char",6); 1.32329 + _cimg_save_pandore_case(0,1,1,"short",6); 1.32330 + _cimg_save_pandore_case(0,1,1,"unsigned short",6); 1.32331 + _cimg_save_pandore_case(0,1,1,"unsigned int",6); 1.32332 + _cimg_save_pandore_case(0,1,1,"int",6); 1.32333 + _cimg_save_pandore_case(0,1,1,"unsigned long",7); 1.32334 + _cimg_save_pandore_case(0,1,1,"long",6); 1.32335 + _cimg_save_pandore_case(0,1,1,"float",7); 1.32336 + _cimg_save_pandore_case(0,1,1,"double",7); 1.32337 + 1.32338 + _cimg_save_pandore_case(0,0,1,"unsigned char",8); 1.32339 + _cimg_save_pandore_case(0,0,1,"char",9); 1.32340 + _cimg_save_pandore_case(0,0,1,"short",9); 1.32341 + _cimg_save_pandore_case(0,0,1,"unsigned short",9); 1.32342 + _cimg_save_pandore_case(0,0,1,"unsigned int",9); 1.32343 + _cimg_save_pandore_case(0,0,1,"int",9); 1.32344 + _cimg_save_pandore_case(0,0,1,"unsigned long",10); 1.32345 + _cimg_save_pandore_case(0,0,1,"long",9); 1.32346 + _cimg_save_pandore_case(0,0,1,"float",10); 1.32347 + _cimg_save_pandore_case(0,0,1,"double",10); 1.32348 + 1.32349 + _cimg_save_pandore_case(0,1,3,"unsigned char",16); 1.32350 + _cimg_save_pandore_case(0,1,3,"char",17); 1.32351 + _cimg_save_pandore_case(0,1,3,"short",17); 1.32352 + _cimg_save_pandore_case(0,1,3,"unsigned short",17); 1.32353 + _cimg_save_pandore_case(0,1,3,"unsigned int",17); 1.32354 + _cimg_save_pandore_case(0,1,3,"int",17); 1.32355 + _cimg_save_pandore_case(0,1,3,"unsigned long",18); 1.32356 + _cimg_save_pandore_case(0,1,3,"long",17); 1.32357 + _cimg_save_pandore_case(0,1,3,"float",18); 1.32358 + _cimg_save_pandore_case(0,1,3,"double",18); 1.32359 + 1.32360 + _cimg_save_pandore_case(0,0,3,"unsigned char",19); 1.32361 + _cimg_save_pandore_case(0,0,3,"char",20); 1.32362 + _cimg_save_pandore_case(0,0,3,"short",20); 1.32363 + _cimg_save_pandore_case(0,0,3,"unsigned short",20); 1.32364 + _cimg_save_pandore_case(0,0,3,"unsigned int",20); 1.32365 + _cimg_save_pandore_case(0,0,3,"int",20); 1.32366 + _cimg_save_pandore_case(0,0,3,"unsigned long",21); 1.32367 + _cimg_save_pandore_case(0,0,3,"long",20); 1.32368 + _cimg_save_pandore_case(0,0,3,"float",21); 1.32369 + _cimg_save_pandore_case(0,0,3,"double",21); 1.32370 + 1.32371 + _cimg_save_pandore_case(1,1,0,"unsigned char",22); 1.32372 + _cimg_save_pandore_case(1,1,0,"char",23); 1.32373 + _cimg_save_pandore_case(1,1,0,"short",23); 1.32374 + _cimg_save_pandore_case(1,1,0,"unsigned short",23); 1.32375 + _cimg_save_pandore_case(1,1,0,"unsigned int",23); 1.32376 + _cimg_save_pandore_case(1,1,0,"int",23); 1.32377 + _cimg_save_pandore_case(1,1,0,"unsigned long",25); 1.32378 + _cimg_save_pandore_case(1,1,0,"long",23); 1.32379 + _cimg_save_pandore_case(1,1,0,"float",25); 1.32380 + _cimg_save_pandore_case(1,1,0,"double",25); 1.32381 + 1.32382 + _cimg_save_pandore_case(0,1,0,"unsigned char",26); 1.32383 + _cimg_save_pandore_case(0,1,0,"char",27); 1.32384 + _cimg_save_pandore_case(0,1,0,"short",27); 1.32385 + _cimg_save_pandore_case(0,1,0,"unsigned short",27); 1.32386 + _cimg_save_pandore_case(0,1,0,"unsigned int",27); 1.32387 + _cimg_save_pandore_case(0,1,0,"int",27); 1.32388 + _cimg_save_pandore_case(0,1,0,"unsigned long",29); 1.32389 + _cimg_save_pandore_case(0,1,0,"long",27); 1.32390 + _cimg_save_pandore_case(0,1,0,"float",29); 1.32391 + _cimg_save_pandore_case(0,1,0,"double",29); 1.32392 + 1.32393 + _cimg_save_pandore_case(0,0,0,"unsigned char",30); 1.32394 + _cimg_save_pandore_case(0,0,0,"char",31); 1.32395 + _cimg_save_pandore_case(0,0,0,"short",31); 1.32396 + _cimg_save_pandore_case(0,0,0,"unsigned short",31); 1.32397 + _cimg_save_pandore_case(0,0,0,"unsigned int",31); 1.32398 + _cimg_save_pandore_case(0,0,0,"int",31); 1.32399 + _cimg_save_pandore_case(0,0,0,"unsigned long",33); 1.32400 + _cimg_save_pandore_case(0,0,0,"long",31); 1.32401 + _cimg_save_pandore_case(0,0,0,"float",33); 1.32402 + _cimg_save_pandore_case(0,0,0,"double",33); 1.32403 + 1.32404 + if (!file) cimg::fclose(nfile); 1.32405 + return *this; 1.32406 + } 1.32407 + 1.32408 + //! Save the image as a PANDORE-5 file. 1.32409 + const CImg<T>& save_pandore(const char *const filename, const unsigned int colorspace=0) const { 1.32410 + return _save_pandore(0,filename,colorspace); 1.32411 + } 1.32412 + 1.32413 + //! Save the image as a PANDORE-5 file. 1.32414 + const CImg<T>& save_pandore(cimg_std::FILE *const file, const unsigned int colorspace=0) const { 1.32415 + return _save_pandore(file,0,colorspace); 1.32416 + } 1.32417 + 1.32418 + // Save the image as a RAW file (internal). 1.32419 + const CImg<T>& _save_raw(cimg_std::FILE *const file, const char *const filename, const bool multiplexed) const { 1.32420 + if (is_empty()) 1.32421 + throw CImgInstanceException("CImg<%s>::save_raw() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.32422 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.32423 + if (!file && !filename) 1.32424 + throw CImgArgumentException("CImg<%s>::save_raw() : Instance image (%u,%u,%u,%u,%p), specified file is (null).", 1.32425 + pixel_type(),width,height,depth,dim,data); 1.32426 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); 1.32427 + if (!multiplexed) cimg::fwrite(data,size(),nfile); 1.32428 + else { 1.32429 + CImg<T> buf(dim); 1.32430 + cimg_forXYZ(*this,x,y,z) { 1.32431 + cimg_forV(*this,k) buf[k] = (*this)(x,y,z,k); 1.32432 + cimg::fwrite(buf.data,dim,nfile); 1.32433 + } 1.32434 + } 1.32435 + if (!file) cimg::fclose(nfile); 1.32436 + return *this; 1.32437 + } 1.32438 + 1.32439 + //! Save the image as a RAW file. 1.32440 + const CImg<T>& save_raw(const char *const filename, const bool multiplexed=false) const { 1.32441 + return _save_raw(0,filename,multiplexed); 1.32442 + } 1.32443 + 1.32444 + //! Save the image as a RAW file. 1.32445 + const CImg<T>& save_raw(cimg_std::FILE *const file, const bool multiplexed=false) const { 1.32446 + return _save_raw(file,0,multiplexed); 1.32447 + } 1.32448 + 1.32449 + //! Save the image as a video sequence file, using FFMPEG library. 1.32450 + const CImg<T>& save_ffmpeg(const char *const filename, const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.32451 + const unsigned int fps=25) const { 1.32452 + if (is_empty()) 1.32453 + throw CImgInstanceException("CImg<%s>::save_ffmpeg() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.32454 + pixel_type(),filename?filename:"(null)",width,height,depth,dim,data); 1.32455 + if (!filename) 1.32456 + throw CImgArgumentException("CImg<%s>::save_ffmpeg() : Instance image (%u,%u,%u,%u,%p), specified filename is (null).", 1.32457 + pixel_type(),width,height,depth,dim,data); 1.32458 + if (!fps) 1.32459 + throw CImgArgumentException("CImg<%s>::save_ffmpeg() : File '%s', specified framerate is 0.", 1.32460 + pixel_type(),filename); 1.32461 +#ifndef cimg_use_ffmpeg 1.32462 + return save_ffmpeg_external(filename,first_frame,last_frame); 1.32463 +#else 1.32464 + get_split('z').save_ffmpeg(filename,first_frame,last_frame,fps); 1.32465 +#endif 1.32466 + return *this; 1.32467 + } 1.32468 + 1.32469 + //! Save the image as a YUV video sequence file. 1.32470 + const CImg<T>& save_yuv(const char *const filename, const bool rgb2yuv=true) const { 1.32471 + get_split('z').save_yuv(filename,rgb2yuv); 1.32472 + return *this; 1.32473 + } 1.32474 + 1.32475 + //! Save the image as a YUV video sequence file. 1.32476 + const CImg<T>& save_yuv(cimg_std::FILE *const file, const bool rgb2yuv=true) const { 1.32477 + get_split('z').save_yuv(file,rgb2yuv); 1.32478 + return *this; 1.32479 + } 1.32480 + 1.32481 + // Save OFF files (internal). 1.32482 + template<typename tf, typename tc> 1.32483 + const CImg<T>& _save_off(cimg_std::FILE *const file, const char *const filename, 1.32484 + const CImgList<tf>& primitives, const CImgList<tc>& colors, const bool invert_faces) const { 1.32485 + if (is_empty()) 1.32486 + throw CImgInstanceException("CImg<%s>::save_off() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.32487 + pixel_type(),filename?filename:"(FILE*)",width,height,depth,dim,data); 1.32488 + if (!file && !filename) 1.32489 + throw CImgArgumentException("CImg<%s>::save_off() : Specified filename is (null).", 1.32490 + pixel_type()); 1.32491 + if (height<3) return get_resize(-100,3,1,1,0)._save_off(file,filename,primitives,colors,invert_faces); 1.32492 + CImgList<tc> _colors; 1.32493 + if (!colors) _colors.insert(primitives.size,CImg<tc>::vector(200,200,200)); 1.32494 + const CImgList<tc>& ncolors = colors?colors:_colors; 1.32495 + 1.32496 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); 1.32497 + cimg_std::fprintf(nfile,"OFF\n%u %u %u\n",width,primitives.size,3*primitives.size); 1.32498 + cimg_forX(*this,i) cimg_std::fprintf(nfile,"%f %f %f\n",(float)((*this)(i,0)),(float)((*this)(i,1)),(float)((*this)(i,2))); 1.32499 + cimglist_for(primitives,l) { 1.32500 + const unsigned int prim = primitives[l].size(); 1.32501 + const bool textured = (prim>4); 1.32502 + const CImg<tc>& color = ncolors[l]; 1.32503 + const unsigned int s = textured?color.dimv():color.size(); 1.32504 + const float 1.32505 + r = textured?(s>0?(float)(color.get_shared_channel(0).mean()/255.0f):1.0f):(s>0?(float)(color(0)/255.0f):1.0f), 1.32506 + g = textured?(s>1?(float)(color.get_shared_channel(1).mean()/255.0f):r) :(s>1?(float)(color(1)/255.0f):r), 1.32507 + b = textured?(s>2?(float)(color.get_shared_channel(2).mean()/255.0f):r) :(s>2?(float)(color(2)/255.0f):r); 1.32508 + 1.32509 + switch (prim) { 1.32510 + case 1 : 1.32511 + cimg_std::fprintf(nfile,"1 %u %f %f %f\n",(unsigned int)primitives(l,0),r,g,b); 1.32512 + break; 1.32513 + case 2 : case 6 : 1.32514 + cimg_std::fprintf(nfile,"2 %u %u %f %f %f\n",(unsigned int)primitives(l,0),(unsigned int)primitives(l,1),r,g,b); 1.32515 + break; 1.32516 + case 3 : case 9 : 1.32517 + if (invert_faces) 1.32518 + cimg_std::fprintf(nfile,"3 %u %u %u %f %f %f\n",(unsigned int)primitives(l,0),(unsigned int)primitives(l,1),(unsigned int)primitives(l,2),r,g,b); 1.32519 + else 1.32520 + cimg_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); 1.32521 + break; 1.32522 + case 4 : case 12 : 1.32523 + if (invert_faces) 1.32524 + cimg_std::fprintf(nfile,"4 %u %u %u %u %f %f %f\n", 1.32525 + (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),(unsigned int)primitives(l,2),(unsigned int)primitives(l,3),r,g,b); 1.32526 + else 1.32527 + cimg_std::fprintf(nfile,"4 %u %u %u %u %f %f %f\n", 1.32528 + (unsigned int)primitives(l,0),(unsigned int)primitives(l,3),(unsigned int)primitives(l,2),(unsigned int)primitives(l,1),r,g,b); 1.32529 + break; 1.32530 + } 1.32531 + } 1.32532 + if (!file) cimg::fclose(nfile); 1.32533 + return *this; 1.32534 + } 1.32535 + 1.32536 + //! Save OFF files. 1.32537 + template<typename tf, typename tc> 1.32538 + const CImg<T>& save_off(const char *const filename, 1.32539 + const CImgList<tf>& primitives, const CImgList<tc>& colors, const bool invert_faces=false) const { 1.32540 + return _save_off(0,filename,primitives,colors,invert_faces); 1.32541 + } 1.32542 + 1.32543 + //! Save OFF files. 1.32544 + template<typename tf, typename tc> 1.32545 + const CImg<T>& save_off(cimg_std::FILE *const file, 1.32546 + const CImgList<tf>& primitives, const CImgList<tc>& colors, const bool invert_faces=false) const { 1.32547 + return _save_off(file,0,primitives,colors,invert_faces); 1.32548 + } 1.32549 + 1.32550 + //! Save the image as a video sequence file, using the external tool 'ffmpeg'. 1.32551 + const CImg<T>& save_ffmpeg_external(const char *const filename, const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.32552 + const char *const codec="mpeg2video") const { 1.32553 + if (is_empty()) 1.32554 + throw CImgInstanceException("CImg<%s>::save_ffmpeg_external() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.32555 + pixel_type(),filename?filename:"(null)",width,height,depth,dim,data); 1.32556 + if (!filename) 1.32557 + throw CImgArgumentException("CImg<%s>::save_ffmpeg_external() : Instance image (%u,%u,%u,%u,%p), specified filename is (null).", 1.32558 + pixel_type(),width,height,depth,dim,data); 1.32559 + get_split('z').save_ffmpeg_external(filename,first_frame,last_frame,codec); 1.32560 + return *this; 1.32561 + } 1.32562 + 1.32563 + //! Save the image using GraphicsMagick's gm. 1.32564 + /** Function that saves the image for other file formats that are not natively handled by CImg, 1.32565 + using the tool 'gm' from the GraphicsMagick package.\n 1.32566 + This is the case for all compressed image formats (GIF,PNG,JPG,TIF, ...). You need to install 1.32567 + the GraphicsMagick package in order to get 1.32568 + this function working properly (see http://www.graphicsmagick.org ). 1.32569 + **/ 1.32570 + const CImg<T>& save_graphicsmagick_external(const char *const filename, const unsigned int quality=100) const { 1.32571 + if (is_empty()) 1.32572 + throw CImgInstanceException("CImg<%s>::save_graphicsmagick_external() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.32573 + pixel_type(),filename?filename:"(null)",width,height,depth,dim,data); 1.32574 + if (!filename) 1.32575 + throw CImgArgumentException("CImg<%s>::save_graphicsmagick_external() : Instance image (%u,%u,%u,%u,%p), specified filename is (null).", 1.32576 + pixel_type(),width,height,depth,dim,data); 1.32577 + char command[1024],filetmp[512]; 1.32578 + cimg_std::FILE *file; 1.32579 + do { 1.32580 + if (dim==1) cimg_std::sprintf(filetmp,"%s%s%s.pgm",cimg::temporary_path(),cimg_OS==2?"\\":"/",cimg::filenamerand()); 1.32581 + else cimg_std::sprintf(filetmp,"%s%s%s.ppm",cimg::temporary_path(),cimg_OS==2?"\\":"/",cimg::filenamerand()); 1.32582 + if ((file=cimg_std::fopen(filetmp,"rb"))!=0) cimg_std::fclose(file); 1.32583 + } while (file); 1.32584 + save_pnm(filetmp); 1.32585 + cimg_std::sprintf(command,"%s -quality %u%% %s \"%s\"",cimg::graphicsmagick_path(),quality,filetmp,filename); 1.32586 + cimg::system(command); 1.32587 + file = cimg_std::fopen(filename,"rb"); 1.32588 + if (!file) 1.32589 + throw CImgIOException("CImg<%s>::save_graphicsmagick_external() : Failed to save image '%s'.\n\n" 1.32590 + "Path of 'gm' : \"%s\"\n" 1.32591 + "Path of temporary filename : \"%s\"\n", 1.32592 + pixel_type(),filename,cimg::graphicsmagick_path(),filetmp); 1.32593 + if (file) cimg::fclose(file); 1.32594 + cimg_std::remove(filetmp); 1.32595 + return *this; 1.32596 + } 1.32597 + 1.32598 + //! Save an image as a gzipped file, using external tool 'gzip'. 1.32599 + const CImg<T>& save_gzip_external(const char *const filename) const { 1.32600 + if (!filename) 1.32601 + throw CImgIOException("CImg<%s>::save_gzip_external() : Cannot save (null) filename.", 1.32602 + pixel_type()); 1.32603 + char command[1024], filetmp[512], body[512]; 1.32604 + const char 1.32605 + *ext = cimg::split_filename(filename,body), 1.32606 + *ext2 = cimg::split_filename(body,0); 1.32607 + cimg_std::FILE *file; 1.32608 + do { 1.32609 + if (!cimg::strcasecmp(ext,"gz")) { 1.32610 + if (*ext2) cimg_std::sprintf(filetmp,"%s%s%s.%s",cimg::temporary_path(),cimg_OS==2?"\\":"/", 1.32611 + cimg::filenamerand(),ext2); 1.32612 + else cimg_std::sprintf(filetmp,"%s%s%s.cimg",cimg::temporary_path(),cimg_OS==2?"\\":"/", 1.32613 + cimg::filenamerand()); 1.32614 + } else { 1.32615 + if (*ext) cimg_std::sprintf(filetmp,"%s%s%s.%s",cimg::temporary_path(),cimg_OS==2?"\\":"/", 1.32616 + cimg::filenamerand(),ext); 1.32617 + else cimg_std::sprintf(filetmp,"%s%s%s.cimg",cimg::temporary_path(),cimg_OS==2?"\\":"/", 1.32618 + cimg::filenamerand()); 1.32619 + } 1.32620 + if ((file=cimg_std::fopen(filetmp,"rb"))!=0) cimg_std::fclose(file); 1.32621 + } while (file); 1.32622 + save(filetmp); 1.32623 + cimg_std::sprintf(command,"%s -c %s > \"%s\"",cimg::gzip_path(),filetmp,filename); 1.32624 + cimg::system(command); 1.32625 + file = cimg_std::fopen(filename,"rb"); 1.32626 + if (!file) 1.32627 + throw CImgIOException("CImgList<%s>::save_gzip_external() : File '%s' cannot be saved.", 1.32628 + pixel_type(),filename); 1.32629 + else cimg::fclose(file); 1.32630 + cimg_std::remove(filetmp); 1.32631 + return *this; 1.32632 + } 1.32633 + 1.32634 + //! Save the image using ImageMagick's convert. 1.32635 + /** Function that saves the image for other file formats that are not natively handled by CImg, 1.32636 + using the tool 'convert' from the ImageMagick package.\n 1.32637 + This is the case for all compressed image formats (GIF,PNG,JPG,TIF, ...). You need to install 1.32638 + the ImageMagick package in order to get 1.32639 + this function working properly (see http://www.imagemagick.org ). 1.32640 + **/ 1.32641 + const CImg<T>& save_imagemagick_external(const char *const filename, const unsigned int quality=100) const { 1.32642 + if (is_empty()) 1.32643 + throw CImgInstanceException("CImg<%s>::save_imagemagick_external() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.32644 + pixel_type(),filename?filename:"(null)",width,height,depth,dim,data); 1.32645 + if (!filename) 1.32646 + throw CImgArgumentException("CImg<%s>::save_imagemagick_external() : Instance image (%u,%u,%u,%u,%p), specified filename is (null).", 1.32647 + pixel_type(),width,height,depth,dim,data); 1.32648 + char command[1024], filetmp[512]; 1.32649 + cimg_std::FILE *file; 1.32650 + do { 1.32651 + cimg_std::sprintf(filetmp,"%s%s%s.%s",cimg::temporary_path(),cimg_OS==2?"\\":"/",cimg::filenamerand(),dim==1?"pgm":"ppm"); 1.32652 + if ((file=cimg_std::fopen(filetmp,"rb"))!=0) cimg_std::fclose(file); 1.32653 + } while (file); 1.32654 + save_pnm(filetmp); 1.32655 + cimg_std::sprintf(command,"%s -quality %u%% %s \"%s\"",cimg::imagemagick_path(),quality,filetmp,filename); 1.32656 + cimg::system(command); 1.32657 + file = cimg_std::fopen(filename,"rb"); 1.32658 + if (!file) 1.32659 + throw CImgIOException("CImg<%s>::save_imagemagick_external() : Failed to save image '%s'.\n\n" 1.32660 + "Path of 'convert' : \"%s\"\n" 1.32661 + "Path of temporary filename : \"%s\"\n", 1.32662 + pixel_type(),filename,cimg::imagemagick_path(),filetmp); 1.32663 + if (file) cimg::fclose(file); 1.32664 + cimg_std::remove(filetmp); 1.32665 + return *this; 1.32666 + } 1.32667 + 1.32668 + //! Save an image as a Dicom file (need '(X)Medcon' : http://xmedcon.sourceforge.net ) 1.32669 + const CImg<T>& save_medcon_external(const char *const filename) const { 1.32670 + if (is_empty()) 1.32671 + throw CImgInstanceException("CImg<%s>::save_medcon_external() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.32672 + pixel_type(),filename?filename:"(null)",width,height,depth,dim,data); 1.32673 + if (!filename) 1.32674 + throw CImgArgumentException("CImg<%s>::save_medcon_external() : Instance image (%u,%u,%u,%u,%p), specified filename is (null).", 1.32675 + pixel_type(),width,height,depth,dim,data); 1.32676 + 1.32677 + char command[1024], filetmp[512], body[512]; 1.32678 + cimg_std::FILE *file; 1.32679 + do { 1.32680 + cimg_std::sprintf(filetmp,"%s.hdr",cimg::filenamerand()); 1.32681 + if ((file=cimg_std::fopen(filetmp,"rb"))!=0) cimg_std::fclose(file); 1.32682 + } while (file); 1.32683 + save_analyze(filetmp); 1.32684 + cimg_std::sprintf(command,"%s -w -c dicom -o %s -f %s",cimg::medcon_path(),filename,filetmp); 1.32685 + cimg::system(command); 1.32686 + cimg_std::remove(filetmp); 1.32687 + cimg::split_filename(filetmp,body); 1.32688 + cimg_std::sprintf(filetmp,"%s.img",body); 1.32689 + cimg_std::remove(filetmp); 1.32690 + cimg_std::sprintf(command,"m000-%s",filename); 1.32691 + file = cimg_std::fopen(command,"rb"); 1.32692 + if (!file) { 1.32693 + cimg::fclose(cimg::fopen(filename,"r")); 1.32694 + throw CImgIOException("CImg<%s>::save_medcon_external() : Failed to save image '%s'.\n\n" 1.32695 + "Path of 'medcon' : \"%s\"\n" 1.32696 + "Path of temporary filename : \"%s\"", 1.32697 + pixel_type(),filename,cimg::medcon_path(),filetmp); 1.32698 + } else cimg::fclose(file); 1.32699 + cimg_std::rename(command,filename); 1.32700 + return *this; 1.32701 + } 1.32702 + 1.32703 + // Try to save the image if other extension is provided. 1.32704 + const CImg<T>& save_other(const char *const filename, const unsigned int quality=100) const { 1.32705 + if (is_empty()) 1.32706 + throw CImgInstanceException("CImg<%s>::save_other() : File '%s', instance image (%u,%u,%u,%u,%p) is empty.", 1.32707 + pixel_type(),filename?filename:"(null)",width,height,depth,dim,data); 1.32708 + if (!filename) 1.32709 + throw CImgIOException("CImg<%s>::save_other() : Instance image (%u,%u,%u,%u,%p), specified filename is (null).", 1.32710 + pixel_type()); 1.32711 + const unsigned int odebug = cimg::exception_mode(); 1.32712 + bool is_saved = true; 1.32713 + cimg::exception_mode() = 0; 1.32714 + try { save_magick(filename); } 1.32715 + catch (CImgException&) { 1.32716 + try { save_imagemagick_external(filename,quality); } 1.32717 + catch (CImgException&) { 1.32718 + try { save_graphicsmagick_external(filename,quality); } 1.32719 + catch (CImgException&) { 1.32720 + is_saved = false; 1.32721 + } 1.32722 + } 1.32723 + } 1.32724 + cimg::exception_mode() = odebug; 1.32725 + if (!is_saved) 1.32726 + throw CImgIOException("CImg<%s>::save_other() : File '%s' cannot be saved.\n" 1.32727 + "Check you have either the ImageMagick or GraphicsMagick package installed.", 1.32728 + pixel_type(),filename); 1.32729 + return *this; 1.32730 + } 1.32731 + 1.32732 + // Get a 40x38 color logo of a 'danger' item (internal). 1.32733 + static CImg<T> logo40x38() { 1.32734 + static bool first_time = true; 1.32735 + static CImg<T> res(40,38,1,3); 1.32736 + if (first_time) { 1.32737 + const unsigned char *ptrs = cimg::logo40x38; 1.32738 + T *ptr1 = res.ptr(0,0,0,0), *ptr2 = res.ptr(0,0,0,1), *ptr3 = res.ptr(0,0,0,2); 1.32739 + for (unsigned int off = 0; off<res.width*res.height;) { 1.32740 + const unsigned char n = *(ptrs++), r = *(ptrs++), g = *(ptrs++), b = *(ptrs++); 1.32741 + for (unsigned int l=0; l<n; ++off, ++l) { *(ptr1++) = (T)r; *(ptr2++) = (T)g; *(ptr3++) = (T)b; } 1.32742 + } 1.32743 + first_time = false; 1.32744 + } 1.32745 + return res; 1.32746 + } 1.32747 + 1.32748 + }; 1.32749 + 1.32750 + /* 1.32751 + #----------------------------------------- 1.32752 + # 1.32753 + # 1.32754 + # 1.32755 + # Definition of the CImgList<> structure 1.32756 + # 1.32757 + # 1.32758 + # 1.32759 + #------------------------------------------ 1.32760 + */ 1.32761 + 1.32762 + //! Class representing list of images CImg<T>. 1.32763 + template<typename T> 1.32764 + struct CImgList { 1.32765 + 1.32766 + //! Size of the list (number of elements inside). 1.32767 + unsigned int size; 1.32768 + 1.32769 + //! Allocation size of the list. 1.32770 + unsigned int allocsize; 1.32771 + 1.32772 + //! Pointer to the first list element. 1.32773 + CImg<T> *data; 1.32774 + 1.32775 + //! Define a CImgList<T>::iterator. 1.32776 + typedef CImg<T>* iterator; 1.32777 + 1.32778 + //! Define a CImgList<T>::const_iterator. 1.32779 + typedef const CImg<T>* const_iterator; 1.32780 + 1.32781 + //! Get value type. 1.32782 + typedef T value_type; 1.32783 + 1.32784 + // Define common T-dependant types. 1.32785 + typedef typename cimg::superset<T,bool>::type Tbool; 1.32786 + typedef typename cimg::superset<T,unsigned char>::type Tuchar; 1.32787 + typedef typename cimg::superset<T,char>::type Tchar; 1.32788 + typedef typename cimg::superset<T,unsigned short>::type Tushort; 1.32789 + typedef typename cimg::superset<T,short>::type Tshort; 1.32790 + typedef typename cimg::superset<T,unsigned int>::type Tuint; 1.32791 + typedef typename cimg::superset<T,int>::type Tint; 1.32792 + typedef typename cimg::superset<T,unsigned long>::type Tulong; 1.32793 + typedef typename cimg::superset<T,long>::type Tlong; 1.32794 + typedef typename cimg::superset<T,float>::type Tfloat; 1.32795 + typedef typename cimg::superset<T,double>::type Tdouble; 1.32796 + typedef typename cimg::last<T,bool>::type boolT; 1.32797 + typedef typename cimg::last<T,unsigned char>::type ucharT; 1.32798 + typedef typename cimg::last<T,char>::type charT; 1.32799 + typedef typename cimg::last<T,unsigned short>::type ushortT; 1.32800 + typedef typename cimg::last<T,short>::type shortT; 1.32801 + typedef typename cimg::last<T,unsigned int>::type uintT; 1.32802 + typedef typename cimg::last<T,int>::type intT; 1.32803 + typedef typename cimg::last<T,unsigned long>::type ulongT; 1.32804 + typedef typename cimg::last<T,long>::type longT; 1.32805 + typedef typename cimg::last<T,float>::type floatT; 1.32806 + typedef typename cimg::last<T,double>::type doubleT; 1.32807 + 1.32808 + //@} 1.32809 + //--------------------------- 1.32810 + // 1.32811 + //! \name Plugins 1.32812 + //@{ 1.32813 + //--------------------------- 1.32814 +#ifdef cimglist_plugin 1.32815 +#include cimglist_plugin 1.32816 +#endif 1.32817 +#ifdef cimglist_plugin1 1.32818 +#include cimglist_plugin1 1.32819 +#endif 1.32820 +#ifdef cimglist_plugin2 1.32821 +#include cimglist_plugin2 1.32822 +#endif 1.32823 +#ifdef cimglist_plugin3 1.32824 +#include cimglist_plugin3 1.32825 +#endif 1.32826 +#ifdef cimglist_plugin4 1.32827 +#include cimglist_plugin4 1.32828 +#endif 1.32829 +#ifdef cimglist_plugin5 1.32830 +#include cimglist_plugin5 1.32831 +#endif 1.32832 +#ifdef cimglist_plugin6 1.32833 +#include cimglist_plugin6 1.32834 +#endif 1.32835 +#ifdef cimglist_plugin7 1.32836 +#include cimglist_plugin7 1.32837 +#endif 1.32838 +#ifdef cimglist_plugin8 1.32839 +#include cimglist_plugin8 1.32840 +#endif 1.32841 + //@} 1.32842 + 1.32843 + //------------------------------------------ 1.32844 + // 1.32845 + //! \name Constructors - Destructor - Copy 1.32846 + //@{ 1.32847 + //------------------------------------------ 1.32848 + 1.32849 + //! Destructor. 1.32850 + ~CImgList() { 1.32851 + if (data) delete[] data; 1.32852 + } 1.32853 + 1.32854 + //! Default constructor. 1.32855 + CImgList(): 1.32856 + size(0),allocsize(0),data(0) {} 1.32857 + 1.32858 + //! Construct an image list containing n empty images. 1.32859 + explicit CImgList(const unsigned int n): 1.32860 + size(n) { 1.32861 + data = new CImg<T>[allocsize = cimg::max(16UL,cimg::nearest_pow2(n))]; 1.32862 + } 1.32863 + 1.32864 + //! Default copy constructor. 1.32865 + template<typename t> 1.32866 + CImgList(const CImgList<t>& list): 1.32867 + size(0),allocsize(0),data(0) { 1.32868 + assign(list.size); 1.32869 + cimglist_for(*this,l) data[l].assign(list[l],false); 1.32870 + } 1.32871 + 1.32872 + CImgList(const CImgList<T>& list): 1.32873 + size(0),allocsize(0),data(0) { 1.32874 + assign(list.size); 1.32875 + cimglist_for(*this,l) data[l].assign(list[l],list[l].is_shared); 1.32876 + } 1.32877 + 1.32878 + //! Advanced copy constructor. 1.32879 + template<typename t> 1.32880 + CImgList(const CImgList<t>& list, const bool shared): 1.32881 + size(0),allocsize(0),data(0) { 1.32882 + assign(list.size); 1.32883 + if (shared) 1.32884 + throw CImgArgumentException("CImgList<%s>::CImgList() : Cannot construct a list instance with shared images from " 1.32885 + "a CImgList<%s> (different pixel types).", 1.32886 + pixel_type(),CImgList<t>::pixel_type()); 1.32887 + cimglist_for(*this,l) data[l].assign(list[l],false); 1.32888 + } 1.32889 + 1.32890 + CImgList(const CImgList<T>& list, const bool shared): 1.32891 + size(0),allocsize(0),data(0) { 1.32892 + assign(list.size); 1.32893 + cimglist_for(*this,l) data[l].assign(list[l],shared); 1.32894 + } 1.32895 + 1.32896 + //! Construct an image list containing n images with specified size. 1.32897 + CImgList(const unsigned int n, const unsigned int width, const unsigned int height=1, 1.32898 + const unsigned int depth=1, const unsigned int dim=1): 1.32899 + size(0),allocsize(0),data(0) { 1.32900 + assign(n); 1.32901 + cimglist_for(*this,l) data[l].assign(width,height,depth,dim); 1.32902 + } 1.32903 + 1.32904 + //! Construct an image list containing n images with specified size, filled with specified value. 1.32905 + CImgList(const unsigned int n, const unsigned int width, const unsigned int height, 1.32906 + const unsigned int depth, const unsigned int dim, const T val): 1.32907 + size(0),allocsize(0),data(0) { 1.32908 + assign(n); 1.32909 + cimglist_for(*this,l) data[l].assign(width,height,depth,dim,val); 1.32910 + } 1.32911 + 1.32912 + //! Construct an image list containing n images with specified size and specified pixel values (int version). 1.32913 + CImgList(const unsigned int n, const unsigned int width, const unsigned int height, 1.32914 + const unsigned int depth, const unsigned int dim, const int val0, const int val1, ...): 1.32915 + size(0),allocsize(0),data(0) { 1.32916 +#define _CImgList_stdarg(t) { \ 1.32917 + assign(n,width,height,depth,dim); \ 1.32918 + const unsigned int siz = width*height*depth*dim, nsiz = siz*n; \ 1.32919 + T *ptrd = data->data; \ 1.32920 + va_list ap; \ 1.32921 + va_start(ap,val1); \ 1.32922 + for (unsigned int l=0, s=0, i=0; i<nsiz; ++i) { \ 1.32923 + *(ptrd++) = (T)(i==0?val0:(i==1?val1:va_arg(ap,t))); \ 1.32924 + if ((++s)==siz) { ptrd = data[++l].data; s=0; } \ 1.32925 + } \ 1.32926 + va_end(ap); \ 1.32927 + } 1.32928 + _CImgList_stdarg(int); 1.32929 + } 1.32930 + 1.32931 + //! Construct an image list containing n images with specified size and specified pixel values (double version). 1.32932 + CImgList(const unsigned int n, const unsigned int width, const unsigned int height, 1.32933 + const unsigned int depth, const unsigned int dim, const double val0, const double val1, ...): 1.32934 + size(0),allocsize(0),data(0) { 1.32935 + _CImgList_stdarg(double); 1.32936 + } 1.32937 + 1.32938 + //! Construct a list containing n copies of the image img. 1.32939 + template<typename t> 1.32940 + CImgList(const unsigned int n, const CImg<t>& img): 1.32941 + size(0),allocsize(0),data(0) { 1.32942 + assign(n); 1.32943 + cimglist_for(*this,l) data[l].assign(img,img.is_shared); 1.32944 + } 1.32945 + 1.32946 + //! Construct a list containing n copies of the image img, forcing the shared state. 1.32947 + template<typename t> 1.32948 + CImgList(const unsigned int n, const CImg<t>& img, const bool shared): 1.32949 + size(0),allocsize(0),data(0) { 1.32950 + assign(n); 1.32951 + cimglist_for(*this,l) data[l].assign(img,shared); 1.32952 + } 1.32953 + 1.32954 + //! Construct an image list from one image. 1.32955 + template<typename t> 1.32956 + explicit CImgList(const CImg<t>& img): 1.32957 + size(0),allocsize(0),data(0) { 1.32958 + assign(1); 1.32959 + data[0].assign(img,img.is_shared); 1.32960 + } 1.32961 + 1.32962 + //! Construct an image list from one image, forcing the shared state. 1.32963 + template<typename t> 1.32964 + explicit CImgList(const CImg<t>& img, const bool shared): 1.32965 + size(0),allocsize(0),data(0) { 1.32966 + assign(1); 1.32967 + data[0].assign(img,shared); 1.32968 + } 1.32969 + 1.32970 + //! Construct an image list from two images. 1.32971 + template<typename t1, typename t2> 1.32972 + CImgList(const CImg<t1>& img1, const CImg<t2>& img2): 1.32973 + size(0),allocsize(0),data(0) { 1.32974 + assign(2); 1.32975 + data[0].assign(img1,img1.is_shared); data[1].assign(img2,img2.is_shared); 1.32976 + } 1.32977 + 1.32978 + //! Construct an image list from two images, forcing the shared state. 1.32979 + template<typename t1, typename t2> 1.32980 + CImgList(const CImg<t1>& img1, const CImg<t2>& img2, const bool shared): 1.32981 + size(0),allocsize(0),data(0) { 1.32982 + assign(2); 1.32983 + data[0].assign(img1,shared); data[1].assign(img2,shared); 1.32984 + } 1.32985 + 1.32986 + //! Construct an image list from three images. 1.32987 + template<typename t1, typename t2, typename t3> 1.32988 + CImgList(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3): 1.32989 + size(0),allocsize(0),data(0) { 1.32990 + assign(3); 1.32991 + data[0].assign(img1,img1.is_shared); data[1].assign(img2,img2.is_shared); data[2].assign(img3,img3.is_shared); 1.32992 + } 1.32993 + 1.32994 + //! Construct an image list from three images, forcing the shared state. 1.32995 + template<typename t1, typename t2, typename t3> 1.32996 + CImgList(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const bool shared): 1.32997 + size(0),allocsize(0),data(0) { 1.32998 + assign(3); 1.32999 + data[0].assign(img1,shared); data[1].assign(img2,shared); data[2].assign(img3,shared); 1.33000 + } 1.33001 + 1.33002 + //! Construct an image list from four images. 1.33003 + template<typename t1, typename t2, typename t3, typename t4> 1.33004 + CImgList(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const CImg<t4>& img4): 1.33005 + size(0),allocsize(0),data(0) { 1.33006 + assign(4); 1.33007 + data[0].assign(img1,img1.is_shared); data[1].assign(img2,img2.is_shared); data[2].assign(img3,img3.is_shared); data[3].assign(img4,img4.is_shared); 1.33008 + } 1.33009 + 1.33010 + //! Construct an image list from four images, forcing the shared state. 1.33011 + template<typename t1, typename t2, typename t3, typename t4> 1.33012 + CImgList(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const CImg<t4>& img4, const bool shared): 1.33013 + size(0),allocsize(0),data(0) { 1.33014 + assign(4); 1.33015 + data[0].assign(img1,shared); data[1].assign(img2,shared); data[2].assign(img3,shared); data[3].assign(img4,shared); 1.33016 + } 1.33017 + 1.33018 + //! Construct an image list from five images. 1.33019 + template<typename t1, typename t2, typename t3, typename t4, typename t5> 1.33020 + CImgList(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const CImg<t4>& img4, 1.33021 + const CImg<t5>& img5): 1.33022 + size(0),allocsize(0),data(0) { 1.33023 + assign(5); 1.33024 + data[0].assign(img1,img1.is_shared); data[1].assign(img2,img2.is_shared); data[2].assign(img3,img3.is_shared); data[3].assign(img4,img4.is_shared); 1.33025 + data[4].assign(img5,img5.is_shared); 1.33026 + } 1.33027 + 1.33028 + //! Construct an image list from five images, forcing the shared state. 1.33029 + template<typename t1, typename t2, typename t3, typename t4, typename t5> 1.33030 + CImgList(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const CImg<t4>& img4, 1.33031 + const CImg<t5>& img5, const bool shared): 1.33032 + size(0),allocsize(0),data(0) { 1.33033 + assign(5); 1.33034 + data[0].assign(img1,shared); data[1].assign(img2,shared); data[2].assign(img3,shared); data[3].assign(img4,shared); 1.33035 + data[4].assign(img5,shared); 1.33036 + } 1.33037 + 1.33038 + //! Construct an image list from six images. 1.33039 + template<typename t1, typename t2, typename t3, typename t4, typename t5, typename t6> 1.33040 + CImgList(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const CImg<t4>& img4, 1.33041 + const CImg<t5>& img5, const CImg<t6>& img6): 1.33042 + size(0),allocsize(0),data(0) { 1.33043 + assign(6); 1.33044 + data[0].assign(img1,img1.is_shared); data[1].assign(img2,img2.is_shared); data[2].assign(img3,img3.is_shared); data[3].assign(img4,img4.is_shared); 1.33045 + data[4].assign(img5,img5.is_shared); data[5].assign(img6,img6.is_shared); 1.33046 + } 1.33047 + 1.33048 + //! Construct an image list from six images, forcing the shared state. 1.33049 + template<typename t1, typename t2, typename t3, typename t4, typename t5, typename t6> 1.33050 + CImgList(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const CImg<t4>& img4, 1.33051 + const CImg<t5>& img5, const CImg<t6>& img6, const bool shared): 1.33052 + size(0),allocsize(0),data(0) { 1.33053 + assign(6); 1.33054 + data[0].assign(img1,shared); data[1].assign(img2,shared); data[2].assign(img3,shared); data[3].assign(img4,shared); 1.33055 + data[4].assign(img5,shared); data[5].assign(img6,shared); 1.33056 + } 1.33057 + 1.33058 + //! Construct an image list from seven images. 1.33059 + template<typename t1, typename t2, typename t3, typename t4, typename t5, typename t6, typename t7> 1.33060 + CImgList(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const CImg<t4>& img4, 1.33061 + const CImg<t5>& img5, const CImg<t6>& img6, const CImg<t7>& img7): 1.33062 + size(0),allocsize(0),data(0) { 1.33063 + assign(7); 1.33064 + data[0].assign(img1,img1.is_shared); data[1].assign(img2,img2.is_shared); data[2].assign(img3,img3.is_shared); data[3].assign(img4,img4.is_shared); 1.33065 + data[4].assign(img5,img5.is_shared); data[5].assign(img6,img6.is_shared); data[6].assign(img7,img7.is_shared); 1.33066 + } 1.33067 + 1.33068 + //! Construct an image list from seven images, forcing the shared state. 1.33069 + template<typename t1, typename t2, typename t3, typename t4, typename t5, typename t6, typename t7> 1.33070 + CImgList(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const CImg<t4>& img4, 1.33071 + const CImg<t5>& img5, const CImg<t6>& img6, const CImg<t7>& img7, const bool shared): 1.33072 + size(0),allocsize(0),data(0) { 1.33073 + assign(7); 1.33074 + data[0].assign(img1,shared); data[1].assign(img2,shared); data[2].assign(img3,shared); data[3].assign(img4,shared); 1.33075 + data[4].assign(img5,shared); data[5].assign(img6,shared); data[6].assign(img7,shared); 1.33076 + } 1.33077 + 1.33078 + //! Construct an image list from eight images. 1.33079 + template<typename t1, typename t2, typename t3, typename t4, typename t5, typename t6, typename t7, typename t8> 1.33080 + CImgList(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const CImg<t4>& img4, 1.33081 + const CImg<t5>& img5, const CImg<t6>& img6, const CImg<t7>& img7, const CImg<t8>& img8): 1.33082 + size(0),allocsize(0),data(0) { 1.33083 + assign(8); 1.33084 + data[0].assign(img1,img1.is_shared); data[1].assign(img2,img2.is_shared); data[2].assign(img3,img3.is_shared); data[3].assign(img4,img4.is_shared); 1.33085 + data[4].assign(img5,img5.is_shared); data[5].assign(img6,img6.is_shared); data[6].assign(img7,img7.is_shared); data[7].assign(img8,img8.is_shared); 1.33086 + } 1.33087 + 1.33088 + //! Construct an image list from eight images, forcing the shared state. 1.33089 + template<typename t1, typename t2, typename t3, typename t4, typename t5, typename t6, typename t7, typename t8> 1.33090 + CImgList(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const CImg<t4>& img4, 1.33091 + const CImg<t5>& img5, const CImg<t6>& img6, const CImg<t7>& img7, const CImg<t8>& img8, const bool shared): 1.33092 + size(0),allocsize(0),data(0) { 1.33093 + assign(8); 1.33094 + data[0].assign(img1,shared); data[1].assign(img2,shared); data[2].assign(img3,shared); data[3].assign(img4,shared); 1.33095 + data[4].assign(img5,shared); data[5].assign(img6,shared); data[6].assign(img7,shared); data[7].assign(img8,shared); 1.33096 + } 1.33097 + 1.33098 + //! Construct an image list from a filename. 1.33099 + CImgList(const char *const filename): 1.33100 + size(0),allocsize(0),data(0) { 1.33101 + assign(filename); 1.33102 + } 1.33103 + 1.33104 + //! In-place version of the default constructor and default destructor. 1.33105 + CImgList<T>& assign() { 1.33106 + if (data) delete[] data; 1.33107 + size = allocsize = 0; 1.33108 + data = 0; 1.33109 + return *this; 1.33110 + } 1.33111 + 1.33112 + //! Equivalent to assign() (STL-compliant name). 1.33113 + CImgList<T>& clear() { 1.33114 + return assign(); 1.33115 + } 1.33116 + 1.33117 + //! In-place version of the corresponding constructor. 1.33118 + CImgList<T>& assign(const unsigned int n) { 1.33119 + if (n) { 1.33120 + if (allocsize<n || allocsize>(n<<2)) { 1.33121 + if (data) delete[] data; 1.33122 + data = new CImg<T>[allocsize=cimg::max(16UL,cimg::nearest_pow2(n))]; 1.33123 + } 1.33124 + size = n; 1.33125 + } else assign(); 1.33126 + return *this; 1.33127 + } 1.33128 + 1.33129 + //! In-place version of the corresponding constructor. 1.33130 + CImgList<T>& assign(const unsigned int n, const unsigned int width, const unsigned int height=1, 1.33131 + const unsigned int depth=1, const unsigned int dim=1) { 1.33132 + assign(n); 1.33133 + cimglist_for(*this,l) data[l].assign(width,height,depth,dim); 1.33134 + return *this; 1.33135 + } 1.33136 + 1.33137 + //! In-place version of the corresponding constructor. 1.33138 + CImgList<T>& assign(const unsigned int n, const unsigned int width, const unsigned int height, 1.33139 + const unsigned int depth, const unsigned int dim, const T val) { 1.33140 + assign(n); 1.33141 + cimglist_for(*this,l) data[l].assign(width,height,depth,dim,val); 1.33142 + return *this; 1.33143 + } 1.33144 + 1.33145 + //! In-place version of the corresponding constructor. 1.33146 + CImgList<T>& assign(const unsigned int n, const unsigned int width, const unsigned int height, 1.33147 + const unsigned int depth, const unsigned int dim, const int val0, const int val1, ...) { 1.33148 + _CImgList_stdarg(int); 1.33149 + return *this; 1.33150 + } 1.33151 + 1.33152 + //! In-place version of the corresponding constructor. 1.33153 + CImgList<T>& assign(const unsigned int n, const unsigned int width, const unsigned int height, 1.33154 + const unsigned int depth, const unsigned int dim, const double val0, const double val1, ...) { 1.33155 + _CImgList_stdarg(double); 1.33156 + return *this; 1.33157 + } 1.33158 + 1.33159 + //! In-place version of the copy constructor. 1.33160 + template<typename t> 1.33161 + CImgList<T>& assign(const CImgList<t>& list) { 1.33162 + assign(list.size); 1.33163 + cimglist_for(*this,l) data[l].assign(list[l],list[l].is_shared); 1.33164 + return *this; 1.33165 + } 1.33166 + 1.33167 + //! In-place version of the copy constructor. 1.33168 + template<typename t> 1.33169 + CImgList<T>& assign(const CImgList<t>& list, const bool shared) { 1.33170 + assign(list.size); 1.33171 + cimglist_for(*this,l) data[l].assign(list[l],shared); 1.33172 + return *this; 1.33173 + } 1.33174 + 1.33175 + //! In-place version of the corresponding constructor. 1.33176 + template<typename t> 1.33177 + CImgList<T>& assign(const unsigned int n, const CImg<t>& img, const bool shared=false) { 1.33178 + assign(n); 1.33179 + cimglist_for(*this,l) data[l].assign(img,shared); 1.33180 + return *this; 1.33181 + } 1.33182 + 1.33183 + //! In-place version of the corresponding constructor. 1.33184 + template<typename t> 1.33185 + CImgList<T>& assign(const CImg<t>& img, const bool shared=false) { 1.33186 + assign(1); 1.33187 + data[0].assign(img,shared); 1.33188 + return *this; 1.33189 + } 1.33190 + 1.33191 + //! In-place version of the corresponding constructor. 1.33192 + template<typename t1, typename t2> 1.33193 + CImgList<T>& assign(const CImg<t1>& img1, const CImg<t2>& img2, const bool shared=false) { 1.33194 + assign(2); 1.33195 + data[0].assign(img1,shared); data[1].assign(img2,shared); 1.33196 + return *this; 1.33197 + } 1.33198 + 1.33199 + //! In-place version of the corresponding constructor. 1.33200 + template<typename t1, typename t2, typename t3> 1.33201 + CImgList<T>& assign(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const bool shared=false) { 1.33202 + assign(3); 1.33203 + data[0].assign(img1,shared); data[1].assign(img2,shared); data[2].assign(img3,shared); 1.33204 + return *this; 1.33205 + } 1.33206 + 1.33207 + //! In-place version of the corresponding constructor. 1.33208 + template<typename t1, typename t2, typename t3, typename t4> 1.33209 + CImgList<T>& assign(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const CImg<t4>& img4, 1.33210 + const bool shared=false) { 1.33211 + assign(4); 1.33212 + data[0].assign(img1,shared); data[1].assign(img2,shared); data[2].assign(img3,shared); data[3].assign(img4,shared); 1.33213 + return *this; 1.33214 + } 1.33215 + 1.33216 + //! In-place version of the corresponding constructor. 1.33217 + template<typename t1, typename t2, typename t3, typename t4, typename t5> 1.33218 + CImgList<T>& assign(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const CImg<t4>& img4, 1.33219 + const CImg<t5>& img5, const bool shared=false) { 1.33220 + assign(5); 1.33221 + data[0].assign(img1,shared); data[1].assign(img2,shared); data[2].assign(img3,shared); data[3].assign(img4,shared); 1.33222 + data[4].assign(img5,shared); 1.33223 + return *this; 1.33224 + } 1.33225 + 1.33226 + //! In-place version of the corresponding constructor. 1.33227 + template<typename t1, typename t2, typename t3, typename t4, typename t5, typename t6> 1.33228 + CImgList<T>& assign(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const CImg<t4>& img4, 1.33229 + const CImg<t5>& img5, const CImg<t6>& img6, const bool shared=false) { 1.33230 + assign(6); 1.33231 + data[0].assign(img1,shared); data[1].assign(img2,shared); data[2].assign(img3,shared); data[3].assign(img4,shared); 1.33232 + data[4].assign(img5,shared); data[5].assign(img6,shared); 1.33233 + return *this; 1.33234 + } 1.33235 + 1.33236 + //! In-place version of the corresponding constructor. 1.33237 + template<typename t1, typename t2, typename t3, typename t4, typename t5, typename t6, typename t7> 1.33238 + CImgList<T>& assign(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const CImg<t4>& img4, 1.33239 + const CImg<t5>& img5, const CImg<t6>& img6, const CImg<t7>& img7, const bool shared=false) { 1.33240 + assign(7); 1.33241 + data[0].assign(img1,shared); data[1].assign(img2,shared); data[2].assign(img3,shared); data[3].assign(img4,shared); 1.33242 + data[4].assign(img5,shared); data[5].assign(img6,shared); data[6].assign(img7,shared); 1.33243 + return *this; 1.33244 + } 1.33245 + 1.33246 + //! In-place version of the corresponding constructor. 1.33247 + template<typename t1, typename t2, typename t3, typename t4, typename t5, typename t6, typename t7, typename t8> 1.33248 + CImgList<T>& assign(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const CImg<t4>& img4, 1.33249 + const CImg<t5>& img5, const CImg<t6>& img6, const CImg<t7>& img7, const CImg<t8>& img8, const bool shared=false) { 1.33250 + assign(8); 1.33251 + data[0].assign(img1,shared); data[1].assign(img2,shared); data[2].assign(img3,shared); data[3].assign(img4,shared); 1.33252 + data[4].assign(img5,shared); data[5].assign(img6,shared); data[6].assign(img7,shared); data[7].assign(img8,shared); 1.33253 + return *this; 1.33254 + } 1.33255 + 1.33256 + //! In-place version of the corresponding constructor. 1.33257 + CImgList<T>& assign(const char *const filename) { 1.33258 + return load(filename); 1.33259 + } 1.33260 + 1.33261 + //! Transfer the content of the instance image list into another one. 1.33262 + template<typename t> 1.33263 + CImgList<T>& transfer_to(CImgList<t>& list) { 1.33264 + list.assign(*this); 1.33265 + assign(); 1.33266 + return list; 1.33267 + } 1.33268 + 1.33269 + CImgList<T>& transfer_to(CImgList<T>& list) { 1.33270 + list.assign(); 1.33271 + return swap(list); 1.33272 + } 1.33273 + 1.33274 + //! Swap all fields of two CImgList instances (use with care !) 1.33275 + CImgList<T>& swap(CImgList<T>& list) { 1.33276 + cimg::swap(size,list.size); 1.33277 + cimg::swap(allocsize,list.allocsize); 1.33278 + cimg::swap(data,list.data); 1.33279 + return list; 1.33280 + } 1.33281 + 1.33282 + //! Return a string describing the type of the image pixels in the list (template parameter \p T). 1.33283 + static const char* pixel_type() { 1.33284 + return cimg::type<T>::string(); 1.33285 + } 1.33286 + 1.33287 + //! Return \p true if list is empty. 1.33288 + bool is_empty() const { 1.33289 + return (!data || !size); 1.33290 + } 1.33291 + 1.33292 + //! Return \p true if list is not empty. 1.33293 + operator bool() const { 1.33294 + return !is_empty(); 1.33295 + } 1.33296 + 1.33297 + //! Return \p true if list if of specified size. 1.33298 + bool is_sameN(const unsigned int n) const { 1.33299 + return (size==n); 1.33300 + } 1.33301 + 1.33302 + //! Return \p true if list if of specified size. 1.33303 + template<typename t> 1.33304 + bool is_sameN(const CImgList<t>& list) const { 1.33305 + return (size==list.size); 1.33306 + } 1.33307 + 1.33308 + // Define useful dimension check functions. 1.33309 + // (not documented because they are macro-generated). 1.33310 +#define _cimglist_def_is_same1(axis) \ 1.33311 + bool is_same##axis(const unsigned int val) const { \ 1.33312 + bool res = true; for (unsigned int l = 0; l<size && res; ++l) res = data[l].is_same##axis(val); return res; \ 1.33313 + } \ 1.33314 + bool is_sameN##axis(const unsigned int n, const unsigned int val) const { \ 1.33315 + return is_sameN(n) && is_same##axis(val); \ 1.33316 + } \ 1.33317 + 1.33318 +#define _cimglist_def_is_same2(axis1,axis2) \ 1.33319 + bool is_same##axis1##axis2(const unsigned int val1, const unsigned int val2) const { \ 1.33320 + bool res = true; for (unsigned int l = 0; l<size && res; ++l) res = data[l].is_same##axis1##axis2(val1,val2); return res; \ 1.33321 + } \ 1.33322 + bool is_sameN##axis1##axis2(const unsigned int n, const unsigned int val1, const unsigned int val2) const { \ 1.33323 + return is_sameN(n) && is_same##axis1##axis2(val1,val2); \ 1.33324 + } \ 1.33325 + 1.33326 +#define _cimglist_def_is_same3(axis1,axis2,axis3) \ 1.33327 + bool is_same##axis1##axis2##axis3(const unsigned int val1, const unsigned int val2, const unsigned int val3) const { \ 1.33328 + bool res = true; for (unsigned int l = 0; l<size && res; ++l) res = data[l].is_same##axis1##axis2##axis3(val1,val2,val3); return res; \ 1.33329 + } \ 1.33330 + bool is_sameN##axis1##axis2##axis3(const unsigned int n, const unsigned int val1, const unsigned int val2, const unsigned int val3) const { \ 1.33331 + return is_sameN(n) && is_same##axis1##axis2##axis3(val1,val2,val3); \ 1.33332 + } \ 1.33333 + 1.33334 +#define _cimglist_def_is_same(axis) \ 1.33335 + template<typename t> bool is_same##axis(const CImg<t>& img) const { \ 1.33336 + bool res = true; for (unsigned int l = 0; l<size && res; ++l) res = data[l].is_same##axis(img); return res; \ 1.33337 + } \ 1.33338 + template<typename t> bool is_same##axis(const CImgList<t>& list) const { \ 1.33339 + const unsigned int lmin = cimg::min(size,list.size); \ 1.33340 + bool res = true; for (unsigned int l = 0; l<lmin && res; ++l) res = data[l].is_same##axis(list[l]); return res; \ 1.33341 + } \ 1.33342 + template<typename t> bool is_sameN##axis(const unsigned int n, const CImg<t>& img) const { \ 1.33343 + return (is_sameN(n) && is_same##axis(img)); \ 1.33344 + } \ 1.33345 + template<typename t> bool is_sameN##axis(const CImgList<t>& list) const { \ 1.33346 + return (is_sameN(list) && is_same##axis(list)); \ 1.33347 + } 1.33348 + 1.33349 + _cimglist_def_is_same(XY) 1.33350 + _cimglist_def_is_same(XZ) 1.33351 + _cimglist_def_is_same(XV) 1.33352 + _cimglist_def_is_same(YZ) 1.33353 + _cimglist_def_is_same(YV) 1.33354 + _cimglist_def_is_same(XYZ) 1.33355 + _cimglist_def_is_same(XYV) 1.33356 + _cimglist_def_is_same(YZV) 1.33357 + _cimglist_def_is_same(XYZV) 1.33358 + _cimglist_def_is_same1(X) 1.33359 + _cimglist_def_is_same1(Y) 1.33360 + _cimglist_def_is_same1(Z) 1.33361 + _cimglist_def_is_same1(V) 1.33362 + _cimglist_def_is_same2(X,Y) 1.33363 + _cimglist_def_is_same2(X,Z) 1.33364 + _cimglist_def_is_same2(X,V) 1.33365 + _cimglist_def_is_same2(Y,Z) 1.33366 + _cimglist_def_is_same2(Y,V) 1.33367 + _cimglist_def_is_same2(Z,V) 1.33368 + _cimglist_def_is_same3(X,Y,Z) 1.33369 + _cimglist_def_is_same3(X,Y,V) 1.33370 + _cimglist_def_is_same3(X,Z,V) 1.33371 + _cimglist_def_is_same3(Y,Z,V) 1.33372 + 1.33373 + bool is_sameXYZV(const unsigned int dx, const unsigned int dy, const unsigned int dz, const unsigned int dv) const { 1.33374 + bool res = true; 1.33375 + for (unsigned int l = 0; l<size && res; ++l) res = data[l].is_sameXYZV(dx,dy,dz,dv); 1.33376 + return res; 1.33377 + } 1.33378 + 1.33379 + bool is_sameNXYZV(const unsigned int n, const unsigned int dx, const unsigned int dy, const unsigned int dz, const unsigned int dv) const { 1.33380 + return is_sameN(n) && is_sameXYZV(dx,dy,dz,dv); 1.33381 + } 1.33382 + 1.33383 + //! Return \c true if the list contains the pixel (n,x,y,z,v). 1.33384 + bool containsNXYZV(const int n, const int x=0, const int y=0, const int z=0, const int v=0) const { 1.33385 + if (is_empty()) return false; 1.33386 + return n>=0 && n<(int)size && x>=0 && x<data[n].dimx() && y>=0 && y<data[n].dimy() && z>=0 && z<data[n].dimz() && v>=0 && v<data[n].dimv(); 1.33387 + } 1.33388 + 1.33389 + //! Return \c true if the list contains the image (n). 1.33390 + bool containsN(const int n) const { 1.33391 + if (is_empty()) return false; 1.33392 + return n>=0 && n<(int)size; 1.33393 + } 1.33394 + 1.33395 + //! Return \c true if one of the image list contains the specified referenced value. If true, set coordinates (n,x,y,z,v). 1.33396 + template<typename t> 1.33397 + bool contains(const T& pixel, t& n, t& x, t&y, t& z, t& v) const { 1.33398 + if (is_empty()) return false; 1.33399 + cimglist_for(*this,l) if (data[l].contains(pixel,x,y,z,v)) { n = (t)l; return true; } 1.33400 + return false; 1.33401 + } 1.33402 + 1.33403 + //! Return \c true if one of the image list contains the specified referenced value. If true, set coordinates (n,x,y,z). 1.33404 + template<typename t> 1.33405 + bool contains(const T& pixel, t& n, t& x, t&y, t& z) const { 1.33406 + t v; 1.33407 + return contains(pixel,n,x,y,z,v); 1.33408 + } 1.33409 + 1.33410 + //! Return \c true if one of the image list contains the specified referenced value. If true, set coordinates (n,x,y). 1.33411 + template<typename t> 1.33412 + bool contains(const T& pixel, t& n, t& x, t&y) const { 1.33413 + t z,v; 1.33414 + return contains(pixel,n,x,y,z,v); 1.33415 + } 1.33416 + 1.33417 + //! Return \c true if one of the image list contains the specified referenced value. If true, set coordinates (n,x). 1.33418 + template<typename t> 1.33419 + bool contains(const T& pixel, t& n, t& x) const { 1.33420 + t y,z,v; 1.33421 + return contains(pixel,n,x,y,z,v); 1.33422 + } 1.33423 + 1.33424 + //! Return \c true if one of the image list contains the specified referenced value. If true, set coordinates (n). 1.33425 + template<typename t> 1.33426 + bool contains(const T& pixel, t& n) const { 1.33427 + t x,y,z,v; 1.33428 + return contains(pixel,n,x,y,z,v); 1.33429 + } 1.33430 + 1.33431 + //! Return \c true if one of the image list contains the specified referenced value. 1.33432 + bool contains(const T& pixel) const { 1.33433 + unsigned int n,x,y,z,v; 1.33434 + return contains(pixel,n,x,y,z,v); 1.33435 + } 1.33436 + 1.33437 + //! Return \c true if the list contains the image 'img'. If true, returns the position (n) of the image in the list. 1.33438 + template<typename t> 1.33439 + bool contains(const CImg<T>& img, t& n) const { 1.33440 + if (is_empty()) return false; 1.33441 + const CImg<T> *const ptr = &img; 1.33442 + cimglist_for(*this,i) if (data+i==ptr) { n = (t)i; return true; } 1.33443 + return false; 1.33444 + } 1.33445 + 1.33446 + //! Return \c true if the list contains the image img. 1.33447 + bool contains(const CImg<T>& img) const { 1.33448 + unsigned int n; 1.33449 + return contains(img,n); 1.33450 + } 1.33451 + 1.33452 + //@} 1.33453 + //------------------------------ 1.33454 + // 1.33455 + //! \name Arithmetics Operators 1.33456 + //@{ 1.33457 + //------------------------------ 1.33458 + 1.33459 + //! Assignment operator 1.33460 + template<typename t> 1.33461 + CImgList<T>& operator=(const CImgList<t>& list) { 1.33462 + return assign(list); 1.33463 + } 1.33464 + 1.33465 + CImgList<T>& operator=(const CImgList<T>& list) { 1.33466 + return assign(list); 1.33467 + } 1.33468 + 1.33469 + //! Assignment operator. 1.33470 + template<typename t> 1.33471 + CImgList<T>& operator=(const CImg<t>& img) { 1.33472 + cimglist_for(*this,l) data[l] = img; 1.33473 + return *this; 1.33474 + } 1.33475 + 1.33476 + //! Assignment operator. 1.33477 + CImgList<T>& operator=(const T val) { 1.33478 + cimglist_for(*this,l) data[l].fill(val); 1.33479 + return *this; 1.33480 + } 1.33481 + 1.33482 + //! Operator+. 1.33483 + CImgList<T> operator+() const { 1.33484 + return CImgList<T>(*this); 1.33485 + } 1.33486 + 1.33487 + //! Operator+=. 1.33488 +#ifdef cimg_use_visualcpp6 1.33489 + CImgList<T>& operator+=(const T val) 1.33490 +#else 1.33491 + template<typename t> 1.33492 + CImgList<T>& operator+=(const t val) 1.33493 +#endif 1.33494 + { 1.33495 + cimglist_for(*this,l) (*this)[l]+=val; 1.33496 + return *this; 1.33497 + } 1.33498 + 1.33499 + //! Operator+=. 1.33500 + template<typename t> 1.33501 + CImgList<T>& operator+=(const CImgList<t>& list) { 1.33502 + const unsigned int sizemax = cimg::min(size,list.size); 1.33503 + for (unsigned int l=0; l<sizemax; ++l) (*this)[l]+=list[l]; 1.33504 + return *this; 1.33505 + } 1.33506 + 1.33507 + //! Operator++ (prefix). 1.33508 + CImgList<T>& operator++() { 1.33509 + cimglist_for(*this,l) ++(*this)[l]; 1.33510 + return *this; 1.33511 + } 1.33512 + 1.33513 + //! Operator++ (postfix). 1.33514 + CImgList<T> operator++(int) { 1.33515 + CImgList<T> copy(*this); 1.33516 + ++*this; 1.33517 + return copy; 1.33518 + } 1.33519 + 1.33520 + //! Operator-. 1.33521 + CImgList<T> operator-() const { 1.33522 + CImgList<T> res(size); 1.33523 + cimglist_for(res,l) res[l].assign(-data[l]); 1.33524 + return res; 1.33525 + } 1.33526 + 1.33527 + //! Operator-=. 1.33528 +#ifdef cimg_use_visualcpp6 1.33529 + CImgList<T>& operator-=(const T val) 1.33530 +#else 1.33531 + template<typename t> 1.33532 + CImgList<T>& operator-=(const t val) 1.33533 +#endif 1.33534 + { 1.33535 + cimglist_for(*this,l) (*this)[l]-=val; 1.33536 + return *this; 1.33537 + } 1.33538 + 1.33539 + //! Operator-=. 1.33540 + template<typename t> 1.33541 + CImgList<T>& operator-=(const CImgList<t>& list) { 1.33542 + const unsigned int sizemax = min(size,list.size); 1.33543 + for (unsigned int l=0; l<sizemax; ++l) (*this)[l]-=list[l]; 1.33544 + return *this; 1.33545 + } 1.33546 + 1.33547 + //! Operator-- (prefix). 1.33548 + CImgList<T>& operator--() { 1.33549 + cimglist_for(*this,l) --(*this)[l]; 1.33550 + return *this; 1.33551 + } 1.33552 + 1.33553 + //! Operator-- (postfix). 1.33554 + CImgList<T> operator--(int) { 1.33555 + CImgList<T> copy(*this); 1.33556 + --*this; 1.33557 + return copy; 1.33558 + } 1.33559 + 1.33560 + //! Operator*=. 1.33561 +#ifdef cimg_use_visualcpp6 1.33562 + CImgList<T>& operator*=(const double val) 1.33563 +#else 1.33564 + template<typename t> 1.33565 + CImgList<T>& operator*=(const t val) 1.33566 +#endif 1.33567 + { 1.33568 + cimglist_for(*this,l) (*this)[l]*=val; 1.33569 + return *this; 1.33570 + } 1.33571 + 1.33572 + //! Operator*=. 1.33573 + template<typename t> 1.33574 + CImgList<T>& operator*=(const CImgList<t>& list) { 1.33575 + const unsigned int N = cimg::min(size,list.size); 1.33576 + for (unsigned int l=0; l<N; ++l) (*this)[l]*=list[l]; 1.33577 + return this; 1.33578 + } 1.33579 + 1.33580 + //! Operator/=. 1.33581 +#ifdef cimg_use_visualcpp6 1.33582 + CImgList<T>& operator/=(const double val) 1.33583 +#else 1.33584 + template<typename t> 1.33585 + CImgList<T>& operator/=(const t val) 1.33586 +#endif 1.33587 + { 1.33588 + cimglist_for(*this,l) (*this)[l]/=val; 1.33589 + return *this; 1.33590 + } 1.33591 + 1.33592 + //! Operator/=. 1.33593 + template<typename t> 1.33594 + CImgList<T>& operator/=(const CImgList<t>& list) { 1.33595 + const unsigned int N = cimg::min(size,list.size); 1.33596 + for (unsigned int l=0; l<N; ++l) (*this)[l]/=list[l]; 1.33597 + return this; 1.33598 + } 1.33599 + 1.33600 + //! Return a reference to the maximum pixel value of the instance list. 1.33601 + const T& max() const { 1.33602 + if (is_empty()) 1.33603 + throw CImgInstanceException("CImgList<%s>::max() : Instance image list is empty.", 1.33604 + pixel_type()); 1.33605 + const T *ptrmax = data->data; 1.33606 + T max_value = *ptrmax; 1.33607 + cimglist_for(*this,l) { 1.33608 + const CImg<T>& img = data[l]; 1.33609 + cimg_for(img,ptr,T) if ((*ptr)>max_value) max_value = *(ptrmax=ptr); 1.33610 + } 1.33611 + return *ptrmax; 1.33612 + } 1.33613 + 1.33614 + //! Return a reference to the maximum pixel value of the instance list. 1.33615 + T& max() { 1.33616 + if (is_empty()) 1.33617 + throw CImgInstanceException("CImgList<%s>::max() : Instance image list is empty.", 1.33618 + pixel_type()); 1.33619 + T *ptrmax = data->data; 1.33620 + T max_value = *ptrmax; 1.33621 + cimglist_for(*this,l) { 1.33622 + const CImg<T>& img = data[l]; 1.33623 + cimg_for(img,ptr,T) if ((*ptr)>max_value) max_value = *(ptrmax=ptr); 1.33624 + } 1.33625 + return *ptrmax; 1.33626 + } 1.33627 + 1.33628 + //! Return a reference to the minimum pixel value of the instance list. 1.33629 + const T& min() const { 1.33630 + if (is_empty()) 1.33631 + throw CImgInstanceException("CImgList<%s>::min() : Instance image list is empty.", 1.33632 + pixel_type()); 1.33633 + const T *ptrmin = data->data; 1.33634 + T min_value = *ptrmin; 1.33635 + cimglist_for(*this,l) { 1.33636 + const CImg<T>& img = data[l]; 1.33637 + cimg_for(img,ptr,T) if ((*ptr)<min_value) min_value = *(ptrmin=ptr); 1.33638 + } 1.33639 + return *ptrmin; 1.33640 + } 1.33641 + 1.33642 + //! Return a reference to the minimum pixel value of the instance list. 1.33643 + T& min() { 1.33644 + if (is_empty()) 1.33645 + throw CImgInstanceException("CImgList<%s>::min() : Instance image list is empty.", 1.33646 + pixel_type()); 1.33647 + T *ptrmin = data->data; 1.33648 + T min_value = *ptrmin; 1.33649 + cimglist_for(*this,l) { 1.33650 + const CImg<T>& img = data[l]; 1.33651 + cimg_for(img,ptr,T) if ((*ptr)<min_value) min_value = *(ptrmin=ptr); 1.33652 + } 1.33653 + return *ptrmin; 1.33654 + } 1.33655 + 1.33656 + //! Return a reference to the minimum pixel value of the instance list. 1.33657 + template<typename t> 1.33658 + const T& minmax(t& max_val) const { 1.33659 + if (is_empty()) 1.33660 + throw CImgInstanceException("CImgList<%s>::minmax() : Instance image list is empty.", 1.33661 + pixel_type()); 1.33662 + const T *ptrmin = data->data; 1.33663 + T min_value = *ptrmin, max_value = min_value; 1.33664 + cimglist_for(*this,l) { 1.33665 + const CImg<T>& img = data[l]; 1.33666 + cimg_for(img,ptr,T) { 1.33667 + const T val = *ptr; 1.33668 + if (val<min_value) { min_value = val; ptrmin = ptr; } 1.33669 + if (val>max_value) max_value = val; 1.33670 + } 1.33671 + } 1.33672 + max_val = (t)max_value; 1.33673 + return *ptrmin; 1.33674 + } 1.33675 + 1.33676 + //! Return a reference to the minimum pixel value of the instance list. 1.33677 + template<typename t> 1.33678 + T& minmax(t& max_val) { 1.33679 + if (is_empty()) 1.33680 + throw CImgInstanceException("CImgList<%s>::minmax() : Instance image list is empty.", 1.33681 + pixel_type()); 1.33682 + T *ptrmin = data->data; 1.33683 + T min_value = *ptrmin, max_value = min_value; 1.33684 + cimglist_for(*this,l) { 1.33685 + const CImg<T>& img = data[l]; 1.33686 + cimg_for(img,ptr,T) { 1.33687 + const T val = *ptr; 1.33688 + if (val<min_value) { min_value = val; ptrmin = ptr; } 1.33689 + if (val>max_value) max_value = val; 1.33690 + } 1.33691 + } 1.33692 + max_val = (t)max_value; 1.33693 + return *ptrmin; 1.33694 + } 1.33695 + 1.33696 + //! Return a reference to the minimum pixel value of the instance list. 1.33697 + template<typename t> 1.33698 + const T& maxmin(t& min_val) const { 1.33699 + if (is_empty()) 1.33700 + throw CImgInstanceException("CImgList<%s>::maxmin() : Instance image list is empty.", 1.33701 + pixel_type()); 1.33702 + const T *ptrmax = data->data; 1.33703 + T min_value = *ptrmax, max_value = min_value; 1.33704 + cimglist_for(*this,l) { 1.33705 + const CImg<T>& img = data[l]; 1.33706 + cimg_for(img,ptr,T) { 1.33707 + const T val = *ptr; 1.33708 + if (val>max_value) { max_value = val; ptrmax = ptr; } 1.33709 + if (val<min_value) min_value = val; 1.33710 + } 1.33711 + } 1.33712 + min_val = (t)min_value; 1.33713 + return *ptrmax; 1.33714 + } 1.33715 + 1.33716 + //! Return a reference to the minimum pixel value of the instance list. 1.33717 + template<typename t> 1.33718 + T& maxmin(t& min_val) { 1.33719 + if (is_empty()) 1.33720 + throw CImgInstanceException("CImgList<%s>::maxmin() : Instance image list is empty.", 1.33721 + pixel_type()); 1.33722 + T *ptrmax = data->data; 1.33723 + T min_value = *ptrmax, max_value = min_value; 1.33724 + cimglist_for(*this,l) { 1.33725 + const CImg<T>& img = data[l]; 1.33726 + cimg_for(img,ptr,T) { 1.33727 + const T val = *ptr; 1.33728 + if (val>max_value) { max_value = val; ptrmax = ptr; } 1.33729 + if (val<min_value) min_value = val; 1.33730 + } 1.33731 + } 1.33732 + min_val = (t)min_value; 1.33733 + return *ptrmax; 1.33734 + } 1.33735 + 1.33736 + //! Return the mean pixel value of the instance list. 1.33737 + double mean() const { 1.33738 + if (is_empty()) 1.33739 + throw CImgInstanceException("CImgList<%s>::mean() : Instance image list is empty.", 1.33740 + pixel_type()); 1.33741 + double val = 0; 1.33742 + unsigned int siz = 0; 1.33743 + cimglist_for(*this,l) { 1.33744 + const CImg<T>& img = data[l]; 1.33745 + cimg_for(img,ptr,T) val+=(double)*ptr; 1.33746 + siz+=img.size(); 1.33747 + } 1.33748 + return val/siz; 1.33749 + } 1.33750 + 1.33751 + //! Return the variance of the instance list. 1.33752 + double variance() { 1.33753 + if (is_empty()) 1.33754 + throw CImgInstanceException("CImgList<%s>::variance() : Instance image list is empty.", 1.33755 + pixel_type()); 1.33756 + double res = 0; 1.33757 + unsigned int siz = 0; 1.33758 + double S = 0, S2 = 0; 1.33759 + cimglist_for(*this,l) { 1.33760 + const CImg<T>& img = data[l]; 1.33761 + cimg_for(img,ptr,T) { const double val = (double)*ptr; S+=val; S2+=val*val; } 1.33762 + siz+=img.size(); 1.33763 + } 1.33764 + res = (S2 - S*S/siz)/siz; 1.33765 + return res; 1.33766 + } 1.33767 + 1.33768 + //! Compute a list of statistics vectors (min,max,mean,variance,xmin,ymin,zmin,vmin,xmax,ymax,zmax,vmax). 1.33769 + CImgList<T>& stats(const unsigned int variance_method=1) { 1.33770 + if (is_empty()) return *this; 1.33771 + cimglist_for(*this,l) data[l].stats(variance_method); 1.33772 + return *this; 1.33773 + } 1.33774 + 1.33775 + CImgList<Tfloat> get_stats(const unsigned int variance_method=1) const { 1.33776 + CImgList<Tfloat> res(size); 1.33777 + cimglist_for(*this,l) res[l] = data[l].get_stats(variance_method); 1.33778 + return res; 1.33779 + } 1.33780 + 1.33781 + //@} 1.33782 + //------------------------- 1.33783 + // 1.33784 + //! \name List Manipulation 1.33785 + //@{ 1.33786 + //------------------------- 1.33787 + 1.33788 + //! Return a reference to the i-th element of the image list. 1.33789 + CImg<T>& operator[](const unsigned int pos) { 1.33790 +#if cimg_debug>=3 1.33791 + if (pos>=size) { 1.33792 + cimg::warn("CImgList<%s>::operator[] : bad list position %u, in a list of %u images", 1.33793 + pixel_type(),pos,size); 1.33794 + return *data; 1.33795 + } 1.33796 +#endif 1.33797 + return data[pos]; 1.33798 + } 1.33799 + 1.33800 + const CImg<T>& operator[](const unsigned int pos) const { 1.33801 +#if cimg_debug>=3 1.33802 + if (pos>=size) { 1.33803 + cimg::warn("CImgList<%s>::operator[] : bad list position %u, in a list of %u images", 1.33804 + pixel_type(),pos,size); 1.33805 + return *data; 1.33806 + } 1.33807 +#endif 1.33808 + return data[pos]; 1.33809 + } 1.33810 + 1.33811 + //! Equivalent to CImgList<T>::operator[] 1.33812 + CImg<T>& operator()(const unsigned int pos) { 1.33813 + return (*this)[pos]; 1.33814 + } 1.33815 + 1.33816 + const CImg<T>& operator()(const unsigned int pos) const { 1.33817 + return (*this)[pos]; 1.33818 + } 1.33819 + 1.33820 + //! Return a reference to (x,y,z,v) pixel of the pos-th image of the list 1.33821 + T& operator()(const unsigned int pos, const unsigned int x, const unsigned int y=0, 1.33822 + const unsigned int z=0, const unsigned int v=0) { 1.33823 + return (*this)[pos](x,y,z,v); 1.33824 + } 1.33825 + const T& operator()(const unsigned int pos, const unsigned int x, const unsigned int y=0, 1.33826 + const unsigned int z=0, const unsigned int v=0) const { 1.33827 + return (*this)[pos](x,y,z,v); 1.33828 + } 1.33829 + 1.33830 + // This function is only here for template tricks. 1.33831 + T _display_object3d_at2(const int i, const int j) const { 1.33832 + return atNXY(i,0,j,0,0,0); 1.33833 + } 1.33834 + 1.33835 + //! Read an image in specified position. 1.33836 + CImg<T>& at(const int pos) { 1.33837 + if (is_empty()) 1.33838 + throw CImgInstanceException("CImgList<%s>::at() : Instance list is empty.", 1.33839 + pixel_type()); 1.33840 + return data[pos<0?0:pos>=(int)size?(int)size-1:pos]; 1.33841 + } 1.33842 + 1.33843 + //! Read a pixel value with Dirichlet boundary conditions. 1.33844 + T& atNXYZV(const int pos, const int x, const int y, const int z, const int v, const T out_val) { 1.33845 + return (pos<0 || pos>=(int)size)?(cimg::temporary(out_val)=out_val):data[pos].atXYZV(x,y,z,v,out_val); 1.33846 + } 1.33847 + 1.33848 + T atNXYZV(const int pos, const int x, const int y, const int z, const int v, const T out_val) const { 1.33849 + return (pos<0 || pos>=(int)size)?out_val:data[pos].atXYZV(x,y,z,v,out_val); 1.33850 + } 1.33851 + 1.33852 + //! Read a pixel value with Neumann boundary conditions. 1.33853 + T& atNXYZV(const int pos, const int x, const int y, const int z, const int v) { 1.33854 + if (is_empty()) 1.33855 + throw CImgInstanceException("CImgList<%s>::atNXYZV() : Instance list is empty.", 1.33856 + pixel_type()); 1.33857 + return _atNXYZV(pos,x,y,z,v); 1.33858 + } 1.33859 + 1.33860 + T atNXYZV(const int pos, const int x, const int y, const int z, const int v) const { 1.33861 + if (is_empty()) 1.33862 + throw CImgInstanceException("CImgList<%s>::atNXYZV() : Instance list is empty.", 1.33863 + pixel_type()); 1.33864 + return _atNXYZV(pos,x,y,z,v); 1.33865 + } 1.33866 + 1.33867 + T& _atNXYZV(const int pos, const int x, const int y, const int z, const int v) { 1.33868 + return data[pos<0?0:(pos>=(int)size?(int)size-1:pos)].atXYZV(x,y,z,v); 1.33869 + } 1.33870 + 1.33871 + T _atNXYZV(const int pos, const int x, const int y, const int z, const int v) const { 1.33872 + return data[pos<0?0:(pos>=(int)size?(int)size-1:pos)].atXYZV(x,y,z,v); 1.33873 + } 1.33874 + 1.33875 + //! Read a pixel value with Dirichlet boundary conditions for the four first coordinates (\c pos, \c x,\c y,\c z). 1.33876 + T& atNXYZ(const int pos, const int x, const int y, const int z, const int v, const T out_val) { 1.33877 + return (pos<0 || pos>=(int)size)?(cimg::temporary(out_val)=out_val):data[pos].atXYZ(x,y,z,v,out_val); 1.33878 + } 1.33879 + 1.33880 + T atNXYZ(const int pos, const int x, const int y, const int z, const int v, const T out_val) const { 1.33881 + return (pos<0 || pos>=(int)size)?out_val:data[pos].atXYZ(x,y,z,v,out_val); 1.33882 + } 1.33883 + 1.33884 + //! Read a pixel value with Neumann boundary conditions for the four first coordinates (\c pos, \c x,\c y,\c z). 1.33885 + T& atNXYZ(const int pos, const int x, const int y, const int z, const int v=0) { 1.33886 + if (is_empty()) 1.33887 + throw CImgInstanceException("CImgList<%s>::atNXYZ() : Instance list is empty.", 1.33888 + pixel_type()); 1.33889 + return _atNXYZ(pos,x,y,z,v); 1.33890 + } 1.33891 + 1.33892 + T atNXYZ(const int pos, const int x, const int y, const int z, const int v=0) const { 1.33893 + if (is_empty()) 1.33894 + throw CImgInstanceException("CImgList<%s>::atNXYZ() : Instance list is empty.", 1.33895 + pixel_type()); 1.33896 + return _atNXYZ(pos,x,y,z,v); 1.33897 + } 1.33898 + 1.33899 + T& _atNXYZ(const int pos, const int x, const int y, const int z, const int v=0) { 1.33900 + return data[pos<0?0:(pos>=(int)size?(int)size-1:pos)].atXYZ(x,y,z,v); 1.33901 + } 1.33902 + 1.33903 + T _atNXYZ(const int pos, const int x, const int y, const int z, const int v=0) const { 1.33904 + return data[pos<0?0:(pos>=(int)size?(int)size-1:pos)].atXYZ(x,y,z,v); 1.33905 + } 1.33906 + 1.33907 + //! Read a pixel value with Dirichlet boundary conditions for the three first coordinates (\c pos, \c x,\c y). 1.33908 + T& atNXY(const int pos, const int x, const int y, const int z, const int v, const T out_val) { 1.33909 + return (pos<0 || pos>=(int)size)?(cimg::temporary(out_val)=out_val):data[pos].atXY(x,y,z,v,out_val); 1.33910 + } 1.33911 + 1.33912 + T atNXY(const int pos, const int x, const int y, const int z, const int v, const T out_val) const { 1.33913 + return (pos<0 || pos>=(int)size)?out_val:data[pos].atXY(x,y,z,v,out_val); 1.33914 + } 1.33915 + 1.33916 + //! Read a pixel value with Neumann boundary conditions for the three first coordinates (\c pos, \c x,\c y). 1.33917 + T& atNXY(const int pos, const int x, const int y, const int z=0, const int v=0) { 1.33918 + if (is_empty()) 1.33919 + throw CImgInstanceException("CImgList<%s>::atNXY() : Instance list is empty.", 1.33920 + pixel_type()); 1.33921 + return _atNXY(pos,x,y,z,v); 1.33922 + } 1.33923 + 1.33924 + T atNXY(const int pos, const int x, const int y, const int z=0, const int v=0) const { 1.33925 + if (is_empty()) 1.33926 + throw CImgInstanceException("CImgList<%s>::atNXY() : Instance list is empty.", 1.33927 + pixel_type()); 1.33928 + return _atNXY(pos,x,y,z,v); 1.33929 + } 1.33930 + 1.33931 + T& _atNXY(const int pos, const int x, const int y, const int z=0, const int v=0) { 1.33932 + return data[pos<0?0:(pos>=(int)size?(int)size-1:pos)].atXY(x,y,z,v); 1.33933 + } 1.33934 + 1.33935 + T _atNXY(const int pos, const int x, const int y, const int z=0, const int v=0) const { 1.33936 + return data[pos<0?0:(pos>=(int)size?(int)size-1:pos)].atXY(x,y,z,v); 1.33937 + } 1.33938 + 1.33939 + //! Read a pixel value with Dirichlet boundary conditions for the two first coordinates (\c pos,\c x). 1.33940 + T& atNX(const int pos, const int x, const int y, const int z, const int v, const T out_val) { 1.33941 + return (pos<0 || pos>=(int)size)?(cimg::temporary(out_val)=out_val):data[pos].atX(x,y,z,v,out_val); 1.33942 + } 1.33943 + 1.33944 + T atNX(const int pos, const int x, const int y, const int z, const int v, const T out_val) const { 1.33945 + return (pos<0 || pos>=(int)size)?out_val:data[pos].atX(x,y,z,v,out_val); 1.33946 + } 1.33947 + 1.33948 + //! Read a pixel value with Neumann boundary conditions for the two first coordinates (\c pos, \c x). 1.33949 + T& atNX(const int pos, const int x, const int y=0, const int z=0, const int v=0) { 1.33950 + if (is_empty()) 1.33951 + throw CImgInstanceException("CImgList<%s>::atNX() : Instance list is empty.", 1.33952 + pixel_type()); 1.33953 + return _atNX(pos,x,y,z,v); 1.33954 + } 1.33955 + 1.33956 + T atNX(const int pos, const int x, const int y=0, const int z=0, const int v=0) const { 1.33957 + if (is_empty()) 1.33958 + throw CImgInstanceException("CImgList<%s>::atNX() : Instance list is empty.", 1.33959 + pixel_type()); 1.33960 + return _atNX(pos,x,y,z,v); 1.33961 + } 1.33962 + 1.33963 + T& _atNX(const int pos, const int x, const int y=0, const int z=0, const int v=0) { 1.33964 + return data[pos<0?0:(pos>=(int)size?(int)size-1:pos)].atX(x,y,z,v); 1.33965 + } 1.33966 + 1.33967 + T _atNX(const int pos, const int x, const int y=0, const int z=0, const int v=0) const { 1.33968 + return data[pos<0?0:(pos>=(int)size?(int)size-1:pos)].atX(x,y,z,v); 1.33969 + } 1.33970 + 1.33971 + //! Read a pixel value with Dirichlet boundary conditions for the first coordinates (\c pos). 1.33972 + T& atN(const int pos, const int x, const int y, const int z, const int v, const T out_val) { 1.33973 + return (pos<0 || pos>=(int)size)?(cimg::temporary(out_val)=out_val):(*this)(pos,x,y,z,v); 1.33974 + } 1.33975 + 1.33976 + T atN(const int pos, const int x, const int y, const int z, const int v, const T out_val) const { 1.33977 + return (pos<0 || pos>=(int)size)?out_val:(*this)(pos,x,y,z,v); 1.33978 + } 1.33979 + 1.33980 + //! Read a pixel value with Neumann boundary conditions for the first coordinates (\c pos). 1.33981 + T& atN(const int pos, const int x=0, const int y=0, const int z=0, const int v=0) { 1.33982 + if (is_empty()) 1.33983 + throw CImgInstanceException("CImgList<%s>::atN() : Instance list is empty.", 1.33984 + pixel_type()); 1.33985 + return _atN(pos,x,y,z,v); 1.33986 + } 1.33987 + 1.33988 + T atN(const int pos, const int x=0, const int y=0, const int z=0, const int v=0) const { 1.33989 + if (is_empty()) 1.33990 + throw CImgInstanceException("CImgList<%s>::atN() : Instance list is empty.", 1.33991 + pixel_type()); 1.33992 + return _atN(pos,x,y,z,v); 1.33993 + } 1.33994 + 1.33995 + T& _atN(const int pos, const int x=0, const int y=0, const int z=0, const int v=0) { 1.33996 + return data[pos<0?0:(pos>=(int)size?(int)size-1:pos)](x,y,z,v); 1.33997 + } 1.33998 + 1.33999 + T _atN(const int pos, const int x=0, const int y=0, const int z=0, const int v=0) const { 1.34000 + return data[pos<0?0:(pos>=(int)size?(int)size-1:pos)](x,y,z,v); 1.34001 + } 1.34002 + 1.34003 + //! Returns a reference to the last element. 1.34004 + CImg<T>& back() { 1.34005 + return (*this)(size-1); 1.34006 + } 1.34007 + 1.34008 + const CImg<T>& back() const { 1.34009 + return (*this)(size-1); 1.34010 + } 1.34011 + 1.34012 + //! Returns a reference to the first element. 1.34013 + CImg<T>& front() { 1.34014 + return *data; 1.34015 + } 1.34016 + 1.34017 + const CImg<T>& front() const { 1.34018 + return *data; 1.34019 + } 1.34020 + 1.34021 + //! Returns an iterator to the beginning of the vector. 1.34022 + iterator begin() { 1.34023 + return data; 1.34024 + } 1.34025 + 1.34026 + const_iterator begin() const { 1.34027 + return data; 1.34028 + } 1.34029 + 1.34030 + //! Return a reference to the first image. 1.34031 + const CImg<T>& first() const { 1.34032 + return *data; 1.34033 + } 1.34034 + 1.34035 + CImg<T>& first() { 1.34036 + return *data; 1.34037 + } 1.34038 + 1.34039 + //! Returns an iterator just past the last element. 1.34040 + iterator end() { 1.34041 + return data + size; 1.34042 + } 1.34043 + 1.34044 + const_iterator end() const { 1.34045 + return data + size; 1.34046 + } 1.34047 + 1.34048 + //! Return a reference to the last image. 1.34049 + const CImg<T>& last() const { 1.34050 + return data[size - 1]; 1.34051 + } 1.34052 + 1.34053 + CImg<T>& last() { 1.34054 + return data[size - 1]; 1.34055 + } 1.34056 + 1.34057 + //! Insert a copy of the image \p img into the current image list, at position \p pos. 1.34058 + template<typename t> 1.34059 + CImgList<T>& insert(const CImg<t>& img, const unsigned int pos, const bool shared) { 1.34060 + const unsigned int npos = pos==~0U?size:pos; 1.34061 + if (npos>size) 1.34062 + throw CImgArgumentException("CImgList<%s>::insert() : Cannot insert at position %u into a list with %u elements", 1.34063 + pixel_type(),npos,size); 1.34064 + if (shared) 1.34065 + throw CImgArgumentException("CImgList<%s>::insert(): Cannot insert a shared image CImg<%s> into a CImgList<%s>", 1.34066 + pixel_type(),img.pixel_type(),pixel_type()); 1.34067 + CImg<T> *new_data = (++size>allocsize)?new CImg<T>[allocsize?(allocsize<<=1):(allocsize=16)]:0; 1.34068 + if (!size || !data) { 1.34069 + data = new_data; 1.34070 + *data = img; 1.34071 + } else { 1.34072 + if (new_data) { 1.34073 + if (npos) cimg_std::memcpy(new_data,data,sizeof(CImg<T>)*npos); 1.34074 + if (npos!=size-1) cimg_std::memcpy(new_data+npos+1,data+npos,sizeof(CImg<T>)*(size-1-npos)); 1.34075 + cimg_std::memset(data,0,sizeof(CImg<T>)*(size-1)); 1.34076 + delete[] data; 1.34077 + data = new_data; 1.34078 + } 1.34079 + else if (npos!=size-1) cimg_std::memmove(data+npos+1,data+npos,sizeof(CImg<T>)*(size-1-npos)); 1.34080 + data[npos].width = data[npos].height = data[npos].depth = data[npos].dim = 0; data[npos].data = 0; 1.34081 + data[npos] = img; 1.34082 + } 1.34083 + return *this; 1.34084 + } 1.34085 + 1.34086 + CImgList<T>& insert(const CImg<T>& img, const unsigned int pos, const bool shared) { 1.34087 + const unsigned int npos = pos==~0U?size:pos; 1.34088 + if (npos>size) 1.34089 + throw CImgArgumentException("CImgList<%s>::insert() : Can't insert at position %u into a list with %u elements", 1.34090 + pixel_type(),npos,size); 1.34091 + if (&img>=data && &img<data+size) return insert(+img,pos,shared); 1.34092 + CImg<T> *new_data = (++size>allocsize)?new CImg<T>[allocsize?(allocsize<<=1):(allocsize=16)]:0; 1.34093 + if (!size || !data) { 1.34094 + data = new_data; 1.34095 + if (shared && img) { 1.34096 + data->width = img.width; data->height = img.height; data->depth = img.depth; data->dim = img.dim; 1.34097 + data->is_shared = true; data->data = img.data; 1.34098 + } else *data = img; 1.34099 + } 1.34100 + else { 1.34101 + if (new_data) { 1.34102 + if (npos) cimg_std::memcpy(new_data,data,sizeof(CImg<T>)*npos); 1.34103 + if (npos!=size-1) cimg_std::memcpy(new_data+npos+1,data+npos,sizeof(CImg<T>)*(size-1-npos)); 1.34104 + if (shared && img) { 1.34105 + new_data[npos].width = img.width; new_data[npos].height = img.height; new_data[npos].depth = img.depth; 1.34106 + new_data[npos].dim = img.dim; new_data[npos].is_shared = true; new_data[npos].data = img.data; 1.34107 + } else { 1.34108 + new_data[npos].width = new_data[npos].height = new_data[npos].depth = new_data[npos].dim = 0; new_data[npos].data = 0; 1.34109 + new_data[npos] = img; 1.34110 + } 1.34111 + cimg_std::memset(data,0,sizeof(CImg<T>)*(size-1)); 1.34112 + delete[] data; 1.34113 + data = new_data; 1.34114 + } else { 1.34115 + if (npos!=size-1) cimg_std::memmove(data+npos+1,data+npos,sizeof(CImg<T>)*(size-1-npos)); 1.34116 + if (shared && img) { 1.34117 + data[npos].width = img.width; data[npos].height = img.height; data[npos].depth = img.depth; data[npos].dim = img.dim; 1.34118 + data[npos].is_shared = true; data[npos].data = img.data; 1.34119 + } else { 1.34120 + data[npos].width = data[npos].height = data[npos].depth = data[npos].dim = 0; data[npos].data = 0; 1.34121 + data[npos] = img; 1.34122 + } 1.34123 + } 1.34124 + } 1.34125 + return *this; 1.34126 + } 1.34127 + 1.34128 + // The two functions below are necessary due to Visual C++ 6.0 function overloading bugs, when 1.34129 + // default parameters are used in function signatures. 1.34130 + template<typename t> 1.34131 + CImgList<T>& insert(const CImg<t>& img, const unsigned int pos) { 1.34132 + return insert(img,pos,false); 1.34133 + } 1.34134 + 1.34135 + //! Insert a copy of the image \p img into the current image list, at position \p pos. 1.34136 + template<typename t> 1.34137 + CImgList<T>& insert(const CImg<t>& img) { 1.34138 + return insert(img,~0U,false); 1.34139 + } 1.34140 + 1.34141 + template<typename t> 1.34142 + CImgList<T> get_insert(const CImg<t>& img, const unsigned int pos=~0U, const bool shared=false) const { 1.34143 + return (+*this).insert(img,pos,shared); 1.34144 + } 1.34145 + 1.34146 + //! Insert n empty images img into the current image list, at position \p pos. 1.34147 + CImgList<T>& insert(const unsigned int n, const unsigned int pos=~0U) { 1.34148 + CImg<T> foo; 1.34149 + if (!n) return *this; 1.34150 + const unsigned int npos = pos==~0U?size:pos; 1.34151 + for (unsigned int i=0; i<n; ++i) insert(foo,npos+i); 1.34152 + return *this; 1.34153 + } 1.34154 + 1.34155 + CImgList<T> get_insert(const unsigned int n, const unsigned int pos=~0U) const { 1.34156 + return (+*this).insert(n,pos); 1.34157 + } 1.34158 + 1.34159 + //! Insert n copies of the image \p img into the current image list, at position \p pos. 1.34160 + template<typename t> 1.34161 + CImgList<T>& insert(const unsigned int n, const CImg<t>& img, const unsigned int pos=~0U, const bool shared=false) { 1.34162 + if (!n) return *this; 1.34163 + const unsigned int npos = pos==~0U?size:pos; 1.34164 + insert(img,npos,shared); 1.34165 + for (unsigned int i=1; i<n; ++i) insert(data[npos],npos+i,shared); 1.34166 + return *this; 1.34167 + } 1.34168 + 1.34169 + template<typename t> 1.34170 + CImgList<T> get_insert(const unsigned int n, const CImg<t>& img, const unsigned int pos=~0U, const bool shared=false) const { 1.34171 + return (+*this).insert(n,img,pos,shared); 1.34172 + } 1.34173 + 1.34174 + //! Insert a copy of the image list \p list into the current image list, starting from position \p pos. 1.34175 + template<typename t> 1.34176 + CImgList<T>& insert(const CImgList<t>& list, const unsigned int pos=~0U, const bool shared=false) { 1.34177 + const unsigned int npos = pos==~0U?size:pos; 1.34178 + if ((void*)this!=(void*)&list) cimglist_for(list,l) insert(list[l],npos+l,shared); 1.34179 + else insert(CImgList<T>(list),npos,shared); 1.34180 + return *this; 1.34181 + } 1.34182 + 1.34183 + template<typename t> 1.34184 + CImgList<T> get_insert(const CImgList<t>& list, const unsigned int pos=~0U, const bool shared=false) const { 1.34185 + return (+*this).insert(list,pos,shared); 1.34186 + } 1.34187 + 1.34188 + //! Insert n copies of the list \p list at position \p pos of the current list. 1.34189 + template<typename t> 1.34190 + CImgList<T>& insert(const unsigned int n, const CImgList<t>& list, const unsigned int pos=~0U, const bool shared=false) { 1.34191 + if (!n) return *this; 1.34192 + const unsigned int npos = pos==~0U?size:pos; 1.34193 + for (unsigned int i=0; i<n; ++i) insert(list,npos,shared); 1.34194 + return *this; 1.34195 + } 1.34196 + 1.34197 + template<typename t> 1.34198 + CImgList<T> get_insert(const unsigned int n, const CImgList<t>& list, const unsigned int pos=~0U, const bool shared=false) const { 1.34199 + return (+*this).insert(n,list,pos,shared); 1.34200 + } 1.34201 + 1.34202 + //! Insert a copy of the image \p img at the end of the current image list. 1.34203 + template<typename t> 1.34204 + CImgList<T>& operator<<(const CImg<t>& img) { 1.34205 + return insert(img); 1.34206 + } 1.34207 + 1.34208 + //! Insert a copy of the image list \p list at the end of the current image list. 1.34209 + template<typename t> 1.34210 + CImgList<T>& operator<<(const CImgList<t>& list) { 1.34211 + return insert(list); 1.34212 + } 1.34213 + 1.34214 + //! Return a copy of the current image list, where the image \p img has been inserted at the end. 1.34215 + template<typename t> 1.34216 + CImgList<T>& operator>>(CImg<t>& img) const { 1.34217 + typedef typename cimg::superset<T,t>::type Tt; 1.34218 + return CImgList<Tt>(*this).insert(img); 1.34219 + } 1.34220 + 1.34221 + //! Insert a copy of the current image list at the beginning of the image list \p list. 1.34222 + template<typename t> 1.34223 + CImgList<T>& operator>>(CImgList<t>& list) const { 1.34224 + return list.insert(*this,0); 1.34225 + } 1.34226 + 1.34227 + //! Remove the images at positions \p pos1 to \p pos2 from the image list. 1.34228 + CImgList<T>& remove(const unsigned int pos1, const unsigned int pos2) { 1.34229 + const unsigned int 1.34230 + npos1 = pos1<pos2?pos1:pos2, 1.34231 + tpos2 = pos1<pos2?pos2:pos1, 1.34232 + npos2 = tpos2<size?tpos2:size-1; 1.34233 + if (npos1>=size) 1.34234 + cimg::warn("CImgList<%s>::remove() : Cannot remove images from a list (%p,%u), at positions %u->%u.", 1.34235 + pixel_type(),data,size,npos1,tpos2); 1.34236 + else { 1.34237 + if (tpos2>=size) 1.34238 + cimg::warn("CImgList<%s>::remove() : Cannot remove all images from a list (%p,%u), at positions %u->%u.", 1.34239 + pixel_type(),data,size,npos1,tpos2); 1.34240 + for (unsigned int k = npos1; k<=npos2; ++k) data[k].assign(); 1.34241 + const unsigned int nb = 1 + npos2 - npos1; 1.34242 + if (!(size-=nb)) return assign(); 1.34243 + if (size>(allocsize>>2) || allocsize<=8) { // Removing items without reallocation. 1.34244 + if (npos1!=size) cimg_std::memmove(data+npos1,data+npos2+1,sizeof(CImg<T>)*(size-npos1)); 1.34245 + cimg_std::memset(data+size,0,sizeof(CImg<T>)*nb); 1.34246 + } else { // Removing items with reallocation. 1.34247 + allocsize>>=2; 1.34248 + while (allocsize>8 && size<(allocsize>>1)) allocsize>>=1; 1.34249 + CImg<T> *new_data = new CImg<T>[allocsize]; 1.34250 + if (npos1) cimg_std::memcpy(new_data,data,sizeof(CImg<T>)*npos1); 1.34251 + if (npos1!=size) cimg_std::memcpy(new_data+npos1,data+npos2+1,sizeof(CImg<T>)*(size-npos1)); 1.34252 + if (size!=allocsize) cimg_std::memset(new_data+size,0,sizeof(allocsize-size)); 1.34253 + cimg_std::memset(data,0,sizeof(CImg<T>)*(size+nb)); 1.34254 + delete[] data; 1.34255 + data = new_data; 1.34256 + } 1.34257 + } 1.34258 + return *this; 1.34259 + } 1.34260 + 1.34261 + CImgList<T> get_remove(const unsigned int pos1, const unsigned int pos2) const { 1.34262 + return (+*this).remove(pos1,pos2); 1.34263 + } 1.34264 + 1.34265 + //! Remove the image at position \p pos from the image list. 1.34266 + CImgList<T>& remove(const unsigned int pos) { 1.34267 + return remove(pos,pos); 1.34268 + } 1.34269 + 1.34270 + CImgList<T> get_remove(const unsigned int pos) const { 1.34271 + return (+*this).remove(pos); 1.34272 + } 1.34273 + 1.34274 + //! Remove the last image from the image list. 1.34275 + CImgList<T>& remove() { 1.34276 + if (size) return remove(size-1); 1.34277 + else cimg::warn("CImgList<%s>::remove() : List is empty", 1.34278 + pixel_type()); 1.34279 + return *this; 1.34280 + } 1.34281 + 1.34282 + CImgList<T> get_remove() const { 1.34283 + return (+*this).remove(); 1.34284 + } 1.34285 + 1.34286 + //! Reverse list order. 1.34287 + CImgList<T>& reverse() { 1.34288 + for (unsigned int l=0; l<size/2; ++l) (*this)[l].swap((*this)[size-1-l]); 1.34289 + return *this; 1.34290 + } 1.34291 + 1.34292 + CImgList<T> get_reverse() const { 1.34293 + return (+*this).reverse(); 1.34294 + } 1.34295 + 1.34296 + //! Get a sub-list. 1.34297 + CImgList<T>& crop(const unsigned int i0, const unsigned int i1, const bool shared=false) { 1.34298 + return get_crop(i0,i1,shared).transfer_to(*this); 1.34299 + } 1.34300 + 1.34301 + CImgList<T> get_crop(const unsigned int i0, const unsigned int i1, const bool shared=false) const { 1.34302 + if (i0>i1 || i1>=size) 1.34303 + throw CImgArgumentException("CImgList<%s>::crop() : Cannot crop a sub-list (%u->%u) from a list (%u,%p)", 1.34304 + pixel_type(),i0,i1,size,data); 1.34305 + CImgList<T> res(i1-i0+1); 1.34306 + cimglist_for(res,l) res[l].assign((*this)[i0+l],shared); 1.34307 + return res; 1.34308 + } 1.34309 + 1.34310 + //! Get sub-images of a sublist. 1.34311 + CImgList<T>& crop(const unsigned int i0, const unsigned int i1, 1.34312 + const int x0, const int y0, const int z0, const int v0, 1.34313 + const int x1, const int y1, const int z1, const int v1) { 1.34314 + return get_crop(i0,i1,x0,y0,z0,v0,x1,y1,z1,v1).transfer_to(*this); 1.34315 + } 1.34316 + 1.34317 + CImgList<T> get_crop(const unsigned int i0, const unsigned int i1, 1.34318 + const int x0, const int y0, const int z0, const int v0, 1.34319 + const int x1, const int y1, const int z1, const int v1) const { 1.34320 + if (i0>i1 || i1>=size) 1.34321 + throw CImgArgumentException("CImgList<%s>::crop() : Cannot crop a sub-list (%u->%u) from a list (%u,%p)", 1.34322 + pixel_type(),i0,i1,size,data); 1.34323 + CImgList<T> res(i1-i0+1); 1.34324 + cimglist_for(res,l) res[l] = (*this)[i0+l].get_crop(x0,y0,z0,v0,x1,y1,z1,v1); 1.34325 + return res; 1.34326 + } 1.34327 + 1.34328 + //! Get sub-images of a sublist. 1.34329 + CImgList<T>& crop(const unsigned int i0, const unsigned int i1, 1.34330 + const int x0, const int y0, const int z0, 1.34331 + const int x1, const int y1, const int z1) { 1.34332 + return get_crop(i0,i1,x0,y0,z0,x1,y1,z1).transfer_to(*this); 1.34333 + } 1.34334 + 1.34335 + CImgList<T> get_crop(const unsigned int i0, const unsigned int i1, 1.34336 + const int x0, const int y0, const int z0, 1.34337 + const int x1, const int y1, const int z1) const { 1.34338 + if (i0>i1 || i1>=size) 1.34339 + throw CImgArgumentException("CImgList<%s>::crop() : Cannot crop a sub-list (%u->%u) from a list (%u,%p)", 1.34340 + pixel_type(),i0,i1,size,data); 1.34341 + CImgList<T> res(i1-i0+1); 1.34342 + cimglist_for(res,l) res[l] = (*this)[i0+l].get_crop(x0,y0,z0,x1,y1,z1); 1.34343 + return res; 1.34344 + } 1.34345 + 1.34346 + //! Get sub-images of a sublist. 1.34347 + CImgList<T>& crop(const unsigned int i0, const unsigned int i1, 1.34348 + const int x0, const int y0, 1.34349 + const int x1, const int y1) { 1.34350 + return get_crop(i0,i1,x0,y0,x1,y1).transfer_to(*this); 1.34351 + } 1.34352 + 1.34353 + CImgList<T> get_crop(const unsigned int i0, const unsigned int i1, 1.34354 + const int x0, const int y0, 1.34355 + const int x1, const int y1) const { 1.34356 + if (i0>i1 || i1>=size) 1.34357 + throw CImgArgumentException("CImgList<%s>::crop() : Cannot crop a sub-list (%u->%u) from a list (%u,%p)", 1.34358 + pixel_type(),i0,i1,size,data); 1.34359 + CImgList<T> res(i1-i0+1); 1.34360 + cimglist_for(res,l) res[l] = (*this)[i0+l].get_crop(x0,y0,x1,y1); 1.34361 + return res; 1.34362 + } 1.34363 + 1.34364 + //! Get sub-images of a sublist. 1.34365 + CImgList<T>& crop(const unsigned int i0, const unsigned int i1, 1.34366 + const int x0, const int x1) { 1.34367 + return get_crop(i0,i1,x0,x1).transfer_to(*this); 1.34368 + } 1.34369 + 1.34370 + CImgList<T> get_crop(const unsigned int i0, const unsigned int i1, 1.34371 + const int x0, const int x1) const { 1.34372 + if (i0>i1 || i1>=size) 1.34373 + throw CImgArgumentException("CImgList<%s>::crop() : Cannot crop a sub-list (%u->%u) from a list (%u,%p)", 1.34374 + pixel_type(),i0,i1,size,data); 1.34375 + CImgList<T> res(i1-i0+1); 1.34376 + cimglist_for(res,l) res[l] = (*this)[i0+l].get_crop(x0,x1); 1.34377 + return res; 1.34378 + } 1.34379 + 1.34380 + //! Display an image list into a CImgDisplay. 1.34381 + const CImgList<T>& operator>>(CImgDisplay& disp) const { 1.34382 + return display(disp); 1.34383 + } 1.34384 + 1.34385 + //! Insert image \p img at the end of the list. 1.34386 + template<typename t> 1.34387 + CImgList<T>& push_back(const CImg<t>& img) { 1.34388 + return insert(img); 1.34389 + } 1.34390 + 1.34391 + //! Insert image \p img at the front of the list. 1.34392 + template<typename t> 1.34393 + CImgList<T>& push_front(const CImg<t>& img) { 1.34394 + return insert(img,0); 1.34395 + } 1.34396 + 1.34397 + //! Insert list \p list at the end of the current list. 1.34398 + template<typename t> 1.34399 + CImgList<T>& push_back(const CImgList<t>& list) { 1.34400 + return insert(list); 1.34401 + } 1.34402 + 1.34403 + //! Insert list \p list at the front of the current list. 1.34404 + template<typename t> 1.34405 + CImgList<T>& push_front(const CImgList<t>& list) { 1.34406 + return insert(list,0); 1.34407 + } 1.34408 + 1.34409 + //! Remove last element of the list. 1.34410 + CImgList<T>& pop_back() { 1.34411 + return remove(size-1); 1.34412 + } 1.34413 + 1.34414 + //! Remove first element of the list. 1.34415 + CImgList<T>& pop_front() { 1.34416 + return remove(0); 1.34417 + } 1.34418 + 1.34419 + //! Remove the element pointed by iterator \p iter. 1.34420 + CImgList<T>& erase(const iterator iter) { 1.34421 + return remove(iter-data); 1.34422 + } 1.34423 + 1.34424 + //@} 1.34425 + //---------------------------- 1.34426 + // 1.34427 + //! \name Fourier Transforms 1.34428 + //@{ 1.34429 + //---------------------------- 1.34430 + 1.34431 + //! Compute the Fast Fourier Transform (along the specified axis). 1.34432 + CImgList<T>& FFT(const char axis, const bool invert=false) { 1.34433 + if (is_empty()) 1.34434 + throw CImgInstanceException("CImgList<%s>::FFT() : Instance list (%u,%p) is empty", 1.34435 + pixel_type(),size,data); 1.34436 + if (!data[0]) 1.34437 + throw CImgInstanceException("CImgList<%s>::FFT() : Real part (%u,%u,%u,%u,%p) is empty", 1.34438 + pixel_type(),data[0].width,data[0].height,data[0].depth,data[0].dim,data[0].data); 1.34439 + if (size>2) 1.34440 + cimg::warn("CImgList<%s>::FFT() : Instance list (%u,%p) have more than 2 images", 1.34441 + pixel_type(),size,data); 1.34442 + if (size==1) insert(CImg<T>(data[0].width,data[0].height,data[0].depth,data[0].dim,0)); 1.34443 + CImg<T> &Ir = data[0], &Ii = data[1]; 1.34444 + if (Ir.width!=Ii.width || Ir.height!=Ii.height || Ir.depth!=Ii.depth || Ir.dim!=Ii.dim) 1.34445 + throw CImgInstanceException("CImgList<%s>::FFT() : Real part (%u,%u,%u,%u,%p) and imaginary part (%u,%u,%u,%u,%p)" 1.34446 + "have different dimensions", 1.34447 + pixel_type(),Ir.width,Ir.height,Ir.depth,Ir.dim,Ir.data,Ii.width,Ii.height,Ii.depth,Ii.dim,Ii.data); 1.34448 + 1.34449 +#ifdef cimg_use_fftw3 1.34450 + fftw_complex *data_in; 1.34451 + fftw_plan data_plan; 1.34452 + 1.34453 + switch (cimg::uncase(axis)) { 1.34454 + case 'x' : { 1.34455 + data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*Ir.width); 1.34456 + data_plan = fftw_plan_dft_1d(Ir.width,data_in,data_in,invert?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE); 1.34457 + cimg_forYZV(Ir,y,z,k) { 1.34458 + T *ptrr = Ir.ptr(0,y,z,k), *ptri = Ii.ptr(0,y,z,k); 1.34459 + double *ptrd = (double*)data_in; 1.34460 + cimg_forX(Ir,x) { *(ptrd++) = (double)*(ptrr++); *(ptrd++) = (double)*(ptri++); } 1.34461 + fftw_execute(data_plan); 1.34462 + const unsigned int fact = Ir.width; 1.34463 + if (invert) { cimg_forX(Ir,x) { *(--ptri) = (T)(*(--ptrd)/fact); *(--ptrr) = (T)(*(--ptrd)/fact); }} 1.34464 + else { cimg_forX(Ir,x) { *(--ptri) = (T)*(--ptrd); *(--ptrr) = (T)*(--ptrd); }} 1.34465 + } 1.34466 + } break; 1.34467 + 1.34468 + case 'y' : { 1.34469 + data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * Ir.height); 1.34470 + data_plan = fftw_plan_dft_1d(Ir.height,data_in,data_in,invert?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE); 1.34471 + const unsigned int off = Ir.width; 1.34472 + cimg_forXZV(Ir,x,z,k) { 1.34473 + T *ptrr = Ir.ptr(x,0,z,k), *ptri = Ii.ptr(x,0,z,k); 1.34474 + double *ptrd = (double*)data_in; 1.34475 + cimg_forY(Ir,y) { *(ptrd++) = (double)*ptrr; *(ptrd++) = (double)*ptri; ptrr+=off; ptri+=off; } 1.34476 + fftw_execute(data_plan); 1.34477 + const unsigned int fact = Ir.height; 1.34478 + if (invert) { cimg_forY(Ir,y) { ptrr-=off; ptri-=off; *ptri = (T)(*(--ptrd)/fact); *ptrr = (T)(*(--ptrd)/fact); }} 1.34479 + else { cimg_forY(Ir,y) { ptrr-=off; ptri-=off; *ptri = (T)*(--ptrd); *ptrr = (T)*(--ptrd); }} 1.34480 + } 1.34481 + } break; 1.34482 + 1.34483 + case 'z' : { 1.34484 + data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * Ir.depth); 1.34485 + data_plan = fftw_plan_dft_1d(Ir.depth,data_in,data_in,invert?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE); 1.34486 + const unsigned int off = Ir.width*Ir.height; 1.34487 + cimg_forXYV(Ir,x,y,k) { 1.34488 + T *ptrr = Ir.ptr(x,y,0,k), *ptri = Ii.ptr(x,y,0,k); 1.34489 + double *ptrd = (double*)data_in; 1.34490 + cimg_forZ(Ir,z) { *(ptrd++) = (double)*ptrr; *(ptrd++) = (double)*ptri; ptrr+=off; ptri+=off; } 1.34491 + fftw_execute(data_plan); 1.34492 + const unsigned int fact = Ir.depth; 1.34493 + if (invert) { cimg_forZ(Ir,z) { ptrr-=off; ptri-=off; *ptri = (T)(*(--ptrd)/fact); *ptrr = (T)(*(--ptrd)/fact); }} 1.34494 + else { cimg_forZ(Ir,z) { ptrr-=off; ptri-=off; *ptri = (T)*(--ptrd); *ptrr = (T)*(--ptrd); }} 1.34495 + } 1.34496 + } break; 1.34497 + 1.34498 + case 'v' : { 1.34499 + data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * Ir.dim); 1.34500 + data_plan = fftw_plan_dft_1d(Ir.dim,data_in,data_in,invert?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE); 1.34501 + const unsigned int off = Ir.width*Ir.height*Ir.depth; 1.34502 + cimg_forXYZ(Ir,x,y,z) { 1.34503 + T *ptrr = Ir.ptr(x,y,z,0), *ptri = Ii.ptr(x,y,z,0); 1.34504 + double *ptrd = (double*)data_in; 1.34505 + cimg_forV(Ir,k) { *(ptrd++) = (double)*ptrr; *(ptrd++) = (double)*ptri; ptrr+=off; ptri+=off; } 1.34506 + fftw_execute(data_plan); 1.34507 + const unsigned int fact = Ir.dim; 1.34508 + if (invert) { cimg_forV(Ir,k) { ptrr-=off; ptri-=off; *ptri = (T)(*(--ptrd)/fact); *ptrr = (T)(*(--ptrd)/fact); }} 1.34509 + else { cimg_forV(Ir,k) { ptrr-=off; ptri-=off; *ptri = (T)*(--ptrd); *ptrr = (T)*(--ptrd); }} 1.34510 + } 1.34511 + } break; 1.34512 + } 1.34513 + 1.34514 + fftw_destroy_plan(data_plan); 1.34515 + fftw_free(data_in); 1.34516 +#else 1.34517 + switch (cimg::uncase(axis)) { 1.34518 + case 'x' : { // Fourier along X 1.34519 + const unsigned int N = Ir.width, N2 = (N>>1); 1.34520 + if (((N-1)&N) && N!=1) 1.34521 + throw CImgInstanceException("CImgList<%s>::FFT() : Dimension of instance image along 'x' is %d != 2^N", 1.34522 + pixel_type(),N); 1.34523 + for (unsigned int i=0, j=0; i<N2; ++i) { 1.34524 + if (j>i) cimg_forYZV(Ir,y,z,v) { cimg::swap(Ir(i,y,z,v),Ir(j,y,z,v)); cimg::swap(Ii(i,y,z,v),Ii(j,y,z,v)); 1.34525 + if (j<N2) { 1.34526 + const unsigned int ri = N-1-i, rj = N-1-j; 1.34527 + cimg::swap(Ir(ri,y,z,v),Ir(rj,y,z,v)); cimg::swap(Ii(ri,y,z,v),Ii(rj,y,z,v)); 1.34528 + }} 1.34529 + for (unsigned int m=N, n=N2; (j+=n)>=m; j-=m, m=n, n>>=1) {} 1.34530 + } 1.34531 + for (unsigned int delta=2; delta<=N; delta<<=1) { 1.34532 + const unsigned int delta2 = (delta>>1); 1.34533 + for (unsigned int i=0; i<N; i+=delta) { 1.34534 + float wr = 1, wi = 0; 1.34535 + const float angle = (float)((invert?+1:-1)*2*cimg::valuePI/delta), 1.34536 + ca = (float)cimg_std::cos(angle), 1.34537 + sa = (float)cimg_std::sin(angle); 1.34538 + for (unsigned int k=0; k<delta2; ++k) { 1.34539 + const unsigned int j = i + k, nj = j + delta2; 1.34540 + cimg_forYZV(Ir,y,z,k) { 1.34541 + T &ir = Ir(j,y,z,k), &ii = Ii(j,y,z,k), &nir = Ir(nj,y,z,k), &nii = Ii(nj,y,z,k); 1.34542 + const float tmpr = (float)(wr*nir - wi*nii), tmpi = (float)(wr*nii + wi*nir); 1.34543 + nir = (T)(ir - tmpr); 1.34544 + nii = (T)(ii - tmpi); 1.34545 + ir += (T)tmpr; 1.34546 + ii += (T)tmpi; 1.34547 + } 1.34548 + const float nwr = wr*ca-wi*sa; 1.34549 + wi = wi*ca + wr*sa; 1.34550 + wr = nwr; 1.34551 + } 1.34552 + } 1.34553 + } 1.34554 + if (invert) (*this)/=N; 1.34555 + } break; 1.34556 + 1.34557 + case 'y' : { // Fourier along Y 1.34558 + const unsigned int N = Ir.height, N2 = (N>>1); 1.34559 + if (((N-1)&N) && N!=1) 1.34560 + throw CImgInstanceException("CImgList<%s>::FFT() : Dimension of instance image(s) along 'y' is %d != 2^N", 1.34561 + pixel_type(),N); 1.34562 + for (unsigned int i=0, j=0; i<N2; ++i) { 1.34563 + if (j>i) cimg_forXZV(Ir,x,z,v) { cimg::swap(Ir(x,i,z,v),Ir(x,j,z,v)); cimg::swap(Ii(x,i,z,v),Ii(x,j,z,v)); 1.34564 + if (j<N2) { 1.34565 + const unsigned int ri = N-1-i, rj = N-1-j; 1.34566 + cimg::swap(Ir(x,ri,z,v),Ir(x,rj,z,v)); cimg::swap(Ii(x,ri,z,v),Ii(x,rj,z,v)); 1.34567 + }} 1.34568 + for (unsigned int m=N, n=N2; (j+=n)>=m; j-=m, m=n, n>>=1) {} 1.34569 + } 1.34570 + for (unsigned int delta=2; delta<=N; delta<<=1) { 1.34571 + const unsigned int delta2 = (delta>>1); 1.34572 + for (unsigned int i=0; i<N; i+=delta) { 1.34573 + float wr = 1, wi = 0; 1.34574 + const float angle = (float)((invert?+1:-1)*2*cimg::valuePI/delta), 1.34575 + ca = (float)cimg_std::cos(angle), sa = (float)cimg_std::sin(angle); 1.34576 + for (unsigned int k=0; k<delta2; ++k) { 1.34577 + const unsigned int j = i + k, nj = j + delta2; 1.34578 + cimg_forXZV(Ir,x,z,k) { 1.34579 + T &ir = Ir(x,j,z,k), &ii = Ii(x,j,z,k), &nir = Ir(x,nj,z,k), &nii = Ii(x,nj,z,k); 1.34580 + const float tmpr = (float)(wr*nir - wi*nii), tmpi = (float)(wr*nii + wi*nir); 1.34581 + nir = (T)(ir - tmpr); 1.34582 + nii = (T)(ii - tmpi); 1.34583 + ir += (T)tmpr; 1.34584 + ii += (T)tmpi; 1.34585 + } 1.34586 + const float nwr = wr*ca-wi*sa; 1.34587 + wi = wi*ca + wr*sa; 1.34588 + wr = nwr; 1.34589 + } 1.34590 + } 1.34591 + } 1.34592 + if (invert) (*this)/=N; 1.34593 + } break; 1.34594 + 1.34595 + case 'z' : { // Fourier along Z 1.34596 + const unsigned int N = Ir.depth, N2 = (N>>1); 1.34597 + if (((N-1)&N) && N!=1) 1.34598 + throw CImgInstanceException("CImgList<%s>::FFT() : Dimension of instance image(s) along 'z' is %d != 2^N", 1.34599 + pixel_type(),N); 1.34600 + for (unsigned int i=0, j=0; i<N2; ++i) { 1.34601 + if (j>i) cimg_forXYV(Ir,x,y,v) { cimg::swap(Ir(x,y,i,v),Ir(x,y,j,v)); cimg::swap(Ii(x,y,i,v),Ii(x,y,j,v)); 1.34602 + if (j<N2) { 1.34603 + const unsigned int ri = N-1-i, rj = N-1-j; 1.34604 + cimg::swap(Ir(x,y,ri,v),Ir(x,y,rj,v)); cimg::swap(Ii(x,y,ri,v),Ii(x,y,rj,v)); 1.34605 + }} 1.34606 + for (unsigned int m=N, n=N2; (j+=n)>=m; j-=m, m=n, n>>=1) {} 1.34607 + } 1.34608 + for (unsigned int delta=2; delta<=N; delta<<=1) { 1.34609 + const unsigned int delta2 = (delta>>1); 1.34610 + for (unsigned int i=0; i<N; i+=delta) { 1.34611 + float wr = 1, wi = 0; 1.34612 + const float angle = (float)((invert?+1:-1)*2*cimg::valuePI/delta), 1.34613 + ca = (float)cimg_std::cos(angle), sa = (float)cimg_std::sin(angle); 1.34614 + for (unsigned int k=0; k<delta2; ++k) { 1.34615 + const unsigned int j = i + k, nj = j + delta2; 1.34616 + cimg_forXYV(Ir,x,y,k) { 1.34617 + T &ir = Ir(x,y,j,k), &ii = Ii(x,y,j,k), &nir = Ir(x,y,nj,k), &nii = Ii(x,y,nj,k); 1.34618 + const float tmpr = (float)(wr*nir - wi*nii), tmpi = (float)(wr*nii + wi*nir); 1.34619 + nir = (T)(ir - tmpr); 1.34620 + nii = (T)(ii - tmpi); 1.34621 + ir += (T)tmpr; 1.34622 + ii += (T)tmpi; 1.34623 + } 1.34624 + const float nwr = wr*ca-wi*sa; 1.34625 + wi = wi*ca + wr*sa; 1.34626 + wr = nwr; 1.34627 + } 1.34628 + } 1.34629 + } 1.34630 + if (invert) (*this)/=N; 1.34631 + } break; 1.34632 + 1.34633 + default : 1.34634 + throw CImgArgumentException("CImgList<%s>::FFT() : Invalid axis '%c', must be 'x','y' or 'z'."); 1.34635 + } 1.34636 +#endif 1.34637 + return *this; 1.34638 + } 1.34639 + 1.34640 + CImgList<Tfloat> get_FFT(const char axis, const bool invert=false) const { 1.34641 + return CImgList<Tfloat>(*this).FFT(axis,invert); 1.34642 + } 1.34643 + 1.34644 + //! Compute the Fast Fourier Transform of a complex image. 1.34645 + CImgList<T>& FFT(const bool invert=false) { 1.34646 + if (is_empty()) 1.34647 + throw CImgInstanceException("CImgList<%s>::FFT() : Instance list (%u,%p) is empty", 1.34648 + pixel_type(),size,data); 1.34649 + if (size>2) 1.34650 + cimg::warn("CImgList<%s>::FFT() : Instance list (%u,%p) have more than 2 images", 1.34651 + pixel_type(),size,data); 1.34652 + if (size==1) insert(CImg<T>(data->width,data->height,data->depth,data->dim,0)); 1.34653 + CImg<T> &Ir = data[0], &Ii = data[1]; 1.34654 + if (Ii.width!=Ir.width || Ii.height!=Ir.height || Ii.depth!=Ir.depth || Ii.dim!=Ir.dim) 1.34655 + throw CImgInstanceException("CImgList<%s>::FFT() : Real (%u,%u,%u,%u,%p) and Imaginary (%u,%u,%u,%u,%p) parts " 1.34656 + "of the instance image have different dimensions", 1.34657 + pixel_type(),Ir.width,Ir.height,Ir.depth,Ir.dim,Ir.data, 1.34658 + Ii.width,Ii.height,Ii.depth,Ii.dim,Ii.data); 1.34659 +#ifdef cimg_use_fftw3 1.34660 + fftw_complex *data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * Ir.width*Ir.height*Ir.depth); 1.34661 + fftw_plan data_plan; 1.34662 + const unsigned int w = Ir.width, wh = w*Ir.height, whd = wh*Ir.depth; 1.34663 + data_plan = fftw_plan_dft_3d(Ir.width,Ir.height,Ir.depth,data_in,data_in,invert?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE); 1.34664 + cimg_forV(Ir,k) { 1.34665 + T *ptrr = Ir.ptr(0,0,0,k), *ptri = Ii.ptr(0,0,0,k); 1.34666 + double *ptrd = (double*)data_in; 1.34667 + for (unsigned int x = 0; x<Ir.width; ++x, ptrr-=wh-1, ptri-=wh-1) 1.34668 + for (unsigned int y = 0; y<Ir.height; ++y, ptrr-=whd-w, ptri-=whd-w) 1.34669 + for (unsigned int z = 0; z<Ir.depth; ++z, ptrr+=wh, ptri+=wh) { 1.34670 + *(ptrd++) = (double)*ptrr; *(ptrd++) = (double)*ptri; 1.34671 + } 1.34672 + fftw_execute(data_plan); 1.34673 + ptrd = (double*)data_in; 1.34674 + ptrr = Ir.ptr(0,0,0,k); 1.34675 + ptri = Ii.ptr(0,0,0,k); 1.34676 + if (!invert) for (unsigned int x = 0; x<Ir.width; ++x, ptrr-=wh-1, ptri-=wh-1) 1.34677 + for (unsigned int y = 0; y<Ir.height; ++y, ptrr-=whd-w, ptri-=whd-w) 1.34678 + for (unsigned int z = 0; z<Ir.depth; ++z, ptrr+=wh, ptri+=wh) { 1.34679 + *ptrr = (T)*(ptrd++); *ptri = (T)*(ptrd++); 1.34680 + } 1.34681 + else for (unsigned int x = 0; x<Ir.width; ++x, ptrr-=wh-1, ptri-=wh-1) 1.34682 + for (unsigned int y = 0; y<Ir.height; ++y, ptrr-=whd-w, ptri-=whd-w) 1.34683 + for (unsigned int z = 0; z<Ir.depth; ++z, ptrr+=wh, ptri+=wh) { 1.34684 + *ptrr = (T)(*(ptrd++)/whd); *ptri = (T)(*(ptrd++)/whd); 1.34685 + } 1.34686 + } 1.34687 + fftw_destroy_plan(data_plan); 1.34688 + fftw_free(data_in); 1.34689 +#else 1.34690 + if (Ir.depth>1) FFT('z',invert); 1.34691 + if (Ir.height>1) FFT('y',invert); 1.34692 + if (Ir.width>1) FFT('x',invert); 1.34693 +#endif 1.34694 + return *this; 1.34695 + } 1.34696 + 1.34697 + CImgList<Tfloat> get_FFT(const bool invert=false) const { 1.34698 + return CImgList<Tfloat>(*this).FFT(invert); 1.34699 + } 1.34700 + 1.34701 + // Return a list where each image has been split along the specified axis. 1.34702 + CImgList<T>& split(const char axis) { 1.34703 + return get_split(axis).transfer_to(*this); 1.34704 + } 1.34705 + 1.34706 + CImgList<T> get_split(const char axis) const { 1.34707 + CImgList<T> res; 1.34708 + cimglist_for(*this,l) { 1.34709 + CImgList<T> tmp = data[l].get_split(axis); 1.34710 + const unsigned int pos = res.size; 1.34711 + res.insert(tmp.size); 1.34712 + cimglist_for(tmp,i) tmp[i].transfer_to(data[pos+i]); 1.34713 + } 1.34714 + return res; 1.34715 + } 1.34716 + 1.34717 + //! Return a single image which is the concatenation of all images of the current CImgList instance. 1.34718 + /** 1.34719 + \param axis : specify the axis for image concatenation. Can be 'x','y','z' or 'v'. 1.34720 + \param align : specify the alignment for image concatenation. Can be 'p' (top), 'c' (center) or 'n' (bottom). 1.34721 + \return A CImg<T> image corresponding to the concatenation is returned. 1.34722 + **/ 1.34723 + CImg<T> get_append(const char axis, const char align='p') const { 1.34724 + if (is_empty()) return CImg<T>(); 1.34725 + if (size==1) return +((*this)[0]); 1.34726 + unsigned int dx = 0, dy = 0, dz = 0, dv = 0, pos = 0; 1.34727 + CImg<T> res; 1.34728 + switch (cimg::uncase(axis)) { 1.34729 + case 'x' : { 1.34730 + switch (cimg::uncase(align)) { 1.34731 + case 'x' : { dy = dz = dv = 1; cimglist_for(*this,l) dx+=(*this)[l].size(); } break; 1.34732 + case 'y' : { dx = size; dz = dv = 1; cimglist_for(*this,l) dy = cimg::max(dy,(unsigned int)(*this)[l].size()); } break; 1.34733 + case 'z' : { dx = size; dy = dv = 1; cimglist_for(*this,l) dz = cimg::max(dz,(unsigned int)(*this)[l].size()); } break; 1.34734 + case 'v' : { dx = size; dy = dz = 1; cimglist_for(*this,l) dv = cimg::max(dz,(unsigned int)(*this)[l].size()); } break; 1.34735 + default : 1.34736 + cimglist_for(*this,l) { 1.34737 + const CImg<T>& img = (*this)[l]; 1.34738 + dx += img.width; 1.34739 + dy = cimg::max(dy,img.height); 1.34740 + dz = cimg::max(dz,img.depth); 1.34741 + dv = cimg::max(dv,img.dim); 1.34742 + } 1.34743 + } 1.34744 + res.assign(dx,dy,dz,dv,0); 1.34745 + switch (cimg::uncase(align)) { 1.34746 + case 'x' : { 1.34747 + cimglist_for(*this,l) { 1.34748 + res.draw_image(pos,CImg<T>((*this)[l],true).unroll('x')); 1.34749 + pos+=(*this)[l].size(); 1.34750 + } 1.34751 + } break; 1.34752 + case 'y' : { 1.34753 + cimglist_for(*this,l) res.draw_image(pos++,CImg<T>((*this)[l],true).unroll('y')); 1.34754 + } break; 1.34755 + case 'z' : { 1.34756 + cimglist_for(*this,l) res.draw_image(pos++,CImg<T>((*this)[l],true).unroll('z')); 1.34757 + } break; 1.34758 + case 'v' : { 1.34759 + cimglist_for(*this,l) res.draw_image(pos++,CImg<T>((*this)[l],true).unroll('v')); 1.34760 + } break; 1.34761 + case 'p' : { 1.34762 + cimglist_for(*this,l) { res.draw_image(pos,(*this)[l]); pos+=(*this)[l].width; } 1.34763 + } break; 1.34764 + case 'n' : { 1.34765 + cimglist_for(*this,l) { 1.34766 + res.draw_image(pos,dy-(*this)[l].height,dz-(*this)[l].depth,dv-(*this)[l].dim,(*this)[l]); 1.34767 + pos+=(*this)[l].width; 1.34768 + } 1.34769 + } break; 1.34770 + default : { 1.34771 + cimglist_for(*this,l) { 1.34772 + res.draw_image(pos,(dy-(*this)[l].height)/2,(dz-(*this)[l].depth)/2,(dv-(*this)[l].dim)/2,(*this)[l]); 1.34773 + pos+=(*this)[l].width; 1.34774 + } 1.34775 + } break; 1.34776 + } 1.34777 + } break; 1.34778 + 1.34779 + case 'y' : { 1.34780 + switch (cimg::uncase(align)) { 1.34781 + case 'x' : { dy = size; dz = dv = 1; cimglist_for(*this,l) dx = cimg::max(dx,(unsigned int)(*this)[l].size()); } break; 1.34782 + case 'y' : { dx = dz = dv = 1; cimglist_for(*this,l) dy+=(*this)[l].size(); } break; 1.34783 + case 'z' : { dy = size; dx = dv = 1; cimglist_for(*this,l) dz = cimg::max(dz,(unsigned int)(*this)[l].size()); } break; 1.34784 + case 'v' : { dy = size; dx = dz = 1; cimglist_for(*this,l) dv = cimg::max(dv,(unsigned int)(*this)[l].size()); } break; 1.34785 + default : 1.34786 + cimglist_for(*this,l) { 1.34787 + const CImg<T>& img = (*this)[l]; 1.34788 + dx = cimg::max(dx,img.width); 1.34789 + dy += img.height; 1.34790 + dz = cimg::max(dz,img.depth); 1.34791 + dv = cimg::max(dv,img.dim); 1.34792 + } 1.34793 + } 1.34794 + res.assign(dx,dy,dz,dv,0); 1.34795 + switch (cimg::uncase(align)) { 1.34796 + case 'x' : { 1.34797 + cimglist_for(*this,l) res.draw_image(0,++pos,CImg<T>((*this)[l],true).unroll('x')); 1.34798 + } break; 1.34799 + case 'y' : { 1.34800 + cimglist_for(*this,l) { 1.34801 + res.draw_image(0,pos,CImg<T>((*this)[l],true).unroll('y')); 1.34802 + pos+=(*this)[l].size(); 1.34803 + } 1.34804 + } break; 1.34805 + case 'z' : { 1.34806 + cimglist_for(*this,l) res.draw_image(0,pos++,CImg<T>((*this)[l],true).unroll('z')); 1.34807 + } break; 1.34808 + case 'v' : { 1.34809 + cimglist_for(*this,l) res.draw_image(0,pos++,CImg<T>((*this)[l],true).unroll('v')); 1.34810 + } break; 1.34811 + case 'p' : { 1.34812 + cimglist_for(*this,l) { res.draw_image(0,pos,(*this)[l]); pos+=(*this)[l].height; } 1.34813 + } break; 1.34814 + case 'n' : { 1.34815 + cimglist_for(*this,l) { 1.34816 + res.draw_image(dx-(*this)[l].width,pos,dz-(*this)[l].depth,dv-(*this)[l].dim,(*this)[l]); 1.34817 + pos+=(*this)[l].height; 1.34818 + } 1.34819 + } break; 1.34820 + default : { 1.34821 + cimglist_for(*this,l) { 1.34822 + res.draw_image((dx-(*this)[l].width)/2,pos,(dz-(*this)[l].depth)/2,(dv-(*this)[l].dim)/2,(*this)[l]); 1.34823 + pos+=(*this)[l].height; 1.34824 + } 1.34825 + } break; 1.34826 + } 1.34827 + } break; 1.34828 + 1.34829 + case 'z' : { 1.34830 + switch (cimg::uncase(align)) { 1.34831 + case 'x' : { dz = size; dy = dv = 1; cimglist_for(*this,l) dx = cimg::max(dx,(unsigned int)(*this)[l].size()); } break; 1.34832 + case 'y' : { dz = size; dx = dv = 1; cimglist_for(*this,l) dy = cimg::max(dz,(unsigned int)(*this)[l].size()); } break; 1.34833 + case 'z' : { dx = dy = dv = 1; cimglist_for(*this,l) dz+=(*this)[l].size(); } break; 1.34834 + case 'v' : { dz = size; dx = dz = 1; cimglist_for(*this,l) dv = cimg::max(dv,(unsigned int)(*this)[l].size()); } break; 1.34835 + default : 1.34836 + cimglist_for(*this,l) { 1.34837 + const CImg<T>& img = (*this)[l]; 1.34838 + dx = cimg::max(dx,img.width); 1.34839 + dy = cimg::max(dy,img.height); 1.34840 + dz += img.depth; 1.34841 + dv = cimg::max(dv,img.dim); 1.34842 + } 1.34843 + } 1.34844 + res.assign(dx,dy,dz,dv,0); 1.34845 + switch (cimg::uncase(align)) { 1.34846 + case 'x' : { 1.34847 + cimglist_for(*this,l) res.draw_image(0,0,pos++,CImg<T>((*this)[l],true).unroll('x')); 1.34848 + } break; 1.34849 + case 'y' : { 1.34850 + cimglist_for(*this,l) res.draw_image(0,0,pos++,CImg<T>((*this)[l],true).unroll('y')); 1.34851 + } break; 1.34852 + case 'z' : { 1.34853 + cimglist_for(*this,l) { 1.34854 + res.draw_image(0,0,pos,CImg<T>((*this)[l],true).unroll('z')); 1.34855 + pos+=(*this)[l].size(); 1.34856 + } 1.34857 + } break; 1.34858 + case 'v' : { 1.34859 + cimglist_for(*this,l) res.draw_image(0,0,pos++,CImg<T>((*this)[l],true).unroll('v')); 1.34860 + } break; 1.34861 + case 'p' : { 1.34862 + cimglist_for(*this,l) { res.draw_image(0,0,pos,(*this)[l]); pos+=(*this)[l].depth; } 1.34863 + } break; 1.34864 + case 'n' : { 1.34865 + cimglist_for(*this,l) { 1.34866 + res.draw_image(dx-(*this)[l].width,dy-(*this)[l].height,pos,dv-(*this)[l].dim,(*this)[l]); 1.34867 + pos+=(*this)[l].depth; 1.34868 + } 1.34869 + } break; 1.34870 + case 'c' : { 1.34871 + cimglist_for(*this,l) { 1.34872 + res.draw_image((dx-(*this)[l].width)/2,(dy-(*this)[l].height)/2,pos,(dv-(*this)[l].dim)/2,(*this)[l]); 1.34873 + pos+=(*this)[l].depth; 1.34874 + } 1.34875 + } break; 1.34876 + } 1.34877 + } break; 1.34878 + 1.34879 + case 'v' : { 1.34880 + switch (cimg::uncase(align)) { 1.34881 + case 'x' : { dv = size; dy = dv = 1; cimglist_for(*this,l) dx = cimg::max(dx,(unsigned int)(*this)[l].size()); } break; 1.34882 + case 'y' : { dv = size; dx = dv = 1; cimglist_for(*this,l) dy = cimg::max(dz,(unsigned int)(*this)[l].size()); } break; 1.34883 + case 'z' : { dv = size; dx = dv = 1; cimglist_for(*this,l) dz = cimg::max(dv,(unsigned int)(*this)[l].size()); } break; 1.34884 + case 'v' : { dx = dy = dz = 1; cimglist_for(*this,l) dv+=(*this)[l].size(); } break; 1.34885 + default : 1.34886 + cimglist_for(*this,l) { 1.34887 + const CImg<T>& img = (*this)[l]; 1.34888 + dx = cimg::max(dx,img.width); 1.34889 + dy = cimg::max(dy,img.height); 1.34890 + dz = cimg::max(dz,img.depth); 1.34891 + dv += img.dim; 1.34892 + } 1.34893 + } 1.34894 + res.assign(dx,dy,dz,dv,0); 1.34895 + switch (cimg::uncase(align)) { 1.34896 + case 'x' : { 1.34897 + cimglist_for(*this,l) res.draw_image(0,0,0,pos++,CImg<T>((*this)[l],true).unroll('x')); 1.34898 + } break; 1.34899 + case 'y' : { 1.34900 + cimglist_for(*this,l) res.draw_image(0,0,0,pos++,CImg<T>((*this)[l],true).unroll('y')); 1.34901 + } break; 1.34902 + case 'z' : { 1.34903 + cimglist_for(*this,l) res.draw_image(0,0,0,pos++,CImg<T>((*this)[l],true).unroll('v')); 1.34904 + } break; 1.34905 + case 'v' : { 1.34906 + cimglist_for(*this,l) { 1.34907 + res.draw_image(0,0,0,pos,CImg<T>((*this)[l],true).unroll('z')); 1.34908 + pos+=(*this)[l].size(); 1.34909 + } 1.34910 + } break; 1.34911 + case 'p' : { 1.34912 + cimglist_for(*this,l) { res.draw_image(0,0,0,pos,(*this)[l]); pos+=(*this)[l].dim; } 1.34913 + } break; 1.34914 + case 'n' : { 1.34915 + cimglist_for(*this,l) { 1.34916 + res.draw_image(dx-(*this)[l].width,dy-(*this)[l].height,dz-(*this)[l].depth,pos,(*this)[l]); 1.34917 + pos+=(*this)[l].dim; 1.34918 + } 1.34919 + } break; 1.34920 + case 'c' : { 1.34921 + cimglist_for(*this,l) { 1.34922 + res.draw_image((dx-(*this)[l].width)/2,(dy-(*this)[l].height)/2,(dz-(*this)[l].depth)/2,pos,(*this)[l]); 1.34923 + pos+=(*this)[l].dim; 1.34924 + } 1.34925 + } break; 1.34926 + } 1.34927 + } break; 1.34928 + default : 1.34929 + throw CImgArgumentException("CImgList<%s>::get_append() : unknow axis '%c', must be 'x','y','z' or 'v'", 1.34930 + pixel_type(),axis); 1.34931 + } 1.34932 + return res; 1.34933 + } 1.34934 + 1.34935 + //! Create an auto-cropped font (along the X axis) from a input font \p font. 1.34936 + CImgList<T>& crop_font() { 1.34937 + return get_crop_font().transfer_to(*this); 1.34938 + } 1.34939 + 1.34940 + CImgList<T> get_crop_font() const { 1.34941 + CImgList<T> res; 1.34942 + cimglist_for(*this,l) { 1.34943 + const CImg<T>& letter = (*this)[l]; 1.34944 + int xmin = letter.width, xmax = 0; 1.34945 + cimg_forXY(letter,x,y) if (letter(x,y)) { if (x<xmin) xmin=x; if (x>xmax) xmax=x; } 1.34946 + if (xmin>xmax) res.insert(CImg<T>(letter.width,letter.height,1,letter.dim,0)); 1.34947 + else res.insert(letter.get_crop(xmin,0,xmax,letter.height-1)); 1.34948 + } 1.34949 + res[' '].resize(res['f'].width); 1.34950 + res[' '+256].resize(res['f'].width); 1.34951 + return res; 1.34952 + } 1.34953 + 1.34954 + //! Invert primitives orientation of a 3D object. 1.34955 + CImgList<T>& invert_object3d() { 1.34956 + cimglist_for(*this,l) { 1.34957 + CImg<T>& p = data[l]; 1.34958 + const unsigned int siz = p.size(); 1.34959 + if (siz==2 || siz==3 || siz==6 || siz==9) cimg::swap(p[0],p[1]); 1.34960 + else if (siz==4 || siz==12) cimg::swap(p[0],p[3],p[1],p[2]); 1.34961 + } 1.34962 + return *this; 1.34963 + } 1.34964 + 1.34965 + CImgList<T> get_invert_object3d() const { 1.34966 + return (+*this).invert_object3d(); 1.34967 + } 1.34968 + 1.34969 + //! Return a CImg pre-defined font with desired size. 1.34970 + /** 1.34971 + \param font_height = height of the desired font (can be 11,13,24,38 or 57) 1.34972 + \param fixed_size = tell if the font has a fixed or variable width. 1.34973 + **/ 1.34974 + static CImgList<T> font(const unsigned int font_width, const bool variable_size=true) { 1.34975 + if (font_width<=11) { 1.34976 + static CImgList<T> font7x11, nfont7x11; 1.34977 + if (!variable_size && !font7x11) font7x11 = _font(cimg::font7x11,7,11,1,0,false); 1.34978 + if (variable_size && !nfont7x11) nfont7x11 = _font(cimg::font7x11,7,11,1,0,true); 1.34979 + return variable_size?nfont7x11:font7x11; 1.34980 + } 1.34981 + if (font_width<=13) { 1.34982 + static CImgList<T> font10x13, nfont10x13; 1.34983 + if (!variable_size && !font10x13) font10x13 = _font(cimg::font10x13,10,13,1,0,false); 1.34984 + if (variable_size && !nfont10x13) nfont10x13 = _font(cimg::font10x13,10,13,1,0,true); 1.34985 + return variable_size?nfont10x13:font10x13; 1.34986 + } 1.34987 + if (font_width<=17) { 1.34988 + static CImgList<T> font8x17, nfont8x17; 1.34989 + if (!variable_size && !font8x17) font8x17 = _font(cimg::font8x17,8,17,1,0,false); 1.34990 + if (variable_size && !nfont8x17) nfont8x17 = _font(cimg::font8x17,8,17,1,0,true); 1.34991 + return variable_size?nfont8x17:font8x17; 1.34992 + } 1.34993 + if (font_width<=19) { 1.34994 + static CImgList<T> font10x19, nfont10x19; 1.34995 + if (!variable_size && !font10x19) font10x19 = _font(cimg::font10x19,10,19,2,0,false); 1.34996 + if (variable_size && !nfont10x19) nfont10x19 = _font(cimg::font10x19,10,19,2,0,true); 1.34997 + return variable_size?nfont10x19:font10x19; 1.34998 + } 1.34999 + if (font_width<=24) { 1.35000 + static CImgList<T> font12x24, nfont12x24; 1.35001 + if (!variable_size && !font12x24) font12x24 = _font(cimg::font12x24,12,24,2,0,false); 1.35002 + if (variable_size && !nfont12x24) nfont12x24 = _font(cimg::font12x24,12,24,2,0,true); 1.35003 + return variable_size?nfont12x24:font12x24; 1.35004 + } 1.35005 + if (font_width<=32) { 1.35006 + static CImgList<T> font16x32, nfont16x32; 1.35007 + if (!variable_size && !font16x32) font16x32 = _font(cimg::font16x32,16,32,2,0,false); 1.35008 + if (variable_size && !nfont16x32) nfont16x32 = _font(cimg::font16x32,16,32,2,0,true); 1.35009 + return variable_size?nfont16x32:font16x32; 1.35010 + } 1.35011 + if (font_width<=38) { 1.35012 + static CImgList<T> font19x38, nfont19x38; 1.35013 + if (!variable_size && !font19x38) font19x38 = _font(cimg::font19x38,19,38,3,0,false); 1.35014 + if (variable_size && !nfont19x38) nfont19x38 = _font(cimg::font19x38,19,38,3,0,true); 1.35015 + return variable_size?nfont19x38:font19x38; 1.35016 + } 1.35017 + static CImgList<T> font29x57, nfont29x57; 1.35018 + if (!variable_size && !font29x57) font29x57 = _font(cimg::font29x57,29,57,5,0,false); 1.35019 + if (variable_size && !nfont29x57) nfont29x57 = _font(cimg::font29x57,29,57,5,0,true); 1.35020 + return variable_size?nfont29x57:font29x57; 1.35021 + } 1.35022 + 1.35023 + static CImgList<T> _font(const unsigned int *const font, const unsigned int w, const unsigned int h, 1.35024 + const unsigned int paddingx, const unsigned int paddingy, const bool variable_size=true) { 1.35025 + CImgList<T> res = CImgList<T>(256,w,h,1,3).insert(CImgList<T>(256,w,h,1,1)); 1.35026 + const unsigned int *ptr = font; 1.35027 + unsigned int m = 0, val = 0; 1.35028 + for (unsigned int y=0; y<h; ++y) 1.35029 + for (unsigned int x=0; x<256*w; ++x) { 1.35030 + m>>=1; if (!m) { m = 0x80000000; val = *(ptr++); } 1.35031 + CImg<T>& img = res[x/w], &mask = res[x/w+256]; 1.35032 + unsigned int xm = x%w; 1.35033 + img(xm,y,0) = img(xm,y,1) = img(xm,y,2) = mask(xm,y,0) = (T)((val&m)?1:0); 1.35034 + } 1.35035 + if (variable_size) res.crop_font(); 1.35036 + if (paddingx || paddingy) cimglist_for(res,l) res[l].resize(res[l].dimx()+paddingx, res[l].dimy()+paddingy,1,-100,0); 1.35037 + return res; 1.35038 + } 1.35039 + 1.35040 + //! Display the current CImgList instance in an existing CImgDisplay window (by reference). 1.35041 + /** 1.35042 + This function displays the list images of the current CImgList instance into an existing CImgDisplay window. 1.35043 + Images of the list are concatenated in a single temporarly image for visualization purposes. 1.35044 + The function returns immediately. 1.35045 + \param disp : reference to an existing CImgDisplay instance, where the current image list will be displayed. 1.35046 + \param axis : specify the axis for image concatenation. Can be 'x','y','z' or 'v'. 1.35047 + \param align : specify the alignment for image concatenation. Can be 'p' (top), 'c' (center) or 'n' (bottom). 1.35048 + \return A reference to the current CImgList instance is returned. 1.35049 + **/ 1.35050 + const CImgList<T>& display(CImgDisplay& disp, const char axis='x', const char align='p') const { 1.35051 + get_append(axis,align).display(disp); 1.35052 + return *this; 1.35053 + } 1.35054 + 1.35055 + //! Display the current CImgList instance in a new display window. 1.35056 + /** 1.35057 + This function opens a new window with a specific title and displays the list images of the current CImgList instance into it. 1.35058 + Images of the list are concatenated in a single temporarly image for visualization purposes. 1.35059 + The function returns when a key is pressed or the display window is closed by the user. 1.35060 + \param title : specify the title of the opening display window. 1.35061 + \param axis : specify the axis for image concatenation. Can be 'x','y','z' or 'v'. 1.35062 + \param align : specify the alignment for image concatenation. Can be 'p' (top), 'c' (center) or 'n' (bottom). 1.35063 + \return A reference to the current CImgList instance is returned. 1.35064 + **/ 1.35065 + const CImgList<T>& display(CImgDisplay &disp, 1.35066 + const bool display_info, const char axis='x', const char align='p') const { 1.35067 + if (is_empty()) 1.35068 + throw CImgInstanceException("CImgList<%s>::display() : Instance list (%u,%u) is empty.", 1.35069 + pixel_type(),size,data); 1.35070 + const CImg<T> visu = get_append(axis,align); 1.35071 + if (display_info) print(disp.title); 1.35072 + visu.display(disp,false); 1.35073 + return *this; 1.35074 + } 1.35075 + 1.35076 + //! Display the current CImgList instance in a new display window. 1.35077 + const CImgList<T>& display(const char *const title=0, 1.35078 + const bool display_info=true, const char axis='x', const char align='p') const { 1.35079 + const CImg<T> visu = get_append(axis,align); 1.35080 + char ntitle[64] = { 0 }; 1.35081 + if (!title) cimg_std::sprintf(ntitle,"CImgList<%s>",pixel_type()); 1.35082 + if (display_info) print(title?title:ntitle); 1.35083 + visu.display(title?title:ntitle,false); 1.35084 + return *this; 1.35085 + } 1.35086 + 1.35087 + //@} 1.35088 + //---------------------------------- 1.35089 + // 1.35090 + //! \name Input-Output 1.35091 + //@{ 1.35092 + //---------------------------------- 1.35093 + 1.35094 + //! Return a C-string containing the values of all images in the instance list. 1.35095 + CImg<charT> value_string(const char separator=',', const unsigned int max_size=0) const { 1.35096 + if (is_empty()) return CImg<ucharT>(1,1,1,1,0); 1.35097 + CImgList<charT> items; 1.35098 + for (unsigned int l = 0; l<size-1; ++l) { 1.35099 + CImg<charT> item = data[l].value_string(separator,0); 1.35100 + item[item.size()-1] = separator; 1.35101 + items.insert(item); 1.35102 + } 1.35103 + items.insert(data[size-1].value_string(separator,0)); 1.35104 + CImg<charT> res = items.get_append('x'); 1.35105 + if (max_size) { res.crop(0,max_size); res(max_size) = 0; } 1.35106 + return res; 1.35107 + } 1.35108 + 1.35109 + //! Print informations about the list on the standard output. 1.35110 + const CImgList<T>& print(const char* title=0, const bool display_stats=true) const { 1.35111 + unsigned long msiz = 0; 1.35112 + cimglist_for(*this,l) msiz += data[l].size(); 1.35113 + msiz*=sizeof(T); 1.35114 + const unsigned int mdisp = msiz<8*1024?0:(msiz<8*1024*1024?1:2); 1.35115 + char ntitle[64] = { 0 }; 1.35116 + if (!title) cimg_std::sprintf(ntitle,"CImgList<%s>",pixel_type()); 1.35117 + cimg_std::fprintf(cimg_stdout,"%s: this = %p, size = %u [%lu %s], data = (CImg<%s>*)%p.\n", 1.35118 + title?title:ntitle,(void*)this,size, 1.35119 + mdisp==0?msiz:(mdisp==1?(msiz>>10):(msiz>>20)), 1.35120 + mdisp==0?"b":(mdisp==1?"Kb":"Mb"), 1.35121 + pixel_type(),(void*)data); 1.35122 + char tmp[16] = { 0 }; 1.35123 + cimglist_for(*this,ll) { 1.35124 + cimg_std::sprintf(tmp,"[%d]",ll); 1.35125 + cimg_std::fprintf(cimg_stdout," "); 1.35126 + data[ll].print(tmp,display_stats); 1.35127 + if (ll==3 && size>8) { ll = size-5; cimg_std::fprintf(cimg_stdout," ...\n"); } 1.35128 + } 1.35129 + return *this; 1.35130 + } 1.35131 + 1.35132 + //! Load an image list from a file. 1.35133 + CImgList<T>& load(const char *const filename) { 1.35134 + const char *ext = cimg::split_filename(filename); 1.35135 + const unsigned int odebug = cimg::exception_mode(); 1.35136 + cimg::exception_mode() = 0; 1.35137 + assign(); 1.35138 + try { 1.35139 +#ifdef cimglist_load_plugin 1.35140 + cimglist_load_plugin(filename); 1.35141 +#endif 1.35142 +#ifdef cimglist_load_plugin1 1.35143 + cimglist_load_plugin1(filename); 1.35144 +#endif 1.35145 +#ifdef cimglist_load_plugin2 1.35146 + cimglist_load_plugin2(filename); 1.35147 +#endif 1.35148 +#ifdef cimglist_load_plugin3 1.35149 + cimglist_load_plugin3(filename); 1.35150 +#endif 1.35151 +#ifdef cimglist_load_plugin4 1.35152 + cimglist_load_plugin4(filename); 1.35153 +#endif 1.35154 +#ifdef cimglist_load_plugin5 1.35155 + cimglist_load_plugin5(filename); 1.35156 +#endif 1.35157 +#ifdef cimglist_load_plugin6 1.35158 + cimglist_load_plugin6(filename); 1.35159 +#endif 1.35160 +#ifdef cimglist_load_plugin7 1.35161 + cimglist_load_plugin7(filename); 1.35162 +#endif 1.35163 +#ifdef cimglist_load_plugin8 1.35164 + cimglist_load_plugin8(filename); 1.35165 +#endif 1.35166 + if (!cimg::strcasecmp(ext,"tif") || 1.35167 + !cimg::strcasecmp(ext,"tiff")) load_tiff(filename); 1.35168 + if (!cimg::strcasecmp(ext,"cimg") || 1.35169 + !cimg::strcasecmp(ext,"cimgz") || 1.35170 + !ext[0]) load_cimg(filename); 1.35171 + if (!cimg::strcasecmp(ext,"rec") || 1.35172 + !cimg::strcasecmp(ext,"par")) load_parrec(filename); 1.35173 + if (!cimg::strcasecmp(ext,"avi") || 1.35174 + !cimg::strcasecmp(ext,"mov") || 1.35175 + !cimg::strcasecmp(ext,"asf") || 1.35176 + !cimg::strcasecmp(ext,"divx") || 1.35177 + !cimg::strcasecmp(ext,"flv") || 1.35178 + !cimg::strcasecmp(ext,"mpg") || 1.35179 + !cimg::strcasecmp(ext,"m1v") || 1.35180 + !cimg::strcasecmp(ext,"m2v") || 1.35181 + !cimg::strcasecmp(ext,"m4v") || 1.35182 + !cimg::strcasecmp(ext,"mjp") || 1.35183 + !cimg::strcasecmp(ext,"mkv") || 1.35184 + !cimg::strcasecmp(ext,"mpe") || 1.35185 + !cimg::strcasecmp(ext,"movie") || 1.35186 + !cimg::strcasecmp(ext,"ogm") || 1.35187 + !cimg::strcasecmp(ext,"qt") || 1.35188 + !cimg::strcasecmp(ext,"rm") || 1.35189 + !cimg::strcasecmp(ext,"vob") || 1.35190 + !cimg::strcasecmp(ext,"wmv") || 1.35191 + !cimg::strcasecmp(ext,"xvid") || 1.35192 + !cimg::strcasecmp(ext,"mpeg")) load_ffmpeg(filename); 1.35193 + if (!cimg::strcasecmp(ext,"gz")) load_gzip_external(filename); 1.35194 + if (is_empty()) throw CImgIOException("CImgList<%s>::load()",pixel_type()); 1.35195 + } catch (CImgIOException& e) { 1.35196 + if (!cimg::strncasecmp(e.message,"cimg::fopen()",13)) { 1.35197 + cimg::exception_mode() = odebug; 1.35198 + throw CImgIOException("CImgList<%s>::load() : File '%s' cannot be opened.",pixel_type(),filename); 1.35199 + } else try { 1.35200 + assign(1); 1.35201 + data->load(filename); 1.35202 + } catch (CImgException&) { 1.35203 + assign(); 1.35204 + } 1.35205 + } 1.35206 + cimg::exception_mode() = odebug; 1.35207 + if (is_empty()) 1.35208 + throw CImgIOException("CImgList<%s>::load() : File '%s', format not recognized.",pixel_type(),filename); 1.35209 + return *this; 1.35210 + } 1.35211 + 1.35212 + static CImgList<T> get_load(const char *const filename) { 1.35213 + return CImgList<T>().load(filename); 1.35214 + } 1.35215 + 1.35216 + //! Load an image list from a .cimg file. 1.35217 + CImgList<T>& load_cimg(const char *const filename) { 1.35218 + return _load_cimg(0,filename); 1.35219 + } 1.35220 + 1.35221 + static CImgList<T> get_load_cimg(const char *const filename) { 1.35222 + return CImgList<T>().load_cimg(filename); 1.35223 + } 1.35224 + 1.35225 + //! Load an image list from a .cimg file. 1.35226 + CImgList<T>& load_cimg(cimg_std::FILE *const file) { 1.35227 + return _load_cimg(file,0); 1.35228 + } 1.35229 + 1.35230 + static CImgList<T> get_load_cimg(cimg_std::FILE *const file) { 1.35231 + return CImgList<T>().load_cimg(file); 1.35232 + } 1.35233 + 1.35234 + CImgList<T>& _load_cimg(cimg_std::FILE *const file, const char *const filename) { 1.35235 +#ifdef cimg_use_zlib 1.35236 +#define _cimgz_load_cimg_case(Tss) { \ 1.35237 + Bytef *const cbuf = new Bytef[csiz]; \ 1.35238 + cimg::fread(cbuf,csiz,nfile); \ 1.35239 + raw.assign(W,H,D,V); \ 1.35240 + unsigned long destlen = raw.size()*sizeof(T); \ 1.35241 + uncompress((Bytef*)raw.data,&destlen,cbuf,csiz); \ 1.35242 + delete[] cbuf; \ 1.35243 + const Tss *ptrs = raw.data; \ 1.35244 + for (unsigned int off = raw.size(); off; --off) *(ptrd++) = (T)*(ptrs++); \ 1.35245 +} 1.35246 +#else 1.35247 +#define _cimgz_load_cimg_case(Tss) \ 1.35248 + throw CImgIOException("CImgList<%s>::load_cimg() : File '%s' contains compressed data, zlib must be used",\ 1.35249 + pixel_type(),filename?filename:"(FILE*)"); 1.35250 +#endif 1.35251 + 1.35252 +#define _cimg_load_cimg_case(Ts,Tss) \ 1.35253 + if (!loaded && !cimg::strcasecmp(Ts,str_pixeltype)) { \ 1.35254 + for (unsigned int l = 0; l<N; ++l) { \ 1.35255 + j = 0; while ((i=cimg_std::fgetc(nfile))!='\n' && i>=0) tmp[j++] = (char)i; tmp[j] = '\0'; \ 1.35256 + W = H = D = V = 0; csiz = 0; \ 1.35257 + if ((err = cimg_std::sscanf(tmp,"%u %u %u %u #%u",&W,&H,&D,&V,&csiz))<4) \ 1.35258 + throw CImgIOException("CImgList<%s>::load_cimg() : File '%s', Image %u has an invalid size (%u,%u,%u,%u)\n", \ 1.35259 + pixel_type(),filename?filename:("(FILE*)"),W,H,D,V); \ 1.35260 + if (W*H*D*V>0) { \ 1.35261 + CImg<Tss> raw; \ 1.35262 + CImg<T> &img = data[l]; \ 1.35263 + img.assign(W,H,D,V); \ 1.35264 + T *ptrd = img.data; \ 1.35265 + if (err==5) _cimgz_load_cimg_case(Tss) \ 1.35266 + else for (int toread = (int)img.size(); toread>0; ) { \ 1.35267 + raw.assign(cimg::min(toread,cimg_iobuffer)); \ 1.35268 + cimg::fread(raw.data,raw.width,nfile); \ 1.35269 + if (endian!=cimg::endianness()) cimg::invert_endianness(raw.data,raw.width); \ 1.35270 + toread-=raw.width; \ 1.35271 + const Tss *ptrs = raw.data; \ 1.35272 + for (unsigned int off = raw.width; off; --off) *(ptrd++) = (T)*(ptrs++); \ 1.35273 + } \ 1.35274 + } \ 1.35275 + } \ 1.35276 + loaded = true; \ 1.35277 + } 1.35278 + 1.35279 + if (!filename && !file) 1.35280 + throw CImgArgumentException("CImgList<%s>::load_cimg() : Cannot load (null) filename.", 1.35281 + pixel_type()); 1.35282 + typedef unsigned char uchar; 1.35283 + typedef unsigned short ushort; 1.35284 + typedef unsigned int uint; 1.35285 + typedef unsigned long ulong; 1.35286 + const int cimg_iobuffer = 12*1024*1024; 1.35287 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); 1.35288 + bool loaded = false, endian = cimg::endianness(); 1.35289 + char tmp[256], str_pixeltype[256], str_endian[256]; 1.35290 + unsigned int j, err, N = 0, W, H, D, V, csiz; 1.35291 + int i; 1.35292 + j = 0; while((i=cimg_std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = '\0'; 1.35293 + err = cimg_std::sscanf(tmp,"%u%*c%255[A-Za-z_]%*c%255[sA-Za-z_ ]",&N,str_pixeltype,str_endian); 1.35294 + if (err<2) { 1.35295 + if (!file) cimg::fclose(nfile); 1.35296 + throw CImgIOException("CImgList<%s>::load_cimg() : File '%s', Unknow CImg RAW header.", 1.35297 + pixel_type(),filename?filename:"(FILE*)"); 1.35298 + } 1.35299 + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; 1.35300 + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; 1.35301 + assign(N); 1.35302 + _cimg_load_cimg_case("bool",bool); 1.35303 + _cimg_load_cimg_case("unsigned_char",uchar); 1.35304 + _cimg_load_cimg_case("uchar",uchar); 1.35305 + _cimg_load_cimg_case("char",char); 1.35306 + _cimg_load_cimg_case("unsigned_short",ushort); 1.35307 + _cimg_load_cimg_case("ushort",ushort); 1.35308 + _cimg_load_cimg_case("short",short); 1.35309 + _cimg_load_cimg_case("unsigned_int",uint); 1.35310 + _cimg_load_cimg_case("uint",uint); 1.35311 + _cimg_load_cimg_case("int",int); 1.35312 + _cimg_load_cimg_case("unsigned_long",ulong); 1.35313 + _cimg_load_cimg_case("ulong",ulong); 1.35314 + _cimg_load_cimg_case("long",long); 1.35315 + _cimg_load_cimg_case("float",float); 1.35316 + _cimg_load_cimg_case("double",double); 1.35317 + if (!loaded) { 1.35318 + if (!file) cimg::fclose(nfile); 1.35319 + throw CImgIOException("CImgList<%s>::load_cimg() : File '%s', cannot read images of pixels coded as '%s'.", 1.35320 + pixel_type(),filename?filename:"(FILE*)",str_pixeltype); 1.35321 + } 1.35322 + if (!file) cimg::fclose(nfile); 1.35323 + return *this; 1.35324 + } 1.35325 + 1.35326 + //! Load a sub-image list from a non compressed .cimg file. 1.35327 + CImgList<T>& load_cimg(const char *const filename, 1.35328 + const unsigned int n0, const unsigned int n1, 1.35329 + const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int v0, 1.35330 + const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int v1) { 1.35331 + return _load_cimg(0,filename,n0,n1,x0,y0,z0,v0,x1,y1,z1,v1); 1.35332 + } 1.35333 + 1.35334 + static CImgList<T> get_load_cimg(const char *const filename, 1.35335 + const unsigned int n0, const unsigned int n1, 1.35336 + const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int v0, 1.35337 + const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int v1) { 1.35338 + return CImgList<T>().load_cimg(filename,n0,n1,x0,y0,z0,v0,x1,y1,z1,v1); 1.35339 + } 1.35340 + 1.35341 + //! Load a sub-image list from a non compressed .cimg file. 1.35342 + CImgList<T>& load_cimg(cimg_std::FILE *const file, 1.35343 + const unsigned int n0, const unsigned int n1, 1.35344 + const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int v0, 1.35345 + const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int v1) { 1.35346 + return _load_cimg(file,0,n0,n1,x0,y0,z0,v0,x1,y1,z1,v1); 1.35347 + } 1.35348 + 1.35349 + static CImgList<T> get_load_cimg(cimg_std::FILE *const file, 1.35350 + const unsigned int n0, const unsigned int n1, 1.35351 + const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int v0, 1.35352 + const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int v1) { 1.35353 + return CImgList<T>().load_cimg(file,n0,n1,x0,y0,z0,v0,x1,y1,z1,v1); 1.35354 + } 1.35355 + 1.35356 + CImgList<T>& _load_cimg(cimg_std::FILE *const file, const char *const filename, 1.35357 + const unsigned int n0, const unsigned int n1, 1.35358 + const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int v0, 1.35359 + const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int v1) { 1.35360 +#define _cimg_load_cimg_case2(Ts,Tss) \ 1.35361 + if (!loaded && !cimg::strcasecmp(Ts,str_pixeltype)) { \ 1.35362 + for (unsigned int l = 0; l<=nn1; ++l) { \ 1.35363 + j = 0; while ((i=cimg_std::fgetc(nfile))!='\n' && i>=0) tmp[j++] = (char)i; tmp[j] = '\0'; \ 1.35364 + W = H = D = V = 0; \ 1.35365 + if (cimg_std::sscanf(tmp,"%u %u %u %u",&W,&H,&D,&V)!=4) \ 1.35366 + throw CImgIOException("CImgList<%s>::load_cimg() : File '%s', Image %u has an invalid size (%u,%u,%u,%u)\n", \ 1.35367 + pixel_type(), filename?filename:("(FILE*)"), W, H, D, V); \ 1.35368 + if (W*H*D*V>0) { \ 1.35369 + if (l<n0 || x0>=W || y0>=H || z0>=D || v0>=D) cimg_std::fseek(nfile,W*H*D*V*sizeof(Tss),SEEK_CUR); \ 1.35370 + else { \ 1.35371 + const unsigned int \ 1.35372 + nx1 = x1>=W?W-1:x1, \ 1.35373 + ny1 = y1>=H?H-1:y1, \ 1.35374 + nz1 = z1>=D?D-1:z1, \ 1.35375 + nv1 = v1>=V?V-1:v1; \ 1.35376 + CImg<Tss> raw(1+nx1-x0); \ 1.35377 + CImg<T> &img = data[l-n0]; \ 1.35378 + img.assign(1+nx1-x0,1+ny1-y0,1+nz1-z0,1+nv1-v0); \ 1.35379 + T *ptrd = img.data; \ 1.35380 + const unsigned int skipvb = v0*W*H*D*sizeof(Tss); \ 1.35381 + if (skipvb) cimg_std::fseek(nfile,skipvb,SEEK_CUR); \ 1.35382 + for (unsigned int v=1+nv1-v0; v; --v) { \ 1.35383 + const unsigned int skipzb = z0*W*H*sizeof(Tss); \ 1.35384 + if (skipzb) cimg_std::fseek(nfile,skipzb,SEEK_CUR); \ 1.35385 + for (unsigned int z=1+nz1-z0; z; --z) { \ 1.35386 + const unsigned int skipyb = y0*W*sizeof(Tss); \ 1.35387 + if (skipyb) cimg_std::fseek(nfile,skipyb,SEEK_CUR); \ 1.35388 + for (unsigned int y=1+ny1-y0; y; --y) { \ 1.35389 + const unsigned int skipxb = x0*sizeof(Tss); \ 1.35390 + if (skipxb) cimg_std::fseek(nfile,skipxb,SEEK_CUR); \ 1.35391 + cimg::fread(raw.data,raw.width,nfile); \ 1.35392 + if (endian!=cimg::endianness()) cimg::invert_endianness(raw.data,raw.width); \ 1.35393 + const Tss *ptrs = raw.data; \ 1.35394 + for (unsigned int off = raw.width; off; --off) *(ptrd++) = (T)*(ptrs++); \ 1.35395 + const unsigned int skipxe = (W-1-nx1)*sizeof(Tss); \ 1.35396 + if (skipxe) cimg_std::fseek(nfile,skipxe,SEEK_CUR); \ 1.35397 + } \ 1.35398 + const unsigned int skipye = (H-1-ny1)*W*sizeof(Tss); \ 1.35399 + if (skipye) cimg_std::fseek(nfile,skipye,SEEK_CUR); \ 1.35400 + } \ 1.35401 + const unsigned int skipze = (D-1-nz1)*W*H*sizeof(Tss); \ 1.35402 + if (skipze) cimg_std::fseek(nfile,skipze,SEEK_CUR); \ 1.35403 + } \ 1.35404 + const unsigned int skipve = (V-1-nv1)*W*H*D*sizeof(Tss); \ 1.35405 + if (skipve) cimg_std::fseek(nfile,skipve,SEEK_CUR); \ 1.35406 + } \ 1.35407 + } \ 1.35408 + } \ 1.35409 + loaded = true; \ 1.35410 + } 1.35411 + 1.35412 + if (!filename && !file) 1.35413 + throw CImgArgumentException("CImgList<%s>::load_cimg() : Cannot load (null) filename.", 1.35414 + pixel_type()); 1.35415 + typedef unsigned char uchar; 1.35416 + typedef unsigned short ushort; 1.35417 + typedef unsigned int uint; 1.35418 + typedef unsigned long ulong; 1.35419 + if (n1<n0 || x1<x0 || y1<y0 || z1<z0 || v1<v0) 1.35420 + throw CImgArgumentException("CImgList<%s>::load_cimg() : File '%s', Bad sub-region coordinates [%u->%u] " 1.35421 + "(%u,%u,%u,%u)->(%u,%u,%u,%u).", 1.35422 + pixel_type(),filename?filename:"(FILE*)", 1.35423 + n0,n1,x0,y0,z0,v0,x1,y1,z1,v1); 1.35424 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); 1.35425 + bool loaded = false, endian = cimg::endianness(); 1.35426 + char tmp[256], str_pixeltype[256], str_endian[256]; 1.35427 + unsigned int j, err, N, W, H, D, V; 1.35428 + int i; 1.35429 + j = 0; while((i=cimg_std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = '\0'; 1.35430 + err = cimg_std::sscanf(tmp,"%u%*c%255[A-Za-z_]%*c%255[sA-Za-z_ ]",&N,str_pixeltype,str_endian); 1.35431 + if (err<2) { 1.35432 + if (!file) cimg::fclose(nfile); 1.35433 + throw CImgIOException("CImgList<%s>::load_cimg() : File '%s', Unknow CImg RAW header.", 1.35434 + pixel_type(),filename?filename:"(FILE*)"); 1.35435 + } 1.35436 + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; 1.35437 + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; 1.35438 + const unsigned int nn1 = n1>=N?N-1:n1; 1.35439 + assign(1+nn1-n0); 1.35440 + _cimg_load_cimg_case2("bool",bool); 1.35441 + _cimg_load_cimg_case2("unsigned_char",uchar); 1.35442 + _cimg_load_cimg_case2("uchar",uchar); 1.35443 + _cimg_load_cimg_case2("char",char); 1.35444 + _cimg_load_cimg_case2("unsigned_short",ushort); 1.35445 + _cimg_load_cimg_case2("ushort",ushort); 1.35446 + _cimg_load_cimg_case2("short",short); 1.35447 + _cimg_load_cimg_case2("unsigned_int",uint); 1.35448 + _cimg_load_cimg_case2("uint",uint); 1.35449 + _cimg_load_cimg_case2("int",int); 1.35450 + _cimg_load_cimg_case2("unsigned_long",ulong); 1.35451 + _cimg_load_cimg_case2("ulong",ulong); 1.35452 + _cimg_load_cimg_case2("long",long); 1.35453 + _cimg_load_cimg_case2("float",float); 1.35454 + _cimg_load_cimg_case2("double",double); 1.35455 + if (!loaded) { 1.35456 + if (!file) cimg::fclose(nfile); 1.35457 + throw CImgIOException("CImgList<%s>::load_cimg() : File '%s', cannot read images of pixels coded as '%s'.", 1.35458 + pixel_type(),filename?filename:"(FILE*)",str_pixeltype); 1.35459 + } 1.35460 + if (!file) cimg::fclose(nfile); 1.35461 + return *this; 1.35462 + } 1.35463 + 1.35464 + //! Load an image list from a PAR/REC (Philips) file. 1.35465 + CImgList<T>& load_parrec(const char *const filename) { 1.35466 + if (!filename) 1.35467 + throw CImgArgumentException("CImgList<%s>::load_parrec() : Cannot load (null) filename.", 1.35468 + pixel_type()); 1.35469 + char body[1024], filenamepar[1024], filenamerec[1024]; 1.35470 + const char *ext = cimg::split_filename(filename,body); 1.35471 + if (!cimg::strcmp(ext,"par")) { cimg_std::strcpy(filenamepar,filename); cimg_std::sprintf(filenamerec,"%s.rec",body); } 1.35472 + if (!cimg::strcmp(ext,"PAR")) { cimg_std::strcpy(filenamepar,filename); cimg_std::sprintf(filenamerec,"%s.REC",body); } 1.35473 + if (!cimg::strcmp(ext,"rec")) { cimg_std::strcpy(filenamerec,filename); cimg_std::sprintf(filenamepar,"%s.par",body); } 1.35474 + if (!cimg::strcmp(ext,"REC")) { cimg_std::strcpy(filenamerec,filename); cimg_std::sprintf(filenamepar,"%s.PAR",body); } 1.35475 + cimg_std::FILE *file = cimg::fopen(filenamepar,"r"); 1.35476 + 1.35477 + // Parse header file 1.35478 + CImgList<floatT> st_slices; 1.35479 + CImgList<uintT> st_global; 1.35480 + int err; 1.35481 + char line[256] = { 0 }; 1.35482 + do { err=cimg_std::fscanf(file,"%255[^\n]%*c",line); } while (err!=EOF && (line[0]=='#' || line[0]=='.')); 1.35483 + do { 1.35484 + unsigned int sn,sizex,sizey,pixsize; 1.35485 + float rs,ri,ss; 1.35486 + err = cimg_std::fscanf(file,"%u%*u%*u%*u%*u%*u%*u%u%*u%u%u%g%g%g%*[^\n]",&sn,&pixsize,&sizex,&sizey,&ri,&rs,&ss); 1.35487 + if (err==7) { 1.35488 + st_slices.insert(CImg<floatT>::vector((float)sn,(float)pixsize,(float)sizex,(float)sizey, 1.35489 + ri,rs,ss,0)); 1.35490 + unsigned int i; for (i=0; i<st_global.size && sn<=st_global[i][2]; ++i) {} 1.35491 + if (i==st_global.size) st_global.insert(CImg<uintT>::vector(sizex,sizey,sn)); 1.35492 + else { 1.35493 + CImg<uintT> &vec = st_global[i]; 1.35494 + if (sizex>vec[0]) vec[0] = sizex; 1.35495 + if (sizey>vec[1]) vec[1] = sizey; 1.35496 + vec[2] = sn; 1.35497 + } 1.35498 + st_slices[st_slices.size-1][7] = (float)i; 1.35499 + } 1.35500 + } while (err==7); 1.35501 + 1.35502 + // Read data 1.35503 + cimg_std::FILE *file2 = cimg::fopen(filenamerec,"rb"); 1.35504 + { cimglist_for(st_global,l) { 1.35505 + const CImg<uintT>& vec = st_global[l]; 1.35506 + insert(CImg<T>(vec[0],vec[1],vec[2])); 1.35507 + }} 1.35508 + 1.35509 + cimglist_for(st_slices,l) { 1.35510 + const CImg<floatT>& vec = st_slices[l]; 1.35511 + const unsigned int 1.35512 + sn = (unsigned int)vec[0]-1, 1.35513 + pixsize = (unsigned int)vec[1], 1.35514 + sizex = (unsigned int)vec[2], 1.35515 + sizey = (unsigned int)vec[3], 1.35516 + imn = (unsigned int)vec[7]; 1.35517 + const float ri = vec[4], rs = vec[5], ss = vec[6]; 1.35518 + switch (pixsize) { 1.35519 + case 8 : { 1.35520 + CImg<ucharT> buf(sizex,sizey); 1.35521 + cimg::fread(buf.data,sizex*sizey,file2); 1.35522 + if (cimg::endianness()) cimg::invert_endianness(buf.data,sizex*sizey); 1.35523 + CImg<T>& img = (*this)[imn]; 1.35524 + cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss)); 1.35525 + } break; 1.35526 + case 16 : { 1.35527 + CImg<ushortT> buf(sizex,sizey); 1.35528 + cimg::fread(buf.data,sizex*sizey,file2); 1.35529 + if (cimg::endianness()) cimg::invert_endianness(buf.data,sizex*sizey); 1.35530 + CImg<T>& img = (*this)[imn]; 1.35531 + cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss)); 1.35532 + } break; 1.35533 + case 32 : { 1.35534 + CImg<uintT> buf(sizex,sizey); 1.35535 + cimg::fread(buf.data,sizex*sizey,file2); 1.35536 + if (cimg::endianness()) cimg::invert_endianness(buf.data,sizex*sizey); 1.35537 + CImg<T>& img = (*this)[imn]; 1.35538 + cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss)); 1.35539 + } break; 1.35540 + default : 1.35541 + cimg::fclose(file); 1.35542 + cimg::fclose(file2); 1.35543 + throw CImgIOException("CImg<%s>::load_parrec() : File '%s', cannot handle image with pixsize = %d bits.", 1.35544 + pixel_type(),filename,pixsize); 1.35545 + } 1.35546 + } 1.35547 + cimg::fclose(file); 1.35548 + cimg::fclose(file2); 1.35549 + if (!size) 1.35550 + throw CImgIOException("CImg<%s>::load_parrec() : File '%s' does not appear to be a valid PAR-REC file.", 1.35551 + pixel_type(),filename); 1.35552 + return *this; 1.35553 + } 1.35554 + 1.35555 + static CImgList<T> get_load_parrec(const char *const filename) { 1.35556 + return CImgList<T>().load_parrec(filename); 1.35557 + } 1.35558 + 1.35559 + //! Load an image sequence from a YUV file. 1.35560 + CImgList<T>& load_yuv(const char *const filename, 1.35561 + const unsigned int sizex, const unsigned int sizey, 1.35562 + const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.35563 + const unsigned int step_frame=1, const bool yuv2rgb=true) { 1.35564 + return _load_yuv(0,filename,sizex,sizey,first_frame,last_frame,step_frame,yuv2rgb); 1.35565 + } 1.35566 + 1.35567 + static CImgList<T> get_load_yuv(const char *const filename, 1.35568 + const unsigned int sizex, const unsigned int sizey=1, 1.35569 + const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.35570 + const unsigned int step_frame=1, const bool yuv2rgb=true) { 1.35571 + return CImgList<T>().load_yuv(filename,sizex,sizey,first_frame,last_frame,step_frame,yuv2rgb); 1.35572 + } 1.35573 + 1.35574 + //! Load an image sequence from a YUV file. 1.35575 + CImgList<T>& load_yuv(cimg_std::FILE *const file, 1.35576 + const unsigned int sizex, const unsigned int sizey, 1.35577 + const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.35578 + const unsigned int step_frame=1, const bool yuv2rgb=true) { 1.35579 + return _load_yuv(file,0,sizex,sizey,first_frame,last_frame,step_frame,yuv2rgb); 1.35580 + } 1.35581 + 1.35582 + static CImgList<T> get_load_yuv(cimg_std::FILE *const file, 1.35583 + const unsigned int sizex, const unsigned int sizey=1, 1.35584 + const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.35585 + const unsigned int step_frame=1, const bool yuv2rgb=true) { 1.35586 + return CImgList<T>().load_yuv(file,sizex,sizey,first_frame,last_frame,step_frame,yuv2rgb); 1.35587 + } 1.35588 + 1.35589 + CImgList<T>& _load_yuv(cimg_std::FILE *const file, const char *const filename, 1.35590 + const unsigned int sizex, const unsigned int sizey, 1.35591 + const unsigned int first_frame, const unsigned int last_frame, 1.35592 + const unsigned int step_frame, const bool yuv2rgb) { 1.35593 + if (!filename && !file) 1.35594 + throw CImgArgumentException("CImgList<%s>::load_yuv() : Cannot load (null) filename.", 1.35595 + pixel_type()); 1.35596 + if (sizex%2 || sizey%2) 1.35597 + throw CImgArgumentException("CImgList<%s>::load_yuv() : File '%s', image dimensions along X and Y must be " 1.35598 + "even numbers (given are %ux%u)\n", 1.35599 + pixel_type(),filename?filename:"(FILE*)",sizex,sizey); 1.35600 + if (!sizex || !sizey) 1.35601 + throw CImgArgumentException("CImgList<%s>::load_yuv() : File '%s', given image sequence size (%u,%u) is invalid", 1.35602 + pixel_type(),filename?filename:"(FILE*)",sizex,sizey); 1.35603 + 1.35604 + const unsigned int 1.35605 + nfirst_frame = first_frame<last_frame?first_frame:last_frame, 1.35606 + nlast_frame = first_frame<last_frame?last_frame:first_frame, 1.35607 + nstep_frame = step_frame?step_frame:1; 1.35608 + 1.35609 + CImg<ucharT> tmp(sizex,sizey,1,3), UV(sizex/2,sizey/2,1,2); 1.35610 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); 1.35611 + bool stopflag = false; 1.35612 + int err; 1.35613 + if (nfirst_frame) { 1.35614 + err = cimg_std::fseek(nfile,nfirst_frame*(sizex*sizey + sizex*sizey/2),SEEK_CUR); 1.35615 + if (err) { 1.35616 + if (!file) cimg::fclose(nfile); 1.35617 + throw CImgIOException("CImgList<%s>::load_yuv() : File '%s' doesn't contain frame number %u " 1.35618 + "(out of range error).", 1.35619 + pixel_type(),filename?filename:"(FILE*)",nfirst_frame); 1.35620 + } 1.35621 + } 1.35622 + unsigned int frame; 1.35623 + for (frame = nfirst_frame; !stopflag && frame<=nlast_frame; frame+=nstep_frame) { 1.35624 + tmp.fill(0); 1.35625 + // *TRY* to read the luminance part, do not replace by cimg::fread ! 1.35626 + err = (int)cimg_std::fread((void*)(tmp.data),1,(size_t)(tmp.width*tmp.height),nfile); 1.35627 + if (err!=(int)(tmp.width*tmp.height)) { 1.35628 + stopflag = true; 1.35629 + if (err>0) 1.35630 + cimg::warn("CImgList<%s>::load_yuv() : File '%s' contains incomplete data," 1.35631 + " or given image dimensions (%u,%u) are incorrect.", 1.35632 + pixel_type(),filename?filename:"(FILE*)",sizex,sizey); 1.35633 + } else { 1.35634 + UV.fill(0); 1.35635 + // *TRY* to read the luminance part, do not replace by cimg::fread ! 1.35636 + err = (int)cimg_std::fread((void*)(UV.data),1,(size_t)(UV.size()),nfile); 1.35637 + if (err!=(int)(UV.size())) { 1.35638 + stopflag = true; 1.35639 + if (err>0) 1.35640 + cimg::warn("CImgList<%s>::load_yuv() : File '%s' contains incomplete data," 1.35641 + " or given image dimensions (%u,%u) are incorrect.", 1.35642 + pixel_type(),filename?filename:"(FILE*)",sizex,sizey); 1.35643 + } else { 1.35644 + cimg_forXY(UV,x,y) { 1.35645 + const int x2 = x*2, y2 = y*2; 1.35646 + tmp(x2,y2,1) = tmp(x2+1,y2,1) = tmp(x2,y2+1,1) = tmp(x2+1,y2+1,1) = UV(x,y,0); 1.35647 + tmp(x2,y2,2) = tmp(x2+1,y2,2) = tmp(x2,y2+1,2) = tmp(x2+1,y2+1,2) = UV(x,y,1); 1.35648 + } 1.35649 + if (yuv2rgb) tmp.YCbCrtoRGB(); 1.35650 + insert(tmp); 1.35651 + if (nstep_frame>1) cimg_std::fseek(nfile,(nstep_frame-1)*(sizex*sizey + sizex*sizey/2),SEEK_CUR); 1.35652 + } 1.35653 + } 1.35654 + } 1.35655 + if (stopflag && nlast_frame!=~0U && frame!=nlast_frame) 1.35656 + cimg::warn("CImgList<%s>::load_yuv() : File '%s', frame %d not reached since only %u frames were found in the file.", 1.35657 + pixel_type(),filename?filename:"(FILE*)",nlast_frame,frame-1,filename); 1.35658 + if (!file) cimg::fclose(nfile); 1.35659 + return *this; 1.35660 + } 1.35661 + 1.35662 + //! Load an image from a video file, using ffmpeg libraries. 1.35663 + // This piece of code has been firstly created by David Starweather (starkdg(at)users(dot)sourceforge(dot)net) 1.35664 + // I modified it afterwards for direct inclusion in the library core. 1.35665 + CImgList<T>& load_ffmpeg(const char *const filename, const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.35666 + const unsigned int step_frame=1, const bool pixel_format=true, const bool resume=false) { 1.35667 + if (!filename) 1.35668 + throw CImgArgumentException("CImgList<%s>::load_ffmpeg() : Cannot load (null) filename.", 1.35669 + pixel_type()); 1.35670 + const unsigned int 1.35671 + nfirst_frame = first_frame<last_frame?first_frame:last_frame, 1.35672 + nlast_frame = first_frame<last_frame?last_frame:first_frame, 1.35673 + nstep_frame = step_frame?step_frame:1; 1.35674 + assign(); 1.35675 + 1.35676 +#ifndef cimg_use_ffmpeg 1.35677 + if ((nfirst_frame || nlast_frame!=~0U || nstep_frame>1) || (resume && (pixel_format || !pixel_format))) 1.35678 + throw CImgArgumentException("CImg<%s>::load_ffmpeg() : File '%s', reading sub-frames from a video file requires the use of ffmpeg.\n" 1.35679 + "('cimg_use_ffmpeg' must be defined).", 1.35680 + pixel_type(),filename); 1.35681 + return load_ffmpeg_external(filename); 1.35682 +#else 1.35683 + const unsigned int ffmpeg_pixfmt = pixel_format?PIX_FMT_RGB24:PIX_FMT_GRAY8; 1.35684 + avcodec_register_all(); 1.35685 + av_register_all(); 1.35686 + static AVFormatContext *format_ctx = 0; 1.35687 + static AVCodecContext *codec_ctx = 0; 1.35688 + static AVCodec *codec = 0; 1.35689 + static AVFrame *avframe = avcodec_alloc_frame(), *converted_frame = avcodec_alloc_frame(); 1.35690 + static int vstream = 0; 1.35691 + 1.35692 + if (resume) { 1.35693 + if (!format_ctx || !codec_ctx || !codec || !avframe || !converted_frame) 1.35694 + throw CImgArgumentException("CImgList<%s>::load_ffmpeg() : File '%s', cannot resume due to unallocated FFMPEG structures.", 1.35695 + pixel_type(),filename); 1.35696 + } else { 1.35697 + // Open video file, find main video stream and codec. 1.35698 + if (format_ctx) av_close_input_file(format_ctx); 1.35699 + if (av_open_input_file(&format_ctx,filename,0,0,0)!=0) 1.35700 + throw CImgIOException("CImgList<%s>::load_ffmpeg() : File '%s' cannot be opened.", 1.35701 + pixel_type(),filename); 1.35702 + if (!avframe || !converted_frame || av_find_stream_info(format_ctx)<0) { 1.35703 + av_close_input_file(format_ctx); format_ctx = 0; 1.35704 + cimg::warn("CImgList<%s>::load_ffmpeg() : File '%s', cannot retrieve stream information.\n" 1.35705 + "Trying with external ffmpeg executable.", 1.35706 + pixel_type(),filename); 1.35707 + return load_ffmpeg_external(filename); 1.35708 + } 1.35709 +#if cimg_debug>=3 1.35710 + dump_format(format_ctx,0,0,0); 1.35711 +#endif 1.35712 + 1.35713 + // Special command : Return informations on main video stream. 1.35714 + // as a vector 1x4 containing : (nb_frames,width,height,fps). 1.35715 + if (!first_frame && !last_frame && !step_frame) { 1.35716 + for (vstream = 0; vstream<(int)(format_ctx->nb_streams); ++vstream) 1.35717 + if (format_ctx->streams[vstream]->codec->codec_type==CODEC_TYPE_VIDEO) break; 1.35718 + if (vstream==(int)format_ctx->nb_streams) assign(); 1.35719 + else { 1.35720 + CImgList<doubleT> timestamps; 1.35721 + int nb_frames; 1.35722 + AVPacket packet; 1.35723 + // Count frames and store timestamps. 1.35724 + for (nb_frames = 0; av_read_frame(format_ctx,&packet)>=0; av_free_packet(&packet)) 1.35725 + if (packet.stream_index==vstream) { 1.35726 + timestamps.insert(CImg<doubleT>::vector((double)packet.pts)); 1.35727 + ++nb_frames; 1.35728 + } 1.35729 + // Get frame with, height and fps. 1.35730 + const int 1.35731 + framew = format_ctx->streams[vstream]->codec->width, 1.35732 + frameh = format_ctx->streams[vstream]->codec->height; 1.35733 + const float 1.35734 + num = (float)(format_ctx->streams[vstream]->r_frame_rate).num, 1.35735 + den = (float)(format_ctx->streams[vstream]->r_frame_rate).den, 1.35736 + fps = num/den; 1.35737 + // Return infos as a list. 1.35738 + assign(2); 1.35739 + (*this)[0].assign(1,4).fill((T)nb_frames,(T)framew,(T)frameh,(T)fps); 1.35740 + (*this)[1] = timestamps.get_append('y'); 1.35741 + } 1.35742 + av_close_input_file(format_ctx); format_ctx = 0; 1.35743 + return *this; 1.35744 + } 1.35745 + 1.35746 + for (vstream = 0; vstream<(int)(format_ctx->nb_streams) && 1.35747 + format_ctx->streams[vstream]->codec->codec_type!=CODEC_TYPE_VIDEO; ) ++vstream; 1.35748 + if (vstream==(int)format_ctx->nb_streams) { 1.35749 + cimg::warn("CImgList<%s>::load_ffmpeg() : File '%s', cannot retrieve video stream.\n" 1.35750 + "Trying with external ffmpeg executable.", 1.35751 + pixel_type(),filename); 1.35752 + av_close_input_file(format_ctx); format_ctx = 0; 1.35753 + return load_ffmpeg_external(filename); 1.35754 + } 1.35755 + codec_ctx = format_ctx->streams[vstream]->codec; 1.35756 + codec = avcodec_find_decoder(codec_ctx->codec_id); 1.35757 + if (!codec) { 1.35758 + cimg::warn("CImgList<%s>::load_ffmpeg() : File '%s', cannot find video codec.\n" 1.35759 + "Trying with external ffmpeg executable.", 1.35760 + pixel_type(),filename); 1.35761 + return load_ffmpeg_external(filename); 1.35762 + } 1.35763 + if (avcodec_open(codec_ctx,codec)<0) { // Open codec 1.35764 + cimg::warn("CImgList<%s>::load_ffmpeg() : File '%s', cannot open video codec.\n" 1.35765 + "Trying with external ffmpeg executable.", 1.35766 + pixel_type(),filename); 1.35767 + return load_ffmpeg_external(filename); 1.35768 + } 1.35769 + } 1.35770 + 1.35771 + // Read video frames 1.35772 + const unsigned int numBytes = avpicture_get_size(ffmpeg_pixfmt,codec_ctx->width,codec_ctx->height); 1.35773 + uint8_t *const buffer = new uint8_t[numBytes]; 1.35774 + avpicture_fill((AVPicture *)converted_frame,buffer,ffmpeg_pixfmt,codec_ctx->width,codec_ctx->height); 1.35775 + const T foo = (T)0; 1.35776 + AVPacket packet; 1.35777 + for (unsigned int frame = 0, next_frame = nfirst_frame; frame<=nlast_frame && av_read_frame(format_ctx,&packet)>=0; ) { 1.35778 + if (packet.stream_index==(int)vstream) { 1.35779 + int decoded = 0; 1.35780 + avcodec_decode_video(codec_ctx,avframe,&decoded,packet.data,packet.size); 1.35781 + if (decoded) { 1.35782 + if (frame==next_frame) { 1.35783 + SwsContext *c = sws_getContext(codec_ctx->width,codec_ctx->height,codec_ctx->pix_fmt,codec_ctx->width, 1.35784 + codec_ctx->height,ffmpeg_pixfmt,1,0,0,0); 1.35785 + sws_scale(c,avframe->data,avframe->linesize,0,codec_ctx->height,converted_frame->data,converted_frame->linesize); 1.35786 + if (ffmpeg_pixfmt==PIX_FMT_RGB24) { 1.35787 + CImg<ucharT> next_image(*converted_frame->data,3,codec_ctx->width,codec_ctx->height,1,true); 1.35788 + insert(next_image._get_permute_axes("yzvx",foo)); 1.35789 + } else { 1.35790 + CImg<ucharT> next_image(*converted_frame->data,1,codec_ctx->width,codec_ctx->height,1,true); 1.35791 + insert(next_image._get_permute_axes("yzvx",foo)); 1.35792 + } 1.35793 + next_frame+=nstep_frame; 1.35794 + } 1.35795 + ++frame; 1.35796 + } 1.35797 + av_free_packet(&packet); 1.35798 + if (next_frame>nlast_frame) break; 1.35799 + } 1.35800 + } 1.35801 + delete[] buffer; 1.35802 +#endif 1.35803 + return *this; 1.35804 + } 1.35805 + 1.35806 + static CImgList<T> get_load_ffmpeg(const char *const filename, const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.35807 + const unsigned int step_frame=1, const bool pixel_format=true) { 1.35808 + return CImgList<T>().load_ffmpeg(filename,first_frame,last_frame,step_frame,pixel_format); 1.35809 + } 1.35810 + 1.35811 + //! Load an image from a video file (MPEG,AVI) using the external tool 'ffmpeg'. 1.35812 + CImgList<T>& load_ffmpeg_external(const char *const filename) { 1.35813 + if (!filename) 1.35814 + throw CImgArgumentException("CImgList<%s>::load_ffmpeg_external() : Cannot load (null) filename.", 1.35815 + pixel_type()); 1.35816 + char command[1024], filetmp[512], filetmp2[512]; 1.35817 + cimg_std::FILE *file = 0; 1.35818 + do { 1.35819 + cimg_std::sprintf(filetmp,"%s%s%s",cimg::temporary_path(),cimg_OS==2?"\\":"/",cimg::filenamerand()); 1.35820 + cimg_std::sprintf(filetmp2,"%s_000001.ppm",filetmp); 1.35821 + if ((file=cimg_std::fopen(filetmp2,"rb"))!=0) cimg_std::fclose(file); 1.35822 + } while (file); 1.35823 + cimg_std::sprintf(filetmp2,"%s_%%6d.ppm",filetmp); 1.35824 +#if cimg_OS!=2 1.35825 + cimg_std::sprintf(command,"%s -i \"%s\" %s >/dev/null 2>&1",cimg::ffmpeg_path(),filename,filetmp2); 1.35826 +#else 1.35827 + cimg_std::sprintf(command,"\"%s -i \"%s\" %s\" >NUL 2>&1",cimg::ffmpeg_path(),filename,filetmp2); 1.35828 +#endif 1.35829 + cimg::system(command,0); 1.35830 + const unsigned int odebug = cimg::exception_mode(); 1.35831 + cimg::exception_mode() = 0; 1.35832 + assign(); 1.35833 + unsigned int i = 1; 1.35834 + for (bool stopflag = false; !stopflag; ++i) { 1.35835 + cimg_std::sprintf(filetmp2,"%s_%.6u.ppm",filetmp,i); 1.35836 + CImg<T> img; 1.35837 + try { img.load_pnm(filetmp2); } 1.35838 + catch (CImgException&) { stopflag = true; } 1.35839 + if (img) { insert(img); cimg_std::remove(filetmp2); } 1.35840 + } 1.35841 + cimg::exception_mode() = odebug; 1.35842 + if (is_empty()) 1.35843 + throw CImgIOException("CImgList<%s>::load_ffmpeg_external() : Failed to open image sequence '%s'.\n" 1.35844 + "Check the filename and if the 'ffmpeg' tool is installed on your system.", 1.35845 + pixel_type(),filename); 1.35846 + return *this; 1.35847 + } 1.35848 + 1.35849 + static CImgList<T> get_load_ffmpeg_external(const char *const filename) { 1.35850 + return CImgList<T>().load_ffmpeg_external(filename); 1.35851 + } 1.35852 + 1.35853 + //! Load a gzipped list, using external tool 'gunzip'. 1.35854 + CImgList<T>& load_gzip_external(const char *const filename) { 1.35855 + if (!filename) 1.35856 + throw CImgIOException("CImg<%s>::load_gzip_external() : Cannot load (null) filename.", 1.35857 + pixel_type()); 1.35858 + char command[1024], filetmp[512], body[512]; 1.35859 + const char 1.35860 + *ext = cimg::split_filename(filename,body), 1.35861 + *ext2 = cimg::split_filename(body,0); 1.35862 + cimg_std::FILE *file = 0; 1.35863 + do { 1.35864 + if (!cimg::strcasecmp(ext,"gz")) { 1.35865 + if (*ext2) cimg_std::sprintf(filetmp,"%s%s%s.%s",cimg::temporary_path(),cimg_OS==2?"\\":"/", 1.35866 + cimg::filenamerand(),ext2); 1.35867 + else cimg_std::sprintf(filetmp,"%s%s%s",cimg::temporary_path(),cimg_OS==2?"\\":"/", 1.35868 + cimg::filenamerand()); 1.35869 + } else { 1.35870 + if (*ext) cimg_std::sprintf(filetmp,"%s%s%s.%s",cimg::temporary_path(),cimg_OS==2?"\\":"/", 1.35871 + cimg::filenamerand(),ext); 1.35872 + else cimg_std::sprintf(filetmp,"%s%s%s",cimg::temporary_path(),cimg_OS==2?"\\":"/", 1.35873 + cimg::filenamerand()); 1.35874 + } 1.35875 + if ((file=cimg_std::fopen(filetmp,"rb"))!=0) cimg_std::fclose(file); 1.35876 + } while (file); 1.35877 + cimg_std::sprintf(command,"%s -c \"%s\" > %s",cimg::gunzip_path(),filename,filetmp); 1.35878 + cimg::system(command); 1.35879 + if (!(file = cimg_std::fopen(filetmp,"rb"))) { 1.35880 + cimg::fclose(cimg::fopen(filename,"r")); 1.35881 + throw CImgIOException("CImg<%s>::load_gzip_external() : File '%s' cannot be opened.", 1.35882 + pixel_type(),filename); 1.35883 + } else cimg::fclose(file); 1.35884 + load(filetmp); 1.35885 + cimg_std::remove(filetmp); 1.35886 + return *this; 1.35887 + } 1.35888 + 1.35889 + static CImgList<T> get_load_gzip_external(const char *const filename) { 1.35890 + return CImgList<T>().load_gzip_external(filename); 1.35891 + } 1.35892 + 1.35893 + //! Load a 3D object from a .OFF file. 1.35894 + template<typename tf, typename tc> 1.35895 + CImgList<T>& load_off(const char *const filename, 1.35896 + CImgList<tf>& primitives, CImgList<tc>& colors, 1.35897 + const bool invert_faces=false) { 1.35898 + return get_load_off(filename,primitives,colors,invert_faces).transfer_to(*this); 1.35899 + } 1.35900 + 1.35901 + template<typename tf, typename tc> 1.35902 + static CImgList<T> get_load_off(const char *const filename, 1.35903 + CImgList<tf>& primitives, CImgList<tc>& colors, 1.35904 + const bool invert_faces=false) { 1.35905 + return CImg<T>().load_off(filename,primitives,colors,invert_faces).get_split('x'); 1.35906 + } 1.35907 + 1.35908 + //! Load a TIFF file. 1.35909 + CImgList<T>& load_tiff(const char *const filename, 1.35910 + const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.35911 + const unsigned int step_frame=1) { 1.35912 + const unsigned int 1.35913 + nfirst_frame = first_frame<last_frame?first_frame:last_frame, 1.35914 + nstep_frame = step_frame?step_frame:1; 1.35915 + unsigned int nlast_frame = first_frame<last_frame?last_frame:first_frame; 1.35916 +#ifndef cimg_use_tiff 1.35917 + if (nfirst_frame || nlast_frame!=~0U || nstep_frame!=1) 1.35918 + throw CImgArgumentException("CImgList<%s>::load_tiff() : File '%s', reading sub-images from a tiff file requires the use of libtiff.\n" 1.35919 + "('cimg_use_tiff' must be defined).", 1.35920 + pixel_type(),filename); 1.35921 + return assign(CImg<T>::get_load_tiff(filename)); 1.35922 +#else 1.35923 + TIFF *tif = TIFFOpen(filename,"r"); 1.35924 + if (tif) { 1.35925 + unsigned int nb_images = 0; 1.35926 + do ++nb_images; while (TIFFReadDirectory(tif)); 1.35927 + if (nfirst_frame>=nb_images || (nlast_frame!=~0U && nlast_frame>=nb_images)) 1.35928 + cimg::warn("CImgList<%s>::load_tiff() : File '%s' contains %u image(s), specified frame range is [%u,%u] (step %u).", 1.35929 + pixel_type(),filename,nb_images,nfirst_frame,nlast_frame,nstep_frame); 1.35930 + if (nfirst_frame>=nb_images) return assign(); 1.35931 + if (nlast_frame>=nb_images) nlast_frame = nb_images-1; 1.35932 + assign(1+(nlast_frame-nfirst_frame)/nstep_frame); 1.35933 + TIFFSetDirectory(tif,0); 1.35934 +#if cimg_debug>=3 1.35935 + TIFFSetWarningHandler(0); 1.35936 + TIFFSetErrorHandler(0); 1.35937 +#endif 1.35938 + cimglist_for(*this,l) data[l]._load_tiff(tif,nfirst_frame+l*nstep_frame); 1.35939 + TIFFClose(tif); 1.35940 + } else throw CImgException("CImgList<%s>::load_tiff() : File '%s' cannot be opened.", 1.35941 + pixel_type(),filename); 1.35942 + return *this; 1.35943 +#endif 1.35944 + } 1.35945 + 1.35946 + static CImgList<T> get_load_tiff(const char *const filename, 1.35947 + const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.35948 + const unsigned int step_frame=1) { 1.35949 + return CImgList<T>().load_tiff(filename,first_frame,last_frame,step_frame); 1.35950 + } 1.35951 + 1.35952 + //! Save an image list into a file. 1.35953 + /** 1.35954 + Depending on the extension of the given filename, a file format is chosen for the output file. 1.35955 + **/ 1.35956 + const CImgList<T>& save(const char *const filename, const int number=-1) const { 1.35957 + if (is_empty()) 1.35958 + throw CImgInstanceException("CImgList<%s>::save() : File '%s, instance list (%u,%p) is empty.", 1.35959 + pixel_type(),filename?filename:"(null)",size,data); 1.35960 + if (!filename) 1.35961 + throw CImgArgumentException("CImg<%s>::save() : Instance list (%u,%p), specified filename is (null).", 1.35962 + pixel_type(),size,data); 1.35963 + const char *ext = cimg::split_filename(filename); 1.35964 + char nfilename[1024]; 1.35965 + const char *const fn = (number>=0)?cimg::number_filename(filename,number,6,nfilename):filename; 1.35966 +#ifdef cimglist_save_plugin 1.35967 + cimglist_save_plugin(fn); 1.35968 +#endif 1.35969 +#ifdef cimglist_save_plugin1 1.35970 + cimglist_save_plugin1(fn); 1.35971 +#endif 1.35972 +#ifdef cimglist_save_plugin2 1.35973 + cimglist_save_plugin2(fn); 1.35974 +#endif 1.35975 +#ifdef cimglist_save_plugin3 1.35976 + cimglist_save_plugin3(fn); 1.35977 +#endif 1.35978 +#ifdef cimglist_save_plugin4 1.35979 + cimglist_save_plugin4(fn); 1.35980 +#endif 1.35981 +#ifdef cimglist_save_plugin5 1.35982 + cimglist_save_plugin5(fn); 1.35983 +#endif 1.35984 +#ifdef cimglist_save_plugin6 1.35985 + cimglist_save_plugin6(fn); 1.35986 +#endif 1.35987 +#ifdef cimglist_save_plugin7 1.35988 + cimglist_save_plugin7(fn); 1.35989 +#endif 1.35990 +#ifdef cimglist_save_plugin8 1.35991 + cimglist_save_plugin8(fn); 1.35992 +#endif 1.35993 +#ifdef cimg_use_tiff 1.35994 + if (!cimg::strcasecmp(ext,"tif") || 1.35995 + !cimg::strcasecmp(ext,"tiff")) return save_tiff(fn); 1.35996 +#endif 1.35997 + if (!cimg::strcasecmp(ext,"cimgz")) return save_cimg(fn,true); 1.35998 + if (!cimg::strcasecmp(ext,"cimg") || !ext[0]) return save_cimg(fn,false); 1.35999 + if (!cimg::strcasecmp(ext,"yuv")) return save_yuv(fn,true); 1.36000 + if (!cimg::strcasecmp(ext,"avi") || 1.36001 + !cimg::strcasecmp(ext,"mov") || 1.36002 + !cimg::strcasecmp(ext,"asf") || 1.36003 + !cimg::strcasecmp(ext,"divx") || 1.36004 + !cimg::strcasecmp(ext,"flv") || 1.36005 + !cimg::strcasecmp(ext,"mpg") || 1.36006 + !cimg::strcasecmp(ext,"m1v") || 1.36007 + !cimg::strcasecmp(ext,"m2v") || 1.36008 + !cimg::strcasecmp(ext,"m4v") || 1.36009 + !cimg::strcasecmp(ext,"mjp") || 1.36010 + !cimg::strcasecmp(ext,"mkv") || 1.36011 + !cimg::strcasecmp(ext,"mpe") || 1.36012 + !cimg::strcasecmp(ext,"movie") || 1.36013 + !cimg::strcasecmp(ext,"ogm") || 1.36014 + !cimg::strcasecmp(ext,"qt") || 1.36015 + !cimg::strcasecmp(ext,"rm") || 1.36016 + !cimg::strcasecmp(ext,"vob") || 1.36017 + !cimg::strcasecmp(ext,"wmv") || 1.36018 + !cimg::strcasecmp(ext,"xvid") || 1.36019 + !cimg::strcasecmp(ext,"mpeg")) return save_ffmpeg(fn); 1.36020 + if (!cimg::strcasecmp(ext,"gz")) return save_gzip_external(fn); 1.36021 + if (size==1) data[0].save(fn,-1); else cimglist_for(*this,l) data[l].save(fn,l); 1.36022 + return *this; 1.36023 + } 1.36024 + 1.36025 + //! Save an image sequence, using FFMPEG library. 1.36026 + // This piece of code has been originally written by David. G. Starkweather. 1.36027 + const CImgList<T>& save_ffmpeg(const char *const filename, const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.36028 + const unsigned int fps=25) const { 1.36029 + if (is_empty()) 1.36030 + throw CImgInstanceException("CImgList<%s>::save_ffmpeg() : File '%s', instance list (%u,%p) is empty.", 1.36031 + pixel_type(),filename?filename:"(null)",size,data); 1.36032 + if (!filename) 1.36033 + throw CImgArgumentException("CImgList<%s>::save_ffmpeg() : Instance list (%u,%p), specified filename is (null).", 1.36034 + pixel_type(),size,data); 1.36035 + if (!fps) 1.36036 + throw CImgArgumentException("CImgList<%s>::save_ffmpeg() : File '%s', specified framerate is 0.", 1.36037 + pixel_type(),filename); 1.36038 + const unsigned int nlast_frame = last_frame==~0U?size-1:last_frame; 1.36039 + if (first_frame>=size || nlast_frame>=size) 1.36040 + throw CImgArgumentException("CImgList<%s>::save_ffmpeg() : File '%s', specified frames [%u,%u] are out of list range (%u elements).", 1.36041 + pixel_type(),filename,first_frame,last_frame,size); 1.36042 + for (unsigned int ll = first_frame; ll<=nlast_frame; ++ll) if (!data[ll].is_sameXYZ(data[0])) 1.36043 + throw CImgInstanceException("CImgList<%s>::save_ffmpeg() : File '%s', images of the sequence have different dimensions.", 1.36044 + pixel_type(),filename); 1.36045 + 1.36046 +#ifndef cimg_use_ffmpeg 1.36047 + return save_ffmpeg_external(filename,first_frame,last_frame); 1.36048 +#else 1.36049 + avcodec_register_all(); 1.36050 + av_register_all(); 1.36051 + const int 1.36052 + frame_dimx = data[first_frame].dimx(), 1.36053 + frame_dimy = data[first_frame].dimy(), 1.36054 + frame_dimv = data[first_frame].dimv(); 1.36055 + if (frame_dimv!=1 && frame_dimv!=3) 1.36056 + throw CImgInstanceException("CImgList<%s>::save_ffmpeg() : File '%s', image[0] (%u,%u,%u,%u,%p) has not 1 or 3 channels.", 1.36057 + pixel_type(),filename,data[0].width,data[0].height,data[0].depth,data[0].dim,data); 1.36058 + 1.36059 + PixelFormat dest_pxl_fmt = PIX_FMT_YUV420P; 1.36060 + PixelFormat src_pxl_fmt = (frame_dimv == 3)?PIX_FMT_RGB24:PIX_FMT_GRAY8; 1.36061 + 1.36062 + int sws_flags = SWS_FAST_BILINEAR; // Interpolation method (keeping same size images for now). 1.36063 + AVOutputFormat *fmt = 0; 1.36064 + fmt = guess_format(0,filename,0); 1.36065 + if (!fmt) fmt = guess_format("mpeg",0,0); // Default format "mpeg". 1.36066 + if (!fmt) 1.36067 + throw CImgArgumentException("CImgList<%s>::save_ffmpeg() : File '%s', could not determine file format from filename.", 1.36068 + pixel_type(),filename); 1.36069 + 1.36070 + AVFormatContext *oc = 0; 1.36071 + oc = av_alloc_format_context(); 1.36072 + if (!oc) // Failed to allocate format context. 1.36073 + throw CImgIOException("CImgList<%s>::save_ffmpeg() : File '%s', failed to allocate structure for format context.", 1.36074 + pixel_type(),filename); 1.36075 + 1.36076 + AVCodec *codec = 0; 1.36077 + AVFrame *picture = 0; 1.36078 + AVFrame *tmp_pict = 0; 1.36079 + oc->oformat = fmt; 1.36080 + cimg_std::sprintf(oc->filename,"%s",filename); 1.36081 + 1.36082 + // Add video stream. 1.36083 + int stream_index = 0; 1.36084 + AVStream *video_str = 0; 1.36085 + if (fmt->video_codec!=CODEC_ID_NONE) { 1.36086 + video_str = av_new_stream(oc,stream_index); 1.36087 + if (!video_str) { // Failed to allocate stream. 1.36088 + av_free(oc); 1.36089 + throw CImgIOException("CImgList<%s>::save_ffmpeg() : File '%s', failed to allocate video stream structure.", 1.36090 + pixel_type(),filename); 1.36091 + } 1.36092 + } else { // No codec identified. 1.36093 + av_free(oc); 1.36094 + throw CImgIOException("CImgList<%s>::save_ffmpeg() : File '%s', no proper codec identified.", 1.36095 + pixel_type(),filename); 1.36096 + } 1.36097 + 1.36098 + AVCodecContext *c = video_str->codec; 1.36099 + c->codec_id = fmt->video_codec; 1.36100 + c->codec_type = CODEC_TYPE_VIDEO; 1.36101 + c->bit_rate = 400000; 1.36102 + c->width = frame_dimx; 1.36103 + c->height = frame_dimy; 1.36104 + c->time_base.num = 1; 1.36105 + c->time_base.den = fps; 1.36106 + c->gop_size = 12; 1.36107 + c->pix_fmt = dest_pxl_fmt; 1.36108 + if (c->codec_id == CODEC_ID_MPEG2VIDEO) c->max_b_frames = 2; 1.36109 + if (c->codec_id == CODEC_ID_MPEG1VIDEO) c->mb_decision = 2; 1.36110 + 1.36111 + if (av_set_parameters(oc,0)<0) { // Parameters not properly set. 1.36112 + av_free(oc); 1.36113 + throw CImgIOException("CImgList<%s>::save_ffmpeg() : File '%s', parameters for avcodec not properly set.", 1.36114 + pixel_type(),filename); 1.36115 + } 1.36116 + 1.36117 + // Open codecs and alloc buffers. 1.36118 + codec = avcodec_find_encoder(c->codec_id); 1.36119 + if (!codec) { // Failed to find codec. 1.36120 + av_free(oc); 1.36121 + throw CImgIOException("CImgList<%s>::save_ffmpeg() : File '%s', no codec found.", 1.36122 + pixel_type(),filename); 1.36123 + } 1.36124 + if (avcodec_open(c,codec)<0) // Failed to open codec. 1.36125 + throw CImgIOException("CImgList<%s>::save_ffmpeg() : File '%s', failed to open codec.", 1.36126 + pixel_type(),filename); 1.36127 + tmp_pict = avcodec_alloc_frame(); 1.36128 + if (!tmp_pict) { // Failed to allocate memory for tmp_pict frame. 1.36129 + avcodec_close(video_str->codec); 1.36130 + av_free(oc); 1.36131 + throw CImgIOException("CImgList<%s>::save_ffmpeg() : File '%s', failed to allocate memory for data buffer.", 1.36132 + pixel_type(),filename); 1.36133 + } 1.36134 + tmp_pict->linesize[0] = (src_pxl_fmt==PIX_FMT_RGB24)?3*frame_dimx:frame_dimx; 1.36135 + tmp_pict->type = FF_BUFFER_TYPE_USER; 1.36136 + int tmp_size = avpicture_get_size(src_pxl_fmt,frame_dimx,frame_dimy); 1.36137 + uint8_t *tmp_buffer = (uint8_t*)av_malloc(tmp_size); 1.36138 + if (!tmp_buffer) { // Failed to allocate memory for tmp buffer. 1.36139 + av_free(tmp_pict); 1.36140 + avcodec_close(video_str->codec); 1.36141 + av_free(oc); 1.36142 + throw CImgIOException("CImgList<%s>::save_ffmpeg() : File '%s', failed to allocate memory for data buffer.", 1.36143 + pixel_type(),filename); 1.36144 + } 1.36145 + 1.36146 + // Associate buffer with tmp_pict. 1.36147 + avpicture_fill((AVPicture*)tmp_pict,tmp_buffer,src_pxl_fmt,frame_dimx,frame_dimy); 1.36148 + picture = avcodec_alloc_frame(); 1.36149 + if (!picture) { // Failed to allocate picture frame. 1.36150 + av_free(tmp_pict->data[0]); 1.36151 + av_free(tmp_pict); 1.36152 + avcodec_close(video_str->codec); 1.36153 + av_free(oc); 1.36154 + throw CImgIOException("CImgList<%s>::save_ffmpeg() : File '%s', failed to allocate memory for picture frame.", 1.36155 + pixel_type(),filename); 1.36156 + } 1.36157 + 1.36158 + int size = avpicture_get_size(c->pix_fmt,frame_dimx,frame_dimy); 1.36159 + uint8_t *buffer = (uint8_t*)av_malloc(size); 1.36160 + if (!buffer) { // Failed to allocate picture frame buffer. 1.36161 + av_free(picture); 1.36162 + av_free(tmp_pict->data[0]); 1.36163 + av_free(tmp_pict); 1.36164 + avcodec_close(video_str->codec); 1.36165 + av_free(oc); 1.36166 + throw CImgIOException("CImgList<%s>::save_ffmpeg() : File '%s', failed to allocate memory for picture frame buffer.", 1.36167 + pixel_type(),filename); 1.36168 + } 1.36169 + 1.36170 + // Associate the buffer with picture. 1.36171 + avpicture_fill((AVPicture*)picture,buffer,c->pix_fmt,frame_dimx,frame_dimy); 1.36172 + 1.36173 + // Open file. 1.36174 + if (!(fmt->flags&AVFMT_NOFILE)) { 1.36175 + if (url_fopen(&oc->pb,filename,URL_WRONLY)<0) 1.36176 + throw CImgIOException("CImgList<%s>::save_ffmpeg() : File '%s' cannot be opened.", 1.36177 + pixel_type(),filename); 1.36178 + } 1.36179 + 1.36180 + if (av_write_header(oc)<0) 1.36181 + throw CImgIOException("CImgList<%s>::save_ffmpeg() : File '%s', could not write header.", 1.36182 + pixel_type(),filename); 1.36183 + double video_pts; 1.36184 + SwsContext *img_convert_context = 0; 1.36185 + img_convert_context = sws_getContext(frame_dimx,frame_dimy,src_pxl_fmt, 1.36186 + c->width,c->height,c->pix_fmt,sws_flags,0,0,0); 1.36187 + if (!img_convert_context) { // Failed to get swscale context. 1.36188 + // if (!(fmt->flags & AVFMT_NOFILE)) url_fclose(&oc->pb); 1.36189 + av_free(picture->data); 1.36190 + av_free(picture); 1.36191 + av_free(tmp_pict->data[0]); 1.36192 + av_free(tmp_pict); 1.36193 + avcodec_close(video_str->codec); 1.36194 + av_free(oc); 1.36195 + throw CImgIOException("CImgList<%s>::save_ffmpeg() : File '%', failed to get conversion context.", 1.36196 + pixel_type(),filename); 1.36197 + } 1.36198 + int ret = 0, out_size; 1.36199 + uint8_t *video_outbuf = 0; 1.36200 + int video_outbuf_size = 1000000; 1.36201 + video_outbuf = (uint8_t*)av_malloc(video_outbuf_size); 1.36202 + if (!video_outbuf) { 1.36203 + // if (!(fmt->flags & AVFMT_NOFILE)) url_fclose(&oc->pb); 1.36204 + av_free(picture->data); 1.36205 + av_free(picture); 1.36206 + av_free(tmp_pict->data[0]); 1.36207 + av_free(tmp_pict); 1.36208 + avcodec_close(video_str->codec); 1.36209 + av_free(oc); 1.36210 + throw CImgIOException("CImgList<%s>::save_ffmpeg() : File '%s', memory allocation error.", 1.36211 + pixel_type(),filename); 1.36212 + } 1.36213 + 1.36214 + // Loop through each desired image in list. 1.36215 + for (unsigned int i = first_frame; i<=nlast_frame; ++i) { 1.36216 + CImg<uint8_t> currentIm = data[i], red, green, blue, gray; 1.36217 + if (src_pxl_fmt == PIX_FMT_RGB24) { 1.36218 + red = currentIm.get_shared_channel(0); 1.36219 + green = currentIm.get_shared_channel(1); 1.36220 + blue = currentIm.get_shared_channel(2); 1.36221 + cimg_forXY(currentIm,X,Y) { // Assign pizel values to data buffer in interlaced RGBRGB ... format. 1.36222 + tmp_pict->data[0][Y*tmp_pict->linesize[0] + 3*X] = red(X,Y); 1.36223 + tmp_pict->data[0][Y*tmp_pict->linesize[0] + 3*X + 1] = green(X,Y); 1.36224 + tmp_pict->data[0][Y*tmp_pict->linesize[0] + 3*X + 2] = blue(X,Y); 1.36225 + } 1.36226 + } else { 1.36227 + gray = currentIm.get_shared_channel(0); 1.36228 + cimg_forXY(currentIm,X,Y) tmp_pict->data[0][Y*tmp_pict->linesize[0] + X] = gray(X,Y); 1.36229 + } 1.36230 + 1.36231 + if (video_str) video_pts = (video_str->pts.val * video_str->time_base.num)/(video_str->time_base.den); 1.36232 + else video_pts = 0.0; 1.36233 + if (!video_str) break; 1.36234 + if (sws_scale(img_convert_context,tmp_pict->data,tmp_pict->linesize,0,c->height,picture->data,picture->linesize)<0) break; 1.36235 + out_size = avcodec_encode_video(c,video_outbuf,video_outbuf_size,picture); 1.36236 + if (out_size>0) { 1.36237 + AVPacket pkt; 1.36238 + av_init_packet(&pkt); 1.36239 + pkt.pts = av_rescale_q(c->coded_frame->pts,c->time_base,video_str->time_base); 1.36240 + if (c->coded_frame->key_frame) pkt.flags|=PKT_FLAG_KEY; 1.36241 + pkt.stream_index = video_str->index; 1.36242 + pkt.data = video_outbuf; 1.36243 + pkt.size = out_size; 1.36244 + ret = av_write_frame(oc,&pkt); 1.36245 + } else if (out_size<0) break; 1.36246 + if (ret) break; // Error occured in writing frame. 1.36247 + } 1.36248 + 1.36249 + // Close codec. 1.36250 + if (video_str) { 1.36251 + avcodec_close(video_str->codec); 1.36252 + av_free(picture->data[0]); 1.36253 + av_free(picture); 1.36254 + av_free(tmp_pict->data[0]); 1.36255 + av_free(tmp_pict); 1.36256 + } 1.36257 + if (av_write_trailer(oc)<0) 1.36258 + throw CImgIOException("CImgList<%s>::save_ffmpeg() : File '%s', failed to write trailer.", 1.36259 + pixel_type(),filename); 1.36260 + av_freep(&oc->streams[stream_index]->codec); 1.36261 + av_freep(&oc->streams[stream_index]); 1.36262 + if (!(fmt->flags&AVFMT_NOFILE)) { 1.36263 + /*if (url_fclose(oc->pb)<0) 1.36264 + throw CImgIOException("CImgList<%s>::save_ffmpeg() : File '%s', failed to close file.", 1.36265 + pixel_type(),filename); 1.36266 + */ 1.36267 + } 1.36268 + av_free(oc); 1.36269 + av_free(video_outbuf); 1.36270 +#endif 1.36271 + return *this; 1.36272 + } 1.36273 + 1.36274 + // Save an image sequence into a YUV file (internal). 1.36275 + const CImgList<T>& _save_yuv(cimg_std::FILE *const file, const char *const filename, const bool rgb2yuv) const { 1.36276 + if (is_empty()) 1.36277 + throw CImgInstanceException("CImgList<%s>::save_yuv() : File '%s', instance list (%u,%p) is empty.", 1.36278 + pixel_type(),filename?filename:"(FILE*)",size,data); 1.36279 + if (!file && !filename) 1.36280 + throw CImgArgumentException("CImg<%s>::save_yuv() : Instance list (%u,%p), specified file is (null).", 1.36281 + pixel_type(),size,data); 1.36282 + if ((*this)[0].dimx()%2 || (*this)[0].dimy()%2) 1.36283 + throw CImgInstanceException("CImgList<%s>::save_yuv() : File '%s', image dimensions must be even numbers (current are %ux%u).", 1.36284 + pixel_type(),filename?filename:"(FILE*)",(*this)[0].dimx(),(*this)[0].dimy()); 1.36285 + 1.36286 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); 1.36287 + cimglist_for(*this,l) { 1.36288 + CImg<ucharT> YCbCr((*this)[l]); 1.36289 + if (rgb2yuv) YCbCr.RGBtoYCbCr(); 1.36290 + cimg::fwrite(YCbCr.data,YCbCr.width*YCbCr.height,nfile); 1.36291 + cimg::fwrite(YCbCr.get_resize(YCbCr.width/2, YCbCr.height/2,1,3,3).ptr(0,0,0,1), 1.36292 + YCbCr.width*YCbCr.height/2,nfile); 1.36293 + } 1.36294 + if (!file) cimg::fclose(nfile); 1.36295 + return *this; 1.36296 + } 1.36297 + 1.36298 + //! Save an image sequence into a YUV file. 1.36299 + const CImgList<T>& save_yuv(const char *const filename=0, const bool rgb2yuv=true) const { 1.36300 + return _save_yuv(0,filename,rgb2yuv); 1.36301 + } 1.36302 + 1.36303 + //! Save an image sequence into a YUV file. 1.36304 + const CImgList<T>& save_yuv(cimg_std::FILE *const file, const bool rgb2yuv=true) const { 1.36305 + return _save_yuv(file,0,rgb2yuv); 1.36306 + } 1.36307 + 1.36308 + //! Save an image list into a .cimg file. 1.36309 + /** 1.36310 + A CImg RAW file is a simple uncompressed binary file that may be used to save list of CImg<T> images. 1.36311 + \param filename : name of the output file. 1.36312 + \return A reference to the current CImgList instance is returned. 1.36313 + **/ 1.36314 + const CImgList<T>& _save_cimg(cimg_std::FILE *const file, const char *const filename, const bool compression) const { 1.36315 + if (is_empty()) 1.36316 + throw CImgInstanceException("CImgList<%s>::save_cimg() : File '%s', instance list (%u,%p) is empty.", 1.36317 + pixel_type(),filename?filename:"(FILE*)",size,data); 1.36318 + if (!file && !filename) 1.36319 + throw CImgArgumentException("CImg<%s>::save_cimg() : Instance list (%u,%p), specified file is (null).", 1.36320 + pixel_type(),size,data); 1.36321 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); 1.36322 + const char *const ptype = pixel_type(), *const etype = cimg::endianness()?"big":"little"; 1.36323 + if (cimg_std::strstr(ptype,"unsigned")==ptype) cimg_std::fprintf(nfile,"%u unsigned_%s %s_endian\n",size,ptype+9,etype); 1.36324 + else cimg_std::fprintf(nfile,"%u %s %s_endian\n",size,ptype,etype); 1.36325 + cimglist_for(*this,l) { 1.36326 + const CImg<T>& img = data[l]; 1.36327 + cimg_std::fprintf(nfile,"%u %u %u %u",img.width,img.height,img.depth,img.dim); 1.36328 + if (img.data) { 1.36329 + CImg<T> tmp; 1.36330 + if (cimg::endianness()) { tmp = img; cimg::invert_endianness(tmp.data,tmp.size()); } 1.36331 + const CImg<T>& ref = cimg::endianness()?tmp:img; 1.36332 + bool compressed = false; 1.36333 + if (compression) { 1.36334 +#ifdef cimg_use_zlib 1.36335 + const unsigned long siz = sizeof(T)*ref.size(); 1.36336 + unsigned long csiz = siz + siz/10 + 16; 1.36337 + Bytef *const cbuf = new Bytef[csiz]; 1.36338 + if (compress(cbuf,&csiz,(Bytef*)ref.data,siz)) { 1.36339 + cimg::warn("CImgList<%s>::save_cimg() : File '%s', failed to save compressed data.\n Data will be saved uncompressed.", 1.36340 + pixel_type(),filename?filename:"(FILE*)"); 1.36341 + compressed = false; 1.36342 + } else { 1.36343 + cimg_std::fprintf(nfile," #%lu\n",csiz); 1.36344 + cimg::fwrite(cbuf,csiz,nfile); 1.36345 + delete[] cbuf; 1.36346 + compressed = true; 1.36347 + } 1.36348 +#else 1.36349 + cimg::warn("CImgList<%s>::save_cimg() : File '%s', cannot save compressed data unless zlib is used " 1.36350 + "('cimg_use_zlib' must be defined).\n Data will be saved uncompressed.", 1.36351 + pixel_type(),filename?filename:"(FILE*)"); 1.36352 + compressed = false; 1.36353 +#endif 1.36354 + } 1.36355 + if (!compressed) { 1.36356 + cimg_std::fputc('\n',nfile); 1.36357 + cimg::fwrite(ref.data,ref.size(),nfile); 1.36358 + } 1.36359 + } else cimg_std::fputc('\n',nfile); 1.36360 + } 1.36361 + if (!file) cimg::fclose(nfile); 1.36362 + return *this; 1.36363 + } 1.36364 + 1.36365 + //! Save an image list into a CImg file (RAW binary file + simple header) 1.36366 + const CImgList<T>& save_cimg(cimg_std::FILE *file, const bool compress=false) const { 1.36367 + return _save_cimg(file,0,compress); 1.36368 + } 1.36369 + 1.36370 + //! Save an image list into a CImg file (RAW binary file + simple header) 1.36371 + const CImgList<T>& save_cimg(const char *const filename, const bool compress=false) const { 1.36372 + return _save_cimg(0,filename,compress); 1.36373 + } 1.36374 + 1.36375 + // Insert the instance image into into an existing .cimg file, at specified coordinates. 1.36376 + const CImgList<T>& _save_cimg(cimg_std::FILE *const file, const char *const filename, 1.36377 + const unsigned int n0, 1.36378 + const unsigned int x0, const unsigned int y0, 1.36379 + const unsigned int z0, const unsigned int v0) const { 1.36380 +#define _cimg_save_cimg_case(Ts,Tss) \ 1.36381 + if (!saved && !cimg::strcasecmp(Ts,str_pixeltype)) { \ 1.36382 + for (unsigned int l=0; l<lmax; ++l) { \ 1.36383 + j = 0; while((i=cimg_std::fgetc(nfile))!='\n') tmp[j++]=(char)i; tmp[j]='\0'; \ 1.36384 + W = H = D = V = 0; \ 1.36385 + if (cimg_std::sscanf(tmp,"%u %u %u %u",&W,&H,&D,&V)!=4) \ 1.36386 + throw CImgIOException("CImgList<%s>::save_cimg() : File '%s', Image %u has an invalid size (%u,%u,%u,%u)\n", \ 1.36387 + pixel_type(), filename?filename:("(FILE*)"), W, H, D, V); \ 1.36388 + if (W*H*D*V>0) { \ 1.36389 + if (l<n0 || x0>=W || y0>=H || z0>=D || v0>=D) cimg_std::fseek(nfile,W*H*D*V*sizeof(Tss),SEEK_CUR); \ 1.36390 + else { \ 1.36391 + const CImg<T>& img = (*this)[l-n0]; \ 1.36392 + const T *ptrs = img.data; \ 1.36393 + const unsigned int \ 1.36394 + x1 = x0 + img.width - 1, \ 1.36395 + y1 = y0 + img.height - 1, \ 1.36396 + z1 = z0 + img.depth - 1, \ 1.36397 + v1 = v0 + img.dim - 1, \ 1.36398 + nx1 = x1>=W?W-1:x1, \ 1.36399 + ny1 = y1>=H?H-1:y1, \ 1.36400 + nz1 = z1>=D?D-1:z1, \ 1.36401 + nv1 = v1>=V?V-1:v1; \ 1.36402 + CImg<Tss> raw(1+nx1-x0); \ 1.36403 + const unsigned int skipvb = v0*W*H*D*sizeof(Tss); \ 1.36404 + if (skipvb) cimg_std::fseek(nfile,skipvb,SEEK_CUR); \ 1.36405 + for (unsigned int v=1+nv1-v0; v; --v) { \ 1.36406 + const unsigned int skipzb = z0*W*H*sizeof(Tss); \ 1.36407 + if (skipzb) cimg_std::fseek(nfile,skipzb,SEEK_CUR); \ 1.36408 + for (unsigned int z=1+nz1-z0; z; --z) { \ 1.36409 + const unsigned int skipyb = y0*W*sizeof(Tss); \ 1.36410 + if (skipyb) cimg_std::fseek(nfile,skipyb,SEEK_CUR); \ 1.36411 + for (unsigned int y=1+ny1-y0; y; --y) { \ 1.36412 + const unsigned int skipxb = x0*sizeof(Tss); \ 1.36413 + if (skipxb) cimg_std::fseek(nfile,skipxb,SEEK_CUR); \ 1.36414 + raw.assign(ptrs, raw.width); \ 1.36415 + ptrs+=img.width; \ 1.36416 + if (endian) cimg::invert_endianness(raw.data,raw.width); \ 1.36417 + cimg::fwrite(raw.data,raw.width,nfile); \ 1.36418 + const unsigned int skipxe = (W-1-nx1)*sizeof(Tss); \ 1.36419 + if (skipxe) cimg_std::fseek(nfile,skipxe,SEEK_CUR); \ 1.36420 + } \ 1.36421 + const unsigned int skipye = (H-1-ny1)*W*sizeof(Tss); \ 1.36422 + if (skipye) cimg_std::fseek(nfile,skipye,SEEK_CUR); \ 1.36423 + } \ 1.36424 + const unsigned int skipze = (D-1-nz1)*W*H*sizeof(Tss); \ 1.36425 + if (skipze) cimg_std::fseek(nfile,skipze,SEEK_CUR); \ 1.36426 + } \ 1.36427 + const unsigned int skipve = (V-1-nv1)*W*H*D*sizeof(Tss); \ 1.36428 + if (skipve) cimg_std::fseek(nfile,skipve,SEEK_CUR); \ 1.36429 + } \ 1.36430 + } \ 1.36431 + } \ 1.36432 + saved = true; \ 1.36433 + } 1.36434 + if (is_empty()) 1.36435 + throw CImgInstanceException("CImgList<%s>::save_cimg() : File '%s', instance list (%u,%p) is empty.", 1.36436 + pixel_type(),filename?filename:"(FILE*)",size,data); 1.36437 + if (!file && !filename) 1.36438 + throw CImgArgumentException("CImg<%s>::save_cimg() : Instance list (%u,%p), specified file is (null).", 1.36439 + pixel_type(),size,data); 1.36440 + typedef unsigned char uchar; 1.36441 + typedef unsigned short ushort; 1.36442 + typedef unsigned int uint; 1.36443 + typedef unsigned long ulong; 1.36444 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"rb+"); 1.36445 + bool saved = false, endian = cimg::endianness(); 1.36446 + char tmp[256], str_pixeltype[256], str_endian[256]; 1.36447 + unsigned int j, err, N, W, H, D, V; 1.36448 + int i; 1.36449 + j = 0; while((i=cimg_std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = '\0'; 1.36450 + err = cimg_std::sscanf(tmp,"%u%*c%255[A-Za-z_]%*c%255[sA-Za-z_ ]",&N,str_pixeltype,str_endian); 1.36451 + if (err<2) { 1.36452 + if (!file) cimg::fclose(nfile); 1.36453 + throw CImgIOException("CImgList<%s>::save_cimg() : File '%s', Unknow CImg RAW header.", 1.36454 + pixel_type(),filename?filename:"(FILE*)"); 1.36455 + } 1.36456 + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; 1.36457 + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; 1.36458 + const unsigned int lmax = cimg::min(N,n0+size); 1.36459 + _cimg_save_cimg_case("bool",bool); 1.36460 + _cimg_save_cimg_case("unsigned_char",uchar); 1.36461 + _cimg_save_cimg_case("uchar",uchar); 1.36462 + _cimg_save_cimg_case("char",char); 1.36463 + _cimg_save_cimg_case("unsigned_short",ushort); 1.36464 + _cimg_save_cimg_case("ushort",ushort); 1.36465 + _cimg_save_cimg_case("short",short); 1.36466 + _cimg_save_cimg_case("unsigned_int",uint); 1.36467 + _cimg_save_cimg_case("uint",uint); 1.36468 + _cimg_save_cimg_case("int",int); 1.36469 + _cimg_save_cimg_case("unsigned_long",ulong); 1.36470 + _cimg_save_cimg_case("ulong",ulong); 1.36471 + _cimg_save_cimg_case("long",long); 1.36472 + _cimg_save_cimg_case("float",float); 1.36473 + _cimg_save_cimg_case("double",double); 1.36474 + if (!saved) { 1.36475 + if (!file) cimg::fclose(nfile); 1.36476 + throw CImgIOException("CImgList<%s>::save_cimg() : File '%s', cannot save images of pixels coded as '%s'.", 1.36477 + pixel_type(),filename?filename:"(FILE*)",str_pixeltype); 1.36478 + } 1.36479 + if (!file) cimg::fclose(nfile); 1.36480 + return *this; 1.36481 + } 1.36482 + 1.36483 + //! Insert the instance image into into an existing .cimg file, at specified coordinates. 1.36484 + const CImgList<T>& save_cimg(const char *const filename, 1.36485 + const unsigned int n0, 1.36486 + const unsigned int x0, const unsigned int y0, 1.36487 + const unsigned int z0, const unsigned int v0) const { 1.36488 + return _save_cimg(0,filename,n0,x0,y0,z0,v0); 1.36489 + } 1.36490 + 1.36491 + //! Insert the instance image into into an existing .cimg file, at specified coordinates. 1.36492 + const CImgList<T>& save_cimg(cimg_std::FILE *const file, 1.36493 + const unsigned int n0, 1.36494 + const unsigned int x0, const unsigned int y0, 1.36495 + const unsigned int z0, const unsigned int v0) const { 1.36496 + return _save_cimg(file,0,n0,x0,y0,z0,v0); 1.36497 + } 1.36498 + 1.36499 + // Create an empty .cimg file with specified dimensions (internal) 1.36500 + static void _save_empty_cimg(cimg_std::FILE *const file, const char *const filename, 1.36501 + const unsigned int nb, 1.36502 + const unsigned int dx, const unsigned int dy, 1.36503 + const unsigned int dz, const unsigned int dv) { 1.36504 + cimg_std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); 1.36505 + const unsigned int siz = dx*dy*dz*dv*sizeof(T); 1.36506 + cimg_std::fprintf(nfile,"%u %s\n",nb,pixel_type()); 1.36507 + for (unsigned int i=nb; i; --i) { 1.36508 + cimg_std::fprintf(nfile,"%u %u %u %u\n",dx,dy,dz,dv); 1.36509 + for (unsigned int off=siz; off; --off) cimg_std::fputc(0,nfile); 1.36510 + } 1.36511 + if (!file) cimg::fclose(nfile); 1.36512 + } 1.36513 + 1.36514 + //! Create an empty .cimg file with specified dimensions. 1.36515 + static void save_empty_cimg(const char *const filename, 1.36516 + const unsigned int nb, 1.36517 + const unsigned int dx, const unsigned int dy=1, 1.36518 + const unsigned int dz=1, const unsigned int dv=1) { 1.36519 + return _save_empty_cimg(0,filename,nb,dx,dy,dz,dv); 1.36520 + } 1.36521 + 1.36522 + //! Create an empty .cimg file with specified dimensions. 1.36523 + static void save_empty_cimg(cimg_std::FILE *const file, 1.36524 + const unsigned int nb, 1.36525 + const unsigned int dx, const unsigned int dy=1, 1.36526 + const unsigned int dz=1, const unsigned int dv=1) { 1.36527 + return _save_empty_cimg(file,0,nb,dx,dy,dz,dv); 1.36528 + } 1.36529 + 1.36530 + //! Save a file in TIFF format. 1.36531 +#ifdef cimg_use_tiff 1.36532 + const CImgList<T>& save_tiff(const char *const filename) const { 1.36533 + if (is_empty()) 1.36534 + throw CImgInstanceException("CImgList<%s>::save_tiff() : File '%s', instance list (%u,%p) is empty.", 1.36535 + pixel_type(),filename?filename:"(null)",size,data); 1.36536 + if (!filename) 1.36537 + throw CImgArgumentException("CImgList<%s>::save_tiff() : Specified filename is (null) for instance list (%u,%p).", 1.36538 + pixel_type(),size,data); 1.36539 + TIFF *tif = TIFFOpen(filename,"w"); 1.36540 + if (tif) { 1.36541 + for (unsigned int dir=0, l=0; l<size; ++l) { 1.36542 + const CImg<T>& img = (*this)[l]; 1.36543 + if (img) { 1.36544 + if (img.depth==1) img._save_tiff(tif,dir++); 1.36545 + else cimg_forZ(img,z) img.get_slice(z)._save_tiff(tif,dir++); 1.36546 + } 1.36547 + } 1.36548 + TIFFClose(tif); 1.36549 + } else 1.36550 + throw CImgException("CImgList<%s>::save_tiff() : File '%s', error while opening stream for tiff file.", 1.36551 + pixel_type(),filename); 1.36552 + return *this; 1.36553 + } 1.36554 +#endif 1.36555 + 1.36556 + //! Save an image list as a gzipped file, using external tool 'gzip'. 1.36557 + const CImgList<T>& save_gzip_external(const char *const filename) const { 1.36558 + if (!filename) 1.36559 + throw CImgIOException("CImg<%s>::save_gzip_external() : Cannot save (null) filename.", 1.36560 + pixel_type()); 1.36561 + char command[1024], filetmp[512], body[512]; 1.36562 + const char 1.36563 + *ext = cimg::split_filename(filename,body), 1.36564 + *ext2 = cimg::split_filename(body,0); 1.36565 + cimg_std::FILE *file; 1.36566 + do { 1.36567 + if (!cimg::strcasecmp(ext,"gz")) { 1.36568 + if (*ext2) cimg_std::sprintf(filetmp,"%s%s%s.%s",cimg::temporary_path(),cimg_OS==2?"\\":"/", 1.36569 + cimg::filenamerand(),ext2); 1.36570 + else cimg_std::sprintf(filetmp,"%s%s%s.cimg",cimg::temporary_path(),cimg_OS==2?"\\":"/", 1.36571 + cimg::filenamerand()); 1.36572 + } else { 1.36573 + if (*ext) cimg_std::sprintf(filetmp,"%s%s%s.%s",cimg::temporary_path(),cimg_OS==2?"\\":"/", 1.36574 + cimg::filenamerand(),ext); 1.36575 + else cimg_std::sprintf(filetmp,"%s%s%s.cimg",cimg::temporary_path(),cimg_OS==2?"\\":"/", 1.36576 + cimg::filenamerand()); 1.36577 + } 1.36578 + if ((file=cimg_std::fopen(filetmp,"rb"))!=0) cimg_std::fclose(file); 1.36579 + } while (file); 1.36580 + save(filetmp); 1.36581 + cimg_std::sprintf(command,"%s -c %s > \"%s\"",cimg::gzip_path(),filetmp,filename); 1.36582 + cimg::system(command); 1.36583 + file = cimg_std::fopen(filename,"rb"); 1.36584 + if (!file) 1.36585 + throw CImgIOException("CImgList<%s>::save_gzip_external() : File '%s' cannot be saved.", 1.36586 + pixel_type(),filename); 1.36587 + else cimg::fclose(file); 1.36588 + cimg_std::remove(filetmp); 1.36589 + return *this; 1.36590 + } 1.36591 + 1.36592 + //! Save an image list into a OFF file. 1.36593 + template<typename tf, typename tc> 1.36594 + const CImgList<T>& save_off(const char *const filename, 1.36595 + const CImgList<tf>& primitives, const CImgList<tc>& colors, const bool invert_faces=false) const { 1.36596 + get_append('x','y').save_off(filename,primitives,colors,invert_faces); 1.36597 + return *this; 1.36598 + } 1.36599 + 1.36600 + //! Save an image list into a OFF file. 1.36601 + template<typename tf, typename tc> 1.36602 + const CImgList<T>& save_off(cimg_std::FILE *const file, 1.36603 + const CImgList<tf>& primitives, const CImgList<tc>& colors, const bool invert_faces=false) const { 1.36604 + get_append('x','y').save_off(file,primitives,colors,invert_faces); 1.36605 + return *this; 1.36606 + } 1.36607 + 1.36608 + //! Save an image sequence using the external tool 'ffmpeg'. 1.36609 + const CImgList<T>& save_ffmpeg_external(const char *const filename, const unsigned int first_frame=0, const unsigned int last_frame=~0U, 1.36610 + const char *const codec="mpeg2video") const { 1.36611 + if (is_empty()) 1.36612 + throw CImgInstanceException("CImgList<%s>::save_ffmpeg_external() : File '%s', instance list (%u,%p) is empty.", 1.36613 + pixel_type(),filename?filename:"(null)",size,data); 1.36614 + if (!filename) 1.36615 + throw CImgArgumentException("CImgList<%s>::save_ffmpeg_external() : Instance list (%u,%p), specified filename is (null).", 1.36616 + pixel_type(),size,data); 1.36617 + char command[1024], filetmp[512], filetmp2[512]; 1.36618 + cimg_std::FILE *file = 0; 1.36619 + const unsigned int nlast_frame = last_frame==~0U?size-1:last_frame; 1.36620 + if (first_frame>=size || nlast_frame>=size) 1.36621 + throw CImgArgumentException("CImgList<%s>::save_ffmpeg_external() : File '%s', specified frames [%u,%u] are out of list range (%u elements).", 1.36622 + pixel_type(),filename,first_frame,last_frame,size); 1.36623 + for (unsigned int ll = first_frame; ll<=nlast_frame; ++ll) if (!data[ll].is_sameXYZ(data[0])) 1.36624 + throw CImgInstanceException("CImgList<%s>::save_ffmpeg_external() : File '%s', all images of the sequence must be of the same dimension.", 1.36625 + pixel_type(),filename); 1.36626 + do { 1.36627 + cimg_std::sprintf(filetmp,"%s%s%s",cimg::temporary_path(),cimg_OS==2?"\\":"/",cimg::filenamerand()); 1.36628 + cimg_std::sprintf(filetmp2,"%s_000001.ppm",filetmp); 1.36629 + if ((file=cimg_std::fopen(filetmp2,"rb"))!=0) cimg_std::fclose(file); 1.36630 + } while (file); 1.36631 + for (unsigned int l = first_frame; l<=nlast_frame; ++l) { 1.36632 + cimg_std::sprintf(filetmp2,"%s_%.6u.ppm",filetmp,l+1); 1.36633 + if (data[l].depth>1 || data[l].dim!=3) data[l].get_resize(-100,-100,1,3).save_pnm(filetmp2); 1.36634 + else data[l].save_pnm(filetmp2); 1.36635 + } 1.36636 +#if cimg_OS!=2 1.36637 + cimg_std::sprintf(command,"ffmpeg -i %s_%%6d.ppm -vcodec %s -sameq -y \"%s\" >/dev/null 2>&1",filetmp,codec,filename); 1.36638 +#else 1.36639 + cimg_std::sprintf(command,"\"ffmpeg -i %s_%%6d.ppm -vcodec %s -sameq -y \"%s\"\" >NUL 2>&1",filetmp,codec,filename); 1.36640 +#endif 1.36641 + cimg::system(command); 1.36642 + file = cimg_std::fopen(filename,"rb"); 1.36643 + if (!file) 1.36644 + throw CImgIOException("CImg<%s>::save_ffmpeg_external() : Failed to save image sequence '%s'.\n\n", 1.36645 + pixel_type(),filename); 1.36646 + else cimg::fclose(file); 1.36647 + cimglist_for(*this,lll) { cimg_std::sprintf(filetmp2,"%s_%.6u.ppm",filetmp,lll+1); cimg_std::remove(filetmp2); } 1.36648 + return *this; 1.36649 + } 1.36650 + 1.36651 + }; 1.36652 + 1.36653 + /* 1.36654 + #--------------------------------------------- 1.36655 + # 1.36656 + # Completion of previously declared functions 1.36657 + # 1.36658 + #---------------------------------------------- 1.36659 + */ 1.36660 + 1.36661 +namespace cimg { 1.36662 + 1.36663 + //! Display a dialog box, where a user can click standard buttons. 1.36664 + /** 1.36665 + Up to 6 buttons can be defined in the dialog window. 1.36666 + This function returns when a user clicked one of the button or closed the dialog window. 1.36667 + \param title = Title of the dialog window. 1.36668 + \param msg = Main message displayed inside the dialog window. 1.36669 + \param button1_txt = Label of the 1st button. 1.36670 + \param button2_txt = Label of the 2nd button. 1.36671 + \param button3_txt = Label of the 3rd button. 1.36672 + \param button4_txt = Label of the 4th button. 1.36673 + \param button5_txt = Label of the 5th button. 1.36674 + \param button6_txt = Label of the 6th button. 1.36675 + \param logo = Logo image displayed at the left of the main message. This parameter is optional. 1.36676 + \param centering = Tell to center the dialog window on the screen. 1.36677 + \return The button number (from 0 to 5), or -1 if the dialog window has been closed by the user. 1.36678 + \note If a button text is set to 0, then the corresponding button (and the followings) won't appear in 1.36679 + the dialog box. At least one button is necessary. 1.36680 + **/ 1.36681 + 1.36682 + template<typename t> 1.36683 + inline int dialog(const char *title, const char *msg, 1.36684 + const char *button1_txt, const char *button2_txt, 1.36685 + const char *button3_txt, const char *button4_txt, 1.36686 + const char *button5_txt, const char *button6_txt, 1.36687 + const CImg<t>& logo, const bool centering = false) { 1.36688 +#if cimg_display!=0 1.36689 + const unsigned char 1.36690 + black[] = { 0,0,0 }, white[] = { 255,255,255 }, gray[] = { 200,200,200 }, gray2[] = { 150,150,150 }; 1.36691 + 1.36692 + // Create buttons and canvas graphics 1.36693 + CImgList<unsigned char> buttons, cbuttons, sbuttons; 1.36694 + if (button1_txt) { buttons.insert(CImg<unsigned char>().draw_text(0,0,button1_txt,black,gray,1,13)); 1.36695 + if (button2_txt) { buttons.insert(CImg<unsigned char>().draw_text(0,0,button2_txt,black,gray,1,13)); 1.36696 + if (button3_txt) { buttons.insert(CImg<unsigned char>().draw_text(0,0,button3_txt,black,gray,1,13)); 1.36697 + if (button4_txt) { buttons.insert(CImg<unsigned char>().draw_text(0,0,button4_txt,black,gray,1,13)); 1.36698 + if (button5_txt) { buttons.insert(CImg<unsigned char>().draw_text(0,0,button5_txt,black,gray,1,13)); 1.36699 + if (button6_txt) { buttons.insert(CImg<unsigned char>().draw_text(0,0,button6_txt,black,gray,1,13)); 1.36700 + }}}}}} 1.36701 + if (!buttons.size) 1.36702 + throw CImgArgumentException("cimg::dialog() : No buttons have been defined. At least one is necessary"); 1.36703 + 1.36704 + unsigned int bw = 0, bh = 0; 1.36705 + cimglist_for(buttons,l) { bw = cimg::max(bw,buttons[l].width); bh = cimg::max(bh,buttons[l].height); } 1.36706 + bw+=8; bh+=8; 1.36707 + if (bw<64) bw=64; 1.36708 + if (bw>128) bw=128; 1.36709 + if (bh<24) bh=24; 1.36710 + if (bh>48) bh=48; 1.36711 + 1.36712 + CImg<unsigned char> button(bw,bh,1,3); 1.36713 + button.draw_rectangle(0,0,bw-1,bh-1,gray); 1.36714 + button.draw_line(0,0,bw-1,0,white).draw_line(0,bh-1,0,0,white); 1.36715 + button.draw_line(bw-1,0,bw-1,bh-1,black).draw_line(bw-1,bh-1,0,bh-1,black); 1.36716 + button.draw_line(1,bh-2,bw-2,bh-2,gray2).draw_line(bw-2,bh-2,bw-2,1,gray2); 1.36717 + CImg<unsigned char> sbutton(bw,bh,1,3); 1.36718 + sbutton.draw_rectangle(0,0,bw-1,bh-1,gray); 1.36719 + sbutton.draw_line(0,0,bw-1,0,black).draw_line(bw-1,0,bw-1,bh-1,black); 1.36720 + sbutton.draw_line(bw-1,bh-1,0,bh-1,black).draw_line(0,bh-1,0,0,black); 1.36721 + sbutton.draw_line(1,1,bw-2,1,white).draw_line(1,bh-2,1,1,white); 1.36722 + sbutton.draw_line(bw-2,1,bw-2,bh-2,black).draw_line(bw-2,bh-2,1,bh-2,black); 1.36723 + sbutton.draw_line(2,bh-3,bw-3,bh-3,gray2).draw_line(bw-3,bh-3,bw-3,2,gray2); 1.36724 + 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); 1.36725 + 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); 1.36726 + CImg<unsigned char> cbutton(bw,bh,1,3); 1.36727 + 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); 1.36728 + 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); 1.36729 + 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); 1.36730 + 1.36731 + cimglist_for(buttons,ll) { 1.36732 + cbuttons.insert(CImg<unsigned char>(cbutton).draw_image(1+(bw-buttons[ll].dimx())/2,1+(bh-buttons[ll].dimy())/2,buttons[ll])); 1.36733 + sbuttons.insert(CImg<unsigned char>(sbutton).draw_image((bw-buttons[ll].dimx())/2,(bh-buttons[ll].dimy())/2,buttons[ll])); 1.36734 + buttons[ll] = CImg<unsigned char>(button).draw_image((bw-buttons[ll].dimx())/2,(bh-buttons[ll].dimy())/2,buttons[ll]); 1.36735 + } 1.36736 + 1.36737 + CImg<unsigned char> canvas; 1.36738 + if (msg) canvas = CImg<unsigned char>().draw_text(0,0,msg,black,gray,1,13); 1.36739 + const unsigned int 1.36740 + bwall = (buttons.size-1)*(12+bw) + bw, 1.36741 + w = cimg::max(196U,36+logo.width+canvas.width, 24+bwall), 1.36742 + h = cimg::max(96U,36+canvas.height+bh,36+logo.height+bh), 1.36743 + lx = 12 + (canvas.data?0:((w-24-logo.width)/2)), 1.36744 + ly = (h-12-bh-logo.height)/2, 1.36745 + tx = lx+logo.width+12, 1.36746 + ty = (h-12-bh-canvas.height)/2, 1.36747 + bx = (w-bwall)/2, 1.36748 + by = h-12-bh; 1.36749 + 1.36750 + if (canvas.data) 1.36751 + canvas = CImg<unsigned char>(w,h,1,3). 1.36752 + draw_rectangle(0,0,w-1,h-1,gray). 1.36753 + draw_line(0,0,w-1,0,white).draw_line(0,h-1,0,0,white). 1.36754 + draw_line(w-1,0,w-1,h-1,black).draw_line(w-1,h-1,0,h-1,black). 1.36755 + draw_image(tx,ty,canvas); 1.36756 + else 1.36757 + canvas = CImg<unsigned char>(w,h,1,3). 1.36758 + draw_rectangle(0,0,w-1,h-1,gray). 1.36759 + draw_line(0,0,w-1,0,white).draw_line(0,h-1,0,0,white). 1.36760 + draw_line(w-1,0,w-1,h-1,black).draw_line(w-1,h-1,0,h-1,black); 1.36761 + if (logo.data) canvas.draw_image(lx,ly,logo); 1.36762 + 1.36763 + unsigned int xbuttons[6]; 1.36764 + cimglist_for(buttons,lll) { xbuttons[lll] = bx+(bw+12)*lll; canvas.draw_image(xbuttons[lll],by,buttons[lll]); } 1.36765 + 1.36766 + // Open window and enter events loop 1.36767 + CImgDisplay disp(canvas,title?title:" ",0,false,centering?true:false); 1.36768 + if (centering) disp.move((CImgDisplay::screen_dimx()-disp.dimx())/2, 1.36769 + (CImgDisplay::screen_dimy()-disp.dimy())/2); 1.36770 + bool stopflag = false, refresh = false; 1.36771 + int oselected = -1, oclicked = -1, selected = -1, clicked = -1; 1.36772 + while (!disp.is_closed && !stopflag) { 1.36773 + if (refresh) { 1.36774 + if (clicked>=0) CImg<unsigned char>(canvas).draw_image(xbuttons[clicked],by,cbuttons[clicked]).display(disp); 1.36775 + else { 1.36776 + if (selected>=0) CImg<unsigned char>(canvas).draw_image(xbuttons[selected],by,sbuttons[selected]).display(disp); 1.36777 + else canvas.display(disp); 1.36778 + } 1.36779 + refresh = false; 1.36780 + } 1.36781 + disp.wait(15); 1.36782 + if (disp.is_resized) disp.resize(disp); 1.36783 + 1.36784 + if (disp.button&1) { 1.36785 + oclicked = clicked; 1.36786 + clicked = -1; 1.36787 + cimglist_for(buttons,l) 1.36788 + if (disp.mouse_y>=(int)by && disp.mouse_y<(int)(by+bh) && 1.36789 + disp.mouse_x>=(int)xbuttons[l] && disp.mouse_x<(int)(xbuttons[l]+bw)) { 1.36790 + clicked = selected = l; 1.36791 + refresh = true; 1.36792 + } 1.36793 + if (clicked!=oclicked) refresh = true; 1.36794 + } else if (clicked>=0) stopflag = true; 1.36795 + 1.36796 + if (disp.key) { 1.36797 + oselected = selected; 1.36798 + switch (disp.key) { 1.36799 + case cimg::keyESC : selected=-1; stopflag=true; break; 1.36800 + case cimg::keyENTER : if (selected<0) selected = 0; stopflag = true; break; 1.36801 + case cimg::keyTAB : 1.36802 + case cimg::keyARROWRIGHT : 1.36803 + case cimg::keyARROWDOWN : selected = (selected+1)%buttons.size; break; 1.36804 + case cimg::keyARROWLEFT : 1.36805 + case cimg::keyARROWUP : selected = (selected+buttons.size-1)%buttons.size; break; 1.36806 + } 1.36807 + disp.key = 0; 1.36808 + if (selected!=oselected) refresh = true; 1.36809 + } 1.36810 + } 1.36811 + if (!disp) selected = -1; 1.36812 + return selected; 1.36813 +#else 1.36814 + cimg_std::fprintf(cimg_stdout,"<%s>\n\n%s\n\n",title,msg); 1.36815 + return -1+0*(int)(button1_txt-button2_txt+button3_txt-button4_txt+button5_txt-button6_txt+logo.width+(int)centering); 1.36816 +#endif 1.36817 + } 1.36818 + 1.36819 + inline int dialog(const char *title, const char *msg, 1.36820 + const char *button1_txt, const char *button2_txt, const char *button3_txt, 1.36821 + const char *button4_txt, const char *button5_txt, const char *button6_txt, 1.36822 + const bool centering) { 1.36823 + return dialog(title,msg,button1_txt,button2_txt,button3_txt,button4_txt,button5_txt,button6_txt, 1.36824 + CImg<unsigned char>::logo40x38(),centering); 1.36825 + } 1.36826 + 1.36827 + // End of cimg:: namespace 1.36828 +} 1.36829 + 1.36830 + // End of cimg_library:: namespace 1.36831 +} 1.36832 + 1.36833 +#ifdef _cimg_redefine_min 1.36834 +#define min(a,b) (((a)<(b))?(a):(b)) 1.36835 +#endif 1.36836 +#ifdef _cimg_redefine_max 1.36837 +#define max(a,b) (((a)>(b))?(a):(b)) 1.36838 +#endif 1.36839 + 1.36840 +#endif 1.36841 +// Local Variables: 1.36842 +// mode: c++ 1.36843 +// End: