57 #define cimg_version 160
88 #if defined(unix) || defined(__unix) || defined(__unix__) \
89 || defined(linux) || defined(__linux) || defined(__linux__) \
90 || defined(sun) || defined(__sun) \
91 || defined(BSD) || defined(__OpenBSD__) || defined(__NetBSD__) \
92 || defined(__FreeBSD__) || defined (__DragonFly__) \
93 || defined(sgi) || defined(__sgi) \
94 || defined(__MACOSX__) || defined(__APPLE__) \
95 || defined(__CYGWIN__)
97 #elif defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \
98 || defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
103 #elif !(cimg_OS==0 || cimg_OS==1 || cimg_OS==2)
104 #error CImg Library: Invalid configuration variable 'cimg_OS'.
105 #error (correct values are '0 = unknown OS', '1 = Unix-like OS', '2 = Microsoft Windows').
110 #pragma warning(push)
111 #pragma warning(disable:4311)
112 #pragma warning(disable:4312)
113 #pragma warning(disable:4800)
114 #pragma warning(disable:4804)
115 #pragma warning(disable:4996)
116 #define _CRT_SECURE_NO_DEPRECATE 1
117 #define _CRT_NONSTDC_NO_DEPRECATE 1
122 #include <sys/types.h>
123 #include <sys/time.h>
131 #define _WIN32_IE 0x0400
136 #define cimg_snprintf _snprintf
137 #define cimg_vsnprintf _vsnprintf
139 #ifndef cimg_snprintf
141 #define cimg_snprintf snprintf
142 #define cimg_vsnprintf vsnprintf
146 #if !defined(cimg_use_cpp11) && __cplusplus>201100
147 #define cimg_use_cpp11
149 #ifdef cimg_use_cpp11
150 #include <initializer_list>
157 #ifndef cimg_file_separator
159 #define cimg_file_separator '\\'
161 #define cimg_file_separator '/'
176 #ifndef cimg_verbosity
177 #define cimg_verbosity 2
178 #elif !(cimg_verbosity==0 || cimg_verbosity==1 || cimg_verbosity==2 || cimg_verbosity==3 || cimg_verbosity==4)
179 #error CImg Library: Configuration variable 'cimg_verbosity' is badly defined.
180 #error (should be { 0=quiet | 1=console | 2=dialog | 3=console+warnings | 4=dialog+warnings }).
190 #define cimg_display 0
192 #if defined(__MACOSX__) || defined(__APPLE__)
193 #define cimg_display 1
195 #define cimg_display 1
198 #define cimg_display 2
200 #elif !(cimg_display==0 || cimg_display==1 || cimg_display==2)
201 #error CImg Library: Configuration variable 'cimg_display' is badly defined.
202 #error (should be { 0=none | 1=X-Window (X11) | 2=Microsoft GDI32 }).
207 #include <X11/Xlib.h>
208 #include <X11/Xutil.h>
209 #include <X11/keysym.h>
214 #include <X11/extensions/XShm.h>
216 #ifdef cimg_use_xrandr
217 #include <X11/extensions/Xrandr.h>
221 #define cimg_appname "CImg"
231 #ifdef cimg_use_openmp
242 #ifdef cimg_use_opencv
245 #define _cimg_redefine_True
249 #define _cimg_redefine_False
292 #define uint64 uint64_hack_
293 #define int64 int64_hack_
307 #ifdef cimg_use_minc2
308 #include "minc_io_simple_volume.h"
309 #include "minc_1_simple.h"
310 #include "minc_1_simple_rw.h"
321 #ifdef cimg_use_ffmpeg
322 #if (defined(_STDINT_H) || defined(_STDINT_H_)) && !defined(UINT64_C)
323 #warning "__STDC_CONSTANT_MACROS has to be defined before including <stdint.h>, this file will probably not compile."
325 #ifndef __STDC_CONSTANT_MACROS
326 #define __STDC_CONSTANT_MACROS // ...or stdint.h wont' define UINT64_C, needed by libavutil
329 #include <libavformat/avformat.h>
330 #include <libavcodec/avcodec.h>
331 #include <libswscale/swscale.h>
355 #ifdef cimg_use_magick
356 #include "Magick++.h"
367 #ifdef cimg_use_fftw3
381 #ifdef cimg_use_board
384 #define _cimg_redefine_None
396 #ifdef cimg_use_openexr
397 #include "ImfRgbaFile.h"
398 #include "ImfInputFile.h"
399 #include "ImfChannelList.h"
400 #include "ImfMatrixAttribute.h"
401 #include "ImfArray.h"
411 #ifdef cimg_use_lapack
413 extern void sgetrf_(
int*,
int*,
float*,
int*,
int*,
int*);
414 extern void sgetri_(
int*,
float*,
int*,
int*,
float*,
int*,
int*);
415 extern void sgetrs_(
char*,
int*,
int*,
float*,
int*,
int*,
float*,
int*,
int*);
416 extern void sgesvd_(
char*,
char*,
int*,
int*,
float*,
int*,
float*,
float*,
int*,
float*,
int*,
float*,
int*,
int*);
417 extern void ssyev_(
char*,
char*,
int*,
float*,
int*,
float*,
float*,
int*,
int*);
418 extern void dgetrf_(
int*,
int*,
double*,
int*,
int*,
int*);
419 extern void dgetri_(
int*,
double*,
int*,
int*,
double*,
int*,
int*);
420 extern void dgetrs_(
char*,
int*,
int*,
double*,
int*,
int*,
double*,
int*,
int*);
421 extern void dgesvd_(
char*,
char*,
int*,
int*,
double*,
int*,
double*,
double*,
422 int*,
double*,
int*,
double*,
int*,
int*);
423 extern void dsyev_(
char*,
char*,
int*,
double*,
int*,
double*,
double*,
int*,
int*);
424 extern void dgels_(
char*,
int*,
int*,
int*,
double*,
int*,
double*,
int*,
double*,
int*,
int*);
425 extern void sgels_(
char*,
int*,
int*,
int*,
float*,
int*,
float*,
int*,
float*,
int*,
int*);
437 #define _cimg_redefine_min
441 #define _cimg_redefine_max
445 #define _cimg_redefine_PI
452 #ifdef cimg_namespace_suffix
453 #define __cimg_library_suffixed(s) cimg_library_##s
454 #define _cimg_library_suffixed(s) __cimg_library_suffixed(s)
455 #define cimg_library_suffixed _cimg_library_suffixed(cimg_namespace_suffix)
457 #define cimg_library_suffixed cimg_library
470 #define cimg_usage(usage) cimg_library_suffixed::cimg::option((char*)0,argc,argv,(char*)0,usage,false)
471 #define cimg_help(str) cimg_library_suffixed::cimg::option((char*)0,argc,argv,str,(char*)0)
472 #define cimg_option(name,defaut,usage) cimg_library_suffixed::cimg::option(name,argc,argv,defaut,usage)
473 #define cimg_argument(pos) \
474 cimg_library_suffixed::cimg::argument(pos,argc,argv)
475 #define cimg_argument1(pos,s0) \
476 cimg_library_suffixed::cimg::argument(pos,argc,argv,1,s0)
477 #define cimg_argument2(pos,s0,s1) \
478 cimg_library_suffixed::cimg::argument(pos,argc,argv,2,s0,s1)
479 #define cimg_argument3(pos,s0,s1,s2) \
480 cimg_library_suffixed::cimg::argument(pos,argc,argv,3,s0,s1,s2)
481 #define cimg_argument4(pos,s0,s1,s2,s3) \
482 cimg_library_suffixed::cimg::argument(pos,argc,argv,4,s0,s1,s2,s3)
483 #define cimg_argument5(pos,s0,s1,s2,s3,s4) \
484 cimg_library_suffixed::cimg::argument(pos,argc,argv,5,s0,s1,s2,s3,s4)
485 #define cimg_argument6(pos,s0,s1,s2,s3,s4,s5) \
486 cimg_library_suffixed::cimg::argument(pos,argc,argv,6,s0,s1,s2,s3,s4,s5)
487 #define cimg_argument7(pos,s0,s1,s2,s3,s4,s5,s6) \
488 cimg_library_suffixed::cimg::argument(pos,argc,argv,7,s0,s1,s2,s3,s4,s5,s6)
489 #define cimg_argument8(pos,s0,s1,s2,s3,s4,s5,s6,s7) \
490 cimg_library_suffixed::cimg::argument(pos,argc,argv,8,s0,s1,s2,s3,s4,s5,s6,s7)
491 #define cimg_argument9(pos,s0,s1,s2,s3,s4,s5,s6,s7,s8) \
492 cimg_library_suffixed::cimg::argument(pos,argc,argv,9,s0,s1,s2,s3,s4,s5,s6,s7,s8)
495 #define CImg_2x2(I,T) T I[4]; \
496 T& I##cc = I[0]; T& I##nc = I[1]; \
497 T& I##cn = I[2]; T& I##nn = I[3]; \
501 #define CImg_3x3(I,T) T I[9]; \
502 T& I##pp = I[0]; T& I##cp = I[1]; T& I##np = I[2]; \
503 T& I##pc = I[3]; T& I##cc = I[4]; T& I##nc = I[5]; \
504 T& I##pn = I[6]; T& I##cn = I[7]; T& I##nn = I[8]; \
505 I##pp = I##cp = I##np = \
506 I##pc = I##cc = I##nc = \
507 I##pn = I##cn = I##nn = 0
509 #define CImg_4x4(I,T) T I[16]; \
510 T& I##pp = I[0]; T& I##cp = I[1]; T& I##np = I[2]; T& I##ap = I[3]; \
511 T& I##pc = I[4]; T& I##cc = I[5]; T& I##nc = I[6]; T& I##ac = I[7]; \
512 T& I##pn = I[8]; T& I##cn = I[9]; T& I##nn = I[10]; T& I##an = I[11]; \
513 T& I##pa = I[12]; T& I##ca = I[13]; T& I##na = I[14]; T& I##aa = I[15]; \
514 I##pp = I##cp = I##np = I##ap = \
515 I##pc = I##cc = I##nc = I##ac = \
516 I##pn = I##cn = I##nn = I##an = \
517 I##pa = I##ca = I##na = I##aa = 0
519 #define CImg_5x5(I,T) T I[25]; \
520 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]; \
521 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]; \
522 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]; \
523 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]; \
524 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]; \
525 I##bb = I##pb = I##cb = I##nb = I##ab = \
526 I##bp = I##pp = I##cp = I##np = I##ap = \
527 I##bc = I##pc = I##cc = I##nc = I##ac = \
528 I##bn = I##pn = I##cn = I##nn = I##an = \
529 I##ba = I##pa = I##ca = I##na = I##aa = 0
531 #define CImg_2x2x2(I,T) T I[8]; \
532 T& I##ccc = I[0]; T& I##ncc = I[1]; \
533 T& I##cnc = I[2]; T& I##nnc = I[3]; \
534 T& I##ccn = I[4]; T& I##ncn = I[5]; \
535 T& I##cnn = I[6]; T& I##nnn = I[7]; \
541 #define CImg_3x3x3(I,T) T I[27]; \
542 T& I##ppp = I[0]; T& I##cpp = I[1]; T& I##npp = I[2]; \
543 T& I##pcp = I[3]; T& I##ccp = I[4]; T& I##ncp = I[5]; \
544 T& I##pnp = I[6]; T& I##cnp = I[7]; T& I##nnp = I[8]; \
545 T& I##ppc = I[9]; T& I##cpc = I[10]; T& I##npc = I[11]; \
546 T& I##pcc = I[12]; T& I##ccc = I[13]; T& I##ncc = I[14]; \
547 T& I##pnc = I[15]; T& I##cnc = I[16]; T& I##nnc = I[17]; \
548 T& I##ppn = I[18]; T& I##cpn = I[19]; T& I##npn = I[20]; \
549 T& I##pcn = I[21]; T& I##ccn = I[22]; T& I##ncn = I[23]; \
550 T& I##pnn = I[24]; T& I##cnn = I[25]; T& I##nnn = I[26]; \
551 I##ppp = I##cpp = I##npp = \
552 I##pcp = I##ccp = I##ncp = \
553 I##pnp = I##cnp = I##nnp = \
554 I##ppc = I##cpc = I##npc = \
555 I##pcc = I##ccc = I##ncc = \
556 I##pnc = I##cnc = I##nnc = \
557 I##ppn = I##cpn = I##npn = \
558 I##pcn = I##ccn = I##ncn = \
559 I##pnn = I##cnn = I##nnn = 0
561 #define cimg_get2x2(img,x,y,z,c,I,T) \
562 I[0] = (T)(img)(x,y,z,c), I[1] = (T)(img)(_n1##x,y,z,c), I[2] = (T)(img)(x,_n1##y,z,c), \
563 I[3] = (T)(img)(_n1##x,_n1##y,z,c)
565 #define cimg_get3x3(img,x,y,z,c,I,T) \
566 I[0] = (T)(img)(_p1##x,_p1##y,z,c), I[1] = (T)(img)(x,_p1##y,z,c), I[2] = (T)(img)(_n1##x,_p1##y,z,c), \
567 I[3] = (T)(img)(_p1##x,y,z,c), I[4] = (T)(img)(x,y,z,c), I[5] = (T)(img)(_n1##x,y,z,c), \
568 I[6] = (T)(img)(_p1##x,_n1##y,z,c), I[7] = (T)(img)(x,_n1##y,z,c), I[8] = (T)(img)(_n1##x,_n1##y,z,c)
570 #define cimg_get4x4(img,x,y,z,c,I,T) \
571 I[0] = (T)(img)(_p1##x,_p1##y,z,c), I[1] = (T)(img)(x,_p1##y,z,c), I[2] = (T)(img)(_n1##x,_p1##y,z,c), \
572 I[3] = (T)(img)(_n2##x,_p1##y,z,c), I[4] = (T)(img)(_p1##x,y,z,c), I[5] = (T)(img)(x,y,z,c), \
573 I[6] = (T)(img)(_n1##x,y,z,c), I[7] = (T)(img)(_n2##x,y,z,c), I[8] = (T)(img)(_p1##x,_n1##y,z,c), \
574 I[9] = (T)(img)(x,_n1##y,z,c), I[10] = (T)(img)(_n1##x,_n1##y,z,c), I[11] = (T)(img)(_n2##x,_n1##y,z,c), \
575 I[12] = (T)(img)(_p1##x,_n2##y,z,c), I[13] = (T)(img)(x,_n2##y,z,c), I[14] = (T)(img)(_n1##x,_n2##y,z,c), \
576 I[15] = (T)(img)(_n2##x,_n2##y,z,c)
578 #define cimg_get5x5(img,x,y,z,c,I,T) \
579 I[0] = (T)(img)(_p2##x,_p2##y,z,c), I[1] = (T)(img)(_p1##x,_p2##y,z,c), I[2] = (T)(img)(x,_p2##y,z,c), \
580 I[3] = (T)(img)(_n1##x,_p2##y,z,c), I[4] = (T)(img)(_n2##x,_p2##y,z,c), I[5] = (T)(img)(_p2##x,_p1##y,z,c), \
581 I[6] = (T)(img)(_p1##x,_p1##y,z,c), I[7] = (T)(img)(x,_p1##y,z,c), I[8] = (T)(img)(_n1##x,_p1##y,z,c), \
582 I[9] = (T)(img)(_n2##x,_p1##y,z,c), I[10] = (T)(img)(_p2##x,y,z,c), I[11] = (T)(img)(_p1##x,y,z,c), \
583 I[12] = (T)(img)(x,y,z,c), I[13] = (T)(img)(_n1##x,y,z,c), I[14] = (T)(img)(_n2##x,y,z,c), \
584 I[15] = (T)(img)(_p2##x,_n1##y,z,c), I[16] = (T)(img)(_p1##x,_n1##y,z,c), I[17] = (T)(img)(x,_n1##y,z,c), \
585 I[18] = (T)(img)(_n1##x,_n1##y,z,c), I[19] = (T)(img)(_n2##x,_n1##y,z,c), I[20] = (T)(img)(_p2##x,_n2##y,z,c), \
586 I[21] = (T)(img)(_p1##x,_n2##y,z,c), I[22] = (T)(img)(x,_n2##y,z,c), I[23] = (T)(img)(_n1##x,_n2##y,z,c), \
587 I[24] = (T)(img)(_n2##x,_n2##y,z,c)
589 #define cimg_get6x6(img,x,y,z,c,I,T) \
590 I[0] = (T)(img)(_p2##x,_p2##y,z,c), I[1] = (T)(img)(_p1##x,_p2##y,z,c), I[2] = (T)(img)(x,_p2##y,z,c), \
591 I[3] = (T)(img)(_n1##x,_p2##y,z,c), I[4] = (T)(img)(_n2##x,_p2##y,z,c), I[5] = (T)(img)(_n3##x,_p2##y,z,c), \
592 I[6] = (T)(img)(_p2##x,_p1##y,z,c), I[7] = (T)(img)(_p1##x,_p1##y,z,c), I[8] = (T)(img)(x,_p1##y,z,c), \
593 I[9] = (T)(img)(_n1##x,_p1##y,z,c), I[10] = (T)(img)(_n2##x,_p1##y,z,c), I[11] = (T)(img)(_n3##x,_p1##y,z,c), \
594 I[12] = (T)(img)(_p2##x,y,z,c), I[13] = (T)(img)(_p1##x,y,z,c), I[14] = (T)(img)(x,y,z,c), \
595 I[15] = (T)(img)(_n1##x,y,z,c), I[16] = (T)(img)(_n2##x,y,z,c), I[17] = (T)(img)(_n3##x,y,z,c), \
596 I[18] = (T)(img)(_p2##x,_n1##y,z,c), I[19] = (T)(img)(_p1##x,_n1##y,z,c), I[20] = (T)(img)(x,_n1##y,z,c), \
597 I[21] = (T)(img)(_n1##x,_n1##y,z,c), I[22] = (T)(img)(_n2##x,_n1##y,z,c), I[23] = (T)(img)(_n3##x,_n1##y,z,c), \
598 I[24] = (T)(img)(_p2##x,_n2##y,z,c), I[25] = (T)(img)(_p1##x,_n2##y,z,c), I[26] = (T)(img)(x,_n2##y,z,c), \
599 I[27] = (T)(img)(_n1##x,_n2##y,z,c), I[28] = (T)(img)(_n2##x,_n2##y,z,c), I[29] = (T)(img)(_n3##x,_n2##y,z,c), \
600 I[30] = (T)(img)(_p2##x,_n3##y,z,c), I[31] = (T)(img)(_p1##x,_n3##y,z,c), I[32] = (T)(img)(x,_n3##y,z,c), \
601 I[33] = (T)(img)(_n1##x,_n3##y,z,c), I[34] = (T)(img)(_n2##x,_n3##y,z,c), I[35] = (T)(img)(_n3##x,_n3##y,z,c)
603 #define cimg_get7x7(img,x,y,z,c,I,T) \
604 I[0] = (T)(img)(_p3##x,_p3##y,z,c), I[1] = (T)(img)(_p2##x,_p3##y,z,c), I[2] = (T)(img)(_p1##x,_p3##y,z,c), \
605 I[3] = (T)(img)(x,_p3##y,z,c), I[4] = (T)(img)(_n1##x,_p3##y,z,c), I[5] = (T)(img)(_n2##x,_p3##y,z,c), \
606 I[6] = (T)(img)(_n3##x,_p3##y,z,c), I[7] = (T)(img)(_p3##x,_p2##y,z,c), I[8] = (T)(img)(_p2##x,_p2##y,z,c), \
607 I[9] = (T)(img)(_p1##x,_p2##y,z,c), I[10] = (T)(img)(x,_p2##y,z,c), I[11] = (T)(img)(_n1##x,_p2##y,z,c), \
608 I[12] = (T)(img)(_n2##x,_p2##y,z,c), I[13] = (T)(img)(_n3##x,_p2##y,z,c), I[14] = (T)(img)(_p3##x,_p1##y,z,c), \
609 I[15] = (T)(img)(_p2##x,_p1##y,z,c), I[16] = (T)(img)(_p1##x,_p1##y,z,c), I[17] = (T)(img)(x,_p1##y,z,c), \
610 I[18] = (T)(img)(_n1##x,_p1##y,z,c), I[19] = (T)(img)(_n2##x,_p1##y,z,c), I[20] = (T)(img)(_n3##x,_p1##y,z,c), \
611 I[21] = (T)(img)(_p3##x,y,z,c), I[22] = (T)(img)(_p2##x,y,z,c), I[23] = (T)(img)(_p1##x,y,z,c), \
612 I[24] = (T)(img)(x,y,z,c), I[25] = (T)(img)(_n1##x,y,z,c), I[26] = (T)(img)(_n2##x,y,z,c), \
613 I[27] = (T)(img)(_n3##x,y,z,c), I[28] = (T)(img)(_p3##x,_n1##y,z,c), I[29] = (T)(img)(_p2##x,_n1##y,z,c), \
614 I[30] = (T)(img)(_p1##x,_n1##y,z,c), I[31] = (T)(img)(x,_n1##y,z,c), I[32] = (T)(img)(_n1##x,_n1##y,z,c), \
615 I[33] = (T)(img)(_n2##x,_n1##y,z,c), I[34] = (T)(img)(_n3##x,_n1##y,z,c), I[35] = (T)(img)(_p3##x,_n2##y,z,c), \
616 I[36] = (T)(img)(_p2##x,_n2##y,z,c), I[37] = (T)(img)(_p1##x,_n2##y,z,c), I[38] = (T)(img)(x,_n2##y,z,c), \
617 I[39] = (T)(img)(_n1##x,_n2##y,z,c), I[40] = (T)(img)(_n2##x,_n2##y,z,c), I[41] = (T)(img)(_n3##x,_n2##y,z,c), \
618 I[42] = (T)(img)(_p3##x,_n3##y,z,c), I[43] = (T)(img)(_p2##x,_n3##y,z,c), I[44] = (T)(img)(_p1##x,_n3##y,z,c), \
619 I[45] = (T)(img)(x,_n3##y,z,c), I[46] = (T)(img)(_n1##x,_n3##y,z,c), I[47] = (T)(img)(_n2##x,_n3##y,z,c), \
620 I[48] = (T)(img)(_n3##x,_n3##y,z,c)
622 #define cimg_get8x8(img,x,y,z,c,I,T) \
623 I[0] = (T)(img)(_p3##x,_p3##y,z,c), I[1] = (T)(img)(_p2##x,_p3##y,z,c), I[2] = (T)(img)(_p1##x,_p3##y,z,c), \
624 I[3] = (T)(img)(x,_p3##y,z,c), I[4] = (T)(img)(_n1##x,_p3##y,z,c), I[5] = (T)(img)(_n2##x,_p3##y,z,c), \
625 I[6] = (T)(img)(_n3##x,_p3##y,z,c), I[7] = (T)(img)(_n4##x,_p3##y,z,c), I[8] = (T)(img)(_p3##x,_p2##y,z,c), \
626 I[9] = (T)(img)(_p2##x,_p2##y,z,c), I[10] = (T)(img)(_p1##x,_p2##y,z,c), I[11] = (T)(img)(x,_p2##y,z,c), \
627 I[12] = (T)(img)(_n1##x,_p2##y,z,c), I[13] = (T)(img)(_n2##x,_p2##y,z,c), I[14] = (T)(img)(_n3##x,_p2##y,z,c), \
628 I[15] = (T)(img)(_n4##x,_p2##y,z,c), I[16] = (T)(img)(_p3##x,_p1##y,z,c), I[17] = (T)(img)(_p2##x,_p1##y,z,c), \
629 I[18] = (T)(img)(_p1##x,_p1##y,z,c), I[19] = (T)(img)(x,_p1##y,z,c), I[20] = (T)(img)(_n1##x,_p1##y,z,c), \
630 I[21] = (T)(img)(_n2##x,_p1##y,z,c), I[22] = (T)(img)(_n3##x,_p1##y,z,c), I[23] = (T)(img)(_n4##x,_p1##y,z,c), \
631 I[24] = (T)(img)(_p3##x,y,z,c), I[25] = (T)(img)(_p2##x,y,z,c), I[26] = (T)(img)(_p1##x,y,z,c), \
632 I[27] = (T)(img)(x,y,z,c), I[28] = (T)(img)(_n1##x,y,z,c), I[29] = (T)(img)(_n2##x,y,z,c), \
633 I[30] = (T)(img)(_n3##x,y,z,c), I[31] = (T)(img)(_n4##x,y,z,c), I[32] = (T)(img)(_p3##x,_n1##y,z,c), \
634 I[33] = (T)(img)(_p2##x,_n1##y,z,c), I[34] = (T)(img)(_p1##x,_n1##y,z,c), I[35] = (T)(img)(x,_n1##y,z,c), \
635 I[36] = (T)(img)(_n1##x,_n1##y,z,c), I[37] = (T)(img)(_n2##x,_n1##y,z,c), I[38] = (T)(img)(_n3##x,_n1##y,z,c), \
636 I[39] = (T)(img)(_n4##x,_n1##y,z,c), I[40] = (T)(img)(_p3##x,_n2##y,z,c), I[41] = (T)(img)(_p2##x,_n2##y,z,c), \
637 I[42] = (T)(img)(_p1##x,_n2##y,z,c), I[43] = (T)(img)(x,_n2##y,z,c), I[44] = (T)(img)(_n1##x,_n2##y,z,c), \
638 I[45] = (T)(img)(_n2##x,_n2##y,z,c), I[46] = (T)(img)(_n3##x,_n2##y,z,c), I[47] = (T)(img)(_n4##x,_n2##y,z,c), \
639 I[48] = (T)(img)(_p3##x,_n3##y,z,c), I[49] = (T)(img)(_p2##x,_n3##y,z,c), I[50] = (T)(img)(_p1##x,_n3##y,z,c), \
640 I[51] = (T)(img)(x,_n3##y,z,c), I[52] = (T)(img)(_n1##x,_n3##y,z,c), I[53] = (T)(img)(_n2##x,_n3##y,z,c), \
641 I[54] = (T)(img)(_n3##x,_n3##y,z,c), I[55] = (T)(img)(_n4##x,_n3##y,z,c), I[56] = (T)(img)(_p3##x,_n4##y,z,c), \
642 I[57] = (T)(img)(_p2##x,_n4##y,z,c), I[58] = (T)(img)(_p1##x,_n4##y,z,c), I[59] = (T)(img)(x,_n4##y,z,c), \
643 I[60] = (T)(img)(_n1##x,_n4##y,z,c), I[61] = (T)(img)(_n2##x,_n4##y,z,c), I[62] = (T)(img)(_n3##x,_n4##y,z,c), \
644 I[63] = (T)(img)(_n4##x,_n4##y,z,c);
646 #define cimg_get9x9(img,x,y,z,c,I,T) \
647 I[0] = (T)(img)(_p4##x,_p4##y,z,c), I[1] = (T)(img)(_p3##x,_p4##y,z,c), I[2] = (T)(img)(_p2##x,_p4##y,z,c), \
648 I[3] = (T)(img)(_p1##x,_p4##y,z,c), I[4] = (T)(img)(x,_p4##y,z,c), I[5] = (T)(img)(_n1##x,_p4##y,z,c), \
649 I[6] = (T)(img)(_n2##x,_p4##y,z,c), I[7] = (T)(img)(_n3##x,_p4##y,z,c), I[8] = (T)(img)(_n4##x,_p4##y,z,c), \
650 I[9] = (T)(img)(_p4##x,_p3##y,z,c), I[10] = (T)(img)(_p3##x,_p3##y,z,c), I[11] = (T)(img)(_p2##x,_p3##y,z,c), \
651 I[12] = (T)(img)(_p1##x,_p3##y,z,c), I[13] = (T)(img)(x,_p3##y,z,c), I[14] = (T)(img)(_n1##x,_p3##y,z,c), \
652 I[15] = (T)(img)(_n2##x,_p3##y,z,c), I[16] = (T)(img)(_n3##x,_p3##y,z,c), I[17] = (T)(img)(_n4##x,_p3##y,z,c), \
653 I[18] = (T)(img)(_p4##x,_p2##y,z,c), I[19] = (T)(img)(_p3##x,_p2##y,z,c), I[20] = (T)(img)(_p2##x,_p2##y,z,c), \
654 I[21] = (T)(img)(_p1##x,_p2##y,z,c), I[22] = (T)(img)(x,_p2##y,z,c), I[23] = (T)(img)(_n1##x,_p2##y,z,c), \
655 I[24] = (T)(img)(_n2##x,_p2##y,z,c), I[25] = (T)(img)(_n3##x,_p2##y,z,c), I[26] = (T)(img)(_n4##x,_p2##y,z,c), \
656 I[27] = (T)(img)(_p4##x,_p1##y,z,c), I[28] = (T)(img)(_p3##x,_p1##y,z,c), I[29] = (T)(img)(_p2##x,_p1##y,z,c), \
657 I[30] = (T)(img)(_p1##x,_p1##y,z,c), I[31] = (T)(img)(x,_p1##y,z,c), I[32] = (T)(img)(_n1##x,_p1##y,z,c), \
658 I[33] = (T)(img)(_n2##x,_p1##y,z,c), I[34] = (T)(img)(_n3##x,_p1##y,z,c), I[35] = (T)(img)(_n4##x,_p1##y,z,c), \
659 I[36] = (T)(img)(_p4##x,y,z,c), I[37] = (T)(img)(_p3##x,y,z,c), I[38] = (T)(img)(_p2##x,y,z,c), \
660 I[39] = (T)(img)(_p1##x,y,z,c), I[40] = (T)(img)(x,y,z,c), I[41] = (T)(img)(_n1##x,y,z,c), \
661 I[42] = (T)(img)(_n2##x,y,z,c), I[43] = (T)(img)(_n3##x,y,z,c), I[44] = (T)(img)(_n4##x,y,z,c), \
662 I[45] = (T)(img)(_p4##x,_n1##y,z,c), I[46] = (T)(img)(_p3##x,_n1##y,z,c), I[47] = (T)(img)(_p2##x,_n1##y,z,c), \
663 I[48] = (T)(img)(_p1##x,_n1##y,z,c), I[49] = (T)(img)(x,_n1##y,z,c), I[50] = (T)(img)(_n1##x,_n1##y,z,c), \
664 I[51] = (T)(img)(_n2##x,_n1##y,z,c), I[52] = (T)(img)(_n3##x,_n1##y,z,c), I[53] = (T)(img)(_n4##x,_n1##y,z,c), \
665 I[54] = (T)(img)(_p4##x,_n2##y,z,c), I[55] = (T)(img)(_p3##x,_n2##y,z,c), I[56] = (T)(img)(_p2##x,_n2##y,z,c), \
666 I[57] = (T)(img)(_p1##x,_n2##y,z,c), I[58] = (T)(img)(x,_n2##y,z,c), I[59] = (T)(img)(_n1##x,_n2##y,z,c), \
667 I[60] = (T)(img)(_n2##x,_n2##y,z,c), I[61] = (T)(img)(_n3##x,_n2##y,z,c), I[62] = (T)(img)(_n4##x,_n2##y,z,c), \
668 I[63] = (T)(img)(_p4##x,_n3##y,z,c), I[64] = (T)(img)(_p3##x,_n3##y,z,c), I[65] = (T)(img)(_p2##x,_n3##y,z,c), \
669 I[66] = (T)(img)(_p1##x,_n3##y,z,c), I[67] = (T)(img)(x,_n3##y,z,c), I[68] = (T)(img)(_n1##x,_n3##y,z,c), \
670 I[69] = (T)(img)(_n2##x,_n3##y,z,c), I[70] = (T)(img)(_n3##x,_n3##y,z,c), I[71] = (T)(img)(_n4##x,_n3##y,z,c), \
671 I[72] = (T)(img)(_p4##x,_n4##y,z,c), I[73] = (T)(img)(_p3##x,_n4##y,z,c), I[74] = (T)(img)(_p2##x,_n4##y,z,c), \
672 I[75] = (T)(img)(_p1##x,_n4##y,z,c), I[76] = (T)(img)(x,_n4##y,z,c), I[77] = (T)(img)(_n1##x,_n4##y,z,c), \
673 I[78] = (T)(img)(_n2##x,_n4##y,z,c), I[79] = (T)(img)(_n3##x,_n4##y,z,c), I[80] = (T)(img)(_n4##x,_n4##y,z,c)
675 #define cimg_get2x2x2(img,x,y,z,c,I,T) \
676 I[0] = (T)(img)(x,y,z,c), I[1] = (T)(img)(_n1##x,y,z,c), I[2] = (T)(img)(x,_n1##y,z,c), \
677 I[3] = (T)(img)(_n1##x,_n1##y,z,c), I[4] = (T)(img)(x,y,_n1##z,c), I[5] = (T)(img)(_n1##x,y,_n1##z,c), \
678 I[6] = (T)(img)(x,_n1##y,_n1##z,c), I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c)
680 #define cimg_get3x3x3(img,x,y,z,c,I,T) \
681 I[0] = (T)(img)(_p1##x,_p1##y,_p1##z,c), I[1] = (T)(img)(x,_p1##y,_p1##z,c), \
682 I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c), I[3] = (T)(img)(_p1##x,y,_p1##z,c), I[4] = (T)(img)(x,y,_p1##z,c), \
683 I[5] = (T)(img)(_n1##x,y,_p1##z,c), I[6] = (T)(img)(_p1##x,_n1##y,_p1##z,c), I[7] = (T)(img)(x,_n1##y,_p1##z,c), \
684 I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c), I[9] = (T)(img)(_p1##x,_p1##y,z,c), I[10] = (T)(img)(x,_p1##y,z,c), \
685 I[11] = (T)(img)(_n1##x,_p1##y,z,c), I[12] = (T)(img)(_p1##x,y,z,c), I[13] = (T)(img)(x,y,z,c), \
686 I[14] = (T)(img)(_n1##x,y,z,c), I[15] = (T)(img)(_p1##x,_n1##y,z,c), I[16] = (T)(img)(x,_n1##y,z,c), \
687 I[17] = (T)(img)(_n1##x,_n1##y,z,c), I[18] = (T)(img)(_p1##x,_p1##y,_n1##z,c), I[19] = (T)(img)(x,_p1##y,_n1##z,c), \
688 I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c), I[21] = (T)(img)(_p1##x,y,_n1##z,c), I[22] = (T)(img)(x,y,_n1##z,c), \
689 I[23] = (T)(img)(_n1##x,y,_n1##z,c), I[24] = (T)(img)(_p1##x,_n1##y,_n1##z,c), I[25] = (T)(img)(x,_n1##y,_n1##z,c), \
690 I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c)
695 #define cimg_for(img,ptrs,T_ptrs) \
696 for (T_ptrs *ptrs = (img)._data, *_max##ptrs = (img)._data + (img).size(); ptrs<_max##ptrs; ++ptrs)
697 #define cimg_rof(img,ptrs,T_ptrs) for (T_ptrs *ptrs = (img)._data + (img).size() - 1; ptrs>=(img)._data; --ptrs)
698 #define cimg_foroff(img,off) for (unsigned long off = 0, _max##off = (img).size(); off<_max##off; ++off)
700 #define cimg_for1(bound,i) for (int i = 0; i<(int)(bound); ++i)
701 #define cimg_forX(img,x) cimg_for1((img)._width,x)
702 #define cimg_forY(img,y) cimg_for1((img)._height,y)
703 #define cimg_forZ(img,z) cimg_for1((img)._depth,z)
704 #define cimg_forC(img,c) cimg_for1((img)._spectrum,c)
705 #define cimg_forXY(img,x,y) cimg_forY(img,y) cimg_forX(img,x)
706 #define cimg_forXZ(img,x,z) cimg_forZ(img,z) cimg_forX(img,x)
707 #define cimg_forYZ(img,y,z) cimg_forZ(img,z) cimg_forY(img,y)
708 #define cimg_forXC(img,x,c) cimg_forC(img,c) cimg_forX(img,x)
709 #define cimg_forYC(img,y,c) cimg_forC(img,c) cimg_forY(img,y)
710 #define cimg_forZC(img,z,c) cimg_forC(img,c) cimg_forZ(img,z)
711 #define cimg_forXYZ(img,x,y,z) cimg_forZ(img,z) cimg_forXY(img,x,y)
712 #define cimg_forXYC(img,x,y,c) cimg_forC(img,c) cimg_forXY(img,x,y)
713 #define cimg_forXZC(img,x,z,c) cimg_forC(img,c) cimg_forXZ(img,x,z)
714 #define cimg_forYZC(img,y,z,c) cimg_forC(img,c) cimg_forYZ(img,y,z)
715 #define cimg_forXYZC(img,x,y,z,c) cimg_forC(img,c) cimg_forXYZ(img,x,y,z)
717 #define cimg_rof1(bound,i) for (int i = (int)(bound)-1; i>=0; --i)
718 #define cimg_rofX(img,x) cimg_rof1((img)._width,x)
719 #define cimg_rofY(img,y) cimg_rof1((img)._height,y)
720 #define cimg_rofZ(img,z) cimg_rof1((img)._depth,z)
721 #define cimg_rofC(img,c) cimg_rof1((img)._spectrum,c)
722 #define cimg_rofXY(img,x,y) cimg_rofY(img,y) cimg_rofX(img,x)
723 #define cimg_rofXZ(img,x,z) cimg_rofZ(img,z) cimg_rofX(img,x)
724 #define cimg_rofYZ(img,y,z) cimg_rofZ(img,z) cimg_rofY(img,y)
725 #define cimg_rofXC(img,x,c) cimg_rofC(img,c) cimg_rofX(img,x)
726 #define cimg_rofYC(img,y,c) cimg_rofC(img,c) cimg_rofY(img,y)
727 #define cimg_rofZC(img,z,c) cimg_rofC(img,c) cimg_rofZ(img,z)
728 #define cimg_rofXYZ(img,x,y,z) cimg_rofZ(img,z) cimg_rofXY(img,x,y)
729 #define cimg_rofXYC(img,x,y,c) cimg_rofC(img,c) cimg_rofXY(img,x,y)
730 #define cimg_rofXZC(img,x,z,c) cimg_rofC(img,c) cimg_rofXZ(img,x,z)
731 #define cimg_rofYZC(img,y,z,c) cimg_rofC(img,c) cimg_rofYZ(img,y,z)
732 #define cimg_rofXYZC(img,x,y,z,c) cimg_rofC(img,c) cimg_rofXYZ(img,x,y,z)
734 #define cimg_for_in1(bound,i0,i1,i) \
735 for (int i = (int)(i0)<0?0:(int)(i0), _max##i = (int)(i1)<(int)(bound)?(int)(i1):(int)(bound)-1; i<=_max##i; ++i)
736 #define cimg_for_inX(img,x0,x1,x) cimg_for_in1((img)._width,x0,x1,x)
737 #define cimg_for_inY(img,y0,y1,y) cimg_for_in1((img)._height,y0,y1,y)
738 #define cimg_for_inZ(img,z0,z1,z) cimg_for_in1((img)._depth,z0,z1,z)
739 #define cimg_for_inC(img,c0,c1,c) cimg_for_in1((img)._spectrum,c0,c1,c)
740 #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)
741 #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)
742 #define cimg_for_inXC(img,x0,c0,x1,c1,x,c) cimg_for_inC(img,c0,c1,c) cimg_for_inX(img,x0,x1,x)
743 #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)
744 #define cimg_for_inYC(img,y0,c0,y1,c1,y,c) cimg_for_inC(img,c0,c1,c) cimg_for_inY(img,y0,y1,y)
745 #define cimg_for_inZC(img,z0,c0,z1,c1,z,c) cimg_for_inC(img,c0,c1,c) cimg_for_inZ(img,z0,z1,z)
746 #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)
747 #define cimg_for_inXYC(img,x0,y0,c0,x1,y1,c1,x,y,c) cimg_for_inC(img,c0,c1,c) cimg_for_inXY(img,x0,y0,x1,y1,x,y)
748 #define cimg_for_inXZC(img,x0,z0,c0,x1,z1,c1,x,z,c) cimg_for_inC(img,c0,c1,c) cimg_for_inXZ(img,x0,z0,x1,z1,x,z)
749 #define cimg_for_inYZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_inC(img,c0,c1,c) cimg_for_inYZ(img,y0,z0,y1,z1,y,z)
750 #define cimg_for_inXYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \
751 cimg_for_inC(img,c0,c1,c) cimg_for_inXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z)
752 #define cimg_for_insideX(img,x,n) cimg_for_inX(img,n,(img)._width-1-(n),x)
753 #define cimg_for_insideY(img,y,n) cimg_for_inY(img,n,(img)._height-1-(n),y)
754 #define cimg_for_insideZ(img,z,n) cimg_for_inZ(img,n,(img)._depth-1-(n),z)
755 #define cimg_for_insideC(img,c,n) cimg_for_inC(img,n,(img)._spectrum-1-(n),c)
756 #define cimg_for_insideXY(img,x,y,n) cimg_for_inXY(img,n,n,(img)._width-1-(n),(img)._height-1-(n),x,y)
757 #define cimg_for_insideXYZ(img,x,y,z,n) \
758 cimg_for_inXYZ(img,n,n,n,(img)._width-1-(n),(img)._height-1-(n),(img)._depth-1-(n),x,y,z)
759 #define cimg_for_insideXYZC(img,x,y,z,c,n) \
760 cimg_for_inXYZ(img,n,n,n,(img)._width-1-(n),(img)._height-1-(n),(img)._depth-1-(n),x,y,z)
762 #define cimg_for_out1(boundi,i0,i1,i) \
763 for (int i = (int)(i0)>0?0:(int)(i1)+1; i<(int)(boundi); ++i, i = i==(int)(i0)?(int)(i1)+1:i)
764 #define cimg_for_out2(boundi,boundj,i0,j0,i1,j1,i,j) \
765 for (int j = 0; j<(int)(boundj); ++j) \
766 for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j?0:(int)(i0)>0?0:(int)(i1)+1; i<(int)(boundi); \
767 ++i, i = _n1j?i:(i==(int)(i0)?(int)(i1)+1:i))
768 #define cimg_for_out3(boundi,boundj,boundk,i0,j0,k0,i1,j1,k1,i,j,k) \
769 for (int k = 0; k<(int)(boundk); ++k) \
770 for (int _n1k = (int)(k<(int)(k0) || k>(int)(k1)), j = 0; j<(int)(boundj); ++j) \
771 for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j || _n1k?0:(int)(i0)>0?0:(int)(i1)+1; i<(int)(boundi); \
772 ++i, i = _n1j || _n1k?i:(i==(int)(i0)?(int)(i1)+1:i))
773 #define cimg_for_out4(boundi,boundj,boundk,boundl,i0,j0,k0,l0,i1,j1,k1,l1,i,j,k,l) \
774 for (int l = 0; l<(int)(boundl); ++l) \
775 for (int _n1l = (int)(l<(int)(l0) || l>(int)(l1)), k = 0; k<(int)(boundk); ++k) \
776 for (int _n1k = (int)(k<(int)(k0) || k>(int)(k1)), j = 0; j<(int)(boundj); ++j) \
777 for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j || _n1k || _n1l?0:(int)(i0)>0?0:(int)(i1)+1; \
778 i<(int)(boundi); ++i, i = _n1j || _n1k || _n1l?i:(i==(int)(i0)?(int)(i1)+1:i))
779 #define cimg_for_outX(img,x0,x1,x) cimg_for_out1((img)._width,x0,x1,x)
780 #define cimg_for_outY(img,y0,y1,y) cimg_for_out1((img)._height,y0,y1,y)
781 #define cimg_for_outZ(img,z0,z1,z) cimg_for_out1((img)._depth,z0,z1,z)
782 #define cimg_for_outC(img,c0,c1,c) cimg_for_out1((img)._spectrum,c0,c1,c)
783 #define cimg_for_outXY(img,x0,y0,x1,y1,x,y) cimg_for_out2((img)._width,(img)._height,x0,y0,x1,y1,x,y)
784 #define cimg_for_outXZ(img,x0,z0,x1,z1,x,z) cimg_for_out2((img)._width,(img)._depth,x0,z0,x1,z1,x,z)
785 #define cimg_for_outXC(img,x0,c0,x1,c1,x,c) cimg_for_out2((img)._width,(img)._spectrum,x0,c0,x1,c1,x,c)
786 #define cimg_for_outYZ(img,y0,z0,y1,z1,y,z) cimg_for_out2((img)._height,(img)._depth,y0,z0,y1,z1,y,z)
787 #define cimg_for_outYC(img,y0,c0,y1,c1,y,c) cimg_for_out2((img)._height,(img)._spectrum,y0,c0,y1,c1,y,c)
788 #define cimg_for_outZC(img,z0,c0,z1,c1,z,c) cimg_for_out2((img)._depth,(img)._spectrum,z0,c0,z1,c1,z,c)
789 #define cimg_for_outXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) \
790 cimg_for_out3((img)._width,(img)._height,(img)._depth,x0,y0,z0,x1,y1,z1,x,y,z)
791 #define cimg_for_outXYC(img,x0,y0,c0,x1,y1,c1,x,y,c) \
792 cimg_for_out3((img)._width,(img)._height,(img)._spectrum,x0,y0,c0,x1,y1,c1,x,y,c)
793 #define cimg_for_outXZC(img,x0,z0,c0,x1,z1,c1,x,z,c) \
794 cimg_for_out3((img)._width,(img)._depth,(img)._spectrum,x0,z0,c0,x1,z1,c1,x,z,c)
795 #define cimg_for_outYZC(img,y0,z0,c0,y1,z1,c1,y,z,c) \
796 cimg_for_out3((img)._height,(img)._depth,(img)._spectrum,y0,z0,c0,y1,z1,c1,y,z,c)
797 #define cimg_for_outXYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \
798 cimg_for_out4((img)._width,(img)._height,(img)._depth,(img)._spectrum,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c)
799 #define cimg_for_borderX(img,x,n) cimg_for_outX(img,n,(img)._width-1-(n),x)
800 #define cimg_for_borderY(img,y,n) cimg_for_outY(img,n,(img)._height-1-(n),y)
801 #define cimg_for_borderZ(img,z,n) cimg_for_outZ(img,n,(img)._depth-1-(n),z)
802 #define cimg_for_borderC(img,c,n) cimg_for_outC(img,n,(img)._spectrum-1-(n),c)
803 #define cimg_for_borderXY(img,x,y,n) cimg_for_outXY(img,n,n,(img)._width-1-(n),(img)._height-1-(n),x,y)
804 #define cimg_for_borderXYZ(img,x,y,z,n) \
805 cimg_for_outXYZ(img,n,n,n,(img)._width-1-(n),(img)._height-1-(n),(img)._depth-1-(n),x,y,z)
806 #define cimg_for_borderXYZC(img,x,y,z,c,n) \
807 cimg_for_outXYZC(img,n,n,n,n,(img)._width-1-(n),(img)._height-1-(n),(img)._depth-1-(n),(img)._spectrum-1-(n),x,y,z,c)
809 #define cimg_for_spiralXY(img,x,y) \
810 for (int x = 0, y = 0, _n1##x = 1, _n1##y = (img).width()*(img).height(); _n1##y; \
811 --_n1##y, _n1##x+=(_n1##x>>2)-((!(_n1##x&3)?--y:((_n1##x&3)==1?(img)._width-1-++x:\
812 ((_n1##x&3)==2?(img)._height-1-++y:--x))))?0:1)
814 #define cimg_for_lineXY(x,y,x0,y0,x1,y1) \
815 for (int x = (int)(x0), y = (int)(y0), _sx = 1, _sy = 1, _steep = 0, \
816 _dx=(x1)>(x0)?(int)(x1)-(int)(x0):(_sx=-1,(int)(x0)-(int)(x1)), \
817 _dy=(y1)>(y0)?(int)(y1)-(int)(y0):(_sy=-1,(int)(y0)-(int)(y1)), \
819 _err = _dx>_dy?(_dy>>1):((_steep=1),(_counter=_dy),(_dx>>1)); \
821 --_counter, x+=_steep? \
822 (y+=_sy,(_err-=_dx)<0?_err+=_dy,_sx:0): \
823 (y+=(_err-=_dy)<0?_err+=_dx,_sy:0,_sx))
825 #define cimg_for2(bound,i) \
826 for (int i = 0, _n1##i = 1>=(bound)?(int)(bound)-1:1; \
827 _n1##i<(int)(bound) || i==--_n1##i; \
829 #define cimg_for2X(img,x) cimg_for2((img)._width,x)
830 #define cimg_for2Y(img,y) cimg_for2((img)._height,y)
831 #define cimg_for2Z(img,z) cimg_for2((img)._depth,z)
832 #define cimg_for2C(img,c) cimg_for2((img)._spectrum,c)
833 #define cimg_for2XY(img,x,y) cimg_for2Y(img,y) cimg_for2X(img,x)
834 #define cimg_for2XZ(img,x,z) cimg_for2Z(img,z) cimg_for2X(img,x)
835 #define cimg_for2XC(img,x,c) cimg_for2C(img,c) cimg_for2X(img,x)
836 #define cimg_for2YZ(img,y,z) cimg_for2Z(img,z) cimg_for2Y(img,y)
837 #define cimg_for2YC(img,y,c) cimg_for2C(img,c) cimg_for2Y(img,y)
838 #define cimg_for2ZC(img,z,c) cimg_for2C(img,c) cimg_for2Z(img,z)
839 #define cimg_for2XYZ(img,x,y,z) cimg_for2Z(img,z) cimg_for2XY(img,x,y)
840 #define cimg_for2XZC(img,x,z,c) cimg_for2C(img,c) cimg_for2XZ(img,x,z)
841 #define cimg_for2YZC(img,y,z,c) cimg_for2C(img,c) cimg_for2YZ(img,y,z)
842 #define cimg_for2XYZC(img,x,y,z,c) cimg_for2C(img,c) cimg_for2XYZ(img,x,y,z)
844 #define cimg_for_in2(bound,i0,i1,i) \
845 for (int i = (int)(i0)<0?0:(int)(i0), \
846 _n1##i = i+1>=(int)(bound)?(int)(bound)-1:i+1; \
847 i<=(int)(i1) && (_n1##i<(int)(bound) || i==--_n1##i); \
849 #define cimg_for_in2X(img,x0,x1,x) cimg_for_in2((img)._width,x0,x1,x)
850 #define cimg_for_in2Y(img,y0,y1,y) cimg_for_in2((img)._height,y0,y1,y)
851 #define cimg_for_in2Z(img,z0,z1,z) cimg_for_in2((img)._depth,z0,z1,z)
852 #define cimg_for_in2C(img,c0,c1,c) cimg_for_in2((img)._spectrum,c0,c1,c)
853 #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)
854 #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)
855 #define cimg_for_in2XC(img,x0,c0,x1,c1,x,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2X(img,x0,x1,x)
856 #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)
857 #define cimg_for_in2YC(img,y0,c0,y1,c1,y,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2Y(img,y0,y1,y)
858 #define cimg_for_in2ZC(img,z0,c0,z1,c1,z,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2Z(img,z0,z1,z)
859 #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)
860 #define cimg_for_in2XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2XZ(img,x0,y0,x1,y1,x,z)
861 #define cimg_for_in2YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2YZ(img,y0,z0,y1,z1,y,z)
862 #define cimg_for_in2XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \
863 cimg_for_in2C(img,c0,c1,c) cimg_for_in2XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z)
865 #define cimg_for3(bound,i) \
866 for (int i = 0, _p1##i = 0, \
867 _n1##i = 1>=(bound)?(int)(bound)-1:1; \
868 _n1##i<(int)(bound) || i==--_n1##i; \
869 _p1##i = i++, ++_n1##i)
870 #define cimg_for3X(img,x) cimg_for3((img)._width,x)
871 #define cimg_for3Y(img,y) cimg_for3((img)._height,y)
872 #define cimg_for3Z(img,z) cimg_for3((img)._depth,z)
873 #define cimg_for3C(img,c) cimg_for3((img)._spectrum,c)
874 #define cimg_for3XY(img,x,y) cimg_for3Y(img,y) cimg_for3X(img,x)
875 #define cimg_for3XZ(img,x,z) cimg_for3Z(img,z) cimg_for3X(img,x)
876 #define cimg_for3XC(img,x,c) cimg_for3C(img,c) cimg_for3X(img,x)
877 #define cimg_for3YZ(img,y,z) cimg_for3Z(img,z) cimg_for3Y(img,y)
878 #define cimg_for3YC(img,y,c) cimg_for3C(img,c) cimg_for3Y(img,y)
879 #define cimg_for3ZC(img,z,c) cimg_for3C(img,c) cimg_for3Z(img,z)
880 #define cimg_for3XYZ(img,x,y,z) cimg_for3Z(img,z) cimg_for3XY(img,x,y)
881 #define cimg_for3XZC(img,x,z,c) cimg_for3C(img,c) cimg_for3XZ(img,x,z)
882 #define cimg_for3YZC(img,y,z,c) cimg_for3C(img,c) cimg_for3YZ(img,y,z)
883 #define cimg_for3XYZC(img,x,y,z,c) cimg_for3C(img,c) cimg_for3XYZ(img,x,y,z)
885 #define cimg_for_in3(bound,i0,i1,i) \
886 for (int i = (int)(i0)<0?0:(int)(i0), \
887 _p1##i = i-1<0?0:i-1, \
888 _n1##i = i+1>=(int)(bound)?(int)(bound)-1:i+1; \
889 i<=(int)(i1) && (_n1##i<(int)(bound) || i==--_n1##i); \
890 _p1##i = i++, ++_n1##i)
891 #define cimg_for_in3X(img,x0,x1,x) cimg_for_in3((img)._width,x0,x1,x)
892 #define cimg_for_in3Y(img,y0,y1,y) cimg_for_in3((img)._height,y0,y1,y)
893 #define cimg_for_in3Z(img,z0,z1,z) cimg_for_in3((img)._depth,z0,z1,z)
894 #define cimg_for_in3C(img,c0,c1,c) cimg_for_in3((img)._spectrum,c0,c1,c)
895 #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)
896 #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)
897 #define cimg_for_in3XC(img,x0,c0,x1,c1,x,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3X(img,x0,x1,x)
898 #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)
899 #define cimg_for_in3YC(img,y0,c0,y1,c1,y,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3Y(img,y0,y1,y)
900 #define cimg_for_in3ZC(img,z0,c0,z1,c1,z,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3Z(img,z0,z1,z)
901 #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)
902 #define cimg_for_in3XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3XZ(img,x0,y0,x1,y1,x,z)
903 #define cimg_for_in3YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3YZ(img,y0,z0,y1,z1,y,z)
904 #define cimg_for_in3XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \
905 cimg_for_in3C(img,c0,c1,c) cimg_for_in3XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z)
907 #define cimg_for4(bound,i) \
908 for (int i = 0, _p1##i = 0, _n1##i = 1>=(bound)?(int)(bound)-1:1, \
909 _n2##i = 2>=(bound)?(int)(bound)-1:2; \
910 _n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i); \
911 _p1##i = i++, ++_n1##i, ++_n2##i)
912 #define cimg_for4X(img,x) cimg_for4((img)._width,x)
913 #define cimg_for4Y(img,y) cimg_for4((img)._height,y)
914 #define cimg_for4Z(img,z) cimg_for4((img)._depth,z)
915 #define cimg_for4C(img,c) cimg_for4((img)._spectrum,c)
916 #define cimg_for4XY(img,x,y) cimg_for4Y(img,y) cimg_for4X(img,x)
917 #define cimg_for4XZ(img,x,z) cimg_for4Z(img,z) cimg_for4X(img,x)
918 #define cimg_for4XC(img,x,c) cimg_for4C(img,c) cimg_for4X(img,x)
919 #define cimg_for4YZ(img,y,z) cimg_for4Z(img,z) cimg_for4Y(img,y)
920 #define cimg_for4YC(img,y,c) cimg_for4C(img,c) cimg_for4Y(img,y)
921 #define cimg_for4ZC(img,z,c) cimg_for4C(img,c) cimg_for4Z(img,z)
922 #define cimg_for4XYZ(img,x,y,z) cimg_for4Z(img,z) cimg_for4XY(img,x,y)
923 #define cimg_for4XZC(img,x,z,c) cimg_for4C(img,c) cimg_for4XZ(img,x,z)
924 #define cimg_for4YZC(img,y,z,c) cimg_for4C(img,c) cimg_for4YZ(img,y,z)
925 #define cimg_for4XYZC(img,x,y,z,c) cimg_for4C(img,c) cimg_for4XYZ(img,x,y,z)
927 #define cimg_for_in4(bound,i0,i1,i) \
928 for (int i = (int)(i0)<0?0:(int)(i0), \
929 _p1##i = i-1<0?0:i-1, \
930 _n1##i = i+1>=(int)(bound)?(int)(bound)-1:i+1, \
931 _n2##i = i+2>=(int)(bound)?(int)(bound)-1:i+2; \
932 i<=(int)(i1) && (_n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i)); \
933 _p1##i = i++, ++_n1##i, ++_n2##i)
934 #define cimg_for_in4X(img,x0,x1,x) cimg_for_in4((img)._width,x0,x1,x)
935 #define cimg_for_in4Y(img,y0,y1,y) cimg_for_in4((img)._height,y0,y1,y)
936 #define cimg_for_in4Z(img,z0,z1,z) cimg_for_in4((img)._depth,z0,z1,z)
937 #define cimg_for_in4C(img,c0,c1,c) cimg_for_in4((img)._spectrum,c0,c1,c)
938 #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)
939 #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)
940 #define cimg_for_in4XC(img,x0,c0,x1,c1,x,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4X(img,x0,x1,x)
941 #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)
942 #define cimg_for_in4YC(img,y0,c0,y1,c1,y,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4Y(img,y0,y1,y)
943 #define cimg_for_in4ZC(img,z0,c0,z1,c1,z,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4Z(img,z0,z1,z)
944 #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)
945 #define cimg_for_in4XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4XZ(img,x0,y0,x1,y1,x,z)
946 #define cimg_for_in4YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4YZ(img,y0,z0,y1,z1,y,z)
947 #define cimg_for_in4XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \
948 cimg_for_in4C(img,c0,c1,c) cimg_for_in4XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z)
950 #define cimg_for5(bound,i) \
951 for (int i = 0, _p2##i = 0, _p1##i = 0, \
952 _n1##i = 1>=(bound)?(int)(bound)-1:1, \
953 _n2##i = 2>=(bound)?(int)(bound)-1:2; \
954 _n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i); \
955 _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i)
956 #define cimg_for5X(img,x) cimg_for5((img)._width,x)
957 #define cimg_for5Y(img,y) cimg_for5((img)._height,y)
958 #define cimg_for5Z(img,z) cimg_for5((img)._depth,z)
959 #define cimg_for5C(img,c) cimg_for5((img)._spectrum,c)
960 #define cimg_for5XY(img,x,y) cimg_for5Y(img,y) cimg_for5X(img,x)
961 #define cimg_for5XZ(img,x,z) cimg_for5Z(img,z) cimg_for5X(img,x)
962 #define cimg_for5XC(img,x,c) cimg_for5C(img,c) cimg_for5X(img,x)
963 #define cimg_for5YZ(img,y,z) cimg_for5Z(img,z) cimg_for5Y(img,y)
964 #define cimg_for5YC(img,y,c) cimg_for5C(img,c) cimg_for5Y(img,y)
965 #define cimg_for5ZC(img,z,c) cimg_for5C(img,c) cimg_for5Z(img,z)
966 #define cimg_for5XYZ(img,x,y,z) cimg_for5Z(img,z) cimg_for5XY(img,x,y)
967 #define cimg_for5XZC(img,x,z,c) cimg_for5C(img,c) cimg_for5XZ(img,x,z)
968 #define cimg_for5YZC(img,y,z,c) cimg_for5C(img,c) cimg_for5YZ(img,y,z)
969 #define cimg_for5XYZC(img,x,y,z,c) cimg_for5C(img,c) cimg_for5XYZ(img,x,y,z)
971 #define cimg_for_in5(bound,i0,i1,i) \
972 for (int i = (int)(i0)<0?0:(int)(i0), \
973 _p2##i = i-2<0?0:i-2, \
974 _p1##i = i-1<0?0:i-1, \
975 _n1##i = i+1>=(int)(bound)?(int)(bound)-1:i+1, \
976 _n2##i = i+2>=(int)(bound)?(int)(bound)-1:i+2; \
977 i<=(int)(i1) && (_n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i)); \
978 _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i)
979 #define cimg_for_in5X(img,x0,x1,x) cimg_for_in5((img)._width,x0,x1,x)
980 #define cimg_for_in5Y(img,y0,y1,y) cimg_for_in5((img)._height,y0,y1,y)
981 #define cimg_for_in5Z(img,z0,z1,z) cimg_for_in5((img)._depth,z0,z1,z)
982 #define cimg_for_in5C(img,c0,c1,c) cimg_for_in5((img)._spectrum,c0,c1,c)
983 #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)
984 #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)
985 #define cimg_for_in5XC(img,x0,c0,x1,c1,x,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5X(img,x0,x1,x)
986 #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)
987 #define cimg_for_in5YC(img,y0,c0,y1,c1,y,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5Y(img,y0,y1,y)
988 #define cimg_for_in5ZC(img,z0,c0,z1,c1,z,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5Z(img,z0,z1,z)
989 #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)
990 #define cimg_for_in5XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5XZ(img,x0,y0,x1,y1,x,z)
991 #define cimg_for_in5YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5YZ(img,y0,z0,y1,z1,y,z)
992 #define cimg_for_in5XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \
993 cimg_for_in5C(img,c0,c1,c) cimg_for_in5XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z)
995 #define cimg_for6(bound,i) \
996 for (int i = 0, _p2##i = 0, _p1##i = 0, \
997 _n1##i = 1>=(bound)?(int)(bound)-1:1, \
998 _n2##i = 2>=(bound)?(int)(bound)-1:2, \
999 _n3##i = 3>=(bound)?(int)(bound)-1:3; \
1000 _n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i); \
1001 _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i)
1002 #define cimg_for6X(img,x) cimg_for6((img)._width,x)
1003 #define cimg_for6Y(img,y) cimg_for6((img)._height,y)
1004 #define cimg_for6Z(img,z) cimg_for6((img)._depth,z)
1005 #define cimg_for6C(img,c) cimg_for6((img)._spectrum,c)
1006 #define cimg_for6XY(img,x,y) cimg_for6Y(img,y) cimg_for6X(img,x)
1007 #define cimg_for6XZ(img,x,z) cimg_for6Z(img,z) cimg_for6X(img,x)
1008 #define cimg_for6XC(img,x,c) cimg_for6C(img,c) cimg_for6X(img,x)
1009 #define cimg_for6YZ(img,y,z) cimg_for6Z(img,z) cimg_for6Y(img,y)
1010 #define cimg_for6YC(img,y,c) cimg_for6C(img,c) cimg_for6Y(img,y)
1011 #define cimg_for6ZC(img,z,c) cimg_for6C(img,c) cimg_for6Z(img,z)
1012 #define cimg_for6XYZ(img,x,y,z) cimg_for6Z(img,z) cimg_for6XY(img,x,y)
1013 #define cimg_for6XZC(img,x,z,c) cimg_for6C(img,c) cimg_for6XZ(img,x,z)
1014 #define cimg_for6YZC(img,y,z,c) cimg_for6C(img,c) cimg_for6YZ(img,y,z)
1015 #define cimg_for6XYZC(img,x,y,z,c) cimg_for6C(img,c) cimg_for6XYZ(img,x,y,z)
1017 #define cimg_for_in6(bound,i0,i1,i) \
1018 for (int i = (int)(i0)<0?0:(int)(i0), \
1019 _p2##i = i-2<0?0:i-2, \
1020 _p1##i = i-1<0?0:i-1, \
1021 _n1##i = i+1>=(int)(bound)?(int)(bound)-1:i+1, \
1022 _n2##i = i+2>=(int)(bound)?(int)(bound)-1:i+2, \
1023 _n3##i = i+3>=(int)(bound)?(int)(bound)-1:i+3; \
1025 (_n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i)); \
1026 _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i)
1027 #define cimg_for_in6X(img,x0,x1,x) cimg_for_in6((img)._width,x0,x1,x)
1028 #define cimg_for_in6Y(img,y0,y1,y) cimg_for_in6((img)._height,y0,y1,y)
1029 #define cimg_for_in6Z(img,z0,z1,z) cimg_for_in6((img)._depth,z0,z1,z)
1030 #define cimg_for_in6C(img,c0,c1,c) cimg_for_in6((img)._spectrum,c0,c1,c)
1031 #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)
1032 #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)
1033 #define cimg_for_in6XC(img,x0,c0,x1,c1,x,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6X(img,x0,x1,x)
1034 #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)
1035 #define cimg_for_in6YC(img,y0,c0,y1,c1,y,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6Y(img,y0,y1,y)
1036 #define cimg_for_in6ZC(img,z0,c0,z1,c1,z,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6Z(img,z0,z1,z)
1037 #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)
1038 #define cimg_for_in6XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6XZ(img,x0,y0,x1,y1,x,z)
1039 #define cimg_for_in6YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6YZ(img,y0,z0,y1,z1,y,z)
1040 #define cimg_for_in6XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \
1041 cimg_for_in6C(img,c0,c1,c) cimg_for_in6XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z)
1043 #define cimg_for7(bound,i) \
1044 for (int i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \
1045 _n1##i = 1>=(bound)?(int)(bound)-1:1, \
1046 _n2##i = 2>=(bound)?(int)(bound)-1:2, \
1047 _n3##i = 3>=(bound)?(int)(bound)-1:3; \
1048 _n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i); \
1049 _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i)
1050 #define cimg_for7X(img,x) cimg_for7((img)._width,x)
1051 #define cimg_for7Y(img,y) cimg_for7((img)._height,y)
1052 #define cimg_for7Z(img,z) cimg_for7((img)._depth,z)
1053 #define cimg_for7C(img,c) cimg_for7((img)._spectrum,c)
1054 #define cimg_for7XY(img,x,y) cimg_for7Y(img,y) cimg_for7X(img,x)
1055 #define cimg_for7XZ(img,x,z) cimg_for7Z(img,z) cimg_for7X(img,x)
1056 #define cimg_for7XC(img,x,c) cimg_for7C(img,c) cimg_for7X(img,x)
1057 #define cimg_for7YZ(img,y,z) cimg_for7Z(img,z) cimg_for7Y(img,y)
1058 #define cimg_for7YC(img,y,c) cimg_for7C(img,c) cimg_for7Y(img,y)
1059 #define cimg_for7ZC(img,z,c) cimg_for7C(img,c) cimg_for7Z(img,z)
1060 #define cimg_for7XYZ(img,x,y,z) cimg_for7Z(img,z) cimg_for7XY(img,x,y)
1061 #define cimg_for7XZC(img,x,z,c) cimg_for7C(img,c) cimg_for7XZ(img,x,z)
1062 #define cimg_for7YZC(img,y,z,c) cimg_for7C(img,c) cimg_for7YZ(img,y,z)
1063 #define cimg_for7XYZC(img,x,y,z,c) cimg_for7C(img,c) cimg_for7XYZ(img,x,y,z)
1065 #define cimg_for_in7(bound,i0,i1,i) \
1066 for (int i = (int)(i0)<0?0:(int)(i0), \
1067 _p3##i = i-3<0?0:i-3, \
1068 _p2##i = i-2<0?0:i-2, \
1069 _p1##i = i-1<0?0:i-1, \
1070 _n1##i = i+1>=(int)(bound)?(int)(bound)-1:i+1, \
1071 _n2##i = i+2>=(int)(bound)?(int)(bound)-1:i+2, \
1072 _n3##i = i+3>=(int)(bound)?(int)(bound)-1:i+3; \
1074 (_n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i)); \
1075 _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i)
1076 #define cimg_for_in7X(img,x0,x1,x) cimg_for_in7((img)._width,x0,x1,x)
1077 #define cimg_for_in7Y(img,y0,y1,y) cimg_for_in7((img)._height,y0,y1,y)
1078 #define cimg_for_in7Z(img,z0,z1,z) cimg_for_in7((img)._depth,z0,z1,z)
1079 #define cimg_for_in7C(img,c0,c1,c) cimg_for_in7((img)._spectrum,c0,c1,c)
1080 #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)
1081 #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)
1082 #define cimg_for_in7XC(img,x0,c0,x1,c1,x,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7X(img,x0,x1,x)
1083 #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)
1084 #define cimg_for_in7YC(img,y0,c0,y1,c1,y,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7Y(img,y0,y1,y)
1085 #define cimg_for_in7ZC(img,z0,c0,z1,c1,z,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7Z(img,z0,z1,z)
1086 #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)
1087 #define cimg_for_in7XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7XZ(img,x0,y0,x1,y1,x,z)
1088 #define cimg_for_in7YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7YZ(img,y0,z0,y1,z1,y,z)
1089 #define cimg_for_in7XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \
1090 cimg_for_in7C(img,c0,c1,c) cimg_for_in7XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z)
1092 #define cimg_for8(bound,i) \
1093 for (int i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \
1094 _n1##i = 1>=(bound)?(int)(bound)-1:1, \
1095 _n2##i = 2>=(bound)?(int)(bound)-1:2, \
1096 _n3##i = 3>=(bound)?(int)(bound)-1:3, \
1097 _n4##i = 4>=(bound)?(int)(bound)-1:4; \
1098 _n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \
1099 i==(_n4##i = _n3##i = _n2##i = --_n1##i); \
1100 _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i)
1101 #define cimg_for8X(img,x) cimg_for8((img)._width,x)
1102 #define cimg_for8Y(img,y) cimg_for8((img)._height,y)
1103 #define cimg_for8Z(img,z) cimg_for8((img)._depth,z)
1104 #define cimg_for8C(img,c) cimg_for8((img)._spectrum,c)
1105 #define cimg_for8XY(img,x,y) cimg_for8Y(img,y) cimg_for8X(img,x)
1106 #define cimg_for8XZ(img,x,z) cimg_for8Z(img,z) cimg_for8X(img,x)
1107 #define cimg_for8XC(img,x,c) cimg_for8C(img,c) cimg_for8X(img,x)
1108 #define cimg_for8YZ(img,y,z) cimg_for8Z(img,z) cimg_for8Y(img,y)
1109 #define cimg_for8YC(img,y,c) cimg_for8C(img,c) cimg_for8Y(img,y)
1110 #define cimg_for8ZC(img,z,c) cimg_for8C(img,c) cimg_for8Z(img,z)
1111 #define cimg_for8XYZ(img,x,y,z) cimg_for8Z(img,z) cimg_for8XY(img,x,y)
1112 #define cimg_for8XZC(img,x,z,c) cimg_for8C(img,c) cimg_for8XZ(img,x,z)
1113 #define cimg_for8YZC(img,y,z,c) cimg_for8C(img,c) cimg_for8YZ(img,y,z)
1114 #define cimg_for8XYZC(img,x,y,z,c) cimg_for8C(img,c) cimg_for8XYZ(img,x,y,z)
1116 #define cimg_for_in8(bound,i0,i1,i) \
1117 for (int i = (int)(i0)<0?0:(int)(i0), \
1118 _p3##i = i-3<0?0:i-3, \
1119 _p2##i = i-2<0?0:i-2, \
1120 _p1##i = i-1<0?0:i-1, \
1121 _n1##i = i+1>=(int)(bound)?(int)(bound)-1:i+1, \
1122 _n2##i = i+2>=(int)(bound)?(int)(bound)-1:i+2, \
1123 _n3##i = i+3>=(int)(bound)?(int)(bound)-1:i+3, \
1124 _n4##i = i+4>=(int)(bound)?(int)(bound)-1:i+4; \
1125 i<=(int)(i1) && (_n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \
1126 i==(_n4##i = _n3##i = _n2##i = --_n1##i)); \
1127 _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i)
1128 #define cimg_for_in8X(img,x0,x1,x) cimg_for_in8((img)._width,x0,x1,x)
1129 #define cimg_for_in8Y(img,y0,y1,y) cimg_for_in8((img)._height,y0,y1,y)
1130 #define cimg_for_in8Z(img,z0,z1,z) cimg_for_in8((img)._depth,z0,z1,z)
1131 #define cimg_for_in8C(img,c0,c1,c) cimg_for_in8((img)._spectrum,c0,c1,c)
1132 #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)
1133 #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)
1134 #define cimg_for_in8XC(img,x0,c0,x1,c1,x,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8X(img,x0,x1,x)
1135 #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)
1136 #define cimg_for_in8YC(img,y0,c0,y1,c1,y,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8Y(img,y0,y1,y)
1137 #define cimg_for_in8ZC(img,z0,c0,z1,c1,z,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8Z(img,z0,z1,z)
1138 #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)
1139 #define cimg_for_in8XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8XZ(img,x0,y0,x1,y1,x,z)
1140 #define cimg_for_in8YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8YZ(img,y0,z0,y1,z1,y,z)
1141 #define cimg_for_in8XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \
1142 cimg_for_in8C(img,c0,c1,c) cimg_for_in8XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z)
1144 #define cimg_for9(bound,i) \
1145 for (int i = 0, _p4##i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \
1146 _n1##i = 1>=(int)(bound)?(int)(bound)-1:1, \
1147 _n2##i = 2>=(int)(bound)?(int)(bound)-1:2, \
1148 _n3##i = 3>=(int)(bound)?(int)(bound)-1:3, \
1149 _n4##i = 4>=(int)(bound)?(int)(bound)-1:4; \
1150 _n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \
1151 i==(_n4##i = _n3##i = _n2##i = --_n1##i); \
1152 _p4##i = _p3##i, _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i)
1153 #define cimg_for9X(img,x) cimg_for9((img)._width,x)
1154 #define cimg_for9Y(img,y) cimg_for9((img)._height,y)
1155 #define cimg_for9Z(img,z) cimg_for9((img)._depth,z)
1156 #define cimg_for9C(img,c) cimg_for9((img)._spectrum,c)
1157 #define cimg_for9XY(img,x,y) cimg_for9Y(img,y) cimg_for9X(img,x)
1158 #define cimg_for9XZ(img,x,z) cimg_for9Z(img,z) cimg_for9X(img,x)
1159 #define cimg_for9XC(img,x,c) cimg_for9C(img,c) cimg_for9X(img,x)
1160 #define cimg_for9YZ(img,y,z) cimg_for9Z(img,z) cimg_for9Y(img,y)
1161 #define cimg_for9YC(img,y,c) cimg_for9C(img,c) cimg_for9Y(img,y)
1162 #define cimg_for9ZC(img,z,c) cimg_for9C(img,c) cimg_for9Z(img,z)
1163 #define cimg_for9XYZ(img,x,y,z) cimg_for9Z(img,z) cimg_for9XY(img,x,y)
1164 #define cimg_for9XZC(img,x,z,c) cimg_for9C(img,c) cimg_for9XZ(img,x,z)
1165 #define cimg_for9YZC(img,y,z,c) cimg_for9C(img,c) cimg_for9YZ(img,y,z)
1166 #define cimg_for9XYZC(img,x,y,z,c) cimg_for9C(img,c) cimg_for9XYZ(img,x,y,z)
1168 #define cimg_for_in9(bound,i0,i1,i) \
1169 for (int i = (int)(i0)<0?0:(int)(i0), \
1170 _p4##i = i-4<0?0:i-4, \
1171 _p3##i = i-3<0?0:i-3, \
1172 _p2##i = i-2<0?0:i-2, \
1173 _p1##i = i-1<0?0:i-1, \
1174 _n1##i = i+1>=(int)(bound)?(int)(bound)-1:i+1, \
1175 _n2##i = i+2>=(int)(bound)?(int)(bound)-1:i+2, \
1176 _n3##i = i+3>=(int)(bound)?(int)(bound)-1:i+3, \
1177 _n4##i = i+4>=(int)(bound)?(int)(bound)-1:i+4; \
1178 i<=(int)(i1) && (_n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \
1179 i==(_n4##i = _n3##i = _n2##i = --_n1##i)); \
1180 _p4##i = _p3##i, _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i)
1181 #define cimg_for_in9X(img,x0,x1,x) cimg_for_in9((img)._width,x0,x1,x)
1182 #define cimg_for_in9Y(img,y0,y1,y) cimg_for_in9((img)._height,y0,y1,y)
1183 #define cimg_for_in9Z(img,z0,z1,z) cimg_for_in9((img)._depth,z0,z1,z)
1184 #define cimg_for_in9C(img,c0,c1,c) cimg_for_in9((img)._spectrum,c0,c1,c)
1185 #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)
1186 #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)
1187 #define cimg_for_in9XC(img,x0,c0,x1,c1,x,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9X(img,x0,x1,x)
1188 #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)
1189 #define cimg_for_in9YC(img,y0,c0,y1,c1,y,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9Y(img,y0,y1,y)
1190 #define cimg_for_in9ZC(img,z0,c0,z1,c1,z,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9Z(img,z0,z1,z)
1191 #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)
1192 #define cimg_for_in9XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9XZ(img,x0,y0,x1,y1,x,z)
1193 #define cimg_for_in9YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9YZ(img,y0,z0,y1,z1,y,z)
1194 #define cimg_for_in9XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \
1195 cimg_for_in9C(img,c0,c1,c) cimg_for_in9XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z)
1197 #define cimg_for2x2(img,x,y,z,c,I,T) \
1198 cimg_for2((img)._height,y) for (int x = 0, \
1200 (I[0] = (T)(img)(0,y,z,c)), \
1201 (I[2] = (T)(img)(0,_n1##y,z,c)), \
1202 1>=(img)._width?(img).width()-1:1); \
1203 (_n1##x<(img).width() && ( \
1204 (I[1] = (T)(img)(_n1##x,y,z,c)), \
1205 (I[3] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \
1211 #define cimg_for_in2x2(img,x0,y0,x1,y1,x,y,z,c,I,T) \
1212 cimg_for_in2((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \
1214 (I[0] = (T)(img)(x,y,z,c)), \
1215 (I[2] = (T)(img)(x,_n1##y,z,c)), \
1216 x+1>=(int)(img)._width?(img).width()-1:x+1); \
1217 x<=(int)(x1) && ((_n1##x<(img).width() && ( \
1218 (I[1] = (T)(img)(_n1##x,y,z,c)), \
1219 (I[3] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \
1225 #define cimg_for3x3(img,x,y,z,c,I,T) \
1226 cimg_for3((img)._height,y) for (int x = 0, \
1229 (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \
1230 (I[3] = I[4] = (T)(img)(0,y,z,c)), \
1231 (I[6] = I[7] = (T)(img)(0,_n1##y,z,c)), \
1232 1>=(img)._width?(img).width()-1:1); \
1233 (_n1##x<(img).width() && ( \
1234 (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \
1235 (I[5] = (T)(img)(_n1##x,y,z,c)), \
1236 (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \
1238 I[0] = I[1], I[1] = I[2], \
1239 I[3] = I[4], I[4] = I[5], \
1240 I[6] = I[7], I[7] = I[8], \
1241 _p1##x = x++, ++_n1##x)
1243 #define cimg_for_in3x3(img,x0,y0,x1,y1,x,y,z,c,I,T) \
1244 cimg_for_in3((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \
1245 _p1##x = x-1<0?0:x-1, \
1247 (I[0] = (T)(img)(_p1##x,_p1##y,z,c)), \
1248 (I[3] = (T)(img)(_p1##x,y,z,c)), \
1249 (I[6] = (T)(img)(_p1##x,_n1##y,z,c)), \
1250 (I[1] = (T)(img)(x,_p1##y,z,c)), \
1251 (I[4] = (T)(img)(x,y,z,c)), \
1252 (I[7] = (T)(img)(x,_n1##y,z,c)), \
1253 x+1>=(int)(img)._width?(img).width()-1:x+1); \
1254 x<=(int)(x1) && ((_n1##x<(img).width() && ( \
1255 (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \
1256 (I[5] = (T)(img)(_n1##x,y,z,c)), \
1257 (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \
1259 I[0] = I[1], I[1] = I[2], \
1260 I[3] = I[4], I[4] = I[5], \
1261 I[6] = I[7], I[7] = I[8], \
1262 _p1##x = x++, ++_n1##x)
1264 #define cimg_for4x4(img,x,y,z,c,I,T) \
1265 cimg_for4((img)._height,y) for (int x = 0, \
1267 _n1##x = 1>=(img)._width?(img).width()-1:1, \
1269 (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \
1270 (I[4] = I[5] = (T)(img)(0,y,z,c)), \
1271 (I[8] = I[9] = (T)(img)(0,_n1##y,z,c)), \
1272 (I[12] = I[13] = (T)(img)(0,_n2##y,z,c)), \
1273 (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \
1274 (I[6] = (T)(img)(_n1##x,y,z,c)), \
1275 (I[10] = (T)(img)(_n1##x,_n1##y,z,c)), \
1276 (I[14] = (T)(img)(_n1##x,_n2##y,z,c)), \
1277 2>=(img)._width?(img).width()-1:2); \
1278 (_n2##x<(img).width() && ( \
1279 (I[3] = (T)(img)(_n2##x,_p1##y,z,c)), \
1280 (I[7] = (T)(img)(_n2##x,y,z,c)), \
1281 (I[11] = (T)(img)(_n2##x,_n1##y,z,c)), \
1282 (I[15] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \
1283 _n1##x==--_n2##x || x==(_n2##x = --_n1##x); \
1284 I[0] = I[1], I[1] = I[2], I[2] = I[3], \
1285 I[4] = I[5], I[5] = I[6], I[6] = I[7], \
1286 I[8] = I[9], I[9] = I[10], I[10] = I[11], \
1287 I[12] = I[13], I[13] = I[14], I[14] = I[15], \
1288 _p1##x = x++, ++_n1##x, ++_n2##x)
1290 #define cimg_for_in4x4(img,x0,y0,x1,y1,x,y,z,c,I,T) \
1291 cimg_for_in4((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \
1292 _p1##x = x-1<0?0:x-1, \
1293 _n1##x = x+1>=(int)(img)._width?(img).width()-1:x+1, \
1295 (I[0] = (T)(img)(_p1##x,_p1##y,z,c)), \
1296 (I[4] = (T)(img)(_p1##x,y,z,c)), \
1297 (I[8] = (T)(img)(_p1##x,_n1##y,z,c)), \
1298 (I[12] = (T)(img)(_p1##x,_n2##y,z,c)), \
1299 (I[1] = (T)(img)(x,_p1##y,z,c)), \
1300 (I[5] = (T)(img)(x,y,z,c)), \
1301 (I[9] = (T)(img)(x,_n1##y,z,c)), \
1302 (I[13] = (T)(img)(x,_n2##y,z,c)), \
1303 (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \
1304 (I[6] = (T)(img)(_n1##x,y,z,c)), \
1305 (I[10] = (T)(img)(_n1##x,_n1##y,z,c)), \
1306 (I[14] = (T)(img)(_n1##x,_n2##y,z,c)), \
1307 x+2>=(int)(img)._width?(img).width()-1:x+2); \
1308 x<=(int)(x1) && ((_n2##x<(img).width() && ( \
1309 (I[3] = (T)(img)(_n2##x,_p1##y,z,c)), \
1310 (I[7] = (T)(img)(_n2##x,y,z,c)), \
1311 (I[11] = (T)(img)(_n2##x,_n1##y,z,c)), \
1312 (I[15] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \
1313 _n1##x==--_n2##x || x==(_n2##x = --_n1##x)); \
1314 I[0] = I[1], I[1] = I[2], I[2] = I[3], \
1315 I[4] = I[5], I[5] = I[6], I[6] = I[7], \
1316 I[8] = I[9], I[9] = I[10], I[10] = I[11], \
1317 I[12] = I[13], I[13] = I[14], I[14] = I[15], \
1318 _p1##x = x++, ++_n1##x, ++_n2##x)
1320 #define cimg_for5x5(img,x,y,z,c,I,T) \
1321 cimg_for5((img)._height,y) for (int x = 0, \
1322 _p2##x = 0, _p1##x = 0, \
1323 _n1##x = 1>=(img)._width?(img).width()-1:1, \
1325 (I[0] = I[1] = I[2] = (T)(img)(_p2##x,_p2##y,z,c)), \
1326 (I[5] = I[6] = I[7] = (T)(img)(0,_p1##y,z,c)), \
1327 (I[10] = I[11] = I[12] = (T)(img)(0,y,z,c)), \
1328 (I[15] = I[16] = I[17] = (T)(img)(0,_n1##y,z,c)), \
1329 (I[20] = I[21] = I[22] = (T)(img)(0,_n2##y,z,c)), \
1330 (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \
1331 (I[8] = (T)(img)(_n1##x,_p1##y,z,c)), \
1332 (I[13] = (T)(img)(_n1##x,y,z,c)), \
1333 (I[18] = (T)(img)(_n1##x,_n1##y,z,c)), \
1334 (I[23] = (T)(img)(_n1##x,_n2##y,z,c)), \
1335 2>=(img)._width?(img).width()-1:2); \
1336 (_n2##x<(img).width() && ( \
1337 (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \
1338 (I[9] = (T)(img)(_n2##x,_p1##y,z,c)), \
1339 (I[14] = (T)(img)(_n2##x,y,z,c)), \
1340 (I[19] = (T)(img)(_n2##x,_n1##y,z,c)), \
1341 (I[24] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \
1342 _n1##x==--_n2##x || x==(_n2##x = --_n1##x); \
1343 I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], \
1344 I[5] = I[6], I[6] = I[7], I[7] = I[8], I[8] = I[9], \
1345 I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], \
1346 I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], \
1347 I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \
1348 _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x)
1350 #define cimg_for_in5x5(img,x0,y0,x1,y1,x,y,z,c,I,T) \
1351 cimg_for_in5((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \
1352 _p2##x = x-2<0?0:x-2, \
1353 _p1##x = x-1<0?0:x-1, \
1354 _n1##x = x+1>=(int)(img)._width?(img).width()-1:x+1, \
1356 (I[0] = (T)(img)(_p2##x,_p2##y,z,c)), \
1357 (I[5] = (T)(img)(_p2##x,_p1##y,z,c)), \
1358 (I[10] = (T)(img)(_p2##x,y,z,c)), \
1359 (I[15] = (T)(img)(_p2##x,_n1##y,z,c)), \
1360 (I[20] = (T)(img)(_p2##x,_n2##y,z,c)), \
1361 (I[1] = (T)(img)(_p1##x,_p2##y,z,c)), \
1362 (I[6] = (T)(img)(_p1##x,_p1##y,z,c)), \
1363 (I[11] = (T)(img)(_p1##x,y,z,c)), \
1364 (I[16] = (T)(img)(_p1##x,_n1##y,z,c)), \
1365 (I[21] = (T)(img)(_p1##x,_n2##y,z,c)), \
1366 (I[2] = (T)(img)(x,_p2##y,z,c)), \
1367 (I[7] = (T)(img)(x,_p1##y,z,c)), \
1368 (I[12] = (T)(img)(x,y,z,c)), \
1369 (I[17] = (T)(img)(x,_n1##y,z,c)), \
1370 (I[22] = (T)(img)(x,_n2##y,z,c)), \
1371 (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \
1372 (I[8] = (T)(img)(_n1##x,_p1##y,z,c)), \
1373 (I[13] = (T)(img)(_n1##x,y,z,c)), \
1374 (I[18] = (T)(img)(_n1##x,_n1##y,z,c)), \
1375 (I[23] = (T)(img)(_n1##x,_n2##y,z,c)), \
1376 x+2>=(int)(img)._width?(img).width()-1:x+2); \
1377 x<=(int)(x1) && ((_n2##x<(img).width() && ( \
1378 (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \
1379 (I[9] = (T)(img)(_n2##x,_p1##y,z,c)), \
1380 (I[14] = (T)(img)(_n2##x,y,z,c)), \
1381 (I[19] = (T)(img)(_n2##x,_n1##y,z,c)), \
1382 (I[24] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \
1383 _n1##x==--_n2##x || x==(_n2##x = --_n1##x)); \
1384 I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], \
1385 I[5] = I[6], I[6] = I[7], I[7] = I[8], I[8] = I[9], \
1386 I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], \
1387 I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], \
1388 I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \
1389 _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x)
1391 #define cimg_for6x6(img,x,y,z,c,I,T) \
1392 cimg_for6((img)._height,y) for (int x = 0, \
1393 _p2##x = 0, _p1##x = 0, \
1394 _n1##x = 1>=(img)._width?(img).width()-1:1, \
1395 _n2##x = 2>=(img)._width?(img).width()-1:2, \
1397 (I[0] = I[1] = I[2] = (T)(img)(_p2##x,_p2##y,z,c)), \
1398 (I[6] = I[7] = I[8] = (T)(img)(0,_p1##y,z,c)), \
1399 (I[12] = I[13] = I[14] = (T)(img)(0,y,z,c)), \
1400 (I[18] = I[19] = I[20] = (T)(img)(0,_n1##y,z,c)), \
1401 (I[24] = I[25] = I[26] = (T)(img)(0,_n2##y,z,c)), \
1402 (I[30] = I[31] = I[32] = (T)(img)(0,_n3##y,z,c)), \
1403 (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \
1404 (I[9] = (T)(img)(_n1##x,_p1##y,z,c)), \
1405 (I[15] = (T)(img)(_n1##x,y,z,c)), \
1406 (I[21] = (T)(img)(_n1##x,_n1##y,z,c)), \
1407 (I[27] = (T)(img)(_n1##x,_n2##y,z,c)), \
1408 (I[33] = (T)(img)(_n1##x,_n3##y,z,c)), \
1409 (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \
1410 (I[10] = (T)(img)(_n2##x,_p1##y,z,c)), \
1411 (I[16] = (T)(img)(_n2##x,y,z,c)), \
1412 (I[22] = (T)(img)(_n2##x,_n1##y,z,c)), \
1413 (I[28] = (T)(img)(_n2##x,_n2##y,z,c)), \
1414 (I[34] = (T)(img)(_n2##x,_n3##y,z,c)), \
1415 3>=(img)._width?(img).width()-1:3); \
1416 (_n3##x<(img).width() && ( \
1417 (I[5] = (T)(img)(_n3##x,_p2##y,z,c)), \
1418 (I[11] = (T)(img)(_n3##x,_p1##y,z,c)), \
1419 (I[17] = (T)(img)(_n3##x,y,z,c)), \
1420 (I[23] = (T)(img)(_n3##x,_n1##y,z,c)), \
1421 (I[29] = (T)(img)(_n3##x,_n2##y,z,c)), \
1422 (I[35] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \
1423 _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3## x = _n2##x = --_n1##x); \
1424 I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], \
1425 I[6] = I[7], I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], \
1426 I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], I[16] = I[17], \
1427 I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \
1428 I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], \
1429 I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], I[34] = I[35], \
1430 _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x)
1432 #define cimg_for_in6x6(img,x0,y0,x1,y1,x,y,z,c,I,T) \
1433 cimg_for_in6((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)x0, \
1434 _p2##x = x-2<0?0:x-2, \
1435 _p1##x = x-1<0?0:x-1, \
1436 _n1##x = x+1>=(int)(img)._width?(img).width()-1:x+1, \
1437 _n2##x = x+2>=(int)(img)._width?(img).width()-1:x+2, \
1439 (I[0] = (T)(img)(_p2##x,_p2##y,z,c)), \
1440 (I[6] = (T)(img)(_p2##x,_p1##y,z,c)), \
1441 (I[12] = (T)(img)(_p2##x,y,z,c)), \
1442 (I[18] = (T)(img)(_p2##x,_n1##y,z,c)), \
1443 (I[24] = (T)(img)(_p2##x,_n2##y,z,c)), \
1444 (I[30] = (T)(img)(_p2##x,_n3##y,z,c)), \
1445 (I[1] = (T)(img)(_p1##x,_p2##y,z,c)), \
1446 (I[7] = (T)(img)(_p1##x,_p1##y,z,c)), \
1447 (I[13] = (T)(img)(_p1##x,y,z,c)), \
1448 (I[19] = (T)(img)(_p1##x,_n1##y,z,c)), \
1449 (I[25] = (T)(img)(_p1##x,_n2##y,z,c)), \
1450 (I[31] = (T)(img)(_p1##x,_n3##y,z,c)), \
1451 (I[2] = (T)(img)(x,_p2##y,z,c)), \
1452 (I[8] = (T)(img)(x,_p1##y,z,c)), \
1453 (I[14] = (T)(img)(x,y,z,c)), \
1454 (I[20] = (T)(img)(x,_n1##y,z,c)), \
1455 (I[26] = (T)(img)(x,_n2##y,z,c)), \
1456 (I[32] = (T)(img)(x,_n3##y,z,c)), \
1457 (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \
1458 (I[9] = (T)(img)(_n1##x,_p1##y,z,c)), \
1459 (I[15] = (T)(img)(_n1##x,y,z,c)), \
1460 (I[21] = (T)(img)(_n1##x,_n1##y,z,c)), \
1461 (I[27] = (T)(img)(_n1##x,_n2##y,z,c)), \
1462 (I[33] = (T)(img)(_n1##x,_n3##y,z,c)), \
1463 (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \
1464 (I[10] = (T)(img)(_n2##x,_p1##y,z,c)), \
1465 (I[16] = (T)(img)(_n2##x,y,z,c)), \
1466 (I[22] = (T)(img)(_n2##x,_n1##y,z,c)), \
1467 (I[28] = (T)(img)(_n2##x,_n2##y,z,c)), \
1468 (I[34] = (T)(img)(_n2##x,_n3##y,z,c)), \
1469 x+3>=(int)(img)._width?(img).width()-1:x+3); \
1470 x<=(int)(x1) && ((_n3##x<(img).width() && ( \
1471 (I[5] = (T)(img)(_n3##x,_p2##y,z,c)), \
1472 (I[11] = (T)(img)(_n3##x,_p1##y,z,c)), \
1473 (I[17] = (T)(img)(_n3##x,y,z,c)), \
1474 (I[23] = (T)(img)(_n3##x,_n1##y,z,c)), \
1475 (I[29] = (T)(img)(_n3##x,_n2##y,z,c)), \
1476 (I[35] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \
1477 _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3## x = _n2##x = --_n1##x)); \
1478 I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], \
1479 I[6] = I[7], I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], \
1480 I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], I[16] = I[17], \
1481 I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \
1482 I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], \
1483 I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], I[34] = I[35], \
1484 _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x)
1486 #define cimg_for7x7(img,x,y,z,c,I,T) \
1487 cimg_for7((img)._height,y) for (int x = 0, \
1488 _p3##x = 0, _p2##x = 0, _p1##x = 0, \
1489 _n1##x = 1>=(img)._width?(img).width()-1:1, \
1490 _n2##x = 2>=(img)._width?(img).width()-1:2, \
1492 (I[0] = I[1] = I[2] = I[3] = (T)(img)(_p3##x,_p3##y,z,c)), \
1493 (I[7] = I[8] = I[9] = I[10] = (T)(img)(0,_p2##y,z,c)), \
1494 (I[14] = I[15] = I[16] = I[17] = (T)(img)(0,_p1##y,z,c)), \
1495 (I[21] = I[22] = I[23] = I[24] = (T)(img)(0,y,z,c)), \
1496 (I[28] = I[29] = I[30] = I[31] = (T)(img)(0,_n1##y,z,c)), \
1497 (I[35] = I[36] = I[37] = I[38] = (T)(img)(0,_n2##y,z,c)), \
1498 (I[42] = I[43] = I[44] = I[45] = (T)(img)(0,_n3##y,z,c)), \
1499 (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \
1500 (I[11] = (T)(img)(_n1##x,_p2##y,z,c)), \
1501 (I[18] = (T)(img)(_n1##x,_p1##y,z,c)), \
1502 (I[25] = (T)(img)(_n1##x,y,z,c)), \
1503 (I[32] = (T)(img)(_n1##x,_n1##y,z,c)), \
1504 (I[39] = (T)(img)(_n1##x,_n2##y,z,c)), \
1505 (I[46] = (T)(img)(_n1##x,_n3##y,z,c)), \
1506 (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \
1507 (I[12] = (T)(img)(_n2##x,_p2##y,z,c)), \
1508 (I[19] = (T)(img)(_n2##x,_p1##y,z,c)), \
1509 (I[26] = (T)(img)(_n2##x,y,z,c)), \
1510 (I[33] = (T)(img)(_n2##x,_n1##y,z,c)), \
1511 (I[40] = (T)(img)(_n2##x,_n2##y,z,c)), \
1512 (I[47] = (T)(img)(_n2##x,_n3##y,z,c)), \
1513 3>=(img)._width?(img).width()-1:3); \
1514 (_n3##x<(img).width() && ( \
1515 (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \
1516 (I[13] = (T)(img)(_n3##x,_p2##y,z,c)), \
1517 (I[20] = (T)(img)(_n3##x,_p1##y,z,c)), \
1518 (I[27] = (T)(img)(_n3##x,y,z,c)), \
1519 (I[34] = (T)(img)(_n3##x,_n1##y,z,c)), \
1520 (I[41] = (T)(img)(_n3##x,_n2##y,z,c)), \
1521 (I[48] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \
1522 _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3##x = _n2##x = --_n1##x); \
1523 I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], \
1524 I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], \
1525 I[14] = I[15], I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], \
1526 I[21] = I[22], I[22] = I[23], I[23] = I[24], I[24] = I[25], I[25] = I[26], I[26] = I[27], \
1527 I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], \
1528 I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], I[40] = I[41], \
1529 I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], I[47] = I[48], \
1530 _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x)
1532 #define cimg_for_in7x7(img,x0,y0,x1,y1,x,y,z,c,I,T) \
1533 cimg_for_in7((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \
1534 _p3##x = x-3<0?0:x-3, \
1535 _p2##x = x-2<0?0:x-2, \
1536 _p1##x = x-1<0?0:x-1, \
1537 _n1##x = x+1>=(int)(img)._width?(img).width()-1:x+1, \
1538 _n2##x = x+2>=(int)(img)._width?(img).width()-1:x+2, \
1540 (I[0] = (T)(img)(_p3##x,_p3##y,z,c)), \
1541 (I[7] = (T)(img)(_p3##x,_p2##y,z,c)), \
1542 (I[14] = (T)(img)(_p3##x,_p1##y,z,c)), \
1543 (I[21] = (T)(img)(_p3##x,y,z,c)), \
1544 (I[28] = (T)(img)(_p3##x,_n1##y,z,c)), \
1545 (I[35] = (T)(img)(_p3##x,_n2##y,z,c)), \
1546 (I[42] = (T)(img)(_p3##x,_n3##y,z,c)), \
1547 (I[1] = (T)(img)(_p2##x,_p3##y,z,c)), \
1548 (I[8] = (T)(img)(_p2##x,_p2##y,z,c)), \
1549 (I[15] = (T)(img)(_p2##x,_p1##y,z,c)), \
1550 (I[22] = (T)(img)(_p2##x,y,z,c)), \
1551 (I[29] = (T)(img)(_p2##x,_n1##y,z,c)), \
1552 (I[36] = (T)(img)(_p2##x,_n2##y,z,c)), \
1553 (I[43] = (T)(img)(_p2##x,_n3##y,z,c)), \
1554 (I[2] = (T)(img)(_p1##x,_p3##y,z,c)), \
1555 (I[9] = (T)(img)(_p1##x,_p2##y,z,c)), \
1556 (I[16] = (T)(img)(_p1##x,_p1##y,z,c)), \
1557 (I[23] = (T)(img)(_p1##x,y,z,c)), \
1558 (I[30] = (T)(img)(_p1##x,_n1##y,z,c)), \
1559 (I[37] = (T)(img)(_p1##x,_n2##y,z,c)), \
1560 (I[44] = (T)(img)(_p1##x,_n3##y,z,c)), \
1561 (I[3] = (T)(img)(x,_p3##y,z,c)), \
1562 (I[10] = (T)(img)(x,_p2##y,z,c)), \
1563 (I[17] = (T)(img)(x,_p1##y,z,c)), \
1564 (I[24] = (T)(img)(x,y,z,c)), \
1565 (I[31] = (T)(img)(x,_n1##y,z,c)), \
1566 (I[38] = (T)(img)(x,_n2##y,z,c)), \
1567 (I[45] = (T)(img)(x,_n3##y,z,c)), \
1568 (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \
1569 (I[11] = (T)(img)(_n1##x,_p2##y,z,c)), \
1570 (I[18] = (T)(img)(_n1##x,_p1##y,z,c)), \
1571 (I[25] = (T)(img)(_n1##x,y,z,c)), \
1572 (I[32] = (T)(img)(_n1##x,_n1##y,z,c)), \
1573 (I[39] = (T)(img)(_n1##x,_n2##y,z,c)), \
1574 (I[46] = (T)(img)(_n1##x,_n3##y,z,c)), \
1575 (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \
1576 (I[12] = (T)(img)(_n2##x,_p2##y,z,c)), \
1577 (I[19] = (T)(img)(_n2##x,_p1##y,z,c)), \
1578 (I[26] = (T)(img)(_n2##x,y,z,c)), \
1579 (I[33] = (T)(img)(_n2##x,_n1##y,z,c)), \
1580 (I[40] = (T)(img)(_n2##x,_n2##y,z,c)), \
1581 (I[47] = (T)(img)(_n2##x,_n3##y,z,c)), \
1582 x+3>=(int)(img)._width?(img).width()-1:x+3); \
1583 x<=(int)(x1) && ((_n3##x<(img).width() && ( \
1584 (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \
1585 (I[13] = (T)(img)(_n3##x,_p2##y,z,c)), \
1586 (I[20] = (T)(img)(_n3##x,_p1##y,z,c)), \
1587 (I[27] = (T)(img)(_n3##x,y,z,c)), \
1588 (I[34] = (T)(img)(_n3##x,_n1##y,z,c)), \
1589 (I[41] = (T)(img)(_n3##x,_n2##y,z,c)), \
1590 (I[48] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \
1591 _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3##x = _n2##x = --_n1##x)); \
1592 I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], \
1593 I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], \
1594 I[14] = I[15], I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], \
1595 I[21] = I[22], I[22] = I[23], I[23] = I[24], I[24] = I[25], I[25] = I[26], I[26] = I[27], \
1596 I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], \
1597 I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], I[40] = I[41], \
1598 I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], I[47] = I[48], \
1599 _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x)
1601 #define cimg_for8x8(img,x,y,z,c,I,T) \
1602 cimg_for8((img)._height,y) for (int x = 0, \
1603 _p3##x = 0, _p2##x = 0, _p1##x = 0, \
1604 _n1##x = 1>=((img)._width)?(img).width()-1:1, \
1605 _n2##x = 2>=((img)._width)?(img).width()-1:2, \
1606 _n3##x = 3>=((img)._width)?(img).width()-1:3, \
1608 (I[0] = I[1] = I[2] = I[3] = (T)(img)(_p3##x,_p3##y,z,c)), \
1609 (I[8] = I[9] = I[10] = I[11] = (T)(img)(0,_p2##y,z,c)), \
1610 (I[16] = I[17] = I[18] = I[19] = (T)(img)(0,_p1##y,z,c)), \
1611 (I[24] = I[25] = I[26] = I[27] = (T)(img)(0,y,z,c)), \
1612 (I[32] = I[33] = I[34] = I[35] = (T)(img)(0,_n1##y,z,c)), \
1613 (I[40] = I[41] = I[42] = I[43] = (T)(img)(0,_n2##y,z,c)), \
1614 (I[48] = I[49] = I[50] = I[51] = (T)(img)(0,_n3##y,z,c)), \
1615 (I[56] = I[57] = I[58] = I[59] = (T)(img)(0,_n4##y,z,c)), \
1616 (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \
1617 (I[12] = (T)(img)(_n1##x,_p2##y,z,c)), \
1618 (I[20] = (T)(img)(_n1##x,_p1##y,z,c)), \
1619 (I[28] = (T)(img)(_n1##x,y,z,c)), \
1620 (I[36] = (T)(img)(_n1##x,_n1##y,z,c)), \
1621 (I[44] = (T)(img)(_n1##x,_n2##y,z,c)), \
1622 (I[52] = (T)(img)(_n1##x,_n3##y,z,c)), \
1623 (I[60] = (T)(img)(_n1##x,_n4##y,z,c)), \
1624 (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \
1625 (I[13] = (T)(img)(_n2##x,_p2##y,z,c)), \
1626 (I[21] = (T)(img)(_n2##x,_p1##y,z,c)), \
1627 (I[29] = (T)(img)(_n2##x,y,z,c)), \
1628 (I[37] = (T)(img)(_n2##x,_n1##y,z,c)), \
1629 (I[45] = (T)(img)(_n2##x,_n2##y,z,c)), \
1630 (I[53] = (T)(img)(_n2##x,_n3##y,z,c)), \
1631 (I[61] = (T)(img)(_n2##x,_n4##y,z,c)), \
1632 (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \
1633 (I[14] = (T)(img)(_n3##x,_p2##y,z,c)), \
1634 (I[22] = (T)(img)(_n3##x,_p1##y,z,c)), \
1635 (I[30] = (T)(img)(_n3##x,y,z,c)), \
1636 (I[38] = (T)(img)(_n3##x,_n1##y,z,c)), \
1637 (I[46] = (T)(img)(_n3##x,_n2##y,z,c)), \
1638 (I[54] = (T)(img)(_n3##x,_n3##y,z,c)), \
1639 (I[62] = (T)(img)(_n3##x,_n4##y,z,c)), \
1640 4>=((img)._width)?(img).width()-1:4); \
1641 (_n4##x<(img).width() && ( \
1642 (I[7] = (T)(img)(_n4##x,_p3##y,z,c)), \
1643 (I[15] = (T)(img)(_n4##x,_p2##y,z,c)), \
1644 (I[23] = (T)(img)(_n4##x,_p1##y,z,c)), \
1645 (I[31] = (T)(img)(_n4##x,y,z,c)), \
1646 (I[39] = (T)(img)(_n4##x,_n1##y,z,c)), \
1647 (I[47] = (T)(img)(_n4##x,_n2##y,z,c)), \
1648 (I[55] = (T)(img)(_n4##x,_n3##y,z,c)), \
1649 (I[63] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \
1650 _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x); \
1651 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], \
1652 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], \
1653 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], \
1654 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], \
1655 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], \
1656 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], \
1657 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], \
1658 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], \
1659 _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x)
1661 #define cimg_for_in8x8(img,x0,y0,x1,y1,x,y,z,c,I,T) \
1662 cimg_for_in8((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \
1663 _p3##x = x-3<0?0:x-3, \
1664 _p2##x = x-2<0?0:x-2, \
1665 _p1##x = x-1<0?0:x-1, \
1666 _n1##x = x+1>=(img).width()?(img).width()-1:x+1, \
1667 _n2##x = x+2>=(img).width()?(img).width()-1:x+2, \
1668 _n3##x = x+3>=(img).width()?(img).width()-1:x+3, \
1670 (I[0] = (T)(img)(_p3##x,_p3##y,z,c)), \
1671 (I[8] = (T)(img)(_p3##x,_p2##y,z,c)), \
1672 (I[16] = (T)(img)(_p3##x,_p1##y,z,c)), \
1673 (I[24] = (T)(img)(_p3##x,y,z,c)), \
1674 (I[32] = (T)(img)(_p3##x,_n1##y,z,c)), \
1675 (I[40] = (T)(img)(_p3##x,_n2##y,z,c)), \
1676 (I[48] = (T)(img)(_p3##x,_n3##y,z,c)), \
1677 (I[56] = (T)(img)(_p3##x,_n4##y,z,c)), \
1678 (I[1] = (T)(img)(_p2##x,_p3##y,z,c)), \
1679 (I[9] = (T)(img)(_p2##x,_p2##y,z,c)), \
1680 (I[17] = (T)(img)(_p2##x,_p1##y,z,c)), \
1681 (I[25] = (T)(img)(_p2##x,y,z,c)), \
1682 (I[33] = (T)(img)(_p2##x,_n1##y,z,c)), \
1683 (I[41] = (T)(img)(_p2##x,_n2##y,z,c)), \
1684 (I[49] = (T)(img)(_p2##x,_n3##y,z,c)), \
1685 (I[57] = (T)(img)(_p2##x,_n4##y,z,c)), \
1686 (I[2] = (T)(img)(_p1##x,_p3##y,z,c)), \
1687 (I[10] = (T)(img)(_p1##x,_p2##y,z,c)), \
1688 (I[18] = (T)(img)(_p1##x,_p1##y,z,c)), \
1689 (I[26] = (T)(img)(_p1##x,y,z,c)), \
1690 (I[34] = (T)(img)(_p1##x,_n1##y,z,c)), \
1691 (I[42] = (T)(img)(_p1##x,_n2##y,z,c)), \
1692 (I[50] = (T)(img)(_p1##x,_n3##y,z,c)), \
1693 (I[58] = (T)(img)(_p1##x,_n4##y,z,c)), \
1694 (I[3] = (T)(img)(x,_p3##y,z,c)), \
1695 (I[11] = (T)(img)(x,_p2##y,z,c)), \
1696 (I[19] = (T)(img)(x,_p1##y,z,c)), \
1697 (I[27] = (T)(img)(x,y,z,c)), \
1698 (I[35] = (T)(img)(x,_n1##y,z,c)), \
1699 (I[43] = (T)(img)(x,_n2##y,z,c)), \
1700 (I[51] = (T)(img)(x,_n3##y,z,c)), \
1701 (I[59] = (T)(img)(x,_n4##y,z,c)), \
1702 (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \
1703 (I[12] = (T)(img)(_n1##x,_p2##y,z,c)), \
1704 (I[20] = (T)(img)(_n1##x,_p1##y,z,c)), \
1705 (I[28] = (T)(img)(_n1##x,y,z,c)), \
1706 (I[36] = (T)(img)(_n1##x,_n1##y,z,c)), \
1707 (I[44] = (T)(img)(_n1##x,_n2##y,z,c)), \
1708 (I[52] = (T)(img)(_n1##x,_n3##y,z,c)), \
1709 (I[60] = (T)(img)(_n1##x,_n4##y,z,c)), \
1710 (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \
1711 (I[13] = (T)(img)(_n2##x,_p2##y,z,c)), \
1712 (I[21] = (T)(img)(_n2##x,_p1##y,z,c)), \
1713 (I[29] = (T)(img)(_n2##x,y,z,c)), \
1714 (I[37] = (T)(img)(_n2##x,_n1##y,z,c)), \
1715 (I[45] = (T)(img)(_n2##x,_n2##y,z,c)), \
1716 (I[53] = (T)(img)(_n2##x,_n3##y,z,c)), \
1717 (I[61] = (T)(img)(_n2##x,_n4##y,z,c)), \
1718 (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \
1719 (I[14] = (T)(img)(_n3##x,_p2##y,z,c)), \
1720 (I[22] = (T)(img)(_n3##x,_p1##y,z,c)), \
1721 (I[30] = (T)(img)(_n3##x,y,z,c)), \
1722 (I[38] = (T)(img)(_n3##x,_n1##y,z,c)), \
1723 (I[46] = (T)(img)(_n3##x,_n2##y,z,c)), \
1724 (I[54] = (T)(img)(_n3##x,_n3##y,z,c)), \
1725 (I[62] = (T)(img)(_n3##x,_n4##y,z,c)), \
1726 x+4>=(img).width()?(img).width()-1:x+4); \
1727 x<=(int)(x1) && ((_n4##x<(img).width() && ( \
1728 (I[7] = (T)(img)(_n4##x,_p3##y,z,c)), \
1729 (I[15] = (T)(img)(_n4##x,_p2##y,z,c)), \
1730 (I[23] = (T)(img)(_n4##x,_p1##y,z,c)), \
1731 (I[31] = (T)(img)(_n4##x,y,z,c)), \
1732 (I[39] = (T)(img)(_n4##x,_n1##y,z,c)), \
1733 (I[47] = (T)(img)(_n4##x,_n2##y,z,c)), \
1734 (I[55] = (T)(img)(_n4##x,_n3##y,z,c)), \
1735 (I[63] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \
1736 _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x)); \
1737 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], \
1738 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], \
1739 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], \
1740 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], \
1741 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], \
1742 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], \
1743 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], \
1744 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], \
1745 _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x)
1747 #define cimg_for9x9(img,x,y,z,c,I,T) \
1748 cimg_for9((img)._height,y) for (int x = 0, \
1749 _p4##x = 0, _p3##x = 0, _p2##x = 0, _p1##x = 0, \
1750 _n1##x = 1>=((img)._width)?(img).width()-1:1, \
1751 _n2##x = 2>=((img)._width)?(img).width()-1:2, \
1752 _n3##x = 3>=((img)._width)?(img).width()-1:3, \
1754 (I[0] = I[1] = I[2] = I[3] = I[4] = (T)(img)(_p4##x,_p4##y,z,c)), \
1755 (I[9] = I[10] = I[11] = I[12] = I[13] = (T)(img)(0,_p3##y,z,c)), \
1756 (I[18] = I[19] = I[20] = I[21] = I[22] = (T)(img)(0,_p2##y,z,c)), \
1757 (I[27] = I[28] = I[29] = I[30] = I[31] = (T)(img)(0,_p1##y,z,c)), \
1758 (I[36] = I[37] = I[38] = I[39] = I[40] = (T)(img)(0,y,z,c)), \
1759 (I[45] = I[46] = I[47] = I[48] = I[49] = (T)(img)(0,_n1##y,z,c)), \
1760 (I[54] = I[55] = I[56] = I[57] = I[58] = (T)(img)(0,_n2##y,z,c)), \
1761 (I[63] = I[64] = I[65] = I[66] = I[67] = (T)(img)(0,_n3##y,z,c)), \
1762 (I[72] = I[73] = I[74] = I[75] = I[76] = (T)(img)(0,_n4##y,z,c)), \
1763 (I[5] = (T)(img)(_n1##x,_p4##y,z,c)), \
1764 (I[14] = (T)(img)(_n1##x,_p3##y,z,c)), \
1765 (I[23] = (T)(img)(_n1##x,_p2##y,z,c)), \
1766 (I[32] = (T)(img)(_n1##x,_p1##y,z,c)), \
1767 (I[41] = (T)(img)(_n1##x,y,z,c)), \
1768 (I[50] = (T)(img)(_n1##x,_n1##y,z,c)), \
1769 (I[59] = (T)(img)(_n1##x,_n2##y,z,c)), \
1770 (I[68] = (T)(img)(_n1##x,_n3##y,z,c)), \
1771 (I[77] = (T)(img)(_n1##x,_n4##y,z,c)), \
1772 (I[6] = (T)(img)(_n2##x,_p4##y,z,c)), \
1773 (I[15] = (T)(img)(_n2##x,_p3##y,z,c)), \
1774 (I[24] = (T)(img)(_n2##x,_p2##y,z,c)), \
1775 (I[33] = (T)(img)(_n2##x,_p1##y,z,c)), \
1776 (I[42] = (T)(img)(_n2##x,y,z,c)), \
1777 (I[51] = (T)(img)(_n2##x,_n1##y,z,c)), \
1778 (I[60] = (T)(img)(_n2##x,_n2##y,z,c)), \
1779 (I[69] = (T)(img)(_n2##x,_n3##y,z,c)), \
1780 (I[78] = (T)(img)(_n2##x,_n4##y,z,c)), \
1781 (I[7] = (T)(img)(_n3##x,_p4##y,z,c)), \
1782 (I[16] = (T)(img)(_n3##x,_p3##y,z,c)), \
1783 (I[25] = (T)(img)(_n3##x,_p2##y,z,c)), \
1784 (I[34] = (T)(img)(_n3##x,_p1##y,z,c)), \
1785 (I[43] = (T)(img)(_n3##x,y,z,c)), \
1786 (I[52] = (T)(img)(_n3##x,_n1##y,z,c)), \
1787 (I[61] = (T)(img)(_n3##x,_n2##y,z,c)), \
1788 (I[70] = (T)(img)(_n3##x,_n3##y,z,c)), \
1789 (I[79] = (T)(img)(_n3##x,_n4##y,z,c)), \
1790 4>=((img)._width)?(img).width()-1:4); \
1791 (_n4##x<(img).width() && ( \
1792 (I[8] = (T)(img)(_n4##x,_p4##y,z,c)), \
1793 (I[17] = (T)(img)(_n4##x,_p3##y,z,c)), \
1794 (I[26] = (T)(img)(_n4##x,_p2##y,z,c)), \
1795 (I[35] = (T)(img)(_n4##x,_p1##y,z,c)), \
1796 (I[44] = (T)(img)(_n4##x,y,z,c)), \
1797 (I[53] = (T)(img)(_n4##x,_n1##y,z,c)), \
1798 (I[62] = (T)(img)(_n4##x,_n2##y,z,c)), \
1799 (I[71] = (T)(img)(_n4##x,_n3##y,z,c)), \
1800 (I[80] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \
1801 _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x); \
1802 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], \
1803 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], \
1804 I[16] = I[17], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \
1805 I[24] = I[25], I[25] = I[26], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], \
1806 I[32] = I[33], I[33] = I[34], I[34] = I[35], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], \
1807 I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[45] = I[46], I[46] = I[47], I[47] = I[48], \
1808 I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[54] = I[55], I[55] = I[56], \
1809 I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[63] = I[64], \
1810 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], \
1811 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], \
1813 _p4##x = _p3##x, _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x)
1815 #define cimg_for_in9x9(img,x0,y0,x1,y1,x,y,z,c,I,T) \
1816 cimg_for_in9((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \
1817 _p4##x = x-4<0?0:x-4, \
1818 _p3##x = x-3<0?0:x-3, \
1819 _p2##x = x-2<0?0:x-2, \
1820 _p1##x = x-1<0?0:x-1, \
1821 _n1##x = x+1>=(img).width()?(img).width()-1:x+1, \
1822 _n2##x = x+2>=(img).width()?(img).width()-1:x+2, \
1823 _n3##x = x+3>=(img).width()?(img).width()-1:x+3, \
1825 (I[0] = (T)(img)(_p4##x,_p4##y,z,c)), \
1826 (I[9] = (T)(img)(_p4##x,_p3##y,z,c)), \
1827 (I[18] = (T)(img)(_p4##x,_p2##y,z,c)), \
1828 (I[27] = (T)(img)(_p4##x,_p1##y,z,c)), \
1829 (I[36] = (T)(img)(_p4##x,y,z,c)), \
1830 (I[45] = (T)(img)(_p4##x,_n1##y,z,c)), \
1831 (I[54] = (T)(img)(_p4##x,_n2##y,z,c)), \
1832 (I[63] = (T)(img)(_p4##x,_n3##y,z,c)), \
1833 (I[72] = (T)(img)(_p4##x,_n4##y,z,c)), \
1834 (I[1] = (T)(img)(_p3##x,_p4##y,z,c)), \
1835 (I[10] = (T)(img)(_p3##x,_p3##y,z,c)), \
1836 (I[19] = (T)(img)(_p3##x,_p2##y,z,c)), \
1837 (I[28] = (T)(img)(_p3##x,_p1##y,z,c)), \
1838 (I[37] = (T)(img)(_p3##x,y,z,c)), \
1839 (I[46] = (T)(img)(_p3##x,_n1##y,z,c)), \
1840 (I[55] = (T)(img)(_p3##x,_n2##y,z,c)), \
1841 (I[64] = (T)(img)(_p3##x,_n3##y,z,c)), \
1842 (I[73] = (T)(img)(_p3##x,_n4##y,z,c)), \
1843 (I[2] = (T)(img)(_p2##x,_p4##y,z,c)), \
1844 (I[11] = (T)(img)(_p2##x,_p3##y,z,c)), \
1845 (I[20] = (T)(img)(_p2##x,_p2##y,z,c)), \
1846 (I[29] = (T)(img)(_p2##x,_p1##y,z,c)), \
1847 (I[38] = (T)(img)(_p2##x,y,z,c)), \
1848 (I[47] = (T)(img)(_p2##x,_n1##y,z,c)), \
1849 (I[56] = (T)(img)(_p2##x,_n2##y,z,c)), \
1850 (I[65] = (T)(img)(_p2##x,_n3##y,z,c)), \
1851 (I[74] = (T)(img)(_p2##x,_n4##y,z,c)), \
1852 (I[3] = (T)(img)(_p1##x,_p4##y,z,c)), \
1853 (I[12] = (T)(img)(_p1##x,_p3##y,z,c)), \
1854 (I[21] = (T)(img)(_p1##x,_p2##y,z,c)), \
1855 (I[30] = (T)(img)(_p1##x,_p1##y,z,c)), \
1856 (I[39] = (T)(img)(_p1##x,y,z,c)), \
1857 (I[48] = (T)(img)(_p1##x,_n1##y,z,c)), \
1858 (I[57] = (T)(img)(_p1##x,_n2##y,z,c)), \
1859 (I[66] = (T)(img)(_p1##x,_n3##y,z,c)), \
1860 (I[75] = (T)(img)(_p1##x,_n4##y,z,c)), \
1861 (I[4] = (T)(img)(x,_p4##y,z,c)), \
1862 (I[13] = (T)(img)(x,_p3##y,z,c)), \
1863 (I[22] = (T)(img)(x,_p2##y,z,c)), \
1864 (I[31] = (T)(img)(x,_p1##y,z,c)), \
1865 (I[40] = (T)(img)(x,y,z,c)), \
1866 (I[49] = (T)(img)(x,_n1##y,z,c)), \
1867 (I[58] = (T)(img)(x,_n2##y,z,c)), \
1868 (I[67] = (T)(img)(x,_n3##y,z,c)), \
1869 (I[76] = (T)(img)(x,_n4##y,z,c)), \
1870 (I[5] = (T)(img)(_n1##x,_p4##y,z,c)), \
1871 (I[14] = (T)(img)(_n1##x,_p3##y,z,c)), \
1872 (I[23] = (T)(img)(_n1##x,_p2##y,z,c)), \
1873 (I[32] = (T)(img)(_n1##x,_p1##y,z,c)), \
1874 (I[41] = (T)(img)(_n1##x,y,z,c)), \
1875 (I[50] = (T)(img)(_n1##x,_n1##y,z,c)), \
1876 (I[59] = (T)(img)(_n1##x,_n2##y,z,c)), \
1877 (I[68] = (T)(img)(_n1##x,_n3##y,z,c)), \
1878 (I[77] = (T)(img)(_n1##x,_n4##y,z,c)), \
1879 (I[6] = (T)(img)(_n2##x,_p4##y,z,c)), \
1880 (I[15] = (T)(img)(_n2##x,_p3##y,z,c)), \
1881 (I[24] = (T)(img)(_n2##x,_p2##y,z,c)), \
1882 (I[33] = (T)(img)(_n2##x,_p1##y,z,c)), \
1883 (I[42] = (T)(img)(_n2##x,y,z,c)), \
1884 (I[51] = (T)(img)(_n2##x,_n1##y,z,c)), \
1885 (I[60] = (T)(img)(_n2##x,_n2##y,z,c)), \
1886 (I[69] = (T)(img)(_n2##x,_n3##y,z,c)), \
1887 (I[78] = (T)(img)(_n2##x,_n4##y,z,c)), \
1888 (I[7] = (T)(img)(_n3##x,_p4##y,z,c)), \
1889 (I[16] = (T)(img)(_n3##x,_p3##y,z,c)), \
1890 (I[25] = (T)(img)(_n3##x,_p2##y,z,c)), \
1891 (I[34] = (T)(img)(_n3##x,_p1##y,z,c)), \
1892 (I[43] = (T)(img)(_n3##x,y,z,c)), \
1893 (I[52] = (T)(img)(_n3##x,_n1##y,z,c)), \
1894 (I[61] = (T)(img)(_n3##x,_n2##y,z,c)), \
1895 (I[70] = (T)(img)(_n3##x,_n3##y,z,c)), \
1896 (I[79] = (T)(img)(_n3##x,_n4##y,z,c)), \
1897 x+4>=(img).width()?(img).width()-1:x+4); \
1898 x<=(int)(x1) && ((_n4##x<(img).width() && ( \
1899 (I[8] = (T)(img)(_n4##x,_p4##y,z,c)), \
1900 (I[17] = (T)(img)(_n4##x,_p3##y,z,c)), \
1901 (I[26] = (T)(img)(_n4##x,_p2##y,z,c)), \
1902 (I[35] = (T)(img)(_n4##x,_p1##y,z,c)), \
1903 (I[44] = (T)(img)(_n4##x,y,z,c)), \
1904 (I[53] = (T)(img)(_n4##x,_n1##y,z,c)), \
1905 (I[62] = (T)(img)(_n4##x,_n2##y,z,c)), \
1906 (I[71] = (T)(img)(_n4##x,_n3##y,z,c)), \
1907 (I[80] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \
1908 _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x)); \
1909 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], \
1910 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], \
1911 I[16] = I[17], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \
1912 I[24] = I[25], I[25] = I[26], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], \
1913 I[32] = I[33], I[33] = I[34], I[34] = I[35], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], \
1914 I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[45] = I[46], I[46] = I[47], I[47] = I[48], \
1915 I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[54] = I[55], I[55] = I[56], \
1916 I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[63] = I[64], \
1917 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], \
1918 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], \
1920 _p4##x = _p3##x, _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x)
1922 #define cimg_for2x2x2(img,x,y,z,c,I,T) \
1923 cimg_for2((img)._depth,z) cimg_for2((img)._height,y) for (int x = 0, \
1925 (I[0] = (T)(img)(0,y,z,c)), \
1926 (I[2] = (T)(img)(0,_n1##y,z,c)), \
1927 (I[4] = (T)(img)(0,y,_n1##z,c)), \
1928 (I[6] = (T)(img)(0,_n1##y,_n1##z,c)), \
1929 1>=(img)._width?(img).width()-1:1); \
1930 (_n1##x<(img).width() && ( \
1931 (I[1] = (T)(img)(_n1##x,y,z,c)), \
1932 (I[3] = (T)(img)(_n1##x,_n1##y,z,c)), \
1933 (I[5] = (T)(img)(_n1##x,y,_n1##z,c)), \
1934 (I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \
1936 I[0] = I[1], I[2] = I[3], I[4] = I[5], I[6] = I[7], \
1939 #define cimg_for_in2x2x2(img,x0,y0,z0,x1,y1,z1,x,y,z,c,I,T) \
1940 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), \
1942 (I[0] = (T)(img)(x,y,z,c)), \
1943 (I[2] = (T)(img)(x,_n1##y,z,c)), \
1944 (I[4] = (T)(img)(x,y,_n1##z,c)), \
1945 (I[6] = (T)(img)(x,_n1##y,_n1##z,c)), \
1946 x+1>=(int)(img)._width?(img).width()-1:x+1); \
1947 x<=(int)(x1) && ((_n1##x<(img).width() && ( \
1948 (I[1] = (T)(img)(_n1##x,y,z,c)), \
1949 (I[3] = (T)(img)(_n1##x,_n1##y,z,c)), \
1950 (I[5] = (T)(img)(_n1##x,y,_n1##z,c)), \
1951 (I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \
1953 I[0] = I[1], I[2] = I[3], I[4] = I[5], I[6] = I[7], \
1956 #define cimg_for3x3x3(img,x,y,z,c,I,T) \
1957 cimg_for3((img)._depth,z) cimg_for3((img)._height,y) for (int x = 0, \
1960 (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,_p1##z,c)), \
1961 (I[3] = I[4] = (T)(img)(0,y,_p1##z,c)), \
1962 (I[6] = I[7] = (T)(img)(0,_n1##y,_p1##z,c)), \
1963 (I[9] = I[10] = (T)(img)(0,_p1##y,z,c)), \
1964 (I[12] = I[13] = (T)(img)(0,y,z,c)), \
1965 (I[15] = I[16] = (T)(img)(0,_n1##y,z,c)), \
1966 (I[18] = I[19] = (T)(img)(0,_p1##y,_n1##z,c)), \
1967 (I[21] = I[22] = (T)(img)(0,y,_n1##z,c)), \
1968 (I[24] = I[25] = (T)(img)(0,_n1##y,_n1##z,c)), \
1969 1>=(img)._width?(img).width()-1:1); \
1970 (_n1##x<(img).width() && ( \
1971 (I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c)), \
1972 (I[5] = (T)(img)(_n1##x,y,_p1##z,c)), \
1973 (I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c)), \
1974 (I[11] = (T)(img)(_n1##x,_p1##y,z,c)), \
1975 (I[14] = (T)(img)(_n1##x,y,z,c)), \
1976 (I[17] = (T)(img)(_n1##x,_n1##y,z,c)), \
1977 (I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c)), \
1978 (I[23] = (T)(img)(_n1##x,y,_n1##z,c)), \
1979 (I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \
1981 I[0] = I[1], I[1] = I[2], I[3] = I[4], I[4] = I[5], I[6] = I[7], I[7] = I[8], \
1982 I[9] = I[10], I[10] = I[11], I[12] = I[13], I[13] = I[14], I[15] = I[16], I[16] = I[17], \
1983 I[18] = I[19], I[19] = I[20], I[21] = I[22], I[22] = I[23], I[24] = I[25], I[25] = I[26], \
1984 _p1##x = x++, ++_n1##x)
1986 #define cimg_for_in3x3x3(img,x0,y0,z0,x1,y1,z1,x,y,z,c,I,T) \
1987 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), \
1988 _p1##x = x-1<0?0:x-1, \
1990 (I[0] = (T)(img)(_p1##x,_p1##y,_p1##z,c)), \
1991 (I[3] = (T)(img)(_p1##x,y,_p1##z,c)), \
1992 (I[6] = (T)(img)(_p1##x,_n1##y,_p1##z,c)), \
1993 (I[9] = (T)(img)(_p1##x,_p1##y,z,c)), \
1994 (I[12] = (T)(img)(_p1##x,y,z,c)), \
1995 (I[15] = (T)(img)(_p1##x,_n1##y,z,c)), \
1996 (I[18] = (T)(img)(_p1##x,_p1##y,_n1##z,c)), \
1997 (I[21] = (T)(img)(_p1##x,y,_n1##z,c)), \
1998 (I[24] = (T)(img)(_p1##x,_n1##y,_n1##z,c)), \
1999 (I[1] = (T)(img)(x,_p1##y,_p1##z,c)), \
2000 (I[4] = (T)(img)(x,y,_p1##z,c)), \
2001 (I[7] = (T)(img)(x,_n1##y,_p1##z,c)), \
2002 (I[10] = (T)(img)(x,_p1##y,z,c)), \
2003 (I[13] = (T)(img)(x,y,z,c)), \
2004 (I[16] = (T)(img)(x,_n1##y,z,c)), \
2005 (I[19] = (T)(img)(x,_p1##y,_n1##z,c)), \
2006 (I[22] = (T)(img)(x,y,_n1##z,c)), \
2007 (I[25] = (T)(img)(x,_n1##y,_n1##z,c)), \
2008 x+1>=(int)(img)._width?(img).width()-1:x+1); \
2009 x<=(int)(x1) && ((_n1##x<(img).width() && ( \
2010 (I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c)), \
2011 (I[5] = (T)(img)(_n1##x,y,_p1##z,c)), \
2012 (I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c)), \
2013 (I[11] = (T)(img)(_n1##x,_p1##y,z,c)), \
2014 (I[14] = (T)(img)(_n1##x,y,z,c)), \
2015 (I[17] = (T)(img)(_n1##x,_n1##y,z,c)), \
2016 (I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c)), \
2017 (I[23] = (T)(img)(_n1##x,y,_n1##z,c)), \
2018 (I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \
2020 I[0] = I[1], I[1] = I[2], I[3] = I[4], I[4] = I[5], I[6] = I[7], I[7] = I[8], \
2021 I[9] = I[10], I[10] = I[11], I[12] = I[13], I[13] = I[14], I[15] = I[16], I[16] = I[17], \
2022 I[18] = I[19], I[19] = I[20], I[21] = I[22], I[22] = I[23], I[24] = I[25], I[25] = I[26], \
2023 _p1##x = x++, ++_n1##x)
2025 #define cimglist_for(list,l) for (int l = 0; l<(int)(list)._width; ++l)
2026 #define cimglist_for_in(list,l0,l1,l) \
2027 for (int l = (int)(l0)<0?0:(int)(l0), _max##l = (unsigned int)l1<(list)._width?(int)(l1):(int)(list)._width-1; \
2030 #define cimglist_apply(list,fn) cimglist_for(list,__##fn) (list)[__##fn].fn
2034 #define _cimgdisplay_instance "[instance(%u,%u,%u,%c%s%c)] CImgDisplay::"
2035 #define cimgdisplay_instance _width,_height,_normalization,_title?'\"':'[',_title?_title:"untitled",_title?'\"':']'
2036 #define _cimg_instance "[instance(%u,%u,%u,%u,%p,%sshared)] CImg<%s>::"
2037 #define cimg_instance _width,_height,_depth,_spectrum,_data,_is_shared?"":"non-",pixel_type()
2038 #define _cimglist_instance "[instance(%u,%u,%p)] CImgList<%s>::"
2039 #define cimglist_instance _width,_allocated_width,_data,pixel_type()
2063 template<
typename T=
float>
struct CImg;
2075 #ifdef cimg_use_vt100
2076 const char t_normal[] = { 0x1b,
'[',
'0',
';',
'0',
';',
'0',
'm', 0 };
2077 const char t_black[] = { 0x1b,
'[',
'0',
';',
'3',
'0',
';',
'5',
'9',
'm', 0 };
2078 const char t_red[] = { 0x1b,
'[',
'0',
';',
'3',
'1',
';',
'5',
'9',
'm', 0 };
2079 const char t_green[] = { 0x1b,
'[',
'0',
';',
'3',
'2',
';',
'5',
'9',
'm', 0 };
2080 const char t_yellow[] = { 0x1b,
'[',
'0',
';',
'3',
'3',
';',
'5',
'9',
'm', 0 };
2081 const char t_blue[] = { 0x1b,
'[',
'0',
';',
'3',
'4',
';',
'5',
'9',
'm', 0 };
2082 const char t_magenta[] = { 0x1b,
'[',
'0',
';',
'3',
'5',
';',
'5',
'9',
'm', 0 };
2083 const char t_cyan[] = { 0x1b,
'[',
'0',
';',
'3',
'6',
';',
'5',
'9',
'm', 0 };
2084 const char t_white[] = { 0x1b,
'[',
'0',
';',
'3',
'7',
';',
'5',
'9',
'm', 0 };
2085 const char t_bold[] = { 0x1b,
'[',
'1',
'm', 0 };
2086 const char t_underscore[] = { 0x1b,
'[',
'4',
'm', 0 };
2088 const char t_normal[] = { 0 };
2089 const char *
const t_black = cimg::t_normal,
2090 *
const t_red = cimg::t_normal,
2091 *
const t_green = cimg::t_normal,
2092 *
const t_yellow = cimg::t_normal,
2093 *
const t_blue = cimg::t_normal,
2094 *
const t_magenta = cimg::t_normal,
2095 *
const t_cyan = cimg::t_normal,
2096 *
const t_white = cimg::t_normal,
2097 *
const t_bold = cimg::t_normal,
2098 *
const t_underscore = cimg::t_normal;
2101 inline std::FILE*
output(std::FILE *file=0);
2105 template<
typename T>
2111 inline int mutex(
const unsigned int n,
const int lock_mode=1);
2113 inline unsigned int& _exception_mode(
const unsigned int value,
const bool is_set) {
2114 static unsigned int mode = cimg_verbosity;
2116 if (is_set) mode = value;
2132 return _exception_mode(mode,
true);
2140 return _exception_mode(0,
false);
2143 inline int dialog(
const char *
const title,
const char *
const msg,
const char *
const button1_label=
"OK",
2144 const char *
const button2_label=0,
const char *
const button3_label=0,
2145 const char *
const button4_label=0,
const char *
const button5_label=0,
2146 const char *
const button6_label=0,
const bool centering=
false);
2148 inline double eval(
const char *
const expression,
2149 const double x=0,
const double y=0,
const double z=0,
const double c=0);
2220 #define _cimg_exception_err(etype,disp_flag) \
2221 std::va_list ap; va_start(ap,format); cimg_vsnprintf(_message,sizeof(_message),format,ap); va_end(ap); \
2222 if (cimg::exception_mode()) { \
2223 std::fprintf(cimg::output(),"\n%s[CImg] *** %s ***%s %s\n",cimg::t_red,etype,cimg::t_normal,_message); \
2224 if (cimg_display && disp_flag && !(cimg::exception_mode()%2)) try { cimg::dialog(etype,_message,"Abort"); } \
2225 catch (CImgException&) {} \
2226 if (cimg::exception_mode()>=3) cimg_library_suffixed::cimg::info(); \
2229 char _message[16384];
2231 CImgException(
const char *
const format, ...) { _cimg_exception_err(
"CImgException",
true); }
2233 const char *
what()
const throw() {
return _message; }
2239 CImgInstanceException(
const char *
const format, ...) { _cimg_exception_err(
"CImgInstanceException",
true); }
2245 CImgArgumentException(
const char *
const format, ...) { _cimg_exception_err(
"CImgArgumentException",
true); }
2251 CImgIOException(
const char *
const format, ...) { _cimg_exception_err(
"CImgIOException",
true); }
2257 CImgDisplayException(
const char *
const format, ...) { _cimg_exception_err(
"CImgDisplayException",
false); }
2263 CImgWarningException(
const char *
const format, ...) { _cimg_exception_err(
"CImgWarningException",
false); }
2284 static const char* string() {
2285 static const char* s[] = {
"unknown",
"unknown8",
"unknown16",
"unknown24",
2286 "unknown32",
"unknown40",
"unknown48",
"unknown56",
2287 "unknown64",
"unknown72",
"unknown80",
"unknown88",
2288 "unknown96",
"unknown104",
"unknown112",
"unknown120",
2290 return s[(
sizeof(T)<17)?
sizeof(T):0];
2292 static bool is_float() {
return false; }
2293 static bool is_inf(
const T) {
return false; }
2294 static bool is_nan(
const T) {
return false; }
2295 static T min() {
return (T)-1>0?(T)0:(T)-1<<(8*
sizeof(T)-1); }
2296 static T max() {
return (T)-1>0?(T)-1:~((T)-1<<(8*
sizeof(T)-1)); }
2297 static T inf() {
return max(); }
2298 static T cut(
const double val) {
return val<(double)min()?min():val>(double)max()?max():(T)val; }
2299 static const char* format() {
return "%s"; }
2300 static const char* format(
const T val) {
static const char *
const s =
"unknown";
cimg::unused(val);
return s; }
2304 static const char* string() {
static const char *
const s =
"bool";
return s; }
2305 static bool is_float() {
return false; }
2306 static bool is_inf(
const bool) {
return false; }
2307 static bool is_nan(
const bool) {
return false; }
2308 static bool min() {
return false; }
2309 static bool max() {
return true; }
2310 static bool inf() {
return max(); }
2311 static bool is_inf() {
return false; }
2312 static bool cut(
const double val) {
return val<(double)min()?min():val>(double)max()?max():(bool)val; }
2313 static const char* format() {
return "%s"; }
2314 static const char* format(
const bool val) {
static const char* s[] = {
"false",
"true" };
return s[val?1:0]; }
2317 template<>
struct type<unsigned char> {
2318 static const char* string() {
static const char *
const s =
"unsigned char";
return s; }
2319 static bool is_float() {
return false; }
2320 static bool is_inf(
const unsigned char) {
return false; }
2321 static bool is_nan(
const unsigned char) {
return false; }
2322 static unsigned char min() {
return 0; }
2323 static unsigned char max() {
return (
unsigned char)~0U; }
2324 static unsigned char inf() {
return max(); }
2325 static unsigned char cut(
const double val) {
2326 return val<(double)min()?min():val>(double)max()?max():(
unsigned char)val; }
2327 static const char* format() {
return "%u"; }
2328 static unsigned int format(
const unsigned char val) {
return (
unsigned int)val; }
2332 static const char* string() {
static const char *
const s =
"char";
return s; }
2333 static bool is_float() {
return false; }
2334 static bool is_inf(
const char) {
return false; }
2335 static bool is_nan(
const char) {
return false; }
2336 static char min() {
return (
char)(-1L<<(8*
sizeof(char)-1)); }
2337 static char max() {
return (
char)~((char)(-1L<<(8*
sizeof(
char)-1))); }
2338 static char inf() {
return max(); }
2339 static char cut(
const double val) {
return val<(double)min()?min():val>(double)max()?max():(char)val; }
2340 static const char* format() {
return "%d"; }
2341 static int format(
const char val) {
return (
int)val; }
2344 template<>
struct type<signed char> {
2345 static const char* string() {
static const char *
const s =
"signed char";
return s; }
2346 static bool is_float() {
return false; }
2347 static bool is_inf(
const signed char) {
return false; }
2348 static bool is_nan(
const signed char) {
return false; }
2349 static signed char min() {
return (
signed char)(-1L<<(8*
sizeof(
signed char)-1)); }
2350 static signed char max() {
return ~((
signed char)(-1L<<(8*
sizeof(
signed char)-1))); }
2351 static signed char inf() {
return max(); }
2352 static signed char cut(
const double val) {
2353 return val<(double)min()?min():val>(double)max()?max():(
signed char)val; }
2354 static const char* format() {
return "%d"; }
2355 static unsigned int format(
const signed char val) {
return (
int)val; }
2358 template<>
struct type<unsigned short> {
2359 static const char* string() {
static const char *
const s =
"unsigned short";
return s; }
2360 static bool is_float() {
return false; }
2361 static bool is_inf(
const unsigned short) {
return false; }
2362 static bool is_nan(
const unsigned short) {
return false; }
2363 static unsigned short min() {
return 0; }
2364 static unsigned short max() {
return (
unsigned short)~0U; }
2365 static unsigned short inf() {
return max(); }
2366 static unsigned short cut(
const double val) {
2367 return val<(double)min()?min():val>(double)max()?max():(
unsigned short)val; }
2368 static const char* format() {
return "%u"; }
2369 static unsigned int format(
const unsigned short val) {
return (
unsigned int)val; }
2373 static const char* string() {
static const char *
const s =
"short";
return s; }
2374 static bool is_float() {
return false; }
2375 static bool is_inf(
const short) {
return false; }
2376 static bool is_nan(
const short) {
return false; }
2377 static short min() {
return (
short)(-1L<<(8*
sizeof(short)-1)); }
2378 static short max() {
return ~((short)(-1L<<(8*
sizeof(
short)-1))); }
2379 static short inf() {
return max(); }
2380 static short cut(
const double val) {
return val<(double)min()?min():val>(double)max()?max():(short)val; }
2381 static const char* format() {
return "%d"; }
2382 static int format(
const short val) {
return (
int)val; }
2385 template<>
struct type<unsigned int> {
2386 static const char* string() {
static const char *
const s =
"unsigned int";
return s; }
2387 static bool is_float() {
return false; }
2388 static bool is_inf(
const unsigned int) {
return false; }
2389 static bool is_nan(
const unsigned int) {
return false; }
2390 static unsigned int min() {
return 0; }
2391 static unsigned int max() {
return (
unsigned int)~0U; }
2392 static unsigned int inf() {
return max(); }
2393 static unsigned int cut(
const double val) {
2394 return val<(double)min()?min():val>(double)max()?max():(
unsigned int)val; }
2395 static const char* format() {
return "%u"; }
2396 static unsigned int format(
const unsigned int val) {
return val; }
2400 static const char* string() {
static const char *
const s =
"int";
return s; }
2401 static bool is_float() {
return false; }
2402 static bool is_inf(
const int) {
return false; }
2403 static bool is_nan(
const int) {
return false; }
2404 static int min() {
return (
int)(-1L<<(8*
sizeof(int)-1)); }
2405 static int max() {
return ~((int)(-1L<<(8*
sizeof(
int)-1))); }
2406 static int inf() {
return max(); }
2407 static int cut(
const double val) {
return val<(double)min()?min():val>(double)max()?max():(int)val; }
2408 static const char* format() {
return "%d"; }
2409 static int format(
const int val) {
return val; }
2412 template<>
struct type<unsigned long> {
2413 static const char* string() {
static const char *
const s =
"unsigned long";
return s; }
2414 static bool is_float() {
return false; }
2415 static bool is_inf(
const unsigned long) {
return false; }
2416 static bool is_nan(
const unsigned long) {
return false; }
2417 static unsigned long min() {
return 0; }
2418 static unsigned long max() {
return (
unsigned long)~0UL; }
2419 static unsigned long inf() {
return max(); }
2420 static unsigned long cut(
const double val) {
2421 return val<(double)min()?min():val>(double)max()?max():(
unsigned long)val; }
2422 static const char* format() {
return "%lu"; }
2423 static unsigned long format(
const unsigned long val) {
return val; }
2427 static const char* string() {
static const char *
const s =
"long";
return s; }
2428 static bool is_float() {
return false; }
2429 static bool is_inf(
const long) {
return false; }
2430 static bool is_nan(
const long) {
return false; }
2431 static long min() {
return (
long)(-1L<<(8*
sizeof(long)-1)); }
2432 static long max() {
return ~((long)(-1L<<(8*
sizeof(
long)-1))); }
2433 static long inf() {
return max(); }
2434 static long cut(
const double val) {
return val<(double)min()?min():val>(double)max()?max():(long)val; }
2435 static const char* format() {
return "%ld"; }
2436 static long format(
const long val) {
return val; }
2440 static const char* string() {
static const char *
const s =
"double";
return s; }
2441 static bool is_float() {
return true; }
2442 static bool is_inf(
const double val) {
2444 return (
bool)isinf(val);
2449 static bool is_nan(
const double val) {
2451 return (
bool)isnan(val);
2456 static double min() {
return -1.7E308; }
2457 static double max() {
return 1.7E308; }
2458 static double inf() {
return max()*max(); }
2459 static double nan() {
static const double val_nan = -std::sqrt(-1.0);
return val_nan; }
2460 static double cut(
const double val) {
return val<min()?min():val>max()?max():val; }
2461 static const char* format() {
return "%.16g"; }
2462 static double format(
const double val) {
return val; }
2466 static const char* string() {
static const char *
const s =
"float";
return s; }
2467 static bool is_float() {
return true; }
2468 static bool is_inf(
const float val) {
2470 return (
bool)isinf(val);
2475 static bool is_nan(
const float val) {
2477 return (
bool)isnan(val);
2482 static float min() {
return -3.4E38f; }
2483 static float max() {
return 3.4E38f; }
2486 static float cut(
const double val) {
return val<(double)min()?min():val>(double)max()?max():(float)val; }
2487 static const char* format() {
return "%.16g"; }
2488 static double format(
const float val) {
return (
double)val; }
2491 template<
typename T,
typename t>
struct superset {
typedef T type; };
2492 template<>
struct superset<bool,unsigned char> {
typedef unsigned char type; };
2493 template<>
struct superset<bool,char> {
typedef char type; };
2494 template<>
struct superset<bool,signed char> {
typedef signed char type; };
2495 template<>
struct superset<bool,unsigned short> {
typedef unsigned short type; };
2496 template<>
struct superset<bool,short> {
typedef short type; };
2497 template<>
struct superset<bool,unsigned int> {
typedef unsigned int type; };
2498 template<>
struct superset<bool,int> {
typedef int type; };
2499 template<>
struct superset<bool,unsigned long> {
typedef unsigned long type; };
2500 template<>
struct superset<bool,long> {
typedef long type; };
2501 template<>
struct superset<bool,float> {
typedef float type; };
2502 template<>
struct superset<bool,double> {
typedef double type; };
2503 template<>
struct superset<unsigned char,char> {
typedef short type; };
2504 template<>
struct superset<unsigned char,signed char> {
typedef short type; };
2505 template<>
struct superset<unsigned char,unsigned short> {
typedef unsigned short type; };
2506 template<>
struct superset<unsigned char,short> {
typedef short type; };
2507 template<>
struct superset<unsigned char,unsigned int> {
typedef unsigned int type; };
2508 template<>
struct superset<unsigned char,int> {
typedef int type; };
2509 template<>
struct superset<unsigned char,unsigned long> {
typedef unsigned long type; };
2510 template<>
struct superset<unsigned char,long> {
typedef long type; };
2511 template<>
struct superset<unsigned char,float> {
typedef float type; };
2512 template<>
struct superset<unsigned char,double> {
typedef double type; };
2513 template<>
struct superset<signed char,unsigned char> {
typedef short type; };
2514 template<>
struct superset<signed char,char> {
typedef short type; };
2515 template<>
struct superset<signed char,unsigned short> {
typedef int type; };
2516 template<>
struct superset<signed char,short> {
typedef short type; };
2517 template<>
struct superset<signed char,unsigned int> {
typedef long type; };
2518 template<>
struct superset<signed char,int> {
typedef int type; };
2519 template<>
struct superset<signed char,unsigned long> {
typedef long type; };
2520 template<>
struct superset<signed char,long> {
typedef long type; };
2521 template<>
struct superset<signed char,float> {
typedef float type; };
2522 template<>
struct superset<signed char,double> {
typedef double type; };
2523 template<>
struct superset<char,unsigned char> {
typedef short type; };
2524 template<>
struct superset<char,signed char> {
typedef short type; };
2525 template<>
struct superset<char,unsigned short> {
typedef int type; };
2526 template<>
struct superset<char,short> {
typedef short type; };
2527 template<>
struct superset<char,unsigned int> {
typedef long type; };
2528 template<>
struct superset<char,int> {
typedef int type; };
2529 template<>
struct superset<char,unsigned long> {
typedef long type; };
2530 template<>
struct superset<char,long> {
typedef long type; };
2531 template<>
struct superset<char,float> {
typedef float type; };
2532 template<>
struct superset<char,double> {
typedef double type; };
2533 template<>
struct superset<unsigned short,char> {
typedef int type; };
2534 template<>
struct superset<unsigned short,signed char> {
typedef int type; };
2535 template<>
struct superset<unsigned short,short> {
typedef int type; };
2536 template<>
struct superset<unsigned short,unsigned int> {
typedef unsigned int type; };
2537 template<>
struct superset<unsigned short,int> {
typedef int type; };
2538 template<>
struct superset<unsigned short,unsigned long> {
typedef unsigned long type; };
2539 template<>
struct superset<unsigned short,long> {
typedef long type; };
2540 template<>
struct superset<unsigned short,float> {
typedef float type; };
2541 template<>
struct superset<unsigned short,double> {
typedef double type; };
2542 template<>
struct superset<short,unsigned short> {
typedef int type; };
2543 template<>
struct superset<short,unsigned int> {
typedef long type; };
2544 template<>
struct superset<short,int> {
typedef int type; };
2545 template<>
struct superset<short,unsigned long> {
typedef long type; };
2546 template<>
struct superset<short,long> {
typedef long type; };
2547 template<>
struct superset<short,float> {
typedef float type; };
2548 template<>
struct superset<short,double> {
typedef double type; };
2549 template<>
struct superset<unsigned int,char> {
typedef long type; };
2550 template<>
struct superset<unsigned int,signed char> {
typedef long type; };
2551 template<>
struct superset<unsigned int,short> {
typedef long type; };
2552 template<>
struct superset<unsigned int,int> {
typedef long type; };
2553 template<>
struct superset<unsigned int,unsigned long> {
typedef unsigned long type; };
2554 template<>
struct superset<unsigned int,long> {
typedef long type; };
2555 template<>
struct superset<unsigned int,float> {
typedef float type; };
2556 template<>
struct superset<unsigned int,double> {
typedef double type; };
2557 template<>
struct superset<int,unsigned int> {
typedef long type; };
2558 template<>
struct superset<int,unsigned long> {
typedef long type; };
2559 template<>
struct superset<int,long> {
typedef long type; };
2560 template<>
struct superset<int,float> {
typedef float type; };
2561 template<>
struct superset<int,double> {
typedef double type; };
2562 template<>
struct superset<unsigned long,char> {
typedef long type; };
2563 template<>
struct superset<unsigned long,signed char> {
typedef long type; };
2564 template<>
struct superset<unsigned long,short> {
typedef long type; };
2565 template<>
struct superset<unsigned long,int> {
typedef long type; };
2566 template<>
struct superset<unsigned long,long> {
typedef long type; };
2567 template<>
struct superset<unsigned long,float> {
typedef double type; };
2568 template<>
struct superset<unsigned long,double> {
typedef double type; };
2569 template<>
struct superset<long,float> {
typedef double type; };
2570 template<>
struct superset<long,double> {
typedef double type; };
2571 template<>
struct superset<float,double> {
typedef double type; };
2573 template<
typename t1,
typename t2,
typename t3>
struct superset2 {
2577 template<
typename t1,
typename t2,
typename t3,
typename t4>
struct superset3 {
2581 template<
typename t1,
typename t2>
struct last {
typedef t2 type; };
2583 #define _cimg_Tt typename cimg::superset<T,t>::type
2584 #define _cimg_Tfloat typename cimg::superset<T,float>::type
2585 #define _cimg_Ttfloat typename cimg::superset2<T,t,float>::type
2586 #define _cimg_Ttdouble typename cimg::superset2<T,t,double>::type
2591 volatile unsigned int nb_wins;
2592 pthread_t* events_thread;
2593 pthread_cond_t wait_event;
2594 pthread_mutex_t wait_event_mutex;
2597 unsigned int nb_bits;
2599 bool is_shm_enabled;
2601 #ifdef cimg_use_xrandr
2602 XRRScreenSize *resolutions;
2603 Rotation curr_rotation;
2604 unsigned int curr_resolution;
2605 unsigned int nb_resolutions;
2607 X11_info():nb_wins(0),events_thread(0),display(0),
2608 nb_bits(0),is_blue_first(false),is_shm_enabled(false),byte_order(false) {
2610 pthread_mutex_init(&wait_event_mutex,0);
2611 pthread_cond_init(&wait_event,0);
2612 #ifdef cimg_use_xrandr
2615 curr_resolution = nb_resolutions = 0;
2620 if (events_thread) {
2621 pthread_cancel(*events_thread);
2622 delete events_thread;
2625 pthread_cond_destroy(&wait_event);
2626 pthread_mutex_unlock(&wait_event_mutex);
2627 pthread_mutex_destroy(&wait_event_mutex);
2630 #if defined(cimg_module)
2631 X11_info& X11_attr();
2632 #elif defined(cimg_main)
2633 X11_info& X11_attr() {
static X11_info val;
return val; }
2635 inline X11_info& X11_attr() {
static X11_info val;
return val; }
2638 #elif cimg_display==2
2641 Win32_info() { wait_event = CreateEvent(0,FALSE,FALSE,0); }
2643 #if defined(cimg_module)
2644 Win32_info& Win32_attr();
2645 #elif defined(cimg_main)
2646 Win32_info& Win32_attr() {
static Win32_info val;
return val; }
2648 inline Win32_info& Win32_attr() {
static Win32_info val;
return val; }
2655 Mutex_info() {
for (
unsigned int i = 0; i<32; ++i) mutex[i] = CreateMutex(0,FALSE,0); }
2656 void lock(
const unsigned int n) { WaitForSingleObject(mutex[n],INFINITE); }
2657 void unlock(
const unsigned int n) { ReleaseMutex(mutex[n]); }
2658 int trylock(
const unsigned int) {
return 0; }
2659 #elif defined(_PTHREAD_H)
2660 pthread_mutex_t mutex[32];
2661 Mutex_info() {
for (
unsigned int i = 0; i<32; ++i) pthread_mutex_init(&mutex[i],0); }
2662 void lock(
const unsigned int n) { pthread_mutex_lock(&mutex[n]); }
2663 void unlock(
const unsigned int n) { pthread_mutex_unlock(&mutex[n]); }
2664 int trylock(
const unsigned int n) {
return pthread_mutex_trylock(&mutex[n]); }
2667 void lock(
const unsigned int) {}
2668 void unlock(
const unsigned int) {}
2669 int trylock(
const unsigned int) {
return 0; }
2672 #if defined(cimg_module)
2674 #elif defined(cimg_main)
2677 inline Mutex_info& Mutex_attr() {
static Mutex_info val;
return val; }
2680 #if defined(cimg_use_magick)
2681 static struct Magick_info {
2683 Magick::InitializeMagick(
"");
2690 const unsigned int keyESC = XK_Escape;
2691 const unsigned int keyF1 = XK_F1;
2692 const unsigned int keyF2 = XK_F2;
2693 const unsigned int keyF3 = XK_F3;
2694 const unsigned int keyF4 = XK_F4;
2695 const unsigned int keyF5 = XK_F5;
2696 const unsigned int keyF6 = XK_F6;
2697 const unsigned int keyF7 = XK_F7;
2698 const unsigned int keyF8 = XK_F8;
2699 const unsigned int keyF9 = XK_F9;
2700 const unsigned int keyF10 = XK_F10;
2701 const unsigned int keyF11 = XK_F11;
2702 const unsigned int keyF12 = XK_F12;
2703 const unsigned int keyPAUSE = XK_Pause;
2704 const unsigned int key1 = XK_1;
2705 const unsigned int key2 = XK_2;
2706 const unsigned int key3 = XK_3;
2707 const unsigned int key4 = XK_4;
2708 const unsigned int key5 = XK_5;
2709 const unsigned int key6 = XK_6;
2710 const unsigned int key7 = XK_7;
2711 const unsigned int key8 = XK_8;
2712 const unsigned int key9 = XK_9;
2713 const unsigned int key0 = XK_0;
2715 const unsigned int keyINSERT = XK_Insert;
2716 const unsigned int keyHOME = XK_Home;
2717 const unsigned int keyPAGEUP = XK_Page_Up;
2718 const unsigned int keyTAB = XK_Tab;
2719 const unsigned int keyQ = XK_q;
2720 const unsigned int keyW = XK_w;
2721 const unsigned int keyE = XK_e;
2722 const unsigned int keyR = XK_r;
2723 const unsigned int keyT = XK_t;
2724 const unsigned int keyY = XK_y;
2725 const unsigned int keyU = XK_u;
2726 const unsigned int keyI = XK_i;
2727 const unsigned int keyO = XK_o;
2728 const unsigned int keyP = XK_p;
2729 const unsigned int keyDELETE = XK_Delete;
2730 const unsigned int keyEND = XK_End;
2733 const unsigned int keyA = XK_a;
2734 const unsigned int keyS = XK_s;
2735 const unsigned int keyD = XK_d;
2736 const unsigned int keyF = XK_f;
2737 const unsigned int keyG = XK_g;
2738 const unsigned int keyH = XK_h;
2739 const unsigned int keyJ = XK_j;
2740 const unsigned int keyK = XK_k;
2741 const unsigned int keyL = XK_l;
2742 const unsigned int keyENTER = XK_Return;
2744 const unsigned int keyZ = XK_z;
2745 const unsigned int keyX = XK_x;
2746 const unsigned int keyC = XK_c;
2747 const unsigned int keyV = XK_v;
2748 const unsigned int keyB = XK_b;
2749 const unsigned int keyN = XK_n;
2750 const unsigned int keyM = XK_m;
2755 const unsigned int keyALT = XK_Alt_L;
2756 const unsigned int keySPACE = XK_space;
2757 const unsigned int keyALTGR = XK_Alt_R;
2759 const unsigned int keyMENU = XK_Menu;
2764 const unsigned int keyPAD0 = XK_KP_0;
2765 const unsigned int keyPAD1 = XK_KP_1;
2766 const unsigned int keyPAD2 = XK_KP_2;
2767 const unsigned int keyPAD3 = XK_KP_3;
2768 const unsigned int keyPAD4 = XK_KP_4;
2769 const unsigned int keyPAD5 = XK_KP_5;
2770 const unsigned int keyPAD6 = XK_KP_6;
2771 const unsigned int keyPAD7 = XK_KP_7;
2772 const unsigned int keyPAD8 = XK_KP_8;
2773 const unsigned int keyPAD9 = XK_KP_9;
2774 const unsigned int keyPADADD = XK_KP_Add;
2775 const unsigned int keyPADSUB = XK_KP_Subtract;
2776 const unsigned int keyPADMUL = XK_KP_Multiply;
2777 const unsigned int keyPADDIV = XK_KP_Divide;
2779 #elif cimg_display==2
2781 const unsigned int keyESC = VK_ESCAPE;
2782 const unsigned int keyF1 = VK_F1;
2783 const unsigned int keyF2 = VK_F2;
2784 const unsigned int keyF3 = VK_F3;
2785 const unsigned int keyF4 = VK_F4;
2786 const unsigned int keyF5 = VK_F5;
2787 const unsigned int keyF6 = VK_F6;
2788 const unsigned int keyF7 = VK_F7;
2789 const unsigned int keyF8 = VK_F8;
2790 const unsigned int keyF9 = VK_F9;
2791 const unsigned int keyF10 = VK_F10;
2792 const unsigned int keyF11 = VK_F11;
2793 const unsigned int keyF12 = VK_F12;
2794 const unsigned int keyPAUSE = VK_PAUSE;
2795 const unsigned int key1 =
'1';
2796 const unsigned int key2 =
'2';
2797 const unsigned int key3 =
'3';
2798 const unsigned int key4 =
'4';
2799 const unsigned int key5 =
'5';
2800 const unsigned int key6 =
'6';
2801 const unsigned int key7 =
'7';
2802 const unsigned int key8 =
'8';
2803 const unsigned int key9 =
'9';
2804 const unsigned int key0 =
'0';
2805 const unsigned int keyBACKSPACE = VK_BACK;
2806 const unsigned int keyINSERT = VK_INSERT;
2807 const unsigned int keyHOME = VK_HOME;
2808 const unsigned int keyPAGEUP = VK_PRIOR;
2809 const unsigned int keyTAB = VK_TAB;
2810 const unsigned int keyQ =
'Q';
2811 const unsigned int keyW =
'W';
2812 const unsigned int keyE =
'E';
2813 const unsigned int keyR =
'R';
2814 const unsigned int keyT =
'T';
2815 const unsigned int keyY =
'Y';
2816 const unsigned int keyU =
'U';
2817 const unsigned int keyI =
'I';
2818 const unsigned int keyO =
'O';
2819 const unsigned int keyP =
'P';
2820 const unsigned int keyDELETE = VK_DELETE;
2821 const unsigned int keyEND = VK_END;
2822 const unsigned int keyPAGEDOWN = VK_NEXT;
2823 const unsigned int keyCAPSLOCK = VK_CAPITAL;
2824 const unsigned int keyA =
'A';
2825 const unsigned int keyS =
'S';
2826 const unsigned int keyD =
'D';
2827 const unsigned int keyF =
'F';
2828 const unsigned int keyG =
'G';
2829 const unsigned int keyH =
'H';
2830 const unsigned int keyJ =
'J';
2831 const unsigned int keyK =
'K';
2832 const unsigned int keyL =
'L';
2833 const unsigned int keyENTER = VK_RETURN;
2834 const unsigned int keySHIFTLEFT = VK_SHIFT;
2835 const unsigned int keyZ =
'Z';
2836 const unsigned int keyX =
'X';
2837 const unsigned int keyC =
'C';
2838 const unsigned int keyV =
'V';
2839 const unsigned int keyB =
'B';
2840 const unsigned int keyN =
'N';
2841 const unsigned int keyM =
'M';
2842 const unsigned int keySHIFTRIGHT = VK_SHIFT;
2843 const unsigned int keyARROWUP = VK_UP;
2844 const unsigned int keyCTRLLEFT = VK_CONTROL;
2845 const unsigned int keyAPPLEFT = VK_LWIN;
2846 const unsigned int keyALT = VK_LMENU;
2847 const unsigned int keySPACE = VK_SPACE;
2848 const unsigned int keyALTGR = VK_CONTROL;
2849 const unsigned int keyAPPRIGHT = VK_RWIN;
2850 const unsigned int keyMENU = VK_APPS;
2851 const unsigned int keyCTRLRIGHT = VK_CONTROL;
2852 const unsigned int keyARROWLEFT = VK_LEFT;
2853 const unsigned int keyARROWDOWN = VK_DOWN;
2854 const unsigned int keyARROWRIGHT = VK_RIGHT;
2855 const unsigned int keyPAD0 = 0x60;
2856 const unsigned int keyPAD1 = 0x61;
2857 const unsigned int keyPAD2 = 0x62;
2858 const unsigned int keyPAD3 = 0x63;
2859 const unsigned int keyPAD4 = 0x64;
2860 const unsigned int keyPAD5 = 0x65;
2861 const unsigned int keyPAD6 = 0x66;
2862 const unsigned int keyPAD7 = 0x67;
2863 const unsigned int keyPAD8 = 0x68;
2864 const unsigned int keyPAD9 = 0x69;
2865 const unsigned int keyPADADD = VK_ADD;
2866 const unsigned int keyPADSUB = VK_SUBTRACT;
2867 const unsigned int keyPADMUL = VK_MULTIPLY;
2868 const unsigned int keyPADDIV = VK_DIVIDE;
2873 const unsigned int keyESC = 1U;
2874 const unsigned int keyF1 = 2U;
2875 const unsigned int keyF2 = 3U;
2876 const unsigned int keyF3 = 4U;
2877 const unsigned int keyF4 = 5U;
2878 const unsigned int keyF5 = 6U;
2879 const unsigned int keyF6 = 7U;
2880 const unsigned int keyF7 = 8U;
2881 const unsigned int keyF8 = 9U;
2882 const unsigned int keyF9 = 10U;
2883 const unsigned int keyF10 = 11U;
2884 const unsigned int keyF11 = 12U;
2885 const unsigned int keyF12 = 13U;
2886 const unsigned int keyPAUSE = 14U;
2887 const unsigned int key1 = 15U;
2888 const unsigned int key2 = 16U;
2889 const unsigned int key3 = 17U;
2890 const unsigned int key4 = 18U;
2891 const unsigned int key5 = 19U;
2892 const unsigned int key6 = 20U;
2893 const unsigned int key7 = 21U;
2894 const unsigned int key8 = 22U;
2895 const unsigned int key9 = 23U;
2896 const unsigned int key0 = 24U;
2897 const unsigned int keyBACKSPACE = 25U;
2898 const unsigned int keyINSERT = 26U;
2899 const unsigned int keyHOME = 27U;
2900 const unsigned int keyPAGEUP = 28U;
2901 const unsigned int keyTAB = 29U;
2902 const unsigned int keyQ = 30U;
2903 const unsigned int keyW = 31U;
2904 const unsigned int keyE = 32U;
2905 const unsigned int keyR = 33U;
2906 const unsigned int keyT = 34U;
2907 const unsigned int keyY = 35U;
2908 const unsigned int keyU = 36U;
2909 const unsigned int keyI = 37U;
2910 const unsigned int keyO = 38U;
2911 const unsigned int keyP = 39U;
2912 const unsigned int keyDELETE = 40U;
2913 const unsigned int keyEND = 41U;
2914 const unsigned int keyPAGEDOWN = 42U;
2915 const unsigned int keyCAPSLOCK = 43U;
2916 const unsigned int keyA = 44U;
2917 const unsigned int keyS = 45U;
2918 const unsigned int keyD = 46U;
2919 const unsigned int keyF = 47U;
2920 const unsigned int keyG = 48U;
2921 const unsigned int keyH = 49U;
2922 const unsigned int keyJ = 50U;
2923 const unsigned int keyK = 51U;
2924 const unsigned int keyL = 52U;
2925 const unsigned int keyENTER = 53U;
2926 const unsigned int keySHIFTLEFT = 54U;
2927 const unsigned int keyZ = 55U;
2928 const unsigned int keyX = 56U;
2929 const unsigned int keyC = 57U;
2930 const unsigned int keyV = 58U;
2931 const unsigned int keyB = 59U;
2932 const unsigned int keyN = 60U;
2933 const unsigned int keyM = 61U;
2934 const unsigned int keySHIFTRIGHT = 62U;
2935 const unsigned int keyARROWUP = 63U;
2936 const unsigned int keyCTRLLEFT = 64U;
2937 const unsigned int keyAPPLEFT = 65U;
2938 const unsigned int keyALT = 66U;
2939 const unsigned int keySPACE = 67U;
2940 const unsigned int keyALTGR = 68U;
2941 const unsigned int keyAPPRIGHT = 69U;
2942 const unsigned int keyMENU = 70U;
2943 const unsigned int keyCTRLRIGHT = 71U;
2944 const unsigned int keyARROWLEFT = 72U;
2945 const unsigned int keyARROWDOWN = 73U;
2946 const unsigned int keyARROWRIGHT = 74U;
2947 const unsigned int keyPAD0 = 75U;
2948 const unsigned int keyPAD1 = 76U;
2949 const unsigned int keyPAD2 = 77U;
2950 const unsigned int keyPAD3 = 78U;
2951 const unsigned int keyPAD4 = 79U;
2952 const unsigned int keyPAD5 = 80U;
2953 const unsigned int keyPAD6 = 81U;
2954 const unsigned int keyPAD7 = 82U;
2955 const unsigned int keyPAD8 = 83U;
2956 const unsigned int keyPAD9 = 84U;
2957 const unsigned int keyPADADD = 85U;
2958 const unsigned int keyPADSUB = 86U;
2959 const unsigned int keyPADMUL = 87U;
2960 const unsigned int keyPADDIV = 88U;
2963 const double PI = 3.14159265358979323846;
2966 const char *
const data_font12x13 =
2967 " .wjwlwmyuw>wjwkwbwjwkwRxuwmwjwkwmyuwJwjwlx`w Fw mwlwlwuwnwuynwuwmyTwlwkwuwmwuwnwlwkwuwmwuw_wuxl"
2968 "wlwkwuwnwuynwuwTwlwlwtwnwtwnw my Qw +wlw b{ \\w Wx`xTw_w[wbxawSwkw nynwky<x1w `y ,w Xwuw CxlwiwlwmyuwbwuwUwiwlwbwiwrwqw^wuwmxuwnwiwlwmy"
2969 "uwJwiwlw^wnwEymymymymy1w^wkxnxtxnw<| gybwkwuwjwtwowmxswnxnwkxlxkw:wlymxlymykwn{myo{nymy2ykwqwqwm{myozn{o{mzpwrwpwkwkwswowkwqwqxswnyozlyozmzp}pwrwqwqwq"
2970 "wswswsxsxqwqwp}qwlwiwjybw`w[wcw_wkwkwkwkw mw\"wlwiw=wtw`xIw awuwlwm{o{mylwn|pwtwtwoy`w_w_wbwiwkxcwqwpwkznwuwjzpyGzqymyaxlylw_zWxkxaxrwqxrwqyswowkwkwkwk"
2971 "wkwkwk}qyo{o{o{o{owkwkwkwkznxswnymymymymyayuwqwrwpwrwpwrwpwrwqwqwpwkwtwlwkwlwuwnwuynwuwmyTwkwlwuwmwuwnwkwlwuwmwuwkxlwuxmwkwlwuwnwuynwuwTwkwlwuwmwuwlwm"
2972 "wkwtwUwuwuwowswowswowswowsw;wqwtw_ymzp~py>w bwswcwkwuwjwuwozpwtwuwnwtwowkwjwmwuwuwkwIxmxuxowuwmwswowswmxnwjwhwowswowsw0wmwowswuwnwrwowswpwswowkwjwrwqw"
2973 "rwpwkwkwtwnwkxsxqxswowswpwswnwswpwswowrwnwmwrwqwqwqwswswrwswowswjwpwlxjwkxuxLw[wcw_wSwkw mw\"wlwiw=wtwmxlwFw cwswnwuwnwkwjwswo{pwrwpwtwtwpwswby`w`yUwlw"
2974 "twpwqwpwswowlw\\wrwrxuwHwrwfwuwjwlwlwTyuwVwlwtwawswowswowswcwuwmwuwmwuwmwuwmwuwlwkwuwnwswpwkwkwkwkwkwkwkwkwswoxswowswowswowswowswowswowrwpwswpwrwpwrwpw"
2975 "rwpwrwpwswoznwtw Ww (wGwtwtwqwqwqwuwuwuwqwswuwqwqw=wqxtw`{nzp~q{ozowrwnxmwtwow bzawkwuwl}rwuwnwtwuwnwtwowkwjwlyjwIwlwswmwiwkwnwuwnwkwhwnwswowswowkwew"
2976 "ewixnwsytwswuwnwrwpwkwrwpwkwkwkwrwpwkwkwuwmwkxsxqwuwtwpwqwqwswowqwqwswowiwmwrwpwswowtwtwpwuwmwuwjwowkwjwlxsxXynzmymznyozlzoznwkwkwtwnwkzuyrzmynzmzowux"
2977 "myozmwswpwrwowtwtwrwrwpwrwp{mwlwiwHyuwpwtwkwmxlynzoxswmwmwswnwswowtxq|owtwtwpym{p{owswnwuwmwlwkwqwqxuwuxqwrwpwtwtwqwqwowlwuwuwkwmwlwtwowuwuwdwjznwl{nw"
2978 "uwnwkx_wtxtwswtwlwtwWwuytwgyjwmwjwawswoyuwVwlwtwnwtwmwtwnwtwmwuwmwlwuwmwuwmwuwmwuwmwuwmwuwmxuwowkwkwkwkwkwkwkwkwkwrwpwuwtwpwqwqwqwqwqwqwqwqwqwowtwpwsw"
2979 "uwqwrwpwrwpwrwpwrwowuwnwswowuwlymymymymymymyuyqymymymymynwkwkwkwjynzmymymymymykwmzowswowswowswowswpwrwozowrwW}q}qwtwtwqwtwtwqwtwtwA}rwuw_{p~r~r}pwtwow"
2980 "rwnxmwtwow aw_w]wtwpwuwmxuwmybwjwlyjwIwlwswmwiwnynwtwnznzkwmynwswTyp}pylwmwtwtwtwswuwn{owkwrwp{o{owk|pwkwkxlwkwuwuwuwqwuwtwpwqwqwswowqwqwswoykwmwrwpws"
2981 "wowuwuwuwowkwjwnwkwjwDwowswowkwswowswowkwswowswowkwkwuwmwkwswswswswowswowswowswoxlwswowkwswpwrwowtwtwqwtwowrwlwoxkwhxVxuxpwtypwuwjwnwtwnwkwswowtxnxmws"
2982 "wowqwqwtwuxqwtwnwtwtwqwswowswmwm{nwuwlxnwkwqwqwtwtwqwrwpwtwtwqwuyuwpwiwhwnwmwrwnwbwkwuwlwlwswoxuxowlwtw`wuwrwszmwtwo}dwuwtwuw[}qymx`wswoyuwow_ylxlwtwo"
2983 "yuwoyuwoyuwmwlwuwmwuwmwuwmwuwmwuwmwuwmwt{swk{o{o{o{owkwkwkwlztwpwuwtwpwqwqwqwqwqwqwqwqwqwnxowtwtwqwrwpwrwpwrwpwrwnwmwswowuwiwkwkwkwkwkwkwswswkwswowswo"
2984 "wswowswowkwkwkwkwswowswowswowswowswowswowswcwtxowswowswowswowswpwrwowswpwrwWwtwtwqwqwqwuwuwuwqwuwswqwqw>wowuw`}q~q|q}qwrwpwrwowtwnwtwo~ izaw]wtwoykwux"
2985 "qwtwswfwjwmwuwuwn}eyaxlwswmwjwjwpwswjwowswmwmwswnzWy]ypwlwtwtwuwswswowrwpwkwrwpwkwkwsyqwrwpwkwkwuwmwkwuwuwuwqwtwuwpwqwqznwqwqzkynwmwrwowuwnwuwuwuwowkw"
2986 "jwnwkxkwGzowswowkwswo{owkwswowswowkwkxlwkwswswswswowswowswowswowjxmwkwswowtwnwuwuwuwpxmwtwlwlwlwiwlytwewtwtwqwswowtxoznwswnxmwswnwuwmwuwnwswowtwtwqwtw"
2987 "twqwtwnwtwtwqwswowswmwmwswowswmwmwkwqwqwtwtwqwrwowuwuwpwuyuwq~own~own~owbwkwuwmznwswmwbwswawuwrwgwtwhwdwuytwXwJwswnxuw=wtwmwswowtxowswqxmwswowswowswow"
2988 "swowswowswnwtwowkwkwkwkwkwkwkwkwkwrwpwtwuwpwqwqwqwqwqwqwqwqwqwnxowtwtwqwrwpwrwpwrwpwrwnwmwswowtwmznznznznznzn~swk{o{o{o{owkwkwkwkwswowswowswowswowswow"
2989 "swowswo}qwuwuwowswowswowswowswowtwnwswowtwUwuwuwowswowswowswowsw@}qx`}q~pzo{pwrwpwrwowtwnwtwow aw_w_}owuwmwuwtwrwswuwewjwkwiwJwkwswmwkwiwp|kwowswmwmws"
2990 "wkwWym}mypwlwszr{owrwpwkwrwpwkwkwqwqwrwpwkwkwtwnwkwtwtwqwtwuwpwqwqwkwqwqwtwiwnwmwrwowuwnwuwuwuwpwuwlwkwmwjwkwHwswowswowkwswowkwkwswowswowkwkwuwmwkwsws"
2991 "wswswowswowswowswowhwnwkwswowtwnwuwuwuwpxmwtwmwkwlwiwmwtydwtwtwqwswowswowtwnwswowkwswnwuwnwtwnwswowtwtwqwtwtwqwtwnwtwtwqwswowswmwmwswowswnwlwkwqwqxuwu"
2992 "xqwrwnyowqwpwiwhwpwuwuwowrwpwuwuwdwkwuwlwlwswo{owkxuwawtxtwszmwtwiwdwuwtwuwXwJwswmwuwKzmwtwlwtxowrwpwtxrxl{o{o{o{o{o{o{owkwkwkwkwkwkwkwkwkwrwpwtwuwpwq"
2993 "wqwqwqwqwqwqwqwqwowtwpwuwswqwrwpwrwpwrwpwrwnwmznwswowswowswowswowswowswowswowswowkwkwkwkwkwkwkwkwkwswowswowswowswowswowswowswcwuwuwowswowswowswowswowt"
2994 "wnwswowtwTymymymymy=wmw^wuwuwmxlxmyowrwowtwnwtwmxmw bwswIwuwmwuwmwuwtwrxswdwjw]wJwkxuxmwlwlwswlwjwowswmwmwswlwSycyawlwswowrwowswpwswowkwjwrwqwrwpwkwkw"
2995 "swowkwqwqwsxowswpwjwswpwswowrwnwmxtxnwlwswpwswmwlwlwjwkwHwswowswowkwswowswowkwswowswowkwkwtwnwkwswswswswowswowswowswowkwswowkwswnxlwswpwtwmxmwjwlwiwTx"
2996 "uxpwtxowswowtwnwswowkwswnynwtwnwswowtwtwqxuwuxqwtwnwtwtwqwswowswmwlwuwnwswowkwjwswo{pwrwmwmwswnwjwiwnymwtwnycwkwuwlwl{mwmwiw_wrwdwtwVwrw*wswmwuw?wtwlw"
2997 "tzqwrwpwtzswkwswowswowswowswowswowswowswnwswpwkwkwkwkwkwkwkwkwswowsxowswowswowswowswowswowrwpwswpxtxpxtxpxtxpxtxnwmwkwswowswowswowswowswowswowswowtxow"
2998 "kwswowswowswowswowkwkwkwkwswowswowswowswowswowswowswlwnxtwowswowswowswowswnxmwswnx >wlw\\wkx`wnwrwoznwtwmxl| gybw^wtwozmwsxpzuxfxlx]wnw_wlxjyn{o{nykwnz"
2999 "mymwkynymwkwewewjwjwrwswqwp{myozn{owizpwrwpwkwkwrwp{owqwqwsxnyowiyowrwozmwlzmwlwswqxsxnwm}qwjxlwGzozmymznynwjzowswowkwkwswowkwswswswswnynzmzowjymxlznx"
3000 "lwswqwrwnwm{mwlwiwHxuxpzmxlymynwswmwnwrwozmxuxo{pwtxn{pzmykwmyo}p{owkyuynwnwrwmwly`w_w_wbwjzo{pwqwnwmwhw_z>zY}M|nwuw2wqwqwryrwqwqyowqwqwqwqwqwqwqwqwqw"
3001 "qwqwqwr{qyo{o{o{o{owkwkwkwkznwsxnymymymymycwuynznznznzmwmwkwuynznznznznznznyuzrymymymymynwkwkwkwjynwswnymymymymybzmznznznznwlzmw hwHwlwSwTw <w8z ]"
3002 "x tx Zxjwmx RwWw/wgw pw_ynwky=wCwmwaw\\w_wnw 1wIwlz 'wiwuwaw mw Pw swlwjw hw f| pyWx/wgw rxSw/wCwmwaw\\w_wnw 1w AwRx nw Pw txk"
3006 const char *
const data_font20x23 =
3007 " 9q\\q^r_rnp`qnq`plp7q\\q^q_qmqbq\\q^q_qmqHqmp_q\\q^r_rnp`qnq7q\\q^q_qmq_q \"r "
3008 " Mq^q^qnq`pnr`qnq`plp6q^q^pmp`qmqaq^q^pmp`qmqIpmq]q^q^qnq`pnr`qnq6q^q^pmp`qmq`q \"plp 'q 5qmq Vq "
3009 " Xq [plp 3qYq_p^rnpLplp8qYq_qNqYq_q4rmpaqYq_q_rmp%qYq^pGq Irc|!pKp]raqjq`p HtNq_qmq\\plqbp_shpdscq[q^q[p [q]s_r`uau]rbv`tcxbua"
3010 "t LsZucrav_udwcxdw`udqiqeq]q]qjreq]sksgrjqbtcv_tcvaud{eqiqgqfqgqjsjqlrjrhrirfzfs`q[sZqMqJqCqNsLq]q]q]q]q .scq]s \\sKt%r [s^raxdxat_qazgqlqlqctJqIqIq"
3011 "LqHsOqiqOtaqmq\\uft nufu`sLs`t\\qKv<r\\rLrepirepitgpeq]r^r^r^r^r^r^{gudxdxdxdxdq]q]q]q]wcrjqbt`t`t`t`tLtlpgqiqeqiqeqiqeqiqgrireq[s_q[q_pnp_pnr`qnq`plp7q["
3012 "q_s`qmqcq[q_s`qmq]pkpbpmr`q[q_s`pmraqmq8q[q^pnp_qnq^qaq\\qnq !pnqd{!pJp^tdunucr _y dvOq_qmq\\plpap_pmpipdudq[p\\p_plplp _q^ubtawcw^rbvavdxcwcw Ou]yerawb"
3013 "xeyexdwbxeqiqeq]q]qkrdq]sksgrjqdxewbxewcwe{eqiqfqhqfqjsjqkqjqfqiqezfs`q[s[sMpJqCqOtLq]q]q]q]q q 1tcq]t ^vaq_w&r \\u_raxdxcxcuczgqlqlqexMsJqJsMq[p^uPq"
3014 "iqdq]uaqmq]qkqcq!qkqguaqmqNpkp\\p]pKtmp:p]plpKpfpfpfpcpipdq]r^r^r^r^r^r^{ixexdxdxdxdq]q]q]q]yerjqdxdxdxdxdxPwnpfqiqeqiqeqiqeqiqfqiqdq\\u_p[p^pnpKqnq_r5p"
3015 "[p^pmp`qmqbp[p^pmp`qmq]tKp[p^pmpLqmq7p[p]pnp_qnq^p`q\\qnq5uauauauaucq`qhq4p]pKr_ueunucr `q \\rkpOq_qmq\\plpctbqmqkqerlpdq\\q\\q_qnpnq\\q%q^qkqcqnqapjrdpjr`"
3016 "sbq]rkp^qcrkrerkq Oplr`sirgtbqkrdripeqjsfq]q]ripeqiqeq]q]qlrcq]sksgskqerjrfqkrdrjrfqkrerjp`q`qiqfqhqeqkskqiqlqdqkq\\qeq]qZq\\qmqNqKqCqOqIq5q]q q 1q`qZq"
3017 " _rlqbtaqjp$q ^qkqatbr^q]rjrewdqhqgqlqlqfrjrOuKqKu8p_rlpOqkqcq]qFpgpcp\"pgpTpkp\\q^p\\p^qLump:p^pjpLpgpepgpbpjpPt`t`t`t`t`qnq_qnqcripeq]q]q]q]q]q]q]q]qj"
3018 "sfskqerjrfrjrfrjrfrjrfrjrRrjrfqiqeqiqeqiqeqiqeqkqcvbrlq`q]q_plp Iq]q_qmqNq]q_qmqKtIq]q_qmq ^q]q^plpKq`q mqkqcqkqcqkqcqkqcqkqdq`qhq5q^qLt`ueunudtasbqip"
3019 "`q`pipcq [qIq_qmq`{gvcqmqkpdq_q\\q\\q]rZq%q_rkraqZq]qaqnqbq]qXqcqiqeqiq1pSpXq`qfrhqnqbqjqdq]qhqfq]q]q]qiqeq]q]qmrbq]qnqmqnqgskqeqhqfqjqdqhqfqjqeqYq`qiq"
3020 "frjreqkskqirnrdrmr]qdq]qZq]qkq)qCqOqIq5q]q q 1q`qZq _qkq_qaq mq ^qkqaqnqar_q]qhqfrnqnreqhqgqlqlqfqhqPwLqLw9p_q_phqdqkqcq]qGplslpiu#pmtlpUpkp\\q_q_r8u"
3021 "mp:p^pjpLpgpepgperipcq^qnq`qnq`qnq`qnq`qnq`qnq`qmqcq]q]q]q]q]q]q]q]q]qhqfskqeqhqfqhqfqhqfqhqfqhqdphpfqirfqiqeqiqeqiqeqiqermrcwcqkq [q 3qZp Oq nqmqm"
3022 "qeqiqeqiqeqiqeqiqeq_piq4q^pLvatd|evdvcqipasaqkqdq [qHq_qmq`{hrnpmpcqmqlpcq_q\\pZp]rZq%q_qiqaqZq]qapmqbq^qWqcqiqeqiqdq]qUsSs[qaqdqhqnqbqjqeq\\qgqgq]q^q\\"
3023 "qiqeq]q]qnraq]qnqmqnqgqnqlqfqfqgqjqeqfqgqjqeqYq`qiqeqjqdqlqmqlqhqnqbqmq]rdq]qZq^pgp=taqns`s`snqatdv_snqcqnsbq]q]qkqcq]qnsmshqns`saqnsasnqcqnr`tbvaqjqe"
3024 "qiqdqkqkqjrkreqiqdw`q`qZq#tnreqkq^qatauaqnsdqiq`raqjqdqiqdpmrcxdqmqmqatbxfyeqiqbqnq`r`q^qfqhrmqmrfqhqgqlqlqgqfqep[pnqnp[p`q`pipbpnqnpNq]taq^qnqnqbqmqb"
3025 "q\\qIqmpkpmqkqkp$qmpkpmqVqmq\\q`q[pLqjqeump:p^pjpLphpdphpapkpbq^qnq`qnq`qnq`qnq`qnq`qnq`qmqdq\\q]q]q]q]q]q]q]q]qgqgqnqlqfqfqhqfqhqfqhqfqhqfqfrjrhqiqnqgqi"
3026 "qeqiqeqiqeqiqdqmqbqkrdqmsbt`t`t`t`t`t`tlsfs_t`t`t`tbq]q]q]q[tbqns`s_s_s_s_s\\q`smpdqjqdqjqdqjqdqjqeqiqdqnscqiq;qlqlqgqgqgqnqmqnqgqjqnqgqgqfq_qjq<{fpjpL"
3027 "vatd|fxeqkqdqipasaqkqdp \\yNqGplqeqmp`qmqmqcrLqZq`qnpnq\\q%q_qiqaqZq^rbqmqbubqms^qaqkqdqiqdq]qXuf{fu_q`qlrnqlqjqlqcqkreq\\qgqgq]q^q\\qiqeq]q]t`q]qnqmqnqg"
3028 "qnqlqfqfqgqkreqfqgqkres[q`qiqeqjqdqlqmqlqhs`s]rcq]qZq#vbwcvbwcwev`wcwcq]q]qlqbq]vnthwcwcwcwcubwcvaqjqdqkqcqkqkqiqkqdqiqdw`q`qZq7smsfxdqlr^qavdvawdqkq_"
3029 "raqjqdpgpeqntdxdqmqmqcwdyfyeqiqcqlq`raq^qfqhqlqlqfqhqgqlqlqgqfqfrZqZraqarkraqLq^vbq^wbqmqbq]tKpmpfpkpjp_plp9plpkplpUs[qaqZpLqjqeump:p^pjpaplp_piqdpiqa"
3030 "plqbq_qlqbqlqbqlqbqlqbqlqbqlqbrmqdq\\q]q]q]q]q]q]q]q]qgqgqnqlqfqfqhqfqhqfqhqfqhqfqerlrgqjqmqgqiqeqiqeqiqeqiqcsaqjqdqnq`vbvbvbvbvbvbvnuivbwcwcwcwcq]q]q]"
3031 "q]wcwcwcwcwcwcwOwcqjqdqjqdqjqdqjqeqiqdwdqiq;pkqkpgpepgpmumpgpjrmpgpepfq_qkq;{hrkpLxdxf|fxepipdqipas`pkpcp ZqHqGplpdt_pmplpmshsMqZqaplplp]q&q^qiqaq[qa"
3032 "t`plqbvcx_q`ucrkr:uc{cucq`qlvlqjqlqcwdq\\qgqgxdvcqjtfyeq]q]s_q]qmsmqgqmqmqfqfqgwdqfqgwcv_q`qiqdqlqbqmqmqmqfr`s]qbq\\q[q#pjqcrlrdqkpcrlrcqkrdq^rlrcrlrdq]"
3033 "q]qmqaq]rlrlqirlrdqkqcrlrerlrcr_qjpbq]qjqdqkqcqlslqhqmqbqkq^q_q`qZq_tjpSqmsmpgrlsdqnsaqmqbqkqdq\\rlrdqlq_raqjqeqgqgrnqnrdqlqcqmqmqcqkqerkq`qaycqlq_rbq^"
3034 "qfqhqlqlqfqhqgqlqlqgqnvnqgrYqYrbqbrirbqLq_rnpmpdwaqmqcydq^qlqLpmpfpkpkq`plpa{RpltkpB{gpXpLqjqdtmpcqHp]plp_plp`pipjpipipmsfplpjphr_qlqbqlqbqlqbqlqbqlqb"
3035 "qlqbqlxkq\\xdxdxdxdq]q]q]q_vjqgqmqmqfqfqhqfqhqfqhqfqhqfqdrnrfqkqlqgqiqeqiqeqiqeqiqcsaqjqdqnq`pjqcpjqcpjqcpjqcpjqcpjqcpjrlrjqkpbqkrdqkrdqkrdqkrdq]q]q]q]"
3036 "qkrdrlrdqkqcqkqcqkqcqkqcqkqOqkqcqjqdqjqdqjqdqjqdqkqcrlrdqkq:pnwnpgpnwnpgplslpgpkrlpgpkqkpfq^qlq6qaqlpMzfzfzfzgqipdqipbqmp`qmqc| fqHqHqlpcuasmplpmpiul"
3037 "qSqZq]p^{+q^qiqaq\\q`ubqlqbpkrdrkrarawcx<tEteq`qlqlqlqjqlqcwdq\\qgqgxdvcqjtfyeq]q]t`q]qmsmqgqmqmqfqfqgvcqfqgv_t`q`qiqdqlqbqmqmqmqgs_q]qaq\\q[q\"vcqjqeq]qj"
3038 "qdqiqdq^qjqcqjqdq]q]qnq`q]qkqkqiqjqeqiqdqjqeqjqcq^s^q]qjqdqkqbqmsmqgqmqbqkq_qas_qYsc{Spkqkphqkrcqntcvcqiqeq\\qjqdqmr`tbqjqeqgqgqmqmqdqlqcqmqmqdqiqfqiqa"
3039 "qaycqlq_qaq^qfqhqlqlqfqhqfqmqmqfqnvnqh}cqc}cqc}cqLq_qmpawbqkqasaq^qkqMpmpfpjsnpaplp`{RplpmqkpB{huatKqjqbrmpcqJt^r]plpctlpjqktlpmpkpltlpjqhq^qlqbqlqbql"
3040 "qbqlqbqlqcrlrcqlxkq\\xdxdxdxdq]q]q]q_vjqgqmqmqfqfqhqfqhqfqhqfqhqfqcteqlqkqgqiqeqiqeqiqeqiqbq`qkrdqmravbvbvbvbvbvbvjqkq]qiqeqiqeqiqeqiqdq]q]q]q^qiqdqjqe"
3041 "qiqeqiqeqiqeqiqeqiqd{hqkpnqdqjqdqjqdqjqdqjqdqkqcqjqdqkq:pnwnpgpnwnpgplslpgplrkpgpkqkpfq^qlq6qaqmqMzg|fxdxfqipdqipbqmqaqmqcp \\wLqK{dt]qmqmqkrmrnrSqZqK"
3042 "{TtKq^qiqaq]r\\rdqkq\\qdqiqaqarkrcsmq<tEtfq_qlqlqlqkqjqdqjqeq\\qgqgq]q^qgqfqiqeq]q]qnraq]qmsmqgqlqnqfqfqgq^qfqgqkq]raq`qiqdqlqbqnqkqnqgt`q^raq\\q[q#wcqjqe"
3043 "q]qjqdydq^qjqcqjqdq]q]s_q]qkqkqiqjqeqiqdqjqeqjqcq]uaq]qjqcqmqaqmpmpmqfs`qmq_ras_qYscpjtRpkqkphqkrcqkreqlrcqiqcr_qjqdqmq_qnqbqjqeqlqlqgqmqmqdqlqcqmqmqd"
3044 "qiqfqiqaqaqiqdqjqaq`q^qfqhqlqlqfqhqfrnqnrfqfqh}cqc}cqc}cqLq_qmp_q^qkq`qMrlqMpmpfpWplpUqRplplqlp=q&qjq`pmp _plp]qkpnpdqhpeqkpnpiq^qjqdqjqdqjqdqjqdqjqdq"
3045 "jqdqkqdq\\q]q]q]q]q]q]q]q]qgqgqlqnqfqfqhqfqhqfqhqfqhqfqbrdqmqjqgqiqeqiqeqiqeqiqbq`wcqlrcwcwcwcwcwcwc~kq]yeyeyeydq]q]q]q^qiqdqjqeqiqeqiqeqiqeqiqeqiqd{hq"
3046 "lpmqdqjqdqjqdqjqdqjqcqmqbqjqcqmq9pkqkpgpepgpmumpgpmrjpgpepfq]pmq:{epmpLzg|evbveqipdqipbqmqaqmpbq [qHqK{cpmq^plqmqkqktRqZqFqOtKq^qiqaq^rZqdy^qdqiqaqaq"
3047 "iq]q:uc{cudq_qlqlqmqjxdqiqfq\\qgqgq]q^qgqfqiqeq]q]qmrbq]qlqlqgqlqnqfqfqgq^qfqgqkr]qaq`qiqcqnqaqnqkqnqhrnq`q_r`q\\q[q$qjqcqjqeq]qjqdydq^qjqcqjqdq]q]s_q]q"
3048 "kqkqiqjqeqiqdqjqeqjqcqZsbq]qjqcqmqaqnqmqnqfs`qmq`r^r`qZr9pkqkphqkrcqjqeqkqcqiqet_qjqcqnq`rnqbqjqeqlqlqgqmqmqdqlqcqmqmqdqiqfqiqaqaqiqdqjqbr`q]qhqgrmqmr"
3049 "fqhqeweqfqgrYqYrdpnqnpdrirdpnqnpNq_qmp_q]qmqcyPrmqMqmpkpmqkvaplpVqRqmpkpmq=q&qjq`pmp(v_plp\\pkpmpdphqepkpmpjq]xdxdxdxdxdxdwdq\\q]q]q]q]q]q]q]q]qgqgqlqnq"
3050 "fqfqhqfqhqfqhqfqhqfqcteqnqiqgqiqeqiqeqiqeqiqbq`vbqjqeqjqdqjqdqjqdqjqdqjqdqjqdqjxkq]yeyeyeydq]q]q]q^qiqdqjqeqiqeqiqeqiqeqiqeqiqQqmplqdqjqdqjqdqjqdqjqcq"
3051 "mqbqjqcqmq9qlqlqgqgqgqnqmqnqgqnqjqgqgqfq]qnq:{eqnpLzg|dt`tdqipcpipbpkp`sbq Zq plq`pmq_pkqmqkqjrQqZqFq'q]rkraq_rYqdy^qdqiqbq`qiq^q6uf{fuaq_qlyjzeqiqeq"
3052 "]qhqfq]q]qhqfqiqeq]q]qlrcq]qlqlqgqkseqhqfq]qhqfqjq]qaq`qiqcqnq`skshrmraq_q_q[q\\q$qjqcqjqeq]qjqdq\\q^qjqcqjqdq]q]qnq`q]qkqkqiqjqeqiqdqjqeqjqcqXqbq]qjqcq"
3053 "mqaqnqmqnqgqmq`s_q\\q`qZq7pmpnqmpgqkrcqjqeqkpbqiqeq\\qjqcs_qlqcqjqeqlqlqgqmqmqdqlqcqmqmqdqiqfqiqaq`qkqdrjrdr_q]riqfrnqnreqhqducqhqerZqZrdwdrkrdwOq_qmp_q"
3054 "^w`q`q[sKplslpTplpWqQpmpkqnp<q&qjq`pmp aplp\\pkplpephqepkplpjq^zfzfzfzfzfzfxcq]q]q]q]q]q]q]q]q]qhqfqkseqhqfqhqfqhqfqhqfqhqcrnreriqfqiqeqiqeqiqeqiqbq`q]"
3055 "qjqeqjqdqjqdqjqdqjqdqjqdqjqdqjqdq]q]q]q]q\\q]q]q]q^qiqdqjqeqiqeqiqeqiqeqiqeqiqQqnpkqdqjqdqjqdqjqdqjqbsaqjqbs7qmqmqeqiqeqiqeqiqeqiqeq]qnp7q]rJrnpnresnpn"
3056 "sct_rcqipcqkqcqkqasaq [rkp&plpcplpnr`qkqmqkrltRqZqFq'q\\qkq`q`r_pjr^qcpjrcqkrbq`rkrdpkr3sSsLrlrnrhqhqeqjreripeqjsfq]q]riqfqiqeq]q]qkrdq]qgqgqkserjrfq]"
3057 "rjrfqjrfpiraq_qkqbt`skshqkqaq`q^q[q\\q$qkrcrlrdqkpcrlrcqipdq^rlrcqjqdq]q]qmqaq]qkqkqiqjqdqkqcrlrerlrcq^pjqbq]rlrbs_rkrfqmq`s`r\\q`qZq6qlrfrmscrlrepkqbrk"
3058 "qdqkpaqjqcs`rlqcrlrernsnrgrnqnrdqlqcrnqnrdrkqdqkraq`qkqdqhqer^q\\rkqdwdqhqbqarjrdpYqYpbubpipbuNq_rnpmpbq^qnqnq`q`qZqIpgpRplp7pgp;q&rlr`pmp bplp[pkufpiq"
3059 "dpkukrlpcqhqfqhqfqhqfqhqfqhqfqhqfqjqcripeq]q]q]q]q]q]q]q]qjsfqkserjrfrjrfrjrfrjrfrjrdrlrfrjreqkqcqkqcqkqcqkqaq`q]qnplqeqkrdqkrdqkrdqkrdqkrdqkrdqksjpjq"
3060 "kpbqipdqipdqipdqipdq]q]q]q]qkqcqjqdqkqcqkqcqkqcqkqcqkq^qbqkqcrlrdrlrdrlrdrlrbsarlrbs6qkqcqkqcqkqcqkqcqkqdq\\r7q\\qFp\\p]r^rcqipcvbqkqas`r \\vOqIqlpcw_pip"
3061 "mpivnrRpZpEqbqIq^q[ubwdxdw]qcwbwaq_wcvbq]qRpSp[q^q^qhqexcxeyexdq\\xeqiqeq]q]qjrexdqgqgqjrdxeq\\xeqiqfx`q_war_ririqiqbqazfq[q\\q$xcwcvbwcxdq]wcqjqdq]q]qlq"
3062 "bq]qkqkqiqjqdwcwcwcq^wbu`wbs_rkrgqkq`q`w`q`qZq$yewdqmq`wdvaqjqbr`qkqcyeyewcqlsdwcxdw`sauczexdq^umteucqhqbq`xLqJsKsMq^vdxdpgpaq`qYqIqkq bqkq?{+yapmp Jp"
3063 "fpfpipcpfpiucqhqfqhqfqhqfqhqfqhqfqhqfqjxixexdxdxdxdq]q]q]q]yeqjrdxdxdxdxdxdrjrgpnwdwcwcwcwaq`q]qnuexdxdxdxdxdxdvnwjvbxdxdxdxdq]q]q]q]wcqjqdwcwcwcwcw^q"
3064 "bwbwcwcwcwaq`w`q4uauauauaucq\\r7p[qFp\\p\\p\\pbqipasapip`q^y ctNqIqmqbu_phsgslrSq\\qEqbqIq^qZsawdxcu\\qbt^taq]uataq]q q]qgpiqfqfw`udwcxdqZudqiqeq]q]qirfxdq"
3065 "gqgqjrbtcqZtcqirfv_q]s_r_rirjrircqazfq[q\\q#tnqcqns`s`snqaucq\\snqcqjqdq]q]qkqcq]qkqkqiqjqbsaqnsasnqcq]t_t_snqaq^rkrhrkraq`w`q`qZq#smrevbs^t`s`qjqbq`qiq"
3066 "dqnrmqdrmrcubqkrcubqntat^r`sc|fxdq^umtcqaqhqbq^tJqIqIqLq]tcxLq`qYqHu `u>{+qnrmqapmp Kpepgpiuhpephscqfqhqfqhqfqhqfqhqfqhqfqhqixgudxdxdxdxdq]q]q]q]wcqjr"
3067 "bt`t`t`t`taphpgplt`s_s_s_s_q`q]qmsctnqctnqctnqctnqctnqctnqbsktgs_uauauaucq]q]q]q[saqjqbs_s_s_s_sNpms_snqbsnqbsnqbsnqaq`qns_q !p Zp jp#q\\q6q7q l"
3068 "q [sjq Qq -q OqZq]q Cq;q HqWq $rIq`qZq _q iqbqKqFqIq`q hp$q]u JqYpmpLp .p jp ]p Xr`q[r !p Tp\"p\\p6q6q mq Yx Qr -r Ps\\q_s"
3069 " Ipkq:q HqWq $qHq`qZq _q iqbqKqFqIq`q hp$q]t IqYpmpLq /q kq Fq_q[q #s Tp\"q^q6p 1p Vu Rs YsJsMy &v<s HqWq &sHtcq]t _q i"
3070 "qbqKqFqIq`q hp$q 2q2q /q kq Hs_q]s \"q (r Xy %t;r GqWq &rFscq]s ^q iqbqKqFqIq`q ,q4r 0r lr G"
3074 const char *
const data_font47x53 =
3076 " 9])]2_2]T\\8^U^3] E])]2`4^U^>])]2_4^U^ 6^T\\5])]1_2]T\\8^U^ K])]2`4^V^3] "
3077 " U]*\\2a4`V\\8^U^5a F]*\\1\\X\\4^U^=]*\\"
3078 "2a5^U^ 7aV\\4]*\\1a4`V\\8^U^ J]*\\1\\X\\4^V^3\\ "
3079 " S],\\1\\W\\5g8^U^6c F],\\1\\V\\5^U^<],\\2]W]6^U^ 8h3],\\0\\W\\5g8^U^ I],\\1\\V\\5^V"
3081 " :\\-]2\\U\\6\\V`7^U^7]U] F\\-]2\\T\\6^U^;\\-]3]U]7^U^ 8\\Va1\\-]1\\U\\6\\V`7^U^ H\\-]2\\T\\6^V^5] =a "
3083 " N\\/]2\\S\\7\\T]6^U^7\\S\\ E\\/]2\\R\\7^U^:\\/]3]S]8^U^ 8\\T^/\\/]1\\S\\7\\T]6^U^ G\\/]2\\R\\7^V^6] =c L^ "
3085 " !^$^3\\ E]U\\ K^$^4^ G^$^4] J^$^3\\ #^$^3\\ 4^ B[ "
3086 "&^ Xe S^ (\\S\\ )Z Q^&^3^2]S\\ A\\S\\ K^&^3^ F^&^4_ >]S"
3087 "\\9^&^3^2]S\\ W^&^3^ 6^ Q] M[ ?` ![1^H]?` =]4](\\ %` >b4c Bb ?`2a .a Ib Pb Aa <a @b Fb =b F^ :] '] Da A"
3088 "].].].].] <_:]._ Xh ?c W^ @` La Pa Sa Va5^U^ @` \"f4_ >`0`*^ $^.` <^F]F^F]G`G] F\\S\\ ;b %a2a2a2a2a <bR"
3089 "\\ D`4^(^3`4`U\\8^V^6\\S\\ J^(^3`4^U^@^(^3_4^U^/^/`U\\8^(^3`4`U\\8^V^ K^(^3`4^V^1^9]+^V^ ?` O\\ D\\6]M] We D]1]T] 9[3bJ\\@e<])]2])\\ "
3090 " T]0d3_7h9i/_;k5f?n:f7e 3g :_8i3h@h9n?l5iB]H]C].].]J^B].`I`H_J]<g?g1g?g4hAuB]H]G]C]F]K_K]S^J^F^G^CrBb7]*b'_ D] :] '] Fc A].].].].] >a:]"
3091 ".a !^T_ Bg ` Dd2_8n?m7g3]:rD]P]P]@g <] 8] 8] B] 3e J^K^ If7^U^+b@d Fb@f5a Ad4e-] :f Ra0d AaF\\HaF\\HeJ\\?]._0_0_0_0_2\\U\\0tHh@n?n?n?n?].].].]"
3092 "-h:_J]<g8g8g8g8g BhV]G]H]C]H]C]H]C]H]G^G^B]*d5](]2\\X\\4aW]8^V^6\\S\\ I](]3]X]5^U^?](]3\\W\\5^U^.^R[9aW]7](]2\\X\\4aW]8^V^ J](]2\\X\\4^V^1]8]+^V^ ?a>w "
3093 "P[ 9[/a:aQa7[ Wl \"h E]1]T]+\\R\\;[4dL]Ag=])]2])\\ U^1f8c8k;j1`;k7h?n;h9g 5i*b:_8k6kBl=n?l7mD]H]C].].]L_A].`I`H`K]>kAj6kAj9kBuB]H]F]E]E^L_L^"
3094 "R^L^D^I^BrBb7^+b(a D] ;] '] Gd A].].].].] ;] (b:].b #^Q] Dj !a Ff3_8n?m8i4]:rD]P]P]Bk ?_ 9] 9_ C]&[0f I]K]=]0g7^U^-fC\\S] IfBf6c B["
3095 "S]5[S].] <i R\\W\\1]T] B\\W\\G]H\\W\\G]H[S]K]?]._0_0_0_0_2c1uIkBn?n?n?n?].].].]-l>`K]>k<k<k<k<k EoF]H]C]H]C]H]C]H]F^I^A],h6]*]2\\V\\6]Wa7^V^6\\S\\ H]*]2\\V]6^U"
3096 "^>]*]3]W]6^U^._V_;]Wa5]*]2\\V\\6]Wa7^V^ I]*]2\\V\\5^V^2]7]+^V^ @]W\\=v P[ 9\\1c<cSd:] \"o #_S^ F]1]T],]S];[5^V^N]A_T]=]*]0]*\\ U]1^T^;e8`S_<"
3097 "^R_2`;k8^R]?n<_T_;^S^ 6^S_.i>_8m:`R`Cn?n?l9`QaE]H]C].].]M_@].aKaH`K]?`S`Bk8`S`Bk;_R_BuB]H]F]E]D]MaM]P]L]B^K^ArB]1]&])c D] <] '] G] :].].].].] "
3098 ";] (^6]*^ #]P^ E^P\\ V^ H^T^4_8n?m:`S`6]:rD]P]P]C`S` Aa :] :a D]&[1^S\\ I^M^=]0^R[7^U^/^R^EZO\\ L^R^ N]U] :],\\0] <j M\\2]R] >\\H]B\\H]=\\M]>"
3099 "]._0_0_0_0_0_/uK`R`Cn?n?n?n?].].].]-n@`K]?`S`>`S`>`S`>`S`>`S` H`ScE]H]C]H]C]H]C]H]E^K^@],^T^5],]1\\V\\6\\U`7^V^6]U\\ F],]2\\T\\6^U^=],]2\\U\\6^U^-e9\\U`4],]1\\"
3100 "V\\6\\U`7^V^ H],]1\\V\\5^V^3]6]+^V^ B`1`1`1`1`6]W]>u P[ 9]2e>eUf;^ %q $^O\\ F]1]T],]S];[5]T]N\\@]P[=]*]0]2ZR\\RZ $]2]P]<_W]8]N]<ZL^4a;]+]MZ/]<^P"
3101 "^=^Q^ 7\\O]1nAa9]N_<_M]C]NaA].]+_L^E]H]C].].]N_?].aKaHaL]@^M^C]P_:^M^C]P_=^M\\6]6]H]F^G^D]MaM]P^N^B^K^-^B]1]&]*e D] =] '] H] 9].].].].] ;] )"
3102 "^5])^ %^O]8^3]LZ U] I^R^6a9_0]+^M^7]:]H]D]P]P]D^M^ Cc ;] ;c E]&[2^PZ H]M]<]1^-^U^1]L];[ N]L] Q]S] :\\,\\1] <dU\\ M\\2\\P\\ >\\H\\A\\H\\<\\M\\=]/a2a2a"
3103 "2a2a1_/]V];_M]C].].].].].].].]-]ObBaL]@^M^@^M^@^M^@^M^@^M^ J^N`D]H]C]H]C]H]C]H]E^K^@]-^Q]5].]1\\T\\7\\S]6^V^5c E].]2]S\\7^U^<].]2\\S\\7^U^,a6\\S]2].]1\\T\\7\\S"
3104 "]6^V^ G].]1\\T\\6^V^4]5]+^V^ De6e6e6e6e9\\U\\>u P[ :_3f@gVf<_ &r $]M[ F]1]T],\\R]>d<^T^P]A^OZ=]+].]4]T\\T] &^3^P^=[S]8[K].]4\\X];],]!]<]N]>^O^ "
3105 " 8ZM^3`P`Ba9]M^=^J\\C]K_B].],^H\\E]H]C].].]O_>].aKaHaL]A^K^D]N^<^K^D]N^>]JZ6]6]H]E]G]C]MaM]O^P^@^M^-^A]1]&]+_W_ D] >] '] H] 9] B].] ;] )]4](]"
3106 " %]N]:c6] G] J^P^7a8_1],^K^;c=]H]D]P]P]E^K^ Ee <] <e F]&[2] =^O^<]1] 0\\H\\<\\ P\\H\\ R\\Q\\+]3\\,\\2] <eU\\ M\\3]P\\ >\\I]A\\I]<\\N]=]/a2a2a2a2a2a1]U]<"
3107 "^J\\C].].].].].].].]-]K_CaL]A^K^B^K^B^K^B^K^B^K^ K]K^D]H]C]H]C]H]C]H]D^M^?]-]P]4]0]1\\R\\ Ha C]0]2]R] E]0]2\\Q\\ 9c 9]0]1\\R\\ !]0]1\\R\\ ?]4] Di:i:i:i:i"
3108 ";\\6]G] P\\ :`5g@gWh>a (_ J]KZ F]1]T],\\R\\?h>]R]P\\@]1]+].]3^V\\V^.] T]2]N]5]8ZJ]-]6]X];]-]!^=]L]?]M] *]5_J_Ec:]L^>]H[C]I^C].],]F[E]H]C].].]"
3109 "P_=].]X]M]X]HbM]A]I]D]M]<]I]D]M]?]%]6]H]E]G]C^NaN^N]Q^>^O^-^@]0]'],_U_ &] '] H] 9] B].] ;] )]4](] %]N]:d7] F] K]N]8c8^1],]I]>i@]H"
3110 "]D]P]P]E]I] Fg =] =g G]&[2] <]O];]1] 1\\F\\=\\ Q\\F\\ S\\Q\\+]3\\.] IeU\\ M\\3\\N\\ ?\\I\\@\\I\\=]M\\<]0c4c4c4c4c3a1]U]<]H[C].].].].].].].]-]J_DbM]A]I]B]I]B]I]B]I]"
3111 "B]I] L]J_E]H]C]H]C]H]C]H]C^O^>].]N] .] '`X_ I] FbWa=bWa=bWa=bWa=bWa<\\6^I^ ?Z2[ :a5gAiXh?c *^ H] 7]1]T]-]S]Aj>]R]Q]@]1],"
3112 "],\\1^X\\X^,] T]3]L]6]'].]7]W];]-]!]<]L]?]M^ +]6^F^F]W]:]K]?]FZC]H^D].]-]DZE]H]C].].]Q_<].]X]M]X]H]X]M]B]G]E]M^>]G]E]M^@]%]6]H]E^I^B]O^X]O]M^R^=]O^"
3113 "-^@]0]']-_S_ '] '] H] 9] B].] ;] )]4](] %]N]:e8_ H] L]M]8]W]7^2]-]G]AmB]H]D]P]P]F]G] Hi >] >i J[3] ;^Q^;]1] 2\\RbT\\Ge R\\VdR\\ T\\"
3114 "Q\\+]4\\2a IfU\\ M\\3\\N\\ ?\\J\\?\\J\\AaM\\ G]W]4]W]4]W]4]W]4]W]4c3^U]=]FZC].].].].].].].]-]H]D]X]M]B]G]D]G]D]G]D]G]D]G]A[H[B]J`E]H]C]H]C]H]C]H]B]O^>g8]N] "
3115 " 1]T_ 3[ 9] G_O^?_O^?_O^?_O^?_O^=\\5]I^ @\\3[ ;c6gAy?d7`8]L]7^7]L]>^ H] 6]1]T]-]S]B_W[U]>]R]R]?]1],],]0d*] T]3]L]6]'].]7\\V];]"
3116 ".] ]<]L]@]K] 7Z PZ X]7^D^G]W]:]K]?]/]G]D].]-]/]H]C].].]R_;].]X^O^X]H]X^N]B]G]E]L]>]G]E]L]@]%]6]H]D]I]A]O]W]O]L^T^<^Q^-^?]0]'].^O^ Sb7]U`2b4`U]8a8])`"
3117 "7]T_ M].]%_O_@_2`0`3`/_3c9] )]4](] N_6]N]3^7a/c0_ <^ D[U^ Ga N]L]9]W]6^3]-]G]B`W]W`C]H]D]P]P]F]G] I_X]X_ ?] ?_X]X_ Nb7]2ZFZ=]Q]:]0] 3[SfU[I"
3118 "g R[UfS[ T\\Q\\+]5]2a IfU\\ M\\3\\N\\ ?\\K]?\\K]AaN] G]W]4]W]4]W]4]W]4]W]4]W]3]T]=]/].].].].].].].]-]G]E]X^N]B]G]D]G]D]G]D]G]D]G]B]J]C]KbF]H]C]H]C]H]C]H]B"
3119 "^Q^=j;]P_9b3b3b3b3b3b3bN`Bb3a2a2a2a V_2_2`1`1`1`1` ;aU] :]U` S^T]U^A^L^A^L^A^L^A^L^?]5]I] @^5\\ <e7gAy@f;e:]L]8`8^N^?^ G] 6]1]T]-\\R\\A]U["
3120 "RZ>]R]R\\>]1],],].`(] U^3]L]6]'].]8]V];].]!^<]L]@]K] :] P]#^8^A]I^W^;]K]@].]G^E].].].]H]C].].]S_:].]W]O]W]H]W]N]C]E]F]L]?]E]F]L]@]%]6]H]D]J^A]O]W]O]"
3121 "L^U^:^S^-^>]0^(]/^M^ Wh:]Wd6f8dW]:e>h2dW]?]Vd<].].]O_>].]WdScK]Vd8f;]Wd7dW]?]Wa6h>h6]L]B]I]A]P`P]K^L^B^K^@l4]4](] PdU]A]N]2^8e5g;]Vd?^J^8]6]L] E]V`"
3122 ">pA]S]S]:e6kDo>]L]:^W^6^4].]E]D_U]U_D]H]D]P]P]G]E] K_W]W_ @] @_W]W_ Qf9]3\\H\\>^S^:]0_ 6[ThT[K]Q\\ S[T\\R]S[ U]S]+]6],] ?]L]@fU\\ M\\3\\N\\ ?\\K\\>\\K\\;]O\\ G"
3123 "^W^6^W^6^W^6^W^6^W^5]W]4^T]>].].].].].].].].]-]G^F]W]N]C]E]F]E]F]E]F]E]F]E]D_L_E]K]W]F]H]C]H]C]H]C]H]A^S^<k<]Ra<h9h9h9h9h9h9hTeFf7e6e6e6e;].].].]\"^;]V"
3124 "d8f7f7f7f7f/^6eX]@]L]?]L]?]L]?]L]B^K^?]Wd>^K^ O]S]S]B]I]B]I]B]I]B]I]@]5^K^ @]4[ ;f8gAyAg<h<]L]8`7]N]>] F] 6]1]T]-\\R\\B]T[6]R]S]>^2]-]*\\.`(] U"
3125 "]2]L]6]'].]9]U];].]!];]L]@]K] =` P`'^7]?\\I]U];]K]@].]F]E].].].]H]C].].]T_9].]W]O]W]H]W^O]C]E]F]L]?]E]F]L]@]%]6]H]C]K]@^P]W]P^K^V^9]S]-^=]/](]0^K^ Xi"
3126 ";]Xf9h9fX]<h?h3fX]?]Xg=].].]P_=].]XfVfL]Xg:h<]Xf9fX]?]Xb7i>h6]L]A]K]@^Q`Q^J^N^@]K]?l4]4](] QfW^A]O^1]6f9h;]Xg@_K]7]6]L]=]G]C^Wc@pA]S]S]<h9mDo>]L]:]U"
3127 "]5^5].]E]E^S]S^E]H]D]P]P]G]E]@Z+]V]V^-Z4]5ZKZ:]V]V^ Sh9]4^J^>]S]9]._ 8[U_Q[T[L]P\\ S[T\\Q]T[ T]U]*]7]*] @]L]@fU\\ M\\3\\N\\ ?\\L]>\\L]:]Q]:]1]U]6]U]6]U]6]"
3128 "U]6]U]6^W^5]S]>].].].].].].].].]-]F]F]W^O]C]E]F]E]F]E]F]E]F]E]C_N_D]L^W]F]H]C]H]C]H]C]H]@]S];]P_=]S^8i:i:i:i:i:i:iVgIh9h9h9h9h<].].].]'d<]Xg:h9h9h9h9h"
3129 "0^8k?]L]?]L]?]L]?]L]A]K]>]Xf>]K] O]R]R]D]G]D]VZOZV]D]KZV]D]G]A]4]K] @]3[ <g7fAyBi>j=]L]8`7]N]?] F^ 6]1]T]5uI]T[6]R]S\\<^3]-]*]1d*] U]3]J]7]']"
3130 ".]9\\T];].\\Ua-^;]L]@]K^?].] Uc Pc+_8]>]J]U];]K]@].]F]E].].].]H]C].].]U_8].]W^Q^W]H]V]O]C]E]F]L]?]E]F]L]@^&]6]H]C]K]?]Q^V]Q]I^X^8^U^.^<]/](]1^I^ ]R_<aT"
3131 "_;_R\\:^Tb=_S^@h4_Ub?bT^=].].]Q_<].aT_X]T^LbT^;_T_=aT_;^Tb?aTZ8_R]>h6]L]A]K]?]Q`Q]H^P^?]K]?l4]4](] R^U^W]@]O]0^7g;_S];bT^@`L]8_7]L]>]E]E^W]V]@pA]S]S]"
3132 "=_T_<oDo?]K^;]U]5_6].\\D]E]R]R]E]H]D]P]P]G]E]A\\+[U]U\\,\\6]6\\L\\;[U]U\\ S_W[V\\9]3^V`V^=^U^9]/a :[T]G[M\\O\\1ZQZ M[S\\P\\S[ Ud)]8](\\ @]L]@fU\\ M\\3\\N\\9ZQZ0\\L\\="
3133 "\\L\\8\\Q\\9]1]U]6]U]6]U]6]U]6]U]6]U]5]S]>].].].].].].].].]-]F]F]V]O]C]E]F]E]F]E]F]E]F]E]B_P_C]L]V^G]H]C]H]C]H]C]H]@^U^;]N^>]T]6]R_;]R_;]R_;]R_;]R_;]R_;]R"
3134 "_X_T^K_R\\:_S^;_S^;_S^;_S^=].].].]*h=bT^;_T_;_T_;_T_;_T_;_T_1^9_T`>]L]?]L]?]L]?]L]A]K]>aT_?]K] P]Q]R]E]F]E]V\\Q\\W]E]K\\W]E]F]A]4^L] A^@ZN\\ =i8e@yCk?^R^"
3135 "=]L]9b8]O^?] Im B]1]T]5uI]T[6]S^T]<^3]-]*]3^X\\X^,] V^3]J]7](^/]9]T];e7]We/]9]N]?]K^?].] Wd Nd._8]O`U\\T\\K]S]<]L^A]-]F^F].]/]-]H]C].].]V_7].]V]Q"
3136 "]V]H]V^P]D]C]G]L]@]C]G]L]?^']6]H]C^M^?]Q]U]Q]Ic6^W^._<]/^)]2^G^ !ZM^=`Q^=^NZ;^Q`>^P^=].^Q`?`Q^>].].]R_;].`R^X\\R^M`Q^=^P^>`Q^=^Q`?`1]MZ;].]L]A^M^?]Q`Q]"
3137 "G^R^>^M^1^4]4](] D]P^A]R^X]@]P^/]9^Vb=^NZ;`Q^AaN^8_7]L]>]E]F^V]U]>]P]>]S]S]>^P^>`T`7]6]J]<]S]5^6]/]C]G]Q]Q]F]H]D]P]P]H]C]C^&]TZ,^7]7^N^6]TZ H]/^U[TZ9"
3138 "]2n;]U]8]0d <[U]F[M\\P]2[R[ M[S\\P\\S[ Tb(]9]'\\ @]L]@fU\\ M\\3]P]9[R[1\\M\\<\\M\\7\\R\\8]2]S]8]S]8]S]8]S]8]S]7]U]6]R]?]-].].].].].].].]-]F]F]V^P]D]C]H]C]H]C]H]"
3139 "C]H]C]B_R_C]L]T]G]H]C]H]C]H]C]H]?^W^:]M]>]U^6ZM^<ZM^<ZM^<ZM^<ZM^<ZM^<ZMbP]M^NZ;^P^=^P^=^P^=^P^>].].].]+i=`Q^=^P^=^P^=^P^=^P^=^P^2^:^P^>]L]?]L]?]L]?]L]"
3140 "A^M^>`Q^@^M^ P]Q]Q]F]E]F]W^S^W]F]L^W]F]E]B]3]M^ B^B^O[ =k8d?xClA^P^>]L]9]X]8^P]>\\ Hl A] 9uI]T[5]T]T]:^ =]*]5^V\\V^.] V]2]J]7](]/^:]S];h:]Xg0]"
3141 "9^P^?]K^?].]!e Je2_7\\PdW\\S\\L]S]<]M^@]-]E]F].]/]-]H]C].].]X_5].]V]Q]V]H]U^Q]D]C]G]L]@]C]G]M^?`)]6]H]B]M]>]Q]U]Q]Hb5c-^;].])] B]=_O]=].]O_>]N^>].]O_?_"
3142 "O]>].].]S_:]._P`P]M_O]=]N]>_O]=]O_?_1]-].]L]@]M]>]RbR]G^R^=]M]1^3]4](] FaSaD^Qa?]R_.]9]R`>]._O]>^N]8`7]L]>]E]G^U]U^?]P]>]S]S]>]N]>^P^7]6]J]<]S]4^7]/]"
3143 "C]G]Q]Q]F]H]D]P]P]H]C]D_&]&_8]8_N_7] B]/]T[3]1l:^W^8]1]W` >\\U\\E\\N\\P]3\\S\\ N\\S\\P\\S\\ S_']:]&\\ @]L]@fU\\ M\\2\\P\\8\\S\\2\\N]<\\N]7\\S]8]2]S]8]S]8]S]8]S]8]S]8]S]"
3144 "7]R]?]-].].].].].].].]-]E]G]U^Q]D]C]H]C]H]C]H]C]H]C]A_T_B]M]S]G]H]C]H]C]H]C]H]>c9]M^?]U]'].].].].].].`O^N].]N^>]N^>]N^>]N^?].].].],_R^>_O]=]N]=]N]=]N]"
3145 "=]N]=]N]2^:]O_?]L]?]L]?]L]?]L]@]M]=_O]?]M] O\\P]Q]F\\D]F\\U^U^V]F\\L^V]F\\D]B]3]M] RuJ`O[ >m9c>wCmA]N]>]L]9]X]7]P]?] Im A] 2\\R\\A]T[5^V^T\\:` ?](\\6]T"
3146 "\\T]/] V]2]J]7])^1_9]S];i;bS^2^8^S_>]K^?].]$e@u@e6_7]QfX\\S\\M^S^=]N^?]-]E]F].]/]-]H]C].].c4].]U]S]U]H]T]Q]D]C]G]M^@]C]G]M]=c-]6]H]B]M]>^R]U]R^G`4c.^:]"
3147 ".])] B]=^M]?^/]M^?]L]>]/]M^?^N^?].].]T_9].^O_O^N^N^?]M^?^M]?]M^?^0]-].]L]@]M]>^S]X]S^F^T^<^O^2_3]4](] GcUcE]Pa?]Vb-]:]O_?].^N^>]O^8a8]L]?]C]H]T]T]?"
3148 "]P]>]S]S]?]L]@^N^8]6]J]=^S^4^8]/]C]H^Q]Q^G]H]D]P]P]H]C]E_%]%_9]9_L_8] B]0^T[3]0_T_>cWc=]1]U_ ?[U\\C[N]R^4]T] N[R\\Q]R[ 'uG]&] @]L]?eU\\ M\\2]R]8]T]3\\N\\;"
3149 "\\N\\7]S\\7]3^S^:^S^:^S^:^S^:^S^9]S]8^R]?]-].].].].].].].]-]E]G]T]Q]D]C]H]C]H]C]H]C]H]C]@_V_A]N]R]G]H]C]H]C]H]C]H]>c9]L]?]U]'].].].].].]._M]O^/]L]?]L]?]L"
3150 "]?]L]?].].].]-^O]>^N^?]M^?]M^?]M^?]M^?]M^ I]O`?]L]?]L]?]L]?]L]@^O^=^M]@^O^ P]P]P\\G]C\\G]T^W^T\\G]M^T\\G]C\\B]3^O^ RuJ[X]P[ >o=\\XaX]BwDoC]L\\>]L]:^X^8]P]?"
3151 "] E] 5] 3]S]A^U[4dT];b @](]6ZR\\RZ.] V]2]J]7]*^7d8]R];]R_<aQ^3]5f<^M_?].]'e=u=e:_6\\Q^S`S]N]Q]=l>]-]E]Fm>k=]-rC].].b3].]U]S]U]H]T^R]D]C]G]M]?]C]"
3152 "G]N^<f1]6]H]B^O^=]S^U^S]F_2a.^9].])] A]>^M]?].]M^?]L]>]/]M^?^M]?].].]U_8].^N^N]N^M]?]L]?^M]?]M^?^0]-].]L]@^O^=]S]X]S]D^V^:]O]2_2]4](] H\\U^W]U\\E]Pa?"
3153 "]Vb-];]M^?].^M]>^P]7a8]L]?]C]H]T]T]?]P]>]S]S]?]L]@]L]8]6p=]Q]3^9]/]C]H]P]P]G]H]C]Q]Q]G]ViV]F_$]$_:]:_J_9] B]0]S[3]0]P]>o=]2]S_ @[U\\C[M]T_5^U^;u O[R\\R]"
3154 "Q[ 'uH]/ZQ] ?]L]?eU\\ M\\1]T]7^U^4\\O]O]I\\O]T`MZQ]S]O]E]3]Q]:]Q]:]Q]:]Q]:]Q]:^S^9]QmO]-m>m>m>m>].].].]1hL]G]T^R]D]C]H]C]H]C]H]C]H]C]?_X_@]O]Q]G]H]C]H]C]"
3155 "H]C]H]=a8]L]?]U]&].].].].].].^M]O].]L]?]L]?]L]?]L]?].].].].^M]?^M]?]L]?]L]?]L]?]L]?]L] I]Pa?]L]?]L]?]L]?]L]?]O]<^M]?]O] O]P]P\\G]C\\G]ScS\\G]N^S\\G]P]P\\B"
3156 "]2]O] QuF]Q[ >oAqDuDqD]L]?]L]:^X^8^R^?\\ D] 5] 3]S]@`X[3bS\\R^G]W^N] P](].\\&] W]1]J]7]*^7c8]Q];ZM^=`O^4]4d:]M_?].])d:u:d=_5\\R]O^R\\N]Q]=j<]-]E]F"
3157 "m>k=]-rC].].a2].]U^U^U]H]S]R]D]C]G]N^?]C]G]P_:g3]6]H]A]O]<]S]S]S]E^1_.^8]-]*] A]>^M]?]/^M^?]K]?]0^M^?]L]?].].]V_7].]M]M]N]L]@^L]?^M]@^M^?]/]-].]L]?]"
3158 "O]<]S]X]S]C^X^9]O]2^1]4](]0_IZ O[R\\X]S\\G^O_>]Vd9_U];]L]?].]L]=]P]8]X^9]L]?]C]I^T]S]@]P]>]S]S]?]L]@]L^9]6p=]Q]3^9]/]C]H]P]P]G]H]C]Q]Q]G]ViV]G_#]#_;];_H"
3159 "_:] B]0]S[3]0\\N\\>o=]2]Q^ A[U\\C[LcX\\6]T]9u O[RfP[ 'uIf7e >]L]>dU\\<] :f5d4]T]:fT\\O^NfT\\UdOeR\\O^F^3]Q]:]Q]:]Q]:]Q]:]Q]:]Q]:^QmO]-m>m>m>m>].].].]1hL]G]S]R"
3160 "]D]C]H]C]H]C]H]C]H]C]>d?]P^Q]G]H]C]H]C]H]C]H]<_7]L]?]U^'].].].].].].^L]P].]K]@]K]@]K]@]K]@].].].].]L]?]L]@^L]@^L]@^L]@^L]@^L] I]Q]X^@]L]?]L]?]L]?]L]?]"
3161 "O]<^M]?]O] O\\WmX]H\\WmX]H\\QaR]H\\N^R]H\\O]P]C]2]O] QuF]R\\ ?qCsDtDrE]L]?]L]:]V]7]R]>x '] 5] 3\\R\\?e3^R\\SbJ^V^O] P](].\\&] W]1]J]7]+^6e:]Q]-^>_M]5^6"
3162 "h<^O` Qe8u8e@^5]R\\M]R\\O^Q^>m?]-]E]Fm>k=]KdFrC].].b3].]T]U]T]H]S^S]D]C]G]P_>]C]Gk6f5]6]H]A^Q^<]S]S]S]F_1_/_8]-]*] A]>]K]A].]K]@]J]?]0]K]?]L]?].].]W_"
3163 "6].]M]M]N]L]@]J]@]K]A]K]?]/^.].]L]?]O]<]T^W]T]C^X^9^Q^3^1]3]']3dN\\ P\\R`Q[G]N_>]Q`;bW];\\K^?]/]L]=]Q^8]W]9]L]?]C]I]S]S]@]P]>]S]S]@]J]B^L^9]6p>^Q^4^9]/]C"
3164 "]H]P]P]G]H]C]Q]Q]G]ViV]H_\"]\"_<]<_F_;] B]1]R[3]1]N]8a6]2]P^ B[U\\C[K`V\\7]T]8u O[RdN[ 'uIf5a <]L]=cU\\<] :f3`1]T];fU\\N^NfU\\T[S]NaQ\\N^G^3^Q^<^Q^<^Q^<^Q^<^Q"
3165 "^;]Q]:]PmO]-m>m>m>m>].].].]1hL]G]S^S]D]C]H]C]H]C]H]C]H]C]=b>]P]P]G]H]C]H]C]H]C]H]<_7]L]?]U_(].].].].].].]K]Q].]J]A]J]A]J]A]J]@].].].].]L]?]L]@]J]A]J]A"
3166 "]J]A]J]A]J] K]P\\V]@]L]?]L]?]L]?]L]?^Q^<]K]@^Q^ O\\WmX]H\\WmX]H\\P_Q]H\\O^Q]H\\O]P]C]2^Q^ D^<]R[ >qDuEsCqD]L]?]L]:]V]7]R]>x '] 5] 3\\R\\=f+]TdL^T^P] P]"
3167 "(].\\2u *]1]J]7],^-_=]P],]>_M]5]7_R^<^Qa Sd .dC^4\\R]M]R\\O]O]>]N_@]-]E]F].]/]KdF]H]C].].]X^4].]T]U]T]H]R]S]D]C]Gk=]C]Gj1c6]6]H]@]Q];^T]S]T^Ga1].^7]-]*"
3168 "] Lh>]K]A].]K]@]J]?]0]K]?]L]?].].]X_5].]M]M]N]L]@]J]@]K]A]K]?]._0].]L]>]Q];^U]V]U^Bb7]Q]3^1^3]'^6iS^ P[P^P[G]N_>]N^=dX]<]J]>^1]L]=^R]8^W]9]L]@]A]J]S"
3169 "]S]@]P]>]S]S]@]J]B]J]9]6]J]>]O]5^8]/]C]H]P]P]G]H]B]R]R]F]C]Iz<]<z=]=z<] B]1]R[7j:\\L\\7_5]2]P^ B[U\\C[ V]T]7u O[R\\U^O[ T] ]L];aU\\<] I]T],]O[X\\>]K]@]"
3170 "O[X\\I`3]O]<]O]<]O]<]O]<]O]<]O];]P]?]-].].].].].].].]-]E]G]R]S]D]C]H]C]H]C]H]C]H]C]<`=]Q]O]G]H]C]H]C]H]C]H];]6]L]?]T_4h9h9h9h9h9h9hK]Q].]J]A]J]A]J]A]J]"
3171 "@].].].]/]J]@]L]@]J]A]J]A]J]A]J]A]J]?tG]Q\\U]@]L]?]L]?]L]?]L]>]Q];]K]?]Q] N\\WmX]H\\WmX]H\\P_Q]H\\P^P]H\\O]P]C]1]Q] C]:]S[ ?sEvEqAoC]L]?]L];^V^8^T^>x "
3172 " '] 5] 4]S]<g-\\T^V^M]S_Q\\ O](].\\2u Se =^1]J]7]-^*^?]O],^?^K]7^7]N]<^Sb Sa (aC]3\\R\\K\\R\\P^O^?]L^A]-]E]F].]/]KdF]H]C].].]W^5].]T^W^T]H]R^T]D]C]Gj<]C]Gj-"
3173 "`7]6]H]@]Q]:]U^S^U]Fb2]/^6]-^+] Nj>]K]A].]K]@p?]0]K]?]L]?].].b3].]M]M]N]L]@]J]@]K]A]K]?].c4].]L]>]Q]:]U]V]U]@`6^S^4^5b2]&b<u P[O]P\\H]N^=]M]>^Ua<]J]="
3174 "c7]L]<]S^8]V^:]L]@]A]J]S]S]@]P]>]S]S]@]J]B]J]9]6]J]?^O^7^7]/]C]H]P]P]G]H]B]R]R]F]C]Iz<]<z=]=z<] B]1]R[7j:\\L\\7_ C^P] B[U\\C[ W]T] W] O[R\\T^P[ T] ]L]7"
3175 "]U\\<] H]T]-\\O\\X\\>\\I\\@\\O\\X\\J`3^O^>^O^>^O^>^O^>^O^=]O]<^P]?]-].].].].].].].]-]E]G]R^T]D]C]H]C]H]C]H]C]H]C];^<]R]N]G]H]C]H]C]H]C]H];]6]L]?]S`8j;j;j;j;j"
3176 ";j;|Q].pApApAp@].].].]/]J]@]L]@]J]A]J]A]J]A]J]A]J]?tG]R]U]@]L]?]L]?]L]?]L]>^S^;]K]?^S^ N\\WmX]H\\WmX]H\\QaR]H\\Q^O]H\\O]P]C]1^S^ D]9]T\\ ?sFwDo?nC]L]?]L];"
3177 "]T]7]T]=] Hj ?] 4]S]8d/]T]T]N^R_R\\ O](] =u Se =]0]J]7].^(]?]O]+]?^K]7]7]L]<gX] Sa (aC]3\\R\\K\\R\\P]M]?]K]A]-]E]F].]/]D]F]H]C].].]V^6].]S]W]S]H]Q]T"
3178 "]D]C]Gg9]C]G]Q_,^7]6]H]@^S^:]U]Q]U]G^X]2]0^5],]+] Pl>]K]A].]K]@p?]0]K]?]L]?].].a2].]M]M]N]L]@]J]@]K]A]K]?]-f8].]L]>^S^:]U]V]U]?^4]S]4^4`0]$`<^Si O[O"
3179 "\\O\\H]N^=]M^@^S`<]J]=c7]L]<]S]8^U]:]L]@]O]O]J]S]S]@]P]>]S]S]@]J]B]J]9]6]J]?]M]7]6]/^E^H]P]P]G]H]A]S]S]E]C]Iz<]<z=]=z<] B]1]R[7j:\\L\\6] A^Q] B[U\\C[Ni:]T]"
3180 " V] O[R\\S]P[ T] ]L]6\\U\\<] Dh2]T]/]P\\W\\?]I\\A]P\\W\\K`2]M]>]M]>]M]>]M]>]M]>^O^=]O]?]-].].].].].].].]-]E]G]Q]T]D]C]H]C]H]C]H]C]H]C]<`=]S]M]G]H]C]H]C]H]"
3181 "C]H];]6]M^?]R`;l=l=l=l=l=l=~Q].pApApAp@].].].]/]J]@]L]@]J]A]J]A]J]A]J]A]J]?tG]S]T]@]L]?]L]?]L]?]L]=]S]:]K]>]S] M]P]P\\G]C\\G]ScS\\G]S^N\\G]P]P\\B]0]S] D]"
3182 "7\\T[ >sFwCn?mB]L]?]L];]T]7]T]=] Hi >] 4]S]7[Xa1]T^T^O]P_T] O](] =u Se =]0]J]7]/^'^A]N]+]?^K]7]8^L^<eW] Sd .dC]3\\R\\K\\R\\P]M]?]K]A]-]E]F].]/]D]F]H"
3183 "]C].].]U^7].]ScS]H]Q^U]D]C]G]/]C]G]O^,^8]6]H]?]S]9]U]Q]U]H^W^3]1^4],]+] Q`P]>]K]A].]K]@p?]0]K]?]L]?].].b3].]M]M]N]L]@]J]@]K]A]K]?]+e9].]L]=]S]9]V]T]"
3184 "V]@_4]S]5_4b2]&b<\\Nd M[O]P\\H]N^=]L]@]Q_<]J]?e7]L];]T]8]T]:]L]@]O]O]J]S]S]@]P]>]S]S]@]J]B]J]9]6]J]?]M]8^6].]E]G]P]Q^G]H]A^T]T^E]C]Iz<]<z=]=z<] B]1]R[3]"
3185 "1\\L\\6] A_R] B\\U\\E\\Ni:]T] V] O\\S\\R]R\\ T] ]L]6\\U\\<] Dh2]T]/\\O[V\\?\\H\\A\\O[V\\L`1]M]>]M]>]M]>]M]>]M]>]M]>^O]?]-].].].].].].].]-]E]G]Q^U]D]C]H]C]H]C]H]C]"
3186 "H]C]=b>]T]L]G]H]C]H]C]H]C]H];]6]M]>]Qa>`P]>`P]>`P]>`P]>`P]>`P]>`PoQ].pApApAp@].].].]/]J]@]L]@]J]A]J]A]J]A]J]A]J]?tG]T]S]@]L]?]L]?]L]?]L]=]S]:]K]>]S] "
3187 "L\\P]P\\F\\C\\F\\T^W^T\\F\\T^M\\F\\C\\B]0]S] E^7]U[ >sFwBl=kA]L]?]L]<^T^8^V^=] Ij >] <u=[U^1\\S]R]O]O_U\\ N](] 1] Ge =]0]J]7]0_&]A]N]+]?^K]8^8]J]:aU\\ Pe 4"
3188 "eA]3\\R\\K\\R\\Qo@]J]A].]F^F].].]E]F]H]C].].]T^8].]RaR]H]P]U]C]E]F].]E]F]N^,]8]6]H]?]S]9^V]Q]V^H^V^4]2_4],]+] Q]M]>]K]A].]K]@],]0]K]?]L]?].].c4].]M]M]N]"
3189 "L]@]J]@]K]A]K]?](d;].]L]=]S]9^W]T]W^@`5^U^5^/_3]'_8ZJ` K[O]P\\H]N^=]L]@]P];]J]@_0]L];]U^9^T^;]L]@]O]O]J]S]S]@]P]>]S]S]@]J]B]J]9]6]J]@^M^:^5].]E]F]Q]Q]F"
3190 "]H]@^U]U^C]E]G_\"]\"_BZT]TZB_F_;] B]1]R[3]1\\L\\?o I_S] A[U]F[ V]T] W] N[S\\R]R[ S] ]L]6\\U\\ ']T]/\\O\\V\\@\\H\\A\\O\\V\\M_0o@o@o@o@o?m>l>].].].].].].].].]-]F^"
3191 "G]P]U]C]E]F]E]F]E]F]E]F]E]=d?^V]L]F]H]C]H]C]H]C]H];]6]N^>]O`?]M]>]M]>]M]>]M]>]M]>]M]>]M]?].].].].]-].].].]/]J]@]L]@]J]A]J]A]J]A]J]A]J] K]U]R]@]L]?]L]?"
3192 "]L]?]L]=^U^:]K]>^U^ L\\P]Q]F\\D]F\\U^U^V]F\\U^M]F\\D]B\\/^U^ OuD]V[ =sFwBk;i@]L]?]L]<]R]7]V];] F^ Nu=[T^3]S]R]O]N_V\\ N](] 1] ].]L]6]1_%]Aq0]>]K]"
3193 "8]7]J]/] Md:u:d>]3\\R\\K\\S\\Po@]J]A].]F]E].].]E]F]H]C].].]S^9].]RaR]H]P^V]C]E]F].]E]F]M],]8]6]H]>]U^8]W^Q^W]H^U^4]2^3]+],] R^M]>]K]A].]K]@],]0]K]?]L]?"
3194 "].].]X_5].]M]M]N]L]@]J]@]K]A]K]?]$`;].]L]=^U^8]W]T]W]@b5]U]5^,]3]'] J\\Q_Q[G]N^=]L]A]O];]J]@].]L];]U]8]R];]L]@]O]O]J]S]S]@]P]>]S]S]@]J]B]J]9]5]L]?]K];"
3195 "^4].^G^F]Q]Q]F]H]?_W]W_B]E]F_#]#_B\\U]U\\B_H_A\\U]U[ H]1]R[3]1]N]?o H`V] @[T]G[ U]T] X] N[S\\Q]S[ S] ]L]6\\U\\ (]T]/]P\\U\\A]I]B]P\\U\\M^/o@o@o@o@o@o@m>].]"
3196 ".].].].].].].]-]F]F]P^V]C]E]F]E]F]E]F]E]F]E]>_X_?]W^L]F]H]C]H]C]H]C]H];]6]P_=]M^@^M]?^M]?^M]?^M]?^M]?^M]?^M]?].].].].]-].].].]/]J]@]L]@]J]A]J]A]J]A]J]"
3197 "A]J] K]U\\Q]@]L]?]L]?]L]?]L]<]U]9]K]=]U] K]Q]Q]F]E]F]W^S^W]F]W^L]F]E]B\\.]U] NuC\\V[ =eXZXdFgXhAi9h@]L]?]L]<]R]7]V];] E] Nu=[S]3\\R]R]O]M_X\\ M]("
3198 "] 1] ].]L]6]2_$]Aq0]>]K]8]7]J]/] Ke=u=e<]3\\R\\K\\S\\Po@]J]A].]F]E].].]E]F]H]C].].]R^:].]RaR]H]O^W]C]E]F].]E]F]M^-]8]6]H]>]U]7]W]O]W]I^S^5]3^2]+],] R"
3199 "]L]>]K]A].]K]@],]0]K]?]L]?].].]W_6].]M]M]N]L]@]J]@]K]A]K]?]\"_<].]L]<]U]7]W]T]W]Ac5^W^6^+^4](] H[R\\X]S\\G]N^=]L]A]O];]J]A^.]L]:]W^9^R];]L]@]O]O]J]S]S]@"
3200 "]P]>]S]S]@]J]B]J]9]5]L]?]K];^4]-]G]D]R]R]E]H]>kA]E]E_$]$_B^V]V^B_J_A^V]V] I]1]R[3]0\\N\\>o G`X] ?\\U_Q[T\\ T]T] ] N\\T\\Q]T\\ S] ]L]6\\U\\ )]T].\\P\\T\\A\\I]A"
3201 "\\P\\T\\N^.o@o@o@o@o@o@m>].].].].].].].].]-]F]F]O^W]C]E]F]E]F]E]F]E]F]E]?_V_@]W]K]F]H]C]H]C]H]C]H];]6k<]L^A]L]?]L]?]L]?]L]?]L]?]L]?]L]?].].].].]-].].].]/"
3202 "]J]@]L]@]J]A]J]A]J]A]J]A]J] K]V\\P]@]L]?]L]?]L]?]L]<^W^9]K]=^W^ J]R]R]D]G]D]W\\Q\\W]D]W\\L]D]G]A\\.^V] NuC]W[ <cWZXdEfXh@g8g?]L]?]L]=^R^8^X^:] F] "
3203 " G\\R\\5[S]4]R]R]O]Lb M](\\ 0] ].]L]6]3_#]Aq0]>]K]9]6]J]/] He@u@e H\\R]M]T]Q^J]A]J]@]/]G^E].]-]F]F]H]C].].]Q^;].]Q_Q]H]N]W]B]G]E]-]G^F]L]-]8]6]I^>^W^7]"
3204 "W]O]W]I^R^6]4^1]+],] R]M^>^M^@]/^M^?]-]0^M^?]L]?].].]V_7].]M]M]N]L]@^L]?^M^A^M^?] ]<].]L]<]U]7]X]R]X]B^W^5]W]6^)]4](] H\\T]W]U\\F]O_=]L]A]P^;^L^A]-]L"
3205 "]:]W]8]P]<]L]@]O]O]J^T]T]?]P]>]S]S]@^L]A^L]8]5]L]@^J]=^3]-^I^D^S]S^E]H]<g>]G]C_%]%_A_W]W_A_L_@_W]W_ J]0]S[3]0]P]5]4],b =[ThT[ R]T]!] M[T\\P]U[ R] ]L"
3206 "]6\\U\\ *]T].]P[S\\B]J]A]P[S\\N].^J]B^J]B^J]B^J]B^J]B^K^A]M]=]/].].].].].].].]-]G^F]N]W]B]G]D]G]D]G]D]G]D]G]?_T_AbK]E]I^C]I^C]I^C]I^;]6j;]K]A]M^?]M^?]M^"
3207 "?]M^?]M^?]M^?]M_?].].].].].].].].]/]J]@]L]@^L]@^L]@^L]@^L]@^L] J^X]Q]?]L]?]L]?]L]?]L];]W]8^M^<]W] I]R]S]C]H]C]VZOZW]C]VZL]C]H]@\\-]W] MuC]X[ ;cWZWbDe"
3208 "WZXe>e6e>]L]?]L]=]P]8^X^:] F^ H\\R\\5[S]5]Q]R]O^L` K]*] 0] !^.]L]6]4_\"]2],^>^M]8]6]J]0] DeCuCe E]R\\M]T\\P]I]A]J]@]/]G]D].]-]F]F]H]C].].]P^<].]Q"
3209 "_Q]H]N^X]B]G]E]-]G]E]L^.]8]5]J]<]W]6^X]O]X^J^Q^6]5^0]+^-] R]M^>^M]?].]M^?]-]/]M^?]L]?].].]U_8].]M]M]N]L]?]L]?^M]?]M^?] ]<].]M^<^W^6aRbB^V^6]W]7^(]4]"
3210 "(] GcUcE]P_=]L]A]P]9]L]@]-]L]:^X]9^P]<]M^@]P^O]I]T]T]?]P]>]S]S]@^L]@]L]8]5]M]?]I]>^2],]I]B_U]U_D]H]:c<]G]B_&]&_?_X]X_?_N_>_X]X_ I]0]S[3]0_T_5]4]+` ;["
3211 "SfU[ P^U^#] L[U\\P]V[ Q] ]M^6\\U\\ ,^U^-\\P\\S\\B\\J]@\\P\\S\\N].]I]B]I]B]I]B]I]B]I]B]I]B^M]=]/].].].].].].].]-]G]E]N^X]B]G]D]G]D]G]D]G]D]G]@_R_A`J]D]J]A]J"
3212 "]A]J]A]J]:]6g8]K]A]M^?]M^?]M^?]M^?]M^?]M^?]M_?].].].].].].].].].]L]?]L]?]L]?]L]?]L]?]L]?]L]3^;aP]?]M^?]M^?]M^?]M^;]W]8^M];]W] H]S]T^B]J^B]J^B]J^B]J^@"
3213 "\\-]W] G^1_ :aW[V`BcW[Wc<d5c=]L]>]N]<]P]7]X]8] F]KZ X]S]5[S]5\\P]R]N]K_ K]*] 0] !],]N]5]5_\"]1],]<]M]9^6^L^0] Ad Nd A\\R]O^U\\P^I^B]K^?]H[C]H^D]"
3214 ".],]G]F]H]C].].]O^=].]P^Q]H]M]X]A]I]D],]I^E]K]AZH^8]5]J]<]W]5bObJ^O^7]6_0]*]-] R]M^>^M]?^/]M^?^.]/]M^?]L]?].].]T_9].]M]M]N]L]?]L]?^M]?]M^?] ]<].]M^;"
3215 "]W]5aRaB^U^6c8_(]4](] FaSaD]P_=]M]@]P]9]L]@]-]L]9b9]O^=^N^?\\P_Q]H]T]T]?]P]=]T]T]?^L]@]L]8]4]N]@^I^?]1],^K^A`W]W`C]H]7]8]I]@^&]&^=i=^N^<i H]0^T[3]1l6]"
3216 "4])_ <\\RbT\\ O]T]#] L\\V\\O]X\\ M^N^6\\U\\ ,]T]-\\OhF\\J]@\\OhQ]/^I^D^I^D^I^D^I^D^I^C]I]B]L]<]H[C].].].].].].].]-]H]D]M]X]A]I]B]I]B]I]B]I]B]I]@_P_B_J]C]J"
3217 "]A]J]A]J]A]J]:]6].]K]A]M^?]M^?]M^?]M^?]M^?]M^?]M_?^/^/^/^/^/].].].].]L]?]L]?]L]?]L]?]L]?]L]?]L]3^;`O]?]M^?]M^?]M^?]M^;c8^M];c G^U]U^@^M^@^M^@^M^@^M^?"
3218 "\\-c H^0_ 9^U[U^@aV[Va:b3a<]L]>^P^=^P]7]X]8_ H^M[ F] 6]S]>ZQ[T^6]P]S^N^K^ K]*] 0]:] 8]0],]O^5]6_2ZI]1]-^<^O^9]4]L]0]<].] Uc Pc1]2\\Q^S`W^P]G]B]K]"
3219 ">^J\\C]I^C].],^H]F]H]C].].]N^>].]C]H]MbA^K^D],^K^D]K^B[I]7]5^L^<c5aMaJ^N]7]6^/]*]-] R^O_>_O]=].]O_>].].]O_?]L]?].].]S_:].]M]M]N]L]>]N]>_O]=]O_?] ]<]-"
3220 "]O_;]X^5aRaC^S^6a8_']4](] D]P^B^Ra>^N]@]Q]7]N]?^.]L]9a8]N]=^N^?]Q_Q]G]U]U]>]P]=]T]T]?_N]>]N]7]4^P^@]G]@^1]+^M^?mB]H]7]8^K^?\\%]%\\;g;\\L\\:g G]/]T[3]2n7]"
3221 "4]'^ <\\F\\ M\\S\\ J\\F\\ L^N^6\\U\\ ,\\S\\-]OhG]K]@]OhQ]LZ=]G]D]G]D]G]D]G]D]G]D]G]D^L]<^J\\C].].].].].].].]-]J_D]MbA^K^B^K^B^K^B^K^B^K^A_N_B^K]B^L^A^L^A^"
3222 "L^A^L^:]6].]K]A^O_?^O_?^O_?^O_?^O_?^O_?^Oa?].].].].]/].].].]-]N]>]L]>]N]=]N]=]N]=]N]=]N]2^;_O]=]O_>]O_>]O_>]O_:a7_O]9a E^P_>^P_>^P_>^P_>^P_>\\,a H^.]"
3223 " /[5]T[S\\8a1`<]L]=^R^<]O^8b7_ H^O\\ F] 6\\R\\=[R[U^5\\N]T]L^M` L]*] 0]:] 8]1^+]P]4]7_1[L_1]<ZL^:^Q^8]4^N^>ZM];].] R` P`.]2]QfXaN]G]B]L^=^L]C]K_B].]+"
3224 "_J]F]H]C].].]M^?].]C]H]La@^M^C]+^M^C]J]B]L^7]4^N^:a4aMaK^M^8]7^.]*^.] Q]P`>`Q^=^NZ;^Q`>_LZ>].^Q`?]L]?].].]Q^;].]M]M]N]L]>^P^>`Q^=^Q`?]/ZL];]-^Q`:a4`"
3225 "P`D^Q^7a8^&]4](] S]Sb>_P^@]R^7^P^>^MZ<]L]9a9]M]=_P`XZB]Q_Q]G^V]V^>]P]=^U]U^?`P^>^P^6]4]Q^?]G]A^0]*^O^<i@]H]7]7^M^=Z$]%Z8e9ZKZ7e F]/^U[TZ9]3^V`V^8]4]"
3226 "&^ <\\H\\ K[R[ I\\H\\ K_P`XZ9\\U\\ ,[R[,\\E\\D\\K]?\\E\\M]O\\=]G]D]G]D]G]D]G]D]G]D]G]D]K];^L]C].].].].].].].]-]K_C]La@^M^@^M^@^M^@^M^@^M^A_L_C`N^A^N^?^N^?^"
3227 "N^?^N^9]6].]L]?]P`>]P`>]P`>]P`>]P`>]P`>]P]X^LZN^NZ;_LZ>_LZ>_LZ>_LZ?].].].]-^P^>]L]>^P^=^P^=^P^=^P^=^P^2^:^P^=^Q`>^Q`>^Q`>^Q`:a7`Q^9a Dk<k<k<k<k>],a "
3228 "H]-] /[,[._0_;]L]=j<]N]7`5a J_S^ F] 6\\R\\=^U[W_5]N^V^K_Rd L],] /]:] 8]1])^T^3]8_0^Q`0]<]Q_8^S^8^3_R_=]R^:].] O] P]+]1\\PdW`N^G^C]N_;`R`C]NaA].]*`O"
3229 "`F]H]C].].]L^@].]C]H]La?`S`B]*`S`B]J]B`Q_6]3_R_9a4aMaL^K^9]8^-])].] Q_Tb>aS^;_R\\:^Sa=`Q]>]-^Sa?]L]?].].]P^<].]M]M]N]L]=_T_=aS^;^Sa?]/^R_:]-^Sa:a3_P_"
3230 "C^P^7_8^%]4](] S_V^X^?aS^>]T^5_T_=`R]<]L]8_8]M^>`SdA]SaS]E^W]W^=]P^=_W]W_>]X]T_<_T_5^4^T^?^G^C^/])^Q^8c=]H]7]6`S` ?] ;c >c E]._W[V\\9]4^J^9]4]%] ;]L]"
3231 " IZQZ H]L] !u ,`Sd9\\U\\ ,ZQZ,]E\\E]L]?]E\\M_S^>^G^F^G^F^G^F^G^F^G^F^G^F^K]:`R`C].].].].].].].]-]ObB]La?`S`>`S`>`S`>`S`>`S`?]J]CcS`?_R_=_R_=_R_=_R_8]6"
3232 "].]V[R^?_Tb>_Tb>_Tb>_Tb>_Tb>_Tb>_T^V_Q]M_R\\:`Q]=`Q]=`Q]=`Q]?].].].],_T_=]L]=_T_;_T_;_T_;_T_;_T_1^:`T_;^Sa=^Sa=^Sa=^Sa9_6aS^7_ Bi:i:i:i:i=]+` I],] /["
3233 ",[-].]:]L]<h;]N]7`3q \"h E] 7]S]=k5]LdIjW^ M],] /]:] 8]1](f9k?n?l/]<j6g7]1j<h9].] LZ PZ(]1]O`U]K]E]Cm8kBn?n?](nE]H]C].].]K^Am>]C]H]K`>kA])kA]J^Cm5"
3234 "]2j7_2`M`K^J]9]8tC])].] PgX]>]Xf9h9fX]<k>],fX]?]L]?].].]O^=].]M]M]N]L]<h<]Xf9fX]?]/j9d4gX]:a3_P_D^O^7_8m4]4](] RfXaBk=^V^3h;j<]L]8_9^L]>qA^U]W]U^D"
3235 "i<]O`?k=]Xg:h3a7f>uCn?]/eSe;]:]H]7]5k >] :a <a D]-h>n?\\H\\8]4]%] 9^R^ *^R^ Xu ,q9\\U\\ /]D\\F]LfH]D\\Li>]E]F]E]F]E]F]E]F]E]F]E]F]JnIkBn?n?n?n?].].]."
3236 "]-n@]K`>k<k<k<k<k=[H[Co<j;j;j;j7]6].]Vf=gX]=gX]=gX]=gX]=gX]=gX]=gTjLh9k<k<k<k?].].].]+h<]L]<h9h9h9h9h Fk:gX]=gX]=gX]=gX]9_6]Xf6_ @e6e6e6e6e;]+_ G\\+["
3237 " /].]-[,[9]L];e:^N^8`2p e D] 7]S]<i4\\JbGgT^ M\\,\\ .]:] 8]1]'d8k?n>i-]<i4e6]0h;g8].] I]0]3]E]Cl6h@l=n?]&jC]H]C].].]J^Bm>]C]H]K`<g?]'g?]I]Bj3]1h6"
3238 "_2_K_L^I^:]8tC])].] OdV]>]Wd6f8dW]:i>]+dW]?]L]?].].]N^>].]M]M]N]L];f;]Wd7dW]?]/i7c3dV]9_2_P_E^M^8_8m4]4](] QdV`B]Xe;d1f8h<]L]8_9]K]>]XdW_@eWeBg;]O"
3239 "`=g;]Vd8f1`6d=uCn?]/eSe;]:]H]7]3g <] 9_ :_ C]+f>n>ZFZ7]4]%] 7f &f Vu ,]XdW_9\\U\\ /\\C\\F\\KfH\\C\\Kg=]E]F]E]F]E]F]E]F]E]F]E]F]JnHh@n?n?n?n?].].].]-l>"
3240 "]K`<g8g8g8g8g J]Vh:h9h9h9h6]6].]Ve;dV]<dV]<dV]<dV]<dV]<dV]<eRiJf7i:i:i:i?].].].]*f;]L];f7f7f7f7f F]Xe7dV]<dV]<dV]<dV]9_6]Wd5_ <\\-\\-\\-\\-\\6]+_ FZ*[ /]"
3241 ".],Z+Z9]L]8`8]L]7^.m W` A] 7\\R\\7b2]H^BaP_ O].] .]:\\ 7]2^%`6k?n:b*]9c/a5],b6b5].\\ H]/\\4]C]Di0b=h9n?]#c?]H]C].].]I_Dm>]C]H]J_9a<]$d?]I^?c0].b3_2"
3242 "_K_M^G^;]8tC](]/] M`T]>]U`2b4`U]7c;])`U]?]L]?].].]M^?].]M]M]N]L]8`8]U`3`U]?],c2a0_T]9_2^N^F^K^8]7m4]4](] O`R^B]Va8b-`3d:]L]7]9^J]?]V`T]>cUc?c9]N_:"
3243 "a8]T`3`-_4`<wDn?]/eSe;]:]H]7]0a 9] 8] 8] B])b<n @]4]&^ 5b \"b Tu ,]V`T]8\\U\\ 0].].]0b;]C]H]C]H]C]H]C]H]C]H^E^H^JnEb=n?n?n?n?].].].]-h:]J_9a2a2a2a"
3244 "2a G\\Rb4b3b3b3b3]6].]Vc7`T]:`T]:`T]:`T]:`T]:`T]:aMcEb2c4c4c4c<].].].]'`8]L]8`1`1`1`1` D]Ua2_T]9_T]9_T]9_T]8]5]U`2] =] &[ "
3245 "O].] E] E] '] S] R] ^ (](]/] C] S] '] V] F^ 7]4](] %])[ 4]7] @])_Q_:] 9]6] 6[ S]0[R"
3246 "^ H]%\\U\\ A\\ @\\ /Z <\\ ,[ M^5](^ =] &[ N]0] D\\ D] '\\ "
3247 " Q^DZ 1] _ )](]/] D^ S] '] V] F] 6]4](] %] ;]7] @] /] 9]6] 6[ S]0g H]%\\U\\ @\\ "
3248 " @\\ J\\ X]4](] <] &[ N]0] D\\ E^ '\\ P^G] 2] X^ )]"
3249 "(^0] D] R] '] V] G^ 6]4](] %] ;]7] @] /] 9]6] 6[ S]0e F]%\\U\\ ?[ ?[ "
3250 "I[ ^4])^ @ZV] &[ M]2] D] E] '] O_K_ 3] V^ *b,]5b E^ R] '] V] "
3251 " G^ 6^5])^ %] ;]7] @] /] 9]6] 6[ S].a D]%\\U\\ ?\\ @\\ J\\ !^4])^ "
3252 " B\\V] &[ M]2] D\\ G\\ L`P` 2] U^ +b =b RZN^ R^ '] V] H^ 4^6]*^ $] ;]7] @] /]"
3253 " 9]6] 6[ S] J] :\\ @\\ J\\ \"^3]*^ A\\V\\ %[ L"
3254 "]4] Vm 2^ S^ ,b =b R\\Q_ R] &] V] I^ 3b:].b $] ;]7] @] /] 9]6] 6[ S] "
3255 " J] @ZU] FZU] PZU] #^2]+^ @b %[ Si 4b "
3256 " %i Ua &] V] Mb 2a:].a #] ;]7] @] /] 9]6] .] J] @b Fb "
3257 "Pb 'b2] E` Qb 1a $g S` %] V] Ma /_:]._ !] "
3258 " ;]7] @] /] 9]6] .] J] @a Ea Oa &a1] D^ "
3259 " X^ Ip Fc Q^ #] V] M_ A] )] ;]7] @] /] 9]6] T] @` "
3260 " D` N` %_/] BZ Ap "
3264 " F]']2] +]']2^ D]']3_ E]']1] \"]']2^ 8] H";
3267 const char *
const _data_font90x103[] = {
3271 " HX 4V >X IX *W FW "
3274 " HX W 4Z 3VCT <Z >X W 4Z "
3275 " HX W 4Z 'VCT ;X W 3Y 2UCT KX W 3Y 0W "
3278 " @W !W 4\\ 5YET ?XHX 8] >W !W 4\\ 7XGX KW !W 4\\ 7XHX +YET :W !W 3[ 5ZFT ?XGX EW !W 3[ 7XGX 5W "
3281 " >W \"V 3\\ 7]HU ?XHX 9` ?W \""
3282 "V 3\\ 7XGX JW \"V 3\\ 7XHX -]HU 9W \"V 3] 7]HT ?XGX DW \"V 3] 8XGX 5V "
3285 " <W $V 3VNV 8_KV ?XHX 9` >W $V 3VNV 8XGX IW $V 3VNV 8XHX -_KV 8W $V 2] 7_KU ?XGX CW $V "
3289 "4VLV :j >XHX :VJV >W &W 4VLV 9XGX HW &W 4VLV 9XHX .j 6W &W 3VMV 9i >XGX BW &W 3VMV 9XGX 7W MW "
3292 " CV 'W 4VJV ;j >XHX ;UGV >V 'W 4VJV :XGX GV 'W 4VJV :XHX .j"
3293 " 5V 'W 3VKV :i >XGX AV 'W 3VKV :XGX 8W N[ "
3296 " DV )W 4VHU <VK_ =XHX ;TEU =V )W 4VHU :XGX FV )W 4VHU :XHX /VK_ 3V )W 3VIV <UK_ =XGX @V )W 3VIV ;XGX 9W "
3299 " DV *V 3UFU =UH\\ <XHX <UD"
3300 "T <V *V 3UFU ;XGX EV *V 3UFU ;XHX /UH\\ 1V *V 2UGU <TH] =XGX ?V *V 2UGU ;XGX 9V a "
3303 " EV ,V 3UDU >TEY ;XHX <TBT <V ,V 3UDU <XGX DV ,V 3UDU <XHX /TEY /V ,V 2U"
3304 "EU =TFZ <XGX >V ,V 2UEU <XGX :V Na "
3307 " DU -V 3VDV ?TCV :XHX <TBT ;U -V 3VDV =XGX CU -V 3VDV =XHX /TCV -U -V 2UCU >TCU :XGX =U -V 2UCU =XGX ;V NV"
3310 " JU /V 3VBV ETBT :U /"
3311 "V 3VBV FU /V 3VBV (U /V 2UAU DU /V 2UAU @V NVGV "
3314 " JX GTBT MX GX 7V :UEU DX GX 7V "
3315 " JX GX 7W 4X GX 6V GX GX 5V (X &X "
3318 " LX IX 7X <UCU DX IX 7X JX IX 6W 3X IX 6X GX IX 5X *X "
3321 " <X ETBT KX KX 6X 1TBT BTAT CX KX 6"
3322 "Y JX KX 6Y (TBT BX KX 5X 1TBT LX KX 4X +X %T #W 9W "
3323 " 3a :a <W 2W >W E\\ AW ,W ,W ,W ,W "
3324 " HY GV +Y 4Z NX @X %W "
3325 " DUDU =Y 7W KW 6Z 4XDT BTAT BW KW 6Z IW KW 6[ ,Y )XDT AW KW 5Z 4XDT "
3326 " KW KW 4Z ,W BW 8V (S <S 9V 7V "
3327 " 3a :a ;W 3W >W H_ AW ,W ,W ,W ,W L] GV +] ;a "
3328 " #[ F^ 8XGX +W BTEU "
3329 " *R 9a :W MW 6\\ 6ZET ?XHX <TAT AW MW 6\\ 7XGX LW MW 5[ 7XGX .Y +ZET @W MW 5\\ 6ZET ?XHX DW MW 4\\ 7XHX 0W AW"
3330 " &XHX MZ +T $Y BS 1W,V MY 8W 7W T 9X 5Z /[ 0Z 8Z /Y GY "
3331 " .\\ <\\ [ 4[ :\\ -a :a :W 4W >W Ja AW ,W ,W ,W ,W N_ GV +_ "
3332 "?e 8] J] Jb 8[ <[ $Y FY 7XGX =Z Di 5W 8Z .Y !W FW *Y 4W)V*W)V-Y(V "
3333 " <UFU 3\\ +[ 0[ 0[ 0[ 0[ 4[=T <e ;W W 5\\ 7\\FT ?XHX <TAT @W W 6^ 8XGX KW W 5] 8XGX .Z@R ?\\FT ?W W 4\\ 7\\"
3334 "FT ?XHX CW W 3\\ 7XHX 1W @W &XHX N\\ ,T :U :U5U ` EX 2VFV .S 4]0W\"b DV V 5V T 7W"
3335 " .` 3[ 7c 8d )Z Dq 8b Hy Bb 7` Na /Z @k .d Kj ?x Mt 7f MX/X'X -X -X2Z&X -]0]0[3X Dc Ii -c Ij 4f N~W$X/X.X&X.X4Y4XDY/Y/Y,Y'~S%a >W $a MY "
3336 " EW 5W >W Kb AW ,W ,W ,W ,W !a GV +a Ch =f ^ Mf 2Z @x Mx <c 3X C~Q)X?X?X Kc 2T "
3337 " .V .T CX $a !W.W N` ;XGX ![ Lb &Z Mi 7[ >a 5a &W 0g #\\ -_ <\\*V.\\*V0a-V\"X )Z /Z /Z /Z /Z 4WJV 1~U+d Kx Mx Mx Mx MX -X -X -X ,j"
3338 " @[3X Dc 8c 8c 8c 8c <cBV.X/X'X/X'X/X'X/X/Y,Y$X &h ;W \"W 5VNV 8]HU ?XHX <TAT ?W \"W 5VNV 8XGX JW \"W 5VMV 9XGX -ZDV @]HU >W \"W 4VNV 8]HU ?XHX "
3339 "BW \"W 3VNV 8XHX 2W ?W &XHX ^ K~\\ >S 3Q +[ @[;[ ;Q ;e HX 2VFV #VBV FS 6`1V#g GV !V 3V !T 7W 0d"
3340 " :` ;j ?k -[ Dq :g Ky Df ;d $f 1Z @o 5j Np Ex Mt :m\"X/X'X -X -X3Z%X -]0]0\\4X Gi Lm 4i Ln ;m#~W$X/X-X(X-X4Y4XCY1Y-Y.Y&~S%a >W $a N[ EV "
3341 "5W >W Lc AW ,W ,W ,W ,W \"b GV +a Dk Aj \"_ h 3Z @x Mx ?i 6X C~Q)X?X?X Ni 6V /V /"
3342 "V DX &f #W0W e >XGX %c#e +b\"i 9_ Be 9d 'V 3k %^ /c @^*V0^*V2d.V\"X )Z /Z /Z /Z /Z 3b 1~U.j Nx Mx Mx Mx MX -X -X -X ,p F\\4X Gi >i "
3343 ">i >i >i BiEV.X/X'X/X'X/X'X/X.Y.Y#X 'j ;V \"V 5VLV :_IT >XHX <TAT >V \"V 5VLV 9XGX IV \"V 4VMV 9XGX ,ZHY A_IT <V \"V 4VLV :_IT >XHX AV \"V 3VLV 9"
3344 "XHX 2V >W &XHX !_ K~[ >T 4R -_ D_?_ >S =t Fh IX 2VFV #VBV FS 7c4V#i HV \"W 3V !T 7V 0f @e >o Co 0"
3345 "\\ Dq <j Ly Fj ?h (i \\ ?Z @r :o\"s Hx Mt <q$X/X'X -X -X4Z$X -]0]0\\4X Im Np 9m Np ?q%~W$X/X-X(X,W5[6XAX1X+X.X%~S%a =V $a ] EV 6W >W M"
3346 "d AW ,W ,W ,W ,W HW 1b GV +b Fm Dm #` \"j 4Z @x Mx Am 8X C~Q)X?X?X!m 9X 0V 0X EX 'h"
3347 " $W0W \"h ?XGX 'g%g 0h%i :a Cf :f *V 4m %^ 0e A^+V/^+V1f1V!X )Z /Z /Z /Z /Z 2` 1~V0o\"x Mx Mx Mx MX -X -X -X ,t J\\4X Im Bm Bm Bm Bm F"
3348 "mHV-X/X'X/X'X/X'X/X-X.X\"X (l ;V $V 4UJU :ULXLU >XHX <UCU =V $V 5VJV :XGX HV $V 4VKV :XGX +ZL\\ AULXLU ;V $V 3UJU :ULXLU >XHX @V $V 2UJU 9XHX 3V"
3349 " =W &XHX !` K~Z >T 4S /a FaAa @T @w Hl KX 2VFV $WCV ES 8e5V$j HV \"V 1V \"T 7V 2j Eh ?q Dp 1\\ Dq >"
3350 "l Ly Hn Bj +l %e E\\ At >s$v Kx Mt >u&X/X'X -X -X5Z#X -^2^0]5X Jo q ;o r Br%~W$X/X-X(X,X6[6XAY3Y+Y0Y%~S%W 3V IW !_ FW 7W >W Md AW "
3351 ",W ,W ,W ,W HW 2[ ?V #[ Hn En #` #l 6\\ Ax Mx Cp 9X C~Q)X?X?X\"o ;Z 1V 1Z FX KS 0i #W2"
3352 "W LV ,i ?XGX *l'h 3l'i ;c Dg ;g ,W 6o %^ 1g B^,V.^,V0g3V X *\\ 1\\ 1\\ 1\\ 1\\ 2^ 0~V2s$x Mx Mx Mx MX -X -X -X ,v L]5X Jo Do Do Do Do HpKW"
3353 "-X/X'X/X'X/X'X/X-Y0Y\"X )n <W &W 5VJV ;TI_ >XHX ;UEU <W &W 5VIV ;XGX HW &W 5VIV ;XGX *g ?TI_ ;W &W 4VJV ;TI_ >XHX @W &W 3VJV :XHX 4W =W &XHX "
3354 " 1\\ 1\\ 1\\ 1\\ 1\\ =XMV K~Y =S 4U 1c IdCc AU Dz In LX 2VFV $VBV ES 9g7V$k HV #W 1W #T 8W 3l Fh ?r Eq 3] Dq ?m L"
3355 "y Ip Em -n )k H\\ Au Av%x Mx Mt ?x(X/X'X -X -X6Z\"X -^2^0]5X Ls\"s ?s\"s Et%~W$X/X,X*X+X6[6X@Y5Y)Y2Y$~S%W 3W JW \"a FW 8W >W NZ 6W ,W "
3356 ",W ,W ,W HW 2X <V X H[G[ Go KZ %[H[ 7\\ Ax Mx Ds ;X C~Q)X?X?X$s >\\ 2V 2\\ GX KS 1j #"
3357 "W2W LV -j ?XGX +ZEZ)VGY 5ZDZ)i <e EUFY <UFX -W 7q %VMU 2YIY CVMU,V.VMU,V0UFX3V X *\\ 1\\ 1\\ 1\\ 1\\ 1\\ 0~W4v%x Mx Mx Mx MX -X -X -X ,x N]5X"
3358 " Ls Hs Hs Hs Hs LsMW,X/X'X/X'X/X'X/X,Y2Y!X *\\G[ <W (W 4UHU <UH] =XHX ;VGV ;W (W 5VHV ;XGX GW (W 4UGU ;XGX )c =UH] 9W (W 3UHU <UH] =XHX ?W (W"
3359 " 2UHU :XHX 5W <W &XHX 5c 8c 8c 8c 8c @WKU J~X >T 5V 2e KfEe CW G| Jp MX 2VFV $VBV ES 9XIX8V$l HV #V /V #T "
3360 " 8V 3n Gh ?s Fr 5^ Dq @n Lx Ir Go .o -q L^ Bv Cx&z x Mt A{)X/X'X -X -X7Z!X -^2^0^6X Mu#t Au#t Gu%~W$X/X,X*X+X6[6X?X5X'X2X#~S%W 2V JW #c FW"
3361 " 9W >W NX 4W ,W ,W ,W ,W HW 2W ;V NW IZCY Hp JY &ZDZ 9^ Bx Mx Eu <X C~Q)X?X?X%u @"
3362 "^ 3V 3^ HX KS 2k \"W4W KV -ZGW ?XGX -X=X+R@W 8X<X .XIX FQ@W <Q@W /W 7dGU %QHU 3XEX DQHU-V-QHU-V/Q@W5V NX +^ 3^ 3^ 3^ 3^ 2\\ 0~W5"
3363 "x&x Mx Mx Mx MX -X -X -X ,z!^6X Mu Ju Ju Ju Ju N}+X/X'X/X'X/X'X/X+X2X X +ZBY ;W *W 4UFU =TF\\ =XHX :VIV 9W *W 5VFV <XGX FW *W 4VGV <XGX (_ :TF\\ 8"
3364 "W *W 3UFU =TF\\ =XHX >W *W 2UFU ;XHX 6W ;W &XHX 7h =h =h =h =h DWJV K~X >T 5W 4g MgFg EY J~ K]FZ MX 2VFV $VBV "
3365 "ES :XGX9V%\\GX HV $W /W 3PATAP GV 3[H[ Gh ?]F] GZE^ 6^ Dq A]FX Lx I\\F\\ G\\G[ /[H] 0u N^ Bw E_D^&{!x Mt B`C_)X/X'X -X -X8Z X -_4_0_7X N^"
3366 "E^$u C^E^$u H^E\\%~W$X/X,Y,Y*W7]8X>Y7Y'Y4Y#~S%W 2V JW $e FV 9W >W NW 3W ,W ,W ,W ,W HW 2W ;V NW IY@X >X "
3367 "4[AV IX &X@X 9^ Bx Mx F^E^ =X C~Q)X?X?X&^E^ B` 4V 4` IX KS 3\\GW \"W4W KV .YBT ?XGX .V7V,P=W :W8W /VEV 3V +V /V "
3368 " 7eGU KU 3WCW ;U-V$U-V LV5V NX +^ 3^ 3^ 3^ 3^ 3^ 1~W6_D^&x Mx Mx Mx MX -X -X -X ,{\"_7X N^E^ L^E^ L^E^ L^E^ L^E^ !^Ed*X/X'X/X'X/X'X/X+Y4Y X +Y?"
3369 "X ;V *V 4UDU >TEZ <XHX 9a 7V *V 4UDV =XGX EV *V 4VEV =XGX )] 7TEZ 6V *V 3UDU >TEZ <XHX =V *V 2UDU <XHX 6V :W &XHX 9k @k @k @k @k EWJV K~W "
3370 " >T 5Y 5g MhHi G[ M~Q L\\AW MX 2VFV $VCV DS :WEW:V%ZAU HV $V -V 3RCTCR HW 4ZDZ H\\LX ?Y?[ HV>\\ 8_ DX )[?T -Y J[B"
3371 "[ I[CZ 0WAZ 2x ^ BX>^ G]=Z&X=b#X -X '];[)X/X'X -X -X:[ NX -_4_0_7X \\?\\%X@^ E\\?\\%X?] J[=X =X <X/X+X,X)X8]8X=Y9Y%Y6Y )Y$W 2W KW %ZMZ FV :W"
3372 " >W X 3W 4W ,W HW 3X ;V NX KY?X Ca 9Y:R HX (X>X :VNV BZ /X '\\?\\ A^ FX0X)X?X?X'\\?\\ "
3373 " Db 5V 5b JX KS 3ZBT !W6W JV .X?R 4V4U HV ;V4V 1VCV 4V *U 0V 7fGU KU 4WAW <U.V#U.V JU6V MX +^ 3^ 3^ 3^ 3^ 3^ 2XIX F]=Z&X -X"
3374 " -X -X -X -X -X -X ,X=b$_7X \\?\\ N\\?\\ N\\?\\ N\\?\\ N\\?\\ #\\?`)X/X'X/X'X/X'X/X*Y6Y NX ,Y=W :V ,V 3UDU >TDX ;a 6V ,V 4UBU GV ,V 3UCU 0` 6TDX 4V ,V"
3375 " 2UDU >TDX >V ,V 1UDU :V 9W (o Do Do Do Do GWIU J~V >T 6Z 6i jIj I\\ N~R M[=U MX 2VFV %VBV H] AWCW;V%Y=R"
3376 " HV %W -V 4UETEU IV 4ZBZ IWGX ?V;[ IS9Z 9VNX DX *Z;R -X JZ>Y JZ?Y 1U>Z 5`C_#` CX;[ H[7W&X9_$X -X (\\6X)X/X'X -X -X;[ MX -_4_0`8X![;[&X"
3377 "=[ F[;[&X<[ LZ8U =X <X/X+X,X)X8]8X<X9X#X6X )Z$W 1V KW &ZKZ FV ;W >W W 2W 4W ,W HW 3W :V MW KX=W Cc "
3378 ";X7P HX (W<W ;WNW BY /X ([;[ Gg JX0X)X?X?X([;[ Fd 6V 6d KX KS 4Y>R !X8X JV /X<P 6V1U IV <U0U 2UAU 3U *U 1V "
3379 " 6fGU KU 4V?V <U/V\"U/V IU7V LX ,` 5` 5` 5` 5` 5` 3XIX G[7W&X -X -X -X -X -X -X -X ,X9_%`8XX6X MX ,X;W"
3380 " :V .V 3UBU ?TBT 7] 3V .V 4VAU GV .V 3UAU 4d 7TBT 1V .V 2UBU ?TBT ;V .V 1UBU <V 8W )r Gr Gr Gr Gr IVHR GX+W =S 5[ 7i!k"
3381 "Jk I] !^ )Y:T MX 2VFV %VBV Le EVAV<V$X:P HV %W -W 6WFTFV IV 4X?Y IRBX ?T7Y IP5Z :VNX DX +Z8P .Y JY<Y KY=X 1S;"
3382 "Y 6];\\$WNW CX9Z J[4U&X6]%X -X )[2V)X/X'X -X -X<[ LX -XNV6VNX0`8X\"Z7Z'X;Z HZ7Z'X;Z LY4R =X <X/X*X.X(X8]8X<Y;Y#Y8Y *Z#W 1V KW 'ZIZ FV <W >W W "
3383 " 2W 4W ,W HW 3W :V MW KW<X Dd <W -W )W;X <WNW AY 0X )Z7Z Jl MX0X)X?X?X)Z7Z Hf 7V 7f"
3384 " LX KS 4X;P W8W IV /W \"V.U JV >U.U 4VAV &V 5U *U 2V 6gGU KU 5W?W =U/V\"U/V IU7V LX ,WNW 5WNW 5WNW 5WNW 5WNW 5WNW 4XHX H[4U&X -X -"
3385 "X -X -X -X -X -X ,X6]&`8X\"Z7Z#Z7Z#Z7Z#Z7Z#Z7Z 'Z8['X/X'X/X'X/X'X/X)Y8Y MX ,W:W 9V 0V 3U@U ?[ 1V 0V 3U@V GV 0V 3U?U 8h 1V 0V 2U@U "
3386 " CV 0V 1U@U >V 7W *`L` I`L` I`L` I`L` I`L` JV =X,X >T 6] 9k\"lKl K_ #\\ 'Y8S MX 2VFV %VBV Nk IVAV=V$X 1V %V +V "
3387 "6YHTHY -V EW 5Y>Y :X ?R5Z .Y ;VMX DX +Y DX IY<Y LY;X 2Q8Y 8[5[&WNW CX8Y KZ1T&X4\\&X -X *Z.T)X/X'X -X -X=[ KX -XNV6VNX0a9X#Z5Z(X:Y IZ5Z("
3388 "X:Z NY1P =X <X/X*X.X'W9WNV:X:Y=Y!Y:Y *Z\"W 1W LW (ZGZ -W >W W 2W 4W ,W HW 3W :V MW KW;W De =W "
3389 " -X *W:W <VLV @Y 1X *Z5Z Mp X0X)X?X?X*Z5Z Jh 8V 8h MX KS 5Y :X:X IV /W #U+T JV ?U+T 5U?U &V 5U +V AgGU KU 5"
3390 "V=V =U0V!U0V IV8V KX ,WNW 5WNW 5WNW 5WNW 5WNW 5WNW 4XHX IZ1T&X -X -X -X -X -X -X -X ,X4\\'a9X#Z5Z%Z5Z%Z5Z%Z5Z%Z5Z )Z5Z(X/X'X/X'X/X'X/X(Y:Y LX -X:W "
3391 " !W 2\\LZ EW +[@[ K[@[ K[@[ K[@[ K[@[ KV <X-X /P 0T 7^ 9k\"lLm La %Z "
3392 " %Z6Q MX 2VFV %VCV n KWAW>V$X 1V &W +W 5XITIX +V EV 4X<X :X ?P2Y -X <WMX DX ,Y CX JY:Y MX9W 2P7Y :Z0Z(WLW DX7X KY.R&X2Z&X -X *Y+R)X"
3393 "/X'X -X -X>[ JX -XNW8WNX0a9X#Y3Y(X9Y JY3Y(X9Y NX LX <X/X*X.X'X:VMV:X9X=X NX:X *Z!W 0V LW )ZEZ .W >W W 2W 4W ,W HW "
3394 " 3W :V MW LX;W Df >W ,W +W8W >WLW @Y 2X +Z3Z!t\"X0X)X?X?X*Y3Y Kj 9V 9j AS 5X 8W:W HV /W #T)T KV "
3395 " @T(T 6U?U &V 5T +V AhGU KU 5V=V =U0V!U0V JV7V WLW 7WLW 7WLW 7WLW 7WLW 7XNX 6XGX IY.R&X -X -X -X -X -X -X -X ,X2Z'a9X#Y3Y%Y3Y%Y3Y%Y3Y%Y3"
3396 "Y )Y3Z)X/X'X/X'X/X'X/X'X:X Ki >W8V *XHZ FW ,Z<Z MZ<Z MZ<Z MZ<Z MZ<Z LV <X.X .R 2S "
3397 "7` :k#nMm Mb &Z $Y4P MX 2VFV &VBV!o KV?V?V#W 0V &V )V 3XKTKX )V EV 5X:X ;X X -Y =VLX DX -Y CY JY:Y NY9X HX ;"
3398 "Z-Y)WLW DX7Y MY,Q&X1Z'X -X +Y)Q)X/X'X -X -X?[ IX -XMV8VMX0XNX:X$Y1Y)X9Y KY1Y)X8X NX LX <X/X)X0X&X:VMV:X9Y?Y NY<Y *Y W 0V LW *ZCZ /W >W W "
3399 " 2W 4W ,W HW 3W :V MW LW:W Dg ?W ,X ,W8W >WLW ?Y 3X +Y1Y\"v#X0X)X?X?X+Y1Y MYNVNY :V :"
3400 "YNVNY BS 5X 8X<X HV /W $T?ZBT*c AT&T 7U?U &V 6U -W @hGU KU 6V;V >U1V U1V KW7V NWLW 7WLW 7WLW 7WLW 7WLW 7WLW 6XGX JY,Q&X -X "
3401 "-X -X -X -X -X -X ,X1Z(XNX:X$Y1Y'Y1Y'Y1Y'Y1Y'Y1Y P)P$Y3[)X/X'X/X'X/X'X/X'Y<Y Km BW8W +UDZ 7P 1W "
3402 " -Y8Y Y8Y Y8Y Y8Y Y8Y MV ;W.X /T 4T 7a ;k#nMn Nc 6P :W4W ?Z ?X6X KY #Y 0X 2VFV &VBV\"p KV?V?V#W 0V 'W )W 2XMTMX 'V FW "
3403 "5X:X ;X Y -X >VKX DX -X BX IX8X NX7W KP 1P =X <Y)X+XLX EX6X NY*P&X0Z(X -X ,Y'P)X/X'X -X -X@Z GX -XMV8VMX0XNX:X%Y/Y*X8X LY/Y*X8Y!X KX <X/X)X0"
3404 "X&X:VMV:X8YAY LY>Y *Z W 0W MW +ZAZ 0W >W W 2W 4W ,W HW 3W :V MW LW:W DSF[ @X -X "
3405 " -X8W ?WJW ?Y 4X ,Y/Y%z%X0X)X?X?X,Y/Y YMVMY ;V ;YMVMY CS 5X 5P*Q JW<W GV /W %TBbET/g BTGb?T 8U?U &V 7U 5_ ?hGU KU 6V;V "
3406 ">U2V NU2V$_7V NXLX 9XLX 9XLX 9XLX 9XLX 8WLW 6XGX KY*P&X -X -X -X -X -X -X -X ,X0Z)XNX:X%Y/Y)Y/Y)Y/Y)Y/Y)Y/Y\"R+R&Y3]*X/X'X/X'X/X'X/X&Y>Y Jp EW:Y "
3407 " +R@Y 7Q 2W .XEVFY\"X5Y\"X5Y\"X5Y\"X5Y NV ;X/X 0V 5T 8c <k#nNo e >^ AW4W ?Z >W6W KY "
3408 " \"Y 0X 2VFV &VCW#[LSKZ KV?V@V\"W 0V 'W )W 1XNTNX &V FW 6Y:Y <X NX -X ?WKX DX .Y CY IX8X NX7W NS 1S @X =X&X,WJW EX6X NY /X/Y(X -X ,"
3409 "Y /X/X'X -X -XAZ FX -XMW:WMX0XMX;X%Y/Y*X8Y MY/Y*X8Y!X KX <X/X)Y1X%W;WMW;W6XAX JX>X *Z NW 0W MW ,Z?Z 1W >W W 2W 4W ,W H"
3410 "W 3W :V MW LW:W DPAY ?Y .W -W6W @WJW >Y 5X ,X-X&_MXM_&X0X)X?X?X,Y/Y !YLVLY <V <YLVLY DS 6Y 6R,R JX>"
3411 "W FV /X 'TCfFT2i CUGfBT 9U?U &V 7U 5] >iGU KU 6V;V >U2V NU2V$]5V NWJW 9WJW 9WJW 9WJW 9WJW 9WJW 8XFX KY /X -X -X -X -X -X -X -X ,X"
3412 "/Y)XMX;X%Y/Y)Y/Y)Y/Y)Y/Y)Y/Y#T-T'Y3]*X/X'X/X'X/X'X/X%X>X Ir GW=\\ GY 9S 3W /XDVDX$X2X$X2X$X"
3413 "2X$X2X V ;X0X 0X 7T 8d <k#~`!g Bd DW4W ?[ ?X7W LY !X /X 2VFV &VCV#ZJSGV KV?VAV!W 0V 'V 'V /d $V FV 5X8X <X NX -X ?VJX DX"
3414 " .X BX HX8X Y7X #V 1V CX >X$X-WJW EX6X Y .X.Y)X -X -Y .X/X'X -X -XBZ EX -XLV:VLX0XMX;X&Y-Y+X7X NY-Y+X7X!X KX <X/X(X2X$X<VKV<X6YCY JY@Y +Z MW /"
3415 "V MW -Y;Y \"Z ;WDX 0Z 2XDW >Z <W !X :WDY IW ,W HX8X MY 3Z *X 3X &X 7] <W 3W :V MW ;X :W:W 4Y @[ )\\ (Y 6X 8QEV :[ "
3416 " JW6W @VIW =Y 6X -Y-Y(]JXJ]'X0X)X?X?X-Y-Y #YKVKY =V =YKVKY IZ 9X 6T.T JW>W FV .X (TDgFT3j CTFhDT 9U?U &V 8U 4\\ =iGU KU 6V"
3417 ";V >U3V MU3V#\\5V MWJW 9WJW 9WJW 9WJW 9WJW 9WJW 8XFX LY .X -X -X -X -X -X -X -X ,X.Y*XMX;X&Y-Y+Y-Y+Y-Y+Y-Y+Y-Y%V/V)Y3_+X/X'X/X'X/X'X/X%Y@Y Is HW?^ "
3418 "?Z /Z /Z /Z /Z /Z /Z6Y NZ 0Z /Z /Z /Z 8Y 1Y 3Z /Z /Z /Z /Z 3ZCV 5WDX DXCVCW%X0W%X0W%X0W%X0W V :X1X 0X 7T 9f =k#~`\"h Cf "
3419 "EW4W @\\ ?X8X LX !Y /X 2VFV 'VBV#XHSET KV?VAV!W 0V (W 'W .` \"V GW 5X8X <X NX -X @VIX DX .X BX HX8X X5W &Y 1Y FX >W\"W.XJX"
3420 " FX6X X -X.Y)X -X -X -X/X'X -X -XCZ DX -XLV:VLX0XLX<X&X+X+X7X NX+X+X7X!X KX <X/X(X2X$X<VKV<X5YEY HYBY +Z LW /W NW .Y9Y 'b ?WG^ 7b 9^GW A` Gl 2_GW"
3421 " MWG_ DW ,W ,W8Y MW ,WG^>^4WG_ 9` @WG^ 9^GW MWG\\ ;f Gm <W6W#X2X#W;X;W5Y7Y#W1X\"u 6W :V MW >^BV\"W:W 3X ?^ 0e AWG_ KV.X ?X <W6W HTG[ K}!WCWCW Ca"
3422 " 7p&{ NW6W AWHW >Z 7X -X+X)\\HXH\\(X0X)X?X?X-X+X $YJVJY >V >YJVJY Ma =X 7V0V JW@W EV .Y *TEiET5k DTEiDT :VAV &V 9U 3_ ;W6W NiGU "
3423 "KU 6V;V >U3V MU3V#_8V NXJX ;XJX ;XJX ;XJX ;XJX ;XJX :XEX LX -X -X -X -X -X -X -X -X ,X.Y*XLX<X&X+X+X+X+X+X+X+X+X+X&X1X*X3`+X/X'X/X'X/X'X/X$YBY Ht "
3424 "IW@_ Cb 7b 7b 7b 7b 7b 7b>a'b 7` 5` 5` 5` AW ,W ,W ,W DY EWG_ 9` 5` 5` 5` 5` (Z <`GV W6W MW6W MW6W MW6W#W1X NWG^ HW1X NWBVBW&W.W&WJP:PJW&W4PJW&W."
3425 "W!V :X2X 0X 6S 8g >k#~`#j Fj GW4W @\\ >W8W LX X .X 2VFV 'VBV$XGSCR KV?VBV X 1V (W 'W ,\\ V GW 5X8X <X NX -X AWIX DX /X "
3426 "BY HX8X X5W ([ 1[ HX ?W W/WHW FX6X!Y -X-Y*X -X .Y -X/X'X -X -XDZ CX -XLW<WLX0XKW<X'Y+X+X7X Y+X+X7X!X KX <X/X'X4X#X<VKV<X4XFY FXBX *Y KW /W NW "
3427 "/Y7Y +g AWIb ;f =bIW De Il 3bIW MWIc FW ,W ,W9Y LW ,WIbBb6WIc >f CWIb =bIW MWI^ =j Im <W6W\"W2W\"W<Z<W4X7X!W2W!u 6W :V MW @bEW\"W:W 2X @c 8j CW"
3428 "Ic MX0W =W <W6W IW/W\"VI^ L}!WCWCW Ee =t&{ W4W BWHW =Y 7X .X*Y*ZFXFZ(X0X)X?X?X.Y+X #WIVIW =V =WIVIW f ?X 8X2X KW@W EV .Z +SE[GVDS6ZDV "
3429 "DSDVDXDS 9UAU %V :U 2` <W6W NiGU KU 6V;V >U4V LU4V\"`:V GX /WHW ;WHW ;WHW ;WHW ;WHW ;WHW :XEX MY -X -X -X -X -X -X -X -X ,X-Y+XKW<X'Y+X,Y+X,Y+"
3430 "X,Y+X,Y+X'Z3Z,Y4WNY,X/X'X/X'X/X'X/X#XBX Gu JWB\\ Ag <g <g <g <g <g <gBe+f <e :e :e :e CW ,W ,W ,W Mc FWIc >f ;f ;f ;f ;f +Z >eJU NW6W MW6W MW6W MW6W\"W"
3431 "2W MWIb IW2W NWAVAW(W,W(WJR<RJW(W4RJW(W,W\"V 9W2X 1X 6T 9i ?k#~`#k Hl HW4W @] ?X9W LW NX .X 2VFV 'VCW$WFSAP KV?VBV NW 1V (V"
3432 " &W *X MV GV 5X6X =X NX -X AVHX DX /X BX GX8X X5X ,^ 1^ LX ?W MW0WHW FX6X!X ,X-Y*X -X .X ,X/X'X -X -XEZ BX -XKV<VKX0XKX=X'Y+Y,X7X Y+Y,X"
3433 "7X!X KX <X/X'X4X\"W=WKV<W3YGY FYDY +Z KW .V NW 0Y5Y /l CWJe ?j AeJW Eh Kl 5eJW MWJe GW ,W ,W:Y KW ,WJdDd7WJe @h DWJe AeJW MWJ_ ?l Im <W6W\"W2W!W=Z="
3434 "W2X9X W2W!u 6W :V MW BeFV!W;X 1W ?f =k CWJe NY2X =X =W6W JW-W$WI` N}!WCWCW Gi Av&{ W4W BVGW <Y 8X .X)X+ZEXEZ)X0X)X?X?X.Y+Y #UHVHU <V <UHVH"
3435 "U !j AX 9Z4Z KWBW DV -Z -TFY@RDT8XAV ETDVBWET :VCV %V ;V )X =W6W NiGU KU 6V;V >U5V KU5V GX<V FX /WHW ;WHW ;WHW ;WHW ;WHW ;WHW :WDX"
3436 " MX ,X -X -X -X -X -X -X -X ,X-Y+XKX=X'Y+Y-Y+Y-Y+Y-Y+Y-Y+Y'Z5Z+Y5WMY,X/X'X/X'X/X'X/X#YDY GX@^ KWCZ Al Al Al Al Al Al AlFh.j ?h =h =h =h EW ,W ,W ,W !g"
3437 " GWJe @h =h =h =h =h ,Z @hLV NW6W MW6W MW6W MW6W\"W2W MWJe KW2W W@VAW)W+W)WJT>TKW)W4TKW)W+W\"V 9X3X 2X 5T :k ?i\"~`$m Jn IW4W A^ ?X:X MW "
3438 " NY .X 2VFV 7~X2XFS <V?VCV MX 2V )W %W +X MV GV 5X6X =X NX -X BVGX DX /X BX GX8X X5X LX -X 7a 1a X @W KW2XHX GX6X!X ,X,X*X -X ."
3439 "X ,X/X'X -X -XFZ AX -XKV<VKX0XJW=X'X)X,X7X X)X,X7X!X KX <X/X'X4X\"X>VIV>X2YIY DYFY +Z JW .V NW 1Y3Y 1n DWLh Bm ChLW Gk Ll 6hLW MWKg HW ,W ,W;Y JW "
3440 ",WKfGg8WKg Cl FWLh ChLW MWK` @m Im <W6W\"X4X!W=Z=W1X;X NW3X!u 6W :V MW CgGV!W;W 0X ?g Am CWKg [4X >Y =W6W JW-W&YJb }!WCWCW Hk Dx&{ W4W CWFW <Y 9"
3441 "X /Y)X,ZDXDZ*X0X)X?X?X.X)X P #SGVGS %P 7V 9P0P CSGVGS !l BX 8ZGWFZ JWCX DV ,Z .SEW<PCS8V?V .P>P JSCVAVDS :WEV $V <V &W >W6W NiGU KU 6V"
3442 ";V BP>P /U5V KU5V EW=V FX 0XHX =XHX =XHX =XHX =XHX =XHX <XDX MX ,X -X -X -X -X -X -X -X ,X,X+XJW=X'X)X-X)X-X)X-X)X-X)X&Z7Z*X5WKX,X/X'X/X'X/X'X/X\"YFY F"
3443 "X=[ KWDY @n Cn Cn Cn Cn Cn CnHj1m Bk @k @k @k FW ,W ,W ,W $j GWKg Cl Al Al Al Al .Z Bs MW6W MW6W MW6W MW6W\"W3X MWLh LW3X V?V@W*V)W*VJV@VKW*V4VKW*V"
3444 ")W#V 9X4X 2X 4S :l ?i\"~`%o Lp JW4W A^ >W:X MW NX -X 2VFV 7~X2WES <V?VDV LX 2V )W %W -\\ V HW 5X6X =X NX .X BWGX DX 0X "
3445 "BY FX:X NX5X LX -X :d 1d $Y @V IV2WFW GX6X\"Y ,X,Y+X -X /Y ,X/X'X -X -XH[ @X -XKW>WKX0XJX>X(Y)X,X7X!Y)X,X7X!Y LX <X/X&X6X!X>VIV>X1YKY BXFX +Z IW .W "
3446 " W 2Y1Y 2o EWMj Dn DjMW Hn Nl 7jMW MWLi IW ,W ,W<Y IW ,WLhIi9WLi En GWMj EjMW MWLa An Im <W6W!W4W W=Z=W1Y=Y MW4W u 6W :V MW DiIV W;W /W =g C"
3447 "m CWLi![4W =Y =W6W KW+W(ZKd!}!WCWCW Im Fy&{ W4W CWFW ;Y :X /X'X-YCXCY*X0X)X?X?X/Y)X!R #QFVFQ $R 9V :R1R DQFVFQ \"n BX 7ZJ\\JZ HWDW CV +[ 1TFW.T:W?V"
3448 " /Q?Q KTCVAWET :XIX $V =V #U >W6W NiGU KU 6V;V BQ?Q 0U6V JU6V BU>V EX 0WFW =WFW =WFW =WFW =WFW =WFW <XDX NY ,X -X -X -X -X -X -X -X ,X,Y,XJ"
3449 "X>X(Y)X.Y)X.Y)X.Y)X.Y)X%Z9Z*Y6WJX,X/X'X/X'X/X'X/X!XFX EX;Z LWDX ?o Do Do Do Do Do DoKn4n Cn Cn Cn Cn HW ,W ,W ,W %l HWLi En Cn Cn Cn Cn /Z Cs LW6W MW6"
3450 "W MW6W MW6W!W4W LWMj LW4W W?V?V+W(V+WKXBXKV+W5XKV+W(V$W 8W4X 2X 5T ;n ?g!~_%p LZDZ JW4W A^ >W:W MW MX -X 2VFV 7~X2WES <WAW"
3451 "DV KX 3V )W %W /` \"V HV 4X6X =X Y .X BVFX DX 0X BX EX:X NX5X LX -X <e /e 'Y @V GV4XFX HX7X!X +X+X+X -X /X +X/X'X -X -XI[ ?X -XJV>VJX0XIW>X(X"
3452 "'X-X7X!X'X-X7X!Y LX <X/X&X6X!X>VIV>X1YKY AXHX +Z HW -V W 3Y/Y 3p FWMk Fo EkMW Io Nl 8kMW MWMk JW ,W ,W=Y HW ,WMjJj:WMk Gp HWMk GkMW MWMb Bo Im <W"
3453 "6W!W4W W>\\>W0X=X LW5X u 6W :V MW EkJV W<X /W >j Fn CWMk\"\\6X =Z >W6W KW+W)[Ke\"}!WCWCW Jo Hz&{ W4W DWDW ;Y ;X /X'X.YBXBY+X0X)X?X?X/X'X#T HV IT "
3454 ":V ;T3T :V CV +o BX 6ZM`MZ GXFX CV *\\ 3SFW,S:V>V 0R@R KSBV@VDS 9e #V ?W \"V ?W6W NiGU KU 6V;V BR@R 1U6V JU6V BV?V EX 1XFX ?XFX ?XFX ?XFX"
3455 " ?XFX ?XFW =XCX NX +X -X -X -X -X -X -X -X ,X+X,XIW>X(X'X/X'X/X'X/X'X/X'X%Z;Z)X5VHX-X/X'X/X'X/X'X/X XHX DX:Y LWEX >p Ep Ep Ep Ep Ep EpMp6o Do Do Do Do"
3456 " HW ,W ,W ,W 'o IWMk Gp Ep Ep Ep Ep 0Z Ds KW6W MW6W MW6W MW6W!W5X LWMk MW5X V>V?W,V'W,VKZDYKW,V5YKW,V'W%W 8X5W 2X 4T ;o @g ~^%q NY@Y KW4W B`"
3457 " ?X<X MV LX -X 2VFV 7~X2WES ;VAVDV JY 4V )V $W 1d $V HV 4X6X =X X .Y CWFX DXLY =XEX 'Y EY<X MX5X LX -X ?e )e +Y ?V:X6V4WDW "
3458 "HX7X!X +X+X+X -X /X +X/X'X -X -XJ[ >X -XJW@WJX0XIX?X(X'X-X7X!X'X-X8Y Y MX <X/X%W6X W?WIV>W/YMY @YJY +Y GW -V W 4X+X 4YE\\ FWNXG\\ H]EX F\\GXNW J\\F[ "
3459 "GW ,\\GXNW MWNXG[ JW ,W ,W?Z GW ,WNXH[KXH[:WNXG[ H]H] IWNXG\\ I\\GXNW MWNXFQ C\\CW CW ,W6W!X6X NW?\\?W.X?X JW6W 1X 6W :V MW 9X=X\"[IZKW W=Y /W @m H]DV "
3460 "CWNXG[\"\\6W =[ >W6W LW)W*ZJWKY\"}!WCWCW K\\H] J{&{ V3W DWDW :Y <X /X'X.XAXAX+X0X)X?X?X/X'X$V IV JV ;V <V5V ;V CV ,^MSKW BX 5x EWFW BV ,_ 5TFW,S:V?W"
3461 " 1SAS LTBV@VDS 9d \"V @W U ?W6W NiGU KU 5V=V ASAS 2U7V IU7V @U@V DX 1WDW ?WDW ?WDW ?WDW ?WDW ?XFX >XCX NX +X -X -X -X -X -X -X -X ,X+X,XIX?"
3462 "X(X'X/X'X/X'X/X'X/X'X$Z=Z(X6WHX-X/X'X/X'X/X'X/X YJY DX9Y MWEW =YE\\ EYE\\ EYE\\ EYE\\ EYE\\ EYE\\ EYE]N\\G[7]EX E\\F[ F\\F[ F\\F[ F\\F[ IW ,W ,W ,W (p IWNXG[ H]H"
3463 "] G]H] G]H] G]H] G]H] 1Z E]H^ JW6W MW6W MW6W MW6W W6W KWNXG\\ MW6W NV>V>V,V&V,VJZFYIV,V6YIV,V&V%W 7W6X 3X LR:T ;q @e N~^&s!Y>Y LW4W B` >W<X N"
3464 "W $x FX 2VFV 7~X2WES ;VAVEW IY 5V *W #W 4XNTNX &V IW 5X5X =X X .X CWEX Di AXH_ +X CX<X MX5X LX -X Be #e /Z @V<^IUDV5WDW HX8Y"
3465 "!X +X+X+X -X /X +X/X'X -X -XK[ =X -XIV@VIX0XHW?X(X'X-X7X!X'X-X8X NZ NX <X/X%X8X NX@VGV@X.c >XJX +Z GW -W !W 5X)X 5U>Z G_CZ I[>T FZC_ KZAZ HW -ZB_ "
3466 "M^BZ KW ,W ,W@Z FW ,^CZMVCZ;^BZ IZBZ I_CZ IZC_ M^ 5Y<S CW ,W6W W6W MW?\\?W.YAY JW6W 2Y 6W :V MW ;\\A\\%YDYLV NW>Y .W AXJa IZ<Q C^BZ MX8X =\\ ?W6W LW)"
3467 "W+YIXJY LW=W JWCWCW LZBZ K]F] ;W >W2W EWDW 9Y =X /X'X/YAXAY,X0X)X?X?X/X'X%X JV KX <V =X7X <V CV -\\JSHT BX 4v DXHX BV -b 7SEV*S;V?W 2TBT LSAV"
3468 "@VCS 9b !V AV MU ?W6W MhGU KU 5V=V ATBT 3U8V HU8V ?UAV CX 1WDW ?WDW ?WDW ?WDW ?WDW ?WDW ?XBX NX +X -X -X -X -X -X -X -X ,X+X,XHW?X(X'X/X'X/X'X"
3469 "/X'X/X'X#Z?Z'X7WGX-X/X'X/X'X/X'X/X NXJX CX9Y MWFW <U>Z FU>Z FU>Z FU>Z FU>Z FU>Z FU>eBZ9[>T FZAZ HZAZ HZAZ HZAZ JW ,W ,W ,W )r J^BZ IZBZ GZBZ GZBZ GZBZ"
3470 " GZBZ 1Z EZB[ JW6W MW6W MW6W MW6W W6W K_CZ MW6W V=V>V-V%V-VHZHYHV-V6YHV-V%V%W 7X7X 4X NU:T <s Ae N~^'u\"X<X LW4W BWNW >W<W MW "
3471 "$w EX 2~X2WES ;WCWEV GY 9W #W 5XMTMX 'V IV 4X4X >X !Y 0Y BVDX Dk CXJc -X BX>X LX5Y MX -X Ee Le 3Z ?U=bKUCU6XDX IX9Y X +X+X+X -X /X +X/X"
3472 "'X -X -XL[ <X -XIV@VIX0XHX@X(X'X-X8Y!X'X-X8X N[ X <X/X%X8X NX@VGV@X.c =XLX +Z FW ,V !W AR9Y H]?Y KZ:R GY?] LY=Y IW -Y?] M]@Y KW ,W ,WAY DW ,]@X"
3473 "NV@X;]@Y JY>Y J]?Y KY?] M] 4X8P CW ,W6W X8X MW?\\?W-XAX IW7X 3Y 5W :V MW =_C_(YBXLV NW?Z -W CXC\\ KY ,]@Y LW8X >] ?W6W LW)W,YHWHY MW=W JWCWCW MY>Y "
3474 "L[B[ ;W >W2W FWBW 9Y >X 0X%X0X@X@X,X0X)X?X?X/X'X&Y JV KY =V >Y7Y =V CV .[HSFR BX 3t BWHW AV .WN\\ 9SFV)S;V?W 3UCU LSAV@VCS 7_ V BV LU ?W"
3475 "6W MhGU KU 5W?W AUCU 4U8V HU8V ?UAV CX 2XDX AXDX AXDX AXDX AXDX AXDX @XBX NX +X -X -X -X -X -X -X -X ,X+X,XHX@X(X'X/X'X/X'X/X'X/X'X\"ZAZ&X8WFX-X/X'"
3476 "X/X'X/X'X/X MXLX BX8X MWFW <R9Y GR9Y GR9Y GR9Y GR9Y GR9Y GR9a>Y;Z:R GY=Y JY=Y JY=Y JY=Y KW ,W ,W ,W *]E[ J]@Y JY>Y IY>Y IY>Y IY>Y IY>Y 2Z FY>Y JW6W MW"
3477 "6W MW6W MW6W W7X K]?Y NW7X V=V=U-V$U-VGZJYFU-V7YFU-V$U%W 7X8X &~X/X:T =t @c L~\\'v\"W:W LW4W CXNX ?X>X MV $x EX 2~X2WES :VDW"
3478 "EV FZ :W #W 7XKTKX )V IV 4X4X >X !X 0Y BWDX Dm FXKf /Y AYBY KX5Y MX -X Gd ~X d 5Y ?V>dLUCU6WBW IX;Z Y +X+Y,X -X 0Y +X/X'X -X -XM[ ;X -XIWBWIX"
3479 "0XGW@X)Y'Y.X8X!Y'Y.X9Y M] #X <X/X$X:X MX@VGV@X-a <YNY ,Z EW ,V !W AP6X H\\=Y LY7P HY=\\ LX;X IW .Y=\\ M[=X KW ,W ,WBY CW ,[=]=W;[=X KY<Y K\\=Y MY=\\ "
3480 "M\\ 4X *W ,W6W NW8X MW@VNV@W,XCX GW8W 3Y 4W :V MW >aEa)X@XNW NWA[ ,W DW?[ LX +[=X KW:X =] ?W6W MW'W-XGWGX MW=W JWCWCW MX<Y NZ>Z <W >W2W FWBW 9Z ?X"
3481 " 0X%X0X@X@X,X0X(X@X@X/Y'Y(Y IV JY >V ?Y5Y >V CV .YFSDP BX 2q @XJX AV /WK[ :SFV)S;V@X 4VDV LSAV@VCS 6\\ MV CV KU ?W6W MhGU KU 4V?V @V"
3482 "DV 5U9V GU9V >UBV BX 2WBW AWBW AWBW AWBW AWBW AXDX @XBX Y +X -X -X -X -X -X -X -X ,X+Y-XGW@X)Y'Y1Y'Y1Y'Y1Y'Y1Y'Y\"ZCZ&Y9WEY.X/X'X/X'X/X'X/X MYNY BX8Y N"
3483 "WFW <P6X GP6X GP6X GP6X GP6X GP6X GP6_<X;Y7P GX;X JX;X JX;X JX;X KW ,W ,W ,W *Z?Y K[=X KY<Y KY<Y KY<Y KY<Y KY<Y 3Z GY<Y KW6W MW6W MW6W MW6W NW8W J\\=Y "
3484 "NW8W NV=V=V.V$V.VFZLYEV.V8YEV.V$V&W 6W8X &~X2\\<T =v Ab K~\\(x$W8W MW4W CXNX ?X>X NW $w DX $VBV#XFS :WFXEV H] ;W #W 9XITIX"
3485 " +V JW 4X4X >X \"Y 3[ BWCX Dn GXLi 1X ?ZFZ JY7Z MX -X Je M~X Me 9Y >U?gMUCV7WBW IX>\\ NX *X*X,X -X 0X *X/X'X -X -XNZ 9X -XHVBVHX0XGXAX)X%X.X9Y!X%"
3486 "X.X:Y La 'X <X/X$X:X LWAWGV@W+_ :XNX ,Z DW ,W \"W &W H[;X MY .X;[ MX9X JW .X;[ M[<X LW ,W ,WCY BW ,Z<\\<X<[<X LX:X K[;X MX;[ M[ 3W )W ,W6W NW8W KW"
3487 "AVNVAW*XEX FW9X 4Y 3W :V MW ?cGc+Y?WNV MWD] +W DV=Z LX +Z;X LW:X >_ @W6W MW'W.YGWFX NW=W JWCWCW NX:X NY<Y <W >W2W FWBW 8Z @X 0X%X0X@X@X,X0X(X@X@X"
3488 "/X%X)Y HV IY ?V @Y3Y ?V CV /YES 6X 1\\H[ JcJc LV 0WI\\ =TFV)S;WAX 5WEW MTAVAWCS 3W 4~W.W KV ?W6W LgGU KU 4WAW @WEW 6U9V GU9V ?VBV BX 2"
3489 "WBW AWBW AWBW AWBW AWBW AWBW AXAX X *X -X -X -X -X -X -X -X ,X*X-XGXAX)X%X1X%X1X%X1X%X1X%X!ZEZ%X9WCX.X/X'X/X'X/X'X/X LXNX AX7X NWFW !W ,W ,W ,W ,W ,W "
3490 ",]:X=Y .X9X LX9X LX9X LX9X LW ,W ,W ,W +Z=X K[<X LX:X KX:X KX:X KX:X KX:X 3Z GX<Z KW6W MW6W MW6W MW6W NW9X J[;X NW9X NU<V=V.U#V.UDZNYDV.U8YDV.U#V&"
3491 "V 5X9W %~X3]<T >x A` J~\\(y%W8W MW4W CXMW >W>W MV $x DX $VCV\"XFS 9XIXEV H_ <W #W ;YHTHY -V JV 3X4X >X #Y ?g AVBX Do HXM"
3492 "k 3Y >l HX7Z MX -X Me J~X Je =Y >V?hNUBU8XBX Ju MX *X*X,w Lq IX *~R'X -X -c 8X -XHVBVHX0XFWAX)X%X.X9Y!X%X.X;Z Ke ,X <X/X$X:X LXBVEVBX+_ 9` +Y CW +V \""
3493 "W %W IZ9X NX .X9Z MW7W JW /X9Z MZ;X LW ,W ,WDY AW ,Z;[;W<Z;X MY:Y LZ9X X9Z MZ 2W )W ,W6W NX:X KWAVNVAW*YGY EW:W 4Z 3W :V MW ?XMYIe,X>WNV MW"
3494 "Ib +W EW;Y MW *Z;X KV:W =_ @W6W NW%W/XFWFX NW=W JWCWCW NW8X!Y:Y =W >| GW@W 8Y @X 0X%X1Y@X@Y-X0X(X@X@X/XImIX*Y GV HY @V AY1Y @V CV /XDS 6X 0YDY JdL"
3495 "d LV 1WF[ >SFV'S<WBY 6XFX MS@VAVAS @~W/W JU >W6W LgGU KU 3WCW ?XFX 7U:V FU:V >UBV AX 3XBX CXBX CXBX CXBX CXBX CXBX BXAw?X *w Lw Lw Lw "
3496 "LX -X -X -X ,X*X-XFWAX)X%X1X%X1X%X1X%X1X%X ZGZ$X:WBX.X/X'X/X'X/X'X/X K` @X7X NWFW W ,W ,W ,W ,W ,W ,[8W=X -W7W LW7W LW7W LW7W LW ,W ,W ,W ,Y:X LZ;X M"
3497 "Y:Y MY:Y MY:Y MY:Y MY:Y \"Y=\\ LW6W MW6W MW6W MW6W MW:W IZ9X NW:W NV<V=V/V#V/VCcCV/V9YCV/V=X>V&V 4W:X %~X2TNV<S =y KWM^LW$~Z({&W7V MW4W CWLX ?"
3498 "X?W MV KX ,X %VBV!XGS 9gFV Ha >W \"W ;WFTFW -V JV 3X4X >X #Y ?f AWBX Dp IXNm 4X <j GX7Z MX -X !e G~X Ge AY =U?ZH^BU8W@W Jt "
3499 "LX *X*X,w Lq IX *~R'X -X -b 7X -XHWDWHX0XFXBX)X%X.X:Y X%X.X<Z Ih 0X <X/X#X<X KXBVEVBX*] 8` ,Z CW +V \"W %W IZ9X X -X9Z NX7X KW /X9Z MY9W LW ,W ,W"
3500 "EY @W ,Y:Z:W<Y9W MX8X LZ9X X9Z MY 1W )W ,W6W MW:W JWAVNVAW)XGX DW:W 4Y 3X :V MW @VHXKWGV,W<^ MWIa *W FW9Y NW *Y9W KW<X >` @W6W NW%W/WEWEW NW=W JW"
3501 "CWCW X8X!X8X =W >| GW@W 7Y AX 0X%X1X?X?X-X0X(X@X@X/XImIX+Y FV GY AV BY/Y AV DX 1XCS 6X 0W@X KdLd LV 1VCZ ?SFV'S;WE[ 7XFX G~X .S@VBWAS @~W0W "
3502 ".P>W >W6W KfGU KU 3XEX >XFX 8U;V:W3U;VCZ9P>WCV:W/Y 3W@W CW@W CW@W CW@W CW@W CXBX CX@w?X *w Lw Lw Lw LX -X -X -X 5p9X-XFXBX)X%X1X%X1X%X1X%X1X%X N"
3503 "ZIZ#X:VAX.X/X'X/X'X/X'X/X K` @X7X NWFW W ,W ,W ,W ,W ,W ,[8X?X -X7X NX7X NX7X NX7X MW ,W ,W ,W ,X9X LY9W MX8X MX8X MX8X MX8X MX8X \"X=] LW6W MW6W MW6"
3504 "W MW6W MW:W IZ9X NW:W NVLuKU/VLuKU/VBaAU/V:YAU/V=X=U&V 4X;X %~X2RLW>T >{!z'~Z)}(W6W NW4W DXLX ?X@X MV KX ,X %VBV!YHS 8eEV"
3505 " Ic ?W !W ;UETEU ,V KW 3X4X >X $Y >c ?WAX DWD^ JbG] 5X 9d DY9[ MX -X #d D~X Dd DY <U@YD\\BU9X@X Kq IX *X*X,w Lq IX *~R'X -X -a 6X -XGVDVGX0XEWB"
3506 "X)X%X.X;Z X%X.X?\\ Gk 4X <X/X#X<X KXBVEVBX)[ 6^ ,Z BW +W #W %W IY7W X -W7Y NW5W KW 0X7Y MY9W LW ,W ,WFY ?W ,Y:Z:W<Y9W MW6W LY7W W7Y MY 1W )W ,W6W"
3507 " MW:W JWBVLVBW(XIX CW;X 5Y 2X :V MX BUDVKVDU.X<] LWI_ :WEW FV7X NW *Y9W JV<X >a AW6W NW%W0XEWEX W=W JWCWCW W6W!X8X =W >| HX@X 7Y BX 0X%X1X?X?X-X0"
3508 "X(X@X@X/XImIX,Y EV FY BV CY-Y BV DX 1XCS 6X 1W>W KeNe LV 1VB[ ASFV'S;YI] 9YGY F~X .S@VDX@S @~W1V ,TEZ >W6W JeGU IX +U 2YIY <YGY :U;V:W3U"
3509 ";VGa<TEZCV:W/X 3X@X EX@X EX@X EX@X EX@X EX@X DX@w?X *w Lw Lw Lw LX -X -X -X 5p9X-XEWBX)X%X1X%X1X%X1X%X1X%X MZKZ\"X;WAX.X/X'X/X'X/X'X/X J^ ?X7X NWFX !W "
3510 ",W ,W ,W ,W ,W ,Z6W?X -W5W NW5W NW5W NW5W MW ,W ,W ,W -X7W LY9W MW6W MW6W MW6W MW6W MW6W \"W=^ LW6W MW6W MW6W MW6W MW;X IY7W NW;X NVLuKU/VLuKU/VA_"
3511 "@U/V;Y@U/V=X=U&V 4X<X $~X,W>T ?|\"}(~X)~(W6W NW4W DXKW >W@X MV KX ,X %VBV!ZIS 7cEV IYNZ8W 0W !W :RCTCR +V KW 3X4X >X %Y"
3512 " =b >V@X DS=\\ K`C[ 6Y 8b BX9[ Nd A~X Ad HY <VAX@ZBV:X?W Kq IX *X*X,w Lq IX *~R'X -X -a 6X -XGVDVGX0XEXCX)X%X.X=[ NX%X.u Fl 6X <X/X\"W<W IWCWEVBW([ "
3513 "5\\ ,Z AW +W #W $V IY7X\"X -X7Y NW5W KW 0X7Y MX8X MW ,W ,WHZ >W ,X8X8W=X8X X6X MY7X\"X7Y MX 0W )W ,W6W MX<X IWCVLVCW&XKX AW<W 5Y 1W 9V LW 4P /TB"
3514 "VMVBT.X;\\ LWI` =\\HW GW7X NW *X8X KV=X >XMW AW6W NW%W0XEWDW W=W JWCWCW!X6X#X6X >W >| HW>W 6Y CX 0X%X1X?X?X-X0X'XAXAX.XImIX-Y DV EY CV DY+Y CV DX 2X"
3515 "BS 6X 1V<V KeNe LV 2V?Y ASFV'S:dNV :XFY E~X .S@i?S @~W2i >h =W6W JeGU IX 4g :g :YFX DgEV:X<gEVHe>hCV:X/X 3X?W EX?W EX?W EX?W EX?W EX@X EX?w?"
3516 "X *w Lw Lw Lw LX -X -X -X 5p9X-XEXCX)X%X1X%X1X%X1X%X1X%X LZMZ!X<W@X.X/X'X/X'X/X'X/X I\\ >X7X NWFY !V +V +V +V +V +V +Y6W@X ,W5W NW5W NW5W NW5W MW ,W ,W"
3517 " ,W -X7X MX8X X6X X6X X6X X6X X6X $X=_ MW6W MW6W MW6W MW6W LW<W HY7X NW<W MVLuKU/VLuKU/V@]?U/V<Y?U/V=X=U&V 3W<X $~X+V>S >}%~R)~V(~P)W6W NW4W"
3518 " DWJX ?XAW L~^ $X ,X %VCV N\\LS 6aDVAW0XLZ9W 0W !W :PATAP +V KV 2X4X >X &Z =e BW@X DP8[ L^?Z 7X :h EY;\\ \"d >~X ?e LY ;U@W>Y"
3519 "AU:W>W Ks KX *X*X,w Lq IX6f+~R'X -X -b 7X -XGWFWGX0XDWCX)X%X.X@^ NX%X.s Bl 8X <X/X\"X>X IXDVCVDX)[ 4\\ -Z @W *V #W $W JX5W\"X -W5X W4W KW 0W5X MX7W"
3520 " MW ,W ,WIZ =W ,X8X8W=X7W W4W MX5W\"W5X MX 0X *W ,W6W LW<W HWCVLVCW&YMY AW=X 6Y 1X 9V LX 1X.Q /TA]AU/W:\\ LWIb A`JW GV5X NW +X7W KW>X >XMX BW6W W#W1WD"
3521 "WDW W=W JWCWCW!W4W#X6X >W >| HW>W 7Y BX 0X%X1X?X?X-X0X'XAXAX.XImIX.Y CV DY DV EY)Y DV DX 2XBS 6X 2W<W =^ =V 2V>Y BSFV'S9bMV ;XFY D~X .S@h>S "
3522 "@~W2i >g <W6W HcGU IX 4g 9e 8YFX EgEV;Y<gEVHf?gBV;Y0Y 3W>W EW>W EW>W EW>W EW>W EW>W EX?w?X *w Lw Lw Lw LX -X -X -X 5p9X-XDWCX)X%X1X%X1X%X1X%X1X%X "
3523 "Ke X=W?X.X/X'X/X'X/X'X/X I\\ >X7X NWEY \"W ,W ,W ,W ,W ,W ,X5W@X -W4W W4W W4W W4W MW ,W ,W ,W -W6X MX7W W4W W4W W4W W4W W4W $W=VMW MW6W MW6W MW6W MW6W "
3524 "LW=X HX5W NW=X MVLuKU/VLuKU/V?[>U/V=Y>U/V=X=U&V 3X=W 7X FW@T ?~&~T*~V)~R*W5V NW4W EXJX ?XBX L~^ $X ,X &VBV Mb 4]CVC]4XJZ:W"
3525 " 0W !W +T KV KV 2X4X >X 'Z <g EW?X +Z L]=Z 9Y <l GZ=] %e e!Y :UAW<XAU;X>X Lu MX *X*X,w Lq IX6f+~R'X -X -c 8X -XFVFVFX0XDXDX)X%X.u MX%X.r"
3526 " ?l :X <X/X\"X>X IXDVCVDX)\\ 4Z ,Y ?W *V #W $W JX5W\"W ,W5X W3W LW 0W5X MX7W MW ,W ,WJY ;W ,X8X8W=X7W W4W MX5W\"W5X MX 0X *W ,W6W LW<W HWCVKUCW%XMX "
3527 "?W>W 6Y 0X 9V LX 5`3R 0T?[?T/W:[ KWId DbKW HW5X NW +X7W JV>W =WLX BW6W W#W1WDWDW W=W JWCWCW!W4W#W4W >W >| IX>X 9Y AX 0X%X1X?X?X-X0X'XAXAX.XImIX/Y B"
3528 "V CY EV FY'Y EV DX 2WAS ?r CV:V =^ =V 2V=Y CSFV'S8`LV <XFX B~X .S@e;S @~W2i >e :W6W GbGU IX 4g 8c 5XFX FgFV:Y<gFVGg@eAV:Y1Y 3X>X GX>X GX>"
3529 "X GX>X GX>X GX>X FX?w?X *w Lw Lw Lw LX -X -X -X 5p9X-XDXDX)X%X1X%X1X%X1X%X1X%X Jc NX>W>X.X/X'X/X'X/X'X/X HZ =X7X NWEZ #W ,W ,W ,W ,W ,W ,X4WAW ,W3W!W3"
3530 "W!W3W!W3W NW ,W ,W ,W .X5W MX7W W4W W4W W4W W4W W4W $W>VLW MW6W MW6W MW6W MW6W KW>W GX5W MW>W LVLuKU/VLuKU/V>Z>U/V>Y=U/V=X=U&V 2W>X 8Y FW@T "
3531 " ?~P(~V*~T(~Q)V4V NW4W EXJX >WBX L~^ $X ,X &VBV Ld 4WAVD`6XHZ;W 0W !W +T KV LW 2X4X >X 'Y ;i GV>X *Z M\\;Y 9X =p HZ?^ 'd "
3532 " Id$Y 9UAW<XAU;W<W Lw X *X*X,w Lq IX6f+~R'X -X -d 9X -XFVFVFX0XCWDX)X%X.t LX%X.p ;k ;X <X/X!X@X HXDVCVDX*^ 4X ,Z ?W *W $W $W JX5W\"W ,W5X W3W LW"
3533 " 0W5X MW6W MW ,W ,WKY :W ,W7W7W=W6W W4W MX5W\"W5X MX /Y ,W ,W6W LX>X GWEVJVEW#a >W>W 7Y 1Y 8V KY 9e8T 0T?Z>T0X:[ KWIf GdLW HW4W MW ,W6W JV?X >XKW BW6"
3534 "W W#W2XDWDX!W=W JWCWCW!W4W#W4W >W >| IW<W :Y @X 0X%X1X?X?X-X0X&XBXBX-XImIX0Y AV BY FV GY%Y FV DX 2WAS ?r DW:W =\\ <V 2V;W CSFV'S7]JV =XFX A~X .S"
3535 "@d:S (V Ii <a 8W6W FaGU IX 4g 6_ 2XFX GgGV:Z<gGVFUFY?a@V:Z2Y 2W<W GW<W GW<W GW<W GW<W GX>X GX>w?X *w Lw Lw Lw LX -X -X -X 5p9X-XCWDX)X%X1X%X1X%",
3537 "X1X%X1X%X Ia MX?W=X.X/X'X/X'X/X'X/X GX <X7X NWDZ $W ,W ,W ,W ,W ,W ,X4WAW ,W3W!W3W!W3W!W3W NW ,W ,W ,W .W4W MW6W W4W W4W W4W W4W W4W $W?VKW MW6W MW6W"
3538 " MW6W MW6W KW>W GX5W MW>W LVLuKU/VLuKU/V?\\?U/V?Y<U/V=X=U&V 2W>X 8X DWBT ?~Q)~W)~R&~(V4V NW4W EWHW >WBW K~^ $X ,X &VBV Kg \""
3539 "VEc8WFZ=W /W !W +T 4~W 5V 1X4X >X (Y -] IW>X )Y M[9X 9X >\\F\\ H[C` 'a Ca$Y 9UAV:WAU;W<W LX<\\!X *X*X,X -X 0X6f+X/X'X -X -XN[ :X -XEVHVEX0XCX"
3540 "EX)X%X.s KX%X.o 6h <X <X/X!X@X GWDVCVDW*_ 4X -Z >W )V $W 6i JX5X$X -X5X V2W LW 1W3W MW6W MW ,W ,WLY 9W ,W7W7W=W6W!X4X NX5X$X5X MW .[ .W ,W6W KW>"
3541 "W FWEVJVEW#a >W?X 8Z 4\\ 8V K[ =i<V 0S=Y=S0X:[ KW@^ IfMW HW4W MY .W6W JW@W =XKX CW6W W#W2WCWCW!W=W JWCWCW\"X4X%X4X ?W >W2W IW<W :Y @X 0X%X1X?X?X-X0X&X"
3542 "BXBX-X%X1~` GV H~` GV H~` GV DX 3XAS ?r DV8V =\\ <V 2V;X DSFV'S4W /XFX @~X .S@VIX;S (V Ii 8Z 5W6W D_GU IX 4g 3Y .XFX HgGV;TNU<gGVFQ@W;Z=V;T"
3543 "NU3Y 1W<W GW<W GW<W GW<W GW<W GW<W GX>X X *X -X -X -X -X -X -X -X ,X*X-XCXEX)X%X1X%X1X%X1X%X1X%X H_ LX@W<X.X/X'X/X'X/X'X/X GX <X7X NWD\\ 8i >i >i >i >i"
3544 " >i >i3WBX ,V2W!V2W!V2W!V2W NW ,W ,W ,W .W4W MW6W!X4X\"X4X\"X4X\"X4X\"X4X M~Y2X@VIW NW6W MW6W MW6W MW6W KW?X GX5X NW?X LVLuKU/VLuKU/V@^@U/V@Y;U/V=X=U&"
3545 "V 2X?W 8X CWBT ?~R*~X)~Q%}(V4W W4W FXHX ?XDX K~^ $X ,X 'WCV Ii &VEe:XEZ>W /W !W +T 4~W 5V 1X4X >X )Y )[ KW=X (Y N[9Y ;Y "
3546 "?Z@Z I]Gb '^ =^$X 9U@V:WAU<X<X MX9Z\"X *X*X,X -X 0X6f+X/X'X -X -XM[ ;X -XEVHVEX0XBWEX)X%X.r JX%X.q 4e =X <X/X!X@X GXFVAVFX*` 5X .Z =W )V $W "
3547 " :m JW3W$W ,W3W!W2W LW 1W3W MW6W MW ,W ,WMY 8W ,W7W7W=W6W!W2W NW3W$W3W MW -^ 2W ,W6W KX@X FWEVJVEW\"_ <W@W 7Y :b 7V Jb FmAX 0S<W<S0W8Y JW<[ KYHVMV GV"
3548 "3X MZ 0W6W IVAX >XIW CW6W!W!W3WCWCW!W=W JWCWCW\"W2W%W3X ?W >W2W JW;X <Y ?X 0X&Y1X?X?X-X0X&YCXCY-X%X2~a GV H~a HV I~b HV DX 3W@S ?r DV8V <Z ;V 2W;W "
3549 "DSFV'S <XFX =V .S@VGW<S (V \"W6W A\\GU IX 2XFX *V;TMU LV2V V;TMU4Z 2X<X IX<X IX<X IX<X IX<X IX<X IX=X X *X -X -X -X -X -X -X -X ,X*X-XB"
3550 "WEX)X%X1X%X1X%X1X%X1X%X G] KX@V;X.X/X'X/X'X/X'X/X GX <X8Y NWC\\ =m Bm Bm Bm Bm Bm Bm3WBW ,W2W\"W2W\"W2W\"W2W NW ,W ,W ,W /X4X NW6W!W2W\"W2W\"W2W\"W2W\"W2W M~Y"
3551 "2W@VHW NW6W MW6W MW6W MW6W JW@W FW3W MW@W KVLuKU/VLuKU/VA`AU/VAY:U/V=X=U&V 1W@X 9X BWBS >~R+~Z*~P#{'V4W W4W FXHX ?XDX K~^ $X "
3552 " ,X 'VBV Gi (VFg;WCZ?W /W !W +T 4~W 6W 1X4X >X *Y &Z LW=X (Y NZ7X ;X ?Z>Z ImNX '[ 8\\%Y 9UAW:WAU<W:W MX7Y#X *X*X,X -X 0X6f+X/X'X -X -XL[ "
3553 "<X -XEWJWEX0XBXFX)X%X.p HX%X.r 0a >X <X/X XBX FXFVAVFX+b 6X /Z <W )W %W =p JW3W$W ,W3W!| LW 1W3W MW6W MW ,W ,WNY 7W ,W7W7W=W6W!W2W NW3W$W3W MW -"
3554 "b 6W ,W6W JW@W EWFVHVFW!] ;WAX 8Y 9` 5V H` HrG[ 0S<W<S0W8Y JW:Y KXF^ HW2W Kc ;W6W IVAX >XIW CW6W!W!W3WCWCW!W=W JWCWCW\"W2W%W2W ?W >W2W JW:W =Y >X 0Y'"
3555 "X0X?X?X-X0X%XCXCX,X%X2~a GV H~a HV I~b HV DX 3W@S ?r DV8V <Z FW;W DSFV'S =XFX <V .S@VFW=S (V \"W6W <WGU IX 1XFX +V;SLU LV2V V;SL"
3556 "U5Z 1W:W IW:W IW:W IW:W IW:W IX<X IX=X X *X -X -X -X -X -X -X -X ,X*X-XBXFX)X%X1X%X1X%X1X%X1X%X F[ JXAW;X.X/X'X/X'X/X'X/X GX <X8X MWB] Bp Ep Ep Ep Ep "
3557 "Ep E~eBW ,|\"|\"|\"| NW ,W ,W ,W /W2W NW6W!W2W\"W2W\"W2W\"W2W\"W2W M~Y2WAWHW NW6W MW6W MW6W MW6W JWAX FW3W MWAX KV<V=V/V#V/VBbCV/VBY:V/V=X>V&V 1XAW 9"
3558 "X @WDT ?~S+~Z)}!y'W4W W4W FWFW >WDW J~^ *r ?V &VBV Eh *VEXIX<XBZ@W /W !W +T 4~W 5f 8V 0X4X >X +Y $Z NW<X 'X NZ7X ;X ?X:X HkMX "
3559 " '[ 7[%X 8UAV8VAU=X:X NX6X#X *X*X,X -X 0X6f+X/X'X -X -XK[ =X -XDVJVDX0XAWFX)X%X.m EX%X.XA\\ -^ ?X <X/X XBX FXFVAVFX,c 6X /Y ;W (V %W ?r JW3W"
3560 "$W ,W3W!| LW 1W3W MW6W MW ,W ,a 6W ,W7W7W=W6W!W2W NW3W$W3W MW ,e :W ,W6W JW@W DWGVHVGW N[ 9WBW 8Y 8^ 3V F^ I~X 0S;U;T1W8Y JW8X MXC\\ HW2W Ia ;W6W IWB"
3561 "W >XHX DW6W!W<W<W3WCWCW!W=W JWCWCW\"W2W%W2W ?W >W2W KX:X ?Y =X /X'X0Y@X@Y-X0X%YDXDY,X%X2~a GV H~a HV I~b HV DX 3W@S ?r DV8V ;X DW;V DSFV'S >XFX "
3562 " ;V .S@VFW=S (V \"W6W :UGU IX 0XFX -V;TLU MV0U!V;TLU6Y 0X:X KX:X KX:X KX:X KX:X KX:X JW<X X *X -X -X -X -X -X -X -X ,X*X-XAWFX)X%X1X%X1X"
3563 "%X1X%X1X%X F[ JXBW:X.X/X'X/X'X/X'X/X GX <X9Y MWA] Er Gr Gr Gr Gr Gr G~gBW ,|\"|\"|\"| NW ,W ,W ,W /W2W NW6W!W2W\"W2W\"W2W\"W2W\"W2W M~Y2WBWGW NW6W MW6W MW6W "
3564 "MW6W IWBW EW3W LWBW IU<V=V.U#V.UCdDV.UCY9V.U=X>V&V 1XBX :X ?WDT ?~S,~[({ x&W4W W4W FWFX ?XFX JV \"q >V &VBV Af -VEXGX=W@ZB"
3565 "W .W !W +T 4~W 5f 8V 0X4X >X ,Y \"Y W;X 'X NZ7X <Y @Y:Y HiLX '^ =^%X 8UAV8VAU=X:X NX5X$X *X*X,X -X 0X(X+X/X'X -X -XJ[ >X -XDVJVDX0XAXGX)X%X.i"
3566 " AX%X.X>Z ,\\ ?X <X/X NWBW DWFVAVFW+XMY 7X 0Z ;W (V %W @s JW3W$W ,W3W!| LW 1W3W MW6W MW ,W ,` 5W ,W7W7W=W6W!W2W NW3W$W3W MW +g =W ,W6W JXBX DWGVH"
3567 "VGW N[ 9WBW 9Y 7^ 3V F^ I[Gr /S;U;T1W8X IW7X NWA[ HW2W F^ ;W6W HVCX >XGW DW6W!W<W<W3WCWCW!W=W JWCWCW\"W2W%W2W ?W >W2W KW9X ?Y =X /X'X/X@X@X,X0X$YEXEY"
3568 "+X%X2~a GV H~a HV I~b HV DX 3W@S 6X 3V8V ;X DX<V DTFV)T >WEW :V .TAVEW?T (V \"W6W :UGU IX /WEW .V;TKU NV/U\"V;TKU7Y /X:X KX:X KX:"
3569 "X KX:X KX:X KX:X KX<X X *X -X -X -X -X -X -X -X ,X*X-XAXGX)X%X1X%X1X%X1X%X1X%X G] KXCW9X.X/X'X/X'X/X'X/X GX <X9Y MW?] Hs Hs Hs Hs Hs Hs H~hBW ,|\"|\"|\"|"
3570 " NW ,W ,W ,W /W2W NW6W!W2W\"W2W\"W2W\"W2W\"W2W M~Y2WBVFW NW6W MW6W MW6W MW6W IWBW EW3W LWBW IU<V=V.U#V.UDYMZEV.UDY8V.U#V&V 0WBX ;X >WDS >~T-~\\(y"
3571 " Mw&W4W W4W GXFX ?XFX JV #r >V 'WCV <c .VEWEW=W?ZCW .W !W :~W 5f 9W 0X4X >X -Y Y!W;X 'Y Y5X =X @Y8Y HgKX 'a Ca%X 8UAV8"
3572 "VAU=W8W NX4X%X *X+Y,X -X 0X(X+X/X'X -X -XI[ ?X -XDWLWDX0X@WGX)X&Y.X 0X&Y.X=Y *[ @X <X/X NXDX DXHW@VHX,YMZ 8X 1Z :W (W &W At JW3W$W ,W3W!| LW 1W3"
3573 "W MW6W MW ,W ,` 5W ,W7W7W=W6W!W2W NW3W$W3W MW )g ?W ,W6W IWBW CWGVHVGW MY 8WCX :Y 6` 5V H` IW@m -S;V<T1W8X IW7X W@[ HW2W Ia ;W6W HVCW >XFX EW6W!W<W<"
3574 "W3WCWCW!W=W JWCWCW\"W2W%W2W ?W >W2W KW8W @Y <X /X'X/X@X@X,X0X#YFXFY*X&Y2~a GV H~a HV I~b HV DX 3W@S 6X 3V8V ;X CX=V CSFV)S =WEW :V -SAVDW@S "
3575 " 'V \"W6W :UGU IX /WEW .V<TJU NV/U\"V<TJU8Z /W8W KW8W KW8W KW8W KW8W KX:X KX<X X *X -X -X -X -X -X -X -X ,X+Y-X@WGX)X&Y1X&Y1X&Y1X&Y1X&Y H_ LX"
3576 "DW9Y.X/X'X/X'X/X'X/X GX <X:Y LW>] Jt It It It It It I~iBW ,|\"|\"|\"| NW ,W ,W ,W /W2W NW6W!W2W\"W2W\"W2W\"W2W\"W2W M~Y2WCVEW NW6W MW6W MW6W MW6W IWCX EW3W L"
3577 "WCX IV=V=V.V$V.VFYKZFV.VFY7V.V$V&V 0XCW ;Y =WFT >~T-~\\'w Ku%W4W W4W GXEW >WFW IV #q =V 6~X JSN^ /VEWCW?W=ZDW .W !W :~W"
3578 " 5f 9V /X4X >X .Y MX\"W:X &X Y5X >Y @X6X FcJX &d Id%X 8UAV8VAU>X8X X4X$X +X+X+X -X /X)X+X/X'X -X -XH[ @X -XCVLVCX0X@XHX(X'X-X /X'X-X<Y *Z @X "
3579 "<X/X NXDX DXHV?VHX-YKY 8X 2Z 9W 'V &W B]?W JW3W$W ,W3W!| LW 1W3W MW6W MW ,W ,a 6W ,W7W7W=W6W!W2W NW3W$W3W MW 'g AW ,W6W IWBW CWHVFVHW NZ 7WDW :Z"
3580 " 6a 6V Jb IU;i ,S;V<S0W7W IW6W W?Z HW2W Kc ;W6W HWEX >XFX EW6W!W<W<W3WCWCW!W=W JWCWCW\"W2W%W2W ?W =V2V KX8X BY ;X /Y)Y/X@X@X,X0X#YFXGZ)X'X0~` GV H~` "
3581 "GV H~` GV DX 3W@S 6X 3V8V M| &Z?V CSFV)S:m AXFX ;V -SAVDW@S 'V \"W6W :UGU *m 5XFX /V;SIU V.T\"V;SIU9Z /X8X MX8X MX8X MX8X MX8X MX8X "
3582 "MX;X NX +X -X -X -X -X -X -X -X ,X+X,X@XHX(X'X/X'X/X'X/X'X/X'X Ha LXFW8X-X/X'X/X'X/X'X/X GX <X;Z LW<\\ L]?W J]?W J]?W J]?W J]?W J]?W J]?{BW ,|\"|\"|\"| NW"
3583 " ,W ,W ,W /W2W NW6W!W2W\"W2W\"W2W\"W2W\"W2W M~Y2WDVDW NW6W MW6W MW6W MW6W HWDW DW3W KWDW HV=V>V-V%V-VGYIZHV-VGY7V-V%V%V /WDX ;X <WFT >~T-~\\'v Is"
3584 "$W4W W4W GWDX ?XGW HV %r =V 6~X JSJ[ 0VEVAV?W<ZFW -W !W \"V Lf 9V /X5X =X /Z MX\"V9X &X NX5X >X ?X6X D`IX $d Ne#X 8UAV8"
3585 "VBU=x X4X$X +X+X+X -X /X)X+X/X'X -X -XG[ AX -XCVLVCX0X?WHX(X'X-X /X'X-X;Y *Y @X <X/X MXFX CXHV?VHX-XIY 9X 3Z 8W 'V &W CZ;W JW3W$W ,W3W!| LW 1W3W"
3586 " MW6W MW ,W ,b 7W ,W7W7W=W6W!W2W NW3W$W3W MW %f BW ,W6W IXDX BWIVFVIW N\\ 8WEX :Y .[ 7V K\\ BT8e *S<X=S0W7V HW6X\"W=X GW2W Me ;W6W GVEX >WDW EW6W!W<W<W"
3587 "3WCWCW!W=W JWCWCW\"W2W%W2W ?W =W4W KW6W CY :X .X)X.YAXAY,X0X\"ZHXHZ(X'X/Y AV BY FV GY%Y FV DX 3W@S 6X 2V:V L| %ZAV BSEV*S:m @XFX <V -SAVCWAS "
3588 " 'V \"W6W :UGU *m 6XFX .V<TIU V/U\"V<TIU9Y .x Mx Mx Mx Mx Mx Mu NX +X -X -X -X -X -X -X -X ,X+X,X?WHX(X'X/X'X/X'X/X'X/X'X Ic MXGW7X-X/X'X/X'X/"
3589 "X'X/X GX <X=[ KW:[ NZ;W KZ;W KZ;W KZ;W KZ;W KZ;W KZ;{BW ,|\"|\"|\"| NW ,W ,W ,W /W2W NW6W!W2W\"W2W\"W2W\"W2W\"W2W &WEVCW NW6W MW6W MW6W MW6W HWEX DW3W KWEX "
3590 " GV>V>V,V&V,VIYGZIV,VIY6V,V&V&W /XEW N~X'VGT =~T-~\\&u Ir#W4W NV4W HXDX ?XHX HV KX ,V 6~X JSHZ 2VDVAV?W;ZGW -W !W \"V "
3591 "Lf :W .X6X =X 0Z LY#~ /X NX5X >X @X5Y AYFX !d >~X >d X 8UAV8VBU>z!X3X%X +X+X+X -X /X)X+X/X'X -X -XF[ BX -XCWNWCX0X?XIX(X'X-X /X'X-X:X )Y AX <X/X"
3592 " MXFX BWHV?VHW-YIY 9X 3Y 7W 'W 'W CX9W JW3W$W ,W3W!W 'W 1W3W MW6W MW ,W ,WNZ 8W ,W7W7W=W6W!W2W NW3W$W3W MW !c CW ,W6W HWDW AWIVFVIW N] 8WFW :Y *"
3593 "Y 8V KY ?R3` (S<X=S0W7V HW5W\"W=X GW2W N[ 0W6W GWFW >XDX FW6W!W<W<W3WCWCW!W=W JWCWCW\"W2W%W2W ?W =W4W LX6X DY :X .X)X-XAXAX+X0X!ZIXIZ'X'X.Y BV CY EV"
3594 " FY'Y EV DX 3W@S 6X 2V:V L| $[CV BTFW,T:m ?XFX =V -TBVBVBT 'V \"W6W :UGU *m 7XFX .V<THU!V/U\"V<THU:Y .z z z z z Nx Nv NX +X -X -X -X"
3595 " -X -X -X -X ,X+X,X?XIX(X'X/X'X/X'X/X'X/X'X Je NXGV6X-X/X'X/X'X/X'X/X GX <X@^ KW9[ X9W KX9W KX9W KX9W KX9W KX9W KX9W MW ,W ,W ,W ,W )W ,W ,W ,W /W2W N"
3596 "W6W!W2W\"W2W\"W2W\"W2W\"W2W &WFVBW NW6W MW6W MW6W MW6W GWFW CW3W JWFW FV>V?W,V'W,VJYEZKW,VJY6W,V'W&W /XFX N~X'WHT =~T-~\\%s Gp\"W4W NV4V GXCW >WH"
3597 "X HW LX ,V 6~X JSGY 3VDWAW@W:ZIW ,W !W \"V Lf :W .X6X =X 1Z JX#~ /X NX5X ?Y @X4X .X Md A~X Ad LX 8UAV8VBU>z!X3X%X +X+X+"
3598 "X -X /X)X+X/X'X -X -XE[ CX -XBVNVBX0X>WIX(X'X-X /X'X-X9X *Y AX <X/X MXFX BXJW?WJX.YGY :X 4Z 7W 'W 'W DX8W JW3W$W ,W3W!W 'W 1W3W MW6W MW ,W ,WLY "
3599 "9W ,W7W7W=W6W!W2W NW3W$W3W MW K_ DW ,W6W HXFX AWIVFVIW ^ 8WFW ;Y (Y 9V LY >Q.X $T>Z?T0W8W HW5W\"W<W GW2W Y -W6W GWGX >WCX FW6W!W<W<W3WCWCW!W=W JWCWC"
3600 "W\"W2W%W2W ?W =W4W LX6X EY 9X .Y+Y-YBXBY+X0X ZJXJZ&X'X-Y CV DY DV EY)Y DV DX 3W@S 6X 2W<W L| #\\FW ASFW,S9m >XFX >V ,SBVBWCS &V \"W6W :U"
3601 "GU *m 8XFX .V<TGU\"V.U#V<TGU;Y -z z z z z z v NX +X -X -X -X -X -X -X -X ,X+X,X>WIX(X'X/X'X/X'X/X'X/X'X KZMZ XHW6X-X/X'X/X'X/X'X/X GX <u JW7Y!X8W "
3602 "LX8W LX8W LX8W LX8W LX8W LX8W MW ,W ,W ,W ,W )W ,W ,W ,W /W2W NW6W!W2W\"W2W\"W2W\"W2W\"W2W &WGWBW NW6W MW6W MW6W MW6W GWFW CW3W JWFW FW?V?V+W(V+WKXCY"
3603 "KV+WKX5V+W(V%W .WFX N~X'WHT =~T-~\\$q Eo\"W4W NV4V GWBW >XIW GW LX ;~X JSFX 3VDV?V@W9ZJW +V \"W !V V -X6X =X 2Z IX#"
3604 "~ /X NX5X ?X ?X4X .X Jd D~X Dd IX 8UAV8VCV>z!X3X%Y ,X,Y+X -X /Y*X+X/X'X -X -XD[ DX -XBVNVBX0X>XJX(Y)X,X /Y)X,X9Y *X AX <X/X LXHX AXJV=VJX.XEY ;X 5"
3605 "Z 6W &V 'W DW7W JW3W$W ,W3W!W 'W 1W3W MW6W MW ,W ,WKY :W ,W7W7W=W6W!W2W NW3W$W3W MW H\\ DW ,W6W GWFW @WJVDVJW!` 9WGX <Y &X 9V LX =P (T?\\@T0W8"
3606 "X IW5W\"W<W GW2W X ,W6W FVGW >XBW FW6W!W<W<W3WCWCW!W=W JWCWCW\"W2W%W2W ?W =W4W LW4W FY 8X -X+X+YCXCY*X0X N\\MXM\\%Y)X+Y DV EY NQFVFQ Y+Y CV DX 3W@S 6X"
3607 " 1V<V K| ![HW @TFW.T9m =XFX ?V ,TCVAVDT &V \"W6W :UGU *m 9XFX -V<SFU\"V/U\"V<SFU;X ,z z z z z z v NY ,X -X -X -X -X -X -X -X ,X,Y,X>XJX"
3608 "(Y)X.Y)X.Y)X.Y)X.Y)X KZKZ!YJW6X,X/X'X/X'X/X'X/X GX <t IW6Y\"W7W LW7W LW7W LW7W LW7W LW7W LW7W MW ,W ,W ,W ,W )W ,W ,W ,W /W2W NW6W!W2W\"W2W\"W2W\"W2W\"W2W "
3609 " &WHWAW NW6W MW6W MW6W MW6W GWGX CW3W JWGX EV?V@W*V)W*VJVAWKW*VJV5W*V)W%W .XGW M~X&WJT <~S,kNn#o Cm!W4W NV4V HXBX ?XJX FW MY"
3610 " <~X JSEX 5VCV?V@W8ZLW *W #W !V V -X6X =X 3Z HX#~ /X NX5X @Y ?X4X /X Ge G~X Ge GX 8UAV9WCU>|\"X3X$X ,X,X*X -X .X*X+X/X'X -X -XC[ EX"
3611 " -XA\\AX0X=WJX'X)X,X .X)X,X8X *X AX <X/X LXHX AXJV=VJX/YEY ;X 6Z 5W &V 'W DW7W JW3W$W ,W3W!W 'W 1W3W MW6W MW ,W ,WJY ;W ,W7W7W=W6W!W2W NW3W$W3W M"
3612 "W EZ EW ,W6W GWFW ?WKVDVKW!b 9WHW <Y $W 9V LW BTAVNUAT/W8X IW5W#W;V FW2W!X +W6W FWIX >XBX GW6W!W<W<W3WCWCW!W=W JWCWCW\"W2W%W2W ?W =W4W MX4X HY 7X"
3613 " -Y-Y+ZDXDZ*X0X Mt#X)X*Y EV FY NSGVGS Y-Y MQFVFQ X 3W@S 6X 1W>W 9X =\\KW >SEW<PCS 6XFX @V +SCVAWES %V \"W6W :UGU &XFX -V<TFU#V"
3614 "/U\"V<TFU<X ,|\"|\"|\"|\"|\"|\"w MX ,X -X -X -X -X -X -X -X ,X,X+X=WJX'X)X-X)X-X)X-X)X-X)X LZIZ!XKW5X,X/X'X/X'X/X'X/X GX <s HW5X\"W7W LW7W LW7W LW7W LW7W LW7W"
3615 " LW7W MW ,W ,W ,W ,W )W ,W ,W ,W /W2W NW6W!W2W\"W2W\"W2W\"W2W\"W2W &WIW@W NW6W MW6W MW6W MW6W FWHW BW3W IWHW DW@VAW)W+W)WJT?UKW)WJT5W)W+W$W -WHX "
3616 "M~X&WJT ;eMQMe+jNQNj!m Bl W4W NW6W HXBX >WJX FW LX <~X JSEX 6WCV?V@W7ZMW *W #W !V !W -X6X =X 4Z GX#~ /X NX5X @X >X4X "
3617 "/X De J~X Je DX 8U@V:WDV>|\"X3X$X ,X-Y*X -X .X*X+X/X'X -X -XB[ FX -XA\\AX0X=XKX'X*Y,X .X*Y,X8Y +X AX <Y1Y KWHW ?WJV=VJW/YCY <X 7Z 4W &W (W EW6"
3618 "W JX5X$X -X5X!X (W 0W5X MW6W MW ,W ,WIY <W ,W7W7W=W6W!X4X NX5X$X5X MW CX EW ,W6W GXHX ?WKVDVKW!XNY :WIX =Y #X :V MX BUCVMVBT/W9Y IW5W#W<W FW3X!W"
3619 " *W6W EVIX ?X@W GW6W!W=Y=W3XDWDX!W=W JWCWCW\"X4X%X4W >W <W6W LX4X HY 7X ,X-X)ZEXEZ)X0X Lr\"X)X)Y FV GY NUHVHU Y/Y MSGVGS !X 3XAS 6X 0W@W 8X ;\\NW "
3620 "=TEX@RDT 5XFY BV +TDV@WGT %V \"W6W :UGU (YFX ,V=TEU#V0U!V=TEU<X ,|\"|\"|\"|\"|\"|\"w MX ,X -X -X -X -X -X -X -X ,X-Y+X=XKX'X*Y-X*Y-X*Y-X*Y-"
3621 "X*Y MZGZ\"XLW5Y,Y1Y'Y1Y'Y1Y'Y1Y GX <r GW4X$W6W MW6W MW6W MW6W MW6W MW6W MW6X NX -X -X -X -X *W ,W ,W ,W /W2W NW6W!X4X\"X4X\"X4X\"X4X\"X4X &WIV@X NW6W MW6W"
3622 " MW6W MW6W FWIX BX5X IWIX CWAVAW(W,W(WJR=SJW(WJR4W(W,W$W -XIX M~X&WJS :dLQLd+iMQNj!l @j NW4W NW6W HW@W >WJW DW MX .VCV"
3623 " :SDW 6VBV?V@W6b )W #W !V !V +X8X <X 5Z FX#~ /X MW5X @X >X4X /X Ad L~X Ld AX 8VAV:WDU=|\"X3X$Y -X-Y*X -X .Y+X+X/X'X -X -XA[ GX -XA\\AX0X<WK"
3624 "X'Y+X+X .Y+Y,X7X +X AX ;X1X JXJX ?XLW=WLX/XAY =X 7Y 3W %V (W EW7X JX5W\"W ,W5X W (W 0W5X MW6W MW ,W ,WHY =W ,W7W7W=W6W W4W MX5W\"W5X MW BX FW ,W6"
3625 "W FWHW >WKVDVKW\"XLX 9WJW =Z #X :V MX AUEVKVDU/X:Y IW5W#W<W EW4W!X *W6W EVJX >X@W GW6W!W=Y=W2WDWDW W=W JWCWCW\"X4W#W4W >W <W6W LW2W IY 6X ,Y/Y(ZFXF"
3626 "Z(X0X Kp!Y+X'Y GV HY NWIVIW Y1Y MUHVHU \"X 2WAS 6X 0YDY 8X :c <TE[FUDS 3XFY CV *SDV@WGS $V \"W6W :UGU )YFX ,V=TDU$V0V\"V=TDU=X +"
3627 "|\"|\"|\"|\"|\"|#x MY -X -X -X -X -X -X -X -X ,X-Y+X<WKX'Y+X,Y+X,Y+X,Y+X,Y+X MZEZ#YNW4X*X1X%X1X%X1X%X1X FX <p EW4X$W7X MW7X MW7X MW7X MW7X MW7X MW7Y MW ,W "
3628 ",W ,W ,W *W ,W ,W ,W .W4W MW6W W4W W4W W4W W4W W4W $WKV?W MW6W MW6W MW6W MW6W EWJW AX5W GWJW BXBVBW'X.W'XJP;QJW'XJP4W'X.W#V ,XIW L~X%WLT :d"
3629 "LQLc*iMQMi k ?i NW4W NW6W IX@X ?XLX DW MY 0VBV :SDW 7VAV?V@X6a )W #W !V !V +X8X <X 6Z EX#~ 0Y MW5X AY >X4X 0X =d ~X"
3630 " d LUAW<XEV>X2X#X3X#X -X.Y)X -X -X+X+X/X'X -X -X@[ HX -X@Z@X0X<XLX&X+X+X -X+X+X7Y ,X AX ;X1X JXJX ?XLV;VLX0YAY =X 8Z 3W %V (W EW7X JX5W\"W ,W5X"
3631 " W (W 0W5X MW6W MW ,W ,WGY >W ,W7W7W=W6W W4W MX5W\"W5X MW BX FW ,W7X FWHW >WLVBVLW#YKX :WJW =Y !W :V MW @VHXJWHV-W:Y IW5W#W<W EW4W!W )W6W EWKX ?X"
3632 "?X HW6W!X>Y>W1WDWDW W=W JWCWCW\"X4W#W4W >W <W6W MX2X KY 5X +Y1Y'[GXH\\(X0X Jn NX+X&Y HV IY NYJVJY Y3Y MWIVIW #X 2WAS 6X 0[H[ 8X :V %` :TEiET 2YGY "
3633 " DV *TEV?WIT $V \"W6W :UGU *YGY ,V<SCU%V0V\"V<SCU=X ,X2X$X2X$X2X$X2X$X2X$X2X$X8X LX -X -X -X -X -X -X -X -X ,X.Y*X<XLX&X+X+X+X+X+X+X+X+X"
3634 "+X NZCZ#`3X*X1X%X1X%X1X%X1X FX <m BW3W$W7X MW7X MW7X MW7X MW7X MW7X MW7Y MW ,W ,W ,W ,W *W ,W ,W ,W .W4W MW6W W4W W4W W4W W4W W4W 5Z IWLV>W MW7X MW7X "
3635 "MW7X MW7X EWJW AX5W GWJW AXCVCW%X0W%X0W%X0W%X0W\"V +WJX ?X 2WLT 9bKQKb)gLQMh Mi =g MW4W MV6W IX@X ?XLX CW MX 0VBV :SDW "
3636 "7VAV?V@X5_ (W #W !V \"W +X8X <X 7Z DX 5X 'X LX7X @X =X4X 0X ;e Le JUAW<XFV=X1W#X3X#Y .X.Y)X -X -Y,X+X/X'X -X -X?[ IX -X@Z@X0X;XMX&Y-Y+"
3637 "X -Y-Y+X6X ,X AX ;X1X IXLX >XLV;VLX1Y?Y >X 9Z 2W %W )W EW7X JX5W\"X -W5X X )W 0X7Y MW6W MW ,W ,WFY ?W ,W7W7W=W6W W4W MX5W\"W5X MW AW FW ,W7X FXJX"
3638 " =WMVBVMW#YJY ;WKX >Y W :V MW ?dId,W;Z IW5W#W=W DW4W!W )W6W DVKW >X>W HW6W W>Y>W1WDWDW W=W JWCWDX\"X4W#W4W >W ;V7W LX2X LY 4X *X1X%]JXJ]'X0X Hj L"
3639 "Y-Y%Y IV JY LYKVKY MY5Y MYJVJY $X 2XBS 6X 2q 9X :V #\\ 7TDgFT /XFX EV )TFV>VJT #V \"W6W :UGU +XFX *V=TCU%V1V!V=TCU=X ,X1W$X1W$X1W"
3640 "$X1W$X1W$X2X%X7X LY .X -X -X -X -X -X -X -X ,X.Y*X;XMX&Y-Y+Y-Y+Y-Y+Y-Y+Y-Y ZAZ$_3Y*X1X%X1X%X1X%X1X FX <i >W3W$W7X MW7X MW7X MW7X MW7X MW7X MW7Z NX -X "
3641 "-X -X -X +W ,W ,W ,W .W4W MW6W W4W W4W W4W W4W W4W 5Z IWMV=W MW7X MW7X MW7X MW7X EWKX AX5W GWKX @XDVDX$X2X$X2X$X2X$X2X\"V +XKW ?X 1WMT 7`JQKa"
3642 "'fLQLf Kg <f LW4W MW8W HW>W >WLW BX NY 1VBV :SDW 8V@V?V?W4] &V $W V \"V *Y:Y <X 8Z DY 5X 'X KW7X @X =X5Y 1Y 8e #e "
3643 " GU@W>YGW>X0X$X4Y\"Y /X/Y(X -X ,Y-X+X/X'X -X -X>[ JX -X@Z@X0X;XMX%Y/Y*X ,Y/Y*X6Y -X AX ;Y3Y IXLX =WLV;VLW0X=Y ?X :Z 1W $V )W EW8Y JY7X\"X -X7Y X "
3644 ")W 0X7Y MW6W MW ,W ,WEY @W ,W7W7W=W6W X6X MY7X\"X7Y MW AW FW ,X8X EWJW <WMVBVMW#XHX :WLW >Y NW :V MW >bGc,W;[ JW6X#W=W DX6X!W )W6W DVLX >W=X IW7"
3645 "X W>Y>W1XEWEX W=W IWDWDW!Y6X#X6X >W ;W8W MX0X MY 4X *Y3Y$^LXL^&X0X Ff IY/Y#Y JV KY JYLVLY KY7Y KYKVKY #X 2XBS 6X 3t ;X :V ![ 8TCfFT .XFX FV )U"
3646 "GV>WKT MW7X :UGU ,XFX *V=TBU&V2W!V=TBU=X -X0X&X0X&X0X&X0X&X0X&X0W%X7X KY /X -X -X -X -X -X -X -X ,X/Y)X;XMX%Y/Y)Y/Y)Y/Y)Y/Y)Y/Y Z?Z$"
3647 "^4Y)Y3Y%Y3Y%Y3Y%Y3Y FX <X -W3W$W8Y MW8Y MW8Y MW8Y MW8Y MW8Y MW8[ NX -X -X -X -X +W ,W ,W ,W .X6X MW6W X6X X6X X6X X6X X6X 5Z I_=X MX8X MX8X MX8X MX8X "
3648 "DWLW @Y7X FWLW >XEVFY\"X5Y\"X5Y\"X5Y\"X5Y!V *WLX @X /WNT 7`JQJ_&eKQKe Je :d KW4W MW8W HW>X ?XNX AX Y 1VCV 9SDW 9V?V?V?X4\\ "
3649 " &W %W V \"V )X:X ;X 9Z CX 4X (Y KW7X AX <Y6Y 1X 4e )e DVAX@ZHW=X0X$X4Y\"Y*P&X0Z(X -X ,Y-X+X/X'X -X -X=[ KX -X?X?X0X:XNX%Y/Y*X ,Y/Y*X5X "
3650 ".Y AX :X3X HXLX =XNW;WNX1Y=Y ?X ;Z 0W $V )W EW8Y JY7W W ,W7Y NX *W /W8Z MW6W MW ,W ,WDY AW ,W7W7W=W6W NW6W LY7W W7Y MW AW FW ,X9Y EWJW <WMVBVMW"
3651 "$XFX ;WMX ?Y MW :V MW =`Ea+X<[ JW6W\"W>W BW6W W )W6W DWMX ?X=X IX8X W?[?W0WEWEW NW=W IWDWDW!Y6W!W6W =W ;W8W MX0X NY 3X )Y5Y\"z%X0X C` FY/Y\"X JV "
3652 "KX HYMVMY IX7X IYLVLY \"X 1XCS 6X 4v <X :V [ 8TBbET ,WEW FV (T$T LX8X :UGU ,WEW )V=m,V3W V=mCX -X0X&X0X&X0X&X0X&X0X&X0X&X7X KY"
3653 "*P&X -X -X -X -X -X -X -X ,X0Z)X:XNX%Y/Y)Y/Y)Y/Y)Y/Y)Y/Y!Z=Z%]3Y(X3X#X3X#X3X#X3X EX <X -W3W$W8Y MW8Y MW8Y MW8Y MW8Y MW8Y MW8[ MW ,X -X -X -X ,W ,W ,W "
3654 ",W -W6W LW6W NW6W MW6W MW6W MW6W MW6W 4Z H^=W LX9Y MX9Y MX9Y MX9Y DWMX @Y7W EWMX =Y8Y Y8Y Y8Y Y8Y Y8Y V *WLX AX .WNT 6^IQI]$cKRJc Id 8c KW4W"
3655 " MX:X IX>X ?XNX AY Y4P VBV 9SDW 9V?V?V?Y4Z %W %W V #W )X:X ;X :Z CY 4X (Y KX9Y AX ;X6X 1Y 1e /e @U@XB[JX<X/W$X4"
3656 "X Y,Q&X1Z'X -X +Y.X+X/X'X -X -X<[ LX -X?X?X0X:XNX$Y1Y)X +Y1Y)X5Y /X @X :X4Y GXNX <XNV9VNX2Y;Y @X ;Y /W $W *W EW9Z JZ9X X -X9Z NX *W /X9Z MW6W MW"
3657 " ,W ,WCY BW ,W7W7W=W6W NX8X LZ9X X9Z MW AW FW +W9Y EXLX <WNV@VNW%YEX ;WNW ?Y LW :V MW <^C_)W=\\ JX7W\"W>W BX8X W )W6W CVNX >W;W IX8X X@[@X0XFWEW "
3658 "NW=W IWDWEX!Z8X!X8X =W :W:W LX0X Y 2X (Y7Y Nv#X0X ?X AY1Y V IV JV FYNVNY GV5V GYMVMY !X 1XCS 6X 5x =X :V MZ 8T?ZBT *VDV FV 'T&T KX"
3659 "8X :UGU ,VDV )V<m-V3V NV<mCX -X/W&X/W&X/W&X/W&X/W&X0X'X6X JY,Q&X -X -X -X -X -X -X -X ,X1Z(X:XNX$Y1Y'Y1Y'Y1Y'Y1Y'Y1Y!Z;Z%[3Y'X4Y#X4Y#X4Y#X4Y EX"
3660 " <X -W3W$W9Z MW9Z MW9Z MW9Z MW9Z MW9Z MW9] NX -X -X -X -X ,W ,W ,W ,W -X8X LW6W NX8X MX8X MX8X MX8X MX8X 4Z H]=X KW9Y LW9Y LW9Y LW9Y CWNW ?Z9X DWNW "
3661 " ;Y;Z MY;Z MY;Z MY;Z MY;Z NV *XMW AY -[ 3ZHRH[\"aJRI` Fb 6a JW4W LW:W HX=W >WNX @Y !Z6Q VBV KP>SEW 9V>WAW>X3Z &W %W V "
3662 " #V 'X<X :X ;Z BY 4X )Y IW9X AY ;Y8Y 2Y .d 1d >U?ZH^MZ<X.X%X5Y NY.R&X2Z&X -X *Y/X+X/X'X -X -X;[ MX -X&X0X9a$Z3Y(X *Y3Y(X4X$P-Y @X :Y5Y GXNX"
3663 " <XNV9VNX2X9Y AX <Z /W #V *W EX:Z JZ9X NX .X9Z MX +W .X;[ MW6W MW ,W ,WBY CW ,W7W7W=W6W NX9Y LZ9X X9Z MW AW FW +W:Z DWLW :^@^$XDY <WNW @Z LW :"
3664 "V MW ;\\@['X>\\ JX8X\"W?W AX9Y X *W6W CVNX ?X;X JX9Y NW@[@W/XFWFX NW=W IXEWEX!Z8X!X8W ;W ;W;X MX.X\"Y 1X 'Y9Y Lt\"X0X ?X @Y3Y MT HV IT Dj ET3T EYNVN"
3665 "Y X 0XDS 6X 6ZM`LY >X :V LY 7T)T (UCU ET(T JX9Y :UGU ,UCU )V;m.V3V NV;mCY7P HX.X(X.X(X.X(X.X(X.X(X.X(X6X IY.R&X -X -X -X -"
3666 "X -X -X -X ,X2Z'X9a$Z3Y&Z3Y&Z3Y&Z3Y&Z3Y!Z9Z&Z3Y&Y5Y#Y5Y#Y5Y#Y5Y EX <X -W3W$X:Z MX:Z MX:Z MX:Z MX:Z MX:Z MX:^ NX -X -X -X -X -W ,W ,W ,W -X8X LW6W NX9Y"
3667 " MX9Y MX9Y MX9Y MX9Y 4Z H\\=Y KW:Z LW:Z LW:Z LW:Z CWNW ?Z9X DWNW :[@[ K[@[ K[@[ K[@[ K[@[ MV )WNX AX ,[ 1WGRFW N_IRH^ Da 5_ IW4W LX<X HW<W >`"
3668 " >Y !Y8S MX +VBV KQ?SFX 9V=VAV=Y6] &V &W NV BX 1X 1V 'Y>Y :X <Z BY 3X GP3Z IX;Y AX :Y9Z 2X GX -X 7a 1a .X 6V@iNa;X.X%X6Z N"
3669 "Z1T&X4\\&X -X *Z0X+X/X'X -X -X:[ NX -X&X0X9a#Z5Z(X *Z5Z(X4Y%R/Y @X 9Y7Y EWNW :WNV9VNW2Y9Y AX =Z .W #V *W EX;[ J[;X MY .X;[ MY2P JW .Y=\\ MW6W MW ,"
3670 "W ,WAY DW ,W7W7W=W6W MX:X K[;X MX;[ MW /P4X FX ,X<[ DXNX :^@^%XBX <` @Y KW :V MW 8V;W%X?^ KY9X!V@X @X:X NX *W6W C_ >X:W JY;Z NXB]BX.XGWGX MW=W H"
3671 "XFWFX [:X NX:X ;W :W<W LX.X\"Y 1X &Y;Y Ip X0X ?X @Z5Z LR GV HR Bh CR1R Cj NX 0YES 6X 7ZJ\\IY ?X :V KY 8U+U 'TBT DU+T IY;Z :UGU "
3672 " ,TBT (V;m.V4V MV;mCY8Q HX.X(X.X(X.X(X.X(X.X(X.X)X5X IZ1T&X -X -X -X -X -X -X -X ,X4\\'X9a#Z5Z%Z5Z%Z5Z%Z5Z%Z5Z\"Z7Z&Z5Z%Y7Y!Y7Y!Y7Y!Y7Y DX <X -W4X$X"
3673 ";[ MX;[ MX;[ MX;[ MX;[ MX;[ MX;`3P=Y .Y2P LY2P LY2P LY2P LW ,W ,W ,W ,X:X KW6W MX:X KX:X KX:X KX:X KX:X 3Z GZ<X JX<[ LX<[ LX<[ LX<[ C` ?[;X C` 9_J"
3674 "_ I_J_ I_J_ I_J_ I_J_ LV )` AX +Z S <[GRFZ A_ 4^ HW4W KX>X HX<X ?` =Z \"Y:T MX +VCV JSASFX :V<VAV<Y8_ 'W 'W NV BX 1X 2W"
3675 " &X>X 9X =Z 1P2Z 3X GQ5Z GX=Y @X 9Y:Y KP8Z GX -X 4^ 1^ +X 5U?gM_9W,W%X7Z L[4U&X6]%X -X )[2X+X/X'X -X -X9[ X -X&X0X8`\"Z7Z'X )Z7Z'X3X%T2Y ?X 9Z9Z E` :"
3676 "_9_3Y7Y BX >Z -W #W +W DX=\\ J\\=Y LY7P HY=\\ LY5R JW -Y?] MW6W MW ,W ,W@Y EW ,W7W7W=W6W MY<Y K\\=Y MY=\\ MW /R6W DW ,Y=[ CWNW 9^@^&X@X <^ @Y JW :V "
3677 " MW HXA` LZ;X V@W ?Y<Y MX +W6W B^ ?X9W JZ<Z NXB]BX.YHWHY MW=W HYGWGY \\<Y NY<X :W :X>X LX.X#Y 0X %Y=Z Gl MX0X ?X ?Z7Z JP FV GP @f AP/P Ah MX "
3678 "/YFSDP BX 8ZFVEY @X :V JX 7V.U %SAS CU.U HZ<Z :UGU ,SAS (V:m/V5W MV:mBY;S HW,W(W,W(W,W(W,W(W,W(X.X)X5X H[4U&X -X -X -X -X -X"
3679 " -X -X ,X6]&X8`\"Z7Z#Z7Z#Z7Z#Z7Z#Z7Z\"Z5Z&[8Z$Z9Z!Z9Z!Z9Z!Z9Z DX <X -W4W\"X=\\ LX=\\ LX=\\ LX=\\ LX=\\ LX=\\ LX=b6R<Y7P GY5R KY5R KY5R KY5R LW ,W ,W ,W ,Y<Y KW"
3680 "6W MY<Y KY<Y KY<Y KY<Y KY<Y 3Z GY<Y JY=[ LY=[ LY=[ LY=[ B^ >\\=Y B^ 7r Gr Gr Gr Gr KV (_ BX )Y S 8RBSCR <] 2\\ GW4W KZBZ HX;W >_ <[ "
3681 " $[=U MX ,VBV JUCSHY :V;WCW<[<b (W 'W NV BX 1X 2W &Y@Y 9X >Z 0R5Z 2X GT9[ GY?Z AY 9[>[ KR;Z FX -X 1[ 1[ (X 5V>dL^9X,X&X9[ J[7W&X9_$X "
3682 "-X (\\6Z+X/X'X -X -X8[!X -X&X0X8`![;[&X ([;[&X3Y&W7[ ?X 8Z;Z D` :^7^3X5Y CX ?Z ,W #W +W DY?] J]?Y KZ:R GY?] LZ8T JW -ZA^ MW6W MW ,W ,W?Y FW ,W7W7"
3683 "W=W6W LY>Y J]?Y KY?] MW /T9X DX ,Y@] CWNW 9]>]'Y@Y =^ AY IW :V MW HYCXNW L\\>Y VAX >Y>Y LY ,W6W B] >X9X K[>[ MXDVMVDX,YIWIY LW=W GYHWHY N]>Y LY"
3684 ">Y :X :X@X LX,X%Y /X $ZAZ Ch KX0X ?X >[;[ ?V 6d >f LX /[HSFR BX 9Z3Y AX :V IX 7V1V #R@R BU0U G[>[ :UGU ,R@R 'V(U)V6W"
3685 " LV(U<Z>U IX,X*X,X*X,X*X,X*X,X*X,X*W4X G[7W&X -X -X -X -X -X -X -X ,X9_%X8`![;[![;[![;[![;[![;[\"Z3Z(];[\"Z;Z NZ;Z NZ;Z NZ;Z CX <X -WJP;X\"Y?] LY?] LY?] "
3686 "LY?] LY?] LY?] LY?XNZ9T<Z:R GZ8T KZ8T KZ8T KZ8T LW ,W ,W ,W +Y>Y JW6W LY>Y IY>Y IY>Y IY>Y IY>Y 2Z FY>Y HY@] KY@] KY@] KY@] B^ >]?Y A^ 6o Do Do Do "
3687 "Do IV (_ CX (Y S (S ,[ 0[ GW4W J\\H\\ GW:W >^ :\\ %[@W MX ,VBV JXFSIZ :V:WEW:\\@e (V 'V MV BX 1X 2V $ZDZ 8X ?Z /U;] 2X GV="
3688 "\\ EZC[ @X 7[@[ JT?[ EX -X /Y 1Y &X 5V=bK\\7X,X&X<^ I]=Z&X=b#X -X ']:\\+X/X'X -X -X7[\"X -X&X0X7_ \\?\\%X '\\?\\%X2X&Z<\\ >X 7[?[ B^ 9^7^4Y5Y CX ?Y +W \"V +W "
3689 " DZB_ J_CZ I[>T G[C_ K[=W JW ,\\GXNW MW6W MW ,W ,W>Y GW ,W7W7W=W6W KZBZ I_CZ J[C_ MW /W>Z DZ .ZB^ C` 8\\>\\&X>Y =\\ AY HW :V MW GZFYNY N]AZ N"
3690 "WCX <ZBZ JZ:Q EW6W B] ?X7W K\\A^ NYFWMWFY,ZJWJY KW=X H[JWJ[ N_BZ JZBZ 8Y <ZDZ LX,X&Y .X #ZCZ >_ FX0X ?X =\\?\\ >V 5b <d KX .\\JSHT BX 8X2X @X :V "
3691 "IX 5V4U Q?Q AV4V F\\A^ ;UGU ,Q?Q 'V'U*V6W LV'U<[AW IX,X*X,X*X,X*X,X*X,X*X,X+X4X F]=Z&X -X -X -X -X -X -X -X ,X=b$X7_ \\?\\ N\\?\\"
3692 " N\\?\\ N\\?\\ N\\?\\ X1X(`?\\ [?[ L[?[ L[?[ L[?[ BX <X -WJS@Z\"ZB_ LZB_ LZB_ LZB_ LZB_ LZB_ LZBYM\\>W;[>T F[=W J[=W J[=W J[=W LW ,W ,W ,W *ZBZ IW6W KZBZ GZBZ "
3693 "GZBZ GZBZ GZBZ 1Z F[BZ GZB^ KZB^ KZB^ KZB^ A\\ =_CZ ?\\ 3l Al Al Al Al HV (^ BX (X NS (S ,Z .Y FW4W In GX:X ?^ 9_ (]FZ MX "
3694 ",VBV J[ISL\\ :V9XGX9^Fi )W )W MV BX 1X 3W #[H[ Et Mx MZC_ 1X GZD^ C[G\\ @Y 7^F] IXF] DX -X ,V 1V #X 4V<^IY5X*X'y G_D^&{!y NX &`B`+X/X'X -X -X6[#"
3695 "w LX&X0X7_ N^E^$X &^E^$X2Y'^C^ =X 7^E^ B^ 8]7]4Y3Y DX @~U&W \"W ,W C\\HYNW JWNXG\\ H]EX F\\GXNW J]D[ JW +kMW MW6W MW ,W ,W=Y HW ,W7W7W=W6W K]H] IWNX"
3696 "G\\ I\\GXNW MW /[E\\ Be 9[GXNW B^ 7\\>\\'X<X =\\ AX GW :V MW G\\IYM^$`F\\ MWEX ;]H] J]BV EW6W A\\ ?X7X L_GaKP#ZJYMYJZ*[LWL[ KW=Y H\\LWL\\ MWNXG] J]H\\ 7a "
3697 "C[H[ L~W'x MX 1iEi HX CX0X ?X <^E^ =V 4` :b JX -^MSLX Lz V0V ?X :V HW 4V7V MP>P @W8W 3~W :_GaKP @UGU ,P>P 'V&U+V6V KV&"
3698 "U;]GZ JX*X,X*X,X*X,X*X,X*X,Y,Y,X4y7_D^&y Ny Ny Ny NX -X -X -X ,{\"X7_ N^E^ L^E^ L^E^ L^E^ L^E^ MV/V(dE^ N^E^ L^E^ L^E^ L^E^ BX <X -WJWF[ \\HYNW K\\HYNW K"
3699 "\\HYNW K\\HYNW K\\HYNW K\\HYNW K\\H[K^E[:]EX E]D[ I]D[ I]D[ I]D[ LW ,W ,W ,W )[F[ HW6W K]H] G]H] G]H] G]H] G]H] 1Z F]G] F[GXNW J[GXNW J[GXNW J[GXNW A\\ =WNX"
3700 "G\\ ?\\ 1h =h =h =h =h FV '] AV &W T )T +X -X EW4W Hl FX9W ?^ 8~R Jp MX ,VCV It 9V8XIX7sLZ *W )W MV BX 1X 3W #n Et M"
3701 "x Mu 0X Gs Ao @X 5t In CX -X )S 1S X 4V9XFU1X*X'x Ex&z y NX %|*X/X'X -X -X5[$w LX&X0X6^ Mu#X %u#X1X'y =X 6u A^ 8]7]4X1X DX @~U&W \"W ,W ClMW J"
3702 "WMk Fo EkMW Is JW *jMW MW6W MW ,W ,W<Y IW ,W7W7W=W6W Jp HWMk GkMW MW /q Ae 9kMW B^ 7\\=[(Y;X >\\ Av 6W :V MW FkL]$u LXGX 9p Hp EW6W A[ ?X6X LpN\\#"
3703 "hKh)s JW<] Lu LWNm Hp 6` Bl K~W'x MX 1iEi HX CX0X ?X ;u <V 3^ 8` IX ,o Lz NT.T >X :V HW 3X=X )X<X 2~W :pN\\ @UGU V&"
3704 "U+V7i.V&U:o JX*X,X*X,X*X,X*X,X*X,X*X-X3y6x&y Ny Ny Ny NX -X -X -X ,z!X6^ Mu Ju Ju Ju Ju KT-T(} Lu Ju Ju Ju AX <X -WJk NlMW KlMW KlMW KlMW KlMW KlMW Kn"
3705 "Is9o Ds Hs Hs Hs LW ,W ,W ,W )p HW6W Jp Ep Ep Ep Ep Ls EkMW JkMW JkMW JkMW A\\ =WMk >\\ /c 8c 8c 8c 8c CV '\\ ?T %W U *T *W ,V DW4W Gj EW8W "
3706 ">\\ 5~P In LX -VBV Is 9V7g6qJZ *V )V LV BX 1X 3V !l Dt Mx Mt /X Gr ?m ?X 4r Hm BX -X &P 1P LX 3V 3X*X'w Cv%x My NX #x(X/X'X"
3707 " -X -X4[%w LX&X0X5] Ls\"X $s\"X1Y(w ;X 5s ?\\ 7\\5\\5Y1Y EX @~U&W !V ,W BjLW JWMj Dn DjMW Hr JW )hLW MW6W MW ,W ,W;Y JW ,W7W7W=W6W In GWMj EjMW MW /p"
3708 " ?d 8iLW B^ 6Z<[)Y:Y >Z @v 6W :V MW EiK]$t JYLZ 7n Fo EW6W A[ ?X5W LWNfM\\\"gKg'q IW<] Ks KWMk Fn 5` Aj J~W'x MX 1iEi HX CX0X ?X :s ;V 2\\ 6"
3709 "^ HX +n Lz MR,R =X :V HW 1ZEZ %ZDZ 0~W :WNfM\\ @UGU !V%U,V6i/V%U9n JX*X,X*X,X*X,X*X,X*X,X*X-X3y5v%y Ny Ny Ny NX -X -X -X ,"
3710 "x NX5] Ls Hs Hs Hs Hs IR+R(WMs Js Hs Hs Hs @X <X -WJk MjLW JjLW JjLW JjLW JjLW JjLW JmHr8n Cr Gr Gr Gr LW ,W ,W ,W (n GW6W In Cn Cn Cn Cn Ls CiLW Ii"
3711 "LW IiLW IiLW @Z <WMj <Z +] 2] 2] 2] 2] @V &[ >R $V NU *U *U *U DW4W Fh DW8X ?\\ 4~ Hl KX -VBV Hp 8V5e4nGZ +W +W LV BX"
3712 " 1X 3V j Ct Mx Mr -X Gq =j >Y 3p Gl AX -X 2X 3W 5X(X(u ?s$v Ky NX \"v'X/X'X -X -X3[&w LX&X0X5] Kq!X #p X0X(v :X 4p =\\ 7\\5\\6Y/Y FX @~U&W !V ,W "
3713 " AhKW JWLh Bm ChLW Gq JW (eJW MW6W MW ,W ,W:Y KW ,W7W7W=W6W Hl FWLh ChLW MW /o >d 7gKW A\\ 5Z<Z(X8X >Z @v 6W :V MW DgI\\$s He 5l Dn EW6W @Y "
3714 ">W4X MWMeM\\!eIe%o HW<] Jq JWLi Dk 2_ @h J~Y(x MX 1iEi HX CX0X ?X 9q :V 1Z 4\\ GX *m Lz LP*P <X :V HW 0m \"l .~W :WMeM\\ @UGU "
3715 " !V%U,V6i/V%U8l JX(X.X(X.X(X.X(X.X(X.Y)X/X2y3s$y Ny Ny Ny NX -X -X -X ,v LX5] Kq Fq Fq Fq Fq GP)P'VKp Gp Ep Ep Ep >X <X -WJj KhKW IhKW IhKW IhKW"
3716 " IhKW IhKW IjEq7m Bq Fq Fq Fq LW ,W ,W ,W &j EW6W Hl Al Al Al Al Ls AgKW HgKW HgKW HgKW @Z <WLh ;Z MV &[ =P \"U V +V )S (S CW4W "
3717 "De DX8X ?\\ 2| Fh IX -VBV Ek 6V4c1kEZ +V +V KV BW 0X 4W Mf At Mx Mq ,X Go :h =X 0l Ej ?X -W 1X 2W 6X(X(s ;o\"s Hy NX r%"
3718 "X/X'X -X -X2['w LX&X0X4\\ Im NX !m NX0Y(t 9X 2m ;Z 5[5[5X-X FX @~U&W !W -W @fJW JWJe ?j AeJW En IW 'cIW MW6W MW ,W ,W9Y LW ,W7W7W=W6W Fh DWJe AeJ"
3719 "W MW .m ;b 6eJW A\\ 5Z<Z)X6X >X ?v 6W :V MW CeG[$r Fc 2h Am EW6W @Y ?X3W MWMdL\\ cGc#m GW;\\ Hm HWKg Ah /] ?f I~Y(x MX 1iEi HX CX0X ?X 7m 8V 0"
3720 "X 2Z FX (j Kz AX :V HW -g Lh ,~W :WMdL\\ @UGU \"V$U-V5i0V$U7i HX(X.X(X.X(X.X(X.X(X.X(X/X2y1o\"y Ny Ny Ny NX -X -X -X ,t"
3721 " JX4\\ Im Bm Bm Bm Bm %VHm Dm Bm Bm Bm =X <X -WJh HfJW HfJW HfJW HfJW HfJW HfJW HhBn4j ?n Cn Cn Cn KW ,W ,W ,W %h DW6W Fh =h =h =h =h KVMi >eJW GeJW"
3722 " GeJW GeJW ?X ;WJe 9X MW &Z =U W ,W *R &Q BW4W B` AW6W >[ /y Dd GX -VCV Af 5V2a.gBZ ,W -W KV CX 0X 4V "
3723 " Kd @t Mx Km *X Ek 6d ;X .h Bh >X .X 1X 1W 7X(X(q 7j Np Ey NX Mm\"X/X'X -X -X1[(w LX&X0X4\\ Gi LX Ni LX/X$n 7X 0i 9Z 5[5[6Y-Y GX @~U&W V -W "
3724 " >cIW JWIb <g =bIW Ci FW %_GW MW6W MW ,W ,W8Y MW ,W7W7W=W6W Ef CWIb =bIW MW +h 8a 5cIW @Z 4Y:Y*Y5X ?X ?v 6W :V MW AbDY$WMf Ca 0f >k EW6W @Y ?"
3725 "W2W MWK`I[ NaEa i EW;\\ Fi FWIc >e ,\\ =b G~Y(x MX 1iEi HX CX0X ?X 5i 6V /V 0X EX &f Iz AX :V /P;W *c Gb )~W :WK`I[ @UGU "
3726 " #V#U.V4i1V#U6f FX(X.X(X.X(X.X(X.X(X.X(X/X2y/j Ny Ny Ny Ny NX -X -X -X ,p FX4\\ Gi >i >i >i >i $VEi @i >i >i >i ;X <X -WIf EcIW FcIW FcIW FcIW Fc"
3727 "IW FcIW Fd>i0g ;i >i >i >i HW ,W ,W ,W #d BW6W Ef ;f ;f ;f ;f JUJe ;cIW FcIW FcIW FcIW ?X ;WIb 7X MW %Y =T X -X )P %P AW4W ?Z"
3728 " >W6X ?Z ,w B` EX .VBV <] 1V0]*b?[ -W -W KV CW /X 4V I` >t Mx Hg 'X Bf 2` :X +d =b ;X .W 0X 1X 9X&X)m 0d Kj ?y NX Jg "
3729 "NX/X'X -X -X0[)w LX&X0X3[ Dc IX Kf LX/Y!g 4X .e 7Z 5Z3Z7Y+Y HX @~U&W V -W =`GW JWG^ 7b 9^GW Ad CW \"YDW MW6W MW ,W ,W7Y NW ,W7W7W=W6W B` @WG^ 9"
3730 "^GW MW (c 2] 3_GW @Z 3X:X*Y4Y @X ?v 6W :V MW ?_AW$WKb @^ +` 9g CW6W ?W ?X2X NWJ^GY K]B^ Ke CW:[ Dd CWG_ 9` 'Y ;^ F~[)x MX 1iEi HX CX0X ?X 2c "
3731 "3V .T .V DX $b Gz AX :V /R>X &[ ?Z %~W :WJ^GY ?UGU #V +V +V 1b EX&X0X&X0X&X0X&X0X&X0Y'X1X1y,d Ky Ny Ny Ny NX -X -X "
3732 "-X ,j @X3[ Dc 8c 8c 8c 8c !VBc ;e :e :e :e 9X <X -WFa B`GW E`GW E`GW E`GW E`GW E`GW D`:d*b 7d 9d 9d 9d EW ,W ,W ,W !` @W6W B` 5` 5` 5` 5` HVHa 7_GW"
3733 " D_GW D_GW D_GW ?X ;WG^ 5X MW 7S @r >Y BS .V,W#Z ;V -V 7W ;W EX ;\\ 6] "
3734 "+Z 5\\ 5Z <W 7X %\\ <] \"X ([ 4c E] /[ (W W .W :Y #X 0Z 2X *\\ $W &W .Z =WDX 3XDW I["
3735 " 0Y 8W -W :V MW <Z ;WH[ 9Y &Z 1] LW ?W >WGXBU FX=X E` \"W >] @WDY 3Z 2X C[ >T :[ KV /TAY "
3736 " EWGXBU =UGU BT 6V +V +V ,Y ?\\ +[ 0[ 0[ 0[ 0[ KT=[ 2[ 0[ 0[ 0[ 7Z ;Y .Y .Y .Y .Y .Y -"
3737 "Y2\\\"Z /\\ 1\\ 1\\ 1\\ CZ 3Z /Z /Z /Z /Z FVCZ 1Y .Y .Y .Y ,W :WDX 2W LW 7R #S"
3738 " >W /W 8W :V \"W 5X )X &Z CW NV .W :W %W"
3739 " @W :W -X -W :V MW LW FW ?W >W NW 0W =W 3S GV /XGZ "
3740 " DW HUGU AT %T 'R JT "
3741 " #T (X :W NX LW 7S =V /V 7W :V \"W"
3742 " 4X'Q &Y %Z DW NV .W :W %W @W :W -W ,W :V MW "
3743 " LW FW ?W >W NW 0W =W 3S GV /j CW HUGU @T "
3744 " %T 'P HT \"Q 'W 9W NW KW "
3745 " 7S =W 1W 7V :W \"V 2X)R &X #Z "
3746 " EW NW /W :W %W @W :W -W ,X ;V NX LW FW ?W >W NW 0W =W "
3747 " 3S GV /j CW HUGU @U &U "
3748 " U \"P 'W 9W NW KV 6S "
3749 " <V 1V 6V :V !V 1Y-U 'X \"Z FW MV /W ;X %W "
3750 " @W :W .X +W ;V NW KW FW ?W >W NW 0W =W 3S GV /h "
3751 " AW HUGU ?T %T NT "
3752 " )X 9W X KV 6S <W 3V 6V 9V \"V "
3753 " /Z1X (X !Z Ga (V 9a ;W $W @W :W .W *W ;V NW KW "
3754 " FW ?W >W NW 0W =W 3S GV .f @W HUGU ?U &"
3756 " 6S ;V 3V 6V :W \"V .[5[ *Y Z "
3757 " Ha (W :a <X $W @W :W /X *X <V X KW FW ?W >W NW 0W =W "
3758 " 3S GV +a >W HUGU >T %T "
3759 " NT +X 8W !X (VIV 6S :V 5V 5U"
3760 " 9W \"U +\\;] )X MZ Ia (W :a =Y %W ?W :W "
3761 " /W )[ ?V #[ KW FW ?W >W NW 0W =W 3S GV 'Z ;W "
3762 " HUGU >U &U U ,W 7W !"
3763 "W 'VIV 6S :V 6W 6V 4V *_C` "
3764 " )Y LZ Ja :a (P7Y $W ?W :W 0X (b GV +b JW FW ?W >W "
3765 " NW 0W =W 3S GV 7W HUGU >U &U "
3766 " U -X 7W \"X 'VJW "
3767 " 6S 9V 7V 5U 3U 'x (Z KZ Ka :a "
3768 " (R:Z $W ?W :W 0X (b GV +b JW FW ?W >W NW 0W =W 3S "
3770 " -X 7W \"X &UJW 6S 9W 9W "
3771 " Bu ([ IZ La :a (T>[ $X ?W :W 1X &a GV +a "
3772 " IW FW ?W >W NW 0W =W 3S GV 7W $V "
3773 " 'V !V .X 6W #X %VLW "
3775 " 8XE] %Y >W :W 3Z $_ GV +_ GW FW ?W >W NW 0W =W "
3776 " 3S GV 7W /QGW 2QGW ,QG"
3778 " 0l +a 8p +_ >W :W ;a !] G"
3779 "V +] EW FW ?W >W NW 0W =W 3S GV 7W /` "
3780 " 1` +` 7a 5W -a #` "
3782 " 7o *^ =W :W ;` KY GV +Y AW FW ?W >W NW 0W =W "
3783 " 3S GV 7W /` 1` +` "
3785 " 8\\ #_ \"} 3n )^ =W :W ;` 9V "
3786 " BW FW ?W >W NW 0W =W 'V 7W /_ "
3787 " 0_ *_ 6` 4W -` !] "
3789 " } 3l '] <W :W ;_ 8V BW FW ?W >W NW 0W =W "
3792 " ,[ M} 2j &\\ ;W :W ;^ 7V BW "
3793 " FW ?W >W NW 0W =W 7W -Y *Y "
3796 " /d #Z 9W :W ;\\ 5V BW FW ?W >W NW 0W =W "
3799 " I} *[ NW 6W :W ;Z 3V BW FW ?W >W"
3807 const unsigned char logo40x38[4576] = {
3808 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,
3809 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,
3810 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,
3811 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,
3812 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,
3813 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,
3814 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,
3815 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,
3816 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,
3817 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,
3818 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,
3819 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,
3820 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,
3821 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,
3822 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,
3823 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,
3824 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,
3825 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,
3826 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,
3827 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,
3828 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,
3829 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,
3830 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,
3831 200,200,200,91,49,124,118,124,71,32,124,95,49,56,114,52,82,121,0};
3840 static std::FILE *res = stderr;
3841 if (file) res = file;
3847 inline unsigned int nb_cpus() {
3848 unsigned int res = 1;
3850 SYSTEM_INFO sysinfo;
3851 GetSystemInfo(&sysinfo);
3852 res = (
unsigned int)sysinfo.dwNumberOfProcessors;
3854 res = (
unsigned int)sysconf(_SC_NPROCESSORS_ONLN);
3860 inline int mutex(
const unsigned int n,
const int lock_mode) {
3861 switch (lock_mode) {
3862 case 0 : cimg::Mutex_attr().unlock(n);
return 0;
3863 case 1 : cimg::Mutex_attr().lock(n);
return 0;
3864 default :
return cimg::Mutex_attr().trylock(n);
3883 inline void warn(
const char *
const format, ...) {
3885 char message[16384] = { 0 };
3887 va_start(ap,format);
3888 cimg_vsnprintf(message,
sizeof(message),format,ap);
3890 #ifdef cimg_strict_warnings
3893 std::fprintf(
cimg::output(),
"\n%s[CImg] *** Warning ***%s%s",cimg::t_red,cimg::t_normal,message);
3907 inline int system(
const char *
const command,
const char *
const module_name=0) {
3909 #ifdef cimg_no_system_calls
3913 const unsigned int l = std::strlen(command);
3915 char *
const ncommand =
new char[l+16];
3916 std::strncpy(ncommand,command,l);
3917 std::strcpy(ncommand+l,
" 2> /dev/null");
3918 const int out_val = std::system(ncommand);
3923 PROCESS_INFORMATION pi;
3925 std::memset(&pi,0,
sizeof(PROCESS_INFORMATION));
3926 std::memset(&si,0,
sizeof(STARTUPINFO));
3927 GetStartupInfo(&si);
3929 si.wShowWindow = SW_HIDE;
3930 si.dwFlags |= SW_HIDE | STARTF_USESHOWWINDOW;
3931 const BOOL res = CreateProcess((LPCTSTR)module_name,(LPTSTR)command,0,0,FALSE,0,0,0,&si,&pi);
3933 WaitForSingleObject(pi.hProcess, INFINITE);
3934 CloseHandle(pi.hThread);
3935 CloseHandle(pi.hProcess);
3937 }
else return std::system(command);
3943 template<
typename T>
3950 template<
typename T>
3951 inline void swap(T& a, T& b) { T t = a; a = b; b = t; }
3954 template<
typename T1,
typename T2>
3955 inline void swap(T1& a1, T1& b1, T2& a2, T2& b2) {
3960 template<
typename T1,
typename T2,
typename T3>
3961 inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3) {
3966 template<
typename T1,
typename T2,
typename T3,
typename T4>
3967 inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4) {
3972 template<
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
3973 inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5) {
3978 template<
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6>
3979 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) {
3980 cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5);
cimg::swap(a6,b6);
3984 template<
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7>
3985 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,
3987 cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6);
cimg::swap(a7,b7);
3991 template<
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8>
3992 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,
3993 T7& a7, T7& b7, T8& a8, T8& b8) {
3994 cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6,a7,b7);
cimg::swap(a8,b8);
4003 return ((
unsigned char*)&x)[0]?
false:
true;
4011 template<
typename T>
4013 if (size)
switch (
sizeof(T)) {
4015 case 2 : {
for (
unsigned short *ptr = (
unsigned short*)buffer+size; ptr>(
unsigned short*)buffer; ) {
4016 const unsigned short val = *(--ptr);
4017 *ptr = (
unsigned short)((val>>8)|((val<<8)));
4020 case 4 : {
for (
unsigned int *ptr = (
unsigned int*)buffer+size; ptr>(
unsigned int*)buffer; ) {
4021 const unsigned int val = *(--ptr);
4022 *ptr = (val>>24)|((val>>8)&0xff00)|((val<<8)&0xff0000)|(val<<24);
4025 default : {
for (T* ptr = buffer+size; ptr>buffer; ) {
4026 unsigned char *pb = (
unsigned char*)(--ptr), *pe = pb +
sizeof(T);
4027 for (
int i = 0; i<(int)
sizeof(T)/2; ++i)
swap(*(pb++),*(--pe));
4038 template<
typename T>
4045 inline unsigned int float2uint(
const float f) {
4047 std::memcpy(&tmp,&f,
sizeof(
float));
4048 if (tmp>=0)
return (
unsigned int)f;
4051 std::memcpy(&u,&f,
sizeof(
float));
4055 inline float uint2float(
const unsigned int u) {
4056 if (u<(1U<<19))
return (
float)u;
4058 const unsigned int v = u|(1U<<(8*
sizeof(
unsigned int)-1));
4060 std::memcpy(&f,&v,
sizeof(
float));
4070 struct timeval st_time;
4071 gettimeofday(&st_time,0);
4072 return (
unsigned long)(st_time.tv_usec/1000 + st_time.tv_sec*1000);
4075 GetSystemTime(&st_time);
4076 return (
unsigned long)(st_time.wMilliseconds + 1000*(st_time.wSecond + 60*(st_time.wMinute + 60*st_time.wHour)));
4083 inline unsigned long tictoc(
const bool is_tic);
4090 return cimg::tictoc(
true);
4098 return cimg::tictoc(
false);
4107 inline void sleep(
const unsigned int milliseconds) {
4110 tv.tv_sec = milliseconds/1000;
4111 tv.tv_nsec = (milliseconds%1000)*1000000;
4114 Sleep(milliseconds);
4118 inline unsigned int _wait(
const unsigned int milliseconds,
unsigned long& timer) {
4120 const unsigned long current_time =
cimg::time();
4121 if (current_time>=timer+milliseconds) { timer = current_time;
return 0; }
4122 const unsigned long time_diff = timer + milliseconds - current_time;
4123 timer = current_time + time_diff;
4125 return (
unsigned int)time_diff;
4135 inline unsigned int wait(
const unsigned int milliseconds) {
4137 static unsigned long timer = 0;
4140 return _wait(milliseconds,timer);
4152 inline unsigned int _rand(
const unsigned int seed=0,
const bool set_seed=
false) {
4153 static unsigned long next = 1;
4155 if (set_seed) next = (
unsigned long)seed;
4156 next = next*1103515245 + 12345 +
rand();
4158 return (
unsigned int)((next>>16)&0x7FFF);
4161 inline void srand() {
4162 const unsigned int t = (
unsigned int)
cimg::time();
4164 cimg::_rand(t+(
unsigned int)getpid(),
true);
4166 cimg::_rand(t+(
unsigned int)_getpid(),
true);
4168 cimg::_rand(t,
true);
4172 inline void srand(
const unsigned int seed) {
4176 inline double rand() {
4177 return cimg::_rand()/32767.;
4183 inline void srand() {
4184 const unsigned int t = (
unsigned int)
cimg::time();
4186 std::srand(t+(
unsigned int)getpid());
4188 std::srand(t+(
unsigned int)_getpid());
4194 inline void srand(
const unsigned int seed) {
4202 return (
double)std::rand()/RAND_MAX;
4222 }
while (w<=0 || w>=1.0);
4223 return x1*std::sqrt((-2*std::log(w))/w);
4229 inline unsigned int prand(
const double z) {
4230 if (z<=1.0e-10)
return 0;
4231 if (z>100)
return (
unsigned int)((std::sqrt(z) *
cimg::grand()) + z);
4233 const double y = std::exp(-z);
4234 for (
double s = 1.0; s>=y; ++k) s*=
cimg::rand();
4239 template<
typename T>
4240 inline T
rol(
const T a,
const unsigned int n=1) {
4241 return n?(T)((a<<n)|(a>>((
sizeof(T)<<3)-n))):a;
4244 inline float rol(
const float a,
const unsigned int n=1) {
4245 return (
float)
rol((
int)a,n);
4248 inline double rol(
const double a,
const unsigned int n=1) {
4249 return (
double)
rol((
long)a,n);
4253 template<
typename T>
4254 inline T
ror(
const T a,
const unsigned int n=1) {
4255 return n?(T)((a>>n)|(a<<((
sizeof(T)<<3)-n))):a;
4258 inline float ror(
const float a,
const unsigned int n=1) {
4259 return (
float)
ror((
int)a,n);
4262 inline double ror(
const double a,
const unsigned int n=1) {
4263 return (
double)
ror((
long)a,n);
4267 template<
typename T>
4271 inline bool abs(
const bool a) {
4274 inline unsigned char abs(
const unsigned char a) {
4277 inline unsigned short abs(
const unsigned short a) {
4280 inline unsigned int abs(
const unsigned int a) {
4283 inline unsigned long abs(
const unsigned long a) {
4286 inline double abs(
const double a) {
4287 return std::fabs(a);
4289 inline float abs(
const float a) {
4290 return (
float)std::fabs((
double)a);
4292 inline int abs(
const int a) {
4297 template<
typename T>
4304 return x>0?(int)(1+std::log10((
double)x)):1;
4308 template<
typename t1,
typename t2>
4309 inline typename cimg::superset<t1,t2>::type
min(
const t1& a,
const t2& b) {
4310 typedef typename cimg::superset<t1,t2>::type t1t2;
4311 return (t1t2)(a<=b?a:b);
4315 template<
typename t1,
typename t2,
typename t3>
4316 inline typename cimg::superset2<t1,t2,t3>::type
min(
const t1& a,
const t2& b,
const t3& c) {
4317 typedef typename cimg::superset2<t1,t2,t3>::type t1t2t3;
4322 template<
typename t1,
typename t2,
typename t3,
typename t4>
4323 inline typename cimg::superset3<t1,t2,t3,t4>::type
min(
const t1& a,
const t2& b,
const t3& c,
const t4& d) {
4324 typedef typename cimg::superset3<t1,t2,t3,t4>::type t1t2t3t4;
4329 template<
typename t1,
typename t2>
4330 inline typename cimg::superset<t1,t2>::type
max(
const t1& a,
const t2& b) {
4331 typedef typename cimg::superset<t1,t2>::type t1t2;
4332 return (t1t2)(a>=b?a:b);
4336 template<
typename t1,
typename t2,
typename t3>
4337 inline typename cimg::superset2<t1,t2,t3>::type
max(
const t1& a,
const t2& b,
const t3& c) {
4338 typedef typename cimg::superset2<t1,t2,t3>::type t1t2t3;
4343 template<
typename t1,
typename t2,
typename t3,
typename t4>
4344 inline typename cimg::superset3<t1,t2,t3,t4>::type
max(
const t1& a,
const t2& b,
const t3& c,
const t4& d) {
4345 typedef typename cimg::superset3<t1,t2,t3,t4>::type t1t2t3t4;
4350 template<
typename T>
4352 return (x<0)?(T)(-1):(x==0?(T)0:(T)1);
4356 template<
typename T>
4358 unsigned long i = 1;
4364 inline double sinc(
const double x) {
4365 return x?std::sin(x)/x:1;
4374 template<
typename T>
4375 inline T
mod(
const T& x,
const T& m) {
4376 const double dx = (double)x, dm = (
double)m;
4377 return (T)(dx - dm * std::floor(dx / dm));
4379 inline int mod(
const bool x,
const bool m) {
4382 inline int mod(
const char x,
const char m) {
4383 return x>=0?x%m:(x%m?m+x%m:0);
4385 inline int mod(
const short x,
const short m) {
4386 return x>=0?x%m:(x%m?m+x%m:0);
4388 inline int mod(
const int x,
const int m) {
4389 return x>=0?x%m:(x%m?m+x%m:0);
4391 inline int mod(
const long x,
const long m) {
4392 return x>=0?x%m:(x%m?m+x%m:0);
4394 inline int mod(
const unsigned char x,
const unsigned char m) {
4397 inline int mod(
const unsigned short x,
const unsigned short m) {
4400 inline int mod(
const unsigned int x,
const unsigned int m) {
4403 inline int mod(
const unsigned long x,
const unsigned long m) {
4413 template<
typename T>
4415 return a*b<=0?0:(a>0?(a<b?a:b):(a<b?b:a));
4419 inline double log2(
const double x) {
4420 static const double base = std::log(2.0);
4421 return std::log(x)/base;
4431 template<
typename T>
4432 inline T
round(
const T x,
const double y=1,
const int rounding_type=0) {
4434 const double sx = (double)x/y, floor = std::floor(sx), delta = sx - floor;
4435 return (T)(y*(rounding_type<0?floor:rounding_type>0?std::ceil(sx):delta<0.5?floor:std::ceil(sx)));
4438 inline double _pythagore(
double a,
double b) {
4440 if (absa>absb) {
const double tmp = absb/absa;
return absa*std::sqrt(1.0+tmp*tmp); }
4441 else {
const double tmp = absa/absb;
return absb==0?0:absb*std::sqrt(1.0+tmp*tmp); }
4444 inline bool _is_self_expr(
const char *expression) {
4445 if (!expression || *expression==
'>' || *expression==
'<')
return false;
4446 for (
const char *s = expression; *s; ++s)
4447 if ((*s==
'i' || *s==
'j') && (s[1]==
'(' || s[1]==
'['))
return true;
4453 return (
char)((x<'A'||x>
'Z')?x:x-
'A'+
'a');
4458 if (str)
for (
char *ptr = str; *ptr; ++ptr) *ptr =
uncase(*ptr);
4468 inline double atof(
const char *
const str) {
4469 double x = 0, y = 1;
4470 if (!str)
return 0;
else { std::sscanf(str,
"%lf/%lf",&x,&y);
return x/y; }
4481 inline int strncasecmp(
const char *
const str1,
const char *
const str2,
const int l) {
4483 if (!str1)
return str2?-1:0;
4484 const char *nstr1 = str1, *nstr2 = str2;
4485 int k, diff = 0;
for (k = 0; k<l && !(diff =
uncase(*nstr1)-
uncase(*nstr2)); ++k) { ++nstr1; ++nstr2; }
4496 inline int strcasecmp(
const char *
const str1,
const char *
const str2) {
4497 if (!str1)
return str2?-1:0;
4499 l1 = (
unsigned int)std::strlen(str1),
4500 l2 = (
unsigned int)std::strlen(str2);
4513 inline bool strpare(
char *
const str,
const char delimiter=
' ',
4514 const bool is_symmetric=
false,
const bool is_iterative=
false) {
4515 if (!str)
return false;
4516 const int l = (int)std::strlen(str);
4518 if (is_symmetric)
for (p = 0, q = l-1; p<q && str[p]==delimiter && str[q]==delimiter; ) {
4519 --q; ++p;
if (!is_iterative)
break;
4521 for (p = 0; p<l && str[p]==delimiter; ) { ++p;
if (!is_iterative)
break; }
4522 for (q = l-1; q>p && str[q]==delimiter; ) { --q;
if (!is_iterative)
break; }
4524 const int n = q - p + 1;
4525 if (n!=l) { std::memmove(str,str+p,n); str[n] = 0;
return true; }
4534 #define cimg_strunescape(ci,co) case ci: *nd = co; ++ns; break;
4535 unsigned int val = 0;
4536 for (
char *ns = str, *nd = str; *ns || (bool)(*nd=0); ++nd)
if (*ns==
'\\')
switch (*(++ns)) {
4537 cimg_strunescape(
'n',
'\n');
4538 cimg_strunescape(
't',
'\t');
4539 cimg_strunescape(
'v',
'\v');
4540 cimg_strunescape(
'b',
'\b');
4541 cimg_strunescape(
'r',
'\r');
4542 cimg_strunescape(
'f',
'\f');
4543 cimg_strunescape(
'a',
'\a');
4544 cimg_strunescape(
'\\',
'\\');
4545 cimg_strunescape(
'\?',
'\?');
4546 cimg_strunescape(
'\'',
'\'');
4547 cimg_strunescape(
'\"',
'\"');
4548 case 0 : *nd = 0;
break;
4549 case '0' :
case '1' :
case '2' :
case '3' :
case '4' :
case '5' :
case '6' :
case '7' :
4550 std::sscanf(ns,
"%o",&val);
while (*ns>=
'0' && *ns<=
'7') ++ns;
4553 std::sscanf(++ns,
"%x",&val);
4554 while ((*ns>=
'0' && *ns<=
'7') || (*ns>=
'a' && *ns<=
'f') || (*ns>=
'A' && *ns<=
'F')) ++ns;
4556 default : *nd = *(ns++);
4557 }
else *nd = *(ns++);
4561 inline const char *strbuffersize(
const unsigned long size) {
4562 static char res[256] = { 0 };
4564 if (size<1024LU) cimg_snprintf(res,
sizeof(res),
"%lu byte%s",size,size>1?
"s":
"");
4565 else if (size<1024*1024LU) {
const float nsize = size/1024.0f; cimg_snprintf(res,
sizeof(res),
"%.1f Kio",nsize); }
4566 else if (size<1024*1024*1024LU) {
4567 const float nsize = size/(1024*1024.0f); cimg_snprintf(res,
sizeof(res),
"%.1f Mio",nsize);
4568 }
else {
const float nsize = size/(1024*1024*1024.0f); cimg_snprintf(res,
sizeof(res),
"%.1f Gio",nsize); }
4574 inline const char *stros() {
4575 #if defined(linux) || defined(__linux) || defined(__linux__)
4576 const char *
const str =
"Linux";
4577 #elif defined(sun) || defined(__sun)
4578 const char *
const str =
"Sun OS";
4579 #elif defined(BSD) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined (__DragonFly__)
4580 const char *
const str =
"BSD";
4581 #elif defined(sgi) || defined(__sgi)
4582 const char *
const str =
"Irix";
4583 #elif defined(__MACOSX__) || defined(__APPLE__)
4584 const char *
const str =
"Mac OS";
4585 #elif defined(unix) || defined(__unix) || defined(__unix__)
4586 const char *
const str =
"Generic Unix";
4587 #elif defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || \
4588 defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
4589 const char *
const str =
"Windows";
4592 *
const _str1 = std::getenv(
"OSTYPE"),
4593 *
const _str2 = _str1?_str1:std::getenv(
"OS"),
4594 *
const str = _str2?_str2:
"Unknown OS";
4602 for (
const char *np = str; np>=str && (p=np); np = std::strchr(np,cimg_file_separator)+1) {}
4607 inline const char* filenamerand() {
4609 static char randomid[9] = { 0 };
4611 for (
unsigned int k = 0; k<8; ++k) {
4612 const int v = (int)std::rand()%3;
4613 randomid[k] = (char)(v==0?(
'0'+(std::rand()%10)):(v==1?(
'a'+(std::rand()%26)):(
'A'+(std::rand()%26))));
4620 inline void winformat_string(
char *
const str) {
4623 char *
const nstr =
new char[MAX_PATH];
4624 if (GetShortPathNameA(str,nstr,MAX_PATH)) std::strcpy(str,nstr);
4637 inline std::FILE *
fopen(
const char *
const path,
const char *
const mode) {
4644 if (*path==
'-' && (!path[1] || path[1]==
'.')) {
4645 res = (*mode==
'r')?stdin:stdout;
4647 if (*mode && mode[1]==
'b') {
4648 if (_setmode(_fileno(res),0x8000)==-1) res = 0;
4651 }
else res = std::fopen(path,mode);
4652 if (!res)
throw CImgIOException(
"cimg::fopen(): Failed to open file '%s' with mode '%s'.",
4665 if (!file)
warn(
"cimg::fclose(): Specified file is (null).");
4666 if (!file || file==stdin || file==stdout)
return 0;
4667 const int errn = std::fclose(file);
4668 if (errn!=0)
warn(
"cimg::fclose(): Error code %d returned during file closing.",
4679 inline const char*
temporary_path(
const char *
const user_path=0,
const bool reinit_path=
false) {
4680 #define _cimg_test_temporary_path(p) \
4681 if (!path_found) { \
4682 cimg_snprintf(s_path,1024,"%s",p); \
4683 cimg_snprintf(tmp,sizeof(tmp),"%s%c%s",s_path,cimg_file_separator,filetmp); \
4684 if ((file=std::fopen(tmp,"wb"))!=0) { cimg::fclose(file); std::remove(tmp); path_found = true; } \
4686 static char *s_path = 0;
4688 if (reinit_path) {
delete[] s_path; s_path = 0; }
4690 if (!s_path) s_path =
new char[1024];
4691 std::memset(s_path,0,1024);
4692 std::strncpy(s_path,user_path,1023);
4693 }
else if (!s_path) {
4694 s_path =
new char[1024];
4695 std::memset(s_path,0,1024);
4696 bool path_found =
false;
4697 char tmp[1024] = { 0 }, filetmp[512] = { 0 };
4698 std::FILE *file = 0;
4699 cimg_snprintf(filetmp,
sizeof(filetmp),
"%s.tmp",cimg::filenamerand());
4700 char *tmpPath = std::getenv(
"TMP");
4701 if (!tmpPath) { tmpPath = std::getenv(
"TEMP"); winformat_string(tmpPath); }
4702 if (tmpPath) _cimg_test_temporary_path(tmpPath);
4704 _cimg_test_temporary_path(
"C:\\WINNT\\Temp");
4705 _cimg_test_temporary_path(
"C:\\WINDOWS\\Temp");
4706 _cimg_test_temporary_path(
"C:\\Temp");
4707 _cimg_test_temporary_path(
"C:");
4708 _cimg_test_temporary_path(
"D:\\WINNT\\Temp");
4709 _cimg_test_temporary_path(
"D:\\WINDOWS\\Temp");
4710 _cimg_test_temporary_path(
"D:\\Temp");
4711 _cimg_test_temporary_path(
"D:");
4713 _cimg_test_temporary_path(
"/tmp");
4714 _cimg_test_temporary_path(
"/var/tmp");
4718 std::strncpy(tmp,filetmp,
sizeof(tmp)-1);
4719 if ((file=std::fopen(tmp,
"wb"))!=0) {
cimg::fclose(file); std::remove(tmp); path_found =
true; }
4723 throw CImgIOException(
"cimg::temporary_path(): Failed to locate path for writing temporary files.\n");
4737 inline const char* programfiles_path(
const char *
const user_path=0,
const bool reinit_path=
false) {
4738 static char *s_path = 0;
4740 if (reinit_path) {
delete[] s_path; s_path = 0; }
4742 if (!s_path) s_path =
new char[1024];
4743 std::memset(s_path,0,1024);
4744 std::strncpy(s_path,user_path,1023);
4745 }
else if (!s_path) {
4746 s_path =
new char[MAX_PATH];
4747 std::memset(s_path,0,MAX_PATH);
4749 #if !defined(__INTEL_COMPILER)
4750 if (!SHGetSpecialFolderPathA(0,s_path,0x0026,
false)) {
4751 const char *
const pfPath = std::getenv(
"PROGRAMFILES");
4752 if (pfPath) std::strncpy(s_path,pfPath,MAX_PATH-1);
4753 else std::strcpy(s_path,
"C:\\PROGRA~1");
4756 std::strcpy(s_path,
"C:\\PROGRA~1");
4770 inline const char*
imagemagick_path(
const char *
const user_path=0,
const bool reinit_path=
false) {
4771 static char *s_path = 0;
4773 if (reinit_path) {
delete[] s_path; s_path = 0; }
4775 if (!s_path) s_path =
new char[1024];
4776 std::memset(s_path,0,1024);
4777 std::strncpy(s_path,user_path,1023);
4778 }
else if (!s_path) {
4779 s_path =
new char[1024];
4780 std::memset(s_path,0,1024);
4781 bool path_found =
false;
4782 std::FILE *file = 0;
4784 const char *
const pf_path = programfiles_path();
4786 std::strcpy(s_path,
".\\convert.exe");
4787 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4789 for (
int k = 32; k>=10 && !path_found; --k) {
4790 cimg_snprintf(s_path,
sizeof(s_path),
"%s\\IMAGEM~1.%.2d-\\convert.exe",pf_path,k);
4791 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4793 for (
int k = 9; k>=0 && !path_found; --k) {
4794 cimg_snprintf(s_path,
sizeof(s_path),
"%s\\IMAGEM~1.%d-Q\\convert.exe",pf_path,k);
4795 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4797 for (
int k = 32; k>=0 && !path_found; --k) {
4798 cimg_snprintf(s_path,
sizeof(s_path),
"%s\\IMAGEM~1.%d\\convert.exe",pf_path,k);
4799 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4801 for (
int k = 32; k>=10 && !path_found; --k) {
4802 cimg_snprintf(s_path,
sizeof(s_path),
"%s\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\convert.exe",pf_path,k);
4803 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4805 for (
int k = 9; k>=0 && !path_found; --k) {
4806 cimg_snprintf(s_path,
sizeof(s_path),
"%s\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\convert.exe",pf_path,k);
4807 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4809 for (
int k = 32; k>=0 && !path_found; --k) {
4810 cimg_snprintf(s_path,
sizeof(s_path),
"%s\\IMAGEM~1.%d\\VISUA~1\\BIN\\convert.exe",pf_path,k);
4811 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4813 for (
int k = 32; k>=10 && !path_found; --k) {
4814 cimg_snprintf(s_path,
sizeof(s_path),
"C:\\IMAGEM~1.%.2d-\\convert.exe",k);
4815 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4817 for (
int k = 9; k>=0 && !path_found; --k) {
4818 cimg_snprintf(s_path,
sizeof(s_path),
"C:\\IMAGEM~1.%d-Q\\convert.exe",k);
4819 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4821 for (
int k = 32; k>=0 && !path_found; --k) {
4822 cimg_snprintf(s_path,
sizeof(s_path),
"C:\\IMAGEM~1.%d\\convert.exe",k);
4823 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4825 for (
int k = 32; k>=10 && !path_found; --k) {
4826 cimg_snprintf(s_path,
sizeof(s_path),
"C:\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\convert.exe",k);
4827 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4829 for (
int k = 9; k>=0 && !path_found; --k) {
4830 cimg_snprintf(s_path,
sizeof(s_path),
"C:\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\convert.exe",k);
4831 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4833 for (
int k = 32; k>=0 && !path_found; --k) {
4834 cimg_snprintf(s_path,
sizeof(s_path),
"C:\\IMAGEM~1.%d\\VISUA~1\\BIN\\convert.exe",k);
4835 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4837 for (
int k = 32; k>=10 && !path_found; --k) {
4838 cimg_snprintf(s_path,
sizeof(s_path),
"D:\\IMAGEM~1.%.2d-\\convert.exe",k);
4839 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4841 for (
int k = 9; k>=0 && !path_found; --k) {
4842 cimg_snprintf(s_path,
sizeof(s_path),
"D:\\IMAGEM~1.%d-Q\\convert.exe",k);
4843 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4845 for (
int k = 32; k>=0 && !path_found; --k) {
4846 cimg_snprintf(s_path,
sizeof(s_path),
"D:\\IMAGEM~1.%d\\convert.exe",k);
4847 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4849 for (
int k = 32; k>=10 && !path_found; --k) {
4850 cimg_snprintf(s_path,
sizeof(s_path),
"D:\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\convert.exe",k);
4851 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4853 for (
int k = 9; k>=0 && !path_found; --k) {
4854 cimg_snprintf(s_path,
sizeof(s_path),
"D:\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\convert.exe",k);
4855 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4857 for (
int k = 32; k>=0 && !path_found; --k) {
4858 cimg_snprintf(s_path,
sizeof(s_path),
"D:\\IMAGEM~1.%d\\VISUA~1\\BIN\\convert.exe",k);
4859 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4861 if (!path_found) std::strcpy(s_path,
"convert.exe");
4864 std::strcpy(s_path,
"./convert");
4865 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4867 if (!path_found) std::strcpy(s_path,
"convert");
4869 winformat_string(s_path);
4882 static char *s_path = 0;
4884 if (reinit_path) {
delete[] s_path; s_path = 0; }
4886 if (!s_path) s_path =
new char[1024];
4887 std::memset(s_path,0,1024);
4888 std::strncpy(s_path,user_path,1023);
4889 }
else if (!s_path) {
4890 s_path =
new char[1024];
4891 std::memset(s_path,0,1024);
4892 bool path_found =
false;
4893 std::FILE *file = 0;
4895 const char *
const pf_path = programfiles_path();
4897 std::strcpy(s_path,
".\\gm.exe");
4898 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4900 for (
int k = 32; k>=10 && !path_found; --k) {
4901 cimg_snprintf(s_path,
sizeof(s_path),
"%s\\GRAPHI~1.%.2d-\\gm.exe",pf_path,k);
4902 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4904 for (
int k = 9; k>=0 && !path_found; --k) {
4905 cimg_snprintf(s_path,
sizeof(s_path),
"%s\\GRAPHI~1.%d-Q\\gm.exe",pf_path,k);
4906 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4908 for (
int k = 32; k>=0 && !path_found; --k) {
4909 cimg_snprintf(s_path,
sizeof(s_path),
"%s\\GRAPHI~1.%d\\gm.exe",pf_path,k);
4910 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4912 for (
int k = 32; k>=10 && !path_found; --k) {
4913 cimg_snprintf(s_path,
sizeof(s_path),
"%s\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",pf_path,k);
4914 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4916 for (
int k = 9; k>=0 && !path_found; --k) {
4917 cimg_snprintf(s_path,
sizeof(s_path),
"%s\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",pf_path,k);
4918 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4920 for (
int k = 32; k>=0 && !path_found; --k) {
4921 cimg_snprintf(s_path,
sizeof(s_path),
"%s\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",pf_path,k);
4922 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4924 for (
int k = 32; k>=10 && !path_found; --k) {
4925 cimg_snprintf(s_path,
sizeof(s_path),
"C:\\GRAPHI~1.%.2d-\\gm.exe",k);
4926 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4928 for (
int k = 9; k>=0 && !path_found; --k) {
4929 cimg_snprintf(s_path,
sizeof(s_path),
"C:\\GRAPHI~1.%d-Q\\gm.exe",k);
4930 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4932 for (
int k = 32; k>=0 && !path_found; --k) {
4933 cimg_snprintf(s_path,
sizeof(s_path),
"C:\\GRAPHI~1.%d\\gm.exe",k);
4934 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4936 for (
int k = 32; k>=10 && !path_found; --k) {
4937 cimg_snprintf(s_path,
sizeof(s_path),
"C:\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",k);
4938 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4940 for (
int k = 9; k>=0 && !path_found; --k) {
4941 cimg_snprintf(s_path,
sizeof(s_path),
"C:\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",k);
4942 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4944 for (
int k = 32; k>=0 && !path_found; --k) {
4945 cimg_snprintf(s_path,
sizeof(s_path),
"C:\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",k);
4946 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4948 for (
int k = 32; k>=10 && !path_found; --k) {
4949 cimg_snprintf(s_path,
sizeof(s_path),
"D:\\GRAPHI~1.%.2d-\\gm.exe",k);
4950 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4952 for (
int k = 9; k>=0 && !path_found; --k) {
4953 cimg_snprintf(s_path,
sizeof(s_path),
"D:\\GRAPHI~1.%d-Q\\gm.exe",k);
4954 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4956 for (
int k = 32; k>=0 && !path_found; --k) {
4957 cimg_snprintf(s_path,
sizeof(s_path),
"D:\\GRAPHI~1.%d\\gm.exe",k);
4958 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4960 for (
int k = 32; k>=10 && !path_found; --k) {
4961 cimg_snprintf(s_path,
sizeof(s_path),
"D:\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",k);
4962 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4964 for (
int k = 9; k>=0 && !path_found; --k) {
4965 cimg_snprintf(s_path,
sizeof(s_path),
"D:\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",k);
4966 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4968 for (
int k = 32; k>=0 && !path_found; --k) {
4969 cimg_snprintf(s_path,
sizeof(s_path),
"D:\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",k);
4970 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4972 if (!path_found) std::strcpy(s_path,
"gm.exe");
4975 std::strcpy(s_path,
"./gm");
4976 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
4978 if (!path_found) std::strcpy(s_path,
"gm");
4980 winformat_string(s_path);
4992 inline const char*
medcon_path(
const char *
const user_path=0,
const bool reinit_path=
false) {
4993 static char *s_path = 0;
4995 if (reinit_path) {
delete[] s_path; s_path = 0; }
4997 if (!s_path) s_path =
new char[1024];
4998 std::memset(s_path,0,1024);
4999 std::strncpy(s_path,user_path,1023);
5000 }
else if (!s_path) {
5001 s_path =
new char[1024];
5002 std::memset(s_path,0,1024);
5003 bool path_found =
false;
5004 std::FILE *file = 0;
5006 const char *
const pf_path = programfiles_path();
5008 std::strcpy(s_path,
".\\medcon.exe");
5009 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5012 cimg_snprintf(s_path,
sizeof(s_path),
"%s\\XMedCon\\bin\\medcon.bat",pf_path);
5013 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5016 cimg_snprintf(s_path,
sizeof(s_path),
"%s\\XMedCon\\bin\\medcon.exe",pf_path);
5017 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5020 std::strcpy(s_path,
"C:\\XMedCon\\bin\\medcon.exe");
5021 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5023 if (!path_found) std::strcpy(s_path,
"medcon.exe");
5026 std::strcpy(s_path,
"./medcon");
5027 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5029 if (!path_found) std::strcpy(s_path,
"medcon");
5031 winformat_string(s_path);
5043 inline const char *
ffmpeg_path(
const char *
const user_path=0,
const bool reinit_path=
false) {
5044 static char *s_path = 0;
5046 if (reinit_path) {
delete[] s_path; s_path = 0; }
5048 if (!s_path) s_path =
new char[1024];
5049 std::memset(s_path,0,1024);
5050 std::strncpy(s_path,user_path,1023);
5051 }
else if (!s_path) {
5052 s_path =
new char[1024];
5053 std::memset(s_path,0,1024);
5054 bool path_found =
false;
5055 std::FILE *file = 0;
5058 std::strcpy(s_path,
".\\ffmpeg.exe");
5059 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5061 if (!path_found) std::strcpy(s_path,
"ffmpeg.exe");
5064 std::strcpy(s_path,
"./ffmpeg");
5065 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5067 if (!path_found) std::strcpy(s_path,
"ffmpeg");
5069 winformat_string(s_path);
5081 inline const char *
gzip_path(
const char *
const user_path=0,
const bool reinit_path=
false) {
5082 static char *s_path = 0;
5084 if (reinit_path) {
delete[] s_path; s_path = 0; }
5086 if (!s_path) s_path =
new char[1024];
5087 std::memset(s_path,0,1024);
5088 std::strncpy(s_path,user_path,1023);
5089 }
else if (!s_path) {
5090 s_path =
new char[1024];
5091 std::memset(s_path,0,1024);
5092 bool path_found =
false;
5093 std::FILE *file = 0;
5096 std::strcpy(s_path,
".\\gzip.exe");
5097 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5099 if (!path_found) std::strcpy(s_path,
"gzip.exe");
5102 std::strcpy(s_path,
"./gzip");
5103 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5105 if (!path_found) std::strcpy(s_path,
"gzip");
5107 winformat_string(s_path);
5119 inline const char *
gunzip_path(
const char *
const user_path=0,
const bool reinit_path=
false) {
5120 static char *s_path = 0;
5122 if (reinit_path) {
delete[] s_path; s_path = 0; }
5124 if (!s_path) s_path =
new char[1024];
5125 std::memset(s_path,0,1024);
5126 std::strncpy(s_path,user_path,1023);
5127 }
else if (!s_path) {
5128 s_path =
new char[1024];
5129 std::memset(s_path,0,1024);
5130 bool path_found =
false;
5131 std::FILE *file = 0;
5134 std::strcpy(s_path,
".\\gunzip.exe");
5135 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5137 if (!path_found) std::strcpy(s_path,
"gunzip.exe");
5140 std::strcpy(s_path,
"./gunzip");
5141 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5143 if (!path_found) std::strcpy(s_path,
"gunzip");
5145 winformat_string(s_path);
5157 inline const char *
dcraw_path(
const char *
const user_path=0,
const bool reinit_path=
false) {
5158 static char *s_path = 0;
5160 if (reinit_path) {
delete[] s_path; s_path = 0; }
5162 if (!s_path) s_path =
new char[1024];
5163 std::memset(s_path,0,1024);
5164 std::strncpy(s_path,user_path,1023);
5165 }
else if (!s_path) {
5166 s_path =
new char[1024];
5167 std::memset(s_path,0,1024);
5168 bool path_found =
false;
5169 std::FILE *file = 0;
5172 std::strcpy(s_path,
".\\dcraw.exe");
5173 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5175 if (!path_found) std::strcpy(s_path,
"dcraw.exe");
5178 std::strcpy(s_path,
"./dcraw");
5179 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5181 if (!path_found) std::strcpy(s_path,
"dcraw");
5183 winformat_string(s_path);
5195 inline const char *
wget_path(
const char *
const user_path=0,
const bool reinit_path=
false) {
5196 static char *s_path = 0;
5198 if (reinit_path) {
delete[] s_path; s_path = 0; }
5200 if (!s_path) s_path =
new char[1024];
5201 std::memset(s_path,0,1024);
5202 std::strncpy(s_path,user_path,1023);
5203 }
else if (!s_path) {
5204 s_path =
new char[1024];
5205 std::memset(s_path,0,1024);
5206 bool path_found =
false;
5207 std::FILE *file = 0;
5210 std::strcpy(s_path,
".\\wget.exe");
5211 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5213 if (!path_found) std::strcpy(s_path,
"wget.exe");
5216 std::strcpy(s_path,
"./wget");
5217 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5219 if (!path_found) std::strcpy(s_path,
"wget");
5221 winformat_string(s_path);
5233 inline const char *
curl_path(
const char *
const user_path=0,
const bool reinit_path=
false) {
5234 static char *s_path = 0;
5236 if (reinit_path) {
delete[] s_path; s_path = 0; }
5238 if (!s_path) s_path =
new char[1024];
5239 std::memset(s_path,0,1024);
5240 std::strncpy(s_path,user_path,1023);
5241 }
else if (!s_path) {
5242 s_path =
new char[1024];
5243 std::memset(s_path,0,1024);
5244 bool path_found =
false;
5245 std::FILE *file = 0;
5248 std::strcpy(s_path,
".\\curl.exe");
5249 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5251 if (!path_found) std::strcpy(s_path,
"curl.exe");
5254 std::strcpy(s_path,
"./curl");
5255 if ((file=std::fopen(s_path,
"r"))!=0) {
cimg::fclose(file); path_found =
true; }
5257 if (!path_found) std::strcpy(s_path,
"curl");
5259 winformat_string(s_path);
5267 if (!filename) {
if (body) *body = 0;
return 0; }
5268 const char *p = 0;
for (
const char *np = filename; np>=filename && (p=np); np = std::strchr(np,
'.')+1) {}
5270 if (body) std::strcpy(body,filename);
5271 return filename + std::strlen(filename);
5273 const unsigned int l = (
unsigned int)(p - filename - 1);
5274 if (body) { std::memcpy(body,filename,l); body[l] = 0; }
5280 const unsigned int digits,
char *
const str) {
5281 if (!filename) {
if (str) *str = 0;
return 0; }
5282 char format[1024] = { 0 }, body[1024] = { 0 };
5284 if (*ext) cimg_snprintf(format,
sizeof(format),
"%%s_%%.%ud.%%s",digits);
5285 else cimg_snprintf(format,
sizeof(format),
"%%s_%%.%ud",digits);
5286 std::sprintf(str,format,body,number,ext);
5296 inline const char *
file_type(std::FILE *
const file,
const char *
const filename) {
5297 if (!file && !filename)
5300 *
const _pnm =
"pnm",
5301 *
const _pfm =
"pfm",
5302 *
const _bmp =
"bmp",
5303 *
const _gif =
"gif",
5304 *
const _jpg =
"jpg",
5305 *
const _off =
"off",
5306 *
const _pan =
"pan",
5307 *
const _png =
"png",
5308 *
const _tif =
"tif",
5309 *
const _inr =
"inr",
5310 *
const _dcm =
"dcm";
5311 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"rb");
5312 const char *f_type = 0, *head;
5313 char header[2048] = { 0 }, item[1024] = { 0 };
5314 const unsigned char *
const uheader = (
unsigned char*)header;
5316 const unsigned int siz = (
unsigned int)std::fread(header,2048,1,nfile);
5319 if (!std::strncmp(header,
"OFF\n",4)) f_type = _off;
5320 else if (!std::strncmp(header,
"#INRIMAGE",9)) f_type = _inr;
5321 else if (!std::strncmp(header,
"PANDORE",7)) f_type = _pan;
5322 else if (!std::strncmp(header+128,
"DICM",4)) f_type = _dcm;
5323 else if (uheader[0]==0xFF && uheader[1]==0xD8 && uheader[2]==0xFF) f_type = _jpg;
5324 else if (header[0]==
'B' && header[1]==
'M') f_type = _bmp;
5325 else if (header[0]==
'G' && header[1]==
'I' && header[2]==
'F' && header[3]==
'8' && header[5]==
'a' &&
5326 (header[4]==
'7' || header[4]==
'9')) f_type = _gif;
5327 else if (uheader[0]==0x89 && uheader[1]==0x50 && uheader[2]==0x4E && uheader[3]==0x47 &&
5328 uheader[4]==0x0D && uheader[5]==0x0A && uheader[6]==0x1A && uheader[7]==0x0A) f_type = _png;
5329 else if ((uheader[0]==0x49 && uheader[1]==0x49) || (uheader[0]==0x4D && uheader[1]==0x4D)) f_type = _tif;
5332 while (head<header+siz && (err=std::sscanf(head,
"%1023[^\n]",item))!=EOF && (*item==
'#' || !err))
5333 head+=1+(err?std::strlen(item):0);
5334 if (std::sscanf(item,
" P%d",&err)==1) f_type = _pnm;
5335 else if (std::sscanf(item,
" P%c",&cerr)==1 && (cerr==
'f' || cerr==
'F')) f_type = _pfm;
5348 template<
typename T>
5349 inline int fread(T *
const ptr,
const unsigned long nmemb, std::FILE *stream) {
5350 if (!ptr || nmemb<=0 || !stream)
5351 throw CImgArgumentException(
"cimg::fread(): Invalid reading request of %u %s%s from file %p to buffer %p.",
5354 const unsigned long wlimitT = 63*1024*1024, wlimit = wlimitT/
sizeof(T);
5355 unsigned long to_read = nmemb, al_read = 0, l_to_read = 0, l_al_read = 0;
5357 l_to_read = (to_read*
sizeof(T))<wlimitT?to_read:wlimit;
5358 l_al_read = (
unsigned long)std::fread((
void*)(ptr+al_read),
sizeof(T),l_to_read,stream);
5361 }
while (l_to_read==l_al_read && to_read>0);
5363 warn(
"cimg::fread(): Only %u/%u elements could be read from file.",
5376 template<
typename T>
5377 inline int fwrite(
const T *ptr,
const unsigned long nmemb, std::FILE *stream) {
5378 if (!ptr || !stream)
5379 throw CImgArgumentException(
"cimg::fwrite(): Invalid writing request of %u %s%s from buffer %p to file %p.",
5381 if (nmemb<=0)
return 0;
5382 const unsigned long wlimitT = 63*1024*1024, wlimit = wlimitT/
sizeof(T);
5383 unsigned long to_write = nmemb, al_write = 0, l_to_write = 0, l_al_write = 0;
5385 l_to_write = (to_write*
sizeof(T))<wlimitT?to_write:wlimit;
5386 l_al_write = (
unsigned long)std::fwrite((
void*)(ptr+al_write),
sizeof(T),l_to_write,stream);
5387 al_write+=l_al_write;
5388 to_write-=l_al_write;
5389 }
while (l_to_write==l_al_write && to_write>0);
5391 warn(
"cimg::fwrite(): Only %u/%u elements could be written in file.",
5401 inline void fempty(std::FILE *
const file,
const char *
const filename) {
5402 if (!file && !filename)
5404 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"wb");
5419 if (!filename_local)
5420 throw CImgArgumentException(
"cimg::load_network_external(): Specified destination string is (null).");
5421 const char *
const _ext =
cimg::split_filename(filename), *
const ext = (*_ext && _ext>filename)?_ext-1:_ext;
5422 char command[1024] = { 0 };
5423 std::FILE *file = 0;
5424 *filename_local = 0;
5426 cimg_snprintf(filename_local,512,
"%s%c%s%s",
5428 if ((file=std::fopen(filename_local,
"rb"))!=0)
cimg::fclose(file);
5432 cimg_snprintf(command,
sizeof(command),
"%s -f --silent --compressed -o \"%s\" \"%s\"",
5435 if (!(file = std::fopen(filename_local,
"rb"))) {
5438 cimg_snprintf(command,
sizeof(command),
"%s -q -r -l 0 --no-cache -O \"%s\" \"%s\"",
5441 if (!(file = std::fopen(filename_local,
"rb")))
5442 throw CImgIOException(
"cimg::load_network_external(): Failed to load file '%s' with external commands "
5443 "'wget' or 'curl'.",filename);
5447 cimg_snprintf(command,
sizeof(command),
"%s.gz",filename_local);
5448 std::rename(filename_local,command);
5449 cimg_snprintf(command,
sizeof(command),
"%s --quiet \"%s.gz\"",
5452 file = std::fopen(filename_local,
"rb");
5454 cimg_snprintf(command,
sizeof(command),
"%s.gz",filename_local);
5455 std::rename(command,filename_local);
5456 file = std::fopen(filename_local,
"rb");
5459 std::fseek(file,0,SEEK_END);
5460 if (std::ftell(file)<=0)
5461 throw CImgIOException(
"cimg::load_network_external(): Failed to load file '%s' with external commands "
5462 "'wget' or 'curl'.",filename);
5464 return filename_local;
5468 inline const char*
option(
const char *
const name,
const int argc,
const char *
const *
const argv,
5469 const char *
const defaut,
const char *
const usage,
const bool reset_static) {
5470 static bool first =
true, visu =
false;
5471 if (reset_static) { first =
true;
return 0; }
5472 const char *res = 0;
5475 visu =
cimg::option(
"-h",argc,argv,(
char*)0,(
char*)0,
false)!=0;
5476 visu |=
cimg::option(
"-help",argc,argv,(
char*)0,(
char*)0,
false)!=0;
5477 visu |=
cimg::option(
"--help",argc,argv,(
char*)0,(
char*)0,
false)!=0;
5479 if (!name && visu) {
5483 std::fprintf(
cimg::output(),
" (%s, %s)\n\n",__DATE__,__TIME__);
5485 if (defaut) std::fprintf(
cimg::output(),
"%s\n",defaut);
5490 while (k<argc && std::strcmp(argv[k],name)) ++k;
5491 res = (k++==argc?defaut:(k==argc?argv[--k]:argv[k]));
5492 }
else res = defaut;
5493 if (visu && usage) std::fprintf(
cimg::output(),
" %s%-16s%s %-24s %s%s%s\n",
5494 cimg::t_bold,name,cimg::t_normal,res?res:
"0",
5495 cimg::t_green,usage,cimg::t_normal);
5500 inline const char*
option(
const char *
const name,
const int argc,
const char *
const *
const argv,
5501 const char *
const defaut,
const char *
const usage=0) {
5502 return option(name,argc,argv,defaut,usage,
false);
5505 inline bool option(
const char *
const name,
const int argc,
const char *
const *
const argv,
5506 const bool defaut,
const char *
const usage=0) {
5507 const char *
const s =
cimg::option(name,argc,argv,(
char*)0);
5513 inline int option(
const char *
const name,
const int argc,
const char *
const *
const argv,
5514 const int defaut,
const char *
const usage=0) {
5515 const char *
const s =
cimg::option(name,argc,argv,(
char*)0);
5516 const int res = s?std::atoi(s):defaut;
5517 char tmp[256] = { 0 };
5518 cimg_snprintf(tmp,
sizeof(tmp),
"%d",res);
5523 inline char option(
const char *
const name,
const int argc,
const char *
const *
const argv,
5524 const char defaut,
const char *
const usage=0) {
5525 const char *
const s =
cimg::option(name,argc,argv,(
char*)0);
5526 const char res = s?*s:defaut;
5527 char tmp[8] = { 0 };
5533 inline float option(
const char *
const name,
const int argc,
const char *
const *
const argv,
5534 const float defaut,
const char *
const usage=0) {
5535 const char *
const s =
cimg::option(name,argc,argv,(
char*)0);
5536 const float res = s?(float)
cimg::atof(s):defaut;
5537 char tmp[256] = { 0 };
5538 cimg_snprintf(tmp,
sizeof(tmp),
"%g",res);
5543 inline double option(
const char *
const name,
const int argc,
const char *
const *
const argv,
5544 const double defaut,
const char *
const usage=0) {
5545 const char *
const s =
cimg::option(name,argc,argv,(
char*)0);
5547 char tmp[256] = { 0 };
5548 cimg_snprintf(tmp,
sizeof(tmp),
"%g",res);
5553 inline const char* argument(
const unsigned int nb,
const int argc,
const char *
const *
const argv,
5554 const unsigned int nb_singles=0, ...) {
5555 for (
int k = 1, pos = 0; k<argc;) {
5556 const char *
const item = argv[k];
5557 bool option = (*item==
'-'), single_option =
false;
5560 va_start(ap,nb_singles);
5561 for (
unsigned int i = 0; i<nb_singles; ++i)
if (!
cimg::strcasecmp(item,va_arg(ap,
char*))) {
5562 single_option =
true;
break;
5566 if (option) { ++k;
if (!single_option) ++k; }
5567 else {
if (pos++==(
int)nb)
return item;
else ++k; }
5577 char tmp[1024] = { 0 };
5578 std::fprintf(
cimg::output(),
"\n %s%sCImg Library %u.%u.%u%s, compiled %s ( %s ) with the following flags:\n\n",
5579 cimg::t_red,cimg::t_bold,cimg_version/100,(cimg_version/10)%10,cimg_version%10,
5580 cimg::t_normal,__DATE__,__TIME__);
5582 std::fprintf(
cimg::output(),
" > Operating System: %s%-13s%s %s('cimg_OS'=%d)%s\n",
5584 cimg_OS==1?
"Unix":(cimg_OS==2?
"Windows":
"Unknow"),
5585 cimg::t_normal,cimg::t_green,
5589 std::fprintf(
cimg::output(),
" > CPU endianness: %s%s Endian%s\n",
5594 std::fprintf(
cimg::output(),
" > Verbosity mode: %s%-13s%s %s('cimg_verbosity'=%d)%s\n",
5596 cimg_verbosity==0?
"Quiet":
5597 cimg_verbosity==1?
"Console":
5598 cimg_verbosity==2?
"Dialog":
5599 cimg_verbosity==3?
"Console+Warnings":
"Dialog+Warnings",
5600 cimg::t_normal,cimg::t_green,
5604 std::fprintf(
cimg::output(),
" > Stricts warnings: %s%-13s%s %s('cimg_strict_warnings' %s)%s\n",
5606 #ifdef cimg_strict_warnings
5607 "Yes",cimg::t_normal,cimg::t_green,
"defined",
5609 "No",cimg::t_normal,cimg::t_green,
"undefined",
5613 std::fprintf(
cimg::output(),
" > Using VT100 messages: %s%-13s%s %s('cimg_use_vt100' %s)%s\n",
5615 #ifdef cimg_use_vt100
5616 "Yes",cimg::t_normal,cimg::t_green,
"defined",
5618 "No",cimg::t_normal,cimg::t_green,
"undefined",
5622 std::fprintf(
cimg::output(),
" > Display type: %s%-13s%s %s('cimg_display'=%d)%s\n",
5624 cimg_display==0?
"No display":cimg_display==1?
"X11":cimg_display==2?
"Windows GDI":
"Unknown",
5625 cimg::t_normal,cimg::t_green,
5630 std::fprintf(
cimg::output(),
" > Using XShm for X11: %s%-13s%s %s('cimg_use_xshm' %s)%s\n",
5632 #ifdef cimg_use_xshm
5633 "Yes",cimg::t_normal,cimg::t_green,
"defined",
5635 "No",cimg::t_normal,cimg::t_green,
"undefined",
5639 std::fprintf(
cimg::output(),
" > Using XRand for X11: %s%-13s%s %s('cimg_use_xrandr' %s)%s\n",
5641 #ifdef cimg_use_xrandr
5642 "Yes",cimg::t_normal,cimg::t_green,
"defined",
5644 "No",cimg::t_normal,cimg::t_green,
"undefined",
5648 std::fprintf(
cimg::output(),
" > Using OpenMP: %s%-13s%s %s('cimg_use_openmp' %s)%s\n",
5650 #ifdef cimg_use_openmp
5651 "Yes",cimg::t_normal,cimg::t_green,
"defined",
5653 "No",cimg::t_normal,cimg::t_green,
"undefined",
5656 std::fprintf(
cimg::output(),
" > Using PNG library: %s%-13s%s %s('cimg_use_png' %s)%s\n",
5659 "Yes",cimg::t_normal,cimg::t_green,
"defined",
5661 "No",cimg::t_normal,cimg::t_green,
"undefined",
5664 std::fprintf(
cimg::output(),
" > Using JPEG library: %s%-13s%s %s('cimg_use_jpeg' %s)%s\n",
5666 #ifdef cimg_use_jpeg
5667 "Yes",cimg::t_normal,cimg::t_green,
"defined",
5669 "No",cimg::t_normal,cimg::t_green,
"undefined",
5673 std::fprintf(
cimg::output(),
" > Using TIFF library: %s%-13s%s %s('cimg_use_tiff' %s)%s\n",
5675 #ifdef cimg_use_tiff
5676 "Yes",cimg::t_normal,cimg::t_green,
"defined",
5678 "No",cimg::t_normal,cimg::t_green,
"undefined",
5682 std::fprintf(
cimg::output(),
" > Using Magick++ library: %s%-13s%s %s('cimg_use_magick' %s)%s\n",
5684 #ifdef cimg_use_magick
5685 "Yes",cimg::t_normal,cimg::t_green,
"defined",
5687 "No",cimg::t_normal,cimg::t_green,
"undefined",
5691 std::fprintf(
cimg::output(),
" > Using FFTW3 library: %s%-13s%s %s('cimg_use_fftw3' %s)%s\n",
5693 #ifdef cimg_use_fftw3
5694 "Yes",cimg::t_normal,cimg::t_green,
"defined",
5696 "No",cimg::t_normal,cimg::t_green,
"undefined",
5700 std::fprintf(
cimg::output(),
" > Using LAPACK library: %s%-13s%s %s('cimg_use_lapack' %s)%s\n",
5702 #ifdef cimg_use_lapack
5703 "Yes",cimg::t_normal,cimg::t_green,
"defined",
5705 "No",cimg::t_normal,cimg::t_green,
"undefined",
5710 std::fprintf(
cimg::output(),
" > Path of ImageMagick: %s%-13s%s\n",
5716 std::fprintf(
cimg::output(),
" > Path of GraphicsMagick: %s%-13s%s\n",
5722 std::fprintf(
cimg::output(),
" > Path of 'medcon': %s%-13s%s\n",
5728 std::fprintf(
cimg::output(),
" > Temporary path: %s%-13s%s\n",
5737 #ifdef cimg_use_lapack
5738 template<
typename T>
5739 inline void getrf(
int &N, T *lapA,
int *IPIV,
int &INFO) {
5740 dgetrf_(&N,&N,lapA,&N,IPIV,&INFO);
5743 inline void getrf(
int &N,
float *lapA,
int *IPIV,
int &INFO) {
5744 sgetrf_(&N,&N,lapA,&N,IPIV,&INFO);
5747 template<
typename T>
5748 inline void getri(
int &N, T *lapA,
int *IPIV, T* WORK,
int &LWORK,
int &INFO) {
5749 dgetri_(&N,lapA,&N,IPIV,WORK,&LWORK,&INFO);
5752 inline void getri(
int &N,
float *lapA,
int *IPIV,
float* WORK,
int &LWORK,
int &INFO) {
5753 sgetri_(&N,lapA,&N,IPIV,WORK,&LWORK,&INFO);
5756 template<
typename T>
5757 inline void gesvd(
char &JOB,
int &M,
int &N, T *lapA,
int &MN,
5758 T *lapS, T *lapU, T *lapV, T *WORK,
int &LWORK,
int &INFO) {
5759 dgesvd_(&JOB,&JOB,&M,&N,lapA,&MN,lapS,lapU,&M,lapV,&N,WORK,&LWORK,&INFO);
5762 inline void gesvd(
char &JOB,
int &M,
int &N,
float *lapA,
int &MN,
5763 float *lapS,
float *lapU,
float *lapV,
float *WORK,
int &LWORK,
int &INFO) {
5764 sgesvd_(&JOB,&JOB,&M,&N,lapA,&MN,lapS,lapU,&M,lapV,&N,WORK,&LWORK,&INFO);
5767 template<
typename T>
5768 inline void getrs(
char &TRANS,
int &N, T *lapA,
int *IPIV, T *lapB,
int &INFO) {
5770 dgetrs_(&TRANS,&N,&one,lapA,&N,IPIV,lapB,&N,&INFO);
5773 inline void getrs(
char &TRANS,
int &N,
float *lapA,
int *IPIV,
float *lapB,
int &INFO) {
5775 sgetrs_(&TRANS,&N,&one,lapA,&N,IPIV,lapB,&N,&INFO);
5778 template<
typename T>
5779 inline void syev(
char &JOB,
char &UPLO,
int &N, T *lapA, T *lapW, T *WORK,
int &LWORK,
int &INFO) {
5780 dsyev_(&JOB,&UPLO,&N,lapA,&N,lapW,WORK,&LWORK,&INFO);
5783 inline void syev(
char &JOB,
char &UPLO,
int &N,
float *lapA,
float *lapW,
float *WORK,
int &LWORK,
int &INFO) {
5784 ssyev_(&JOB,&UPLO,&N,lapA,&N,lapW,WORK,&LWORK,&INFO);
5787 template<
typename T>
5788 inline void sgels(
char & TRANS,
int &M,
int &N,
int &NRHS, T* lapA,
int &LDA,
5789 T* lapB,
int &LDB, T* WORK,
int &LWORK,
int &INFO){
5790 dgels_(&TRANS, &M, &N, &NRHS, lapA, &LDA, lapB, &LDB, WORK, &LWORK, &INFO);
5793 inline void sgels(
char & TRANS,
int &M,
int &N,
int &NRHS,
float* lapA,
int &LDA,
5794 float* lapB,
int &LDB,
float* WORK,
int &LWORK,
int &INFO){
5795 sgels_(&TRANS, &M, &N, &NRHS, lapA, &LDA, lapB, &LDB, WORK, &LWORK, &INFO);
5812 #define _cimg_create_ext_operators(typ) \
5813 template<typename T> \
5814 inline CImg<typename cimg::superset<T,typ>::type> operator+(const typ val, const CImg<T>& img) { \
5817 template<typename T> \
5818 inline CImg<typename cimg::superset<T,typ>::type> operator-(const typ val, const CImg<T>& img) { \
5819 typedef typename cimg::superset<T,typ>::type Tt; \
5820 return CImg<Tt>(img._width,img._height,img._depth,img._spectrum,val)-=img; \
5822 template<typename T> \
5823 inline CImg<typename cimg::superset<T,typ>::type> operator*(const typ val, const CImg<T>& img) { \
5826 template<typename T> \
5827 inline CImg<typename cimg::superset<T,typ>::type> operator/(const typ val, const CImg<T>& img) { \
5828 return val*img.get_invert(); \
5830 template<typename T> \
5831 inline CImg<typename cimg::superset<T,typ>::type> operator&(const typ val, const CImg<T>& img) { \
5834 template<typename T> \
5835 inline CImg<typename cimg::superset<T,typ>::type> operator|(const typ val, const CImg<T>& img) { \
5838 template<typename T> \
5839 inline CImg<typename cimg::superset<T,typ>::type> operator^(const typ val, const CImg<T>& img) { \
5842 template<typename T> \
5843 inline bool operator==(const typ val, const CImg<T>& img) { \
5844 return img == val; \
5846 template<typename T> \
5847 inline bool operator!=(const typ val, const CImg<T>& img) { \
5848 return img != val; \
5851 _cimg_create_ext_operators(
bool)
5852 _cimg_create_ext_operators(
unsigned char)
5853 _cimg_create_ext_operators(
char)
5854 _cimg_create_ext_operators(
signed char)
5855 _cimg_create_ext_operators(
unsigned short)
5856 _cimg_create_ext_operators(
short)
5857 _cimg_create_ext_operators(
unsigned int)
5858 _cimg_create_ext_operators(
int)
5859 _cimg_create_ext_operators(
unsigned long)
5860 _cimg_create_ext_operators(
long)
5861 _cimg_create_ext_operators(
float)
5862 _cimg_create_ext_operators(
double)
5864 template<typename T>
5865 inline CImg<_cimg_Tfloat> operator+(const
char *const expression, const CImg<T>& img) {
5866 return img + expression;
5869 template<
typename T>
5870 inline CImg<_cimg_Tfloat> operator-(
const char *
const expression,
const CImg<T>& img) {
5871 return CImg<_cimg_Tfloat>(img._width,img._height,img._depth,img._spectrum,expression,
true)-=img;
5874 template<
typename T>
5875 inline CImg<_cimg_Tfloat> operator*(
const char *
const expression,
const CImg<T>& img) {
5876 return img*expression;
5879 template<
typename T>
5880 inline CImg<_cimg_Tfloat> operator/(
const char *
const expression,
const CImg<T>& img) {
5881 return expression*img.get_invert();
5884 template<
typename T>
5885 inline CImg<T> operator&(
const char *
const expression,
const CImg<T>& img) {
5886 return img & expression;
5889 template<
typename T>
5890 inline CImg<T> operator|(
const char *
const expression,
const CImg<T>& img) {
5891 return img | expression;
5894 template<
typename T>
5895 inline CImg<T> operator^(
const char *
const expression,
const CImg<T>& img) {
5896 return img ^ expression;
5899 template<
typename T>
5900 inline bool operator==(
const char *
const expression,
const CImg<T>& img) {
5901 return img == expression;
5904 template<
typename T>
5905 inline bool operator!=(
const char *
const expression,
const CImg<T>& img) {
5906 return img != expression;
5909 template<
typename T>
5910 inline CImg<_cimg_Tfloat>
sqr(
const CImg<T>& instance) {
5911 return instance.get_sqr();
5914 template<
typename T>
5915 inline CImg<_cimg_Tfloat> sqrt(
const CImg<T>& instance) {
5916 return instance.get_sqrt();
5919 template<
typename T>
5920 inline CImg<_cimg_Tfloat> exp(
const CImg<T>& instance) {
5921 return instance.get_exp();
5924 template<
typename T>
5925 inline CImg<_cimg_Tfloat> log(
const CImg<T>& instance) {
5926 return instance.get_log();
5929 template<
typename T>
5930 inline CImg<_cimg_Tfloat>
log2(
const CImg<T>& instance) {
5931 return instance.get_log2();
5934 template<
typename T>
5935 inline CImg<_cimg_Tfloat> log10(
const CImg<T>& instance) {
5936 return instance.get_log10();
5939 template<
typename T>
5940 inline CImg<_cimg_Tfloat>
abs(
const CImg<T>& instance) {
5941 return instance.get_abs();
5944 template<
typename T>
5945 inline CImg<_cimg_Tfloat>
sign(
const CImg<T>& instance) {
5946 return instance.get_sign();
5949 template<
typename T>
5950 inline CImg<_cimg_Tfloat> cos(
const CImg<T>& instance) {
5951 return instance.get_cos();
5954 template<
typename T>
5955 inline CImg<_cimg_Tfloat> sin(
const CImg<T>& instance) {
5956 return instance.get_sin();
5959 template<
typename T>
5960 inline CImg<_cimg_Tfloat>
sinc(
const CImg<T>& instance) {
5961 return instance.get_sinc();
5964 template<
typename T>
5965 inline CImg<_cimg_Tfloat> tan(
const CImg<T>& instance) {
5966 return instance.get_tan();
5969 template<
typename T>
5970 inline CImg<_cimg_Tfloat> acos(
const CImg<T>& instance) {
5971 return instance.get_acos();
5974 template<
typename T>
5975 inline CImg<_cimg_Tfloat> asin(
const CImg<T>& instance) {
5976 return instance.get_asin();
5979 template<
typename T>
5980 inline CImg<_cimg_Tfloat> atan(
const CImg<T>& instance) {
5981 return instance.get_atan();
5984 template<
typename T>
5985 inline CImg<_cimg_Tfloat> cosh(
const CImg<T>& instance) {
5986 return instance.get_cosh();
5989 template<
typename T>
5990 inline CImg<_cimg_Tfloat> sinh(
const CImg<T>& instance) {
5991 return instance.get_sinh();
5994 template<
typename T>
5995 inline CImg<_cimg_Tfloat> tanh(
const CImg<T>& instance) {
5996 return instance.get_tanh();
5999 template<
typename T>
6000 inline CImg<T> transpose(
const CImg<T>& instance) {
6001 return instance.get_transpose();
6004 template<
typename T>
6005 inline CImg<_cimg_Tfloat> invert(
const CImg<T>& instance) {
6006 return instance.get_invert();
6009 template<
typename T>
6010 inline CImg<_cimg_Tfloat> pseudoinvert(
const CImg<T>& instance) {
6011 return instance.get_pseudoinvert();
6037 unsigned long _timer, _fps_frames, _fps_timer;
6038 unsigned int _width, _height, _normalization;
6039 float _fps_fps, _min, _max;
6040 bool _is_fullscreen;
6042 volatile unsigned int _window_width, _window_height, _button, _keys[128], _released_keys[128];
6043 volatile int _window_x, _window_y, _mouse_x, _mouse_y, _wheel;
6044 volatile bool _is_closed, _is_resized, _is_moved, _is_event,
6045 _is_keyESC, _is_keyF1, _is_keyF2, _is_keyF3, _is_keyF4, _is_keyF5, _is_keyF6, _is_keyF7,
6046 _is_keyF8, _is_keyF9, _is_keyF10, _is_keyF11, _is_keyF12, _is_keyPAUSE, _is_key1, _is_key2,
6047 _is_key3, _is_key4, _is_key5, _is_key6, _is_key7, _is_key8, _is_key9, _is_key0,
6048 _is_keyBACKSPACE, _is_keyINSERT, _is_keyHOME, _is_keyPAGEUP, _is_keyTAB, _is_keyQ, _is_keyW, _is_keyE,
6049 _is_keyR, _is_keyT, _is_keyY, _is_keyU, _is_keyI, _is_keyO, _is_keyP, _is_keyDELETE,
6050 _is_keyEND, _is_keyPAGEDOWN, _is_keyCAPSLOCK, _is_keyA, _is_keyS, _is_keyD, _is_keyF, _is_keyG,
6051 _is_keyH, _is_keyJ, _is_keyK, _is_keyL, _is_keyENTER, _is_keySHIFTLEFT, _is_keyZ, _is_keyX,
6052 _is_keyC, _is_keyV, _is_keyB, _is_keyN, _is_keyM, _is_keySHIFTRIGHT, _is_keyARROWUP, _is_keyCTRLLEFT,
6053 _is_keyAPPLEFT, _is_keyALT, _is_keySPACE, _is_keyALTGR, _is_keyAPPRIGHT, _is_keyMENU, _is_keyCTRLRIGHT,
6054 _is_keyARROWLEFT, _is_keyARROWDOWN, _is_keyARROWRIGHT, _is_keyPAD0, _is_keyPAD1, _is_keyPAD2, _is_keyPAD3,
6055 _is_keyPAD4, _is_keyPAD5, _is_keyPAD6, _is_keyPAD7, _is_keyPAD8, _is_keyPAD9, _is_keyPADADD, _is_keyPADSUB,
6056 _is_keyPADMUL, _is_keyPADDIV;
6065 #ifdef cimgdisplay_plugin
6066 #include cimgdisplay_plugin
6068 #ifdef cimgdisplay_plugin1
6069 #include cimgdisplay_plugin1
6071 #ifdef cimgdisplay_plugin2
6072 #include cimgdisplay_plugin2
6074 #ifdef cimgdisplay_plugin3
6075 #include cimgdisplay_plugin3
6077 #ifdef cimgdisplay_plugin4
6078 #include cimgdisplay_plugin4
6080 #ifdef cimgdisplay_plugin5
6081 #include cimgdisplay_plugin5
6083 #ifdef cimgdisplay_plugin6
6084 #include cimgdisplay_plugin6
6086 #ifdef cimgdisplay_plugin7
6087 #include cimgdisplay_plugin7
6089 #ifdef cimgdisplay_plugin8
6090 #include cimgdisplay_plugin8
6120 _width(0),_height(0),_normalization(0),
6122 _is_fullscreen(false),
6124 _window_width(0),_window_height(0),_button(0),
6125 _window_x(0),_window_y(0),_mouse_x(-1),_mouse_y(-1),_wheel(0),
6126 _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) {
6143 _width(0),_height(0),_normalization(0),
6145 _is_fullscreen(false),
6147 _window_width(0),_window_height(0),_button(0),
6148 _window_x(0),_window_y(0),_mouse_x(-1),_mouse_y(-1),_wheel(0),
6149 _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) {
6162 template<
typename T>
6166 _width(0),_height(0),_normalization(0),
6168 _is_fullscreen(false),
6170 _window_width(0),_window_height(0),_button(0),
6171 _window_x(0),_window_y(0),_mouse_x(-1),_mouse_y(-1),_wheel(0),
6172 _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) {
6185 template<
typename T>
6189 _width(0),_height(0),_normalization(0),
6191 _is_fullscreen(false),
6193 _window_width(0),_window_height(0),_button(0),
6194 _window_x(0),_window_y(0),_mouse_x(-1),_mouse_y(-1),_wheel(0),
6195 _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) {
6205 _width(0),_height(0),_normalization(0),
6207 _is_fullscreen(false),
6209 _window_width(0),_window_height(0),_button(0),
6210 _window_x(0),_window_y(0),_mouse_x(-1),_mouse_y(-1),_wheel(0),
6211 _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) {
6217 static void _no_display_exception() {
6236 _no_display_exception();
6243 template<
typename T>
6247 _no_display_exception();
6254 template<
typename T>
6258 _no_display_exception();
6266 _no_display_exception();
6267 return assign(disp._width,disp._height);
6286 #define cimg_fitscreen(dx,dy,dz) CImgDisplay::_fitscreen(dx,dy,dz,128,-85,false), \
6287 CImgDisplay::_fitscreen(dx,dy,dz,128,-85,true)
6288 static unsigned int _fitscreen(
const unsigned int dx,
const unsigned int dy,
const unsigned int dz,
6289 const int dmin,
const int dmax,
const bool return_y) {
6290 const unsigned int _nw = dx + (dz>1?dz:0), _nh = dy + (dz>1?dz:0);
6291 unsigned int nw = _nw?_nw:1, nh = _nh?_nh:1;
6294 mw = dmin<0?(
unsigned int)(sw*-dmin/100):(unsigned int)dmin,
6295 mh = dmin<0?(unsigned int)(sh*-dmin/100):(unsigned int)dmin,
6296 Mw = dmax<0?(unsigned int)(sw*-dmax/100):(unsigned int)dmax,
6297 Mh = dmax<0?(unsigned int)(sh*-dmax/100):(unsigned int)dmax;
6298 if (nw<mw) { nh = nh*mw/nw; nh+=(nh==0?1:0); nw = mw; }
6299 if (nh<mh) { nw = nw*mh/nh; nw+=(nw==0?1:0); nh = mh; }
6300 if (nw>Mw) { nh = nh*Mw/nw; nh+=(nh==0?1:0); nw = Mw; }
6301 if (nh>Mh) { nw = nw*Mh/nh; nw+=(nw==0?1:0); nh = Mh; }
6304 return return_y?nh:nw;
6318 template<
typename t>
6327 template<
typename t>
6344 operator bool()
const {
6359 return !(_width && _height);
6397 return _is_fullscreen;
6405 return _is_keyESC || _is_keyF1 || _is_keyF2 || _is_keyF3 ||
6406 _is_keyF4 || _is_keyF5 || _is_keyF6 || _is_keyF7 ||
6407 _is_keyF8 || _is_keyF9 || _is_keyF10 || _is_keyF11 ||
6408 _is_keyF12 || _is_keyPAUSE || _is_key1 || _is_key2 ||
6409 _is_key3 || _is_key4 || _is_key5 || _is_key6 ||
6410 _is_key7 || _is_key8 || _is_key9 || _is_key0 ||
6411 _is_keyBACKSPACE || _is_keyINSERT || _is_keyHOME ||
6412 _is_keyPAGEUP || _is_keyTAB || _is_keyQ || _is_keyW ||
6413 _is_keyE || _is_keyR || _is_keyT || _is_keyY ||
6414 _is_keyU || _is_keyI || _is_keyO || _is_keyP ||
6415 _is_keyDELETE || _is_keyEND || _is_keyPAGEDOWN ||
6416 _is_keyCAPSLOCK || _is_keyA || _is_keyS || _is_keyD ||
6417 _is_keyF || _is_keyG || _is_keyH || _is_keyJ ||
6418 _is_keyK || _is_keyL || _is_keyENTER ||
6419 _is_keySHIFTLEFT || _is_keyZ || _is_keyX || _is_keyC ||
6420 _is_keyV || _is_keyB || _is_keyN || _is_keyM ||
6421 _is_keySHIFTRIGHT || _is_keyARROWUP || _is_keyCTRLLEFT ||
6422 _is_keyAPPLEFT || _is_keyALT || _is_keySPACE || _is_keyALTGR ||
6423 _is_keyAPPRIGHT || _is_keyMENU || _is_keyCTRLRIGHT ||
6424 _is_keyARROWLEFT || _is_keyARROWDOWN || _is_keyARROWRIGHT ||
6425 _is_keyPAD0 || _is_keyPAD1 || _is_keyPAD2 ||
6426 _is_keyPAD3 || _is_keyPAD4 || _is_keyPAD5 ||
6427 _is_keyPAD6 || _is_keyPAD7 || _is_keyPAD8 ||
6428 _is_keyPAD9 || _is_keyPADADD || _is_keyPADSUB ||
6429 _is_keyPADMUL || _is_keyPADDIV;
6447 #define _cimg_iskey_test(k) if (keycode==cimg::key##k) return _is_key##k;
6448 _cimg_iskey_test(ESC); _cimg_iskey_test(F1); _cimg_iskey_test(F2); _cimg_iskey_test(F3);
6449 _cimg_iskey_test(F4); _cimg_iskey_test(F5); _cimg_iskey_test(F6); _cimg_iskey_test(F7);
6450 _cimg_iskey_test(F8); _cimg_iskey_test(F9); _cimg_iskey_test(F10); _cimg_iskey_test(F11);
6451 _cimg_iskey_test(F12); _cimg_iskey_test(PAUSE); _cimg_iskey_test(1); _cimg_iskey_test(2);
6452 _cimg_iskey_test(3); _cimg_iskey_test(4); _cimg_iskey_test(5); _cimg_iskey_test(6);
6453 _cimg_iskey_test(7); _cimg_iskey_test(8); _cimg_iskey_test(9); _cimg_iskey_test(0);
6454 _cimg_iskey_test(BACKSPACE); _cimg_iskey_test(INSERT); _cimg_iskey_test(HOME);
6455 _cimg_iskey_test(PAGEUP); _cimg_iskey_test(TAB); _cimg_iskey_test(Q); _cimg_iskey_test(W);
6456 _cimg_iskey_test(E); _cimg_iskey_test(R); _cimg_iskey_test(T); _cimg_iskey_test(Y);
6457 _cimg_iskey_test(U); _cimg_iskey_test(I); _cimg_iskey_test(O); _cimg_iskey_test(P);
6458 _cimg_iskey_test(DELETE); _cimg_iskey_test(END); _cimg_iskey_test(PAGEDOWN);
6459 _cimg_iskey_test(CAPSLOCK); _cimg_iskey_test(A); _cimg_iskey_test(S); _cimg_iskey_test(D);
6460 _cimg_iskey_test(F); _cimg_iskey_test(G); _cimg_iskey_test(H); _cimg_iskey_test(J);
6461 _cimg_iskey_test(K); _cimg_iskey_test(L); _cimg_iskey_test(ENTER);
6462 _cimg_iskey_test(SHIFTLEFT); _cimg_iskey_test(Z); _cimg_iskey_test(X); _cimg_iskey_test(C);
6463 _cimg_iskey_test(V); _cimg_iskey_test(B); _cimg_iskey_test(N); _cimg_iskey_test(M);
6464 _cimg_iskey_test(SHIFTRIGHT); _cimg_iskey_test(ARROWUP); _cimg_iskey_test(CTRLLEFT);
6465 _cimg_iskey_test(APPLEFT); _cimg_iskey_test(ALT); _cimg_iskey_test(SPACE); _cimg_iskey_test(ALTGR);
6466 _cimg_iskey_test(APPRIGHT); _cimg_iskey_test(MENU); _cimg_iskey_test(CTRLRIGHT);
6467 _cimg_iskey_test(ARROWLEFT); _cimg_iskey_test(ARROWDOWN); _cimg_iskey_test(ARROWRIGHT);
6468 _cimg_iskey_test(PAD0); _cimg_iskey_test(PAD1); _cimg_iskey_test(PAD2);
6469 _cimg_iskey_test(PAD3); _cimg_iskey_test(PAD4); _cimg_iskey_test(PAD5);
6470 _cimg_iskey_test(PAD6); _cimg_iskey_test(PAD7); _cimg_iskey_test(PAD8);
6471 _cimg_iskey_test(PAD9); _cimg_iskey_test(PADADD); _cimg_iskey_test(PADSUB);
6472 _cimg_iskey_test(PADMUL); _cimg_iskey_test(PADDIV);
6491 static bool f =
false;
6493 #define _cimg_iskey_test2(k) if (!cimg::strcasecmp(keycode,#k)) return _is_key##k;
6494 _cimg_iskey_test2(ESC); _cimg_iskey_test2(F1); _cimg_iskey_test2(F2); _cimg_iskey_test2(F3);
6495 _cimg_iskey_test2(F4); _cimg_iskey_test2(F5); _cimg_iskey_test2(F6); _cimg_iskey_test2(F7);
6496 _cimg_iskey_test2(F8); _cimg_iskey_test2(F9); _cimg_iskey_test2(F10); _cimg_iskey_test2(F11);
6497 _cimg_iskey_test2(F12); _cimg_iskey_test2(PAUSE); _cimg_iskey_test2(1); _cimg_iskey_test2(2);
6498 _cimg_iskey_test2(3); _cimg_iskey_test2(4); _cimg_iskey_test2(5); _cimg_iskey_test2(6);
6499 _cimg_iskey_test2(7); _cimg_iskey_test2(8); _cimg_iskey_test2(9); _cimg_iskey_test2(0);
6500 _cimg_iskey_test2(BACKSPACE); _cimg_iskey_test2(INSERT); _cimg_iskey_test2(HOME);
6501 _cimg_iskey_test2(PAGEUP); _cimg_iskey_test2(TAB); _cimg_iskey_test2(Q); _cimg_iskey_test2(W);
6502 _cimg_iskey_test2(E); _cimg_iskey_test2(R); _cimg_iskey_test2(T); _cimg_iskey_test2(Y);
6503 _cimg_iskey_test2(U); _cimg_iskey_test2(I); _cimg_iskey_test2(O); _cimg_iskey_test2(P);
6504 _cimg_iskey_test2(DELETE); _cimg_iskey_test2(END); _cimg_iskey_test2(PAGEDOWN);
6505 _cimg_iskey_test2(CAPSLOCK); _cimg_iskey_test2(A); _cimg_iskey_test2(S); _cimg_iskey_test2(D);
6506 _cimg_iskey_test2(F); _cimg_iskey_test2(G); _cimg_iskey_test2(H); _cimg_iskey_test2(J);
6507 _cimg_iskey_test2(K); _cimg_iskey_test2(L); _cimg_iskey_test2(ENTER);
6508 _cimg_iskey_test2(SHIFTLEFT); _cimg_iskey_test2(Z); _cimg_iskey_test2(X); _cimg_iskey_test2(C);
6509 _cimg_iskey_test2(V); _cimg_iskey_test2(B); _cimg_iskey_test2(N); _cimg_iskey_test2(M);
6510 _cimg_iskey_test2(SHIFTRIGHT); _cimg_iskey_test2(ARROWUP); _cimg_iskey_test2(CTRLLEFT);
6511 _cimg_iskey_test2(APPLEFT); _cimg_iskey_test2(ALT); _cimg_iskey_test2(SPACE); _cimg_iskey_test2(ALTGR);
6512 _cimg_iskey_test2(APPRIGHT); _cimg_iskey_test2(MENU); _cimg_iskey_test2(CTRLRIGHT);
6513 _cimg_iskey_test2(ARROWLEFT); _cimg_iskey_test2(ARROWDOWN); _cimg_iskey_test2(ARROWRIGHT);
6514 _cimg_iskey_test2(PAD0); _cimg_iskey_test2(PAD1); _cimg_iskey_test2(PAD2);
6515 _cimg_iskey_test2(PAD3); _cimg_iskey_test2(PAD4); _cimg_iskey_test2(PAD5);
6516 _cimg_iskey_test2(PAD6); _cimg_iskey_test2(PAD7); _cimg_iskey_test2(PAD8);
6517 _cimg_iskey_test2(PAD9); _cimg_iskey_test2(PADADD); _cimg_iskey_test2(PADSUB);
6518 _cimg_iskey_test2(PADMUL); _cimg_iskey_test2(PADDIV);
6539 bool is_key_sequence(
const unsigned int *
const keycodes_sequence,
const unsigned int length,
6540 const bool remove_sequence=
false) {
6541 if (keycodes_sequence && length) {
6543 *
const ps_end = keycodes_sequence + length - 1,
6544 *
const pk_end = (
unsigned int*)_keys + 1 +
sizeof(_keys)/
sizeof(
unsigned int) - length,
6546 for (
unsigned int *pk = (
unsigned int*)_keys; pk<pk_end; ) {
6549 const unsigned int *ps = ps_end, *pk2 = pk;
6550 for (
unsigned int i = 1; i<length; ++i) res = (*(--ps)==*(pk2++));
6552 if (remove_sequence) std::memset((
void*)(pk-1),0,
sizeof(
unsigned int)*length);
6561 #define _cimg_iskey_def(k) \
6562 bool is_key##k() const { \
6563 return _is_key##k; \
6609 _no_display_exception();
6617 _no_display_exception();
6638 return (
int)_height;
6665 return _normalization;
6683 return (
int)_window_width;
6692 return (
int)_window_height;
6803 unsigned int key(
const unsigned int pos=0)
const {
6804 return pos<(
sizeof(_keys)/
sizeof(
unsigned int))?_keys[pos]:0;
6821 return pos<(
sizeof(_released_keys)/
sizeof(
unsigned int))?_released_keys[pos]:0;
6834 #define _cimg_keycode(k) if (!cimg::strcasecmp(keycode,#k)) return cimg::key##k;
6835 _cimg_keycode(ESC); _cimg_keycode(F1); _cimg_keycode(F2); _cimg_keycode(F3);
6836 _cimg_keycode(F4); _cimg_keycode(F5); _cimg_keycode(F6); _cimg_keycode(F7);
6837 _cimg_keycode(F8); _cimg_keycode(F9); _cimg_keycode(F10); _cimg_keycode(F11);
6838 _cimg_keycode(F12); _cimg_keycode(PAUSE); _cimg_keycode(1); _cimg_keycode(2);
6839 _cimg_keycode(3); _cimg_keycode(4); _cimg_keycode(5); _cimg_keycode(6);
6840 _cimg_keycode(7); _cimg_keycode(8); _cimg_keycode(9); _cimg_keycode(0);
6841 _cimg_keycode(BACKSPACE); _cimg_keycode(INSERT); _cimg_keycode(HOME);
6842 _cimg_keycode(PAGEUP); _cimg_keycode(TAB); _cimg_keycode(Q); _cimg_keycode(W);
6843 _cimg_keycode(E); _cimg_keycode(R); _cimg_keycode(T); _cimg_keycode(Y);
6844 _cimg_keycode(U); _cimg_keycode(I); _cimg_keycode(O); _cimg_keycode(P);
6845 _cimg_keycode(DELETE); _cimg_keycode(END); _cimg_keycode(PAGEDOWN);
6846 _cimg_keycode(CAPSLOCK); _cimg_keycode(A); _cimg_keycode(S); _cimg_keycode(D);
6847 _cimg_keycode(F); _cimg_keycode(G); _cimg_keycode(H); _cimg_keycode(J);
6848 _cimg_keycode(K); _cimg_keycode(L); _cimg_keycode(ENTER);
6849 _cimg_keycode(SHIFTLEFT); _cimg_keycode(Z); _cimg_keycode(X); _cimg_keycode(C);
6850 _cimg_keycode(V); _cimg_keycode(B); _cimg_keycode(N); _cimg_keycode(M);
6851 _cimg_keycode(SHIFTRIGHT); _cimg_keycode(ARROWUP); _cimg_keycode(CTRLLEFT);
6852 _cimg_keycode(APPLEFT); _cimg_keycode(ALT); _cimg_keycode(SPACE); _cimg_keycode(ALTGR);
6853 _cimg_keycode(APPRIGHT); _cimg_keycode(MENU); _cimg_keycode(CTRLRIGHT);
6854 _cimg_keycode(ARROWLEFT); _cimg_keycode(ARROWDOWN); _cimg_keycode(ARROWRIGHT);
6855 _cimg_keycode(PAD0); _cimg_keycode(PAD1); _cimg_keycode(PAD2);
6856 _cimg_keycode(PAD3); _cimg_keycode(PAD4); _cimg_keycode(PAD5);
6857 _cimg_keycode(PAD6); _cimg_keycode(PAD7); _cimg_keycode(PAD8);
6858 _cimg_keycode(PAD9); _cimg_keycode(PADADD); _cimg_keycode(PADSUB);
6859 _cimg_keycode(PADMUL); _cimg_keycode(PADDIV);
6870 const float delta = (
cimg::time()-_fps_timer)/1000.0f;
6873 _fps_fps = _fps_frames/delta;
6894 template<
typename T>
6909 template<
typename T>
6912 cimglist_for(list,l) {
6913 const CImg<T>& img = list._data[l];
6914 img.__get_select(*
this,_normalization,(img._width-1)/2,(img._height-1)/2,(img._depth-1)/2).move_to(visu[l]);
6952 return assign(pos_x,pos_y);
6966 resize(_window_width,_window_height,force_redraw);
6980 return assign(width,height,0,3,force_redraw);
6994 template<
typename T>
6996 return resize(img._width,img._height,force_redraw);
7009 return resize(disp._width,disp._height,force_redraw);
7013 template<
typename t,
typename T>
7014 static void _render_resize(
const T *ptrs,
const unsigned int ws,
const unsigned int hs,
7015 t *ptrd,
const unsigned int wd,
const unsigned int hd) {
7016 unsigned int *
const offx =
new unsigned int[wd], *
const offy =
new unsigned int[hd+1], *poffx, *poffy;
7019 poffx = offx; curr = 0;
for (
unsigned int x = 0; x<wd; ++x) {
7020 old = curr; curr+=s; *(poffx++) = (
unsigned int)curr - (
unsigned int)old;
7023 poffy = offy; curr = 0;
for (
unsigned int y = 0; y<hd; ++y) {
7024 old = curr; curr+=s; *(poffy++) = ws*((
unsigned int)curr - (
unsigned int)old);
7028 for (
unsigned int y = 0; y<hd; ) {
7029 const T *ptr = ptrs;
7031 for (
unsigned int x = 0; x<wd; ++x) { *(ptrd++) = *ptr; ptr+=*(poffx++); }
7033 unsigned int dy = *(poffy++);
7034 for ( ; !dy && y<hd; std::memcpy(ptrd,ptrd - wd,
sizeof(t)*wd), ++y, ptrd+=wd, dy = *(poffy++)) {}
7037 delete[] offx;
delete[] offy;
7066 return assign(0,0,format);
7084 if (
is_empty() || _is_fullscreen==is_fullscreen)
return *
this;
7096 return assign(_width,_height,0,3,force_redraw);
7123 return assign(pos_x,pos_y);
7136 pthread_cond_broadcast(&cimg::X11_attr().wait_event);
7137 #elif cimg_display==2
7138 SetEvent(cimg::Win32_attr().wait_event);
7149 const unsigned int buttoncode = button==1?1:button==2?2:button==3?4:0;
7150 if (is_pressed) _button |= buttoncode;
else _button &= ~buttoncode;
7151 _is_event = buttoncode?
true:
false;
7154 pthread_cond_broadcast(&cimg::X11_attr().wait_event);
7155 #elif cimg_display==2
7156 SetEvent(cimg::Win32_attr().wait_event);
7170 pthread_cond_broadcast(&cimg::X11_attr().wait_event);
7171 #elif cimg_display==2
7172 SetEvent(cimg::Win32_attr().wait_event);
7184 _is_event = amplitude?
true:
false;
7187 pthread_cond_broadcast(&cimg::X11_attr().wait_event);
7188 #elif cimg_display==2
7189 SetEvent(cimg::Win32_attr().wait_event);
7200 std::memset((
void*)_keys,0,
sizeof(_keys));
7201 std::memset((
void*)_released_keys,0,
sizeof(_released_keys));
7202 _is_keyESC = _is_keyF1 = _is_keyF2 = _is_keyF3 = _is_keyF4 = _is_keyF5 = _is_keyF6 = _is_keyF7 = _is_keyF8 =
7203 _is_keyF9 = _is_keyF10 = _is_keyF11 = _is_keyF12 = _is_keyPAUSE = _is_key1 = _is_key2 = _is_key3 = _is_key4 =
7204 _is_key5 = _is_key6 = _is_key7 = _is_key8 = _is_key9 = _is_key0 = _is_keyBACKSPACE = _is_keyINSERT =
7205 _is_keyHOME = _is_keyPAGEUP = _is_keyTAB = _is_keyQ = _is_keyW = _is_keyE = _is_keyR = _is_keyT = _is_keyY =
7206 _is_keyU = _is_keyI = _is_keyO = _is_keyP = _is_keyDELETE = _is_keyEND = _is_keyPAGEDOWN = _is_keyCAPSLOCK =
7207 _is_keyA = _is_keyS = _is_keyD = _is_keyF = _is_keyG = _is_keyH = _is_keyJ = _is_keyK = _is_keyL =
7208 _is_keyENTER = _is_keySHIFTLEFT = _is_keyZ = _is_keyX = _is_keyC = _is_keyV = _is_keyB = _is_keyN =
7209 _is_keyM = _is_keySHIFTRIGHT = _is_keyARROWUP = _is_keyCTRLLEFT = _is_keyAPPLEFT = _is_keyALT = _is_keySPACE =
7210 _is_keyALTGR = _is_keyAPPRIGHT = _is_keyMENU = _is_keyCTRLRIGHT = _is_keyARROWLEFT = _is_keyARROWDOWN =
7211 _is_keyARROWRIGHT = _is_keyPAD0 = _is_keyPAD1 = _is_keyPAD2 = _is_keyPAD3 = _is_keyPAD4 = _is_keyPAD5 =
7212 _is_keyPAD6 = _is_keyPAD7 = _is_keyPAD8 = _is_keyPAD9 = _is_keyPADADD = _is_keyPADSUB = _is_keyPADMUL =
7213 _is_keyPADDIV =
false;
7216 pthread_cond_broadcast(&cimg::X11_attr().wait_event);
7217 #elif cimg_display==2
7218 SetEvent(cimg::Win32_attr().wait_event);
7231 #define _cimg_set_key(k) if (keycode==cimg::key##k) _is_key##k = is_pressed;
7232 _cimg_set_key(ESC); _cimg_set_key(F1); _cimg_set_key(F2); _cimg_set_key(F3);
7233 _cimg_set_key(F4); _cimg_set_key(F5); _cimg_set_key(F6); _cimg_set_key(F7);
7234 _cimg_set_key(F8); _cimg_set_key(F9); _cimg_set_key(F10); _cimg_set_key(F11);
7235 _cimg_set_key(F12); _cimg_set_key(PAUSE); _cimg_set_key(1); _cimg_set_key(2);
7236 _cimg_set_key(3); _cimg_set_key(4); _cimg_set_key(5); _cimg_set_key(6);
7237 _cimg_set_key(7); _cimg_set_key(8); _cimg_set_key(9); _cimg_set_key(0);
7238 _cimg_set_key(BACKSPACE); _cimg_set_key(INSERT); _cimg_set_key(HOME);
7239 _cimg_set_key(PAGEUP); _cimg_set_key(TAB); _cimg_set_key(Q); _cimg_set_key(W);
7240 _cimg_set_key(E); _cimg_set_key(R); _cimg_set_key(T); _cimg_set_key(Y);
7241 _cimg_set_key(U); _cimg_set_key(I); _cimg_set_key(O); _cimg_set_key(P);
7242 _cimg_set_key(DELETE); _cimg_set_key(END); _cimg_set_key(PAGEDOWN);
7243 _cimg_set_key(CAPSLOCK); _cimg_set_key(A); _cimg_set_key(S); _cimg_set_key(D);
7244 _cimg_set_key(F); _cimg_set_key(G); _cimg_set_key(H); _cimg_set_key(J);
7245 _cimg_set_key(K); _cimg_set_key(L); _cimg_set_key(ENTER);
7246 _cimg_set_key(SHIFTLEFT); _cimg_set_key(Z); _cimg_set_key(X); _cimg_set_key(C);
7247 _cimg_set_key(V); _cimg_set_key(B); _cimg_set_key(N); _cimg_set_key(M);
7248 _cimg_set_key(SHIFTRIGHT); _cimg_set_key(ARROWUP); _cimg_set_key(CTRLLEFT);
7249 _cimg_set_key(APPLEFT); _cimg_set_key(ALT); _cimg_set_key(SPACE); _cimg_set_key(ALTGR);
7250 _cimg_set_key(APPRIGHT); _cimg_set_key(MENU); _cimg_set_key(CTRLRIGHT);
7251 _cimg_set_key(ARROWLEFT); _cimg_set_key(ARROWDOWN); _cimg_set_key(ARROWRIGHT);
7252 _cimg_set_key(PAD0); _cimg_set_key(PAD1); _cimg_set_key(PAD2);
7253 _cimg_set_key(PAD3); _cimg_set_key(PAD4); _cimg_set_key(PAD5);
7254 _cimg_set_key(PAD6); _cimg_set_key(PAD7); _cimg_set_key(PAD8);
7255 _cimg_set_key(PAD9); _cimg_set_key(PADADD); _cimg_set_key(PADSUB);
7256 _cimg_set_key(PADMUL); _cimg_set_key(PADDIV);
7259 std::memmove((
void*)(_keys+1),(
void*)_keys,
sizeof(_keys) -
sizeof(
unsigned int));
7261 if (*_released_keys) {
7262 std::memmove((
void*)(_released_keys+1),(
void*)_released_keys,
sizeof(_released_keys) -
sizeof(
unsigned int));
7263 *_released_keys = 0;
7267 std::memmove((
void*)(_keys+1),(
void*)_keys,
sizeof(_keys) -
sizeof(
unsigned int));
7270 if (*_released_keys)
7271 std::memmove((
void*)(_released_keys+1),(
void*)_released_keys,
sizeof(_released_keys) -
sizeof(
unsigned int));
7274 _is_event = keycode?
true:
false;
7277 pthread_cond_broadcast(&cimg::X11_attr().wait_event);
7278 #elif cimg_display==2
7279 SetEvent(cimg::Win32_attr().wait_event);
7291 _is_resized = _is_moved = _is_event =
false;
7292 _fps_timer = _fps_frames = _timer = 0;
7309 cimg::_wait(milliseconds,_timer);
7315 disp1._is_event =
false;
7316 while (!disp1._is_closed && !disp1._is_event)
wait_all();
7321 disp1._is_event = disp2._is_event =
false;
7322 while ((!disp1._is_closed || !disp2._is_closed) &&
7323 !disp1._is_event && !disp2._is_event)
wait_all();
7328 disp1._is_event = disp2._is_event = disp3._is_event =
false;
7329 while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed) &&
7330 !disp1._is_event && !disp2._is_event && !disp3._is_event)
wait_all();
7335 disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event =
false;
7336 while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed) &&
7337 !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event)
wait_all();
7343 disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event =
false;
7344 while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed) &&
7345 !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event)
7352 disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event =
7353 disp6._is_event =
false;
7354 while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed ||
7355 !disp6._is_closed) &&
7356 !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event &&
7363 disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event =
7364 disp6._is_event = disp7._is_event =
false;
7365 while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed ||
7366 !disp6._is_closed || !disp7._is_closed) &&
7367 !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event &&
7368 !disp6._is_event && !disp7._is_event)
wait_all();
7374 disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event =
7375 disp6._is_event = disp7._is_event = disp8._is_event =
false;
7376 while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed ||
7377 !disp6._is_closed || !disp7._is_closed || !disp8._is_closed) &&
7378 !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event &&
7379 !disp6._is_event && !disp7._is_event && !disp8._is_event)
wait_all();
7385 disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event =
7386 disp6._is_event = disp7._is_event = disp8._is_event = disp9._is_event =
false;
7387 while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed ||
7388 !disp6._is_closed || !disp7._is_closed || !disp8._is_closed || !disp9._is_closed) &&
7389 !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event &&
7390 !disp6._is_event && !disp7._is_event && !disp8._is_event && !disp9._is_event)
wait_all();
7397 disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event =
7398 disp6._is_event = disp7._is_event = disp8._is_event = disp9._is_event = disp10._is_event =
false;
7399 while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed ||
7400 !disp6._is_closed || !disp7._is_closed || !disp8._is_closed || !disp9._is_closed || !disp10._is_closed) &&
7401 !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event &&
7402 !disp6._is_event && !disp7._is_event && !disp8._is_event && !disp9._is_event && !disp10._is_event)
7410 return _no_display_exception();
7421 template<
typename T>
7440 template<
typename T>
7443 _no_display_exception();
7452 Atom _wm_window_atom, _wm_protocol_atom;
7453 Window _window, _background_window;
7457 #ifdef cimg_use_xshm
7458 XShmSegmentInfo *_shminfo;
7462 Display *
const dpy = cimg::X11_attr().display;
7465 Display *
const _dpy = XOpenDisplay(0);
7468 res = DisplayWidth(_dpy,DefaultScreen(_dpy));
7469 XCloseDisplay(_dpy);
7471 #ifdef cimg_use_xrandr
7472 if (cimg::X11_attr().resolutions && cimg::X11_attr().curr_resolution)
7473 res = cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].width;
7474 else res = DisplayWidth(dpy,DefaultScreen(dpy));
7476 res = DisplayWidth(dpy,DefaultScreen(dpy));
7483 Display *
const dpy = cimg::X11_attr().display;
7486 Display *
const _dpy = XOpenDisplay(0);
7488 throw CImgDisplayException(
"CImgDisplay::screen_height(): Failed to open X11 display.");
7489 res = DisplayHeight(_dpy,DefaultScreen(_dpy));
7490 XCloseDisplay(_dpy);
7492 #ifdef cimg_use_xrandr
7493 if (cimg::X11_attr().resolutions && cimg::X11_attr().curr_resolution)
7494 res = cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].height;
7495 else res = DisplayHeight(dpy,DefaultScreen(dpy));
7497 res = DisplayHeight(dpy,DefaultScreen(dpy));
7504 if (!cimg::X11_attr().display)
return;
7505 if (cimg::mutex(13,2)) {
cimg::sleep(10);
return; }
7506 pthread_cond_wait(&cimg::X11_attr().wait_event,&cimg::X11_attr().wait_event_mutex);
7510 void _handle_events(
const XEvent *
const pevent) {
7511 Display *
const dpy = cimg::X11_attr().display;
7512 XEvent
event = *pevent;
7513 switch (event.type) {
7514 case ClientMessage : {
7515 if ((
int)event.xclient.message_type==(
int)_wm_protocol_atom &&
7516 (
int)event.xclient.data.l[0]==(
int)_wm_window_atom) {
7517 XUnmapWindow(cimg::X11_attr().display,_window);
7518 _is_closed = _is_event =
true;
7519 pthread_cond_broadcast(&cimg::X11_attr().wait_event);
7522 case ConfigureNotify : {
7523 while (XCheckWindowEvent(dpy,_window,StructureNotifyMask,&event)) {}
7524 const unsigned int nw =
event.xconfigure.width, nh =
event.xconfigure.height;
7525 const int nx =
event.xconfigure.x, ny =
event.xconfigure.y;
7526 if (nw && nh && (nw!=_window_width || nh!=_window_height)) {
7527 _window_width = nw; _window_height = nh; _mouse_x = _mouse_y = -1;
7528 XResizeWindow(dpy,_window,_window_width,_window_height);
7529 _is_resized = _is_event =
true;
7530 pthread_cond_broadcast(&cimg::X11_attr().wait_event);
7532 if (nx!=_window_x || ny!=_window_y) {
7533 _window_x = nx; _window_y = ny; _is_moved = _is_event =
true;
7534 pthread_cond_broadcast(&cimg::X11_attr().wait_event);
7538 while (XCheckWindowEvent(dpy,_window,ExposureMask,&event)) {}
7540 if (_is_fullscreen) {
7541 XWindowAttributes attr;
7542 XGetWindowAttributes(dpy,_window,&attr);
7543 while (attr.map_state!=IsViewable) XSync(dpy,0);
7544 XSetInputFocus(dpy,_window,RevertToParent,CurrentTime);
7547 case ButtonPress : {
7549 _mouse_x =
event.xmotion.x; _mouse_y =
event.xmotion.y;
7550 if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=
width() || _mouse_y>=
height()) _mouse_x = _mouse_y = -1;
7551 switch (event.xbutton.button) {
7556 }
while (XCheckWindowEvent(dpy,_window,ButtonPressMask,&event));
7558 case ButtonRelease : {
7560 _mouse_x =
event.xmotion.x; _mouse_y =
event.xmotion.y;
7561 if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=
width() || _mouse_y>=
height()) _mouse_x = _mouse_y = -1;
7562 switch (event.xbutton.button) {
7569 }
while (XCheckWindowEvent(dpy,_window,ButtonReleaseMask,&event));
7572 char tmp = 0; KeySym ksym;
7573 XLookupString(&event.xkey,&tmp,1,&ksym,0);
7574 set_key((
unsigned int)ksym,
true);
7577 char keys_return[32];
7578 XQueryKeymap(dpy,keys_return);
7579 const unsigned int kc =
event.xkey.keycode, kc1 = kc/8, kc2 = kc%8;
7580 const bool is_key_pressed = kc1>=32?
false:(keys_return[kc1]>>kc2)&1;
7581 if (!is_key_pressed) {
7582 char tmp = 0; KeySym ksym;
7583 XLookupString(&event.xkey,&tmp,1,&ksym,0);
7584 set_key((
unsigned int)ksym,
false);
7588 while (XCheckWindowEvent(dpy,_window,EnterWindowMask,&event)) {}
7589 _mouse_x =
event.xmotion.x;
7590 _mouse_y =
event.xmotion.y;
7591 if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=
width() || _mouse_y>=
height()) _mouse_x = _mouse_y = -1;
7593 case LeaveNotify : {
7594 while (XCheckWindowEvent(dpy,_window,LeaveWindowMask,&event)) {}
7595 _mouse_x = _mouse_y =-1; _is_event =
true;
7596 pthread_cond_broadcast(&cimg::X11_attr().wait_event);
7598 case MotionNotify : {
7599 while (XCheckWindowEvent(dpy,_window,PointerMotionMask,&event)) {}
7600 _mouse_x =
event.xmotion.x;
7601 _mouse_y =
event.xmotion.y;
7602 if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=
width() || _mouse_y>=
height()) _mouse_x = _mouse_y = -1;
7604 pthread_cond_broadcast(&cimg::X11_attr().wait_event);
7609 static void* _events_thread(
void *arg) {
7610 Display *
const dpy = cimg::X11_attr().display;
7612 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,0);
7613 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,0);
7614 if (!arg)
for (;;) {
7616 bool event_flag = XCheckTypedEvent(dpy,ClientMessage,&event);
7617 if (!event_flag) event_flag = XCheckMaskEvent(dpy,
7618 ExposureMask | StructureNotifyMask | ButtonPressMask |
7619 KeyPressMask | PointerMotionMask | EnterWindowMask |
7620 LeaveWindowMask | ButtonReleaseMask | KeyReleaseMask,&event);
7622 for (
unsigned int i = 0; i<cimg::X11_attr().nb_wins; ++i)
7623 if (!cimg::X11_attr().wins[i]->_is_closed &&
event.xany.window==cimg::X11_attr().wins[i]->_window)
7624 cimg::X11_attr().wins[i]->_handle_events(&event);
7625 XUnlockDisplay(dpy);
7626 pthread_testcancel();
7632 void _set_colormap(Colormap& _colormap,
const unsigned int dim) {
7633 XColor colormap[256];
7636 for (
unsigned int index = 0; index<256; ++index) {
7637 colormap[index].pixel = index;
7638 colormap[index].red = colormap[index].green = colormap[index].blue = (
unsigned short)(index<<8);
7639 colormap[index].flags = DoRed | DoGreen | DoBlue;
7643 for (
unsigned int index = 0, r = 8; r<256; r+=16)
7644 for (
unsigned int g = 8; g<256; g+=16) {
7645 colormap[index].pixel = index;
7646 colormap[index].red = colormap[index].blue = (
unsigned short)(r<<8);
7647 colormap[index].green = (
unsigned short)(g<<8);
7648 colormap[index++].flags = DoRed | DoGreen | DoBlue;
7652 for (
unsigned int index = 0, r = 16; r<256; r+=32)
7653 for (
unsigned int g = 16; g<256; g+=32)
7654 for (
unsigned int b = 32; b<256; b+=64) {
7655 colormap[index].pixel = index;
7656 colormap[index].red = (
unsigned short)(r<<8);
7657 colormap[index].green = (
unsigned short)(g<<8);
7658 colormap[index].blue = (
unsigned short)(b<<8);
7659 colormap[index++].flags = DoRed | DoGreen | DoBlue;
7663 XStoreColors(cimg::X11_attr().display,_colormap,colormap,256);
7666 void _map_window() {
7667 Display *
const dpy = cimg::X11_attr().display;
7668 bool is_exposed =
false, is_mapped =
false;
7669 XWindowAttributes attr;
7671 XMapRaised(dpy,_window);
7673 XWindowEvent(dpy,_window,StructureNotifyMask | ExposureMask,&event);
7674 switch (event.type) {
7675 case MapNotify : is_mapped =
true;
break;
7676 case Expose : is_exposed =
true;
break;
7678 }
while (!is_exposed || !is_mapped);
7680 XGetWindowAttributes(dpy,_window,&attr);
7681 if (attr.map_state!=IsViewable) { XSync(dpy,0);
cimg::sleep(10); }
7682 }
while (attr.map_state!=IsViewable);
7687 void _paint(
const bool wait_expose=
true) {
7688 if (_is_closed || !_image)
return;
7689 Display *
const dpy = cimg::X11_attr().display;
7692 event.xexpose.type = Expose;
7693 event.xexpose.serial = 0;
7694 event.xexpose.send_event = 1;
7695 event.xexpose.display = dpy;
7696 event.xexpose.window = _window;
7697 event.xexpose.x = 0;
7698 event.xexpose.y = 0;
7699 event.xexpose.width =
width();
7700 event.xexpose.height =
height();
7701 event.xexpose.count = 0;
7702 XSendEvent(dpy,_window,0,0,&event);
7704 GC gc = DefaultGC(dpy,DefaultScreen(dpy));
7705 #ifdef cimg_use_xshm
7706 if (_shminfo) XShmPutImage(dpy,_window,gc,_image,0,0,0,0,_width,_height,1);
7707 else XPutImage(dpy,_window,gc,_image,0,0,0,0,_width,_height);
7709 XPutImage(dpy,_window,gc,_image,0,0,0,0,_width,_height);
7714 template<
typename T>
7715 void _resize(T pixel_type,
const unsigned int ndimx,
const unsigned int ndimy,
const bool force_redraw) {
7716 Display *
const dpy = cimg::X11_attr().display;
7719 #ifdef cimg_use_xshm
7721 XShmSegmentInfo *
const nshminfo =
new XShmSegmentInfo;
7722 XImage *
const nimage = XShmCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),
7723 cimg::X11_attr().nb_bits,ZPixmap,0,nshminfo,ndimx,ndimy);
7724 if (!nimage) {
delete nshminfo;
return; }
7726 nshminfo->shmid = shmget(IPC_PRIVATE,ndimx*ndimy*
sizeof(T),IPC_CREAT | 0777);
7727 if (nshminfo->shmid==-1) { XDestroyImage(nimage);
delete nshminfo;
return; }
7729 nshminfo->shmaddr = nimage->data = (
char*)shmat(nshminfo->shmid,0,0);
7730 if (nshminfo->shmaddr==(
char*)-1) {
7731 shmctl(nshminfo->shmid,IPC_RMID,0); XDestroyImage(nimage);
delete nshminfo;
return;
7733 nshminfo->readOnly = 0;
7734 cimg::X11_attr().is_shm_enabled =
true;
7735 XErrorHandler oldXErrorHandler = XSetErrorHandler(_assign_xshm);
7736 XShmAttach(dpy,nshminfo);
7738 XSetErrorHandler(oldXErrorHandler);
7739 if (!cimg::X11_attr().is_shm_enabled) {
7740 shmdt(nshminfo->shmaddr);
7741 shmctl(nshminfo->shmid,IPC_RMID,0);
7742 XDestroyImage(nimage);
7746 T *
const ndata = (T*)nimage->data;
7747 if (force_redraw) _render_resize((T*)_data,_width,_height,ndata,ndimx,ndimy);
7748 else std::memset(ndata,0,
sizeof(T)*ndimx*ndimy);
7749 XShmDetach(dpy,_shminfo);
7750 XDestroyImage(_image);
7751 shmdt(_shminfo->shmaddr);
7752 shmctl(_shminfo->shmid,IPC_RMID,0);
7754 _shminfo = nshminfo;
7756 _data = (
void*)ndata;
7764 T *ndata = (T*)std::malloc(ndimx*ndimy*
sizeof(T));
7765 if (force_redraw) _render_resize((T*)_data,_width,_height,ndata,ndimx,ndimy);
7766 else std::memset(ndata,0,
sizeof(T)*ndimx*ndimy);
7767 _data = (
void*)ndata;
7768 XDestroyImage(_image);
7769 _image = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),
7770 cimg::X11_attr().nb_bits,ZPixmap,0,(
char*)_data,ndimx,ndimy,8,0);
7774 void _init_fullscreen() {
7775 if (!_is_fullscreen || _is_closed)
return;
7776 Display *
const dpy = cimg::X11_attr().display;
7777 _background_window = 0;
7779 #ifdef cimg_use_xrandr
7781 if (XRRQueryExtension(dpy,&foo,&foo)) {
7782 XRRRotations(dpy,DefaultScreen(dpy),&cimg::X11_attr().curr_rotation);
7783 if (!cimg::X11_attr().resolutions) {
7784 cimg::X11_attr().resolutions = XRRSizes(dpy,DefaultScreen(dpy),&foo);
7785 cimg::X11_attr().nb_resolutions = (
unsigned int)foo;
7787 if (cimg::X11_attr().resolutions) {
7788 cimg::X11_attr().curr_resolution = 0;
7789 for (
unsigned int i = 0; i<cimg::X11_attr().nb_resolutions; ++i) {
7791 nw = (
unsigned int)(cimg::X11_attr().resolutions[i].width),
7792 nh = (
unsigned int)(cimg::X11_attr().resolutions[i].height);
7793 if (nw>=_width && nh>=_height &&
7794 nw<=(
unsigned int)(cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].width) &&
7795 nh<=(
unsigned int)(cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].height))
7796 cimg::X11_attr().curr_resolution = i;
7798 if (cimg::X11_attr().curr_resolution>0) {
7799 XRRScreenConfiguration *config = XRRGetScreenInfo(dpy,DefaultRootWindow(dpy));
7800 XRRSetScreenConfig(dpy,config,DefaultRootWindow(dpy),
7801 cimg::X11_attr().curr_resolution,cimg::X11_attr().curr_rotation,CurrentTime);
7802 XRRFreeScreenConfigInfo(config);
7807 if (!cimg::X11_attr().resolutions)
7809 "init_fullscreen(): Xrandr extension not supported by the X server.",
7810 cimgdisplay_instance);
7814 if (sx==_width && sy==_height)
return;
7815 XSetWindowAttributes winattr;
7816 winattr.override_redirect = 1;
7817 _background_window = XCreateWindow(dpy,DefaultRootWindow(dpy),0,0,sx,sy,0,0,
7818 InputOutput,CopyFromParent,CWOverrideRedirect,&winattr);
7819 const unsigned long buf_size = (
unsigned long)sx*sy*(cimg::X11_attr().nb_bits==8?1:
7820 (cimg::X11_attr().nb_bits==16?2:4));
7821 void *background_data = std::malloc(buf_size);
7822 std::memset(background_data,0,buf_size);
7823 XImage *background_image = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),cimg::X11_attr().nb_bits,
7824 ZPixmap,0,(
char*)background_data,sx,sy,8,0);
7826 XSelectInput(dpy,_background_window,StructureNotifyMask);
7827 XMapRaised(dpy,_background_window);
7828 do XWindowEvent(dpy,_background_window,StructureNotifyMask,&event);
7829 while (event.type!=MapNotify);
7830 GC gc = DefaultGC(dpy,DefaultScreen(dpy));
7831 #ifdef cimg_use_xshm
7832 if (_shminfo) XShmPutImage(dpy,_background_window,gc,background_image,0,0,0,0,sx,sy,0);
7833 else XPutImage(dpy,_background_window,gc,background_image,0,0,0,0,sx,sy);
7835 XPutImage(dpy,_background_window,gc,background_image,0,0,0,0,sx,sy);
7837 XWindowAttributes attr;
7838 XGetWindowAttributes(dpy,_background_window,&attr);
7839 while (attr.map_state!=IsViewable) XSync(dpy,0);
7840 XDestroyImage(background_image);
7843 void _desinit_fullscreen() {
7844 if (!_is_fullscreen)
return;
7845 Display *
const dpy = cimg::X11_attr().display;
7846 XUngrabKeyboard(dpy,CurrentTime);
7847 #ifdef cimg_use_xrandr
7848 if (cimg::X11_attr().resolutions && cimg::X11_attr().curr_resolution) {
7849 XRRScreenConfiguration *config = XRRGetScreenInfo(dpy,DefaultRootWindow(dpy));
7850 XRRSetScreenConfig(dpy,config,DefaultRootWindow(dpy),0,cimg::X11_attr().curr_rotation,CurrentTime);
7851 XRRFreeScreenConfigInfo(config);
7853 cimg::X11_attr().curr_resolution = 0;
7856 if (_background_window) XDestroyWindow(dpy,_background_window);
7857 _background_window = 0;
7858 _is_fullscreen =
false;
7861 static int _assign_xshm(Display *dpy, XErrorEvent *error) {
7863 cimg::X11_attr().is_shm_enabled =
false;
7867 void _assign(
const unsigned int dimw,
const unsigned int dimh,
const char *
const ptitle=0,
7868 const unsigned int normalization_type=3,
7869 const bool fullscreen_flag=
false,
const bool closed_flag=
false) {
7873 const char *
const nptitle = ptitle?ptitle:
"";
7874 const unsigned int s = std::strlen(nptitle) + 1;
7875 char *
const tmp_title = s?
new char[s]:0;
7876 if (s) std::memcpy(tmp_title,nptitle,s*
sizeof(
char));
7882 Display* &dpy = cimg::X11_attr().display;
7884 dpy = XOpenDisplay(0);
7886 throw CImgDisplayException(_cimgdisplay_instance
7887 "assign(): Failed to open X11 display.",
7888 cimgdisplay_instance);
7890 cimg::X11_attr().nb_bits = DefaultDepth(dpy,DefaultScreen(dpy));
7891 if (cimg::X11_attr().nb_bits!=8 && cimg::X11_attr().nb_bits!=16 &&
7892 cimg::X11_attr().nb_bits!=24 && cimg::X11_attr().nb_bits!=32)
7893 throw CImgDisplayException(_cimgdisplay_instance
7894 "assign(): Invalid %u bits screen mode detected "
7895 "(only 8, 16, 24 and 32 bits modes are managed).",
7896 cimgdisplay_instance,
7897 cimg::X11_attr().nb_bits);
7898 XVisualInfo vtemplate;
7899 vtemplate.visualid = XVisualIDFromVisual(DefaultVisual(dpy,DefaultScreen(dpy)));
7901 XVisualInfo *vinfo = XGetVisualInfo(dpy,VisualIDMask,&vtemplate,&nb_visuals);
7902 if (vinfo && vinfo->red_mask<vinfo->blue_mask) cimg::X11_attr().is_blue_first =
true;
7903 cimg::X11_attr().byte_order = ImageByteOrder(dpy);
7907 cimg::X11_attr().events_thread =
new pthread_t;
7908 pthread_create(cimg::X11_attr().events_thread,0,_events_thread,0);
7909 }
else XLockDisplay(dpy);
7914 _normalization = normalization_type<4?normalization_type:3;
7915 _is_fullscreen = fullscreen_flag;
7916 _window_x = _window_y = 0;
7917 _is_closed = closed_flag;
7922 if (_is_fullscreen) {
7923 if (!_is_closed) _init_fullscreen();
7925 XSetWindowAttributes winattr;
7926 winattr.override_redirect = 1;
7927 _window = XCreateWindow(dpy,DefaultRootWindow(dpy),(sx-_width)/2,(sy-_height)/2,_width,_height,0,0,
7928 InputOutput,CopyFromParent,CWOverrideRedirect,&winattr);
7930 _window = XCreateSimpleWindow(dpy,DefaultRootWindow(dpy),0,0,_width,_height,0,0L,0L);
7932 XSelectInput(dpy,_window,
7933 ExposureMask | StructureNotifyMask | ButtonPressMask | KeyPressMask | PointerMotionMask |
7934 EnterWindowMask | LeaveWindowMask | ButtonReleaseMask | KeyReleaseMask);
7936 XStoreName(dpy,_window,_title?_title:
" ");
7937 if (cimg::X11_attr().nb_bits==8) {
7938 _colormap = XCreateColormap(dpy,_window,DefaultVisual(dpy,DefaultScreen(dpy)),AllocAll);
7939 _set_colormap(_colormap,3);
7940 XSetWindowColormap(dpy,_window,_colormap);
7943 static const char *
const _window_class = cimg_appname;
7944 XClassHint *
const window_class = XAllocClassHint();
7945 window_class->res_name = (
char*)_window_class;
7946 window_class->res_class = (
char*)_window_class;
7947 XSetClassHint(dpy,_window,window_class);
7948 XFree(window_class);
7950 _window_width = _width;
7951 _window_height = _height;
7954 #ifdef cimg_use_xshm
7956 if (XShmQueryExtension(dpy)) {
7957 _shminfo =
new XShmSegmentInfo;
7958 _image = XShmCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),cimg::X11_attr().nb_bits,
7959 ZPixmap,0,_shminfo,_width,_height);
7960 if (!_image) {
delete _shminfo; _shminfo = 0; }
7962 _shminfo->shmid = shmget(IPC_PRIVATE,_image->bytes_per_line*_image->height,IPC_CREAT|0777);
7963 if (_shminfo->shmid==-1) { XDestroyImage(_image);
delete _shminfo; _shminfo = 0; }
7965 _shminfo->shmaddr = _image->data = (
char*)(_data = shmat(_shminfo->shmid,0,0));
7966 if (_shminfo->shmaddr==(
char*)-1) {
7967 shmctl(_shminfo->shmid,IPC_RMID,0); XDestroyImage(_image);
delete _shminfo; _shminfo = 0;
7969 _shminfo->readOnly = 0;
7970 cimg::X11_attr().is_shm_enabled =
true;
7971 XErrorHandler oldXErrorHandler = XSetErrorHandler(_assign_xshm);
7972 XShmAttach(dpy,_shminfo);
7974 XSetErrorHandler(oldXErrorHandler);
7975 if (!cimg::X11_attr().is_shm_enabled) {
7976 shmdt(_shminfo->shmaddr); shmctl(_shminfo->shmid,IPC_RMID,0); XDestroyImage(_image);
7977 delete _shminfo; _shminfo = 0;
7986 const unsigned long buf_size = (
unsigned long)_width*_height*(cimg::X11_attr().nb_bits==8?1:
7987 (cimg::X11_attr().nb_bits==16?2:4));
7988 _data = std::malloc(buf_size);
7989 _image = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),cimg::X11_attr().nb_bits,
7990 ZPixmap,0,(
char*)_data,_width,_height,8,0);
7993 _wm_window_atom = XInternAtom(dpy,
"WM_DELETE_WINDOW",0);
7994 _wm_protocol_atom = XInternAtom(dpy,
"WM_PROTOCOLS",0);
7995 XSetWMProtocols(dpy,_window,&_wm_window_atom,1);
7997 if (_is_fullscreen) XGrabKeyboard(dpy,_window,1,GrabModeAsync,GrabModeAsync,CurrentTime);
7998 cimg::X11_attr().wins[cimg::X11_attr().nb_wins++]=
this;
7999 if (!_is_closed) _map_window();
else { _window_x = _window_y = cimg::type<int>::min(); }
8000 XUnlockDisplay(dpy);
8006 Display *
const dpy = cimg::X11_attr().display;
8011 for (i = 0; i<cimg::X11_attr().nb_wins && cimg::X11_attr().wins[i]!=
this; ++i) {}
8012 for (; i<cimg::X11_attr().nb_wins-1; ++i) cimg::X11_attr().wins[i] = cimg::X11_attr().wins[i+1];
8013 --cimg::X11_attr().nb_wins;
8016 if (_is_fullscreen && !_is_closed) _desinit_fullscreen();
8017 XDestroyWindow(dpy,_window);
8019 #ifdef cimg_use_xshm
8021 XShmDetach(dpy,_shminfo);
8022 XDestroyImage(_image);
8023 shmdt(_shminfo->shmaddr);
8024 shmctl(_shminfo->shmid,IPC_RMID,0);
8029 XDestroyImage(_image);
8030 _data = 0; _image = 0;
8031 if (cimg::X11_attr().nb_bits==8) XFreeColormap(dpy,_colormap);
8037 _width = _height = _normalization = _window_width = _window_height = 0;
8038 _window_x = _window_y = 0;
8039 _is_fullscreen =
false;
8045 XUnlockDisplay(dpy);
8050 const unsigned int normalization_type=3,
8051 const bool fullscreen_flag=
false,
const bool closed_flag=
false) {
8052 if (!dimw || !dimh)
return assign();
8053 _assign(dimw,dimh,
title,normalization_type,fullscreen_flag,closed_flag);
8055 std::memset(_data,0,(cimg::X11_attr().nb_bits==8?
sizeof(
unsigned char):
8056 (cimg::X11_attr().nb_bits==16?
sizeof(
unsigned short):
sizeof(
unsigned int)))*
8057 (
unsigned long)_width*_height);
8061 template<
typename T>
8063 const unsigned int normalization_type=3,
8064 const bool fullscreen_flag=
false,
const bool closed_flag=
false) {
8065 if (!img)
return assign();
8067 const CImg<T>& nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width-1)/2,
8070 _assign(nimg._width,nimg._height,
title,normalization_type,fullscreen_flag,closed_flag);
8071 if (_normalization==2) _min = (float)nimg.min_max(_max);
8075 template<
typename T>
8077 const unsigned int normalization_type=3,
8078 const bool fullscreen_flag=
false,
const bool closed_flag=
false) {
8079 if (!list)
return assign();
8081 const CImg<T> img = list>
'x', &nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width-1)/2,
8084 _assign(nimg._width,nimg._height,
title,normalization_type,fullscreen_flag,closed_flag);
8085 if (_normalization==2) _min = (float)nimg.min_max(_max);
8090 if (!disp)
return assign();
8091 _assign(disp._width,disp._height,disp._title,disp._normalization,disp._is_fullscreen,disp._is_closed);
8092 std::memcpy(_data,disp._data,(cimg::X11_attr().nb_bits==8?
sizeof(
unsigned char):
8093 cimg::X11_attr().nb_bits==16?
sizeof(
unsigned short):
8094 sizeof(
unsigned int))*(
unsigned long)_width*_height);
8098 CImgDisplay&
resize(
const int nwidth,
const int nheight,
const bool force_redraw=
true) {
8099 if (!nwidth || !nheight || (
is_empty() && (nwidth<0 || nheight<0)))
return assign();
8101 Display *
const dpy = cimg::X11_attr().display;
8103 tmpdimx = (nwidth>0)?nwidth:(-nwidth*
width()/100),
8104 tmpdimy = (nheight>0)?nheight:(-nheight*
height()/100),
8105 dimx = tmpdimx?tmpdimx:1,
8106 dimy = tmpdimy?tmpdimy:1;
8108 if (_window_width!=dimx || _window_height!=dimy) {
8109 XWindowAttributes attr;
8110 for (
unsigned int i = 0; i<10; ++i) {
8111 XResizeWindow(dpy,_window,dimx,dimy);
8112 XGetWindowAttributes(dpy,_window,&attr);
8113 if (attr.width==(
int)dimx && attr.height==(
int)dimy)
break;
8117 if (_width!=dimx || _height!=dimy)
switch (cimg::X11_attr().nb_bits) {
8118 case 8 : {
unsigned char pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); }
break;
8119 case 16 : {
unsigned short pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); }
break;
8120 default : {
unsigned int pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); }
8122 _window_width = _width = dimx; _window_height = _height = dimy;
8123 _is_resized =
false;
8124 XUnlockDisplay(dpy);
8126 if (force_redraw)
return paint();
8133 const unsigned long buf_size = (
unsigned long)_width*_height*
8134 (cimg::X11_attr().nb_bits==8?1:(cimg::X11_attr().nb_bits==16?2:4));
8135 void *image_data = std::malloc(buf_size);
8136 std::memcpy(image_data,_data,buf_size);
8137 assign(_width,_height,_title,_normalization,!_is_fullscreen,
false);
8138 std::memcpy(_data,image_data,buf_size);
8139 std::free(image_data);
8142 return assign(_width,_height,_title,_normalization,!_is_fullscreen,
false);
8146 if (
is_empty() || !_is_closed)
return *
this;
8147 Display *
const dpy = cimg::X11_attr().
display;
8149 if (_is_fullscreen) _init_fullscreen();
8152 XUnlockDisplay(dpy);
8157 if (
is_empty() || _is_closed)
return *
this;
8158 Display *
const dpy = cimg::X11_attr().
display;
8160 if (_is_fullscreen) _desinit_fullscreen();
8161 XUnmapWindow(dpy,_window);
8162 _window_x = _window_y = -1;
8164 XUnlockDisplay(dpy);
8171 Display *
const dpy = cimg::X11_attr().display;
8173 XMoveWindow(dpy,_window,posx,posy);
8174 _window_x = posx; _window_y = posy;
8176 XUnlockDisplay(dpy);
8182 Display *
const dpy = cimg::X11_attr().
display;
8184 XUndefineCursor(dpy,_window);
8185 XUnlockDisplay(dpy);
8191 Display *
const dpy = cimg::X11_attr().
display;
8193 const char pix_data[8] = { 0 };
8195 col.red = col.green = col.blue = 0;
8196 Pixmap pix = XCreateBitmapFromData(dpy,_window,pix_data,8,8);
8197 Cursor cur = XCreatePixmapCursor(dpy,pix,pix,&col,&col,0,0);
8198 XFreePixmap(dpy,pix);
8199 XDefineCursor(dpy,_window,cur);
8200 XUnlockDisplay(dpy);
8205 if (
is_empty() || _is_closed)
return *
this;
8206 Display *
const dpy = cimg::X11_attr().
display;
8208 XWarpPointer(dpy,0L,_window,0,0,0,0,posx,posy);
8209 _mouse_x = posx; _mouse_y = posy;
8212 XUnlockDisplay(dpy);
8218 char tmp[1024] = { 0 };
8220 va_start(ap, format);
8221 cimg_vsnprintf(tmp,
sizeof(tmp),format,ap);
8223 if (!std::strcmp(_title,tmp))
return *
this;
8225 const unsigned int s = std::strlen(tmp) + 1;
8226 _title =
new char[s];
8227 std::memcpy(_title,tmp,s*
sizeof(
char));
8228 Display *
const dpy = cimg::X11_attr().display;
8230 XStoreName(dpy,_window,tmp);
8231 XUnlockDisplay(dpy);
8235 template<
typename T>
8238 throw CImgArgumentException(_cimgdisplay_instance
8239 "display(): Empty specified image.",
8240 cimgdisplay_instance);
8247 Display *
const dpy = cimg::X11_attr().
display;
8249 _paint(wait_expose);
8250 XUnlockDisplay(dpy);
8254 template<
typename T>
8257 throw CImgArgumentException(_cimgdisplay_instance
8258 "render(): Empty specified image.",
8259 cimgdisplay_instance);
8261 if (img._depth!=1)
return render(img.get_projections2d((img._width-1)/2,(img._height-1)/2,(img._depth-1)/2));
8262 if (cimg::X11_attr().nb_bits==8 && (img._width!=_width || img._height!=_height))
8263 return render(img.get_resize(_width,_height,1,-100,1));
8264 if (cimg::X11_attr().nb_bits==8 && !flag8 && img._spectrum==3) {
8265 static const CImg<typename CImg<T>::ucharT> default_colormap = CImg<typename CImg<T>::ucharT>::default_LUT256();
8266 return render(img.get_index(default_colormap,1,
false));
8269 Display *
const dpy = cimg::X11_attr().
display;
8272 *data2 = (img._spectrum>1)?img.data(0,0,0,1):data1,
8273 *data3 = (img._spectrum>2)?img.data(0,0,0,2):data1;
8275 if (cimg::X11_attr().is_blue_first)
cimg::swap(data1,data3);
8278 if (!_normalization || (_normalization==3 && cimg::type<T>::string()==cimg::type<unsigned char>::string())) {
8280 switch (cimg::X11_attr().nb_bits) {
8282 _set_colormap(_colormap,img._spectrum);
8283 unsigned char *
const ndata = (img._width==_width && img._height==_height)?(
unsigned char*)_data:
new unsigned char[(
unsigned long)img._width*img._height];
8284 unsigned char *ptrd = (
unsigned char*)ndata;
8285 switch (img._spectrum) {
8286 case 1 :
for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) (*ptrd++) = (
unsigned char)*(data1++);
8288 case 2 :
for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8289 const unsigned char R = (
unsigned char)*(data1++), G = (
unsigned char)*(data2++);
8290 (*ptrd++) = (R&0xf0) | (G>>4);
8292 default :
for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8293 const unsigned char R = (
unsigned char)*(data1++), G = (
unsigned char)*(data2++), B = (
unsigned char)*(data3++);
8294 (*ptrd++) = (R&0xe0) | ((G>>5)<<2) | (B>>6);
8297 if (ndata!=_data) { _render_resize(ndata,img._width,img._height,(
unsigned char*)_data,_width,_height);
delete[] ndata; }
8300 unsigned short *
const ndata = (img._width==_width && img._height==_height)?(
unsigned short*)_data:
new unsigned short[(
unsigned long)img._width*img._height];
8301 unsigned char *ptrd = (
unsigned char*)ndata;
8302 const
unsigned int M = 248;
8303 switch (img._spectrum) {
8305 if (cimg::X11_attr().byte_order)
for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8306 const unsigned char val = (
unsigned char)*(data1++), G = val>>2;
8307 *(ptrd++) = (val&M) | (G>>3);
8308 *(ptrd++) = (G<<5) | (G>>1);
8309 }
else for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8310 const unsigned char val = (
unsigned char)*(data1++), G = val>>2;
8311 *(ptrd++) = (G<<5) | (G>>1);
8312 *(ptrd++) = (val&M) | (G>>3);
8316 if (cimg::X11_attr().byte_order)
for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8317 const unsigned char G = (
unsigned char)*(data2++)>>2;
8318 *(ptrd++) = ((
unsigned char)*(data1++)&M) | (G>>3);
8320 }
else for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8321 const unsigned char G = (
unsigned char)*(data2++)>>2;
8323 *(ptrd++) = ((
unsigned char)*(data1++)&M) | (G>>3);
8327 if (cimg::X11_attr().byte_order)
for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8328 const unsigned char G = (
unsigned char)*(data2++)>>2;
8329 *(ptrd++) = ((
unsigned char)*(data1++)&M) | (G>>3);
8330 *(ptrd++) = (G<<5) | ((
unsigned char)*(data3++)>>3);
8331 }
else for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8332 const unsigned char G = (
unsigned char)*(data2++)>>2;
8333 *(ptrd++) = (G<<5) | ((
unsigned char)*(data3++)>>3);
8334 *(ptrd++) = ((
unsigned char)*(data1++)&M) | (G>>3);
8337 if (ndata!=_data) { _render_resize(ndata,img._width,img._height,(
unsigned short*)_data,_width,_height);
delete[] ndata; }
8340 unsigned int *
const ndata = (img._width==_width && img._height==_height)?(
unsigned int*)_data:
new unsigned int[(
unsigned long)img._width*img._height];
8341 if (
sizeof(
int)==4) {
8342 unsigned int *ptrd = ndata;
8343 switch (img._spectrum) {
8346 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8347 const unsigned char val = (
unsigned char)*(data1++);
8348 *(ptrd++) = (val<<16) | (val<<8) | val;
8351 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8352 const unsigned char val = (
unsigned char)*(data1++);
8353 *(ptrd++) = (val<<16) | (val<<8) | val;
8358 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy)
8359 *(ptrd++) = ((
unsigned char)*(data1++)<<16) | ((
unsigned char)*(data2++)<<8);
8361 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy)
8362 *(ptrd++) = ((
unsigned char)*(data2++)<<16) | ((
unsigned char)*(data1++)<<8);
8366 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy)
8367 *(ptrd++) = ((
unsigned char)*(data1++)<<16) | ((
unsigned char)*(data2++)<<8) | (
unsigned char)*(data3++);
8369 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy)
8370 *(ptrd++) = ((
unsigned char)*(data3++)<<24) | ((
unsigned char)*(data2++)<<16) | ((
unsigned char)*(data1++)<<8);
8373 unsigned char *ptrd = (
unsigned char*)ndata;
8374 switch (img._spectrum) {
8376 if (cimg::X11_attr().byte_order)
for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8378 *(ptrd++) = (
unsigned char)*(data1++);
8381 }
else for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8384 *(ptrd++) = (
unsigned char)*(data1++);
8389 if (cimg::X11_attr().byte_order)
cimg::swap(data1,data2);
8390 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8392 *(ptrd++) = (
unsigned char)*(data2++);
8393 *(ptrd++) = (
unsigned char)*(data1++);
8398 if (cimg::X11_attr().byte_order)
for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8400 *(ptrd++) = (
unsigned char)*(data1++);
8401 *(ptrd++) = (
unsigned char)*(data2++);
8402 *(ptrd++) = (
unsigned char)*(data3++);
8403 }
else for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8404 *(ptrd++) = (
unsigned char)*(data3++);
8405 *(ptrd++) = (
unsigned char)*(data2++);
8406 *(ptrd++) = (
unsigned char)*(data1++);
8411 if (ndata!=_data) { _render_resize(ndata,img._width,img._height,(
unsigned int*)_data,_width,_height);
delete[] ndata; }
8415 if (_normalization==3) {
8416 if (cimg::type<T>::is_float()) _min = (float)img.min_max(_max);
8417 else { _min = (float)cimg::type<T>::min(); _max = (float)cimg::type<T>::max(); }
8418 }
else if ((_min>_max) || _normalization==1) _min = (
float)img.min_max(_max);
8419 const float delta = _max - _min, mm = 255/(delta?delta:1.0f);
8420 switch (cimg::X11_attr().nb_bits) {
8422 _set_colormap(_colormap,img._spectrum);
8423 unsigned char *
const ndata = (img._width==_width && img._height==_height)?(
unsigned char*)_data:
new unsigned char[(
unsigned long)img._width*img._height];
8424 unsigned char *ptrd = (
unsigned char*)ndata;
8425 switch (img._spectrum) {
8426 case 1 :
for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8427 const unsigned char R = (
unsigned char)((*(data1++)-_min)*mm);
8430 case 2 :
for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8432 R = (
unsigned char)((*(data1++)-_min)*mm),
8433 G = (
unsigned char)((*(data2++)-_min)*mm);
8434 (*ptrd++) = (R&0xf0) | (G>>4);
8437 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8439 R = (
unsigned char)((*(data1++)-_min)*mm),
8440 G = (
unsigned char)((*(data2++)-_min)*mm),
8441 B = (
unsigned char)((*(data3++)-_min)*mm);
8442 *(ptrd++) = (R&0xe0) | ((G>>5)<<2) | (B>>6);
8445 if (ndata!=_data) { _render_resize(ndata,img._width,img._height,(
unsigned char*)_data,_width,_height);
delete[] ndata; }
8448 unsigned short *
const ndata = (img._width==_width && img._height==_height)?(
unsigned short*)_data:
new unsigned short[(
unsigned long)img._width*img._height];
8449 unsigned char *ptrd = (
unsigned char*)ndata;
8450 const
unsigned int M = 248;
8451 switch (img._spectrum) {
8453 if (cimg::X11_attr().byte_order)
for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8454 const unsigned char val = (
unsigned char)((*(data1++)-_min)*mm), G = val>>2;
8455 *(ptrd++) = (val&M) | (G>>3);
8456 *(ptrd++) = (G<<5) | (val>>3);
8457 }
else for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8458 const unsigned char val = (
unsigned char)((*(data1++)-_min)*mm), G = val>>2;
8459 *(ptrd++) = (G<<5) | (val>>3);
8460 *(ptrd++) = (val&M) | (G>>3);
8464 if (cimg::X11_attr().byte_order)
for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8465 const unsigned char G = (
unsigned char)((*(data2++)-_min)*mm)>>2;
8466 *(ptrd++) = ((
unsigned char)((*(data1++)-_min)*mm)&M) | (G>>3);
8468 }
else for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8469 const unsigned char G = (
unsigned char)((*(data2++)-_min)*mm)>>2;
8471 *(ptrd++) = ((
unsigned char)((*(data1++)-_min)*mm)&M) | (G>>3);
8475 if (cimg::X11_attr().byte_order)
for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8476 const unsigned char G = (
unsigned char)((*(data2++)-_min)*mm)>>2;
8477 *(ptrd++) = ((
unsigned char)((*(data1++)-_min)*mm)&M) | (G>>3);
8478 *(ptrd++) = (G<<5) | ((
unsigned char)((*(data3++)-_min)*mm)>>3);
8479 }
else for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8480 const unsigned char G = (
unsigned char)((*(data2++)-_min)*mm)>>2;
8481 *(ptrd++) = (G<<5) | ((
unsigned char)((*(data3++)-_min)*mm)>>3);
8482 *(ptrd++) = ((
unsigned char)((*(data1++)-_min)*mm)&M) | (G>>3);
8485 if (ndata!=_data) { _render_resize(ndata,img._width,img._height,(
unsigned short*)_data,_width,_height);
delete[] ndata; }
8488 unsigned int *
const ndata = (img._width==_width && img._height==_height)?(
unsigned int*)_data:
new unsigned int[(
unsigned long)img._width*img._height];
8489 if (
sizeof(
int)==4) {
8490 unsigned int *ptrd = ndata;
8491 switch (img._spectrum) {
8494 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8495 const unsigned char val = (
unsigned char)((*(data1++)-_min)*mm);
8496 *(ptrd++) = (val<<16) | (val<<8) | val;
8499 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8500 const unsigned char val = (
unsigned char)((*(data1++)-_min)*mm);
8501 *(ptrd++) = (val<<24) | (val<<16) | (val<<8);
8506 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy)
8508 ((
unsigned char)((*(data1++)-_min)*mm)<<16) |
8509 ((
unsigned char)((*(data2++)-_min)*mm)<<8);
8511 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy)
8513 ((
unsigned char)((*(data2++)-_min)*mm)<<16) |
8514 ((
unsigned char)((*(data1++)-_min)*mm)<<8);
8518 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy)
8520 ((
unsigned char)((*(data1++)-_min)*mm)<<16) |
8521 ((
unsigned char)((*(data2++)-_min)*mm)<<8) |
8522 (
unsigned char)((*(data3++)-_min)*mm);
8524 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy)
8526 ((
unsigned char)((*(data3++)-_min)*mm)<<24) |
8527 ((
unsigned char)((*(data2++)-_min)*mm)<<16) |
8528 ((
unsigned char)((*(data1++)-_min)*mm)<<8);
8531 unsigned char *ptrd = (
unsigned char*)ndata;
8532 switch (img._spectrum) {
8534 if (cimg::X11_attr().byte_order)
for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8535 const unsigned char val = (
unsigned char)((*(data1++)-_min)*mm);
8540 }
else for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8541 const unsigned char val = (
unsigned char)((*(data1++)-_min)*mm);
8549 if (cimg::X11_attr().byte_order)
cimg::swap(data1,data2);
8550 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8552 (*ptrd++) = (
unsigned char)((*(data2++)-_min)*mm);
8553 (*ptrd++) = (
unsigned char)((*(data1++)-_min)*mm);
8558 if (cimg::X11_attr().byte_order)
8559 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8561 (*ptrd++) = (
unsigned char)((*(data1++)-_min)*mm);
8562 (*ptrd++) = (
unsigned char)((*(data2++)-_min)*mm);
8563 (*ptrd++) = (
unsigned char)((*(data3++)-_min)*mm);
8564 }
else for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8565 (*ptrd++) = (
unsigned char)((*(data3++)-_min)*mm);
8566 (*ptrd++) = (
unsigned char)((*(data2++)-_min)*mm);
8567 (*ptrd++) = (
unsigned char)((*(data1++)-_min)*mm);
8573 _render_resize(ndata,img._width,img._height,(
unsigned int*)_data,_width,_height);
delete[] ndata;
8578 XUnlockDisplay(dpy);
8582 template<
typename T>
8585 const unsigned char *ptrs = (
unsigned char*)_data;
8586 img.
assign(_width,_height,1,3);
8588 *data1 = img.data(0,0,0,0),
8589 *data2 = img.data(0,0,0,1),
8590 *data3 = img.data(0,0,0,2);
8591 if (cimg::X11_attr().is_blue_first)
cimg::swap(data1,data3);
8592 switch (cimg::X11_attr().nb_bits) {
8594 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8595 const unsigned char val = *(ptrs++);
8596 *(data1++) = (T)(val&0xe0);
8597 *(data2++) = (T)((val&0x1c)<<3);
8598 *(data3++) = (T)(val<<6);
8602 if (cimg::X11_attr().byte_order)
for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8603 const unsigned char val0 = *(ptrs++), val1 = *(ptrs++);
8604 *(data1++) = (T)(val0&0xf8);
8605 *(data2++) = (T)((val0<<5) | ((val1&0xe0)>>5));
8606 *(data3++) = (T)(val1<<3);
8607 }
else for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8608 const unsigned short val0 = *(ptrs++), val1 = *(ptrs++);
8609 *(data1++) = (T)(val1&0xf8);
8610 *(data2++) = (T)((val1<<5) | ((val0&0xe0)>>5));
8611 *(data3++) = (T)(val0<<3);
8615 if (cimg::X11_attr().byte_order)
for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8617 *(data1++) = (T)*(ptrs++);
8618 *(data2++) = (T)*(ptrs++);
8619 *(data3++) = (T)*(ptrs++);
8620 }
else for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
8621 *(data3++) = (T)*(ptrs++);
8622 *(data2++) = (T)*(ptrs++);
8623 *(data1++) = (T)*(ptrs++);
8633 #elif cimg_display==2
8635 bool _is_mouse_tracked, _is_cursor_visible;
8636 HANDLE _thread, _is_created, _mutex;
8637 HWND _window, _background_window;
8638 CLIENTCREATESTRUCT _ccs;
8639 unsigned int *_data;
8646 mode.dmSize =
sizeof(DEVMODE);
8647 mode.dmDriverExtra = 0;
8648 EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&mode);
8649 return mode.dmPelsWidth;
8654 mode.dmSize =
sizeof(DEVMODE);
8655 mode.dmDriverExtra = 0;
8656 EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&mode);
8657 return mode.dmPelsHeight;
8661 WaitForSingleObject(cimg::Win32_attr().wait_event,INFINITE);
8664 static LRESULT APIENTRY _handle_events(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) {
8673 disp->_mouse_x = disp->_mouse_y = -1;
8674 disp->_window_x = disp->_window_y = 0;
8675 disp->set_button().set_key(0).set_key(0,
false)._is_closed =
true;
8676 ReleaseMutex(disp->_mutex);
8677 ShowWindow(disp->_window,SW_HIDE);
8678 disp->_is_event =
true;
8679 SetEvent(cimg::Win32_attr().wait_event);
8682 while (PeekMessage(&st_msg,window,WM_SIZE,WM_SIZE,PM_REMOVE)) {}
8683 WaitForSingleObject(disp->_mutex,INFINITE);
8684 const unsigned int nw = LOWORD(lParam),nh = HIWORD(lParam);
8685 if (nw && nh && (nw!=disp->_width || nh!=disp->_height)) {
8686 disp->_window_width = nw;
8687 disp->_window_height = nh;
8688 disp->_mouse_x = disp->_mouse_y = -1;
8689 disp->_is_resized = disp->_is_event =
true;
8690 SetEvent(cimg::Win32_attr().wait_event);
8692 ReleaseMutex(disp->_mutex);
8695 while (PeekMessage(&st_msg,window,WM_SIZE,WM_SIZE,PM_REMOVE)) {}
8696 WaitForSingleObject(disp->_mutex,INFINITE);
8697 const int nx = (int)(
short)(LOWORD(lParam)), ny = (
int)(short)(HIWORD(lParam));
8698 if (nx!=disp->_window_x || ny!=disp->_window_y) {
8699 disp->_window_x = nx;
8700 disp->_window_y = ny;
8701 disp->_is_moved = disp->_is_event =
true;
8702 SetEvent(cimg::Win32_attr().wait_event);
8704 ReleaseMutex(disp->_mutex);
8708 if (disp->_is_cursor_visible)
while (ShowCursor(TRUE)<0);
else while (ShowCursor(FALSE)>=0);
8711 disp->set_key((
unsigned int)wParam);
8712 SetEvent(cimg::Win32_attr().wait_event);
8715 disp->set_key((
unsigned int)wParam,
false);
8716 SetEvent(cimg::Win32_attr().wait_event);
8718 case WM_MOUSEMOVE : {
8719 while (PeekMessage(&st_msg,window,WM_MOUSEMOVE,WM_MOUSEMOVE,PM_REMOVE)) {}
8720 disp->_mouse_x = LOWORD(lParam);
8721 disp->_mouse_y = HIWORD(lParam);
8722 #if (_WIN32_WINNT>=0x0400) && !defined(NOTRACKMOUSEEVENT)
8723 if (!disp->_is_mouse_tracked) {
8724 TRACKMOUSEEVENT tme;
8725 tme.cbSize =
sizeof(TRACKMOUSEEVENT);
8726 tme.dwFlags = TME_LEAVE;
8727 tme.hwndTrack = disp->_window;
8728 if (TrackMouseEvent(&tme)) disp->_is_mouse_tracked =
true;
8731 if (disp->_mouse_x<0 || disp->_mouse_y<0 || disp->_mouse_x>=disp->width() || disp->_mouse_y>=disp->height())
8732 disp->_mouse_x = disp->_mouse_y = -1;
8733 disp->_is_event =
true;
8734 SetEvent(cimg::Win32_attr().wait_event);
8735 if (disp->_is_cursor_visible)
while (ShowCursor(TRUE)<0);
else while (ShowCursor(FALSE)>=0);
8737 case WM_MOUSELEAVE : {
8738 disp->_mouse_x = disp->_mouse_y = -1;
8739 disp->_is_mouse_tracked =
false;
8740 while (ShowCursor(TRUE)<0);
8742 case WM_LBUTTONDOWN :
8743 disp->set_button(1);
8744 SetEvent(cimg::Win32_attr().wait_event);
8746 case WM_RBUTTONDOWN :
8747 disp->set_button(2);
8748 SetEvent(cimg::Win32_attr().wait_event);
8750 case WM_MBUTTONDOWN :
8751 disp->set_button(3);
8752 SetEvent(cimg::Win32_attr().wait_event);
8755 disp->set_button(1,
false);
8756 SetEvent(cimg::Win32_attr().wait_event);
8759 disp->set_button(2,
false);
8760 SetEvent(cimg::Win32_attr().wait_event);
8763 disp->set_button(3,
false);
8764 SetEvent(cimg::Win32_attr().wait_event);
8767 disp->set_wheel((
int)((
short)HIWORD(wParam))/120);
8768 SetEvent(cimg::Win32_attr().wait_event);
8770 return DefWindowProc(window,msg,wParam,lParam);
8773 static DWORD WINAPI _events_thread(
void* arg) {
8775 const char *
const title = (
const char*)(((
void**)arg)[1]);
8777 delete[] (
void**)arg;
8778 disp->_bmi.bmiHeader.biSize =
sizeof(BITMAPINFOHEADER);
8779 disp->_bmi.bmiHeader.biWidth = disp->width();
8780 disp->_bmi.bmiHeader.biHeight = -disp->height();
8781 disp->_bmi.bmiHeader.biPlanes = 1;
8782 disp->_bmi.bmiHeader.biBitCount = 32;
8783 disp->_bmi.bmiHeader.biCompression = BI_RGB;
8784 disp->_bmi.bmiHeader.biSizeImage = 0;
8785 disp->_bmi.bmiHeader.biXPelsPerMeter = 1;
8786 disp->_bmi.bmiHeader.biYPelsPerMeter = 1;
8787 disp->_bmi.bmiHeader.biClrUsed = 0;
8788 disp->_bmi.bmiHeader.biClrImportant = 0;
8789 disp->_data =
new unsigned int[(
unsigned long)disp->_width*disp->_height];
8790 if (!disp->_is_fullscreen) {
8792 rect.left = rect.top = 0; rect.right = disp->_width-1; rect.bottom = disp->_height-1;
8793 AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
false);
8795 border1 = (rect.right - rect.left + 1 - disp->_width)/2,
8796 border2 = rect.bottom - rect.top + 1 - disp->_height - border1;
8797 disp->_window = CreateWindowA(
"MDICLIENT",title?title:
" ",
8798 WS_OVERLAPPEDWINDOW | (disp->_is_closed?0:WS_VISIBLE), CW_USEDEFAULT,CW_USEDEFAULT,
8799 disp->_width + 2*border1, disp->_height + border1 + border2,
8800 0,0,0,&(disp->_ccs));
8801 if (!disp->_is_closed) {
8802 GetWindowRect(disp->_window,&rect);
8803 disp->_window_x = rect.left + border1;
8804 disp->_window_y = rect.top + border2;
8805 }
else disp->_window_x = disp->_window_y = 0;
8808 disp->_window = CreateWindowA(
"MDICLIENT",title?title:
" ",
8809 WS_POPUP | (disp->_is_closed?0:WS_VISIBLE), (sx-disp->_width)/2,
8810 (sy-disp->_height)/2,
8811 disp->_width,disp->_height,0,0,0,&(disp->_ccs));
8812 disp->_window_x = disp->_window_y = 0;
8814 SetForegroundWindow(disp->_window);
8815 disp->_hdc = GetDC(disp->_window);
8816 disp->_window_width = disp->_width;
8817 disp->_window_height = disp->_height;
8820 SetWindowLongPtr(disp->_window,GWLP_USERDATA,(LONG_PTR)disp);
8821 SetWindowLongPtr(disp->_window,GWLP_WNDPROC,(LONG_PTR)_handle_events);
8823 SetWindowLong(disp->_window,GWL_USERDATA,(LONG)disp);
8824 SetWindowLong(disp->_window,GWL_WNDPROC,(LONG)_handle_events);
8826 SetEvent(disp->_is_created);
8827 while (GetMessage(&msg,0,0,0)) DispatchMessage(&msg);
8832 if (_is_closed) _window_x = _window_y = -1;
8835 rect.left = rect.top = 0; rect.right = _width-1; rect.bottom = _height-1;
8836 AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
false);
8838 border1 = (rect.right - rect.left + 1 - _width)/2,
8839 border2 = rect.bottom - rect.top + 1 - _height - border1;
8840 GetWindowRect(_window,&rect);
8841 _window_x = rect.left + border1;
8842 _window_y = rect.top + border2;
8847 void _init_fullscreen() {
8848 _background_window = 0;
8849 if (!_is_fullscreen || _is_closed) _curr_mode.dmSize = 0;
8852 unsigned int imode = 0, ibest = 0, bestbpp = 0, bw = ~0U, bh = ~0U;
8853 for (mode.dmSize =
sizeof(DEVMODE), mode.dmDriverExtra = 0; EnumDisplaySettings(0,imode,&mode); ++imode) {
8854 const unsigned int nw = mode.dmPelsWidth, nh = mode.dmPelsHeight;
8855 if (nw>=_width && nh>=_height && mode.dmBitsPerPel>=bestbpp && nw<=bw && nh<=bh) {
8856 bestbpp = mode.dmBitsPerPel;
8862 _curr_mode.dmSize =
sizeof(DEVMODE); _curr_mode.dmDriverExtra = 0;
8863 EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&_curr_mode);
8864 EnumDisplaySettings(0,ibest,&mode);
8865 ChangeDisplaySettings(&mode,0);
8866 }
else _curr_mode.dmSize = 0;
8869 if (sx!=_width || sy!=_height) {
8870 CLIENTCREATESTRUCT background_ccs;
8871 _background_window = CreateWindowA(
"MDICLIENT",
"",WS_POPUP | WS_VISIBLE, 0,0,sx,sy,0,0,0,&background_ccs);
8872 SetForegroundWindow(_background_window);
8877 void _desinit_fullscreen() {
8878 if (!_is_fullscreen)
return;
8879 if (_background_window) DestroyWindow(_background_window);
8880 _background_window = 0;
8881 if (_curr_mode.dmSize) ChangeDisplaySettings(&_curr_mode,0);
8882 _is_fullscreen =
false;
8885 CImgDisplay& _assign(
const unsigned int dimw,
const unsigned int dimh,
const char *
const ptitle=0,
8886 const unsigned int normalization_type=3,
8887 const bool fullscreen_flag=
false,
const bool closed_flag=
false) {
8890 const char *
const nptitle = ptitle?ptitle:
"";
8891 const unsigned int s = (
unsigned int)std::strlen(nptitle) + 1;
8892 char *
const tmp_title = s?
new char[s]:0;
8893 if (s) std::memcpy(tmp_title,nptitle,s*
sizeof(
char));
8901 _normalization = normalization_type<4?normalization_type:3;
8902 _is_fullscreen = fullscreen_flag;
8903 _window_x = _window_y = 0;
8904 _is_closed = closed_flag;
8905 _is_cursor_visible =
true;
8906 _is_mouse_tracked =
false;
8909 if (_is_fullscreen) _init_fullscreen();
8912 void *
const arg = (
void*)(
new void*[2]);
8913 ((
void**)arg)[0] = (
void*)
this;
8914 ((
void**)arg)[1] = (
void*)_title;
8915 _mutex = CreateMutex(0,FALSE,0);
8916 _is_created = CreateEvent(0,FALSE,FALSE,0);
8917 _thread = CreateThread(0,0,_events_thread,arg,0,0);
8918 WaitForSingleObject(_is_created,INFINITE);
8924 DestroyWindow(_window);
8925 TerminateThread(_thread,0);
8930 if (_is_fullscreen) _desinit_fullscreen();
8931 _width = _height = _normalization = _window_width = _window_height = 0;
8932 _window_x = _window_y = 0;
8933 _is_fullscreen =
false;
8941 CImgDisplay&
assign(
const unsigned int dimw,
const unsigned int dimh,
const char *
const title=0,
8942 const unsigned int normalization_type=3,
8943 const bool fullscreen_flag=
false,
const bool closed_flag=
false) {
8944 if (!dimw || !dimh)
return assign();
8945 _assign(dimw,dimh,title,normalization_type,fullscreen_flag,closed_flag);
8947 std::memset(_data,0,
sizeof(
unsigned int)*_width*_height);
8951 template<
typename T>
8953 const unsigned int normalization_type=3,
8954 const bool fullscreen_flag=
false,
const bool closed_flag=
false) {
8955 if (!img)
return assign();
8957 const CImg<T>& nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width-1)/2,
8960 _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag);
8961 if (_normalization==2) _min = (float)nimg.min_max(_max);
8965 template<
typename T>
8967 const unsigned int normalization_type=3,
8968 const bool fullscreen_flag=
false,
const bool closed_flag=
false) {
8969 if (!list)
return assign();
8971 const CImg<T> img = list>
'x', &nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width-1)/2,
8974 _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag);
8975 if (_normalization==2) _min = (float)nimg.min_max(_max);
8980 if (!disp)
return assign();
8981 _assign(disp._width,disp._height,disp._title,disp._normalization,disp._is_fullscreen,disp._is_closed);
8982 std::memcpy(_data,disp._data,
sizeof(
unsigned int)*_width*_height);
8986 CImgDisplay&
resize(
const int nwidth,
const int nheight,
const bool force_redraw=
true) {
8987 if (!nwidth || !nheight || (
is_empty() && (nwidth<0 || nheight<0)))
return assign();
8990 tmpdimx = (nwidth>0)?nwidth:(-nwidth*_width/100),
8991 tmpdimy = (nheight>0)?nheight:(-nheight*_height/100),
8992 dimx = tmpdimx?tmpdimx:1,
8993 dimy = tmpdimy?tmpdimy:1;
8994 if (_window_width!=dimx || _window_height!=dimy) {
8995 RECT rect; rect.left = rect.top = 0; rect.right = dimx - 1; rect.bottom = dimy - 1;
8996 AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
false);
8997 const int cwidth = rect.right - rect.left + 1, cheight = rect.bottom - rect.top + 1;
8998 SetWindowPos(_window,0,0,0,cwidth,cheight,SWP_NOMOVE | SWP_NOZORDER | SWP_NOCOPYBITS);
9000 if (_width!=dimx || _height!=dimy) {
9001 unsigned int *
const ndata =
new unsigned int[dimx*dimy];
9002 if (force_redraw) _render_resize(_data,_width,_height,ndata,dimx,dimy);
9003 else std::memset(ndata,0x80,
sizeof(
unsigned int)*dimx*dimy);
9006 _bmi.bmiHeader.biWidth = dimx;
9007 _bmi.bmiHeader.biHeight = -(int)dimy;
9011 _window_width = dimx; _window_height = dimy;
9012 _is_resized =
false;
9014 if (force_redraw)
return paint();
9021 const unsigned long buf_size = _width*_height*4UL;
9022 void *odata = std::malloc(buf_size);
9023 std::memcpy(odata,_data,buf_size);
9024 assign(_width,_height,_title,_normalization,!_is_fullscreen,
false);
9025 std::memcpy(_data,odata,buf_size);
9029 return assign(_width,_height,_title,_normalization,!_is_fullscreen,
false);
9033 if (
is_empty() || !_is_closed)
return *
this;
9035 if (_is_fullscreen) _init_fullscreen();
9036 ShowWindow(_window,SW_SHOW);
9037 _update_window_pos();
9042 if (
is_empty() || _is_closed)
return *
this;
9044 if (_is_fullscreen) _desinit_fullscreen();
9045 ShowWindow(_window,SW_HIDE);
9046 _window_x = _window_y = 0;
9052 if (!_is_fullscreen) {
9053 RECT rect; rect.left = rect.top = 0; rect.right = _window_width-1; rect.bottom = _window_height-1;
9054 AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
false);
9055 const int border1 = (rect.right-rect.left+1-_width)/2, border2 = rect.bottom-rect.top+1-_height-border1;
9056 SetWindowPos(_window,0,posx-border1,posy-border2,0,0,SWP_NOSIZE | SWP_NOZORDER);
9057 }
else SetWindowPos(_window,0,posx,posy,0,0,SWP_NOSIZE | SWP_NOZORDER);
9066 _is_cursor_visible =
true;
9072 _is_cursor_visible =
false;
9077 if (_is_closed || posx<0 || posy<0)
return *
this;
9078 _update_window_pos();
9079 const int res = (int)SetCursorPos(_window_x + posx,_window_y + posy);
9080 if (res) { _mouse_x = posx; _mouse_y = posy; }
9086 char tmp[1024] = { 0 };
9088 va_start(ap, format);
9089 cimg_vsnprintf(tmp,
sizeof(tmp),format,ap);
9091 if (!std::strcmp(_title,tmp))
return *
this;
9093 const unsigned int s = (
unsigned int)std::strlen(tmp) + 1;
9094 _title =
new char[s];
9095 std::memcpy(_title,tmp,s*
sizeof(
char));
9096 SetWindowTextA(_window, tmp);
9100 template<
typename T>
9103 throw CImgArgumentException(_cimgdisplay_instance
9104 "display(): Empty specified image.",
9105 cimgdisplay_instance);
9111 if (_is_closed)
return *
this;
9112 WaitForSingleObject(_mutex,INFINITE);
9113 SetDIBitsToDevice(_hdc,0,0,_width,_height,0,0,0,_height,_data,&_bmi,DIB_RGB_COLORS);
9114 ReleaseMutex(_mutex);
9118 template<
typename T>
9121 throw CImgArgumentException(_cimgdisplay_instance
9122 "render(): Empty specified image.",
9123 cimgdisplay_instance);
9126 if (img._depth!=1)
return render(img.get_projections2d((img._width-1)/2,(img._height-1)/2,(img._depth-1)/2));
9130 *data2 = (img._spectrum>=2)?img.data(0,0,0,1):data1,
9131 *data3 = (img._spectrum>=3)?img.data(0,0,0,2):data1;
9133 WaitForSingleObject(_mutex,INFINITE);
9135 *
const ndata = (img._width==_width && img._height==_height)?_data:
9136 new unsigned int[(
unsigned long)img._width*img._height],
9139 if (!_normalization || (_normalization==3 && cimg::type<T>::string()==cimg::type<unsigned char>::string())) {
9141 switch (img._spectrum) {
9143 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
9144 const unsigned char val = (
unsigned char)*(data1++);
9145 *(ptrd++) = (val<<16) | (val<<8) | val;
9149 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy)
9150 *(ptrd++) = ((
unsigned char)*(data1++)<<16) | ((
unsigned char)*(data2++)<<8);
9153 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy)
9154 *(ptrd++) = ((
unsigned char)*(data1++)<<16) | ((
unsigned char)*(data2++)<<8) | (
unsigned char)*(data3++);
9158 if (_normalization==3) {
9159 if (cimg::type<T>::is_float()) _min = (
float)img.min_max(_max);
9160 else { _min = (float)cimg::type<T>::min(); _max = (float)cimg::type<T>::max(); }
9161 }
else if ((_min>_max) || _normalization==1) _min = (
float)img.min_max(_max);
9162 const float delta = _max - _min, mm = 255/(delta?delta:1.0f);
9163 switch (img._spectrum) {
9165 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
9166 const unsigned char val = (
unsigned char)((*(data1++)-_min)*mm);
9167 *(ptrd++) = (val<<16) | (val<<8) | val;
9171 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
9173 R = (
unsigned char)((*(data1++)-_min)*mm),
9174 G = (
unsigned char)((*(data2++)-_min)*mm);
9175 *(ptrd++) = (R<<16) | (G<<8);
9179 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
9181 R = (
unsigned char)((*(data1++)-_min)*mm),
9182 G = (
unsigned char)((*(data2++)-_min)*mm),
9183 B = (
unsigned char)((*(data3++)-_min)*mm);
9184 *(ptrd++) = (R<<16) | (G<<8) | B;
9189 if (ndata!=_data) { _render_resize(ndata,img._width,img._height,_data,_width,_height);
delete[] ndata; }
9190 ReleaseMutex(_mutex);
9194 template<
typename T>
9197 const unsigned int *ptrs = _data;
9198 img.
assign(_width,_height,1,3);
9200 *data1 = img.data(0,0,0,0),
9201 *data2 = img.data(0,0,0,1),
9202 *data3 = img.data(0,0,0,2);
9203 for (
unsigned long xy = (
unsigned long)img._width*img._height; xy>0; --xy) {
9204 const unsigned int val = *(ptrs++);
9205 *(data1++) = (T)(
unsigned char)(val>>16);
9206 *(data2++) = (T)(
unsigned char)((val>>8)&0xFF);
9207 *(data3++) = (T)(
unsigned char)(val&0xFF);
9321 template<
typename T>
9324 unsigned int _width, _height, _depth, _spectrum;
9370 typedef typename cimg::superset<T,bool>::type Tbool;
9371 typedef typename cimg::superset<T,unsigned char>::type Tuchar;
9372 typedef typename cimg::superset<T,char>::type Tchar;
9373 typedef typename cimg::superset<T,unsigned short>::type Tushort;
9374 typedef typename cimg::superset<T,short>::type Tshort;
9375 typedef typename cimg::superset<T,unsigned int>::type Tuint;
9376 typedef typename cimg::superset<T,int>::type Tint;
9377 typedef typename cimg::superset<T,unsigned long>::type Tulong;
9378 typedef typename cimg::superset<T,long>::type Tlong;
9379 typedef typename cimg::superset<T,float>::type Tfloat;
9380 typedef typename cimg::superset<T,double>::type Tdouble;
9381 typedef typename cimg::last<T,bool>::type boolT;
9382 typedef typename cimg::last<T,unsigned char>::type ucharT;
9383 typedef typename cimg::last<T,char>::type charT;
9384 typedef typename cimg::last<T,unsigned short>::type ushortT;
9385 typedef typename cimg::last<T,short>::type shortT;
9386 typedef typename cimg::last<T,unsigned int>::type uintT;
9387 typedef typename cimg::last<T,int>::type intT;
9388 typedef typename cimg::last<T,unsigned long>::type ulongT;
9389 typedef typename cimg::last<T,long>::type longT;
9390 typedef typename cimg::last<T,float>::type floatT;
9391 typedef typename cimg::last<T,double>::type doubleT;
9400 #include cimg_plugin
9403 #include cimg_plugin1
9406 #include cimg_plugin2
9409 #include cimg_plugin3
9412 #include cimg_plugin4
9415 #include cimg_plugin5
9418 #include cimg_plugin6
9421 #include cimg_plugin7
9424 #include cimg_plugin8
9445 if (!_is_shared)
delete[] _data;
9465 CImg():_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {}
9490 explicit CImg(
const unsigned int size_x,
const unsigned int size_y=1,
9491 const unsigned int size_z=1,
const unsigned int size_c=1):
9493 const unsigned long siz = (
unsigned long)size_x*size_y*size_z*size_c;
9495 _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c;
9496 try { _data =
new T[siz]; }
catch (...) {
9497 _width = _height = _depth = _spectrum = 0; _data = 0;
9499 "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).",
9501 cimg::strbuffersize(
sizeof(T)*size_x*size_y*size_z*size_c),
9502 size_x,size_y,size_z,size_c);
9504 }
else { _width = _height = _depth = _spectrum = 0; _data = 0; }
9522 CImg(
const unsigned int size_x,
const unsigned int size_y,
9523 const unsigned int size_z,
const unsigned int size_c,
const T value):
9525 const unsigned long siz = (
unsigned long)size_x*size_y*size_z*size_c;
9527 _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c;
9528 try { _data =
new T[siz]; }
catch (...) {
9529 _width = _height = _depth = _spectrum = 0; _data = 0;
9531 "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).",
9533 cimg::strbuffersize(
sizeof(T)*size_x*size_y*size_z*size_c),
9534 size_x,size_y,size_z,size_c);
9537 }
else { _width = _height = _depth = _spectrum = 0; _data = 0; }
9568 CImg(
const unsigned int size_x,
const unsigned int size_y,
const unsigned int size_z,
const unsigned int size_c,
9569 const int value0,
const int value1, ...):
9570 _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
9571 #define _CImg_stdarg(img,a0,a1,N,t) { \
9572 unsigned long _siz = (unsigned long)N; \
9576 T *ptrd = (img)._data; \
9577 *(ptrd++) = (T)a0; \
9579 *(ptrd++) = (T)a1; \
9580 for (; _siz; --_siz) *(ptrd++) = (T)va_arg(ap,t); \
9585 assign(size_x,size_y,size_z,size_c);
9586 _CImg_stdarg(*
this,value0,value1,(
unsigned long)size_x*size_y*size_z*size_c,
int);
9589 #ifdef cimg_use_cpp11
9615 template<
typename t>
9616 CImg(
const unsigned int size_x,
const unsigned int size_y,
const unsigned int size_z,
const unsigned int size_c,
9617 const std::initializer_list<t> values,
9618 const bool repeat_values=
true):
9619 _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
9620 #define _cimg_constructor_cpp11(repeat_values) \
9621 auto it = values.begin(); \
9622 unsigned long siz = size(); \
9623 if (repeat_values) for (T *ptrd = _data; siz--; ) { \
9624 *(ptrd++) = (T)(*(it++)); if (it==values.end()) it = values.begin(); } \
9625 else { siz = cimg::min(siz,values.size()); for (T *ptrd = _data; siz--; ) *(ptrd++) = (T)(*(it++)); }
9626 assign(size_x,size_y,size_z,size_c);
9627 _cimg_constructor_cpp11(repeat_values);
9630 template<
typename t>
9631 CImg(
const unsigned int size_x,
const unsigned int size_y,
const unsigned int size_z,
9632 std::initializer_list<t> values,
9633 const bool repeat_values=
true):
9634 _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
9635 assign(size_x,size_y,size_z);
9636 _cimg_constructor_cpp11(repeat_values);
9639 template<
typename t>
9640 CImg(
const unsigned int size_x,
const unsigned int size_y,
9641 std::initializer_list<t> values,
9642 const bool repeat_values=
true):
9643 _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
9645 _cimg_constructor_cpp11(repeat_values);
9648 template<
typename t>
9649 CImg(
const unsigned int size_x,
9650 std::initializer_list<t> values,
9651 const bool repeat_values=
true):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
9653 _cimg_constructor_cpp11(repeat_values);
9673 template<
typename t>
9674 CImg(
const std::initializer_list<t> values):
9675 _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
9676 assign(values.size(),1,1,1);
9677 auto it = values.begin();
9678 unsigned long siz = _width;
9679 for (T *ptrd = _data; siz--; ) *(ptrd++) = (T)(*(it++));
9682 template<
typename t>
9683 CImg<T> &
operator=(std::initializer_list<t> values) {
9684 _cimg_constructor_cpp11(siz>values.size());
9711 CImg(
const unsigned int size_x,
const unsigned int size_y,
const unsigned int size_z,
const unsigned int size_c,
9712 const double value0,
const double value1, ...):
9713 _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
9714 assign(size_x,size_y,size_z,size_c);
9715 _CImg_stdarg(*
this,value0,value1,(
unsigned long)size_x*size_y*size_z*size_c,
double);
9748 CImg(
const unsigned int size_x,
const unsigned int size_y,
const unsigned int size_z,
const unsigned int size_c,
9749 const char *
const values,
const bool repeat_values):_is_shared(false) {
9750 const unsigned long siz = (
unsigned long)size_x*size_y*size_z*size_c;
9752 _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c;
9753 try { _data =
new T[siz]; }
catch (...) {
9754 _width = _height = _depth = _spectrum = 0; _data = 0;
9756 "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).",
9758 cimg::strbuffersize(
sizeof(T)*size_x*size_y*size_z*size_c),
9759 size_x,size_y,size_z,size_c);
9761 fill(values,repeat_values);
9762 }
else { _width = _height = _depth = _spectrum = 0; _data = 0; }
9795 template<
typename t>
9796 CImg(
const t *
const values,
const unsigned int size_x,
const unsigned int size_y=1,
9797 const unsigned int size_z=1,
const unsigned int size_c=1,
const bool is_shared=
false):_is_shared(false) {
9799 _width = _height = _depth = _spectrum = 0; _data = 0;
9801 "CImg(): Invalid construction request of a (%u,%u,%u,%u) shared instance "
9802 "from a (%s*) buffer (pixel types are different).",
9806 const unsigned long siz = (
unsigned long)size_x*size_y*size_z*size_c;
9807 if (values && siz) {
9808 _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c;
9809 try { _data =
new T[siz]; }
catch (...) {
9810 _width = _height = _depth = _spectrum = 0; _data = 0;
9812 "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).",
9814 cimg::strbuffersize(
sizeof(T)*size_x*size_y*size_z*size_c),
9815 size_x,size_y,size_z,size_c);
9818 const t *ptrs = values; cimg_for(*
this,ptrd,T) *ptrd = (T)*(ptrs++);
9819 }
else { _width = _height = _depth = _spectrum = 0; _data = 0; }
9823 CImg(
const T *
const values,
const unsigned int size_x,
const unsigned int size_y=1,
9824 const unsigned int size_z=1,
const unsigned int size_c=1,
const bool is_shared=
false) {
9825 const unsigned long siz = (
unsigned long)size_x*size_y*size_z*size_c;
9826 if (values && siz) {
9827 _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; _is_shared =
is_shared;
9828 if (_is_shared) _data =
const_cast<T*
>(values);
9830 try { _data =
new T[siz]; }
catch (...) {
9831 _width = _height = _depth = _spectrum = 0; _data = 0;
9833 "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).",
9835 cimg::strbuffersize(
sizeof(T)*size_x*size_y*size_z*size_c),
9836 size_x,size_y,size_z,size_c);
9838 std::memcpy(_data,values,siz*
sizeof(T)); }
9839 }
else { _width = _height = _depth = _spectrum = 0; _is_shared =
false; _data = 0; }
9863 explicit CImg(
const char *
const filename):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
9886 template<
typename t>
9888 const unsigned long siz = img.size();
9889 if (img._data && siz) {
9890 _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum;
9891 try { _data =
new T[siz]; }
catch (...) {
9892 _width = _height = _depth = _spectrum = 0; _data = 0;
9894 "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).",
9896 cimg::strbuffersize(
sizeof(T)*img._width*img._height*img._depth*img._spectrum),
9897 img._width,img._height,img._depth,img._spectrum);
9899 const t *ptrs = img._data; cimg_for(*
this,ptrd,T) *ptrd = (T)*(ptrs++);
9900 }
else { _width = _height = _depth = _spectrum = 0; _data = 0; }
9905 const unsigned long siz = img.size();
9906 if (img._data && siz) {
9907 _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum;
9908 _is_shared = img._is_shared;
9909 if (_is_shared) _data =
const_cast<T*
>(img._data);
9911 try { _data =
new T[siz]; }
catch (...) {
9912 _width = _height = _depth = _spectrum = 0; _data = 0;
9914 "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).",
9916 cimg::strbuffersize(
sizeof(T)*img._width*img._height*img._depth*img._spectrum),
9917 img._width,img._height,img._depth,img._spectrum);
9920 std::memcpy(_data,img._data,siz*
sizeof(T));
9922 }
else { _width = _height = _depth = _spectrum = 0; _is_shared =
false; _data = 0; }
9940 template<
typename t>
9943 _width = _height = _depth = _spectrum = 0; _data = 0;
9945 "CImg(): Invalid construction request of a shared instance from a "
9946 "CImg<%s> image (%u,%u,%u,%u,%p) (pixel types are different).",
9950 const unsigned long siz = img.size();
9951 if (img._data && siz) {
9952 _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum;
9953 try { _data =
new T[siz]; }
catch (...) {
9954 _width = _height = _depth = _spectrum = 0; _data = 0;
9956 "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).",
9958 cimg::strbuffersize(
sizeof(T)*img._width*img._height*img._depth*img._spectrum),
9959 img._width,img._height,img._depth,img._spectrum);
9961 const t *ptrs = img._data; cimg_for(*
this,ptrd,T) *ptrd = (T)*(ptrs++);
9962 }
else { _width = _height = _depth = _spectrum = 0; _data = 0; }
9967 const unsigned long siz = img.size();
9968 if (img._data && siz) {
9969 _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum;
9971 if (_is_shared) _data =
const_cast<T*
>(img._data);
9973 try { _data =
new T[siz]; }
catch (...) {
9974 _width = _height = _depth = _spectrum = 0; _data = 0;
9976 "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).",
9978 cimg::strbuffersize(
sizeof(T)*img._width*img._height*img._depth*img._spectrum),
9979 img._width,img._height,img._depth,img._spectrum);
9981 std::memcpy(_data,img._data,siz*
sizeof(T));
9983 }
else { _width = _height = _depth = _spectrum = 0; _is_shared =
false; _data = 0; }
10006 template<
typename t>
10008 _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
10022 template<
typename t>
10024 _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
10025 assign(img,dimensions).fill(value);
10038 explicit CImg(
const CImgDisplay &disp):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
10044 #ifdef cimg_use_cpp11
10045 CImg(
CImg<T>&& img):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
10049 if (_is_shared)
return assign(img);
10050 return img.swap(*
this);
10059 if (!_is_shared)
delete[] _data;
10060 _width = _height = _depth = _spectrum = 0; _is_shared =
false; _data = 0;
10069 const unsigned int size_z=1,
const unsigned int size_c=1) {
10070 const unsigned long siz = (
unsigned long)size_x*size_y*size_z*size_c;
10071 if (!siz)
return assign();
10072 const unsigned long curr_siz =
size();
10073 if (siz!=curr_siz) {
10076 "assign(): Invalid assignement request of shared instance from specified "
10077 "image (%u,%u,%u,%u).",
10079 size_x,size_y,size_z,size_c);
10082 try { _data =
new T[siz]; }
catch (...) {
10083 _width = _height = _depth = _spectrum = 0; _data = 0;
10085 "assign(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).",
10087 cimg::strbuffersize(
sizeof(T)*size_x*size_y*size_z*size_c),
10088 size_x,size_y,size_z,size_c);
10092 _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c;
10101 const unsigned int size_z,
const unsigned int size_c,
const T value) {
10102 return assign(size_x,size_y,size_z,size_c).fill(value);
10110 const unsigned int size_z,
const unsigned int size_c,
10111 const int value0,
const int value1, ...) {
10112 assign(size_x,size_y,size_z,size_c);
10113 _CImg_stdarg(*
this,value0,value1,(
unsigned long)size_x*size_y*size_z*size_c,
int);
10122 const unsigned int size_z,
const unsigned int size_c,
10123 const double value0,
const double value1, ...) {
10124 assign(size_x,size_y,size_z,size_c);
10125 _CImg_stdarg(*
this,value0,value1,(
unsigned long)size_x*size_y*size_z*size_c,
double);
10134 const unsigned int size_z,
const unsigned int size_c,
10135 const char *
const values,
const bool repeat_values) {
10136 return assign(size_x,size_y,size_z,size_c).fill(values,repeat_values);
10143 template<
typename t>
10144 CImg<T>&
assign(
const t *
const values,
const unsigned int size_x,
const unsigned int size_y=1,
10145 const unsigned int size_z=1,
const unsigned int size_c=1) {
10146 const unsigned long siz = (
unsigned long)size_x*size_y*size_z*size_c;
10147 if (!values || !siz)
return assign();
10148 assign(size_x,size_y,size_z,size_c);
10149 const t *ptrs = values; cimg_for(*
this,ptrd,T) *ptrd = (T)*(ptrs++);
10154 CImg<T>&
assign(
const T *
const values,
const unsigned int size_x,
const unsigned int size_y=1,
10155 const unsigned int size_z=1,
const unsigned int size_c=1) {
10156 const unsigned long siz = (
unsigned long)size_x*size_y*size_z*size_c;
10157 if (!values || !siz)
return assign();
10158 const unsigned long curr_siz =
size();
10159 if (values==_data && siz==curr_siz)
return assign(size_x,size_y,size_z,size_c);
10160 if (_is_shared || values+siz<_data || values>=_data+
size()) {
10161 assign(size_x,size_y,size_z,size_c);
10162 if (_is_shared) std::memmove(_data,values,siz*
sizeof(T));
10163 else std::memcpy(_data,values,siz*
sizeof(T));
10166 try { new_data =
new T[siz]; }
catch (...) {
10167 _width = _height = _depth = _spectrum = 0; _data = 0;
10169 "assign(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).",
10171 cimg::strbuffersize(
sizeof(T)*size_x*size_y*size_z*size_c),
10172 size_x,size_y,size_z,size_c);
10174 std::memcpy(new_data,values,siz*
sizeof(T));
10175 delete[] _data; _data = new_data; _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c;
10181 template<
typename t>
10182 CImg<T>&
assign(
const t *
const values,
const unsigned int size_x,
const unsigned int size_y,
10183 const unsigned int size_z,
const unsigned int size_c,
const bool is_shared) {
10186 "assign(): Invalid assignment request of shared instance from (%s*) buffer"
10187 "(pixel types are different).",
10190 return assign(values,size_x,size_y,size_z,size_c);
10194 CImg<T>&
assign(
const T *
const values,
const unsigned int size_x,
const unsigned int size_y,
10195 const unsigned int size_z,
const unsigned int size_c,
const bool is_shared) {
10196 const unsigned long siz = (
unsigned long)size_x*size_y*size_z*size_c;
10197 if (!values || !siz) {
10200 "assign(): Invalid assignment request of shared instance from (null) or "
10205 if (!is_shared) {
if (_is_shared)
assign();
assign(values,size_x,size_y,size_z,size_c); }
10208 if (values+siz<_data || values>=_data+
size())
assign();
10210 "assign(): Shared image instance has overlapping memory.",
10213 _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; _is_shared =
true;
10214 _data =
const_cast<T*
>(values);
10224 return load(filename);
10231 template<
typename t>
10233 return assign(img._data,img._width,img._height,img._depth,img._spectrum);
10240 template<
typename t>
10242 return assign(img._data,img._width,img._height,img._depth,img._spectrum,is_shared);
10249 template<
typename t>
10251 if (!dimensions || !*dimensions)
return assign(img._width,img._height,img._depth,img._spectrum);
10252 unsigned int siz[4] = { 0,1,1,1 }, k = 0;
10253 for (
const char *s = dimensions; *s && k<4; ++k) {
10254 char item[256] = { 0 };
10255 if (std::sscanf(s,
"%255[^0-9%xyzvwhdcXYZVWHDC]",item)>0) s+=std::strlen(item);
10257 unsigned int val = 0;
char sep = 0;
10258 if (std::sscanf(s,
"%u%c",&val,&sep)>0) {
10259 if (sep==
'%') siz[k] = val*(k==0?_width:k==1?_height:k==2?_depth:_spectrum)/100;
10261 while (*s>=
'0' && *s<=
'9') ++s;
if (sep==
'%') ++s;
10263 case 'x' :
case 'w' : siz[k] = img._width; ++s;
break;
10264 case 'y' :
case 'h' : siz[k] = img._height; ++s;
break;
10265 case 'z' :
case 'd' : siz[k] = img._depth; ++s;
break;
10266 case 'c' :
case 's' : siz[k] = img._spectrum; ++s;
break;
10269 "assign(): Invalid character '%c' detected in specified dimension string '%s'.",
10275 return assign(siz[0],siz[1],siz[2],siz[3]);
10282 template<
typename t>
10284 return assign(img,dimensions).fill(value);
10322 template<
typename t>
10331 if (_is_shared || img._is_shared) img.assign(*
this);
10355 template<
typename t>
10357 const unsigned int npos = pos>list._width?list._width:pos;
10396 return _empty.assign();
10439 #if cimg_verbosity>=3
10440 T&
operator()(
const unsigned int x,
const unsigned int y=0,
10441 const unsigned int z=0,
const unsigned int c=0) {
10442 const unsigned long off = (
unsigned long)
offset(x,y,z,c);
10443 if (!_data || off>=
size()) {
10445 "operator(): Invalid pixel request, at coordinates (%u,%u,%u,%u) [offset=%u].",
10450 else return _data[off];
10454 const T&
operator()(
const unsigned int x,
const unsigned int y=0,
10455 const unsigned int z=0,
const unsigned int c=0)
const {
10456 return const_cast<CImg<T>*
>(
this)->
operator()(x,y,z,c);
10472 T&
operator()(
const unsigned int x,
const unsigned int y,
const unsigned int z,
const unsigned int c,
10473 const unsigned long wh,
const unsigned long whd=0) {
10475 return (*
this)(x,y,z,c);
10479 const T&
operator()(
const unsigned int x,
const unsigned int y,
const unsigned int z,
const unsigned int c,
10480 const unsigned long wh,
const unsigned long whd=0)
const {
10482 return (*
this)(x,y,z,c);
10489 const T&
operator()(
const unsigned int x)
const {
10493 T&
operator()(
const unsigned int x,
const unsigned int y) {
10494 return _data[x + y*_width];
10497 const T&
operator()(
const unsigned int x,
const unsigned int y)
const {
10498 return _data[x + y*_width];
10501 T&
operator()(
const unsigned int x,
const unsigned int y,
const unsigned int z) {
10502 return _data[x + y*(
unsigned long)_width + z*(
unsigned long)_width*_height];
10505 const T&
operator()(
const unsigned int x,
const unsigned int y,
const unsigned int z)
const {
10506 return _data[x + y*(
unsigned long)_width + z*(
unsigned long)_width*_height];
10509 T&
operator()(
const unsigned int x,
const unsigned int y,
const unsigned int z,
const unsigned int c) {
10510 return _data[x + y*(
unsigned long)_width + z*(
unsigned long)_width*_height +
10511 c*(
unsigned long)_width*_height*_depth];
10514 const T&
operator()(
const unsigned int x,
const unsigned int y,
const unsigned int z,
const unsigned int c)
const {
10515 return _data[x + y*(
unsigned long)_width + z*(
unsigned long)_width*_height +
10516 c*(
unsigned long)_width*_height*_depth];
10519 T&
operator()(
const unsigned int x,
const unsigned int y,
const unsigned int z,
const unsigned int,
10520 const unsigned long wh) {
10521 return _data[x + y*_width + z*wh];
10524 const T&
operator()(
const unsigned int x,
const unsigned int y,
const unsigned int z,
const unsigned int,
10525 const unsigned long wh)
const {
10526 return _data[x + y*_width + z*wh];
10529 T&
operator()(
const unsigned int x,
const unsigned int y,
const unsigned int z,
const unsigned int c,
10530 const unsigned long wh,
const unsigned long whd) {
10531 return _data[x + y*_width + z*wh + c*whd];
10534 const T&
operator()(
const unsigned int x,
const unsigned int y,
const unsigned int z,
const unsigned int c,
10535 const unsigned long wh,
const unsigned long whd)
const {
10536 return _data[x + y*_width + z*wh + c*whd];
10567 operator const T*()
const {
10586 return fill(value);
10613 fill(expression,
true);
10626 template<
typename t>
10672 template<
typename t>
10675 #ifdef cimg_use_openmp
10676 #pragma omp parallel for if (size()>=524288)
10678 cimg_rof(*
this,ptrd,T) *ptrd = (T)(*ptrd + value);
10695 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
10696 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"operator+=");
10697 T *ptrd = *expression==
'<'?
end()-1:_data;
10698 if (*expression==
'<') cimg_rofXYZC(*
this,x,y,z,c) { *ptrd = (T)(*ptrd + mp(x,y,z,c)); --ptrd; }
10699 else if (*expression==
'>') cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)(*ptrd + mp(x,y,z,c)); ++ptrd; }
10701 #ifdef cimg_use_openmp
10702 if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
10703 #pragma omp parallel
10705 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
10706 #pragma omp for collapse(3)
10707 cimg_forYZC(*
this,y,z,c) {
10708 T *ptrd =
data(0,y,z,c);
10709 cimg_forX(*
this,x) { *ptrd = (T)(*ptrd + lmp(x,y,z,c)); ++ptrd; }
10714 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)(*ptrd + mp(x,y,z,c)); ++ptrd; }
10718 *
this+=
CImg<T>(_width,_height,_depth,_spectrum,expression,
true);
10744 template<
typename t>
10746 const unsigned long siz =
size(), isiz = img.size();
10749 T *ptrd = _data, *
const ptre = _data + siz;
10750 if (siz>isiz)
for (
unsigned long n = siz/isiz; n; --n)
10751 for (
const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
10752 *ptrd = (T)(*ptrd + *(ptrs++));
10753 for (
const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)(*ptrd + *(ptrs++));
10766 #ifdef cimg_use_openmp
10767 #pragma omp parallel for if (size()>=524288)
10769 cimg_rof(*
this,ptrd,T) ++*ptrd;
10781 const CImg<T> copy(*
this,
false);
10804 template<
typename t>
10823 template<
typename t>
10832 template<
typename t>
10835 #ifdef cimg_use_openmp
10836 #pragma omp parallel for if (size()>=524288)
10838 cimg_rof(*
this,ptrd,T) *ptrd = (T)(*ptrd - value);
10851 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
10852 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"operator-=");
10853 T *ptrd = *expression==
'<'?
end()-1:_data;
10854 if (*expression==
'<') cimg_rofXYZC(*
this,x,y,z,c) { *ptrd = (T)(*ptrd - mp(x,y,z,c)); --ptrd; }
10855 else if (*expression==
'>') cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)(*ptrd - mp(x,y,z,c)); ++ptrd; }
10857 #ifdef cimg_use_openmp
10858 if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
10859 #pragma omp parallel
10861 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
10862 #pragma omp for collapse(3)
10863 cimg_forYZC(*
this,y,z,c) {
10864 T *ptrd =
data(0,y,z,c);
10865 cimg_forX(*
this,x) { *ptrd = (T)(*ptrd - lmp(x,y,z,c)); ++ptrd; }
10870 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)(*ptrd + mp(x,y,z,c)); ++ptrd; }
10874 *
this-=
CImg<T>(_width,_height,_depth,_spectrum,expression,
true);
10884 template<
typename t>
10886 const unsigned long siz =
size(), isiz = img.size();
10889 T *ptrd = _data, *
const ptre = _data + siz;
10890 if (siz>isiz)
for (
unsigned long n = siz/isiz; n; --n)
10891 for (
const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
10892 *ptrd = (T)(*ptrd - *(ptrs++));
10893 for (
const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)(*ptrd - *(ptrs++));
10904 #ifdef cimg_use_openmp
10905 #pragma omp parallel for if (size()>=524288)
10907 cimg_rof(*
this,ptrd,T) *ptrd = *ptrd-(T)1;
10916 const CImg<T> copy(*
this,
false);
10936 return CImg<T>(_width,_height,_depth,_spectrum,(T)0)-=*
this;
10944 template<
typename t>
10963 template<
typename t>
10972 template<
typename t>
10975 #ifdef cimg_use_openmp
10976 #pragma omp parallel for if (size()>=262144)
10978 cimg_rof(*
this,ptrd,T) *ptrd = (T)(*ptrd * value);
10991 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
10992 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"operator*=");
10993 T *ptrd = *expression==
'<'?
end()-1:_data;
10994 if (*expression==
'<') cimg_rofXYZC(*
this,x,y,z,c) { *ptrd = (T)(*ptrd * mp(x,y,z,c)); --ptrd; }
10995 else if (*expression==
'>') cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)(*ptrd * mp(x,y,z,c)); ++ptrd; }
10997 #ifdef cimg_use_openmp
10998 if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
10999 #pragma omp parallel
11001 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
11002 #pragma omp for collapse(3)
11003 cimg_forYZC(*
this,y,z,c) {
11004 T *ptrd =
data(0,y,z,c);
11005 cimg_forX(*
this,x) { *ptrd = (T)(*ptrd * lmp(x,y,z,c)); ++ptrd; }
11010 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)(*ptrd * mp(x,y,z,c)); ++ptrd; }
11014 mul(
CImg<T>(_width,_height,_depth,_spectrum,expression,
true));
11037 template<
typename t>
11039 return ((*
this)*img).
move_to(*
this);
11047 template<
typename t>
11066 template<
typename t>
11068 if (_width!=img._height || _depth!=1 || _spectrum!=1)
11070 "operator*(): Invalid multiplication of instance by specified "
11071 "matrix (%u,%u,%u,%u,%p)",
11073 img._width,img._height,img._depth,img._spectrum,img._data);
11075 #ifdef cimg_use_openmp
11076 #pragma omp parallel for if (size()>1024 && img.size()>1024) collapse(2)
11077 cimg_forXY(res,i,j) {
11078 _cimg_Ttdouble value = 0; cimg_forX(*
this,k) value+=(*this)(k,j)*img(i,k); res(i,j) = (_cimg_Tt)value;
11081 _cimg_Tt *ptrd = res._data;
11082 cimg_forXY(res,i,j) {
11083 _cimg_Ttdouble value = 0; cimg_forX(*
this,k) value+=(*this)(k,j)*img(i,k); *(ptrd++) = (_cimg_Tt)value;
11093 template<
typename t>
11096 #ifdef cimg_use_openmp
11097 #pragma omp parallel for if (size()>=32768)
11099 cimg_rof(*
this,ptrd,T) *ptrd = (T)(*ptrd / value);
11112 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
11113 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"operator/=");
11114 T *ptrd = *expression==
'<'?
end()-1:_data;
11115 if (*expression==
'<') cimg_rofXYZC(*
this,x,y,z,c) { *ptrd = (T)(*ptrd / mp(x,y,z,c)); --ptrd; }
11116 else if (*expression==
'>') cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)(*ptrd / mp(x,y,z,c)); ++ptrd; }
11118 #ifdef cimg_use_openmp
11119 if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
11120 #pragma omp parallel
11122 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
11123 #pragma omp for collapse(3)
11124 cimg_forYZC(*
this,y,z,c) {
11125 T *ptrd =
data(0,y,z,c);
11126 cimg_forX(*
this,x) { *ptrd = (T)(*ptrd / lmp(x,y,z,c)); ++ptrd; }
11131 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)(*ptrd / mp(x,y,z,c)); ++ptrd; }
11135 div(
CImg<T>(_width,_height,_depth,_spectrum,expression,
true));
11152 template<
typename t>
11154 return (*
this*img.get_invert()).
move_to(*
this);
11162 template<
typename t>
11181 template<
typename t>
11183 return (*
this)*img.get_invert();
11190 template<
typename t>
11193 #ifdef cimg_use_openmp
11194 #pragma omp parallel for if (size()>=16384)
11196 cimg_rof(*
this,ptrd,T) *ptrd = (T)
cimg::mod(*ptrd,(T)value);
11209 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
11210 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"operator%=");
11211 T *ptrd = *expression==
'<'?
end()-1:_data;
11212 if (*expression==
'<') cimg_rofXYZC(*
this,x,y,z,c) { *ptrd = (T)
cimg::mod(*ptrd,(T)mp(x,y,z,c)); --ptrd; }
11213 else if (*expression==
'>') cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)
cimg::mod(*ptrd,(T)mp(x,y,z,c)); ++ptrd; }
11215 #ifdef cimg_use_openmp
11216 if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
11217 #pragma omp parallel
11219 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
11220 #pragma omp for collapse(3)
11221 cimg_forYZC(*
this,y,z,c) {
11222 T *ptrd =
data(0,y,z,c);
11223 cimg_forX(*
this,x) { *ptrd = (T)
cimg::mod(*ptrd,(T)lmp(x,y,z,c)); ++ptrd; }
11228 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)
cimg::mod(*ptrd,(T)mp(x,y,z,c)); ++ptrd; }
11232 *
this%=
CImg<T>(_width,_height,_depth,_spectrum,expression,
true);
11242 template<
typename t>
11244 const unsigned long siz =
size(), isiz = img.size();
11247 T *ptrd = _data, *
const ptre = _data + siz;
11248 if (siz>isiz)
for (
unsigned long n = siz/isiz; n; --n)
11249 for (
const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
11251 for (
const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd =
cimg::mod(*ptrd,(T)*(ptrs++));
11261 template<
typename t>
11280 template<
typename t>
11289 template<
typename t>
11292 #ifdef cimg_use_openmp
11293 #pragma omp parallel for if (size()>=32768)
11295 cimg_rof(*
this,ptrd,T) *ptrd = (T)((
unsigned long)*ptrd & (
unsigned long)value);
11308 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
11309 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"operator&=");
11310 T *ptrd = *expression==
'<'?
end()-1:_data;
11311 if (*expression==
'<')
11312 cimg_rofXYZC(*
this,x,y,z,c) { *ptrd = (T)((
unsigned long)*ptrd & (
unsigned long)mp(x,y,z,c)); --ptrd; }
11313 else if (*expression==
'>')
11314 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)((
unsigned long)*ptrd & (
unsigned long)mp(x,y,z,c)); ++ptrd; }
11316 #ifdef cimg_use_openmp
11317 if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
11318 #pragma omp parallel
11320 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
11321 #pragma omp for collapse(3)
11322 cimg_forYZC(*
this,y,z,c) {
11323 T *ptrd =
data(0,y,z,c);
11324 cimg_forX(*
this,x) { *ptrd = (T)((
unsigned long)*ptrd & (
unsigned long)lmp(x,y,z,c)); ++ptrd; }
11329 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)((
unsigned long)*ptrd & (
unsigned long)mp(x,y,z,c)); ++ptrd; }
11333 *
this&=
CImg<T>(_width,_height,_depth,_spectrum,expression,
true);
11343 template<
typename t>
11345 const unsigned long siz =
size(), isiz = img.size();
11348 T *ptrd = _data, *
const ptre = _data + siz;
11349 if (siz>isiz)
for (
unsigned long n = siz/isiz; n; --n)
11350 for (
const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
11351 *ptrd = (T)((
unsigned long)*ptrd & (
unsigned long)*(ptrs++));
11352 for (
const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)((
unsigned long)*ptrd & (
unsigned long)*(ptrs++));
11362 template<
typename t>
11364 return (+*
this)&=value;
11373 return (+*
this)&=expression;
11381 template<
typename t>
11383 return (+*
this)&=img;
11390 template<
typename t>
11393 #ifdef cimg_use_openmp
11394 #pragma omp parallel for if (size()>=32768)
11396 cimg_rof(*
this,ptrd,T) *ptrd = (T)((
unsigned long)*ptrd | (
unsigned long)value);
11409 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
11410 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"operator|=");
11411 T *ptrd = *expression==
'<'?
end()-1:_data;
11412 if (*expression==
'<')
11413 cimg_rofXYZC(*
this,x,y,z,c) { *ptrd = (T)((
unsigned long)*ptrd | (
unsigned long)mp(x,y,z,c)); --ptrd; }
11414 else if (*expression==
'>')
11415 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)((
unsigned long)*ptrd | (
unsigned long)mp(x,y,z,c)); ++ptrd; }
11417 #ifdef cimg_use_openmp
11418 if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
11419 #pragma omp parallel
11421 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
11422 #pragma omp for collapse(3)
11423 cimg_forYZC(*
this,y,z,c) {
11424 T *ptrd =
data(0,y,z,c);
11425 cimg_forX(*
this,x) { *ptrd = (T)((
unsigned long)*ptrd | (
unsigned long)lmp(x,y,z,c)); ++ptrd; }
11430 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)((
unsigned long)*ptrd | (
unsigned long)mp(x,y,z,c)); ++ptrd; }
11434 *
this|=
CImg<T>(_width,_height,_depth,_spectrum,expression,
true);
11444 template<
typename t>
11446 const unsigned long siz =
size(), isiz = img.size();
11449 T *ptrd = _data, *
const ptre = _data + siz;
11450 if (siz>isiz)
for (
unsigned long n = siz/isiz; n; --n)
11451 for (
const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
11452 *ptrd = (T)((
unsigned long)*ptrd | (
unsigned long)*(ptrs++));
11453 for (
const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)((
unsigned long)*ptrd | (
unsigned long)*(ptrs++));
11463 template<
typename t>
11465 return (+*
this)|=value;
11474 return (+*
this)|=expression;
11482 template<
typename t>
11484 return (+*
this)|=img;
11493 template<
typename t>
11496 #ifdef cimg_use_openmp
11497 #pragma omp parallel for if (size()>=32768)
11499 cimg_rof(*
this,ptrd,T) *ptrd = (T)((
unsigned long)*ptrd ^ (
unsigned long)value);
11514 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
11515 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"operator^=");
11516 T *ptrd = *expression==
'<'?
end()-1:_data;
11517 if (*expression==
'<')
11518 cimg_rofXYZC(*
this,x,y,z,c) { *ptrd = (T)((
unsigned long)*ptrd ^ (
unsigned long)mp(x,y,z,c)); --ptrd; }
11519 else if (*expression==
'>')
11520 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)((
unsigned long)*ptrd ^ (
unsigned long)mp(x,y,z,c)); ++ptrd; }
11522 #ifdef cimg_use_openmp
11523 if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
11524 #pragma omp parallel
11526 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
11527 #pragma omp for collapse(3)
11528 cimg_forYZC(*
this,y,z,c) {
11529 T *ptrd =
data(0,y,z,c);
11530 cimg_forX(*
this,x) { *ptrd = (T)((
unsigned long)*ptrd ^ (
unsigned long)lmp(x,y,z,c)); ++ptrd; }
11535 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)((
unsigned long)*ptrd ^ (
unsigned long)mp(x,y,z,c)); ++ptrd; }
11539 *
this^=
CImg<T>(_width,_height,_depth,_spectrum,expression,
true);
11551 template<
typename t>
11553 const unsigned long siz =
size(), isiz = img.size();
11556 T *ptrd = _data, *
const ptre = _data + siz;
11557 if (siz>isiz)
for (
unsigned long n = siz/isiz; n; --n)
11558 for (
const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
11559 *ptrd = (T)((
unsigned long)*ptrd ^ (
unsigned long)*(ptrs++));
11560 for (
const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)((
unsigned long)*ptrd ^ (
unsigned long)*(ptrs++));
11570 template<
typename t>
11572 return (+*
this)^=value;
11581 return (+*
this)^=expression;
11589 template<
typename t>
11591 return (+*
this)^=img;
11598 template<
typename t>
11601 #ifdef cimg_use_openmp
11602 #pragma omp parallel for if (size()>=65536)
11604 cimg_rof(*
this,ptrd,T) *ptrd = (T)(((
long)*ptrd) << (int)value);
11617 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
11618 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"operator<<=");
11619 T *ptrd = *expression==
'<'?
end()-1:_data;
11620 if (*expression==
'<') cimg_rofXYZC(*
this,x,y,z,c) { *ptrd = (T)((
long)*ptrd << (int)mp(x,y,z,c)); --ptrd; }
11621 else if (*expression==
'>') cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)((
long)*ptrd << (int)mp(x,y,z,c)); ++ptrd; }
11623 #ifdef cimg_use_openmp
11624 if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
11625 #pragma omp parallel
11627 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
11628 #pragma omp for collapse(3)
11629 cimg_forYZC(*
this,y,z,c) {
11630 T *ptrd =
data(0,y,z,c);
11631 cimg_forX(*
this,x) { *ptrd = (T)((
long)*ptrd << (int)lmp(x,y,z,c)); ++ptrd; }
11636 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)((
long)*ptrd << (int)mp(x,y,z,c)); ++ptrd; }
11640 *this<<=CImg<T>(_width,_height,_depth,_spectrum,expression,
true);
11650 template<
typename t>
11652 const unsigned long siz =
size(), isiz = img.size();
11655 T *ptrd = _data, *
const ptre = _data + siz;
11656 if (siz>isiz)
for (
unsigned long n = siz/isiz; n; --n)
11657 for (
const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
11658 *ptrd = (T)((
long)*ptrd << (int)*(ptrs++));
11659 for (
const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)((
long)*ptrd << (int)*(ptrs++));
11669 template<
typename t>
11671 return (+*
this)<<=value;
11680 return (+*
this)<<=expression;
11689 template<
typename t>
11691 return (+*
this)<<=img;
11698 template<
typename t>
11701 #ifdef cimg_use_openmp
11702 #pragma omp parallel for if (size()>=65536)
11704 cimg_rof(*
this,ptrd,T) *ptrd = (T)(((
long)*ptrd) >> (int)value);
11717 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
11718 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"operator<<=");
11719 T *ptrd = *expression==
'<'?
end()-1:_data;
11720 if (*expression==
'<') cimg_rofXYZC(*
this,x,y,z,c) { *ptrd = (T)((
long)*ptrd >> (int)mp(x,y,z,c)); --ptrd; }
11721 else if (*expression==
'>') cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)((
long)*ptrd >> (int)mp(x,y,z,c)); ++ptrd; }
11723 #ifdef cimg_use_openmp
11724 if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
11725 #pragma omp parallel
11727 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
11728 #pragma omp for collapse(3)
11729 cimg_forYZC(*
this,y,z,c) {
11730 T *ptrd =
data(0,y,z,c);
11731 cimg_forX(*
this,x) { *ptrd = (T)((
long)*ptrd >> (int)lmp(x,y,z,c)); ++ptrd; }
11736 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)((
long)*ptrd >> (int)mp(x,y,z,c)); ++ptrd; }
11740 *
this>>=
CImg<T>(_width,_height,_depth,_spectrum,expression,
true);
11750 template<
typename t>
11752 const unsigned long siz =
size(), isiz = img.size();
11755 T *ptrd = _data, *
const ptre = _data + siz;
11756 if (siz>isiz)
for (
unsigned long n = siz/isiz; n; --n)
11757 for (
const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
11758 *ptrd = (T)((
long)*ptrd >> (int)*(ptrs++));
11759 for (
const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)((
long)*ptrd >> (int)*(ptrs++));
11769 template<
typename t>
11771 return (+*
this)>>=value;
11780 return (+*
this)>>=expression;
11789 template<
typename t>
11791 return (+*
this)>>=img;
11799 CImg<T> res(_width,_height,_depth,_spectrum);
11800 const T *ptrs = _data;
11801 cimg_for(res,ptrd,T) {
const unsigned long value = (
unsigned long)*(ptrs++); *ptrd = (T)~value; }
11810 template<
typename t>
11813 typedef _cimg_Tt Tt;
11814 bool is_equal =
true;
11815 for (T *ptrd = _data +
size(); is_equal && ptrd>_data; is_equal = ((Tt)*(--ptrd)==(Tt)value)) {}
11825 if (
is_empty())
return !*expression;
11828 bool is_equal =
true;
11830 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
11831 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"operator<<=");
11832 const T *ptrs = *expression==
'<'?
end()-1:_data;
11833 if (*expression==
'<')
11834 cimg_rofXYZC(*
this,x,y,z,c) {
if (!is_equal)
break; is_equal = ((double)*(ptrs--)==mp(x,y,z,c)); }
11835 else if (*expression==
'>')
11836 cimg_forXYZC(*
this,x,y,z,c) {
if (!is_equal)
break; is_equal = ((double)*(ptrs++)==mp(x,y,z,c)); }
11837 else cimg_forXYZC(*
this,x,y,z,c) {
if (!is_equal)
break; is_equal = ((double)*(ptrs++)==mp(x,y,z,c)); }
11840 is_equal = (*
this==
CImg<T>(_width,_height,_depth,_spectrum,expression,
true));
11865 template<
typename t>
11867 typedef _cimg_Tt Tt;
11868 const unsigned long siz =
size();
11869 bool is_equal =
true;
11870 if (siz!=img.size())
return false;
11871 t *ptrs = img._data + siz;
11872 for (T *ptrd = _data + siz; is_equal && ptrd>_data; is_equal = ((Tt)*(--ptrd)==(Tt)*(--ptrs))) {}
11881 template<
typename t>
11883 return !((*this)==value);
11892 return !((*this)==expression);
11903 template<
typename t>
11905 return !((*this)==img);
11938 template<
typename t>
11953 template<
typename t>
12009 return (
int)_width;
12024 return (
int)_height;
12041 return (
int)_depth;
12060 return (
int)_spectrum;
12080 return (
unsigned long)_width*_height*_depth*_spectrum;
12116 #if cimg_verbosity>=3
12117 T *
data(
const unsigned int x,
const unsigned int y=0,
const unsigned int z=0,
const unsigned int c=0) {
12118 const unsigned long off = (
unsigned long)
offset(x,y,z,c);
12121 "data(): Invalid pointer request, at coordinates (%u,%u,%u,%u) [offset=%u].",
12124 return _data + off;
12128 const T*
data(
const unsigned int x,
const unsigned int y=0,
const unsigned int z=0,
const unsigned int c=0)
const {
12129 return const_cast<CImg<T>*
>(
this)->
data(x,y,z,c);
12132 T*
data(
const unsigned int x,
const unsigned int y=0,
const unsigned int z=0,
const unsigned int c=0) {
12133 return _data + x + y*(
unsigned long)_width + z*(
unsigned long)_width*_height +
12134 c*(
unsigned long)_width*_height*_depth;
12137 const T*
data(
const unsigned int x,
const unsigned int y=0,
const unsigned int z=0,
const unsigned int c=0)
const {
12138 return _data + x + y*_width + z*(
unsigned long)_width*_height + c*(
unsigned long)_width*_height*_depth;
12158 long offset(
const int x,
const int y=0,
const int z=0,
const int c=0)
const {
12159 return x + y*(long)_width + z*(
long)_width*_height + c*(long)_width*_height*_depth;
12194 return _data +
size();
12199 return _data +
size();
12225 return *(_data +
size() - 1);
12230 return *(_data +
size() - 1);
12252 return (offset<0 || offset>=(
int)
size())?out_value:(*this)[
offset];
12272 "at(): Empty instance.",
12274 return _at(offset);
12277 T& _at(
const int offset) {
12278 const unsigned int siz = (
unsigned int)
size();
12279 return (*
this)[offset<0?0:(unsigned int)offset>=siz?siz-1:
offset];
12283 T
at(
const int offset)
const {
12286 "at(): Empty instance.",
12288 return _at(offset);
12291 T _at(
const int offset)
const {
12292 const unsigned int siz = (
unsigned int)
size();
12293 return (*
this)[offset<0?0:(unsigned int)offset>=siz?siz-1:
offset];
12313 T&
atX(
const int x,
const int y,
const int z,
const int c,
const T out_value) {
12318 T
atX(
const int x,
const int y,
const int z,
const int c,
const T out_value)
const {
12319 return (x<0 || x>=
width())?out_value:(*this)(x,y,z,c);
12340 T&
atX(
const int x,
const int y=0,
const int z=0,
const int c=0) {
12343 "atX(): Empty instance.",
12345 return _atX(x,y,z,c);
12348 T& _atX(
const int x,
const int y=0,
const int z=0,
const int c=0) {
12349 return (*
this)(x<0?0:(x>=
width()?
width()-1:x),y,z,c);
12353 T
atX(
const int x,
const int y=0,
const int z=0,
const int c=0)
const {
12356 "atX(): Empty instance.",
12358 return _atX(x,y,z,c);
12361 T _atX(
const int x,
const int y=0,
const int z=0,
const int c=0)
const {
12362 return (*
this)(x<0?0:(x>=
width()?
width()-1:x),y,z,c);
12369 T&
atXY(
const int x,
const int y,
const int z,
const int c,
const T out_value) {
12374 T
atXY(
const int x,
const int y,
const int z,
const int c,
const T out_value)
const {
12375 return (x<0 || y<0 || x>=
width() || y>=
height())?out_value:(*this)(x,y,z,c);
12385 T&
atXY(
const int x,
const int y,
const int z=0,
const int c=0) {
12388 "atXY(): Empty instance.",
12390 return _atXY(x,y,z,c);
12393 T& _atXY(
const int x,
const int y,
const int z=0,
const int c=0) {
12398 T
atXY(
const int x,
const int y,
const int z=0,
const int c=0)
const {
12401 "atXY(): Empty instance.",
12403 return _atXY(x,y,z,c);
12406 T _atXY(
const int x,
const int y,
const int z=0,
const int c=0)
const {
12415 T&
atXYZ(
const int x,
const int y,
const int z,
const int c,
const T out_value) {
12421 T
atXYZ(
const int x,
const int y,
const int z,
const int c,
const T out_value)
const {
12422 return (x<0 || y<0 || z<0 || x>=
width() || y>=
height() || z>=
depth())?out_value:(*this)(x,y,z,c);
12432 T&
atXYZ(
const int x,
const int y,
const int z,
const int c=0) {
12435 "atXYZ(): Empty instance.",
12437 return _atXYZ(x,y,z,c);
12440 T& _atXYZ(
const int x,
const int y,
const int z,
const int c=0) {
12446 T
atXYZ(
const int x,
const int y,
const int z,
const int c=0)
const {
12449 "atXYZ(): Empty instance.",
12451 return _atXYZ(x,y,z,c);
12454 T _atXYZ(
const int x,
const int y,
const int z,
const int c=0)
const {
12464 T&
atXYZC(
const int x,
const int y,
const int z,
const int c,
const T out_value) {
12470 T
atXYZC(
const int x,
const int y,
const int z,
const int c,
const T out_value)
const {
12482 T&
atXYZC(
const int x,
const int y,
const int z,
const int c) {
12485 "atXYZC(): Empty instance.",
12487 return _atXYZC(x,y,z,c);
12490 T& _atXYZC(
const int x,
const int y,
const int z,
const int c) {
12496 T
atXYZC(
const int x,
const int y,
const int z,
const int c)
const {
12499 "atXYZC(): Empty instance.",
12501 return _atXYZC(x,y,z,c);
12504 T _atXYZC(
const int x,
const int y,
const int z,
const int c)
const {
12525 Tfloat
linear_atX(
const float fx,
const int y,
const int z,
const int c,
const T out_value)
const {
12527 x = (int)fx - (fx>=0?0:1), nx = x + 1;
12531 Ic = (Tfloat)
atX(x,y,z,c,out_value), In = (Tfloat)
atXY(nx,y,z,c,out_value);
12532 return Ic + dx*(In-Ic);
12552 Tfloat
linear_atX(
const float fx,
const int y=0,
const int z=0,
const int c=0)
const {
12555 "linear_atX(): Empty instance.",
12558 return _linear_atX(fx,y,z,c);
12561 Tfloat _linear_atX(
const float fx,
const int y=0,
const int z=0,
const int c=0)
const {
12563 nfx = fx<0?0:(fx>_width-1?_width-1:fx);
12565 x = (
unsigned int)nfx;
12571 Ic = (Tfloat)(*
this)(x,y,z,c), In = (Tfloat)(*this)(nx,y,z,c);
12572 return Ic + dx*(In-Ic);
12580 Tfloat
linear_atXY(
const float fx,
const float fy,
const int z,
const int c,
const T out_value)
const {
12582 x = (int)fx - (fx>=0?0:1), nx = x + 1,
12583 y = (int)fy - (fy>=0?0:1), ny = y + 1;
12588 Icc = (Tfloat)
atXY(x,y,z,c,out_value), Inc = (Tfloat)
atXY(nx,y,z,c,out_value),
12589 Icn = (Tfloat)
atXY(x,ny,z,c,out_value), Inn = (Tfloat)
atXY(nx,ny,z,c,out_value);
12590 return Icc + dx*(Inc-Icc + dy*(Icc+Inn-Icn-Inc)) + dy*(Icn-Icc);
12601 Tfloat
linear_atXY(
const float fx,
const float fy,
const int z=0,
const int c=0)
const {
12604 "linear_atXY(): Empty instance.",
12607 return _linear_atXY(fx,fy,z,c);
12610 Tfloat _linear_atXY(
const float fx,
const float fy,
const int z=0,
const int c=0)
const {
12612 nfx = fx<0?0:(fx>_width-1?_width-1:fx),
12613 nfy = fy<0?0:(fy>_height-1?_height-1:fy);
12615 x = (
unsigned int)nfx,
12616 y = (
unsigned int)nfy;
12624 Icc = (Tfloat)(*
this)(x,y,z,c), Inc = (Tfloat)(*this)(nx,y,z,c),
12625 Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c);
12626 return Icc + dx*(Inc-Icc + dy*(Icc+Inn-Icn-Inc)) + dy*(Icn-Icc);
12634 Tfloat
linear_atXYZ(
const float fx,
const float fy,
const float fz,
const int c,
const T out_value)
const {
12636 x = (int)fx - (fx>=0?0:1), nx = x + 1,
12637 y = (int)fy - (fy>=0?0:1), ny = y + 1,
12638 z = (int)fz - (fz>=0?0:1), nz = z + 1;
12644 Iccc = (Tfloat)
atXYZ(x,y,z,c,out_value), Incc = (Tfloat)
atXYZ(nx,y,z,c,out_value),
12645 Icnc = (Tfloat)
atXYZ(x,ny,z,c,out_value), Innc = (Tfloat)
atXYZ(nx,ny,z,c,out_value),
12646 Iccn = (Tfloat)
atXYZ(x,y,nz,c,out_value), Incn = (Tfloat)
atXYZ(nx,y,nz,c,out_value),
12647 Icnn = (Tfloat)
atXYZ(x,ny,nz,c,out_value), Innn = (Tfloat)
atXYZ(nx,ny,nz,c,out_value);
12650 dy*(Iccc+Innc-Icnc-Incc +
12651 dz*(Iccn+Innn+Icnc+Incc-Icnn-Incn-Iccc-Innc)) +
12652 dz*(Iccc+Incn-Iccn-Incc)) +
12654 dz*(Iccc+Icnn-Iccn-Icnc)) +
12666 Tfloat
linear_atXYZ(
const float fx,
const float fy=0,
const float fz=0,
const int c=0)
const {
12669 "linear_atXYZ(): Empty instance.",
12672 return _linear_atXYZ(fx,fy,fz,c);
12675 Tfloat _linear_atXYZ(
const float fx,
const float fy=0,
const float fz=0,
const int c=0)
const {
12677 nfx = fx<0?0:(fx>_width-1?_width-1:fx),
12678 nfy = fy<0?0:(fy>_height-1?_height-1:fy),
12679 nfz = fz<0?0:(fz>_depth-1?_depth-1:fz);
12681 x = (
unsigned int)nfx,
12682 y = (
unsigned int)nfy,
12683 z = (
unsigned int)nfz;
12693 Iccc = (Tfloat)(*
this)(x,y,z,c), Incc = (Tfloat)(*this)(nx,y,z,c),
12694 Icnc = (Tfloat)(*this)(x,ny,z,c), Innc = (Tfloat)(*this)(nx,ny,z,c),
12695 Iccn = (Tfloat)(*this)(x,y,nz,c), Incn = (Tfloat)(*this)(nx,y,nz,c),
12696 Icnn = (Tfloat)(*this)(x,ny,nz,c), Innn = (Tfloat)(*this)(nx,ny,nz,c);
12699 dy*(Iccc+Innc-Icnc-Incc +
12700 dz*(Iccn+Innn+Icnc+Incc-Icnn-Incn-Iccc-Innc)) +
12701 dz*(Iccc+Incn-Iccn-Incc)) +
12703 dz*(Iccc+Icnn-Iccn-Icnc)) +
12712 Tfloat
linear_atXYZC(
const float fx,
const float fy,
const float fz,
const float fc,
const T out_value)
const {
12714 x = (int)fx - (fx>=0?0:1), nx = x + 1,
12715 y = (int)fy - (fy>=0?0:1), ny = y + 1,
12716 z = (int)fz - (fz>=0?0:1), nz = z + 1,
12717 c = (int)fc - (fc>=0?0:1), nc = c + 1;
12724 Icccc = (Tfloat)
atXYZC(x,y,z,c,out_value), Inccc = (Tfloat)
atXYZC(nx,y,z,c,out_value),
12725 Icncc = (Tfloat)
atXYZC(x,ny,z,c,out_value), Inncc = (Tfloat)
atXYZC(nx,ny,z,c,out_value),
12726 Iccnc = (Tfloat)
atXYZC(x,y,nz,c,out_value), Incnc = (Tfloat)
atXYZC(nx,y,nz,c,out_value),
12727 Icnnc = (Tfloat)
atXYZC(x,ny,nz,c,out_value), Innnc = (Tfloat)
atXYZC(nx,ny,nz,c,out_value),
12728 Icccn = (Tfloat)
atXYZC(x,y,z,nc,out_value), Inccn = (Tfloat)
atXYZC(nx,y,z,nc,out_value),
12729 Icncn = (Tfloat)
atXYZC(x,ny,z,nc,out_value), Inncn = (Tfloat)
atXYZC(nx,ny,z,nc,out_value),
12730 Iccnn = (Tfloat)
atXYZC(x,y,nz,nc,out_value), Incnn = (Tfloat)
atXYZC(nx,y,nz,nc,out_value),
12731 Icnnn = (Tfloat)
atXYZC(x,ny,nz,nc,out_value), Innnn = (Tfloat)
atXYZC(nx,ny,nz,nc,out_value);
12734 dy*(Icccc+Inncc-Icncc-Inccc +
12735 dz*(Iccnc+Innnc+Icncc+Inccc-Icnnc-Incnc-Icccc-Inncc +
12736 dc*(Iccnn+Innnn+Icncn+Inccn+Icnnc+Incnc+Icccc+Inncc-
12737 Icnnn-Incnn-Icccn-Inncn-Iccnc-Innnc-Icncc-Inccc)) +
12738 dc*(Icccn+Inncn+Icncc+Inccc-Icncn-Inccn-Icccc-Inncc)) +
12739 dz*(Icccc+Incnc-Iccnc-Inccc +
12740 dc*(Icccn+Incnn+Iccnc+Inccc-Iccnn-Inccn-Icccc-Incnc)) +
12741 dc*(Icccc+Inccn-Inccc-Icccn)) +
12743 dz*(Icccc+Icnnc-Iccnc-Icncc +
12744 dc*(Icccn+Icnnn+Iccnc+Icncc-Iccnn-Icncn-Icccc-Icnnc)) +
12745 dc*(Icccc+Icncn-Icncc-Icccn)) +
12747 dc*(Icccc+Iccnn-Iccnc-Icccn)) +
12759 Tfloat
linear_atXYZC(
const float fx,
const float fy=0,
const float fz=0,
const float fc=0)
const {
12762 "linear_atXYZC(): Empty instance.",
12765 return _linear_atXYZC(fx,fy,fz,fc);
12768 Tfloat _linear_atXYZC(
const float fx,
const float fy=0,
const float fz=0,
const float fc=0)
const {
12770 nfx = fx<0?0:(fx>_width-1?_width-1:fx),
12771 nfy = fy<0?0:(fy>_height-1?_height-1:fy),
12772 nfz = fz<0?0:(fz>_depth-1?_depth-1:fz),
12773 nfc = fc<0?0:(fc>_spectrum-1?_spectrum-1:fc);
12775 x = (
unsigned int)nfx,
12776 y = (
unsigned int)nfy,
12777 z = (
unsigned int)nfz,
12778 c = (
unsigned int)nfc;
12790 Icccc = (Tfloat)(*
this)(x,y,z,c), Inccc = (Tfloat)(*this)(nx,y,z,c),
12791 Icncc = (Tfloat)(*this)(x,ny,z,c), Inncc = (Tfloat)(*this)(nx,ny,z,c),
12792 Iccnc = (Tfloat)(*this)(x,y,nz,c), Incnc = (Tfloat)(*this)(nx,y,nz,c),
12793 Icnnc = (Tfloat)(*this)(x,ny,nz,c), Innnc = (Tfloat)(*this)(nx,ny,nz,c),
12794 Icccn = (Tfloat)(*this)(x,y,z,nc), Inccn = (Tfloat)(*this)(nx,y,z,nc),
12795 Icncn = (Tfloat)(*this)(x,ny,z,nc), Inncn = (Tfloat)(*this)(nx,ny,z,nc),
12796 Iccnn = (Tfloat)(*this)(x,y,nz,nc), Incnn = (Tfloat)(*this)(nx,y,nz,nc),
12797 Icnnn = (Tfloat)(*this)(x,ny,nz,nc), Innnn = (Tfloat)(*this)(nx,ny,nz,nc);
12800 dy*(Icccc+Inncc-Icncc-Inccc +
12801 dz*(Iccnc+Innnc+Icncc+Inccc-Icnnc-Incnc-Icccc-Inncc +
12802 dc*(Iccnn+Innnn+Icncn+Inccn+Icnnc+Incnc+Icccc+Inncc-
12803 Icnnn-Incnn-Icccn-Inncn-Iccnc-Innnc-Icncc-Inccc)) +
12804 dc*(Icccn+Inncn+Icncc+Inccc-Icncn-Inccn-Icccc-Inncc)) +
12805 dz*(Icccc+Incnc-Iccnc-Inccc +
12806 dc*(Icccn+Incnn+Iccnc+Inccc-Iccnn-Inccn-Icccc-Incnc)) +
12807 dc*(Icccc+Inccn-Inccc-Icccn)) +
12809 dz*(Icccc+Icnnc-Iccnc-Icncc +
12810 dc*(Icccn+Icnnn+Iccnc+Icncc-Iccnn-Icncn-Icccc-Icnnc)) +
12811 dc*(Icccc+Icncn-Icncc-Icccn)) +
12813 dc*(Icccc+Iccnn-Iccnc-Icccn)) +
12834 Tfloat
cubic_atX(
const float fx,
const int y,
const int z,
const int c,
const T out_value)
const {
12836 x = (int)fx - (fx>=0?0:1), px = x - 1, nx = x + 1, ax = x + 2;
12840 Ip = (Tfloat)
atX(px,y,z,c,out_value), Ic = (Tfloat)
atX(x,y,z,c,out_value),
12841 In = (Tfloat)
atX(nx,y,z,c,out_value), Ia = (Tfloat)
atX(ax,y,z,c,out_value);
12842 return Ic + 0.5f*(dx*(-Ip+In) + dx*dx*(2*Ip-5*Ic+4*In-Ia) + dx*dx*dx*(-Ip+3*Ic-3*In+Ia));
12850 Tfloat
cubic_atX(
const float fx,
const int y,
const int z,
const int c,
const T out_value,
12851 const Tfloat min_value,
const Tfloat max_value)
const {
12852 const Tfloat val =
cubic_atX(fx,y,z,c,out_value);
12853 return val<min_value?min_value:val>max_value?max_value:val;
12873 Tfloat
cubic_atX(
const float fx,
const int y=0,
const int z=0,
const int c=0)
const {
12876 "cubic_atX(): Empty instance.",
12878 return _cubic_atX(fx,y,z,c);
12881 Tfloat _cubic_atX(
const float fx,
const int y=0,
const int z=0,
const int c=0)
const {
12883 nfx = fx<0?0:(fx>_width-1?_width-1:fx);
12889 px = x-1<0?0:x-1, nx = dx>0?x+1:x, ax = x+2>=
width()?
width()-1:x+2;
12891 Ip = (Tfloat)(*
this)(px,y,z,c), Ic = (Tfloat)(*this)(x,y,z,c),
12892 In = (Tfloat)(*this)(nx,y,z,c), Ia = (Tfloat)(*this)(ax,y,z,c);
12893 return Ic + 0.5f*(dx*(-Ip+In) + dx*dx*(2*Ip-5*Ic+4*In-Ia) + dx*dx*dx*(-Ip+3*Ic-3*In+Ia));
12901 Tfloat
cubic_atX(
const float fx,
const int y,
const int z,
const int c,
12902 const Tfloat min_value,
const Tfloat max_value)
const {
12903 const Tfloat val =
cubic_atX(fx,y,z,c);
12904 return val<min_value?min_value:val>max_value?max_value:val;
12907 Tfloat _cubic_atX(
const float fx,
const int y,
const int z,
const int c,
12908 const Tfloat min_value,
const Tfloat max_value)
const {
12909 const Tfloat val = _cubic_atX(fx,y,z,c);
12910 return val<min_value?min_value:val>max_value?max_value:val;
12918 Tfloat
cubic_atXY(
const float fx,
const float fy,
const int z,
const int c,
const T out_value)
const {
12920 x = (int)fx - (fx>=0?0:1), px = x - 1, nx = x + 1, ax = x + 2,
12921 y = (int)fy - (fy>=0?0:1), py = y - 1, ny = y + 1, ay = y + 2;
12922 const float dx = fx - x, dy = fy - y;
12924 Ipp = (Tfloat)
atXY(px,py,z,c,out_value), Icp = (Tfloat)
atXY(x,py,z,c,out_value),
12925 Inp = (Tfloat)
atXY(nx,py,z,c,out_value), Iap = (Tfloat)
atXY(ax,py,z,c,out_value),
12926 Ip = Icp + 0.5f*(dx*(-Ipp+Inp) + dx*dx*(2*Ipp-5*Icp+4*Inp-Iap) + dx*dx*dx*(-Ipp+3*Icp-3*Inp+Iap)),
12927 Ipc = (Tfloat)
atXY(px,y,z,c,out_value), Icc = (Tfloat)
atXY(x, y,z,c,out_value),
12928 Inc = (Tfloat)
atXY(nx,y,z,c,out_value), Iac = (Tfloat)
atXY(ax,y,z,c,out_value),
12929 Ic = Icc + 0.5f*(dx*(-Ipc+Inc) + dx*dx*(2*Ipc-5*Icc+4*Inc-Iac) + dx*dx*dx*(-Ipc+3*Icc-3*Inc+Iac)),
12930 Ipn = (Tfloat)
atXY(px,ny,z,c,out_value), Icn = (Tfloat)
atXY(x,ny,z,c,out_value),
12931 Inn = (Tfloat)
atXY(nx,ny,z,c,out_value), Ian = (Tfloat)
atXY(ax,ny,z,c,out_value),
12932 In = Icn + 0.5f*(dx*(-Ipn+Inn) + dx*dx*(2*Ipn-5*Icn+4*Inn-Ian) + dx*dx*dx*(-Ipn+3*Icn-3*Inn+Ian)),
12933 Ipa = (Tfloat)
atXY(px,ay,z,c,out_value), Ica = (Tfloat)
atXY(x,ay,z,c,out_value),
12934 Ina = (Tfloat)
atXY(nx,ay,z,c,out_value), Iaa = (Tfloat)
atXY(ax,ay,z,c,out_value),
12935 Ia = Ica + 0.5f*(dx*(-Ipa+Ina) + dx*dx*(2*Ipa-5*Ica+4*Ina-Iaa) + dx*dx*dx*(-Ipa+3*Ica-3*Ina+Iaa));
12936 return Ic + 0.5f*(dy*(-Ip+In) + dy*dy*(2*Ip-5*Ic+4*In-Ia) + dy*dy*dy*(-Ip+3*Ic-3*In+Ia));
12944 Tfloat
cubic_atXY(
const float fx,
const float fy,
const int z,
const int c,
const T out_value,
12945 const Tfloat min_value,
const Tfloat max_value)
const {
12946 const Tfloat val =
cubic_atXY(fx,fy,z,c,out_value);
12947 return val<min_value?min_value:val>max_value?max_value:val;
12958 Tfloat
cubic_atXY(
const float fx,
const float fy,
const int z=0,
const int c=0)
const {
12961 "cubic_atXY(): Empty instance.",
12963 return _cubic_atXY(fx,fy,z,c);
12966 Tfloat _cubic_atXY(
const float fx,
const float fy,
const int z=0,
const int c=0)
const {
12968 nfx = fx<0?0:(fx>_width-1?_width-1:fx),
12969 nfy = fy<0?0:(fy>_height-1?_height-1:fy);
12970 const int x = (int)nfx, y = (
int)nfy;
12971 const float dx = nfx - x, dy = nfy - y;
12973 px = x-1<0?0:x-1, nx = dx>0?x+1:x, ax = x+2>=
width()?
width()-1:x+2,
12974 py = y-1<0?0:y-1, ny = dy>0?y+1:y, ay = y+2>=
height()?
height()-1:y+2;
12976 Ipp = (Tfloat)(*
this)(px,py,z,c), Icp = (Tfloat)(*this)(x,py,z,c), Inp = (Tfloat)(*this)(nx,py,z,c),
12977 Iap = (Tfloat)(*this)(ax,py,z,c),
12978 Ip = Icp + 0.5f*(dx*(-Ipp+Inp) + dx*dx*(2*Ipp-5*Icp+4*Inp-Iap) + dx*dx*dx*(-Ipp+3*Icp-3*Inp+Iap)),
12979 Ipc = (Tfloat)(*this)(px,y,z,c), Icc = (Tfloat)(*this)(x, y,z,c), Inc = (Tfloat)(*this)(nx,y,z,c),
12980 Iac = (Tfloat)(*this)(ax,y,z,c),
12981 Ic = Icc + 0.5f*(dx*(-Ipc+Inc) + dx*dx*(2*Ipc-5*Icc+4*Inc-Iac) + dx*dx*dx*(-Ipc+3*Icc-3*Inc+Iac)),
12982 Ipn = (Tfloat)(*this)(px,ny,z,c), Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c),
12983 Ian = (Tfloat)(*this)(ax,ny,z,c),
12984 In = Icn + 0.5f*(dx*(-Ipn+Inn) + dx*dx*(2*Ipn-5*Icn+4*Inn-Ian) + dx*dx*dx*(-Ipn+3*Icn-3*Inn+Ian)),
12985 Ipa = (Tfloat)(*this)(px,ay,z,c), Ica = (Tfloat)(*this)(x,ay,z,c), Ina = (Tfloat)(*this)(nx,ay,z,c),
12986 Iaa = (Tfloat)(*this)(ax,ay,z,c),
12987 Ia = Ica + 0.5f*(dx*(-Ipa+Ina) + dx*dx*(2*Ipa-5*Ica+4*Ina-Iaa) + dx*dx*dx*(-Ipa+3*Ica-3*Ina+Iaa));
12988 return Ic + 0.5f*(dy*(-Ip+In) + dy*dy*(2*Ip-5*Ic+4*In-Ia) + dy*dy*dy*(-Ip+3*Ic-3*In+Ia));
12996 Tfloat
cubic_atXY(
const float fx,
const float fy,
const int z,
const int c,
12997 const Tfloat min_value,
const Tfloat max_value)
const {
12999 return val<min_value?min_value:val>max_value?max_value:val;
13002 Tfloat _cubic_atXY(
const float fx,
const float fy,
const int z,
const int c,
13003 const Tfloat min_value,
const Tfloat max_value)
const {
13004 const Tfloat val = _cubic_atXY(fx,fy,z,c);
13005 return val<min_value?min_value:val>max_value?max_value:val;
13013 Tfloat
cubic_atXYZ(
const float fx,
const float fy,
const float fz,
const int c,
const T out_value)
const {
13015 x = (int)fx - (fx>=0?0:1), px = x - 1, nx = x + 1, ax = x + 2,
13016 y = (int)fy - (fy>=0?0:1), py = y - 1, ny = y + 1, ay = y + 2,
13017 z = (int)fz - (fz>=0?0:1), pz = z - 1, nz = z + 1, az = z + 2;
13018 const float dx = fx - x, dy = fy - y, dz = fz - z;
13020 Ippp = (Tfloat)
atXYZ(px,py,pz,c,out_value), Icpp = (Tfloat)
atXYZ(x,py,pz,c,out_value),
13021 Inpp = (Tfloat)
atXYZ(nx,py,pz,c,out_value), Iapp = (Tfloat)
atXYZ(ax,py,pz,c,out_value),
13022 Ipp = Icpp + 0.5f*(dx*(-Ippp+Inpp) + dx*dx*(2*Ippp-5*Icpp+4*Inpp-Iapp) + dx*dx*dx*(-Ippp+3*Icpp-3*Inpp+Iapp)),
13023 Ipcp = (Tfloat)
atXYZ(px,y,pz,c,out_value), Iccp = (Tfloat)
atXYZ(x, y,pz,c,out_value),
13024 Incp = (Tfloat)
atXYZ(nx,y,pz,c,out_value), Iacp = (Tfloat)
atXYZ(ax,y,pz,c,out_value),
13025 Icp = Iccp + 0.5f*(dx*(-Ipcp+Incp) + dx*dx*(2*Ipcp-5*Iccp+4*Incp-Iacp) + dx*dx*dx*(-Ipcp+3*Iccp-3*Incp+Iacp)),
13026 Ipnp = (Tfloat)
atXYZ(px,ny,pz,c,out_value), Icnp = (Tfloat)
atXYZ(x,ny,pz,c,out_value),
13027 Innp = (Tfloat)
atXYZ(nx,ny,pz,c,out_value), Ianp = (Tfloat)
atXYZ(ax,ny,pz,c,out_value),
13028 Inp = Icnp + 0.5f*(dx*(-Ipnp+Innp) + dx*dx*(2*Ipnp-5*Icnp+4*Innp-Ianp) + dx*dx*dx*(-Ipnp+3*Icnp-3*Innp+Ianp)),
13029 Ipap = (Tfloat)
atXYZ(px,ay,pz,c,out_value), Icap = (Tfloat)
atXYZ(x,ay,pz,c,out_value),
13030 Inap = (Tfloat)
atXYZ(nx,ay,pz,c,out_value), Iaap = (Tfloat)
atXYZ(ax,ay,pz,c,out_value),
13031 Iap = Icap + 0.5f*(dx*(-Ipap+Inap) + dx*dx*(2*Ipap-5*Icap+4*Inap-Iaap) + dx*dx*dx*(-Ipap+3*Icap-3*Inap+Iaap)),
13032 Ip = Icp + 0.5f*(dy*(-Ipp+Inp) + dy*dy*(2*Ipp-5*Icp+4*Inp-Iap) + dy*dy*dy*(-Ipp+3*Icp-3*Inp+Iap)),
13033 Ippc = (Tfloat)
atXYZ(px,py,z,c,out_value), Icpc = (Tfloat)
atXYZ(x,py,z,c,out_value),
13034 Inpc = (Tfloat)
atXYZ(nx,py,z,c,out_value), Iapc = (Tfloat)
atXYZ(ax,py,z,c,out_value),
13035 Ipc = Icpc + 0.5f*(dx*(-Ippc+Inpc) + dx*dx*(2*Ippc-5*Icpc+4*Inpc-Iapc) + dx*dx*dx*(-Ippc+3*Icpc-3*Inpc+Iapc)),
13036 Ipcc = (Tfloat)
atXYZ(px,y,z,c,out_value), Iccc = (Tfloat)
atXYZ(x, y,z,c,out_value),
13037 Incc = (Tfloat)
atXYZ(nx,y,z,c,out_value), Iacc = (Tfloat)
atXYZ(ax,y,z,c,out_value),
13038 Icc = Iccc + 0.5f*(dx*(-Ipcc+Incc) + dx*dx*(2*Ipcc-5*Iccc+4*Incc-Iacc) + dx*dx*dx*(-Ipcc+3*Iccc-3*Incc+Iacc)),
13039 Ipnc = (Tfloat)
atXYZ(px,ny,z,c,out_value), Icnc = (Tfloat)
atXYZ(x,ny,z,c,out_value),
13040 Innc = (Tfloat)
atXYZ(nx,ny,z,c,out_value), Ianc = (Tfloat)
atXYZ(ax,ny,z,c,out_value),
13041 Inc = Icnc + 0.5f*(dx*(-Ipnc+Innc) + dx*dx*(2*Ipnc-5*Icnc+4*Innc-Ianc) + dx*dx*dx*(-Ipnc+3*Icnc-3*Innc+Ianc)),
13042 Ipac = (Tfloat)
atXYZ(px,ay,z,c,out_value), Icac = (Tfloat)
atXYZ(x,ay,z,c,out_value),
13043 Inac = (Tfloat)
atXYZ(nx,ay,z,c,out_value), Iaac = (Tfloat)
atXYZ(ax,ay,z,c,out_value),
13044 Iac = Icac + 0.5f*(dx*(-Ipac+Inac) + dx*dx*(2*Ipac-5*Icac+4*Inac-Iaac) + dx*dx*dx*(-Ipac+3*Icac-3*Inac+Iaac)),
13045 Ic = Icc + 0.5f*(dy*(-Ipc+Inc) + dy*dy*(2*Ipc-5*Icc+4*Inc-Iac) + dy*dy*dy*(-Ipc+3*Icc-3*Inc+Iac)),
13046 Ippn = (Tfloat)
atXYZ(px,py,nz,c,out_value), Icpn = (Tfloat)
atXYZ(x,py,nz,c,out_value),
13047 Inpn = (Tfloat)
atXYZ(nx,py,nz,c,out_value), Iapn = (Tfloat)
atXYZ(ax,py,nz,c,out_value),
13048 Ipn = Icpn + 0.5f*(dx*(-Ippn+Inpn) + dx*dx*(2*Ippn-5*Icpn+4*Inpn-Iapn) + dx*dx*dx*(-Ippn+3*Icpn-3*Inpn+Iapn)),
13049 Ipcn = (Tfloat)
atXYZ(px,y,nz,c,out_value), Iccn = (Tfloat)
atXYZ(x, y,nz,c,out_value),
13050 Incn = (Tfloat)
atXYZ(nx,y,nz,c,out_value), Iacn = (Tfloat)
atXYZ(ax,y,nz,c,out_value),
13051 Icn = Iccn + 0.5f*(dx*(-Ipcn+Incn) + dx*dx*(2*Ipcn-5*Iccn+4*Incn-Iacn) + dx*dx*dx*(-Ipcn+3*Iccn-3*Incn+Iacn)),
13052 Ipnn = (Tfloat)
atXYZ(px,ny,nz,c,out_value), Icnn = (Tfloat)
atXYZ(x,ny,nz,c,out_value),
13053 Innn = (Tfloat)
atXYZ(nx,ny,nz,c,out_value), Iann = (Tfloat)
atXYZ(ax,ny,nz,c,out_value),
13054 Inn = Icnn + 0.5f*(dx*(-Ipnn+Innn) + dx*dx*(2*Ipnn-5*Icnn+4*Innn-Iann) + dx*dx*dx*(-Ipnn+3*Icnn-3*Innn+Iann)),
13055 Ipan = (Tfloat)
atXYZ(px,ay,nz,c,out_value), Ican = (Tfloat)
atXYZ(x,ay,nz,c,out_value),
13056 Inan = (Tfloat)
atXYZ(nx,ay,nz,c,out_value), Iaan = (Tfloat)
atXYZ(ax,ay,nz,c,out_value),
13057 Ian = Ican + 0.5f*(dx*(-Ipan+Inan) + dx*dx*(2*Ipan-5*Ican+4*Inan-Iaan) + dx*dx*dx*(-Ipan+3*Ican-3*Inan+Iaan)),
13058 In = Icn + 0.5f*(dy*(-Ipn+Inn) + dy*dy*(2*Ipn-5*Icn+4*Inn-Ian) + dy*dy*dy*(-Ipn+3*Icn-3*Inn+Ian)),
13059 Ippa = (Tfloat)
atXYZ(px,py,az,c,out_value), Icpa = (Tfloat)
atXYZ(x,py,az,c,out_value),
13060 Inpa = (Tfloat)
atXYZ(nx,py,az,c,out_value), Iapa = (Tfloat)
atXYZ(ax,py,az,c,out_value),
13061 Ipa = Icpa + 0.5f*(dx*(-Ippa+Inpa) + dx*dx*(2*Ippa-5*Icpa+4*Inpa-Iapa) + dx*dx*dx*(-Ippa+3*Icpa-3*Inpa+Iapa)),
13062 Ipca = (Tfloat)
atXYZ(px,y,az,c,out_value), Icca = (Tfloat)
atXYZ(x, y,az,c,out_value),
13063 Inca = (Tfloat)
atXYZ(nx,y,az,c,out_value), Iaca = (Tfloat)
atXYZ(ax,y,az,c,out_value),
13064 Ica = Icca + 0.5f*(dx*(-Ipca+Inca) + dx*dx*(2*Ipca-5*Icca+4*Inca-Iaca) + dx*dx*dx*(-Ipca+3*Icca-3*Inca+Iaca)),
13065 Ipna = (Tfloat)
atXYZ(px,ny,az,c,out_value), Icna = (Tfloat)
atXYZ(x,ny,az,c,out_value),
13066 Inna = (Tfloat)
atXYZ(nx,ny,az,c,out_value), Iana = (Tfloat)
atXYZ(ax,ny,az,c,out_value),
13067 Ina = Icna + 0.5f*(dx*(-Ipna+Inna) + dx*dx*(2*Ipna-5*Icna+4*Inna-Iana) + dx*dx*dx*(-Ipna+3*Icna-3*Inna+Iana)),
13068 Ipaa = (Tfloat)
atXYZ(px,ay,az,c,out_value), Icaa = (Tfloat)
atXYZ(x,ay,az,c,out_value),
13069 Inaa = (Tfloat)
atXYZ(nx,ay,az,c,out_value), Iaaa = (Tfloat)
atXYZ(ax,ay,az,c,out_value),
13070 Iaa = Icaa + 0.5f*(dx*(-Ipaa+Inaa) + dx*dx*(2*Ipaa-5*Icaa+4*Inaa-Iaaa) + dx*dx*dx*(-Ipaa+3*Icaa-3*Inaa+Iaaa)),
13071 Ia = Ica + 0.5f*(dy*(-Ipa+Ina) + dy*dy*(2*Ipa-5*Ica+4*Ina-Iaa) + dy*dy*dy*(-Ipa+3*Ica-3*Ina+Iaa));
13072 return Ic + 0.5f*(dz*(-Ip+In) + dz*dz*(2*Ip-5*Ic+4*In-Ia) + dz*dz*dz*(-Ip+3*Ic-3*In+Ia));
13080 Tfloat
cubic_atXYZ(
const float fx,
const float fy,
const float fz,
const int c,
const T out_value,
13081 const Tfloat min_value,
const Tfloat max_value)
const {
13082 const Tfloat val =
cubic_atXYZ(fx,fy,fz,c,out_value);
13083 return val<min_value?min_value:val>max_value?max_value:val;
13094 Tfloat
cubic_atXYZ(
const float fx,
const float fy,
const float fz,
const int c=0)
const {
13097 "cubic_atXYZ(): Empty instance.",
13099 return _cubic_atXYZ(fx,fy,fz,c);
13102 Tfloat _cubic_atXYZ(
const float fx,
const float fy,
const float fz,
const int c=0)
const {
13104 nfx = fx<0?0:(fx>_width-1?_width-1:fx),
13105 nfy = fy<0?0:(fy>_height-1?_height-1:fy),
13106 nfz = fz<0?0:(fz>_depth-1?_depth-1:fz);
13107 const int x = (int)nfx, y = (
int)nfy, z = (int)nfz;
13108 const float dx = nfx - x, dy = nfy - y, dz = nfz - z;
13110 px = x-1<0?0:x-1, nx = dx>0?x+1:x, ax = x+2>=
width()?
width()-1:x+2,
13111 py = y-1<0?0:y-1, ny = dy>0?y+1:y, ay = y+2>=
height()?
height()-1:y+2,
13112 pz = z-1<0?0:z-1, nz = dz>0?z+1:z, az = z+2>=
depth()?
depth()-1:z+2;
13114 Ippp = (Tfloat)(*
this)(px,py,pz,c), Icpp = (Tfloat)(*this)(x,py,pz,c),
13115 Inpp = (Tfloat)(*this)(nx,py,pz,c), Iapp = (Tfloat)(*this)(ax,py,pz,c),
13116 Ipp = Icpp + 0.5f*(dx*(-Ippp+Inpp) + dx*dx*(2*Ippp-5*Icpp+4*Inpp-Iapp) + dx*dx*dx*(-Ippp+3*Icpp-3*Inpp+Iapp)),
13117 Ipcp = (Tfloat)(*this)(px,y,pz,c), Iccp = (Tfloat)(*this)(x, y,pz,c),
13118 Incp = (Tfloat)(*this)(nx,y,pz,c), Iacp = (Tfloat)(*this)(ax,y,pz,c),
13119 Icp = Iccp + 0.5f*(dx*(-Ipcp+Incp) + dx*dx*(2*Ipcp-5*Iccp+4*Incp-Iacp) + dx*dx*dx*(-Ipcp+3*Iccp-3*Incp+Iacp)),
13120 Ipnp = (Tfloat)(*this)(px,ny,pz,c), Icnp = (Tfloat)(*this)(x,ny,pz,c),
13121 Innp = (Tfloat)(*this)(nx,ny,pz,c), Ianp = (Tfloat)(*this)(ax,ny,pz,c),
13122 Inp = Icnp + 0.5f*(dx*(-Ipnp+Innp) + dx*dx*(2*Ipnp-5*Icnp+4*Innp-Ianp) + dx*dx*dx*(-Ipnp+3*Icnp-3*Innp+Ianp)),
13123 Ipap = (Tfloat)(*this)(px,ay,pz,c), Icap = (Tfloat)(*this)(x,ay,pz,c),
13124 Inap = (Tfloat)(*this)(nx,ay,pz,c), Iaap = (Tfloat)(*this)(ax,ay,pz,c),
13125 Iap = Icap + 0.5f*(dx*(-Ipap+Inap) + dx*dx*(2*Ipap-5*Icap+4*Inap-Iaap) + dx*dx*dx*(-Ipap+3*Icap-3*Inap+Iaap)),
13126 Ip = Icp + 0.5f*(dy*(-Ipp+Inp) + dy*dy*(2*Ipp-5*Icp+4*Inp-Iap) + dy*dy*dy*(-Ipp+3*Icp-3*Inp+Iap)),
13127 Ippc = (Tfloat)(*this)(px,py,z,c), Icpc = (Tfloat)(*this)(x,py,z,c),
13128 Inpc = (Tfloat)(*this)(nx,py,z,c), Iapc = (Tfloat)(*this)(ax,py,z,c),
13129 Ipc = Icpc + 0.5f*(dx*(-Ippc+Inpc) + dx*dx*(2*Ippc-5*Icpc+4*Inpc-Iapc) + dx*dx*dx*(-Ippc+3*Icpc-3*Inpc+Iapc)),
13130 Ipcc = (Tfloat)(*this)(px,y,z,c), Iccc = (Tfloat)(*this)(x, y,z,c),
13131 Incc = (Tfloat)(*this)(nx,y,z,c), Iacc = (Tfloat)(*this)(ax,y,z,c),
13132 Icc = Iccc + 0.5f*(dx*(-Ipcc+Incc) + dx*dx*(2*Ipcc-5*Iccc+4*Incc-Iacc) + dx*dx*dx*(-Ipcc+3*Iccc-3*Incc+Iacc)),
13133 Ipnc = (Tfloat)(*this)(px,ny,z,c), Icnc = (Tfloat)(*this)(x,ny,z,c),
13134 Innc = (Tfloat)(*this)(nx,ny,z,c), Ianc = (Tfloat)(*this)(ax,ny,z,c),
13135 Inc = Icnc + 0.5f*(dx*(-Ipnc+Innc) + dx*dx*(2*Ipnc-5*Icnc+4*Innc-Ianc) + dx*dx*dx*(-Ipnc+3*Icnc-3*Innc+Ianc)),
13136 Ipac = (Tfloat)(*this)(px,ay,z,c), Icac = (Tfloat)(*this)(x,ay,z,c),
13137 Inac = (Tfloat)(*this)(nx,ay,z,c), Iaac = (Tfloat)(*this)(ax,ay,z,c),
13138 Iac = Icac + 0.5f*(dx*(-Ipac+Inac) + dx*dx*(2*Ipac-5*Icac+4*Inac-Iaac) + dx*dx*dx*(-Ipac+3*Icac-3*Inac+Iaac)),
13139 Ic = Icc + 0.5f*(dy*(-Ipc+Inc) + dy*dy*(2*Ipc-5*Icc+4*Inc-Iac) + dy*dy*dy*(-Ipc+3*Icc-3*Inc+Iac)),
13140 Ippn = (Tfloat)(*this)(px,py,nz,c), Icpn = (Tfloat)(*this)(x,py,nz,c),
13141 Inpn = (Tfloat)(*this)(nx,py,nz,c), Iapn = (Tfloat)(*this)(ax,py,nz,c),
13142 Ipn = Icpn + 0.5f*(dx*(-Ippn+Inpn) + dx*dx*(2*Ippn-5*Icpn+4*Inpn-Iapn) + dx*dx*dx*(-Ippn+3*Icpn-3*Inpn+Iapn)),
13143 Ipcn = (Tfloat)(*this)(px,y,nz,c), Iccn = (Tfloat)(*this)(x, y,nz,c),
13144 Incn = (Tfloat)(*this)(nx,y,nz,c), Iacn = (Tfloat)(*this)(ax,y,nz,c),
13145 Icn = Iccn + 0.5f*(dx*(-Ipcn+Incn) + dx*dx*(2*Ipcn-5*Iccn+4*Incn-Iacn) + dx*dx*dx*(-Ipcn+3*Iccn-3*Incn+Iacn)),
13146 Ipnn = (Tfloat)(*this)(px,ny,nz,c), Icnn = (Tfloat)(*this)(x,ny,nz,c),
13147 Innn = (Tfloat)(*this)(nx,ny,nz,c), Iann = (Tfloat)(*this)(ax,ny,nz,c),
13148 Inn = Icnn + 0.5f*(dx*(-Ipnn+Innn) + dx*dx*(2*Ipnn-5*Icnn+4*Innn-Iann) + dx*dx*dx*(-Ipnn+3*Icnn-3*Innn+Iann)),
13149 Ipan = (Tfloat)(*this)(px,ay,nz,c), Ican = (Tfloat)(*this)(x,ay,nz,c),
13150 Inan = (Tfloat)(*this)(nx,ay,nz,c), Iaan = (Tfloat)(*this)(ax,ay,nz,c),
13151 Ian = Ican + 0.5f*(dx*(-Ipan+Inan) + dx*dx*(2*Ipan-5*Ican+4*Inan-Iaan) + dx*dx*dx*(-Ipan+3*Ican-3*Inan+Iaan)),
13152 In = Icn + 0.5f*(dy*(-Ipn+Inn) + dy*dy*(2*Ipn-5*Icn+4*Inn-Ian) + dy*dy*dy*(-Ipn+3*Icn-3*Inn+Ian)),
13153 Ippa = (Tfloat)(*this)(px,py,az,c), Icpa = (Tfloat)(*this)(x,py,az,c),
13154 Inpa = (Tfloat)(*this)(nx,py,az,c), Iapa = (Tfloat)(*this)(ax,py,az,c),
13155 Ipa = Icpa + 0.5f*(dx*(-Ippa+Inpa) + dx*dx*(2*Ippa-5*Icpa+4*Inpa-Iapa) + dx*dx*dx*(-Ippa+3*Icpa-3*Inpa+Iapa)),
13156 Ipca = (Tfloat)(*this)(px,y,az,c), Icca = (Tfloat)(*this)(x, y,az,c),
13157 Inca = (Tfloat)(*this)(nx,y,az,c), Iaca = (Tfloat)(*this)(ax,y,az,c),
13158 Ica = Icca + 0.5f*(dx*(-Ipca+Inca) + dx*dx*(2*Ipca-5*Icca+4*Inca-Iaca) + dx*dx*dx*(-Ipca+3*Icca-3*Inca+Iaca)),
13159 Ipna = (Tfloat)(*this)(px,ny,az,c), Icna = (Tfloat)(*this)(x,ny,az,c),
13160 Inna = (Tfloat)(*this)(nx,ny,az,c), Iana = (Tfloat)(*this)(ax,ny,az,c),
13161 Ina = Icna + 0.5f*(dx*(-Ipna+Inna) + dx*dx*(2*Ipna-5*Icna+4*Inna-Iana) + dx*dx*dx*(-Ipna+3*Icna-3*Inna+Iana)),
13162 Ipaa = (Tfloat)(*this)(px,ay,az,c), Icaa = (Tfloat)(*this)(x,ay,az,c),
13163 Inaa = (Tfloat)(*this)(nx,ay,az,c), Iaaa = (Tfloat)(*this)(ax,ay,az,c),
13164 Iaa = Icaa + 0.5f*(dx*(-Ipaa+Inaa) + dx*dx*(2*Ipaa-5*Icaa+4*Inaa-Iaaa) + dx*dx*dx*(-Ipaa+3*Icaa-3*Inaa+Iaaa)),
13165 Ia = Ica + 0.5f*(dy*(-Ipa+Ina) + dy*dy*(2*Ipa-5*Ica+4*Ina-Iaa) + dy*dy*dy*(-Ipa+3*Ica-3*Ina+Iaa));
13166 return Ic + 0.5f*(dz*(-Ip+In) + dz*dz*(2*Ip-5*Ic+4*In-Ia) + dz*dz*dz*(-Ip+3*Ic-3*In+Ia));
13174 Tfloat
cubic_atXYZ(
const float fx,
const float fy,
const float fz,
const int c,
13175 const Tfloat min_value,
const Tfloat max_value)
const {
13177 return val<min_value?min_value:val>max_value?max_value:val;
13180 Tfloat _cubic_atXYZ(
const float fx,
const float fy,
const float fz,
const int c,
13181 const Tfloat min_value,
const Tfloat max_value)
const {
13182 const Tfloat val = _cubic_atXYZ(fx,fy,fz,c);
13183 return val<min_value?min_value:val>max_value?max_value:val;
13202 const bool is_added=
false) {
13204 x = (int)fx - (fx>=0?0:1), nx = x + 1,
13205 y = (int)fy - (fy>=0?0:1), ny = y + 1;
13210 if (y>=0 && y<
height()) {
13211 if (x>=0 && x<
width()) {
13212 const float w1 = (1-dx)*(1-dy), w2 = is_added?1:(1-w1);
13213 (*this)(x,y,z,c) = (T)(w1*value + w2*(*this)(x,y,z,c));
13215 if (nx>=0 && nx<
width()) {
13216 const float w1 = dx*(1-dy), w2 = is_added?1:(1-w1);
13217 (*this)(nx,y,z,c) = (T)(w1*value + w2*(*this)(nx,y,z,c));
13220 if (ny>=0 && ny<
height()) {
13221 if (x>=0 && x<
width()) {
13222 const float w1 = (1-dx)*dy, w2 = is_added?1:(1-w1);
13223 (*this)(x,ny,z,c) = (T)(w1*value + w2*(*this)(x,ny,z,c));
13225 if (nx>=0 && nx<
width()) {
13226 const float w1 = dx*dy, w2 = is_added?1:(1-w1);
13227 (*this)(nx,ny,z,c) = (T)(w1*value + w2*(*this)(nx,ny,z,c));
13240 const bool is_added=
false) {
13242 x = (int)fx - (fx>=0?0:1), nx = x + 1,
13243 y = (int)fy - (fy>=0?0:1), ny = y + 1,
13244 z = (int)fz - (fz>=0?0:1), nz = z + 1;
13250 if (z>=0 && z<
depth()) {
13251 if (y>=0 && y<
height()) {
13252 if (x>=0 && x<
width()) {
13253 const float w1 = (1-dx)*(1-dy)*(1-dz), w2 = is_added?1:(1-w1);
13254 (*this)(x,y,z,c) = (T)(w1*value + w2*(*this)(x,y,z,c));
13256 if (nx>=0 && nx<
width()) {
13257 const float w1 = dx*(1-dy)*(1-dz), w2 = is_added?1:(1-w1);
13258 (*this)(nx,y,z,c) = (T)(w1*value + w2*(*this)(nx,y,z,c));
13261 if (ny>=0 && ny<
height()) {
13262 if (x>=0 && x<
width()) {
13263 const float w1 = (1-dx)*dy*(1-dz), w2 = is_added?1:(1-w1);
13264 (*this)(x,ny,z,c) = (T)(w1*value + w2*(*this)(x,ny,z,c));
13266 if (nx>=0 && nx<
width()) {
13267 const float w1 = dx*dy*(1-dz), w2 = is_added?1:(1-w1);
13268 (*this)(nx,ny,z,c) = (T)(w1*value + w2*(*this)(nx,ny,z,c));
13272 if (nz>=0 && nz<
depth()) {
13273 if (y>=0 && y<
height()) {
13274 if (x>=0 && x<
width()) {
13275 const float w1 = (1-dx)*(1-dy)*dz, w2 = is_added?1:(1-w1);
13276 (*this)(x,y,nz,c) = (T)(w1*value + w2*(*this)(x,y,nz,c));
13278 if (nx>=0 && nx<
width()) {
13279 const float w1 = dx*(1-dy)*dz, w2 = is_added?1:(1-w1);
13280 (*this)(nx,y,nz,c) = (T)(w1*value + w2*(*this)(nx,y,nz,c));
13283 if (ny>=0 && ny<
height()) {
13284 if (x>=0 && x<
width()) {
13285 const float w1 = (1-dx)*dy*dz, w2 = is_added?1:(1-w1);
13286 (*this)(x,ny,nz,c) = (T)(w1*value + w2*(*this)(x,ny,nz,c));
13288 if (nx>=0 && nx<
width()) {
13289 const float w1 = dx*dy*dz, w2 = is_added?1:(1-w1);
13290 (*this)(nx,ny,nz,c) = (T)(w1*value + w2*(*this)(nx,ny,nz,c));
13314 char s_item[256] = { 0 };
13315 const T *ptrs = _data;
13316 unsigned int string_size = 0;
13317 for (
unsigned long off = 0, siz = (
unsigned int)
size(); off<siz && string_size<=max_size; ++off) {
13318 const unsigned int printed_size = 1U + cimg_snprintf(s_item,
sizeof(s_item),
13321 item[printed_size-1] = separator;
13323 if (max_size) string_size+=printed_size;
13327 if (max_size && res._width>max_size) res.
crop(0,max_size);
13357 return !(_data && _width && _height && _depth && _spectrum);
13380 return _width==size_x;
13384 template<
typename t>
13396 return _height==size_y;
13400 template<
typename t>
13412 return _depth==size_z;
13416 template<
typename t>
13423 return _spectrum==size_c;
13427 template<
typename t>
13436 bool is_sameXY(
const unsigned int size_x,
const unsigned int size_y)
const {
13437 return _width==size_x && _height==size_y;
13444 template<
typename t>
13446 return is_sameXY(img._width,img._height);
13454 return is_sameXY(disp._width,disp._height);
13461 bool is_sameXZ(
const unsigned int size_x,
const unsigned int size_z)
const {
13462 return _width==size_x && _depth==size_z;
13469 template<
typename t>
13471 return is_sameXZ(img._width,img._depth);
13478 bool is_sameXC(
const unsigned int size_x,
const unsigned int size_c)
const {
13479 return _width==size_x && _spectrum==size_c;
13486 template<
typename t>
13488 return is_sameXC(img._width,img._spectrum);
13495 bool is_sameYZ(
const unsigned int size_y,
const unsigned int size_z)
const {
13496 return _height==size_y && _depth==size_z;
13503 template<
typename t>
13505 return is_sameYZ(img._height,img._depth);
13512 bool is_sameYC(
const unsigned int size_y,
const unsigned int size_c)
const {
13513 return _height==size_y && _spectrum==size_c;
13520 template<
typename t>
13522 return is_sameYC(img._height,img._spectrum);
13529 bool is_sameZC(
const unsigned int size_z,
const unsigned int size_c)
const {
13530 return _depth==size_z && _spectrum==size_c;
13537 template<
typename t>
13539 return is_sameZC(img._depth,img._spectrum);
13546 bool is_sameXYZ(
const unsigned int size_x,
const unsigned int size_y,
const unsigned int size_z)
const {
13547 return is_sameXY(size_x,size_y) && _depth==size_z;
13554 template<
typename t>
13556 return is_sameXYZ(img._width,img._height,img._depth);
13563 bool is_sameXYC(
const unsigned int size_x,
const unsigned int size_y,
const unsigned int size_c)
const {
13564 return is_sameXY(size_x,size_y) && _spectrum==size_c;
13571 template<
typename t>
13573 return is_sameXYC(img._width,img._height,img._spectrum);
13580 bool is_sameXZC(
const unsigned int size_x,
const unsigned int size_z,
const unsigned int size_c)
const {
13581 return is_sameXZ(size_x,size_z) && _spectrum==size_c;
13588 template<
typename t>
13590 return is_sameXZC(img._width,img._depth,img._spectrum);
13597 bool is_sameYZC(
const unsigned int size_y,
const unsigned int size_z,
const unsigned int size_c)
const {
13598 return is_sameYZ(size_y,size_z) && _spectrum==size_c;
13605 template<
typename t>
13607 return is_sameYZC(img._height,img._depth,img._spectrum);
13616 const unsigned int size_z,
const unsigned int size_c)
const {
13617 return is_sameXYZ(size_x,size_y,size_z) && _spectrum==size_c;
13624 template<
typename t>
13626 return is_sameXYZC(img._width,img._height,img._depth,img._spectrum);
13645 bool containsXYZC(
const int x,
const int y=0,
const int z=0,
const int c=0)
const {
13646 return !
is_empty() && x>=0 && x<width() && y>=0 && y<height() && z>=0 && z<depth() && c>=0 && c<
spectrum();
13670 template<
typename t>
13671 bool contains(
const T& pixel, t& x, t& y, t& z, t& c)
const {
13672 const unsigned long wh = (
unsigned long)_width*_height, whd = wh*_depth, siz = whd*_spectrum;
13673 const T *
const ppixel = &pixel;
13674 if (
is_empty() || ppixel<_data || ppixel>=_data+siz)
return false;
13675 unsigned long off = (
unsigned long)(ppixel - _data);
13676 const unsigned long nc = off/whd;
13678 const unsigned long nz = off/wh;
13680 const unsigned long ny = off/_width, nx = off%_width;
13681 x = (t)nx; y = (t)ny; z = (t)nz; c = (t)nc;
13689 template<
typename t>
13691 const unsigned long wh = (
unsigned long)_width*_height, whd = wh*_depth, siz = whd*_spectrum;
13692 const T *
const ppixel = &pixel;
13693 if (
is_empty() || ppixel<_data || ppixel>=_data+siz)
return false;
13694 unsigned long off = ((
unsigned long)(ppixel - _data))%whd;
13695 const unsigned long nz = off/wh;
13697 const unsigned long ny = off/_width, nx = off%_width;
13698 x = (t)nx; y = (t)ny; z = (t)nz;
13706 template<
typename t>
13708 const unsigned long wh = (
unsigned long)_width*_height, siz = wh*_depth*_spectrum;
13709 const T *
const ppixel = &pixel;
13710 if (
is_empty() || ppixel<_data || ppixel>=_data+siz)
return false;
13711 unsigned long off = ((
unsigned int)(ppixel - _data))%wh;
13712 const unsigned long ny = off/_width, nx = off%_width;
13713 x = (t)nx; y = (t)ny;
13721 template<
typename t>
13723 const T *
const ppixel = &pixel;
13724 if (
is_empty() || ppixel<_data || ppixel>=_data+
size())
return false;
13725 x = (t)(((
unsigned long)(ppixel - _data))%_width);
13734 const T *
const ppixel = &pixel;
13735 return !
is_empty() && ppixel>=_data && ppixel<_data +
size();
13757 template<
typename t>
13759 const unsigned long csiz =
size(), isiz = img.size();
13760 return !((
void*)(_data + csiz)<=(
void*)img._data || (
void*)_data>=(
void*)(img._data + isiz));
13777 template<
typename tp,
typename tc,
typename to>
13780 const to& opacities,
13781 const bool full_check=
true,
13782 char *
const error_message=0)
const {
13783 if (error_message) *error_message = 0;
13787 if (primitives || colors || opacities) {
13788 if (error_message) std::sprintf(error_message,
13789 "3d object (%u,%u) defines no vertices but %u primitives, "
13790 "%u colors and %lu opacities",
13791 _width,primitives._width,primitives._width,
13792 colors._width,(
unsigned long)opacities.size());
13799 if (_height!=3 || _depth>1 || _spectrum>1) {
13800 if (error_message) std::sprintf(error_message,
13801 "3d object (%u,%u) has invalid vertex dimensions (%u,%u,%u,%u)",
13802 _width,primitives._width,_width,_height,_depth,_spectrum);
13805 if (colors._width>primitives._width+1) {
13806 if (error_message) std::sprintf(error_message,
13807 "3d object (%u,%u) defines %u colors",
13808 _width,primitives._width,colors._width);
13811 if (opacities.size()>primitives._width) {
13812 if (error_message) std::sprintf(error_message,
13813 "3d object (%u,%u) defines %lu opacities",
13814 _width,primitives._width,(
unsigned long)opacities.size());
13817 if (!full_check)
return true;
13820 cimglist_for(primitives,l) {
13821 const CImg<tp>& primitive = primitives[l];
13822 const unsigned long psiz = primitive.size();
13825 const unsigned int i0 = (
unsigned int)primitive(0);
13827 if (error_message) std::sprintf(error_message,
13828 "3d object (%u,%u) refers to invalid vertex indice %u in "
13829 "point primitive [%u]",
13830 _width,primitives._width,i0,l);
13836 i0 = (
unsigned int)primitive(0),
13837 i1 = (
unsigned int)primitive(1);
13838 if (i0>=_width || i1>=_width) {
13839 if (error_message) std::sprintf(error_message,
13840 "3d object (%u,%u) refers to invalid vertex indices (%u,%u) in "
13841 "sphere primitive [%u]",
13842 _width,primitives._width,i0,i1,l);
13849 i0 = (
unsigned int)primitive(0),
13850 i1 = (
unsigned int)primitive(1);
13851 if (i0>=_width || i1>=_width) {
13852 if (error_message) std::sprintf(error_message,
13853 "3d object (%u,%u) refers to invalid vertex indices (%u,%u) in "
13854 "segment primitive [%u]",
13855 _width,primitives._width,i0,i1,l);
13862 i0 = (
unsigned int)primitive(0),
13863 i1 = (
unsigned int)primitive(1),
13864 i2 = (
unsigned int)primitive(2);
13865 if (i0>=_width || i1>=_width || i2>=_width) {
13866 if (error_message) std::sprintf(error_message,
13867 "3d object (%u,%u) refers to invalid vertex indices (%u,%u,%u) in "
13868 "triangle primitive [%u]",
13869 _width,primitives._width,i0,i1,i2,l);
13876 i0 = (
unsigned int)primitive(0),
13877 i1 = (
unsigned int)primitive(1),
13878 i2 = (
unsigned int)primitive(2),
13879 i3 = (
unsigned int)primitive(3);
13880 if (i0>=_width || i1>=_width || i2>=_width || i3>=_width) {
13881 if (error_message) std::sprintf(error_message,
13882 "3d object (%u,%u) refers to invalid vertex indices (%u,%u,%u,%u) in "
13883 "quadrangle primitive [%u]",
13884 _width,primitives._width,i0,i1,i2,i3,l);
13889 if (error_message) std::sprintf(error_message,
13890 "3d object (%u,%u) defines an invalid primitive [%u] of size %u",
13891 _width,primitives._width,l,(
unsigned int)psiz);
13897 cimglist_for(colors,c) {
13898 const CImg<tc>& color = colors[c];
13900 if (error_message) std::sprintf(error_message,
13901 "3d object (%u,%u) defines no color for primitive [%u]",
13902 _width,primitives._width,c);
13908 if (colors._width>primitives._width) {
13910 if (!light || light._depth>1) {
13911 if (error_message) std::sprintf(error_message,
13912 "3d object (%u,%u) defines an invalid light texture (%u,%u,%u,%u)",
13913 _width,primitives._width,light._width,
13914 light._height,light._depth,light._spectrum);
13932 bool is_CImg3d(
const bool full_check=
true,
char *
const error_message=0)
const {
13933 if (error_message) *error_message = 0;
13936 if (_width!=1 || _height<8 || _depth!=1 || _spectrum!=1) {
13937 if (error_message) std::sprintf(error_message,
13938 "CImg3d has invalid dimensions (%u,%u,%u,%u)",
13939 _width,_height,_depth,_spectrum);
13942 const T *ptrs = _data, *
const ptre =
end();
13943 if (!_is_CImg3d(*(ptrs++),
'C') || !_is_CImg3d(*(ptrs++),
'I') || !_is_CImg3d(*(ptrs++),
'm') ||
13944 !_is_CImg3d(*(ptrs++),
'g') || !_is_CImg3d(*(ptrs++),
'3') || !_is_CImg3d(*(ptrs++),
'd')) {
13945 if (error_message) std::sprintf(error_message,
13946 "CImg3d header not found");
13950 nb_points = cimg::float2uint((
float)*(ptrs++)),
13951 nb_primitives = cimg::float2uint((
float)*(ptrs++));
13955 const unsigned long minimal_size = 8UL + 3*nb_points + 6*nb_primitives;
13956 if (_data + minimal_size>ptre) {
13957 if (error_message) std::sprintf(error_message,
13958 "CImg3d (%u,%u) has only %lu values, while at least %lu values were expected",
13959 nb_points,nb_primitives,
size(),minimal_size);
13966 if (nb_primitives) {
13967 if (error_message) std::sprintf(error_message,
13968 "CImg3d (%u,%u) defines no vertices but %u primitives",
13969 nb_points,nb_primitives,nb_primitives);
13973 if (error_message) std::sprintf(error_message,
13974 "CImg3d (%u,%u) is an empty object but contains %u value%s "
13975 "more than expected",
13976 nb_points,nb_primitives,(
unsigned int)(ptre-ptrs),(ptre-ptrs)>1?
"s":
"");
13981 if (ptrs+3*nb_points>ptre) {
13982 if (error_message) std::sprintf(error_message,
13983 "CImg3d (%u,%u) defines only %u vertices data",
13984 nb_points,nb_primitives,(
unsigned int)(ptre-ptrs)/3);
13991 if (error_message) std::sprintf(error_message,
13992 "CImg3d (%u,%u) defines %u vertices but no primitive",
13993 nb_points,nb_primitives,nb_points);
13997 if (!full_check)
return true;
13999 for (
unsigned int p = 0; p<nb_primitives; ++p) {
14000 const unsigned int nb_inds = (
unsigned int)*(ptrs++);
14003 const unsigned int i0 = cimg::float2uint((
float)*(ptrs++));
14004 if (i0>=nb_points) {
14005 if (error_message) std::sprintf(error_message,
14006 "CImg3d (%u,%u) refers to invalid vertex indice %u in point primitive [%u]",
14007 nb_points,nb_primitives,i0,p);
14013 i0 = cimg::float2uint((
float)*(ptrs++)),
14014 i1 = cimg::float2uint((
float)*(ptrs++));
14016 if (i0>=nb_points || i1>=nb_points) {
14017 if (error_message) std::sprintf(error_message,
14018 "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u) in "
14019 "sphere primitive [%u]",
14020 nb_points,nb_primitives,i0,i1,p);
14024 case 2 :
case 6 : {
14026 i0 = cimg::float2uint((
float)*(ptrs++)),
14027 i1 = cimg::float2uint((
float)*(ptrs++));
14028 if (nb_inds==6) ptrs+=4;
14029 if (i0>=nb_points || i1>=nb_points) {
14030 if (error_message) std::sprintf(error_message,
14031 "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u) in "
14032 "segment primitive [%u]",
14033 nb_points,nb_primitives,i0,i1,p);
14037 case 3 :
case 9 : {
14039 i0 = cimg::float2uint((
float)*(ptrs++)),
14040 i1 = cimg::float2uint((
float)*(ptrs++)),
14041 i2 = cimg::float2uint((
float)*(ptrs++));
14042 if (nb_inds==9) ptrs+=6;
14043 if (i0>=nb_points || i1>=nb_points || i2>=nb_points) {
14044 if (error_message) std::sprintf(error_message,
14045 "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u,%u) in "
14046 "triangle primitive [%u]",
14047 nb_points,nb_primitives,i0,i1,i2,p);
14051 case 4 :
case 12 : {
14053 i0 = cimg::float2uint((
float)*(ptrs++)),
14054 i1 = cimg::float2uint((
float)*(ptrs++)),
14055 i2 = cimg::float2uint((
float)*(ptrs++)),
14056 i3 = cimg::float2uint((
float)*(ptrs++));
14057 if (nb_inds==12) ptrs+=8;
14058 if (i0>=nb_points || i1>=nb_points || i2>=nb_points || i3>=nb_points) {
14059 if (error_message) std::sprintf(error_message,
14060 "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u,%u,%u) in "
14061 "quadrangle primitive [%u]",
14062 nb_points,nb_primitives,i0,i1,i2,i3,p);
14067 if (error_message) std::sprintf(error_message,
14068 "CImg3d (%u,%u) defines an invalid primitive [%u] of size %u",
14069 nb_points,nb_primitives,p,nb_inds);
14073 if (error_message) std::sprintf(error_message,
14074 "CImg3d (%u,%u) has incomplete primitive data for primitive [%u], "
14075 "%u values missing",
14076 nb_points,nb_primitives,p,(
unsigned int)(ptrs-ptre));
14083 if (error_message) std::sprintf(error_message,
14084 "CImg3d (%u,%u) defines no color/texture data",
14085 nb_points,nb_primitives);
14088 for (
unsigned int c = 0; c<nb_primitives; ++c) {
14089 if (*(ptrs++)!=(T)-128) ptrs+=2;
14090 else if ((ptrs+=3)<ptre) {
14091 const unsigned int w = (
unsigned int)*(ptrs-3), h = (
unsigned int)*(ptrs-2), s = (
unsigned int)*(ptrs-1);
14094 if (error_message) std::sprintf(error_message,
14095 "CImg3d (%u,%u) refers to invalid shared sprite/texture indice %u "
14096 "for primitive [%u]",
14097 nb_points,nb_primitives,w,c);
14100 }
else ptrs+=w*h*s;
14103 if (error_message) std::sprintf(error_message,
14104 "CImg3d (%u,%u) has incomplete color/texture data for primitive [%u], "
14105 "%u values missing",
14106 nb_points,nb_primitives,c,(
unsigned int)(ptrs-ptre));
14113 if (error_message) std::sprintf(error_message,
14114 "CImg3d (%u,%u) defines no opacity data",
14115 nb_points,nb_primitives);
14118 for (
unsigned int o = 0; o<nb_primitives; ++o) {
14119 if (*(ptrs++)==(T)-128 && (ptrs+=3)<ptre) {
14120 const unsigned int w = (
unsigned int)*(ptrs-3), h = (
unsigned int)*(ptrs-2), s = (
unsigned int)*(ptrs-1);
14123 if (error_message) std::sprintf(error_message,
14124 "CImg3d (%u,%u) refers to invalid shared opacity indice %u "
14125 "for primitive [%u]",
14126 nb_points,nb_primitives,w,o);
14129 }
else ptrs+=w*h*s;
14132 if (error_message) std::sprintf(error_message,
14133 "CImg3d (%u,%u) has incomplete opacity data for primitive [%u]",
14134 nb_points,nb_primitives,o);
14141 if (error_message) std::sprintf(error_message,
14142 "CImg3d (%u,%u) contains %u value%s more than expected",
14143 nb_points,nb_primitives,(
unsigned int)(ptre-ptrs),(ptre-ptrs)>1?
"s":
"");
14149 static bool _is_CImg3d(
const T val,
const char c) {
14150 return val>=(T)c && val<(T)(c+1);
14171 unsigned int mempos, result;
14172 const char *
const calling_function;
14175 #define _cimg_mp_return(x) { *se = saved_char; return x; }
14176 #define _cimg_mp_opcode0(op) _cimg_mp_return(opcode0(op));
14177 #define _cimg_mp_opcode1(op,i1) _cimg_mp_return(opcode1(op,i1));
14178 #define _cimg_mp_opcode2(op,i1,i2) { const unsigned int _i1 = i1, _i2 = i2; _cimg_mp_return(opcode2(op,_i1,_i2)); }
14179 #define _cimg_mp_opcode3(op,i1,i2,i3) \
14180 { const unsigned int _i1 = i1, _i2 = i2, _i3 = i3; _cimg_mp_return(opcode3(op,_i1,_i2,_i3)); }
14181 #define _cimg_mp_opcode6(op,i1,i2,i3,i4,i5,i6) \
14182 { const unsigned int _i1 = i1, _i2 = i2, _i3 = i3, _i4 = i4, _i5 = i5, _i6 = i6; \
14183 _cimg_mp_return(opcode6(op,_i1,_i2,_i3,_i4,_i5,_i6)); }
14185 #if defined(_WIN64)
14187 #define _cimg_mp_enfunc(op) (long)((char*)(op)-(char*)mp_u)
14188 #define _cimg_mp_defunc(mp) (*(mp_func)((char*)mp_u+(mp).opcode[0]))(mp)
14190 #define _cimg_mp_enfunc(op) (long)(op)
14191 #define _cimg_mp_defunc(mp) (*(mp_func)((mp).opcode[0]))(mp)
14197 _cimg_math_parser(
const CImg<T>& img,
const char *
const expression,
const char *
const funcname=0):
14198 reference(img),calling_function(funcname?funcname:
"cimg_math_parser") {
14199 unsigned int l = 0;
14201 l = (
unsigned int)std::strlen(expression);
14202 expr.
assign(expression,l+1);
14204 char *d = expr._data;
14205 for (
const char *s = expr._data; *s || (
bool)(*d=0); ++s)
if (*s!=
' ') *(d++) = *s;
14206 l = (
unsigned int)(d - expr._data);
14210 "CImg<%s>::%s(): Empty specified expression.",
14215 unsigned int *pd = level._data;
14216 for (
const char *ps = expr._data; *ps && lv>=0; ++ps)
14217 *(pd++) = (
unsigned int)(*ps==
'('||*ps==
'['?lv++:*ps==
')'||*ps==
']'?--lv:lv);
14220 "CImg<%s>::%s(): Unbalanced parentheses/brackets in specified expression '%s'.",
14229 mem[3] = (double)reference._width;
14230 mem[4] = (
double)reference._height;
14231 mem[5] = (double)reference._depth;
14232 mem[6] = (
double)reference._spectrum;
14234 mem[8] = std::exp(1.0);
14237 label1pos.
assign(128,1,1,1,~0U);
14238 label1pos[
'w'] = 3;
14239 label1pos[
'h'] = 4;
14240 label1pos[
'd'] = 5;
14241 label1pos[
's'] = 6;
14243 label1pos[
'e'] = 8;
14244 label1pos[
'x'] = 9;
14245 label1pos[
'y'] = 10;
14246 label1pos[
'z'] = 11;
14247 label1pos[
'c'] = 12;
14248 result = compile(expr._data,expr._data+l);
14252 unsigned int opcode0(
const mp_func op) {
14253 if (mempos>=mem._width) mem.
resize(-200,1,1,1,0);
14254 const unsigned int pos = mempos++;
14259 unsigned int opcode1(
const mp_func op,
const unsigned int arg1) {
14260 if (mempos>=mem._width) mem.
resize(-200,1,1,1,0);
14261 const unsigned int pos = mempos++;
14266 unsigned int opcode2(
const mp_func op,
const unsigned int arg1,
const unsigned int arg2) {
14267 if (mempos>=mem._width) mem.
resize(-200,1,1,1,0);
14268 const unsigned int pos = mempos++;
14273 unsigned int opcode3(
const mp_func op,
14274 const unsigned int arg1,
const unsigned int arg2,
const unsigned int arg3) {
14275 if (mempos>=mem._width) mem.
resize(-200,1,1,1,0);
14276 const unsigned int pos = mempos++;
14281 unsigned int opcode6(
const mp_func op,
14282 const unsigned int arg1,
const unsigned int arg2,
const unsigned int arg3,
14283 const unsigned int arg4,
const unsigned int arg5,
const unsigned int arg6) {
14284 if (mempos>=mem._width) mem.
resize(-200,1,1,1,0);
14285 const unsigned int pos = mempos++;
14286 CImg<longT>::vector(_cimg_mp_enfunc(op),pos,arg1,arg2,arg3,arg4,arg5,arg6).move_to(code);
14291 unsigned int compile(
char *
const ss,
char *
const se) {
14292 if (!ss || se<=ss || !*ss) {
14294 "CImg<%s>::%s(): Missing item in specified expression '%s'.",
14299 *
const se1 = se-1, *
const se2 = se-2, *
const se3 = se-3, *
const se4 = se-4,
14300 *
const ss1 = ss+1, *
const ss2 = ss+2, *
const ss3 = ss+3, *
const ss4 = ss+4,
14301 *
const ss5 = ss+5, *
const ss6 = ss+6, *
const ss7 = ss+7;
14302 const char saved_char = *se; *se = 0;
14303 const unsigned int clevel = level[ss-expr._data], clevel1 = clevel+1;
14304 if (*se1==
';')
return compile(ss,se1);
14307 char end = 0, sep = 0;
double val = 0;
14308 const int nb = std::sscanf(ss,
"%lf%c%c",&val,&sep,&end);
14310 if (val==0 || val==1 || val==2) _cimg_mp_return((
int)val);
14311 if (mempos>=mem._width) mem.
resize(-200,1,1,1,0);
14312 const unsigned int pos = mempos++;
14314 _cimg_mp_return(pos);
14316 if (nb==2 && sep==
'%') {
14317 if (val==0 || val==100 || val==200) _cimg_mp_return((
int)(val/100));
14318 if (mempos>=mem._width) mem.
resize(-200,1,1,1,0);
14319 const unsigned int pos = mempos++;
14320 mem[pos] = val/100;
14321 _cimg_mp_return(pos);
14323 if (ss1==se)
switch (*ss) {
14324 case 'w' :
case 'h' :
case 'd' :
case 's' :
14325 case 'x' :
case 'y' :
case 'z' :
case 'c' :
case 'e' : _cimg_mp_return(label1pos[*ss]);
14326 case 'u' :
if (label1pos[
'u']!=~0U) _cimg_mp_return(label1pos[
'u']); _cimg_mp_opcode2(mp_u,0,1);
14327 case 'g' :
if (label1pos[
'g']!=~0U) _cimg_mp_return(label1pos[
'g']); _cimg_mp_opcode0(mp_g);
14328 case 'i' :
if (label1pos[
'i']!=~0U) _cimg_mp_return(label1pos[
'i']); _cimg_mp_opcode0(mp_i);
14329 case '?' : _cimg_mp_opcode2(mp_u,0,1);
14332 if (*ss==
'p' && *ss1==
'i') _cimg_mp_return(label1pos[0]);
14334 if (*ss1==
'm') {
if (label1pos[1]!=~0U) _cimg_mp_return(label1pos[1]); _cimg_mp_opcode0(mp_im); }
14335 if (*ss1==
'M') {
if (label1pos[2]!=~0U) _cimg_mp_return(label1pos[2]); _cimg_mp_opcode0(mp_iM); }
14336 if (*ss1==
'a') {
if (label1pos[3]!=~0U) _cimg_mp_return(label1pos[3]); _cimg_mp_opcode0(mp_ia); }
14337 if (*ss1==
'v') {
if (label1pos[4]!=~0U) _cimg_mp_return(label1pos[4]); _cimg_mp_opcode0(mp_iv); }
14340 if (*ss==
'x') {
if (label1pos[5]!=~0U) _cimg_mp_return(label1pos[5]); _cimg_mp_opcode0(mp_xm); }
14341 if (*ss==
'y') {
if (label1pos[6]!=~0U) _cimg_mp_return(label1pos[6]); _cimg_mp_opcode0(mp_ym); }
14342 if (*ss==
'z') {
if (label1pos[7]!=~0U) _cimg_mp_return(label1pos[7]); _cimg_mp_opcode0(mp_zm); }
14343 if (*ss==
'c') {
if (label1pos[8]!=~0U) _cimg_mp_return(label1pos[8]); _cimg_mp_opcode0(mp_cm); }
14346 if (*ss==
'x') {
if (label1pos[9]!=~0U) _cimg_mp_return(label1pos[9]); _cimg_mp_opcode0(mp_xM); }
14347 if (*ss==
'y') {
if (label1pos[10]!=~0U) _cimg_mp_return(label1pos[10]); _cimg_mp_opcode0(mp_yM); }
14348 if (*ss==
'z') {
if (label1pos[11]!=~0U) _cimg_mp_return(label1pos[11]); _cimg_mp_opcode0(mp_zM); }
14349 if (*ss==
'c') {
if (label1pos[12]!=~0U) _cimg_mp_return(label1pos[12]); _cimg_mp_opcode0(mp_cM); }
14354 for (
char *s = se2; s>ss; --s)
14355 if (*s==
';' && level[s-expr._data]==clevel) { compile(ss,s); _cimg_mp_return(compile(s+1,se)); }
14356 for (
char *s = ss1, *ps = ss, *ns = ss2; s<se1; ++s, ++ps, ++ns)
14357 if (*s==
'=' && *ns!=
'=' && *ps!=
'=' && *ps!=
'>' && *ps!=
'<' && *ps!=
'!' && level[s-expr._data]==clevel) {
14358 CImg<charT> variable_name(ss,(
unsigned int)(s-ss+1));
14359 variable_name.
back() = 0;
14360 bool is_valid_name =
true;
14361 if (*ss>=
'0' && *ss<=
'9') is_valid_name =
false;
14362 else for (
const char *ns = ss+1; ns<s; ++ns)
14363 if ((*ns<'a' || *ns>
'z') && (*ns<'A' || *ns>
'Z') && (*ns<'0' || *ns>
'9') && *ns!=
'_') {
14364 is_valid_name =
false;
break;
14366 if (!is_valid_name) {
14369 "CImg<%s>::%s(): Invalid variable name '%s' in specified expression "
14372 variable_name._data,
14373 (ss-8)>expr._data?
"...":
"",
14374 (ss-8)>expr._data?ss-8:expr._data,
14375 se<&expr.
back()?
"...":
"");
14377 const unsigned int pos = compile(s+1,se);
14380 if (variable_name[0] && variable_name[1] && !variable_name[2]) {
14381 const char c1 = variable_name[0], c2 = variable_name[1];
14382 if (c1==
'p' && c2==
'i') variable_name.
fill((
char)0,(
char)0);
14383 else if (c1==
'i') {
14384 if (c2==
'm') variable_name.
fill(1,0);
14385 else if (c2==
'M') variable_name.
fill(2,0);
14386 else if (c2==
'a') variable_name.
fill(3,0);
14387 else if (c2==
'v') variable_name.
fill(4,0);
14388 }
else if (c2==
'm') {
14389 if (c1==
'x') variable_name.
fill(5,0);
14390 else if (c1==
'y') variable_name.
fill(6,0);
14391 else if (c1==
'z') variable_name.
fill(7,0);
14392 else if (c1==
'c') variable_name.
fill(8,0);
14393 }
else if (c2==
'M') {
14394 if (c1==
'x') variable_name.
fill(9,0);
14395 else if (c1==
'y') variable_name.
fill(10,0);
14396 else if (c1==
'z') variable_name.
fill(11,0);
14397 else if (c1==
'c') variable_name.
fill(12,0);
14400 if (variable_name[1]) {
14401 int label_pos = -1;
14402 cimglist_for(labelM,i)
14403 if (!std::strcmp(variable_name,labelM[i])) { label_pos = i;
break; }
14405 if (labelM._width>=labelMpos._width) labelMpos.
resize(-200,1,1,1,0);
14406 label_pos = labelM._width;
14407 variable_name.
move_to(labelM);
14409 labelMpos[label_pos] = pos;
14410 }
else label1pos[*variable_name] = pos;
14411 _cimg_mp_return(pos);
14415 for (
char *s = se3, *ns = se2; s>ss; --s, --ns)
if (*s==
'|' && *ns==
'|' && level[s-expr._data]==clevel) {
14416 const unsigned int mem_A = compile(ss,s), bp1 = code._width, mem_B = compile(s+2,se);
14417 if (mempos>=mem._width) mem.
resize(-200,1,1,1,0);
14418 const unsigned int pos = mempos++;
14419 CImg<longT>::vector(_cimg_mp_enfunc(mp_logical_or),pos,mem_A,mem_B,code._width-bp1).move_to(code,bp1);
14420 _cimg_mp_return(pos);
14422 for (
char *s = se3, *ns = se2; s>ss; --s, --ns)
if (*s==
'&' && *ns==
'&' && level[s-expr._data]==clevel) {
14423 const unsigned int mem_A = compile(ss,s), bp1 = code._width, mem_B = compile(s+2,se);
14424 if (mempos>=mem._width) mem.
resize(-200,1,1,1,0);
14425 const unsigned int pos = mempos++;
14426 CImg<longT>::vector(_cimg_mp_enfunc(mp_logical_and),pos,mem_A,mem_B,code._width-bp1).move_to(code,bp1);
14427 _cimg_mp_return(pos);
14429 for (
char *s = se2; s>ss; --s)
14430 if (*s==
'|' && level[s-expr._data]==clevel)
14431 _cimg_mp_opcode2(mp_bitwise_or,compile(ss,s),compile(s+1,se));
14432 for (
char *s = se2; s>ss; --s)
14433 if (*s==
'&' && level[s-expr._data]==clevel)
14434 _cimg_mp_opcode2(mp_bitwise_and,compile(ss,s),compile(s+1,se));
14435 for (
char *s = se3, *ns = se2; s>ss; --s, --ns)
14436 if (*s==
'!' && *ns==
'=' && level[s-expr._data]==clevel)
14437 _cimg_mp_opcode2(mp_noteq,compile(ss,s),compile(s+2,se));
14438 for (
char *s = se3, *ns = se2; s>ss; --s, --ns)
14439 if (*s==
'=' && *ns==
'=' && level[s-expr._data]==clevel)
14440 _cimg_mp_opcode2(mp_eqeq,compile(ss,s),compile(s+2,se));
14441 for (
char *s = se3, *ns = se2; s>ss; --s, --ns)
14442 if (*s==
'<' && *ns==
'=' && level[s-expr._data]==clevel)
14443 _cimg_mp_opcode2(mp_infeq,compile(ss,s),compile(s+2,se));
14444 for (
char *s = se3, *ns = se2; s>ss; --s, --ns)
14445 if (*s==
'>' && *ns==
'=' && level[s-expr._data]==clevel)
14446 _cimg_mp_opcode2(mp_supeq,compile(ss,s),compile(s+2,se));
14447 for (
char *s = se2, *ns = se1, *ps = se3; s>ss; --s, --ns, --ps)
14448 if (*s==
'<' && *ns!=
'<' && *ps!=
'<' && level[s-expr._data]==clevel)
14449 _cimg_mp_opcode2(mp_inf,compile(ss,s),compile(s+1,se));
14450 for (
char *s = se2, *ns = se1, *ps = se3; s>ss; --s, --ns, --ps)
14451 if (*s==
'>' && *ns!=
'>' && *ps!=
'>' && level[s-expr._data]==clevel)
14452 _cimg_mp_opcode2(mp_sup,compile(ss,s),compile(s+1,se));
14453 for (
char *s = se3, *ns = se2; s>ss; --s, --ns)
14454 if (*s==
'<' && *ns==
'<' && level[s-expr._data]==clevel)
14455 _cimg_mp_opcode2(mp_lsl,compile(ss,s),compile(s+2,se));
14456 for (
char *s = se3, *ns = se2; s>ss; --s, --ns)
14457 if (*s==
'>' && *ns==
'>' && level[s-expr._data]==clevel)
14458 _cimg_mp_opcode2(mp_lsr,compile(ss,s),compile(s+2,se));
14459 for (
char *s = se2, *ps = se3; s>ss; --s, --ps)
14460 if (*s==
'+' && *ps!=
'-' && *ps!=
'+' && *ps!=
'*' && *ps!=
'/' && *ps!=
'%' &&
14461 *ps!=
'&' && *ps!=
'|' && *ps!=
'^' && *ps!=
'!' && *ps!=
'~' &&
14462 (*ps!=
'e' || !(ps>ss && (*(ps-1)==
'.' || (*(ps-1)>=
'0' && *(ps-1)<=
'9')))) && level[s-expr._data]==clevel)
14463 _cimg_mp_opcode2(mp_add,compile(ss,s),compile(s+1,se));
14464 for (
char *s = se2, *ps = se3; s>ss; --s, --ps)
14465 if (*s==
'-' && *ps!=
'-' && *ps!=
'+' && *ps!=
'*' && *ps!=
'/' && *ps!=
'%' &&
14466 *ps!=
'&' && *ps!=
'|' && *ps!=
'^' && *ps!=
'!' && *ps!=
'~' &&
14467 (*ps!=
'e' || !(ps>ss && (*(ps-1)==
'.' || (*(ps-1)>=
'0' && *(ps-1)<=
'9')))) && level[s-expr._data]==clevel)
14468 _cimg_mp_opcode2(mp_sub,compile(ss,s),compile(s+1,se));
14469 for (
char *s = se2; s>ss; --s)
if (*s==
'*' && level[s-expr._data]==clevel) {
14470 const unsigned int mem_A = compile(ss,s), bp1 = code._width, mem_B = compile(s+1,se);
14471 if (mempos>=mem._width) mem.
resize(-200,1,1,1,0);
14472 const unsigned int pos = mempos++;
14473 CImg<longT>::vector(_cimg_mp_enfunc(mp_mul),pos,mem_A,mem_B,code._width-bp1).move_to(code,bp1);
14474 _cimg_mp_return(pos);
14476 for (
char *s = se2; s>ss; --s)
14477 if (*s==
'/' && level[s-expr._data]==clevel)
14478 _cimg_mp_opcode2(mp_div,compile(ss,s),compile(s+1,se));
14479 for (
char *s = se2, *ns = se1; s>ss; --s, --ns)
14480 if (*s==
'%' && *ns!=
'^' && level[s-expr._data]==clevel)
14481 _cimg_mp_opcode2(mp_modulo,compile(ss,s),compile(s+1,se));
14483 if (*ss==
'+') _cimg_mp_return(compile(ss1,se));
14484 if (*ss==
'-') _cimg_mp_opcode1(mp_minus,compile(ss1,se));
14485 if (*ss==
'!') _cimg_mp_opcode1(mp_logical_not,compile(ss1,se));
14486 if (*ss==
'~') _cimg_mp_opcode1(mp_bitwise_not,compile(ss1,se));
14488 for (
char *s = se2; s>ss; --s)
14489 if (*s==
'^' && level[s-expr._data]==clevel)
14490 _cimg_mp_opcode2(mp_pow,compile(ss,s),compile(s+1,se));
14494 const bool is_relative = *ss==
'j';
14495 if ((*ss==
'i' || is_relative) && *ss1==
'[') {
14496 if (*ss2==
']') _cimg_mp_opcode0(mp_i);
14497 _cimg_mp_opcode1(is_relative?mp_joff:mp_ioff,compile(ss2,se1));
14501 if (*ss==
'(') _cimg_mp_return(compile(ss1,se1));
14502 if (!std::strncmp(ss,
"sin(",4)) _cimg_mp_opcode1(mp_sin,compile(ss4,se1));
14503 if (!std::strncmp(ss,
"cos(",4)) _cimg_mp_opcode1(mp_cos,compile(ss4,se1));
14504 if (!std::strncmp(ss,
"tan(",4)) _cimg_mp_opcode1(mp_tan,compile(ss4,se1));
14505 if (!std::strncmp(ss,
"asin(",5)) _cimg_mp_opcode1(mp_asin,compile(ss5,se1));
14506 if (!std::strncmp(ss,
"acos(",5)) _cimg_mp_opcode1(mp_acos,compile(ss5,se1));
14507 if (!std::strncmp(ss,
"atan(",5)) _cimg_mp_opcode1(mp_atan,compile(ss5,se1));
14508 if (!std::strncmp(ss,
"sinh(",5)) _cimg_mp_opcode1(mp_sinh,compile(ss5,se1));
14509 if (!std::strncmp(ss,
"cosh(",5)) _cimg_mp_opcode1(mp_cosh,compile(ss5,se1));
14510 if (!std::strncmp(ss,
"tanh(",5)) _cimg_mp_opcode1(mp_tanh,compile(ss5,se1));
14511 if (!std::strncmp(ss,
"log10(",6)) _cimg_mp_opcode1(mp_log10,compile(ss6,se1));
14512 if (!std::strncmp(ss,
"log2(",5)) _cimg_mp_opcode1(mp_log2,compile(ss5,se1));
14513 if (!std::strncmp(ss,
"log(",4)) _cimg_mp_opcode1(mp_log,compile(ss4,se1));
14514 if (!std::strncmp(ss,
"exp(",4)) _cimg_mp_opcode1(mp_exp,compile(ss4,se1));
14515 if (!std::strncmp(ss,
"sqrt(",5)) _cimg_mp_opcode1(mp_sqrt,compile(ss5,se1));
14516 if (!std::strncmp(ss,
"sign(",5)) _cimg_mp_opcode1(mp_sign,compile(ss5,se1));
14517 if (!std::strncmp(ss,
"abs(",4)) _cimg_mp_opcode1(mp_abs,compile(ss4,se1));
14518 if (!std::strncmp(ss,
"atan2(",6)) {
14519 char *s1 = ss6;
while (s1<se2 && (*s1!=
',' || level[s1-expr._data]!=clevel1)) ++s1;
14520 _cimg_mp_opcode2(mp_atan2,compile(ss6,s1),compile(s1+1,se1));
14522 if (*ss==
'i' && *ss1==
'f' && *ss2==
'(') {
14523 char *s1 = ss3;
while (s1<se4 && (*s1!=
',' || level[s1-expr._data]!=clevel1)) ++s1;
14524 char *s2 = s1+1;
while (s2<se2 && (*s2!=
',' || level[s2-expr._data]!=clevel1)) ++s2;
14525 const unsigned int mem_cond = compile(ss3,s1), bp1 = code._width, mem_A = compile(s1+1,s2),
14526 bp2 = code._width, mem_B = compile(s2+1,se1);
14527 if (mempos>=mem._width) mem.
resize(-200,1,1,1,0);
14528 const unsigned int pos = mempos++;
14529 CImg<longT>::vector(_cimg_mp_enfunc(mp_if),pos,mem_cond,mem_A,mem_B,bp2-bp1,code._width-bp2).
14531 _cimg_mp_return(pos);
14533 if (!std::strncmp(ss,
"round(",6)) {
14534 unsigned int value = 0,
round = 1, direction = 0;
14535 char *s1 = ss6;
while (s1<se2 && (*s1!=
',' || level[s1-expr._data]!=clevel1)) ++s1;
14536 value = compile(ss6,s1==se2?++s1:s1);
14538 char *s2 = s1+1;
while (s2<se2 && (*s2!=
',' || level[s2-expr._data]!=clevel1)) ++s2;
14539 round = compile(s1+1,s2==se2?++s2:s2);
14540 if (s2<se1) direction = compile(s2+1,se1);
14542 _cimg_mp_opcode3(mp_round,value,
round,direction);
14544 if ((*ss==
'?' || *ss==
'u') && *ss1==
'(') {
14545 if (*ss2==
')') _cimg_mp_opcode2(mp_u,0,1);
14546 char *s1 = ss2;
while (s1<se1 && (*s1!=
',' || level[s1-expr._data]!=clevel1)) ++s1;
14547 if (s1<se1) _cimg_mp_opcode2(mp_u,compile(ss2,s1),compile(s1+1,se1));
14548 _cimg_mp_opcode2(mp_u,0,compile(ss2,s1));
14550 const bool is_relative = *ss==
'j';
14551 if ((*ss==
'i' || is_relative) && *ss1==
'(') {
14552 if (*ss2==
')') _cimg_mp_opcode0(mp_i);
14554 indx = is_relative?0:9, indy = is_relative?0:10,
14555 indz = is_relative?0:11, indc = is_relative?0:12,
14556 borders = 0, interpolation = 0;
14558 char *s1 = ss2;
while (s1<se2 && (*s1!=
',' || level[s1-expr._data]!=clevel1)) ++s1;
14559 indx = compile(ss2,s1==se2?++s1:s1);
14561 char *s2 = s1+1;
while (s2<se2 && (*s2!=
',' || level[s2-expr._data]!=clevel1)) ++s2;
14562 indy = compile(s1+1,s2==se2?++s2:s2);
14564 char *s3 = s2+1;
while (s3<se2 && (*s3!=
',' || level[s3-expr._data]!=clevel1)) ++s3;
14565 indz = compile(s2+1,s3==se2?++s3:s3);
14567 char *s4 = s3+1;
while (s4<se2 && (*s4!=
',' || level[s4-expr._data]!=clevel1)) ++s4;
14568 indc = compile(s3+1,s4==se2?++s4:s4);
14570 char *s5 = s4+1;
while (s5<se2 && (*s5!=
',' || level[s5-expr._data]!=clevel1)) ++s5;
14571 interpolation = compile(s4+1,s5==se2?++s5:s5);
14572 if (s5<se1) borders = compile(s5+1,se1);
14578 _cimg_mp_opcode6(is_relative?mp_jxyzc:mp_ixyzc,indx,indy,indz,indc,interpolation,borders);
14580 if (!std::strncmp(ss,
"min(",4) || !std::strncmp(ss,
"max(",4) ||
14581 !std::strncmp(ss,
"med(",4) || !std::strncmp(ss,
"kth(",4)) {
14583 if (mempos>=mem.
size()) mem.
resize(-200,1,1,1,0);
14584 const unsigned int pos = mempos++;
14585 CImg<longT>::vector(_cimg_mp_enfunc(*ss==
'k'?mp_kth:ss[1]==
'i'?mp_min:ss[1]==
'a'?mp_max:mp_med),pos).
14587 for (
char *s = ss4; s<se; ++s) {
14588 char *ns = s;
while (ns<se && (*ns!=
',' || level[ns-expr._data]!=clevel1) &&
14589 (*ns!=
')' || level[ns-expr._data]!=clevel)) ++ns;
14594 _cimg_mp_return(pos);
14596 if (!std::strncmp(ss,
"arg(",4)) {
14598 if (mempos>=mem.
size()) mem.
resize(-200,1,1,1,0);
14599 const unsigned int pos = mempos++;
14601 for (
char *s = ss4; s<se; ++s) {
14602 char *ns = s;
while (ns<se && (*ns!=
',' || level[ns-expr._data]!=clevel1) &&
14603 (*ns!=
')' || level[ns-expr._data]!=clevel)) ++ns;
14608 _cimg_mp_return(pos);
14610 if (!std::strncmp(ss,
"narg(",5)) {
14611 if (*ss5==
')') _cimg_mp_return(0);
14612 unsigned int nb_args = 0;
14613 for (
char *s = ss5; s<se; ++s) {
14614 char *ns = s;
while (ns<se && (*ns!=
',' || level[ns-expr._data]!=clevel1) &&
14615 (*ns!=
')' || level[ns-expr._data]!=clevel)) ++ns;
14618 if (nb_args==0 || nb_args==1) _cimg_mp_return(nb_args);
14619 if (mempos>=mem.
size()) mem.
resize(-200,1,1,1,0);
14620 const unsigned int pos = mempos++;
14621 mem[pos] = nb_args;
14622 _cimg_mp_return(pos);
14624 if (!std::strncmp(ss,
"isval(",6)) {
14625 char sep = 0, end = 0;
double val = 0;
14626 if (std::sscanf(ss6,
"%lf%c%c",&val,&sep,&end)==2 && sep==
')') _cimg_mp_return(1);
14627 _cimg_mp_return(0);
14629 if (!std::strncmp(ss,
"isnan(",6)) _cimg_mp_opcode1(mp_isnan,compile(ss6,se1));
14630 if (!std::strncmp(ss,
"isinf(",6)) _cimg_mp_opcode1(mp_isinf,compile(ss6,se1));
14631 if (!std::strncmp(ss,
"isint(",6)) _cimg_mp_opcode1(mp_isint,compile(ss6,se1));
14632 if (!std::strncmp(ss,
"isbool(",7)) _cimg_mp_opcode1(mp_isbool,compile(ss7,se1));
14633 if (!std::strncmp(ss,
"rol(",4) || !std::strncmp(ss,
"ror(",4)) {
14634 unsigned int value = 0, nb = 1;
14635 char *s1 = ss4;
while (s1<se2 && (*s1!=
',' || level[s1-expr._data]!=clevel1)) ++s1;
14636 value = compile(ss4,s1==se2?++s1:s1);
14638 char *s2 = s1+1;
while (s2<se2 && (*s2!=
',' || level[s2-expr._data]!=clevel1)) ++s2;
14639 nb = compile(s1+1,se1);
14641 _cimg_mp_opcode2(*ss2==
'l'?mp_rol:mp_ror,value,nb);
14644 if (!std::strncmp(ss,
"sinc(",5)) _cimg_mp_opcode1(mp_sinc,compile(ss5,se1));
14645 if (!std::strncmp(ss,
"int(",4)) _cimg_mp_opcode1(mp_int,compile(ss4,se1));
14649 CImg<charT> variable_name(ss,(
unsigned int)(se-ss+1));
14650 variable_name.
back() = 0;
14651 if (variable_name[1]) {
14652 cimglist_for(labelM,i)
if (!std::strcmp(variable_name,labelM[i])) _cimg_mp_return(labelMpos[i]);
14653 }
else if (label1pos[*variable_name]!=~0U) _cimg_mp_return(label1pos[*variable_name]);
14656 "CImg<%s>::%s(): Invalid item '%s' in specified expression '%s%s%s'.\n",
14658 variable_name._data,
14659 (ss-8)>expr._data?
"...":
"",
14660 (ss-8)>expr._data?ss-8:expr._data,
14661 se<&expr.
back()?
"...":
"");
14667 static double mp_u(_cimg_math_parser& mp) {
14668 return mp.mem[mp.opcode(2)] +
cimg::rand()*(mp.mem[mp.opcode(3)]-mp.mem[mp.opcode(2)]);
14670 static double mp_g(_cimg_math_parser& mp) {
14674 static double mp_i(_cimg_math_parser& mp) {
14675 return (
double)mp.reference.atXYZC((
int)mp.mem[9],(
int)mp.mem[10],(
int)mp.mem[11],(
int)mp.mem[12],0);
14677 static double mp_logical_and(_cimg_math_parser& mp) {
14678 const bool is_A = (bool)mp.mem[mp.opcode(2)];
14679 const CImg<longT> *
const pE = ++mp.p_code + mp.opcode(4);
14680 if (!is_A) { mp.p_code = pE - 1;
return 0; }
14681 const unsigned int mem_B = (
unsigned int)mp.opcode(3);
14682 for ( ; mp.p_code<pE; ++mp.p_code) {
14684 mp.opcode._data = op._data; mp.opcode._height = op._height;
14685 const unsigned int target = (
unsigned int)mp.opcode[1];
14686 mp.mem[target] = _cimg_mp_defunc(mp);
14689 return (
double)(bool)mp.mem[mem_B];
14691 static double mp_logical_or(_cimg_math_parser& mp) {
14692 const bool is_A = (bool)mp.mem[mp.opcode(2)];
14693 const CImg<longT> *
const pE = ++mp.p_code + mp.opcode(4);
14694 if (is_A) { mp.p_code = pE - 1;
return 1; }
14695 const unsigned int mem_B = (
unsigned int)mp.opcode(3);
14696 for ( ; mp.p_code<pE; ++mp.p_code) {
14698 mp.opcode._data = op._data; mp.opcode._height = op._height;
14699 const unsigned int target = (
unsigned int)mp.opcode[1];
14700 mp.mem[target] = _cimg_mp_defunc(mp);
14703 return (
double)(bool)mp.mem[mem_B];
14705 static double mp_infeq(_cimg_math_parser& mp) {
14706 return (
double)(mp.mem[mp.opcode(2)]<=mp.mem[mp.opcode(3)]);
14708 static double mp_supeq(_cimg_math_parser& mp) {
14709 return (
double)(mp.mem[mp.opcode(2)]>=mp.mem[mp.opcode(3)]);
14711 static double mp_noteq(_cimg_math_parser& mp) {
14712 return (
double)(mp.mem[mp.opcode(2)]!=mp.mem[mp.opcode(3)]);
14714 static double mp_eqeq(_cimg_math_parser& mp) {
14715 return (
double)(mp.mem[mp.opcode(2)]==mp.mem[mp.opcode(3)]);
14717 static double mp_inf(_cimg_math_parser& mp) {
14718 return (
double)(mp.mem[mp.opcode(2)]<mp.mem[mp.opcode(3)]);
14720 static double mp_sup(_cimg_math_parser& mp) {
14721 return (
double)(mp.mem[mp.opcode(2)]>mp.mem[mp.opcode(3)]);
14723 static double mp_add(_cimg_math_parser& mp) {
14724 return mp.mem[mp.opcode(2)] + mp.mem[mp.opcode(3)];
14726 static double mp_sub(_cimg_math_parser& mp) {
14727 return mp.mem[mp.opcode(2)] - mp.mem[mp.opcode(3)];
14729 static double mp_mul(_cimg_math_parser& mp) {
14730 const double A = mp.mem[mp.opcode(2)];
14731 const CImg<longT> *
const pE = ++mp.p_code + mp.opcode(4);
14732 if (!A) { mp.p_code = pE - 1;
return 0; }
14733 const unsigned int mem_B = (
unsigned int)mp.opcode(3);
14734 for ( ; mp.p_code<pE; ++mp.p_code) {
14736 mp.opcode._data = op._data; mp.opcode._height = op._height;
14737 const unsigned int target = (
unsigned int)mp.opcode[1];
14738 mp.mem[target] = _cimg_mp_defunc(mp);
14741 return A*(double)mp.mem[mem_B];
14743 static double mp_div(_cimg_math_parser& mp) {
14744 return mp.mem[mp.opcode(2)] / mp.mem[mp.opcode(3)];
14746 static double mp_minus(_cimg_math_parser& mp) {
14747 return -mp.mem[mp.opcode(2)];
14749 static double mp_not(_cimg_math_parser& mp) {
14750 return !mp.mem[mp.opcode(2)];
14752 static double mp_logical_not(_cimg_math_parser& mp) {
14753 return !mp.mem[mp.opcode(2)];
14755 static double mp_bitwise_not(_cimg_math_parser& mp) {
14756 return ~(
unsigned long)mp.mem[mp.opcode(2)];
14758 static double mp_modulo(_cimg_math_parser& mp) {
14759 return cimg::mod(mp.mem[mp.opcode(2)],mp.mem[mp.opcode(3)]);
14761 static double mp_bitwise_and(_cimg_math_parser& mp) {
14762 return ((
unsigned long)mp.mem[mp.opcode(2)] & (
unsigned long)mp.mem[mp.opcode(3)]);
14764 static double mp_bitwise_or(_cimg_math_parser& mp) {
14765 return ((
unsigned long)mp.mem[mp.opcode(2)] | (
unsigned long)mp.mem[mp.opcode(3)]);
14767 static double mp_pow(_cimg_math_parser& mp) {
14768 const double v = mp.mem[mp.opcode(2)], p = mp.mem[mp.opcode(3)];
14769 if (p==0)
return 1;
14770 if (p==0.5)
return std::sqrt(v);
14771 if (p==1)
return v;
14772 if (p==2)
return v*v;
14773 if (p==3)
return v*v*v;
14774 if (p==4)
return v*v*v*v;
14775 return std::pow(v,p);
14777 static double mp_sin(_cimg_math_parser& mp) {
14778 return std::sin(mp.mem[mp.opcode(2)]);
14780 static double mp_cos(_cimg_math_parser& mp) {
14781 return std::cos(mp.mem[mp.opcode(2)]);
14783 static double mp_tan(_cimg_math_parser& mp) {
14784 return std::tan(mp.mem[mp.opcode(2)]);
14786 static double mp_asin(_cimg_math_parser& mp) {
14787 return std::asin(mp.mem[mp.opcode(2)]);
14789 static double mp_acos(_cimg_math_parser& mp) {
14790 return std::acos(mp.mem[mp.opcode(2)]);
14792 static double mp_atan(_cimg_math_parser& mp) {
14793 return std::atan(mp.mem[mp.opcode(2)]);
14795 static double mp_sinh(_cimg_math_parser& mp) {
14796 return std::sinh(mp.mem[mp.opcode(2)]);
14798 static double mp_cosh(_cimg_math_parser& mp) {
14799 return std::cosh(mp.mem[mp.opcode(2)]);
14801 static double mp_tanh(_cimg_math_parser& mp) {
14802 return std::tanh(mp.mem[mp.opcode(2)]);
14804 static double mp_log10(_cimg_math_parser& mp) {
14805 return std::log10(mp.mem[mp.opcode(2)]);
14807 static double mp_log2(_cimg_math_parser& mp) {
14810 static double mp_log(_cimg_math_parser& mp) {
14811 return std::log(mp.mem[mp.opcode(2)]);
14813 static double mp_exp(_cimg_math_parser& mp) {
14814 return std::exp(mp.mem[mp.opcode(2)]);
14816 static double mp_sqrt(_cimg_math_parser& mp) {
14817 return std::sqrt(mp.mem[mp.opcode(2)]);
14819 static double mp_sign(_cimg_math_parser& mp) {
14822 static double mp_abs(_cimg_math_parser& mp) {
14823 return cimg::abs(mp.mem[mp.opcode(2)]);
14825 static double mp_atan2(_cimg_math_parser& mp) {
14826 return std::atan2(mp.mem[mp.opcode(2)],mp.mem[mp.opcode(3)]);
14828 static double mp_if(_cimg_math_parser& mp) {
14829 const bool is_cond = (bool)mp.mem[mp.opcode(2)];
14830 const unsigned int mem_A = (
unsigned int)mp.opcode(3), mem_B = (
unsigned int)mp.opcode(4);
14832 *
const pB = ++mp.p_code + mp.opcode(5),
14833 *
const pE = pB + mp.opcode(6);
14835 for ( ; mp.p_code<pB; ++mp.p_code) {
14837 mp.opcode._data = op._data; mp.opcode._height = op._height;
14838 const unsigned int target = (
unsigned int)mp.opcode[1];
14839 mp.mem[target] = _cimg_mp_defunc(mp);
14841 mp.p_code = pE - 1;
14842 return mp.mem[mem_A];
14844 for (mp.p_code = pB; mp.p_code<pE; ++mp.p_code) {
14846 mp.opcode._data = op._data; mp.opcode._height = op._height;
14847 const unsigned int target = (
unsigned int)mp.opcode[1];
14848 mp.mem[target] = _cimg_mp_defunc(mp);
14851 return mp.mem[mem_B];
14853 static double mp_round(_cimg_math_parser& mp) {
14854 return cimg::round(mp.mem[mp.opcode(2)],mp.mem[mp.opcode(3)],(int)mp.mem[mp.opcode(4)]);
14856 static double mp_ixyzc(_cimg_math_parser& mp) {
14857 const int i = (int)mp.mem[mp.opcode(6)], b = (int)mp.mem[mp.opcode(7)];
14859 if (b==2)
return (
double)mp.reference.atXYZC(
cimg::mod((
int)mp.mem[mp.opcode(2)],mp.reference.width()),
14860 cimg::mod((
int)mp.mem[mp.opcode(3)],mp.reference.height()),
14861 cimg::mod((
int)mp.mem[mp.opcode(4)],mp.reference.depth()),
14862 cimg::mod((
int)mp.mem[mp.opcode(5)],mp.reference.spectrum()));
14863 if (b==1)
return (
double)mp.reference.atXYZC((
int)mp.mem[mp.opcode(2)],
14864 (int)mp.mem[mp.opcode(3)],
14865 (int)mp.mem[mp.opcode(4)],
14866 (int)mp.mem[mp.opcode(5)]);
14867 return (
double)mp.reference.atXYZC((
int)mp.mem[mp.opcode(2)],
14868 (int)mp.mem[mp.opcode(3)],
14869 (int)mp.mem[mp.opcode(4)],
14870 (int)mp.mem[mp.opcode(5)],0);
14872 if (b==2)
return (
double)mp.reference.linear_atXYZC(
cimg::mod((
float)mp.mem[mp.opcode(2)],(float)mp.reference.width()),
14873 cimg::mod((
float)mp.mem[mp.opcode(3)],(float)mp.reference.height()),
14874 cimg::mod((
float)mp.mem[mp.opcode(4)],(float)mp.reference.depth()),
14875 cimg::mod((
float)mp.mem[mp.opcode(5)],(float)mp.reference.spectrum()));
14876 if (b==1)
return (
double)mp.reference.linear_atXYZC((
float)mp.mem[mp.opcode(2)],
14877 (float)mp.mem[mp.opcode(3)],
14878 (float)mp.mem[mp.opcode(4)],
14879 (float)mp.mem[mp.opcode(5)]);
14880 return (
double)mp.reference.linear_atXYZC((
float)mp.mem[mp.opcode(2)],
14881 (float)mp.mem[mp.opcode(3)],
14882 (float)mp.mem[mp.opcode(4)],
14883 (float)mp.mem[mp.opcode(5)],0);
14886 static double mp_jxyzc(_cimg_math_parser& mp) {
14887 const double x = mp.mem[9], y = mp.mem[10], z = mp.mem[11], c = mp.mem[12];
14888 const int i = (int)mp.mem[mp.opcode(6)], b = (int)mp.mem[mp.opcode(7)];
14890 if (b==2)
return (
double)mp.reference.atXYZC(
cimg::mod((
int)(x+mp.mem[mp.opcode(2)]),mp.reference.width()),
14891 cimg::mod((
int)(y+mp.mem[mp.opcode(3)]),mp.reference.height()),
14892 cimg::mod((
int)(z+mp.mem[mp.opcode(4)]),mp.reference.depth()),
14893 cimg::mod((
int)(c+mp.mem[mp.opcode(5)]),mp.reference.spectrum()));
14894 if (b==1)
return (
double)mp.reference.atXYZC((
int)(x+mp.mem[mp.opcode(2)]),
14895 (
int)(y+mp.mem[mp.opcode(3)]),
14896 (
int)(z+mp.mem[mp.opcode(4)]),
14897 (
int)(c+mp.mem[mp.opcode(5)]));
14898 return (
double)mp.reference.atXYZC((
int)(x+mp.mem[mp.opcode(2)]),
14899 (
int)(y+mp.mem[mp.opcode(3)]),
14900 (
int)(z+mp.mem[mp.opcode(4)]),
14901 (
int)(c+mp.mem[mp.opcode(5)]),0);
14903 if (b==2)
return (
double)mp.reference.linear_atXYZC(
cimg::mod((
float)(x+mp.mem[mp.opcode(2)]),(
float)mp.reference.width()),
14904 cimg::mod((
float)(y+mp.mem[mp.opcode(3)]),(
float)mp.reference.height()),
14905 cimg::mod((
float)(z+mp.mem[mp.opcode(4)]),(
float)mp.reference.depth()),
14906 cimg::mod((
float)(c+mp.mem[mp.opcode(5)]),(
float)mp.reference.spectrum()));
14907 if (b==1)
return (
double)mp.reference.linear_atXYZC((
float)(x+mp.mem[mp.opcode(2)]),
14908 (
float)(y+mp.mem[mp.opcode(3)]),
14909 (
float)(z+mp.mem[mp.opcode(4)]),
14910 (
float)(c+mp.mem[mp.opcode(5)]));
14911 return (
double)mp.reference.linear_atXYZC((
float)(x+mp.mem[mp.opcode(2)]),
14912 (
float)(y+mp.mem[mp.opcode(3)]),
14913 (
float)(z+mp.mem[mp.opcode(4)]),
14914 (
float)(c+mp.mem[mp.opcode(5)]),0);
14917 static double mp_min(_cimg_math_parser& mp) {
14918 double val = mp.mem[mp.opcode(2)];
14919 for (
unsigned int i = 3; i<mp.opcode._height; ++i) val =
cimg::min(val,mp.mem[mp.opcode(i)]);
14922 static double mp_max(_cimg_math_parser& mp) {
14923 double val = mp.mem[mp.opcode(2)];
14924 for (
unsigned int i = 3; i<mp.opcode._height; ++i) val =
cimg::max(val,mp.mem[mp.opcode(i)]);
14927 static double mp_med(_cimg_math_parser& mp) {
14929 double *p = values.
data();
14930 for (
unsigned int i = 2; i<mp.opcode._height; ++i) *(p++) = mp.mem[mp.opcode(i)];
14933 static double mp_kth(_cimg_math_parser& mp) {
14935 double *p = values.
data();
14936 for (
unsigned int i = 3; i<mp.opcode._height; ++i) *(p++) = mp.mem[mp.opcode(i)];
14937 int ind = (int)
cimg::round(mp.mem[mp.opcode(2)]);
14938 if (ind<0) ind+=1+values.
width();
14942 static double mp_isnan(_cimg_math_parser& mp) {
14943 const double val = mp.mem[mp.opcode(2)];
14946 static double mp_isinf(_cimg_math_parser& mp) {
14947 const double val = mp.mem[mp.opcode(2)];
14950 static double mp_isint(_cimg_math_parser& mp) {
14951 const double val = mp.mem[mp.opcode(2)];
14952 return (
double)(
cimg::mod(val,1.0)==0);
14954 static double mp_isbool(_cimg_math_parser& mp) {
14955 const double val = mp.mem[mp.opcode(2)];
14956 return (val==0.0 || val==1.0);
14958 static double mp_rol(_cimg_math_parser& mp) {
14959 return cimg::rol(mp.mem[mp.opcode(2)],(
unsigned int)mp.mem[mp.opcode(3)]);
14961 static double mp_ror(_cimg_math_parser& mp) {
14962 return cimg::ror(mp.mem[mp.opcode(2)],(
unsigned int)mp.mem[mp.opcode(3)]);
14964 static double mp_lsl(_cimg_math_parser& mp) {
14965 return (
long)mp.mem[mp.opcode(2)]<<(
unsigned int)mp.mem[mp.opcode(3)];
14967 static double mp_lsr(_cimg_math_parser& mp) {
14968 return (
long)mp.mem[mp.opcode(2)]>>(
unsigned int)mp.mem[mp.opcode(3)];
14970 static double mp_sinc(_cimg_math_parser& mp) {
14973 static double mp_im(_cimg_math_parser& mp) {
14974 if (!mp.reference_stats) mp.reference.get_stats().move_to(mp.reference_stats);
14975 return mp.reference_stats?mp.reference_stats[0]:0;
14977 static double mp_iM(_cimg_math_parser& mp) {
14978 if (!mp.reference_stats) mp.reference.get_stats().move_to(mp.reference_stats);
14979 return mp.reference_stats?mp.reference_stats[1]:0;
14981 static double mp_ia(_cimg_math_parser& mp) {
14982 if (!mp.reference_stats) mp.reference.get_stats().move_to(mp.reference_stats);
14983 return mp.reference_stats?mp.reference_stats[2]:0;
14985 static double mp_iv(_cimg_math_parser& mp) {
14986 if (!mp.reference_stats) mp.reference.get_stats().move_to(mp.reference_stats);
14987 return mp.reference_stats?mp.reference_stats[3]:0;
14989 static double mp_xm(_cimg_math_parser& mp) {
14990 if (!mp.reference_stats) mp.reference.get_stats().move_to(mp.reference_stats);
14991 return mp.reference_stats?mp.reference_stats[4]:0;
14993 static double mp_ym(_cimg_math_parser& mp) {
14994 if (!mp.reference_stats) mp.reference.get_stats().move_to(mp.reference_stats);
14995 return mp.reference_stats?mp.reference_stats[5]:0;
14997 static double mp_zm(_cimg_math_parser& mp) {
14998 if (!mp.reference_stats) mp.reference.get_stats().move_to(mp.reference_stats);
14999 return mp.reference_stats?mp.reference_stats[6]:0;
15001 static double mp_cm(_cimg_math_parser& mp) {
15002 if (!mp.reference_stats) mp.reference.get_stats().move_to(mp.reference_stats);
15003 return mp.reference_stats?mp.reference_stats[7]:0;
15005 static double mp_xM(_cimg_math_parser& mp) {
15006 if (!mp.reference_stats) mp.reference.get_stats().move_to(mp.reference_stats);
15007 return mp.reference_stats?mp.reference_stats[8]:0;
15009 static double mp_yM(_cimg_math_parser& mp) {
15010 if (!mp.reference_stats) mp.reference.get_stats().move_to(mp.reference_stats);
15011 return mp.reference_stats?mp.reference_stats[9]:0;
15013 static double mp_zM(_cimg_math_parser& mp) {
15014 if (!mp.reference_stats) mp.reference.get_stats().move_to(mp.reference_stats);
15015 return mp.reference_stats?mp.reference_stats[10]:0;
15017 static double mp_cM(_cimg_math_parser& mp) {
15018 if (!mp.reference_stats) mp.reference.get_stats().move_to(mp.reference_stats);
15019 return mp.reference_stats?mp.reference_stats[11]:0;
15021 static double mp_arg(_cimg_math_parser& mp) {
15022 const int _ind = (int)mp.mem[mp.opcode(2)];
15023 const unsigned int nb_args = mp.opcode._height-2, ind = _ind<0?_ind+nb_args:(
unsigned int)_ind;
15024 if (ind>=nb_args)
return 0;
15025 return mp.mem[mp.opcode(ind+2)];
15027 static double mp_int(_cimg_math_parser& mp) {
15028 return (
double)(long)mp.mem[mp.opcode(2)];
15030 static double mp_ioff(_cimg_math_parser& mp) {
15031 const unsigned long off = (
unsigned long)mp.mem[mp.opcode(2)];
15032 if (off>=mp.reference.size())
return 0;
15033 return (
double)mp.reference[off];
15035 static double mp_joff(_cimg_math_parser& mp) {
15036 const int x = (int)mp.mem[9], y = (
int)mp.mem[10], z = (int)mp.mem[11], c = (
int)mp.mem[12];
15037 const unsigned long off = mp.reference.offset(x,y,z,c) + (
unsigned long)(mp.mem[mp.opcode(2)]);
15038 if (off>=mp.reference.size())
return 0;
15039 return (
double)mp.reference[off];
15043 double operator()(
const double x,
const double y,
const double z,
const double c) {
15044 if (!mem)
return 0;
15045 mem[9] = x; mem[10] = y; mem[11] = z; mem[12] = c;
15046 opcode._is_shared =
true; opcode._width = opcode._depth = opcode._spectrum = 1;
15048 for (p_code = code._data; p_code<code.
end(); ++p_code) {
15051 opcode._data = op._data; opcode._height = op._height;
15052 const unsigned int target = (
unsigned int)opcode[1];
15053 mem[target] = _cimg_mp_defunc(*
this);
15055 return mem[result];
15074 #ifdef cimg_use_openmp
15075 #pragma omp parallel for if (size()>=524288)
15077 cimg_rof(*
this,ptrd,T) {
const T val = *ptrd; *ptrd = (T)(val*val); };
15101 #ifdef cimg_use_openmp
15102 #pragma omp parallel for if (size()>=8192)
15104 cimg_rof(*
this,ptrd,T) *ptrd = (T)std::sqrt((
double)*ptrd);
15122 #ifdef cimg_use_openmp
15123 #pragma omp parallel for if (size()>=4096)
15125 cimg_rof(*
this,ptrd,T) *ptrd = (T)std::exp((
double)*ptrd);
15144 #ifdef cimg_use_openmp
15145 #pragma omp parallel for if (size()>=262144)
15147 cimg_rof(*
this,ptrd,T) *ptrd = (T)std::log((
double)*ptrd);
15166 #ifdef cimg_use_openmp
15167 #pragma omp parallel for if (size()>=4096)
15169 cimg_rof(*
this,ptrd,T) *ptrd = (T)
cimg::log2((
double)*ptrd);
15188 #ifdef cimg_use_openmp
15189 #pragma omp parallel for if (size()>=4096)
15191 cimg_rof(*
this,ptrd,T) *ptrd = (T)std::log10((
double)*ptrd);
15209 #ifdef cimg_use_openmp
15210 #pragma omp parallel for if (size()>=524288)
15212 cimg_rof(*
this,ptrd,T) *ptrd =
cimg::abs(*ptrd);
15235 #ifdef cimg_use_openmp
15236 #pragma omp parallel for if (size()>=32768)
15238 cimg_rof(*
this,ptrd,T) *ptrd =
cimg::sign(*ptrd);
15257 #ifdef cimg_use_openmp
15258 #pragma omp parallel for if (size()>=8192)
15260 cimg_rof(*
this,ptrd,T) *ptrd = (T)std::cos((
double)*ptrd);
15279 #ifdef cimg_use_openmp
15280 #pragma omp parallel for if (size()>=8192)
15282 cimg_rof(*
this,ptrd,T) *ptrd = (T)std::sin((
double)*ptrd);
15302 #ifdef cimg_use_openmp
15303 #pragma omp parallel for if (size()>=2048)
15305 cimg_rof(*
this,ptrd,T) *ptrd = (T)
cimg::sinc((
double)*ptrd);
15324 #ifdef cimg_use_openmp
15325 #pragma omp parallel for if (size()>=2048)
15327 cimg_rof(*
this,ptrd,T) *ptrd = (T)std::tan((
double)*ptrd);
15346 #ifdef cimg_use_openmp
15347 #pragma omp parallel for if (size()>=2048)
15349 cimg_rof(*
this,ptrd,T) *ptrd = (T)std::cosh((
double)*ptrd);
15368 #ifdef cimg_use_openmp
15369 #pragma omp parallel for if (size()>=2048)
15371 cimg_rof(*
this,ptrd,T) *ptrd = (T)std::sinh((
double)*ptrd);
15390 #ifdef cimg_use_openmp
15391 #pragma omp parallel for if (size()>=2048)
15393 cimg_rof(*
this,ptrd,T) *ptrd = (T)std::tanh((
double)*ptrd);
15412 #ifdef cimg_use_openmp
15413 #pragma omp parallel for if (size()>=8192)
15415 cimg_rof(*
this,ptrd,T) *ptrd = (T)std::acos((
double)*ptrd);
15434 #ifdef cimg_use_openmp
15435 #pragma omp parallel for if (size()>=8192)
15437 cimg_rof(*
this,ptrd,T) *ptrd = (T)std::asin((
double)*ptrd);
15456 #ifdef cimg_use_openmp
15457 #pragma omp parallel for if (size()>=8192)
15459 cimg_rof(*
this,ptrd,T) *ptrd = (T)std::atan((
double)*ptrd);
15485 template<
typename t>
15487 const unsigned long siz =
size(), isiz = img.size();
15490 T *ptrd = _data, *
const ptre = _data + siz;
15491 if (siz>isiz)
for (
unsigned long n = siz/isiz; n; --n)
15492 for (
const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
15493 *ptrd = (T)std::atan2((
double)*ptrd,(double)*(ptrs++));
15494 for (
const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)std::atan2((
double)*ptrd,(double)*(ptrs++));
15500 template<
typename t>
15522 template<
typename t>
15524 const unsigned long siz =
size(), isiz = img.size();
15527 T *ptrd = _data, *
const ptre = _data + siz;
15528 if (siz>isiz)
for (
unsigned long n = siz/isiz; n; --n)
15529 for (
const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
15530 *ptrd = (T)(*ptrd * *(ptrs++));
15531 for (
const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)(*ptrd * *(ptrs++));
15537 template<
typename t>
15546 template<
typename t>
15548 const unsigned long siz =
size(), isiz = img.size();
15551 T *ptrd = _data, *
const ptre = _data + siz;
15552 if (siz>isiz)
for (
unsigned long n = siz/isiz; n; --n)
15553 for (
const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
15554 *ptrd = (T)(*ptrd / *(ptrs++));
15555 for (
const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)(*ptrd / *(ptrs++));
15561 template<
typename t>
15585 #ifdef cimg_use_openmp
15586 #pragma omp parallel for if (size()>=32768)
15588 cimg_rof(*
this,ptrd,T) {
const T val = *ptrd; *ptrd = (T)(1.0/(val*val*val*val)); }
15592 #ifdef cimg_use_openmp
15593 #pragma omp parallel for if (size()>=32768)
15595 cimg_rof(*
this,ptrd,T) {
const T val = *ptrd; *ptrd = (T)(1.0/(val*val*val)); }
15599 #ifdef cimg_use_openmp
15600 #pragma omp parallel for if (size()>=32768)
15602 cimg_rof(*
this,ptrd,T) {
const T val = *ptrd; *ptrd = (T)(1.0/(val*val)); }
15606 #ifdef cimg_use_openmp
15607 #pragma omp parallel for if (size()>=32768)
15609 cimg_rof(*
this,ptrd,T) {
const T val = *ptrd; *ptrd = (T)(1.0/val); }
15613 #ifdef cimg_use_openmp
15614 #pragma omp parallel for if (size()>=8192)
15616 cimg_rof(*
this,ptrd,T) {
const T val = *ptrd; *ptrd = (T)(1/std::sqrt((
double)val)); }
15619 if (p==0)
return fill(1);
15620 if (p==0.5)
return sqrt();
15621 if (p==1)
return *
this;
15622 if (p==2)
return sqr();
15624 #ifdef cimg_use_openmp
15625 #pragma omp parallel for if (size()>=262144)
15627 cimg_rof(*
this,ptrd,T) {
const T val = *ptrd; *ptrd = val*val*val; }
15631 #ifdef cimg_use_openmp
15632 #pragma omp parallel for if (size()>=131072)
15634 cimg_rof(*
this,ptrd,T) {
const T val = *ptrd; *ptrd = val*val*val*val; }
15637 #ifdef cimg_use_openmp
15638 #pragma omp parallel for if (size()>=1024)
15640 cimg_rof(*
this,ptrd,T) *ptrd = (T)std::pow((
double)*ptrd,p);
15658 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
15659 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"pow");
15660 T *ptrd = *expression==
'<'?
end()-1:_data;
15661 if (*expression==
'<') cimg_rofXYZC(*
this,x,y,z,c) { *ptrd = (T)std::pow((
double)*ptrd,mp(x,y,z,c)); --ptrd; }
15662 else if (*expression==
'>')
15663 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)std::pow((
double)*ptrd,mp(x,y,z,c)); ++ptrd; }
15665 #ifdef cimg_use_openmp
15666 if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
15667 #pragma omp parallel
15669 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
15670 #pragma omp for collapse(3)
15671 cimg_forYZC(*
this,y,z,c) {
15672 T *ptrd =
data(0,y,z,c);
15673 cimg_forX(*
this,x) { *ptrd = (T)std::pow((
double)*ptrd,lmp(x,y,z,c)); ++ptrd; }
15678 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)std::pow((
double)*ptrd,mp(x,y,z,c)); ++ptrd; }
15683 values.fill(expression,
true);
15686 values.load(expression);
15703 template<
typename t>
15705 const unsigned long siz =
size(), isiz = img.size();
15708 T *ptrd = _data, *
const ptre = _data + siz;
15709 if (siz>isiz)
for (
unsigned long n = siz/isiz; n; --n)
15710 for (
const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
15711 *ptrd = (T)std::pow((
double)*ptrd,(double)(*(ptrs++)));
15712 for (
const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)std::pow((
double)*ptrd,(double)(*(ptrs++)));
15718 template<
typename t>
15729 #ifdef cimg_use_openmp
15730 #pragma omp parallel for if (size()>=32768)
15732 cimg_rof(*
this,ptrd,T) *ptrd = (T)
cimg::rol(*ptrd,n);
15738 return (+*
this).
rol(n);
15750 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
15751 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"rol");
15752 T *ptrd = *expression==
'<'?
end()-1:_data;
15753 if (*expression==
'<')
15754 cimg_rofXYZC(*
this,x,y,z,c) { *ptrd = (T)
cimg::rol(*ptrd,(
unsigned int)mp(x,y,z,c)); --ptrd; }
15755 else if (*expression==
'>')
15756 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)
cimg::rol(*ptrd,(
unsigned int)mp(x,y,z,c)); ++ptrd; }
15758 #ifdef cimg_use_openmp
15759 if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
15760 #pragma omp parallel
15762 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
15763 #pragma omp for collapse(3)
15764 cimg_forYZC(*
this,y,z,c) {
15765 T *ptrd =
data(0,y,z,c);
15766 cimg_forX(*
this,x) { *ptrd = (T)
cimg::rol(*ptrd,(
unsigned int)lmp(x,y,z,c)); ++ptrd; }
15771 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)
cimg::rol(*ptrd,(
unsigned int)mp(x,y,z,c)); ++ptrd; }
15776 values.fill(expression,
true);
15779 values.load(expression);
15789 return (+*
this).
rol(expression);
15796 template<
typename t>
15798 const unsigned long siz =
size(), isiz = img.size();
15801 T *ptrd = _data, *
const ptre = _data + siz;
15802 if (siz>isiz)
for (
unsigned long n = siz/isiz; n; --n)
15803 for (
const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
15804 *ptrd = (T)
cimg::rol(*ptrd,(
unsigned int)(*(ptrs++)));
15805 for (
const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)
cimg::rol(*ptrd,(
unsigned int)(*(ptrs++)));
15811 template<
typename t>
15813 return (+*
this).
rol(img);
15822 #ifdef cimg_use_openmp
15823 #pragma omp parallel for if (size()>=32768)
15825 cimg_rof(*
this,ptrd,T) *ptrd = (T)
cimg::ror(*ptrd,n);
15831 return (+*
this).
ror(n);
15843 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
15844 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"ror");
15845 T *ptrd = *expression==
'<'?
end()-1:_data;
15846 if (*expression==
'<')
15847 cimg_rofXYZC(*
this,x,y,z,c) { *ptrd = (T)
cimg::ror(*ptrd,(
unsigned int)mp(x,y,z,c)); --ptrd; }
15848 else if (*expression==
'>')
15849 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)
cimg::ror(*ptrd,(
unsigned int)mp(x,y,z,c)); ++ptrd; }
15851 #ifdef cimg_use_openmp
15852 if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
15853 #pragma omp parallel
15855 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
15856 #pragma omp for collapse(3)
15857 cimg_forYZC(*
this,y,z,c) {
15858 T *ptrd =
data(0,y,z,c);
15859 cimg_forX(*
this,x) { *ptrd = (T)
cimg::ror(*ptrd,(
unsigned int)lmp(x,y,z,c)); ++ptrd; }
15864 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)
cimg::ror(*ptrd,(
unsigned int)mp(x,y,z,c)); ++ptrd; }
15869 values.fill(expression,
true);
15872 values.load(expression);
15882 return (+*
this).
ror(expression);
15889 template<
typename t>
15891 const unsigned long siz =
size(), isiz = img.size();
15894 T *ptrd = _data, *
const ptre = _data + siz;
15895 if (siz>isiz)
for (
unsigned long n = siz/isiz; n; --n)
15896 for (
const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
15897 *ptrd = (T)
cimg::ror(*ptrd,(
unsigned int)(*(ptrs++)));
15898 for (
const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)
cimg::ror(*ptrd,(
unsigned int)(*(ptrs++)));
15904 template<
typename t>
15906 return (+*
this).
ror(img);
15917 #ifdef cimg_use_openmp
15918 #pragma omp parallel for if (size()>=65536)
15920 cimg_rof(*
this,ptrd,T) *ptrd =
cimg::min(*ptrd,val);
15926 return (+*
this).
min(val);
15935 template<
typename t>
15937 const unsigned long siz =
size(), isiz = img.size();
15940 T *ptrd = _data, *
const ptre = _data + siz;
15941 if (siz>isiz)
for (
unsigned long n = siz/isiz; n; --n)
15942 for (
const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
15944 for (
const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd =
cimg::min((T)*(ptrs++),*ptrd);
15950 template<
typename t>
15966 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
15967 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"min");
15968 T *ptrd = *expression==
'<'?
end()-1:_data;
15969 if (*expression==
'<') cimg_rofXYZC(*
this,x,y,z,c) { *ptrd = (T)
cimg::min(*ptrd,(T)mp(x,y,z,c)); --ptrd; }
15970 else if (*expression==
'>') cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)
cimg::min(*ptrd,(T)mp(x,y,z,c)); ++ptrd; }
15972 #ifdef cimg_use_openmp
15973 if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
15974 #pragma omp parallel
15976 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
15977 #pragma omp for collapse(3)
15978 cimg_forYZC(*
this,y,z,c) {
15979 T *ptrd =
data(0,y,z,c);
15980 cimg_forX(*
this,x) { *ptrd = (T)
cimg::min(*ptrd,(T)lmp(x,y,z,c)); ++ptrd; }
15985 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)
cimg::min(*ptrd,(T)mp(x,y,z,c)); ++ptrd; }
15988 CImg<T> values(_width,_height,_depth,_spectrum);
15990 values.fill(expression,
true);
15993 values.load(expression);
16014 #ifdef cimg_use_openmp
16015 #pragma omp parallel for if (size()>=65536)
16017 cimg_rof(*
this,ptrd,T) *ptrd =
cimg::max(*ptrd,val);
16023 return (+*
this).
max(val);
16032 template<
typename t>
16034 const unsigned long siz =
size(), isiz = img.size();
16037 T *ptrd = _data, *
const ptre = _data + siz;
16038 if (siz>isiz)
for (
unsigned long n = siz/isiz; n; --n)
16039 for (
const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
16041 for (
const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd =
cimg::max((T)*(ptrs++),*ptrd);
16047 template<
typename t>
16063 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
16064 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"max");
16065 T *ptrd = *expression==
'<'?
end()-1:_data;
16066 if (*expression==
'<') cimg_rofXYZC(*
this,x,y,z,c) { *ptrd = (T)
cimg::max(*ptrd,(T)mp(x,y,z,c)); --ptrd; }
16067 else if (*expression==
'>') cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)
cimg::max(*ptrd,(T)mp(x,y,z,c)); ++ptrd; }
16069 #ifdef cimg_use_openmp
16070 if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
16071 #pragma omp parallel
16073 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
16074 #pragma omp for collapse(3)
16075 cimg_forYZC(*
this,y,z,c) {
16076 T *ptrd =
data(0,y,z,c);
16077 cimg_forX(*
this,x) { *ptrd = (T)
cimg::max(*ptrd,(T)lmp(x,y,z,c)); ++ptrd; }
16082 cimg_forXYZC(*
this,x,y,z,c) { *ptrd = (T)
cimg::max(*ptrd,(T)mp(x,y,z,c)); ++ptrd; }
16085 CImg<T> values(_width,_height,_depth,_spectrum);
16087 values.fill(expression,
true);
16090 values.load(expression);
16109 "min(): Empty instance.",
16111 T *ptr_min = _data;
16112 T min_value = *ptr_min;
16113 cimg_for(*
this,ptrs,T)
if (*ptrs<min_value) min_value = *(ptr_min=ptrs);
16121 "min(): Empty instance.",
16123 const T *ptr_min = _data;
16124 T min_value = *ptr_min;
16125 cimg_for(*
this,ptrs,T)
if (*ptrs<min_value) min_value = *(ptr_min=ptrs);
16135 "max(): Empty instance.",
16137 T *ptr_max = _data;
16138 T max_value = *ptr_max;
16139 cimg_for(*
this,ptrs,T)
if (*ptrs>max_value) max_value = *(ptr_max=ptrs);
16147 "max(): Empty instance.",
16149 const T *ptr_max = _data;
16150 T max_value = *ptr_max;
16151 cimg_for(*
this,ptrs,T)
if (*ptrs>max_value) max_value = *(ptr_max=ptrs);
16159 template<
typename t>
16163 "min_max(): Empty instance.",
16165 T *ptr_min = _data;
16166 T min_value = *ptr_min, max_value = min_value;
16167 cimg_for(*
this,ptrs,T) {
16168 const T val = *ptrs;
16169 if (val<min_value) { min_value = val; ptr_min = ptrs; }
16170 if (val>max_value) max_value = val;
16172 max_val = (t)max_value;
16177 template<
typename t>
16181 "min_max(): Empty instance.",
16183 const T *ptr_min = _data;
16184 T min_value = *ptr_min, max_value = min_value;
16185 cimg_for(*
this,ptrs,T) {
16186 const T val = *ptrs;
16187 if (val<min_value) { min_value = val; ptr_min = ptrs; }
16188 if (val>max_value) max_value = val;
16190 max_val = (t)max_value;
16198 template<
typename t>
16202 "max_min(): Empty instance.",
16204 T *ptr_max = _data;
16205 T max_value = *ptr_max, min_value = max_value;
16206 cimg_for(*
this,ptrs,T) {
16207 const T val = *ptrs;
16208 if (val>max_value) { max_value = val; ptr_max = ptrs; }
16209 if (val<min_value) min_value = val;
16211 min_val = (t)min_value;
16216 template<
typename t>
16220 "max_min(): Empty instance.",
16222 const T *ptr_max = _data;
16223 T max_value = *ptr_max, min_value = max_value;
16224 cimg_for(*
this,ptrs,T) {
16225 const T val = *ptrs;
16226 if (val>max_value) { max_value = val; ptr_max = ptrs; }
16227 if (val<min_value) min_value = val;
16229 min_val = (t)min_value;
16240 "kth_smallest(): Empty instance.",
16243 unsigned int l = 0, ir =
size() - 1;
16246 if (ir==l+1 && arr[ir]<arr[l])
cimg::swap(arr[l],arr[ir]);
16249 const unsigned int mid = (l + ir)>>1;
16251 if (arr[l]>arr[ir])
cimg::swap(arr[l],arr[ir]);
16252 if (arr[l+1]>arr[ir])
cimg::swap(arr[l+1],arr[ir]);
16253 if (arr[l]>arr[l+1])
cimg::swap(arr[l],arr[l+1]);
16254 unsigned int i = l + 1, j = ir;
16255 const T pivot = arr[l+1];
16257 do ++i;
while (arr[i]<pivot);
16258 do --j;
while (arr[j]>pivot);
16264 if (j>=k) ir = j - 1;
16276 "median(): Empty instance.",
16278 const unsigned int s =
size();
16289 "sum(): Empty instance.",
16292 cimg_for(*
this,ptrs,T) res+=(Tdouble)*ptrs;
16302 "mean(): Empty instance.",
16305 cimg_for(*
this,ptrs,T) res+=(Tdouble)*ptrs;
16320 Tdouble
variance(
const unsigned int variance_method=1)
const {
16330 template<
typename t>
16334 "variance_mean(): Empty instance.",
16337 Tdouble
variance = 0, average = 0;
16338 const unsigned long siz =
size();
16339 switch (variance_method) {
16341 Tdouble S = 0, S2 = 0;
16342 cimg_for(*
this,ptrs,T) {
const Tdouble val = (Tdouble)*ptrs; S+=val; S2+=val*val; }
16343 variance = (S2 - S*S/siz)/siz;
16347 Tdouble S = 0, S2 = 0;
16348 cimg_for(*
this,ptrs,T) {
const Tdouble val = (Tdouble)*ptrs; S+=val; S2+=val*val; }
16349 variance = siz>1?(S2 - S*S/siz)/(siz - 1):0;
16355 const unsigned long siz2 = siz>>1;
16356 const Tdouble med_i = (double)buf[siz2];
16357 cimg_for(buf,ptrs,Tfloat) {
16358 const Tdouble val = (Tdouble)*ptrs; *ptrs = (Tfloat)
cimg::abs(val - med_i); average+=val;
16361 const Tdouble sig = (Tdouble)(1.4828*buf[siz2]);
16362 variance = sig*sig;
16366 const unsigned long siz2 = siz>>1;
16367 cimg_for(buf,ptrs,Tfloat) {
16368 const Tdouble val = (Tdouble)*ptrs; (*ptrs)=(Tfloat)((*ptrs)*val); average+=val;
16372 const Tfloat *ptrs = buf._data;
16373 for (
unsigned long j = 0; j<siz2; ++j) a+=(Tdouble)*(ptrs++);
16374 const Tdouble sig = (Tdouble)(2.6477*std::sqrt(a/siz2));
16375 variance = sig*sig;
16378 mean = (t)(average/siz);
16379 return variance>0?variance:0;
16394 "variance_noise(): Empty instance.",
16397 const unsigned long siz =
size();
16398 if (!siz || !_data)
return 0;
16399 if (variance_method>1) {
16402 const Tdouble cste = 1.0/std::sqrt(20.0);
16403 #ifdef cimg_use_openmp
16404 #pragma omp parallel for if (_width*_height>=262144 && _spectrum>=2)
16406 cimg_forC(*
this,c) {
16408 cimg_for3x3(*
this,x,y,0,c,I,T) {
16409 tmp(x,y,c) = cste*((Tdouble)Inc + (Tdouble)Ipc + (Tdouble)Icn +
16410 (Tdouble)Icp - 4*(Tdouble)Icc);
16414 const Tdouble cste = 1.0/std::sqrt(42.0);
16415 #ifdef cimg_use_openmp
16416 #pragma omp parallel for if (_width*_height*_depth>=262144 && _spectrum>=2)
16418 cimg_forC(*
this,c) {
16420 cimg_for3x3x3(*
this,x,y,z,c,I,T) {
16421 tmp(x,y,z,c) = cste*(
16422 (Tdouble)Incc + (Tdouble)Ipcc + (Tdouble)Icnc + (Tdouble)Icpc +
16423 (Tdouble)Iccn + (Tdouble)Iccp - 6*(Tdouble)Iccc);
16427 return tmp.
variance(variance_method);
16431 Tdouble
variance = 0, S = 0, S2 = 0;
16433 const Tdouble cste = 1.0/std::sqrt(20.0);
16435 cimg_forC(*
this,c) cimg_for3x3(*
this,x,y,0,c,I,T) {
16436 const Tdouble val = cste*((Tdouble)Inc + (Tdouble)Ipc +
16437 (Tdouble)Icn + (Tdouble)Icp - 4*(Tdouble)Icc);
16438 S+=val; S2+=val*val;
16441 const Tdouble cste = 1.0/std::sqrt(42.0);
16443 cimg_forC(*
this,c) cimg_for3x3x3(*
this,x,y,z,c,I,T) {
16444 const Tdouble val = cste *
16445 ((Tdouble)Incc + (Tdouble)Ipcc + (Tdouble)Icnc +
16447 (Tdouble)Iccn + (Tdouble)Iccp - 6*(Tdouble)Iccc);
16448 S+=val; S2+=val*val;
16451 if (variance_method) variance = siz>1?(S2 - S*S/siz)/(siz - 1):0;
16452 else variance = (S2 - S*S/siz)/siz;
16453 return variance>0?variance:0;
16460 template<
typename t>
16462 if (img.size()!=
size())
16464 "MSE(): Instance and specified image (%u,%u,%u,%u,%p) have different dimensions.",
16466 img._width,img._height,img._depth,img._spectrum,img._data);
16468 const t* ptr2 = img._data;
16469 cimg_for(*
this,ptr1,T) {
16470 const Tdouble diff = (Tdouble)*ptr1 - (Tdouble)*(ptr2++);
16473 const unsigned long siz = img.size();
16474 if (siz) vMSE/=siz;
16483 template<
typename t>
16485 const Tdouble vMSE = (Tdouble)std::sqrt(
MSE(img));
16497 double eval(
const char *
const expression,
16498 const double x=0,
const double y=0,
const double z=0,
const double c=0)
const {
16499 if (!expression)
return 0;
16500 return _cimg_math_parser(*
this,expression,
"eval")(x,y,z,c);
16508 template<
typename t>
16511 if (!expression)
return res.
fill(0);
16512 _cimg_math_parser mp(*
this,expression,
"eval");
16513 #ifdef cimg_use_openmp
16514 #pragma omp parallel if (res._height>=512 && std::strlen(expression)>=6)
16516 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
16518 for (
unsigned int i = 0; i<res._height; ++i) {
16519 const unsigned int i4 = 4*i;
16520 const double x = (double)xyzc[i4], y = (
double)xyzc[i4+1], z = (double)xyzc[i4+2], c = (
double)xyzc[i4+3];
16521 res[i] = lmp(x,y,z,c);
16525 const t *ps = xyzc._data;
16526 cimg_for(res,pd,
double) {
16527 const double x = (double)*(ps++), y = (double)*(ps++), z = (double)*(ps++), c = (double)*(ps++);
16541 const unsigned long siz =
size();
16542 const T *
const odata = _data;
16543 const T *pm = odata, *pM = odata;
16544 Tdouble S = 0, S2 = 0;
16546 cimg_for(*
this,ptrs,T) {
16547 const T val = *ptrs;
16548 const Tdouble _val = (Tdouble)val;
16549 if (val<m) { m = val; pm = ptrs; }
16550 if (val>M) { M = val; pM = ptrs; }
16555 mean_value = S/siz,
16556 _variance_value = variance_method==0?(S2 - S*S/siz)/siz:
16557 (variance_method==1?(siz>1?(S2 - S*S/siz)/(siz - 1):0):
16559 variance_value = _variance_value>0?_variance_value:0;
16561 xm = 0, ym = 0, zm = 0, cm = 0,
16562 xM = 0, yM = 0, zM = 0, cM = 0;
16565 return CImg<Tdouble>(1,12).
fill((Tdouble)m,(Tdouble)M,mean_value,variance_value,
16566 (Tdouble)xm,(Tdouble)ym,(Tdouble)zm,(Tdouble)cm,
16567 (Tdouble)xM,(Tdouble)yM,(Tdouble)zM,(Tdouble)cM);
16592 "magnitude(): Empty instance.",
16595 switch (magnitude_type) {
16597 cimg_for(*
this,ptrs,T) {
const Tdouble val = (Tdouble)
cimg::abs(*ptrs);
if (val>res) res = val; }
16600 cimg_for(*
this,ptrs,T) res+=(Tdouble)
cimg::abs(*ptrs);
16603 cimg_for(*
this,ptrs,T) res+=(Tdouble)
cimg::sqr(*ptrs);
16604 res = (Tdouble)std::sqrt(res);
16616 "trace(): Empty instance.",
16619 cimg_forX(*
this,k) res+=(Tdouble)(*
this)(k,k);
16627 if (
is_empty() || _width!=_height || _depth!=1 || _spectrum!=1)
16629 "det(): Instance is not a square matrix.",
16633 case 1 :
return (Tdouble)((*this)(0,0));
16634 case 2 :
return (Tdouble)((*this)(0,0))*(Tdouble)((*
this)(1,1)) - (Tdouble)((*
this)(0,1))*(Tdouble)((*
this)(1,0));
16637 a = (Tdouble)_data[0], d = (Tdouble)_data[1], g = (Tdouble)_data[2],
16638 b = (Tdouble)_data[3], e = (Tdouble)_data[4], h = (Tdouble)_data[5],
16639 c = (Tdouble)_data[6], f = (Tdouble)_data[7], i = (Tdouble)_data[8];
16640 return i*a*e - a*h*f - i*b*d + b*g*f + c*d*h - c*g*e;
16647 Tdouble res = d?(Tdouble)1:(Tdouble)-1;
16648 cimg_forX(lu,i) res*=lu(i,i);
16658 template<
typename t>
16662 "dot(): Empty instance.",
16666 "dot(): Empty specified image.",
16671 for (
unsigned int off = 0; off<nb; ++off) res+=(Tdouble)_data[off]*(Tdouble)img[off];
16683 if (res._height!=_spectrum) res.assign(1,_spectrum);
16684 const unsigned long whd = (
unsigned long)_width*_height*_depth;
16685 const T *ptrs =
data(x,y,z);
16686 T *ptrd = res._data;
16687 cimg_forC(*
this,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
16699 const int n = (int)std::sqrt((
double)_spectrum);
16700 const T *ptrs =
data(x,y,z,0);
16701 const unsigned long whd = (
unsigned long)_width*_height*_depth;
16703 T *ptrd = res._data;
16704 cimg_forC(*
this,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
16715 const T *ptrs =
data(x,y,z,0);
16716 const unsigned long whd = (
unsigned long)_width*_height*_depth;
16717 if (_spectrum==6)
return tensor(*ptrs,*(ptrs+whd),*(ptrs+2*whd),*(ptrs+3*whd),*(ptrs+4*whd),*(ptrs+5*whd));
16718 if (_spectrum==3)
return tensor(*ptrs,*(ptrs+whd),*(ptrs+2*whd));
16729 template<
typename t>
16731 if (x<_width && y<_height && z<_depth) {
16732 const t *ptrs = vec._data;
16733 const unsigned long whd = (
unsigned long)_width*_height*_depth;
16734 T *ptrd =
data(x,y,z);
16735 for (
unsigned int k =
cimg::min((
unsigned int)vec.size(),_spectrum); k; --k) {
16736 *ptrd = (T)*(ptrs++); ptrd+=whd;
16749 template<
typename t>
16761 template<
typename t>
16763 T *ptrd =
data(x,y,z,0);
16764 const unsigned long siz = (
unsigned long)_width*_height*_depth;
16765 if (ten._height==2) {
16766 *ptrd = (T)ten[0]; ptrd+=siz;
16767 *ptrd = (T)ten[1]; ptrd+=siz;
16771 *ptrd = (T)ten[0]; ptrd+=siz;
16772 *ptrd = (T)ten[1]; ptrd+=siz;
16773 *ptrd = (T)ten[2]; ptrd+=siz;
16774 *ptrd = (T)ten[4]; ptrd+=siz;
16775 *ptrd = (T)ten[5]; ptrd+=siz;
16798 const unsigned long siz =
size();
16801 case 4 : _width = _height = 2;
break;
16802 case 9 : _width = _height = 3;
break;
16803 case 16 : _width = _height = 4;
break;
16804 case 25 : _width = _height = 5;
break;
16805 case 36 : _width = _height = 6;
break;
16806 case 49 : _width = _height = 7;
break;
16807 case 64 : _width = _height = 8;
break;
16808 case 81 : _width = _height = 9;
break;
16809 case 100 : _width = _height = 10;
break;
16811 unsigned long i = 11, i2 = i*i;
16812 while (i2<siz) { i2+=2*i + 1; ++i; }
16813 if (i2==siz) _width = _height = i;
16815 "matrix(): Invalid instance size %u (should be a square integer).",
16825 return (+*
this).
matrix();
16838 const unsigned long siz =
size();
16843 res(0,0) = (*this)(0);
16844 res(1,0) = res(0,1) = (*this)(1);
16845 res(1,1) = (*this)(2);
16849 res(0,0) = (*this)(0);
16850 res(1,0) = res(0,1) = (*this)(1);
16851 res(2,0) = res(0,2) = (*this)(2);
16852 res(1,1) = (*this)(3);
16853 res(2,1) = res(1,2) = (*this)(4);
16854 res(2,2) = (*this)(5);
16858 "tensor(): Invalid instance size (does not define a 1x1, 2x2 or 3x3 tensor).",
16876 cimg_foroff(*
this,off) res(off,off) = (*this)(off);
16901 const unsigned int siz =
size() - 1;
16904 const Tdouble delta = (Tdouble)a1 - (Tdouble)a0;
16905 cimg_foroff(*
this,l) *(ptr++) = (T)(a0 + delta*l/siz);
16920 if (_width==1) { _width = _height; _height = 1;
return *
this; }
16921 if (_height==1) { _height = _width; _width = 1;
return *
this; }
16922 if (_width==_height) {
16923 cimg_forYZC(*
this,y,z,c)
for (
int x = y; x<
width(); ++x)
cimg::swap((*
this)(x,y,z,c),(*
this)(y,x,z,c));
16939 template<
typename t>
16941 if (_width!=1 || _height<3 || img._width!=1 || img._height<3)
16943 "cross(): Instance and/or specified image (%u,%u,%u,%u,%p) are not 3d vectors.",
16945 img._width,img._height,img._depth,img._spectrum,img._data);
16947 const T x = (*this)[0], y = (*this)[1], z = (*this)[2];
16948 (*this)[0] = (T)(y*img[2] - z*img[1]);
16949 (*this)[1] = (T)(z*img[0] - x*img[2]);
16950 (*this)[2] = (T)(x*img[1] - y*img[0]);
16955 template<
typename t>
16967 if (_width!=_height || _depth!=1 || _spectrum!=1)
16969 "invert(): Instance is not a square matrix.",
16971 #ifdef cimg_use_lapack
16972 int INFO = (int)use_LU, N = _width, LWORK = 4*N, *
const IPIV =
new int[N];
16974 *
const lapA =
new Tfloat[N*N],
16975 *
const WORK =
new Tfloat[LWORK];
16976 cimg_forXY(*
this,k,l) lapA[k*N+l] = (Tfloat)((*
this)(k,l));
16977 cimg::getrf(N,lapA,IPIV,INFO);
16980 "invert(): LAPACK function dgetrf_() returned error code %d.",
16984 cimg::getri(N,lapA,IPIV,WORK,LWORK,INFO);
16987 "invert(): LAPACK function dgetri_() returned error code %d.",
16991 if (!INFO) cimg_forXY(*
this,k,l) (*this)(k,l) = (T)(lapA[k*N+l]);
else fill(0);
16992 delete[] IPIV;
delete[] lapA;
delete[] WORK;
16994 const double dete = _width>3?-1.0:
det();
16995 if (dete!=0.0 && _width==2) {
16997 a = _data[0], c = _data[1],
16998 b = _data[2], d = _data[3];
16999 _data[0] = (T)(d/dete); _data[1] = (T)(-c/dete);
17000 _data[2] = (T)(-b/dete); _data[3] = (T)(a/dete);
17001 }
else if (dete!=0.0 && _width==3) {
17003 a = _data[0], d = _data[1], g = _data[2],
17004 b = _data[3], e = _data[4], h = _data[5],
17005 c = _data[6], f = _data[7], i = _data[8];
17006 _data[0] = (T)((i*e-f*h)/dete), _data[1] = (T)((g*f-i*d)/dete), _data[2] = (T)((d*h-g*e)/dete);
17007 _data[3] = (T)((h*c-i*b)/dete), _data[4] = (T)((i*a-c*g)/dete), _data[5] = (T)((g*b-a*h)/dete);
17008 _data[6] = (T)((b*f-e*c)/dete), _data[7] = (T)((d*c-a*f)/dete), _data[8] = (T)((a*e-d*b)/dete);
17014 cimg_forX(*
this,j) {
17017 col._solve(A,indx);
17018 cimg_forX(*
this,i) (*this)(j,i) = (T)col(i);
17021 CImg<Tfloat> U(_width,_width), S(1,_width), V(_width,_width);
17024 cimg_forY(S,k)
if (S[k]!=0) S[k]=1/S[k];
17049 const Tfloat tolerance = (
sizeof(Tfloat)<=4?5.96e-8f:1.11e-16f)*
cimg::max(_width,_height)*S.max();
17051 const Tfloat s = S(x), invs = s>tolerance?1/s:(Tfloat)0;
17052 cimg_forY(V,y) V(x,y)*=invs;
17054 return V*U.transpose();
17062 template<
typename t>
17064 if (_width!=1 || _depth!=1 || _spectrum!=1 || _height!=A._height || A._depth!=1 || A._spectrum!=1)
17066 "solve(): Instance and specified matrix (%u,%u,%u,%u,%p) have "
17067 "incompatible dimensions.",
17069 A._width,A._height,A._depth,A._spectrum,A._data);
17070 typedef _cimg_Ttfloat Ttfloat;
17071 if (A._width==A._height) {
17072 #ifdef cimg_use_lapack
17074 int INFO, N = _height, LWORK = 4*N, *
const IPIV =
new int[N];
17076 *
const lapA =
new Ttfloat[N*N],
17077 *
const lapB =
new Ttfloat[N],
17078 *
const WORK =
new Ttfloat[LWORK];
17079 cimg_forXY(A,k,l) lapA[k*N+l] = (Ttfloat)(A(k,l));
17080 cimg_forY(*
this,i) lapB[i] = (Ttfloat)((*
this)(i));
17081 cimg::getrf(N,lapA,IPIV,INFO);
17084 "solve(): LAPACK library function dgetrf_() returned error code %d.",
17089 cimg::getrs(TRANS,N,lapA,IPIV,lapB,INFO);
17092 "solve(): LAPACK library function dgetrs_() returned error code %d.",
17096 if (!INFO) cimg_forY(*
this,i) (*this)(i) = (T)(lapB[i]);
else fill(0);
17097 delete[] IPIV;
delete[] lapA;
delete[] lapB;
delete[] WORK;
17106 #ifdef cimg_use_lapack
17108 int INFO, N = A._width, M = A._height, LWORK = -1, LDA = M, LDB = M, NRHS = _width;
17109 Ttfloat WORK_QUERY;
17111 *
const lapA =
new Ttfloat[M*N],
17112 *
const lapB =
new Ttfloat[M*NRHS];
17113 cimg::sgels(TRANS, M, N, NRHS, lapA, LDA, lapB, LDB, &WORK_QUERY, LWORK, INFO);
17114 LWORK = (int) WORK_QUERY;
17115 Ttfloat *
const WORK =
new Ttfloat[LWORK];
17116 cimg_forXY(A,k,l) lapA[k*M+l] = (Ttfloat)(A(k,l));
17117 cimg_forXY(*
this,k,l) lapB[k*M+l] = (Ttfloat)((*
this)(k,l));
17118 cimg::sgels(TRANS, M, N, NRHS, lapA, LDA, lapB, LDB, WORK, LWORK, INFO);
17121 "solve(): LAPACK library function sgels() returned error code %d.",
17126 cimg_forXY(*
this,k,l) (*this)(k,l) = (T)lapB[k*M+l];
17128 assign(A.get_pseudoinvert()*(*this));
17129 delete[] lapA;
delete[] lapB;
delete[] WORK;
17131 assign(A.get_pseudoinvert()*(*this));
17138 template<
typename t>
17143 template<
typename t,
typename ti>
17145 typedef _cimg_Ttfloat Ttfloat;
17146 const int N =
size();
17149 for (
int i = 0; i<N; ++i) {
17150 const int ip = (int)indx[i];
17151 Ttfloat sum = (*this)(ip);
17152 (*this)(ip) = (*
this)(i);
17153 if (ii>=0)
for (
int j = ii; j<=i-1; ++j) sum-=A(j,i)*(*this)(j);
17154 else if (sum!=0) ii = i;
17155 (*this)(i) = (T)sum;
17157 for (
int i = N - 1; i>=0; --i) {
17159 for (
int j = i + 1; j<N; ++j) sum-=A(j,i)*(*this)(j);
17160 (*this)(i) = (T)(sum/A(i,i));
17172 template<
typename t>
17174 const unsigned int siz = (int)
size();
17175 if (A._width!=3 || A._height!=siz)
17177 "solve_tridiagonal(): Instance and tridiagonal matrix "
17178 "(%u,%u,%u,%u,%p) have incompatible dimensions.",
17180 A._width,A._height,A._depth,A._spectrum,A._data);
17181 typedef _cimg_Ttfloat Ttfloat;
17182 const Ttfloat epsilon = 1e-4f;
17184 for (
int i = 1; i<(int)siz; ++i) {
17185 const Ttfloat m = A(0,i)/(B[i-1]?B[i-1]:epsilon);
17186 B[i] -= m*A(2,i-1);
17189 (*this)[siz-1] = (T)(V[siz-1]/(B[siz-1]?B[siz-1]:epsilon));
17190 for (
int i = (
int)siz - 2; i>=0; --i) (*
this)[i] = (T)((V[i] - A(2,i)*(*this)[i+1])/(B[i]?B[i]:epsilon));
17195 template<
typename t>
17205 template<
typename t>
17207 if (
is_empty()) { val.assign(); vec.assign(); }
17209 if (_width!=_height || _depth>1 || _spectrum>1)
17211 "eigen(): Instance is not a square matrix.",
17214 if (val.size()<(
unsigned long)_width) val.assign(1,_width);
17215 if (vec.size()<(
unsigned long)_width*_width) vec.assign(_width,_width);
17217 case 1 : { val[0] = (t)(*
this)[0]; vec[0] = (t)1; }
break;
17219 const double a = (*this)[0], b = (*this)[1], c = (*this)[2], d = (*this)[3], e = a + d;
17220 double f = e*e - 4*(a*d - b*c);
17223 "eigen(): Complex eigenvalues found.",
17227 const double l1 = 0.5*(e-f), l2 = 0.5*(e+f);
17228 const double theta1 = std::atan2(l2-a,b), theta2 = std::atan2(l1-a,b);
17231 vec(0,0) = (t)std::cos(theta1);
17232 vec(0,1) = (t)std::sin(theta1);
17233 vec(1,0) = (t)std::cos(theta2);
17234 vec(1,1) = (t)std::sin(theta2);
17238 "eigen(): Eigenvalues computation of general matrices is limited "
17239 "to 2x2 matrices.",
17252 eigen(res[0],res[1]);
17261 template<
typename t>
17263 if (
is_empty()) { val.assign(); vec.assign(); }
17265 #ifdef cimg_use_lapack
17266 char JOB =
'V', UPLO =
'U';
17267 int N = _width, LWORK = 4*N, INFO;
17269 *
const lapA =
new Tfloat[N*N],
17270 *
const lapW =
new Tfloat[N],
17271 *
const WORK =
new Tfloat[LWORK];
17272 cimg_forXY(*
this,k,l) lapA[k*N+l] = (Tfloat)((*
this)(k,l));
17273 cimg::syev(JOB,UPLO,N,lapA,lapW,WORK,LWORK,INFO);
17276 "symmetric_eigen(): LAPACK library function dsyev_() returned error code %d.",
17283 cimg_forY(val,i) val(i) = (T)lapW[N-1-i];
17284 cimg_forXY(vec,k,l) vec(k,l) = (T)(lapA[(N-1-k)*N+l]);
17285 }
else { val.fill(0); vec.fill(0); }
17286 delete[] lapA;
delete[] lapW;
delete[] WORK;
17288 if (_width!=_height || _depth>1 || _spectrum>1)
17290 "eigen(): Instance is not a square matrix.",
17293 val.assign(1,_width);
17294 if (vec._data) vec.assign(_width,_width);
17297 if (_width==2) { vec[1] = -vec[2]; vec[3] = vec[0]; }
17301 SVD(vec,val,V,
false);
17303 bool is_ambiguous =
false;
17306 if (val[p]>eig) eig = (float)val[p];
17308 cimg_forY(vec,y) scal+=vec(p,y)*V(p,y);
17309 if (
cimg::abs(scal)<0.9f) is_ambiguous =
true;
17310 if (scal<0) val[p] = -val[p];
17312 if (is_ambiguous) {
17314 SVD(vec,val,V,
false,40,eig);
17319 val.sort(permutations,
false);
17321 cimg_forY(permutations,y) tmp(y) = vec(permutations(y),k);
17322 std::memcpy(vec.data(0,k),tmp._data,
sizeof(t)*_width);
17345 template<
typename t>
17347 permutations.assign(_width,_height,_depth,_spectrum);
17349 cimg_foroff(permutations,off) permutations[off] = (t)off;
17350 return _quicksort(0,
size()-1,permutations,is_increasing,
true);
17354 template<
typename t>
17356 return (+*
this).
sort(permutations,is_increasing);
17374 _quicksort(0,
size()-1,perm,is_increasing,
false);
17378 get_crop(0,0,0,0,_width-1,0,0,0).sort(perm,is_increasing);
17380 cimg_forXYZC(*
this,x,y,z,c) (*this)(x,y,z,c) = img(perm[x],y,z,c);
17384 get_crop(0,0,0,0,0,_height-1,0,0).sort(perm,is_increasing);
17386 cimg_forXYZC(*
this,x,y,z,c) (*this)(x,y,z,c) = img(x,perm[y],z,c);
17390 get_crop(0,0,0,0,0,0,_depth-1,0).sort(perm,is_increasing);
17392 cimg_forXYZC(*
this,x,y,z,c) (*this)(x,y,z,c) = img(x,y,perm[z],c);
17396 get_crop(0,0,0,0,0,0,0,_spectrum-1).sort(perm,is_increasing);
17398 cimg_forXYZC(*
this,x,y,z,c) (*this)(x,y,z,c) = img(x,y,z,perm[c]);
17402 "sort(): Invalid specified axis '%c' "
17403 "(should be { x | y | z | c }).",
17404 cimg_instance,axis);
17411 return (+*
this).
sort(is_increasing,axis);
17414 template<
typename t>
17415 CImg<T>& _quicksort(
const int indm,
const int indM,
CImg<t>& permutations,
17416 const bool is_increasing,
const bool is_permutations) {
17418 const int mid = (indm + indM)/2;
17419 if (is_increasing) {
17420 if ((*
this)[indm]>(*this)[mid]) {
17422 if (is_permutations)
cimg::swap(permutations[indm],permutations[mid]);
17424 if ((*
this)[mid]>(*
this)[indM]) {
17426 if (is_permutations)
cimg::swap(permutations[indM],permutations[mid]);
17428 if ((*
this)[indm]>(*
this)[mid]) {
17430 if (is_permutations)
cimg::swap(permutations[indm],permutations[mid]);
17433 if ((*
this)[indm]<(*
this)[mid]) {
17435 if (is_permutations)
cimg::swap(permutations[indm],permutations[mid]);
17437 if ((*
this)[mid]<(*
this)[indM]) {
17439 if (is_permutations)
cimg::swap(permutations[indM],permutations[mid]);
17441 if ((*
this)[indm]<(*
this)[mid]) {
17443 if (is_permutations)
cimg::swap(permutations[indm],permutations[mid]);
17446 if (indM - indm>=3) {
17447 const T pivot = (*this)[mid];
17448 int i = indm, j = indM;
17449 if (is_increasing) {
17451 while ((*
this)[i]<pivot) ++i;
17452 while ((*
this)[j]>pivot) --j;
17454 if (is_permutations)
cimg::swap(permutations[i],permutations[j]);
17460 while ((*
this)[i]>pivot) ++i;
17461 while ((*
this)[j]<pivot) --j;
17463 if (is_permutations)
cimg::swap(permutations[i],permutations[j]);
17468 if (indm<j) _quicksort(indm,j,permutations,is_increasing,is_permutations);
17469 if (i<indM) _quicksort(i,indM,permutations,is_increasing,is_permutations);
17493 template<
typename t>
17495 const unsigned int max_iteration=40,
const float lambda=0)
const {
17496 if (
is_empty()) { U.assign(); S.assign(); V.assign(); }
17500 const unsigned int delta =
cimg::min(U._width,U._height);
17501 for (
unsigned int i = 0; i<delta; ++i) U(i,i) = (t)(U(i,i) + lambda);
17503 if (S.size()<_width) S.assign(1,_width);
17504 if (V._width<_width || V._height<_height) V.assign(_width,_width);
17506 t anorm = 0, c, f, g = 0, h, s, scale = 0;
17510 l = i+1; rv1[i] = scale*g; g = s = scale = 0;
17514 for (
int k = i; k<
height(); ++k) { U(i,k)/=scale; s+= U(i,k)*U(i,k); }
17515 f = U(i,i); g = (t)((f>=0?-1:1)*std::sqrt(s)); h=f*g-s; U(i,i) = f-g;
17516 for (
int j = l; j<
width(); ++j) {
17518 for (
int k=i; k<
height(); ++k) s+= U(i,k)*U(j,k);
17520 for (
int k = i; k<
height(); ++k) U(j,k)+= f*U(i,k);
17522 for (
int k = i; k<
height(); ++k) U(i,k)*= scale;
17531 for (
int k = l; k<
width(); ++k) { U(k,i)/= scale; s+= U(k,i)*U(k,i); }
17532 f = U(l,i); g = (t)((f>=0?-1:1)*std::sqrt(s)); h = f*g-s; U(l,i) = f-g;
17533 for (
int k = l; k<
width(); ++k) rv1[k]=U(k,i)/h;
17534 for (
int j = l; j<
height(); ++j) {
17536 for (
int k = l; k<
width(); ++k) s+= U(k,j)*U(k,i);
17537 for (
int k = l; k<
width(); ++k) U(k,j)+= s*rv1[k];
17539 for (
int k = l; k<
width(); ++k) U(k,i)*= scale;
17545 for (
int i =
width()-1; i>=0; --i) {
17548 for (
int j = l; j<
width(); ++j) V(i,j) =(U(j,i)/U(l,i))/g;
17549 for (
int j = l; j<
width(); ++j) {
17551 for (
int k = l; k<
width(); ++k) s+= U(k,i)*V(j,k);
17552 for (
int k = l; k<
width(); ++k) V(j,k)+= s*V(i,k);
17555 for (
int j = l; j<
width(); ++j) V(j,i) = V(i,j) = (t)0.0;
17557 V(i,i) = (t)1.0; g = rv1[i]; l = i;
17562 for (
int j = l; j<
width(); ++j) U(j,i) = 0;
17565 for (
int j = l; j<
width(); ++j) {
17566 s = 0;
for (
int k = l; k<
height(); ++k) s+= U(i,k)*U(j,k);
17568 for (
int k = i; k<
height(); ++k) U(j,k)+= f*U(i,k);
17570 for (
int j = i; j<
height(); ++j) U(i,j)*= g;
17571 }
else for (
int j = i; j<
height(); ++j) U(i,j) = 0;
17575 for (
int k =
width()-1; k>=0; --k) {
17576 for (
unsigned int its = 0; its<max_iteration; ++its) {
17578 for (l = k; l>=1; --l) {
17580 if ((
cimg::abs(rv1[l])+anorm)==anorm) { flag =
false;
break; }
17581 if ((
cimg::abs(S[nm])+anorm)==anorm)
break;
17585 for (
int i = l; i<=k; ++i) {
17586 f = s*rv1[i]; rv1[i] = c*rv1[i];
17587 if ((
cimg::abs(f)+anorm)==anorm)
break;
17588 g = S[i]; h = (t)cimg::_pythagore(f,g); S[i] = h; h = 1/h; c = g*h; s = -f*h;
17589 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; }
17594 if (l==k) {
if (z<0) { S[k] = -z; cimg_forX(U,j) V(k,j) = -V(k,j); }
break; }
17596 t x = S[l], y = S[nm];
17597 g = rv1[nm]; h = rv1[k];
17598 f = ((y-z)*(y+z)+(g-h)*(g+h))/
cimg::max((t)1e-25,2*h*y);
17599 g = (t)cimg::_pythagore(f,1.0);
17600 f = ((x-z)*(x+z)+h*((y/(f + (f>=0?g:-g)))-h))/
cimg::max((t)1e-25,x);
17602 for (
int j = l; j<=nm; ++j) {
17604 g = rv1[i]; h = s*g; g = c*g;
17606 t z = (t)cimg::_pythagore(f,h);
17608 f = x*c+g*s; g = g*c-x*s; h = y*s; y*=c;
17609 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; }
17610 z = (t)cimg::_pythagore(f,h); S[j] = z;
17611 if (z) { z = 1/
cimg::max((t)1e-25,z); c = f*z; s = h*z; }
17612 f = c*g+s*y; x = c*y-s*g;
17613 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; }
17615 rv1[l] = 0; rv1[k]=f; S[k]=x;
17622 S.sort(permutations,
false);
17624 cimg_forY(permutations,y) tmp(y) = U(permutations(y),k);
17625 std::memcpy(U.data(0,k),tmp._data,
sizeof(t)*_width);
17628 cimg_forY(permutations,y) tmp(y) = V(permutations(y),k);
17629 std::memcpy(V.data(0,k),tmp._data,
sizeof(t)*_width);
17642 const unsigned int max_iteration=40,
const float lambda=0)
const {
17644 SVD(res[0],res[1],res[2],sorting,max_iteration,lambda);
17649 template<
typename t>
17651 const int N =
width();
17656 cimg_forX(*
this,i) {
17658 cimg_forX(*
this,j) {
17659 const Tfloat tmp =
cimg::abs((*
this)(j,i));
17660 if (tmp>vmax) vmax = tmp;
17662 if (vmax==0) { indx.fill(0);
return fill(0); }
17665 cimg_forX(*
this,j) {
17666 for (
int i = 0; i<j; ++i) {
17667 Tfloat sum=(*this)(j,i);
17668 for (
int k = 0; k<i; ++k) sum-=(*
this)(k,i)*(*
this)(j,k);
17669 (*this)(j,i) = (T)sum;
17672 for (
int i = j; i<
width(); ++i) {
17673 Tfloat sum=(*this)(j,i);
17674 for (
int k = 0; k<j; ++k) sum-=(*
this)(k,i)*(*
this)(j,k);
17675 (*this)(j,i) = (T)sum;
17676 const Tfloat tmp = vv[i]*cimg::
abs(sum);
17677 if (tmp>=vmax) { vmax=tmp; imax=i; }
17680 cimg_forX(*
this,k) cimg::
swap((*this)(k,imax),(*this)(k,j));
17685 if ((*this)(j,j)==0) (*this)(j,j) = (T)1e-20;
17687 const Tfloat tmp = 1/(Tfloat)(*
this)(j,j);
17688 for (
int i=j+1; i<N; ++i) (*
this)(j,i) = (T)((*this)(j,i)*tmp);
17705 template<
typename tf,
typename t>
17707 const unsigned int starting_node,
const unsigned int ending_node,
17709 if (starting_node>=nb_nodes)
17710 throw CImgArgumentException(
"CImg<%s>::dijkstra(): Specified indice of starting node %u is higher "
17711 "than number of nodes %u.",
17714 dist(starting_node) = 0;
17715 previous_node.assign(1,nb_nodes,1,1,(t)-1);
17716 previous_node(starting_node) = (t)starting_node;
17718 cimg_forX(Q,u) Q(u) = u;
17720 unsigned int sizeQ = nb_nodes;
17723 const unsigned int umin = Q(0);
17724 if (umin==ending_node) sizeQ = 0;
17726 const T dmin = dist(umin);
17728 for (
unsigned int q = 1; q<sizeQ; ++q) {
17729 const unsigned int v = Q(q);
17732 const T alt = dmin + d;
17735 previous_node(v) = (t)umin;
17736 const T distpos = dist(Q(q));
17737 for (
unsigned int pos = q, par = 0; pos && distpos<dist(Q(par=(pos+1)/2-1)); pos=par)
17744 const T distpos = dist(Q(0));
17745 for (
unsigned int pos = 0, left = 0, right = 0;
17746 ((right=2*(pos+1),(left=right-1))<sizeQ && distpos>dist(Q(left))) ||
17747 (right<sizeQ && distpos>dist(Q(right)));) {
17749 if (dist(Q(left))<dist(Q(right))) {
cimg::swap(Q(pos),Q(left)); pos = left; }
17750 else {
cimg::swap(Q(pos),Q(right)); pos = right; }
17751 }
else {
cimg::swap(Q(pos),Q(left)); pos = left; }
17759 template<
typename tf,
typename t>
17761 const unsigned int starting_node,
const unsigned int ending_node=~0U) {
17763 return dijkstra(distance,nb_nodes,starting_node,ending_node,foo);
17775 template<
typename t>
17778 return get_dijkstra(starting_node,ending_node,previous_node).move_to(*
this);
17782 template<
typename t>
17784 CImg<t>& previous_node)
const {
17785 if (_width!=_height || _depth!=1 || _spectrum!=1)
17787 "dijkstra(): Instance is not a graph adjacency matrix.",
17790 return dijkstra(*
this,_width,starting_node,ending_node,previous_node);
17795 return get_dijkstra(starting_node,ending_node).move_to(*
this);
17811 return CImg<T>(str,(
unsigned int)std::strlen(str)+(is_last_zero?1:0),1,1,1,
is_shared);
17830 CImg<T> r(1,2); T *ptr = r._data;
17831 *(ptr++) = a0; *(ptr++) = a1;
17842 CImg<T> r(1,3); T *ptr = r._data;
17843 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2;
17855 CImg<T> r(1,4); T *ptr = r._data;
17856 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3;
17861 static CImg<T> vector(
const T& a0,
const T& a1,
const T& a2,
const T& a3,
const T& a4) {
17862 CImg<T> r(1,5); T *ptr = r._data;
17863 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; *(ptr++) = a4;
17868 static CImg<T> vector(
const T& a0,
const T& a1,
const T& a2,
const T& a3,
const T& a4,
const T& a5) {
17869 CImg<T> r(1,6); T *ptr = r._data;
17870 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; *(ptr++) = a4; *(ptr++) = a5;
17876 const T& a4,
const T& a5,
const T& a6) {
17877 CImg<T> r(1,7); T *ptr = r._data;
17878 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3;
17879 *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6;
17885 const T& a4,
const T& a5,
const T& a6,
const T& a7) {
17886 CImg<T> r(1,8); T *ptr = r._data;
17887 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3;
17888 *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7;
17894 const T& a4,
const T& a5,
const T& a6,
const T& a7,
17896 CImg<T> r(1,9); T *ptr = r._data;
17897 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3;
17898 *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7;
17905 const T& a4,
const T& a5,
const T& a6,
const T& a7,
17906 const T& a8,
const T& a9) {
17907 CImg<T> r(1,10); T *ptr = r._data;
17908 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3;
17909 *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7;
17910 *(ptr++) = a8; *(ptr++) = a9;
17916 const T& a4,
const T& a5,
const T& a6,
const T& a7,
17917 const T& a8,
const T& a9,
const T& a10) {
17918 CImg<T> r(1,11); T *ptr = r._data;
17919 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3;
17920 *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7;
17921 *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10;
17927 const T& a4,
const T& a5,
const T& a6,
const T& a7,
17928 const T& a8,
const T& a9,
const T& a10,
const T& a11) {
17929 CImg<T> r(1,12); T *ptr = r._data;
17930 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3;
17931 *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7;
17932 *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11;
17938 const T& a4,
const T& a5,
const T& a6,
const T& a7,
17939 const T& a8,
const T& a9,
const T& a10,
const T& a11,
17941 CImg<T> r(1,13); T *ptr = r._data;
17942 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3;
17943 *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7;
17944 *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11;
17951 const T& a4,
const T& a5,
const T& a6,
const T& a7,
17952 const T& a8,
const T& a9,
const T& a10,
const T& a11,
17953 const T& a12,
const T& a13) {
17954 CImg<T> r(1,14); T *ptr = r._data;
17955 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3;
17956 *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7;
17957 *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11;
17958 *(ptr++) = a12; *(ptr++) = a13;
17964 const T& a4,
const T& a5,
const T& a6,
const T& a7,
17965 const T& a8,
const T& a9,
const T& a10,
const T& a11,
17966 const T& a12,
const T& a13,
const T& a14) {
17967 CImg<T> r(1,15); T *ptr = r._data;
17968 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3;
17969 *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7;
17970 *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11;
17971 *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14;
17977 const T& a4,
const T& a5,
const T& a6,
const T& a7,
17978 const T& a8,
const T& a9,
const T& a10,
const T& a11,
17979 const T& a12,
const T& a13,
const T& a14,
const T& a15) {
17980 CImg<T> r(1,16); T *ptr = r._data;
17981 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3;
17982 *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7;
17983 *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11;
17984 *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14; *(ptr++) = a15;
18005 const T& a2,
const T& a3) {
18006 CImg<T> r(2,2); T *ptr = r._data;
18007 *(ptr++) = a0; *(ptr++) = a1;
18008 *(ptr++) = a2; *(ptr++) = a3;
18025 const T& a3,
const T& a4,
const T& a5,
18026 const T& a6,
const T& a7,
const T& a8) {
18027 CImg<T> r(3,3); T *ptr = r._data;
18028 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2;
18029 *(ptr++) = a3; *(ptr++) = a4; *(ptr++) = a5;
18030 *(ptr++) = a6; *(ptr++) = a7; *(ptr++) = a8;
18036 const T& a4,
const T& a5,
const T& a6,
const T& a7,
18037 const T& a8,
const T& a9,
const T& a10,
const T& a11,
18038 const T& a12,
const T& a13,
const T& a14,
const T& a15) {
18039 CImg<T> r(4,4); T *ptr = r._data;
18040 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3;
18041 *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7;
18042 *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11;
18043 *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14; *(ptr++) = a15;
18048 static CImg<T> matrix(
const T& a0,
const T& a1,
const T& a2,
const T& a3,
const T& a4,
18049 const T& a5,
const T& a6,
const T& a7,
const T& a8,
const T& a9,
18050 const T& a10,
const T& a11,
const T& a12,
const T& a13,
const T& a14,
18051 const T& a15,
const T& a16,
const T& a17,
const T& a18,
const T& a19,
18052 const T& a20,
const T& a21,
const T& a22,
const T& a23,
const T& a24) {
18053 CImg<T> r(5,5); T *ptr = r._data;
18054 *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; *(ptr++) = a4;
18055 *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; *(ptr++) = a8; *(ptr++) = a9;
18056 *(ptr++) = a10; *(ptr++) = a11; *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14;
18057 *(ptr++) = a15; *(ptr++) = a16; *(ptr++) = a17; *(ptr++) = a18; *(ptr++) = a19;
18058 *(ptr++) = a20; *(ptr++) = a21; *(ptr++) = a22; *(ptr++) = a23; *(ptr++) = a24;
18073 return matrix(a0,a1,a1,a2);
18077 static CImg<T> tensor(
const T& a0,
const T& a1,
const T& a2,
const T& a3,
const T& a4,
const T& a5) {
18078 return matrix(a0,a1,a2,a1,a3,a4,a2,a4,a5);
18088 return matrix(a0,0,0,a1);
18093 return matrix(a0,0,0,0,a1,0,0,0,a2);
18098 return matrix(a0,0,0,0,0,a1,0,0,0,0,a2,0,0,0,0,a3);
18103 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);
18112 cimg_forX(res,x) res(x,x) = 1;
18136 const bool is_quaternion=
false) {
18138 if (!is_quaternion) {
18139 const float norm = (float)std::sqrt(x*x + y*y + z*z),
18140 nx = norm>0?x/norm:0,
18141 ny = norm>0?y/norm:0,
18142 nz = norm>0?z/norm:1,
18144 sina = (float)std::sin(nw/2),
18145 cosa = (float)std::cos(nw/2);
18151 const float norm = (float)std::sqrt(x*x + y*y + z*z + w*w);
18153 else { X = Y = Z = 0; W = 1; }
18155 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;
18156 return CImg<T>::matrix((T)(1-2*(yy+zz)), (T)(2*(xy+zw)), (T)(2*(xz-yw)),
18157 (T)(2*(xy-zw)), (T)(1-2*(xx+zz)), (T)(2*(yz+xw)),
18158 (T)(2*(xz+yw)), (T)(2*(yz-xw)), (T)(1-2*(xx+yy)));
18174 if (val &&
sizeof(T)!=1) cimg_for(*
this,ptrd,T) *ptrd = val;
18175 else std::memset(_data,(
int)val,
sizeof(T)*
size());
18181 return CImg<T>(_width,_height,_depth,_spectrum).
fill(val);
18191 T *ptrd, *ptre =
end()-1;
18192 for (ptrd = _data; ptrd<ptre; ) { *(ptrd++) = val0; *(ptrd++) = val1; }
18193 if (ptrd!=ptre+1) *(ptrd++) = val0;
18199 return CImg<T>(_width,_height,_depth,_spectrum).
fill(val0,val1);
18205 T *ptrd, *ptre =
end()-2;
18206 for (ptrd = _data; ptrd<ptre; ) { *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2; }
18208 switch (ptre - ptrd) {
18209 case 2 : *(--ptre) = val1;
18210 case 1 : *(--ptre) = val0;
18217 return CImg<T>(_width,_height,_depth,_spectrum).
fill(val0,val1,val2);
18223 T *ptrd, *ptre =
end()-3;
18224 for (ptrd = _data; ptrd<ptre; ) { *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2; *(ptrd++) = val3; }
18226 switch (ptre - ptrd) {
18227 case 3 : *(--ptre) = val2;
18228 case 2 : *(--ptre) = val1;
18229 case 1 : *(--ptre) = val0;
18236 return CImg<T>(_width,_height,_depth,_spectrum).
fill(val0,val1,val2,val3);
18240 CImg<T>&
fill(
const T val0,
const T val1,
const T val2,
const T val3,
const T val4) {
18242 T *ptrd, *ptre =
end()-4;
18243 for (ptrd = _data; ptrd<ptre; ) {
18244 *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2; *(ptrd++) = val3; *(ptrd++) = val4;
18247 switch (ptre - ptrd) {
18248 case 4 : *(--ptre) = val3;
18249 case 3 : *(--ptre) = val2;
18250 case 2 : *(--ptre) = val1;
18251 case 1 : *(--ptre) = val0;
18257 CImg<T> get_fill(
const T val0,
const T val1,
const T val2,
const T val3,
const T val4)
const {
18258 return CImg<T>(_width,_height,_depth,_spectrum).
fill(val0,val1,val2,val3,val4);
18262 CImg<T>&
fill(
const T val0,
const T val1,
const T val2,
const T val3,
const T val4,
const T val5) {
18264 T *ptrd, *ptre =
end()-5;
18265 for (ptrd = _data; ptrd<ptre; ) {
18266 *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2; *(ptrd++) = val3; *(ptrd++) = val4; *(ptrd++) = val5;
18269 switch (ptre - ptrd) {
18270 case 5 : *(--ptre) = val4;
18271 case 4 : *(--ptre) = val3;
18272 case 3 : *(--ptre) = val2;
18273 case 2 : *(--ptre) = val1;
18274 case 1 : *(--ptre) = val0;
18280 CImg<T> get_fill(
const T val0,
const T val1,
const T val2,
const T val3,
const T val4,
const T val5)
const {
18281 return CImg<T>(_width,_height,_depth,_spectrum).
fill(val0,val1,val2,val3,val4,val5);
18285 CImg<T>&
fill(
const T val0,
const T val1,
const T val2,
const T val3,
const T val4,
const T val5,
const T val6) {
18287 T *ptrd, *ptre =
end()-6;
18288 for (ptrd = _data; ptrd<ptre; ) {
18289 *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2; *(ptrd++) = val3; *(ptrd++) = val4; *(ptrd++) = val5;
18293 switch (ptre - ptrd) {
18294 case 6 : *(--ptre) = val5;
18295 case 5 : *(--ptre) = val4;
18296 case 4 : *(--ptre) = val3;
18297 case 3 : *(--ptre) = val2;
18298 case 2 : *(--ptre) = val1;
18299 case 1 : *(--ptre) = val0;
18305 CImg<T> get_fill(
const T val0,
const T val1,
const T val2,
const T val3,
const T val4,
const T val5,
18306 const T val6)
const {
18307 return CImg<T>(_width,_height,_depth,_spectrum).
fill(val0,val1,val2,val3,val4,val5,val6);
18311 CImg<T>&
fill(
const T val0,
const T val1,
const T val2,
const T val3,
const T val4,
const T val5,
18312 const T val6,
const T val7) {
18314 T *ptrd, *ptre =
end()-7;
18315 for (ptrd = _data; ptrd<ptre; ) {
18316 *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2; *(ptrd++) = val3;
18317 *(ptrd++) = val4; *(ptrd++) = val5; *(ptrd++) = val6; *(ptrd++) = val7;
18320 switch (ptre - ptrd) {
18321 case 7 : *(--ptre) = val6;
18322 case 6 : *(--ptre) = val5;
18323 case 5 : *(--ptre) = val4;
18324 case 4 : *(--ptre) = val3;
18325 case 3 : *(--ptre) = val2;
18326 case 2 : *(--ptre) = val1;
18327 case 1 : *(--ptre) = val0;
18333 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,
18334 const T val7)
const {
18335 return CImg<T>(_width,_height,_depth,_spectrum).
fill(val0,val1,val2,val3,val4,val5,val6,val7);
18339 CImg<T>&
fill(
const T val0,
const T val1,
const T val2,
const T val3,
const T val4,
const T val5,
const T val6,
18340 const T val7,
const T val8) {
18342 T *ptrd, *ptre =
end()-8;
18343 for (ptrd = _data; ptrd<ptre; ) {
18344 *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2;
18345 *(ptrd++) = val3; *(ptrd++) = val4; *(ptrd++) = val5;
18346 *(ptrd++) = val6; *(ptrd++) = val7; *(ptrd++) = val8;
18349 switch (ptre - ptrd) {
18350 case 8 : *(--ptre) = val7;
18351 case 7 : *(--ptre) = val6;
18352 case 6 : *(--ptre) = val5;
18353 case 5 : *(--ptre) = val4;
18354 case 4 : *(--ptre) = val3;
18355 case 3 : *(--ptre) = val2;
18356 case 2 : *(--ptre) = val1;
18357 case 1 : *(--ptre) = val0;
18363 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,
18364 const T val7,
const T val8)
const {
18365 return CImg<T>(_width,_height,_depth,_spectrum).
fill(val0,val1,val2,val3,val4,val5,val6,val7,val8);
18369 CImg<T>&
fill(
const T val0,
const T val1,
const T val2,
const T val3,
const T val4,
const T val5,
const T val6,
18370 const T val7,
const T val8,
const T val9) {
18372 T *ptrd, *ptre =
end()-9;
18373 for (ptrd = _data; ptrd<ptre; ) {
18374 *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2; *(ptrd++) = val3; *(ptrd++) = val4;
18375 *(ptrd++) = val5; *(ptrd++) = val6; *(ptrd++) = val7; *(ptrd++) = val8; *(ptrd++) = val9;
18378 switch (ptre - ptrd) {
18379 case 9 : *(--ptre) = val8;
18380 case 8 : *(--ptre) = val7;
18381 case 7 : *(--ptre) = val6;
18382 case 6 : *(--ptre) = val5;
18383 case 5 : *(--ptre) = val4;
18384 case 4 : *(--ptre) = val3;
18385 case 3 : *(--ptre) = val2;
18386 case 2 : *(--ptre) = val1;
18387 case 1 : *(--ptre) = val0;
18393 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,
18394 const T val7,
const T val8,
const T val9)
const {
18395 return CImg<T>(_width,_height,_depth,_spectrum).
fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9);
18399 CImg<T>&
fill(
const T val0,
const T val1,
const T val2,
const T val3,
const T val4,
const T val5,
const T val6,
18400 const T val7,
const T val8,
const T val9,
const T val10) {
18402 T *ptrd, *ptre =
end()-10;
18403 for (ptrd = _data; ptrd<ptre; ) {
18404 *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2; *(ptrd++) = val3; *(ptrd++) = val4;
18405 *(ptrd++) = val5; *(ptrd++) = val6; *(ptrd++) = val7; *(ptrd++) = val8; *(ptrd++) = val9;
18409 switch (ptre - ptrd) {
18410 case 10 : *(--ptre) = val9;
18411 case 9 : *(--ptre) = val8;
18412 case 8 : *(--ptre) = val7;
18413 case 7 : *(--ptre) = val6;
18414 case 6 : *(--ptre) = val5;
18415 case 5 : *(--ptre) = val4;
18416 case 4 : *(--ptre) = val3;
18417 case 3 : *(--ptre) = val2;
18418 case 2 : *(--ptre) = val1;
18419 case 1 : *(--ptre) = val0;
18425 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,
18426 const T val7,
const T val8,
const T val9,
const T val10)
const {
18427 return CImg<T>(_width,_height,_depth,_spectrum).
fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10);
18431 CImg<T>&
fill(
const T val0,
const T val1,
const T val2,
const T val3,
const T val4,
const T val5,
const T val6,
18432 const T val7,
const T val8,
const T val9,
const T val10,
const T val11) {
18434 T *ptrd, *ptre =
end()-11;
18435 for (ptrd = _data; ptrd<ptre; ) {
18436 *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2; *(ptrd++) = val3; *(ptrd++) = val4; *(ptrd++) = val5;
18437 *(ptrd++) = val6; *(ptrd++) = val7; *(ptrd++) = val8; *(ptrd++) = val9; *(ptrd++) = val10; *(ptrd++) = val11;
18440 switch (ptre - ptrd) {
18441 case 11 : *(--ptre) = val10;
18442 case 10 : *(--ptre) = val9;
18443 case 9 : *(--ptre) = val8;
18444 case 8 : *(--ptre) = val7;
18445 case 7 : *(--ptre) = val6;
18446 case 6 : *(--ptre) = val5;
18447 case 5 : *(--ptre) = val4;
18448 case 4 : *(--ptre) = val3;
18449 case 3 : *(--ptre) = val2;
18450 case 2 : *(--ptre) = val1;
18451 case 1 : *(--ptre) = val0;
18457 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,
18458 const T val7,
const T val8,
const T val9,
const T val10,
const T val11)
const {
18459 return CImg<T>(_width,_height,_depth,_spectrum).
fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,
18464 CImg<T>&
fill(
const T val0,
const T val1,
const T val2,
const T val3,
const T val4,
const T val5,
const T val6,
18465 const T val7,
const T val8,
const T val9,
const T val10,
const T val11,
const T val12) {
18467 T *ptrd, *ptre =
end()-12;
18468 for (ptrd = _data; ptrd<ptre; ) {
18469 *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2; *(ptrd++) = val3; *(ptrd++) = val4; *(ptrd++) = val5;
18470 *(ptrd++) = val6; *(ptrd++) = val7; *(ptrd++) = val8; *(ptrd++) = val9; *(ptrd++) = val10; *(ptrd++) = val11;
18474 switch (ptre - ptrd) {
18475 case 12 : *(--ptre) = val11;
18476 case 11 : *(--ptre) = val10;
18477 case 10 : *(--ptre) = val9;
18478 case 9 : *(--ptre) = val8;
18479 case 8 : *(--ptre) = val7;
18480 case 7 : *(--ptre) = val6;
18481 case 6 : *(--ptre) = val5;
18482 case 5 : *(--ptre) = val4;
18483 case 4 : *(--ptre) = val3;
18484 case 3 : *(--ptre) = val2;
18485 case 2 : *(--ptre) = val1;
18486 case 1 : *(--ptre) = val0;
18492 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,
18493 const T val7,
const T val8,
const T val9,
const T val10,
const T val11,
const T val12)
const {
18494 return CImg<T>(_width,_height,_depth,_spectrum).
fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,
18499 CImg<T>&
fill(
const T val0,
const T val1,
const T val2,
const T val3,
const T val4,
const T val5,
const T val6,
18500 const T val7,
const T val8,
const T val9,
const T val10,
const T val11,
const T val12,
18503 T *ptrd, *ptre =
end()-13;
18504 for (ptrd = _data; ptrd<ptre; ) {
18505 *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2; *(ptrd++) = val3; *(ptrd++) = val4; *(ptrd++) = val5;
18506 *(ptrd++) = val6; *(ptrd++) = val7; *(ptrd++) = val8; *(ptrd++) = val9; *(ptrd++) = val10; *(ptrd++) = val11;
18507 *(ptrd++) = val12; *(ptrd++) = val13;
18510 switch (ptre - ptrd) {
18511 case 13 : *(--ptre) = val12;
18512 case 12 : *(--ptre) = val11;
18513 case 11 : *(--ptre) = val10;
18514 case 10 : *(--ptre) = val9;
18515 case 9 : *(--ptre) = val8;
18516 case 8 : *(--ptre) = val7;
18517 case 7 : *(--ptre) = val6;
18518 case 6 : *(--ptre) = val5;
18519 case 5 : *(--ptre) = val4;
18520 case 4 : *(--ptre) = val3;
18521 case 3 : *(--ptre) = val2;
18522 case 2 : *(--ptre) = val1;
18523 case 1 : *(--ptre) = val0;
18529 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,
18530 const T val7,
const T val8,
const T val9,
const T val10,
const T val11,
const T val12,
18531 const T val13)
const {
18532 return CImg<T>(_width,_height,_depth,_spectrum).
fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,
18533 val11,val12,val13);
18537 CImg<T>&
fill(
const T val0,
const T val1,
const T val2,
const T val3,
const T val4,
const T val5,
const T val6,
18538 const T val7,
const T val8,
const T val9,
const T val10,
const T val11,
const T val12,
18539 const T val13,
const T val14) {
18541 T *ptrd, *ptre =
end()-14;
18542 for (ptrd = _data; ptrd<ptre; ) {
18543 *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2; *(ptrd++) = val3; *(ptrd++) = val4; *(ptrd++) = val5;
18544 *(ptrd++) = val6; *(ptrd++) = val7; *(ptrd++) = val8; *(ptrd++) = val9; *(ptrd++) = val10; *(ptrd++) = val11;
18545 *(ptrd++) = val12; *(ptrd++) = val13; *(ptrd++) = val14;
18548 switch (ptre - ptrd) {
18549 case 14 : *(--ptre) = val13;
18550 case 13 : *(--ptre) = val12;
18551 case 12 : *(--ptre) = val11;
18552 case 11 : *(--ptre) = val10;
18553 case 10 : *(--ptre) = val9;
18554 case 9 : *(--ptre) = val8;
18555 case 8 : *(--ptre) = val7;
18556 case 7 : *(--ptre) = val6;
18557 case 6 : *(--ptre) = val5;
18558 case 5 : *(--ptre) = val4;
18559 case 4 : *(--ptre) = val3;
18560 case 3 : *(--ptre) = val2;
18561 case 2 : *(--ptre) = val1;
18562 case 1 : *(--ptre) = val0;
18568 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,
18569 const T val7,
const T val8,
const T val9,
const T val10,
const T val11,
const T val12,
18570 const T val13,
const T val14)
const {
18571 return CImg<T>(_width,_height,_depth,_spectrum).
fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,
18572 val11,val12,val13,val14);
18576 CImg<T>&
fill(
const T val0,
const T val1,
const T val2,
const T val3,
const T val4,
const T val5,
const T val6,
18577 const T val7,
const T val8,
const T val9,
const T val10,
const T val11,
const T val12,
18578 const T val13,
const T val14,
const T val15) {
18580 T *ptrd, *ptre =
end()-15;
18581 for (ptrd = _data; ptrd<ptre; ) {
18582 *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2; *(ptrd++) = val3; *(ptrd++) = val4; *(ptrd++) = val5;
18583 *(ptrd++) = val6; *(ptrd++) = val7; *(ptrd++) = val8; *(ptrd++) = val9; *(ptrd++) = val10; *(ptrd++) = val11;
18584 *(ptrd++) = val12; *(ptrd++) = val13; *(ptrd++) = val14; *(ptrd++) = val15;
18587 switch (ptre - ptrd) {
18588 case 15 : *(--ptre) = val14;
18589 case 14 : *(--ptre) = val13;
18590 case 13 : *(--ptre) = val12;
18591 case 12 : *(--ptre) = val11;
18592 case 11 : *(--ptre) = val10;
18593 case 10 : *(--ptre) = val9;
18594 case 9 : *(--ptre) = val8;
18595 case 8 : *(--ptre) = val7;
18596 case 7 : *(--ptre) = val6;
18597 case 6 : *(--ptre) = val5;
18598 case 5 : *(--ptre) = val4;
18599 case 4 : *(--ptre) = val3;
18600 case 3 : *(--ptre) = val2;
18601 case 2 : *(--ptre) = val1;
18602 case 1 : *(--ptre) = val0;
18608 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,
18609 const T val7,
const T val8,
const T val9,
const T val10,
const T val11,
const T val12,
18610 const T val13,
const T val14,
const T val15)
const {
18611 return CImg<T>(_width,_height,_depth,_spectrum).
fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,
18612 val11,val12,val13,val14,val15);
18621 if (
is_empty() || !expression || !*expression)
return *
this;
18625 const CImg<T> _base = cimg::_is_self_expr(expression)?+*
this:
CImg<T>(), &base = _base?_base:*
this;
18626 _cimg_math_parser mp(base,expression+(*expression==
'>' || *expression==
'<'?1:0),
"fill");
18627 T *ptrd = *expression==
'<'?
end()-1:_data;
18628 if (*expression==
'<') cimg_rofXYZC(*
this,x,y,z,c) *(ptrd--) = (T)mp(x,y,z,c);
18629 else if (*expression==
'>') cimg_forXYZC(*
this,x,y,z,c) *(ptrd++) = (T)mp(x,y,z,c);
18631 #ifdef cimg_use_openmp
18632 if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
18633 #pragma omp parallel
18635 _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
18636 #pragma omp for collapse(3)
18637 cimg_forYZC(*
this,y,z,c) {
18638 T *ptrd =
data(0,y,z,c);
18639 cimg_forX(*
this,x) *ptrd++ = (T)lmp(x,y,z,c);
18644 cimg_forXYZC(*
this,x,y,z,c) *(ptrd++) = (T)mp(x,y,z,c);
18647 char item[16384] = { 0 }, sep = 0;
18648 const char *nexpression = expression;
18649 unsigned long nb = 0;
18650 const unsigned long siz =
size();
18652 for (
double val = 0; *nexpression && nb<siz; ++nb) {
18654 const int err = std::sscanf(nexpression,
"%4095[ \n\t0-9.e+-]%c",item,&sep);
18655 if (err>0 && std::sscanf(item,
"%lf",&val)==1) {
18656 nexpression+=std::strlen(item) + (err>1?1:0);
18657 *(ptrd++) = (T)val;
18661 if (nb<siz && (sep || *nexpression))
18663 if (repeat_flag && nb && nb<siz)
18664 for (T *ptrs = _data, *
const ptre = _data + siz; ptrd<ptre; ++ptrs) *(ptrd++) = *ptrs;
18672 return (+*
this).
fill(values,repeat_values);
18681 template<
typename t>
18683 if (
is_empty() || !values)
return *
this;
18684 T *ptrd = _data, *ptre = ptrd +
size();
18685 for (t *ptrs = values._data, *ptrs_end = ptrs + values.size(); ptrs<ptrs_end && ptrd<ptre; ++ptrs)
18686 *(ptrd++) = (T)*ptrs;
18687 if (repeat_values && ptrd<ptre)
for (T *ptrs = _data; ptrd<ptre; ++ptrs) *(ptrd++) = *ptrs;
18692 template<
typename t>
18694 return repeat_values?
CImg<T>(_width,_height,_depth,_spectrum).
fill(values,repeat_values):
18695 (+*
this).
fill(values,repeat_values);
18705 CImg<T>&
fillX(
const unsigned int y,
const unsigned int z,
const unsigned int c,
const int a0, ...) {
18706 #define _cimg_fill1(x,y,z,c,off,siz,t) { \
18707 va_list ap; va_start(ap,a0); T *ptrd = data(x,y,z,c); *ptrd = (T)a0; \
18708 for (unsigned long k = 1; k<siz; ++k) { ptrd+=off; *ptrd = (T)va_arg(ap,t); } \
18710 if (y<_height && z<_depth && c<_spectrum) _cimg_fill1(0,y,z,c,1,_width,
int);
18715 CImg<T>&
fillX(
const unsigned int y,
const unsigned int z,
const unsigned int c,
const double a0, ...) {
18716 if (y<_height && z<_depth && c<_spectrum) _cimg_fill1(0,y,z,c,1,_width,
double);
18727 CImg<T>&
fillY(
const unsigned int x,
const unsigned int z,
const unsigned int c,
const int a0, ...) {
18728 if (x<_width && z<_depth && c<_spectrum) _cimg_fill1(x,0,z,c,_width,_height,
int);
18733 CImg<T>&
fillY(
const unsigned int x,
const unsigned int z,
const unsigned int c,
const double a0, ...) {
18734 if (x<_width && z<_depth && c<_spectrum) _cimg_fill1(x,0,z,c,_width,_height,
double);
18745 CImg<T>&
fillZ(
const unsigned int x,
const unsigned int y,
const unsigned int c,
const int a0, ...) {
18746 const unsigned long wh = (
unsigned long)_width*_height;
18747 if (x<_width && y<_height && c<_spectrum) _cimg_fill1(x,y,0,c,wh,_depth,
int);
18752 CImg<T>&
fillZ(
const unsigned int x,
const unsigned int y,
const unsigned int c,
const double a0, ...) {
18753 const unsigned long wh = (
unsigned long)_width*_height;
18754 if (x<_width && y<_height && c<_spectrum) _cimg_fill1(x,y,0,c,wh,_depth,
double);
18765 CImg<T>&
fillC(
const unsigned int x,
const unsigned int y,
const unsigned int z,
const int a0, ...) {
18766 const unsigned long whd = (
unsigned long)_width*_height*_depth;
18767 if (x<_width && y<_height && z<_depth) _cimg_fill1(x,y,z,0,whd,_spectrum,
int);
18772 CImg<T>&
fillC(
const unsigned int x,
const unsigned int y,
const unsigned int z,
const double a0, ...) {
18773 const unsigned long whd = (
unsigned long)_width*_height*_depth;
18774 if (x<_width && y<_height && z<_depth) _cimg_fill1(x,y,z,0,whd,_spectrum,
double);
18792 for (
const T *ps = _data, *
const pse =
end(); ps<pse; ++ps)
18793 if (*ps!=value) *(pd++) = *ps;
18794 if (pd==res._data)
return CImg<T>();
18795 return res.resize(1,pd-res._data,1,1,-1);
18804 template<
typename t>
18810 template<
typename t>
18812 if (!values)
return *
this;
18813 if (values.size()==1)
return get_discard(*values);
18816 const t *
const pve = values.end();
18817 for (
const T *ps = _data, *
const pse =
end(); ps<pse; ) {
18819 const t *pv = values._data;
18820 while (_ps<pse && pv<pve) {
if (*(_ps++)!=(T)*pv)
break; ++pv; }
18822 const unsigned int l = _ps - ps;
18823 if (l==1) *(pd++) = *ps;
else { std::memcpy(pd,ps,
sizeof(T)*l); pd+=l; }
18827 if (pd==res._data)
return CImg<T>();
18828 return res.resize(1,pd-res._data,1,1,-1);
18851 const float delta = (float)val_max - (
float)val_min;
18852 cimg_for(*
this,ptrd,T) *ptrd = (T)(val_min +
cimg::rand()*delta);
18858 return (+*
this).
rand(val_min,val_max);
18871 #ifdef cimg_use_openmp
18872 #pragma omp parallel for if (size()>=8192)
18874 cimg_rof(*
this,ptrd,T) *ptrd =
cimg::round(*ptrd,y,rounding_type);
18880 return (+*
this).
round(y,rounding_type);
18904 Tfloat nsigma = (Tfloat)sigma, m = 0, M = 0;
18905 if (nsigma==0 && noise_type!=3)
return *
this;
18906 if (nsigma<0 || noise_type==2) m = (Tfloat)
min_max(M);
18907 if (nsigma<0) nsigma = (Tfloat)(-nsigma*(M-m)/100.0);
18908 switch (noise_type) {
18910 cimg_rof(*
this,ptrd,T) {
18911 Tfloat val = (Tfloat)(*ptrd + nsigma*
cimg::grand());
18912 if (val>vmax) val = vmax;
18913 if (val<vmin) val = vmin;
18918 cimg_rof(*
this,ptrd,T) {
18919 Tfloat val = (Tfloat)(*ptrd + nsigma*
cimg::crand());
18920 if (val>vmax) val = vmax;
18921 if (val<vmin) val = vmin;
18926 if (nsigma<0) nsigma = -nsigma;
18932 cimg_rof(*
this,ptrd,T) *ptrd = (T)
cimg::prand(*ptrd);
18936 const Tfloat sqrt2 = (Tfloat)std::sqrt(2.0);
18937 cimg_rof(*
this,ptrd,T) {
18939 val0 = (Tfloat)*ptrd/sqrt2,
18942 Tfloat val = (Tfloat)std::sqrt(re*re + im*im);
18943 if (val>vmax) val = vmax;
18944 if (val<vmin) val = vmin;
18950 "noise(): Invalid specified noise type %d "
18951 "(should be { 0=gaussian | 1=uniform | 2=salt&Pepper | 3=poisson }).",
18961 return (+*
this).
noise(sigma,noise_type);
18977 const T a = min_value<max_value?min_value:max_value, b = min_value<max_value?max_value:min_value;
18979 const Tfloat fm = (Tfloat)m, fM = (Tfloat)M;
18980 if (m==M)
return fill(min_value);
18982 #ifdef cimg_use_openmp
18983 #pragma omp parallel for if (size()>=65536)
18985 cimg_rof(*
this,ptrd,T) *ptrd = (T)((*ptrd-fm)/(fM-fm)*(b-a)+a);
19004 const unsigned long whd = (
unsigned long)_width*_height*_depth;
19005 #ifdef cimg_use_openmp
19006 #pragma omp parallel for collapse(2) if (_width>=512 && _height*_depth>=16)
19008 cimg_forYZ(*
this,y,z) {
19009 T *ptrd =
data(0,y,z,0);
19010 cimg_forX(*
this,x) {
19011 const T *ptrs = ptrd;
19013 cimg_forC(*
this,c) { n+=
cimg::sqr((
float)*ptrs); ptrs+=whd; }
19014 n = (float)std::sqrt(n);
19016 if (n>0) cimg_forC(*
this,c) { *_ptrd = (T)(*_ptrd/n); _ptrd+=whd; }
19017 else cimg_forC(*
this,c) { *_ptrd = (T)0; _ptrd+=whd; }
19039 if (_spectrum==1)
return abs();
19040 return get_norm(norm_type).move_to(*
this);
19046 if (_spectrum==1)
return get_abs();
19047 const unsigned long whd = (
unsigned long)_width*_height*_depth;
19049 switch (norm_type) {
19051 #ifdef cimg_use_openmp
19052 #pragma omp parallel for collapse(2) if (_width>=512 && _height*_depth>=16)
19054 cimg_forYZ(*
this,y,z) {
19055 const unsigned long off =
offset(0,y,z);
19056 const T *ptrs = _data + off;
19057 Tfloat *ptrd = res._data + off;
19058 cimg_forX(*
this,x) {
19060 const T *_ptrs = ptrs++;
19061 cimg_forC(*
this,c) {
const Tfloat val = (Tfloat)
cimg::abs(*_ptrs);
if (val>n) n = val; _ptrs+=whd; }
19067 #ifdef cimg_use_openmp
19068 #pragma omp parallel for collapse(2) if (_width>=512 && _height*_depth>=16)
19070 cimg_forYZ(*
this,y,z) {
19071 const unsigned long off =
offset(0,y,z);
19072 const T *ptrs = _data + off;
19073 Tfloat *ptrd = res._data + off;
19074 cimg_forX(*
this,x) {
19076 const T *_ptrs = ptrs++;
19077 cimg_forC(*
this,c) { n+=
cimg::abs(*_ptrs); _ptrs+=whd; }
19083 #ifdef cimg_use_openmp
19084 #pragma omp parallel for collapse(2) if (_width>=512 && _height*_depth>=16)
19086 cimg_forYZ(*
this,y,z) {
19087 const unsigned long off =
offset(0,y,z);
19088 const T *ptrs = _data + off;
19089 Tfloat *ptrd = res._data + off;
19090 cimg_forX(*
this,x) {
19092 const T *_ptrs = ptrs++;
19093 cimg_forC(*
this,c) { n+=
cimg::sqr((Tfloat)*_ptrs); _ptrs+=whd; }
19094 *(ptrd++) = (Tfloat)std::sqrt((Tfloat)n);
19115 const T a = min_value<max_value?min_value:max_value, b = min_value<max_value?max_value:min_value;
19116 #ifdef cimg_use_openmp
19117 #pragma omp parallel for if (size()>=32768)
19119 cimg_rof(*
this,ptrd,T) *ptrd = (*ptrd<a)?a:((*ptrd>b)?b:*ptrd);
19125 return (+*
this).
cut(min_value,max_value);
19142 "quantize(): Invalid quantization request with 0 values.",
19146 Tfloat m, M = (Tfloat)
max_min(m), range = M - m;
19149 #ifdef cimg_use_openmp
19150 #pragma omp parallel for if (size()>=32768)
19152 cimg_rof(*
this,ptrd,T) {
19153 const unsigned int val = (
unsigned int)((*ptrd-m)*nb_levels/range);
19154 *ptrd = (T)(m +
cimg::min(val,nb_levels-1)*range/nb_levels);
19156 #ifdef cimg_use_openmp
19157 #pragma omp parallel for if (size()>=32768)
19159 cimg_rof(*
this,ptrd,T) {
19160 const unsigned int val = (
unsigned int)((*ptrd-m)*nb_levels/range);
19169 return (+*
this).
quantize(n,keep_range);
19184 CImg<T>&
threshold(
const T value,
const bool soft_threshold=
false,
const bool strict_threshold=
false) {
19186 if (strict_threshold) {
19187 if (soft_threshold)
19188 #ifdef cimg_use_openmp
19189 #pragma omp parallel for if (size()>=32768)
19191 cimg_rof(*
this,ptrd,T) {
const T v = *ptrd; *ptrd = v>value?(T)(v-value):v<-(float)value?(T)(v+value):(T)0; }
19193 #ifdef cimg_use_openmp
19194 #pragma omp parallel for if (size()>=65536)
19196 cimg_rof(*
this,ptrd,T) *ptrd = *ptrd>value?(T)1:(T)0;
19198 if (soft_threshold)
19199 #ifdef cimg_use_openmp
19200 #pragma omp parallel for if (size()>=32768)
19202 cimg_rof(*
this,ptrd,T) {
19203 const T v = *ptrd; *ptrd = v>=value?(T)(v-value):v<=-(float)value?(T)(v+value):(T)0;
19206 #ifdef cimg_use_openmp
19207 #pragma omp parallel for if (size()>=65536)
19209 cimg_rof(*
this,ptrd,T) *ptrd = *ptrd>=value?(T)1:(T)0;
19216 return (+*
this).
threshold(value,soft_threshold,strict_threshold);
19238 return get_histogram(nb_levels,min_value,max_value).move_to(*
this);
19249 T vmin = min_value<max_value?min_value:max_value, vmax = min_value<max_value?max_value:min_value;
19251 cimg_rof(*
this,ptrs,T) {
19252 const T val = *ptrs;
19253 if (val>=vmin && val<=vmax) ++res[val==vmax?nb_levels-1:(
unsigned int)((val-vmin)*nb_levels/(vmax-vmin))];
19261 T vmax = 0, vmin =
min_max(vmax);
19280 if (!nb_levels ||
is_empty())
return *
this;
19281 T vmin = min_value<max_value?min_value:max_value, vmax = min_value<max_value?max_value:min_value;
19283 unsigned long cumul = 0;
19284 cimg_forX(hist,pos) { cumul+=hist[pos]; hist[pos] = cumul; }
19285 #ifdef cimg_use_openmp
19286 #pragma omp parallel for if (size()>=1048576)
19288 cimg_rof(*
this,ptrd,T) {
19289 const int pos = (int)((*ptrd-vmin)*(nb_levels-1)/(vmax-vmin));
19290 if (pos>=0 && pos<(
int)nb_levels) *ptrd = (T)(vmin + (vmax-vmin)*hist[pos]/
size());
19297 if (!nb_levels ||
is_empty())
return *
this;
19298 T vmax = 0, vmin =
min_max(vmax);
19299 return equalize(nb_levels,vmin,vmax);
19304 return (+*
this).
equalize(nblevels,val_min,val_max);
19309 return (+*
this).
equalize(nblevels);
19327 template<
typename t>
19329 return get_index(colormap,dithering,map_indexes).move_to(*
this);
19333 template<
typename t>
19336 if (colormap._spectrum!=_spectrum)
19338 "index(): Instance and specified colormap (%u,%u,%u,%u,%p) "
19339 "have incompatible dimensions.",
19341 colormap._width,colormap._height,colormap._depth,colormap._spectrum,colormap._data);
19343 typedef typename CImg<t>::Tuint tuint;
19345 const unsigned long
19346 whd = (
unsigned long)_width*_height*_depth,
19347 pwhd = (
unsigned long)colormap._width*colormap._height*colormap._depth;
19348 CImg<tuint> res(_width,_height,_depth,map_indexes?_spectrum:1);
19349 tuint *ptrd = res._data;
19351 const float ndithering = (dithering<0?0:dithering>1?1:dithering)/16;
19352 Tfloat valm = 0, valM = (Tfloat)
max_min(valm);
19353 if (valm==valM && valm>=0 && valM<=255) { valm = 0; valM = 255; }
19355 Tfloat *cache_current = cache.data(1,0,0,0), *cache_next = cache.data(1,1,0,0);
19356 const unsigned long cwhd = (
unsigned long)cache._width*cache._height*cache._depth;
19357 switch (_spectrum) {
19359 cimg_forYZ(*
this,y,z) {
19361 Tfloat *ptrc0 = cache_next;
const T *ptrs0 =
data(0,y+1,z,0);
19362 cimg_forX(*
this,x) *(ptrc0++) = (Tfloat)*(ptrs0++);
19364 Tfloat *ptrs0 = cache_current, *ptrsn0 = cache_next;
19365 cimg_forX(*
this,x) {
19366 const Tfloat _val0 = (Tfloat)*ptrs0, val0 = _val0<valm?valm:_val0>valM?valM:_val0;
19368 for (
const t *ptrp0 = colormap._data, *ptrp_end = ptrp0 + pwhd; ptrp0<ptrp_end; ) {
19369 const Tfloat pval0 = (Tfloat)*(ptrp0++) - val0, dist = pval0*pval0;
19370 if (dist<distmin) { ptrmin0 = ptrp0 - 1; distmin = dist; }
19372 const Tfloat err0 = ((*(ptrs0++)=val0) - (Tfloat)*ptrmin0)*ndithering;
19373 *ptrs0+=7*err0; *(ptrsn0-1)+=3*err0; *(ptrsn0++)+=5*err0; *ptrsn0+=err0;
19374 if (map_indexes) *(ptrd++) = (tuint)*ptrmin0;
else *(ptrd++) = (tuint)(ptrmin0 - colormap._data);
19380 tuint *ptrd1 = ptrd + whd;
19381 cimg_forYZ(*
this,y,z) {
19383 Tfloat *ptrc0 = cache_next, *ptrc1 = ptrc0 + cwhd;
19384 const T *ptrs0 =
data(0,y+1,z,0), *ptrs1 = ptrs0 + whd;
19385 cimg_forX(*
this,x) { *(ptrc0++) = (Tfloat)*(ptrs0++); *(ptrc1++) = (Tfloat)*(ptrs1++); }
19388 *ptrs0 = cache_current, *ptrs1 = ptrs0 + cwhd,
19389 *ptrsn0 = cache_next, *ptrsn1 = ptrsn0 + cwhd;
19390 cimg_forX(*
this,x) {
19392 _val0 = (Tfloat)*ptrs0, val0 = _val0<valm?valm:_val0>valM?valM:_val0,
19393 _val1 = (Tfloat)*ptrs1, val1 = _val1<valm?valm:_val1>valM?valM:_val1;
19395 for (
const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp_end = ptrp1; ptrp0<ptrp_end; ) {
19397 pval0 = (Tfloat)*(ptrp0++) - val0, pval1 = (Tfloat)*(ptrp1++) - val1,
19398 dist = pval0*pval0 + pval1*pval1;
19399 if (dist<distmin) { ptrmin0 = ptrp0 - 1; distmin = dist; }
19401 const t *
const ptrmin1 = ptrmin0 + pwhd;
19403 err0 = ((*(ptrs0++)=val0) - (Tfloat)*ptrmin0)*ndithering,
19404 err1 = ((*(ptrs1++)=val1) - (Tfloat)*ptrmin1)*ndithering;
19405 *ptrs0+=7*err0; *ptrs1+=7*err1;
19406 *(ptrsn0-1)+=3*err0; *(ptrsn1-1)+=3*err1;
19407 *(ptrsn0++)+=5*err0; *(ptrsn1++)+=5*err1;
19408 *ptrsn0+=err0; *ptrsn1+=err1;
19409 if (map_indexes) { *(ptrd++) = (tuint)*ptrmin0; *(ptrd1++) = (tuint)*ptrmin1; }
19410 else *(ptrd++) = (tuint)(ptrmin0 - colormap._data);
19416 tuint *ptrd1 = ptrd + whd, *ptrd2 = ptrd1 + whd;
19417 cimg_forYZ(*
this,y,z) {
19419 Tfloat *ptrc0 = cache_next, *ptrc1 = ptrc0 + cwhd, *ptrc2 = ptrc1 + cwhd;
19420 const T *ptrs0 =
data(0,y+1,z,0), *ptrs1 = ptrs0 + whd, *ptrs2 = ptrs1 + whd;
19421 cimg_forX(*
this,x) {
19422 *(ptrc0++) = (Tfloat)*(ptrs0++); *(ptrc1++) = (Tfloat)*(ptrs1++); *(ptrc2++) = (Tfloat)*(ptrs2++);
19426 *ptrs0 = cache_current, *ptrs1 = ptrs0 + cwhd, *ptrs2 = ptrs1 + cwhd,
19427 *ptrsn0 = cache_next, *ptrsn1 = ptrsn0 + cwhd, *ptrsn2 = ptrsn1 + cwhd;
19428 cimg_forX(*
this,x) {
19430 _val0 = (Tfloat)*ptrs0, val0 = _val0<valm?valm:_val0>valM?valM:_val0,
19431 _val1 = (Tfloat)*ptrs1, val1 = _val1<valm?valm:_val1>valM?valM:_val1,
19432 _val2 = (Tfloat)*ptrs2, val2 = _val2<valm?valm:_val2>valM?valM:_val2;
19434 for (
const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd,
19435 *ptrp_end = ptrp1; ptrp0<ptrp_end; ) {
19437 pval0 = (Tfloat)*(ptrp0++) - val0,
19438 pval1 = (Tfloat)*(ptrp1++) - val1,
19439 pval2 = (Tfloat)*(ptrp2++) - val2,
19440 dist = pval0*pval0 + pval1*pval1 + pval2*pval2;
19441 if (dist<distmin) { ptrmin0 = ptrp0 - 1; distmin = dist; }
19443 const t *
const ptrmin1 = ptrmin0 + pwhd, *
const ptrmin2 = ptrmin1 + pwhd;
19445 err0 = ((*(ptrs0++)=val0) - (Tfloat)*ptrmin0)*ndithering,
19446 err1 = ((*(ptrs1++)=val1) - (Tfloat)*ptrmin1)*ndithering,
19447 err2 = ((*(ptrs2++)=val2) - (Tfloat)*ptrmin2)*ndithering;
19449 *ptrs0+=7*err0; *ptrs1+=7*err1; *ptrs2+=7*err2;
19450 *(ptrsn0-1)+=3*err0; *(ptrsn1-1)+=3*err1; *(ptrsn2-1)+=3*err2;
19451 *(ptrsn0++)+=5*err0; *(ptrsn1++)+=5*err1; *(ptrsn2++)+=5*err2;
19452 *ptrsn0+=err0; *ptrsn1+=err1; *ptrsn2+=err2;
19455 *(ptrd++) = (tuint)*ptrmin0; *(ptrd1++) = (tuint)*ptrmin1; *(ptrd2++) = (tuint)*ptrmin2;
19456 }
else *(ptrd++) = (tuint)(ptrmin0 - colormap._data);
19462 cimg_forYZ(*
this,y,z) {
19464 Tfloat *ptrc = cache_next;
19465 cimg_forC(*
this,c) {
19466 Tfloat *_ptrc = ptrc;
const T *_ptrs =
data(0,y+1,z,c);
19467 cimg_forX(*
this,x) *(_ptrc++) = (Tfloat)*(_ptrs++);
19471 Tfloat *ptrs = cache_current, *ptrsn = cache_next;
19472 cimg_forX(*
this,x) {
19474 for (
const t *ptrp = colormap._data, *ptrp_end = ptrp + pwhd; ptrp<ptrp_end; ++ptrp) {
19475 Tfloat dist = 0; Tfloat *_ptrs = ptrs;
const t *_ptrp = ptrp;
19476 cimg_forC(*
this,c) {
19477 const Tfloat _val = *_ptrs, val = _val<valm?valm:_val>valM?valM:_val;
19478 dist+=
cimg::sqr((*_ptrs=val) - (Tfloat)*_ptrp); _ptrs+=cwhd; _ptrp+=pwhd;
19480 if (dist<distmin) { ptrmin = ptrp; distmin = dist; }
19482 const t *_ptrmin = ptrmin; Tfloat *_ptrs = ptrs++, *_ptrsn = (ptrsn++)-1;
19483 cimg_forC(*
this,c) {
19484 const Tfloat err = (*(_ptrs++) - (Tfloat)*_ptrmin)*ndithering;
19485 *_ptrs+=7*err; *(_ptrsn++)+=3*err; *(_ptrsn++)+=5*err; *_ptrsn+=err;
19486 _ptrmin+=pwhd; _ptrs+=cwhd-1; _ptrsn+=cwhd-2;
19489 tuint *_ptrd = ptrd++;
19490 cimg_forC(*
this,c) { *_ptrd = (tuint)*ptrmin; _ptrd+=whd; ptrmin+=pwhd; }
19492 else *(ptrd++) = (tuint)(ptrmin - colormap._data);
19498 switch (_spectrum) {
19500 #ifdef cimg_use_openmp
19501 #pragma omp parallel for collapse(2) if (_width>=64 && _height*_depth>=16 && pwhd>=16)
19503 cimg_forYZ(*
this,y,z) {
19504 tuint *ptrd = res.data(0,y,z);
19505 for (
const T *ptrs0 =
data(0,y,z), *ptrs_end = ptrs0 + _width; ptrs0<ptrs_end; ) {
19506 const Tfloat val0 = (Tfloat)*(ptrs0++);
19508 for (
const t *ptrp0 = colormap._data, *ptrp_end = ptrp0 + pwhd; ptrp0<ptrp_end; ) {
19509 const Tfloat pval0 = (Tfloat)*(ptrp0++) - val0, dist = pval0*pval0;
19510 if (dist<distmin) { ptrmin0 = ptrp0 - 1; distmin = dist; }
19512 if (map_indexes) *(ptrd++) = (tuint)*ptrmin0;
else *(ptrd++) = (tuint)(ptrmin0 - colormap._data);
19517 #ifdef cimg_use_openmp
19518 #pragma omp parallel for collapse(2) if (_width>=64 && _height*_depth>=16 && pwhd>=16)
19520 cimg_forYZ(*
this,y,z) {
19521 tuint *ptrd = res.data(0,y,z), *ptrd1 = ptrd + whd;
19522 for (
const T *ptrs0 =
data(0,y,z), *ptrs1 = ptrs0 + whd, *ptrs_end = ptrs0 + _width; ptrs0<ptrs_end; ) {
19523 const Tfloat val0 = (Tfloat)*(ptrs0++), val1 = (Tfloat)*(ptrs1++);
19525 for (
const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp_end = ptrp1; ptrp0<ptrp_end; ) {
19527 pval0 = (Tfloat)*(ptrp0++) - val0, pval1 = (Tfloat)*(ptrp1++) - val1,
19528 dist = pval0*pval0 + pval1*pval1;
19529 if (dist<distmin) { ptrmin0 = ptrp0 - 1; distmin = dist; }
19531 if (map_indexes) { *(ptrd++) = (tuint)*ptrmin0; *(ptrd1++) = (tuint)*(ptrmin0 + pwhd); }
19532 else *(ptrd++) = (tuint)(ptrmin0 - colormap._data);
19537 #ifdef cimg_use_openmp
19538 #pragma omp parallel for collapse(2) if (_width>=64 && _height*_depth>=16 && pwhd>=16)
19540 cimg_forYZ(*
this,y,z) {
19541 tuint *ptrd = res.data(0,y,z), *ptrd1 = ptrd + whd, *ptrd2 = ptrd1 + whd;
19542 for (
const T *ptrs0 =
data(0,y,z), *ptrs1 = ptrs0 + whd, *ptrs2 = ptrs1 + whd,
19543 *ptrs_end = ptrs0 + _width; ptrs0<ptrs_end; ) {
19544 const Tfloat val0 = (Tfloat)*(ptrs0++), val1 = (Tfloat)*(ptrs1++), val2 = (Tfloat)*(ptrs2++);
19546 for (
const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd,
19547 *ptrp_end = ptrp1; ptrp0<ptrp_end; ) {
19549 pval0 = (Tfloat)*(ptrp0++) - val0,
19550 pval1 = (Tfloat)*(ptrp1++) - val1,
19551 pval2 = (Tfloat)*(ptrp2++) - val2,
19552 dist = pval0*pval0 + pval1*pval1 + pval2*pval2;
19553 if (dist<distmin) { ptrmin0 = ptrp0 - 1; distmin = dist; }
19556 *(ptrd++) = (tuint)*ptrmin0;
19557 *(ptrd1++) = (tuint)*(ptrmin0 + pwhd);
19558 *(ptrd2++) = (tuint)*(ptrmin0 + 2*pwhd);
19559 }
else *(ptrd++) = (tuint)(ptrmin0 - colormap._data);
19564 #ifdef cimg_use_openmp
19565 #pragma omp parallel for collapse(2) if (_width>=64 && _height*_depth>=16 && pwhd>=16)
19567 cimg_forYZ(*
this,y,z) {
19568 tuint *ptrd = res.data(0,y,z);
19569 for (
const T *ptrs =
data(0,y,z), *ptrs_end = ptrs + _width; ptrs<ptrs_end; ++ptrs) {
19571 for (
const t *ptrp = colormap._data, *ptrp_end = ptrp + pwhd; ptrp<ptrp_end; ++ptrp) {
19572 Tfloat dist = 0;
const T *_ptrs = ptrs;
const t *_ptrp = ptrp;
19573 cimg_forC(*
this,c) { dist+=
cimg::sqr((Tfloat)*_ptrs - (Tfloat)*_ptrp); _ptrs+=whd; _ptrp+=pwhd; }
19574 if (dist<distmin) { ptrmin = ptrp; distmin = dist; }
19577 tuint *_ptrd = ptrd++;
19578 cimg_forC(*
this,c) { *_ptrd = (tuint)*ptrmin; _ptrd+=whd; ptrmin+=pwhd; }
19580 else *(ptrd++) = (tuint)(ptrmin - colormap._data);
19602 template<
typename t>
19604 return get_map(colormap,boundary_conditions).move_to(*
this);
19608 template<
typename t>
19610 if (_spectrum!=1 && colormap._spectrum!=1)
19612 "map(): Instance and specified colormap (%u,%u,%u,%u,%p) "
19613 "have incompatible dimensions.",
19615 colormap._width,colormap._height,colormap._depth,colormap._spectrum,colormap._data);
19617 const unsigned long
19618 whd = (
unsigned long)_width*_height*_depth,
19619 pwhd = (
unsigned long)colormap._width*colormap._height*colormap._depth;
19620 CImg<t> res(_width,_height,_depth,colormap._spectrum==1?_spectrum:colormap._spectrum);
19621 switch (colormap._spectrum) {
19624 const T *ptrs = _data;
19625 switch (boundary_conditions) {
19627 cimg_for(res,ptrd,t) {
19628 const unsigned long ind = (
unsigned long)*(ptrs++);
19629 *ptrd = colormap[ind%pwhd];
19632 cimg_for(res,ptrd,t) {
19633 const long ind = (long)*(ptrs++);
19634 *ptrd = colormap[ind<0?0:ind>=(long)pwhd?pwhd-1:ind];
19637 cimg_for(res,ptrd,t) {
19638 const unsigned long ind = (
unsigned long)*(ptrs++);
19639 *ptrd = ind<pwhd?colormap[ind]:(t)0;
19645 switch (boundary_conditions) {
19647 const t *
const ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd;
19648 t *ptrd0 = res._data, *ptrd1 = ptrd0 + whd;
19649 for (
const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
19650 const unsigned long _ind = (
unsigned long)*(ptrs++), ind = _ind%pwhd;
19651 *(ptrd0++) = ptrp0[ind]; *(ptrd1++) = ptrp1[ind];
19655 const t *
const ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd;
19656 t *ptrd0 = res._data, *ptrd1 = ptrd0 + whd;
19657 for (
const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
19658 const long _ind = (long)*(ptrs++), ind = _ind<0?0:_ind>=(long)pwhd?pwhd-1:_ind;
19659 *(ptrd0++) = ptrp0[ind]; *(ptrd1++) = ptrp1[ind];
19663 const t *
const ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd;
19664 t *ptrd0 = res._data, *ptrd1 = ptrd0 + whd;
19665 for (
const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
19666 const unsigned long ind = (
unsigned long)*(ptrs++);
19667 const bool is_in = ind<pwhd;
19668 *(ptrd0++) = is_in?ptrp0[ind]:(t)0; *(ptrd1++) = is_in?ptrp1[ind]:(t)0;
19675 switch (boundary_conditions) {
19677 const t *
const ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd;
19678 t *ptrd0 = res._data, *ptrd1 = ptrd0 + whd, *ptrd2 = ptrd1 + whd;
19679 for (
const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
19680 const unsigned long _ind = (
unsigned long)*(ptrs++), ind = _ind%pwhd;
19681 *(ptrd0++) = ptrp0[ind]; *(ptrd1++) = ptrp1[ind]; *(ptrd2++) = ptrp2[ind];
19685 const t *
const ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd;
19686 t *ptrd0 = res._data, *ptrd1 = ptrd0 + whd, *ptrd2 = ptrd1 + whd;
19687 for (
const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
19688 const long _ind = (long)*(ptrs++), ind = _ind<0?0:_ind>=(long)pwhd?pwhd-1:_ind;
19689 *(ptrd0++) = ptrp0[ind]; *(ptrd1++) = ptrp1[ind]; *(ptrd2++) = ptrp2[ind];
19693 const t *
const ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd;
19694 t *ptrd0 = res._data, *ptrd1 = ptrd0 + whd, *ptrd2 = ptrd1 + whd;
19695 for (
const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
19696 const unsigned long ind = (
unsigned long)*(ptrs++);
19697 const bool is_in = ind<pwhd;
19698 *(ptrd0++) = is_in?ptrp0[ind]:(t)0; *(ptrd1++) = is_in?ptrp1[ind]:(t)0; *(ptrd2++) = is_in?ptrp2[ind]:(t)0;
19705 switch (boundary_conditions) {
19707 t *ptrd = res._data;
19708 for (
const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
19709 const unsigned long _ind = (
unsigned long)*(ptrs++), ind = _ind%pwhd;
19710 const t *ptrp = colormap._data + ind;
19711 t *_ptrd = ptrd++; cimg_forC(res,c) { *_ptrd = *ptrp; _ptrd+=whd; ptrp+=pwhd; }
19715 t *ptrd = res._data;
19716 for (
const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
19717 const long _ind = (long)*(ptrs++), ind = _ind<0?0:_ind>=(long)pwhd?pwhd-1:_ind;
19718 const t *ptrp = colormap._data + ind;
19719 t *_ptrd = ptrd++; cimg_forC(res,c) { *_ptrd = *ptrp; _ptrd+=whd; ptrp+=pwhd; }
19723 t *ptrd = res._data;
19724 for (
const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
19725 const unsigned long ind = (
unsigned long)*(ptrs++);
19726 const bool is_in = ind<pwhd;
19728 const t *ptrp = colormap._data + ind;
19729 t *_ptrd = ptrd++; cimg_forC(res,c) { *_ptrd = *ptrp; _ptrd+=whd; ptrp+=pwhd; }
19731 t *_ptrd = ptrd++; cimg_forC(res,c) { *_ptrd = (t)0; _ptrd+=whd; }
19752 CImg<T>&
label(
const bool is_high_connectivity=
false,
const Tfloat tolerance=0) {
19753 return get_label(is_high_connectivity,tolerance).move_to(*
this);
19758 const Tfloat tolerance=0)
const {
19762 int dx[13], dy[13], dz[13], nb = 0;
19763 dx[nb]=1; dy[nb] = 0; dz[nb++]=0;
19764 dx[nb]=0; dy[nb] = 1; dz[nb++]=0;
19765 if (is_high_connectivity) {
19766 dx[nb]=1; dy[nb] = 1; dz[nb++]=0;
19767 dx[nb]=1; dy[nb] = -1; dz[nb++]=0;
19770 dx[nb]=0; dy[nb] = 0; dz[nb++]=1;
19771 if (is_high_connectivity) {
19772 dx[nb]=1; dy[nb] = 1; dz[nb++]=-1;
19773 dx[nb]=1; dy[nb] = 0; dz[nb++]=-1;
19774 dx[nb]=1; dy[nb] = -1; dz[nb++]=-1;
19775 dx[nb]=0; dy[nb] = 1; dz[nb++]=-1;
19777 dx[nb]=0; dy[nb] = 1; dz[nb++]=1;
19778 dx[nb]=1; dy[nb] = -1; dz[nb++]=1;
19779 dx[nb]=1; dy[nb] = 0; dz[nb++]=1;
19780 dx[nb]=1; dy[nb] = 1; dz[nb++]=1;
19783 return _get_label(nb,dx,dy,dz,tolerance);
19791 template<
typename t>
19793 return get_label(connectivity_mask,tolerance).move_to(*
this);
19797 template<
typename t>
19799 const Tfloat tolerance=0)
const {
19801 cimg_for(connectivity_mask,ptr,t)
if (*ptr) ++nb;
19802 CImg<intT> dx(nb,1,1,1,0), dy(nb,1,1,1,0), dz(nb,1,1,1,0);
19804 cimg_forXYZ(connectivity_mask,x,y,z)
if ((x || y || z) &&
19805 connectivity_mask(x,y,z)) {
19806 dx[nb] = x; dy[nb] = y; dz[nb++] = z;
19808 return _get_label(nb,dx,dy,dz,tolerance);
19812 *
const dx,
const int *
const dy,
const int *
const dz,
19813 const Tfloat tolerance)
const {
19815 cimg_forC(*
this,c) {
19819 unsigned long *ptr = _res.data();
19820 cimg_foroff(_res,p) *(ptr++) = p;
19823 for (
unsigned int n = 0; n<nb; ++n) {
19824 const int _dx = dx[n], _dy = dy[n], _dz = dz[n];
19825 if (_dx || _dy || _dz) {
19828 x1 = _dx<0?_width:_width - _dx,
19830 y1 = _dy<0?_height:_height - _dy,
19832 z1 = _dz<0?_depth:_depth - _dz;
19833 const long wh = (long)_width*_height, offset = (
long)_dz*wh + (long)_dy*_width + _dx;
19834 for (
long z = z0, nz = z0 + _dz, pz = z0*wh; z<z1; ++z, ++nz, pz+=wh) {
19835 for (
long y = y0, ny = y0 + _dy, py = y0*_width + pz; y<y1; ++y, ++ny, py+=_width) {
19836 for (
long x = x0, nx = x0 + _dx, p = x0 + py; x<x1; ++x, ++nx, ++p) {
19837 if ((Tfloat)
cimg::abs((*
this)(x,y,z,c,wh)-(*
this)(nx,ny,nz,c,wh))<=tolerance) {
19838 const long q = p +
offset;
19839 unsigned long x, y;
19840 for (x = p<q?q:p, y = p<q?p:q; x!=y && _res[x]!=x; ) { x = _res[x];
if (x<y)
cimg::swap(x,y); }
19841 if (x!=y) _res[x] = y;
19842 for (
unsigned long _p = p; _p!=y; ) {
const unsigned long h = _res[_p]; _res[_p] = y; _p = h; }
19843 for (
unsigned long _q = q; _q!=y; ) {
const unsigned long h = _res[_q]; _res[_q] = y; _q = h; }
19852 unsigned long counter = 0;
19854 cimg_foroff(_res,p) { *ptr = *ptr==p?counter++:_res[*ptr]; ++ptr; }
19860 CImg<T>& _system_strescape() {
19861 #define cimg_system_strescape(c,s) case c : if (p!=ptrs) CImg<T>(ptrs,(unsigned int)(p-ptrs),1,1,1,false).\
19863 CImg<T>(s,(unsigned int)std::strlen(s),1,1,1,false).move_to(list); ptrs = p+1; break
19865 const T *ptrs = _data;
19866 cimg_for(*
this,p,T) switch ((
int)*p) {
19867 cimg_system_strescape(
'\\',
"\\\\");
19868 cimg_system_strescape(
'\"',
"\\\"");
19869 cimg_system_strescape(
'!',
"\"\\!\"");
19870 cimg_system_strescape(
'`',
"\\`");
19871 cimg_system_strescape(
'$',
"\\$");
19873 if (ptrs<
end()) CImg<T>(ptrs,(
unsigned int)(
end()-ptrs),1,1,1,
false).move_to(list);
19874 return (list>
'x').move_to(*
this);
19893 colormap.assign(1,256,1,3);
19894 for (
unsigned int index = 0, r = 16; r<256; r+=32)
19895 for (
unsigned int g = 16; g<256; g+=32)
19896 for (
unsigned int b = 32; b<256; b+=64) {
19897 colormap(0,
index,0) = (Tuchar)r;
19898 colormap(0,
index,1) = (Tuchar)g;
19899 colormap(0,
index++,2) = (Tuchar)b;
19916 tmp.get_shared_channel(0).sequence(0,359);
19917 colormap = tmp.HSVtoRGB();
19929 static const unsigned char pal[] = {
19930 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,
19931 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,
19932 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,
19933 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,
19934 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,
19935 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,
19936 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,
19937 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,
19938 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,
19939 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,
19940 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,
19941 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,
19942 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,
19943 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,
19944 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,
19945 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,
19946 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,
19947 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,
19948 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,
19949 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,
19950 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,
19951 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,
19952 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,
19953 23,168,19,50,240,244,185,0,1,144,10,168,31,82,1,13 };
19954 static const CImg<Tuchar> colormap(pal,1,256,1,3,
false);
19967 colormap.assign(1,4,1,3,0);
19968 colormap[1] = colormap[2] = colormap[3] = colormap[6] = colormap[7] = colormap[11] = 255;
19969 colormap.resize(1,256,1,3,3);
19983 if (!colormap) colormap.assign(1,2,1,3).fill(0,255,255,0,255,255).resize(1,256,1,3,3);
19997 colormap.assign(1,4,1,3,0);
19998 colormap[2] = colormap[3] = colormap[5] = colormap[6] = colormap[8] = colormap[9] = 255;
19999 colormap.resize(1,256,1,3,3);
20014 colormap.assign(1,4,1,3,0);
20015 colormap[0] = colormap[1] = colormap[5] = colormap[9] = colormap[10] = 255;
20016 colormap.resize(1,256,1,3,0,2);
20031 colormap.assign(1,8,1,3,0);
20032 colormap[1] = colormap[3] = colormap[5] = colormap[7] =
20033 colormap[10] = colormap[11] = colormap[12] = colormap[13] =
20034 colormap[20] = colormap[21] = colormap[22] = colormap[23] = 255;
20035 colormap.resize(1,256,1,3,3);
20043 cimg_for(*
this,ptr,T) {
20045 sval = (Tfloat)*ptr,
20046 nsval = (sval<0?0:sval>255?255:sval)/255,
20047 val = (Tfloat)(nsval<=0.04045f?nsval/12.92f:std::pow((nsval+0.055f)/(1.055f),2.4f));
20048 *ptr = (T)(val*255);
20060 cimg_for(*
this,ptr,T) {
20062 val = (Tfloat)*ptr,
20063 nval = (val<0?0:val>255?255:val)/255,
20064 sval = (Tfloat)(nval<=0.0031308f?nval*12.92f:1.055f*std::pow(nval,0.416667f)-0.055f);
20065 *ptr = (T)(sval*255);
20079 "RGBtoHSV(): Instance is not a RGB image.",
20082 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20083 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20088 nR = (R<0?0:(R>255?255:R))/255,
20089 nG = (G<0?0:(G>255?255:G))/255,
20090 nB = (B<0?0:(B>255?255:B))/255,
20093 Tfloat H = 0, S = 0;
20096 f = (nR==m)?(nG-nB):((nG==m)?(nB-nR):(nR-nG)),
20097 i = (Tfloat)((nR==m)?3:((nG==m)?5:1));
20119 "HSVtoRGB(): Instance is not a HSV image.",
20122 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20123 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20128 R = 0, G = 0, B = 0;
20129 if (H==0 && S==0) R = G = B = V;
20132 const int i = (int)std::floor(H);
20134 f = (i&1)?(H - i):(1 - H + i),
20139 case 0 : R = V; G = n; B = m;
break;
20140 case 1 : R = n; G = V; B = m;
break;
20141 case 2 : R = m; G = V; B = n;
break;
20142 case 3 : R = m; G = n; B = V;
break;
20143 case 4 : R = n; G = m; B = V;
break;
20144 case 5 : R = V; G = m; B = n;
break;
20147 R*=255; G*=255; B*=255;
20148 *(p1++) = (T)(R<0?0:(R>255?255:R));
20149 *(p2++) = (T)(G<0?0:(G>255?255:G));
20150 *(p3++) = (T)(B<0?0:(B>255?255:B));
20164 "RGBtoHSL(): Instance is not a RGB image.",
20167 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20168 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20173 nR = (R<0?0:(R>255?255:R))/255,
20174 nG = (G<0?0:(G>255?255:G))/255,
20175 nB = (B<0?0:(B>255?255:B))/255,
20179 Tfloat H = 0, S = 0;
20180 if (M==m) H = S = 0;
20183 f = (nR==m)?(nG-nB):((nG==m)?(nB-nR):(nR-nG)),
20184 i = (nR==m)?3.0f:((nG==m)?5.0f:1.0f);
20188 S = (2*L<=1)?((M-m)/(M+m)):((M-m)/(2-M-m));
20206 "HSLtoRGB(): Instance is not a HSL image.",
20209 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20210 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20215 q = 2*L<1?L*(1+S):(L+S-L*S),
20221 ntr = tr<0?tr+1:(tr>1?tr-1:tr),
20222 ntg = tg<0?tg+1:(tg>1?tg-1:tg),
20223 ntb = tb<0?tb+1:(tb>1?tb-1:tb),
20224 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))),
20225 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))),
20226 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)));
20227 *(p1++) = (T)(R<0?0:(R>255?255:R));
20228 *(p2++) = (T)(G<0?0:(G>255?255:G));
20229 *(p3++) = (T)(B<0?0:(B>255?255:B));
20243 "RGBtoHSI(): Instance is not a RGB image.",
20246 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20247 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20252 nR = (R<0?0:(R>255?255:R))/255,
20253 nG = (G<0?0:(G>255?255:G))/255,
20254 nB = (B<0?0:(B>255?255:B))/255,
20256 theta = (Tfloat)(std::acos(0.5f*((nR-nG)+(nR-nB))/std::sqrt(std::pow(nR-nG,2)+(nR-nB)*(nG-nB)))*180/
cimg::PI),
20257 sum = nR + nG + nB;
20258 Tfloat H = 0, S = 0, I = 0;
20259 if (theta>0) H = (nB<=nG)?theta:360-theta;
20260 if (sum>0) S = 1 - 3/sum*m;
20278 "HSItoRGB(): Instance is not a HSI image.",
20281 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20282 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20288 R = 0, G = 0, B = 0;
20291 R = (Tfloat)(I*(1+S*std::cos(H*
cimg::PI/180)/std::cos((60-H)*
cimg::PI/180)));
20293 }
else if (H<240) {
20296 G = (Tfloat)(I*(1+S*std::cos(H*
cimg::PI/180)/std::cos((60-H)*
cimg::PI/180)));
20301 B = (Tfloat)(I*(1+S*std::cos(H*
cimg::PI/180)/std::cos((60-H)*
cimg::PI/180)));
20304 R*=255; G*=255; B*=255;
20305 *(p1++) = (T)(R<0?0:(R>255?255:R));
20306 *(p2++) = (T)(G<0?0:(G>255?255:G));
20307 *(p3++) = (T)(B<0?0:(B>255?255:B));
20321 "RGBtoYCbCr(): Instance is not a RGB image.",
20324 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20325 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20330 Y = (66*R + 129*G + 25*B + 128)/256 + 16,
20331 Cb = (-38*R - 74*G + 112*B + 128)/256 + 128,
20332 Cr = (112*R - 94*G - 18*B + 128)/256 + 128;
20333 *(p1++) = (T)(Y<0?0:(Y>255?255:Y));
20334 *(p2++) = (T)(Cb<0?0:(Cb>255?255:Cb));
20335 *(p3++) = (T)(Cr<0?0:(Cr>255?255:Cr));
20349 "YCbCrtoRGB(): Instance is not a YCbCr image.",
20352 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20353 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20355 Y = (Tfloat)*p1 - 16,
20356 Cb = (Tfloat)*p2 - 128,
20357 Cr = (Tfloat)*p3 - 128,
20358 R = (298*Y + 409*Cr + 128)/256,
20359 G = (298*Y - 100*Cb - 208*Cr + 128)/256,
20360 B = (298*Y + 516*Cb + 128)/256;
20361 *(p1++) = (T)(R<0?0:(R>255?255:R));
20362 *(p2++) = (T)(G<0?0:(G>255?255:G));
20363 *(p3++) = (T)(B<0?0:(B>255?255:B));
20377 "RGBtoYUV(): Instance is not a RGB image.",
20380 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20381 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20383 R = (Tfloat)*p1/255,
20384 G = (Tfloat)*p2/255,
20385 B = (Tfloat)*p3/255,
20386 Y = 0.299f*R + 0.587f*G + 0.114f*B;
20388 *(p2++) = (T)(0.492f*(B-Y));
20389 *(p3++) = (T)(0.877*(R-Y));
20403 "YUVtoRGB(): Instance is not a YUV image.",
20406 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20407 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20412 R = (Y + 1.140f*V)*255,
20413 G = (Y - 0.395f*U - 0.581f*V)*255,
20414 B = (Y + 2.032f*U)*255;
20415 *(p1++) = (T)(R<0?0:(R>255?255:R));
20416 *(p2++) = (T)(G<0?0:(G>255?255:G));
20417 *(p3++) = (T)(B<0?0:(B>255?255:B));
20431 "RGBtoCMY(): Instance is not a RGB image.",
20434 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20435 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20443 *(p1++) = (T)(C<0?0:(C>255?255:C));
20444 *(p2++) = (T)(M<0?0:(M>255?255:M));
20445 *(p3++) = (T)(Y<0?0:(Y>255?255:Y));
20459 "CMYtoRGB(): Instance is not a CMY image.",
20462 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20463 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20471 *(p1++) = (T)(R<0?0:(R>255?255:R));
20472 *(p2++) = (T)(G<0?0:(G>255?255:G));
20473 *(p3++) = (T)(B<0?0:(B>255?255:B));
20492 "CMYtoCMYK(): Instance is not a CMY image.",
20496 const T *ps1 =
data(0,0,0,0), *ps2 =
data(0,0,0,1), *ps3 =
data(0,0,0,2);
20497 Tfloat *pd1 = res.data(0,0,0,0), *pd2 = res.data(0,0,0,1), *pd3 = res.data(0,0,0,2), *pd4 = res.data(0,0,0,3);
20498 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20500 C = (Tfloat)*(ps1++),
20501 M = (Tfloat)*(ps2++),
20502 Y = (Tfloat)*(ps3++),
20504 if (K>=255) C = M = Y = 0;
20505 else {
const Tfloat K1 = 255 - K; C = 255*(C - K)/K1; M = 255*(M - K)/K1; Y = 255*(Y - K)/K1; }
20506 *(pd1++) = (Tfloat)(C<0?0:(C>255?255:C));
20507 *(pd2++) = (Tfloat)(M<0?0:(M>255?255:M));
20508 *(pd3++) = (Tfloat)(Y<0?0:(Y>255?255:Y));
20509 *(pd4++) = (Tfloat)(K<0?0:(K>255?255:K));
20523 "CMYKtoCMY(): Instance is not a CMYK image.",
20527 const T *ps1 =
data(0,0,0,0), *ps2 =
data(0,0,0,1), *ps3 =
data(0,0,0,2), *ps4 =
data(0,0,0,3);
20528 Tfloat *pd1 = res.data(0,0,0,0), *pd2 = res.data(0,0,0,1), *pd3 = res.data(0,0,0,2);
20529 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20531 C = (Tfloat)*(ps1++),
20532 M = (Tfloat)*(ps2++),
20533 Y = (Tfloat)*(ps3++),
20534 K = (Tfloat)*(ps4++),
20539 *(pd1++) = (Tfloat)(nC<0?0:(nC>255?255:nC));
20540 *(pd2++) = (Tfloat)(nM<0?0:(nM>255?255:nM));
20541 *(pd3++) = (Tfloat)(nY<0?0:(nY>255?255:nY));
20553 "RGBtoXYZ(): Instance is not a RGB image.",
20556 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20557 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20559 R = (Tfloat)*p1/255,
20560 G = (Tfloat)*p2/255,
20561 B = (Tfloat)*p3/255;
20562 *(p1++) = (T)(0.412453f*R + 0.357580f*G + 0.180423f*B);
20563 *(p2++) = (T)(0.212671f*R + 0.715160f*G + 0.072169f*B);
20564 *(p3++) = (T)(0.019334f*R + 0.119193f*G + 0.950227f*B);
20578 "XYZtoRGB(): Instance is not a XYZ image.",
20581 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20582 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20584 X = (Tfloat)*p1*255,
20585 Y = (Tfloat)*p2*255,
20586 Z = (Tfloat)*p3*255,
20587 R = 3.240479f*X - 1.537150f*Y - 0.498535f*Z,
20588 G = -0.969256f*X + 1.875992f*Y + 0.041556f*Z,
20589 B = 0.055648f*X - 0.204043f*Y + 1.057311f*Z;
20590 *(p1++) = (T)(R<0?0:(R>255?255:R));
20591 *(p2++) = (T)(G<0?0:(G>255?255:G));
20592 *(p3++) = (T)(B<0?0:(B>255?255:B));
20604 #define _cimg_Labf(x) ((x)>=0.008856f?(std::pow(x,(Tfloat)1/3)):(7.787f*(x)+16.0f/116))
20608 "XYZtoLab(): Instance is not a XYZ image.",
20612 Xn = (Tfloat)(0.412453f + 0.357580f + 0.180423f),
20613 Yn = (Tfloat)(0.212671f + 0.715160f + 0.072169f),
20614 Zn = (Tfloat)(0.019334f + 0.119193f + 0.950227f);
20615 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20616 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20621 XXn = X/Xn, YYn = Y/Yn, ZZn = Z/Zn,
20622 fX = (Tfloat)_cimg_Labf(XXn),
20623 fY = (Tfloat)_cimg_Labf(YYn),
20624 fZ = (Tfloat)_cimg_Labf(ZZn);
20625 *(p1++) = (T)
cimg::max(0.0f,116*fY - 16);
20626 *(p2++) = (T)(500*(fX - fY));
20627 *(p3++) = (T)(200*(fY - fZ));
20639 #define _cimg_Labfi(x) ((x)>=0.206893f?((x)*(x)*(x)):(((x)-16.0f/116)/7.787f))
20643 "LabtoXYZ(): Instance is not a Lab image.",
20647 Xn = (Tfloat)(0.412453f + 0.357580f + 0.180423f),
20648 Yn = (Tfloat)(0.212671f + 0.715160f + 0.072169f),
20649 Zn = (Tfloat)(0.019334f + 0.119193f + 0.950227f);
20650 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20651 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20657 Y = (Tfloat)(Yn*_cimg_Labfi(cY)),
20658 pY = (Tfloat)std::pow(Y/Yn,(Tfloat)1/3),
20679 "XYZtoxyY(): Instance is not a XYZ image.",
20682 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20683 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20689 nsum = sum>0?sum:1;
20690 *(p1++) = (T)(X/nsum);
20691 *(p2++) = (T)(Y/nsum);
20706 "xyYtoXYZ(): Instance is not a xyY image.",
20709 T *p1 =
data(0,0,0,0), *p2 =
data(0,0,0,1), *p3 =
data(0,0,0,2);
20710 for (
unsigned long N = (
unsigned long)_width*_height*_depth; N; --N) {
20716 *(p1++) = (T)(px*Y/ny);
20718 *(p3++) = (T)((1-px-py)*Y/ny);
20800 "RGBtoBayer(): Instance is not a RGB image.",
20803 CImg<T> res(_width,_height,_depth,1);
20804 const T *ptr_r =
data(0,0,0,0), *ptr_g =
data(0,0,0,1), *ptr_b =
data(0,0,0,2);
20805 T *ptrd = res._data;
20806 cimg_forXYZ(*
this,x,y,z) {
20808 if (x%2) *(ptrd++) = *ptr_b;
20809 else *(ptrd++) = *ptr_g;
20811 if (x%2) *(ptrd++) = *ptr_g;
20812 else *(ptrd++) = *ptr_r;
20814 ++ptr_r; ++ptr_g; ++ptr_b;
20828 "BayertoRGB(): Instance is not a Bayer image.",
20833 Tuchar *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1), *ptr_b = res.data(0,0,0,2);
20834 switch (interpolation_type) {
20839 cimg_forXYZ(*
this,x,y,z) {
20840 const int _p1x = x?x-1:1, _p1y = y?y-1:1, _n1x = x<
width()-1?x+1:x-1, _n1y = y<
height()-1?y+1:y-1;
20841 cimg_get3x3(*
this,x,y,z,0,I,T);
20847 cx = 1/(1+alpha), cy = 1/(1+beta);
20848 *ptr_g = (Tuchar)((cx*(Inc+Ipc) + cy*(Icn+Icp))/(2*(cx+cy)));
20849 }
else *ptr_g = (Tuchar)Icc;
20851 if (x%2) *ptr_g = (Tuchar)Icc;
20856 cx = 1/(1+alpha), cy = 1/(1+beta);
20857 *ptr_g = (Tuchar)((cx*(Inc+Ipc) + cy*(Icn+Icp))/(2*(cx+cy)));
20862 cimg_forXYZ(*
this,x,y,z) {
20863 const int _p1x = x?x-1:1, _p1y = y?y-1:1, _n1x = x<
width()-1?x+1:x-1, _n1y = y<
height()-1?y+1:y-1;
20864 cimg_get3x3(*
this,x,y,z,0,I,T);
20865 cimg_get3x3(res,x,y,z,1,G,T);
20867 if (x%2) *ptr_b = (Tuchar)Icc;
20868 else { *ptr_r = (Tuchar)((Icn+Icp)/2); *ptr_b = (Tuchar)((Inc+Ipc)/2); }
20870 if (x%2) { *ptr_r = (Tuchar)((Inc+Ipc)/2); *ptr_b = (Tuchar)((Icn+Icp)/2); }
20871 else *ptr_r = (Tuchar)Icc;
20875 ptr_r = res.data(0,0,0,0);
20876 ptr_g = res.data(0,0,0,1);
20877 ptr_b = res.data(0,0,0,2);
20878 cimg_forXYZ(*
this,x,y,z) {
20879 const int _p1x = x?x-1:1, _p1y = y?y-1:1, _n1x = x<
width()-1?x+1:x-1, _n1y = y<
height()-1?y+1:y-1;
20880 cimg_get3x3(res,x,y,z,0,R,T);
20881 cimg_get3x3(res,x,y,z,1,G,T);
20882 cimg_get3x3(res,x,y,z,2,B,T);
20888 cx = 1/(1+alpha), cy = 1/(1+beta);
20889 *ptr_r = (Tuchar)((cx*(Rnc+Rpc) + cy*(Rcn+Rcp))/(2*(cx+cy)));
20896 cx = 1/(1+alpha), cy = 1/(1+beta);
20897 *ptr_b = (Tuchar)((cx*(Bnc+Bpc) + cy*(Bcn+Bcp))/(2*(cx+cy)));
20900 ++ptr_r; ++ptr_g; ++ptr_b;
20904 cimg_forXYZ(*
this,x,y,z) {
20905 const int _p1x = x?x-1:1, _p1y = y?y-1:1, _n1x = x<
width()-1?x+1:x-1, _n1y = y<
height()-1?y+1:y-1;
20906 cimg_get3x3(*
this,x,y,z,0,I,T);
20909 *ptr_r = (Tuchar)((Ipp+Inn+Ipn+Inp)/4); *ptr_g = (Tuchar)((Inc+Ipc+Icn+Icp)/4); *ptr_b = (Tuchar)Icc;
20910 }
else { *ptr_r = (Tuchar)((Icp+Icn)/2); *ptr_g = (Tuchar)Icc; *ptr_b = (Tuchar)((Inc+Ipc)/2); }
20912 if (x%2) { *ptr_r = (Tuchar)((Ipc+Inc)/2); *ptr_g = (Tuchar)Icc; *ptr_b = (Tuchar)((Icn+Icp)/2); }
20914 *ptr_r = (Tuchar)Icc; *ptr_g = (Tuchar)((Inc+Ipc+Icn+Icp)/4); *ptr_b = (Tuchar)((Ipp+Inn+Ipn+Inp)/4);
20917 ++ptr_r; ++ptr_g; ++ptr_b;
20921 cimg_forXYZ(*
this,x,y,z) {
20922 const int _p1x = x?x-1:1, _p1y = y?y-1:1, _n1x = x<
width()-1?x+1:x-1, _n1y = y<
height()-1?y+1:y-1;
20923 cimg_get3x3(*
this,x,y,z,0,I,T);
20926 *ptr_r = (Tuchar)
cimg::min(Ipp,Inn,Ipn,Inp);
20927 *ptr_g = (Tuchar)
cimg::min(Inc,Ipc,Icn,Icp);
20928 *ptr_b = (Tuchar)Icc;
20929 }
else { *ptr_r = (Tuchar)
cimg::min(Icn,Icp); *ptr_g = (Tuchar)Icc; *ptr_b = (Tuchar)
cimg::min(Inc,Ipc); }
20931 if (x%2) { *ptr_r = (Tuchar)
cimg::min(Inc,Ipc); *ptr_g = (Tuchar)Icc; *ptr_b = (Tuchar)
cimg::min(Icn,Icp); }
20933 *ptr_r = (Tuchar)Icc;
20934 *ptr_g = (Tuchar)
cimg::min(Inc,Ipc,Icn,Icp);
20935 *ptr_b = (Tuchar)
cimg::min(Ipp,Inn,Ipn,Inp);
20938 ++ptr_r; ++ptr_g; ++ptr_b;
20942 const T *ptrs = _data;
20944 cimg_forXYZ(*
this,x,y,z) {
20945 const T val = *(ptrs++);
20946 if (y%2) {
if (x%2) *ptr_b = val;
else *ptr_g = val; }
else {
if (x%2) *ptr_g = val;
else *ptr_r = val; }
20947 ++ptr_r; ++ptr_g; ++ptr_b;
20961 static float _cimg_lanczos(
const float x) {
20962 if (x<=-2 || x>=2)
return 0;
20963 const float a = (float)
cimg::PI*x, b = 0.5f*a;
20964 return (
float)(x?std::sin(a)*std::sin(b)/(a*b):1);
20990 const int size_z=-100,
const int size_c=-100,
20991 const int interpolation_type=1,
const unsigned int boundary_conditions=0,
20992 const float centering_x = 0,
const float centering_y = 0,
20993 const float centering_z = 0,
const float centering_c = 0) {
20994 if (!size_x || !size_y || !size_z || !size_c)
return assign();
20996 _sx = (
unsigned int)(size_x<0?-size_x*
width()/100:size_x),
20997 _sy = (
unsigned int)(size_y<0?-size_y*
height()/100:size_y),
20998 _sz = (
unsigned int)(size_z<0?-size_z*
depth()/100:size_z),
20999 _sc = (
unsigned int)(size_c<0?-size_c*
spectrum()/100:size_c),
21000 sx = _sx?_sx:1, sy = _sy?_sy:1, sz = _sz?_sz:1, sc = _sc?_sc:1;
21001 if (sx==_width && sy==_height && sz==_depth && sc==_spectrum)
return *
this;
21003 if (interpolation_type==-1 && sx*sy*sz*sc==
size()) {
21004 _width = sx; _height = sy; _depth = sz; _spectrum = sc;
21007 return get_resize(sx,sy,sz,sc,interpolation_type,boundary_conditions,
21008 centering_x,centering_y,centering_z,centering_c).move_to(*
this);
21013 const int size_z = -100,
const int size_c = -100,
21014 const int interpolation_type=1,
const unsigned int boundary_conditions=0,
21015 const float centering_x = 0,
const float centering_y = 0,
21016 const float centering_z = 0,
const float centering_c = 0)
const {
21017 if (centering_x<0 || centering_x>1 || centering_y<0 || centering_y>1 ||
21018 centering_z<0 || centering_z>1 || centering_c<0 || centering_c>1)
21020 "resize(): Specified centering arguments (%g,%g,%g,%g) are outside range [0,1].",
21022 centering_x,centering_y,centering_z,centering_c);
21024 if (!size_x || !size_y || !size_z || !size_c)
return CImg<T>();
21026 _sx = (
unsigned int)(size_x<0?-size_x*
width()/100:size_x),
21027 _sy = (
unsigned int)(size_y<0?-size_y*
height()/100:size_y),
21028 _sz = (
unsigned int)(size_z<0?-size_z*
depth()/100:size_z),
21029 _sc = (
unsigned int)(size_c<0?-size_c*
spectrum()/100:size_c),
21030 sx = _sx?_sx:1, sy = _sy?_sy:1, sz = _sz?_sz:1, sc = _sc?_sc:1;
21031 if (sx==_width && sy==_height && sz==_depth && sc==_spectrum)
return +*
this;
21035 switch (interpolation_type) {
21040 std::memcpy(res.assign(sx,sy,sz,sc,0)._data,_data,
sizeof(T)*
cimg::min(
size(),sx*sy*sz*sc));
21047 xc = (int)(centering_x*((
int)sx -
width())),
21048 yc = (
int)(centering_y*((int)sy -
height())),
21049 zc = (int)(centering_z*((
int)sz -
depth())),
21050 cc = (int)(centering_c*((
int)sc -
spectrum()));
21052 switch (boundary_conditions) {
21054 res.assign(sx,sy,sz,sc);
21060 #ifdef cimg_use_openmp
21061 #pragma omp parallel for collapse(3) if (res.size()>=65536)
21063 for (
int c = c0; c<(int)sc; c+=
spectrum())
21064 for (
int z = z0; z<(int)sz; z+=
depth())
21065 for (
int y = y0; y<(int)sy; y+=
height())
21066 for (
int x = x0; x<(int)sx; x+=
width())
21067 res.draw_image(x,y,z,c,*
this);
21070 res.assign(sx,sy,sz,sc).draw_image(xc,yc,zc,cc,*
this);
21074 for (
int x = xc-1; x>=0; --x) res.draw_image(x,yc,zc,cc,sprite);
21076 if (xc+
width()<(
int)sx) {
21078 for (
int x = xc+
width(); x<(int)sx; ++x) res.draw_image(x,yc,zc,cc,sprite);
21081 res.get_crop(0,yc,zc,cc,sx-1,yc,zc+
depth()-1,cc+
spectrum()-1).move_to(sprite);
21082 for (
int y = yc-1; y>=0; --y) res.draw_image(0,y,zc,cc,sprite);
21084 if (yc+
height()<(
int)sy) {
21086 for (
int y = yc+
height(); y<(int)sy; ++y) res.draw_image(0,y,zc,cc,sprite);
21089 res.get_crop(0,0,zc,cc,sx-1,sy-1,zc,cc+
spectrum()-1).move_to(sprite);
21090 for (
int z = zc-1; z>=0; --z) res.draw_image(0,0,z,cc,sprite);
21092 if (zc+
depth()<(
int)sz) {
21093 res.get_crop(0,0,zc+
depth()-1,cc,sx-1,sy-1,zc+
depth()-1,cc+
spectrum()-1).move_to(sprite);
21094 for (
int z = zc+
depth(); z<(int)sz; ++z) res.draw_image(0,0,z,cc,sprite);
21097 res.get_crop(0,0,0,cc,sx-1,sy-1,sz-1,cc).move_to(sprite);
21098 for (
int c = cc-1; c>=0; --c) res.draw_image(0,0,0,c,sprite);
21101 res.get_crop(0,0,0,cc+
spectrum()-1,sx-1,sy-1,sz-1,cc+
spectrum()-1).move_to(sprite);
21102 for (
int c = cc+
spectrum(); c<(int)sc; ++c) res.draw_image(0,0,0,c,sprite);
21106 res.assign(sx,sy,sz,sc,0).draw_image(xc,yc,zc,cc,*
this);
21114 res.assign(sx,sy,sz,sc);
21115 CImg<ulongT> off_x(sx), off_y(sy+1), off_z(sz+1), off_c(sc+1);
21116 const unsigned long
21117 wh = (
unsigned long)_width*_height,
21118 whd = (
unsigned long)_width*_height*_depth,
21119 sxy = (
unsigned long)sx*sy,
21120 sxyz = (
unsigned long)sx*sy*sz;
21121 if (sx==_width) off_x.fill(1);
21123 unsigned long *poff_x = off_x._data, curr = 0;
21124 cimg_forX(res,x) {
const unsigned long old = curr; curr = ((x+1LU)*_width/sx); *(poff_x++) = curr - old; }
21126 if (sy==_height) off_y.fill(_width);
21128 unsigned long *poff_y = off_y._data, curr = 0;
21130 const unsigned long old = curr;
21131 curr = ((y+1LU)*_height/sy);
21132 *(poff_y++) = _width*(curr - old);
21136 if (sz==_depth) off_z.fill(wh);
21138 unsigned long *poff_z = off_z._data, curr = 0;
21140 const unsigned long old = curr;
21141 curr = ((z+1LU)*_depth/sz);
21142 *(poff_z++) = wh*(curr - old);
21146 if (sc==_spectrum) off_c.fill(whd);
21148 unsigned long *poff_c = off_c._data, curr = 0;
21150 const unsigned long old = curr;
21151 curr = ((c+1LU)*_spectrum/sc);
21152 *(poff_c++) = whd*(curr - old);
21157 T *ptrd = res._data;
21158 const T* ptrc = _data;
21159 const unsigned long *poff_c = off_c._data;
21160 for (
unsigned int c = 0; c<sc; ) {
21161 const T *ptrz = ptrc;
21162 const unsigned long *poff_z = off_z._data;
21163 for (
unsigned int z = 0; z<sz; ) {
21164 const T *ptry = ptrz;
21165 const unsigned long *poff_y = off_y._data;
21166 for (
unsigned int y = 0; y<sy; ) {
21167 const T *ptrx = ptry;
21168 const unsigned long *poff_x = off_x._data;
21169 cimg_forX(res,x) { *(ptrd++) = *ptrx; ptrx+=*(poff_x++); }
21171 unsigned long dy = *(poff_y++);
21172 for (;!dy && y<dy; std::memcpy(ptrd,ptrd - sx,
sizeof(T)*sx), ++y, ptrd+=sx, dy = *(poff_y++)) {}
21176 unsigned long dz = *(poff_z++);
21177 for (;!dz && z<dz; std::memcpy(ptrd,ptrd-sxy,
sizeof(T)*sxy), ++z, ptrd+=sxy, dz = *(poff_z++)) {}
21181 unsigned long dc = *(poff_c++);
21182 for (;!dc && c<dc; std::memcpy(ptrd,ptrd-sxyz,
sizeof(T)*sxyz), ++c, ptrd+=sxyz, dc = *(poff_c++)) {}
21190 bool instance_first =
true;
21193 for (
unsigned int a = _width*sx, b = _width, c = sx, s = 0, t = 0; a; ) {
21196 cimg_forYZC(tmp,y,z,v) tmp(t,y,z,v)+=(Tfloat)(*
this)(s,y,z,v)*d;
21198 cimg_forYZC(tmp,y,z,v) tmp(t,y,z,v)/=_width;
21202 if (!c) { ++s; c = sx; }
21205 instance_first =
false;
21209 for (
unsigned int a = _height*sy, b = _height, c = sy, s = 0, t = 0; a; ) {
21212 if (instance_first)
21213 cimg_forXZC(tmp,x,z,v) tmp(x,t,z,v)+=(Tfloat)(*
this)(x,s,z,v)*d;
21215 cimg_forXZC(tmp,x,z,v) tmp(x,t,z,v)+=(Tfloat)res(x,s,z,v)*d;
21217 cimg_forXZC(tmp,x,z,v) tmp(x,t,z,v)/=_height;
21221 if (!c) { ++s; c = sy; }
21224 instance_first =
false;
21228 for (
unsigned int a = _depth*sz, b = _depth, c = sz, s = 0, t = 0; a; ) {
21231 if (instance_first)
21232 cimg_forXYC(tmp,x,y,v) tmp(x,y,t,v)+=(Tfloat)(*
this)(x,y,s,v)*d;
21234 cimg_forXYC(tmp,x,y,v) tmp(x,y,t,v)+=(Tfloat)res(x,y,s,v)*d;
21236 cimg_forXYC(tmp,x,y,v) tmp(x,y,t,v)/=_depth;
21240 if (!c) { ++s; c = sz; }
21243 instance_first =
false;
21245 if (sc!=_spectrum) {
21247 for (
unsigned int a = _spectrum*sc, b = _spectrum, c = sc, s = 0, t = 0; a; ) {
21250 if (instance_first)
21251 cimg_forXYZ(tmp,x,y,z) tmp(x,y,z,t)+=(Tfloat)(*
this)(x,y,z,s)*d;
21253 cimg_forXYZ(tmp,x,y,z) tmp(x,y,z,t)+=(Tfloat)res(x,y,z,s)*d;
21255 cimg_forXYZ(tmp,x,y,z) tmp(x,y,z,t)/=_spectrum;
21259 if (!c) { ++s; c = sc; }
21262 instance_first =
false;
21271 CImg<T> resx, resy, resz, resc;
21274 if (_width==1)
get_resize(sx,_height,_depth,_spectrum,1).move_to(resx);
21276 if (_width>sx)
get_resize(sx,_height,_depth,_spectrum,2).move_to(resx);
21278 const float fx = (!boundary_conditions && sx>_width)?(sx>1?(_width-1.0f)/(sx-1):0):(float)_width/sx;
21279 resx.assign(sx,_height,_depth,_spectrum);
21280 float curr = 0, old = 0;
21281 unsigned int *poff = off._data;
21282 float *pfoff = foff._data;
21283 cimg_forX(resx,x) {
21284 *(pfoff++) = curr - (
unsigned int)curr;
21287 *(poff++) = (
unsigned int)curr - (
unsigned int)old;
21289 #ifdef cimg_use_openmp
21290 #pragma omp parallel for collapse(3) if (resx.size()>=65536)
21292 cimg_forYZC(resx,y,z,c) {
21293 const T *ptrs =
data(0,y,z,c), *
const ptrsmax = ptrs + (_width-1);
21294 T *ptrd = resx.data(0,y,z,c);
21295 const unsigned int *poff = off._data;
21296 const float *pfoff = foff._data;
21297 cimg_forX(resx,x) {
21298 const float alpha = *(pfoff++);
21299 const T val1 = *ptrs, val2 = ptrs<ptrsmax?*(ptrs+1):val1;
21300 *(ptrd++) = (T)((1-alpha)*val1 + alpha*val2);
21306 }
else resx.assign(*
this,
true);
21309 if (_height==1) resx.get_resize(sx,sy,_depth,_spectrum,1).move_to(resy);
21311 if (_height>sy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy);
21313 const float fy = (!boundary_conditions && sy>_height)?(sy>1?(_height-1.0f)/(sy-1):0):(float)_height/sy;
21314 resy.assign(sx,sy,_depth,_spectrum);
21315 float curr = 0, old = 0;
21316 unsigned int *poff = off._data;
21317 float *pfoff = foff._data;
21318 cimg_forY(resy,y) {
21319 *(pfoff++) = curr - (
unsigned int)curr;
21322 *(poff++) = sx*((
unsigned int)curr-(
unsigned int)old);
21324 #ifdef cimg_use_openmp
21325 #pragma omp parallel for collapse(3) if (resy.size()>=65536)
21327 cimg_forXZC(resy,x,z,c) {
21328 const T *ptrs = resx.data(x,0,z,c), *
const ptrsmax = ptrs + (_height-1)*sx;
21329 T *ptrd = resy.data(x,0,z,c);
21330 const unsigned int *poff = off._data;
21331 const float *pfoff = foff._data;
21332 cimg_forY(resy,y) {
21333 const float alpha = *(pfoff++);
21334 const T val1 = *ptrs, val2 = ptrs<ptrsmax?*(ptrs+sx):val1;
21335 *ptrd = (T)((1-alpha)*val1 + alpha*val2);
21343 }
else resy.assign(resx,
true);
21346 if (_depth==1) resy.get_resize(sx,sy,sz,_spectrum,1).move_to(resz);
21348 if (_depth>sz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz);
21350 const float fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth-1.0f)/(sz-1):0):(float)_depth/sz;
21351 const unsigned int sxy = sx*sy;
21352 resz.assign(sx,sy,sz,_spectrum);
21353 float curr = 0, old = 0;
21354 unsigned int *poff = off._data;
21355 float *pfoff = foff._data;
21356 cimg_forZ(resz,z) {
21357 *(pfoff++) = curr - (
unsigned int)curr;
21360 *(poff++) = sxy*((
unsigned int)curr - (
unsigned int)old);
21362 #ifdef cimg_use_openmp
21363 #pragma omp parallel for collapse(3) if (resz.size()>=65536)
21365 cimg_forXYC(resz,x,y,c) {
21366 const T *ptrs = resy.data(x,y,0,c), *
const ptrsmax = ptrs + (_depth-1)*sxy;
21367 T *ptrd = resz.data(x,y,0,c);
21368 const unsigned int *poff = off._data;
21369 const float *pfoff = foff._data;
21370 cimg_forZ(resz,z) {
21371 const float alpha = *(pfoff++);
21372 const T val1 = *ptrs, val2 = ptrs<ptrsmax?*(ptrs+sxy):val1;
21373 *ptrd = (T)((1-alpha)*val1 + alpha*val2);
21381 }
else resz.assign(resy,
true);
21383 if (sc!=_spectrum) {
21384 if (_spectrum==1) resz.get_resize(sx,sy,sz,sc,1).move_to(resc);
21386 if (_spectrum>sc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc);
21388 const float fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum-1.0f)/(sc-1):0):
21389 (float)_spectrum/sc;
21390 const unsigned int sxyz = sx*sy*sz;
21391 resc.assign(sx,sy,sz,sc);
21392 float curr = 0, old = 0;
21393 unsigned int *poff = off._data;
21394 float *pfoff = foff._data;
21395 cimg_forC(resc,c) {
21396 *(pfoff++) = curr - (
unsigned int)curr;
21399 *(poff++) = sxyz*((
unsigned int)curr - (
unsigned int)old);
21401 #ifdef cimg_use_openmp
21402 #pragma omp parallel for collapse(3) if (resc.size()>=65536)
21404 cimg_forXYZ(resc,x,y,z) {
21405 const T *ptrs = resz.data(x,y,z,0), *
const ptrsmax = ptrs + (_spectrum-1)*sxyz;
21406 T *ptrd = resc.data(x,y,z,0);
21407 const unsigned int *poff = off._data;
21408 const float *pfoff = foff._data;
21409 cimg_forC(resc,c) {
21410 const float alpha = *(pfoff++);
21411 const T val1 = *ptrs, val2 = ptrs<ptrsmax?*(ptrs+sxyz):val1;
21412 *ptrd = (T)((1-alpha)*val1 + alpha*val2);
21420 }
else resc.assign(resz,
true);
21421 return resc._is_shared?(resz._is_shared?(resy._is_shared?(resx._is_shared?(+(*this)):resx):resy):resz):resc;
21427 CImg<T> resx, resy, resz, resc;
21429 if (sx<_width)
get_resize(sx,_height,_depth,_spectrum,1).move_to(resx);
21431 resx.assign(sx,_height,_depth,_spectrum,0);
21432 const int dx = sx*2, dy =
width()*2;
21433 int err = (int)(dy + centering_x*(sx*dy/
width() - dy)), xs = 0;
21434 cimg_forX(resx,x)
if ((err-=dy)<=0) {
21435 cimg_forYZC(resx,y,z,c) resx(x,y,z,c) = (*this)(xs,y,z,c);
21440 }
else resx.assign(*
this,
true);
21443 if (sy<_height) resx.get_resize(sx,sy,_depth,_spectrum,1).move_to(resy);
21445 resy.assign(sx,sy,_depth,_spectrum,0);
21446 const int dx = sy*2, dy =
height()*2;
21447 int err = (int)(dy + centering_y*(sy*dy/
height() - dy)), ys = 0;
21448 cimg_forY(resy,y)
if ((err-=dy)<=0) {
21449 cimg_forXZC(resy,x,z,c) resy(x,y,z,c) = resx(x,ys,z,c);
21455 }
else resy.assign(resx,
true);
21458 if (sz<_depth) resy.get_resize(sx,sy,sz,_spectrum,1).move_to(resz);
21460 resz.assign(sx,sy,sz,_spectrum,0);
21461 const int dx = sz*2, dy =
depth()*2;
21462 int err = (int)(dy + centering_z*(sz*dy/
depth() - dy)), zs = 0;
21463 cimg_forZ(resz,z)
if ((err-=dy)<=0) {
21464 cimg_forXYC(resz,x,y,c) resz(x,y,z,c) = resy(x,y,zs,c);
21470 }
else resz.assign(resy,
true);
21472 if (sc!=_spectrum) {
21473 if (sc<_spectrum) resz.get_resize(sx,sy,sz,sc,1).move_to(resc);
21475 resc.assign(sx,sy,sz,sc,0);
21476 const int dx = sc*2, dy =
spectrum()*2;
21477 int err = (int)(dy + centering_c*(sc*dy/
spectrum() - dy)), cs = 0;
21478 cimg_forC(resc,c)
if ((err-=dy)<=0) {
21479 cimg_forXYZ(resc,x,y,z) resc(x,y,z,c) = resz(x,y,z,cs);
21485 }
else resc.assign(resz,
true);
21487 return resc._is_shared?(resz._is_shared?(resy._is_shared?(resx._is_shared?(+(*this)):resx):resy):resz):resc;
21496 CImg<T> resx, resy, resz, resc;
21499 if (_width==1)
get_resize(sx,_height,_depth,_spectrum,1).move_to(resx);
21501 if (_width>sx)
get_resize(sx,_height,_depth,_spectrum,2).move_to(resx);
21503 const float fx = (!boundary_conditions && sx>_width)?(sx>1?(_width-1.0f)/(sx-1):0):(float)_width/sx;
21504 resx.assign(sx,_height,_depth,_spectrum);
21505 float curr = 0, old = 0;
21506 unsigned int *poff = off._data;
21507 float *pfoff = foff._data;
21508 cimg_forX(resx,x) {
21509 *(pfoff++) = curr - (
unsigned int)curr;
21512 *(poff++) = (
unsigned int)curr - (
unsigned int)old;
21514 #ifdef cimg_use_openmp
21515 #pragma omp parallel for collapse(3) if (resx.size()>=65536)
21517 cimg_forYZC(resx,y,z,c) {
21518 const T *
const ptrs0 =
data(0,y,z,c), *ptrs = ptrs0, *
const ptrsmax = ptrs + (_width-2);
21519 T *ptrd = resx.data(0,y,z,c);
21520 const unsigned int *poff = off._data;
21521 const float *pfoff = foff._data;
21522 cimg_forX(resx,x) {
21523 const float t = *(pfoff++);
21525 val1 = (Tfloat)*ptrs,
21526 val0 = ptrs>ptrs0?(Tfloat)*(ptrs-1):val1,
21527 val2 = ptrs<=ptrsmax?(Tfloat)*(ptrs+1):val1,
21528 val3 = ptrs<ptrsmax?(Tfloat)*(ptrs+2):val2,
21529 val = val1 + 0.5f*(t*(-val0+val2) + t*t*(2*val0-5*val1+4*val2-val3) +
21530 t*t*t*(-val0+3*val1-3*val2+val3));
21531 *(ptrd++) = (T)(val<vmin?vmin:val>vmax?vmax:val);
21537 }
else resx.assign(*
this,
true);
21540 if (_height==1) resx.get_resize(sx,sy,_depth,_spectrum,1).move_to(resy);
21542 if (_height>sy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy);
21544 const float fy = (!boundary_conditions && sy>_height)?(sy>1?(_height-1.0f)/(sy-1):0):(float)_height/sy;
21545 resy.assign(sx,sy,_depth,_spectrum);
21546 float curr = 0, old = 0;
21547 unsigned int *poff = off._data;
21548 float *pfoff = foff._data;
21549 cimg_forY(resy,y) {
21550 *(pfoff++) = curr - (
unsigned int)curr;
21553 *(poff++) = sx*((
unsigned int)curr-(
unsigned int)old);
21555 #ifdef cimg_use_openmp
21556 #pragma omp parallel for collapse(3) if (resy.size()>=65536)
21558 cimg_forXZC(resy,x,z,c) {
21559 const T *
const ptrs0 = resx.data(x,0,z,c), *ptrs = ptrs0, *
const ptrsmax = ptrs + (_height-2)*sx;
21560 T *ptrd = resy.data(x,0,z,c);
21561 const unsigned int *poff = off._data;
21562 const float *pfoff = foff._data;
21563 cimg_forY(resy,y) {
21564 const float t = *(pfoff++);
21566 val1 = (Tfloat)*ptrs,
21567 val0 = ptrs>ptrs0?(Tfloat)*(ptrs-sx):val1,
21568 val2 = ptrs<=ptrsmax?(Tfloat)*(ptrs+sx):val1,
21569 val3 = ptrs<ptrsmax?(Tfloat)*(ptrs+2*sx):val2,
21570 val = val1 + 0.5f*(t*(-val0+val2) + t*t*(2*val0-5*val1+4*val2-val3) +
21571 t*t*t*(-val0+3*val1-3*val2+val3));
21572 *ptrd = (T)(val<vmin?vmin:val>vmax?vmax:val);
21580 }
else resy.assign(resx,
true);
21583 if (_depth==1) resy.get_resize(sx,sy,sz,_spectrum,1).move_to(resz);
21585 if (_depth>sz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz);
21587 const float fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth-1.0f)/(sz-1):0):(float)_depth/sz;
21588 const unsigned int sxy = sx*sy;
21589 resz.assign(sx,sy,sz,_spectrum);
21590 float curr = 0, old = 0;
21591 unsigned int *poff = off._data;
21592 float *pfoff = foff._data;
21593 cimg_forZ(resz,z) {
21594 *(pfoff++) = curr - (
unsigned int)curr;
21597 *(poff++) = sxy*((
unsigned int)curr - (
unsigned int)old);
21599 #ifdef cimg_use_openmp
21600 #pragma omp parallel for collapse(3) if (resz.size()>=65536)
21602 cimg_forXYC(resz,x,y,c) {
21603 const T *
const ptrs0 = resy.data(x,y,0,c), *ptrs = ptrs0, *
const ptrsmax = ptrs + (_depth-2)*sxy;
21604 T *ptrd = resz.data(x,y,0,c);
21605 const unsigned int *poff = off._data;
21606 const float *pfoff = foff._data;
21607 cimg_forZ(resz,z) {
21608 const float t = *(pfoff++);
21610 val1 = (Tfloat)*ptrs,
21611 val0 = ptrs>ptrs0?(Tfloat)*(ptrs-sxy):val1,
21612 val2 = ptrs<=ptrsmax?(Tfloat)*(ptrs+sxy):val1,
21613 val3 = ptrs<ptrsmax?(Tfloat)*(ptrs+2*sxy):val2,
21614 val = val1 + 0.5f*(t*(-val0+val2) + t*t*(2*val0-5*val1+4*val2-val3) +
21615 t*t*t*(-val0+3*val1-3*val2+val3));
21616 *ptrd = (T)(val<vmin?vmin:val>vmax?vmax:val);
21624 }
else resz.assign(resy,
true);
21626 if (sc!=_spectrum) {
21627 if (_spectrum==1) resz.get_resize(sx,sy,sz,sc,1).move_to(resc);
21629 if (_spectrum>sc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc);
21631 const float fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum-1.0f)/(sc-1):0):
21632 (float)_spectrum/sc;
21633 const unsigned int sxyz = sx*sy*sz;
21634 resc.assign(sx,sy,sz,sc);
21635 float curr = 0, old = 0;
21636 unsigned int *poff = off._data;
21637 float *pfoff = foff._data;
21638 cimg_forC(resc,c) {
21639 *(pfoff++) = curr - (
unsigned int)curr;
21642 *(poff++) = sxyz*((
unsigned int)curr - (
unsigned int)old);
21644 #ifdef cimg_use_openmp
21645 #pragma omp parallel for collapse(3) if (resc.size()>=65536)
21647 cimg_forXYZ(resc,x,y,z) {
21648 const T *
const ptrs0 = resz.data(x,y,z,0), *ptrs = ptrs0, *
const ptrsmax = ptrs + (_spectrum-2)*sxyz;
21649 T *ptrd = resc.data(x,y,z,0);
21650 const unsigned int *poff = off._data;
21651 const float *pfoff = foff._data;
21652 cimg_forC(resc,c) {
21653 const float t = *(pfoff++);
21655 val1 = (Tfloat)*ptrs,
21656 val0 = ptrs>ptrs0?(Tfloat)*(ptrs-sxyz):val1,
21657 val2 = ptrs<=ptrsmax?(Tfloat)*(ptrs+sxyz):val1,
21658 val3 = ptrs<ptrsmax?(Tfloat)*(ptrs+2*sxyz):val2,
21659 val = val1 + 0.5f*(t*(-val0+val2) + t*t*(2*val0-5*val1+4*val2-val3) +
21660 t*t*t*(-val0+3*val1-3*val2+val3));
21661 *ptrd = (T)(val<vmin?vmin:val>vmax?vmax:val);
21669 }
else resc.assign(resz,
true);
21671 return resc._is_shared?(resz._is_shared?(resy._is_shared?(resx._is_shared?(+(*this)):resx):resy):resz):resc;
21680 CImg<T> resx, resy, resz, resc;
21683 if (_width==1)
get_resize(sx,_height,_depth,_spectrum,1).move_to(resx);
21685 if (_width>sx)
get_resize(sx,_height,_depth,_spectrum,2).move_to(resx);
21687 const float fx = (!boundary_conditions && sx>_width)?(sx>1?(_width-1.0f)/(sx-1):0):(float)_width/sx;
21688 resx.assign(sx,_height,_depth,_spectrum);
21689 float curr = 0, old = 0;
21690 unsigned int *poff = off._data;
21691 float *pfoff = foff._data;
21692 cimg_forX(resx,x) {
21693 *(pfoff++) = curr - (
unsigned int)curr;
21696 *(poff++) = (
unsigned int)curr - (
unsigned int)old;
21698 #ifdef cimg_use_openmp
21699 #pragma omp parallel for collapse(3) if (resx.size()>=65536)
21701 cimg_forYZC(resx,y,z,c) {
21702 const T *
const ptrs0 =
data(0,y,z,c), *ptrs = ptrs0, *
const ptrsmin = ptrs0 + 1,
21703 *
const ptrsmax = ptrs0 + (_width-2);
21704 T *ptrd = resx.data(0,y,z,c);
21705 const unsigned int *poff = off._data;
21706 const float *pfoff = foff._data;
21707 cimg_forX(resx,x) {
21710 w0 = _cimg_lanczos(t+2),
21711 w1 = _cimg_lanczos(t+1),
21712 w2 = _cimg_lanczos(t),
21713 w3 = _cimg_lanczos(t-1),
21714 w4 = _cimg_lanczos(t-2);
21716 val2 = (Tfloat)*ptrs,
21717 val1 = ptrs>=ptrsmin?(Tfloat)*(ptrs-1):val2,
21718 val0 = ptrs>ptrsmin?(Tfloat)*(ptrs-2):val1,
21719 val3 = ptrs<=ptrsmax?(Tfloat)*(ptrs+1):val2,
21720 val4 = ptrs<ptrsmax?(Tfloat)*(ptrs+2):val3,
21721 val = (val0*w0 + val1*w1 + val2*w2 + val3*w3 + val4*w4)/(w1 + w2 + w3 + w4);
21722 *(ptrd++) = (T)(val<vmin?vmin:val>vmax?vmax:val);
21728 }
else resx.assign(*
this,
true);
21731 if (_height==1) resx.get_resize(sx,sy,_depth,_spectrum,1).move_to(resy);
21733 if (_height>sy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy);
21735 const float fy = (!boundary_conditions && sy>_height)?(sy>1?(_height-1.0f)/(sy-1):0):(float)_height/sy;
21736 resy.assign(sx,sy,_depth,_spectrum);
21737 float curr = 0, old = 0;
21738 unsigned int *poff = off._data;
21739 float *pfoff = foff._data;
21740 cimg_forY(resy,y) {
21741 *(pfoff++) = curr - (
unsigned int)curr;
21744 *(poff++) = sx*((
unsigned int)curr-(
unsigned int)old);
21746 #ifdef cimg_use_openmp
21747 #pragma omp parallel for collapse(3) if (resy.size()>=65536)
21749 cimg_forXZC(resy,x,z,c) {
21750 const T *
const ptrs0 = resx.data(x,0,z,c), *ptrs = ptrs0, *
const ptrsmin = ptrs0 + sx,
21751 *
const ptrsmax = ptrs0 + (_height-2)*sx;
21752 T *ptrd = resy.data(x,0,z,c);
21753 const unsigned int *poff = off._data;
21754 const float *pfoff = foff._data;
21755 cimg_forY(resy,y) {
21758 w0 = _cimg_lanczos(t+2),
21759 w1 = _cimg_lanczos(t+1),
21760 w2 = _cimg_lanczos(t),
21761 w3 = _cimg_lanczos(t-1),
21762 w4 = _cimg_lanczos(t-2);
21764 val2 = (Tfloat)*ptrs,
21765 val1 = ptrs>=ptrsmin?(Tfloat)*(ptrs-sx):val2,
21766 val0 = ptrs>ptrsmin?(Tfloat)*(ptrs-2*sx):val1,
21767 val3 = ptrs<=ptrsmax?(Tfloat)*(ptrs+sx):val2,
21768 val4 = ptrs<ptrsmax?(Tfloat)*(ptrs+2*sx):val3,
21769 val = (val0*w0 + val1*w1 + val2*w2 + val3*w3 + val4*w4)/(w1 + w2 + w3 + w4);
21770 *ptrd = (T)(val<vmin?vmin:val>vmax?vmax:val);
21778 }
else resy.assign(resx,
true);
21781 if (_depth==1) resy.get_resize(sx,sy,sz,_spectrum,1).move_to(resz);
21783 if (_depth>sz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz);
21785 const float fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth-1.0f)/(sz-1):0):(float)_depth/sz;
21786 const unsigned int sxy = sx*sy;
21787 resz.assign(sx,sy,sz,_spectrum);
21788 float curr = 0, old = 0;
21789 unsigned int *poff = off._data;
21790 float *pfoff = foff._data;
21791 cimg_forZ(resz,z) {
21792 *(pfoff++) = curr - (
unsigned int)curr;
21795 *(poff++) = sxy*((
unsigned int)curr - (
unsigned int)old);
21797 #ifdef cimg_use_openmp
21798 #pragma omp parallel for collapse(3) if (resz.size()>=65536)
21800 cimg_forXYC(resz,x,y,c) {
21801 const T *
const ptrs0 = resy.data(x,y,0,c), *ptrs = ptrs0, *
const ptrsmin = ptrs0 + sxy,
21802 *
const ptrsmax = ptrs0 + (_depth-2)*sxy;
21803 T *ptrd = resz.data(x,y,0,c);
21804 const unsigned int *poff = off._data;
21805 const float *pfoff = foff._data;
21806 cimg_forZ(resz,z) {
21809 w0 = _cimg_lanczos(t+2),
21810 w1 = _cimg_lanczos(t+1),
21811 w2 = _cimg_lanczos(t),
21812 w3 = _cimg_lanczos(t-1),
21813 w4 = _cimg_lanczos(t-2);
21815 val2 = (Tfloat)*ptrs,
21816 val1 = ptrs>=ptrsmin?(Tfloat)*(ptrs-sxy):val2,
21817 val0 = ptrs>ptrsmin?(Tfloat)*(ptrs-2*sxy):val1,
21818 val3 = ptrs<=ptrsmax?(Tfloat)*(ptrs+sxy):val2,
21819 val4 = ptrs<ptrsmax?(Tfloat)*(ptrs+2*sxy):val3,
21820 val = (val0*w0 + val1*w1 + val2*w2 + val3*w3 + val4*w4)/(w1 + w2 + w3 + w4);
21821 *ptrd = (T)(val<vmin?vmin:val>vmax?vmax:val);
21829 }
else resz.assign(resy,
true);
21831 if (sc!=_spectrum) {
21832 if (_spectrum==1) resz.get_resize(sx,sy,sz,sc,1).move_to(resc);
21834 if (_spectrum>sc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc);
21836 const float fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum-1.0f)/(sc-1):0):
21837 (float)_spectrum/sc;
21838 const unsigned int sxyz = sx*sy*sz;
21839 resc.assign(sx,sy,sz,sc);
21840 float curr = 0, old = 0;
21841 unsigned int *poff = off._data;
21842 float *pfoff = foff._data;
21843 cimg_forC(resc,c) {
21844 *(pfoff++) = curr - (
unsigned int)curr;
21847 *(poff++) = sxyz*((
unsigned int)curr - (
unsigned int)old);
21849 #ifdef cimg_use_openmp
21850 #pragma omp parallel for collapse(3) if (resc.size()>=65536)
21852 cimg_forXYZ(resc,x,y,z) {
21853 const T *
const ptrs0 = resz.data(x,y,z,0), *ptrs = ptrs0, *
const ptrsmin = ptrs0 + sxyz,
21854 *
const ptrsmax = ptrs + (_spectrum-2)*sxyz;
21855 T *ptrd = resc.data(x,y,z,0);
21856 const unsigned int *poff = off._data;
21857 const float *pfoff = foff._data;
21858 cimg_forC(resc,c) {
21861 w0 = _cimg_lanczos(t+2),
21862 w1 = _cimg_lanczos(t+1),
21863 w2 = _cimg_lanczos(t),
21864 w3 = _cimg_lanczos(t-1),
21865 w4 = _cimg_lanczos(t-2);
21867 val2 = (Tfloat)*ptrs,
21868 val1 = ptrs>=ptrsmin?(Tfloat)*(ptrs-sxyz):val2,
21869 val0 = ptrs>ptrsmin?(Tfloat)*(ptrs-2*sxyz):val1,
21870 val3 = ptrs<=ptrsmax?(Tfloat)*(ptrs+sxyz):val2,
21871 val4 = ptrs<ptrsmax?(Tfloat)*(ptrs+2*sxyz):val3,
21872 val = (val0*w0 + val1*w1 + val2*w2 + val3*w3 + val4*w4)/(w1 + w2 + w3 + w4);
21873 *ptrd = (T)(val<vmin?vmin:val>vmax?vmax:val);
21881 }
else resc.assign(resz,
true);
21883 return resc._is_shared?(resz._is_shared?(resy._is_shared?(resx._is_shared?(+(*this)):resx):resy):resz):resc;
21890 "resize(): Invalid specified interpolation %d "
21891 "(should be { -1=raw | 0=none | 1=nearest | 2=average | 3=linear | 4=grid | "
21892 "5=cubic | 6=lanczos }).",
21894 interpolation_type);
21909 template<
typename t>
21911 const int interpolation_type=1,
const unsigned int boundary_conditions=0,
21912 const float centering_x = 0,
const float centering_y = 0,
21913 const float centering_z = 0,
const float centering_c = 0) {
21914 return resize(src._width,src._height,src._depth,src._spectrum,interpolation_type,boundary_conditions,
21915 centering_x,centering_y,centering_z,centering_c);
21919 template<
typename t>
21921 const int interpolation_type=1,
const unsigned int boundary_conditions=0,
21922 const float centering_x = 0,
const float centering_y = 0,
21923 const float centering_z = 0,
const float centering_c = 0)
const {
21924 return get_resize(src._width,src._height,src._depth,src._spectrum,interpolation_type,boundary_conditions,
21925 centering_x,centering_y,centering_z,centering_c);
21939 const int interpolation_type=1,
const unsigned int boundary_conditions=0,
21940 const float centering_x = 0,
const float centering_y = 0,
21941 const float centering_z = 0,
const float centering_c = 0) {
21942 return resize(disp.
width(),disp.
height(),_depth,_spectrum,interpolation_type,boundary_conditions,
21943 centering_x,centering_y,centering_z,centering_c);
21948 const int interpolation_type=1,
const unsigned int boundary_conditions=0,
21949 const float centering_x = 0,
const float centering_y = 0,
21950 const float centering_z = 0,
const float centering_c = 0)
const {
21951 return get_resize(disp.
width(),disp.
height(),_depth,_spectrum,interpolation_type,boundary_conditions,
21952 centering_x,centering_y,centering_z,centering_c);
21963 const Tfloat mask[9] = { 0.07842776544f, 0.1231940459f, 0.07842776544f,
21964 0.1231940459f, 0.1935127547f, 0.1231940459f,
21965 0.07842776544f, 0.1231940459f, 0.07842776544f };
21967 CImg<T> res(_width/2,_height/2,_depth,_spectrum);
21968 T *ptrd = res._data;
21969 cimg_forZC(*
this,z,c) cimg_for3x3(*
this,x,y,z,c,I,T)
21970 if (x%2 && y%2) *(ptrd++) = (T)
21971 (I[0]*mask[0] + I[1]*mask[1] + I[2]*mask[2] +
21972 I[3]*mask[3] + I[4]*mask[4] + I[5]*mask[5] +
21973 I[6]*mask[6] + I[7]*mask[7] + I[8]*mask[8]);
21988 #define _cimg_gs2x_for3(bound,i) \
21989 for (int i = 0, _p1##i = 0, \
21990 _n1##i = 1>=(bound)?(int)(bound)-1:1; \
21991 _n1##i<(int)(bound) || i==--_n1##i; \
21992 _p1##i = i++, ++_n1##i, ptrd1+=(res)._width, ptrd2+=(res)._width)
21994 #define _cimg_gs2x_for3x3(img,x,y,z,c,I,T) \
21995 _cimg_gs2x_for3((img)._height,y) for (int x = 0, \
21998 (I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \
21999 (I[3] = I[4] = (T)(img)(0,y,z,c)), \
22000 (I[7] = (T)(img)(0,_n1##y,z,c)), \
22001 1>=(img)._width?(img).width()-1:1); \
22002 (_n1##x<(img).width() && ( \
22003 (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \
22004 (I[5] = (T)(img)(_n1##x,y,z,c)), \
22005 (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \
22008 I[3] = I[4], I[4] = I[5], \
22010 _p1##x = x++, ++_n1##x)
22013 CImg<T> res(_width<<1,_height<<1,_depth,_spectrum);
22015 cimg_forZC(*
this,z,c) {
22017 *ptrd1 = res.data(0,0,z,c),
22018 *ptrd2 = ptrd1 + res._width;
22019 _cimg_gs2x_for3x3(*
this,x,y,z,c,I,T) {
22020 if (Icp!=Icn && Ipc!=Inc) {
22021 *(ptrd1++) = Ipc==Icp?Ipc:Icc;
22022 *(ptrd1++) = Icp==Inc?Inc:Icc;
22023 *(ptrd2++) = Ipc==Icn?Ipc:Icc;
22024 *(ptrd2++) = Icn==Inc?Inc:Icc;
22025 }
else { *(ptrd1++) = Icc; *(ptrd1++) = Icc; *(ptrd2++) = Icc; *(ptrd2++) = Icc; }
22042 #define _cimg_gs3x_for3(bound,i) \
22043 for (int i = 0, _p1##i = 0, \
22044 _n1##i = 1>=(bound)?(int)(bound)-1:1; \
22045 _n1##i<(int)(bound) || i==--_n1##i; \
22046 _p1##i = i++, ++_n1##i, ptrd1+=2*(res)._width, ptrd2+=2*(res)._width, ptrd3+=2*(res)._width)
22048 #define _cimg_gs3x_for3x3(img,x,y,z,c,I,T) \
22049 _cimg_gs3x_for3((img)._height,y) for (int x = 0, \
22052 (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \
22053 (I[3] = I[4] = (T)(img)(0,y,z,c)), \
22054 (I[6] = I[7] = (T)(img)(0,_n1##y,z,c)), \
22055 1>=(img)._width?(img).width()-1:1); \
22056 (_n1##x<(img).width() && ( \
22057 (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \
22058 (I[5] = (T)(img)(_n1##x,y,z,c)), \
22059 (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \
22061 I[0] = I[1], I[1] = I[2], \
22062 I[3] = I[4], I[4] = I[5], \
22063 I[6] = I[7], I[7] = I[8], \
22064 _p1##x = x++, ++_n1##x)
22067 CImg<T> res(3*_width,3*_height,_depth,_spectrum);
22069 cimg_forZC(*
this,z,c) {
22071 *ptrd1 = res.data(0,0,z,c),
22072 *ptrd2 = ptrd1 + res._width,
22073 *ptrd3 = ptrd2 + res._width;
22074 _cimg_gs3x_for3x3(*
this,x,y,z,c,I,T) {
22075 if (Icp != Icn && Ipc != Inc) {
22076 *(ptrd1++) = Ipc==Icp?Ipc:Icc;
22077 *(ptrd1++) = (Ipc==Icp && Icc!=Inp) || (Icp==Inc && Icc!=Ipp)?Icp:Icc;
22078 *(ptrd1++) = Icp==Inc?Inc:Icc;
22079 *(ptrd2++) = (Ipc==Icp && Icc!=Ipn) || (Ipc==Icn && Icc!=Ipp)?Ipc:Icc;
22081 *(ptrd2++) = (Icp==Inc && Icc!=Inn) || (Icn==Inc && Icc!=Inp)?Inc:Icc;
22082 *(ptrd3++) = Ipc==Icn?Ipc:Icc;
22083 *(ptrd3++) = (Ipc==Icn && Icc!=Inn) || (Icn==Inc && Icc!=Ipn)?Icn:Icc;
22084 *(ptrd3++) = Icn==Inc?Inc:Icc;
22086 *(ptrd1++) = Icc; *(ptrd1++) = Icc; *(ptrd1++) = Icc;
22087 *(ptrd2++) = Icc; *(ptrd2++) = Icc; *(ptrd2++) = Icc;
22088 *(ptrd3++) = Icc; *(ptrd3++) = Icc; *(ptrd3++) = Icc;
22101 T *pf, *pb, *buf = 0;
22104 pf = _data; pb =
data(_width-1);
22105 const unsigned int width2 = _width/2;
22106 for (
unsigned int yzv = 0; yzv<_height*_depth*_spectrum; ++yzv) {
22107 for (
unsigned int x = 0; x<width2; ++x) {
const T val = *pf; *(pf++) = *pb; *(pb--) = val; }
22108 pf+=_width - width2;
22109 pb+=_width + width2;
22113 buf =
new T[_width];
22114 pf = _data; pb =
data(0,_height-1);
22115 const unsigned int height2 = _height/2;
22116 for (
unsigned int zv = 0; zv<_depth*_spectrum; ++zv) {
22117 for (
unsigned int y = 0; y<height2; ++y) {
22118 std::memcpy(buf,pf,_width*
sizeof(T));
22119 std::memcpy(pf,pb,_width*
sizeof(T));
22120 std::memcpy(pb,buf,_width*
sizeof(T));
22124 pf+=(
unsigned long)_width*(_height - height2);
22125 pb+=(
unsigned long)_width*(_height + height2);
22129 buf =
new T[(
unsigned long)_width*_height];
22130 pf = _data; pb =
data(0,0,_depth-1);
22131 const unsigned int depth2 = _depth/2;
22132 cimg_forC(*
this,c) {
22133 for (
unsigned int z = 0; z<depth2; ++z) {
22134 std::memcpy(buf,pf,_width*_height*
sizeof(T));
22135 std::memcpy(pf,pb,_width*_height*
sizeof(T));
22136 std::memcpy(pb,buf,_width*_height*
sizeof(T));
22137 pf+=(
unsigned long)_width*_height;
22138 pb-=(
unsigned long)_width*_height;
22140 pf+=(
unsigned long)_width*_height*(_depth - depth2);
22141 pb+=(
unsigned long)_width*_height*(_depth + depth2);
22145 buf =
new T[(
unsigned long)_width*_height*_depth];
22146 pf = _data; pb =
data(0,0,0,_spectrum-1);
22147 const unsigned int _spectrum2 = _spectrum/2;
22148 for (
unsigned int v = 0; v<_spectrum2; ++v) {
22149 std::memcpy(buf,pf,_width*_height*_depth*
sizeof(T));
22150 std::memcpy(pf,pb,_width*_height*_depth*
sizeof(T));
22151 std::memcpy(pb,buf,_width*_height*_depth*
sizeof(T));
22152 pf+=(
unsigned long)_width*_height*_depth;
22153 pb-=(
unsigned long)_width*_height*_depth;
22158 "mirror(): Invalid specified axis '%c'.",
22168 return (+*
this).
mirror(axis);
22177 for (
const char *s = axes; *s; s++)
mirror(*s);
22183 return (+*
this).
mirror(axes);
22199 CImg<T>&
shift(
const int delta_x,
const int delta_y=0,
const int delta_z=0,
const int delta_c=0,
22200 const int boundary_conditions=0) {
22203 switch (boundary_conditions) {
22206 if (delta_x<0) cimg_forYZC(*
this,y,z,c) {
22207 std::memmove(
data(0,y,z,c),
data(-delta_x,y,z,c),(_width+delta_x)*
sizeof(T));
22208 std::memset(
data(_width+delta_x,y,z,c),0,-delta_x*
sizeof(T));
22209 }
else cimg_forYZC(*
this,y,z,c) {
22210 std::memmove(
data(delta_x,y,z,c),
data(0,y,z,c),(_width-delta_x)*
sizeof(T));
22211 std::memset(
data(0,y,z,c),0,delta_x*
sizeof(T));
22216 const int ndelta_x = (-delta_x>=
width())?
width()-1:-delta_x;
22217 if (!ndelta_x)
return *
this;
22218 cimg_forYZC(*
this,y,z,c) {
22219 std::memmove(
data(0,y,z,c),
data(ndelta_x,y,z,c),(_width-ndelta_x)*
sizeof(T));
22220 T *ptrd =
data(_width-1,y,z,c);
22221 const T val = *ptrd;
22222 for (
int l = 0; l<ndelta_x-1; ++l) *(--ptrd) = val;
22225 const int ndelta_x = (delta_x>=
width())?
width()-1:delta_x;
22226 if (!ndelta_x)
return *
this;
22227 cimg_forYZC(*
this,y,z,c) {
22228 std::memmove(
data(ndelta_x,y,z,c),
data(0,y,z,c),(_width-ndelta_x)*
sizeof(T));
22229 T *ptrd =
data(0,y,z,c);
22230 const T val = *ptrd;
22231 for (
int l = 0; l<ndelta_x-1; ++l) *(++ptrd) = val;
22237 if (!ndelta_x)
return *
this;
22238 T *
const buf =
new T[
cimg::abs(ndelta_x)];
22239 if (ndelta_x>0) cimg_forYZC(*
this,y,z,c) {
22240 std::memcpy(buf,
data(0,y,z,c),ndelta_x*
sizeof(T));
22241 std::memmove(
data(0,y,z,c),
data(ndelta_x,y,z,c),(_width-ndelta_x)*
sizeof(T));
22242 std::memcpy(
data(_width-ndelta_x,y,z,c),buf,ndelta_x*
sizeof(T));
22243 }
else cimg_forYZC(*
this,y,z,c) {
22244 std::memcpy(buf,
data(_width+ndelta_x,y,z,c),-ndelta_x*
sizeof(T));
22245 std::memmove(
data(-ndelta_x,y,z,c),
data(0,y,z,c),(_width+ndelta_x)*
sizeof(T));
22246 std::memcpy(
data(0,y,z,c),buf,-ndelta_x*
sizeof(T));
22253 switch (boundary_conditions) {
22256 if (delta_y<0) cimg_forZC(*
this,z,c) {
22257 std::memmove(
data(0,0,z,c),
data(0,-delta_y,z,c),_width*(_height+delta_y)*
sizeof(T));
22258 std::memset(
data(0,_height+delta_y,z,c),0,-delta_y*_width*
sizeof(T));
22259 }
else cimg_forZC(*
this,z,c) {
22260 std::memmove(
data(0,delta_y,z,c),
data(0,0,z,c),_width*(_height-delta_y)*
sizeof(T));
22261 std::memset(
data(0,0,z,c),0,delta_y*_width*
sizeof(T));
22266 const int ndelta_y = (-delta_y>=
height())?
height()-1:-delta_y;
22267 if (!ndelta_y)
return *
this;
22268 cimg_forZC(*
this,z,c) {
22269 std::memmove(
data(0,0,z,c),
data(0,ndelta_y,z,c),_width*(_height-ndelta_y)*
sizeof(T));
22270 T *ptrd =
data(0,_height-ndelta_y,z,c), *ptrs =
data(0,_height-1,z,c);
22271 for (
int l = 0; l<ndelta_y-1; ++l) { std::memcpy(ptrd,ptrs,_width*
sizeof(T)); ptrd+=_width; }
22274 const int ndelta_y = (delta_y>=
height())?
height()-1:delta_y;
22275 if (!ndelta_y)
return *
this;
22276 cimg_forZC(*
this,z,c) {
22277 std::memmove(
data(0,ndelta_y,z,c),
data(0,0,z,c),_width*(_height-ndelta_y)*
sizeof(T));
22278 T *ptrd =
data(0,1,z,c), *ptrs =
data(0,0,z,c);
22279 for (
int l = 0; l<ndelta_y-1; ++l) { std::memcpy(ptrd,ptrs,_width*
sizeof(T)); ptrd+=_width; }
22285 if (!ndelta_y)
return *
this;
22286 T *
const buf =
new T[(
unsigned long)_width*
cimg::abs(ndelta_y)];
22287 if (ndelta_y>0) cimg_forZC(*
this,z,c) {
22288 std::memcpy(buf,
data(0,0,z,c),_width*ndelta_y*
sizeof(T));
22289 std::memmove(
data(0,0,z,c),
data(0,ndelta_y,z,c),_width*(_height-ndelta_y)*
sizeof(T));
22290 std::memcpy(
data(0,_height-ndelta_y,z,c),buf,_width*ndelta_y*
sizeof(T));
22291 }
else cimg_forZC(*
this,z,c) {
22292 std::memcpy(buf,
data(0,_height+ndelta_y,z,c),-ndelta_y*_width*
sizeof(T));
22293 std::memmove(
data(0,-ndelta_y,z,c),
data(0,0,z,c),_width*(_height+ndelta_y)*
sizeof(T));
22294 std::memcpy(
data(0,0,z,c),buf,-ndelta_y*_width*
sizeof(T));
22301 switch (boundary_conditions) {
22304 if (delta_z<0) cimg_forC(*
this,c) {
22305 std::memmove(
data(0,0,0,c),
data(0,0,-delta_z,c),_width*_height*(_depth+delta_z)*
sizeof(T));
22306 std::memset(
data(0,0,_depth+delta_z,c),0,_width*_height*(-delta_z)*
sizeof(T));
22307 }
else cimg_forC(*
this,c) {
22308 std::memmove(
data(0,0,delta_z,c),
data(0,0,0,c),_width*_height*(_depth-delta_z)*
sizeof(T));
22309 std::memset(
data(0,0,0,c),0,delta_z*_width*_height*
sizeof(T));
22314 const int ndelta_z = (-delta_z>=
depth())?
depth()-1:-delta_z;
22315 if (!ndelta_z)
return *
this;
22316 cimg_forC(*
this,c) {
22317 std::memmove(
data(0,0,0,c),
data(0,0,ndelta_z,c),_width*_height*(_depth-ndelta_z)*
sizeof(T));
22318 T *ptrd =
data(0,0,_depth-ndelta_z,c), *ptrs =
data(0,0,_depth-1,c);
22319 for (
int l = 0; l<ndelta_z-1; ++l) {
22320 std::memcpy(ptrd,ptrs,_width*_height*
sizeof(T)); ptrd+=(
unsigned long)_width*_height;
22324 const int ndelta_z = (delta_z>=
depth())?
depth()-1:delta_z;
22325 if (!ndelta_z)
return *
this;
22326 cimg_forC(*
this,c) {
22327 std::memmove(
data(0,0,ndelta_z,c),
data(0,0,0,c),_width*_height*(_depth-ndelta_z)*
sizeof(T));
22328 T *ptrd =
data(0,0,1,c), *ptrs =
data(0,0,0,c);
22329 for (
int l = 0; l<ndelta_z-1; ++l) {
22330 std::memcpy(ptrd,ptrs,_width*_height*
sizeof(T)); ptrd+=(
unsigned long)_width*_height;
22337 if (!ndelta_z)
return *
this;
22338 T *
const buf =
new T[(
unsigned long)_width*_height*
cimg::abs(ndelta_z)];
22339 if (ndelta_z>0) cimg_forC(*
this,c) {
22340 std::memcpy(buf,
data(0,0,0,c),_width*_height*ndelta_z*
sizeof(T));
22341 std::memmove(
data(0,0,0,c),
data(0,0,ndelta_z,c),_width*_height*(_depth-ndelta_z)*
sizeof(T));
22342 std::memcpy(
data(0,0,_depth-ndelta_z,c),buf,_width*_height*ndelta_z*
sizeof(T));
22343 }
else cimg_forC(*
this,c) {
22344 std::memcpy(buf,
data(0,0,_depth+ndelta_z,c),-ndelta_z*_width*_height*
sizeof(T));
22345 std::memmove(
data(0,0,-ndelta_z,c),
data(0,0,0,c),_width*_height*(_depth+ndelta_z)*
sizeof(T));
22346 std::memcpy(
data(0,0,0,c),buf,-ndelta_z*_width*_height*
sizeof(T));
22353 switch (boundary_conditions) {
22357 std::memmove(_data,
data(0,0,0,-delta_c),_width*_height*_depth*(_spectrum+delta_c)*
sizeof(T));
22358 std::memset(
data(0,0,0,_spectrum+delta_c),0,_width*_height*_depth*(-delta_c)*
sizeof(T));
22360 std::memmove(
data(0,0,0,delta_c),_data,_width*_height*_depth*(_spectrum-delta_c)*
sizeof(T));
22361 std::memset(_data,0,delta_c*_width*_height*_depth*
sizeof(T));
22367 if (!ndelta_c)
return *
this;
22368 std::memmove(_data,
data(0,0,0,ndelta_c),_width*_height*_depth*(_spectrum-ndelta_c)*
sizeof(T));
22369 T *ptrd =
data(0,0,0,_spectrum-ndelta_c), *ptrs =
data(0,0,0,_spectrum-1);
22370 for (
int l = 0; l<ndelta_c-1; ++l) {
22371 std::memcpy(ptrd,ptrs,_width*_height*_depth*
sizeof(T)); ptrd+=(
unsigned long)_width*_height*_depth;
22375 if (!ndelta_c)
return *
this;
22376 std::memmove(
data(0,0,0,ndelta_c),_data,_width*_height*_depth*(_spectrum-ndelta_c)*
sizeof(T));
22377 T *ptrd =
data(0,0,0,1);
22378 for (
int l = 0; l<ndelta_c-1; ++l) {
22379 std::memcpy(ptrd,_data,_width*_height*_depth*
sizeof(T)); ptrd+=(
unsigned long)_width*_height*_depth;
22385 if (!ndelta_c)
return *
this;
22386 T *
const buf =
new T[(
unsigned long)_width*_height*_depth*
cimg::abs(ndelta_c)];
22388 std::memcpy(buf,_data,_width*_height*_depth*ndelta_c*
sizeof(T));
22389 std::memmove(_data,
data(0,0,0,ndelta_c),_width*_height*_depth*(_spectrum-ndelta_c)*
sizeof(T));
22390 std::memcpy(
data(0,0,0,_spectrum-ndelta_c),buf,_width*_height*_depth*ndelta_c*
sizeof(T));
22392 std::memcpy(buf,
data(0,0,0,_spectrum+ndelta_c),-ndelta_c*_width*_height*_depth*
sizeof(T));
22393 std::memmove(
data(0,0,0,-ndelta_c),_data,_width*_height*_depth*(_spectrum+ndelta_c)*
sizeof(T));
22394 std::memcpy(_data,buf,-ndelta_c*_width*_height*_depth*
sizeof(T));
22403 CImg<T> get_shift(
const int delta_x,
const int delta_y=0,
const int delta_z=0,
const int delta_c=0,
22404 const int boundary_conditions=0)
const {
22405 return (+*
this).
shift(delta_x,delta_y,delta_z,delta_c,boundary_conditions);
22419 const T foo = (T)0;
22420 return _get_permute_axes(order,foo);
22423 template<
typename t>
22424 CImg<t> _get_permute_axes(
const char *
const permut,
const t&)
const {
22427 const T* ptrs = _data;
22430 res.assign(_width,_height,_spectrum,_depth);
22431 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22432 cimg_forXYZC(*
this,x,y,z,c) res(x,y,c,z,wh,whd) = (t)*(ptrs++);
22435 res.assign(_width,_depth,_height,_spectrum);
22436 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22437 cimg_forXYZC(*
this,x,y,z,c) res(x,z,y,c,wh,whd) = (t)*(ptrs++);
22440 res.assign(_width,_depth,_spectrum,_height);
22441 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22442 cimg_forXYZC(*
this,x,y,z,c) res(x,z,c,y,wh,whd) = (t)*(ptrs++);
22445 res.assign(_width,_spectrum,_height,_depth);
22446 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22447 cimg_forXYZC(*
this,x,y,z,c) res(x,c,y,z,wh,whd) = (t)*(ptrs++);
22450 res.assign(_width,_spectrum,_depth,_height);
22451 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22452 cimg_forXYZC(*
this,x,y,z,c) res(x,c,z,y,wh,whd) = (t)*(ptrs++);
22455 res.assign(_height,_width,_depth,_spectrum);
22456 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22457 cimg_forXYZC(*
this,x,y,z,c) res(y,x,z,c,wh,whd) = (t)*(ptrs++);
22460 res.assign(_height,_width,_spectrum,_depth);
22461 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22462 cimg_forXYZC(*
this,x,y,z,c) res(y,x,c,z,wh,whd) = (t)*(ptrs++);
22465 res.assign(_height,_depth,_width,_spectrum);
22466 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22467 cimg_forXYZC(*
this,x,y,z,c) res(y,z,x,c,wh,whd) = (t)*(ptrs++);
22470 res.assign(_height,_depth,_spectrum,_width);
22473 t *ptr_r = res.data(0,0,0,0);
22474 for (
unsigned int siz = _height*_depth*_spectrum; siz; --siz) {
22475 *(ptr_r++) = (t)*(ptrs++);
22479 t *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1);
22480 for (
unsigned int siz = _height*_depth*_spectrum; siz; --siz) {
22481 *(ptr_r++) = (t)*(ptrs++); *(ptr_g++) = (t)*(ptrs++);
22485 t *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1), *ptr_b = res.data(0,0,0,2);
22486 for (
unsigned int siz = _height*_depth*_spectrum; siz; --siz) {
22487 *(ptr_r++) = (t)*(ptrs++); *(ptr_g++) = (t)*(ptrs++); *(ptr_b++) = (t)*(ptrs++);
22491 t *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1), *ptr_b = res.data(0,0,0,2), *ptr_a = res.data(0,0,0,3);
22492 for (
unsigned int siz = _height*_depth*_spectrum; siz; --siz) {
22493 *(ptr_r++) = (t)*(ptrs++); *(ptr_g++) = (t)*(ptrs++); *(ptr_b++) = (t)*(ptrs++); *(ptr_a++) = (t)*(ptrs++);
22497 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22498 cimg_forXYZC(*
this,x,y,z,c) res(y,z,c,x,wh,whd) = *(ptrs++);
22504 res.assign(_height,_spectrum,_width,_depth);
22505 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22506 cimg_forXYZC(*
this,x,y,z,c) res(y,c,x,z,wh,whd) = (t)*(ptrs++);
22509 res.assign(_height,_spectrum,_depth,_width);
22510 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22511 cimg_forXYZC(*
this,x,y,z,c) res(y,c,z,x,wh,whd) = (t)*(ptrs++);
22514 res.assign(_depth,_width,_height,_spectrum);
22515 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22516 cimg_forXYZC(*
this,x,y,z,c) res(z,x,y,c,wh,whd) = (t)*(ptrs++);
22519 res.assign(_depth,_width,_spectrum,_height);
22520 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22521 cimg_forXYZC(*
this,x,y,z,c) res(z,x,c,y,wh,whd) = (t)*(ptrs++);
22524 res.assign(_depth,_height,_width,_spectrum);
22525 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22526 cimg_forXYZC(*
this,x,y,z,c) res(z,y,x,c,wh,whd) = (t)*(ptrs++);
22529 res.assign(_depth,_height,_spectrum,_width);
22530 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22531 cimg_forXYZC(*
this,x,y,z,c) res(z,y,c,x,wh,whd) = (t)*(ptrs++);
22534 res.assign(_depth,_spectrum,_width,_height);
22535 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22536 cimg_forXYZC(*
this,x,y,z,c) res(z,c,x,y,wh,whd) = (t)*(ptrs++);
22539 res.assign(_depth,_spectrum,_height,_width);
22540 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22541 cimg_forXYZC(*
this,x,y,z,c) res(z,c,y,x,wh,whd) = (t)*(ptrs++);
22544 res.assign(_spectrum,_width,_height,_depth);
22545 switch (_spectrum) {
22547 const T *ptr_r =
data(0,0,0,0);
22548 t *ptrd = res._data;
22549 for (
unsigned long siz = (
unsigned long)_width*_height*_depth; siz; --siz) *(ptrd++) = (t)*(ptr_r++);
22552 const T *ptr_r =
data(0,0,0,0), *ptr_g =
data(0,0,0,1);
22553 t *ptrd = res._data;
22554 for (
unsigned long siz = (
unsigned long)_width*_height*_depth; siz; --siz) {
22555 *(ptrd++) = (t)*(ptr_r++); *(ptrd++) = (t)*(ptr_g++);
22559 const T *ptr_r =
data(0,0,0,0), *ptr_g =
data(0,0,0,1), *ptr_b =
data(0,0,0,2);
22560 t *ptrd = res._data;
22561 for (
unsigned long siz = (
unsigned long)_width*_height*_depth; siz; --siz) {
22562 *(ptrd++) = (t)*(ptr_r++); *(ptrd++) = (t)*(ptr_g++); *(ptrd++) = (t)*(ptr_b++);
22566 const T *ptr_r =
data(0,0,0,0), *ptr_g =
data(0,0,0,1), *ptr_b =
data(0,0,0,2), *ptr_a =
data(0,0,0,3);
22567 t *ptrd = res._data;
22568 for (
unsigned long siz = (
unsigned long)_width*_height*_depth; siz; --siz) {
22569 *(ptrd++) = (t)*(ptr_r++); *(ptrd++) = (t)*(ptr_g++); *(ptrd++) = (t)*(ptr_b++); *(ptrd++) = (t)*(ptr_a++);
22573 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22574 cimg_forXYZC(*
this,x,y,z,c) res(c,x,y,z,wh,whd) = (t)*(ptrs++);
22579 res.assign(_spectrum,_width,_depth,_height);
22580 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22581 cimg_forXYZC(*
this,x,y,z,c) res(c,x,z,y,wh,whd) = (t)*(ptrs++);
22584 res.assign(_spectrum,_height,_width,_depth);
22585 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22586 cimg_forXYZC(*
this,x,y,z,c) res(c,y,x,z,wh,whd) = (t)*(ptrs++);
22589 res.assign(_spectrum,_height,_depth,_width);
22590 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22591 cimg_forXYZC(*
this,x,y,z,c) res(c,y,z,x,wh,whd) = (t)*(ptrs++);
22594 res.assign(_spectrum,_depth,_width,_height);
22595 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22596 cimg_forXYZC(*
this,x,y,z,c) res(c,z,x,y,wh,whd) = (t)*(ptrs++);
22599 res.assign(_spectrum,_depth,_height,_width);
22600 const unsigned long wh = (
unsigned long)res._width*res._height, whd = wh*res._depth;
22601 cimg_forXYZC(*
this,x,y,z,c) res(c,z,y,x,wh,whd) = (t)*(ptrs++);
22604 throw CImgArgumentException(_cimg_instance
22605 "permute_axes(): Invalid specified permutation '%s'.",
22616 const unsigned int siz =
size();
22617 if (siz)
switch (axis) {
22618 case 'x' : _width = siz; _height = _depth = _spectrum = 1;
break;
22619 case 'y' : _height = siz; _width = _depth = _spectrum = 1;
break;
22620 case 'z' : _depth = siz; _width = _height = _spectrum = 1;
break;
22621 default : _spectrum = siz; _width = _height = _depth = 1;
22628 return (+*
this).
unroll(axis);
22638 CImg<T>&
rotate(
const float angle,
const unsigned int interpolation=1,
const unsigned int boundary=0) {
22639 const float nangle =
cimg::mod(angle,360.0f);
22640 if (nangle==0.0f)
return *
this;
22641 return get_rotate(angle,interpolation,boundary).move_to(*
this);
22645 CImg<T> get_rotate(
const float angle,
const unsigned int interpolation=1,
const unsigned int boundary=0)
const {
22648 const float nangle =
cimg::mod(angle,360.0f);
22649 if (boundary!=1 &&
cimg::mod(nangle,90.0f)==0) {
22651 const int iangle = (int)nangle/90;
22654 res.assign(_height,_width,_depth,_spectrum);
22655 T *ptrd = res._data;
22656 cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*
this)(y,hm1-x,z,c);
22659 res.assign(_width,_height,_depth,_spectrum);
22660 T *ptrd = res._data;
22661 cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*
this)(wm1-x,hm1-y,z,c);
22664 res.assign(_height,_width,_depth,_spectrum);
22665 T *ptrd = res._data;
22666 cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*
this)(wm1-y,x,z,c);
22674 rad = (float)(nangle*
cimg::PI/180.0),
22675 ca = (float)std::cos(rad),
22676 sa = (float)std::sin(rad),
22679 w2 = 0.5f*_width, h2 = 0.5f*_height,
22680 dw2 = 0.5f*(ux+vx), dh2 = 0.5f*(uy+vy);
22681 res.assign((
int)(ux+vx),(
int)(uy+vy),_depth,_spectrum);
22682 switch (boundary) {
22684 switch (interpolation) {
22686 #ifdef cimg_use_openmp
22687 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22689 cimg_forXYZC(res,x,y,z,c) {
22690 const Tfloat val =
cubic_atXY(w2 + (x-dw2)*ca + (y-dh2)*sa,h2 - (x-dw2)*sa + (y-dh2)*ca,z,c,0);
22691 res(x,y,z,c) = (T)(val<vmin?vmin:val>vmax?vmax:val);
22695 #ifdef cimg_use_openmp
22696 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22698 cimg_forXYZC(res,x,y,z,c)
22699 res(x,y,z,c) = (T)
linear_atXY(w2 + (x-dw2)*ca + (y-dh2)*sa,h2 - (x-dw2)*sa + (y-dh2)*ca,z,c,0);
22702 #ifdef cimg_use_openmp
22703 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22705 cimg_forXYZC(res,x,y,z,c)
22706 res(x,y,z,c) =
atXY((
int)(w2 + (x-dw2)*ca + (y-dh2)*sa),(
int)(h2 - (x-dw2)*sa + (y-dh2)*ca),z,c,0);
22711 switch (interpolation) {
22713 #ifdef cimg_use_openmp
22714 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22716 cimg_forXYZC(res,x,y,z,c) {
22717 const Tfloat val = _cubic_atXY(w2 + (x-dw2)*ca + (y-dh2)*sa,h2 - (x-dw2)*sa + (y-dh2)*ca,z,c);
22718 res(x,y,z,c) = (T)(val<vmin?vmin:val>vmax?vmax:val);
22722 #ifdef cimg_use_openmp
22723 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22725 cimg_forXYZC(res,x,y,z,c)
22726 res(x,y,z,c) = (T)_linear_atXY(w2 + (x-dw2)*ca + (y-dh2)*sa,h2 - (x-dw2)*sa + (y-dh2)*ca,z,c);
22729 #ifdef cimg_use_openmp
22730 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22732 cimg_forXYZC(res,x,y,z,c)
22733 res(x,y,z,c) = _atXY((
int)(w2 + (x-dw2)*ca + (y-dh2)*sa),(
int)(h2 - (x-dw2)*sa + (y-dh2)*ca),z,c);
22738 switch (interpolation) {
22740 #ifdef cimg_use_openmp
22741 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22743 cimg_forXYZC(res,x,y,z,c) {
22744 const Tfloat val = _cubic_atXY(
cimg::mod(w2 + (x-dw2)*ca + (y-dh2)*sa,(
float)
width()),
22746 res(x,y,z,c) = (T)(val<vmin?vmin:val>vmax?vmax:val);
22750 #ifdef cimg_use_openmp
22751 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22753 cimg_forXYZC(res,x,y,z,c)
22754 res(x,y,z,c) = (T)_linear_atXY(
cimg::mod(w2 + (x-dw2)*ca + (y-dh2)*sa,(
float)
width()),
22758 #ifdef cimg_use_openmp
22759 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22761 cimg_forXYZC(res,x,y,z,c)
22762 res(x,y,z,c) = (*this)(
cimg::mod((
int)(w2 + (x-dw2)*ca + (y-dh2)*sa),
width()),
22769 "rotate(): Invalid specified border conditions %d "
22770 "(should be { 0=dirichlet | 1=neumann | 2=periodic }).",
22787 CImg<T>&
rotate(
const float angle,
const float cx,
const float cy,
const float zoom,
22788 const unsigned int interpolation=1,
const unsigned int boundary=3) {
22789 return get_rotate(angle,cx,cy,zoom,interpolation,boundary).move_to(*
this);
22794 const unsigned int interpolation=1,
const unsigned int boundary=3)
const {
22795 if (interpolation>2)
22797 "rotate(): Invalid specified interpolation type %d "
22798 "(should be { 0=none | 1=linear | 2=cubic }).",
22802 CImg<T> res(_width,_height,_depth,_spectrum);
22805 rad = (float)((angle*
cimg::PI)/180.0),
22806 ca = (float)std::cos(rad)/zoom,
22807 sa = (float)std::sin(rad)/zoom;
22808 switch (boundary) {
22810 switch (interpolation) {
22812 #ifdef cimg_use_openmp
22813 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22815 cimg_forXYZC(res,x,y,z,c) {
22816 const Tfloat val =
cubic_atXY(cx + (x-cx)*ca + (y-cy)*sa,cy - (x-cx)*sa + (y-cy)*ca,z,c,0);
22817 res(x,y,z,c) = (T)(val<vmin?vmin:val>vmax?vmax:val);
22821 #ifdef cimg_use_openmp
22822 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22824 cimg_forXYZC(res,x,y,z,c)
22825 res(x,y,z,c) = (T)
linear_atXY(cx + (x-cx)*ca + (y-cy)*sa,cy - (x-cx)*sa + (y-cy)*ca,z,c,0);
22828 #ifdef cimg_use_openmp
22829 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22831 cimg_forXYZC(res,x,y,z,c)
22832 res(x,y,z,c) =
atXY((
int)(cx + (x-cx)*ca + (y-cy)*sa),(
int)(cy - (x-cx)*sa + (y-cy)*ca),z,c,0);
22837 switch (interpolation) {
22839 #ifdef cimg_use_openmp
22840 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22842 cimg_forXYZC(res,x,y,z,c) {
22843 const Tfloat val = _cubic_atXY(cx + (x-cx)*ca + (y-cy)*sa,cy - (x-cx)*sa + (y-cy)*ca,z,c);
22844 res(x,y,z,c) = (T)(val<vmin?vmin:val>vmax?vmax:val);
22848 #ifdef cimg_use_openmp
22849 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22851 cimg_forXYZC(res,x,y,z,c)
22852 res(x,y,z,c) = (T)_linear_atXY(cx + (x-cx)*ca + (y-cy)*sa,cy - (x-cx)*sa + (y-cy)*ca,z,c);
22855 #ifdef cimg_use_openmp
22856 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22858 cimg_forXYZC(res,x,y,z,c)
22859 res(x,y,z,c) = _atXY((
int)(cx + (x-cx)*ca + (y-cy)*sa),(
int)(cy - (x-cx)*sa + (y-cy)*ca),z,c);
22864 switch (interpolation) {
22866 #ifdef cimg_use_openmp
22867 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22869 cimg_forXYZC(res,x,y,z,c) {
22870 const Tfloat val = _cubic_atXY(
cimg::mod(cx + (x-cx)*ca + (y-cy)*sa,(
float)
width()),
22872 res(x,y,z,c) = (T)(val<vmin?vmin:val>vmax?vmax:val);
22876 #ifdef cimg_use_openmp
22877 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22879 cimg_forXYZC(res,x,y,z,c)
22880 res(x,y,z,c) = (T)_linear_atXY(
cimg::mod(cx + (x-cx)*ca + (y-cy)*sa,(
float)
width()),
22884 #ifdef cimg_use_openmp
22885 #pragma omp parallel for collapse(3) if (res.size()>=2048)
22887 cimg_forXYZC(res,x,y,z,c)
22888 res(x,y,z,c) = (*this)(
cimg::mod((
int)(cx + (x-cx)*ca + (y-cy)*sa),
width()),
22895 "rotate(): Invalid specified border conditions %d "
22896 "(should be { 0=dirichlet | 1=neumann | 2=periodic }).",
22910 template<
typename t>
22912 const unsigned int interpolation=1,
const unsigned int boundary_conditions=0) {
22913 return get_warp(warp,is_relative,interpolation,boundary_conditions).move_to(*
this);
22917 template<
typename t>
22919 const unsigned int interpolation=1,
const unsigned int boundary_conditions=0)
const {
22920 if (
is_empty() || !warp)
return *
this;
22923 "warp(): Instance and specified relative warping field (%u,%u,%u,%u,%p) "
22924 "have different XYZ dimensions.",
22926 warp._width,warp._height,warp._depth,warp._spectrum,warp._data);
22928 CImg<T> res(warp._width,warp._height,warp._depth,_spectrum);
22930 if (warp._spectrum==1) {
22932 if (interpolation==2) {
22933 if (boundary_conditions==2)
22934 #ifdef cimg_use_openmp
22935 #pragma omp parallel for collapse(3) if (res.size()>=4096)
22937 cimg_forYZC(res,y,z,c) {
22938 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
22939 cimg_forX(res,x) *(ptrd++) = (T)_cubic_atX(
cimg::mod(x - (
float)*(ptrs0++),(
float)_width),y,z,c);
22941 else if (boundary_conditions==1)
22942 #ifdef cimg_use_openmp
22943 #pragma omp parallel for collapse(3) if (res.size()>=4096)
22945 cimg_forYZC(res,y,z,c) {
22946 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
22947 cimg_forX(res,x) *(ptrd++) = (T)_cubic_atX(x - (
float)*(ptrs0++),y,z,c);
22950 #ifdef cimg_use_openmp
22951 #pragma omp parallel for collapse(3) if (res.size()>=4096)
22953 cimg_forYZC(res,y,z,c) {
22954 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
22955 cimg_forX(res,x) *(ptrd++) = (T)
cubic_atX(x - (
float)*(ptrs0++),y,z,c,0);
22957 }
else if (interpolation==1) {
22958 if (boundary_conditions==2)
22959 #ifdef cimg_use_openmp
22960 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
22962 cimg_forYZC(res,y,z,c) {
22963 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
22964 cimg_forX(res,x) *(ptrd++) = (T)_linear_atX(
cimg::mod(x - (
float)*(ptrs0++),(
float)_width),y,z,c);
22966 else if (boundary_conditions==1)
22967 #ifdef cimg_use_openmp
22968 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
22970 cimg_forYZC(res,y,z,c) {
22971 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
22972 cimg_forX(res,x) *(ptrd++) = (T)_linear_atX(x - (
float)*(ptrs0++),y,z,c);
22975 #ifdef cimg_use_openmp
22976 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
22978 cimg_forYZC(res,y,z,c) {
22979 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
22980 cimg_forX(res,x) *(ptrd++) = (T)
linear_atX(x - (
float)*(ptrs0++),y,z,c,0);
22983 if (boundary_conditions==2)
22984 cimg_forYZC(res,y,z,c) {
22985 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
22986 cimg_forX(res,x) *(ptrd++) = (*
this)(
cimg::mod(x - (
int)*(ptrs0++),(
int)_width),y,z,c);
22988 else if (boundary_conditions==1)
22989 cimg_forYZC(res,y,z,c) {
22990 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
22991 cimg_forX(res,x) *(ptrd++) = _atX(x - (
int)*(ptrs0++),y,z,c);
22994 cimg_forYZC(res,y,z,c) {
22995 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
22996 cimg_forX(res,x) *(ptrd++) =
atX(x - (
int)*(ptrs0++),y,z,c,0);
23000 if (interpolation==2) {
23001 if (boundary_conditions==2)
23002 #ifdef cimg_use_openmp
23003 #pragma omp parallel for collapse(3) if (res.size()>=4096)
23005 cimg_forYZC(res,y,z,c) {
23006 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
23007 cimg_forX(res,x) *(ptrd++) = (T)_cubic_atX(
cimg::mod((
float)*(ptrs0++),(
float)_width),0,0,c);
23009 else if (boundary_conditions==1)
23010 #ifdef cimg_use_openmp
23011 #pragma omp parallel for collapse(3) if (res.size()>=4096)
23013 cimg_forYZC(res,y,z,c) {
23014 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
23015 cimg_forX(res,x) *(ptrd++) = (T)_cubic_atX((
float)*(ptrs0++),0,0,c);
23018 #ifdef cimg_use_openmp
23019 #pragma omp parallel for collapse(3) if (res.size()>=4096)
23021 cimg_forYZC(res,y,z,c) {
23022 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
23023 cimg_forX(res,x) *(ptrd++) = (T)
cubic_atX((
float)*(ptrs0++),0,0,c,0);
23025 }
else if (interpolation==1) {
23026 if (boundary_conditions==2)
23027 #ifdef cimg_use_openmp
23028 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
23030 cimg_forYZC(res,y,z,c) {
23031 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
23032 cimg_forX(res,x) *(ptrd++) = (T)_linear_atX(
cimg::mod((
float)*(ptrs0++),(
float)_width),0,0,c);
23034 else if (boundary_conditions==1)
23035 #ifdef cimg_use_openmp
23036 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
23038 cimg_forYZC(res,y,z,c) {
23039 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
23040 cimg_forX(res,x) *(ptrd++) = (T)_linear_atX((
float)*(ptrs0++),0,0,c);
23043 #ifdef cimg_use_openmp
23044 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
23046 cimg_forYZC(res,y,z,c) {
23047 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
23048 cimg_forX(res,x) *(ptrd++) = (T)
linear_atX((
float)*(ptrs0++),0,0,c,0);
23051 if (boundary_conditions==2)
23052 cimg_forYZC(res,y,z,c) {
23053 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
23054 cimg_forX(res,x) *(ptrd++) = (*
this)(
cimg::mod((
int)*(ptrs0++),(
int)_width),0,0,c);
23056 else if (boundary_conditions==1)
23057 cimg_forYZC(res,y,z,c) {
23058 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
23059 cimg_forX(res,x) *(ptrd++) = _atX((
int)*(ptrs0++),0,0,c);
23062 cimg_forYZC(res,y,z,c) {
23063 const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
23064 cimg_forX(res,x) *(ptrd++) =
atX((
int)*(ptrs0++),0,0,c,0);
23069 }
else if (warp._spectrum==2) {
23071 if (interpolation==2) {
23072 if (boundary_conditions==2)
23073 #ifdef cimg_use_openmp
23074 #pragma omp parallel for collapse(3) if (res.size()>=4096)
23076 cimg_forYZC(res,y,z,c) {
23077 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23078 cimg_forX(res,x) *(ptrd++) = (T)_cubic_atXY(
cimg::mod(x - (
float)*(ptrs0++),(
float)_width),
23079 cimg::mod(y - (
float)*(ptrs1++),(
float)_height),z,c);
23081 else if (boundary_conditions==1)
23082 #ifdef cimg_use_openmp
23083 #pragma omp parallel for collapse(3) if (res.size()>=4096)
23085 cimg_forYZC(res,y,z,c) {
23086 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23087 cimg_forX(res,x) *(ptrd++) = (T)_cubic_atXY(x - (
float)*(ptrs0++),y - (
float)*(ptrs1++),z,c);
23090 #ifdef cimg_use_openmp
23091 #pragma omp parallel for collapse(3) if (res.size()>=4096)
23093 cimg_forYZC(res,y,z,c) {
23094 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23095 cimg_forX(res,x) *(ptrd++) = (T)
cubic_atXY(x - (
float)*(ptrs0++),y - (
float)*(ptrs1++),z,c,0);
23097 }
else if (interpolation==1) {
23098 if (boundary_conditions==2)
23099 #ifdef cimg_use_openmp
23100 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
23102 cimg_forYZC(res,y,z,c) {
23103 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23104 cimg_forX(res,x) *(ptrd++) = (T)_linear_atXY(
cimg::mod(x - (
float)*(ptrs0++),(
float)_width),
23105 cimg::mod(y - (
float)*(ptrs1++),(
float)_height),z,c);
23107 else if (boundary_conditions==1)
23108 #ifdef cimg_use_openmp
23109 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
23111 cimg_forYZC(res,y,z,c) {
23112 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23113 cimg_forX(res,x) *(ptrd++) = (T)_linear_atXY(x - (
float)*(ptrs0++),y - (
float)*(ptrs1++),z,c);
23116 #ifdef cimg_use_openmp
23117 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
23119 cimg_forYZC(res,y,z,c) {
23120 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23121 cimg_forX(res,x) *(ptrd++) = (T)
linear_atXY(x - (
float)*(ptrs0++),y - (
float)*(ptrs1++),z,c,0);
23124 if (boundary_conditions==2)
23125 cimg_forYZC(res,y,z,c) {
23126 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23127 cimg_forX(res,x) *(ptrd++) = (*
this)(
cimg::mod(x - (
int)*(ptrs0++),(
int)_width),
23128 cimg::mod(y - (
int)*(ptrs1++),(
int)_height),z,c);
23130 else if (boundary_conditions==1)
23131 cimg_forYZC(res,y,z,c) {
23132 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23133 cimg_forX(res,x) *(ptrd++) = _atXY(x - (
int)*(ptrs0++),y - (
int)*(ptrs1++),z,c);
23136 cimg_forYZC(res,y,z,c) {
23137 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23138 cimg_forX(res,x) *(ptrd++) =
atXY(x - (
int)*(ptrs0++),y - (
int)*(ptrs1++),z,c,0);
23142 if (interpolation==2) {
23143 if (boundary_conditions==2)
23144 #ifdef cimg_use_openmp
23145 #pragma omp parallel for collapse(3) if (res.size()>=4096)
23147 cimg_forYZC(res,y,z,c) {
23148 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23149 cimg_forX(res,x) *(ptrd++) = (T)_cubic_atXY(
cimg::mod((
float)*(ptrs0++),(
float)_width),
23150 cimg::mod((
float)*(ptrs1++),(
float)_height),0,c);
23152 else if (boundary_conditions==1)
23153 #ifdef cimg_use_openmp
23154 #pragma omp parallel for collapse(3) if (res.size()>=4096)
23156 cimg_forYZC(res,y,z,c) {
23157 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23158 cimg_forX(res,x) *(ptrd++) = (T)_cubic_atXY((
float)*(ptrs0++),(
float)*(ptrs1++),0,c);
23161 #ifdef cimg_use_openmp
23162 #pragma omp parallel for collapse(3) if (res.size()>=4096)
23164 cimg_forYZC(res,y,z,c) {
23165 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23166 cimg_forX(res,x) *(ptrd++) = (T)
cubic_atXY((
float)*(ptrs0++),(
float)*(ptrs1++),0,c,0);
23168 }
else if (interpolation==1) {
23169 if (boundary_conditions==2)
23170 #ifdef cimg_use_openmp
23171 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
23173 cimg_forYZC(res,y,z,c) {
23174 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23175 cimg_forX(res,x) *(ptrd++) = (T)_linear_atXY(
cimg::mod((
float)*(ptrs0++),(
float)_width),
23176 cimg::mod((
float)*(ptrs1++),(
float)_height),0,c);
23178 else if (boundary_conditions==1)
23179 #ifdef cimg_use_openmp
23180 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
23182 cimg_forYZC(res,y,z,c) {
23183 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23184 cimg_forX(res,x) *(ptrd++) = (T)_linear_atXY((
float)*(ptrs0++),(
float)*(ptrs1++),0,c);
23187 #ifdef cimg_use_openmp
23188 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
23190 cimg_forYZC(res,y,z,c) {
23191 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23192 cimg_forX(res,x) *(ptrd++) = (T)
linear_atXY((
float)*(ptrs0++),(
float)*(ptrs1++),0,c,0);
23195 if (boundary_conditions==2)
23196 cimg_forYZC(res,y,z,c) {
23197 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23198 cimg_forX(res,x) *(ptrd++) = (*
this)(
cimg::mod((
int)*(ptrs0++),(
int)_width),
23199 cimg::mod((
int)*(ptrs1++),(
int)_height),0,c);
23201 else if (boundary_conditions==1)
23202 cimg_forYZC(res,y,z,c) {
23203 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23204 cimg_forX(res,x) *(ptrd++) = _atXY((
int)*(ptrs0++),(
int)*(ptrs1++),0,c);
23207 cimg_forYZC(res,y,z,c) {
23208 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
23209 cimg_forX(res,x) *(ptrd++) =
atXY((
int)*(ptrs0++),(
int)*(ptrs1++),0,c,0);
23214 }
else if (warp._spectrum==3) {
23216 if (interpolation==2) {
23217 if (boundary_conditions==2)
23218 #ifdef cimg_use_openmp
23219 #pragma omp parallel for collapse(3) if (res.size()>=4096)
23221 cimg_forYZC(res,y,z,c) {
23222 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23223 T *ptrd = res.data(0,y,z,c);
23224 cimg_forX(res,x) *(ptrd++) = (T)_cubic_atXYZ(
cimg::mod(x - (
float)*(ptrs0++),(
float)_width),
23225 cimg::mod(y - (
float)*(ptrs1++),(
float)_height),
23226 cimg::mod(z - (
float)*(ptrs2++),(
float)_depth),c);
23228 else if (boundary_conditions==1)
23229 #ifdef cimg_use_openmp
23230 #pragma omp parallel for collapse(3) if (res.size()>=4096)
23232 cimg_forYZC(res,y,z,c) {
23233 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23234 T *ptrd = res.data(0,y,z,c);
23236 *(ptrd++) = (T)_cubic_atXYZ(x - (
float)*(ptrs0++),y - (
float)*(ptrs1++),z - (
float)*(ptrs2++),c);
23239 #ifdef cimg_use_openmp
23240 #pragma omp parallel for collapse(3) if (res.size()>=4096)
23242 cimg_forYZC(res,y,z,c) {
23243 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23244 T *ptrd = res.data(0,y,z,c);
23246 *(ptrd++) = (T)
cubic_atXYZ(x - (
float)*(ptrs0++),y - (
float)*(ptrs1++),z - (
float)*(ptrs2++),c,0);
23248 }
else if (interpolation==1) {
23249 if (boundary_conditions==2)
23250 #ifdef cimg_use_openmp
23251 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
23253 cimg_forYZC(res,y,z,c) {
23254 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23255 T *ptrd = res.data(0,y,z,c);
23256 cimg_forX(res,x) *(ptrd++) = (T)_linear_atXYZ(
cimg::mod(x - (
float)*(ptrs0++),(
float)_width),
23257 cimg::mod(y - (
float)*(ptrs1++),(
float)_height),
23258 cimg::mod(z - (
float)*(ptrs2++),(
float)_depth),c);
23260 else if (boundary_conditions==1)
23261 #ifdef cimg_use_openmp
23262 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
23264 cimg_forYZC(res,y,z,c) {
23265 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23266 T *ptrd = res.data(0,y,z,c);
23268 *(ptrd++) = (T)_linear_atXYZ(x - (
float)*(ptrs0++),y - (
float)*(ptrs1++),z - (
float)*(ptrs2++),c);
23271 #ifdef cimg_use_openmp
23272 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
23274 cimg_forYZC(res,y,z,c) {
23275 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23276 T *ptrd = res.data(0,y,z,c);
23278 *(ptrd++) = (T)
linear_atXYZ(x - (
float)*(ptrs0++),y - (
float)*(ptrs1++),z - (
float)*(ptrs2++),c,0);
23281 if (boundary_conditions==2)
23282 cimg_forYZC(res,y,z,c) {
23283 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23284 T *ptrd = res.data(0,y,z,c);
23285 cimg_forX(res,x) *(ptrd++) = (*
this)(
cimg::mod(x - (
int)*(ptrs0++),(
int)_width),
23286 cimg::mod(y - (
int)*(ptrs1++),(
int)_height),
23287 cimg::mod(z - (
int)*(ptrs2++),(
int)_depth),c);
23289 else if (boundary_conditions==1)
23290 cimg_forYZC(res,y,z,c) {
23291 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23292 T *ptrd = res.data(0,y,z,c);
23293 cimg_forX(res,x) *(ptrd++) = _atXYZ(x - (
int)*(ptrs0++),y - (
int)*(ptrs1++),z - (
int)*(ptrs2++),c);
23296 cimg_forYZC(res,y,z,c) {
23297 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23298 T *ptrd = res.data(0,y,z,c);
23299 cimg_forX(res,x) *(ptrd++) =
atXYZ(x - (
int)*(ptrs0++),y - (
int)*(ptrs1++),z - (
int)*(ptrs2++),c,0);
23303 if (interpolation==2) {
23304 if (boundary_conditions==2)
23305 #ifdef cimg_use_openmp
23306 #pragma omp parallel for collapse(3) if (res.size()>=4096)
23308 cimg_forYZC(res,y,z,c) {
23309 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23310 T *ptrd = res.data(0,y,z,c);
23311 cimg_forX(res,x) *(ptrd++) = (T)_cubic_atXYZ(
cimg::mod((
float)*(ptrs0++),(
float)_width),
23312 cimg::mod((
float)*(ptrs1++),(
float)_height),
23313 cimg::mod((
float)*(ptrs2++),(
float)_depth),c);
23315 else if (boundary_conditions==1)
23316 #ifdef cimg_use_openmp
23317 #pragma omp parallel for collapse(3) if (res.size()>=4096)
23319 cimg_forYZC(res,y,z,c) {
23320 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23321 T *ptrd = res.data(0,y,z,c);
23322 cimg_forX(res,x) *(ptrd++) = (T)_cubic_atXYZ((
float)*(ptrs0++),(
float)*(ptrs1++),(
float)*(ptrs2++),c);
23325 #ifdef cimg_use_openmp
23326 #pragma omp parallel for collapse(3) if (res.size()>=4096)
23328 cimg_forYZC(res,y,z,c) {
23329 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23330 T *ptrd = res.data(0,y,z,c);
23331 cimg_forX(res,x) *(ptrd++) = (T)
cubic_atXYZ((
float)*(ptrs0++),(
float)*(ptrs1++),(
float)*(ptrs2++),c,0);
23333 }
else if (interpolation==1) {
23334 if (boundary_conditions==2)
23335 #ifdef cimg_use_openmp
23336 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
23338 cimg_forYZC(res,y,z,c) {
23339 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23340 T *ptrd = res.data(0,y,z,c);
23341 cimg_forX(res,x) *(ptrd++) = (T)_linear_atXYZ(
cimg::mod((
float)*(ptrs0++),(
float)_width),
23342 cimg::mod((
float)*(ptrs1++),(
float)_height),
23343 cimg::mod((
float)*(ptrs2++),(
float)_depth),c);
23345 else if (boundary_conditions==1)
23346 #ifdef cimg_use_openmp
23347 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
23349 cimg_forYZC(res,y,z,c) {
23350 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23351 T *ptrd = res.data(0,y,z,c);
23352 cimg_forX(res,x) *(ptrd++) = (T)_linear_atXYZ((
float)*(ptrs0++),(
float)*(ptrs1++),(
float)*(ptrs2++),c);
23355 #ifdef cimg_use_openmp
23356 #pragma omp parallel for collapse(3) if (res.size()>=1048576)
23358 cimg_forYZC(res,y,z,c) {
23359 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23360 T *ptrd = res.data(0,y,z,c);
23361 cimg_forX(res,x) *(ptrd++) = (T)
linear_atXYZ((
float)*(ptrs0++),(
float)*(ptrs1++),(
float)*(ptrs2++),c,0);
23364 if (boundary_conditions==2)
23365 cimg_forYZC(res,y,z,c) {
23366 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23367 T *ptrd = res.data(0,y,z,c);
23368 cimg_forX(res,x) *(ptrd++) = (*
this)(
cimg::mod((
int)*(ptrs0++),(
int)_width),
23369 cimg::mod((
int)*(ptrs1++),(
int)_height),
23370 cimg::mod((
int)*(ptrs2++),(
int)_depth),c);
23372 else if (boundary_conditions==1)
23373 cimg_forYZC(res,y,z,c) {
23374 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23375 T *ptrd = res.data(0,y,z,c);
23376 cimg_forX(res,x) *(ptrd++) = _atXYZ((
int)*(ptrs0++),(
int)*(ptrs1++),(
int)*(ptrs2++),c);
23379 cimg_forYZC(res,y,z,c) {
23380 const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2);
23381 T *ptrd = res.data(0,y,z,c);
23382 cimg_forX(res,x) *(ptrd++) =
atXYZ((
int)*(ptrs0++),(
int)*(ptrs1++),(
int)*(ptrs2++),c,0);
23397 if (
is_empty() || _depth<2)
return +*
this;
23399 _x0 = (x0>=_width)?_width - 1:x0,
23400 _y0 = (y0>=_height)?_height - 1:y0,
23401 _z0 = (z0>=_depth)?_depth - 1:z0;
23403 img_xy =
get_crop(0,0,_z0,0,_width-1,_height-1,_z0,_spectrum-1),
23404 img_zy =
get_crop(_x0,0,0,0,_x0,_height-1,_depth-1,_spectrum-1).permute_axes(
"xzyc").
23405 resize(_depth,_height,1,-100,-1),
23406 img_xz =
get_crop(0,_y0,0,0,_width-1,_y0,_depth-1,_spectrum-1).resize(_width,_depth,1,-100,-1);
23407 return CImg<T>(_width + _depth,_height + _depth,1,_spectrum,
cimg::min(img_xy.min(),img_zy.min(),img_xz.min())).
23408 draw_image(0,0,img_xy).draw_image(img_xy._width,0,img_zy).
23414 if (_depth<2)
return *
this;
23431 const int x1,
const int y1,
const int z1,
const int c1,
23432 const bool boundary_conditions=
false) {
23433 return get_crop(x0,y0,z0,c0,x1,y1,z1,c1,boundary_conditions).move_to(*
this);
23438 const int x1,
const int y1,
const int z1,
const int c1,
23439 const bool boundary_conditions=
false)
const {
23442 "crop(): Empty instance.",
23445 nx0 = x0<x1?x0:x1, nx1 = x0^x1^nx0,
23446 ny0 = y0<y1?y0:y1, ny1 = y0^y1^ny0,
23447 nz0 = z0<z1?z0:z1, nz1 = z0^z1^nz0,
23448 nc0 = c0<c1?c0:c1, nc1 = c0^c1^nc0;
23449 CImg<T> res(1U + nx1 - nx0,1U + ny1 - ny0,1U + nz1 - nz0,1U + nc1 - nc0);
23451 if (boundary_conditions) cimg_forXYZC(res,x,y,z,c) res(x,y,z,c) = _atXYZC(nx0+x,ny0+y,nz0+z,nc0+c);
23452 else res.fill(0).draw_image(-nx0,-ny0,-nz0,-nc0,*
this);
23453 }
else res.draw_image(-nx0,-ny0,-nz0,-nc0,*
this);
23459 const int x1,
const int y1,
const int z1,
23460 const bool boundary_conditions=
false) {
23461 return crop(x0,y0,z0,0,x1,y1,z1,_spectrum-1,boundary_conditions);
23466 const int x1,
const int y1,
const int z1,
23467 const bool boundary_conditions=
false)
const {
23468 return get_crop(x0,y0,z0,0,x1,y1,z1,_spectrum-1,boundary_conditions);
23473 const int x1,
const int y1,
23474 const bool boundary_conditions=
false) {
23475 return crop(x0,y0,0,0,x1,y1,_depth - 1,_spectrum - 1,boundary_conditions);
23480 const int x1,
const int y1,
23481 const bool boundary_conditions=
false)
const {
23482 return get_crop(x0,y0,0,0,x1,y1,_depth - 1,_spectrum - 1,boundary_conditions);
23486 CImg<T>&
crop(
const int x0,
const int x1,
const bool boundary_conditions=
false) {
23487 return crop(x0,0,0,0,x1,_height-1,_depth-1,_spectrum-1,boundary_conditions);
23492 return get_crop(x0,0,0,0,x1,_height-1,_depth-1,_spectrum-1,boundary_conditions);
23498 for (
const char *s = axes; *s; ++s) {
23500 const CImg<intT> coords = _autocrop(value,axis);
23501 if (coords[0]==-1 && coords[1]==-1)
return assign();
23502 else switch (axis) {
23504 const int x0 = coords[0], x1 = coords[1];
23505 if (x0>=0 && x1>=0)
crop(x0,x1);
23508 const int y0 = coords[0], y1 = coords[1];
23509 if (y0>=0 && y1>=0)
crop(0,y0,_width-1,y1);
23512 const int z0 = coords[0], z1 = coords[1];
23513 if (z0>=0 && z1>=0)
crop(0,0,z0,_width-1,_height-1,z1);
23516 const int c0 = coords[0], c1 = coords[1];
23517 if (c0>=0 && c1>=0)
crop(0,0,0,c0,_width-1,_height-1,_depth-1,c1);
23526 return (+*
this).
autocrop(value,axes);
23538 const unsigned int w = _width, h = _height, d = _depth, s = _spectrum;
23540 if (_width==w && _height==h && _depth==d && _spectrum==s) {
23546 for (
const char *s = axes; *s; ++s) {
23550 int x0 =
width(), x1 = -1;
23551 cimg_forC(*
this,c) {
23553 const int nx0 = coords[0], nx1 = coords[1];
23559 int y0 =
height(), y1 = -1;
23560 cimg_forC(*
this,c) {
23562 const int ny0 = coords[0], ny1 = coords[1];
23568 int z0 =
depth(), z1 = -1;
23569 cimg_forC(*
this,c) {
23571 const int nz0 = coords[0], nz1 = coords[1];
23574 if (z0==
depth() && z1==-1)
return assign();
else crop(0,0,z0,_width-1,_height-1,z1);
23583 return (+*
this).
autocrop(color,axes);
23596 CImg<intT> _autocrop(
const T value,
const char axis)
const {
23600 int x0 = -1, x1 = -1;
23601 cimg_forX(*
this,x) cimg_forYZC(*this,y,z,c)
23604 for (
int x =
width()-1; x>=0; --x) cimg_forYZC(*
this,y,z,c)
23605 if ((*
this)(x,y,z,c)!=value) { x1 = x; x = 0; y =
height(); z =
depth(); c =
spectrum(); }
23610 int y0 = -1, y1 = -1;
23611 cimg_forY(*
this,y) cimg_forXZC(*this,x,z,c)
23614 for (
int y =
height()-1; y>=0; --y) cimg_forXZC(*
this,x,z,c)
23615 if ((*
this)(x,y,z,c)!=value) { y1 = y; x =
width(); y = 0; z =
depth(); c =
spectrum(); }
23620 int z0 = -1, z1 = -1;
23621 cimg_forZ(*
this,z) cimg_forXYC(*this,x,y,c)
23624 for (
int z =
depth()-1; z>=0; --z) cimg_forXYC(*
this,x,y,c)
23625 if ((*
this)(x,y,z,c)!=value) { z1 = z; x =
width(); y =
height(); z = 0; c =
spectrum(); }
23630 int c0 = -1, c1 = -1;
23631 cimg_forC(*
this,c) cimg_forXYZ(*this,x,y,z)
23634 for (
int c =
spectrum()-1; c>=0; --c) cimg_forXYZ(*
this,x,y,z)
23635 if ((*
this)(x,y,z,c)!=value) { c1 = c; x =
width(); y =
height(); z =
depth(); c = 0; }
23680 return rows(y0,y0);
23694 return get_rows(y0,y1).move_to(*
this);
23753 const float L=256,
const float dl=0.1f,
23754 const unsigned int interpolation_type=2,
const bool is_backward_tracking=
false,
23755 const bool is_oriented_only=
false)
const {
23756 if (_spectrum!=2 && _spectrum!=3)
23758 "streamline(): Instance is not a 2d or 3d vector field.",
23760 if (_spectrum==2) {
23761 if (is_oriented_only) {
23763 return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,
true,
23764 0,0,0,_width-1.0f,_height-1.0f,0.0f);
23767 return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,
false,
23768 0,0,0,_width-1.0f,_height-1.0f,0.0f);
23771 if (is_oriented_only) {
23773 return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,
true,
23774 0,0,0,_width-1.0f,_height-1.0f,_depth-1.0f);
23777 return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,
false,
23778 0,0,0,_width-1.0f,_height-1.0f,_depth-1.0f);
23800 template<
typename tfunc>
23802 const float x,
const float y,
const float z,
23803 const float L=256,
const float dl=0.1f,
23804 const unsigned int interpolation_type=2,
const bool is_backward_tracking=
false,
23805 const bool is_oriented_only=
false,
23806 const float x0=0,
const float y0=0,
const float z0=0,
23807 const float x1=0,
const float y1=0,
const float z1=0) {
23814 const bool is_bounded = (x0!=x1 || y0!=y1 || z0!=z1);
23815 if (L<=0 || (is_bounded && (x<x0 || x>x1 || y<y0 || y>y1 || z<z0 || z>z1)))
return CImg<floatT>();
23816 const unsigned int size_L = (
unsigned int)
cimg::round(L/dl+1);
23818 const float dl2 = dl/2;
23820 *ptr_x = coordinates.
data(0,0),
23821 *ptr_y = coordinates.
data(0,1),
23822 *ptr_z = coordinates.
data(0,2),
23823 pu = (float)(dl*func(x,y,z,0)),
23824 pv = (
float)(dl*func(x,y,z,1)),
23825 pw = (
float)(dl*func(x,y,z,2)),
23826 X = x, Y = y, Z = z;
23828 switch (interpolation_type) {
23830 cimg_forX(coordinates,l) {
23831 *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z;
23833 xi = (int)(X>0?X+0.5f:X-0.5f),
23834 yi = (int)(Y>0?Y+0.5f:Y-0.5f),
23835 zi = (int)(Z>0?Z+0.5f:Z-0.5f);
23837 u = (float)(dl*func((
float)xi,(float)yi,(
float)zi,0)),
23838 v = (float)(dl*func((
float)xi,(float)yi,(
float)zi,1)),
23839 w = (float)(dl*func((
float)xi,(float)yi,(
float)zi,2));
23840 if (is_oriented_only && u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; }
23841 if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); }
else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); }
23842 if (is_bounded && (X<x0 || X>x1 || Y<y0 || Y>y1 || Z<z0 || Z>z1))
break;
23846 cimg_forX(coordinates,l) {
23847 *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z;
23849 u = (float)(dl*func(X,Y,Z,0)),
23850 v = (
float)(dl*func(X,Y,Z,1)),
23851 w = (
float)(dl*func(X,Y,Z,2));
23852 if (is_oriented_only && u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; }
23853 if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); }
else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); }
23854 if (is_bounded && (X<x0 || X>x1 || Y<y0 || Y>y1 || Z<z0 || Z>z1))
break;
23858 cimg_forX(coordinates,l) {
23859 *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z;
23861 u0 = (float)(dl2*func(X,Y,Z,0)),
23862 v0 = (
float)(dl2*func(X,Y,Z,1)),
23863 w0 = (
float)(dl2*func(X,Y,Z,2));
23864 if (is_oriented_only && u0*pu + v0*pv + w0*pw<0) { u0 = -u0; v0 = -v0; w0 = -w0; }
23866 u = (float)(dl*func(X+u0,Y+v0,Z+w0,0)),
23867 v = (
float)(dl*func(X+u0,Y+v0,Z+w0,1)),
23868 w = (
float)(dl*func(X+u0,Y+v0,Z+w0,2));
23869 if (is_oriented_only && u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; }
23870 if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); }
else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); }
23871 if (is_bounded && (X<x0 || X>x1 || Y<y0 || Y>y1 || Z<z0 || Z>z1))
break;
23875 cimg_forX(coordinates,x) {
23876 *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z;
23878 u0 = (float)(dl2*func(X,Y,Z,0)),
23879 v0 = (
float)(dl2*func(X,Y,Z,1)),
23880 w0 = (
float)(dl2*func(X,Y,Z,2));
23881 if (is_oriented_only && u0*pu + v0*pv + w0*pw<0) { u0 = -u0; v0 = -v0; w0 = -w0; }
23883 u1 = (float)(dl2*func(X+u0,Y+v0,Z+w0,0)),
23884 v1 = (
float)(dl2*func(X+u0,Y+v0,Z+w0,1)),
23885 w1 = (
float)(dl2*func(X+u0,Y+v0,Z+w0,2));
23886 if (is_oriented_only && u1*pu + v1*pv + w1*pw<0) { u1 = -u1; v1 = -v1; w1 = -w1; }
23888 u2 = (float)(dl2*func(X+u1,Y+v1,Z+w1,0)),
23889 v2 = (
float)(dl2*func(X+u1,Y+v1,Z+w1,1)),
23890 w2 = (
float)(dl2*func(X+u1,Y+v1,Z+w1,2));
23891 if (is_oriented_only && u2*pu + v2*pv + w2*pw<0) { u2 = -u2; v2 = -v2; w2 = -w2; }
23893 u3 = (float)(dl2*func(X+u2,Y+v2,Z+w2,0)),
23894 v3 = (
float)(dl2*func(X+u2,Y+v2,Z+w2,1)),
23895 w3 = (
float)(dl2*func(X+u2,Y+v2,Z+w2,2));
23896 if (is_oriented_only && u2*pu + v2*pv + w2*pw<0) { u3 = -u3; v3 = -v3; w3 = -w3; }
23898 u = (u0 + u3)/3 + (u1 + u2)/1.5f,
23899 v = (v0 + v3)/3 + (v1 + v2)/1.5f,
23900 w = (w0 + w3)/3 + (w1 + w2)/1.5f;
23901 if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); }
else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); }
23902 if (is_bounded && (X<x0 || X>x1 || Y<y0 || Y>y1 || Z<z0 || Z>z1))
break;
23906 if (ptr_x!=coordinates.
data(0,1)) coordinates.
resize((
int)(ptr_x-coordinates.
data()),3,1,1,0);
23907 return coordinates;
23912 const float x,
const float y,
const float z,
23913 const float L=256,
const float dl=0.1f,
23914 const unsigned int interpolation_type=2,
const bool is_backward_tracking=
true,
23915 const bool is_oriented_only=
false,
23916 const float x0=0,
const float y0=0,
const float z0=0,
23917 const float x1=0,
const float y1=0,
const float z1=0) {
23918 _functor4d_streamline_expr func(expression);
23919 return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,is_oriented_only,x0,y0,z0,x1,y1,z1);
23925 float operator()(
const float x,
const float y,
const float z,
const unsigned int c)
const {
23926 return c<2?(float)ref._linear_atXY(x,y,(
int)z,c):0;
23933 float operator()(
const float x,
const float y,
const float z,
const unsigned int c)
const {
23934 return (
float)ref._linear_atXYZ(x,y,z,c);
23943 float operator()(
const float x,
const float y,
const float z,
const unsigned int c)
const {
23944 #define _cimg_vecalign2d(i,j) if (I(i,j,0)*I(0,0,0)+I(i,j,1)*I(0,0,1)<0) { I(i,j,0) = -I(i,j,0); I(i,j,1) = -I(i,j,1); }
23946 xi = (int)x - (x>=0?0:1), nxi = xi + 1,
23947 yi = (int)y - (y>=0?0:1), nyi = yi + 1,
23954 if (xi<0) xi = 0;
if (nxi<0) nxi = 0;
23955 if (xi>=ref.width()) xi = ref.width()-1;
if (nxi>=ref.width()) nxi = ref.width()-1;
23956 if (yi<0) yi = 0;
if (nyi<0) nyi = 0;
23957 if (yi>=ref.height()) yi = ref.height()-1;
if (nyi>=ref.height()) nyi = ref.height()-1;
23958 I(0,0,0) = (float)ref(xi,yi,zi,0); I(0,0,1) = (float)ref(xi,yi,zi,1);
23959 I(1,0,0) = (float)ref(nxi,yi,zi,0); I(1,0,1) = (float)ref(nxi,yi,zi,1);
23960 I(1,1,0) = (float)ref(nxi,nyi,zi,0); I(1,1,1) = (float)ref(nxi,nyi,zi,1);
23961 I(0,1,0) = (float)ref(xi,nyi,zi,0); I(0,1,1) = (float)ref(xi,nyi,zi,1);
23962 _cimg_vecalign2d(1,0); _cimg_vecalign2d(1,1); _cimg_vecalign2d(0,1);
23964 return c<2?(float)pI->_linear_atXY(dx,dy,0,c):0;
23973 float operator()(
const float x,
const float y,
const float z,
const unsigned int c)
const {
23974 #define _cimg_vecalign3d(i,j,k) if (I(i,j,k,0)*I(0,0,0,0)+I(i,j,k,1)*I(0,0,0,1)+I(i,j,k,2)*I(0,0,0,2)<0) { \
23975 I(i,j,k,0) = -I(i,j,k,0); I(i,j,k,1) = -I(i,j,k,1); I(i,j,k,2) = -I(i,j,k,2); }
23977 xi = (int)x - (x>=0?0:1), nxi = xi + 1,
23978 yi = (int)y - (y>=0?0:1), nyi = yi + 1,
23979 zi = (int)z - (z>=0?0:1), nzi = zi + 1;
23986 if (xi<0) xi = 0;
if (nxi<0) nxi = 0;
23987 if (xi>=ref.width()) xi = ref.width()-1;
if (nxi>=ref.width()) nxi = ref.width()-1;
23988 if (yi<0) yi = 0;
if (nyi<0) nyi = 0;
23989 if (yi>=ref.height()) yi = ref.height()-1;
if (nyi>=ref.height()) nyi = ref.height()-1;
23990 if (zi<0) zi = 0;
if (nzi<0) nzi = 0;
23991 if (zi>=ref.depth()) zi = ref.depth()-1;
if (nzi>=ref.depth()) nzi = ref.depth()-1;
23992 I(0,0,0,0) = (float)ref(xi,yi,zi,0); I(0,0,0,1) = (float)ref(xi,yi,zi,1);
23993 I(0,0,0,2) = (float)ref(xi,yi,zi,2); I(1,0,0,0) = (float)ref(nxi,yi,zi,0);
23994 I(1,0,0,1) = (float)ref(nxi,yi,zi,1); I(1,0,0,2) = (float)ref(nxi,yi,zi,2);
23995 I(1,1,0,0) = (float)ref(nxi,nyi,zi,0); I(1,1,0,1) = (float)ref(nxi,nyi,zi,1);
23996 I(1,1,0,2) = (float)ref(nxi,nyi,zi,2); I(0,1,0,0) = (float)ref(xi,nyi,zi,0);
23997 I(0,1,0,1) = (float)ref(xi,nyi,zi,1); I(0,1,0,2) = (float)ref(xi,nyi,zi,2);
23998 I(0,0,1,0) = (float)ref(xi,yi,nzi,0); I(0,0,1,1) = (float)ref(xi,yi,nzi,1);
23999 I(0,0,1,2) = (float)ref(xi,yi,nzi,2); I(1,0,1,0) = (float)ref(nxi,yi,nzi,0);
24000 I(1,0,1,1) = (float)ref(nxi,yi,nzi,1); I(1,0,1,2) = (float)ref(nxi,yi,nzi,2);
24001 I(1,1,1,0) = (float)ref(nxi,nyi,nzi,0); I(1,1,1,1) = (float)ref(nxi,nyi,nzi,1);
24002 I(1,1,1,2) = (float)ref(nxi,nyi,nzi,2); I(0,1,1,0) = (float)ref(xi,nyi,nzi,0);
24003 I(0,1,1,1) = (float)ref(xi,nyi,nzi,1); I(0,1,1,2) = (float)ref(xi,nyi,nzi,2);
24004 _cimg_vecalign3d(1,0,0); _cimg_vecalign3d(1,1,0); _cimg_vecalign3d(0,1,0);
24005 _cimg_vecalign3d(0,0,1); _cimg_vecalign3d(1,0,1); _cimg_vecalign3d(1,1,1); _cimg_vecalign3d(0,1,1);
24007 return (
float)pI->_linear_atXYZ(dx,dy,dz,c);
24017 float operator()(
const float x,
const float y,
const float z,
const unsigned int c)
const {
24018 return (
float)(*mp)(x,y,z,c);
24031 const unsigned int y0=0,
const unsigned int z0=0,
const unsigned int c0=0) {
24032 const unsigned int beg = (
unsigned int)
offset(x0,y0,z0,c0),
end =
offset(x1,y0,z0,c0);
24035 "get_shared_points(): Invalid request of a shared-memory subset (%u->%u,%u,%u,%u).",
24039 return CImg<T>(_data+beg,x1-x0+1,1,1,1,
true);
24044 const unsigned int y0=0,
const unsigned int z0=0,
const unsigned int c0=0)
const {
24045 const unsigned int beg = (
unsigned int)
offset(x0,y0,z0,c0),
end =
offset(x1,y0,z0,c0);
24048 "get_shared_points(): Invalid request of a shared-memory subset (%u->%u,%u,%u,%u).",
24052 return CImg<T>(_data+beg,x1-x0+1,1,1,1,
true);
24063 const unsigned int z0=0,
const unsigned int c0=0) {
24064 const unsigned int beg =
offset(0,y0,z0,c0),
end =
offset(0,y1,z0,c0);
24067 "get_shared_rows(): Invalid request of a shared-memory subset "
24068 "(0->%u,%u->%u,%u,%u).",
24070 _width-1,y0,y1,z0,c0);
24072 return CImg<T>(_data+beg,_width,y1-y0+1,1,1,
true);
24077 const unsigned int z0=0,
const unsigned int c0=0)
const {
24078 const unsigned int beg =
offset(0,y0,z0,c0),
end =
offset(0,y1,z0,c0);
24081 "get_shared_rows(): Invalid request of a shared-memory subset "
24082 "(0->%u,%u->%u,%u,%u).",
24084 _width-1,y0,y1,z0,c0);
24086 return CImg<T>(_data+beg,_width,y1-y0+1,1,1,
true);
24114 "get_shared_slices(): Invalid request of a shared-memory subset "
24115 "(0->%u,0->%u,%u->%u,%u).",
24117 _width-1,_height-1,z0,z1,c0);
24119 return CImg<T>(_data+beg,_width,_height,z1-z0+1,1,
true);
24127 "get_shared_slices(): Invalid request of a shared-memory subset "
24128 "(0->%u,0->%u,%u->%u,%u).",
24130 _width-1,_height-1,z0,z1,c0);
24132 return CImg<T>(_data+beg,_width,_height,z1-z0+1,1,
true);
24158 "get_shared_channels(): Invalid request of a shared-memory subset "
24159 "(0->%u,0->%u,0->%u,%u->%u).",
24161 _width-1,_height-1,_depth-1,c0,c1);
24163 return CImg<T>(_data+beg,_width,_height,_depth,c1-c0+1,
true);
24171 "get_shared_channels(): Invalid request of a shared-memory subset "
24172 "(0->%u,0->%u,0->%u,%u->%u).",
24174 _width-1,_height-1,_depth-1,c0,c1);
24176 return CImg<T>(_data+beg,_width,_height,_depth,c1-c0+1,
true);
24194 return CImg<T>(_data,_width,_height,_depth,_spectrum,
true);
24199 return CImg<T>(_data,_width,_height,_depth,_spectrum,
true);
24217 const unsigned int dp = (
unsigned int)(nb?-nb:1);
24221 res.
assign(_width/dp+(_width%dp?1:0),1,1);
24222 const unsigned int pe = _width - dp;
24223 #ifdef cimg_use_openmp
24224 #pragma omp parallel for if (res._width>=128 && _height*_depth*_spectrum>=128)
24226 for (
unsigned int p = 0; p<pe; p+=dp)
24227 get_crop(p,0,0,0,p+dp-1,_height-1,_depth-1,_spectrum-1).move_to(res[p/dp]);
24228 get_crop((res._width-1)*dp,0,0,0,_width-1,_height-1,_depth-1,_spectrum-1).move_to(res.
back());
24229 }
else res.
assign(*
this);
24233 res.
assign(_height/dp+(_height%dp?1:0),1,1);
24234 const unsigned int pe = _height - dp;
24235 #ifdef cimg_use_openmp
24236 #pragma omp parallel for if (res._width>=128 && _width*_depth*_spectrum>=128)
24238 for (
unsigned int p = 0; p<pe; p+=dp)
24239 get_crop(0,p,0,0,_width-1,p+dp-1,_depth-1,_spectrum-1).move_to(res[p/dp]);
24240 get_crop(0,(res._width-1)*dp,0,0,_width-1,_height-1,_depth-1,_spectrum-1).move_to(res.
back());
24241 }
else res.
assign(*
this);
24245 res.
assign(_depth/dp+(_depth%dp?1:0),1,1);
24246 const unsigned int pe = _depth - dp;
24247 #ifdef cimg_use_openmp
24248 #pragma omp parallel for if (res._width>=128 && _width*_height*_spectrum>=128)
24250 for (
unsigned int p = 0; p<pe; p+=dp)
24251 get_crop(0,0,p,0,_width-1,_height-1,p+dp-1,_spectrum-1).move_to(res[p/dp]);
24252 get_crop(0,0,(res._width-1)*dp,0,_width-1,_height-1,_depth-1,_spectrum-1).move_to(res.
back());
24253 }
else res.
assign(*
this);
24256 if (_spectrum>dp) {
24257 res.
assign(_spectrum/dp+(_spectrum%dp?1:0),1,1);
24258 const unsigned int pe = _spectrum - dp;
24259 #ifdef cimg_use_openmp
24260 #pragma omp parallel for if (res._width>=128 && _width*_height*_depth>=128)
24262 for (
unsigned int p = 0; p<pe; p+=dp)
24263 get_crop(0,0,0,p,_width-1,_height-1,_depth-1,p+dp-1).move_to(res[p/dp]);
24264 get_crop(0,0,0,(res._width-1)*dp,_width-1,_height-1,_depth-1,_spectrum-1).move_to(res.
back());
24265 }
else res.
assign(*
this);
24269 const unsigned int siz = _axis==
'x'?_width:_axis==
'y'?_height:_axis==
'z'?_depth:_axis==
'c'?_spectrum:0;
24270 if ((
unsigned int)nb>siz)
24272 "get_split(): Instance cannot be split along %c-axis into %u blocs.",
24275 if (nb==1) res.
assign(*
this);
24277 int err = (int)siz;
24278 unsigned int _p = 0;
24281 cimg_forX(*
this,p)
if ((err-=nb)<=0) {
24282 get_crop(_p,0,0,0,p,_height-1,_depth-1,_spectrum-1).move_to(res);
24288 cimg_forY(*
this,p)
if ((err-=nb)<=0) {
24289 get_crop(0,_p,0,0,_width-1,p,_depth-1,_spectrum-1).move_to(res);
24295 cimg_forZ(*
this,p)
if ((err-=nb)<=0) {
24296 get_crop(0,0,_p,0,_width-1,_height-1,p,_spectrum-1).move_to(res);
24302 cimg_forC(*
this,p)
if ((err-=nb)<=0) {
24303 get_crop(0,0,0,_p,_width-1,_height-1,_depth-1,p).move_to(res);
24323 for (
const T *ps = _data, *_ps = ps, *
const pe =
end(); ps<pe; ) {
24324 while (_ps<pe && *_ps==value) ++_ps;
24325 unsigned int siz = _ps - ps;
24326 if (siz && keep_values) res.
insert(
CImg<T>(ps,1,siz,1,1,is_shared),~0U,is_shared);
24328 while (_ps<pe && *_ps!=value) ++_ps;
24330 if (siz) res.
insert(
CImg<T>(ps,1,siz,1,1,is_shared),~0U,is_shared);
24342 template<
typename t>
24347 if (values.size()==1)
return get_split(*values,keep_values,is_shared);
24348 const t *pve = values.end();
24349 for (
const T *ps = _data, *_ps = ps, *
const pe =
end(); ps<pe; ) {
24355 const T *__ps = _ps;
24356 while (__ps<pe && pv<pve && *__ps==(T)*pv) { ++__ps; ++pv; }
24357 if (pv==pve) _ps = __ps;
24359 unsigned int siz = _ps - ps;
24360 if (siz && keep_values) res.
insert(
CImg<T>(ps,1,siz,1,1,is_shared),~0U,is_shared);
24366 while (_ps<pe && *_ps!=(T)*pv) ++_ps;
24368 const T *__ps = _ps + 1;
24370 while (__ps<pe && pv<pve && *__ps==(T)*pv) { ++__ps; ++pv; }
24371 if (pv!=pve) _ps = __ps;
24373 }
while (_ps<pe && pv!=pve);
24377 if (siz) res.
insert(
CImg<T>(ps,1,siz,1,1,is_shared),~0U,is_shared);
24387 T *p0 = _data, current = *p0;
24388 cimg_for(*
this,p,T)
if (*p!=current) {
24389 res.
insert(
CImg<T>(p0,1,p-p0,1,1,is_shared),~0U,is_shared); p0 = p; current = *p;
24401 template<
typename t>
24404 if (!img)
return *
this;
24411 if (!img)
return *
this;
24416 template<
typename t>
24419 if (!img)
return +*
this;
24426 if (!img)
return +*
this;
24446 template<
typename t>
24448 if (
is_empty() || !mask)
return *
this;
24449 return get_correlate(mask,boundary_conditions,is_normalized).move_to(*
this);
24453 template<
typename t>
24455 const bool is_normalized=
false)
const {
24456 if (
is_empty() || !mask)
return *
this;
24457 typedef _cimg_Ttfloat Ttfloat;
24459 if (boundary_conditions && mask._width==mask._height &&
24460 ((mask._depth==1 && mask._width<=5) || (mask._depth==mask._width && mask._width<=3))) {
24462 Ttfloat *ptrd = res._data;
24463 switch (mask._depth) {
24468 const CImg<t> _mask = mask.get_shared_channel(c%mask._spectrum);
24469 if (is_normalized) {
24470 const Ttfloat _M = (Ttfloat)_mask.magnitude(2), M = _M*_M;
24471 cimg_for3x3x3(_img,x,y,z,0,I,T) {
24472 const Ttfloat N = M*(I[ 0]*I[ 0] + I[ 1]*I[ 1] + I[ 2]*I[ 2] +
24473 I[ 3]*I[ 3] + I[ 4]*I[ 4] + I[ 5]*I[ 5] +
24474 I[ 6]*I[ 6] + I[ 7]*I[ 7] + I[ 8]*I[ 8] +
24475 I[ 9]*I[ 9] + I[10]*I[10] + I[11]*I[11] +
24476 I[12]*I[12] + I[13]*I[13] + I[14]*I[14] +
24477 I[15]*I[15] + I[16]*I[16] + I[17]*I[17] +
24478 I[18]*I[18] + I[19]*I[19] + I[20]*I[20] +
24479 I[21]*I[21] + I[22]*I[22] + I[23]*I[23] +
24480 I[24]*I[24] + I[25]*I[25] + I[26]*I[26]);
24481 *(ptrd++) = (Ttfloat)(N?(I[ 0]*_mask[ 0] + I[ 1]*_mask[ 1] + I[ 2]*_mask[ 2] +
24482 I[ 3]*_mask[ 3] + I[ 4]*_mask[ 4] + I[ 5]*_mask[ 5] +
24483 I[ 6]*_mask[ 6] + I[ 7]*_mask[ 7] + I[ 8]*_mask[ 8] +
24484 I[ 9]*_mask[ 9] + I[10]*_mask[10] + I[11]*_mask[11] +
24485 I[12]*_mask[12] + I[13]*_mask[13] + I[14]*_mask[14] +
24486 I[15]*_mask[15] + I[16]*_mask[16] + I[17]*_mask[17] +
24487 I[18]*_mask[18] + I[19]*_mask[19] + I[20]*_mask[20] +
24488 I[21]*_mask[21] + I[22]*_mask[22] + I[23]*_mask[23] +
24489 I[24]*_mask[24] + I[25]*_mask[25] + I[26]*_mask[26])/std::sqrt(N):0);
24491 }
else cimg_for3x3x3(_img,x,y,z,0,I,T)
24492 *(ptrd++) = (Ttfloat)(I[ 0]*_mask[ 0] + I[ 1]*_mask[ 1] + I[ 2]*_mask[ 2] +
24493 I[ 3]*_mask[ 3] + I[ 4]*_mask[ 4] + I[ 5]*_mask[ 5] +
24494 I[ 6]*_mask[ 6] + I[ 7]*_mask[ 7] + I[ 8]*_mask[ 8] +
24495 I[ 9]*_mask[ 9] + I[10]*_mask[10] + I[11]*_mask[11] +
24496 I[12]*_mask[12] + I[13]*_mask[13] + I[14]*_mask[14] +
24497 I[15]*_mask[15] + I[16]*_mask[16] + I[17]*_mask[17] +
24498 I[18]*_mask[18] + I[19]*_mask[19] + I[20]*_mask[20] +
24499 I[21]*_mask[21] + I[22]*_mask[22] + I[23]*_mask[23] +
24500 I[24]*_mask[24] + I[25]*_mask[25] + I[26]*_mask[26]);
24507 const CImg<t> _mask = mask.get_shared_channel(c%mask._spectrum);
24508 if (is_normalized) {
24509 const Ttfloat _M = (Ttfloat)_mask.magnitude(2), M = _M*_M;
24510 cimg_for2x2x2(_img,x,y,z,0,I,T) {
24511 const Ttfloat N = M*(I[0]*I[0] + I[1]*I[1] +
24512 I[2]*I[2] + I[3]*I[3] +
24513 I[4]*I[4] + I[5]*I[5] +
24514 I[6]*I[6] + I[7]*I[7]);
24515 *(ptrd++) = (Ttfloat)(N?(I[0]*_mask[0] + I[1]*_mask[1] +
24516 I[2]*_mask[2] + I[3]*_mask[3] +
24517 I[4]*_mask[4] + I[5]*_mask[5] +
24518 I[6]*_mask[6] + I[7]*_mask[7])/std::sqrt(N):0);
24520 }
else cimg_for2x2x2(_img,x,y,z,0,I,T)
24521 *(ptrd++) = (Ttfloat)(I[0]*_mask[0] + I[1]*_mask[1] +
24522 I[2]*_mask[2] + I[3]*_mask[3] +
24523 I[4]*_mask[4] + I[5]*_mask[5] +
24524 I[6]*_mask[6] + I[7]*_mask[7]);
24529 switch (mask._width) {
24534 const CImg<t> _mask = mask.get_shared_channel(c%mask._spectrum);
24535 if (is_normalized) {
24536 const Ttfloat _M = (Ttfloat)_mask.magnitude(2), M = _M*_M;
24537 cimg_forZ(_img,z) cimg_for6x6(_img,x,y,z,0,I,T) {
24538 const Ttfloat N = M*(I[ 0]*I[ 0] + I[ 1]*I[ 1] + I[ 2]*I[ 2] + I[ 3]*I[ 3] + I[ 4]*I[ 4] + I[ 5]*I[ 5] +
24539 I[ 6]*I[ 6] + I[ 7]*I[ 7] + I[ 8]*I[ 8] + I[ 9]*I[ 9] + I[10]*I[10] + I[11]*I[11] +
24540 I[12]*I[12] + I[13]*I[13] + I[14]*I[14] + I[15]*I[15] + I[16]*I[16] + I[17]*I[17] +
24541 I[18]*I[18] + I[19]*I[19] + I[20]*I[20] + I[21]*I[21] + I[22]*I[22] + I[23]*I[23] +
24542 I[24]*I[24] + I[25]*I[25] + I[26]*I[26] + I[27]*I[27] + I[28]*I[28] + I[29]*I[29] +
24543 I[30]*I[30] + I[31]*I[31] + I[32]*I[32] + I[33]*I[33] + I[34]*I[34] + I[35]*I[35]);
24544 *(ptrd++) = (Ttfloat)(N?(I[ 0]*_mask[ 0] + I[ 1]*_mask[ 1] + I[ 2]*_mask[ 2] + I[ 3]*_mask[ 3] + I[ 4]*_mask[ 4] + I[ 5]*_mask[ 5] +
24545 I[ 6]*_mask[ 6] + I[ 7]*_mask[ 7] + I[ 8]*_mask[ 8] + I[ 9]*_mask[ 9] + I[10]*_mask[10] + I[11]*_mask[11] +
24546 I[12]*_mask[12] + I[13]*_mask[13] + I[14]*_mask[14] + I[15]*_mask[15] + I[16]*_mask[16] + I[17]*_mask[17] +
24547 I[18]*_mask[18] + I[19]*_mask[19] + I[20]*_mask[20] + I[21]*_mask[21] + I[22]*_mask[22] + I[23]*_mask[23] +
24548 I[24]*_mask[24] + I[25]*_mask[25] + I[26]*_mask[26] + I[27]*_mask[27] + I[28]*_mask[28] + I[29]*_mask[29] +
24549 I[30]*_mask[30] + I[31]*_mask[31] + I[32]*_mask[32] + I[33]*_mask[33] + I[34]*_mask[34] + I[35]*_mask[35])/std::sqrt(N):0);
24551 }
else cimg_forZ(_img,z) cimg_for6x6(_img,x,y,z,0,I,T)
24552 *(ptrd++) = (Ttfloat)(I[ 0]*_mask[ 0] + I[ 1]*_mask[ 1] + I[ 2]*_mask[ 2] + I[ 3]*_mask[ 3] + I[ 4]*_mask[ 4] + I[ 5]*_mask[ 5] +
24553 I[ 6]*_mask[ 6] + I[ 7]*_mask[ 7] + I[ 8]*_mask[ 8] + I[ 9]*_mask[ 9] + I[10]*_mask[10] + I[11]*_mask[11] +
24554 I[12]*_mask[12] + I[13]*_mask[13] + I[14]*_mask[14] + I[15]*_mask[15] + I[16]*_mask[16] + I[17]*_mask[17] +
24555 I[18]*_mask[18] + I[19]*_mask[19] + I[20]*_mask[20] + I[21]*_mask[21] + I[22]*_mask[22] + I[23]*_mask[23] +
24556 I[24]*_mask[24] + I[25]*_mask[25] + I[26]*_mask[26] + I[27]*_mask[27] + I[28]*_mask[28] + I[29]*_mask[29] +
24557 I[30]*_mask[30] + I[31]*_mask[31] + I[32]*_mask[32] + I[33]*_mask[33] + I[34]*_mask[34] + I[35]*_mask[35]);
24564 const CImg<t> _mask = mask.get_shared_channel(c%mask._spectrum);
24565 if (is_normalized) {
24566 const Ttfloat _M = (Ttfloat)_mask.magnitude(2), M = _M*_M;
24567 cimg_forZ(_img,z) cimg_for5x5(_img,x,y,z,0,I,T) {
24568 const Ttfloat N = M*(I[ 0]*I[ 0] + I[ 1]*I[ 1] + I[ 2]*I[ 2] + I[ 3]*I[ 3] + I[ 4]*I[ 4] +
24569 I[ 5]*I[ 5] + I[ 6]*I[ 6] + I[ 7]*I[ 7] + I[ 8]*I[ 8] + I[ 9]*I[ 9] +
24570 I[10]*I[10] + I[11]*I[11] + I[12]*I[12] + I[13]*I[13] + I[14]*I[14] +
24571 I[15]*I[15] + I[16]*I[16] + I[17]*I[17] + I[18]*I[18] + I[19]*I[19] +
24572 I[20]*I[20] + I[21]*I[21] + I[22]*I[22] + I[23]*I[23] + I[24]*I[24]);
24573 *(ptrd++) = (Ttfloat)(N?(I[ 0]*_mask[ 0] + I[ 1]*_mask[ 1] + I[ 2]*_mask[ 2] + I[ 3]*_mask[ 3] + I[ 4]*_mask[ 4] +
24574 I[ 5]*_mask[ 5] + I[ 6]*_mask[ 6] + I[ 7]*_mask[ 7] + I[ 8]*_mask[ 8] + I[ 9]*_mask[ 9] +
24575 I[10]*_mask[10] + I[11]*_mask[11] + I[12]*_mask[12] + I[13]*_mask[13] + I[14]*_mask[14] +
24576 I[15]*_mask[15] + I[16]*_mask[16] + I[17]*_mask[17] + I[18]*_mask[18] + I[19]*_mask[19] +
24577 I[20]*_mask[20] + I[21]*_mask[21] + I[22]*_mask[22] + I[23]*_mask[23] + I[24]*_mask[24])/std::sqrt(N):0);
24579 }
else cimg_forZ(_img,z) cimg_for5x5(_img,x,y,z,0,I,T)
24580 *(ptrd++) = (Ttfloat)(I[ 0]*_mask[ 0] + I[ 1]*_mask[ 1] + I[ 2]*_mask[ 2] + I[ 3]*_mask[ 3] + I[ 4]*_mask[ 4] +
24581 I[ 5]*_mask[ 5] + I[ 6]*_mask[ 6] + I[ 7]*_mask[ 7] + I[ 8]*_mask[ 8] + I[ 9]*_mask[ 9] +
24582 I[10]*_mask[10] + I[11]*_mask[11] + I[12]*_mask[12] + I[13]*_mask[13] + I[14]*_mask[14] +
24583 I[15]*_mask[15] + I[16]*_mask[16] + I[17]*_mask[17] + I[18]*_mask[18] + I[19]*_mask[19] +
24584 I[20]*_mask[20] + I[21]*_mask[21] + I[22]*_mask[22] + I[23]*_mask[23] + I[24]*_mask[24]);
24591 const CImg<t> _mask = mask.get_shared_channel(c%mask._spectrum);
24592 if (is_normalized) {
24593 const Ttfloat _M = (Ttfloat)_mask.magnitude(2), M = _M*_M;
24594 cimg_forZ(_img,z) cimg_for4x4(_img,x,y,z,0,I,T) {
24595 const Ttfloat N = M*(I[ 0]*I[ 0] + I[ 1]*I[ 1] + I[ 2]*I[ 2] + I[ 3]*I[ 3] +
24596 I[ 4]*I[ 4] + I[ 5]*I[ 5] + I[ 6]*I[ 6] + I[ 7]*I[ 7] +
24597 I[ 8]*I[ 8] + I[ 9]*I[ 9] + I[10]*I[10] + I[11]*I[11] +
24598 I[12]*I[12] + I[13]*I[13] + I[14]*I[14] + I[15]*I[15]);
24599 *(ptrd++) = (Ttfloat)(N?(I[ 0]*_mask[ 0] + I[ 1]*_mask[ 1] + I[ 2]*_mask[ 2] + I[ 3]*_mask[ 3] +
24600 I[ 4]*_mask[ 4] + I[ 5]*_mask[ 5] + I[ 6]*_mask[ 6] + I[ 7]*_mask[ 7] +
24601 I[ 8]*_mask[ 8] + I[ 9]*_mask[ 9] + I[10]*_mask[10] + I[11]*_mask[11] +
24602 I[12]*_mask[12] + I[13]*_mask[13] + I[14]*_mask[14] + I[15]*_mask[15])/std::sqrt(N):0);
24604 }
else cimg_forZ(_img,z) cimg_for4x4(_img,x,y,z,0,I,T)
24605 *(ptrd++) = (Ttfloat)(I[ 0]*_mask[ 0] + I[ 1]*_mask[ 1] + I[ 2]*_mask[ 2] + I[ 3]*_mask[ 3] +
24606 I[ 4]*_mask[ 4] + I[ 5]*_mask[ 5] + I[ 6]*_mask[ 6] + I[ 7]*_mask[ 7] +
24607 I[ 8]*_mask[ 8] + I[ 9]*_mask[ 9] + I[10]*_mask[10] + I[11]*_mask[11] +
24608 I[12]*_mask[12] + I[13]*_mask[13] + I[14]*_mask[14] + I[15]*_mask[15]);
24615 const CImg<t> _mask = mask.get_shared_channel(c%mask._spectrum);
24616 if (is_normalized) {
24617 const Ttfloat _M = (Ttfloat)_mask.magnitude(2), M = _M*_M;
24618 cimg_forZ(_img,z) cimg_for3x3(_img,x,y,z,0,I,T) {
24619 const Ttfloat N = M*(I[0]*I[0] + I[1]*I[1] + I[2]*I[2] +
24620 I[3]*I[3] + I[4]*I[4] + I[5]*I[5] +
24621 I[6]*I[6] + I[7]*I[7] + I[8]*I[8]);
24622 *(ptrd++) = (Ttfloat)(N?(I[0]*_mask[0] + I[1]*_mask[1] + I[2]*_mask[2] +
24623 I[3]*_mask[3] + I[4]*_mask[4] + I[5]*_mask[5] +
24624 I[6]*_mask[6] + I[7]*_mask[7] + I[8]*_mask[8])/std::sqrt(N):0);
24626 }
else cimg_forZ(_img,z) cimg_for3x3(_img,x,y,z,0,I,T)
24627 *(ptrd++) = (Ttfloat)(I[0]*_mask[0] + I[1]*_mask[1] + I[2]*_mask[2] +
24628 I[3]*_mask[3] + I[4]*_mask[4] + I[5]*_mask[5] +
24629 I[6]*_mask[6] + I[7]*_mask[7] + I[8]*_mask[8]);
24636 const CImg<t> _mask = mask.get_shared_channel(c%mask._spectrum);
24637 if (is_normalized) {
24638 const Ttfloat _M = (Ttfloat)_mask.magnitude(2), M = _M*_M;
24639 cimg_forZ(_img,z) cimg_for2x2(_img,x,y,z,0,I,T) {
24640 const Ttfloat N = M*(I[0]*I[0] + I[1]*I[1] +
24641 I[2]*I[2] + I[3]*I[3]);
24642 *(ptrd++) = (Ttfloat)(N?(I[0]*_mask[0] + I[1]*_mask[1] +
24643 I[2]*_mask[2] + I[3]*_mask[3])/std::sqrt(N):0);
24645 }
else cimg_forZ(_img,z) cimg_for2x2(_img,x,y,z,0,I,T)
24646 *(ptrd++) = (Ttfloat)(I[0]*_mask[0] + I[1]*_mask[1] +
24647 I[2]*_mask[2] + I[3]*_mask[3]);
24651 if (is_normalized) res.fill(1);
24652 else cimg_forC(res,c) {
24654 const CImg<t> _mask = mask.get_shared_channel(c%mask._spectrum);
24655 res.get_shared_channel(c).assign(_img)*=_mask[0];
24662 mx2 = mask.width()/2, my2 = mask.height()/2, mz2 = mask.depth()/2,
24663 mx1 = mx2 - 1 + (mask.width()%2), my1 = my2 - 1 + (mask.height()%2), mz1 = mz2 - 1 + (mask.depth()%2),
24665 #ifdef cimg_use_openmp
24666 #pragma omp parallel for if (res._spectrum>=2)
24670 const CImg<t> _mask = mask.get_shared_channel(c%mask._spectrum);
24671 if (is_normalized) {
24672 const Ttfloat _M = (Ttfloat)_mask.magnitude(2), M = _M*_M;
24673 #ifdef cimg_use_openmp
24674 #pragma omp parallel for collapse(3) if (_width*_height*_depth>=32768)
24676 for (
int z = mz1; z<mze; ++z)
24677 for (
int y = my1; y<mye; ++y)
24678 for (
int x = mx1; x<mxe; ++x) {
24679 Ttfloat val = 0, N = 0;
24680 for (
int zm = -mz1; zm<=mz2; ++zm)
24681 for (
int ym = -my1; ym<=my2; ++ym)
24682 for (
int xm = -mx1; xm<=mx2; ++xm) {
24683 const Ttfloat _val = (Ttfloat)_img(x+xm,y+ym,z+zm);
24684 val+=_val*_mask(mx1+xm,my1+ym,mz1+zm);
24688 res(x,y,z,c) = (Ttfloat)(N?val/std::sqrt(N):0);
24690 if (boundary_conditions)
24691 #ifdef cimg_use_openmp
24692 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
24694 cimg_forYZ(res,y,z)
24695 for (
int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) {
24696 Ttfloat val = 0, N = 0;
24697 for (
int zm = -mz1; zm<=mz2; ++zm)
24698 for (
int ym = -my1; ym<=my2; ++ym)
24699 for (
int xm = -mx1; xm<=mx2; ++xm) {
24700 const Ttfloat _val = (Ttfloat)_img._atXYZ(x+xm,y+ym,z+zm);
24701 val+=_val*_mask(mx1+xm,my1+ym,mz1+zm);
24705 res(x,y,z,c) = (Ttfloat)(N?val/std::sqrt(N):0);
24708 #ifdef cimg_use_openmp
24709 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
24711 cimg_forYZ(res,y,z)
24712 for (
int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) {
24713 Ttfloat val = 0, N = 0;
24714 for (
int zm = -mz1; zm<=mz2; ++zm)
24715 for (
int ym = -my1; ym<=my2; ++ym)
24716 for (
int xm = -mx1; xm<=mx2; ++xm) {
24717 const Ttfloat _val = (Ttfloat)_img.atXYZ(x+xm,y+ym,z+zm,0,0);
24718 val+=_val*_mask(mx1+xm,my1+ym,mz1+zm);
24722 res(x,y,z,c) = (Ttfloat)(N?val/std::sqrt(N):0);
24725 #ifdef cimg_use_openmp
24726 #pragma omp parallel for collapse(3) if (_width*_height*_depth>=32768)
24728 for (
int z = mz1; z<mze; ++z)
24729 for (
int y = my1; y<mye; ++y)
24730 for (
int x = mx1; x<mxe; ++x) {
24732 for (
int zm = -mz1; zm<=mz2; ++zm)
24733 for (
int ym = -my1; ym<=my2; ++ym)
24734 for (
int xm = -mx1; xm<=mx2; ++xm)
24735 val+=_img(x+xm,y+ym,z+zm)*_mask(mx1+xm,my1+ym,mz1+zm);
24736 res(x,y,z,c) = (Ttfloat)val;
24738 if (boundary_conditions)
24739 #ifdef cimg_use_openmp
24740 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
24742 cimg_forYZ(res,y,z)
24743 for (
int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) {
24745 for (
int zm = -mz1; zm<=mz2; ++zm)
24746 for (
int ym = -my1; ym<=my2; ++ym)
24747 for (
int xm = -mx1; xm<=mx2; ++xm)
24748 val+=_img._atXYZ(x+xm,y+ym,z+zm)*_mask(mx1+xm,my1+ym,mz1+zm);
24749 res(x,y,z,c) = (Ttfloat)val;
24752 #ifdef cimg_use_openmp
24753 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
24755 cimg_forYZ(res,y,z)
24756 for (
int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) {
24758 for (
int zm = -mz1; zm<=mz2; ++zm)
24759 for (
int ym = -my1; ym<=my2; ++ym)
24760 for (
int xm = -mx1; xm<=mx2; ++xm)
24761 val+=_img.atXYZ(x+xm,y+ym,z+zm,0,0)*_mask(mx1+xm,my1+ym,mz1+zm);
24762 res(x,y,z,c) = (Ttfloat)val;
24779 template<
typename t>
24781 if (
is_empty() || !mask)
return *
this;
24782 return get_convolve(mask,boundary_conditions,is_normalized).move_to(*
this);
24786 template<
typename t>
24788 const bool is_normalized=
false)
const {
24789 if (
is_empty() || !mask)
return *
this;
24791 resize(mask,-1),boundary_conditions,is_normalized);
24800 template<
typename t>
24802 const bool is_normalized=
false) {
24803 if (
is_empty() || !mask)
return *
this;
24804 return get_erode(mask,boundary_conditions,is_normalized).move_to(*
this);
24808 template<
typename t>
24810 const bool is_normalized=
false)
const {
24811 if (
is_empty() || !mask)
return *
this;
24812 typedef _cimg_Tt Tt;
24815 mx2 = mask.width()/2, my2 = mask.height()/2, mz2 = mask.depth()/2,
24816 mx1 = mx2 - 1 + (mask.width()%2), my1 = my2 - 1 + (mask.height()%2), mz1 = mz2 - 1 + (mask.depth()%2),
24818 #ifdef cimg_use_openmp
24819 #pragma omp parallel for if (_spectrum>=2)
24821 cimg_forC(*
this,c) {
24823 const CImg<t> _mask = mask.get_shared_channel(c%mask._spectrum);
24824 if (is_normalized) {
24825 #ifdef cimg_use_openmp
24826 #pragma omp parallel for collapse(3) if (_width*_height*_depth>=32768)
24828 for (
int z = mz1; z<mze; ++z)
24829 for (
int y = my1; y<mye; ++y)
24830 for (
int x = mx1; x<mxe; ++x) {
24832 for (
int zm = -mz1; zm<=mz2; ++zm)
24833 for (
int ym = -my1; ym<=my2; ++ym)
24834 for (
int xm = -mx1; xm<=mx2; ++xm) {
24835 const t mval = _mask(mx1+xm,my1+ym,mz1+zm);
24836 const Tt cval = (Tt)(_img(x+xm,y+ym,z+zm) + mval);
24837 if (mval && cval<min_val) min_val = cval;
24839 res(x,y,z,c) = min_val;
24841 if (boundary_conditions)
24842 #ifdef cimg_use_openmp
24843 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
24845 cimg_forYZ(res,y,z)
24846 for (
int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) {
24848 for (
int zm = -mz1; zm<=mz2; ++zm)
24849 for (
int ym = -my1; ym<=my2; ++ym)
24850 for (
int xm = -mx1; xm<=mx2; ++xm) {
24851 const t mval = _mask(mx1+xm,my1+ym,mz1+zm);
24852 const Tt cval = (Tt)(_img._atXYZ(x+xm,y+ym,z+zm) + mval);
24853 if (mval && cval<min_val) min_val = cval;
24855 res(x,y,z,c) = min_val;
24858 #ifdef cimg_use_openmp
24859 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
24861 cimg_forYZ(res,y,z)
24862 for (
int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) {
24864 for (
int zm = -mz1; zm<=mz2; ++zm)
24865 for (
int ym = -my1; ym<=my2; ++ym)
24866 for (
int xm = -mx1; xm<=mx2; ++xm) {
24867 const t mval = _mask(mx1+xm,my1+ym,mz1+zm);
24868 const Tt cval = (Tt)(_img.atXYZ(x+xm,y+ym,z+zm,0,0) + mval);
24869 if (mval && cval<min_val) min_val = cval;
24871 res(x,y,z,c) = min_val;
24875 #ifdef cimg_use_openmp
24876 #pragma omp parallel for collapse(3) if (_width*_height*_depth>=32768)
24878 for (
int z = mz1; z<mze; ++z)
24879 for (
int y = my1; y<mye; ++y)
24880 for (
int x = mx1; x<mxe; ++x) {
24882 for (
int zm = -mz1; zm<=mz2; ++zm)
24883 for (
int ym = -my1; ym<=my2; ++ym)
24884 for (
int xm = -mx1; xm<=mx2; ++xm) {
24885 const Tt cval = (Tt)_img(x+xm,y+ym,z+zm);
24886 if (_mask(mx1+xm,my1+ym,mz1+zm) && cval<min_val) min_val = cval;
24888 res(x,y,z,c) = min_val;
24890 if (boundary_conditions)
24891 #ifdef cimg_use_openmp
24892 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
24894 cimg_forYZ(res,y,z)
24895 for (
int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) {
24897 for (
int zm = -mz1; zm<=mz2; ++zm)
24898 for (
int ym = -my1; ym<=my2; ++ym)
24899 for (
int xm = -mx1; xm<=mx2; ++xm) {
24900 const T cval = (Tt)_img._atXYZ(x+xm,y+ym,z+zm);
24901 if (_mask(mx1+xm,my1+ym,mz1+zm) && cval<min_val) min_val = cval;
24903 res(x,y,z,c) = min_val;
24906 #ifdef cimg_use_openmp
24907 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
24909 cimg_forYZ(res,y,z)
24910 for (
int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) {
24912 for (
int zm = -mz1; zm<=mz2; ++zm)
24913 for (
int ym = -my1; ym<=my2; ++ym)
24914 for (
int xm = -mx1; xm<=mx2; ++xm) {
24915 const T cval = (Tt)_img.atXYZ(x+xm,y+ym,z+zm,0,0);
24916 if (_mask(mx1+xm,my1+ym,mz1+zm) && cval<min_val) min_val = cval;
24918 res(x,y,z,c) = min_val;
24931 CImg<T>&
erode(
const unsigned int sx,
const unsigned int sy,
const unsigned int sz=1) {
24932 if (
is_empty() || (sx==1 && sy==1 && sz==1))
return *
this;
24933 if (sx>1 && _width>1) {
24934 const int L =
width(), off = 1, s = (int)sx, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1, s2 = _s2>L?L:_s2;
24936 #ifdef cimg_use_opemp
24937 #pragma omp parallel for collapse(3) firstprivate(buf) if (size()>524288)
24939 cimg_forYZC(*
this,y,z,c) {
24940 T *
const ptrdb = buf._data, *ptrd = buf._data, *
const ptrde = buf._data + L - 1;
24941 const T *
const ptrsb =
data(0,y,z,c), *ptrs = ptrsb, *
const ptrse = ptrs + L*off - off;
24942 T cur = *ptrs; ptrs+=off;
bool is_first =
true;
24943 for (
int p = s2 - 1; p>0 && ptrs<=ptrse; --p) {
24944 const T val = *ptrs; ptrs+=off;
if (val<=cur) { cur = val; is_first =
false; }}
24947 T *pd =
data(0,y,z,c); cur =
cimg::min(cur,*ptrse); cimg_forX(buf,x) { *pd = cur; pd+=off; }
24949 for (
int p = s1; p>0 && ptrd<=ptrde; --p) {
24950 const T val = *ptrs;
if (ptrs<ptrse) ptrs+=off;
if (val<=cur) { cur = val; is_first =
false; }
24953 for (
int p = L - s - 1; p>0; --p) {
24954 const T val = *ptrs; ptrs+=off;
24956 const T *nptrs = ptrs - off; cur = val;
24957 for (
int q = s - 2; q>0; --q) { nptrs-=off;
const T nval = *nptrs;
if (nval<cur) cur = nval; }
24958 nptrs-=off;
const T nval = *nptrs;
if (nval<cur) { cur = nval; is_first =
true; }
else is_first =
false;
24959 }
else {
if (val<=cur) cur = val;
else if (cur==*(ptrs-s*off)) is_first =
true; }
24962 ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off;
24963 for (
int p = s1; p>0 && ptrs>=ptrsb; --p) {
24964 const T val = *ptrs; ptrs-=off;
if (val<cur) cur = val;
24967 for (
int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) {
24968 const T val = *ptrs;
if (ptrs>ptrsb) ptrs-=off;
if (val<cur) cur = val; *(ptrd--) = cur;
24970 T *pd =
data(0,y,z,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; }
24975 if (sy>1 && _height>1) {
24976 const int L =
height(), off =
width(), s = (int)sy, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1,
24979 #ifdef cimg_use_opemp
24980 #pragma omp parallel for collapse(3) firstprivate(buf) if (size()>524288)
24982 cimg_forXZC(*
this,x,z,c) {
24983 T *
const ptrdb = buf._data, *ptrd = ptrdb, *
const ptrde = buf._data + L - 1;
24984 const T *
const ptrsb =
data(x,0,z,c), *ptrs = ptrsb, *
const ptrse = ptrs + L*off - off;
24985 T cur = *ptrs; ptrs+=off;
bool is_first =
true;
24986 for (
int p = s2 - 1; p>0 && ptrs<=ptrse; --p) {
24987 const T val = *ptrs; ptrs+=off;
if (val<=cur) { cur = val; is_first =
false; }
24991 T *pd =
data(x,0,z,c); cur =
cimg::min(cur,*ptrse); cimg_forX(buf,x) { *pd = cur; pd+=off; }
24993 for (
int p = s1; p>0 && ptrd<=ptrde; --p) {
24994 const T val = *ptrs;
if (ptrs<ptrse) ptrs+=off;
if (val<=cur) { cur = val; is_first =
false; }
24997 for (
int p = L - s - 1; p>0; --p) {
24998 const T val = *ptrs; ptrs+=off;
25000 const T *nptrs = ptrs - off; cur = val;
25001 for (
int q = s - 2; q>0; --q) { nptrs-=off;
const T nval = *nptrs;
if (nval<cur) cur = nval; }
25002 nptrs-=off;
const T nval = *nptrs;
if (nval<cur) { cur = nval; is_first =
true; }
else is_first =
false;
25003 }
else {
if (val<=cur) cur = val;
else if (cur==*(ptrs-s*off)) is_first =
true; }
25006 ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off;
25007 for (
int p = s1; p>0 && ptrs>=ptrsb; --p) {
25008 const T val = *ptrs; ptrs-=off;
if (val<cur) cur = val;
25011 for (
int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) {
25012 const T val = *ptrs;
if (ptrs>ptrsb) ptrs-=off;
if (val<cur) cur = val; *(ptrd--) = cur;
25014 T *pd =
data(x,0,z,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; }
25019 if (sz>1 && _depth>1) {
25020 const int L =
depth(), off =
width()*
height(), s = (int)sz, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1,
25023 #ifdef cimg_use_opemp
25024 #pragma omp parallel for collapse(3) firstprivate(buf) if (size()>524288)
25026 cimg_forXYC(*
this,x,y,c) {
25027 T *
const ptrdb = buf._data, *ptrd = ptrdb, *
const ptrde = buf._data + L - 1;
25028 const T *
const ptrsb =
data(x,y,0,c), *ptrs = ptrsb, *
const ptrse = ptrs + L*off - off;
25029 T cur = *ptrs; ptrs+=off;
bool is_first =
true;
25030 for (
int p = s2 - 1; p>0 && ptrs<=ptrse; --p) {
25031 const T val = *ptrs; ptrs+=off;
if (val<=cur) { cur = val; is_first =
false; }
25035 T *pd =
data(x,y,0,c); cur =
cimg::min(cur,*ptrse); cimg_forX(buf,x) { *pd = cur; pd+=off; }
25037 for (
int p = s1; p>0 && ptrd<=ptrde; --p) {
25038 const T val = *ptrs;
if (ptrs<ptrse) ptrs+=off;
if (val<=cur) { cur = val; is_first =
false; }
25041 for (
int p = L - s - 1; p>0; --p) {
25042 const T val = *ptrs; ptrs+=off;
25044 const T *nptrs = ptrs - off; cur = val;
25045 for (
int q = s - 2; q>0; --q) { nptrs-=off;
const T nval = *nptrs;
if (nval<cur) cur = nval; }
25046 nptrs-=off;
const T nval = *nptrs;
if (nval<cur) { cur = nval; is_first =
true; }
else is_first =
false;
25047 }
else {
if (val<=cur) cur = val;
else if (cur==*(ptrs-s*off)) is_first =
true; }
25050 ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off;
25051 for (
int p = s1; p>0 && ptrs>=ptrsb; --p) {
25052 const T val = *ptrs; ptrs-=off;
if (val<cur) cur = val;
25055 for (
int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) {
25056 const T val = *ptrs;
if (ptrs>ptrsb) ptrs-=off;
if (val<cur) cur = val; *(ptrd--) = cur;
25058 T *pd =
data(x,y,0,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; }
25067 return (+*
this).
erode(sx,sy,sz);
25075 return erode(s,s,s);
25080 return (+*
this).
erode(s);
25089 template<
typename t>
25091 const bool is_normalized=
false) {
25092 if (
is_empty() || !mask)
return *
this;
25093 return get_dilate(mask,boundary_conditions,is_normalized).move_to(*
this);
25097 template<
typename t>
25099 const bool is_normalized=
false)
const {
25100 if (
is_empty() || !mask)
return *
this;
25101 typedef _cimg_Tt Tt;
25102 CImg<Tt> res(_width,_height,_depth,_spectrum);
25104 mx2 = mask.width()/2, my2 = mask.height()/2, mz2 = mask.depth()/2,
25105 mx1 = mx2 - 1 + (mask.width()%2), my1 = my2 - 1 + (mask.height()%2), mz1 = mz2 - 1 + (mask.depth()%2),
25107 #ifdef cimg_use_openmp
25108 #pragma omp parallel for if (_spectrum>=2)
25110 cimg_forC(*
this,c) {
25112 const CImg<t> _mask = mask.get_shared_channel(c%mask._spectrum);
25113 if (is_normalized) {
25114 #ifdef cimg_use_openmp
25115 #pragma omp parallel for collapse(3) if (_width*_height*_depth>=32768)
25117 for (
int z = mz1; z<mze; ++z)
25118 for (
int y = my1; y<mye; ++y)
25119 for (
int x = mx1; x<mxe; ++x) {
25121 for (
int zm = -mz1; zm<=mz2; ++zm)
25122 for (
int ym = -my1; ym<=my2; ++ym)
25123 for (
int xm = -mx1; xm<=mx2; ++xm) {
25124 const t mval = _mask(mx1+xm,my1+ym,mz1+zm);
25125 const Tt cval = (Tt)(_img(x+xm,y+ym,z+zm) - mval);
25126 if (mval && cval>max_val) max_val = cval;
25128 res(x,y,z,c) = max_val;
25130 if (boundary_conditions)
25131 #ifdef cimg_use_openmp
25132 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
25134 cimg_forYZ(res,y,z)
25135 for (
int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) {
25137 for (
int zm = -mz1; zm<=mz2; ++zm)
25138 for (
int ym = -my1; ym<=my2; ++ym)
25139 for (
int xm = -mx1; xm<=mx2; ++xm) {
25140 const t mval = _mask(mx1+xm,my1+ym,mz1+zm);
25141 const Tt cval = (Tt)(_img._atXYZ(x+xm,y+ym,z+zm) - mval);
25142 if (mval && cval>max_val) max_val = cval;
25144 res(x,y,z,c) = max_val;
25147 #ifdef cimg_use_openmp
25148 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
25150 cimg_forYZ(*
this,y,z)
25151 for (
int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) {
25153 for (
int zm = -mz1; zm<=mz2; ++zm)
25154 for (
int ym = -my1; ym<=my2; ++ym)
25155 for (
int xm = -mx1; xm<=mx2; ++xm) {
25156 const t mval = _mask(mx1+xm,my1+ym,mz1+zm);
25157 const Tt cval = (Tt)(_img.atXYZ(x+xm,y+ym,z+zm,0,0) - mval);
25158 if (mval && cval>max_val) max_val = cval;
25160 res(x,y,z,c) = max_val;
25163 #ifdef cimg_use_openmp
25164 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth>=128)
25166 for (
int z = mz1; z<mze; ++z)
25167 for (
int y = my1; y<mye; ++y)
25168 for (
int x = mx1; x<mxe; ++x) {
25170 for (
int zm = -mz1; zm<=mz2; ++zm)
25171 for (
int ym = -my1; ym<=my2; ++ym)
25172 for (
int xm = -mx1; xm<=mx2; ++xm) {
25173 const Tt cval = (Tt)_img(x+xm,y+ym,z+zm);
25174 if (_mask(mx1+xm,my1+ym,mz1+zm) && cval>max_val) max_val = cval;
25176 res(x,y,z,c) = max_val;
25178 if (boundary_conditions)
25179 #ifdef cimg_use_openmp
25180 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
25182 cimg_forYZ(res,y,z)
25183 for (
int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) {
25185 for (
int zm = -mz1; zm<=mz2; ++zm)
25186 for (
int ym = -my1; ym<=my2; ++ym)
25187 for (
int xm = -mx1; xm<=mx2; ++xm) {
25188 const T cval = (Tt)_img._atXYZ(x+xm,y+ym,z+zm);
25189 if (_mask(mx1+xm,my1+ym,mz1+zm) && cval>max_val) max_val = cval;
25191 res(x,y,z,c) = max_val;
25194 #ifdef cimg_use_openmp
25195 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
25197 cimg_forYZ(res,y,z)
25198 for (
int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1-1 || x>=mxe)?++x:(x=mxe))) {
25200 for (
int zm = -mz1; zm<=mz2; ++zm)
25201 for (
int ym = -my1; ym<=my2; ++ym)
25202 for (
int xm = -mx1; xm<=mx2; ++xm) {
25203 const T cval = (Tt)_img.atXYZ(x+xm,y+ym,z+zm,0,0);
25204 if (_mask(mx1+xm,my1+ym,mz1+zm) && cval>max_val) max_val = cval;
25206 res(x,y,z,c) = max_val;
25219 CImg<T>&
dilate(
const unsigned int sx,
const unsigned int sy,
const unsigned int sz=1) {
25220 if (
is_empty() || (sx==1 && sy==1 && sz==1))
return *
this;
25221 if (sx>1 && _width>1) {
25222 const int L =
width(), off = 1, s = (int)sx, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1, s2 = _s2>L?L:_s2;
25224 #ifdef cimg_use_opemp
25225 #pragma omp parallel for collapse(3) firstprivate(buf) if (size()>524288)
25227 cimg_forYZC(*
this,y,z,c) {
25228 T *
const ptrdb = buf._data, *ptrd = ptrdb, *
const ptrde = buf._data + L - 1;
25229 const T *
const ptrsb =
data(0,y,z,c), *ptrs = ptrsb, *
const ptrse = ptrs + L*off - off;
25230 T cur = *ptrs; ptrs+=off;
bool is_first =
true;
25231 for (
int p = s2 - 1; p>0 && ptrs<=ptrse; --p) {
25232 const T val = *ptrs; ptrs+=off;
if (val>=cur) { cur = val; is_first =
false; }
25236 T *pd =
data(0,y,z,c); cur =
cimg::max(cur,*ptrse); cimg_forX(buf,x) { *pd = cur; pd+=off; }
25238 for (
int p = s1; p>0 && ptrd<=ptrde; --p) {
25239 const T val = *ptrs;
if (ptrs<ptrse) ptrs+=off;
if (val>=cur) { cur = val; is_first =
false; }
25242 for (
int p = L - s - 1; p>0; --p) {
25243 const T val = *ptrs; ptrs+=off;
25245 const T *nptrs = ptrs - off; cur = val;
25246 for (
int q = s - 2; q>0; --q) { nptrs-=off;
const T nval = *nptrs;
if (nval>cur) cur = nval; }
25247 nptrs-=off;
const T nval = *nptrs;
if (nval>cur) { cur = nval; is_first =
true; }
else is_first =
false;
25248 }
else {
if (val>=cur) cur = val;
else if (cur==*(ptrs-s*off)) is_first =
true; }
25251 ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off;
25252 for (
int p = s1; p>0 && ptrs>=ptrsb; --p) {
25253 const T val = *ptrs; ptrs-=off;
if (val>cur) cur = val;
25256 for (
int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) {
25257 const T val = *ptrs;
if (ptrs>ptrsb) ptrs-=off;
if (val>cur) cur = val; *(ptrd--) = cur;
25259 T *pd =
data(0,y,z,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; }
25264 if (sy>1 && _height>1) {
25265 const int L =
height(), off =
width(), s = (int)sy, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1,
25268 #ifdef cimg_use_opemp
25269 #pragma omp parallel for collapse(3) firstprivate(buf) if (size()>524288)
25271 cimg_forXZC(*
this,x,z,c) {
25272 T *
const ptrdb = buf._data, *ptrd = ptrdb, *
const ptrde = buf._data + L - 1;
25273 const T *
const ptrsb =
data(x,0,z,c), *ptrs = ptrsb, *
const ptrse = ptrs + L*off - off;
25274 T cur = *ptrs; ptrs+=off;
bool is_first =
true;
25275 for (
int p = s2 - 1; p>0 && ptrs<=ptrse; --p) {
25276 const T val = *ptrs; ptrs+=off;
if (val>=cur) { cur = val; is_first =
false; }
25280 T *pd =
data(x,0,z,c); cur =
cimg::max(cur,*ptrse); cimg_forX(buf,x) { *pd = cur; pd+=off; }
25282 for (
int p = s1; p>0 && ptrd<=ptrde; --p) {
25283 const T val = *ptrs;
if (ptrs<ptrse) ptrs+=off;
if (val>=cur) { cur = val; is_first =
false; }
25286 for (
int p = L - s - 1; p>0; --p) {
25287 const T val = *ptrs; ptrs+=off;
25289 const T *nptrs = ptrs - off; cur = val;
25290 for (
int q = s - 2; q>0; --q) { nptrs-=off;
const T nval = *nptrs;
if (nval>cur) cur = nval; }
25291 nptrs-=off;
const T nval = *nptrs;
if (nval>cur) { cur = nval; is_first =
true; }
else is_first =
false;
25292 }
else {
if (val>=cur) cur = val;
else if (cur==*(ptrs-s*off)) is_first =
true; }
25295 ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off;
25296 for (
int p = s1; p>0 && ptrs>=ptrsb; --p) {
25297 const T val = *ptrs; ptrs-=off;
if (val>cur) cur = val;
25300 for (
int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) {
25301 const T val = *ptrs;
if (ptrs>ptrsb) ptrs-=off;
if (val>cur) cur = val; *(ptrd--) = cur;
25303 T *pd =
data(x,0,z,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; }
25308 if (sz>1 && _depth>1) {
25309 const int L =
depth(), off =
width()*
height(), s = (int)sz, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1,
25312 #ifdef cimg_use_opemp
25313 #pragma omp parallel for collapse(3) firstprivate(buf) if (size()>524288)
25315 cimg_forXYC(*
this,x,y,c) {
25316 T *
const ptrdb = buf._data, *ptrd = ptrdb, *
const ptrde = buf._data + L - 1;
25317 const T *
const ptrsb =
data(x,y,0,c), *ptrs = ptrsb, *
const ptrse = ptrs + L*off - off;
25318 T cur = *ptrs; ptrs+=off;
bool is_first =
true;
25319 for (
int p = s2 - 1; p>0 && ptrs<=ptrse; --p) {
25320 const T val = *ptrs; ptrs+=off;
if (val>=cur) { cur = val; is_first =
false; }
25324 T *pd =
data(x,y,0,c); cur =
cimg::max(cur,*ptrse); cimg_forX(buf,x) { *pd = cur; pd+=off; }
25326 for (
int p = s1; p>0 && ptrd<=ptrde; --p) {
25327 const T val = *ptrs;
if (ptrs<ptrse) ptrs+=off;
if (val>=cur) { cur = val; is_first =
false; }
25330 for (
int p = L - s - 1; p>0; --p) {
25331 const T val = *ptrs; ptrs+=off;
25333 const T *nptrs = ptrs - off; cur = val;
25334 for (
int q = s - 2; q>0; --q) { nptrs-=off;
const T nval = *nptrs;
if (nval>cur) cur = nval; }
25335 nptrs-=off;
const T nval = *nptrs;
if (nval>cur) { cur = nval; is_first =
true; }
else is_first =
false;
25336 }
else {
if (val>=cur) cur = val;
else if (cur==*(ptrs-s*off)) is_first =
true; }
25339 ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off;
25340 for (
int p = s1; p>0 && ptrs>=ptrsb; --p) {
25341 const T val = *ptrs; ptrs-=off;
if (val>cur) cur = val;
25344 for (
int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) {
25345 const T val = *ptrs;
if (ptrs>ptrsb) ptrs-=off;
if (val>cur) cur = val; *(ptrd--) = cur;
25347 T *pd =
data(x,y,0,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; }
25356 return (+*
this).
dilate(sx,sy,sz);
25369 return (+*
this).
dilate(s);
25379 template<
typename t>
25384 "watershed(): image instance and specified priority (%u,%u,%u,%u,%p) "
25385 "have different dimensions.",
25387 priority._width,priority._height,priority._depth,priority._spectrum,priority._data);
25388 if (_spectrum!=1) {
25390 get_shared_channel(c).watershed(priority.get_shared_channel(c%priority._spectrum),fill_lines);
25394 CImg<boolT> is_queued(_width,_height,_depth,1,0);
25396 unsigned int sizeQ = 0;
25399 const T *ptrs = _data;
25400 cimg_forXYZ(*
this,x,y,z)
if (*(ptrs++)) {
25401 if (x-1>=0 && !(*
this)(x-1,y,z)) Q._priority_queue_insert(is_queued,sizeQ,priority(x-1,y,z),x-1,y,z);
25402 if (x+1<
width() && !(*
this)(x+1,y,z)) Q._priority_queue_insert(is_queued,sizeQ,priority(x+1,y,z),x+1,y,z);
25403 if (y-1>=0 && !(*
this)(x,y-1,z)) Q._priority_queue_insert(is_queued,sizeQ,priority(x,y-1,z),x,y-1,z);
25404 if (y+1<
height() && !(*
this)(x,y+1,z)) Q._priority_queue_insert(is_queued,sizeQ,priority(x,y+1,z),x,y+1,z);
25405 if (z-1>=0 && !(*
this)(x,y,z-1)) Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z-1),x,y,z-1);
25406 if (z+1<
depth() && !(*
this)(x,y,z+1)) Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z+1),x,y,z+1);
25413 const int x = (int)Q(0,1), y = (int)Q(0,2), z = (int)Q(0,3);
25414 Q._priority_queue_remove(sizeQ);
25417 bool is_same_label =
true;
25418 unsigned int label = 0;
25420 if ((*
this)(x-1,y,z)) {
25421 if (!label) label = (
unsigned int)(*
this)(x-1,y,z);
25422 else if (label!=(*
this)(x-1,y,z)) is_same_label =
false;
25423 }
else Q._priority_queue_insert(is_queued,sizeQ,priority(x-1,y,z),x-1,y,z);
25426 if ((*
this)(x+1,y,z)) {
25427 if (!label) label = (
unsigned int)(*
this)(x+1,y,z);
25428 else if (label!=(*
this)(x+1,y,z)) is_same_label =
false;
25429 }
else Q._priority_queue_insert(is_queued,sizeQ,priority(x+1,y,z),x+1,y,z);
25432 if ((*
this)(x,y-1,z)) {
25433 if (!label) label = (
unsigned int)(*
this)(x,y-1,z);
25434 else if (label!=(*
this)(x,y-1,z)) is_same_label =
false;
25435 }
else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y-1,z),x,y-1,z);
25438 if ((*
this)(x,y+1,z)) {
25439 if (!label) label = (
unsigned int)(*
this)(x,y+1,z);
25440 else if (label!=(*
this)(x,y+1,z)) is_same_label =
false;
25441 }
else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y+1,z),x,y+1,z);
25444 if ((*
this)(x,y,z-1)) {
25445 if (!label) label = (
unsigned int)(*
this)(x,y,z-1);
25446 else if (label!=(*
this)(x,y,z-1)) is_same_label =
false;
25447 }
else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z-1),x,y,z-1);
25450 if ((*
this)(x,y,z+1)) {
25451 if (!label) label = (
unsigned int)(*
this)(x,y,z+1);
25452 else if (label!=(*
this)(x,y,z+1)) is_same_label =
false;
25453 }
else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z+1),x,y,z+1);
25455 if (is_same_label) (*this)(x,y,z) = (T)
label;
25463 const T *ptrs = _data;
25464 cimg_forXYZ(*
this,x,y,z)
if (!*(ptrs++) &&
25465 ((x-1>=0 && (*
this)(x-1,y,z)) || (x+1<
width() && (*
this)(x+1,y,z)) ||
25466 (y-1>=0 && (*
this)(x,y-1,z)) || (y+1<
height() && (*
this)(x,y+1,z)) ||
25467 (z-1>=0 && (*
this)(x,y,z-1)) || (z+1>
depth() && (*
this)(x,y,z+1))))
25468 Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z),x,y,z);
25472 const int x = (int)Q(0,1), y = (int)Q(0,2), z = (int)Q(0,3);
25473 Q._priority_queue_remove(sizeQ);
25475 int xmax = 0, ymax = 0, zmax = 0;
25477 if ((*
this)(x-1,y,z)) {
25478 if (priority(x-1,y,z)>pmax) { pmax = priority(x-1,y,z); xmax = x-1; ymax = y; zmax = z; }
25479 }
else Q._priority_queue_insert(is_queued,sizeQ,priority(x-1,y,z),x-1,y,z);
25482 if ((*
this)(x+1,y,z)) {
25483 if (priority(x+1,y,z)>pmax) { pmax = priority(x+1,y,z); xmax = x+1; ymax = y; zmax = z; }
25484 }
else Q._priority_queue_insert(is_queued,sizeQ,priority(x+1,y,z),x+1,y,z);
25487 if ((*
this)(x,y-1,z)) {
25488 if (priority(x,y-1,z)>pmax) { pmax = priority(x,y-1,z); xmax = x; ymax = y-1; zmax = z; }
25489 }
else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y-1,z),x,y-1,z);
25492 if ((*
this)(x,y+1,z)) {
25493 if (priority(x,y+1,z)>pmax) { pmax = priority(x,y+1,z); xmax = x; ymax = y+1; zmax = z; }
25494 }
else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y+1,z),x,y+1,z);
25497 if ((*
this)(x,y,z-1)) {
25498 if (priority(x,y,z-1)>pmax) { pmax = priority(x,y,z-1); xmax = x; ymax = y; zmax = z-1; }
25499 }
else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z-1),x,y,z-1);
25502 if ((*
this)(x,y,z+1)) {
25503 if (priority(x,y,z+1)>pmax) { pmax = priority(x,y,z+1); xmax = x; ymax = y; zmax = z+1; }
25504 }
else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z+1),x,y,z+1);
25506 (*this)(x,y,z) = (*
this)(xmax,ymax,zmax);
25513 template<
typename t>
25515 return (+*
this).
watershed(priority,fill_lines);
25519 template<
typename t>
25520 bool _priority_queue_insert(
CImg<boolT>& is_queued,
unsigned int& siz,
const t value,
25521 const unsigned int x,
const unsigned int y,
const unsigned int z) {
25522 if (is_queued(x,y,z))
return false;
25523 is_queued(x,y,z) =
true;
25525 (*this)(siz-1,0) = (T)value; (*this)(siz-1,1) = (T)x; (*this)(siz-1,2) = (T)y; (*this)(siz-1,3) = (T)z;
25526 for (
unsigned int pos = siz - 1, par = 0; pos && value>(*this)(par=(pos+1)/2-1,0); pos = par) {
25533 CImg<T>& _priority_queue_remove(
unsigned int& siz) {
25534 (*this)(0,0) = (*
this)(--siz,0); (*this)(0,1) = (*
this)(siz,1);
25535 (*this)(0,2) = (*
this)(siz,2); (*this)(0,3) = (*
this)(siz,3);
25536 const float value = (*this)(0,0);
25537 for (
unsigned int pos = 0, left = 0, right = 0;
25538 ((right=2*(pos+1),(left=right-1))<siz && value<(*
this)(left,0)) || (right<siz && value<(*this)(right,0));) {
25540 if ((*
this)(left,0)>(*
this)(right,0)) {
25565 CImg<T>&
deriche(
const float sigma,
const int order=0,
const char axis=
'x',
const bool boundary_conditions=
true) {
25566 #define _cimg_deriche_apply \
25567 CImg<Tfloat> Y(N); \
25568 Tfloat *ptrY = Y._data, yb = 0, yp = 0; \
25570 if (boundary_conditions) { xp = *ptrX; yb = yp = (Tfloat)(coefp*xp); } \
25571 for (int m = 0; m<N; ++m) { \
25572 const T xc = *ptrX; ptrX+=off; \
25573 const Tfloat yc = *(ptrY++) = (Tfloat)(a0*xc + a1*xp - b1*yp - b2*yb); \
25574 xp = xc; yb = yp; yp = yc; \
25576 T xn = (T)0, xa = (T)0; \
25577 Tfloat yn = 0, ya = 0; \
25578 if (boundary_conditions) { xn = xa = *(ptrX-off); yn = ya = (Tfloat)coefn*xn; } \
25579 for (int n = N-1; n>=0; --n) { \
25580 const T xc = *(ptrX-=off); \
25581 const Tfloat yc = (Tfloat)(a2*xn + a3*xa - b1*yn - b2*ya); \
25582 xa = xn; xn = xc; ya = yn; yn = yc; \
25583 *ptrX = (T)(*(--ptrY)+yc); \
25586 const float nsigma = sigma>=0?sigma:-sigma*(naxis==
'x'?_width:naxis==
'y'?_height:naxis==
'z'?_depth:_spectrum)/100;
25587 if (
is_empty() || (nsigma<0.1f && !order))
return *
this;
25589 nnsigma = nsigma<0.1f?0.1f:nsigma,
25590 alpha = 1.695f/nnsigma,
25591 ema = (float)std::exp(-alpha),
25592 ema2 = (float)std::exp(-2*alpha),
25595 float a0 = 0, a1 = 0, a2 = 0, a3 = 0, coefp = 0, coefn = 0;
25598 const float k = (1-ema)*(1-ema)/(1+2*alpha*ema-ema2);
25600 a1 = k*(alpha-1)*ema;
25601 a2 = k*(alpha+1)*ema;
25605 const float k = -(1-ema)*(1-ema)*(1-ema)/(2*(ema+1)*ema);
25612 ea = (float)std::exp(-alpha),
25613 k = -(ema2-1)/(2*alpha*ema),
25614 kn = (-2*(-1+3*ea-3*ea*ea+ea*ea*ea)/(3*ea+1+3*ea*ea+ea*ea*ea));
25616 a1 = -kn*(1+k*alpha)*ema;
25617 a2 = kn*(1-k*alpha)*ema;
25622 "deriche(): Invalid specified filter order %u "
25623 "(should be { 0=smoothing | 1=1st-derivative | 2=2nd-derivative }).",
25627 coefp = (a0+a1)/(1+b1+b2);
25628 coefn = (a2+a3)/(1+b1+b2);
25631 const int N = _width;
25632 const unsigned long off = 1U;
25633 #ifdef cimg_use_openmp
25634 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
25636 cimg_forYZC(*
this,y,z,c) { T *ptrX =
data(0,y,z,c); _cimg_deriche_apply; }
25639 const int N = _height;
25640 const unsigned long off = (
unsigned long)_width;
25641 #ifdef cimg_use_openmp
25642 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
25644 cimg_forXZC(*
this,x,z,c) { T *ptrX =
data(x,0,z,c); _cimg_deriche_apply; }
25647 const int N = _depth;
25648 const unsigned long off = (
unsigned long)_width*_height;
25649 #ifdef cimg_use_openmp
25650 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
25652 cimg_forXYC(*
this,x,y,c) { T *ptrX =
data(x,y,0,c); _cimg_deriche_apply; }
25655 const int N = _spectrum;
25656 const unsigned long off = (
unsigned long)_width*_height*_depth;
25657 #ifdef cimg_use_openmp
25658 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
25660 cimg_forXYZ(*
this,x,y,z) { T *ptrX =
data(x,y,z,0); _cimg_deriche_apply; }
25668 const bool boundary_conditions=
true)
const {
25685 const int order,
const bool boundary_conditions) {
25689 for (
int pass = 0; pass<2; ++pass) {
25690 for (
int k = 1; k<K; ++k) val[k] = (Tfloat)(boundary_conditions?*data:0);
25691 for (
int n = 0; n<N; ++n) {
25692 val[0] = (Tfloat)(*data)*filter[0];
25693 for (
int k = 1; k<K; ++k) val[0]+=val[k]*filter[k];
25695 if (!pass) data+=off;
else data-=off;
25696 for (
int k = K-1; k>0; --k) val[k] = val[k-1];
25698 if (!pass) data-=off;
25703 for (
int pass = 0; pass<2; ++pass) {
25704 for (
int k = 0; k<3; ++k) x[k] = (Tfloat)(boundary_conditions?*data:0);
25705 for (
int k = 0; k<K; ++k) val[k] = 0;
25706 for (
int n = 0; n<N-1; ++n) {
25708 x[0] = (Tfloat)*(data+off);
25709 val[0] = 0.5f * (x[0] - x[2])*filter[0];
25710 }
else val[0] = (Tfloat)(*data)*filter[0];
25711 for (
int k = 1; k<K; ++k) val[0]+=val[k]*filter[k];
25715 for (
int k = 2; k>0; --k) x[k] = x[k-1];
25717 for (
int k = K-1; k>0; --k) val[k] = val[k-1];
25724 for (
int pass = 0; pass<2; ++pass) {
25725 for (
int k = 0; k<3; ++k) x[k] = (Tfloat)(boundary_conditions?*data:0);
25726 for (
int k = 0; k<K; ++k) val[k] = 0;
25727 for (
int n = 0; n<N-1; ++n) {
25728 if (!pass) { x[0] = (Tfloat)*(data+off); val[0] = (x[1] - x[2])*filter[0]; }
25729 else { x[0] = (Tfloat)*(data-off); val[0] = (x[2] - x[1])*filter[0]; }
25730 for (
int k = 1; k<K; ++k) val[0]+=val[k]*filter[k];
25732 if (!pass) data+=off;
else data-=off;
25733 for (
int k = 2; k>0; --k) x[k] = x[k-1];
25734 for (
int k = K-1; k>0; --k) val[k] = val[k-1];
25741 for (
int pass = 0; pass<2; ++pass) {
25742 for (
int k = 0; k<3; ++k) x[k] = (Tfloat)(boundary_conditions?*data:0);
25743 for (
int k = 0; k<K; ++k) val[k] = 0;
25744 for (
int n = 0; n<N-1; ++n) {
25745 if (!pass) { x[0] = (Tfloat)*(data+off); val[0] = (x[0] - 2*x[1] + x[2])*filter[0]; }
25746 else { x[0] = (Tfloat)*(data-off); val[0] = 0.5f*(x[2] - x[0])*filter[0]; }
25747 for (
int k = 1; k<K; ++k) val[0]+=val[k]*filter[k];
25749 if (!pass) data+=off;
else data-=off;
25750 for (
int k = 2; k>0; --k) x[k] = x[k-1];
25751 for (
int k = K-1; k>0; --k) val[k] = val[k-1];
25771 CImg<T>&
vanvliet(
const float sigma,
const int order,
const char axis=
'x',
const bool boundary_conditions=
true) {
25774 const float nsigma = sigma>=0?sigma:-sigma*(naxis==
'x'?_width:naxis==
'y'?_height:naxis==
'z'?_depth:_spectrum)/100;
25775 if (
is_empty() || (nsigma<0.1f && !order))
return *
this;
25777 nnsigma = nsigma<0.1f?0.1f:nsigma,
25778 q = (Tfloat)(nnsigma<2.5?3.97156-4.14554*std::sqrt(1-0.2689*nnsigma):0.98711*nnsigma-0.96330),
25779 b0 = 1.57825f + 2.44413f*q + 1.4281f*q*q + 0.422205f*q*q*q,
25780 b1 = (2.44413f*q + 2.85619f*q*q + 1.26661f*q*q*q),
25781 b2 = -(1.4281f*q*q + 1.26661f*q*q*q),
25782 b3 = 0.422205f*q*q*q,
25783 B = 1.f - (b1 + b2 + b3)/b0;
25785 filter[0] = B; filter[1] = b1/b0; filter[2] = b2/b0; filter[3] = b3/b0;
25789 #ifdef cimg_use_openmp
25790 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
25792 cimg_forYZC(*
this,y,z,c)
25793 _cimg_recursive_apply<4>(
data(0,y,z,c),filter,_width,1U,order,boundary_conditions);
25796 #ifdef cimg_use_openmp
25797 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
25799 cimg_forXZC(*
this,x,z,c)
25800 _cimg_recursive_apply<4>(
data(x,0,z,c),filter,_height,(
unsigned long)_width,order,boundary_conditions);
25803 #ifdef cimg_use_openmp
25804 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
25806 cimg_forXYC(*
this,x,y,c)
25807 _cimg_recursive_apply<4>(
data(x,y,0,c),filter,_depth,(
unsigned long)(_width*_height),
25808 order,boundary_conditions);
25811 #ifdef cimg_use_openmp
25812 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
25814 cimg_forXYZ(*
this,x,y,z)
25815 _cimg_recursive_apply<4>(
data(x,y,z,0),filter,_spectrum,(
unsigned long)(_width*_height*_depth),
25816 order,boundary_conditions);
25824 const bool boundary_conditions=
true)
const {
25840 CImg<T>&
blur(
const float sigma_x,
const float sigma_y,
const float sigma_z,
25841 const bool boundary_conditions=
true,
const bool is_gaussian=
false) {
25844 if (_width>1)
vanvliet(sigma_x,0,
'x',boundary_conditions);
25845 if (_height>1)
vanvliet(sigma_y,0,
'y',boundary_conditions);
25846 if (_depth>1)
vanvliet(sigma_z,0,
'z',boundary_conditions);
25848 if (_width>1)
deriche(sigma_x,0,
'x',boundary_conditions);
25849 if (_height>1)
deriche(sigma_y,0,
'y',boundary_conditions);
25850 if (_depth>1)
deriche(sigma_z,0,
'z',boundary_conditions);
25858 const bool boundary_conditions=
true,
const bool is_gaussian=
false)
const {
25859 return CImg<Tfloat>(*
this,
false).
blur(sigma_x,sigma_y,sigma_z,boundary_conditions,is_gaussian);
25868 CImg<T>&
blur(
const float sigma,
const bool boundary_conditions=
true,
const bool is_gaussian=
false) {
25869 const float nsigma = sigma>=0?sigma:-sigma*
cimg::max(_width,_height,_depth)/100;
25870 return blur(nsigma,nsigma,nsigma,boundary_conditions,is_gaussian);
25875 return CImg<Tfloat>(*
this,
false).
blur(sigma,boundary_conditions,is_gaussian);
25889 template<
typename t>
25891 const float amplitude=60,
const float dl=0.8f,
const float da=30,
25892 const float gauss_prec=2,
const unsigned int interpolation_type=0,
25893 const bool is_fast_approx=1) {
25896 if (!
is_sameXYZ(G) || (G._spectrum!=3 && G._spectrum!=6))
25898 "blur_anisotropic(): Invalid specified diffusion tensor field (%u,%u,%u,%u,%p).",
25900 G._width,G._height,G._depth,G._spectrum,G._data);
25902 if (
is_empty() || amplitude<=0 || dl<0)
return *
this;
25903 const bool is_3d = (G._spectrum==6);
25904 T val_min, val_max =
max_min(val_min);
25907 CImg<Tfloat> velocity(_width,_height,_depth,_spectrum);
25908 for (
unsigned int iteration = 0; iteration<(
unsigned int)amplitude; ++iteration) {
25909 Tfloat *ptrd = velocity._data, veloc_max = 0;
25911 cimg_forC(*
this,c) {
25912 CImg_3x3x3(I,Tfloat);
25913 cimg_for3x3x3(*
this,x,y,z,c,I,Tfloat) {
25915 ixx = Incc + Ipcc - 2*Iccc,
25916 ixy = (Innc + Ippc - Inpc - Ipnc)/4,
25917 ixz = (Incn + Ipcp - Incp - Ipcn)/4,
25918 iyy = Icnc + Icpc - 2*Iccc,
25919 iyz = (Icnn + Icpp - Icnp - Icpn)/4,
25920 izz = Iccn + Iccp - 2*Iccc,
25921 veloc = (Tfloat)(G(x,y,z,0)*ixx + 2*G(x,y,z,1)*ixy + 2*G(x,y,z,2)*ixz +
25922 G(x,y,z,3)*iyy + 2*G(x,y,z,4)*iyz + G(x,y,z,5)*izz);
25924 if (veloc>veloc_max) veloc_max = veloc;
else if (-veloc>veloc_max) veloc_max = -veloc;
25928 cimg_forZC(*
this,z,c) {
25929 CImg_3x3(I,Tfloat);
25930 cimg_for3x3(*
this,x,y,z,c,I,Tfloat) {
25932 ixx = Inc + Ipc - 2*Icc,
25933 ixy = (Inn + Ipp - Inp - Ipn)/4,
25934 iyy = Icn + Icp - 2*Icc,
25935 veloc = (Tfloat)(G(x,y,0,0)*ixx + 2*G(x,y,0,1)*ixy + G(x,y,0,2)*iyy);
25937 if (veloc>veloc_max) veloc_max = veloc;
else if (-veloc>veloc_max) veloc_max = -veloc;
25940 if (veloc_max>0) *
this+=(velocity*=dl/veloc_max);
25943 const unsigned long whd = (
unsigned long)_width*_height*_depth;
25944 const float sqrt2amplitude = (float)std::sqrt(2*amplitude);
25946 CImg<Tfloat> res(_width,_height,_depth,_spectrum,0), W(_width,_height,_depth,is_3d?4:3), val(_spectrum,1,1,1,0);
25949 for (
float phi = (180%(
int)da)/2.0f; phi<=180; phi+=da) {
25950 const float phir = (float)(phi*
cimg::PI/180), datmp = (float)(da/std::cos(phir)),
25951 da2 = datmp<1?360.0f:datmp;
25952 for (
float theta = 0; theta<360; (theta+=da2),++N) {
25954 thetar = (float)(theta*
cimg::PI/180),
25955 vx = (float)(std::cos(thetar)*std::cos(phir)),
25956 vy = (
float)(std::sin(thetar)*std::cos(phir)),
25957 vz = (
float)std::sin(phir);
25959 *pa = G.data(0,0,0,0), *pb = G.data(0,0,0,1), *pc = G.data(0,0,0,2),
25960 *pd = G.data(0,0,0,3), *pe = G.data(0,0,0,4), *pf = G.data(0,0,0,5);
25961 Tfloat *pd0 = W.data(0,0,0,0), *pd1 = W.data(0,0,0,1), *pd2 = W.data(0,0,0,2), *pd3 = W.data(0,0,0,3);
25962 cimg_forXYZ(G,xg,yg,zg) {
25963 const t a = *(pa++), b = *(pb++), c = *(pc++), d = *(pd++), e = *(pe++), f = *(pf++);
25965 u = (float)(a*vx + b*vy + c*vz),
25966 v = (float)(b*vx + d*vy + e*vz),
25967 w = (float)(c*vx + e*vy + f*vz),
25968 n = (float)std::sqrt(1e-5+u*u+v*v+w*w),
25970 *(pd0++) = (Tfloat)(u*dln);
25971 *(pd1++) = (Tfloat)(v*dln);
25972 *(pd2++) = (Tfloat)(w*dln);
25973 *(pd3++) = (Tfloat)n;
25976 #ifdef cimg_use_openmp
25977 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=2) firstprivate(val)
25979 cimg_forXYZ(*
this,x,y,z) {
25982 n = (float)W(x,y,z,3),
25983 fsigma = (float)(n*sqrt2amplitude),
25984 fsigma2 = 2*fsigma*fsigma,
25985 length = gauss_prec*fsigma;
25991 switch (interpolation_type) {
25993 for (
float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) {
25995 cx = (int)(X+0.5f),
25996 cy = (int)(Y+0.5f),
25997 cz = (int)(Z+0.5f);
25999 u = (float)W(cx,cy,cz,0),
26000 v = (float)W(cx,cy,cz,1),
26001 w = (float)W(cx,cy,cz,2);
26002 if (is_fast_approx) { cimg_forC(*
this,c) val[c]+=(Tfloat)(*
this)(cx,cy,cz,c); ++S; }
26004 const float coef = (float)std::exp(-l*l/fsigma2);
26005 cimg_forC(*
this,c) val[c]+=(Tfloat)(coef*(*
this)(cx,cy,cz,c));
26012 for (
float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) {
26014 u = (float)(W._linear_atXYZ(X,Y,Z,0)),
26015 v = (
float)(W._linear_atXYZ(X,Y,Z,1)),
26016 w = (
float)(W._linear_atXYZ(X,Y,Z,2));
26017 if (is_fast_approx) { cimg_forC(*
this,c) val[c]+=(Tfloat)_linear_atXYZ(X,Y,Z,c); ++S; }
26019 const float coef = (float)std::exp(-l*l/fsigma2);
26020 cimg_forC(*
this,c) val[c]+=(Tfloat)(coef*_linear_atXYZ(X,Y,Z,c));
26027 for (
float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) {
26029 u0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,0)),
26030 v0 = (
float)(0.5f*W._linear_atXYZ(X,Y,Z,1)),
26031 w0 = (
float)(0.5f*W._linear_atXYZ(X,Y,Z,2)),
26032 u = (
float)(W._linear_atXYZ(X+u0,Y+v0,Z+w0,0)),
26033 v = (
float)(W._linear_atXYZ(X+u0,Y+v0,Z+w0,1)),
26034 w = (
float)(W._linear_atXYZ(X+u0,Y+v0,Z+w0,2));
26035 if (is_fast_approx) { cimg_forC(*
this,c) val[c]+=(Tfloat)_linear_atXYZ(X,Y,Z,c); ++S; }
26037 const float coef = (float)std::exp(-l*l/fsigma2);
26038 cimg_forC(*
this,c) val[c]+=(Tfloat)(coef*_linear_atXYZ(X,Y,Z,c));
26045 Tfloat *ptrd = res.data(x,y,z);
26046 if (S>0) cimg_forC(res,c) { *ptrd+=val[c]/S; ptrd+=whd; }
26047 else cimg_forC(res,c) { *ptrd+=(Tfloat)((*
this)(x,y,z,c)); ptrd+=whd; }
26052 for (
float theta = (360%(
int)da)/2.0f; theta<360; (theta+=da),++N) {
26053 const float thetar = (float)(theta*
cimg::PI/180),
26054 vx = (float)(std::cos(thetar)), vy = (
float)(std::sin(thetar));
26055 const t *pa = G.data(0,0,0,0), *pb = G.data(0,0,0,1), *pc = G.data(0,0,0,2);
26056 Tfloat *pd0 = W.data(0,0,0,0), *pd1 = W.data(0,0,0,1), *pd2 = W.data(0,0,0,2);
26057 cimg_forXY(G,xg,yg) {
26058 const t a = *(pa++), b = *(pb++), c = *(pc++);
26060 u = (float)(a*vx + b*vy),
26061 v = (float)(b*vx + c*vy),
26062 n = (float)std::sqrt(1e-5+u*u+v*v),
26064 *(pd0++) = (Tfloat)(u*dln);
26065 *(pd1++) = (Tfloat)(v*dln);
26066 *(pd2++) = (Tfloat)n;
26069 #ifdef cimg_use_openmp
26070 #pragma omp parallel for if (_width>=256 && _height>=2) firstprivate(val)
26072 cimg_forXY(*
this,x,y) {
26075 n = (float)W(x,y,0,2),
26076 fsigma = (float)(n*sqrt2amplitude),
26077 fsigma2 = 2*fsigma*fsigma,
26078 length = gauss_prec*fsigma;
26083 switch (interpolation_type) {
26085 for (
float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) {
26087 cx = (int)(X+0.5f),
26088 cy = (int)(Y+0.5f);
26090 u = (float)W(cx,cy,0,0),
26091 v = (float)W(cx,cy,0,1);
26092 if (is_fast_approx) { cimg_forC(*
this,c) val[c]+=(Tfloat)(*
this)(cx,cy,0,c); ++S; }
26094 const float coef = (float)std::exp(-l*l/fsigma2);
26095 cimg_forC(*
this,c) val[c]+=(Tfloat)(coef*(*
this)(cx,cy,0,c));
26102 for (
float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) {
26104 u = (float)(W._linear_atXY(X,Y,0,0)),
26105 v = (
float)(W._linear_atXY(X,Y,0,1));
26106 if (is_fast_approx) { cimg_forC(*
this,c) val[c]+=(Tfloat)_linear_atXY(X,Y,0,c); ++S; }
26108 const float coef = (float)std::exp(-l*l/fsigma2);
26109 cimg_forC(*
this,c) val[c]+=(Tfloat)(coef*_linear_atXY(X,Y,0,c));
26116 for (
float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) {
26118 u0 = (float)(0.5f*W._linear_atXY(X,Y,0,0)),
26119 v0 = (
float)(0.5f*W._linear_atXY(X,Y,0,1)),
26120 u = (
float)(W._linear_atXY(X+u0,Y+v0,0,0)),
26121 v = (
float)(W._linear_atXY(X+u0,Y+v0,0,1));
26122 if (is_fast_approx) { cimg_forC(*
this,c) val[c]+=(Tfloat)_linear_atXY(X,Y,0,c); ++S; }
26124 const float coef = (float)std::exp(-l*l/fsigma2);
26125 cimg_forC(*
this,c) val[c]+=(Tfloat)(coef*_linear_atXY(X,Y,0,c));
26132 Tfloat *ptrd = res.data(x,y);
26133 if (S>0) cimg_forC(res,c) { *ptrd+=val[c]/S; ptrd+=whd; }
26134 else cimg_forC(res,c) { *ptrd+=(Tfloat)((*
this)(x,y,0,c)); ptrd+=whd; }
26138 const Tfloat *ptrs = res._data;
26139 cimg_for(*
this,ptrd,T) {
26140 const Tfloat val = *(ptrs++)/N;
26141 *ptrd = val<val_min?val_min:(val>val_max?val_max:(T)val);
26148 template<
typename t>
26150 const float amplitude=60,
const float dl=0.8f,
const float da=30,
26151 const float gauss_prec=2,
const unsigned int interpolation_type=0,
26152 const bool is_fast_approx=
true)
const {
26153 return (+*
this).
blur_anisotropic(G,amplitude,dl,da,gauss_prec,interpolation_type,is_fast_approx);
26171 const float alpha=0.6f,
const float sigma=1.1f,
const float dl=0.8f,
const float da=30,
26172 const float gauss_prec=2,
const unsigned int interpolation_type=0,
26173 const bool is_fast_approx=
true) {
26175 amplitude,dl,da,gauss_prec,interpolation_type,is_fast_approx);
26180 const float alpha=0.6f,
const float sigma=1.1f,
const float dl=0.8f,
26181 const float da=30,
const float gauss_prec=2,
const unsigned int interpolation_type=0,
26182 const bool is_fast_approx=
true)
const {
26183 return (+*
this).
blur_anisotropic(amplitude,sharpness,anisotropy,alpha,sigma,dl,da,gauss_prec,interpolation_type,
26202 template<
typename t>
26204 const float sigma_x,
const float sigma_y,
const float sigma_z,
const float sigma_r,
26205 const int bgrid_x,
const int bgrid_y,
const int bgrid_z,
const int bgrid_r,
26206 const bool interpolation_type=
true) {
26209 "blur_bilateral(): Invalid size for specified guide image (%u,%u,%u,%u,%p).",
26211 guide._width,guide._height,guide._depth,guide._spectrum,guide._data);
26213 T m, M = guide.max_min(m);
26214 if (m==M)
return *
this;
26215 const float range = (float)(M - m);
26217 bx0 = bgrid_x>=0?bgrid_x:_width*-bgrid_x/100,
26218 by0 = bgrid_y>=0?bgrid_y:_height*-bgrid_y/100,
26219 bz0 = bgrid_z>=0?bgrid_z:_depth*-bgrid_z/100,
26220 br0 = bgrid_r>=0?bgrid_r:(int)(-range*bgrid_r/100),
26226 _sigma_x = sigma_x>=0?sigma_x:-sigma_x*_width/100,
26227 _sigma_y = sigma_y>=0?sigma_y:-sigma_y*_height/100,
26228 _sigma_z = sigma_z>=0?sigma_z:-sigma_z*_depth/100,
26229 _sigma_r = sigma_r>=0?sigma_r:-sigma_r*range/100,
26230 nsigma_x = _sigma_x*bx/_width,
26231 nsigma_y = _sigma_y*by/_height,
26232 nsigma_z = _sigma_z*bz/_depth,
26233 nsigma_r = _sigma_r*br/range;
26234 if (nsigma_x>0 || nsigma_y>0 || nsigma_z>0 || nsigma_r>0) {
26235 const bool is_3d = (_depth>1);
26238 cimg_forC(*
this,c) {
26239 const CImg<t> _guide = guide.get_shared_channel(c%guide._spectrum);
26240 bgrid.fill(0); bgridw.
fill(0);
26241 cimg_forXYZ(*
this,x,y,z) {
26242 const T val = (*this)(x,y,z,c);
26243 const float gval = (float)_guide(x,y,z);
26244 const int X = x*bx/_width, Y = y*by/_height, Z = z*bz/_depth,
26245 R = (int)
cimg::min(br-1.0f,(gval-m)*br/range);
26246 bgrid(X,Y,Z,R) += (float)val;
26247 bgridw(X,Y,Z,R) += 1;
26249 bgrid.
blur(nsigma_x,nsigma_y,nsigma_z,
true).
deriche(nsigma_r,0,
'c',
false);
26250 bgridw.
blur(nsigma_x,nsigma_y,nsigma_z,
true).
deriche(nsigma_r,0,
'c',
false);
26251 if (interpolation_type) cimg_forXYZ(*
this,x,y,z) {
26252 const float gval = (float)_guide(x,y,z),
26253 X = (float)x*bx/_width, Y = (
float)y*by/_height, Z = (float)z*bz/_depth,
26254 R = (
float)
cimg::min(br-1.0f,(gval-m)*br/range),
26255 bval0 = bgrid._linear_atXYZC(X,Y,Z,R), bval1 = bgridw._linear_atXYZC(X,Y,Z,R);
26256 (*this)(x,y,z,c) = (T)(bval0/bval1);
26257 }
else cimg_forXYZ(*
this,x,y,z) {
26258 const float gval = (float)_guide(x,y,z);
26259 const int X = x*bx/_width, Y = y*by/_height, Z = z*bz/_depth,
26260 R = (int)
cimg::min(br-1.0f,(gval-m)*br/range);
26261 const float bval0 = bgrid(X,Y,Z,R), bval1 = bgridw(X,Y,Z,R);
26262 (*this)(x,y,z,c) = (T)(bval0/bval1);
26267 cimg_forC(*
this,c) {
26268 const CImg<t> _guide = guide.get_shared_channel(c%guide._spectrum);
26270 cimg_forXY(*
this,x,y) {
26271 const T val = (*this)(x,y,c);
26272 const float gval = (float)_guide(x,y);
26273 const int X = x*bx/_width, Y = y*by/_height, R = (int)
cimg::min(br-1.0f,(gval-m)*br/range);
26274 bgrid(X,Y,R,0) += (float)val;
26275 bgrid(X,Y,R,1) += 1;
26277 bgrid.
blur(nsigma_x,nsigma_y,0,
true).
blur(0,0,nsigma_r,
false);
26278 if (interpolation_type) cimg_forXY(*
this,x,y) {
26279 const float gval = (float)_guide(x,y),
26280 X = (float)x*bx/_width, Y = (
float)y*by/_height, R = (float)
cimg::min(br-1.0f,(gval-m)*br/range),
26281 bval0 = bgrid._linear_atXYZ(X,Y,R,0), bval1 = bgrid._linear_atXYZ(X,Y,R,1);
26282 (*this)(x,y,c) = (T)(bval0/bval1);
26283 }
else cimg_forXY(*
this,x,y) {
26284 const float gval = (float)_guide(x,y);
26285 const int X = x*bx/_width, Y = y*by/_height, R = (int)
cimg::min(br-1.0f,(gval-m)*br/range);
26286 const float bval0 = bgrid(X,Y,R,0), bval1 = bgrid(X,Y,R,1);
26287 (*this)(x,y,c) = (T)(bval0/bval1);
26296 template<
typename t>
26298 const float sigma_x,
const float sigma_y,
const float sigma_z,
const float sigma_r,
26299 const int bgrid_x,
const int bgrid_y,
const int bgrid_z,
const int bgrid_r,
26300 const bool interpolation_type=
true)
const {
26301 return (+*
this).
blur_bilateral(guide,sigma_x,sigma_y,sigma_z,sigma_r,bgrid_x,bgrid_y,bgrid_z,bgrid_r,
26302 interpolation_type);
26314 template<
typename t>
26316 const float sigma_s,
const float sigma_r,
const int bgrid_s=-33,
const int bgrid_r=32,
26317 const bool interpolation_type=
true) {
26318 const float nsigma_s = sigma_s>=0?sigma_s:-sigma_s*
cimg::max(_width,_height,_depth)/100;
26319 return blur_bilateral(guide,nsigma_s,nsigma_s,nsigma_s,sigma_r,bgrid_s,bgrid_s,bgrid_s,bgrid_r,
26320 interpolation_type);
26324 template<
typename t>
26326 const float sigma_s,
const float sigma_r,
const int bgrid_s=-33,
const int bgrid_r=32,
26327 const bool interpolation_type=
true)
const {
26328 return (+*
this).
blur_bilateral(guide,sigma_s,sigma_s,sigma_s,sigma_r,bgrid_s,bgrid_s,bgrid_s,bgrid_r,
26329 interpolation_type);
26342 const unsigned int lookup_size=4,
const float smoothness=0,
const bool is_fast_approx=
true) {
26343 if (
is_empty() || !patch_size || !lookup_size)
return *
this;
26344 return get_blur_patch(sigma_s,sigma_p,patch_size,lookup_size,smoothness,is_fast_approx).move_to(*
this);
26349 const unsigned int lookup_size=4,
const float smoothness=0,
26350 const bool is_fast_approx=
true)
const {
26352 #define _cimg_blur_patch3d_fast(N) \
26353 cimg_for##N##XYZ(res,x,y,z) { \
26354 T *pP = P._data; cimg_forC(res,c) { cimg_get##N##x##N##x##N(img,x,y,z,c,pP,T); pP+=N3; } \
26355 const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, \
26356 x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; \
26357 float sum_weights = 0; \
26358 cimg_for_in##N##XYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) if (cimg::abs(img(x,y,z,0) - img(p,q,r,0))<sigma_p3) { \
26359 T *pQ = Q._data; cimg_forC(res,c) { cimg_get##N##x##N##x##N(img,p,q,r,c,pQ,T); pQ+=N3; } \
26360 float distance2 = 0; \
26361 pQ = Q._data; cimg_for(P,pP,T) { const float dI = (float)*pP - (float)*(pQ++); distance2+=dI*dI; } \
26362 distance2/=Pnorm; \
26363 const float dx = (float)p - x, dy = (float)q - y, dz = (float)r - z, \
26364 alldist = distance2 + (dx*dx + dy*dy + dz*dz)/sigma_s2, weight = alldist>3?0.0f:1.0f; \
26365 sum_weights+=weight; \
26366 cimg_forC(res,c) res(x,y,z,c)+=weight*(*this)(p,q,r,c); \
26368 if (sum_weights>0) cimg_forC(res,c) res(x,y,z,c)/=sum_weights; \
26369 else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); \
26372 #define _cimg_blur_patch3d(N) \
26373 cimg_for##N##XYZ(res,x,y,z) { \
26374 T *pP = P._data; cimg_forC(res,c) { cimg_get##N##x##N##x##N(img,x,y,z,c,pP,T); pP+=N3; } \
26375 const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, \
26376 x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; \
26377 float sum_weights = 0, weight_max = 0; \
26378 cimg_for_in##N##XYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) if (p!=x || q!=y || r!=z) { \
26379 T *pQ = Q._data; cimg_forC(res,c) { cimg_get##N##x##N##x##N(img,p,q,r,c,pQ,T); pQ+=N3; } \
26380 float distance2 = 0; \
26381 pQ = Q._data; cimg_for(P,pP,T) { const float dI = (float)*pP - (float)*(pQ++); distance2+=dI*dI; } \
26382 distance2/=Pnorm; \
26383 const float dx = (float)p - x, dy = (float)q - y, dz = (float)r - z, \
26384 alldist = distance2 + (dx*dx + dy*dy + dz*dz)/sigma_s2, weight = (float)std::exp(-alldist); \
26385 if (weight>weight_max) weight_max = weight; \
26386 sum_weights+=weight; \
26387 cimg_forC(res,c) res(x,y,z,c)+=weight*(*this)(p,q,r,c); \
26389 sum_weights+=weight_max; cimg_forC(res,c) res(x,y,z,c)+=weight_max*(*this)(x,y,z,c); \
26390 if (sum_weights>0) cimg_forC(res,c) res(x,y,z,c)/=sum_weights; \
26391 else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); \
26394 #define _cimg_blur_patch2d_fast(N) \
26395 cimg_for##N##XY(res,x,y) { \
26396 T *pP = P._data; cimg_forC(res,c) { cimg_get##N##x##N(img,x,y,0,c,pP,T); pP+=N2; } \
26397 const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; \
26398 float sum_weights = 0; \
26399 cimg_for_in##N##XY(res,x0,y0,x1,y1,p,q) if (cimg::abs(img(x,y,0,0) - img(p,q,0,0))<sigma_p3) { \
26400 T *pQ = Q._data; cimg_forC(res,c) { cimg_get##N##x##N(img,p,q,0,c,pQ,T); pQ+=N2; } \
26401 float distance2 = 0; \
26402 pQ = Q._data; cimg_for(P,pP,T) { const float dI = (float)*pP - (float)*(pQ++); distance2+=dI*dI; } \
26403 distance2/=Pnorm; \
26404 const float dx = (float)p - x, dy = (float)q - y, \
26405 alldist = distance2 + (dx*dx+dy*dy)/sigma_s2, weight = alldist>3?0.0f:1.0f; \
26406 sum_weights+=weight; \
26407 cimg_forC(res,c) res(x,y,c)+=weight*(*this)(p,q,c); \
26409 if (sum_weights>0) cimg_forC(res,c) res(x,y,c)/=sum_weights; \
26410 else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); \
26413 #define _cimg_blur_patch2d(N) \
26414 cimg_for##N##XY(res,x,y) { \
26415 T *pP = P._data; cimg_forC(res,c) { cimg_get##N##x##N(img,x,y,0,c,pP,T); pP+=N2; } \
26416 const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; \
26417 float sum_weights = 0, weight_max = 0; \
26418 cimg_for_in##N##XY(res,x0,y0,x1,y1,p,q) if (p!=x || q!=y) { \
26419 T *pQ = Q._data; cimg_forC(res,c) { cimg_get##N##x##N(img,p,q,0,c,pQ,T); pQ+=N2; } \
26420 float distance2 = 0; \
26421 pQ = Q._data; cimg_for(P,pP,T) { const float dI = (float)*pP - (float)*(pQ++); distance2+=dI*dI; } \
26422 distance2/=Pnorm; \
26423 const float dx = (float)p - x, dy = (float)q - y, \
26424 alldist = distance2 + (dx*dx+dy*dy)/sigma_s2, weight = (float)std::exp(-alldist); \
26425 if (weight>weight_max) weight_max = weight; \
26426 sum_weights+=weight; \
26427 cimg_forC(res,c) res(x,y,c)+=weight*(*this)(p,q,c); \
26429 sum_weights+=weight_max; cimg_forC(res,c) res(x,y,c)+=weight_max*(*this)(x,y,c); \
26430 if (sum_weights>0) cimg_forC(res,c) res(x,y,c)/=sum_weights; \
26431 else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); \
26434 if (
is_empty() || !patch_size || !lookup_size)
return +*
this;
26437 CImg<T> P(patch_size*patch_size*_spectrum), Q(P);
26439 nsigma_s = sigma_s>=0?sigma_s:-sigma_s*
cimg::max(_width,_height,_depth)/100,
26440 sigma_s2 = nsigma_s*nsigma_s, sigma_p2 = sigma_p*sigma_p, sigma_p3 = 3*sigma_p,
26441 Pnorm = P.size()*sigma_p2;
26442 const int rsize2 = (int)lookup_size/2, rsize1 = (
int)lookup_size - rsize2 - 1;
26443 const unsigned int N2 = patch_size*patch_size, N3 = N2*patch_size;
26445 if (_depth>1)
switch (patch_size) {
26446 case 2 :
if (is_fast_approx) _cimg_blur_patch3d_fast(2)
else _cimg_blur_patch3d(2)
break;
26447 case 3 :
if (is_fast_approx) _cimg_blur_patch3d_fast(3)
else _cimg_blur_patch3d(3)
break;
26449 const int psize2 = (int)patch_size/2, psize1 = (
int)patch_size - psize2 - 1;
26450 if (is_fast_approx)
26451 #ifdef cimg_use_openmp
26452 #pragma omp parallel for collapse(2) if (res._width>=32 && res._height*res._depth>=4) private(P,Q)
26454 cimg_forXYZ(res,x,y,z) {
26455 P = img.get_crop(x - psize1,y - psize1,z - psize1,x + psize2,y + psize2,z + psize2,
true);
26456 const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1,
26457 x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2;
26458 float sum_weights = 0;
26459 cimg_for_inXYZ(res,x0,y0,z0,x1,y1,z1,p,q,r)
if (
cimg::abs(img(x,y,z,0)-img(p,q,r,0))<sigma_p3) {
26460 (Q = img.get_crop(p - psize1,q - psize1,r - psize1,p + psize2,q + psize2,r + psize2,
true))-=P;
26462 dx = (float)x - p, dy = (
float)y - q, dz = (float)z - r,
26463 distance2 = (
float)(Q.pow(2).sum()/Pnorm + (dx*dx + dy*dy + dz*dz)/sigma_s2),
26464 weight = distance2>3?0.0f:1.0f;
26465 sum_weights+=weight;
26466 cimg_forC(res,c) res(x,y,z,c)+=weight*(*this)(p,q,r,c);
26468 if (sum_weights>0) cimg_forC(res,c) res(x,y,z,c)/=sum_weights;
26469 else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*
this)(x,y,z,c));
26471 #ifdef cimg_use_openmp
26472 #pragma omp parallel for collapse(2) if (res._width>=32 && res._height*res._depth>=4) firstprivate(P,Q)
26474 cimg_forXYZ(res,x,y,z) {
26475 P = img.get_crop(x - psize1,y - psize1,z - psize1,x + psize2,y + psize2,z + psize2,
true);
26476 const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1,
26477 x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2;
26478 float sum_weights = 0, weight_max = 0;
26479 cimg_for_inXYZ(res,x0,y0,z0,x1,y1,z1,p,q,r)
if (p!=x || q!=y || r!=z) {
26480 (Q = img.get_crop(p - psize1,q - psize1,r - psize1,p + psize2,q + psize2,r + psize2,
true))-=P;
26482 dx = (float)x - p, dy = (
float)y - q, dz = (float)z - r,
26483 distance2 = (
float)(Q.pow(2).sum()/Pnorm + (dx*dx + dy*dy + dz*dz)/sigma_s2),
26484 weight = (float)std::exp(-distance2);
26485 if (weight>weight_max) weight_max = weight;
26486 sum_weights+=weight;
26487 cimg_forC(res,c) res(x,y,z,c)+=weight*(*this)(p,q,r,c);
26489 sum_weights+=weight_max; cimg_forC(res,c) res(x,y,z,c)+=weight_max*(*this)(x,y,z,c);
26490 if (sum_weights>0) cimg_forC(res,c) res(x,y,z,c)/=sum_weights;
26491 else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*
this)(x,y,z,c));
26494 }
else switch (patch_size) {
26495 case 2 :
if (is_fast_approx) _cimg_blur_patch2d_fast(2)
else _cimg_blur_patch2d(2)
break;
26496 case 3 :
if (is_fast_approx) _cimg_blur_patch2d_fast(3)
else _cimg_blur_patch2d(3)
break;
26497 case 4 :
if (is_fast_approx) _cimg_blur_patch2d_fast(4)
else _cimg_blur_patch2d(4)
break;
26498 case 5 :
if (is_fast_approx) _cimg_blur_patch2d_fast(5)
else _cimg_blur_patch2d(5)
break;
26499 case 6 :
if (is_fast_approx) _cimg_blur_patch2d_fast(6)
else _cimg_blur_patch2d(6)
break;
26500 case 7 :
if (is_fast_approx) _cimg_blur_patch2d_fast(7)
else _cimg_blur_patch2d(7)
break;
26501 case 8 :
if (is_fast_approx) _cimg_blur_patch2d_fast(8)
else _cimg_blur_patch2d(8)
break;
26502 case 9 :
if (is_fast_approx) _cimg_blur_patch2d_fast(9)
else _cimg_blur_patch2d(9)
break;
26504 const int psize2 = (int)patch_size/2, psize1 = (
int)patch_size - psize2 - 1;
26505 if (is_fast_approx)
26506 #ifdef cimg_use_openmp
26507 #pragma omp parallel for if (res._width>=32 && res._height>=4) firstprivate(P,Q)
26509 cimg_forXY(res,x,y) {
26510 P = img.get_crop(x - psize1,y - psize1,x + psize2,y + psize2,
true);
26511 const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2;
26512 float sum_weights = 0;
26513 cimg_for_inXY(res,x0,y0,x1,y1,p,q)
if (
cimg::abs(img(x,y,0)-img(p,q,0))<sigma_p3) {
26514 (Q = img.get_crop(p - psize1,q - psize1,p + psize2,q + psize2,
true))-=P;
26516 dx = (float)x - p, dy = (
float)y - q,
26517 distance2 = (float)(Q.pow(2).sum()/Pnorm + (dx*dx + dy*dy)/sigma_s2),
26518 weight = distance2>3?0.0f:1.0f;
26519 sum_weights+=weight;
26520 cimg_forC(res,c) res(x,y,c)+=weight*(*this)(p,q,c);
26522 if (sum_weights>0) cimg_forC(res,c) res(x,y,c)/=sum_weights;
26523 else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*
this)(x,y,c));
26525 #ifdef cimg_use_openmp
26526 #pragma omp parallel for if (res._width>=32 && res._height>=4) firstprivate(P,Q)
26528 cimg_forXY(res,x,y) {
26529 P = img.get_crop(x - psize1,y - psize1,x + psize2,y + psize2,
true);
26530 const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2;
26531 float sum_weights = 0, weight_max = 0;
26532 cimg_for_inXY(res,x0,y0,x1,y1,p,q)
if (p!=x || q!=y) {
26533 (Q = img.get_crop(p - psize1,q - psize1,p + psize2,q + psize2,
true))-=P;
26535 dx = (float)x - p, dy = (
float)y - q,
26536 distance2 = (float)(Q.pow(2).sum()/Pnorm + (dx*dx + dy*dy)/sigma_s2),
26537 weight = (float)std::exp(-distance2);
26538 if (weight>weight_max) weight_max = weight;
26539 sum_weights+=weight;
26540 cimg_forC(res,c) res(x,y,c)+=weight*(*this)(p,q,c);
26542 sum_weights+=weight_max; cimg_forC(res,c) res(x,y,c)+=weight_max*(*this)(x,y,c);
26543 if (sum_weights>0) cimg_forC(res,c) res(x,y,c)/=sum_weights;
26544 else cimg_forC(res,c) res(x,y,0,c) = (Tfloat)((*
this)(x,y,c));
26557 if (!n)
return *
this;
26563 if (
is_empty() || n<=1)
return +*
this;
26564 CImg<T> res(_width,_height,_depth,_spectrum);
26565 T *ptrd = res._data;
26567 const int hl = n/2, hr = hl - 1 + n%2;
26568 if (res._depth!=1) {
26570 #if cimg_use_openmp
26571 #pragma omp parallel for collapse(3) if (_width>=16 && _height*_depth*_spectrum>=4)
26573 cimg_forXYZC(*
this,x,y,z,c) {
26575 x0 = x - hl, y0 = y - hl, z0 = z-hl, x1 = x + hr, y1 = y + hr, z1 = z+hr,
26576 nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, nz0 = z0<0?0:z0,
26578 const float val0 = (float)(*
this)(x,y,z,c);
26580 unsigned int nb_values = 0;
26581 T *ptrd = values.data();
26582 cimg_for_inXYZ(*
this,nx0,ny0,nz0,nx1,ny1,nz1,p,q,r)
26583 if (
cimg::abs((
float)(*
this)(p,q,r,c)-val0)<=
threshold) { *(ptrd++) = (*
this)(p,q,r,c); ++nb_values; }
26584 res(x,y,z,c) = values.get_shared_points(0,nb_values-1).median();
26587 #if cimg_use_openmp
26588 #pragma omp parallel for collapse(3) if (_width>=16 && _height*_depth*_spectrum>=4)
26590 cimg_forXYZC(*
this,x,y,z,c) {
26592 x0 = x - hl, y0 = y - hl, z0 = z-hl, x1 = x + hr, y1 = y + hr, z1 = z+hr,
26593 nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, nz0 = z0<0?0:z0,
26595 res(x,y,z,c) =
get_crop(nx0,ny0,nz0,c,nx1,ny1,nz1,c).median();
26598 #define _cimg_median_sort(a,b) if ((a)>(b)) cimg::swap(a,b)
26599 if (res._height!=1) {
26601 #ifdef cimg_use_openmp
26602 #pragma omp parallel for collapse(2) if (_width>=16 && _height*_spectrum>=4)
26604 cimg_forXYC(*
this,x,y,c) {
26606 x0 = x - hl, y0 = y - hl, x1 = x + hr, y1 = y + hr,
26607 nx0 = x0<0?0:x0, ny0 = y0<0?0:y0,
26609 const float val0 = (float)(*
this)(x,y,c);
26611 unsigned int nb_values = 0;
26612 T *ptrd = values.data();
26613 cimg_for_inXY(*
this,nx0,ny0,nx1,ny1,p,q)
26614 if (
cimg::abs((
float)(*
this)(p,q,c)-val0)<=
threshold) { *(ptrd++) = (*
this)(p,q,c); ++nb_values; }
26615 res(x,y,c) = values.get_shared_points(0,nb_values-1).median();
26619 #if cimg_use_openmp
26620 #pragma omp parallel for if (_spectrum>=2)
26622 cimg_forC(*
this,c) {
26625 cimg_for3x3(*
this,x,y,0,c,I,T) {
26626 std::memcpy(J,I,9*
sizeof(T));
26627 _cimg_median_sort(Jcp, Jnp); _cimg_median_sort(Jcc, Jnc); _cimg_median_sort(Jcn, Jnn);
26628 _cimg_median_sort(Jpp, Jcp); _cimg_median_sort(Jpc, Jcc); _cimg_median_sort(Jpn, Jcn);
26629 _cimg_median_sort(Jcp, Jnp); _cimg_median_sort(Jcc, Jnc); _cimg_median_sort(Jcn, Jnn);
26630 _cimg_median_sort(Jpp, Jpc); _cimg_median_sort(Jnc, Jnn); _cimg_median_sort(Jcc, Jcn);
26631 _cimg_median_sort(Jpc, Jpn); _cimg_median_sort(Jcp, Jcc); _cimg_median_sort(Jnp, Jnc);
26632 _cimg_median_sort(Jcc, Jcn); _cimg_median_sort(Jcc, Jnp); _cimg_median_sort(Jpn, Jcc);
26633 _cimg_median_sort(Jcc, Jnp);
26639 #if cimg_use_openmp
26640 #pragma omp parallel for if (_spectrum>=2)
26642 cimg_forC(*
this,c) {
26645 cimg_for5x5(*
this,x,y,0,c,I,T) {
26646 std::memcpy(J,I,25*
sizeof(T));
26647 _cimg_median_sort(Jbb,Jpb); _cimg_median_sort(Jnb,Jab); _cimg_median_sort(Jcb,Jab);
26648 _cimg_median_sort(Jcb,Jnb); _cimg_median_sort(Jpp,Jcp); _cimg_median_sort(Jbp,Jcp);
26649 _cimg_median_sort(Jbp,Jpp); _cimg_median_sort(Jap,Jbc); _cimg_median_sort(Jnp,Jbc);
26650 _cimg_median_sort(Jnp,Jap); _cimg_median_sort(Jcc,Jnc); _cimg_median_sort(Jpc,Jnc);
26651 _cimg_median_sort(Jpc,Jcc); _cimg_median_sort(Jbn,Jpn); _cimg_median_sort(Jac,Jpn);
26652 _cimg_median_sort(Jac,Jbn); _cimg_median_sort(Jnn,Jan); _cimg_median_sort(Jcn,Jan);
26653 _cimg_median_sort(Jcn,Jnn); _cimg_median_sort(Jpa,Jca); _cimg_median_sort(Jba,Jca);
26654 _cimg_median_sort(Jba,Jpa); _cimg_median_sort(Jna,Jaa); _cimg_median_sort(Jcb,Jbp);
26655 _cimg_median_sort(Jnb,Jpp); _cimg_median_sort(Jbb,Jpp); _cimg_median_sort(Jbb,Jnb);
26656 _cimg_median_sort(Jab,Jcp); _cimg_median_sort(Jpb,Jcp); _cimg_median_sort(Jpb,Jab);
26657 _cimg_median_sort(Jpc,Jac); _cimg_median_sort(Jnp,Jac); _cimg_median_sort(Jnp,Jpc);
26658 _cimg_median_sort(Jcc,Jbn); _cimg_median_sort(Jap,Jbn); _cimg_median_sort(Jap,Jcc);
26659 _cimg_median_sort(Jnc,Jpn); _cimg_median_sort(Jbc,Jpn); _cimg_median_sort(Jbc,Jnc);
26660 _cimg_median_sort(Jba,Jna); _cimg_median_sort(Jcn,Jna); _cimg_median_sort(Jcn,Jba);
26661 _cimg_median_sort(Jpa,Jaa); _cimg_median_sort(Jnn,Jaa); _cimg_median_sort(Jnn,Jpa);
26662 _cimg_median_sort(Jan,Jca); _cimg_median_sort(Jnp,Jcn); _cimg_median_sort(Jap,Jnn);
26663 _cimg_median_sort(Jbb,Jnn); _cimg_median_sort(Jbb,Jap); _cimg_median_sort(Jbc,Jan);
26664 _cimg_median_sort(Jpb,Jan); _cimg_median_sort(Jpb,Jbc); _cimg_median_sort(Jpc,Jba);
26665 _cimg_median_sort(Jcb,Jba); _cimg_median_sort(Jcb,Jpc); _cimg_median_sort(Jcc,Jpa);
26666 _cimg_median_sort(Jnb,Jpa); _cimg_median_sort(Jnb,Jcc); _cimg_median_sort(Jnc,Jca);
26667 _cimg_median_sort(Jab,Jca); _cimg_median_sort(Jab,Jnc); _cimg_median_sort(Jac,Jna);
26668 _cimg_median_sort(Jbp,Jna); _cimg_median_sort(Jbp,Jac); _cimg_median_sort(Jbn,Jaa);
26669 _cimg_median_sort(Jpp,Jaa); _cimg_median_sort(Jpp,Jbn); _cimg_median_sort(Jcp,Jpn);
26670 _cimg_median_sort(Jcp,Jan); _cimg_median_sort(Jnc,Jpa); _cimg_median_sort(Jbn,Jna);
26671 _cimg_median_sort(Jcp,Jnc); _cimg_median_sort(Jcp,Jbn); _cimg_median_sort(Jpb,Jap);
26672 _cimg_median_sort(Jnb,Jpc); _cimg_median_sort(Jbp,Jcn); _cimg_median_sort(Jpc,Jcn);
26673 _cimg_median_sort(Jap,Jcn); _cimg_median_sort(Jab,Jbc); _cimg_median_sort(Jpp,Jcc);
26674 _cimg_median_sort(Jcp,Jac); _cimg_median_sort(Jab,Jpp); _cimg_median_sort(Jab,Jcp);
26675 _cimg_median_sort(Jcc,Jac); _cimg_median_sort(Jbc,Jac); _cimg_median_sort(Jpp,Jcp);
26676 _cimg_median_sort(Jbc,Jcc); _cimg_median_sort(Jpp,Jbc); _cimg_median_sort(Jpp,Jcn);
26677 _cimg_median_sort(Jcc,Jcn); _cimg_median_sort(Jcp,Jcn); _cimg_median_sort(Jcp,Jbc);
26678 _cimg_median_sort(Jcc,Jnn); _cimg_median_sort(Jcp,Jcc); _cimg_median_sort(Jbc,Jnn);
26679 _cimg_median_sort(Jcc,Jba); _cimg_median_sort(Jbc,Jba); _cimg_median_sort(Jbc,Jcc);
26685 #ifdef cimg_use_openmp
26686 #pragma omp parallel for collapse(2) if (_width>=16 && _height*_spectrum>=4)
26688 cimg_forXYC(*
this,x,y,c) {
26690 x0 = x - hl, y0 = y - hl, x1 = x + hr, y1 = y + hr,
26691 nx0 = x0<0?0:x0, ny0 = y0<0?0:y0,
26693 res(x,y,c) =
get_crop(nx0,ny0,0,c,nx1,ny1,0,c).median();
26700 #ifdef cimg_use_openmp
26701 #pragma omp parallel for if (_width>=16 && _spectrum>=2)
26703 cimg_forXC(*
this,x,c) {
26705 x0 = x - hl, x1 = x + hr,
26706 nx0 = x0<0?0:x0, nx1 = x1>=
width()?
width()-1:x1;
26707 const float val0 = (float)(*
this)(x,c);
26709 unsigned int nb_values = 0;
26710 T *ptrd = values.data();
26711 cimg_for_inX(*
this,nx0,nx1,p)
26712 if (
cimg::abs((
float)(*
this)(p,c)-val0)<=
threshold) { *(ptrd++) = (*
this)(p,c); ++nb_values; }
26713 res(x,c) = values.get_shared_points(0,nb_values-1).median();
26717 #ifdef cimg_use_openmp
26718 #pragma omp parallel for if (_spectrum>=2)
26720 cimg_forC(*
this,c) {
26722 cimg_for2x2(*
this,x,y,0,c,I,T) res(x,c) = (T)(0.5f*(I[0]+I[1]));
26726 #ifdef cimg_use_openmp
26727 #pragma omp parallel for if (_spectrum>=2)
26729 cimg_forC(*
this,c) {
26731 cimg_for3x3(*
this,x,y,0,c,I,T)
26732 res(x,c) = I[3]<I[4]?(I[4]<I[5]?I[4]:(I[3]<I[5]?I[5]:I[3])):(I[3]<I[5]?I[3]:(I[4]<I[5]?I[5]:I[4]));
26736 #ifdef cimg_use_openmp
26737 #pragma omp parallel for if (_width>=16 && _spectrum>=2)
26739 cimg_forXC(*
this,x,c) {
26741 x0 = x - hl, x1 = x + hr,
26742 nx0 = x0<0?0:x0, nx1 = x1>=
width()?
width()-1:x1;
26743 res(x,c) =
get_crop(nx0,0,0,c,nx1,0,0,c).median();
26760 CImg<T>&
sharpen(
const float amplitude,
const bool sharpen_type=
false,
const float edge=1,
26761 const float alpha=0,
const float sigma=0) {
26763 T val_min, val_max =
max_min(val_min);
26764 const float nedge = edge/2;
26765 CImg<Tfloat> velocity(_width,_height,_depth,_spectrum), _veloc_max(_spectrum);
26768 if (sharpen_type) {
26770 if (sigma>0) G.blur(sigma);
26771 #ifdef cimg_use_openmp
26772 #pragma omp parallel for collapse(2) if (_width>=32 && _height*_depth>=16)
26774 cimg_forYZ(G,y,z) {
26775 Tfloat *ptrG0 = G.data(0,y,z,0), *ptrG1 = G.data(0,y,z,1),
26776 *ptrG2 = G.data(0,y,z,2), *ptrG3 = G.data(0,y,z,3);
26779 G.get_tensor_at(x,y,z).symmetric_eigen(val,vec);
26780 if (val[0]<0) val[0] = 0;
26781 if (val[1]<0) val[1] = 0;
26782 if (val[2]<0) val[2] = 0;
26783 *(ptrG0++) = vec(0,0);
26784 *(ptrG1++) = vec(0,1);
26785 *(ptrG2++) = vec(0,2);
26786 *(ptrG3++) = 1 - (Tfloat)std::pow(1+val[0]+val[1]+val[2],-(Tfloat)nedge);
26789 #ifdef cimg_use_openmp
26790 #pragma omp parallel for if (_width*_height*_depth>=512 && _spectrum>=2)
26792 cimg_forC(*
this,c) {
26793 Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0;
26794 CImg_3x3x3(I,Tfloat);
26795 cimg_for3x3x3(*
this,x,y,z,c,I,Tfloat) {
26801 ixx = Incc + Ipcc - 2*Iccc,
26802 ixy = (Innc + Ippc - Inpc - Ipnc)/4,
26803 ixz = (Incn + Ipcp - Incp - Ipcn)/4,
26804 iyy = Icnc + Icpc - 2*Iccc,
26805 iyz = (Icnn + Icpp - Icnp - Icpn)/4,
26806 izz = Iccn + Iccp - 2*Iccc,
26813 itt = u*u*ixx + v*v*iyy + w*w*izz + 2*u*v*ixy + 2*u*w*ixz + 2*v*w*iyz,
26817 if (veloc>veloc_max) veloc_max = veloc;
else if (-veloc>veloc_max) veloc_max = -veloc;
26819 _veloc_max[c] = veloc_max;
26822 cimg_forC(*
this,c) {
26823 Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0;
26824 CImg_3x3x3(I,Tfloat);
26825 cimg_for3x3x3(*
this,x,y,z,c,I,Tfloat) {
26826 const Tfloat veloc = -Ipcc - Incc - Icpc - Icnc - Iccp - Iccn + 6*Iccc;
26828 if (veloc>veloc_max) veloc_max = veloc;
else if (-veloc>veloc_max) veloc_max = -veloc;
26830 _veloc_max[c] = veloc_max;
26833 if (sharpen_type) {
26835 if (sigma>0) G.blur(sigma);
26836 #ifdef cimg_use_openmp
26837 #pragma omp parallel for if (_width>=32 && _height>=16)
26841 Tfloat *ptrG0 = G.data(0,y,0,0), *ptrG1 = G.data(0,y,0,1), *ptrG2 = G.data(0,y,0,2);
26843 G.get_tensor_at(x,y).symmetric_eigen(val,vec);
26844 if (val[0]<0) val[0] = 0;
26845 if (val[1]<0) val[1] = 0;
26846 *(ptrG0++) = vec(0,0);
26847 *(ptrG1++) = vec(0,1);
26848 *(ptrG2++) = 1 - (Tfloat)std::pow(1 + val[0] + val[1],-(Tfloat)nedge);
26851 #ifdef cimg_use_openmp
26852 #pragma omp parallel for if (_width*_height>=512 && _spectrum>=2)
26854 cimg_forC(*
this,c) {
26855 Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0;
26856 CImg_3x3(I,Tfloat);
26857 cimg_for3x3(*
this,x,y,0,c,I,Tfloat) {
26862 ixx = Inc + Ipc - 2*Icc,
26863 ixy = (Inn + Ipp - Inp - Ipn)/4,
26864 iyy = Icn + Icp - 2*Icc,
26869 itt = u*u*ixx + v*v*iyy + 2*u*v*ixy,
26873 if (veloc>veloc_max) veloc_max = veloc;
else if (-veloc>veloc_max) veloc_max = -veloc;
26875 _veloc_max[c] = veloc_max;
26878 cimg_forC(*
this,c) {
26879 Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0;
26880 CImg_3x3(I,Tfloat);
26881 cimg_for3x3(*
this,x,y,0,c,I,Tfloat) {
26882 const Tfloat veloc = -Ipc - Inc - Icp - Icn + 4*Icc;
26884 if (veloc>veloc_max) veloc_max = veloc;
else if (-veloc>veloc_max) veloc_max = -veloc;
26886 _veloc_max[c] = veloc_max;
26889 const Tfloat veloc_max = _veloc_max.max();
26890 if (veloc_max<=0)
return *
this;
26891 return ((velocity*=amplitude/veloc_max)+=*
this).cut(val_min,val_max).move_to(*
this);
26896 const float alpha=0,
const float sigma=0)
const {
26897 return (+*
this).
sharpen(amplitude,sharpen_type,edge,alpha,sigma);
26914 bool is_3d =
false;
26916 for (
unsigned int a = 0; axes[a]; ++a) {
26919 case 'x' :
case 'y' :
break;
26920 case 'z' : is_3d =
true;
break;
26923 "get_gradient(): Invalid specified axis '%c'.",
26928 }
else is_3d = (_depth>1);
26933 #ifdef cimg_use_openmp
26934 #pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
26936 cimg_forC(*
this,c) {
26937 const unsigned long off = c*_width*_height*_depth;
26938 Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off, *ptrd2 = grad[2]._data + off;
26939 CImg_3x3x3(I,Tfloat);
26940 cimg_for3x3x3(*
this,x,y,z,c,I,Tfloat) {
26941 *(ptrd0++) = Iccc - Ipcc;
26942 *(ptrd1++) = Iccc - Icpc;
26943 *(ptrd2++) = Iccc - Iccp;
26948 #ifdef cimg_use_openmp
26949 #pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
26951 cimg_forC(*
this,c) {
26952 const unsigned long off = c*_width*_height*_depth;
26953 Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off, *ptrd2 = grad[2]._data + off;
26954 CImg_2x2x2(I,Tfloat);
26955 cimg_for2x2x2(*
this,x,y,z,c,I,Tfloat) {
26956 *(ptrd0++) = Incc - Iccc;
26957 *(ptrd1++) = Icnc - Iccc;
26958 *(ptrd2++) = Iccn - Iccc;
26973 #ifdef cimg_use_openmp
26974 #pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
26976 cimg_forC(*
this,c) {
26977 const unsigned long off = c*_width*_height*_depth;
26978 Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off, *ptrd2 = grad[2]._data + off;
26979 CImg_3x3x3(I,Tfloat);
26980 cimg_for3x3x3(*
this,x,y,z,c,I,Tfloat) {
26981 *(ptrd0++) = (Incc - Ipcc)/2;
26982 *(ptrd1++) = (Icnc - Icpc)/2;
26983 *(ptrd2++) = (Iccn - Iccp)/2;
26988 }
else switch (scheme) {
26990 #ifdef cimg_use_openmp
26991 #pragma omp parallel for collapse(2) if (_width*_height>=1048576 && _depth*_spectrum>=2)
26993 cimg_forZC(*
this,z,c) {
26994 const unsigned long off = c*_width*_height*_depth + z*_width*_height;
26995 Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off;
26996 CImg_3x3(I,Tfloat);
26997 cimg_for3x3(*
this,x,y,z,c,I,Tfloat) {
26998 *(ptrd0++) = Icc - Ipc;
26999 *(ptrd1++) = Icc - Icp;
27004 #ifdef cimg_use_openmp
27005 #pragma omp parallel for collapse(2) if (_width*_height>=1048576 && _depth*_spectrum>=2)
27007 cimg_forZC(*
this,z,c) {
27008 const unsigned long off = c*_width*_height*_depth + z*_width*_height;
27009 Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off;
27010 CImg_2x2(I,Tfloat);
27011 cimg_for2x2(*
this,x,y,z,c,I,Tfloat) {
27012 *(ptrd0++) = Inc - Icc;
27013 *(ptrd1++) = Icn - Icc;
27018 #ifdef cimg_use_openmp
27019 #pragma omp parallel for collapse(2) if (_width*_height>=1048576 && _depth*_spectrum>=2)
27021 cimg_forZC(*
this,z,c) {
27022 const unsigned long off = c*_width*_height*_depth + z*_width*_height;
27023 Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off;
27024 CImg_3x3(I,Tfloat);
27025 cimg_for3x3(*
this,x,y,z,c,I,Tfloat) {
27026 *(ptrd0++) = -Ipp - 2*Ipc - Ipn + Inp + 2*Inc + Inn;
27027 *(ptrd1++) = -Ipp - 2*Icp - Inp + Ipn + 2*Icn + Inn;
27032 #ifdef cimg_use_openmp
27033 #pragma omp parallel for collapse(2) if (_width*_height>=1048576 && _depth*_spectrum>=2)
27035 cimg_forZC(*
this,z,c) {
27036 const unsigned long off = c*_width*_height*_depth + z*_width*_height;
27037 Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off;
27038 CImg_3x3(I,Tfloat);
27039 const Tfloat a = (Tfloat)(0.25f*(2-std::sqrt(2.0f))), b = (Tfloat)(0.5f*(std::sqrt(2.0f)-1));
27040 cimg_for3x3(*
this,x,y,z,c,I,Tfloat) {
27041 *(ptrd0++) = -a*Ipp - b*Ipc - a*Ipn + a*Inp + b*Inc + a*Inn;
27042 *(ptrd1++) = -a*Ipp - b*Icp - a*Inp + a*Ipn + b*Icn + a*Inn;
27055 #ifdef cimg_use_openmp
27056 #pragma omp parallel for collapse(2) if (_width*_height>=1048576 && _depth*_spectrum>=2)
27058 cimg_forZC(*
this,z,c) {
27059 const unsigned long off = c*_width*_height*_depth + z*_width*_height;
27060 Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off;
27061 CImg_3x3(I,Tfloat);
27062 cimg_for3x3(*
this,x,y,z,c,I,Tfloat) {
27063 *(ptrd0++) = (Inc - Ipc)/2;
27064 *(ptrd1++) = (Icn - Icp)/2;
27069 if (!axes)
return grad;
27071 for (
unsigned int l = 0; axes[l]; ++l) {
27074 case 'x' : res.
insert(grad[0]);
break;
27075 case 'y' : res.
insert(grad[1]);
break;
27076 case 'z' : res.
insert(grad[2]);
break;
27089 const char *naxes = axes, *
const def_axes2d =
"xxxyyy", *
const def_axes3d =
"xxxyxzyyyzzz";
27090 if (!axes) naxes = _depth>1?def_axes3d:def_axes2d;
27091 const unsigned int lmax = std::strlen(naxes);
27094 "get_hessian(): Invalid specified axes '%s'.",
27098 res.
assign(lmax/2,_width,_height,_depth,_spectrum);
27101 #ifdef cimg_use_openmp
27102 #pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
27104 cimg_forC(*
this,c) {
27105 const unsigned long off = c*_width*_height*_depth;
27107 *ptrd0 = res[0]._data + off, *ptrd1 = res[1]._data + off, *ptrd2 = res[2]._data + off,
27108 *ptrd3 = res[3]._data + off, *ptrd4 = res[4]._data + off, *ptrd5 = res[5]._data + off;
27109 CImg_3x3x3(I,Tfloat);
27110 cimg_for3x3x3(*
this,x,y,z,c,I,Tfloat) {
27111 *(ptrd0++) = Ipcc + Incc - 2*Iccc;
27112 *(ptrd1++) = (Ippc + Innc - Ipnc - Inpc)/4;
27113 *(ptrd2++) = (Ipcp + Incn - Ipcn - Incp)/4;
27114 *(ptrd3++) = Icpc + Icnc - 2*Iccc;
27115 *(ptrd4++) = (Icpp + Icnn - Icpn - Icnp)/4;
27116 *(ptrd5++) = Iccn + Iccp - 2*Iccc;
27120 #ifdef cimg_use_openmp
27121 #pragma omp parallel for collapse(2) if (_width*_height>=1048576 && _depth*_spectrum>=2)
27123 cimg_forZC(*
this,z,c) {
27124 const unsigned long off = c*_width*_height*_depth + z*_width*_height;
27125 Tfloat *ptrd0 = res[0]._data + off, *ptrd1 = res[1]._data + off, *ptrd2 = res[2]._data + off;
27126 CImg_3x3(I,Tfloat);
27127 cimg_for3x3(*
this,x,y,z,c,I,Tfloat) {
27128 *(ptrd0++) = Ipc + Inc - 2*Icc;
27129 *(ptrd1++) = (Ipp + Inn - Ipn - Inp)/4;
27130 *(ptrd2++) = Icp + Icn - 2*Icc;
27133 }
else for (
unsigned int l = 0; l<lmax; ) {
27134 const unsigned int l2 = l/2;
27135 char axis1 = naxes[l++], axis2 = naxes[l++];
27137 bool valid_axis =
false;
27138 if (axis1==
'x' && axis2==
'x') {
27140 #ifdef cimg_use_openmp
27141 #pragma omp parallel for collapse(2) if (_width*_height>=1048576 && _depth*_spectrum>=2)
27143 cimg_forZC(*
this,z,c) {
27144 Tfloat *ptrd = res[l2].
data(0,0,z,c);
27145 CImg_3x3(I,Tfloat);
27146 cimg_for3x3(*
this,x,y,z,c,I,Tfloat) *(ptrd++) = Ipc + Inc - 2*Icc;
27149 else if (axis1==
'x' && axis2==
'y') {
27151 #ifdef cimg_use_openmp
27152 #pragma omp parallel for collapse(2) if (_width*_height>=1048576 && _depth*_spectrum>=2)
27154 cimg_forZC(*
this,z,c) {
27155 Tfloat *ptrd = res[l2].
data(0,0,z,c);
27156 CImg_3x3(I,Tfloat);
27157 cimg_for3x3(*
this,x,y,z,c,I,Tfloat) *(ptrd++) = (Ipp + Inn - Ipn - Inp)/4;
27160 else if (axis1==
'x' && axis2==
'z') {
27162 #ifdef cimg_use_openmp
27163 #pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
27165 cimg_forC(*
this,c) {
27166 Tfloat *ptrd = res[l2].
data(0,0,0,c);
27167 CImg_3x3x3(I,Tfloat);
27168 cimg_for3x3x3(*
this,x,y,z,c,I,Tfloat) *(ptrd++) = (Ipcp + Incn - Ipcn - Incp)/4;
27171 else if (axis1==
'y' && axis2==
'y') {
27173 #ifdef cimg_use_openmp
27174 #pragma omp parallel for collapse(2) if (_width*_height>=1048576 && _depth*_spectrum>=2)
27176 cimg_forZC(*
this,z,c) {
27177 Tfloat *ptrd = res[l2].
data(0,0,z,c);
27178 CImg_3x3(I,Tfloat);
27179 cimg_for3x3(*
this,x,y,z,c,I,Tfloat) *(ptrd++) = Icp + Icn - 2*Icc;
27182 else if (axis1==
'y' && axis2==
'z') {
27184 #ifdef cimg_use_openmp
27185 #pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
27187 cimg_forC(*
this,c) {
27188 Tfloat *ptrd = res[l2].
data(0,0,0,c);
27189 CImg_3x3x3(I,Tfloat);
27190 cimg_forC(*
this,c) cimg_for3x3x3(*
this,x,y,z,c,I,Tfloat) *(ptrd++) = (Icpp + Icnn - Icpn - Icnp)/4;
27193 else if (axis1==
'z' && axis2==
'z') {
27195 #ifdef cimg_use_openmp
27196 #pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
27198 cimg_forC(*
this,c) {
27199 Tfloat *ptrd = res[l2].
data(0,0,0,c);
27200 CImg_3x3x3(I,Tfloat);
27201 cimg_for3x3x3(*
this,x,y,z,c,I,Tfloat) *(ptrd++) = Iccn + Iccp - 2*Iccc;
27204 else if (!valid_axis)
27206 "get_hessian(): Invalid specified axes '%s'.",
27223 #ifdef cimg_use_openmp
27224 #pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
27226 cimg_forC(*
this,c) {
27227 Tfloat *ptrd = res.data(0,0,0,c);
27228 CImg_3x3x3(I,Tfloat);
27229 cimg_for3x3x3(*
this,x,y,z,c,I,Tfloat) *(ptrd++) = Incc + Ipcc + Icnc + Icpc + Iccn + Iccp - 6*Iccc;
27231 }
else if (_height>1) {
27232 #ifdef cimg_use_openmp
27233 #pragma omp parallel for if (_width*_height>=1048576 && _depth*_spectrum>=2)
27235 cimg_forC(*
this,c) {
27236 Tfloat *ptrd = res.data(0,0,0,c);
27237 CImg_3x3(I,Tfloat);
27238 cimg_for3x3(*
this,x,y,0,c,I,Tfloat) *(ptrd++) = Inc + Ipc + Icn + Icp - 4*Icc;
27241 #ifdef cimg_use_openmp
27242 #pragma omp parallel for if (_width>=1048576 && _height*_depth*_spectrum>=2)
27244 cimg_forC(*
this,c) {
27245 Tfloat *ptrd = res.data(0,0,0,c);
27246 CImg_3x3(I,Tfloat);
27247 cimg_for3x3(*
this,x,y,0,c,I,Tfloat) *(ptrd++) = Inc + Ipc - 2*Icc;
27266 res.assign(_width,_height,_depth,6,0);
27269 #ifdef cimg_use_openmp
27270 #pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
27272 cimg_forC(*
this,c) {
27274 *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2),
27275 *ptrd3 = res.data(0,0,0,3), *ptrd4 = res.data(0,0,0,4), *ptrd5 = res.data(0,0,0,5);
27276 CImg_3x3x3(I,Tfloat);
27277 cimg_for3x3x3(*
this,x,y,z,c,I,Tfloat) {
27279 ix = (Incc - Ipcc)/2,
27280 iy = (Icnc - Icpc)/2,
27281 iz = (Iccn - Iccp)/2;
27292 #ifdef cimg_use_openmp
27293 #pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
27295 cimg_forC(*
this,c) {
27297 *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2),
27298 *ptrd3 = res.data(0,0,0,3), *ptrd4 = res.data(0,0,0,4), *ptrd5 = res.data(0,0,0,5);
27299 CImg_3x3x3(I,Tfloat);
27300 cimg_for3x3x3(*
this,x,y,z,c,I,Tfloat) {
27302 ixf = Incc - Iccc, ixb = Iccc - Ipcc,
27303 iyf = Icnc - Iccc, iyb = Iccc - Icpc,
27304 izf = Iccn - Iccc, izb = Iccc - Iccp;
27305 *(ptrd0++)+=(ixf*ixf + 2*ixf*ixb + ixb*ixb)/4;
27306 *(ptrd1++)+=(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb)/4;
27307 *(ptrd2++)+=(ixf*izf + ixf*izb + ixb*izf + ixb*izb)/4;
27308 *(ptrd3++)+=(iyf*iyf + 2*iyf*iyb + iyb*iyb)/4;
27309 *(ptrd4++)+=(iyf*izf + iyf*izb + iyb*izf + iyb*izb)/4;
27310 *(ptrd5++)+=(izf*izf + 2*izf*izb + izb*izb)/4;
27315 #ifdef cimg_use_openmp
27316 #pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
27318 cimg_forC(*
this,c) {
27320 *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2),
27321 *ptrd3 = res.data(0,0,0,3), *ptrd4 = res.data(0,0,0,4), *ptrd5 = res.data(0,0,0,5);
27322 CImg_3x3x3(I,Tfloat);
27323 cimg_for3x3x3(*
this,x,y,z,c,I,Tfloat) {
27325 ixf = Incc - Iccc, ixb = Iccc - Ipcc,
27326 iyf = Icnc - Iccc, iyb = Iccc - Icpc,
27327 izf = Iccn - Iccc, izb = Iccc - Iccp;
27328 *(ptrd0++)+=(ixf*ixf + ixb*ixb)/2;
27329 *(ptrd1++)+=(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb)/4;
27330 *(ptrd2++)+=(ixf*izf + ixf*izb + ixb*izf + ixb*izb)/4;
27331 *(ptrd3++)+=(iyf*iyf + iyb*iyb)/2;
27332 *(ptrd4++)+=(iyf*izf + iyf*izb + iyb*izf + iyb*izb)/4;
27333 *(ptrd5++)+=(izf*izf + izb*izb)/2;
27339 res.assign(_width,_height,_depth,3,0);
27342 #ifdef cimg_use_openmp
27343 #pragma omp parallel for if (_width*_height>=1048576 && _depth*_spectrum>=2)
27345 cimg_forC(*
this,c) {
27346 Tfloat *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2);
27347 CImg_3x3(I,Tfloat);
27348 cimg_for3x3(*
this,x,y,0,c,I,Tfloat) {
27350 ix = (Inc - Ipc)/2,
27351 iy = (Icn - Icp)/2;
27359 #ifdef cimg_use_openmp
27360 #pragma omp parallel for if (_width*_height>=1048576 && _depth*_spectrum>=2)
27362 cimg_forC(*
this,c) {
27363 Tfloat *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2);
27364 CImg_3x3(I,Tfloat);
27365 cimg_for3x3(*
this,x,y,0,c,I,Tfloat) {
27367 ixf = Inc - Icc, ixb = Icc - Ipc,
27368 iyf = Icn - Icc, iyb = Icc - Icp;
27369 *(ptrd0++)+=(ixf*ixf + 2*ixf*ixb + ixb*ixb)/4;
27370 *(ptrd1++)+=(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb)/4;
27371 *(ptrd2++)+=(iyf*iyf + 2*iyf*iyb + iyb*iyb)/4;
27376 #ifdef cimg_use_openmp
27377 #pragma omp parallel for if (_width*_height>=1048576 && _depth*_spectrum>=2)
27379 cimg_forC(*
this,c) {
27380 Tfloat *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2);
27381 CImg_3x3(I,Tfloat);
27382 cimg_for3x3(*
this,x,y,0,c,I,Tfloat) {
27384 ixf = Inc - Icc, ixb = Icc - Ipc,
27385 iyf = Icn - Icc, iyb = Icc - Icp;
27386 *(ptrd0++)+=(ixf*ixf + ixb*ixb)/2;
27387 *(ptrd1++)+=(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb)/4;
27388 *(ptrd2++)+=(iyf*iyf + iyb*iyb)/2;
27406 const float alpha=0.6f,
const float sigma=1.1f,
const bool is_sqrt=
false) {
27409 nsharpness =
cimg::max(sharpness,1e-5f),
27410 power1 = (is_sqrt?0.5f:1)*nsharpness,
27411 power2 = power1/(1e-7f+1-anisotropy);
27412 blur(alpha).normalize(0,(T)255);
27416 #ifdef cimg_use_openmp
27417 #pragma omp parallel for collapse(2) if(_width>=256 && _height*_depth>=256)
27419 cimg_forYZ(*
this,y,z) {
27421 *ptrd0 = res.data(0,y,z,0), *ptrd1 = res.data(0,y,z,1), *ptrd2 = res.data(0,y,z,2),
27422 *ptrd3 = res.data(0,y,z,3), *ptrd4 = res.data(0,y,z,4), *ptrd5 = res.data(0,y,z,5);
27424 cimg_forX(*
this,x) {
27425 res.get_tensor_at(x,y,z).symmetric_eigen(val,vec);
27427 _l1 = val[2], _l2 = val[1], _l3 = val[0],
27428 l1 = _l1>0?_l1:0, l2 = _l2>0?_l2:0, l3 = _l3>0?_l3:0,
27429 ux = vec(0,0), uy = vec(0,1), uz = vec(0,2),
27430 vx = vec(1,0), vy = vec(1,1), vz = vec(1,2),
27431 wx = vec(2,0), wy = vec(2,1), wz = vec(2,2),
27432 n1 = (float)std::pow(1+l1+l2+l3,-power1),
27433 n2 = (float)std::pow(1+l1+l2+l3,-power2);
27434 *(ptrd0++) = n1*(ux*ux + vx*vx) + n2*wx*wx;
27435 *(ptrd1++) = n1*(ux*uy + vx*vy) + n2*wx*wy;
27436 *(ptrd2++) = n1*(ux*uz + vx*vz) + n2*wx*wz;
27437 *(ptrd3++) = n1*(uy*uy + vy*vy) + n2*wy*wy;
27438 *(ptrd4++) = n1*(uy*uz + vy*vz) + n2*wy*wz;
27439 *(ptrd5++) = n1*(uz*uz + vz*vz) + n2*wz*wz;
27444 #ifdef cimg_use_openmp
27445 #pragma omp parallel for if(_width>=256 && _height>=256)
27447 cimg_forY(*
this,y) {
27448 Tfloat *ptrd0 = res.data(0,y,0,0), *ptrd1 = res.data(0,y,0,1), *ptrd2 = res.data(0,y,0,2);
27450 cimg_forX(*
this,x) {
27451 res.get_tensor_at(x,y).symmetric_eigen(val,vec);
27453 _l1 = val[1], _l2 = val[0],
27454 l1 = _l1>0?_l1:0, l2 = _l2>0?_l2:0,
27455 ux = vec(1,0), uy = vec(1,1),
27456 vx = vec(0,0), vy = vec(0,1),
27457 n1 = (float)std::pow(1+l1+l2,-power1),
27458 n2 = (float)std::pow(1+l1+l2,-power2);
27459 *(ptrd0++) = n1*ux*ux + n2*vx*vx;
27460 *(ptrd1++) = n1*ux*uy + n2*vx*vy;
27461 *(ptrd2++) = n1*uy*uy + n2*vy*vy;
27465 return res.move_to(*
this);
27470 const float alpha=0.6f,
const float sigma=1.1f,
const bool is_sqrt=
false)
const {
27484 const unsigned int nb_scales=0,
const unsigned int iteration_max=10000,
27485 const bool is_backward=
false) {
27486 return get_displacement(source,smoothness,precision,nb_scales,iteration_max,is_backward).move_to(*
this);
27491 const float smoothness=0.1f,
const float precision=5.0f,
27492 const unsigned int nb_scales=0,
const unsigned int iteration_max=10000,
27493 const bool is_backward=
false)
const {
27494 if (
is_empty() || !source)
return +*
this;
27497 "displacement(): Instance and source image (%u,%u,%u,%u,%p) have "
27498 "different dimensions.",
27500 source._width,source._height,source._depth,source._spectrum,source._data);
27503 "displacement(): Invalid specified precision %g "
27507 const unsigned int _nb_scales = nb_scales>0?nb_scales:
27508 (
unsigned int)(2*std::log((
double)(
cimg::max(_width,_height))));
27509 const float _precision = (float)std::pow(10.0,-(
double)precision);
27510 float sm, sM = source.max_min(sm), tm, tM =
max_min(tm);
27511 const float sdelta = sm==sM?1:(sM - sm), tdelta = tm==tM?1:(tM - tm);
27512 const bool is_3d = source._depth>1;
27515 for (
int scale = _nb_scales-1; scale>=0; --scale) {
27516 const float factor = (float)std::pow(1.5,(
double)scale);
27518 _sw = (
unsigned int)(_width/factor), sw = _sw?_sw:1,
27519 _sh = (
unsigned int)(_height/factor), sh = _sh?_sh:1,
27520 _sd = (
unsigned int)(_depth/factor), sd = _sd?_sd:1;
27521 if (sw<5 && sh<5 && (!is_3d || sd<5))
continue;
27523 I1 = (source.get_resize(sw,sh,sd,-100,2)-=sm)/=sdelta,
27525 if (U) (U*=1.5f).
resize(I2._width,I2._height,I2._depth,-100,3);
27526 else U.
assign(I2._width,I2._height,I2._depth,is_3d?3:2,0);
27528 const CImgList<Tfloat> dI = is_backward?I1.get_gradient():I2.get_gradient();
27530 for (
unsigned int iteration = 0; iteration<iteration_max; ++iteration) {
27533 if (smoothness>=0) cimg_for3XYZ(U,x,y,z) {
27535 X = is_backward?x - U(x,y,z,0):x + U(x,y,z,0),
27536 Y = is_backward?y - U(x,y,z,1):y + U(x,y,z,1),
27537 Z = is_backward?z - U(x,y,z,2):z + U(x,y,z,2);
27538 float delta_I = 0, _energy_regul = 0;
27539 if (is_backward) cimg_forC(I2,c) delta_I+=(float)(I1.linear_atXYZ(X,Y,Z,c) - I2(x,y,z,c));
27540 else cimg_forC(I2,c) delta_I+=(float)(I1(x,y,z,c) - I2.linear_atXYZ(X,Y,Z,c));
27543 Ux = 0.5f*(U(_n1x,y,z,c) - U(_p1x,y,z,c)),
27544 Uy = 0.5f*(U(x,_n1y,z,c) - U(x,_p1y,z,c)),
27545 Uz = 0.5f*(U(x,y,_n1z,c) - U(x,y,_p1z,c)),
27546 Uxx = U(_n1x,y,z,c) + U(_p1x,y,z,c),
27547 Uyy = U(x,_n1y,z,c) + U(x,_p1y,z,c),
27548 Uzz = U(x,y,_n1z,c) + U(x,y,_p1z,c);
27549 U(x,y,z,c) = (float)(U(x,y,z,c) + dt*(delta_I*dI[c].linear_atXYZ(X,Y,Z) +
27550 smoothness* ( Uxx + Uyy + Uzz)))/(1+6*smoothness*dt);
27551 _energy_regul+=Ux*Ux + Uy*Uy + Uz*Uz;
27553 _energy+=delta_I*delta_I + smoothness*_energy_regul;
27555 const float nsmoothness = -smoothness;
27556 cimg_for3XYZ(U,x,y,z) {
27558 X = is_backward?x - U(x,y,z,0):x + U(x,y,z,0),
27559 Y = is_backward?y - U(x,y,z,1):y + U(x,y,z,1),
27560 Z = is_backward?z - U(x,y,z,2):z + U(x,y,z,2);
27561 float delta_I = 0, _energy_regul = 0;
27562 if (is_backward) cimg_forC(I2,c) delta_I+=(float)(I1.linear_atXYZ(X,Y,Z,c) - I2(x,y,z,c));
27563 else cimg_forC(I2,c) delta_I+=(float)(I1(x,y,z,c) - I2.linear_atXYZ(X,Y,Z,c));
27566 Ux = 0.5f*(U(_n1x,y,z,c) - U(_p1x,y,z,c)),
27567 Uy = 0.5f*(U(x,_n1y,z,c) - U(x,_p1y,z,c)),
27568 Uz = 0.5f*(U(x,y,_n1z,c) - U(x,y,_p1z,c)),
27569 N2 = Ux*Ux + Uy*Uy + Uz*Uz,
27572 coef_a = (1 - Ux*Ux/N2)/N,
27573 coef_b = -2*Ux*Uy/N3,
27574 coef_c = -2*Ux*Uz/N3,
27575 coef_d = (1 - Uy*Uy/N2)/N,
27576 coef_e = -2*Uy*Uz/N3,
27577 coef_f = (1 - Uz*Uz/N2)/N,
27578 Uxx = U(_n1x,y,z,c) + U(_p1x,y,z,c),
27579 Uyy = U(x,_n1y,z,c) + U(x,_p1y,z,c),
27580 Uzz = U(x,y,_n1z,c) + U(x,y,_p1z,c),
27581 Uxy = 0.25f*(U(_n1x,_n1y,z,c) + U(_p1x,_p1y,z,c) - U(_n1x,_p1y,z,c) - U(_n1x,_p1y,z,c)),
27582 Uxz = 0.25f*(U(_n1x,y,_n1z,c) + U(_p1x,y,_p1z,c) - U(_n1x,y,_p1z,c) - U(_n1x,y,_p1z,c)),
27583 Uyz = 0.25f*(U(x,_n1y,_n1z,c) + U(x,_p1y,_p1z,c) - U(x,_n1y,_p1z,c) - U(x,_n1y,_p1z,c));
27584 U(x,y,z,c) = (float)(U(x,y,z,c) + dt*(delta_I*dI[c].linear_atXYZ(X,Y,Z) +
27585 nsmoothness* ( coef_a*Uxx + coef_b*Uxy +
27586 coef_c*Uxz + coef_d*Uyy +
27587 coef_e*Uyz + coef_f*Uzz ))
27588 )/(1+2*(coef_a+coef_d+coef_f)*nsmoothness*dt);
27591 _energy+=delta_I*delta_I + nsmoothness*_energy_regul;
27595 if (smoothness>=0) cimg_for3XY(U,x,y) {
27597 X = is_backward?x - U(x,y,0):x + U(x,y,0),
27598 Y = is_backward?y - U(x,y,1):y + U(x,y,1);
27599 float delta_I = 0, _energy_regul = 0;
27600 if (is_backward) cimg_forC(I2,c) delta_I+=(float)(I1.linear_atXY(X,Y,c) - I2(x,y,c));
27601 else cimg_forC(I2,c) delta_I+=(float)(I1(x,y,c) - I2.linear_atXY(X,Y,c));
27604 Ux = 0.5f*(U(_n1x,y,c) - U(_p1x,y,c)),
27605 Uy = 0.5f*(U(x,_n1y,c) - U(x,_p1y,c)),
27606 Uxx = U(_n1x,y,c) + U(_p1x,y,c),
27607 Uyy = U(x,_n1y,c) + U(x,_p1y,c);
27608 U(x,y,c) = (float)(U(x,y,c) + dt*(delta_I*dI[c].linear_atXY(X,Y) +
27609 smoothness*( Uxx + Uyy )))/(1+4*smoothness*dt);
27610 _energy_regul+=Ux*Ux + Uy*Uy;
27612 _energy+=delta_I*delta_I + smoothness*_energy_regul;
27614 const float nsmoothness = -smoothness;
27615 cimg_for3XY(U,x,y) {
27617 X = is_backward?x - U(x,y,0):x + U(x,y,0),
27618 Y = is_backward?y - U(x,y,1):y + U(x,y,1);
27619 float delta_I = 0, _energy_regul = 0;
27620 if (is_backward) cimg_forC(I2,c) delta_I+=(float)(I1.linear_atXY(X,Y,c) - I2(x,y,c));
27621 else cimg_forC(I2,c) delta_I+=(float)(I1(x,y,c) - I2.linear_atXY(X,Y,c));
27624 Ux = 0.5f*(U(_n1x,y,c) - U(_p1x,y,c)),
27625 Uy = 0.5f*(U(x,_n1y,c) - U(x,_p1y,c)),
27626 N2 = Ux*Ux + Uy*Uy,
27630 coef_b = -2*Ux*Uy/N3,
27632 Uxx = U(_n1x,y,c) + U(_p1x,y,c),
27633 Uyy = U(x,_n1y,c) + U(x,_p1y,c),
27634 Uxy = 0.25f*(U(_n1x,_n1y,c) + U(_p1x,_p1y,c) - U(_n1x,_p1y,c) - U(_n1x,_p1y,c));
27635 U(x,y,c) = (float)(U(x,y,c) + dt*(delta_I*dI[c].linear_atXY(X,Y) +
27636 nsmoothness*( coef_a*Uxx + coef_b*Uxy + coef_c*Uyy )))/
27637 (1+2*(coef_a+coef_c)*nsmoothness*dt);
27640 _energy+=delta_I*delta_I + nsmoothness*_energy_regul;
27644 const float d_energy = (_energy - energy)/(sw*sh*sd);
27645 if (d_energy<=0 && -d_energy<_precision)
break;
27646 if (d_energy>0) dt*=0.5f;
27667 bool is_value =
false;
27668 cimg_for(*
this,ptr,T) *ptr = *ptr==value?is_value=
true,0:(T)999999999;
27671 case 0 :
return _distance_core(_distance_sep_cdt,_distance_dist_cdt);
27672 case 1 :
return _distance_core(_distance_sep_mdt,_distance_dist_mdt);
27673 case 3 :
return _distance_core(_distance_sep_edt,_distance_dist_edt);
27674 default :
return _distance_core(_distance_sep_edt,_distance_dist_edt).sqrt();
27684 static long _distance_sep_edt(
const long i,
const long u,
const long *
const g) {
27685 return (u*u-i*i+g[u]-g[i])/(2*(u-i));
27688 static long _distance_dist_edt(
const long x,
const long i,
const long *
const g) {
27689 return (x-i)*(x-i) + g[i];
27692 static long _distance_sep_mdt(
const long i,
const long u,
const long *
const g) {
27693 return (u-i<=g[u]-g[i]?999999999:(g[u]-g[i]+u+i)/2);
27696 static long _distance_dist_mdt(
const long x,
const long i,
const long *
const g) {
27697 return (x<i?i-x:x-i) + g[i];
27700 static long _distance_sep_cdt(
const long i,
const long u,
const long *
const g) {
27701 const long h = (i+u)/2;
27702 if (g[i]<=g[u]) {
return h<i+g[u]?i+g[u]:h; }
27703 return h<u-g[i]?h:u-g[i];
27706 static long _distance_dist_cdt(
const long x,
const long i,
const long *
const g) {
27707 const long d = x<i?i-x:x-i;
27708 return d<g[i]?g[i]:d;
27711 static void _distance_scan(
const unsigned int len,
27712 const long *
const g,
27713 long (*
const sep)(
const long,
const long,
const long *
const),
27714 long (*
const f)(
const long,
const long,
const long *
const),
27718 long q = s[0] = t[0] = 0;
27719 for (
int u = 1; u<(int)len; ++u) {
27720 while ((q>=0) && f(t[q],s[q],g)>f(t[q],u,g)) { --q; }
27721 if (q<0) { q = 0; s[0] = u; }
27722 else {
const long w = 1 + sep(s[q], u, g);
if (w<(
long)len) { ++q; s[q] = u; t[q] = w; }}
27724 for (
int u = (
int)len-1; u>=0; --u) { dt[u] = f(u,s[q],g);
if (u==t[q]) --q; }
27727 CImg<T>& _distance_core(
long (*
const sep)(
const long,
const long,
const long *
const),
27728 long (*
const f)(
const long,
const long,
const long *
const)) {
27729 const unsigned long wh = (
unsigned long)_width*_height;
27730 #ifdef cimg_use_openmp
27731 #pragma omp parallel for if (_spectrum>=2)
27733 cimg_forC(*
this,c) {
27734 CImg<longT> g(_width), dt(_width), s(_width), t(_width);
27736 #ifdef cimg_use_openmp
27737 #pragma omp parallel for collapse(2) if (_width>=512 && _height*_depth>=16) firstprivate(g,dt,s,t)
27739 cimg_forYZ(*
this,y,z) {
27740 cimg_forX(*
this,x) g[x] = (
long)img(x,y,z,0,wh);
27741 _distance_scan(_width,g,sep,f,s,t,dt);
27742 cimg_forX(*this,x) img(x,y,z,0,wh) = (T)dt[x];
27745 g.assign(_height); dt.assign(_height); s.assign(_height); t.assign(_height);
27746 #ifdef cimg_use_openmp
27747 #pragma omp parallel for collapse(2) if (_height>=512 && _width*_depth>=16) firstprivate(g,dt,s,t)
27749 cimg_forXZ(*
this,x,z) {
27750 cimg_forY(*
this,y) g[y] = (
long)img(x,y,z,0,wh);
27751 _distance_scan(_height,g,sep,f,s,t,dt);
27752 cimg_forY(*this,y) img(x,y,z,0,wh) = (T)dt[y];
27756 g.assign(_depth); dt.assign(_depth); s.assign(_depth); t.assign(_depth);
27757 #ifdef cimg_use_openmp
27758 #pragma omp parallel for collapse(2) if (_depth>=512 && _width*_height>=16) firstprivate(g,dt,s,t)
27760 cimg_forXY(*
this,x,y) {
27761 cimg_forZ(*
this,z) g[z] = (
long)img(x,y,z,0,wh);
27762 _distance_scan(_depth,g,sep,f,s,t,dt);
27763 cimg_forZ(*this,z) img(x,y,z,0,wh) = (T)dt[z];
27776 template<typename t>
27779 bool is_value =
false;
27780 cimg_for(*
this,ptr,T) *ptr = *ptr==value?is_value=
true,0:(T)999999999;
27782 const unsigned long wh = (
unsigned long)_width*_height;
27783 #ifdef cimg_use_openmp
27784 #pragma omp parallel for if (_spectrum>=2)
27786 cimg_forC(*
this,c) {
27788 #ifdef cimg_use_openmp
27789 #pragma omp parallel for collapse(3) if (_width*_height*_depth>=1024)
27791 cimg_forXYZ(metric_mask,dx,dy,dz) {
27792 const t weight = metric_mask(dx,dy,dz);
27794 for (
int z = dz, nz = 0; z<
depth(); ++z,++nz) {
27795 for (
int y = dy , ny = 0; y<
height(); ++y,++ny) {
27796 for (
int x = dx, nx = 0; x<
width(); ++x,++nx) {
27797 const T dd = img(nx,ny,nz,0,wh) + weight;
27798 if (dd<img(x,y,z,0,wh)) img(x,y,z,0,wh) = dd;
27802 for (
int z =
depth() - 1 - dz, nz =
depth() - 1; z>=0; --z,--nz) {
27803 for (
int y =
height() - 1 - dy, ny =
height() - 1; y>=0; --y,--ny) {
27804 for (
int x =
width() - 1 - dx, nx =
width() - 1; x>=0; --x,--nx) {
27805 const T dd = img(nx,ny,nz,0,wh) + weight;
27806 if (dd<img(x,y,z,0,wh)) img(x,y,z,0,wh) = dd;
27817 template<
typename t>
27828 template<
typename t,
typename to>
27835 template<
typename t,
typename to>
27839 if (
is_empty())
return return_path.assign();
27842 "distance_dijkstra(): image instance and metric map (%u,%u,%u,%u) "
27843 "have incompatible dimensions.",
27845 metric._width,metric._height,metric._depth,metric._spectrum);
27846 typedef typename cimg::superset<t,long>::type td;
27847 CImg<td> result(_width,_height,_depth,_spectrum), Q;
27849 if (return_path) return_path.assign(_width,_height,_depth,_spectrum);
27851 cimg_forC(*
this,c) {
27853 const CImg<t> met = metric.get_shared_channel(c%metric._spectrum);
27854 CImg<td> res = result.get_shared_channel(c);
27856 unsigned int sizeQ = 0;
27860 cimg_forXYZ(img,x,y,z)
if (img(x,y,z)==value) {
27861 Q._priority_queue_insert(is_queued,sizeQ,0,x,y,z);
27863 if (path) path(x,y,z) = (to)0;
27870 const int x = (int)Q(0,1), y = (int)Q(0,2), z = (int)Q(0,3);
27871 const td P = (td)-Q(0,0);
27872 Q._priority_queue_remove(sizeQ);
27876 if (x-1>=0 && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x-1,y,z)+P),x-1,y,z)) {
27877 res(x-1,y,z) = npot;
if (path) path(x-1,y,z) = (to)2;
27879 if (x+1<
width() && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x+1,y,z)+P),x+1,y,z)) {
27880 res(x+1,y,z) = npot;
if (path) path(x+1,y,z) = (to)1;
27882 if (y-1>=0 && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x,y-1,z)+P),x,y-1,z)) {
27883 res(x,y-1,z) = npot;
if (path) path(x,y-1,z) = (to)8;
27885 if (y+1<
height() && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x,y+1,z)+P),x,y+1,z)) {
27886 res(x,y+1,z) = npot;
if (path) path(x,y+1,z) = (to)4;
27888 if (z-1>=0 && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x,y,z-1)+P),x,y,z-1)) {
27889 res(x,y,z-1) = npot;
if (path) path(x,y,z-1) = (to)32;
27891 if (z+1<
depth() && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x,y,z+1)+P),x,y,z+1)) {
27892 res(x,y,z+1) = npot;
if (path) path(x,y,z+1) = (to)16;
27895 if (is_high_connectivity) {
27896 const float sqrt2 = std::sqrt(2.0f), sqrt3 = std::sqrt(3.0f);
27899 if (x-1>=0 && y-1>=0 &&
27900 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x-1,y-1,z)+P)),x-1,y-1,z)) {
27901 res(x-1,y-1,z) = npot;
if (path) path(x-1,y-1,z) = (to)10;
27903 if (x+1<
width() && y-1>=0 &&
27904 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x+1,y-1,z)+P)),x+1,y-1,z)) {
27905 res(x+1,y-1,z) = npot;
if (path) path(x+1,y-1,z) = (to)9;
27907 if (x-1>=0 && y+1<
height() &&
27908 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x-1,y+1,z)+P)),x-1,y+1,z)) {
27909 res(x-1,y+1,z) = npot;
if (path) path(x-1,y+1,z) = (to)6;
27912 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x+1,y+1,z)+P)),x+1,y+1,z)) {
27913 res(x+1,y+1,z) = npot;
if (path) path(x+1,y+1,z) = (to)5;
27918 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x-1,y,z-1)+P)),x-1,y,z-1)) {
27919 res(x-1,y,z-1) = npot;
if (path) path(x-1,y,z-1) = (to)34;
27922 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x+1,y,z-1)+P)),x+1,y,z-1)) {
27923 res(x+1,y,z-1) = npot;
if (path) path(x+1,y,z-1) = (to)33;
27926 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x,y-1,z-1)+P)),x,y-1,z-1)) {
27927 res(x,y-1,z-1) = npot;
if (path) path(x,y-1,z-1) = (to)40;
27930 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x,y+1,z-1)+P)),x,y+1,z-1)) {
27931 res(x,y+1,z-1) = npot;
if (path) path(x,y+1,z-1) = (to)36;
27933 if (x-1>=0 && y-1>=0 &&
27934 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x-1,y-1,z-1)+P)),x-1,y-1,z-1)) {
27935 res(x-1,y-1,z-1) = npot;
if (path) path(x-1,y-1,z-1) = (to)42;
27937 if (x+1<
width() && y-1>=0 &&
27938 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x+1,y-1,z-1)+P)),x+1,y-1,z-1)) {
27939 res(x+1,y-1,z-1) = npot;
if (path) path(x+1,y-1,z-1) = (to)41;
27941 if (x-1>=0 && y+1<
height() &&
27942 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x-1,y+1,z-1)+P)),x-1,y+1,z-1)) {
27943 res(x-1,y+1,z-1) = npot;
if (path) path(x-1,y+1,z-1) = (to)38;
27946 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x+1,y+1,z-1)+P)),x+1,y+1,z-1)) {
27947 res(x+1,y+1,z-1) = npot;
if (path) path(x+1,y+1,z-1) = (to)37;
27953 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x-1,y,z+1)+P)),x-1,y,z+1)) {
27954 res(x-1,y,z+1) = npot;
if (path) path(x-1,y,z+1) = (to)18;
27957 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x+1,y,z+1)+P)),x+1,y,z+1)) {
27958 res(x+1,y,z+1) = npot;
if (path) path(x+1,y,z+1) = (to)17;
27961 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x,y-1,z+1)+P)),x,y-1,z+1)) {
27962 res(x,y-1,z+1) = npot;
if (path) path(x,y-1,z+1) = (to)24;
27965 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x,y+1,z+1)+P)),x,y+1,z+1)) {
27966 res(x,y+1,z+1) = npot;
if (path) path(x,y+1,z+1) = (to)20;
27968 if (x-1>=0 && y-1>=0 &&
27969 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x-1,y-1,z+1)+P)),x-1,y-1,z+1)) {
27970 res(x-1,y-1,z+1) = npot;
if (path) path(x-1,y-1,z+1) = (to)26;
27972 if (x+1<
width() && y-1>=0 &&
27973 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x+1,y-1,z+1)+P)),x+1,y-1,z+1)) {
27974 res(x+1,y-1,z+1) = npot;
if (path) path(x+1,y-1,z+1) = (to)25;
27976 if (x-1>=0 && y+1<
height() &&
27977 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x-1,y+1,z+1)+P)),x-1,y+1,z+1)) {
27978 res(x-1,y+1,z+1) = npot;
if (path) path(x-1,y+1,z+1) = (to)22;
27981 Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x+1,y+1,z+1)+P)),x+1,y+1,z+1)) {
27982 res(x+1,y+1,z+1) = npot;
if (path) path(x+1,y+1,z+1) = (to)21;
27992 template<
typename t>
27994 const bool is_high_connectivity=
false) {
27999 template<
typename t>
28001 const bool is_high_connectivity=
false)
const {
28011 template<
typename t>
28017 template<
typename t>
28022 "distance_eikonal(): image instance and metric map (%u,%u,%u,%u) have "
28023 "incompatible dimensions.",
28025 metric._width,metric._height,metric._depth,metric._spectrum);
28029 #ifdef cimg_use_openmp
28030 #pragma omp parallel for if (_spectrum>=2) firstprivate(Q,state)
28032 cimg_forC(*
this,c) {
28034 const CImg<t> met = metric.get_shared_channel(c%metric._spectrum);
28036 unsigned int sizeQ = 0;
28040 Tfloat *ptr1 = res._data;
char *ptr2 = state._data;
28041 cimg_for(img,ptr0,T) {
if (*ptr0==value) { *ptr1 = 0; *ptr2 = 1; } ++ptr1; ++ptr2; }
28044 ptr2 = state._data;
28045 cimg_forXYZ(img,x,y,z)
if (*(ptr2++)==1) {
28046 if (x-1>=0 && state(x-1,y,z)==-1) {
28047 const Tfloat dist = res(x-1,y,z) = __distance_eikonal(res,met(x-1,y,z),x-1,y,z);
28048 Q._eik_priority_queue_insert(state,sizeQ,-dist,x-1,y,z);
28050 if (x+1<
width() && state(x+1,y,z)==-1) {
28051 const Tfloat dist = res(x+1,y,z) = __distance_eikonal(res,met(x+1,y,z),x+1,y,z);
28052 Q._eik_priority_queue_insert(state,sizeQ,-dist,x+1,y,z);
28054 if (y-1>=0 && state(x,y-1,z)==-1) {
28055 const Tfloat dist = res(x,y-1,z) = __distance_eikonal(res,met(x,y-1,z),x,y-1,z);
28056 Q._eik_priority_queue_insert(state,sizeQ,-dist,x,y-1,z);
28058 if (y+1<
height() && state(x,y+1,z)==-1) {
28059 const Tfloat dist = res(x,y+1,z) = __distance_eikonal(res,met(x,y+1,z),x,y+1,z);
28060 Q._eik_priority_queue_insert(state,sizeQ,-dist,x,y+1,z);
28062 if (z-1>=0 && state(x,y,z-1)==-1) {
28063 const Tfloat dist = res(x,y,z-1) = __distance_eikonal(res,met(x,y,z-1),x,y,z-1);
28064 Q._eik_priority_queue_insert(state,sizeQ,-dist,x,y,z-1);
28066 if (z+1<
depth() && state(x,y,z+1)==-1) {
28067 const Tfloat dist = res(x,y,z+1) = __distance_eikonal(res,met(x,y,z+1),x,y,z+1);
28068 Q._eik_priority_queue_insert(state,sizeQ,-dist,x,y,z+1);
28074 int x = -1, y = -1, z = -1;
28075 while (sizeQ && x<0) {
28076 x = (int)Q(0,1); y = (int)Q(0,2); z = (int)Q(0,3);
28077 Q._priority_queue_remove(sizeQ);
28078 if (state(x,y,z)==1) x = -1;
else state(x,y,z) = 1;
28081 if (x-1>=0 && state(x-1,y,z)!=1) {
28082 const Tfloat dist = __distance_eikonal(res,met(x-1,y,z),x-1,y,z);
28083 if (dist<res(x-1,y,z)) { res(x-1,y,z) = dist; Q._eik_priority_queue_insert(state,sizeQ,-dist,x-1,y,z); }
28085 if (x+1<
width() && state(x+1,y,z)!=1) {
28086 const Tfloat dist = __distance_eikonal(res,met(x+1,y,z),x+1,y,z);
28087 if (dist<res(x+1,y,z)) { res(x+1,y,z) = dist; Q._eik_priority_queue_insert(state,sizeQ,-dist,x+1,y,z); }
28089 if (y-1>=0 && state(x,y-1,z)!=1) {
28090 const Tfloat dist = __distance_eikonal(res,met(x,y-1,z),x,y-1,z);
28091 if (dist<res(x,y-1,z)) { res(x,y-1,z) = dist; Q._eik_priority_queue_insert(state,sizeQ,-dist,x,y-1,z); }
28093 if (y+1<
height() && state(x,y+1,z)!=1) {
28094 const Tfloat dist = __distance_eikonal(res,met(x,y+1,z),x,y+1,z);
28095 if (dist<res(x,y+1,z)) { res(x,y+1,z) = dist; Q._eik_priority_queue_insert(state,sizeQ,-dist,x,y+1,z); }
28097 if (z-1>=0 && state(x,y,z-1)!=1) {
28098 const Tfloat dist = __distance_eikonal(res,met(x,y,z-1),x,y,z-1);
28099 if (dist<res(x,y,z-1)) { res(x,y,z-1) = dist; Q._eik_priority_queue_insert(state,sizeQ,-dist,x,y,z-1); }
28101 if (z+1<
depth() && state(x,y,z+1)!=1) {
28102 const Tfloat dist = __distance_eikonal(res,met(x,y,z+1),x,y,z+1);
28103 if (dist<res(x,y,z+1)) { res(x,y,z+1) = dist; Q._eik_priority_queue_insert(state,sizeQ,-dist,x,y,z+1); }
28112 Tfloat __distance_eikonal(
const CImg<Tfloat>& res,
const Tfloat P,
28113 const int x=0,
const int y=0,
const int z=0)
const {
28115 T T1 =
cimg::min(x-1>=0?res(x-1,y,z):M,x+1<
width()?res(x+1,y,z):M);
28120 T3 =
cimg::min(z-1>=0?res(x,y,z-1):M,z+1<
depth()?res(x,y,z+1):M);
28124 if (P<=0)
return (Tfloat)T1;
28125 if (T3<M && ___distance_eikonal(3,-2*(T1+T2+T3),T1*T1+T2*T2+T3*T3-P*P,root))
return cimg::max((Tfloat)T3,root);
28126 if (T2<M && ___distance_eikonal(2,-2*(T1+T2),T1*T1+T2*T2-P*P,root))
return cimg::max((Tfloat)T2,root);
28128 }
else if (_height>1) {
28131 if (P<=0)
return (Tfloat)T1;
28132 if (T2<M && ___distance_eikonal(2,-2*(T1+T2),T1*T1+T2*T2-P*P,root))
return cimg::max((Tfloat)T2,root);
28135 if (P<=0)
return (Tfloat)T1;
28142 static bool ___distance_eikonal(
const Tfloat a,
const Tfloat b,
const Tfloat c, Tfloat &root) {
28143 const Tfloat delta = b*b - 4*a*c;
28144 if (delta<0)
return false;
28145 root = 0.5f*(-b + std::sqrt(delta))/a;
28150 template<
typename t>
28151 void _eik_priority_queue_insert(CImg<charT>& state,
unsigned int& siz,
const t value,
28152 const unsigned int x,
const unsigned int y,
const unsigned int z) {
28153 if (state(x,y,z)>0)
return;
28156 (*this)(siz-1,0) = (T)value; (*this)(siz-1,1) = (T)x; (*this)(siz-1,2) = (T)y; (*this)(siz-1,3) = (T)z;
28157 for (
unsigned int pos = siz - 1, par = 0; pos && value>(*this)(par=(pos+1)/2-1,0); pos = par) {
28172 for (
unsigned int iteration = 0; iteration<nb_iterations; ++iteration) {
28173 Tfloat *ptrd = velocity._data, veloc_max = 0;
28175 CImg_3x3x3(I,Tfloat);
28176 cimg_forC(*
this,c) cimg_for3x3x3(*
this,x,y,z,c,I,Tfloat)
if (band_size<=0 ||
cimg::abs(Iccc)<band_size) {
28178 gx = (Incc - Ipcc)/2,
28179 gy = (Icnc - Icpc)/2,
28180 gz = (Iccn - Iccp)/2,
28182 ix = gx*sgn>0?(Incc - Iccc):(Iccc - Ipcc),
28183 iy = gy*sgn>0?(Icnc - Iccc):(Iccc - Icpc),
28184 iz = gz*sgn>0?(Iccn - Iccc):(Iccc - Iccp),
28185 ng = (Tfloat)(1e-5f + std::sqrt(gx*gx + gy*gy + gz*gz)),
28189 veloc = sgn*(ngx*ix + ngy*iy + ngz*iz - 1);
28191 if (veloc>veloc_max) veloc_max = veloc;
else if (-veloc>veloc_max) veloc_max = -veloc;
28192 }
else *(ptrd++) = 0;
28194 CImg_3x3(I,Tfloat);
28195 cimg_forC(*
this,c) cimg_for3x3(*
this,x,y,0,c,I,Tfloat)
if (band_size<=0 ||
cimg::abs(Icc)<band_size) {
28197 gx = (Inc - Ipc)/2,
28198 gy = (Icn - Icp)/2,
28200 ix = gx*sgn>0?(Inc - Icc):(Icc - Ipc),
28201 iy = gy*sgn>0?(Icn - Icc):(Icc - Icp),
28202 ng = (Tfloat)(1e-5f + std::sqrt(gx*gx + gy*gy)),
28205 veloc = sgn*(ngx*ix + ngy*iy - 1);
28207 if (veloc>veloc_max) veloc_max = veloc;
else if (-veloc>veloc_max) veloc_max = -veloc;
28208 }
else *(ptrd++) = 0;
28210 if (veloc_max>0) *
this+=(velocity*=time_step/veloc_max);
28217 const float time_step=0.5f)
const {
28233 if (
is_empty() || !nb_scales)
return +*
this;
28235 const Tfloat sqrt2 = std::sqrt(2);
28236 if (nb_scales==1) {
28239 const unsigned int w = _width/2;
28243 "haar(): Sub-image width %u is not even.",
28247 res.assign(_width,_height,_depth,_spectrum);
28248 if (
invert) cimg_forYZC(*
this,y,z,c) {
28249 for (
unsigned int x = 0, xw = w, x2 = 0; x<w; ++x, ++xw) {
28250 const Tfloat val0 = (Tfloat)(*
this)(x,y,z,c), val1 = (Tfloat)(*this)(xw,y,z,c);
28251 res(x2++,y,z,c) = (val0 - val1)/sqrt2;
28252 res(x2++,y,z,c) = (val0 + val1)/sqrt2;
28254 }
else cimg_forYZC(*
this,y,z,c) {
28255 for (
unsigned int x = 0, xw = w, x2 = 0; x<w; ++x, ++xw) {
28256 const Tfloat val0 = (Tfloat)(*
this)(x2++,y,z,c), val1 = (Tfloat)(*this)(x2++,y,z,c);
28257 res(x,y,z,c) = (val0 + val1)/sqrt2;
28258 res(xw,y,z,c) = (val1 - val0)/sqrt2;
28261 }
else return *
this;
28264 const unsigned int h = _height/2;
28268 "haar(): Sub-image height %u is not even.",
28272 res.assign(_width,_height,_depth,_spectrum);
28273 if (
invert) cimg_forXZC(*
this,x,z,c) {
28274 for (
unsigned int y = 0, yh = h, y2 = 0; y<h; ++y, ++yh) {
28275 const Tfloat val0 = (Tfloat)(*
this)(x,y,z,c), val1 = (Tfloat)(*this)(x,yh,z,c);
28276 res(x,y2++,z,c) = (val0 - val1)/sqrt2;
28277 res(x,y2++,z,c) = (val0 + val1)/sqrt2;
28279 }
else cimg_forXZC(*
this,x,z,c) {
28280 for (
unsigned int y = 0, yh = h, y2 = 0; y<h; ++y, ++yh) {
28281 const Tfloat val0 = (Tfloat)(*
this)(x,y2++,z,c), val1 = (Tfloat)(*this)(x,y2++,z,c);
28282 res(x,y,z,c) = (val0 + val1)/sqrt2;
28283 res(x,yh,z,c) = (val1 - val0)/sqrt2;
28286 }
else return *
this;
28289 const unsigned int d = _depth/2;
28293 "haar(): Sub-image depth %u is not even.",
28297 res.assign(_width,_height,_depth,_spectrum);
28298 if (
invert) cimg_forXYC(*
this,x,y,c) {
28299 for (
unsigned int z = 0, zd = d, z2 = 0; z<d; ++z, ++zd) {
28300 const Tfloat val0 = (Tfloat)(*
this)(x,y,z,c), val1 = (Tfloat)(*this)(x,y,zd,c);
28301 res(x,y,z2++,c) = (val0 - val1)/sqrt2;
28302 res(x,y,z2++,c) = (val0 + val1)/sqrt2;
28304 }
else cimg_forXYC(*
this,x,y,c) {
28305 for (
unsigned int z = 0, zd = d, z2 = 0; z<d; ++z, ++zd) {
28306 const Tfloat val0 = (Tfloat)(*
this)(x,y,z2++,c), val1 = (Tfloat)(*this)(x,y,z2++,c);
28307 res(x,y,z,c) = (val0 + val1)/sqrt2;
28308 res(x,y,zd,c) = (val1 - val0)/sqrt2;
28311 }
else return *
this;
28315 "haar(): Invalid specified axis '%c' "
28316 "(should be { x | y | z }).",
28325 unsigned int w = _width;
28326 for (
unsigned int s = 1; w && s<nb_scales; ++s) w/=2;
28327 for (w = w?w:1; w<=_width; w*=2) res.draw_image(res.get_crop(0,w-1).get_haar(
'x',
true,1));
28330 unsigned int h = _width;
28331 for (
unsigned int s = 1; h && s<nb_scales; ++s) h/=2;
28332 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));
28335 unsigned int d = _depth;
28336 for (
unsigned int s = 1; d && s<nb_scales; ++s) d/=2;
28337 for (d = d?d:1; d<=_depth; d*=2)
28338 res.draw_image(res.get_crop(0,0,0,_width-1,_height-1,d-1).get_haar(
'z',
true,1));
28342 "haar(): Invalid specified axis '%c' "
28343 "(should be { x | y | z }).",
28351 for (
unsigned int s = 1, w = _width/2; w && s<nb_scales; ++s, w/=2)
28352 res.draw_image(res.get_crop(0,w-1).get_haar(
'x',
false,1));
28355 for (
unsigned int s = 1, h = _height/2; h && s<nb_scales; ++s, h/=2)
28356 res.draw_image(res.get_crop(0,0,_width-1,h-1).get_haar(
'y',
false,1));
28359 for (
unsigned int s = 1, d = _depth/2; d && s<nb_scales; ++s, d/=2)
28360 res.draw_image(res.get_crop(0,0,0,_width-1,_height-1,d-1).get_haar(
'z',
false,1));
28364 "haar(): Invalid specified axis '%c' "
28365 "(should be { x | y | z }).",
28386 if (nb_scales==1) {
28390 if (res)
return res;
28397 unsigned int w = _width, h = _height, d = _depth;
28398 for (
unsigned int s = 1; w && h && d && s<nb_scales; ++s) { w/=2; h/=2; d/=2; }
28399 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)
28400 res.draw_image(res.get_crop(0,0,0,w-1,h-1,d-1).get_haar(
true,1));
28402 unsigned int w = _width, h = _height;
28403 for (
unsigned int s = 1; w && h && s<nb_scales; ++s) { w/=2; h/=2; }
28404 for (w = w?w:1, h = h?h:1; w<=_width && h<=_height; w*=2, h*=2)
28405 res.draw_image(res.get_crop(0,0,0,w-1,h-1,0).get_haar(
true,1));
28409 unsigned int w = _width, d = _depth;
28410 for (
unsigned int s = 1; w && d && s<nb_scales; ++s) { w/=2; d/=2; }
28411 for (w = w?w:1, d = d?d:1; w<=_width && d<=_depth; w*=2, d*=2)
28412 res.draw_image(res.get_crop(0,0,0,w-1,0,d-1).get_haar(
true,1));
28414 unsigned int w = _width;
28415 for (
unsigned int s = 1; w && s<nb_scales; ++s) w/=2;
28416 for (w = w?w:1; w<=_width; w*=2)
28417 res.draw_image(res.get_crop(0,0,0,w-1,0,0).get_haar(
true,1));
28423 unsigned int h = _height, d = _depth;
28424 for (
unsigned int s = 1; h && d && s<nb_scales; ++s) { h/=2; d/=2; }
28425 for (h = h?h:1, d = d?d:1; h<=_height && d<=_depth; h*=2, d*=2)
28426 res.draw_image(res.get_crop(0,0,0,0,h-1,d-1).get_haar(
true,1));
28428 unsigned int h = _height;
28429 for (
unsigned int s = 1; h && s<nb_scales; ++s) h/=2;
28430 for (h = h?h:1; h<=_height; h*=2)
28431 res.draw_image(res.get_crop(0,0,0,0,h-1,0).get_haar(
true,1));
28435 unsigned int d = _depth;
28436 for (
unsigned int s = 1; d && s<nb_scales; ++s) d/=2;
28437 for (d = d?d:1; d<=_depth; d*=2)
28438 res.draw_image(res.get_crop(0,0,0,0,0,d-1).get_haar(
true,1));
28439 }
else return *
this;
28447 for (
unsigned int s = 1, w = _width/2, h = _height/2, d = _depth/2; w && h && d && s<nb_scales;
28448 ++s, w/=2, h/=2, d/=2)
28449 res.draw_image(res.get_crop(0,0,0,w-1,h-1,d-1).haar(
false,1));
28450 else for (
unsigned int s = 1, w = _width/2, h = _height/2; w && h && s<nb_scales; ++s, w/=2, h/=2)
28451 res.draw_image(res.get_crop(0,0,0,w-1,h-1,0).haar(
false,1));
28453 if (_depth>1)
for (
unsigned int s = 1, w = _width/2, d = _depth/2; w && d && s<nb_scales; ++s, w/=2, d/=2)
28454 res.draw_image(res.get_crop(0,0,0,w-1,0,d-1).haar(
false,1));
28455 else for (
unsigned int s = 1, w = _width/2; w && s<nb_scales; ++s, w/=2)
28456 res.draw_image(res.get_crop(0,0,0,w-1,0,0).haar(
false,1));
28461 for (
unsigned int s = 1, h = _height/2, d = _depth/2; h && d && s<nb_scales; ++s, h/=2, d/=2)
28462 res.draw_image(res.get_crop(0,0,0,0,h-1,d-1).haar(
false,1));
28463 else for (
unsigned int s = 1, h = _height/2; h && s<nb_scales; ++s, h/=2)
28464 res.draw_image(res.get_crop(0,0,0,0,h-1,0).haar(
false,1));
28466 if (_depth>1)
for (
unsigned int s = 1, d = _depth/2; d && s<nb_scales; ++s, d/=2)
28467 res.draw_image(res.get_crop(0,0,0,0,0,d-1).haar(
false,1));
28510 if (!imag) imag.assign(real._width,real._height,real._depth,real._spectrum,0);
28511 if (!real.is_sameXYZC(imag))
28513 "imaginary part (%u,%u,%u,%u,%p) have different dimensions.",
28515 real._width,real._height,real._depth,real._spectrum,real._data,
28516 imag._width,imag._height,imag._depth,imag._spectrum,imag._data);
28517 #ifdef cimg_use_fftw3
28519 fftw_complex *data_in;
28520 fftw_plan data_plan;
28524 data_in = (fftw_complex*)fftw_malloc(
sizeof(fftw_complex)*real._width);
28526 "for computing FFT of image (%u,%u,%u,%u) along the X-axis.",
28528 cimg::strbuffersize(
sizeof(fftw_complex)*real._width),
28529 real._width,real._height,real._depth,real._spectrum);
28531 data_plan = fftw_plan_dft_1d(real._width,data_in,data_in,is_invert?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE);
28532 cimg_forYZC(real,y,z,c) {
28533 T *ptrr = real.data(0,y,z,c), *ptri = imag.data(0,y,z,c);
28534 double *ptrd = (
double*)data_in;
28535 cimg_forX(real,x) { *(ptrd++) = (
double)*(ptrr++); *(ptrd++) = (
double)*(ptri++); }
28536 fftw_execute(data_plan);
28537 const unsigned int fact = real._width;
28538 if (is_invert) cimg_forX(real,x) { *(--ptri) = (T)(*(--ptrd)/fact); *(--ptrr) = (T)(*(--ptrd)/fact); }
28539 else cimg_forX(real,x) { *(--ptri) = (T)*(--ptrd); *(--ptrr) = (T)*(--ptrd); }
28543 data_in = (fftw_complex*)fftw_malloc(
sizeof(fftw_complex) * real._height);
28545 "for computing FFT of image (%u,%u,%u,%u) along the Y-axis.",
28547 cimg::strbuffersize(
sizeof(fftw_complex)*real._height),
28548 real._width,real._height,real._depth,real._spectrum);
28550 data_plan = fftw_plan_dft_1d(real._height,data_in,data_in,is_invert?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE);
28551 const unsigned int off = real._width;
28552 cimg_forXZC(real,x,z,c) {
28553 T *ptrr = real.data(x,0,z,c), *ptri = imag.data(x,0,z,c);
28554 double *ptrd = (
double*)data_in;
28555 cimg_forY(real,y) { *(ptrd++) = (
double)*ptrr; *(ptrd++) = (
double)*ptri; ptrr+=off; ptri+=off; }
28556 fftw_execute(data_plan);
28557 const unsigned int fact = real._height;
28559 cimg_forY(real,y) { ptrr-=off; ptri-=off; *ptri = (T)(*(--ptrd)/fact); *ptrr = (T)(*(--ptrd)/fact); }
28560 else cimg_forY(real,y) { ptrr-=off; ptri-=off; *ptri = (T)*(--ptrd); *ptrr = (T)*(--ptrd); }
28564 data_in = (fftw_complex*)fftw_malloc(
sizeof(fftw_complex) * real._depth);
28566 "for computing FFT of image (%u,%u,%u,%u) along the Z-axis.",
28568 cimg::strbuffersize(
sizeof(fftw_complex)*real._depth),
28569 real._width,real._height,real._depth,real._spectrum);
28571 data_plan = fftw_plan_dft_1d(real._depth,data_in,data_in,is_invert?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE);
28572 const unsigned long off = (
unsigned long)real._width*real._height;
28573 cimg_forXYC(real,x,y,c) {
28574 T *ptrr = real.data(x,y,0,c), *ptri = imag.data(x,y,0,c);
28575 double *ptrd = (
double*)data_in;
28576 cimg_forZ(real,z) { *(ptrd++) = (
double)*ptrr; *(ptrd++) = (
double)*ptri; ptrr+=off; ptri+=off; }
28577 fftw_execute(data_plan);
28578 const unsigned int fact = real._depth;
28580 cimg_forZ(real,z) { ptrr-=off; ptri-=off; *ptri = (T)(*(--ptrd)/fact); *ptrr = (T)(*(--ptrd)/fact); }
28581 else cimg_forZ(real,z) { ptrr-=off; ptri-=off; *ptri = (T)*(--ptrd); *ptrr = (T)*(--ptrd); }
28585 data_in = (fftw_complex*)fftw_malloc(
sizeof(fftw_complex) * real._spectrum);
28587 "for computing FFT of image (%u,%u,%u,%u) along the C-axis.",
28589 cimg::strbuffersize(
sizeof(fftw_complex)*real._spectrum),
28590 real._width,real._height,real._depth,real._spectrum);
28592 data_plan = fftw_plan_dft_1d(real._spectrum,data_in,data_in,is_invert?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE);
28593 const unsigned long off = (
unsigned long)real._width*real._height*real._depth;
28594 cimg_forXYZ(real,x,y,z) {
28595 T *ptrr = real.data(x,y,z,0), *ptri = imag.data(x,y,z,0);
28596 double *ptrd = (
double*)data_in;
28597 cimg_forC(real,c) { *(ptrd++) = (
double)*ptrr; *(ptrd++) = (
double)*ptri; ptrr+=off; ptri+=off; }
28598 fftw_execute(data_plan);
28599 const unsigned int fact = real._spectrum;
28601 cimg_forC(real,c) { ptrr-=off; ptri-=off; *ptri = (T)(*(--ptrd)/fact); *ptrr = (T)(*(--ptrd)/fact); }
28602 else cimg_forC(real,c) { ptrr-=off; ptri-=off; *ptri = (T)*(--ptrd); *ptrr = (T)*(--ptrd); }
28606 fftw_destroy_plan(data_plan);
28607 fftw_free(data_in);
28612 const unsigned int N = real._width, N2 = (N>>1);
28613 if (((N-1)&N) && N!=1)
28614 throw CImgInstanceException(
"CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) "
28615 "have non 2^N dimension along the X-axis.",
28617 real._width,real._height,real._depth,real._spectrum);
28619 for (
unsigned int i = 0, j = 0; i<N2; ++i) {
28620 if (j>i) cimg_forYZC(real,y,z,c) {
28621 cimg::swap(real(i,y,z,c),real(j,y,z,c));
cimg::swap(imag(i,y,z,c),imag(j,y,z,c));
28623 const unsigned int ri = N-1-i, rj = N-1-j;
28624 cimg::swap(real(ri,y,z,c),real(rj,y,z,c));
cimg::swap(imag(ri,y,z,c),imag(rj,y,z,c));
28627 for (
unsigned int m = N, n = N2; (j+=n)>=m; j-=m, m = n, n>>=1) {}
28629 for (
unsigned int delta = 2; delta<=N; delta<<=1) {
28630 const unsigned int delta2 = (delta>>1);
28631 for (
unsigned int i = 0; i<N; i+=delta) {
28632 float wr = 1, wi = 0;
28633 const float angle = (float)((is_invert?+1:-1)*2*
cimg::PI/delta),
28634 ca = (
float)std::cos(angle),
28635 sa = (float)std::sin(angle);
28636 for (
unsigned int k = 0; k<delta2; ++k) {
28637 const unsigned int j = i + k, nj = j + delta2;
28638 cimg_forYZC(real,y,z,c) {
28639 T &ir = real(j,y,z,c), &ii = imag(j,y,z,c), &nir = real(nj,y,z,c), &nii = imag(nj,y,z,c);
28640 const float tmpr = (float)(wr*nir - wi*nii), tmpi = (float)(wr*nii + wi*nir);
28641 nir = (T)(ir - tmpr);
28642 nii = (T)(ii - tmpi);
28646 const float nwr = wr*ca-wi*sa;
28647 wi = wi*ca + wr*sa;
28652 if (is_invert) { real/=N; imag/=N; }
28655 const unsigned int N = real._height, N2 = (N>>1);
28656 if (((N-1)&N) && N!=1)
28657 throw CImgInstanceException(
"CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) "
28658 "have non 2^N dimension along the Y-axis.",
28660 real._width,real._height,real._depth,real._spectrum);
28662 for (
unsigned int i = 0, j = 0; i<N2; ++i) {
28663 if (j>i) cimg_forXZC(real,x,z,c) {
28664 cimg::swap(real(x,i,z,c),real(x,j,z,c));
cimg::swap(imag(x,i,z,c),imag(x,j,z,c));
28666 const unsigned int ri = N - 1 - i, rj = N - 1 - j;
28667 cimg::swap(real(x,ri,z,c),real(x,rj,z,c));
cimg::swap(imag(x,ri,z,c),imag(x,rj,z,c));
28670 for (
unsigned int m = N, n = N2; (j+=n)>=m; j-=m, m = n, n>>=1) {}
28672 for (
unsigned int delta = 2; delta<=N; delta<<=1) {
28673 const unsigned int delta2 = (delta>>1);
28674 for (
unsigned int i = 0; i<N; i+=delta) {
28675 float wr = 1, wi = 0;
28676 const float angle = (float)((is_invert?+1:-1)*2*
cimg::PI/delta),
28677 ca = (
float)std::cos(angle), sa = (float)std::sin(angle);
28678 for (
unsigned int k = 0; k<delta2; ++k) {
28679 const unsigned int j = i + k, nj = j + delta2;
28680 cimg_forXZC(real,x,z,c) {
28681 T &ir = real(x,j,z,c), &ii = imag(x,j,z,c), &nir = real(x,nj,z,c), &nii = imag(x,nj,z,c);
28682 const float tmpr = (float)(wr*nir - wi*nii), tmpi = (float)(wr*nii + wi*nir);
28683 nir = (T)(ir - tmpr);
28684 nii = (T)(ii - tmpi);
28688 const float nwr = wr*ca-wi*sa;
28689 wi = wi*ca + wr*sa;
28694 if (is_invert) { real/=N; imag/=N; }
28697 const unsigned int N = real._depth, N2 = (N>>1);
28698 if (((N-1)&N) && N!=1)
28699 throw CImgInstanceException(
"CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) "
28700 "have non 2^N dimension along the Z-axis.",
28702 real._width,real._height,real._depth,real._spectrum);
28704 for (
unsigned int i = 0, j = 0; i<N2; ++i) {
28705 if (j>i) cimg_forXYC(real,x,y,c) {
28706 cimg::swap(real(x,y,i,c),real(x,y,j,c));
cimg::swap(imag(x,y,i,c),imag(x,y,j,c));
28708 const unsigned int ri = N - 1 - i, rj = N - 1 - j;
28709 cimg::swap(real(x,y,ri,c),real(x,y,rj,c));
cimg::swap(imag(x,y,ri,c),imag(x,y,rj,c));
28712 for (
unsigned int m = N, n = N2; (j+=n)>=m; j-=m, m = n, n>>=1) {}
28714 for (
unsigned int delta = 2; delta<=N; delta<<=1) {
28715 const unsigned int delta2 = (delta>>1);
28716 for (
unsigned int i = 0; i<N; i+=delta) {
28717 float wr = 1, wi = 0;
28718 const float angle = (float)((is_invert?+1:-1)*2*
cimg::PI/delta),
28719 ca = (
float)std::cos(angle), sa = (float)std::sin(angle);
28720 for (
unsigned int k = 0; k<delta2; ++k) {
28721 const unsigned int j = i + k, nj = j + delta2;
28722 cimg_forXYC(real,x,y,c) {
28723 T &ir = real(x,y,j,c), &ii = imag(x,y,j,c), &nir = real(x,y,nj,c), &nii = imag(x,y,nj,c);
28724 const float tmpr = (float)(wr*nir - wi*nii), tmpi = (float)(wr*nii + wi*nir);
28725 nir = (T)(ir - tmpr);
28726 nii = (T)(ii - tmpi);
28730 const float nwr = wr*ca-wi*sa;
28731 wi = wi*ca + wr*sa;
28736 if (is_invert) { real/=N; imag/=N; }
28739 throw CImgArgumentException(
"CImgList<%s>::FFT(): Invalid specified axis '%c' for real and imaginary parts "
28741 "(should be { x | y | z }).",
28743 real._width,real._height,real._depth,real._spectrum);
28756 static void FFT(
CImg<T>& real,
CImg<T>& imag,
const bool is_invert=
false,
const unsigned int nb_threads=0) {
28761 if (!imag) imag.assign(real._width,real._height,real._depth,real._spectrum,0);
28762 if (!real.is_sameXYZC(imag))
28764 "imaginary part (%u,%u,%u,%u,%p) have different dimensions.",
28766 real._width,real._height,real._depth,real._spectrum,real._data,
28767 imag._width,imag._height,imag._depth,imag._spectrum,imag._data);
28769 #ifdef cimg_use_fftw3
28771 #ifndef cimg_use_fftw3_singlethread
28772 const unsigned int _nb_threads = nb_threads?nb_threads:cimg::nb_cpus();
28773 static int fftw_st = fftw_init_threads();
28775 fftw_plan_with_nthreads(_nb_threads);
28779 fftw_complex *data_in = (fftw_complex*)fftw_malloc(
sizeof(fftw_complex)*real._width*real._height*real._depth);
28781 "for computing FFT of image (%u,%u,%u,%u).",
28783 cimg::strbuffersize(
sizeof(fftw_complex)*real._width*
28784 real._height*real._depth*real._spectrum),
28785 real._width,real._height,real._depth,real._spectrum);
28787 fftw_plan data_plan;
28788 const unsigned long w = (
unsigned long)real._width, wh = w*real._height, whd = wh*real._depth;
28789 data_plan = fftw_plan_dft_3d(real._width,real._height,real._depth,data_in,data_in,
28790 is_invert?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE);
28791 cimg_forC(real,c) {
28792 T *ptrr = real.data(0,0,0,c), *ptri = imag.data(0,0,0,c);
28793 double *ptrd = (
double*)data_in;
28794 for (
unsigned int x = 0; x<real._width; ++x, ptrr-=wh-1, ptri-=wh-1)
28795 for (
unsigned int y = 0; y<real._height; ++y, ptrr-=whd-w, ptri-=whd-w)
28796 for (
unsigned int z = 0; z<real._depth; ++z, ptrr+=wh, ptri+=wh) {
28797 *(ptrd++) = (
double)*ptrr; *(ptrd++) = (
double)*ptri;
28799 fftw_execute(data_plan);
28800 ptrd = (
double*)data_in;
28801 ptrr = real.data(0,0,0,c);
28802 ptri = imag.data(0,0,0,c);
28803 if (!is_invert)
for (
unsigned int x = 0; x<real._width; ++x, ptrr-=wh-1, ptri-=wh-1)
28804 for (
unsigned int y = 0; y<real._height; ++y, ptrr-=whd-w, ptri-=whd-w)
28805 for (
unsigned int z = 0; z<real._depth; ++z, ptrr+=wh, ptri+=wh) {
28806 *ptrr = (T)*(ptrd++); *ptri = (T)*(ptrd++);
28808 else for (
unsigned int x = 0; x<real._width; ++x, ptrr-=wh-1, ptri-=wh-1)
28809 for (
unsigned int y = 0; y<real._height; ++y, ptrr-=whd-w, ptri-=whd-w)
28810 for (
unsigned int z = 0; z<real._depth; ++z, ptrr+=wh, ptri+=wh) {
28811 *ptrr = (T)(*(ptrd++)/whd); *ptri = (T)(*(ptrd++)/whd);
28814 fftw_destroy_plan(data_plan);
28815 fftw_free(data_in);
28816 #ifndef cimg_use_fftw3_singlethread
28817 fftw_cleanup_threads();
28822 if (real._depth>1)
FFT(real,imag,
'z',is_invert);
28823 if (real._height>1)
FFT(real,imag,
'y',is_invert);
28824 if (real._width>1)
FFT(real,imag,
'x',is_invert);
28842 if (_height!=3 || _depth>1 || _spectrum>1)
28844 "shift_object3d(): Instance is not a set of 3d vertices.",
28861 if (_height!=3 || _depth>1 || _spectrum>1)
28863 "shift_object3d(): Instance is not a set of 3d vertices.",
28868 xm, xM = (float)xcoords.max_min(xm),
28869 ym, yM = (float)ycoords.max_min(ym),
28870 zm, zM = (float)zcoords.max_min(zm);
28871 xcoords-=(xm + xM)/2; ycoords-=(ym + yM)/2; zcoords-=(zm + zM)/2;
28887 if (_height!=3 || _depth>1 || _spectrum>1)
28889 "resize_object3d(): Instance is not a set of 3d vertices.",
28894 xm, xM = (float)xcoords.max_min(xm),
28895 ym, yM = (float)ycoords.max_min(ym),
28896 zm, zM = (float)zcoords.max_min(zm);
28897 if (xm<xM) {
if (sx>0) xcoords*=sx/(xM-xm);
else xcoords*=-sx/100; }
28898 if (ym<yM) {
if (sy>0) ycoords*=sy/(yM-ym);
else ycoords*=-sy/100; }
28899 if (zm<zM) {
if (sz>0) zcoords*=sz/(zM-zm);
else zcoords*=-sz/100; }
28910 if (_height!=3 || _depth>1 || _spectrum>1)
28912 "resize_object3d(): Instance is not a set of 3d vertices.",
28917 xm, xM = (float)xcoords.max_min(xm),
28918 ym, yM = (float)ycoords.max_min(ym),
28919 zm, zM = (float)zcoords.max_min(zm);
28920 const float dx = xM - xm, dy = yM - ym, dz = zM - zm, dmax =
cimg::max(dx,dy,dz);
28921 if (dmax>0) { xcoords/=dmax; ycoords/=dmax; zcoords/=dmax; }
28936 template<
typename tf,
typename tp,
typename tff>
28939 if (!obj_vertices || !obj_primitives)
return *
this;
28940 if (obj_vertices._height!=3 || obj_vertices._depth>1 || obj_vertices._spectrum>1)
28942 "append_object3d(): Specified vertice image (%u,%u,%u,%u,%p) is not a "
28943 "set of 3d vertices.",
28945 obj_vertices._width,obj_vertices._height,
28946 obj_vertices._depth,obj_vertices._spectrum,obj_vertices._data);
28949 if (_height!=3 || _depth>1 || _spectrum>1)
28951 "append_object3d(): Instance is not a set of 3d vertices.",
28954 const unsigned int P = _width;
28955 append(obj_vertices,
'x');
28956 const unsigned int N = primitives._width;
28957 primitives.
insert(obj_primitives);
28958 for (
unsigned int i = N; i<primitives._width; ++i) {
28960 switch (p.size()) {
28961 case 1 : p[0]+=P;
break;
28962 case 5 : p[0]+=P; p[1]+=P;
break;
28963 case 2 :
case 6 : p[0]+=P; p[1]+=P;
break;
28964 case 3 :
case 9 : p[0]+=P; p[1]+=P; p[2]+=P;
break;
28965 case 4 :
case 12 : p[0]+=P; p[1]+=P; p[2]+=P; p[3]+=P;
break;
28978 template<
typename tp,
typename tc,
typename tt,
typename tx>
28984 "texturize_object3d(): image instance is not a set of 3d points.",
28986 if (coords && (coords._width!=_width || coords._height!=2))
28988 "texturize_object3d(): Invalid specified texture coordinates (%u,%u,%u,%u,%p).",
28990 coords._width,coords._height,coords._depth,coords._spectrum,coords._data);
28993 _coords.assign(_width,2);
28997 dx = xmax>xmin?xmax-xmin:1,
28998 dy = ymax>ymin?ymax-ymin:1;
28999 cimg_forX(*
this,p) {
29000 _coords(p,0) = (
unsigned int)(((*
this)(p,0)-xmin)*(texture._width-1)/dx);
29001 _coords(p,1) = (
unsigned int)(((*
this)(p,1)-ymin)*(texture._height-1)/dy);
29003 }
else _coords = coords;
29005 int texture_ind = -1;
29006 cimglist_for(primitives,l) {
29008 const unsigned int siz = p.size();
29012 i0 = (
unsigned int)p[0],
29013 x0 = (
unsigned int)_coords(i0,0), y0 = (
unsigned int)_coords(i0,1);
29014 texture.get_vector_at(x0,y0).move_to(colors[l]);
29016 case 2 :
case 6 : {
29018 i0 = (
unsigned int)p[0], i1 = (
unsigned int)p[1],
29019 x0 = (
unsigned int)_coords(i0,0), y0 = (
unsigned int)_coords(i0,1),
29020 x1 = (
unsigned int)_coords(i1,0), y1 = (
unsigned int)_coords(i1,1);
29021 if (texture_ind<0) colors[texture_ind=l] = texture;
else colors[l].
assign(colors[texture_ind],
true);
29024 case 3 :
case 9 : {
29026 i0 = (
unsigned int)p[0], i1 = (
unsigned int)p[1], i2 = (
unsigned int)p[2],
29027 x0 = (
unsigned int)_coords(i0,0), y0 = (
unsigned int)_coords(i0,1),
29028 x1 = (
unsigned int)_coords(i1,0), y1 = (
unsigned int)_coords(i1,1),
29029 x2 = (
unsigned int)_coords(i2,0), y2 = (
unsigned int)_coords(i2,1);
29030 if (texture_ind<0) colors[texture_ind=l] = texture;
else colors[l].
assign(colors[texture_ind],
true);
29033 case 4 :
case 12 : {
29035 i0 = (
unsigned int)p[0], i1 = (
unsigned int)p[1], i2 = (
unsigned int)p[2], i3 = (
unsigned int)p[3],
29036 x0 = (
unsigned int)_coords(i0,0), y0 = (
unsigned int)_coords(i0,1),
29037 x1 = (
unsigned int)_coords(i1,0), y1 = (
unsigned int)_coords(i1,1),
29038 x2 = (
unsigned int)_coords(i2,0), y2 = (
unsigned int)_coords(i2,1),
29039 x3 = (
unsigned int)_coords(i3,0), y3 = (
unsigned int)_coords(i3,1);
29040 if (texture_ind<0) colors[texture_ind=l] = texture;
else colors[l].
assign(colors[texture_ind],
true);
29041 CImg<tp>::vector(i0,i1,i2,i3,x0,y0,x1,y1,x2,y2,x3,y3).move_to(p);
29065 template<
typename tf,
typename tc,
typename te>
29067 if (!
is_sameXY(elevation) || elevation._depth>1 || elevation._spectrum>1)
29069 "get_elevation3d(): Instance and specified elevation (%u,%u,%u,%u,%p) "
29070 "have incompatible dimensions.",
29072 elevation._width,elevation._height,elevation._depth,
29073 elevation._spectrum,elevation._data);
29075 float m, M = (float)
max_min(m);
29078 const unsigned int size_x1 = _width - 1, size_y1 = _height - 1;
29079 for (
unsigned int y = 0; y<size_y1; ++y)
29080 for (
unsigned int x = 0; x<size_x1; ++x) {
29081 const unsigned char
29082 r = (
unsigned char)(((*
this)(x,y,0) - m)*255/(M-m)),
29083 g = _spectrum>1?(
unsigned char)(((*
this)(x,y,1) - m)*255/(M-m)):r,
29084 b = _spectrum>2?(
unsigned char)(((*
this)(x,y,2) - m)*255/(M-m)):(_spectrum>1?0:r);
29088 return elevation3d(primitives,func,0,0,_width-1.0f,_height-1.0f,_width,_height);
29100 template<
typename tf,
typename tc>
29102 const unsigned int x0,
const unsigned int y0,
const unsigned int z0,
29103 const bool normalize_colors=
false)
const {
29104 float m = 0, M = 0, delta = 1;
29105 if (normalize_colors) { m = (float)
min_max(M); delta = 255/(m==M?1:M-m); }
29107 _x0 = (x0>=_width)?_width - 1:x0,
29108 _y0 = (y0>=_height)?_height - 1:y0,
29109 _z0 = (z0>=_depth)?_depth - 1:z0;
29111 if (normalize_colors) {
29112 ((
get_crop(0,0,_z0,0,_width-1,_height-1,_z0,_spectrum-1)-=m)*=delta).
move_to(img_xy);
29113 ((
get_crop(0,_y0,0,0,_width-1,_y0,_depth-1,_spectrum-1)-=m)*=delta).resize(_width,_depth,1,-100,-1).
29115 ((
get_crop(_x0,0,0,0,_x0,_height-1,_depth-1,_spectrum-1)-=m)*=delta).resize(_height,_depth,1,-100,-1).
29118 get_crop(0,0,_z0,0,_width-1,_height-1,_z0,_spectrum-1).move_to(img_xy);
29119 get_crop(0,_y0,0,0,_width-1,_y0,_depth-1,_spectrum-1).resize(_width,_depth,1,-100,-1).move_to(img_xz);
29120 get_crop(_x0,0,0,0,_x0,_height-1,_depth-1,_spectrum-1).resize(_height,_depth,1,-100,-1).move_to(img_yz);
29123 0,_width-1,_width-1,0, 0,_width-1,_width-1,0, _x0,_x0,_x0,_x0,
29124 0,0,_height-1,_height-1, _y0,_y0,_y0,_y0, 0,_height-1,_height-1,0,
29125 _z0,_z0,_z0,_z0, 0,0,_depth-1,_depth-1, 0,0,_depth-1,_depth-1);
29127 CImg<tf>::vector(0,1,2,3,0,0,img_xy._width-1,0,img_xy._width-1,img_xy._height-1,0,img_xy._height-1).
29129 CImg<tf>::vector(4,5,6,7,0,0,img_xz._width-1,0,img_xz._width-1,img_xz._height-1,0,img_xz._height-1).
29131 CImg<tf>::vector(8,9,10,11,0,0,img_yz._width-1,0,img_yz._width-1,img_yz._height-1,0,img_yz._height-1).
29134 img_xy.move_to(colors);
29135 img_xz.move_to(colors);
29136 img_yz.move_to(colors);
29157 template<
typename tf>
29159 const int size_x=-100,
const int size_y=-100)
const {
29162 "get_isoline3d(): Instance is not a scalar image.",
29166 "get_isoline3d(): Instance is not a 2d image.",
29171 if ((size_x==-100 && size_y==-100) || (size_x==
width() && size_y==
height())) {
29172 const _functor2d_int func(*
this);
29175 const _functor2d_float func(*
this);
29199 template<
typename tf>
29201 const int size_x=-100,
const int size_y=-100,
const int size_z=-100)
const {
29204 "get_isosurface3d(): Instance is not a scalar image.",
29209 if ((size_x==-100 && size_y==-100 && size_z==-100) || (size_x==
width() && size_y==
height() && size_z==
depth())) {
29210 const _functor3d_int func(*
this);
29214 const _functor3d_float func(*
this);
29216 size_x,size_y,size_z);
29232 template<
typename tf,
typename tfunc>
29234 const float x0,
const float y0,
const float x1,
const float y1,
29235 const int size_x=256,
const int size_y=256) {
29237 nx0 = x0<x1?x0:x1, ny0 = y0<y1?y0:y1,
29238 nx1 = x0<x1?x1:x0, ny1 = y0<y1?y1:y0;
29240 _nsize_x = (
unsigned int)(size_x>=0?size_x:(nx1-nx0)*-size_x/100),
29241 nsize_x = _nsize_x?_nsize_x:1, nsize_x1 = nsize_x - 1,
29242 _nsize_y = (
unsigned int)(size_y>=0?size_y:(ny1-ny0)*-size_y/100),
29243 nsize_y = _nsize_y?_nsize_y:1, nsize_y1 = nsize_y - 1;
29244 if (nsize_x<2 || nsize_y<2)
29250 floatT *ptr_x = vertices.
data(0,0), *ptr_y = vertices.
data(0,1), *ptr_z = vertices.
data(0,2);
29251 for (
unsigned int y = 0; y<nsize_y; ++y) {
29252 const float Y = ny0 + y*(ny1-ny0)/nsize_y1;
29253 for (
unsigned int x = 0; x<nsize_x; ++x) {
29254 const float X = nx0 + x*(nx1-nx0)/nsize_x1;
29255 *(ptr_x++) = (
float)x;
29256 *(ptr_y++) = (
float)y;
29257 *(ptr_z++) = (
float)func(X,Y);
29260 primitives.
assign(nsize_x1*nsize_y1,1,4);
29261 for (
unsigned int p = 0, y = 0; y<nsize_y1; ++y) {
29262 const unsigned int yw = y*nsize_x;
29263 for (
unsigned int x = 0; x<nsize_x1; ++x) {
29264 const unsigned int xpyw = x + yw, xpyww = xpyw + nsize_x;
29265 primitives[p++].fill(xpyw,xpyww,xpyww+1,xpyw+1);
29272 template<
typename tf>
29274 const float x0,
const float y0,
const float x1,
const float y1,
29275 const int size_x=256,
const int size_y=256) {
29276 const _functor2d_expr func(expression);
29277 return elevation3d(primitives,func,x0,y0,x1,y1,size_x,size_y);
29293 template<
typename tf,
typename tfunc>
29295 const float x0,
const float y0,
const float x1,
const float y1,
29296 const int size_x=256,
const int size_y=256) {
29297 static const unsigned int edges[16] = { 0x0, 0x9, 0x3, 0xa, 0x6, 0xf, 0x5, 0xc, 0xc,
29298 0x5, 0xf, 0x6, 0xa, 0x3, 0x9, 0x0 };
29299 static const int segments[16][4] = { { -1,-1,-1,-1 }, { 0,3,-1,-1 }, { 0,1,-1,-1 }, { 1,3,-1,-1 },
29300 { 1,2,-1,-1 }, { 0,1,2,3 }, { 0,2,-1,-1 }, { 2,3,-1,-1 },
29301 { 2,3,-1,-1 }, { 0,2,-1,-1}, { 0,3,1,2 }, { 1,2,-1,-1 },
29302 { 1,3,-1,-1 }, { 0,1,-1,-1}, { 0,3,-1,-1}, { -1,-1,-1,-1 } };
29304 _nx = (
unsigned int)(size_x>=0?size_x:
cimg::round((x1-x0)*-size_x/100 + 1)),
29305 _ny = (
unsigned int)(size_y>=0?size_y:
cimg::round((y1-y0)*-size_y/100 + 1)),
29312 const float dx = (x1 - x0)/nxm1, dy = (y1 - y0)/nym1;
29314 CImg<intT> indices1(nx,1,1,2,-1), indices2(nx,1,1,2);
29316 float X = x0, Y = y0, nX = X + dx, nY = Y + dy;
29319 cimg_forX(values1,x) { values1(x) = (float)func(X,Y); X+=dx; }
29322 for (
unsigned int yi = 0, nyi = 1; yi<nym1; ++yi, ++nyi, Y=nY, nY+=dy) {
29323 X = x0; nX = X + dx;
29325 for (
unsigned int xi = 0, nxi = 1; xi<nxm1; ++xi, ++nxi, X=nX, nX+=dx) {
29329 val0 = values1(xi),
29330 val1 = values1(nxi),
29331 val2 = values2(nxi) = (float)func(nX,nY),
29332 val3 = values2(xi) = (float)func(X,nY);
29334 configuration = (val0<isovalue?1:0) | (val1<isovalue?2:0) | (val2<isovalue?4:0) | (val3<isovalue?8:0),
29335 edge = edges[configuration];
29339 if ((edge&1) && indices1(xi,0)<0) {
29340 const float Xi = X + (isovalue-val0)*dx/(val1-val0);
29341 indices1(xi,0) = vertices._width;
29344 if ((edge&2) && indices1(nxi,1)<0) {
29345 const float Yi = Y + (isovalue-val1)*dy/(val2-val1);
29346 indices1(nxi,1) = vertices._width;
29349 if ((edge&4) && indices2(xi,0)<0) {
29350 const float Xi = X + (isovalue-val3)*dx/(val2-val3);
29351 indices2(xi,0) = vertices._width;
29354 if ((edge&8) && indices1(xi,1)<0) {
29355 const float Yi = Y + (isovalue-val0)*dy/(val3-val0);
29356 indices1(xi,1) = vertices._width;
29361 for (
const int *segment = segments[configuration]; *segment!=-1; ) {
29362 const unsigned int p0 = *(segment++), p1 = *(segment++);
29364 i0 = (tf)(_isoline3d_indice(p0,indices1,indices2,xi,nxi)),
29365 i1 = (tf)(_isoline3d_indice(p1,indices1,indices2,xi,nxi));
29370 values1.swap(values2);
29371 indices1.swap(indices2);
29373 return vertices>
'x';
29377 template<
typename tf>
29379 const float x0,
const float y0,
const float x1,
const float y1,
29380 const int size_x=256,
const int size_y=256) {
29381 const _functor2d_expr func(expression);
29382 return isoline3d(primitives,func,isovalue,x0,y0,x1,y1,size_x,size_y);
29385 template<
typename t>
29386 static int _isoline3d_indice(
const unsigned int edge,
const CImg<t>& indices1,
const CImg<t>& indices2,
29387 const unsigned int x,
const unsigned int nx) {
29389 case 0 :
return (
int)indices1(x,0);
29390 case 1 :
return (
int)indices1(nx,1);
29391 case 2 :
return (
int)indices2(x,0);
29392 case 3 :
return (
int)indices1(x,1);
29413 template<
typename tf,
typename tfunc>
29415 const float x0,
const float y0,
const float z0,
29416 const float x1,
const float y1,
const float z1,
29417 const int size_x=32,
const int size_y=32,
const int size_z=32) {
29418 static const unsigned int edges[256] = {
29419 0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
29420 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
29421 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
29422 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
29423 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
29424 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
29425 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
29426 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
29427 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
29428 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
29429 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
29430 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
29431 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
29432 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
29433 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190,
29434 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000
29437 static const int triangles[256][16] = {
29438 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29439 { 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29440 { 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29441 { 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29442 { 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29443 { 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29444 { 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29445 { 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 },
29446 { 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29447 { 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29448 { 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29449 { 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 },
29450 { 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29451 { 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 },
29452 { 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 },
29453 { 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29454 { 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29455 { 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29456 { 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29457 { 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 },
29458 { 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29459 { 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 },
29460 { 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 },
29461 { 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1 },
29462 { 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29463 { 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1 },
29464 { 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 },
29465 { 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1 },
29466 { 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1 },
29467 { 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1 },
29468 { 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1 },
29469 { 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1 },
29470 { 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29471 { 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29472 { 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29473 { 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1 },
29474 { 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29475 { 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 },
29476 { 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 },
29477 { 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 },
29478 { 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29479 { 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 },
29480 { 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 },
29481 { 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1 },
29482 { 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1 },
29483 { 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1 },
29484 { 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1 },
29485 { 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1 },
29486 { 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29487 { 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1 },
29488 { 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1 },
29489 { 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29490 { 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1 },
29491 { 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 },
29492 { 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 },
29493 { 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 },
29494 { 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 },
29495 { 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 },
29496 { 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1 },
29497 { 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1 },
29498 { 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1 },
29499 { 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1 },
29500 { 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1 },
29501 { 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29502 { 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29503 { 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29504 { 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29505 { 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 },
29506 { 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29507 { 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1 },
29508 { 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 },
29509 { 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 },
29510 { 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29511 { 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 },
29512 { 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 },
29513 { 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 },
29514 { 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1 },
29515 { 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1 },
29516 { 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1 },
29517 { 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1 },
29518 { 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29519 { 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1 },
29520 { 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 },
29521 { 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 },
29522 { 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 },
29523 { 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 },
29524 { 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1 },
29525 { 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1 },
29526 { 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 },
29527 { 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1 },
29528 { 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1 },
29529 { 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1 },
29530 { 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1 },
29531 { 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1 },
29532 { 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1 },
29533 { 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1 },
29534 { 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29535 { 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1 },
29536 { 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1 },
29537 { 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1 },
29538 { 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1 },
29539 { 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1 },
29540 { 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29541 { 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1 },
29542 { 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1 },
29543 { 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1 },
29544 { 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1 },
29545 { 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1 },
29546 { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1 },
29547 { 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1 },
29548 { 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1 },
29549 { 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29550 { 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1 },
29551 { 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1 },
29552 { 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1 },
29553 { 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1 },
29554 { 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1 },
29555 { 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1 },
29556 { 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1 },
29557 { 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29558 { 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1 },
29559 { 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1 },
29560 { 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1 },
29561 { 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1 },
29562 { 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 },
29563 { 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29564 { 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1 },
29565 { 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29566 { 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29567 { 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29568 { 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29569 { 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 },
29570 { 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29571 { 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 },
29572 { 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 },
29573 { 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1 },
29574 { 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29575 { 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1 },
29576 { 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1 },
29577 { 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 },
29578 { 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 },
29579 { 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 },
29580 { 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1 },
29581 { 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1 },
29582 { 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29583 { 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1 },
29584 { 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1 },
29585 { 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1 },
29586 { 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1 },
29587 { 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1 },
29588 { 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1 },
29589 { 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 },
29590 { 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 },
29591 { 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29592 { 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 },
29593 { 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 },
29594 { 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1 },
29595 { 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1 },
29596 { 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1 },
29597 { 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29598 { 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29599 { 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 },
29600 { 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 },
29601 { 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1 },
29602 { 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 },
29603 { 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 },
29604 { 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 },
29605 { 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1 },
29606 { 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1 },
29607 { 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1 },
29608 { 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1 },
29609 { 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1 },
29610 { 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1 },
29611 { 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1 },
29612 { 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1 },
29613 { 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1 },
29614 { 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1 },
29615 { 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1 },
29616 { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1 },
29617 { 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1 },
29618 { 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1 },
29619 { 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1 },
29620 { 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 },
29621 { 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 },
29622 { 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 },
29623 { 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1 },
29624 { 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1 },
29625 { 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29626 { 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1 },
29627 { 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1 },
29628 { 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29629 { 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29630 { 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29631 { 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1 },
29632 { 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1 },
29633 { 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1 },
29634 { 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1 },
29635 { 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 },
29636 { 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 },
29637 { 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1 },
29638 { 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1 },
29639 { 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1 },
29640 { 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1 },
29641 { 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1 },
29642 { 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29643 { 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1 },
29644 { 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1 },
29645 { 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29646 { 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1 },
29647 { 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1 },
29648 { 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1 },
29649 { 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1 },
29650 { 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1 },
29651 { 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1 },
29652 { 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1 },
29653 { 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29654 { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1 },
29655 { 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1 },
29656 { 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1 },
29657 { 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1 },
29658 { 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1 },
29659 { 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29660 { 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1 },
29661 { 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29662 { 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1 },
29663 { 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1 },
29664 { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1 },
29665 { 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1 },
29666 { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1 },
29667 { 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1 },
29668 { 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1 },
29669 { 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1 },
29670 { 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1 },
29671 { 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1 },
29672 { 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1 },
29673 { 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29674 { 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1 },
29675 { 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1 },
29676 { 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29677 { 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29678 { 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29679 { 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1 },
29680 { 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1 },
29681 { 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29682 { 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1 },
29683 { 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1 },
29684 { 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29685 { 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29686 { 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 },
29687 { 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29688 { 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 },
29689 { 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29690 { 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29691 { 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29692 { 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
29693 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }
29697 _nx = (
unsigned int)(size_x>=0?size_x:
cimg::round((x1-x0)*-size_x/100 + 1)),
29698 _ny = (
unsigned int)(size_y>=0?size_y:
cimg::round((y1-y0)*-size_y/100 + 1)),
29699 _nz = (
unsigned int)(size_z>=0?size_z:
cimg::round((z1-z0)*-size_z/100 + 1)),
29708 const float dx = (x1 - x0)/nxm1, dy = (y1 - y0)/nym1, dz = (z1 - z0)/nzm1;
29710 CImg<intT> indices1(nx,ny,1,3,-1), indices2(indices1);
29712 float X = 0, Y = 0, Z = 0, nX = 0, nY = 0, nZ = 0;
29716 cimg_forY(values1,y) {
29718 cimg_forX(values1,x) { values1(x,y) = (float)func(X,Y,z0); X+=dx; }
29723 Z = z0; nZ = Z + dz;
29724 for (
unsigned int zi = 0; zi<nzm1; ++zi, Z = nZ, nZ+=dz) {
29725 Y = y0; nY = Y + dy;
29727 for (
unsigned int yi = 0, nyi = 1; yi<nym1; ++yi, ++nyi, Y = nY, nY+=dy) {
29728 X = x0; nX = X + dx;
29729 for (
unsigned int xi = 0, nxi = 1; xi<nxm1; ++xi, ++nxi, X = nX, nX+=dx) {
29733 val0 = values1(xi,yi),
29734 val1 = values1(nxi,yi),
29735 val2 = values1(nxi,nyi),
29736 val3 = values1(xi,nyi),
29737 val4 = values2(xi,yi) = (float)func(X,Y,nZ),
29738 val5 = values2(nxi,yi) = (float)func(nX,Y,nZ),
29739 val6 = values2(nxi,nyi) = (float)func(nX,nY,nZ),
29740 val7 = values2(xi,nyi) = (float)func(X,nY,nZ);
29742 const unsigned int configuration =
29743 (val0<isovalue?1:0) | (val1<isovalue?2:0) | (val2<isovalue?4:0) | (val3<isovalue?8:0) |
29744 (val4<isovalue?16:0) | (val5<isovalue?32:0) | (val6<isovalue?64:0) | (val7<isovalue?128:0),
29745 edge = edges[configuration];
29749 if ((edge&1) && indices1(xi,yi,0)<0) {
29750 const float Xi = X + (isovalue-val0)*dx/(val1-val0);
29751 indices1(xi,yi,0) = vertices._width;
29754 if ((edge&2) && indices1(nxi,yi,1)<0) {
29755 const float Yi = Y + (isovalue-val1)*dy/(val2-val1);
29756 indices1(nxi,yi,1) = vertices._width;
29759 if ((edge&4) && indices1(xi,nyi,0)<0) {
29760 const float Xi = X + (isovalue-val3)*dx/(val2-val3);
29761 indices1(xi,nyi,0) = vertices._width;
29764 if ((edge&8) && indices1(xi,yi,1)<0) {
29765 const float Yi = Y + (isovalue-val0)*dy/(val3-val0);
29766 indices1(xi,yi,1) = vertices._width;
29769 if ((edge&16) && indices2(xi,yi,0)<0) {
29770 const float Xi = X + (isovalue-val4)*dx/(val5-val4);
29771 indices2(xi,yi,0) = vertices._width;
29774 if ((edge&32) && indices2(nxi,yi,1)<0) {
29775 const float Yi = Y + (isovalue-val5)*dy/(val6-val5);
29776 indices2(nxi,yi,1) = vertices._width;
29779 if ((edge&64) && indices2(xi,nyi,0)<0) {
29780 const float Xi = X + (isovalue-val7)*dx/(val6-val7);
29781 indices2(xi,nyi,0) = vertices._width;
29784 if ((edge&128) && indices2(xi,yi,1)<0) {
29785 const float Yi = Y + (isovalue-val4)*dy/(val7-val4);
29786 indices2(xi,yi,1) = vertices._width;
29789 if ((edge&256) && indices1(xi,yi,2)<0) {
29790 const float Zi = Z+ (isovalue-val0)*dz/(val4-val0);
29791 indices1(xi,yi,2) = vertices._width;
29794 if ((edge&512) && indices1(nxi,yi,2)<0) {
29795 const float Zi = Z + (isovalue-val1)*dz/(val5-val1);
29796 indices1(nxi,yi,2) = vertices._width;
29799 if ((edge&1024) && indices1(nxi,nyi,2)<0) {
29800 const float Zi = Z + (isovalue-val2)*dz/(val6-val2);
29801 indices1(nxi,nyi,2) = vertices._width;
29804 if ((edge&2048) && indices1(xi,nyi,2)<0) {
29805 const float Zi = Z + (isovalue-val3)*dz/(val7-val3);
29806 indices1(xi,nyi,2) = vertices._width;
29811 for (
const int *triangle = triangles[configuration]; *triangle!=-1; ) {
29812 const unsigned int p0 = *(triangle++), p1 = *(triangle++), p2 = *(triangle++);
29814 i0 = (tf)(_isosurface3d_indice(p0,indices1,indices2,xi,yi,nxi,nyi)),
29815 i1 = (tf)(_isosurface3d_indice(p1,indices1,indices2,xi,yi,nxi,nyi)),
29816 i2 = (tf)(_isosurface3d_indice(p2,indices1,indices2,xi,yi,nxi,nyi));
29825 return vertices>
'x';
29829 template<
typename tf>
29831 const float x0,
const float y0,
const float z0,
29832 const float x1,
const float y1,
const float z1,
29833 const int dx=32,
const int dy=32,
const int dz=32) {
29834 const _functor3d_expr func(expression);
29835 return isosurface3d(primitives,func,isovalue,x0,y0,z0,x1,y1,z1,dx,dy,dz);
29838 template<
typename t>
29839 static int _isosurface3d_indice(
const unsigned int edge,
const CImg<t>& indices1,
const CImg<t>& indices2,
29840 const unsigned int x,
const unsigned int y,
29841 const unsigned int nx,
const unsigned int ny) {
29843 case 0 :
return indices1(x,y,0);
29844 case 1 :
return indices1(nx,y,1);
29845 case 2 :
return indices1(x,ny,0);
29846 case 3 :
return indices1(x,y,1);
29847 case 4 :
return indices2(x,y,0);
29848 case 5 :
return indices2(nx,y,1);
29849 case 6 :
return indices2(x,ny,0);
29850 case 7 :
return indices2(x,y,1);
29851 case 8 :
return indices1(x,y,2);
29852 case 9 :
return indices1(nx,y,2);
29853 case 10 :
return indices1(nx,ny,2);
29854 case 11 :
return indices1(x,ny,2);
29863 float operator()(
const float x,
const float y)
const {
29864 return (
float)ref((
int)x,(
int)y);
29871 float operator()(
const float x,
const float y)
const {
29872 return (
float)ref._linear_atXY(x,y);
29880 float operator()(
const float x,
const float y)
const {
29881 return (
float)(*mp)(x,y,0,0);
29888 float operator()(
const float x,
const float y,
const float z)
const {
29889 return (
float)ref((
int)x,(
int)y,(
int)z);
29896 float operator()(
const float x,
const float y,
const float z)
const {
29897 return (
float)ref._linear_atXYZ(x,y,z);
29905 float operator()(
const float x,
const float y,
const float z)
const {
29906 return (
float)(*mp)(x,y,z,0);
29913 float operator()(
const float x,
const float y,
const float z,
const unsigned int c)
const {
29914 return (
float)ref((
int)x,(
int)y,(
int)z,c);
29934 template<
typename tf>
29936 const float size_x=200,
const float size_y=100,
const float size_z=100) {
29937 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);
29939 0.,size_x,size_x, 0., 0.,size_x,size_x, 0.,
29940 0., 0.,size_y,size_y, 0., 0.,size_y,size_y,
29941 0., 0., 0., 0.,size_z,size_z,size_z,size_z);
29960 template<
typename tf>
29962 const float radius=50,
const float size_z=100,
const unsigned int subdivisions=24) {
29968 for (
float delta = 360.0f/subdivisions, angle = 0; angle<360; angle+=delta) {
29969 const float a = (float)(angle*
cimg::PI/180);
29970 CImg<floatT>::vector((
float)(radius*std::cos(a)),(
float)(radius*std::sin(a)),0).move_to(vertices);
29972 const unsigned int nbr = vertices._width - 2;
29973 for (
unsigned int p = 0; p<nbr; ++p) {
29974 const unsigned int curr = 2 + p, next = 2 + ((p+1)%nbr);
29978 return vertices>
'x';
29997 template<
typename tf>
29999 const float radius=50,
const float size_z=100,
const unsigned int subdivisions=24) {
30005 for (
float delta = 360.0f/subdivisions, angle = 0; angle<360; angle+=delta) {
30006 const float a = (float)(angle*
cimg::PI/180);
30007 CImg<floatT>::vector((
float)(radius*std::cos(a)),(
float)(radius*std::sin(a)),0.0f).move_to(vertices);
30008 CImg<floatT>::vector((
float)(radius*std::cos(a)),(
float)(radius*std::sin(a)),size_z).move_to(vertices);
30010 const unsigned int nbr = (vertices._width - 2)/2;
30011 for (
unsigned int p = 0; p<nbr; ++p) {
30012 const unsigned int curr = 2+2*p, next = 2+(2*((p+1)%nbr));
30017 return vertices>
'x';
30037 template<
typename tf>
30039 const float radius1=100,
const float radius2=30,
30040 const unsigned int subdivisions1=24,
const unsigned int subdivisions2=12) {
30042 if (!subdivisions1 || !subdivisions2)
return CImg<floatT>();
30044 for (
unsigned int v = 0; v<subdivisions1; ++v) {
30046 beta = (float)(v*2*
cimg::PI/subdivisions1),
30047 xc = radius1*(float)std::cos(beta),
30048 yc = radius1*(float)std::sin(beta);
30049 for (
unsigned int u = 0; u<subdivisions2; ++u) {
30051 alpha = (float)(u*2*
cimg::PI/subdivisions2),
30052 x = xc + radius2*(float)(std::cos(alpha)*std::cos(beta)),
30053 y = yc + radius2*(
float)(std::cos(alpha)*std::sin(beta)),
30054 z = radius2*(
float)std::sin(alpha);
30058 for (
unsigned int vv = 0; vv<subdivisions1; ++vv) {
30059 const unsigned int nv = (vv+1)%subdivisions1;
30060 for (
unsigned int uu = 0; uu<subdivisions2; ++uu) {
30061 const unsigned int nu = (uu+1)%subdivisions2, svv = subdivisions2*vv, snv = subdivisions2*nv;
30065 return vertices>
'x';
30085 template<
typename tf>
30087 const float size_x=100,
const float size_y=100,
30088 const unsigned int subdivisions_x=10,
const unsigned int subdivisions_y=10) {
30090 if (!subdivisions_x || !subdivisions_y)
return CImg<floatT>();
30092 const unsigned int w = subdivisions_x + 1, h = subdivisions_y + 1;
30093 const float fx = (float)size_x/w, fy = (
float)size_y/h;
30094 for (
unsigned int y = 0; y<h; ++y)
for (
unsigned int x = 0; x<w; ++x)
30096 for (
unsigned int y = 0; y<subdivisions_y; ++y)
for (
unsigned int x = 0; x<subdivisions_x; ++x) {
30097 const int off1 = x+y*w, off2 = x+1+y*w, off3 = x+1+(y+1)*w, off4 = x+(y+1)*w;
30100 return vertices>
'x';
30118 template<
typename tf>
30120 const float radius=50,
const unsigned int subdivisions=3) {
30124 const double tmp = (1+std::sqrt(5.0f))/2, a = 1.0/std::sqrt(1+tmp*tmp), b = tmp*a;
30125 CImgList<floatT> vertices(12,1,3,1,1, b,a,0.0, -b,a,0.0, -b,-a,0.0, b,-a,0.0, a,0.0,b, a,0.0,-b,
30126 -a,0.0,-b, -a,0.0,b, 0.0,b,a, 0.0,-b,a, 0.0,-b,-a, 0.0,b,-a);
30127 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,
30128 8,0,11, 8,11,1, 9,10,3, 9,2,10, 8,4,0, 11,0,5, 4,9,3,
30129 5,3,10, 7,8,1, 6,1,11, 7,2,9, 6,10,2);
30131 float he = (float)a;
30134 for (
unsigned int i = 0; i<subdivisions; ++i) {
30135 const unsigned int L = primitives._width;
30137 const float he2 = he*he;
30138 for (
unsigned int l = 0; l<L; ++l) {
30140 p0 = (
unsigned int)primitives(0,0), p1 = (
unsigned int)primitives(0,1), p2 = (
unsigned int)primitives(0,2);
30142 x0 = vertices(p0,0), y0 = vertices(p0,1), z0 = vertices(p0,2),
30143 x1 = vertices(p1,0), y1 = vertices(p1,1), z1 = vertices(p1,2),
30144 x2 = vertices(p2,0), y2 = vertices(p2,1), z2 = vertices(p2,2),
30145 tnx0 = (x0+x1)/2, tny0 = (y0+y1)/2, tnz0 = (z0+z1)/2, nn0 = (
float)std::sqrt(tnx0*tnx0+tny0*tny0+tnz0*tnz0),
30146 tnx1 = (x0+x2)/2, tny1 = (y0+y2)/2, tnz1 = (z0+z2)/2, nn1 = (
float)std::sqrt(tnx1*tnx1+tny1*tny1+tnz1*tnz1),
30147 tnx2 = (x1+x2)/2, tny2 = (y1+y2)/2, tnz2 = (z1+z2)/2, nn2 = (
float)std::sqrt(tnx2*tnx2+tny2*tny2+tnz2*tnz2),
30148 nx0 = tnx0/nn0, ny0 = tny0/nn0, nz0 = tnz0/nn0,
30149 nx1 = tnx1/nn1, ny1 = tny1/nn1, nz1 = tnz1/nn1,
30150 nx2 = tnx2/nn2, ny2 = tny2/nn2, nz2 = tnz2/nn2;
30151 int i0 = -1, i1 = -1, i2 = -1;
30152 cimglist_for(vertices,p) {
30153 const float x = (float)vertices(p,0), y = (float)vertices(p,1), z = (float)vertices(p,2);
30168 return (vertices>
'x')*=radius;
30187 template<
typename tf,
typename t>
30189 const CImg<t>&
tensor,
const unsigned int subdivisions=3) {
30193 tensor.symmetric_eigen(S,V);
30194 const float orient =
30195 (V(0,1)*V(1,2) - V(0,2)*V(1,1))*V(2,0) +
30196 (V(0,2)*V(1,0) - V(0,0)*V(1,2))*V(2,1) +
30197 (V(0,0)*V(1,1) - V(0,1)*V(1,0))*V(2,2);
30198 if (orient<0) { V(2,0) = -V(2,0); V(2,1) = -V(2,1); V(2,2) = -V(2,2); }
30199 const float l0 = S[0], l1 = S[1], l2 = S[2];
30214 template<
typename tp,
typename tc,
typename to>
30217 const to& opacities,
30218 const bool full_check=
true) {
30223 template<
typename tp,
typename tc>
30226 const bool full_check=
true) {
30231 template<
typename tp>
30233 const bool full_check=
true) {
30243 template<
typename tp,
typename tc,
typename to>
30246 const to& opacities,
30247 const bool full_check=
true)
const {
30248 char error_message[1024] = { 0 };
30249 if (!
is_object3d(primitives,colors,opacities,full_check,error_message))
30251 "object3dtoCImg3d(): Invalid specified 3d object (%u,%u) (%s).",
30252 cimg_instance,_width,primitives._width,error_message);
30253 CImg<floatT> res(1,_size_object3dtoCImg3d(primitives,colors,opacities));
30254 float *ptrd = res._data;
30257 *(ptrd++) =
'C' + 0.5f; *(ptrd++) =
'I' + 0.5f; *(ptrd++) =
'm' + 0.5f;
30258 *(ptrd++) =
'g' + 0.5f; *(ptrd++) =
'3' + 0.5f; *(ptrd++) =
'd' + 0.5f;
30261 *(ptrd++) = cimg::uint2float(_width);
30262 *(ptrd++) = cimg::uint2float(primitives._width);
30265 if (
is_empty() || !primitives)
return res;
30266 const T *ptrx =
data(0,0), *ptry =
data(0,1), *ptrz =
data(0,2);
30267 cimg_forX(*
this,p) {
30268 *(ptrd++) = (
float)*(ptrx++);
30269 *(ptrd++) = (
float)*(ptry++);
30270 *(ptrd++) = (
float)*(ptrz++);
30274 cimglist_for(primitives,p) {
30275 *(ptrd++) = (
float)primitives[p].
size();
30276 const tp *ptrp = primitives[p]._data;
30277 cimg_foroff(primitives[p],i) *(ptrd++) = cimg::uint2float((
unsigned int)*(ptrp++));
30281 const unsigned int csiz =
cimg::min(colors._width,primitives._width);
30282 for (
int c = 0; c<(int)csiz; ++c) {
30283 const CImg<tc>& color = colors[c];
30284 const tc *ptrc = color._data;
30285 if (color.size()==3) { *(ptrd++) = (
float)*(ptrc++); *(ptrd++) = (
float)*(ptrc++); *(ptrd++) = (
float)*ptrc; }
30287 *(ptrd++) = -128.0f;
30288 int shared_ind = -1;
30289 if (color.is_shared())
for (
int i = 0; i<c; ++i)
if (ptrc==colors[i]._data) { shared_ind = i;
break; }
30290 if (shared_ind<0) {
30291 *(ptrd++) = (
float)color._width;
30292 *(ptrd++) = (
float)color._height;
30293 *(ptrd++) = (
float)color._spectrum;
30294 cimg_foroff(color,l) *(ptrd++) = (
float)*(ptrc++);
30296 *(ptrd++) = (
float)shared_ind;
30302 const int csiz2 = primitives._width - colors._width;
30303 for (
int c = 0; c<csiz2; ++c) { *(ptrd++) = 200.0f; *(ptrd++) = 200.0f; *(ptrd++) = 200.0f; }
30306 ptrd = _object3dtoCImg3d(opacities,ptrd);
30307 const float *ptre = res.
end();
30308 while (ptrd<ptre) *(ptrd++) = 1.0f;
30312 template<
typename to>
30313 float* _object3dtoCImg3d(
const CImgList<to>& opacities,
float *ptrd)
const {
30314 cimglist_for(opacities,o) {
30315 const CImg<to>& opacity = opacities[o];
30316 const to *ptro = opacity._data;
30317 if (opacity.size()==1) *(ptrd++) = (float)*ptro;
30319 *(ptrd++) = -128.0f;
30320 int shared_ind = -1;
30321 if (opacity.is_shared())
for (
int i = 0; i<o; ++i)
if (ptro==opacities[i]._data) { shared_ind = i;
break; }
30322 if (shared_ind<0) {
30323 *(ptrd++) = (
float)opacity._width;
30324 *(ptrd++) = (
float)opacity._height;
30325 *(ptrd++) = (
float)opacity._spectrum;
30326 cimg_foroff(opacity,l) *(ptrd++) = (
float)*(ptro++);
30328 *(ptrd++) = (
float)shared_ind;
30337 template<
typename to>
30338 float* _object3dtoCImg3d(
const CImg<to>& opacities,
float *ptrd)
const {
30339 const to *ptro = opacities._data;
30340 cimg_foroff(opacities,o) *(ptrd++) = (
float)*(ptro++);
30344 template<
typename tp,
typename tc,
typename to>
30345 unsigned int _size_object3dtoCImg3d(
const CImgList<tp>& primitives,
30346 const CImgList<tc>& colors,
30347 const CImgList<to>& opacities)
const {
30348 unsigned int siz = 8 + 3*
width();
30349 cimglist_for(primitives,p) siz+=primitives[p].size() + 1;
30350 for (
int c = cimg::
min(primitives._width,colors._width)-1; c>=0; --c) {
30352 else {
const unsigned int csiz = colors[c].size(); siz+=(csiz!=3)?4+csiz:3; }
30354 if (colors._width<primitives._width) siz+=3*(primitives._width - colors._width);
30355 cimglist_for(opacities,o) {
30357 else {
const unsigned int osiz = opacities[o].size(); siz+=(osiz!=1)?4+osiz:1; }
30359 siz+=primitives._width - opacities._width;
30363 template<
typename tp,
typename tc,
typename to>
30364 unsigned int _size_object3dtoCImg3d(
const CImgList<tp>& primitives,
30365 const CImgList<tc>& colors,
30366 const CImg<to>& opacities)
const {
30367 unsigned int siz = 8 + 3*
width();
30368 cimglist_for(primitives,p) siz+=primitives[p].size() + 1;
30369 for (
int c = cimg::
min(primitives._width,colors._width)-1; c>=0; --c) {
30370 const unsigned int csiz = colors[c].size(); siz+=(csiz!=3)?4+csiz:3;
30372 if (colors._width<primitives._width) siz+=3*(primitives._width - colors._width);
30373 siz+=primitives.size();
30379 template<
typename tp,
typename tc>
30382 const bool full_check=
true)
const {
30388 template<
typename tp>
30390 const bool full_check=
true)
const {
30399 cimglist_for(primitives,p) primitives(p,0) = p;
30410 template<
typename tp,
typename tc,
typename to>
30414 const bool full_check=
true) {
30419 template<
typename tp,
typename tc,
typename to>
30423 const bool full_check=
true)
const {
30424 char error_message[1024] = { 0 };
30425 if (!
is_CImg3d(full_check,error_message))
30427 "CImg3dtoobject3d(): image instance is not a CImg3d (%s).",
30428 cimg_instance,error_message);
30429 const T *ptrs = _data + 6;
30431 nb_points = cimg::float2uint((
float)*(ptrs++)),
30432 nb_primitives = cimg::float2uint((
float)*(ptrs++));
30435 primitives.
assign(nb_primitives);
30436 cimglist_for(primitives,p) {
30437 const unsigned int nb_inds = (
unsigned int)*(ptrs++);
30438 primitives[p].
assign(1,nb_inds);
30439 tp *ptrp = primitives[p]._data;
30440 for (
unsigned int i = 0; i<nb_inds; ++i) *(ptrp++) = (tp)cimg::float2uint((
float)*(ptrs++));
30442 colors.
assign(nb_primitives);
30443 cimglist_for(colors,c) {
30444 if (*ptrs==(T)-128) {
30446 const unsigned int w = (
unsigned int)*(ptrs++), h = (
unsigned int)*(ptrs++), s = (
unsigned int)*(ptrs++);
30447 if (!h && !s) colors[c].
assign(colors[w],
true);
30448 else { colors[c].
assign(ptrs,w,h,1,s,
false); ptrs+=w*h*s; }
30449 }
else { colors[c].
assign(ptrs,1,1,1,3,
false); ptrs+=3; }
30451 opacities.
assign(nb_primitives);
30452 cimglist_for(opacities,o) {
30453 if (*ptrs==(T)-128) {
30455 const unsigned int w = (
unsigned int)*(ptrs++), h = (
unsigned int)*(ptrs++), s = (
unsigned int)*(ptrs++);
30456 if (!h && !s) opacities[o].
assign(opacities[w],
true);
30457 else { opacities[o].
assign(ptrs,w,h,1,s,
false); ptrs+=w*h*s; }
30458 }
else opacities[o].
assign(1,1,1,1,*(ptrs++));
30470 #define cimg_init_scanline(color,opacity) \
30471 const float _sc_nopacity = cimg::abs((float)opacity), _sc_copacity = 1 - cimg::max((float)opacity,0); \
30472 const unsigned long _sc_whd = (unsigned long)_width*_height*_depth
30474 #define cimg_draw_scanline(x0,x1,y,color,opacity,brightness) \
30475 _draw_scanline(x0,x1,y,color,opacity,brightness,_sc_nopacity,_sc_copacity,_sc_whd)
30480 template<
typename tc>
30481 CImg<T>& _draw_scanline(
const int x0,
const int x1,
const int y,
30482 const tc *
const color,
const float opacity,
30483 const float brightness,
30484 const float nopacity,
const float copacity,
const unsigned long whd) {
30486 const int nx0 = x0>0?x0:0, nx1 = x1<
width()?x1:
width()-1, dx = nx1 - nx0;
30488 const tc *col = color;
30489 const unsigned long off = whd - dx - 1;
30490 T *ptrd =
data(nx0,y);
30492 if (brightness==1) {
30493 if (
sizeof(T)!=1) cimg_forC(*
this,c) {
30494 const T val = (T)*(col++);
30495 for (
int x = dx; x>=0; --x) *(ptrd++) = val;
30497 }
else cimg_forC(*
this,c) {
30498 const T val = (T)*(col++);
30499 std::memset(ptrd,(
int)val,dx+1);
30502 }
else if (brightness<1) {
30503 if (
sizeof(T)!=1) cimg_forC(*
this,c) {
30504 const T val = (T)(*(col++)*brightness);
30505 for (
int x = dx; x>=0; --x) *(ptrd++) = val;
30507 }
else cimg_forC(*
this,c) {
30508 const T val = (T)(*(col++)*brightness);
30509 std::memset(ptrd,(
int)val,dx+1);
30513 if (
sizeof(T)!=1) cimg_forC(*
this,c) {
30514 const T val = (T)((2-brightness)**(col++) + (brightness-1)*maxval);
30515 for (
int x = dx; x>=0; --x) *(ptrd++) = val;
30517 }
else cimg_forC(*
this,c) {
30518 const T val = (T)((2-brightness)**(col++) + (brightness-1)*maxval);
30519 std::memset(ptrd,(
int)val,dx+1);
30524 if (brightness==1) {
30525 cimg_forC(*
this,c) {
30526 const T val = (T)*(col++);
30527 for (
int x = dx; x>=0; --x) { *ptrd = (T)(val*nopacity + *ptrd*copacity); ++ptrd; }
30530 }
else if (brightness<=1) {
30531 cimg_forC(*
this,c) {
30532 const T val = (T)(*(col++)*brightness);
30533 for (
int x = dx; x>=0; --x) { *ptrd = (T)(val*nopacity + *ptrd*copacity); ++ptrd; }
30537 cimg_forC(*
this,c) {
30538 const T val = (T)((2-brightness)**(col++) + (brightness-1)*maxval);
30539 for (
int x = dx; x>=0; --x) { *ptrd = (T)(val*nopacity + *ptrd*copacity); ++ptrd; }
30564 template<
typename tc>
30566 const tc *
const color,
const float opacity=1) {
30570 "draw_point(): Specified color is (null).",
30573 const unsigned long whd = (
unsigned long)_width*_height*_depth;
30575 T *ptrd =
data(x0,y0,z0,0);
30576 const tc *col = color;
30577 if (opacity>=1) cimg_forC(*
this,c) { *ptrd = (T)*(col++); ptrd+=whd; }
30578 else cimg_forC(*
this,c) { *ptrd = (T)(*(col++)*nopacity + *ptrd*copacity); ptrd+=whd; }
30584 template<
typename tc>
30586 const tc *
const color,
const float opacity=1) {
30596 template<
typename t,
typename tc>
30598 const tc *
const color,
const float opacity=1) {
30599 if (
is_empty() || !points)
return *
this;
30600 switch (points._height) {
30603 "draw_point(): Invalid specified point set (%u,%u,%u,%u,%p).",
30605 points._width,points._height,points._depth,points._spectrum,points._data);
30607 cimg_forX(points,i)
draw_point((
int)points(i,0),(
int)points(i,1),color,opacity);
30610 cimg_forX(points,i)
draw_point((
int)points(i,0),(
int)points(i,1),(
int)points(i,2),color,opacity);
30636 template<
typename tc>
30638 const int x1,
const int y1,
30639 const tc *
const color,
const float opacity=1,
30640 const unsigned int pattern=~0U,
const bool init_hatch=
true) {
30644 "draw_line(): Specified color is (null).",
30646 static unsigned int hatch = ~0U - (~0U>>1);
30647 if (init_hatch) hatch = ~0U - (~0U>>1);
30648 const bool xdir = x0<x1, ydir = y0<y1;
30650 nx0 = x0, nx1 = x1, ny0 = y0, ny1 = y1,
30651 &xleft = xdir?nx0:nx1, &yleft = xdir?ny0:ny1,
30652 &xright = xdir?nx1:nx0, &yright = xdir?ny1:ny0,
30653 &xup = ydir?nx0:nx1, &yup = ydir?ny0:ny1,
30654 &xdown = ydir?nx1:nx0, &ydown = ydir?ny1:ny0;
30655 if (xright<0 || xleft>=
width())
return *
this;
30656 if (xleft<0) { yleft-=(int)((
float)xleft*((float)yright - yleft)/((float)xright - xleft)); xleft = 0; }
30657 if (xright>=
width()) {
30658 yright-=(int)(((
float)xright -
width())*((
float)yright - yleft)/((
float)xright - xleft));
30659 xright =
width() - 1;
30661 if (ydown<0 || yup>=
height())
return *
this;
30662 if (yup<0) { xup-=(int)((
float)yup*((float)xdown - xup)/((float)ydown - yup)); yup = 0; }
30664 xdown-=(int)(((
float)ydown -
height())*((
float)xdown - xup)/((
float)ydown - yup));
30667 T *ptrd0 =
data(nx0,ny0);
30668 int dx = xright - xleft, dy = ydown - yup;
30669 const bool steep = dy>dx;
30670 if (steep)
cimg::swap(nx0,ny0,nx1,ny1,dx,dy);
30672 offx = (nx0<nx1?1:-1)*(steep?
width():1),
30673 offy = (ny0<ny1?1:-1)*(steep?1:
width());
30674 const unsigned long wh = (
unsigned long)_width*_height;
30676 if (~pattern)
for (
int error = dx>>1, x = 0; x<=dx; ++x) {
30677 if (pattern&hatch) {
30678 T *ptrd = ptrd0;
const tc* col = color;
30679 cimg_forC(*
this,c) { *ptrd = (T)*(col++); ptrd+=wh; }
30681 hatch>>=1;
if (!hatch) hatch = ~0U - (~0U>>1);
30683 if ((error-=dy)<0) { ptrd0+=offy; error+=dx; }
30684 }
else for (
int error = dx>>1, x = 0; x<=dx; ++x) {
30685 T *ptrd = ptrd0;
const tc* col = color; cimg_forC(*
this,c) { *ptrd = (T)*(col++); ptrd+=wh; }
30687 if ((error-=dy)<0) { ptrd0+=offy; error+=dx; }
30691 if (~pattern)
for (
int error = dx>>1, x = 0; x<=dx; ++x) {
30692 if (pattern&hatch) {
30693 T *ptrd = ptrd0;
const tc* col = color;
30694 cimg_forC(*
this,c) { *ptrd = (T)(nopacity**(col++) + *ptrd*copacity); ptrd+=wh; }
30696 hatch>>=1;
if (!hatch) hatch = ~0U - (~0U>>1);
30698 if ((error-=dy)<0) { ptrd0+=offy; error+=dx; }
30699 }
else for (
int error = dx>>1, x = 0; x<=dx; ++x) {
30700 T *ptrd = ptrd0;
const tc* col = color;
30701 cimg_forC(*
this,c) { *ptrd = (T)(nopacity**(col++) + *ptrd*copacity); ptrd+=wh; }
30703 if ((error-=dy)<0) { ptrd0+=offy; error+=dx; }
30723 template<
typename tz,
typename tc>
30725 const int x0,
const int y0,
const float z0,
30726 const int x1,
const int y1,
const float z1,
30727 const tc *
const color,
const float opacity=1,
30728 const unsigned int pattern=~0U,
const bool init_hatch=
true) {
30729 typedef typename cimg::superset<tz,float>::type tzfloat;
30730 if (
is_empty() || z0<=0 || z1<=0)
return *
this;
30733 "draw_line(): Specified color is (null).",
30737 "draw_line(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have "
30738 "different dimensions.",
30740 zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data);
30741 static unsigned int hatch = ~0U - (~0U>>1);
30742 if (init_hatch) hatch = ~0U - (~0U>>1);
30743 const bool xdir = x0<x1, ydir = y0<y1;
30745 nx0 = x0, nx1 = x1, ny0 = y0, ny1 = y1,
30746 &xleft = xdir?nx0:nx1, &yleft = xdir?ny0:ny1,
30747 &xright = xdir?nx1:nx0, &yright = xdir?ny1:ny0,
30748 &xup = ydir?nx0:nx1, &yup = ydir?ny0:ny1,
30749 &xdown = ydir?nx1:nx0, &ydown = ydir?ny1:ny0;
30751 Z0 = 1/(tzfloat)z0, Z1 = 1/(tzfloat)z1, nz0 = Z0, nz1 = Z1, dz = Z1 - Z0,
30752 &zleft = xdir?nz0:nz1,
30753 &zright = xdir?nz1:nz0,
30754 &zup = ydir?nz0:nz1,
30755 &zdown = ydir?nz1:nz0;
30756 if (xright<0 || xleft>=
width())
return *
this;
30758 const float D = (float)xright - xleft;
30759 yleft-=(int)((
float)xleft*((float)yright - yleft)/D);
30760 zleft-=(tzfloat)xleft*(zright - zleft)/D;
30763 if (xright>=
width()) {
30764 const float d = (float)xright -
width(), D = (float)xright - xleft;
30765 yright-=(int)(d*((
float)yright - yleft)/D);
30766 zright-=(tzfloat)d*(zright - zleft)/D;
30767 xright =
width() - 1;
30769 if (ydown<0 || yup>=
height())
return *
this;
30771 const float D = (float)ydown - yup;
30772 xup-=(int)((
float)yup*((float)xdown - xup)/D);
30773 zup-=(tzfloat)yup*(zdown - zup)/D;
30777 const float d = (float)ydown -
height(), D = (float)ydown - yup;
30778 xdown-=(int)(d*((
float)xdown - xup)/D);
30779 zdown-=(tzfloat)d*(zdown - zup)/D;
30782 T *ptrd0 =
data(nx0,ny0);
30783 tz *ptrz = zbuffer.data(nx0,ny0);
30784 int dx = xright - xleft, dy = ydown - yup;
30785 const bool steep = dy>dx;
30786 if (steep)
cimg::swap(nx0,ny0,nx1,ny1,dx,dy);
30788 offx = (nx0<nx1?1:-1)*(steep?
width():1),
30789 offy = (ny0<ny1?1:-1)*(steep?1:
width());
30790 const unsigned long wh = (
unsigned long)_width*_height,
30793 if (~pattern)
for (
int error = dx>>1, x = 0; x<=dx; ++x) {
30794 const tzfloat z = Z0 + x*dz/ndx;
30795 if (z>=(tzfloat)*ptrz && pattern&hatch) {
30797 T *ptrd = ptrd0;
const tc *col = color;
30798 cimg_forC(*
this,c) { *ptrd = (T)*(col++); ptrd+=wh; }
30800 hatch>>=1;
if (!hatch) hatch = ~0U - (~0U>>1);
30801 ptrd0+=offx; ptrz+=offx;
30802 if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; }
30803 }
else for (
int error = dx>>1, x = 0; x<=dx; ++x) {
30804 const tzfloat z = Z0 + x*dz/ndx;
30805 if (z>=(tzfloat)*ptrz) {
30807 T *ptrd = ptrd0;
const tc *col = color;
30808 cimg_forC(*
this,c) { *ptrd = (T)*(col++); ptrd+=wh; }
30810 ptrd0+=offx; ptrz+=offx;
30811 if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; }
30815 if (~pattern)
for (
int error = dx>>1, x = 0; x<=dx; ++x) {
30816 const tzfloat z = Z0 + x*dz/ndx;
30817 if (z>=(tzfloat)*ptrz && pattern&hatch) {
30819 T *ptrd = ptrd0;
const tc *col = color;
30820 cimg_forC(*
this,c) { *ptrd = (T)(nopacity**(col++) + *ptrd*copacity); ptrd+=wh; }
30822 hatch>>=1;
if (!hatch) hatch = ~0U - (~0U>>1);
30823 ptrd0+=offx; ptrz+=offx;
30824 if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; }
30825 }
else for (
int error = dx>>1, x = 0; x<=dx; ++x) {
30826 const tzfloat z = Z0 + x*dz/ndx;
30827 if (z>=(tzfloat)*ptrz) {
30829 T *ptrd = ptrd0;
const tc *col = color;
30830 cimg_forC(*
this,c) { *ptrd = (T)(nopacity**(col++) + *ptrd*copacity); ptrd+=wh; }
30832 ptrd0+=offx; ptrz+=offx;
30833 if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; }
30852 template<
typename tc>
30854 const int x1,
const int y1,
const int z1,
30855 const tc *
const color,
const float opacity=1,
30856 const unsigned int pattern=~0U,
const bool init_hatch=
true) {
30860 "draw_line(): Specified color is (null).",
30862 static unsigned int hatch = ~0U - (~0U>>1);
30863 if (init_hatch) hatch = ~0U - (~0U>>1);
30864 int nx0 = x0, ny0 = y0, nz0 = z0, nx1 = x1, ny1 = y1, nz1 = z1;
30865 if (nx0>nx1)
cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1);
30866 if (nx1<0 || nx0>=
width())
return *
this;
30868 const float D = 1.0f + nx1 - nx0;
30869 ny0-=(int)((
float)nx0*(1.0f + ny1 - ny0)/D);
30870 nz0-=(int)((
float)nx0*(1.0f + nz1 - nz0)/D);
30873 if (nx1>=
width()) {
30874 const float d = (float)nx1 -
width(), D = 1.0f + nx1 - nx0;
30875 ny1+=(int)(d*(1.0f + ny0 - ny1)/D);
30876 nz1+=(int)(d*(1.0f + nz0 - nz1)/D);
30879 if (ny0>ny1)
cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1);
30880 if (ny1<0 || ny0>=
height())
return *
this;
30882 const float D = 1.0f + ny1 - ny0;
30883 nx0-=(int)((
float)ny0*(1.0f + nx1 - nx0)/D);
30884 nz0-=(int)((
float)ny0*(1.0f + nz1 - nz0)/D);
30888 const float d = (float)ny1 -
height(), D = 1.0f + ny1 - ny0;
30889 nx1+=(int)(d*(1.0f + nx0 - nx1)/D);
30890 nz1+=(int)(d*(1.0f + nz0 - nz1)/D);
30893 if (nz0>nz1)
cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1);
30894 if (nz1<0 || nz0>=
depth())
return *
this;
30896 const float D = 1.0f + nz1 - nz0;
30897 nx0-=(int)((
float)nz0*(1.0f + nx1 - nx0)/D);
30898 ny0-=(int)((
float)nz0*(1.0f + ny1 - ny0)/D);
30901 if (nz1>=
depth()) {
30902 const float d = (float)nz1 -
depth(), D = 1.0f + nz1 - nz0;
30903 nx1+=(int)(d*(1.0f + nx0 - nx1)/D);
30904 ny1+=(int)(d*(1.0f + ny0 - ny1)/D);
30908 const unsigned long whd = (
unsigned long)_width*_height*_depth;
30909 const float px = (nx1 - nx0)/(
float)dmax, py = (ny1 - ny0)/(
float)dmax, pz = (nz1 - nz0)/(
float)dmax;
30910 float x = (float)nx0, y = (
float)ny0, z = (float)nz0;
30911 if (opacity>=1)
for (
unsigned int t = 0; t<=dmax; ++t) {
30912 if (!(~pattern) || (~pattern && pattern&hatch)) {
30913 T* ptrd =
data((
unsigned int)x,(
unsigned int)y,(
unsigned int)z);
30914 const tc *col = color; cimg_forC(*
this,c) { *ptrd = (T)*(col++); ptrd+=whd; }
30916 x+=px; y+=py; z+=pz;
if (pattern) { hatch>>=1;
if (!hatch) hatch = ~0U - (~0U>>1); }
30919 for (
unsigned int t = 0; t<=dmax; ++t) {
30920 if (!(~pattern) || (~pattern && pattern&hatch)) {
30921 T* ptrd =
data((
unsigned int)x,(
unsigned int)y,(
unsigned int)z);
30922 const tc *col = color; cimg_forC(*
this,c) { *ptrd = (T)(*(col++)*nopacity + *ptrd*copacity); ptrd+=whd; }
30924 x+=px; y+=py; z+=pz;
if (pattern) { hatch>>=1;
if (!hatch) hatch = ~0U - (~0U>>1); }
30953 template<
typename tc>
30955 const int x1,
const int y1,
30957 const int tx0,
const int ty0,
30958 const int tx1,
const int ty1,
30959 const float opacity=1,
30960 const unsigned int pattern=~0U,
const bool init_hatch=
true) {
30962 if (texture._depth>1 || texture._spectrum<_spectrum)
30964 "draw_line(): Invalid specified texture (%u,%u,%u,%u,%p).",
30966 texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
30967 if (
is_overlapped(texture))
return draw_line(x0,y0,x1,y1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch);
30968 static unsigned int hatch = ~0U - (~0U>>1);
30969 if (init_hatch) hatch = ~0U - (~0U>>1);
30970 const bool xdir = x0<x1, ydir = y0<y1;
30972 dtx = tx1-tx0, dty = ty1-ty0,
30973 nx0 = x0, nx1 = x1, ny0 = y0, ny1 = y1,
30974 tnx0 = tx0, tnx1 = tx1, tny0 = ty0, tny1 = ty1,
30975 &xleft = xdir?nx0:nx1, &yleft = xdir?ny0:ny1, &xright = xdir?nx1:nx0, &yright = xdir?ny1:ny0,
30976 &txleft = xdir?tnx0:tnx1, &tyleft = xdir?tny0:tny1, &txright = xdir?tnx1:tnx0, &tyright = xdir?tny1:tny0,
30977 &xup = ydir?nx0:nx1, &yup = ydir?ny0:ny1, &xdown = ydir?nx1:nx0, &ydown = ydir?ny1:ny0,
30978 &txup = ydir?tnx0:tnx1, &tyup = ydir?tny0:tny1, &txdown = ydir?tnx1:tnx0, &tydown = ydir?tny1:tny0;
30979 if (xright<0 || xleft>=
width())
return *
this;
30981 const float D = (float)xright - xleft;
30982 yleft-=(int)((
float)xleft*((float)yright - yleft)/D);
30983 txleft-=(int)((
float)xleft*((float)txright - txleft)/D);
30984 tyleft-=(int)((
float)xleft*((float)tyright - tyleft)/D);
30987 if (xright>=
width()) {
30988 const float d = (float)xright -
width(), D = (float)xright - xleft;
30989 yright-=(int)(d*((
float)yright - yleft)/D);
30990 txright-=(int)(d*((
float)txright - txleft)/D);
30991 tyright-=(int)(d*((
float)tyright - tyleft)/D);
30992 xright =
width() - 1;
30994 if (ydown<0 || yup>=
height())
return *
this;
30996 const float D = (float)ydown - yup;
30997 xup-=(int)((
float)yup*((float)xdown - xup)/D);
30998 txup-=(int)((
float)yup*((float)txdown - txup)/D);
30999 tyup-=(int)((
float)yup*((float)tydown - tyup)/D);
31003 const float d = (float)ydown -
height(), D = (float)ydown - yup;
31004 xdown-=(int)(d*((
float)xdown - xup)/D);
31005 txdown-=(int)(d*((
float)txdown - txup)/D);
31006 tydown-=(int)(d*((
float)tydown - tyup)/D);
31009 T *ptrd0 =
data(nx0,ny0);
31010 int dx = xright - xleft, dy = ydown - yup;
31011 const bool steep = dy>dx;
31012 if (steep)
cimg::swap(nx0,ny0,nx1,ny1,dx,dy);
31014 offx = (nx0<nx1?1:-1)*(steep?
width():1),
31015 offy = (ny0<ny1?1:-1)*(steep?1:
width()),
31017 const unsigned long wh = (
unsigned long)_width*_height;
31020 if (~pattern)
for (
int error = dx>>1, x = 0; x<=dx; ++x) {
31021 if (pattern&hatch) {
31023 const int tx = tx0 + x*dtx/ndx, ty = ty0 + x*dty/ndx;
31024 cimg_forC(*
this,c) { *ptrd = (T)texture(tx,ty,0,c); ptrd+=wh; }
31026 hatch>>=1;
if (!hatch) hatch = ~0U - (~0U>>1);
31028 if ((error-=dy)<0) { ptrd0+=offy; error+=dx; }
31029 }
else for (
int error = dx>>1, x = 0; x<=dx; ++x) {
31031 const int tx = tx0 + x*dtx/ndx, ty = ty0 + x*dty/ndx;
31032 cimg_forC(*
this,c) { *ptrd = (T)texture(tx,ty,0,c); ptrd+=wh; }
31034 if ((error-=dy)<0) { ptrd0+=offy; error+=dx; }
31038 if (~pattern)
for (
int error = dx>>1, x = 0; x<=dx; ++x) {
31040 if (pattern&hatch) {
31041 const int tx = tx0 + x*dtx/ndx, ty = ty0 + x*dty/ndx;
31042 cimg_forC(*
this,c) { *ptrd = (T)(nopacity*texture(tx,ty,0,c) + *ptrd*copacity); ptrd+=wh; }
31044 hatch>>=1;
if (!hatch) hatch = ~0U - (~0U>>1);
31046 if ((error-=dy)<0) { ptrd0+=offy; error+=dx; }
31047 }
else for (
int error = dx>>1, x = 0; x<=dx; ++x) {
31049 const int tx = tx0 + x*dtx/ndx, ty = ty0 + x*dty/ndx;
31050 cimg_forC(*
this,c) { *ptrd = (T)(nopacity*texture(tx,ty,0,c) + *ptrd*copacity); ptrd+=wh; }
31052 if ((error-=dy)<0) { ptrd0+=offy; error+=dx; }
31075 template<
typename tc>
31077 const int x1,
const int y1,
const float z1,
31079 const int tx0,
const int ty0,
31080 const int tx1,
const int ty1,
31081 const float opacity=1,
31082 const unsigned int pattern=~0U,
const bool init_hatch=
true) {
31083 if (
is_empty() && z0<=0 && z1<=0)
return *
this;
31084 if (texture._depth>1 || texture._spectrum<_spectrum)
31086 "draw_line(): Invalid specified texture (%u,%u,%u,%u,%p).",
31088 texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
31090 return draw_line(x0,y0,z0,x1,y1,z1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch);
31091 static unsigned int hatch = ~0U - (~0U>>1);
31092 if (init_hatch) hatch = ~0U - (~0U>>1);
31093 const bool xdir = x0<x1, ydir = y0<y1;
31095 nx0 = x0, nx1 = x1, ny0 = y0, ny1 = y1,
31096 &xleft = xdir?nx0:nx1, &yleft = xdir?ny0:ny1,
31097 &xright = xdir?nx1:nx0, &yright = xdir?ny1:ny0,
31098 &xup = ydir?nx0:nx1, &yup = ydir?ny0:ny1,
31099 &xdown = ydir?nx1:nx0, &ydown = ydir?ny1:ny0;
31101 Tx0 = tx0/z0, Tx1 = tx1/z1,
31102 Ty0 = ty0/z0, Ty1 = ty1/z1,
31103 Z0 = 1/z0, Z1 = 1/z1,
31104 dz = Z1 - Z0, dtx = Tx1 - Tx0, dty = Ty1 - Ty0,
31105 tnx0 = Tx0, tnx1 = Tx1, tny0 = Ty0, tny1 = Ty1, nz0 = Z0, nz1 = Z1,
31106 &zleft = xdir?nz0:nz1, &txleft = xdir?tnx0:tnx1, &tyleft = xdir?tny0:tny1,
31107 &zright = xdir?nz1:nz0, &txright = xdir?tnx1:tnx0, &tyright = xdir?tny1:tny0,
31108 &zup = ydir?nz0:nz1, &txup = ydir?tnx0:tnx1, &tyup = ydir?tny0:tny1,
31109 &zdown = ydir?nz1:nz0, &txdown = ydir?tnx1:tnx0, &tydown = ydir?tny1:tny0;
31110 if (xright<0 || xleft>=
width())
return *
this;
31112 const float D = (float)xright - xleft;
31113 yleft-=(int)((
float)xleft*((float)yright - yleft)/D);
31114 zleft-=(float)xleft*(zright - zleft)/D;
31115 txleft-=(float)xleft*(txright - txleft)/D;
31116 tyleft-=(float)xleft*(tyright - tyleft)/D;
31119 if (xright>=
width()) {
31120 const float d = (float)xright -
width(), D = (float)xright - xleft;
31121 yright-=(int)(d*((
float)yright - yleft)/D);
31122 zright-=d*(zright - zleft)/D;
31123 txright-=d*(txright - txleft)/D;
31124 tyright-=d*(tyright - tyleft)/D;
31125 xright =
width() - 1;
31127 if (ydown<0 || yup>=
height())
return *
this;
31129 const float D = (float)ydown - yup;
31130 xup-=(int)((
float)yup*((float)xdown - xup)/D);
31131 zup-=(float)yup*(zdown - zup)/D;
31132 txup-=(float)yup*(txdown - txup)/D;
31133 tyup-=(float)yup*(tydown - tyup)/D;
31137 const float d = (float)ydown -
height(), D = (float)ydown - yup;
31138 xdown-=(int)(d*((
float)xdown - xup)/D);
31139 zdown-=d*(zdown - zup)/D;
31140 txdown-=d*(txdown - txup)/D;
31141 tydown-=d*(tydown - tyup)/D;
31144 T *ptrd0 =
data(nx0,ny0);
31145 int dx = xright - xleft, dy = ydown - yup;
31146 const bool steep = dy>dx;
31147 if (steep)
cimg::swap(nx0,ny0,nx1,ny1,dx,dy);
31149 offx = (nx0<nx1?1:-1)*(steep?
width():1),
31150 offy = (ny0<ny1?1:-1)*(steep?1:
width()),
31152 const unsigned long wh = (
unsigned long)_width*_height;
31155 if (~pattern)
for (
int error = dx>>1, x = 0; x<=dx; ++x) {
31156 if (pattern&hatch) {
31157 const float z = Z0 + x*dz/ndx, tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx;
31158 T *ptrd = ptrd0; cimg_forC(*
this,c) { *ptrd = (T)texture((
int)(tx/z),(
int)(ty/z),0,c); ptrd+=wh; }
31160 hatch>>=1;
if (!hatch) hatch = ~0U - (~0U>>1);
31162 if ((error-=dy)<0) { ptrd0+=offy; error+=dx; }
31163 }
else for (
int error = dx>>1, x = 0; x<=dx; ++x) {
31164 const float z = Z0 + x*dz/ndx, tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx;
31165 T *ptrd = ptrd0; cimg_forC(*
this,c) { *ptrd = (T)texture((
int)(tx/z),(
int)(ty/z),0,c); ptrd+=wh; }
31167 if ((error-=dy)<0) { ptrd0+=offy; error+=dx; }
31171 if (~pattern)
for (
int error = dx>>1, x = 0; x<=dx; ++x) {
31172 if (pattern&hatch) {
31173 const float z = Z0 + x*dz/ndx, tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx;
31175 cimg_forC(*
this,c) {
31176 *ptrd = (T)(nopacity*texture((
int)(tx/z),(
int)(ty/z),0,c) + *ptrd*copacity); ptrd+=wh;
31179 hatch>>=1;
if (!hatch) hatch = ~0U - (~0U>>1);
31181 if ((error-=dy)<0) { ptrd0+=offy; error+=dx; }
31182 }
else for (
int error = dx>>1, x = 0; x<=dx; ++x) {
31183 const float z = Z0 + x*dz/ndx, tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx;
31185 cimg_forC(*
this,c) { *ptrd = (T)(nopacity*texture((
int)(tx/z),(
int)(ty/z),0,c) + *ptrd*copacity); ptrd+=wh; }
31187 if ((error-=dy)<0) { ptrd0+=offy; error+=dx; }
31211 template<
typename tz,
typename tc>
31213 const int x0,
const int y0,
const float z0,
31214 const int x1,
const int y1,
const float z1,
31216 const int tx0,
const int ty0,
31217 const int tx1,
const int ty1,
31218 const float opacity=1,
31219 const unsigned int pattern=~0U,
const bool init_hatch=
true) {
31220 typedef typename cimg::superset<tz,float>::type tzfloat;
31221 if (
is_empty() || z0<=0 || z1<=0)
return *
this;
31224 "draw_line(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have "
31225 "different dimensions.",
31227 zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data);
31228 if (texture._depth>1 || texture._spectrum<_spectrum)
31230 "draw_line(): Invalid specified texture (%u,%u,%u,%u,%p).",
31232 texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
31234 return draw_line(zbuffer,x0,y0,z0,x1,y1,z1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch);
31235 static unsigned int hatch = ~0U - (~0U>>1);
31236 if (init_hatch) hatch = ~0U - (~0U>>1);
31237 const bool xdir = x0<x1, ydir = y0<y1;
31239 nx0 = x0, nx1 = x1, ny0 = y0, ny1 = y1,
31240 &xleft = xdir?nx0:nx1, &yleft = xdir?ny0:ny1,
31241 &xright = xdir?nx1:nx0, &yright = xdir?ny1:ny0,
31242 &xup = ydir?nx0:nx1, &yup = ydir?ny0:ny1,
31243 &xdown = ydir?nx1:nx0, &ydown = ydir?ny1:ny0;
31245 Tx0 = tx0/z0, Tx1 = tx1/z1,
31246 Ty0 = ty0/z0, Ty1 = ty1/z1,
31247 dtx = Tx1 - Tx0, dty = Ty1 - Ty0,
31248 tnx0 = Tx0, tnx1 = Tx1, tny0 = Ty0, tny1 = Ty1,
31249 &txleft = xdir?tnx0:tnx1, &tyleft = xdir?tny0:tny1,
31250 &txright = xdir?tnx1:tnx0, &tyright = xdir?tny1:tny0,
31251 &txup = ydir?tnx0:tnx1, &tyup = ydir?tny0:tny1,
31252 &txdown = ydir?tnx1:tnx0, &tydown = ydir?tny1:tny0;
31254 Z0 = 1/(tzfloat)z0, Z1 = 1/(tzfloat)z1,
31255 dz = Z1 - Z0, nz0 = Z0, nz1 = Z1,
31256 &zleft = xdir?nz0:nz1,
31257 &zright = xdir?nz1:nz0,
31258 &zup = ydir?nz0:nz1,
31259 &zdown = ydir?nz1:nz0;
31260 if (xright<0 || xleft>=
width())
return *
this;
31262 const float D = (float)xright - xleft;
31263 yleft-=(int)((
float)xleft*((float)yright - yleft)/D);
31264 zleft-=(float)xleft*(zright - zleft)/D;
31265 txleft-=(float)xleft*(txright - txleft)/D;
31266 tyleft-=(float)xleft*(tyright - tyleft)/D;
31269 if (xright>=
width()) {
31270 const float d = (float)xright -
width(), D = (float)xright - xleft;
31271 yright-=(int)(d*((
float)yright - yleft)/D);
31272 zright-=d*(zright - zleft)/D;
31273 txright-=d*(txright - txleft)/D;
31274 tyright-=d*(tyright - tyleft)/D;
31275 xright =
width()-1;
31277 if (ydown<0 || yup>=
height())
return *
this;
31279 const float D = (float)ydown - yup;
31280 xup-=(int)((
float)yup*((float)xdown - xup)/D);
31281 zup-=yup*(zdown - zup)/D;
31282 txup-=yup*(txdown - txup)/D;
31283 tyup-=yup*(tydown - tyup)/D;
31287 const float d = (float)ydown -
height(), D = (float)ydown - yup;
31288 xdown-=(int)(d*((
float)xdown - xup)/D);
31289 zdown-=d*(zdown - zup)/D;
31290 txdown-=d*(txdown - txup)/D;
31291 tydown-=d*(tydown - tyup)/D;
31294 T *ptrd0 =
data(nx0,ny0);
31295 tz *ptrz = zbuffer.data(nx0,ny0);
31296 int dx = xright - xleft, dy = ydown - yup;
31297 const bool steep = dy>dx;
31298 if (steep)
cimg::swap(nx0,ny0,nx1,ny1,dx,dy);
31300 offx = (nx0<nx1?1:-1)*(steep?
width():1),
31301 offy = (ny0<ny1?1:-1)*(steep?1:
width()),
31303 const unsigned long wh = (
unsigned long)_width*_height;
31306 if (~pattern)
for (
int error = dx>>1, x = 0; x<=dx; ++x) {
31307 if (pattern&hatch) {
31308 const tzfloat z = Z0 + x*dz/ndx;
31309 if (z>=(tzfloat)*ptrz) {
31311 const float tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx;
31312 T *ptrd = ptrd0; cimg_forC(*
this,c) { *ptrd = (T)texture((
int)(tx/z),(
int)(ty/z),0,c); ptrd+=wh; }
31315 hatch>>=1;
if (!hatch) hatch = ~0U - (~0U>>1);
31316 ptrd0+=offx; ptrz+=offx;
31317 if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; }
31318 }
else for (
int error = dx>>1, x = 0; x<=dx; ++x) {
31319 const tzfloat z = Z0 + x*dz/ndx;
31320 if (z>=(tzfloat)*ptrz) {
31322 const float tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx;
31323 T *ptrd = ptrd0; cimg_forC(*
this,c) { *ptrd = (T)texture((
int)(tx/z),(
int)(ty/z),0,c); ptrd+=wh; }
31325 ptrd0+=offx; ptrz+=offx;
31326 if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; }
31330 if (~pattern)
for (
int error = dx>>1, x = 0; x<=dx; ++x) {
31331 if (pattern&hatch) {
31332 const tzfloat z = Z0 + x*dz/ndx;
31333 if (z>=(tzfloat)*ptrz) {
31335 const float tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx;
31337 cimg_forC(*
this,c) {
31338 *ptrd = (T)(nopacity*texture((
int)(tx/z),(
int)(ty/z),0,c) + *ptrd*copacity); ptrd+=wh;
31342 hatch>>=1;
if (!hatch) hatch = ~0U - (~0U>>1);
31343 ptrd0+=offx; ptrz+=offx;
31344 if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; }
31345 }
else for (
int error = dx>>1, x = 0; x<=dx; ++x) {
31346 const tzfloat z = Z0 + x*dz/ndx;
31347 if (z>=(tzfloat)*ptrz) {
31349 const float tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx;
31351 cimg_forC(*
this,c) {
31352 *ptrd = (T)(nopacity*texture((
int)(tx/z),(
int)(ty/z),0,c) + *ptrd*copacity); ptrd+=wh;
31355 ptrd0+=offx; ptrz+=offx;
31356 if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; }
31373 template<
typename t,
typename tc>
31375 const tc *
const color,
const float opacity=1,
31376 const unsigned int pattern=~0U,
const bool init_hatch=
true) {
31377 if (
is_empty() || !points || points._width<2)
return *
this;
31378 bool ninit_hatch = init_hatch;
31379 switch (points._height) {
31382 "draw_line(): Invalid specified point set (%u,%u,%u,%u,%p).",
31384 points._width,points._height,points._depth,points._spectrum,points._data);
31387 const int x0 = (int)points(0,0), y0 = (int)points(0,1);
31388 int ox = x0, oy = y0;
31389 for (
unsigned int i = 1; i<points._width; ++i) {
31390 const int x = (int)points(i,0), y = (int)points(i,1);
31391 draw_line(ox,oy,x,y,color,opacity,pattern,ninit_hatch);
31392 ninit_hatch =
false;
31397 const int x0 = (int)points(0,0), y0 = (int)points(0,1), z0 = (int)points(0,2);
31398 int ox = x0, oy = y0, oz = z0;
31399 for (
unsigned int i = 1; i<points._width; ++i) {
31400 const int x = (int)points(i,0), y = (int)points(i,1), z = (int)points(i,2);
31401 draw_line(ox,oy,oz,x,y,z,color,opacity,pattern,ninit_hatch);
31402 ninit_hatch =
false;
31403 ox = x; oy = y; oz = z;
31422 template<
typename tc>
31424 const int x1,
const int y1,
31425 const tc *
const color,
const float opacity=1,
31426 const float angle=30,
const float length=-10,
31427 const unsigned int pattern=~0U) {
31429 const float u = (float)(x0 - x1), v = (float)(y0 - y1), sq = u*u + v*v,
31430 deg = (float)(angle*
cimg::PI/180), ang = (sq>0)?(
float)std::atan2(v,u):0.0f,
31431 l = (length>=0)?length:-length*(
float)std::sqrt(sq)/100;
31434 cl = (float)std::cos(ang - deg), sl = (float)std::sin(ang - deg),
31435 cr = (float)std::cos(ang + deg), sr = (float)std::sin(ang + deg);
31437 xl = x1 + (int)(l*cl), yl = y1 + (int)(l*sl),
31438 xr = x1 + (int)(l*cr), yr = y1 + (int)(l*sr),
31439 xc = x1 + (int)((l+1)*(cl+cr))/2, yc = y1 + (int)((l+1)*(sl+sr))/2;
31440 draw_line(x0,y0,xc,yc,color,opacity,pattern).draw_triangle(x1,y1,xl,yl,xr,yr,color,opacity);
31479 template<
typename tc>
31481 const int x1,
const int y1,
const float u1,
const float v1,
31482 const tc *
const color,
const float opacity=1,
31483 const float precision=0.25,
const unsigned int pattern=~0U,
31484 const bool init_hatch=
true) {
31488 "draw_spline(): Specified color is (null).",
31490 if (x0==x1 && y0==y1)
return draw_point(x0,y0,color,opacity);
31491 bool ninit_hatch = init_hatch;
31493 ax = u0 + u1 + 2*(x0 - x1),
31494 bx = 3*(x1 - x0) - 2*u0 - u1,
31495 ay = v0 + v1 + 2*(y0 - y1),
31496 by = 3*(y1 - y0) - 2*v0 - v1,
31497 _precision = 1/(std::sqrt(
cimg::sqr((
float)x0-x1)+
cimg::sqr((
float)y0-y1))*(precision>0?precision:1));
31498 int ox = x0, oy = y0;
31499 for (
float t = 0; t<1; t+=_precision) {
31500 const float t2 = t*t, t3 = t2*t;
31502 nx = (int)(ax*t3 + bx*t2 + u0*t + x0),
31503 ny = (int)(ay*t3 + by*t2 + v0*t + y0);
31504 draw_line(ox,oy,nx,ny,color,opacity,pattern,ninit_hatch);
31505 ninit_hatch =
false;
31508 return draw_line(ox,oy,x1,y1,color,opacity,pattern,
false);
31516 template<
typename tc>
31517 CImg<T>&
draw_spline(
const int x0,
const int y0,
const int z0,
const float u0,
const float v0,
const float w0,
31518 const int x1,
const int y1,
const int z1,
const float u1,
const float v1,
const float w1,
31519 const tc *
const color,
const float opacity=1,
31520 const float precision=4,
const unsigned int pattern=~0U,
31521 const bool init_hatch=
true) {
31525 "draw_spline(): Specified color is (null).",
31527 if (x0==x1 && y0==y1 && z0==z1)
return draw_point(x0,y0,z0,color,opacity);
31528 bool ninit_hatch = init_hatch;
31530 ax = u0 + u1 + 2*(x0 - x1),
31531 bx = 3*(x1 - x0) - 2*u0 - u1,
31532 ay = v0 + v1 + 2*(y0 - y1),
31533 by = 3*(y1 - y0) - 2*v0 - v1,
31534 az = w0 + w1 + 2*(z0 - z1),
31535 bz = 3*(z1 - z0) - 2*w0 - w1,
31536 _precision = 1/(std::sqrt(
cimg::sqr(x0-x1)+
cimg::sqr(y0-y1))*(precision>0?precision:1));
31537 int ox = x0, oy = y0, oz = z0;
31538 for (
float t = 0; t<1; t+=_precision) {
31539 const float t2 = t*t, t3 = t2*t;
31541 nx = (int)(ax*t3 + bx*t2 + u0*t + x0),
31542 ny = (int)(ay*t3 + by*t2 + v0*t + y0),
31543 nz = (int)(az*t3 + bz*t2 + w0*t + z0);
31544 draw_line(ox,oy,oz,nx,ny,nz,color,opacity,pattern,ninit_hatch);
31545 ninit_hatch =
false;
31546 ox = nx; oy = ny; oz = nz;
31548 return draw_line(ox,oy,oz,x1,y1,z1,color,opacity,pattern,
false);
31571 template<
typename t>
31573 const int x1,
const int y1,
const float u1,
const float v1,
31575 const int tx0,
const int ty0,
const int tx1,
const int ty1,
31576 const float opacity=1,
31577 const float precision=4,
const unsigned int pattern=~0U,
31578 const bool init_hatch=
true) {
31579 if (texture._depth>1 || texture._spectrum<_spectrum)
31581 "draw_spline(): Invalid specified texture (%u,%u,%u,%u,%p).",
31583 texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
31586 return draw_spline(x0,y0,u0,v0,x1,y1,u1,v1,+texture,tx0,ty0,tx1,ty1,precision,opacity,pattern,init_hatch);
31587 if (x0==x1 && y0==y1)
return draw_point(x0,y0,texture.get_vector_at(x0,y0),opacity);
31588 bool ninit_hatch = init_hatch;
31590 ax = u0 + u1 + 2*(x0 - x1),
31591 bx = 3*(x1 - x0) - 2*u0 - u1,
31592 ay = v0 + v1 + 2*(y0 - y1),
31593 by = 3*(y1 - y0) - 2*v0 - v1,
31594 _precision = 1/(std::sqrt(
cimg::sqr(x0-x1)+
cimg::sqr(y0-y1))*(precision>0?precision:1));
31595 int ox = x0, oy = y0, otx = tx0, oty = ty0;
31596 for (
float t1 = 0; t1<1; t1+=_precision) {
31597 const float t2 = t1*t1, t3 = t2*t1;
31599 nx = (int)(ax*t3 + bx*t2 + u0*t1 + x0),
31600 ny = (int)(ay*t3 + by*t2 + v0*t1 + y0),
31601 ntx = tx0 + (int)((tx1-tx0)*t1),
31602 nty = ty0 + (
int)((ty1-ty0)*t1);
31603 draw_line(ox,oy,nx,ny,texture,otx,oty,ntx,nty,opacity,pattern,ninit_hatch);
31604 ninit_hatch =
false;
31605 ox = nx; oy = ny; otx = ntx; oty = nty;
31607 return draw_line(ox,oy,x1,y1,texture,otx,oty,tx1,ty1,opacity,pattern,
false);
31621 template<
typename tp,
typename tt,
typename tc>
31623 const tc *
const color,
const float opacity=1,
31624 const bool is_closed_set=
false,
const float precision=4,
31625 const unsigned int pattern=~0U,
const bool init_hatch=
true) {
31626 if (
is_empty() || !points || !tangents || points._width<2 || tangents._width<2)
return *
this;
31627 bool ninit_hatch = init_hatch;
31628 switch (points._height) {
31631 "draw_spline(): Invalid specified point set (%u,%u,%u,%u,%p).",
31633 points._width,points._height,points._depth,points._spectrum,points._data);
31636 const int x0 = (int)points(0,0), y0 = (int)points(0,1);
31637 const float u0 = (float)tangents(0,0), v0 = (float)tangents(0,1);
31638 int ox = x0, oy = y0;
31639 float ou = u0, ov = v0;
31640 for (
unsigned int i = 1; i<points._width; ++i) {
31641 const int x = (int)points(i,0), y = (int)points(i,1);
31642 const float u = (float)tangents(i,0), v = (float)tangents(i,1);
31643 draw_spline(ox,oy,ou,ov,x,y,u,v,color,precision,opacity,pattern,ninit_hatch);
31644 ninit_hatch =
false;
31645 ox = x; oy = y; ou = u; ov = v;
31647 if (is_closed_set)
draw_spline(ox,oy,ou,ov,x0,y0,u0,v0,color,precision,opacity,pattern,
false);
31650 const int x0 = (int)points(0,0), y0 = (int)points(0,1), z0 = (int)points(0,2);
31651 const float u0 = (float)tangents(0,0), v0 = (float)tangents(0,1), w0 = (float)tangents(0,2);
31652 int ox = x0, oy = y0, oz = z0;
31653 float ou = u0, ov = v0, ow = w0;
31654 for (
unsigned int i = 1; i<points._width; ++i) {
31655 const int x = (int)points(i,0), y = (int)points(i,1), z = (int)points(i,2);
31656 const float u = (float)tangents(i,0), v = (float)tangents(i,1), w = (float)tangents(i,2);
31657 draw_spline(ox,oy,oz,ou,ov,ow,x,y,z,u,v,w,color,opacity,pattern,ninit_hatch);
31658 ninit_hatch =
false;
31659 ox = x; oy = y; oz = z; ou = u; ov = v; ow = w;
31661 if (is_closed_set)
draw_spline(ox,oy,oz,ou,ov,ow,x0,y0,z0,u0,v0,w0,color,precision,opacity,pattern,
false);
31671 template<
typename tp,
typename tc>
31673 const tc *
const color,
const float opacity=1,
31674 const bool is_closed_set=
false,
const float precision=4,
31675 const unsigned int pattern=~0U,
const bool init_hatch=
true) {
31676 if (
is_empty() || !points || points._width<2)
return *
this;
31678 switch (points._height) {
31681 "draw_spline(): Invalid specified point set (%u,%u,%u,%u,%p).",
31683 points._width,points._height,points._depth,points._spectrum,points._data);
31685 tangents.assign(points._width,points._height);
31686 cimg_forX(points,p) {
31688 p0 = is_closed_set?(p+points._width-1)%points._width:(p?p-1:0),
31689 p1 = is_closed_set?(p+1)%points._width:(p+1<points._width?p+1:p);
31691 x = (float)points(p,0),
31692 y = (float)points(p,1),
31693 x0 = (float)points(p0,0),
31694 y0 = (float)points(p0,1),
31695 x1 = (float)points(p1,0),
31696 y1 = (float)points(p1,1),
31699 n0 = 1e-8f + (float)std::sqrt(u0*u0 + v0*v0),
31702 n1 = 1e-8f + (float)std::sqrt(u1*u1 + v1*v1),
31705 n = 1e-8f + (float)std::sqrt(u*u + v*v),
31706 fact = 0.5f*(n0 + n1);
31707 tangents(p,0) = (Tfloat)(fact*u/n);
31708 tangents(p,1) = (Tfloat)(fact*v/n);
31712 tangents.assign(points._width,points._height);
31713 cimg_forX(points,p) {
31715 p0 = is_closed_set?(p+points._width-1)%points._width:(p?p-1:0),
31716 p1 = is_closed_set?(p+1)%points._width:(p+1<points._width?p+1:p);
31718 x = (float)points(p,0),
31719 y = (float)points(p,1),
31720 z = (float)points(p,2),
31721 x0 = (float)points(p0,0),
31722 y0 = (float)points(p0,1),
31723 z0 = (float)points(p0,2),
31724 x1 = (float)points(p1,0),
31725 y1 = (float)points(p1,1),
31726 z1 = (float)points(p1,2),
31730 n0 = 1e-8f + (float)std::sqrt(u0*u0 + v0*v0 + w0*w0),
31734 n1 = 1e-8f + (float)std::sqrt(u1*u1 + v1*v1 + w1*w1),
31738 n = 1e-8f + (float)std::sqrt(u*u + v*v + w*w),
31739 fact = 0.5f*(n0 + n1);
31740 tangents(p,0) = (Tfloat)(fact*u/n);
31741 tangents(p,1) = (Tfloat)(fact*v/n);
31742 tangents(p,2) = (Tfloat)(fact*w/n);
31746 return draw_spline(points,tangents,color,opacity,is_closed_set,precision,pattern,init_hatch);
31750 #define _cimg_for_triangle1(img,xl,xr,y,x0,y0,x1,y1,x2,y2) \
31751 for (int y = y0<0?0:y0, \
31752 xr = y0>=0?x0:(x0-y0*(x2-x0)/(y2-y0)), \
31753 xl = y1>=0?(y0>=0?(y0==y1?x1:x0):(x0-y0*(x1-x0)/(y1-y0))):(x1-y1*(x2-x1)/(y2-y1)), \
31757 _dxn = x2>x1?x2-x1:(_sxn=-1,x1-x2), \
31758 _dxr = x2>x0?x2-x0:(_sxr=-1,x0-x2), \
31759 _dxl = x1>x0?x1-x0:(_sxl=-1,x0-x1), \
31763 _counter = (_dxn-=_dyn?_dyn*(_dxn/_dyn):0, \
31764 _dxr-=_dyr?_dyr*(_dxr/_dyr):0, \
31765 _dxl-=_dyl?_dyl*(_dxl/_dyl):0, \
31766 cimg::min((int)(img)._height-y-1,y2-y)), \
31770 _rxn = _dyn?(x2-x1)/_dyn:0, \
31771 _rxr = _dyr?(x2-x0)/_dyr:0, \
31772 _rxl = (y0!=y1 && y1>0)?(_dyl?(x1-x0)/_dyl:0): \
31773 (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxn); \
31774 _counter>=0; --_counter, ++y, \
31775 xr+=_rxr+((_errr-=_dxr)<0?_errr+=_dyr,_sxr:0), \
31776 xl+=(y!=y1)?_rxl+((_errl-=_dxl)<0?(_errl+=_dyl,_sxl):0): \
31777 (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxl=_rxn, x1-xl))
31779 #define _cimg_for_triangle2(img,xl,cl,xr,cr,y,x0,y0,c0,x1,y1,c1,x2,y2,c2) \
31780 for (int y = y0<0?0:y0, \
31781 xr = y0>=0?x0:(x0-y0*(x2-x0)/(y2-y0)), \
31782 cr = y0>=0?c0:(c0-y0*(c2-c0)/(y2-y0)), \
31783 xl = y1>=0?(y0>=0?(y0==y1?x1:x0):(x0-y0*(x1-x0)/(y1-y0))):(x1-y1*(x2-x1)/(y2-y1)), \
31784 cl = y1>=0?(y0>=0?(y0==y1?c1:c0):(c0-y0*(c1-c0)/(y1-y0))):(c1-y1*(c2-c1)/(y2-y1)), \
31788 _dxn = x2>x1?x2-x1:(_sxn=-1,x1-x2), \
31789 _dxr = x2>x0?x2-x0:(_sxr=-1,x0-x2), \
31790 _dxl = x1>x0?x1-x0:(_sxl=-1,x0-x1), \
31791 _dcn = c2>c1?c2-c1:(_scn=-1,c1-c2), \
31792 _dcr = c2>c0?c2-c0:(_scr=-1,c0-c2), \
31793 _dcl = c1>c0?c1-c0:(_scl=-1,c0-c1), \
31797 _counter =(_dxn-=_dyn?_dyn*(_dxn/_dyn):0, \
31798 _dxr-=_dyr?_dyr*(_dxr/_dyr):0, \
31799 _dxl-=_dyl?_dyl*(_dxl/_dyl):0, \
31800 _dcn-=_dyn?_dyn*(_dcn/_dyn):0, \
31801 _dcr-=_dyr?_dyr*(_dcr/_dyr):0, \
31802 _dcl-=_dyl?_dyl*(_dcl/_dyl):0, \
31803 cimg::min((int)(img)._height-y-1,y2-y)), \
31804 _errn = _dyn/2, _errcn = _errn, \
31805 _errr = _dyr/2, _errcr = _errr, \
31806 _errl = _dyl/2, _errcl = _errl, \
31807 _rxn = _dyn?(x2-x1)/_dyn:0, \
31808 _rcn = _dyn?(c2-c1)/_dyn:0, \
31809 _rxr = _dyr?(x2-x0)/_dyr:0, \
31810 _rcr = _dyr?(c2-c0)/_dyr:0, \
31811 _rxl = (y0!=y1 && y1>0)?(_dyl?(x1-x0)/_dyl:0): \
31812 (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxn), \
31813 _rcl = (y0!=y1 && y1>0)?(_dyl?(c1-c0)/_dyl:0): \
31814 (_errcl=_errcn, _dcl=_dcn, _dyl=_dyn, _scl=_scn, _rcn ); \
31815 _counter>=0; --_counter, ++y, \
31816 xr+=_rxr+((_errr-=_dxr)<0?_errr+=_dyr,_sxr:0), \
31817 cr+=_rcr+((_errcr-=_dcr)<0?_errcr+=_dyr,_scr:0), \
31818 xl+=(y!=y1)?(cl+=_rcl+((_errcl-=_dcl)<0?(_errcl+=_dyl,_scl):0), \
31819 _rxl+((_errl-=_dxl)<0?(_errl+=_dyl,_sxl):0)): \
31820 (_errcl=_errcn, _dcl=_dcn, _dyl=_dyn, _scl=_scn, _rcl=_rcn, cl=c1, \
31821 _errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxl=_rxn, x1-xl))
31823 #define _cimg_for_triangle3(img,xl,txl,tyl,xr,txr,tyr,y,x0,y0,tx0,ty0,x1,y1,tx1,ty1,x2,y2,tx2,ty2) \
31824 for (int y = y0<0?0:y0, \
31825 xr = y0>=0?x0:(x0-y0*(x2-x0)/(y2-y0)), \
31826 txr = y0>=0?tx0:(tx0-y0*(tx2-tx0)/(y2-y0)), \
31827 tyr = y0>=0?ty0:(ty0-y0*(ty2-ty0)/(y2-y0)), \
31828 xl = y1>=0?(y0>=0?(y0==y1?x1:x0):(x0-y0*(x1-x0)/(y1-y0))):(x1-y1*(x2-x1)/(y2-y1)), \
31829 txl = y1>=0?(y0>=0?(y0==y1?tx1:tx0):(tx0-y0*(tx1-tx0)/(y1-y0))):(tx1-y1*(tx2-tx1)/(y2-y1)), \
31830 tyl = y1>=0?(y0>=0?(y0==y1?ty1:ty0):(ty0-y0*(ty1-ty0)/(y1-y0))):(ty1-y1*(ty2-ty1)/(y2-y1)), \
31831 _sxn=1, _stxn=1, _styn=1, \
31832 _sxr=1, _stxr=1, _styr=1, \
31833 _sxl=1, _stxl=1, _styl=1, \
31834 _dxn = x2>x1?x2-x1:(_sxn=-1,x1-x2), \
31835 _dxr = x2>x0?x2-x0:(_sxr=-1,x0-x2), \
31836 _dxl = x1>x0?x1-x0:(_sxl=-1,x0-x1), \
31837 _dtxn = tx2>tx1?tx2-tx1:(_stxn=-1,tx1-tx2), \
31838 _dtxr = tx2>tx0?tx2-tx0:(_stxr=-1,tx0-tx2), \
31839 _dtxl = tx1>tx0?tx1-tx0:(_stxl=-1,tx0-tx1), \
31840 _dtyn = ty2>ty1?ty2-ty1:(_styn=-1,ty1-ty2), \
31841 _dtyr = ty2>ty0?ty2-ty0:(_styr=-1,ty0-ty2), \
31842 _dtyl = ty1>ty0?ty1-ty0:(_styl=-1,ty0-ty1), \
31846 _counter =(_dxn-=_dyn?_dyn*(_dxn/_dyn):0, \
31847 _dxr-=_dyr?_dyr*(_dxr/_dyr):0, \
31848 _dxl-=_dyl?_dyl*(_dxl/_dyl):0, \
31849 _dtxn-=_dyn?_dyn*(_dtxn/_dyn):0, \
31850 _dtxr-=_dyr?_dyr*(_dtxr/_dyr):0, \
31851 _dtxl-=_dyl?_dyl*(_dtxl/_dyl):0, \
31852 _dtyn-=_dyn?_dyn*(_dtyn/_dyn):0, \
31853 _dtyr-=_dyr?_dyr*(_dtyr/_dyr):0, \
31854 _dtyl-=_dyl?_dyl*(_dtyl/_dyl):0, \
31855 cimg::min((int)(img)._height-y-1,y2-y)), \
31856 _errn = _dyn/2, _errtxn = _errn, _errtyn = _errn, \
31857 _errr = _dyr/2, _errtxr = _errr, _errtyr = _errr, \
31858 _errl = _dyl/2, _errtxl = _errl, _errtyl = _errl, \
31859 _rxn = _dyn?(x2-x1)/_dyn:0, \
31860 _rtxn = _dyn?(tx2-tx1)/_dyn:0, \
31861 _rtyn = _dyn?(ty2-ty1)/_dyn:0, \
31862 _rxr = _dyr?(x2-x0)/_dyr:0, \
31863 _rtxr = _dyr?(tx2-tx0)/_dyr:0, \
31864 _rtyr = _dyr?(ty2-ty0)/_dyr:0, \
31865 _rxl = (y0!=y1 && y1>0)?(_dyl?(x1-x0)/_dyl:0): \
31866 (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxn), \
31867 _rtxl = (y0!=y1 && y1>0)?(_dyl?(tx1-tx0)/_dyl:0): \
31868 (_errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxn ), \
31869 _rtyl = (y0!=y1 && y1>0)?(_dyl?(ty1-ty0)/_dyl:0): \
31870 (_errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyn ); \
31871 _counter>=0; --_counter, ++y, \
31872 xr+=_rxr+((_errr-=_dxr)<0?_errr+=_dyr,_sxr:0), \
31873 txr+=_rtxr+((_errtxr-=_dtxr)<0?_errtxr+=_dyr,_stxr:0), \
31874 tyr+=_rtyr+((_errtyr-=_dtyr)<0?_errtyr+=_dyr,_styr:0), \
31875 xl+=(y!=y1)?(txl+=_rtxl+((_errtxl-=_dtxl)<0?(_errtxl+=_dyl,_stxl):0), \
31876 tyl+=_rtyl+((_errtyl-=_dtyl)<0?(_errtyl+=_dyl,_styl):0), \
31877 _rxl+((_errl-=_dxl)<0?(_errl+=_dyl,_sxl):0)): \
31878 (_errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxl=_rtxn, txl=tx1, \
31879 _errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyl=_rtyn, tyl=ty1,\
31880 _errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxl=_rxn, x1-xl))
31882 #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) \
31883 for (int y = y0<0?0:y0, \
31884 xr = y0>=0?x0:(x0-y0*(x2-x0)/(y2-y0)), \
31885 cr = y0>=0?c0:(c0-y0*(c2-c0)/(y2-y0)), \
31886 txr = y0>=0?tx0:(tx0-y0*(tx2-tx0)/(y2-y0)), \
31887 tyr = y0>=0?ty0:(ty0-y0*(ty2-ty0)/(y2-y0)), \
31888 xl = y1>=0?(y0>=0?(y0==y1?x1:x0):(x0-y0*(x1-x0)/(y1-y0))):(x1-y1*(x2-x1)/(y2-y1)), \
31889 cl = y1>=0?(y0>=0?(y0==y1?c1:c0):(c0-y0*(c1-c0)/(y1-y0))):(c1-y1*(c2-c1)/(y2-y1)), \
31890 txl = y1>=0?(y0>=0?(y0==y1?tx1:tx0):(tx0-y0*(tx1-tx0)/(y1-y0))):(tx1-y1*(tx2-tx1)/(y2-y1)), \
31891 tyl = y1>=0?(y0>=0?(y0==y1?ty1:ty0):(ty0-y0*(ty1-ty0)/(y1-y0))):(ty1-y1*(ty2-ty1)/(y2-y1)), \
31892 _sxn=1, _scn=1, _stxn=1, _styn=1, \
31893 _sxr=1, _scr=1, _stxr=1, _styr=1, \
31894 _sxl=1, _scl=1, _stxl=1, _styl=1, \
31895 _dxn = x2>x1?x2-x1:(_sxn=-1,x1-x2), \
31896 _dxr = x2>x0?x2-x0:(_sxr=-1,x0-x2), \
31897 _dxl = x1>x0?x1-x0:(_sxl=-1,x0-x1), \
31898 _dcn = c2>c1?c2-c1:(_scn=-1,c1-c2), \
31899 _dcr = c2>c0?c2-c0:(_scr=-1,c0-c2), \
31900 _dcl = c1>c0?c1-c0:(_scl=-1,c0-c1), \
31901 _dtxn = tx2>tx1?tx2-tx1:(_stxn=-1,tx1-tx2), \
31902 _dtxr = tx2>tx0?tx2-tx0:(_stxr=-1,tx0-tx2), \
31903 _dtxl = tx1>tx0?tx1-tx0:(_stxl=-1,tx0-tx1), \
31904 _dtyn = ty2>ty1?ty2-ty1:(_styn=-1,ty1-ty2), \
31905 _dtyr = ty2>ty0?ty2-ty0:(_styr=-1,ty0-ty2), \
31906 _dtyl = ty1>ty0?ty1-ty0:(_styl=-1,ty0-ty1), \
31910 _counter =(_dxn-=_dyn?_dyn*(_dxn/_dyn):0, \
31911 _dxr-=_dyr?_dyr*(_dxr/_dyr):0, \
31912 _dxl-=_dyl?_dyl*(_dxl/_dyl):0, \
31913 _dcn-=_dyn?_dyn*(_dcn/_dyn):0, \
31914 _dcr-=_dyr?_dyr*(_dcr/_dyr):0, \
31915 _dcl-=_dyl?_dyl*(_dcl/_dyl):0, \
31916 _dtxn-=_dyn?_dyn*(_dtxn/_dyn):0, \
31917 _dtxr-=_dyr?_dyr*(_dtxr/_dyr):0, \
31918 _dtxl-=_dyl?_dyl*(_dtxl/_dyl):0, \
31919 _dtyn-=_dyn?_dyn*(_dtyn/_dyn):0, \
31920 _dtyr-=_dyr?_dyr*(_dtyr/_dyr):0, \
31921 _dtyl-=_dyl?_dyl*(_dtyl/_dyl):0, \
31922 cimg::min((int)(img)._height-y-1,y2-y)), \
31923 _errn = _dyn/2, _errcn = _errn, _errtxn = _errn, _errtyn = _errn, \
31924 _errr = _dyr/2, _errcr = _errr, _errtxr = _errr, _errtyr = _errr, \
31925 _errl = _dyl/2, _errcl = _errl, _errtxl = _errl, _errtyl = _errl, \
31926 _rxn = _dyn?(x2-x1)/_dyn:0, \
31927 _rcn = _dyn?(c2-c1)/_dyn:0, \
31928 _rtxn = _dyn?(tx2-tx1)/_dyn:0, \
31929 _rtyn = _dyn?(ty2-ty1)/_dyn:0, \
31930 _rxr = _dyr?(x2-x0)/_dyr:0, \
31931 _rcr = _dyr?(c2-c0)/_dyr:0, \
31932 _rtxr = _dyr?(tx2-tx0)/_dyr:0, \
31933 _rtyr = _dyr?(ty2-ty0)/_dyr:0, \
31934 _rxl = (y0!=y1 && y1>0)?(_dyl?(x1-x0)/_dyl:0): \
31935 (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxn), \
31936 _rcl = (y0!=y1 && y1>0)?(_dyl?(c1-c0)/_dyl:0): \
31937 (_errcl=_errcn, _dcl=_dcn, _dyl=_dyn, _scl=_scn, _rcn ), \
31938 _rtxl = (y0!=y1 && y1>0)?(_dyl?(tx1-tx0)/_dyl:0): \
31939 (_errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxn ), \
31940 _rtyl = (y0!=y1 && y1>0)?(_dyl?(ty1-ty0)/_dyl:0): \
31941 (_errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyn ); \
31942 _counter>=0; --_counter, ++y, \
31943 xr+=_rxr+((_errr-=_dxr)<0?_errr+=_dyr,_sxr:0), \
31944 cr+=_rcr+((_errcr-=_dcr)<0?_errcr+=_dyr,_scr:0), \
31945 txr+=_rtxr+((_errtxr-=_dtxr)<0?_errtxr+=_dyr,_stxr:0), \
31946 tyr+=_rtyr+((_errtyr-=_dtyr)<0?_errtyr+=_dyr,_styr:0), \
31947 xl+=(y!=y1)?(cl+=_rcl+((_errcl-=_dcl)<0?(_errcl+=_dyl,_scl):0), \
31948 txl+=_rtxl+((_errtxl-=_dtxl)<0?(_errtxl+=_dyl,_stxl):0), \
31949 tyl+=_rtyl+((_errtyl-=_dtyl)<0?(_errtyl+=_dyl,_styl):0), \
31950 _rxl+((_errl-=_dxl)<0?(_errl+=_dyl,_sxl):0)): \
31951 (_errcl=_errcn, _dcl=_dcn, _dyl=_dyn, _scl=_scn, _rcl=_rcn, cl=c1, \
31952 _errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxl=_rtxn, txl=tx1, \
31953 _errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyl=_rtyn, tyl=ty1, \
31954 _errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxl=_rxn, x1-xl))
31956 #define _cimg_for_triangle5(img,xl,txl,tyl,lxl,lyl,xr,txr,tyr,lxr,lyr,y,x0,y0,\
31957 tx0,ty0,lx0,ly0,x1,y1,tx1,ty1,lx1,ly1,x2,y2,tx2,ty2,lx2,ly2) \
31958 for (int y = y0<0?0:y0, \
31959 xr = y0>=0?x0:(x0-y0*(x2-x0)/(y2-y0)), \
31960 txr = y0>=0?tx0:(tx0-y0*(tx2-tx0)/(y2-y0)), \
31961 tyr = y0>=0?ty0:(ty0-y0*(ty2-ty0)/(y2-y0)), \
31962 lxr = y0>=0?lx0:(lx0-y0*(lx2-lx0)/(y2-y0)), \
31963 lyr = y0>=0?ly0:(ly0-y0*(ly2-ly0)/(y2-y0)), \
31964 xl = y1>=0?(y0>=0?(y0==y1?x1:x0):(x0-y0*(x1-x0)/(y1-y0))):(x1-y1*(x2-x1)/(y2-y1)), \
31965 txl = y1>=0?(y0>=0?(y0==y1?tx1:tx0):(tx0-y0*(tx1-tx0)/(y1-y0))):(tx1-y1*(tx2-tx1)/(y2-y1)), \
31966 tyl = y1>=0?(y0>=0?(y0==y1?ty1:ty0):(ty0-y0*(ty1-ty0)/(y1-y0))):(ty1-y1*(ty2-ty1)/(y2-y1)), \
31967 lxl = y1>=0?(y0>=0?(y0==y1?lx1:lx0):(lx0-y0*(lx1-lx0)/(y1-y0))):(lx1-y1*(lx2-lx1)/(y2-y1)), \
31968 lyl = y1>=0?(y0>=0?(y0==y1?ly1:ly0):(ly0-y0*(ly1-ly0)/(y1-y0))):(ly1-y1*(ly2-ly1)/(y2-y1)), \
31969 _sxn=1, _stxn=1, _styn=1, _slxn=1, _slyn=1, \
31970 _sxr=1, _stxr=1, _styr=1, _slxr=1, _slyr=1, \
31971 _sxl=1, _stxl=1, _styl=1, _slxl=1, _slyl=1, \
31972 _dxn = x2>x1?x2-x1:(_sxn=-1,x1-x2), _dyn = y2-y1, \
31973 _dxr = x2>x0?x2-x0:(_sxr=-1,x0-x2), _dyr = y2-y0, \
31974 _dxl = x1>x0?x1-x0:(_sxl=-1,x0-x1), _dyl = y1-y0, \
31975 _dtxn = tx2>tx1?tx2-tx1:(_stxn=-1,tx1-tx2), \
31976 _dtxr = tx2>tx0?tx2-tx0:(_stxr=-1,tx0-tx2), \
31977 _dtxl = tx1>tx0?tx1-tx0:(_stxl=-1,tx0-tx1), \
31978 _dtyn = ty2>ty1?ty2-ty1:(_styn=-1,ty1-ty2), \
31979 _dtyr = ty2>ty0?ty2-ty0:(_styr=-1,ty0-ty2), \
31980 _dtyl = ty1>ty0?ty1-ty0:(_styl=-1,ty0-ty1), \
31981 _dlxn = lx2>lx1?lx2-lx1:(_slxn=-1,lx1-lx2), \
31982 _dlxr = lx2>lx0?lx2-lx0:(_slxr=-1,lx0-lx2), \
31983 _dlxl = lx1>lx0?lx1-lx0:(_slxl=-1,lx0-lx1), \
31984 _dlyn = ly2>ly1?ly2-ly1:(_slyn=-1,ly1-ly2), \
31985 _dlyr = ly2>ly0?ly2-ly0:(_slyr=-1,ly0-ly2), \
31986 _dlyl = ly1>ly0?ly1-ly0:(_slyl=-1,ly0-ly1), \
31987 _counter =(_dxn-=_dyn?_dyn*(_dxn/_dyn):0, \
31988 _dxr-=_dyr?_dyr*(_dxr/_dyr):0, \
31989 _dxl-=_dyl?_dyl*(_dxl/_dyl):0, \
31990 _dtxn-=_dyn?_dyn*(_dtxn/_dyn):0, \
31991 _dtxr-=_dyr?_dyr*(_dtxr/_dyr):0, \
31992 _dtxl-=_dyl?_dyl*(_dtxl/_dyl):0, \
31993 _dtyn-=_dyn?_dyn*(_dtyn/_dyn):0, \
31994 _dtyr-=_dyr?_dyr*(_dtyr/_dyr):0, \
31995 _dtyl-=_dyl?_dyl*(_dtyl/_dyl):0, \
31996 _dlxn-=_dyn?_dyn*(_dlxn/_dyn):0, \
31997 _dlxr-=_dyr?_dyr*(_dlxr/_dyr):0, \
31998 _dlxl-=_dyl?_dyl*(_dlxl/_dyl):0, \
31999 _dlyn-=_dyn?_dyn*(_dlyn/_dyn):0, \
32000 _dlyr-=_dyr?_dyr*(_dlyr/_dyr):0, \
32001 _dlyl-=_dyl?_dyl*(_dlyl/_dyl):0, \
32002 cimg::min((int)(img)._height-y-1,y2-y)), \
32003 _errn = _dyn/2, _errtxn = _errn, _errtyn = _errn, _errlxn = _errn, _errlyn = _errn, \
32004 _errr = _dyr/2, _errtxr = _errr, _errtyr = _errr, _errlxr = _errr, _errlyr = _errr, \
32005 _errl = _dyl/2, _errtxl = _errl, _errtyl = _errl, _errlxl = _errl, _errlyl = _errl, \
32006 _rxn = _dyn?(x2-x1)/_dyn:0, \
32007 _rtxn = _dyn?(tx2-tx1)/_dyn:0, \
32008 _rtyn = _dyn?(ty2-ty1)/_dyn:0, \
32009 _rlxn = _dyn?(lx2-lx1)/_dyn:0, \
32010 _rlyn = _dyn?(ly2-ly1)/_dyn:0, \
32011 _rxr = _dyr?(x2-x0)/_dyr:0, \
32012 _rtxr = _dyr?(tx2-tx0)/_dyr:0, \
32013 _rtyr = _dyr?(ty2-ty0)/_dyr:0, \
32014 _rlxr = _dyr?(lx2-lx0)/_dyr:0, \
32015 _rlyr = _dyr?(ly2-ly0)/_dyr:0, \
32016 _rxl = (y0!=y1 && y1>0)?(_dyl?(x1-x0)/_dyl:0): \
32017 (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxn), \
32018 _rtxl = (y0!=y1 && y1>0)?(_dyl?(tx1-tx0)/_dyl:0): \
32019 (_errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxn ), \
32020 _rtyl = (y0!=y1 && y1>0)?(_dyl?(ty1-ty0)/_dyl:0): \
32021 (_errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyn ), \
32022 _rlxl = (y0!=y1 && y1>0)?(_dyl?(lx1-lx0)/_dyl:0): \
32023 (_errlxl=_errlxn, _dlxl=_dlxn, _dyl=_dyn, _slxl=_slxn, _rlxn ), \
32024 _rlyl = (y0!=y1 && y1>0)?(_dyl?(ly1-ly0)/_dyl:0): \
32025 (_errlyl=_errlyn, _dlyl=_dlyn, _dyl=_dyn, _slyl=_slyn, _rlyn ); \
32026 _counter>=0; --_counter, ++y, \
32027 xr+=_rxr+((_errr-=_dxr)<0?_errr+=_dyr,_sxr:0), \
32028 txr+=_rtxr+((_errtxr-=_dtxr)<0?_errtxr+=_dyr,_stxr:0), \
32029 tyr+=_rtyr+((_errtyr-=_dtyr)<0?_errtyr+=_dyr,_styr:0), \
32030 lxr+=_rlxr+((_errlxr-=_dlxr)<0?_errlxr+=_dyr,_slxr:0), \
32031 lyr+=_rlyr+((_errlyr-=_dlyr)<0?_errlyr+=_dyr,_slyr:0), \
32032 xl+=(y!=y1)?(txl+=_rtxl+((_errtxl-=_dtxl)<0?(_errtxl+=_dyl,_stxl):0), \
32033 tyl+=_rtyl+((_errtyl-=_dtyl)<0?(_errtyl+=_dyl,_styl):0), \
32034 lxl+=_rlxl+((_errlxl-=_dlxl)<0?(_errlxl+=_dyl,_slxl):0), \
32035 lyl+=_rlyl+((_errlyl-=_dlyl)<0?(_errlyl+=_dyl,_slyl):0), \
32036 _rxl+((_errl-=_dxl)<0?(_errl+=_dyl,_sxl):0)): \
32037 (_errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxl=_rtxn, txl=tx1, \
32038 _errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyl=_rtyn, tyl=ty1, \
32039 _errlxl=_errlxn, _dlxl=_dlxn, _dyl=_dyn, _slxl=_slxn, _rlxl=_rlxn, lxl=lx1, \
32040 _errlyl=_errlyn, _dlyl=_dlyn, _dyl=_dyn, _slyl=_slyn, _rlyl=_rlyn, lyl=ly1, \
32041 _errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxl=_rxn, x1-xl))
32044 template<
typename tc>
32045 CImg<T>& _draw_triangle(
const int x0,
const int y0,
32046 const int x1,
const int y1,
32047 const int x2,
const int y2,
32048 const tc *
const color,
const float opacity,
32049 const float brightness) {
32050 cimg_init_scanline(color,opacity);
32051 const float nbrightness = brightness<0?0:(brightness>2?2:brightness);
32052 int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2;
32056 if (ny0<
height() && ny2>=0) {
32057 if ((nx1 - nx0)*(ny2 - ny0) - (nx2 - nx0)*(ny1 - ny0)<0)
32058 _cimg_for_triangle1(*
this,xl,xr,y,nx0,ny0,nx1,ny1,nx2,ny2)
32059 cimg_draw_scanline(xl,xr,y,color,opacity,nbrightness);
32061 _cimg_for_triangle1(*this,xl,xr,y,nx0,ny0,nx1,ny1,nx2,ny2)
32062 cimg_draw_scanline(xr,xl,y,color,opacity,nbrightness);
32078 template<typename tc>
32080 const
int x1, const
int y1,
32081 const
int x2, const
int y2,
32082 const tc *const color, const
float opacity=1) {
32086 "draw_triangle(): Specified color is (null).",
32088 _draw_triangle(x0,y0,x1,y1,x2,y2,color,opacity,1);
32104 template<
typename tc>
32106 const int x1,
const int y1,
32107 const int x2,
const int y2,
32108 const tc *
const color,
const float opacity,
32109 const unsigned int pattern) {
32113 "draw_triangle(): Specified color is (null).",
32115 draw_line(x0,y0,x1,y1,color,opacity,pattern,
true).
32116 draw_line(x1,y1,x2,y2,color,opacity,pattern,
false).
32117 draw_line(x2,y2,x0,y0,color,opacity,pattern,
false);
32137 template<
typename tz,
typename tc>
32139 const int x0,
const int y0,
const float z0,
32140 const int x1,
const int y1,
const float z1,
32141 const int x2,
const int y2,
const float z2,
32142 const tc *
const color,
const float opacity=1,
32143 const float brightness=1) {
32144 typedef typename cimg::superset<tz,float>::type tzfloat;
32145 if (
is_empty() || z0<=0 || z1<=0 || z2<=0)
return *
this;
32148 "draw_triangle(): Specified color is (null).",
32152 "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have "
32153 "different dimensions.",
32155 zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data);
32159 nbrightness = brightness<0?0:(brightness>2?2:brightness);
32160 const long whd = (long)_width*_height*_depth, offx = _spectrum*whd;
32161 int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2;
32162 tzfloat nz0 = 1/(tzfloat)z0, nz1 = 1/(tzfloat)z1, nz2 = 1/(tzfloat)z2;
32163 if (ny0>ny1)
cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1);
32164 if (ny0>ny2)
cimg::swap(nx0,nx2,ny0,ny2,nz0,nz2);
32165 if (ny1>ny2)
cimg::swap(nx1,nx2,ny1,ny2,nz1,nz2);
32166 if (ny0>=
height() || ny2<0)
return *
this;
32168 pzl = (nz1 - nz0)/(ny1 - ny0),
32169 pzr = (nz2 - nz0)/(ny2 - ny0),
32170 pzn = (nz2 - nz1)/(ny2 - ny1),
32171 zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)),
32172 zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1)));
32173 _cimg_for_triangle1(*
this,xleft0,xright0,y,nx0,ny0,nx1,ny1,nx2,ny2) {
32174 if (y==ny1) { zl = nz1; pzl = pzn; }
32175 int xleft = xleft0, xright = xright0;
32176 tzfloat zleft = zl, zright = zr;
32177 if (xright<xleft)
cimg::swap(xleft,xright,zleft,zright);
32178 const int dx = xright - xleft;
32179 const tzfloat pentez = (zright - zleft)/dx;
32180 if (xleft<0 && dx) zleft-=xleft*(zright - zleft)/dx;
32181 if (xleft<0) xleft = 0;
32182 if (xright>=
width()-1) xright =
width() - 1;
32183 T* ptrd =
data(xleft,y,0,0);
32184 tz *ptrz = zbuffer.data(xleft,y);
32186 if (nbrightness==1)
for (
int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) {
32187 if (zleft>=(tzfloat)*ptrz) {
32189 const tc *col = color; cimg_forC(*
this,c) { *ptrd = (T)*(col++); ptrd+=whd; }
32193 }
else if (nbrightness<1)
for (
int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) {
32194 if (zleft>=(tzfloat)*ptrz) {
32196 const tc *col = color; cimg_forC(*
this,c) { *ptrd = (T)(nbrightness*(*col++)); ptrd+=whd; }
32200 }
else for (
int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) {
32201 if (zleft>=(tzfloat)*ptrz) {
32203 const tc *col = color;
32204 cimg_forC(*
this,c) { *ptrd = (T)((2-nbrightness)**(col++) + (nbrightness-1)*maxval); ptrd+=whd; }
32210 if (nbrightness==1)
for (
int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) {
32211 if (zleft>=(tzfloat)*ptrz) {
32213 const tc *col = color; cimg_forC(*
this,c) { *ptrd = (T)(nopacity**(col++) + *ptrd*copacity); ptrd+=whd; }
32217 }
else if (nbrightness<1)
for (
int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) {
32218 if (zleft>=(tzfloat)*ptrz) {
32220 const tc *col = color;
32221 cimg_forC(*
this,c) { *ptrd = (T)(nopacity*nbrightness**(col++) + *ptrd*copacity); ptrd+=whd; }
32225 }
else for (
int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) {
32226 if (zleft>=(tzfloat)*ptrz) {
32228 const tc *col = color;
32229 cimg_forC(*
this,c) {
32230 const T val = (T)((2-nbrightness)**(col++) + (nbrightness-1)*maxval);
32231 *ptrd = (T)(nopacity*val + *ptrd*copacity);
32258 template<
typename tc>
32260 const int x1,
const int y1,
32261 const int x2,
const int y2,
32262 const tc *
const color,
32263 const float brightness0,
32264 const float brightness1,
32265 const float brightness2,
32266 const float opacity=1) {
32270 "draw_triangle(): Specified color is (null).",
32274 const long whd = (long)_width*_height*_depth, offx = _spectrum*whd-1;
32275 int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
32276 nc0 = (int)((brightness0<0.0f?0.0f:(brightness0>2.0f?2.0f:brightness0))*256.0f),
32277 nc1 = (int)((brightness1<0.0f?0.0f:(brightness1>2.0f?2.0f:brightness1))*256.0f),
32278 nc2 = (int)((brightness2<0.0f?0.0f:(brightness2>2.0f?2.0f:brightness2))*256.0f);
32279 if (ny0>ny1)
cimg::swap(nx0,nx1,ny0,ny1,nc0,nc1);
32280 if (ny0>ny2)
cimg::swap(nx0,nx2,ny0,ny2,nc0,nc2);
32281 if (ny1>ny2)
cimg::swap(nx1,nx2,ny1,ny2,nc1,nc2);
32282 if (ny0>=
height() || ny2<0)
return *
this;
32283 _cimg_for_triangle2(*
this,xleft0,cleft0,xright0,cright0,y,nx0,ny0,nc0,nx1,ny1,nc1,nx2,ny2,nc2) {
32284 int xleft = xleft0, xright = xright0, cleft = cleft0, cright = cright0;
32285 if (xright<xleft)
cimg::swap(xleft,xright,cleft,cright);
32287 dx = xright - xleft,
32288 dc = cright>cleft?cright - cleft:cleft - cright,
32289 rc = dx?(cright - cleft)/dx:0,
32290 sc = cright>cleft?1:-1,
32291 ndc = dc-(dx?dx*(dc/dx):0);
32293 if (xleft<0 && dx) cleft-=xleft*(cright - cleft)/dx;
32294 if (xleft<0) xleft = 0;
32295 if (xright>=
width()-1) xright =
width() - 1;
32296 T* ptrd =
data(xleft,y);
32297 if (opacity>=1)
for (
int x = xleft; x<=xright; ++x) {
32298 const tc *col = color;
32299 cimg_forC(*
this,c) {
32300 *ptrd = (T)(cleft<256?cleft**(col++)/256:((512-cleft)**(col++)+(cleft-256)*maxval)/256);
32304 cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0);
32305 }
else for (
int x = xleft; x<=xright; ++x) {
32306 const tc *col = color;
32307 cimg_forC(*
this,c) {
32308 const T val = (T)(cleft<256?cleft**(col++)/256:((512-cleft)**(col++)+(cleft-256)*maxval)/256);
32309 *ptrd = (T)(nopacity*val + *ptrd*copacity);
32313 cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0);
32320 template<
typename tz,
typename tc>
32322 const int x0,
const int y0,
const float z0,
32323 const int x1,
const int y1,
const float z1,
32324 const int x2,
const int y2,
const float z2,
32325 const tc *
const color,
32326 const float brightness0,
32327 const float brightness1,
32328 const float brightness2,
32329 const float opacity=1) {
32330 typedef typename cimg::superset<tz,float>::type tzfloat;
32331 if (
is_empty() || z0<=0 || z1<=0 || z2<=0)
return *
this;
32334 "draw_triangle(): Specified color is (null).",
32338 "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have "
32339 "different dimensions.",
32341 zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data);
32344 const long whd = (long)_width*_height*_depth, offx = _spectrum*whd;
32345 int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
32346 nc0 = (int)((brightness0<0.0f?0.0f:(brightness0>2.0f?2.0f:brightness0))*256.0f),
32347 nc1 = (int)((brightness1<0.0f?0.0f:(brightness1>2.0f?2.0f:brightness1))*256.0f),
32348 nc2 = (int)((brightness2<0.0f?0.0f:(brightness2>2.0f?2.0f:brightness2))*256.0f);
32349 tzfloat nz0 = 1/(tzfloat)z0, nz1 = 1/(tzfloat)z1, nz2 = 1/(tzfloat)z2;
32350 if (ny0>ny1)
cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1,nc0,nc1);
32351 if (ny0>ny2)
cimg::swap(nx0,nx2,ny0,ny2,nz0,nz2,nc0,nc2);
32352 if (ny1>ny2)
cimg::swap(nx1,nx2,ny1,ny2,nz1,nz2,nc1,nc2);
32353 if (ny0>=
height() || ny2<0)
return *
this;
32355 pzl = (nz1 - nz0)/(ny1 - ny0),
32356 pzr = (nz2 - nz0)/(ny2 - ny0),
32357 pzn = (nz2 - nz1)/(ny2 - ny1),
32358 zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)),
32359 zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1)));
32360 _cimg_for_triangle2(*
this,xleft0,cleft0,xright0,cright0,y,nx0,ny0,nc0,nx1,ny1,nc1,nx2,ny2,nc2) {
32361 if (y==ny1) { zl = nz1; pzl = pzn; }
32362 int xleft = xleft0, xright = xright0, cleft = cleft0, cright = cright0;
32363 tzfloat zleft = zl, zright = zr;
32364 if (xright<xleft)
cimg::swap(xleft,xright,zleft,zright,cleft,cright);
32366 dx = xright - xleft,
32367 dc = cright>cleft?cright - cleft:cleft - cright,
32368 rc = dx?(cright-cleft)/dx:0,
32369 sc = cright>cleft?1:-1,
32370 ndc = dc-(dx?dx*(dc/dx):0);
32371 const tzfloat pentez = (zright - zleft)/dx;
32373 if (xleft<0 && dx) {
32374 cleft-=xleft*(cright - cleft)/dx;
32375 zleft-=xleft*(zright - zleft)/dx;
32377 if (xleft<0) xleft = 0;
32379 T *ptrd =
data(xleft,y);
32380 tz *ptrz = zbuffer.data(xleft,y);
32381 if (opacity>=1)
for (
int x = xleft; x<=xright; ++x, ++ptrd, ++ptrz) {
32382 if (zleft>=(tzfloat)*ptrz) {
32384 const tc *col = color;
32385 cimg_forC(*
this,c) {
32386 *ptrd = (T)(cleft<256?cleft**(col++)/256:((512-cleft)**(col++)+(cleft-256)*maxval)/256);
32392 cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0);
32393 }
else for (
int x = xleft; x<=xright; ++x, ++ptrd, ++ptrz) {
32394 if (zleft>=(tzfloat)*ptrz) {
32396 const tc *col = color;
32397 cimg_forC(*
this,c) {
32398 const T val = (T)(cleft<256?cleft**(col++)/256:((512-cleft)**(col++)+(cleft-256)*maxval)/256);
32399 *ptrd = (T)(nopacity*val + *ptrd*copacity);
32405 cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0);
32425 template<
typename tc1,
typename tc2,
typename tc3>
32427 const int x1,
const int y1,
32428 const int x2,
const int y2,
32429 const tc1 *
const color1,
32430 const tc2 *
const color2,
32431 const tc3 *
const color3,
32432 const float opacity=1) {
32433 const unsigned char one = 1;
32435 get_shared_channel(c).draw_triangle(x0,y0,x1,y1,x2,y2,&one,color1[c],color2[c],color3[c],opacity);
32457 template<
typename tc>
32459 const int x1,
const int y1,
32460 const int x2,
const int y2,
32462 const int tx0,
const int ty0,
32463 const int tx1,
const int ty1,
32464 const int tx2,
const int ty2,
32465 const float opacity=1,
32466 const float brightness=1) {
32468 if (texture._depth>1 || texture._spectrum<_spectrum)
32470 "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).",
32472 texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
32474 return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness);
32478 nbrightness = brightness<0?0:(brightness>2?2:brightness);
32479 const long whd = (long)_width*_height*_depth, twhd = (
long)texture._width*texture._height*texture._depth,
32480 offx = _spectrum*whd-1;
32481 int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
32482 ntx0 = tx0, nty0 = ty0, ntx1 = tx1, nty1 = ty1, ntx2 = tx2, nty2 = ty2;
32483 if (ny0>ny1)
cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1);
32484 if (ny0>ny2)
cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2);
32485 if (ny1>ny2)
cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2);
32486 if (ny0>=
height() || ny2<0)
return *
this;
32487 _cimg_for_triangle3(*
this,xleft0,txleft0,tyleft0,xright0,txright0,tyright0,y,
32488 nx0,ny0,ntx0,nty0,nx1,ny1,ntx1,nty1,nx2,ny2,ntx2,nty2) {
32490 xleft = xleft0, xright = xright0,
32491 txleft = txleft0, txright = txright0,
32492 tyleft = tyleft0, tyright = tyright0;
32493 if (xright<xleft)
cimg::swap(xleft,xright,txleft,txright,tyleft,tyright);
32495 dx = xright - xleft,
32496 dtx = txright>txleft?txright - txleft:txleft - txright,
32497 dty = tyright>tyleft?tyright - tyleft:tyleft - tyright,
32498 rtx = dx?(txright - txleft)/dx:0,
32499 rty = dx?(tyright - tyleft)/dx:0,
32500 stx = txright>txleft?1:-1,
32501 sty = tyright>tyleft?1:-1,
32502 ndtx = dtx - (dx?dx*(dtx/dx):0),
32503 ndty = dty - (dx?dx*(dty/dx):0);
32504 int errtx = dx>>1, errty = errtx;
32505 if (xleft<0 && dx) {
32506 txleft-=xleft*(txright - txleft)/dx;
32507 tyleft-=xleft*(tyright - tyleft)/dx;
32509 if (xleft<0) xleft = 0;
32511 T* ptrd =
data(xleft,y,0,0);
32513 if (nbrightness==1)
for (
int x = xleft; x<=xright; ++x) {
32514 const tc *col = texture.data(txleft,tyleft);
32515 cimg_forC(*
this,c) {
32517 ptrd+=whd; col+=twhd;
32520 txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0);
32521 tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0);
32522 }
else if (nbrightness<1)
for (
int x = xleft; x<=xright; ++x) {
32523 const tc *col = texture.data(txleft,tyleft);
32524 cimg_forC(*
this,c) {
32525 *ptrd = (T)(nbrightness**col);
32526 ptrd+=whd; col+=twhd;
32529 txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0);
32530 tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0);
32531 }
else for (
int x = xleft; x<=xright; ++x) {
32532 const tc *col = texture.data(txleft,tyleft);
32533 cimg_forC(*
this,c) {
32534 *ptrd = (T)((2-nbrightness)**(col++) + (nbrightness-1)*maxval);
32535 ptrd+=whd; col+=twhd;
32538 txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0);
32539 tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0);
32542 if (nbrightness==1)
for (
int x = xleft; x<=xright; ++x) {
32543 const tc *col = texture.data(txleft,tyleft);
32544 cimg_forC(*
this,c) {
32545 *ptrd = (T)(nopacity**col + *ptrd*copacity);
32546 ptrd+=whd; col+=twhd;
32549 txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0);
32550 tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0);
32551 }
else if (nbrightness<1)
for (
int x = xleft; x<=xright; ++x) {
32552 const tc *col = texture.data(txleft,tyleft);
32553 cimg_forC(*
this,c) {
32554 *ptrd = (T)(nopacity*nbrightness**col + *ptrd*copacity);
32555 ptrd+=whd; col+=twhd;
32558 txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0);
32559 tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0);
32560 }
else for (
int x = xleft; x<=xright; ++x) {
32561 const tc *col = texture.data(txleft,tyleft);
32562 cimg_forC(*
this,c) {
32563 const T val = (T)((2-nbrightness)**(col++) + (nbrightness-1)*maxval);
32564 *ptrd = (T)(nopacity*val + *ptrd*copacity);
32565 ptrd+=whd; col+=twhd;
32568 txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0);
32569 tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0);
32577 template<
typename tc>
32579 const int x1,
const int y1,
const float z1,
32580 const int x2,
const int y2,
const float z2,
32582 const int tx0,
const int ty0,
32583 const int tx1,
const int ty1,
32584 const int tx2,
const int ty2,
32585 const float opacity=1,
32586 const float brightness=1) {
32587 if (
is_empty() || z0<=0 || z1<=0 || z2<=0)
return *
this;
32588 if (texture._depth>1 || texture._spectrum<_spectrum)
32590 "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).",
32592 texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
32594 return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness);
32598 nbrightness = brightness<0?0:(brightness>2?2:brightness);
32599 const long whd = (long)_width*_height*_depth, twhd = (
long)texture._width*texture._height*texture._depth,
32600 offx = _spectrum*whd-1;
32601 int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2;
32603 ntx0 = tx0/z0, nty0 = ty0/z0,
32604 ntx1 = tx1/z1, nty1 = ty1/z1,
32605 ntx2 = tx2/z2, nty2 = ty2/z2,
32606 nz0 = 1/z0, nz1 = 1/z1, nz2 = 1/z2;
32607 if (ny0>ny1)
cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nz0,nz1);
32608 if (ny0>ny2)
cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nz0,nz2);
32609 if (ny1>ny2)
cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nz1,nz2);
32610 if (ny0>=
height() || ny2<0)
return *
this;
32612 ptxl = (ntx1 - ntx0)/(ny1 - ny0),
32613 ptxr = (ntx2 - ntx0)/(ny2 - ny0),
32614 ptxn = (ntx2 - ntx1)/(ny2 - ny1),
32615 ptyl = (nty1 - nty0)/(ny1 - ny0),
32616 ptyr = (nty2 - nty0)/(ny2 - ny0),
32617 ptyn = (nty2 - nty1)/(ny2 - ny1),
32618 pzl = (nz1 - nz0)/(ny1 - ny0),
32619 pzr = (nz2 - nz0)/(ny2 - ny0),
32620 pzn = (nz2 - nz1)/(ny2 - ny1),
32621 zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)),
32622 txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)),
32623 tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)),
32624 zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))),
32625 txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))):
32626 (ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))),
32627 tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))):
32628 (ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1)));
32629 _cimg_for_triangle1(*
this,xleft0,xright0,y,nx0,ny0,nx1,ny1,nx2,ny2) {
32630 if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; }
32631 int xleft = xleft0, xright = xright0;
32633 zleft = zl, zright = zr,
32634 txleft = txl, txright = txr,
32635 tyleft = tyl, tyright = tyr;
32636 if (xright<xleft)
cimg::swap(xleft,xright,zleft,zright,txleft,txright,tyleft,tyright);
32637 const int dx = xright - xleft;
32639 pentez = (zright - zleft)/dx,
32640 pentetx = (txright - txleft)/dx,
32641 pentety = (tyright - tyleft)/dx;
32642 if (xleft<0 && dx) {
32643 zleft-=xleft*(zright - zleft)/dx;
32644 txleft-=xleft*(txright - txleft)/dx;
32645 tyleft-=xleft*(tyright - tyleft)/dx;
32647 if (xleft<0) xleft = 0;
32649 T* ptrd =
data(xleft,y,0,0);
32651 if (nbrightness==1)
for (
int x = xleft; x<=xright; ++x) {
32652 const float invz = 1/zleft;
32653 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
32654 cimg_forC(*
this,c) {
32656 ptrd+=whd; col+=twhd;
32658 ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
32659 }
else if (nbrightness<1)
for (
int x=xleft; x<=xright; ++x) {
32660 const float invz = 1/zleft;
32661 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
32662 cimg_forC(*
this,c) {
32663 *ptrd = (T)(nbrightness**col);
32664 ptrd+=whd; col+=twhd;
32666 ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
32667 }
else for (
int x = xleft; x<=xright; ++x) {
32668 const float invz = 1/zleft;
32669 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
32670 cimg_forC(*
this,c) {
32671 *ptrd = (T)((2-nbrightness)**col + (nbrightness-1)*maxval);
32672 ptrd+=whd; col+=twhd;
32674 ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
32677 if (nbrightness==1)
for (
int x = xleft; x<=xright; ++x) {
32678 const float invz = 1/zleft;
32679 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
32680 cimg_forC(*
this,c) {
32681 *ptrd = (T)(nopacity**col + *ptrd*copacity);
32682 ptrd+=whd; col+=twhd;
32684 ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
32685 }
else if (nbrightness<1)
for (
int x = xleft; x<=xright; ++x) {
32686 const float invz = 1/zleft;
32687 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
32688 cimg_forC(*
this,c) {
32689 *ptrd = (T)(nopacity*nbrightness**col + *ptrd*copacity);
32690 ptrd+=whd; col+=twhd;
32692 ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
32693 }
else for (
int x = xleft; x<=xright; ++x) {
32694 const float invz = 1/zleft;
32695 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
32696 cimg_forC(*
this,c) {
32697 const T val = (T)((2-nbrightness)**col + (nbrightness-1)*maxval);
32698 *ptrd = (T)(nopacity*val + *ptrd*copacity);
32699 ptrd+=whd; col+=twhd;
32701 ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
32704 zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl;
32710 template<
typename tz,
typename tc>
32712 const int x0,
const int y0,
const float z0,
32713 const int x1,
const int y1,
const float z1,
32714 const int x2,
const int y2,
const float z2,
32716 const int tx0,
const int ty0,
32717 const int tx1,
const int ty1,
32718 const int tx2,
const int ty2,
32719 const float opacity=1,
32720 const float brightness=1) {
32721 typedef typename cimg::superset<tz,float>::type tzfloat;
32722 if (
is_empty() || z0<=0 || z1<=0 || z2<=0)
return *
this;
32725 "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have "
32726 "different dimensions.",
32728 zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data);
32730 if (texture._depth>1 || texture._spectrum<_spectrum)
32732 "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).",
32734 texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
32736 return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness);
32740 nbrightness = brightness<0?0:(brightness>2?2:brightness);
32741 const long whd = (long)_width*_height*_depth, twhd = (
long)texture._width*texture._height*texture._depth,
32742 offx = _spectrum*whd;
32743 int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2;
32745 ntx0 = tx0/z0, nty0 = ty0/z0,
32746 ntx1 = tx1/z1, nty1 = ty1/z1,
32747 ntx2 = tx2/z2, nty2 = ty2/z2;
32748 tzfloat nz0 = 1/(tzfloat)z0, nz1 = 1/(tzfloat)z1, nz2 = 1/(tzfloat)z2;
32749 if (ny0>ny1)
cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nz0,nz1);
32750 if (ny0>ny2)
cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nz0,nz2);
32751 if (ny1>ny2)
cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nz1,nz2);
32752 if (ny0>=
height() || ny2<0)
return *
this;
32754 ptxl = (ntx1 - ntx0)/(ny1 - ny0),
32755 ptxr = (ntx2 - ntx0)/(ny2 - ny0),
32756 ptxn = (ntx2 - ntx1)/(ny2 - ny1),
32757 ptyl = (nty1 - nty0)/(ny1 - ny0),
32758 ptyr = (nty2 - nty0)/(ny2 - ny0),
32759 ptyn = (nty2 - nty1)/(ny2 - ny1),
32760 txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)),
32761 tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)),
32762 txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))):
32763 (ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))),
32764 tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))):
32765 (ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1)));
32767 pzl = (nz1 - nz0)/(ny1 - ny0),
32768 pzr = (nz2 - nz0)/(ny2 - ny0),
32769 pzn = (nz2 - nz1)/(ny2 - ny1),
32770 zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)),
32771 zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1)));
32772 _cimg_for_triangle1(*
this,xleft0,xright0,y,nx0,ny0,nx1,ny1,nx2,ny2) {
32773 if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; }
32774 int xleft = xleft0, xright = xright0;
32775 float txleft = txl, txright = txr, tyleft = tyl, tyright = tyr;
32776 tzfloat zleft = zl, zright = zr;
32777 if (xright<xleft)
cimg::swap(xleft,xright,zleft,zright,txleft,txright,tyleft,tyright);
32778 const int dx = xright - xleft;
32779 const float pentetx = (txright - txleft)/dx, pentety = (tyright - tyleft)/dx;
32780 const tzfloat pentez = (zright - zleft)/dx;
32781 if (xleft<0 && dx) {
32782 zleft-=xleft*(zright - zleft)/dx;
32783 txleft-=xleft*(txright - txleft)/dx;
32784 tyleft-=xleft*(tyright - tyleft)/dx;
32786 if (xleft<0) xleft = 0;
32788 T *ptrd =
data(xleft,y,0,0);
32789 tz *ptrz = zbuffer.data(xleft,y);
32791 if (nbrightness==1)
for (
int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) {
32792 if (zleft>=(tzfloat)*ptrz) {
32794 const tzfloat invz = 1/zleft;
32795 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
32796 cimg_forC(*
this,c) {
32798 ptrd+=whd; col+=twhd;
32802 zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
32803 }
else if (nbrightness<1)
for (
int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) {
32804 if (zleft>=(tzfloat)*ptrz) {
32806 const tzfloat invz = 1/zleft;
32807 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
32808 cimg_forC(*
this,c) {
32809 *ptrd = (T)(nbrightness**col);
32810 ptrd+=whd; col+=twhd;
32814 zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
32815 }
else for (
int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) {
32816 if (zleft>=(tzfloat)*ptrz) {
32818 const tzfloat invz = 1/zleft;
32819 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
32820 cimg_forC(*
this,c) {
32821 *ptrd = (T)((2-nbrightness)**col + (nbrightness-1)*maxval);
32822 ptrd+=whd; col+=twhd;
32826 zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
32829 if (nbrightness==1)
for (
int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) {
32830 if (zleft>=(tzfloat)*ptrz) {
32832 const tzfloat invz = 1/zleft;
32833 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
32834 cimg_forC(*
this,c) {
32835 *ptrd = (T)(nopacity**col + *ptrd*copacity);
32836 ptrd+=whd; col+=twhd;
32840 zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
32841 }
else if (nbrightness<1)
for (
int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) {
32842 if (zleft>=(tzfloat)*ptrz) {
32844 const tzfloat invz = 1/zleft;
32845 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
32846 cimg_forC(*
this,c) {
32847 *ptrd = (T)(nopacity*nbrightness**col + *ptrd*copacity);
32848 ptrd+=whd; col+=twhd;
32852 zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
32853 }
else for (
int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) {
32854 if (zleft>=(tzfloat)*ptrz) {
32856 const tzfloat invz = 1/zleft;
32857 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
32858 cimg_forC(*
this,c) {
32859 const T val = (T)((2-nbrightness)**col + (nbrightness-1)*maxval);
32860 *ptrd = (T)(nopacity*val + *ptrd*copacity);
32861 ptrd+=whd; col+=twhd;
32865 zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
32868 zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl;
32891 template<
typename tc,
typename tl>
32893 const int x1,
const int y1,
32894 const int x2,
const int y2,
32895 const tc *
const color,
32897 const int lx0,
const int ly0,
32898 const int lx1,
const int ly1,
32899 const int lx2,
const int ly2,
32900 const float opacity=1) {
32904 "draw_triangle(): Specified color is (null).",
32906 if (light._depth>1 || light._spectrum<_spectrum)
32908 "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).",
32909 cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data);
32910 if (
is_overlapped(light))
return draw_triangle(x0,y0,x1,y1,x2,y2,color,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
32913 int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
32914 nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2;
32915 const long whd = (long)_width*_height*_depth, offx = _spectrum*whd-1;
32916 if (ny0>ny1)
cimg::swap(nx0,nx1,ny0,ny1,nlx0,nlx1,nly0,nly1);
32917 if (ny0>ny2)
cimg::swap(nx0,nx2,ny0,ny2,nlx0,nlx2,nly0,nly2);
32918 if (ny1>ny2)
cimg::swap(nx1,nx2,ny1,ny2,nlx1,nlx2,nly1,nly2);
32919 if (ny0>=
height() || ny2<0)
return *
this;
32920 _cimg_for_triangle3(*
this,xleft0,lxleft0,lyleft0,xright0,lxright0,lyright0,y,
32921 nx0,ny0,nlx0,nly0,nx1,ny1,nlx1,nly1,nx2,ny2,nlx2,nly2) {
32923 xleft = xleft0, xright = xright0,
32924 lxleft = lxleft0, lxright = lxright0,
32925 lyleft = lyleft0, lyright = lyright0;
32926 if (xright<xleft)
cimg::swap(xleft,xright,lxleft,lxright,lyleft,lyright);
32928 dx = xright - xleft,
32929 dlx = lxright>lxleft?lxright - lxleft:lxleft - lxright,
32930 dly = lyright>lyleft?lyright - lyleft:lyleft - lyright,
32931 rlx = dx?(lxright - lxleft)/dx:0,
32932 rly = dx?(lyright - lyleft)/dx:0,
32933 slx = lxright>lxleft?1:-1,
32934 sly = lyright>lyleft?1:-1,
32935 ndlx = dlx - (dx?dx*(dlx/dx):0),
32936 ndly = dly - (dx?dx*(dly/dx):0);
32937 int errlx = dx>>1, errly = errlx;
32938 if (xleft<0 && dx) {
32939 lxleft-=xleft*(lxright - lxleft)/dx;
32940 lyleft-=xleft*(lyright - lyleft)/dx;
32942 if (xleft<0) xleft = 0;
32944 T* ptrd =
data(xleft,y,0,0);
32945 if (opacity>=1)
for (
int x = xleft; x<=xright; ++x) {
32946 const tc *col = color;
32947 cimg_forC(*
this,c) {
32948 const tl l = light(lxleft,lyleft,c);
32949 *ptrd = (T)(l<1?l**(col++):((2-l)**(col++)+(l-1)*maxval));
32953 lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0);
32954 lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0);
32955 }
else for (
int x = xleft; x<=xright; ++x) {
32956 const tc *col = color;
32957 cimg_forC(*
this,c) {
32958 const tl l = light(lxleft,lyleft,c);
32959 const T val = (T)(l<1?l**(col++):((2-l)**(col++)+(l-1)*maxval));
32960 *ptrd = (T)(nopacity*val + *ptrd*copacity);
32964 lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0);
32965 lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0);
32972 template<
typename tz,
typename tc,
typename tl>
32974 const int x0,
const int y0,
const float z0,
32975 const int x1,
const int y1,
const float z1,
32976 const int x2,
const int y2,
const float z2,
32977 const tc *
const color,
32979 const int lx0,
const int ly0,
32980 const int lx1,
const int ly1,
32981 const int lx2,
const int ly2,
32982 const float opacity=1) {
32983 typedef typename cimg::superset<tz,float>::type tzfloat;
32984 if (
is_empty() || z0<=0 || z1<=0 || z2<=0)
return *
this;
32987 "draw_triangle(): Specified color is (null).",
32989 if (light._depth>1 || light._spectrum<_spectrum)
32991 "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).",
32992 cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data);
32995 "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have "
32996 "different dimensions.",
32998 zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data);
32999 if (
is_overlapped(light))
return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,
33000 +light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
33003 const long whd = (long)_width*_height*_depth, offx = _spectrum*whd;
33004 int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
33005 nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2;
33006 tzfloat nz0 = 1/(tzfloat)z0, nz1 = 1/(tzfloat)z1, nz2 = 1/(tzfloat)z2;
33007 if (ny0>ny1)
cimg::swap(nx0,nx1,ny0,ny1,nlx0,nlx1,nly0,nly1,nz0,nz1);
33008 if (ny0>ny2)
cimg::swap(nx0,nx2,ny0,ny2,nlx0,nlx2,nly0,nly2,nz0,nz2);
33009 if (ny1>ny2)
cimg::swap(nx1,nx2,ny1,ny2,nlx1,nlx2,nly1,nly2,nz1,nz2);
33010 if (ny0>=
height() || ny2<0)
return *
this;
33012 pzl = (nz1 - nz0)/(ny1 - ny0),
33013 pzr = (nz2 - nz0)/(ny2 - ny0),
33014 pzn = (nz2 - nz1)/(ny2 - ny1),
33015 zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)),
33016 zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1)));
33017 _cimg_for_triangle3(*
this,xleft0,lxleft0,lyleft0,xright0,lxright0,lyright0,y,
33018 nx0,ny0,nlx0,nly0,nx1,ny1,nlx1,nly1,nx2,ny2,nlx2,nly2) {
33019 if (y==ny1) { zl = nz1; pzl = pzn; }
33021 xleft = xleft0, xright = xright0,
33022 lxleft = lxleft0, lxright = lxright0,
33023 lyleft = lyleft0, lyright = lyright0;
33024 tzfloat zleft = zl, zright = zr;
33025 if (xright<xleft)
cimg::swap(xleft,xright,zleft,zright,lxleft,lxright,lyleft,lyright);
33027 dx = xright - xleft,
33028 dlx = lxright>lxleft?lxright - lxleft:lxleft - lxright,
33029 dly = lyright>lyleft?lyright - lyleft:lyleft - lyright,
33030 rlx = dx?(lxright - lxleft)/dx:0,
33031 rly = dx?(lyright - lyleft)/dx:0,
33032 slx = lxright>lxleft?1:-1,
33033 sly = lyright>lyleft?1:-1,
33034 ndlx = dlx - (dx?dx*(dlx/dx):0),
33035 ndly = dly - (dx?dx*(dly/dx):0);
33036 const tzfloat pentez = (zright - zleft)/dx;
33037 int errlx = dx>>1, errly = errlx;
33038 if (xleft<0 && dx) {
33039 zleft-=xleft*(zright - zleft)/dx;
33040 lxleft-=xleft*(lxright - lxleft)/dx;
33041 lyleft-=xleft*(lyright - lyleft)/dx;
33043 if (xleft<0) xleft = 0;
33045 T *ptrd =
data(xleft,y,0,0);
33046 tz *ptrz = zbuffer.data(xleft,y);
33047 if (opacity>=1)
for (
int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) {
33048 if (zleft>=(tzfloat)*ptrz) {
33050 const tc *col = color;
33051 cimg_forC(*
this,c) {
33052 const tl l = light(lxleft,lyleft,c);
33053 const tc cval = *(col++);
33054 *ptrd = (T)(l<1?l*cval:(2-l)*cval+(l-1)*maxval);
33060 lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0);
33061 lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0);
33062 }
else for (
int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) {
33063 if (zleft>=(tzfloat)*ptrz) {
33065 const tc *col = color;
33066 cimg_forC(*
this,c) {
33067 const tl l = light(lxleft,lyleft,c);
33068 const tc cval = *(col++);
33069 const T val = (T)(l<1?l*cval:(2-l)*cval+(l-1)*maxval);
33070 *ptrd = (T)(nopacity*val + *ptrd*copacity);
33076 lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0);
33077 lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0);
33104 template<
typename tc>
33106 const int x1,
const int y1,
33107 const int x2,
const int y2,
33109 const int tx0,
const int ty0,
33110 const int tx1,
const int ty1,
33111 const int tx2,
const int ty2,
33112 const float brightness0,
33113 const float brightness1,
33114 const float brightness2,
33115 const float opacity=1) {
33117 if (texture._depth>1 || texture._spectrum<_spectrum)
33119 "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).",
33121 texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
33123 return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,
33124 brightness0,brightness1,brightness2,opacity);
33127 const long whd = (long)_width*_height*_depth, twhd = (
long)texture._width*texture._height*texture._depth,
33128 offx = _spectrum*whd-1;
33129 int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
33130 ntx0 = tx0, nty0 = ty0, ntx1 = tx1, nty1 = ty1, ntx2 = tx2, nty2 = ty2,
33131 nc0 = (int)((brightness0<0.0f?0.0f:(brightness0>2.0f?2.0f:brightness0))*256.0f),
33132 nc1 = (int)((brightness1<0.0f?0.0f:(brightness1>2.0f?2.0f:brightness1))*256.0f),
33133 nc2 = (int)((brightness2<0.0f?0.0f:(brightness2>2.0f?2.0f:brightness2))*256.0f);
33134 if (ny0>ny1)
cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nc0,nc1);
33135 if (ny0>ny2)
cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nc0,nc2);
33136 if (ny1>ny2)
cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nc1,nc2);
33137 if (ny0>=
height() || ny2<0)
return *
this;
33138 _cimg_for_triangle4(*
this,xleft0,cleft0,txleft0,tyleft0,xright0,cright0,txright0,tyright0,y,
33139 nx0,ny0,nc0,ntx0,nty0,nx1,ny1,nc1,ntx1,nty1,nx2,ny2,nc2,ntx2,nty2) {
33141 xleft = xleft0, xright = xright0,
33142 cleft = cleft0, cright = cright0,
33143 txleft = txleft0, txright = txright0,
33144 tyleft = tyleft0, tyright = tyright0;
33145 if (xright<xleft)
cimg::swap(xleft,xright,cleft,cright,txleft,txright,tyleft,tyright);
33147 dx = xright - xleft,
33148 dc = cright>cleft?cright - cleft:cleft - cright,
33149 dtx = txright>txleft?txright - txleft:txleft - txright,
33150 dty = tyright>tyleft?tyright - tyleft:tyleft - tyright,
33151 rc = dx?(cright - cleft)/dx:0,
33152 rtx = dx?(txright - txleft)/dx:0,
33153 rty = dx?(tyright - tyleft)/dx:0,
33154 sc = cright>cleft?1:-1,
33155 stx = txright>txleft?1:-1,
33156 sty = tyright>tyleft?1:-1,
33157 ndc = dc - (dx?dx*(dc/dx):0),
33158 ndtx = dtx - (dx?dx*(dtx/dx):0),
33159 ndty = dty - (dx?dx*(dty/dx):0);
33160 int errc = dx>>1, errtx = errc, errty = errc;
33161 if (xleft<0 && dx) {
33162 cleft-=xleft*(cright - cleft)/dx;
33163 txleft-=xleft*(txright - txleft)/dx;
33164 tyleft-=xleft*(tyright - tyleft)/dx;
33166 if (xleft<0) xleft = 0;
33168 T* ptrd =
data(xleft,y,0,0);
33169 if (opacity>=1)
for (
int x = xleft; x<=xright; ++x) {
33170 const tc *col = texture.data(txleft,tyleft);
33171 cimg_forC(*
this,c) {
33172 *ptrd = (T)(cleft<256?cleft**col/256:((512-cleft)**col+(cleft-256)*maxval)/256);
33173 ptrd+=whd; col+=twhd;
33176 cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0);
33177 txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0);
33178 tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0);
33179 }
else for (
int x = xleft; x<=xright; ++x) {
33180 const tc *col = texture.data(txleft,tyleft);
33181 cimg_forC(*
this,c) {
33182 const T val = (T)(cleft<256?cleft**col/256:((512-cleft)**col+(cleft-256)*maxval)/256);
33183 *ptrd = (T)(nopacity*val + *ptrd*copacity);
33184 ptrd+=whd; col+=twhd;
33187 cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0);
33188 txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0);
33189 tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0);
33196 template<
typename tc>
33198 const int x1,
const int y1,
const float z1,
33199 const int x2,
const int y2,
const float z2,
33201 const int tx0,
const int ty0,
33202 const int tx1,
const int ty1,
33203 const int tx2,
const int ty2,
33204 const float brightness0,
33205 const float brightness1,
33206 const float brightness2,
33207 const float opacity=1) {
33208 if (
is_empty() || z0<=0 || z1<=0 || z2<=0)
return *
this;
33209 if (texture._depth>1 || texture._spectrum<_spectrum)
33211 "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).",
33213 texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
33214 if (
is_overlapped(texture))
return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,
33215 brightness0,brightness1,brightness2,opacity);
33218 const long whd = (long)_width*_height*_depth, twhd = (
long)texture._width*texture._height*texture._depth,
33219 offx = _spectrum*whd-1;
33220 int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
33221 nc0 = (int)((brightness0<0.0f?0.0f:(brightness0>2.0f?2.0f:brightness0))*256.0f),
33222 nc1 = (int)((brightness1<0.0f?0.0f:(brightness1>2.0f?2.0f:brightness1))*256.0f),
33223 nc2 = (int)((brightness2<0.0f?0.0f:(brightness2>2.0f?2.0f:brightness2))*256.0f);
33225 ntx0 = tx0/z0, nty0 = ty0/z0,
33226 ntx1 = tx1/z1, nty1 = ty1/z1,
33227 ntx2 = tx2/z2, nty2 = ty2/z2,
33228 nz0 = 1/z0, nz1 = 1/z1, nz2 = 1/z2;
33229 if (ny0>ny1)
cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nz0,nz1,nc0,nc1);
33230 if (ny0>ny2)
cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nz0,nz2,nc0,nc2);
33231 if (ny1>ny2)
cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nz1,nz2,nc1,nc2);
33232 if (ny0>=
height() || ny2<0)
return *
this;
33234 ptxl = (ntx1 - ntx0)/(ny1 - ny0),
33235 ptxr = (ntx2 - ntx0)/(ny2 - ny0),
33236 ptxn = (ntx2 - ntx1)/(ny2 - ny1),
33237 ptyl = (nty1 - nty0)/(ny1 - ny0),
33238 ptyr = (nty2 - nty0)/(ny2 - ny0),
33239 ptyn = (nty2 - nty1)/(ny2 - ny1),
33240 pzl = (nz1 - nz0)/(ny1 - ny0),
33241 pzr = (nz2 - nz0)/(ny2 - ny0),
33242 pzn = (nz2 - nz1)/(ny2 - ny1),
33243 zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)),
33244 txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)),
33245 tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)),
33246 zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))),
33247 txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))):
33248 (ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))),
33249 tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))):
33250 (ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1)));
33251 _cimg_for_triangle2(*
this,xleft0,cleft0,xright0,cright0,y,nx0,ny0,nc0,nx1,ny1,nc1,nx2,ny2,nc2) {
33252 if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; }
33254 xleft = xleft0, xright = xright0,
33255 cleft = cleft0, cright = cright0;
33257 zleft = zl, zright = zr,
33258 txleft = txl, txright = txr,
33259 tyleft = tyl, tyright = tyr;
33260 if (xright<xleft)
cimg::swap(xleft,xright,zleft,zright,txleft,txright,tyleft,tyright,cleft,cright);
33262 dx = xright - xleft,
33263 dc = cright>cleft?cright - cleft:cleft - cright,
33264 rc = dx?(cright - cleft)/dx:0,
33265 sc = cright>cleft?1:-1,
33266 ndc = dc - (dx?dx*(dc/dx):0);
33268 pentez = (zright - zleft)/dx,
33269 pentetx = (txright - txleft)/dx,
33270 pentety = (tyright - tyleft)/dx;
33272 if (xleft<0 && dx) {
33273 cleft-=xleft*(cright - cleft)/dx;
33274 zleft-=xleft*(zright - zleft)/dx;
33275 txleft-=xleft*(txright - txleft)/dx;
33276 tyleft-=xleft*(tyright - tyleft)/dx;
33278 if (xleft<0) xleft = 0;
33280 T* ptrd =
data(xleft,y,0,0);
33281 if (opacity>=1)
for (
int x = xleft; x<=xright; ++x) {
33282 const float invz = 1/zleft;
33283 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
33284 cimg_forC(*
this,c) {
33285 *ptrd = (T)(cleft<256?cleft**col/256:((512-cleft)**col+(cleft-256)*maxval)/256);
33286 ptrd+=whd; col+=twhd;
33288 ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
33289 cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0);
33290 }
else for (
int x = xleft; x<=xright; ++x) {
33291 const float invz = 1/zleft;
33292 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
33293 cimg_forC(*
this,c) {
33294 const T val = (T)(cleft<256?cleft**col/256:((512-cleft)**col+(cleft-256)*maxval)/256);
33295 *ptrd = (T)(nopacity*val + *ptrd*copacity);
33296 ptrd+=whd; col+=twhd;
33298 ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
33299 cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0);
33301 zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl;
33307 template<
typename tz,
typename tc>
33309 const int x0,
const int y0,
const float z0,
33310 const int x1,
const int y1,
const float z1,
33311 const int x2,
const int y2,
const float z2,
33313 const int tx0,
const int ty0,
33314 const int tx1,
const int ty1,
33315 const int tx2,
const int ty2,
33316 const float brightness0,
33317 const float brightness1,
33318 const float brightness2,
33319 const float opacity=1) {
33320 typedef typename cimg::superset<tz,float>::type tzfloat;
33321 if (
is_empty() || z0<=0 || z1<=0 || z2<=0)
return *
this;
33324 "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have "
33325 "different dimensions.",
33327 zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data);
33328 if (texture._depth>1 || texture._spectrum<_spectrum)
33330 "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).",
33332 texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
33334 return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,
33335 brightness0,brightness1,brightness2,opacity);
33338 const long whd = (long)_width*_height*_depth, twhd = (
long)texture._width*texture._height*texture._depth,
33339 offx = _spectrum*whd;
33340 int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
33341 nc0 = (int)((brightness0<0.0f?0.0f:(brightness0>2.0f?2.0f:brightness0))*256.0f),
33342 nc1 = (int)((brightness1<0.0f?0.0f:(brightness1>2.0f?2.0f:brightness1))*256.0f),
33343 nc2 = (int)((brightness2<0.0f?0.0f:(brightness2>2.0f?2.0f:brightness2))*256.0f);
33345 ntx0 = tx0/z0, nty0 = ty0/z0,
33346 ntx1 = tx1/z1, nty1 = ty1/z1,
33347 ntx2 = tx2/z2, nty2 = ty2/z2;
33348 tzfloat nz0 = 1/(tzfloat)z0, nz1 = 1/(tzfloat)z1, nz2 = 1/(tzfloat)z2;
33349 if (ny0>ny1)
cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nz0,nz1,nc0,nc1);
33350 if (ny0>ny2)
cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nz0,nz2,nc0,nc2);
33351 if (ny1>ny2)
cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nz1,nz2,nc1,nc2);
33352 if (ny0>=
height() || ny2<0)
return *
this;
33354 ptxl = (ntx1 - ntx0)/(ny1 - ny0),
33355 ptxr = (ntx2 - ntx0)/(ny2 - ny0),
33356 ptxn = (ntx2 - ntx1)/(ny2 - ny1),
33357 ptyl = (nty1 - nty0)/(ny1 - ny0),
33358 ptyr = (nty2 - nty0)/(ny2 - ny0),
33359 ptyn = (nty2 - nty1)/(ny2 - ny1),
33360 txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)),
33361 tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)),
33362 txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))):
33363 (ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))),
33364 tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))):
33365 (ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1)));
33367 pzl = (nz1 - nz0)/(ny1 - ny0),
33368 pzr = (nz2 - nz0)/(ny2 - ny0),
33369 pzn = (nz2 - nz1)/(ny2 - ny1),
33370 zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)),
33371 zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1)));
33372 _cimg_for_triangle2(*
this,xleft0,cleft0,xright0,cright0,y,nx0,ny0,nc0,nx1,ny1,nc1,nx2,ny2,nc2) {
33373 if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; }
33374 int xleft = xleft0, xright = xright0, cleft = cleft0, cright = cright0;
33375 float txleft = txl, txright = txr, tyleft = tyl, tyright = tyr;
33376 tzfloat zleft = zl, zright = zr;
33377 if (xright<xleft)
cimg::swap(xleft,xright,zleft,zright,txleft,txright,tyleft,tyright,cleft,cright);
33379 dx = xright - xleft,
33380 dc = cright>cleft?cright - cleft:cleft - cright,
33381 rc = dx?(cright - cleft)/dx:0,
33382 sc = cright>cleft?1:-1,
33383 ndc = dc - (dx?dx*(dc/dx):0);
33384 float pentetx = (txright - txleft)/dx, pentety = (tyright - tyleft)/dx;
33385 const tzfloat pentez = (zright - zleft)/dx;
33387 if (xleft<0 && dx) {
33388 cleft-=xleft*(cright - cleft)/dx;
33389 zleft-=xleft*(zright - zleft)/dx;
33390 txleft-=xleft*(txright - txleft)/dx;
33391 tyleft-=xleft*(tyright - tyleft)/dx;
33393 if (xleft<0) xleft = 0;
33395 T* ptrd =
data(xleft,y);
33396 tz *ptrz = zbuffer.data(xleft,y);
33397 if (opacity>=1)
for (
int x = xleft; x<=xright; ++x, ++ptrd, ++ptrz) {
33398 if (zleft>=(tzfloat)*ptrz) {
33400 const tzfloat invz = 1/zleft;
33401 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
33402 cimg_forC(*
this,c) {
33403 *ptrd = (T)(cleft<256?cleft**col/256:((512-cleft)**col+(cleft-256)*maxval)/256);
33404 ptrd+=whd; col+=twhd;
33408 zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
33409 cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0);
33410 }
else for (
int x = xleft; x<=xright; ++x, ++ptrd, ++ptrz) {
33411 if (zleft>=(tzfloat)*ptrz) {
33413 const tzfloat invz = 1/zleft;
33414 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
33415 cimg_forC(*
this,c) {
33416 const T val = (T)(cleft<256?cleft**col/256:((512-cleft)**col+(cleft-256)*maxval)/256);
33417 *ptrd = (T)(nopacity*val + *ptrd*copacity);
33418 ptrd+=whd; col+=twhd;
33422 zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
33423 cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0);
33425 zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl;
33454 template<
typename tc,
typename tl>
33456 const int x1,
const int y1,
33457 const int x2,
const int y2,
33459 const int tx0,
const int ty0,
33460 const int tx1,
const int ty1,
33461 const int tx2,
const int ty2,
33463 const int lx0,
const int ly0,
33464 const int lx1,
const int ly1,
33465 const int lx2,
const int ly2,
33466 const float opacity=1) {
33468 if (texture._depth>1 || texture._spectrum<_spectrum)
33470 "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).",
33472 texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
33473 if (light._depth>1 || light._spectrum<_spectrum)
33475 "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).",
33476 cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data);
33478 return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
33480 return draw_triangle(x0,y0,x1,y1,x2,y2,texture,tx0,ty0,tx1,ty1,tx2,ty2,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
33483 const long whd = (long)_width*_height*_depth, twhd = (
long)texture._width*texture._height*texture._depth,
33484 offx = _spectrum*whd-1;
33485 int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
33486 ntx0 = tx0, nty0 = ty0, ntx1 = tx1, nty1 = ty1, ntx2 = tx2, nty2 = ty2,
33487 nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2;
33488 if (ny0>ny1)
cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nlx0,nlx1,nly0,nly1);
33489 if (ny0>ny2)
cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nlx0,nlx2,nly0,nly2);
33490 if (ny1>ny2)
cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nlx1,nlx2,nly1,nly2);
33491 if (ny0>=
height() || ny2<0)
return *
this;
33492 _cimg_for_triangle5(*
this,xleft0,lxleft0,lyleft0,txleft0,tyleft0,xright0,lxright0,lyright0,txright0,tyright0,y,
33493 nx0,ny0,nlx0,nly0,ntx0,nty0,nx1,ny1,nlx1,nly1,ntx1,nty1,nx2,ny2,nlx2,nly2,ntx2,nty2) {
33495 xleft = xleft0, xright = xright0,
33496 lxleft = lxleft0, lxright = lxright0,
33497 lyleft = lyleft0, lyright = lyright0,
33498 txleft = txleft0, txright = txright0,
33499 tyleft = tyleft0, tyright = tyright0;
33500 if (xright<xleft)
cimg::swap(xleft,xright,lxleft,lxright,lyleft,lyright,txleft,txright,tyleft,tyright);
33502 dx = xright - xleft,
33503 dlx = lxright>lxleft?lxright - lxleft:lxleft - lxright,
33504 dly = lyright>lyleft?lyright - lyleft:lyleft - lyright,
33505 dtx = txright>txleft?txright - txleft:txleft - txright,
33506 dty = tyright>tyleft?tyright - tyleft:tyleft - tyright,
33507 rlx = dx?(lxright - lxleft)/dx:0,
33508 rly = dx?(lyright - lyleft)/dx:0,
33509 rtx = dx?(txright - txleft)/dx:0,
33510 rty = dx?(tyright - tyleft)/dx:0,
33511 slx = lxright>lxleft?1:-1,
33512 sly = lyright>lyleft?1:-1,
33513 stx = txright>txleft?1:-1,
33514 sty = tyright>tyleft?1:-1,
33515 ndlx = dlx - (dx?dx*(dlx/dx):0),
33516 ndly = dly - (dx?dx*(dly/dx):0),
33517 ndtx = dtx - (dx?dx*(dtx/dx):0),
33518 ndty = dty - (dx?dx*(dty/dx):0);
33519 int errlx = dx>>1, errly = errlx, errtx = errlx, errty = errlx;
33520 if (xleft<0 && dx) {
33521 lxleft-=xleft*(lxright - lxleft)/dx;
33522 lyleft-=xleft*(lyright - lyleft)/dx;
33523 txleft-=xleft*(txright - txleft)/dx;
33524 tyleft-=xleft*(tyright - tyleft)/dx;
33526 if (xleft<0) xleft = 0;
33528 T* ptrd =
data(xleft,y,0,0);
33529 if (opacity>=1)
for (
int x = xleft; x<=xright; ++x) {
33530 const tc *col = texture.data(txleft,tyleft);
33531 cimg_forC(*
this,c) {
33532 const tl l = light(lxleft,lyleft,c);
33533 *ptrd = (T)(l<1?l**col:(2-l)**col+(l-1)*maxval);
33534 ptrd+=whd; col+=twhd;
33537 lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0);
33538 lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0);
33539 txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0);
33540 tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0);
33541 }
else for (
int x = xleft; x<=xright; ++x) {
33542 const tc *col = texture.data(txleft,tyleft);
33543 cimg_forC(*
this,c) {
33544 const tl l = light(lxleft,lyleft,c);
33545 const T val = (T)(l<1?l**col:(2-l)**col+(l-1)*maxval);
33546 *ptrd = (T)(nopacity*val + *ptrd*copacity);
33547 ptrd+=whd; col+=twhd;
33550 lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0);
33551 lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0);
33552 txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0);
33553 tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0);
33560 template<
typename tc,
typename tl>
33562 const int x1,
const int y1,
const float z1,
33563 const int x2,
const int y2,
const float z2,
33565 const int tx0,
const int ty0,
33566 const int tx1,
const int ty1,
33567 const int tx2,
const int ty2,
33569 const int lx0,
const int ly0,
33570 const int lx1,
const int ly1,
33571 const int lx2,
const int ly2,
33572 const float opacity=1) {
33573 if (
is_empty() || z0<=0 || z1<=0 || z2<=0)
return *
this;
33574 if (texture._depth>1 || texture._spectrum<_spectrum)
33576 "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).",
33578 texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
33579 if (light._depth>1 || light._spectrum<_spectrum)
33581 "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).",
33582 cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data);
33584 return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,
33585 light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
33587 return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,texture,tx0,ty0,tx1,ty1,tx2,ty2,
33588 +light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
33591 const long whd = (long)_width*_height*_depth, twhd = (
long)texture._width*texture._height*texture._depth,
33592 offx = _spectrum*whd-1;
33593 int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
33594 nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2;
33596 ntx0 = tx0/z0, nty0 = ty0/z0,
33597 ntx1 = tx1/z1, nty1 = ty1/z1,
33598 ntx2 = tx2/z2, nty2 = ty2/z2,
33599 nz0 = 1/z0, nz1 = 1/z1, nz2 = 1/z2;
33600 if (ny0>ny1)
cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nlx0,nlx1,nly0,nly1,nz0,nz1);
33601 if (ny0>ny2)
cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nlx0,nlx2,nly0,nly2,nz0,nz2);
33602 if (ny1>ny2)
cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nlx1,nlx2,nly1,nly2,nz1,nz2);
33603 if (ny0>=
height() || ny2<0)
return *
this;
33605 ptxl = (ntx1 - ntx0)/(ny1 - ny0),
33606 ptxr = (ntx2 - ntx0)/(ny2 - ny0),
33607 ptxn = (ntx2 - ntx1)/(ny2 - ny1),
33608 ptyl = (nty1 - nty0)/(ny1 - ny0),
33609 ptyr = (nty2 - nty0)/(ny2 - ny0),
33610 ptyn = (nty2 - nty1)/(ny2 - ny1),
33611 pzl = (nz1 - nz0)/(ny1 - ny0),
33612 pzr = (nz2 - nz0)/(ny2 - ny0),
33613 pzn = (nz2 - nz1)/(ny2 - ny1),
33614 zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)),
33615 txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)),
33616 tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)),
33617 zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))),
33618 txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))):
33619 (ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))),
33620 tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))):
33621 (ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1)));
33622 _cimg_for_triangle3(*
this,xleft0,lxleft0,lyleft0,xright0,lxright0,lyright0,y,
33623 nx0,ny0,nlx0,nly0,nx1,ny1,nlx1,nly1,nx2,ny2,nlx2,nly2) {
33624 if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; }
33626 xleft = xleft0, xright = xright0,
33627 lxleft = lxleft0, lxright = lxright0,
33628 lyleft = lyleft0, lyright = lyright0;
33630 zleft = zl, zright = zr,
33631 txleft = txl, txright = txr,
33632 tyleft = tyl, tyright = tyr;
33634 cimg::swap(xleft,xright,zleft,zright,txleft,txright,tyleft,tyright,lxleft,lxright,lyleft,lyright);
33636 dx = xright - xleft,
33637 dlx = lxright>lxleft?lxright - lxleft:lxleft - lxright,
33638 dly = lyright>lyleft?lyright - lyleft:lyleft - lyright,
33639 rlx = dx?(lxright - lxleft)/dx:0,
33640 rly = dx?(lyright - lyleft)/dx:0,
33641 slx = lxright>lxleft?1:-1,
33642 sly = lyright>lyleft?1:-1,
33643 ndlx = dlx - (dx?dx*(dlx/dx):0),
33644 ndly = dly - (dx?dx*(dly/dx):0);
33646 pentez = (zright - zleft)/dx,
33647 pentetx = (txright - txleft)/dx,
33648 pentety = (tyright - tyleft)/dx;
33649 int errlx = dx>>1, errly = errlx;
33650 if (xleft<0 && dx) {
33651 zleft-=xleft*(zright - zleft)/dx;
33652 lxleft-=xleft*(lxright - lxleft)/dx;
33653 lyleft-=xleft*(lyright - lyleft)/dx;
33654 txleft-=xleft*(txright - txleft)/dx;
33655 tyleft-=xleft*(tyright - tyleft)/dx;
33657 if (xleft<0) xleft = 0;
33659 T* ptrd =
data(xleft,y,0,0);
33660 if (opacity>=1)
for (
int x = xleft; x<=xright; ++x) {
33661 const float invz = 1/zleft;
33662 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
33663 cimg_forC(*
this,c) {
33664 const tl l = light(lxleft,lyleft,c);
33665 *ptrd = (T)(l<1?l**col:(2-l)**col+(l-1)*maxval);
33666 ptrd+=whd; col+=twhd;
33668 ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
33669 lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0);
33670 lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0);
33671 }
else for (
int x = xleft; x<=xright; ++x) {
33672 const float invz = 1/zleft;
33673 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
33674 cimg_forC(*
this,c) {
33675 const tl l = light(lxleft,lyleft,c);
33676 const T val = (T)(l<1?l**col:(2-l)**col+(l-1)*maxval);
33677 *ptrd = (T)(nopacity*val + *ptrd*copacity);
33678 ptrd+=whd; col+=twhd;
33680 ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
33681 lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0);
33682 lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0);
33684 zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl;
33690 template<
typename tz,
typename tc,
typename tl>
33692 const int x0,
const int y0,
const float z0,
33693 const int x1,
const int y1,
const float z1,
33694 const int x2,
const int y2,
const float z2,
33696 const int tx0,
const int ty0,
33697 const int tx1,
const int ty1,
33698 const int tx2,
const int ty2,
33700 const int lx0,
const int ly0,
33701 const int lx1,
const int ly1,
33702 const int lx2,
const int ly2,
33703 const float opacity=1) {
33704 typedef typename cimg::superset<tz,float>::type tzfloat;
33705 if (
is_empty() || z0<=0 || z1<=0 || z2<=0)
return *
this;
33708 "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have "
33709 "different dimensions.",
33711 zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data);
33712 if (texture._depth>1 || texture._spectrum<_spectrum)
33714 "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).",
33716 texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
33717 if (light._depth>1 || light._spectrum<_spectrum)
33719 "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).",
33720 cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data);
33722 return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,
33723 +texture,tx0,ty0,tx1,ty1,tx2,ty2,light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
33725 return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,
33726 texture,tx0,ty0,tx1,ty1,tx2,ty2,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
33729 const long whd = (long)_width*_height*_depth, twhd = (
long)texture._width*texture._height*texture._depth,
33730 offx = _spectrum*whd;
33731 int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
33732 nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2;
33734 ntx0 = tx0/z0, nty0 = ty0/z0,
33735 ntx1 = tx1/z1, nty1 = ty1/z1,
33736 ntx2 = tx2/z2, nty2 = ty2/z2;
33737 tzfloat nz0 = 1/(tzfloat)z0, nz1 = 1/(tzfloat)z1, nz2 = 1/(tzfloat)z2;
33738 if (ny0>ny1)
cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nlx0,nlx1,nly0,nly1,nz0,nz1);
33739 if (ny0>ny2)
cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nlx0,nlx2,nly0,nly2,nz0,nz2);
33740 if (ny1>ny2)
cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nlx1,nlx2,nly1,nly2,nz1,nz2);
33741 if (ny0>=
height() || ny2<0)
return *
this;
33743 ptxl = (ntx1 - ntx0)/(ny1 - ny0),
33744 ptxr = (ntx2 - ntx0)/(ny2 - ny0),
33745 ptxn = (ntx2 - ntx1)/(ny2 - ny1),
33746 ptyl = (nty1 - nty0)/(ny1 - ny0),
33747 ptyr = (nty2 - nty0)/(ny2 - ny0),
33748 ptyn = (nty2 - nty1)/(ny2 - ny1),
33749 txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)),
33750 tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)),
33751 txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))):
33752 (ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))),
33753 tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))):
33754 (ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1)));
33756 pzl = (nz1 - nz0)/(ny1 - ny0),
33757 pzr = (nz2 - nz0)/(ny2 - ny0),
33758 pzn = (nz2 - nz1)/(ny2 - ny1),
33759 zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)),
33760 zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1)));
33761 _cimg_for_triangle3(*
this,xleft0,lxleft0,lyleft0,xright0,lxright0,lyright0,y,
33762 nx0,ny0,nlx0,nly0,nx1,ny1,nlx1,nly1,nx2,ny2,nlx2,nly2) {
33763 if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; }
33765 xleft = xleft0, xright = xright0,
33766 lxleft = lxleft0, lxright = lxright0,
33767 lyleft = lyleft0, lyright = lyright0;
33768 float txleft = txl, txright = txr, tyleft = tyl, tyright = tyr;
33769 tzfloat zleft = zl, zright = zr;
33771 cimg::swap(xleft,xright,zleft,zright,txleft,txright,tyleft,tyright,lxleft,lxright,lyleft,lyright);
33773 dx = xright - xleft,
33774 dlx = lxright>lxleft?lxright - lxleft:lxleft - lxright,
33775 dly = lyright>lyleft?lyright - lyleft:lyleft - lyright,
33776 rlx = dx?(lxright - lxleft)/dx:0,
33777 rly = dx?(lyright - lyleft)/dx:0,
33778 slx = lxright>lxleft?1:-1,
33779 sly = lyright>lyleft?1:-1,
33780 ndlx = dlx - (dx?dx*(dlx/dx):0),
33781 ndly = dly - (dx?dx*(dly/dx):0);
33782 float pentetx = (txright - txleft)/dx, pentety = (tyright - tyleft)/dx;
33783 const tzfloat pentez = (zright - zleft)/dx;
33784 int errlx = dx>>1, errly = errlx;
33785 if (xleft<0 && dx) {
33786 zleft-=xleft*(zright - zleft)/dx;
33787 lxleft-=xleft*(lxright - lxleft)/dx;
33788 lyleft-=xleft*(lyright - lyleft)/dx;
33789 txleft-=xleft*(txright - txleft)/dx;
33790 tyleft-=xleft*(tyright - tyleft)/dx;
33792 if (xleft<0) xleft = 0;
33794 T* ptrd =
data(xleft,y);
33795 tz *ptrz = zbuffer.data(xleft,y);
33796 if (opacity>=1)
for (
int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) {
33797 if (zleft>=(tzfloat)*ptrz) {
33799 const tzfloat invz = 1/zleft;
33800 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
33801 cimg_forC(*
this,c) {
33802 const tl l = light(lxleft,lyleft,c);
33803 *ptrd = (T)(l<1?l**col:(2-l)**col+(l-1)*maxval);
33804 ptrd+=whd; col+=twhd;
33808 zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
33809 lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0);
33810 lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0);
33811 }
else for (
int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) {
33812 if (zleft>=(tzfloat)*ptrz) {
33814 const tzfloat invz = 1/zleft;
33815 const tc *col = texture.data((
int)(txleft*invz),(
int)(tyleft*invz));
33816 cimg_forC(*
this,c) {
33817 const tl l = light(lxleft,lyleft,c);
33818 const T val = (T)(l<1?l**col:(2-l)**col+(l-1)*maxval);
33819 *ptrd = (T)(nopacity*val + *ptrd*copacity);
33820 ptrd+=whd; col+=twhd;
33824 zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
33825 lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0);
33826 lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0);
33828 zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl;
33847 const int x1,
const int y1,
const int z1,
const int c1,
33848 const T val,
const float opacity=1) {
33850 const bool bx = (x0<x1), by = (y0<y1), bz = (z0<z1), bc = (c0<c1);
33852 nx0 = bx?x0:x1, nx1 = bx?x1:x0,
33853 ny0 = by?y0:y1, ny1 = by?y1:y0,
33854 nz0 = bz?z0:z1, nz1 = bz?z1:z0,
33855 nc0 = bc?c0:c1, nc1 = bc?c1:c0;
33857 lX = (1 + nx1 - nx0) + (nx1>=
width()?
width() - 1 - nx1:0) + (nx0<0?nx0:0),
33858 lY = (1 + ny1 - ny0) + (ny1>=
height()?
height() - 1 - ny1:0) + (ny0<0?ny0:0),
33859 lZ = (1 + nz1 - nz0) + (nz1>=
depth()?
depth() - 1 - nz1:0) + (nz0<0?nz0:0),
33860 lC = (1 + nc1 - nc0) + (nc1>=
spectrum()?
spectrum() - 1 - nc1:0) + (nc0<0?nc0:0);
33861 const unsigned long
33862 offX = (
unsigned long)_width - lX,
33863 offY = (
unsigned long)_width*(_height - lY),
33864 offZ = (
unsigned long)_width*_height*(_depth - lZ);
33866 T *ptrd =
data(nx0<0?0:nx0,ny0<0?0:ny0,nz0<0?0:nz0,nc0<0?0:nc0);
33867 if (lX>0 && lY>0 && lZ>0 && lC>0)
33868 for (
int v = 0; v<lC; ++v) {
33869 for (
int z = 0; z<lZ; ++z) {
33870 for (
int y = 0; y<lY; ++y) {
33872 if (
sizeof(T)!=1) {
for (
int x = 0; x<lX; ++x) *(ptrd++) = val; ptrd+=offX; }
33873 else { std::memset(ptrd,(
int)val,lX); ptrd+=_width; }
33874 }
else {
for (
int x = 0; x<lX; ++x) { *ptrd = (T)(nopacity*val + *ptrd*copacity); ++ptrd; } ptrd+=offX; }
33894 template<
typename tc>
33896 const int x1,
const int y1,
const int z1,
33897 const tc *
const color,
const float opacity=1) {
33901 "draw_rectangle(): Specified color is (null).",
33903 cimg_forC(*
this,c)
draw_rectangle(x0,y0,z0,c,x1,y1,z1,c,(T)color[c],opacity);
33908 template<
typename tc>
33910 const int x1,
const int y1,
const int z1,
33911 const tc *
const color,
const float opacity,
33912 const unsigned int pattern) {
33913 return draw_line(x0,y0,z0,x1,y0,z0,color,opacity,pattern,
true).
33914 draw_line(x1,y0,z0,x1,y1,z0,color,opacity,pattern,
false).
33915 draw_line(x1,y1,z0,x0,y1,z0,color,opacity,pattern,
false).
33916 draw_line(x0,y1,z0,x0,y0,z0,color,opacity,pattern,
false).
33917 draw_line(x0,y0,z1,x1,y0,z1,color,opacity,pattern,
true).
33918 draw_line(x1,y0,z1,x1,y1,z1,color,opacity,pattern,
false).
33919 draw_line(x1,y1,z1,x0,y1,z1,color,opacity,pattern,
false).
33920 draw_line(x0,y1,z1,x0,y0,z1,color,opacity,pattern,
false).
33921 draw_line(x0,y0,z0,x0,y0,z1,color,opacity,pattern,
true).
33922 draw_line(x1,y0,z0,x1,y0,z1,color,opacity,pattern,
true).
33923 draw_line(x1,y1,z0,x1,y1,z1,color,opacity,pattern,
true).
33924 draw_line(x0,y1,z0,x0,y1,z1,color,opacity,pattern,
true);
33936 template<
typename tc>
33938 const int x1,
const int y1,
33939 const tc *
const color,
const float opacity=1) {
33944 template<
typename tc>
33946 const int x1,
const int y1,
33947 const tc *
const color,
const float opacity,
33948 const unsigned int pattern) {
33950 if (y0==y1)
return draw_line(x0,y0,x1,y0,color,opacity,pattern,
true);
33951 if (x0==x1)
return draw_line(x0,y0,x0,y1,color,opacity,pattern,
true);
33952 const bool bx = (x0<x1), by = (y0<y1);
33954 nx0 = bx?x0:x1, nx1 = bx?x1:x0,
33955 ny0 = by?y0:y1, ny1 = by?y1:y0;
33956 if (ny1==ny0+1)
return draw_line(nx0,ny0,nx1,ny0,color,opacity,pattern,
true).
33957 draw_line(nx1,ny1,nx0,ny1,color,opacity,pattern,
false);
33958 return draw_line(nx0,ny0,nx1,ny0,color,opacity,pattern,
true).
33959 draw_line(nx1,ny0+1,nx1,ny1-1,color,opacity,pattern,
false).
33960 draw_line(nx1,ny1,nx0,ny1,color,opacity,pattern,
false).
33961 draw_line(nx0,ny1-1,nx0,ny0+1,color,opacity,pattern,
false);
33970 template<
typename t,
typename tc>
33972 const tc *
const color,
const float opacity=1) {
33973 if (
is_empty() || !points)
return *
this;
33976 "draw_polygon(): Specified color is (null).",
33981 unsigned int nb_points = 1, p = 0;
33982 int cx = npoints(0,0) = (int)points(0,0), cy = npoints(0,1) = (int)points(0,1);
33983 const int cx0 = cx, cy0 = cy;
33984 for (p = 1; p<points._width; ++p) {
33985 const int nx = (int)points(p,0), ny = (int)points(p,1);
33986 if (nx!=cx || ny!=cy) { npoints(nb_points,0) = nx; npoints(nb_points++,1) = ny; cx = nx; cy = ny; }
33989 if ((
int)points(p,0)==cx0 && (
int)points(p,1)==cy0) --nb_points;
33990 if (nb_points<=1)
return draw_point((
int)npoints(0,0),(
int)npoints(0,1),color,opacity);
33991 if (nb_points==2)
return draw_line((
int)npoints(0,0),(
int)npoints(0,1),
33992 (
int)npoints(1,0),(
int)npoints(1,1),color,opacity);
33993 if (nb_points==3)
return draw_triangle((
int)npoints(0,0),(
int)npoints(0,1),
33994 (
int)npoints(1,0),(
int)npoints(1,1),
33995 (
int)npoints(2,0),(
int)npoints(2,1),color,opacity);
33998 if (npoints(0,1)==npoints(nb_points-1,1)) {
33999 const intT y0 = npoints(0,1);
34000 unsigned int off = 1;
34001 while ((
int)npoints(off,1)==y0 && off<nb_points) ++off;
34002 if (off<nb_points) {
34003 npoints.get_shared_points(0,nb_points-1,0).shift(-(
int)off,0,0,0,2);
34004 npoints.get_shared_points(0,nb_points-1,1).shift(-(
int)off,0,0,0,2);
34008 cimg_init_scanline(color,1);
34011 npoints.resize(nb_points,2,1,1,0);
34012 CImg<intT> npoints_x = npoints.get_shared_row(0), npoints_y = npoints.get_shared_row(1);
34013 int xmax = 0, xmin = (int)npoints_x.min_max(xmax), ymax = 0, ymin = (int)npoints_y.min_max(ymax);
34014 if (xmax<0 || xmin>=
width() || ymax<0 || ymin>=
height())
return *
this;
34015 if (ymin==ymax)
return cimg_draw_scanline(xmin,xmax,ymin,color,opacity,1);
34017 nxmin = xmin<0?0:(unsigned int)xmin, nxmax = xmax>=
width()?_width-1:(
unsigned int)xmax,
34018 nymin = ymin<0?0:(
unsigned int)ymin, nymax = ymax>=
height()?_height-1:(
unsigned int)ymax,
34019 dx = 1 + nxmax - nxmin,
34020 dy = 1 + nymax - nymin;
34021 npoints_x-=nxmin; npoints_y-=nymin;
34022 unsigned char one = 1;
34025 cimg_forC(_color,c) _color.get_shared_channel(c).fill(color[c]);
34026 return draw_image(nxmin,nymin,0,0,_color,mask,opacity,1);
34031 xmax = 0, xmin = (int)npoints.get_shared_points(0,nb_points-1,0).min_max(xmax),
34032 ymax = 0, ymin = (int)npoints.get_shared_points(0,nb_points-1,1).min_max(ymax);
34033 if (xmax<0 || xmin>=
width() || ymax<0 || ymin>=
height())
return *
this;
34034 if (ymin==ymax)
return cimg_draw_scanline(xmin,xmax,ymin,color,1,1);
34036 nymin = ymin<0?0:(
unsigned int)ymin,
34037 nymax = ymax>=
height()?_height-1:(
unsigned int)ymax,
34038 dy = 1 + nymax - nymin;
34040 cx = (int)npoints(0,0), cy = (int)npoints(0,1);
34041 unsigned int cp = 0;
34042 for (
unsigned int p = 0; p<nb_points; ++p) {
34043 const unsigned int np = (p!=nb_points-1)?p+1:0, ap = (np!=nb_points-1)?np+1:0;
34045 nx = (int)npoints(np,0), ny = (int)npoints(np,1), ay = (int)npoints(ap,1),
34046 y0 = cy - nymin, y1 = ny - nymin;
34048 const int countermin = ((ny<ay && cy<ny) || (ny>ay && cy>ny))?1:0;
34049 for (
int x = cx, y = y0, _sx = 1, _sy = 1,
34050 _dx = nx>cx?nx-cx:((_sx=-1),cx-nx),
34051 _dy = y1>y0?y1-y0:((_sy=-1),y0-y1),
34052 _counter = ((_dx-=_dy?_dy*(_dx/_dy):0),_dy),
34054 _rx = _dy?(nx-cx)/_dy:0;
34055 _counter>=countermin;
34056 --_counter, y+=_sy, x+=_rx + ((_err-=_dx)<0?_err+=_dy,_sx:0))
34057 if (y>=0 && y<(
int)dy) X(++X(0,y),y) = x;
34058 cp = np; cx = nx; cy = ny;
34060 const int pp = (cp?cp-1:nb_points-1), py = (
int)npoints(pp,1);
34061 if (y0>=0 && y0<(
int)dy) {
34062 cimg_draw_scanline(cx<nx?cx:nx,cx<nx?nx:cx,y0+nymin,color,1,1);
34063 if ((cy>py && ay>cy) || (cy<py && ay<cy)) X(++X(0,y0),y0) = cx;
34065 if (cy!=ay) { cp = np; cx = nx; cy = ny; }
34070 for (
int y = 0; y<(int)dy; ++y) {
34071 tmp.assign(X.data(1,y),X(0,y),1,1,1,
true).
sort();
34072 for (
int i = 1; i<=X(0,y); ) {
34073 const int xb = X(i++,y), xe = X(i++,y);
34074 cimg_draw_scanline(xb,xe,nymin+y,color,1,1);
34081 template<
typename t,
typename tc>
34083 const tc *
const color,
const float opacity,
const unsigned int pattern) {
34084 if (
is_empty() || !points || points._width<3)
return *
this;
34085 bool ninit_hatch =
true;
34086 switch (points._height) {
34089 "draw_polygon(): Invalid specified point set.",
34093 int x = npoints(0,0) = (int)points(0,0), y = npoints(0,1) = (int)points(0,1);
34094 unsigned int nb_points = 1;
34095 for (
unsigned int p = 1; p<points._width; ++p) {
34096 const int nx = (int)points(p,0), ny = (int)points(p,1);
34097 if (nx!=x || ny!=y) { npoints(nb_points,0) = nx; npoints(nb_points++,1) = ny; x = nx; y = ny; }
34099 const int x0 = (int)npoints(0,0), y0 = (int)npoints(0,1);
34100 int ox = x0, oy = y0;
34101 for (
unsigned int i = 1; i<nb_points; ++i) {
34102 const int x = (int)npoints(i,0), y = (int)npoints(i,1);
34103 draw_line(ox,oy,x,y,color,opacity,pattern,ninit_hatch);
34104 ninit_hatch =
false;
34107 draw_line(ox,oy,x0,y0,color,opacity,pattern,
false);
34112 x = npoints(0,0) = (int)points(0,0),
34113 y = npoints(0,1) = (int)points(0,1),
34114 z = npoints(0,2) = (int)points(0,2);
34115 unsigned int nb_points = 1;
34116 for (
unsigned int p = 1; p<points._width; ++p) {
34117 const int nx = (int)points(p,0), ny = (int)points(p,1), nz = (int)points(p,2);
34118 if (nx!=x || ny!=y || nz!=z) {
34119 npoints(nb_points,0) = nx; npoints(nb_points,1) = ny; npoints(nb_points++,2) = nz;
34120 x = nx; y = ny; z = nz;
34123 const int x0 = (int)npoints(0,0), y0 = (int)npoints(0,1), z0 = (int)npoints(0,2);
34124 int ox = x0, oy = y0, oz = z0;
34125 for (
unsigned int i = 1; i<nb_points; ++i) {
34126 const int x = (int)npoints(i,0), y = (int)npoints(i,1), z = (int)npoints(i,2);
34127 draw_line(ox,oy,oz,x,y,z,color,opacity,pattern,ninit_hatch);
34128 ninit_hatch =
false;
34129 ox = x; oy = y; oz = z;
34131 draw_line(ox,oy,oz,x0,y0,z0,color,opacity,pattern,
false);
34147 template<
typename tc>
34149 const tc *
const color,
const float opacity=1) {
34150 return _draw_ellipse(x0,y0,r1,r2,angle,color,opacity,0U);
34161 template<
typename t,
typename tc>
34163 const tc *
const color,
const float opacity=1) {
34165 const CImg<t> &val = eig[0], &vec = eig[1];
34166 return draw_ellipse(x0,y0,std::sqrt(val(0)),std::sqrt(val(1)),
34167 std::atan2(vec(0,1),vec(0,0))*180/
cimg::PI,
34182 template<
typename tc>
34184 const tc *
const color,
const float opacity,
const unsigned int pattern) {
34185 if (pattern) _draw_ellipse(x0,y0,r1,r2,angle,color,opacity,pattern);
34198 template<
typename t,
typename tc>
34200 const tc *
const color,
const float opacity,
34201 const unsigned int pattern) {
34203 const CImg<t> &val = eig[0], &vec = eig[1];
34204 return draw_ellipse(x0,y0,std::sqrt(val(0)),std::sqrt(val(1)),
34205 std::atan2(vec(0,1),vec(0,0))*180/
cimg::PI,
34206 color,opacity,pattern);
34209 template<
typename tc>
34210 CImg<T>& _draw_ellipse(
const int x0,
const int y0,
const float r1,
const float r2,
const float angle,
34211 const tc *
const color,
const float opacity,
34212 const unsigned int pattern) {
34216 "draw_ellipse(): Specified color is (null).",
34218 if (r1<=0 || r2<=0)
return draw_point(x0,y0,color,opacity);
34219 cimg_init_scanline(color,opacity);
34222 nangle = (float)(angle*
cimg::PI/180),
34223 u = (float)std::cos(nangle),
34224 v = (float)std::sin(nangle),
34226 l1 = (float)std::pow(rmax/(nr1>0?nr1:1e-6),2),
34227 l2 = (
float)std::pow(rmax/(nr2>0?nr2:1e-6),2),
34228 a = l1*u*u + l2*v*v,
34230 c = l1*v*v + l2*u*u;
34232 yb = (int)std::sqrt(a*rmax*rmax/(a*c - b*b)),
34233 tymin = y0 - yb - 1,
34234 tymax = y0 + yb + 1,
34235 ymin = tymin<0?0:tymin,
34237 int oxmin = 0, oxmax = 0;
34238 bool first_line =
true;
34239 for (
int y = ymin; y<=ymax; ++y) {
34241 Y = y - y0 + (y<y0?0.5f:-0.5f),
34242 delta = b*b*Y*Y - a*(c*Y*Y - rmax*rmax),
34243 sdelta = delta>0?(float)std::sqrt(delta)/a:0.0f,
34245 fxmin = x0 - 0.5f - bY - sdelta,
34246 fxmax = x0 + 0.5f - bY + sdelta;
34247 const int xmin = (int)fxmin, xmax = (
int)fxmax;
34248 if (!pattern) cimg_draw_scanline(xmin,xmax,y,color,opacity,1);
34251 if (y0-yb>=0) cimg_draw_scanline(xmin,xmax,y,color,opacity,1);
34252 else draw_point(xmin,y,color,opacity).draw_point(xmax,y,color,opacity);
34253 first_line =
false;
34255 if (xmin<oxmin) cimg_draw_scanline(xmin,oxmin-1,y,color,opacity,1);
34256 else cimg_draw_scanline(oxmin+(oxmin==xmin?0:1),xmin,y,color,opacity,1);
34257 if (xmax<oxmax) cimg_draw_scanline(xmax,oxmax-1,y,color,opacity,1);
34258 else cimg_draw_scanline(oxmax+(oxmax==xmax?0:1),xmax,y,color,opacity,1);
34259 if (y==tymax) cimg_draw_scanline(xmin+1,xmax-1,y,color,opacity,1);
34262 oxmin = xmin; oxmax = xmax;
34277 template<
typename tc>
34279 const tc *
const color,
const float opacity=1) {
34283 "draw_circle(): Specified color is (null).",
34285 cimg_init_scanline(color,opacity);
34286 if (radius<0 || x0-radius>=
width() || y0+radius<0 || y0-radius>=
height())
return *
this;
34287 if (y0>=0 && y0<
height()) cimg_draw_scanline(x0-radius,x0+radius,y0,color,opacity,1);
34288 for (
int f = 1-radius, ddFx = 0, ddFy = -(radius<<1), x = 0, y = radius; x<y; ) {
34290 const int x1 = x0-x, x2 = x0+x, y1 = y0-y, y2 = y0+y;
34291 if (y1>=0 && y1<
height()) cimg_draw_scanline(x1,x2,y1,color,opacity,1);
34292 if (y2>=0 && y2<
height()) cimg_draw_scanline(x1,x2,y2,color,opacity,1);
34295 const bool no_diag = y!=(x++);
34297 const int x1 = x0-y, x2 = x0+y, y1 = y0-x, y2 = y0+x;
34299 if (y1>=0 && y1<
height()) cimg_draw_scanline(x1,x2,y1,color,opacity,1);
34300 if (y2>=0 && y2<
height()) cimg_draw_scanline(x1,x2,y2,color,opacity,1);
34315 template<
typename tc>
34317 const tc *
const color,
const float opacity,
34318 const unsigned int pattern) {
34323 "draw_circle(): Specified color is (null).",
34325 if (radius<0 || x0-radius>=
width() || y0+radius<0 || y0-radius>=
height())
return *
this;
34326 if (!radius)
return draw_point(x0,y0,color,opacity);
34327 draw_point(x0-radius,y0,color,opacity).draw_point(x0+radius,y0,color,opacity).
34328 draw_point(x0,y0-radius,color,opacity).draw_point(x0,y0+radius,color,opacity);
34329 if (radius==1)
return *
this;
34330 for (
int f = 1-radius, ddFx = 0, ddFy = -(radius<<1), x = 0, y = radius; x<y; ) {
34331 if (f>=0) { f+=(ddFy+=2); --y; }
34332 ++x; ++(f+=(ddFx+=2));
34334 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;
34335 draw_point(x1,y1,color,opacity).draw_point(x1,y2,color,opacity).
34336 draw_point(x2,y1,color,opacity).draw_point(x2,y2,color,opacity);
34338 draw_point(x3,y3,color,opacity).draw_point(x4,y4,color,opacity).
34339 draw_point(x4,y3,color,opacity).draw_point(x3,y4,color,opacity);
34354 template<
typename t>
34356 const CImg<t>& sprite,
const float opacity=1) {
34357 if (
is_empty() || !sprite)
return *
this;
34360 return assign(sprite,
false);
34361 const bool bx = (x0<0), by = (y0<0), bz = (z0<0), bc = (c0<0);
34363 lX = sprite.width() - (x0 + sprite.width()>
width()?x0 + sprite.width() -
width():0) + (bx?x0:0),
34364 lY = sprite.height() - (y0 + sprite.height()>
height()?y0 + sprite.height() -
height():0) + (by?y0:0),
34365 lZ = sprite.depth() - (z0 + sprite.depth()>
depth()?z0 + sprite.depth() -
depth():0) + (bz?z0:0),
34366 lC = sprite.spectrum() - (c0 + sprite.spectrum()>
spectrum()?c0 + sprite.spectrum() -
spectrum():0) + (bc?c0:0);
34368 *ptrs = sprite._data -
34370 (by?y0*sprite.width():0) -
34371 (bz?z0*sprite.width()*sprite.height():0) -
34372 (bc?c0*sprite.width()*sprite.height()*sprite.depth():0);
34373 const unsigned long
34374 offX = (
unsigned long)_width - lX,
34375 soffX = (
unsigned long)sprite._width - lX,
34376 offY = (
unsigned long)_width*(_height - lY),
34377 soffY = (
unsigned long)sprite._width*(sprite._height - lY),
34378 offZ = (
unsigned long)_width*_height*(_depth - lZ),
34379 soffZ = (
unsigned long)sprite._width*sprite._height*(sprite._depth - lZ);
34381 if (lX>0 && lY>0 && lZ>0 && lC>0) {
34382 T *ptrd =
data(x0<0?0:x0,y0<0?0:y0,z0<0?0:z0,c0<0?0:c0);
34383 for (
int v = 0; v<lC; ++v) {
34384 for (
int z = 0; z<lZ; ++z) {
34385 for (
int y = 0; y<lY; ++y) {
34386 if (opacity>=1)
for (
int x = 0; x<lX; ++x) *(ptrd++) = (T)*(ptrs++);
34387 else for (
int x = 0; x<lX; ++x) { *ptrd = (T)(nopacity*(*(ptrs++)) + *ptrd*copacity); ++ptrd; }
34388 ptrd+=offX; ptrs+=soffX;
34390 ptrd+=offY; ptrs+=soffY;
34392 ptrd+=offZ; ptrs+=soffZ;
34400 const CImg<T>& sprite,
const float opacity=1) {
34401 if (
is_empty() || !sprite)
return *
this;
34404 return assign(sprite,
false);
34405 const bool bx = (x0<0), by = (y0<0), bz = (z0<0), bc = (c0<0);
34407 lX = sprite.width() - (x0 + sprite.width()>
width()?x0 + sprite.width() -
width():0) + (bx?x0:0),
34408 lY = sprite.height() - (y0 + sprite.height()>
height()?y0 + sprite.height() -
height():0) + (by?y0:0),
34409 lZ = sprite.depth() - (z0 + sprite.depth()>
depth()?z0 + sprite.depth() -
depth():0) + (bz?z0:0),
34410 lC = sprite.spectrum() - (c0 + sprite.spectrum()>
spectrum()?c0 + sprite.spectrum() -
spectrum():0) + (bc?c0:0);
34412 *ptrs = sprite._data -
34414 (by?y0*sprite.width():0) -
34415 (bz?z0*sprite.width()*sprite.height():0) -
34416 (bc?c0*sprite.width()*sprite.height()*sprite.depth():0);
34417 const unsigned long
34418 offX = (
unsigned long)_width - lX,
34419 soffX = (
unsigned long)sprite._width - lX,
34420 offY = (
unsigned long)_width*(_height - lY),
34421 soffY = (
unsigned long)sprite._width*(sprite._height - lY),
34422 offZ = (
unsigned long)_width*_height*(_depth - lZ),
34423 soffZ = (
unsigned long)sprite._width*sprite._height*(sprite._depth - lZ),
34424 slX = lX*
sizeof(T);
34426 if (lX>0 && lY>0 && lZ>0 && lC>0) {
34427 T *ptrd =
data(x0<0?0:x0,y0<0?0:y0,z0<0?0:z0,c0<0?0:c0);
34428 for (
int v = 0; v<lC; ++v) {
34429 for (
int z = 0; z<lZ; ++z) {
34431 for (
int y = 0; y<lY; ++y) { std::memcpy(ptrd,ptrs,slX); ptrd+=_width; ptrs+=sprite._width; }
34432 else for (
int y = 0; y<lY; ++y) {
34433 for (
int x = 0; x<lX; ++x) { *ptrd = (T)(nopacity*(*(ptrs++)) + *ptrd*copacity); ++ptrd; }
34434 ptrd+=offX; ptrs+=soffX;
34436 ptrd+=offY; ptrs+=soffY;
34438 ptrd+=offZ; ptrs+=soffZ;
34445 template<
typename t>
34447 const CImg<t>& sprite,
const float opacity=1) {
34448 return draw_image(x0,y0,z0,0,sprite,opacity);
34452 template<
typename t>
34454 const CImg<t>& sprite,
const float opacity=1) {
34459 template<
typename t>
34461 const CImg<t>& sprite,
const float opacity=1) {
34466 template<
typename t>
34485 template<
typename ti,
typename tm>
34488 const float mask_max_value=1) {
34489 if (
is_empty() || !sprite || !mask)
return *
this;
34492 if (mask._width!=sprite._width || mask._height!=sprite._height || mask._depth!=sprite._depth)
34494 "draw_image(): Sprite (%u,%u,%u,%u,%p) and mask (%u,%u,%u,%u,%p) have "
34495 "incompatible dimensions.",
34497 sprite._width,sprite._height,sprite._depth,sprite._spectrum,sprite._data,
34498 mask._width,mask._height,mask._depth,mask._spectrum,mask._data);
34500 const bool bx = (x0<0), by = (y0<0), bz = (z0<0), bc = (c0<0);
34502 lX = sprite.width() - (x0 + sprite.width()>
width()?x0 + sprite.width() -
width():0) + (bx?x0:0),
34503 lY = sprite.height() - (y0 + sprite.height()>
height()?y0 + sprite.height() -
height():0) + (by?y0:0),
34504 lZ = sprite.depth() - (z0 + sprite.depth()>
depth()?z0 + sprite.depth() -
depth():0) + (bz?z0:0),
34505 lC = sprite.spectrum() - (c0 + sprite.spectrum()>
spectrum()?c0 + sprite.spectrum() -
spectrum():0) + (bc?c0:0);
34507 coff = -(bx?x0:0)-(by?y0*mask.width():0)-(bz?z0*mask.width()*mask.height():0)-
34508 (bc?c0*mask.width()*mask.height()*mask.depth():0),
34509 ssize = mask.width()*mask.height()*mask.depth()*mask.spectrum();
34510 const ti *ptrs = sprite._data + coff;
34511 const tm *ptrm = mask._data + coff;
34512 const unsigned long
34513 offX = (
unsigned long)_width - lX,
34514 soffX = (
unsigned long)sprite._width - lX,
34515 offY = (
unsigned long)_width*(_height - lY),
34516 soffY = (
unsigned long)sprite._width*(sprite._height - lY),
34517 offZ = (
unsigned long)_width*_height*(_depth - lZ),
34518 soffZ = (
unsigned long)sprite._width*sprite._height*(sprite._depth - lZ);
34519 if (lX>0 && lY>0 && lZ>0 && lC>0) {
34520 T *ptrd =
data(x0<0?0:x0,y0<0?0:y0,z0<0?0:z0,c0<0?0:c0);
34521 for (
int c = 0; c<lC; ++c) {
34522 ptrm = mask._data + (ptrm - mask._data)%ssize;
34523 for (
int z = 0; z<lZ; ++z) {
34524 for (
int y = 0; y<lY; ++y) {
34525 for (
int x = 0; x<lX; ++x) {
34526 const float mopacity = (float)(*(ptrm++)*opacity),
34528 *ptrd = (T)((nopacity*(*(ptrs++)) + *ptrd*copacity)/mask_max_value);
34531 ptrd+=offX; ptrs+=soffX; ptrm+=soffX;
34533 ptrd+=offY; ptrs+=soffY; ptrm+=soffY;
34535 ptrd+=offZ; ptrs+=soffZ; ptrm+=soffZ;
34542 template<
typename ti,
typename tm>
34545 const float mask_max_value=1) {
34546 return draw_image(x0,y0,z0,0,sprite,mask,opacity,mask_max_value);
34550 template<
typename ti,
typename tm>
34553 const float mask_max_value=1) {
34554 return draw_image(x0,y0,0,sprite,mask,opacity,mask_max_value);
34558 template<
typename ti,
typename tm>
34561 const float mask_max_value=1) {
34562 return draw_image(x0,0,sprite,mask,opacity,mask_max_value);
34566 template<
typename ti,
typename tm>
34568 const float mask_max_value=1) {
34569 return draw_image(0,sprite,mask,opacity,mask_max_value);
34582 template<
typename tc1,
typename tc2,
typename t>
34584 const char *
const text,
34585 const tc1 *
const foreground_color,
const tc2 *
const background_color,
34586 const float opacity,
const CImgList<t>& font, ...) {
34587 if (!font)
return *
this;
34588 char tmp[2048] = { 0 }; std::va_list ap; va_start(ap,font);
34589 cimg_vsnprintf(tmp,
sizeof(tmp),text,ap); va_end(ap);
34590 return _draw_text(x0,y0,tmp,foreground_color,background_color,opacity,font,
false);
34597 template<
typename tc,
typename t>
34599 const char *
const text,
34600 const tc *
const foreground_color,
const int,
34601 const float opacity,
const CImgList<t>& font, ...) {
34602 if (!font)
return *
this;
34603 char tmp[2048] = { 0 }; std::va_list ap; va_start(ap,font);
34604 cimg_vsnprintf(tmp,
sizeof(tmp),text,ap); va_end(ap);
34605 return _draw_text(x0,y0,tmp,foreground_color,(tc*)0,opacity,font,
false);
34612 template<
typename tc,
typename t>
34614 const char *
const text,
34615 const int,
const tc *
const background_color,
34616 const float opacity,
const CImgList<t>& font, ...) {
34617 if (!font)
return *
this;
34618 char tmp[2048] = { 0 }; std::va_list ap; va_start(ap,font);
34619 cimg_vsnprintf(tmp,
sizeof(tmp),text,ap); va_end(ap);
34620 return _draw_text(x0,y0,tmp,(tc*)0,background_color,opacity,font,
false);
34635 template<
typename tc1,
typename tc2>
34637 const char *
const text,
34638 const tc1 *
const foreground_color,
const tc2 *
const background_color,
34639 const float opacity=1,
const unsigned int font_height=13, ...) {
34640 if (!font_height)
return *
this;
34641 char tmp[2048] = { 0 };
34642 std::va_list ap; va_start(ap,font_height); cimg_vsnprintf(tmp,
sizeof(tmp),text,ap); va_end(ap);
34644 _draw_text(x0,y0,tmp,foreground_color,background_color,opacity,font,
true);
34649 template<
typename tc>
34651 const char *
const text,
34652 const tc *
const foreground_color,
const int background_color=0,
34653 const float opacity=1,
const unsigned int font_height=13, ...) {
34654 if (!font_height)
return *
this;
34656 char tmp[2048] = { 0 };
34657 std::va_list ap; va_start(ap,font_height); cimg_vsnprintf(tmp,
sizeof(tmp),text,ap); va_end(ap);
34658 return draw_text(x0,y0,
"%s",foreground_color,(
const tc*)0,opacity,font_height,tmp);
34662 template<
typename tc>
34664 const char *
const text,
34665 const int,
const tc *
const background_color,
34666 const float opacity=1,
const unsigned int font_height=13, ...) {
34667 if (!font_height)
return *
this;
34668 char tmp[2048] = { 0 };
34669 std::va_list ap; va_start(ap,font_height); cimg_vsnprintf(tmp,
sizeof(tmp),text,ap); va_end(ap);
34670 return draw_text(x0,y0,
"%s",(tc*)0,background_color,opacity,font_height,tmp);
34673 template<
typename tc1,
typename tc2,
typename t>
34674 CImg<T>& _draw_text(
const int x0,
const int y0,
34675 const char *
const text,
34676 const tc1 *
const foreground_color,
const tc2 *
const background_color,
34678 const bool is_native_font) {
34679 if (!text)
return *
this;
34682 "draw_text(): Empty specified font.",
34685 const unsigned int text_length = (
unsigned int)std::strlen(text);
34686 const bool _is_empty =
is_empty();
34689 int x = 0, y = 0, w = 0;
34690 unsigned char c = 0;
34691 for (
unsigned int i = 0; i<text_length; ++i) {
34694 case '\n' : y+=font[0]._height;
if (x>w) w = x; x = 0;
break;
34695 case '\t' : x+=4*font[
' ']._width;
break;
34696 default :
if (c<font._width) x+=font[c]._width;
34699 if (x!=0 || c==
'\n') {
34701 y+=font[0]._height;
34703 assign(x0+w,y0+y,1,is_native_font?1:font[0]._spectrum,0);
34706 int x = x0, y = y0;
34707 for (
unsigned int i = 0; i<text_length; ++i) {
34708 const unsigned char c = text[i];
34710 case '\n' : y+=font[0]._height; x = x0;
break;
34711 case '\t' : x+=4*font[
' ']._width;
break;
34712 default :
if (c<font._width) {
34713 CImg<T> letter = font[c];
34715 if (is_native_font && _spectrum>letter._spectrum) letter.resize(-100,-100,1,_spectrum,0,2);
34716 const unsigned int cmin =
cimg::min(_spectrum,letter._spectrum);
34717 if (foreground_color)
34718 for (
unsigned int c = 0; c<cmin; ++c)
34719 if (foreground_color[c]!=1) letter.get_shared_channel(c)*=foreground_color[c];
34720 if (c+256<font.
width()) {
34721 if (background_color)
34722 for (
unsigned int c = 0; c<cmin; ++c)
34723 draw_rectangle(x,y,0,c,x+letter._width-1,y+letter._height-1,0,c,background_color[c],opacity);
34724 draw_image(x,y,letter,font[c+256],opacity,(T)255);
34745 template<
typename t1,
typename t2>
34747 const t2 *
const color,
const float opacity=1,
34748 const unsigned int sampling=25,
const float factor=-20,
34749 const bool is_arrow=
true,
const unsigned int pattern=~0U) {
34750 return draw_quiver(flow,
CImg<t2>(color,_spectrum,1,1,1,
true),opacity,sampling,factor,is_arrow,pattern);
34764 template<
typename t1,
typename t2>
34766 const CImg<t2>& color,
const float opacity=1,
34767 const unsigned int sampling=25,
const float factor=-20,
34768 const bool is_arrow=
true,
const unsigned int pattern=~0U) {
34770 if (!flow || flow._spectrum!=2)
34772 "draw_quiver(): Invalid dimensions of specified flow (%u,%u,%u,%u,%p).",
34774 flow._width,flow._height,flow._depth,flow._spectrum,flow._data);
34777 "draw_quiver(): Invalid sampling value %g "
34781 const bool colorfield = (color._width==flow._width && color._height==flow._height &&
34782 color._depth==1 && color._spectrum==_spectrum);
34786 float m, M = (float)flow.get_norm(2).max_min(m);
34788 if (!vmax) vmax = 1;
34790 }
else { fact = factor; vmax = 1; }
34792 for (
unsigned int y = sampling/2; y<_height; y+=sampling)
34793 for (
unsigned int x = sampling/2; x<_width; x+=sampling) {
34794 const unsigned int X = x*flow._width/_width, Y = y*flow._height/_height;
34795 float u = (float)flow(X,Y,0,0)*fact/vmax, v = (float)flow(X,Y,0,1)*fact/vmax;
34797 const int xx = x+(int)u, yy = y+(
int)v;
34798 if (colorfield)
draw_arrow(x,y,xx,yy,color.get_vector_at(X,Y)._data,opacity,45,sampling/5.0f,pattern);
34799 else draw_arrow(x,y,xx,yy,color._data,opacity,45,sampling/5.0f,pattern);
34802 draw_line((
int)(x-0.5*u),(
int)(y-0.5*v),(
int)(x+0.5*u),(
int)(y+0.5*v),
34803 color.get_vector_at(X,Y)._data,opacity,pattern);
34804 else draw_line((
int)(x-0.5*u),(
int)(y-0.5*v),(
int)(x+0.5*u),(
int)(y+0.5*v),
34805 color._data,opacity,pattern);
34821 template<
typename t,
typename tc>
34823 const tc *
const color,
const float opacity=1,
34824 const unsigned int pattern=~0U,
const unsigned int font_height=13,
34825 const bool allow_zero=
true) {
34827 const int yt = (y+3+font_height)<_height?(y+3):(y-2-font_height);
34828 const int siz = (int)values_x.size()-1;
34829 char txt[32] = { 0 };
34832 draw_line(0,y,_width-1,y,color,opacity,pattern);
34834 cimg_snprintf(txt,
sizeof(txt),
"%g",(
double)*values_x);
34835 label.assign().draw_text(0,0,txt,color,(tc*)0,opacity,font_height);
34837 _xt = (
width() - label.width())/2,
34838 xt = _xt<3?3:_xt+label.width()>=
width()-2?
width()-3-label.width():_xt;
34840 if (allow_zero || txt[0]!=
'0' || txt[1]!=0)
34841 draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height);
34844 if (values_x[0]<values_x[siz])
draw_arrow(0,y,_width-1,y,color,opacity,30,5,pattern);
34845 else draw_arrow(_width-1,y,0,y,color,opacity,30,5,pattern);
34846 cimg_foroff(values_x,x) {
34847 cimg_snprintf(txt,
sizeof(txt),
"%g",(
double)values_x(x));
34848 label.assign().draw_text(0,0,txt,color,(tc*)0,opacity,font_height);
34850 xi = (int)(x*(_width-1)/siz),
34851 _xt = xi - label.width()/2,
34852 xt = _xt<3?3:_xt+label.width()>=
width()-2?
width()-3-label.width():_xt;
34853 draw_point(xi,y-1,color,opacity).draw_point(xi,y+1,color,opacity);
34854 if (allow_zero || txt[0]!=
'0' || txt[1]!=0)
34855 draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height);
34871 template<
typename t,
typename tc>
34873 const tc *
const color,
const float opacity=1,
34874 const unsigned int pattern=~0U,
const unsigned int font_height=13,
34875 const bool allow_zero=
true) {
34877 int siz = (int)values_y.size()-1;
34878 char txt[32] = { 0 };
34881 draw_line(x,0,x,_height-1,color,opacity,pattern);
34883 cimg_snprintf(txt,
sizeof(txt),
"%g",(
double)*values_y);
34884 label.assign().draw_text(0,0,txt,color,(tc*)0,opacity,font_height);
34886 _yt = (
height() - label.height())/2,
34887 yt = _yt<0?0:_yt+label.height()>=
height()?
height()-1-label.height():_yt,
34888 _xt = x - 2 - label.width(),
34889 xt = _xt>=0?_xt:x+3;
34891 if (allow_zero || txt[0]!=
'0' || txt[1]!=0)
34892 draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height);
34895 if (values_y[0]<values_y[siz])
draw_arrow(x,0,x,_height-1,color,opacity,30,5,pattern);
34896 else draw_arrow(x,_height-1,x,0,color,opacity,30,5,pattern);
34897 cimg_foroff(values_y,y) {
34898 cimg_snprintf(txt,
sizeof(txt),
"%g",(
double)values_y(y));
34899 label.assign().draw_text(0,0,txt,color,(tc*)0,opacity,font_height);
34901 yi = (int)(y*(_height-1)/siz),
34902 _yt = yi - label.height()/2,
34903 yt = _yt<0?0:_yt+label.height()>=
height()?
height()-1-label.height():_yt,
34904 _xt = x - 2 - label.width(),
34905 xt = _xt>=0?_xt:x+3;
34906 draw_point(x-1,yi,color,opacity).draw_point(x+1,yi,color,opacity);
34907 if (allow_zero || txt[0]!=
'0' || txt[1]!=0)
34908 draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height);
34925 template<
typename tx,
typename ty,
typename tc>
34927 const tc *
const color,
const float opacity=1,
34928 const unsigned int pattern_x=~0U,
const unsigned int pattern_y=~0U,
34929 const unsigned int font_height=13,
const bool allow_zero=
true) {
34931 const CImg<tx> nvalues_x(values_x._data,values_x.size(),1,1,1,
true);
34932 const int sizx = (int)values_x.size()-1, wm1 =
width()-1;
34934 float ox = (float)*nvalues_x;
34935 for (
unsigned int x = sizx?1:0; x<_width; ++x) {
34936 const float nx = (float)nvalues_x._linear_atX((
float)x*sizx/wm1);
34937 if (nx*ox<=0) {
draw_axis(nx==0?x:x-1,values_y,color,opacity,pattern_y,font_height,allow_zero);
break; }
34941 const CImg<ty> nvalues_y(values_y._data,values_y.size(),1,1,1,
true);
34942 const int sizy = (int)values_y.size()-1, hm1 =
height()-1;
34944 float oy = (float)nvalues_y[0];
34945 for (
unsigned int y = sizy?1:0; y<_height; ++y) {
34946 const float ny = (float)nvalues_y._linear_atX((
float)y*sizy/hm1);
34947 if (ny*oy<=0) {
draw_axis(values_x,ny==0?y:y-1,color,opacity,pattern_x,font_height,allow_zero);
break; }
34955 template<
typename tc>
34957 const tc *
const color,
const float opacity=1,
34958 const int subdivisionx=-60,
const int subdivisiony=-60,
34959 const float precisionx=0,
const float precisiony=0,
34960 const unsigned int pattern_x=~0U,
const unsigned int pattern_y=~0U,
34961 const unsigned int font_height=13) {
34963 const bool allow_zero = (x0*x1>0) || (y0*y1>0);
34966 px = dx<=0?1:precisionx==0?(float)std::pow(10.0,(
int)std::log10(dx)-2.0):precisionx,
34967 py = dy<=0?1:precisiony==0?(float)std::pow(10.0,(
int)std::log10(dy)-2.0):precisiony;
34968 if (x0!=x1 && y0!=y1)
34971 color,opacity,pattern_x,pattern_y,font_height,allow_zero);
34972 else if (x0==x1 && y0!=y1)
34974 color,opacity,pattern_y,font_height);
34975 else if (x0!=x1 && y0==y1)
34977 color,opacity,pattern_x,font_height);
34990 template<
typename tx,
typename ty,
typename tc>
34992 const tc *
const color,
const float opacity=1,
34993 const unsigned int pattern_x=~0U,
const unsigned int pattern_y=~0U) {
34995 if (values_x) cimg_foroff(values_x,x) {
34996 const int xi = (int)values_x[x];
34997 if (xi>=0 && xi<
width())
draw_line(xi,0,xi,_height-1,color,opacity,pattern_x);
34999 if (values_y) cimg_foroff(values_y,y) {
35000 const int yi = (int)values_y[y];
35001 if (yi>=0 && yi<
height())
draw_line(0,yi,_width-1,yi,color,opacity,pattern_y);
35007 template<
typename tc>
35009 const float offsetx,
const float offsety,
35010 const bool invertx,
const bool inverty,
35011 const tc *
const color,
const float opacity=1,
35012 const unsigned int pattern_x=~0U,
const unsigned int pattern_y=~0U) {
35016 const float dx = delta_x>0?delta_x:_width*-delta_x/100;
35017 const unsigned int nx = (
unsigned int)(_width/dx);
35019 if (offsetx) cimg_foroff(seqx,x) seqx(x) = (
unsigned int)
cimg::mod(seqx(x)+offsetx,(float)_width);
35020 if (invertx) cimg_foroff(seqx,x) seqx(x) = _width - 1 - seqx(x);
35023 const float dy = delta_y>0?delta_y:_height*-delta_y/100;
35024 const unsigned int ny = (
unsigned int)(_height/dy);
35026 if (offsety) cimg_foroff(seqy,y) seqy(y) = (
unsigned int)
cimg::mod(seqy(y)+offsety,(float)_height);
35027 if (inverty) cimg_foroff(seqy,y) seqy(y) = _height - 1 - seqy(y);
35029 return draw_grid(seqx,seqy,color,opacity,pattern_x,pattern_y);
35058 template<
typename t,
typename tc>
35060 const tc *
const color,
const float opacity=1,
35061 const unsigned int plot_type=1,
const int vertex_type=1,
35062 const double ymin=0,
const double ymax=0,
const unsigned int pattern=~0U) {
35063 if (
is_empty() || _height<=1)
return *
this;
35066 "draw_graph(): Specified color is (null).",
35071 if (plot_type==3) {
35072 color1.assign(_spectrum); color2.assign(_spectrum);
35073 cimg_forC(*
this,c) {
35075 color2[c] = (tc)(color[c]*0.4f);
35080 const unsigned long
35082 _siz1 = siz - (plot_type!=3?1:0),
35083 siz1 = _siz1?_siz1:1;
35085 _width1 = _width - (plot_type!=3?1:0),
35086 width1 = _width1?_width1:1;
35087 double m = ymin, M = ymax;
35088 if (ymin==ymax) m = (double)data.max_min(M);
35089 if (m==M) { --m; ++M; }
35090 const float ca = (float)(M-m)/(_height-1);
35091 bool init_hatch =
true;
35094 switch (plot_type%4) {
35096 int oX = 0, oY = (int)((data[0]-m)/ca);
35097 const float fx = (float)_width1/siz1;
35099 const int Y = (int)((*data-m)/ca);
35101 }
else for (
unsigned long off = 1; off<siz; ++off) {
35104 Y = (int)((data[off]-m)/ca);
35105 draw_line(oX,oY,X,Y,color,opacity,pattern,init_hatch);
35107 init_hatch =
false;
35111 const CImg<t> ndata(data._data,siz,1,1,1,
true);
35112 int oY = (int)((data[0]-m)/ca);
35113 cimg_forX(*
this,x) {
35114 const int Y = (int)((ndata._cubic_atX((
float)x*siz1/width1)-m)/ca);
35115 if (x>0)
draw_line(x,oY,x+1,Y,color,opacity,pattern,init_hatch);
35116 init_hatch =
false;
35121 const int Y0 = (int)(-m/ca);
35122 const float fx = (float)_width/(siz-1);
35124 cimg_foroff(data,off) {
35126 X = (int)((off+1)*fx),
35127 Y = (
int)((data[off]-m)/ca);
35129 draw_line(oX,Y,oX,Y0,color2.data(),opacity).
35130 draw_line(oX,Y0,X,Y0,Y<=Y0?color2.data():color1.data(),opacity).
35131 draw_line(X,Y,X,Y0,color1.data(),opacity).
35132 draw_line(oX,Y,X,Y,Y<=Y0?color1.data():color2.data(),opacity);
35140 const unsigned int wb2 = plot_type==3?_width1/(2*siz):0;
35141 const float fx = (float)_width1/siz1;
35142 switch (vertex_type%8) {
35144 cimg_foroff(data,off) {
35146 X = (int)(off*fx) + wb2,
35147 Y = (int)((data[off]-m)/ca);
35152 cimg_foroff(data,off) {
35154 X = (int)(off*fx) + wb2,
35155 Y = (int)((data[off]-m)/ca);
35156 draw_line(X-3,Y,X+3,Y,color,opacity).draw_line(X,Y-3,X,Y+3,color,opacity);
35160 cimg_foroff(data,off) {
35162 X = (int)(off*fx) + wb2,
35163 Y = (int)((data[off]-m)/ca);
35164 draw_line(X-3,Y-3,X+3,Y+3,color,opacity).draw_line(X-3,Y+3,X+3,Y-3,color,opacity);
35168 cimg_foroff(data,off) {
35170 X = (int)(off*fx) + wb2,
35171 Y = (int)((data[off]-m)/ca);
35176 cimg_foroff(data,off) {
35178 X = (int)(off*fx) + wb2,
35179 Y = (int)((data[off]-m)/ca);
35184 cimg_foroff(data,off) {
35186 X = (int)(off*fx) + wb2,
35187 Y = (int)((data[off]-m)/ca);
35192 cimg_foroff(data,off) {
35194 X = (int)(off*fx) + wb2,
35195 Y = (int)((data[off]-m)/ca);
35219 template<
typename tc,
typename t>
35221 const tc *
const color,
const float opacity,
35222 CImg<t>& region,
const float sigma=0,
35223 const bool is_high_connexity=
false) {
35225 #define _cimg_draw_fill_test(x,y,z,res) if (region(x,y,z)) res = false; else { \
35227 const T *reference_col = reference_color._data + _spectrum, *ptrs = data(x,y,z) + siz; \
35228 for (unsigned int i = _spectrum; res && i; --i) { ptrs-=whd; res = (cimg::abs(*ptrs - *(--reference_col))<=sigma); } \
35229 region(x,y,z) = (t)(res?1:noregion); \
35232 #define _cimg_draw_fill_set(x,y,z) { \
35233 const tc *col = color; \
35234 T *ptrd = data(x,y,z); \
35235 if (opacity>=1) cimg_forC(*this,c) { *ptrd = (T)*(col++); ptrd+=whd; } \
35236 else cimg_forC(*this,c) { *ptrd = (T)(*(col++)*nopacity + *ptrd*copacity); ptrd+=whd; } \
35239 #define _cimg_draw_fill_insert(x,y,z) { \
35240 if (posr1>=remaining._height) remaining.resize(3,remaining._height<<1,1,1,0); \
35241 unsigned int *ptrr = remaining.data(0,posr1); \
35242 *(ptrr++) = x; *(ptrr++) = y; *(ptrr++) = z; ++posr1; \
35245 #define _cimg_draw_fill_test_neighbor(x,y,z,cond) if (cond) { \
35246 const unsigned int tx = x, ty = y, tz = z; \
35247 _cimg_draw_fill_test(tx,ty,tz,res); if (res) _cimg_draw_fill_insert(tx,ty,tz); \
35252 "draw_fill(): Specified color is (null).",
35255 region.assign(_width,_height,_depth,1,(t)0);
35258 const unsigned long whd = (
unsigned long)_width*_height*_depth, siz = (
unsigned long)_spectrum*whd;
35259 const unsigned int W1 = _width-1, H1 = _height-1, D1 = _depth-1;
35260 const bool is_3d = (_depth>1);
35263 remaining(0,0) = x; remaining(1,0) = y; remaining(2,0) = z;
35264 unsigned int posr0 = 0, posr1 = 1;
35265 region(x,y,z) = (t)1;
35266 const t noregion = ((t)1==(t)2)?(t)0:(t)(-1);
35268 const unsigned int *pcurr = remaining.
data(0,posr0++), xc = *(pcurr++), yc = *(pcurr++), zc = *(pcurr++);
35269 if (posr0>=512) { remaining.
shift(0,-(
int)posr0); posr1-=posr0; posr0 = 0; }
35271 unsigned int nxc = xc;
35273 _cimg_draw_fill_set(nxc,yc,zc);
35274 _cimg_draw_fill_test_neighbor(nxc,yc-1,zc,yc!=0);
35275 _cimg_draw_fill_test_neighbor(nxc,yc+1,zc,yc<H1);
35276 _cimg_draw_fill_test_neighbor(nxc,yc,zc-1,zc!=0);
35277 _cimg_draw_fill_test_neighbor(nxc,yc,zc+1,zc<D1);
35278 if (nxc) { --nxc; _cimg_draw_fill_test(nxc,yc,zc,cont); }
else cont =
false;
35282 if ((++nxc)<=W1) { _cimg_draw_fill_test(nxc,yc,zc,cont); }
else cont =
false;
35284 _cimg_draw_fill_set(nxc,yc,zc);
35285 _cimg_draw_fill_test_neighbor(nxc,yc-1,zc,yc!=0);
35286 _cimg_draw_fill_test_neighbor(nxc,yc+1,zc,yc<H1);
35287 _cimg_draw_fill_test_neighbor(nxc,yc,zc-1,zc!=0);
35288 _cimg_draw_fill_test_neighbor(nxc,yc,zc+1,zc<D1);
35291 unsigned int nyc = yc;
35293 if (nyc) { --nyc; _cimg_draw_fill_test(xc,nyc,zc,cont); }
else cont =
false;
35295 _cimg_draw_fill_set(xc,nyc,zc);
35296 _cimg_draw_fill_test_neighbor(xc-1,nyc,zc,xc!=0);
35297 _cimg_draw_fill_test_neighbor(xc+1,nyc,zc,xc<W1);
35298 _cimg_draw_fill_test_neighbor(xc,nyc,zc-1,zc!=0);
35299 _cimg_draw_fill_test_neighbor(xc,nyc,zc+1,zc<D1);
35304 if ((++nyc)<=H1) { _cimg_draw_fill_test(xc,nyc,zc,cont); }
else cont =
false;
35306 _cimg_draw_fill_set(xc,nyc,zc);
35307 _cimg_draw_fill_test_neighbor(xc-1,nyc,zc,xc!=0);
35308 _cimg_draw_fill_test_neighbor(xc+1,nyc,zc,xc<W1);
35309 _cimg_draw_fill_test_neighbor(xc,nyc,zc-1,zc!=0);
35310 _cimg_draw_fill_test_neighbor(xc,nyc,zc+1,zc<D1);
35313 unsigned int nzc = zc;
35315 if (nzc) { --nzc; _cimg_draw_fill_test(xc,yc,nzc,cont); }
else cont =
false;
35317 _cimg_draw_fill_set(xc,yc,nzc);
35318 _cimg_draw_fill_test_neighbor(xc-1,yc,nzc,xc!=0);
35319 _cimg_draw_fill_test_neighbor(xc+1,yc,nzc,xc<W1);
35320 _cimg_draw_fill_test_neighbor(xc,yc-1,nzc,yc!=0);
35321 _cimg_draw_fill_test_neighbor(xc,yc+1,nzc,yc<H1);
35326 if ((++nzc)<=D1) { _cimg_draw_fill_test(xc,yc,nzc,cont); }
else cont =
false;
35328 _cimg_draw_fill_set(xc,nyc,zc);
35329 _cimg_draw_fill_test_neighbor(xc-1,yc,nzc,xc!=0);
35330 _cimg_draw_fill_test_neighbor(xc+1,yc,nzc,xc<W1);
35331 _cimg_draw_fill_test_neighbor(xc,yc-1,nzc,yc!=0);
35332 _cimg_draw_fill_test_neighbor(xc,yc+1,nzc,yc<H1);
35335 }
while (posr1>posr0);
35337 const unsigned int *pcurr = remaining.
data(0,posr0++), xc = *(pcurr++), yc = *(pcurr++);
35338 if (posr0>=512) { remaining.
shift(0,-(
int)posr0); posr1-=posr0; posr0 = 0; }
35340 unsigned int nxc = xc;
35342 _cimg_draw_fill_set(nxc,yc,0);
35343 _cimg_draw_fill_test_neighbor(nxc,yc-1,0,yc!=0);
35344 _cimg_draw_fill_test_neighbor(nxc,yc+1,0,yc<H1);
35345 if (is_high_connexity) {
35346 _cimg_draw_fill_test_neighbor(nxc-1,yc-1,0,(nxc!=0 && yc!=0));
35347 _cimg_draw_fill_test_neighbor(nxc+1,yc-1,0,(nxc<W1 && yc!=0));
35348 _cimg_draw_fill_test_neighbor(nxc-1,yc+1,0,(nxc!=0 && yc<H1));
35349 _cimg_draw_fill_test_neighbor(nxc+1,yc+1,0,(nxc<W1 && yc<H1));
35351 if (nxc) { --nxc; _cimg_draw_fill_test(nxc,yc,0,cont); }
else cont =
false;
35355 if ((++nxc)<=W1) { _cimg_draw_fill_test(nxc,yc,0,cont); }
else cont =
false;
35357 _cimg_draw_fill_set(nxc,yc,0);
35358 _cimg_draw_fill_test_neighbor(nxc,yc-1,0,yc!=0);
35359 _cimg_draw_fill_test_neighbor(nxc,yc+1,0,yc<H1);
35360 if (is_high_connexity) {
35361 _cimg_draw_fill_test_neighbor(nxc-1,yc-1,0,(nxc!=0 && yc!=0));
35362 _cimg_draw_fill_test_neighbor(nxc+1,yc-1,0,(nxc<W1 && yc!=0));
35363 _cimg_draw_fill_test_neighbor(nxc-1,yc+1,0,(nxc!=0 && yc<H1));
35364 _cimg_draw_fill_test_neighbor(nxc+1,yc+1,0,(nxc<W1 && yc<H1));
35368 unsigned int nyc = yc;
35370 if (nyc) { --nyc; _cimg_draw_fill_test(xc,nyc,0,cont); }
else cont =
false;
35372 _cimg_draw_fill_set(xc,nyc,0);
35373 _cimg_draw_fill_test_neighbor(xc-1,nyc,0,xc!=0);
35374 _cimg_draw_fill_test_neighbor(xc+1,nyc,0,xc<W1);
35375 if (is_high_connexity) {
35376 _cimg_draw_fill_test_neighbor(xc-1,nyc-1,0,(xc!=0 && nyc!=0));
35377 _cimg_draw_fill_test_neighbor(xc+1,nyc-1,0,(xc<W1 && nyc!=0));
35378 _cimg_draw_fill_test_neighbor(xc-1,nyc+1,0,(xc!=0 && nyc<H1));
35379 _cimg_draw_fill_test_neighbor(xc+1,nyc+1,0,(xc<W1 && nyc<H1));
35385 if ((++nyc)<=H1) { _cimg_draw_fill_test(xc,nyc,0,cont); }
else cont =
false;
35387 _cimg_draw_fill_set(xc,nyc,0);
35388 _cimg_draw_fill_test_neighbor(xc-1,nyc,0,xc!=0);
35389 _cimg_draw_fill_test_neighbor(xc+1,nyc,0,xc<W1);
35390 if (is_high_connexity) {
35391 _cimg_draw_fill_test_neighbor(xc-1,nyc-1,0,(xc!=0 && nyc!=0));
35392 _cimg_draw_fill_test_neighbor(xc+1,nyc-1,0,(xc<W1 && nyc!=0));
35393 _cimg_draw_fill_test_neighbor(xc-1,nyc+1,0,(xc!=0 && nyc<H1));
35394 _cimg_draw_fill_test_neighbor(xc+1,nyc+1,0,(xc<W1 && nyc<H1));
35398 }
while (posr1>posr0);
35399 if (noregion) cimg_for(region,ptrd,t)
if (*ptrd==noregion) *ptrd = (t)0;
35405 template<
typename tc>
35407 const tc *
const color,
const float opacity=1,
35408 const float sigma=0,
const bool is_high_connexity=
false) {
35410 return draw_fill(x,y,z,color,opacity,tmp,sigma,is_high_connexity);
35414 template<
typename tc>
35416 const tc *
const color,
const float opacity=1,
35417 const float sigma=0,
const bool is_high_connexity=
false) {
35419 return draw_fill(x,y,0,color,opacity,tmp,sigma,is_high_connexity);
35433 cimg_forZC(*
this,z,c) {
35435 for (
int delta = 1<<
cimg::min(scale,31U); delta>1; delta>>=1) {
35436 const int delta2 = delta>>1;
35437 const float r = alpha*delta + beta;
35440 for (
int y0 = 0; y0<h; y0+=delta)
35441 for (
int x0 = 0; x0<w; x0+=delta) {
35442 const int x1 = (x0 + delta)%w, y1 = (y0 + delta)%h, xc = (x0 + delta2)%w, yc = (y0 + delta2)%h;
35443 const Tfloat val = (Tfloat)(0.25f*(ref(x0,y0) + ref(x0,y1) + ref(x0,y1) + ref(x1,y1)) + r*
cimg::crand());
35444 ref(xc,yc) = (T)(val<m?m:val>M?M:val);
35448 for (
int y = -delta2; y<h; y+=delta)
35449 for (
int x0=0; x0<w; x0+=delta) {
35450 const int y0 =
cimg::mod(y,h), x1 = (x0 + delta)%w, y1 = (y + delta)%h,
35451 xc = (x0 + delta2)%w, yc = (y + delta2)%h;
35452 const Tfloat val = (Tfloat)(0.25f*(ref(xc,y0) + ref(x0,yc) + ref(xc,y1) + ref(x1,yc)) + r*
cimg::crand());
35453 ref(xc,yc) = (T)(val<m?m:val>M?M:val);
35455 for (
int y0 = 0; y0<h; y0+=delta)
35456 for (
int x = -delta2; x<w; x+=delta) {
35457 const int x0 =
cimg::mod(x,w), x1 = (x + delta)%w, y1 = (y0 + delta)%h,
35458 xc = (x + delta2)%w, yc = (y0 + delta2)%h;
35459 const Tfloat val = (Tfloat)(0.25f*(ref(xc,y0) + ref(x0,yc) + ref(xc,y1) + ref(x1,yc)) + r*
cimg::crand());
35460 ref(xc,yc) = (T)(val<m?m:val>M?M:val);
35462 for (
int y = -delta2; y<h; y+=delta)
35463 for (
int x = -delta2; x<w; x+=delta) {
35464 const int x0 =
cimg::mod(x,w), y0 =
cimg::mod(y,h), x1 = (x + delta)%w, y1 = (y + delta)%h,
35465 xc = (x + delta2)%w, yc = (y + delta2)%h;
35466 const Tfloat val = (Tfloat)(0.25f*(ref(xc,y0) + ref(x0,yc) + ref(xc,y1) + ref(x1,yc)) + r*
cimg::crand());
35467 ref(xc,yc) = (T)(val<m?m:val>M?M:val);
35493 template<
typename tc>
35495 const CImg<tc>& colormap,
const float opacity=1,
35496 const double z0r=-2,
const double z0i=-2,
const double z1r=2,
const double z1i=2,
35497 const unsigned int iteration_max=255,
35498 const bool is_normalized_iteration=
false,
35499 const bool is_julia_set=
false,
35500 const double param_r=0,
const double param_i=0) {
35503 if (colormap) palette.assign(colormap._data,colormap.size()/colormap._spectrum,1,1,colormap._spectrum,
true);
35504 if (palette && palette._spectrum!=_spectrum)
35506 "draw_mandelbrot(): Instance and specified colormap (%u,%u,%u,%u,%p) have "
35507 "incompatible dimensions.",
35509 colormap._width,colormap._height,colormap._depth,colormap._spectrum,colormap._data);
35511 const float nopacity =
cimg::abs(opacity), copacity = 1 -
cimg::max(opacity,0), ln2 = (float)std::log(2.0);
35517 #ifdef cimg_use_openmp
35518 #pragma omp parallel for collapse(2) if ((1+_x1-_x0)*(1+_y1-_y0)>=2048)
35520 for (
int q = _y0; q<=_y1; ++q)
35521 for (
int p = _x0; p<=_x1; ++p) {
35522 unsigned int iteration = 0;
35523 const double x = z0r + p*(z1r-z0r)/_width, y = z0i + q*(z1i-z0i)/_height;
35524 double zr, zi, cr, ci;
35525 if (is_julia_set) { zr = x; zi = y; cr = param_r; ci = param_i; }
35526 else { zr = param_r; zi = param_i; cr = x; ci = y; }
35527 for (iteration=1; zr*zr + zi*zi<=4 && iteration<=iteration_max; ++iteration) {
35528 const double temp = zr*zr - zi*zi + cr;
35532 if (iteration>iteration_max) {
35534 if (opacity>=1) cimg_forC(*
this,c) (*this)(p,q,0,c) = (T)palette(0,c);
35535 else cimg_forC(*
this,c) (*this)(p,q,0,c) = (T)(palette(0,c)*nopacity + (*this)(p,q,0,c)*copacity);
35537 if (opacity>=1) cimg_forC(*
this,c) (*this)(p,q,0,c) = (T)0;
35538 else cimg_forC(*
this,c) (*this)(p,q,0,c) = (T)((*this)(p,q,0,c)*copacity);
35540 }
else if (is_normalized_iteration) {
35543 niteration = (float)(iteration + 1 - std::log(std::log(normz))/ln2);
35545 if (opacity>=1) cimg_forC(*
this,c) (*this)(p,q,0,c) = (T)palette._linear_atX(niteration,c);
35546 else cimg_forC(*
this,c)
35547 (*this)(p,q,0,c) = (T)(palette._linear_atX(niteration,c)*nopacity + (*this)(p,q,0,c)*copacity);
35549 if (opacity>=1) cimg_forC(*
this,c) (*this)(p,q,0,c) = (T)niteration;
35550 else cimg_forC(*
this,c) (*this)(p,q,0,c) = (T)(niteration*nopacity + (*this)(p,q,0,c)*copacity);
35554 if (opacity>=1) cimg_forC(*
this,c) (*this)(p,q,0,c) = (T)palette._atX(iteration,c);
35555 else cimg_forC(*
this,c) (*this)(p,q,0,c) = (T)(palette(iteration,c)*nopacity + (*this)(p,q,0,c)*copacity);
35557 if (opacity>=1) cimg_forC(*
this,c) (*this)(p,q,0,c) = (T)iteration;
35558 else cimg_forC(*
this,c) (*this)(p,q,0,c) = (T)(iteration*nopacity + (*this)(p,q,0,c)*copacity);
35566 template<
typename tc>
35568 const double z0r=-2,
const double z0i=-2,
const double z1r=2,
const double z1i=2,
35569 const unsigned int iteration_max=255,
35570 const bool is_normalized_iteration=
false,
35571 const bool is_julia_set=
false,
35572 const double param_r=0,
const double param_i=0) {
35574 z0r,z0i,z1r,z1i,iteration_max,is_normalized_iteration,is_julia_set,param_r,param_i);
35584 template<
typename tc>
35586 const tc *
const color,
const float opacity=1) {
35590 "draw_gaussian(): Specified color is (null).",
35592 const float sigma2 = 2*sigma*sigma, nopacity =
cimg::abs(opacity), copacity = 1 -
cimg::max(opacity,0);
35593 const unsigned long whd = (
unsigned long)_width*_height*_depth;
35594 const tc *col = color;
35595 cimg_forX(*
this,x) {
35596 const float dx = (x - xc), val = (
float)std::exp(-dx*dx/sigma2);
35597 T *ptrd =
data(x,0,0,0);
35598 if (opacity>=1) cimg_forC(*
this,c) { *ptrd = (T)(val*(*col++)); ptrd+=whd; }
35599 else cimg_forC(*
this,c) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whd; }
35613 template<
typename t,
typename tc>
35615 const tc *
const color,
const float opacity=1) {
35617 if (tensor._width!=2 || tensor._height!=2 || tensor._depth!=1 || tensor._spectrum!=1)
35619 "draw_gaussian(): Specified tensor (%u,%u,%u,%u,%p) is not a 2x2 matrix.",
35621 tensor._width,tensor._height,tensor._depth,tensor._spectrum,tensor._data);
35624 "draw_gaussian(): Specified color is (null).",
35626 typedef typename CImg<t>::Tfloat tfloat;
35627 const CImg<tfloat> invT = tensor.get_invert(), invT2 = (invT*invT)/(-2.0);
35628 const tfloat a = invT2(0,0), b = 2*invT2(1,0), c = invT2(1,1);
35630 const unsigned long whd = (
unsigned long)_width*_height*_depth;
35631 const tc *col = color;
35633 cimg_forY(*
this,y) {
35635 cimg_forX(*
this,x) {
35636 const float val = (float)std::exp(a*dx*dx + b*dx*dy + c*dy*dy);
35637 T *ptrd =
data(x,y,0,0);
35638 if (opacity>=1) cimg_forC(*
this,c) { *ptrd = (T)(val*(*col++)); ptrd+=whd; }
35639 else cimg_forC(*
this,c) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whd; }
35649 template<
typename tc>
35651 const tc *
const color,
const float opacity=1) {
35653 a = r1*ru*ru + r2*rv*rv,
35655 c = r1*rv*rv + r2*ru*ru;
35661 template<
typename tc>
35663 const tc *
const color,
const float opacity=1) {
35668 template<
typename t,
typename tc>
35670 const tc *
const color,
const float opacity=1) {
35672 typedef typename CImg<t>::Tfloat tfloat;
35673 if (tensor._width!=3 || tensor._height!=3 || tensor._depth!=1 || tensor._spectrum!=1)
35675 "draw_gaussian(): Specified tensor (%u,%u,%u,%u,%p) is not a 3x3 matrix.",
35677 tensor._width,tensor._height,tensor._depth,tensor._spectrum,tensor._data);
35679 const CImg<tfloat> invT = tensor.get_invert(), invT2 = (invT*invT)/(-2.0);
35680 const tfloat a = invT2(0,0), b = 2*invT2(1,0), c = 2*invT2(2,0), d = invT2(1,1), e = 2*invT2(2,1), f = invT2(2,2);
35682 const unsigned long whd = (
unsigned long)_width*_height*_depth;
35683 const tc *col = color;
35684 cimg_forXYZ(*
this,x,y,z) {
35686 dx = (x - xc), dy = (y - yc), dz = (z - zc),
35687 val = (
float)std::exp(a*dx*dx + b*dx*dy + c*dx*dz + d*dy*dy + e*dy*dz + f*dz*dz);
35688 T *ptrd =
data(x,y,z,0);
35689 if (opacity>=1) cimg_forC(*
this,c) { *ptrd = (T)(val*(*col++)); ptrd+=whd; }
35690 else cimg_forC(*
this,c) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whd; }
35697 template<
typename tc>
35699 const tc *
const color,
const float opacity=1) {
35721 template<
typename tp,
typename tf,
typename tc,
typename to>
35725 const unsigned int render_type=4,
35726 const bool is_double_sided=
false,
const float focale=700,
35727 const float lightx=0,
const float lighty=0,
const float lightz=-5e8,
35728 const float specular_lightness=0.2f,
const float specular_shininess=0.1f) {
35729 return draw_object3d(x0,y0,z0,vertices,primitives,colors,opacities,render_type,
35730 is_double_sided,focale,lightx,lighty,lightz,
35735 template<
typename tp,
typename tf,
typename tc,
typename to,
typename tz>
35739 const unsigned int render_type,
35740 const bool is_double_sided,
const float focale,
35741 const float lightx,
const float lighty,
const float lightz,
35742 const float specular_lightness,
const float specular_shininess,
35744 return _draw_object3d(0,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities,
35745 render_type,is_double_sided,focale,lightx,lighty,lightz,
35746 specular_lightness,specular_shininess,1);
35749 #ifdef cimg_use_board
35750 template<
typename tp,
typename tf,
typename tc,
typename to>
35752 const float x0,
const float y0,
const float z0,
35755 const unsigned int render_type=4,
35756 const bool is_double_sided=
false,
const float focale=700,
35757 const float lightx=0,
const float lighty=0,
const float lightz=-5e8,
35758 const float specular_lightness=0.2f,
const float specular_shininess=0.1f) {
35759 return draw_object3d(board,x0,y0,z0,vertices,primitives,colors,opacities,render_type,
35760 is_double_sided,focale,lightx,lighty,lightz,
35764 template<
typename tp,
typename tf,
typename tc,
typename to,
typename tz>
35766 const float x0,
const float y0,
const float z0,
35767 const CImg<tp>& vertices,
const CImgList<tf>& primitives,
35768 const CImgList<tc>& colors,
const CImg<to>& opacities,
35769 const unsigned int render_type,
35770 const bool is_double_sided,
const float focale,
35771 const float lightx,
const float lighty,
const float lightz,
35772 const float specular_lightness,
const float specular_shininess,
35773 CImg<tz>& zbuffer) {
35774 return _draw_object3d((
void*)&board,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities,
35775 render_type,is_double_sided,focale,lightx,lighty,lightz,
35776 specular_lightness,specular_shininess,1);
35781 template<
typename tp,
typename tf,
typename tc,
typename to>
35785 const unsigned int render_type=4,
35786 const bool is_double_sided=
false,
const float focale=700,
35787 const float lightx=0,
const float lighty=0,
const float lightz=-5e8,
35788 const float specular_lightness=0.2f,
const float specular_shininess=0.1f) {
35789 return draw_object3d(x0,y0,z0,vertices,primitives,colors,opacities,render_type,
35790 is_double_sided,focale,lightx,lighty,lightz,
35795 template<
typename tp,
typename tf,
typename tc,
typename to,
typename tz>
35799 const unsigned int render_type,
35800 const bool is_double_sided,
const float focale,
35801 const float lightx,
const float lighty,
const float lightz,
35802 const float specular_lightness,
const float specular_shininess,
35804 return _draw_object3d(0,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities,
35805 render_type,is_double_sided,focale,lightx,lighty,lightz,
35806 specular_lightness,specular_shininess,1);
35809 #ifdef cimg_use_board
35810 template<
typename tp,
typename tf,
typename tc,
typename to>
35812 const float x0,
const float y0,
const float z0,
35815 const unsigned int render_type=4,
35816 const bool is_double_sided=
false,
const float focale=700,
35817 const float lightx=0,
const float lighty=0,
const float lightz=-5e8,
35818 const float specular_lightness=0.2f,
const float specular_shininess=0.1f) {
35819 return draw_object3d(board,x0,y0,z0,vertices,primitives,colors,opacities,render_type,
35820 is_double_sided,focale,lightx,lighty,lightz,
35824 template<
typename tp,
typename tf,
typename tc,
typename to,
typename tz>
35826 const float x0,
const float y0,
const float z0,
35827 const CImg<tp>& vertices,
const CImgList<tf>& primitives,
35828 const CImgList<tc>& colors,
const CImgList<to>& opacities,
35829 const unsigned int render_type,
35830 const bool is_double_sided,
const float focale,
35831 const float lightx,
const float lighty,
const float lightz,
35832 const float specular_lightness,
const float specular_shininess,
35833 CImg<tz>& zbuffer) {
35834 return _draw_object3d((
void*)&board,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities,
35835 render_type,is_double_sided,focale,lightx,lighty,lightz,
35836 specular_lightness,specular_shininess,1);
35841 template<
typename tp,
typename tf,
typename tc>
35845 const unsigned int render_type=4,
35846 const bool is_double_sided=
false,
const float focale=700,
35847 const float lightx=0,
const float lighty=0,
const float lightz=-5e8,
35848 const float specular_lightness=0.2f,
const float specular_shininess=0.1f) {
35850 render_type,is_double_sided,focale,lightx,lighty,lightz,
35855 template<
typename tp,
typename tf,
typename tc,
typename tz>
35859 const unsigned int render_type,
35860 const bool is_double_sided,
const float focale,
35861 const float lightx,
const float lighty,
const float lightz,
35862 const float specular_lightness,
const float specular_shininess,
35865 render_type,is_double_sided,focale,lightx,lighty,lightz,
35866 specular_lightness,specular_shininess,zbuffer);
35869 #ifdef cimg_use_board
35870 template<
typename tp,
typename tf,
typename tc,
typename to>
35872 const float x0,
const float y0,
const float z0,
35875 const unsigned int render_type=4,
35876 const bool is_double_sided=
false,
const float focale=700,
35877 const float lightx=0,
const float lighty=0,
const float lightz=-5e8,
35878 const float specular_lightness=0.2f,
const float specular_shininess=0.1f) {
35880 render_type,is_double_sided,focale,lightx,lighty,lightz,
35884 template<
typename tp,
typename tf,
typename tc,
typename to,
typename tz>
35886 const float x0,
const float y0,
const float z0,
35887 const CImg<tp>& vertices,
const CImgList<tf>& primitives,
35888 const CImgList<tc>& colors,
35889 const unsigned int render_type,
35890 const bool is_double_sided,
const float focale,
35891 const float lightx,
const float lighty,
const float lightz,
35892 const float specular_lightness,
const float specular_shininess,
35893 CImg<tz>& zbuffer) {
35895 render_type,is_double_sided,focale,lightx,lighty,lightz,
35896 specular_lightness,specular_shininess,zbuffer);
35900 template<
typename t,
typename to>
35901 static float __draw_object3d(
const CImgList<t>& opacities,
const unsigned int n_primitive, CImg<to>& opacity) {
35902 if (n_primitive>=opacities._width || opacities[n_primitive].is_empty()) { opacity.assign();
return 1; }
35903 if (opacities[n_primitive].
size()==1) { opacity.assign();
return opacities(n_primitive,0); }
35904 opacity.assign(opacities[n_primitive],
true);
35908 template<
typename t,
typename to>
35909 static float __draw_object3d(
const CImg<t>& opacities,
const unsigned int n_primitive, CImg<to>& opacity) {
35911 return n_primitive>=opacities._width?1.0f:(float)opacities[n_primitive];
35914 template<
typename tz,
typename tp,
typename tf,
typename tc,
typename to>
35915 CImg<T>& _draw_object3d(
void *
const pboard, CImg<tz>& zbuffer,
35916 const float X,
const float Y,
const float Z,
35917 const CImg<tp>& vertices,
35918 const CImgList<tf>& primitives,
35919 const CImgList<tc>& colors,
35920 const to& opacities,
35921 const unsigned int render_type,
35922 const bool is_double_sided,
const float focale,
35923 const float lightx,
const float lighty,
const float lightz,
35924 const float specular_lightness,
const float specular_shininess,
35925 const float sprite_scale) {
35926 typedef typename cimg::superset2<tp,tz,float>::type tpfloat;
35927 if (
is_empty() || !vertices || !primitives)
return *
this;
35928 char error_message[1024] = { 0 };
35929 if (!vertices.is_object3d(primitives,colors,opacities,
false,error_message))
35930 throw CImgArgumentException(_cimg_instance
35931 "draw_object3d(): Invalid specified 3d object (%u,%u) (%s).",
35932 cimg_instance,vertices._width,primitives._width,error_message);
35933 if (render_type==5) cimg::mutex(10);
35935 #ifndef cimg_use_board
35936 if (pboard)
return *
this;
35939 nspec = 1 - (specular_lightness<0.0f?0.0f:(specular_lightness>1.0f?1.0f:specular_lightness)),
35940 nspec2 = 1 + (specular_shininess<0.0f?0.0f:specular_shininess),
35941 nsl1 = (nspec2 - 1)/
cimg::sqr(nspec - 1),
35942 nsl2 = 1 - 2*nsl1*nspec,
35943 nsl3 = nspec2 - nsl1 - nsl2;
35946 CImg<floatT> light_texture;
35947 if (render_type==5) {
35948 if (colors._width>primitives._width) {
35949 static CImg<floatT> default_light_texture;
35950 static const tc *lptr = 0;
35951 static tc ref_values[64] = { 0 };
35952 const CImg<tc>& img = colors.back();
35953 bool is_same_texture = (lptr==img._data);
35954 if (is_same_texture)
35955 for (
unsigned int r = 0, j = 0; j<8; ++j)
35956 for (
unsigned int i = 0; i<8; ++i)
35957 if (ref_values[r++]!=img(i*img._width/9,j*img._height/9,0,(i+j)%img._spectrum)) {
35958 is_same_texture =
false;
break;
35960 if (!is_same_texture || default_light_texture._spectrum<_spectrum) {
35961 (default_light_texture.assign(img,
false)/=255).
resize(-100,-100,1,_spectrum);
35962 lptr = colors.back().data();
35963 for (
unsigned int r = 0, j = 0; j<8; ++j)
35964 for (
unsigned int i = 0; i<8; ++i)
35965 ref_values[r++] = img(i*img._width/9,j*img._height/9,0,(i+j)%img._spectrum);
35967 light_texture.assign(default_light_texture,
true);
35969 static CImg<floatT> default_light_texture;
35970 static float olightx = 0, olighty = 0, olightz = 0, ospecular_shininess = 0;
35971 if (!default_light_texture ||
35972 lightx!=olightx || lighty!=olighty || lightz!=olightz ||
35973 specular_shininess!=ospecular_shininess || default_light_texture._spectrum<_spectrum) {
35974 default_light_texture.assign(512,512);
35979 nl = (float)std::sqrt(dlx*dlx + dly*dly + dlz*dlz),
35980 nlx = (default_light_texture._width - 1)/2*(1 + dlx/nl),
35981 nly = (default_light_texture._height - 1)/2*(1 + dly/nl),
35983 default_light_texture.draw_gaussian(nlx,nly,default_light_texture._width/3.0f,white);
35984 cimg_forXY(default_light_texture,x,y) {
35985 const float factor = default_light_texture(x,y);
35986 if (factor>nspec) default_light_texture(x,y) =
cimg::min(2,nsl1*factor*factor + nsl2*factor + nsl3);
35988 default_light_texture.resize(-100,-100,1,_spectrum);
35989 olightx = lightx; olighty = lighty; olightz = lightz; ospecular_shininess = specular_shininess;
35991 light_texture.assign(default_light_texture,
true);
35996 CImg<tpfloat> projections(vertices._width,2);
35997 tpfloat parallzmin = cimg::type<tpfloat>::max();
35998 const float absfocale = focale?
cimg::abs(focale):0;
36000 #ifdef cimg_use_openmp
36001 #pragma omp parallel for if (projections.size()>4096)
36003 cimg_forX(projections,l) {
36005 x = (tpfloat)vertices(l,0),
36006 y = (tpfloat)vertices(l,1),
36007 z = (tpfloat)vertices(l,2);
36008 const tpfloat projectedz = z + Z + absfocale;
36009 projections(l,1) = Y + absfocale*y/projectedz;
36010 projections(l,0) = X + absfocale*x/projectedz;
36014 #ifdef cimg_use_openmp
36015 #pragma omp parallel for if (projections.size()>4096)
36017 cimg_forX(projections,l) {
36019 x = (tpfloat)vertices(l,0),
36020 y = (tpfloat)vertices(l,1),
36021 z = (tpfloat)vertices(l,2);
36022 if (z<parallzmin) parallzmin = z;
36023 projections(l,1) = Y + y;
36024 projections(l,0) = X + x;
36027 const float _focale = absfocale?absfocale:(1e5f-parallzmin);
36030 CImg<uintT> visibles(primitives._width,1,1,1,~0U);
36031 CImg<tpfloat> zrange(primitives._width);
36032 const tpfloat zmin = absfocale?(tpfloat)(1.5f - absfocale):cimg::type<tpfloat>::
min();
36034 #ifdef cimg_use_openmp
36035 #pragma omp parallel for if (primitives.size()>4096)
36037 cimglist_for(primitives,l) {
36038 const CImg<tf>& primitive = primitives[l];
36039 switch (primitive.size()) {
36041 const unsigned int i0 = (
unsigned int)primitive(0);
36042 const tpfloat z0 = Z + vertices(i0,2);
36044 visibles(l) = (
unsigned int)l;
36050 i0 = (
unsigned int)primitive(0),
36051 i1 = (
unsigned int)primitive(1);
36053 Xc = 0.5f*((float)vertices(i0,0) + (float)vertices(i1,0)),
36054 Yc = 0.5f*((
float)vertices(i0,1) + (float)vertices(i1,1)),
36055 Zc = 0.5f*((
float)vertices(i0,2) + (float)vertices(i1,2)),
36057 zc = _zc + _focale,
36058 xc = X + Xc*(absfocale?absfocale/zc:1),
36059 yc = Y + Yc*(absfocale?absfocale/zc:1),
36060 radius = 0.5f*std::sqrt(
cimg::sqr(vertices(i1,0) - vertices(i0,0)) +
36061 cimg::sqr(vertices(i1,1) - vertices(i0,1)) +
36062 cimg::sqr(vertices(i1,2) - vertices(i0,2)))*(absfocale?absfocale/zc:1),
36067 if (xM>=0 && xm<_width && yM>=0 && ym<_height && _zc>zmin) {
36068 visibles(l) = (
unsigned int)l;
36075 i0 = (
unsigned int)primitive(0),
36076 i1 = (
unsigned int)primitive(1);
36078 x0 = projections(i0,0), y0 = projections(i0,1), z0 = Z + vertices(i0,2),
36079 x1 = projections(i1,0), y1 = projections(i1,1), z1 = Z + vertices(i1,2);
36080 tpfloat xm, xM, ym, yM;
36081 if (x0<x1) { xm = x0; xM = x1; }
else { xm = x1; xM = x0; }
36082 if (y0<y1) { ym = y0; yM = y1; }
else { ym = y1; yM = y0; }
36083 if (xM>=0 && xm<_width && yM>=0 && ym<_height && z0>zmin && z1>zmin) {
36084 visibles(l) = (
unsigned int)l;
36085 zrange(l) = (z0 + z1)/2;
36091 i0 = (
unsigned int)primitive(0),
36092 i1 = (
unsigned int)primitive(1),
36093 i2 = (
unsigned int)primitive(2);
36095 x0 = projections(i0,0), y0 = projections(i0,1), z0 = Z + vertices(i0,2),
36096 x1 = projections(i1,0), y1 = projections(i1,1), z1 = Z + vertices(i1,2),
36097 x2 = projections(i2,0), y2 = projections(i2,1), z2 = Z + vertices(i2,2);
36098 tpfloat xm, xM, ym, yM;
36099 if (x0<x1) { xm = x0; xM = x1; }
else { xm = x1; xM = x0; }
36100 if (x2<xm) xm = x2;
36101 if (x2>xM) xM = x2;
36102 if (y0<y1) { ym = y0; yM = y1; }
else { ym = y1; yM = y0; }
36103 if (y2<ym) ym = y2;
36104 if (y2>yM) yM = y2;
36105 if (xM>=0 && xm<_width && yM>=0 && ym<_height && z0>zmin && z1>zmin && z2>zmin) {
36106 const tpfloat d = (x1-x0)*(y2-y0) - (x2-x0)*(y1-y0);
36107 if (is_double_sided || d<0) {
36108 visibles(l) = (
unsigned int)l;
36109 zrange(l) = (z0 + z1 + z2)/3;
36116 i0 = (
unsigned int)primitive(0),
36117 i1 = (
unsigned int)primitive(1),
36118 i2 = (
unsigned int)primitive(2),
36119 i3 = (
unsigned int)primitive(3);
36121 x0 = projections(i0,0), y0 = projections(i0,1), z0 = Z + vertices(i0,2),
36122 x1 = projections(i1,0), y1 = projections(i1,1), z1 = Z + vertices(i1,2),
36123 x2 = projections(i2,0), y2 = projections(i2,1), z2 = Z + vertices(i2,2),
36124 x3 = projections(i3,0), y3 = projections(i3,1), z3 = Z + vertices(i3,2);
36125 tpfloat xm, xM, ym, yM;
36126 if (x0<x1) { xm = x0; xM = x1; }
else { xm = x1; xM = x0; }
36127 if (x2<xm) xm = x2;
36128 if (x2>xM) xM = x2;
36129 if (x3<xm) xm = x3;
36130 if (x3>xM) xM = x3;
36131 if (y0<y1) { ym = y0; yM = y1; }
else { ym = y1; yM = y0; }
36132 if (y2<ym) ym = y2;
36133 if (y2>yM) yM = y2;
36134 if (y3<ym) ym = y3;
36135 if (y3>yM) yM = y3;
36136 if (xM>=0 && xm<_width && yM>=0 && ym<_height && z0>zmin && z1>zmin && z2>zmin) {
36137 const float d = (x1 - x0)*(y2 - y0) - (x2 - x0)*(y1 - y0);
36138 if (is_double_sided || d<0) {
36139 visibles(l) = (
unsigned int)l;
36140 zrange(l) = (z0 + z1 + z2 + z3)/4;
36145 throw CImgArgumentException(_cimg_instance
36146 "draw_object3d(): Invalid primitive[%u] with size %u "
36147 "(should have size 1,2,3,4,5,6,9 or 12).",
36149 l,primitive.size());
36154 unsigned int *p_visibles = visibles._data;
36155 float *p_zrange = zrange._data;
36156 const float *ptrz = p_zrange;
36157 cimg_for(visibles,ptr,
unsigned int) {
36158 if (*ptr!=~0U) { *(p_visibles++) = *ptr; *(p_zrange++) = *ptrz; }
36161 const unsigned int nb_visibles = p_zrange - zrange._data;
36162 if (!nb_visibles)
return *
this;
36163 CImg<uintT> permutations;
36164 CImg<tpfloat>(zrange._data,nb_visibles,1,1,1,
true).
sort(permutations,
false);
36167 CImg<floatT> lightprops;
36168 switch (render_type) {
36170 lightprops.assign(nb_visibles);
36171 #ifdef cimg_use_openmp
36172 #pragma omp parallel for if (nb_visibles>4096)
36174 cimg_forX(lightprops,l) {
36175 const CImg<tf>& primitive = primitives(visibles(permutations(l)));
36176 const unsigned int psize = primitive.size();
36177 if (psize==3 || psize==4 || psize==9 || psize==12) {
36179 i0 = (
unsigned int)primitive(0),
36180 i1 = (
unsigned int)primitive(1),
36181 i2 = (
unsigned int)primitive(2);
36183 x0 = (tpfloat)vertices(i0,0), y0 = (tpfloat)vertices(i0,1), z0 = (tpfloat)vertices(i0,2),
36184 x1 = (tpfloat)vertices(i1,0), y1 = (tpfloat)vertices(i1,1), z1 = (tpfloat)vertices(i1,2),
36185 x2 = (tpfloat)vertices(i2,0), y2 = (tpfloat)vertices(i2,1), z2 = (tpfloat)vertices(i2,2),
36186 dx1 = x1 - x0, dy1 = y1 - y0, dz1 = z1 - z0,
36187 dx2 = x2 - x0, dy2 = y2 - y0, dz2 = z2 - z0,
36188 nx = dy1*dz2 - dz1*dy2,
36189 ny = dz1*dx2 - dx1*dz2,
36190 nz = dx1*dy2 - dy1*dx2,
36191 norm = (tpfloat)std::sqrt(1e-5f + nx*nx + ny*ny + nz*nz),
36192 lx = X + (x0 + x1 + x2)/3 - lightx,
36193 ly = Y + (y0 + y1 + y2)/3 - lighty,
36194 lz = Z + (z0 + z1 + z2)/3 - lightz,
36195 nl = (tpfloat)
std::
sqrt(1e-5f + lx*lx + ly*ly + lz*lz),
36196 factor = cimg::
max(cimg::
abs(-lx*nx-ly*ny-lz*nz)/(norm*nl),0);
36197 lightprops[l] = factor<=nspec?factor:(nsl1*factor*factor + nsl2*factor + nsl3);
36198 } else lightprops[l] = 1;
36204 CImg<tpfloat> vertices_normals(vertices._width,3,1,1,0);
36205 #ifdef cimg_use_openmp
36206 #pragma omp parallel for if (nb_visibles>4096)
36208 for (
unsigned int l = 0; l<nb_visibles; ++l) {
36209 const CImg<tf>& primitive = primitives[visibles(l)];
36210 const unsigned int psize = primitive.size();
36212 triangle_flag = (psize==3) || (psize==9),
36213 rectangle_flag = (psize==4) || (psize==12);
36214 if (triangle_flag || rectangle_flag) {
36216 i0 = (
unsigned int)primitive(0),
36217 i1 = (
unsigned int)primitive(1),
36218 i2 = (
unsigned int)primitive(2),
36219 i3 = rectangle_flag?(
unsigned int)primitive(3):0;
36221 x0 = (tpfloat)vertices(i0,0), y0 = (tpfloat)vertices(i0,1), z0 = (tpfloat)vertices(i0,2),
36222 x1 = (tpfloat)vertices(i1,0), y1 = (tpfloat)vertices(i1,1), z1 = (tpfloat)vertices(i1,2),
36223 x2 = (tpfloat)vertices(i2,0), y2 = (tpfloat)vertices(i2,1), z2 = (tpfloat)vertices(i2,2),
36224 dx1 = x1 - x0, dy1 = y1 - y0, dz1 = z1 - z0,
36225 dx2 = x2 - x0, dy2 = y2 - y0, dz2 = z2 - z0,
36226 nnx = dy1*dz2 - dz1*dy2,
36227 nny = dz1*dx2 - dx1*dz2,
36228 nnz = dx1*dy2 - dy1*dx2,
36229 norm = (tpfloat)(1e-5f + std::sqrt(nnx*nnx + nny*nny + nnz*nnz)),
36233 vertices_normals(i0,0)+=nx; vertices_normals(i0,1)+=ny; vertices_normals(i0,2)+=nz;
36234 vertices_normals(i1,0)+=nx; vertices_normals(i1,1)+=ny; vertices_normals(i1,2)+=nz;
36235 vertices_normals(i2,0)+=nx; vertices_normals(i2,1)+=ny; vertices_normals(i2,2)+=nz;
36236 if (rectangle_flag) { vertices_normals(i3,0)+=nx; vertices_normals(i3,1)+=ny; vertices_normals(i3,2)+=nz; }
36240 if (is_double_sided) cimg_forX(vertices_normals,p) if (vertices_normals(p,2)>0) {
36241 vertices_normals(p,0) = -vertices_normals(p,0);
36242 vertices_normals(p,1) = -vertices_normals(p,1);
36243 vertices_normals(p,2) = -vertices_normals(p,2);
36246 if (render_type==4) {
36247 lightprops.assign(vertices._width);
36248 #ifdef cimg_use_openmp
36249 #pragma omp parallel for if (nb_visibles>4096)
36251 cimg_forX(lightprops,l) {
36253 nx = vertices_normals(l,0),
36254 ny = vertices_normals(l,1),
36255 nz = vertices_normals(l,2),
36256 norm = (tpfloat)std::sqrt(1e-5f + nx*nx + ny*ny + nz*nz),
36257 lx = X + vertices(l,0) - lightx,
36258 ly = Y + vertices(l,1) - lighty,
36259 lz = Z + vertices(l,2) - lightz,
36260 nl = (tpfloat)std::sqrt(1e-5f + lx*lx + ly*ly + lz*lz),
36261 factor =
cimg::max((-lx*nx-ly*ny-lz*nz)/(norm*nl),0);
36262 lightprops[l] = factor<=nspec?factor:(nsl1*factor*factor + nsl2*factor + nsl3);
36266 lw2 = light_texture._width/2 - 1,
36267 lh2 = light_texture._height/2 - 1;
36268 lightprops.assign(vertices._width,2);
36269 #ifdef cimg_use_openmp
36270 #pragma omp parallel for if (nb_visibles>4096)
36272 cimg_forX(lightprops,l) {
36274 nx = vertices_normals(l,0),
36275 ny = vertices_normals(l,1),
36276 nz = vertices_normals(l,2),
36277 norm = (tpfloat)std::sqrt(1e-5f + nx*nx + ny*ny + nz*nz),
36280 lightprops(l,0) = lw2*(1 + nnx);
36281 lightprops(l,1) = lh2*(1 + nny);
36288 const CImg<tc> default_color(1,_spectrum,1,1,(tc)200);
36289 typedef typename to::value_type _to;
36290 CImg<_to> _opacity;
36292 for (
unsigned int l = 0; l<nb_visibles; ++l) {
36293 const unsigned int n_primitive = visibles(permutations(l));
36294 const CImg<tf>& primitive = primitives[n_primitive];
36296 &__color = n_primitive<colors._width?colors[n_primitive]:CImg<tc>(),
36297 _color = (__color && __color.size()!=_spectrum && __color._spectrum<_spectrum)?
36298 __color.get_resize(-100,-100,-100,_spectrum,0):CImg<tc>(),
36299 &color = _color?_color:(__color?__color:default_color);
36300 const tc *
const pcolor = color._data;
36301 const float opacity = __draw_object3d(opacities,n_primitive,_opacity);
36303 #ifdef cimg_use_board
36304 LibBoard::Board &board = *(LibBoard::Board*)pboard;
36307 switch (primitive.size()) {
36309 const unsigned int n0 = (
unsigned int)primitive[0];
36310 const int x0 = (int)projections(n0,0), y0 = (int)projections(n0,1);
36312 if (_opacity.is_empty()) {
36314 if (color.size()==_spectrum) {
36316 #ifdef cimg_use_board
36318 board.setPenColorRGBi(color[0],color[1],color[2],(
unsigned char)(opacity*255));
36319 board.fillCircle((
float)x0,
height()-(
float)y0,0);
36323 const tpfloat z = Z + vertices(n0,2);
36324 const float factor = focale<0?1:sprite_scale*(absfocale?absfocale/(z + absfocale):1);
36326 _sw = (
unsigned int)(color._width*factor),
36327 _sh = (
unsigned int)(color._height*factor),
36328 sw = _sw?_sw:1, sh = _sh?_sh:1;
36329 const int nx0 = x0 - (int)sw/2, ny0 = y0 - (
int)sh/2;
36330 if (sw<=3*_width/2 && sh<=3*_height/2 &&
36331 (nx0+(
int)sw/2>=0 || nx0-(
int)sw/2<width() || ny0+(
int)sh/2>=0 || ny0-(
int)sh/2<
height())) {
36333 _sprite = (sw!=color._width || sh!=color._height)?
36334 color.get_resize(sw,sh,1,-100,render_type<=3?1:3):CImg<tc>(),
36335 &sprite = _sprite?_sprite:color;
36337 #ifdef cimg_use_board
36339 board.setPenColorRGBi(128,128,128);
36340 board.setFillColor(LibBoard::Color::None);
36341 board.drawRectangle((
float)nx0,
height()-(
float)ny0,sw,sh);
36347 const tpfloat z = Z + vertices(n0,2);
36348 const float factor = focale<0?1:sprite_scale*(absfocale?absfocale/(z + absfocale):1);
36350 _sw = (
unsigned int)(
cimg::max(color._width,_opacity._width)*factor),
36351 _sh = (
unsigned int)(
cimg::max(color._height,_opacity._height)*factor),
36352 sw = _sw?_sw:1, sh = _sh?_sh:1;
36353 const int nx0 = x0 - (int)sw/2, ny0 = y0 - (
int)sh/2;
36354 if (sw<=3*_width/2 && sh<=3*_height/2 &&
36355 (nx0+(
int)sw/2>=0 || nx0-(
int)sw/2<width() || ny0+(
int)sh/2>=0 || ny0-(
int)sh/2<height())) {
36357 _sprite = (sw!=color._width || sh!=color._height)?
36358 color.get_resize(sw,sh,1,-100,render_type<=3?1:3):CImg<tc>(),
36359 &sprite = _sprite?_sprite:color;
36361 _nopacity = (sw!=_opacity._width || sh!=_opacity._height)?
36362 _opacity.get_resize(sw,sh,1,-100,render_type<=3?1:3):CImg<_to>(),
36363 &nopacity = _nopacity?_nopacity:_opacity;
36365 #ifdef cimg_use_board
36367 board.setPenColorRGBi(128,128,128);
36368 board.setFillColor(LibBoard::Color::None);
36369 board.drawRectangle((
float)nx0,
height()-(
float)ny0,sw,sh);
36377 n0 = (
unsigned int)primitive[0],
36378 n1 = (
unsigned int)primitive[1];
36380 x0 = (int)projections(n0,0), y0 = (int)projections(n0,1),
36381 x1 = (int)projections(n1,0), y1 = (int)projections(n1,1);
36383 z0 = vertices(n0,2) + Z + _focale,
36384 z1 = vertices(n1,2) + Z + _focale;
36386 if (zbuffer)
draw_line(zbuffer,x0,y0,z0,x1,y1,z1,pcolor,opacity);
36387 else draw_line(x0,y0,x1,y1,pcolor,opacity);
36388 #ifdef cimg_use_board
36390 board.setPenColorRGBi(color[0],color[1],color[2],(
unsigned char)(opacity*255));
36391 board.drawLine((
float)x0,
height()-(
float)y0,x1,
height()-(
float)y1);
36395 draw_point(x0,y0,pcolor,opacity).draw_point(x1,y1,pcolor,opacity);
36396 #ifdef cimg_use_board
36398 board.setPenColorRGBi(color[0],color[1],color[2],(
unsigned char)(opacity*255));
36399 board.drawCircle((
float)x0,
height()-(
float)y0,0);
36400 board.drawCircle((
float)x1,
height()-(
float)y1,0);
36407 n0 = (
unsigned int)primitive[0],
36408 n1 = (
unsigned int)primitive[1],
36409 is_wireframe = (
unsigned int)primitive[2];
36411 Xc = 0.5f*((float)vertices(n0,0) + (float)vertices(n1,0)),
36412 Yc = 0.5f*((
float)vertices(n0,1) + (float)vertices(n1,1)),
36413 Zc = 0.5f*((
float)vertices(n0,2) + (float)vertices(n1,2)),
36414 zc = Z + Zc + _focale,
36415 xc = X + Xc*(absfocale?absfocale/zc:1),
36416 yc = Y + Yc*(absfocale?absfocale/zc:1),
36417 radius = 0.5f*std::sqrt(
cimg::sqr(vertices(n1,0) - vertices(n0,0)) +
36418 cimg::sqr(vertices(n1,1) - vertices(n0,1)) +
36419 cimg::sqr(vertices(n1,2) - vertices(n0,2)))*(absfocale?absfocale/zc:1);
36420 switch (render_type) {
36423 #ifdef cimg_use_board
36425 board.setPenColorRGBi(color[0],color[1],color[2],(
unsigned char)(opacity*255));
36426 board.fillCircle(xc,
height()-yc,0);
36431 draw_circle((
int)xc,(
int)yc,(
int)radius,pcolor,opacity,~0U);
36432 #ifdef cimg_use_board
36434 board.setPenColorRGBi(color[0],color[1],color[2],(
unsigned char)(opacity*255));
36435 board.setFillColor(LibBoard::Color::None);
36436 board.drawCircle(xc,
height()-yc,radius);
36441 if (is_wireframe)
draw_circle((
int)xc,(
int)yc,(
int)radius,pcolor,opacity,~0U);
36442 else draw_circle((
int)xc,(
int)yc,(
int)radius,pcolor,opacity);
36443 #ifdef cimg_use_board
36445 board.setPenColorRGBi(color[0],color[1],color[2],(
unsigned char)(opacity*255));
36446 if (!is_wireframe) board.fillCircle(xc,
height()-yc,radius);
36448 board.setFillColor(LibBoard::Color::None);
36449 board.drawCircle(xc,
height()-yc,radius);
36458 throw CImgArgumentException(_cimg_instance
36459 "draw_object3d(): Undefined texture for line primitive [%u].",
36460 cimg_instance,n_primitive);
36462 n0 = (
unsigned int)primitive[0],
36463 n1 = (
unsigned int)primitive[1],
36464 tx0 = (
unsigned int)primitive[2],
36465 ty0 = (
unsigned int)primitive[3],
36466 tx1 = (
unsigned int)primitive[4],
36467 ty1 = (
unsigned int)primitive[5];
36469 x0 = (int)projections(n0,0), y0 = (int)projections(n0,1),
36470 x1 = (int)projections(n1,0), y1 = (int)projections(n1,1);
36472 z0 = vertices(n0,2) + Z + _focale,
36473 z1 = vertices(n1,2) + Z + _focale;
36475 if (zbuffer)
draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity);
36476 else draw_line(x0,y0,x1,y1,color,tx0,ty0,tx1,ty1,opacity);
36477 #ifdef cimg_use_board
36479 board.setPenColorRGBi(128,128,128,(
unsigned char)(opacity*255));
36480 board.drawLine((
float)x0,
height()-(
float)y0,(
float)x1,
height()-(
float)y1);
36484 draw_point(x0,y0,color.get_vector_at(tx0,ty0)._data,opacity).
36485 draw_point(x1,y1,color.get_vector_at(tx1,ty1)._data,opacity);
36486 #ifdef cimg_use_board
36488 board.setPenColorRGBi(128,128,128,(
unsigned char)(opacity*255));
36489 board.drawCircle((
float)x0,
height()-(
float)y0,0);
36490 board.drawCircle((
float)x1,
height()-(
float)y1,0);
36497 n0 = (
unsigned int)primitive[0],
36498 n1 = (
unsigned int)primitive[1],
36499 n2 = (
unsigned int)primitive[2];
36501 x0 = (int)projections(n0,0), y0 = (int)projections(n0,1),
36502 x1 = (int)projections(n1,0), y1 = (int)projections(n1,1),
36503 x2 = (int)projections(n2,0), y2 = (int)projections(n2,1);
36505 z0 = vertices(n0,2) + Z + _focale,
36506 z1 = vertices(n1,2) + Z + _focale,
36507 z2 = vertices(n2,2) + Z + _focale;
36508 switch (render_type) {
36510 draw_point(x0,y0,pcolor,opacity).draw_point(x1,y1,pcolor,opacity).draw_point(x2,y2,pcolor,opacity);
36511 #ifdef cimg_use_board
36513 board.setPenColorRGBi(color[0],color[1],color[2],(
unsigned char)(opacity*255));
36514 board.drawCircle((
float)x0,
height()-(
float)y0,0);
36515 board.drawCircle((
float)x1,
height()-(
float)y1,0);
36516 board.drawCircle((
float)x2,
height()-(
float)y2,0);
36522 draw_line(zbuffer,x0,y0,z0,x1,y1,z1,pcolor,opacity).draw_line(zbuffer,x0,y0,z0,x2,y2,z2,pcolor,opacity).
36523 draw_line(zbuffer,x1,y1,z1,x2,y2,z2,pcolor,opacity);
36525 draw_line(x0,y0,x1,y1,pcolor,opacity).draw_line(x0,y0,x2,y2,pcolor,opacity).
36527 #ifdef cimg_use_board
36529 board.setPenColorRGBi(color[0],color[1],color[2],(
unsigned char)(opacity*255));
36530 board.drawLine((
float)x0,
height()-(
float)y0,(
float)x1,
height()-(
float)y1);
36531 board.drawLine((
float)x0,
height()-(
float)y0,(
float)x2,
height()-(
float)y2);
36532 board.drawLine((
float)x1,
height()-(
float)y1,(
float)x2,
height()-(
float)y2);
36537 if (zbuffer)
draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity);
36539 #ifdef cimg_use_board
36541 board.setPenColorRGBi(color[0],color[1],color[2],(
unsigned char)(opacity*255));
36542 board.fillTriangle((
float)x0,
height()-(
float)y0,
36543 (
float)x1,
height()-(
float)y1,
36544 (
float)x2,
height()-(
float)y2);
36549 if (zbuffer)
draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity,lightprops(l));
36550 else _draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity,lightprops(l));
36551 #ifdef cimg_use_board
36553 const float lp =
cimg::min(lightprops(l),1);
36554 board.setPenColorRGBi((
unsigned char)(color[0]*lp),
36555 (
unsigned char)(color[1]*lp),
36556 (
unsigned char)(color[2]*lp),
36557 (
unsigned char)(opacity*255));
36558 board.fillTriangle((
float)x0,
height()-(
float)y0,
36559 (
float)x1,
height()-(
float)y1,
36560 (
float)x2,
height()-(
float)y2);
36566 draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,
36567 lightprops(n0),lightprops(n1),lightprops(n2),opacity);
36568 else draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,lightprops(n0),lightprops(n1),lightprops(n2),opacity);
36569 #ifdef cimg_use_board
36571 board.setPenColorRGBi((
unsigned char)(color[0]),
36572 (
unsigned char)(color[1]),
36573 (
unsigned char)(color[2]),
36574 (
unsigned char)(opacity*255));
36575 board.fillGouraudTriangle((
float)x0,
height()-(
float)y0,lightprops(n0),
36576 (
float)x1,
height()-(
float)y1,lightprops(n1),
36577 (
float)x2,
height()-(
float)y2,lightprops(n2));
36583 lx0 = (
unsigned int)lightprops(n0,0), ly0 = (
unsigned int)lightprops(n0,1),
36584 lx1 = (
unsigned int)lightprops(n1,0), ly1 = (
unsigned int)lightprops(n1,1),
36585 lx2 = (
unsigned int)lightprops(n2,0), ly2 = (
unsigned int)lightprops(n2,1);
36587 draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
36588 else draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
36589 #ifdef cimg_use_board
36592 l0 = light_texture((
int)(light_texture.width()/2*(1+lightprops(n0,0))),
36593 (int)(light_texture.height()/2*(1+lightprops(n0,1)))),
36594 l1 = light_texture((
int)(light_texture.width()/2*(1+lightprops(n1,0))),
36595 (int)(light_texture.height()/2*(1+lightprops(n1,1)))),
36596 l2 = light_texture((
int)(light_texture.width()/2*(1+lightprops(n2,0))),
36597 (int)(light_texture.height()/2*(1+lightprops(n2,1))));
36598 board.setPenColorRGBi((
unsigned char)(color[0]),
36599 (
unsigned char)(color[1]),
36600 (
unsigned char)(color[2]),
36601 (
unsigned char)(opacity*255));
36602 board.fillGouraudTriangle((
float)x0,
height()-(
float)y0,l0,
36603 (
float)x1,
height()-(
float)y1,l1,
36604 (
float)x2,
height()-(
float)y2,l2);
36612 n0 = (
unsigned int)primitive[0],
36613 n1 = (
unsigned int)primitive[1],
36614 n2 = (
unsigned int)primitive[2],
36615 n3 = (
unsigned int)primitive[3];
36617 x0 = (int)projections(n0,0), y0 = (int)projections(n0,1),
36618 x1 = (int)projections(n1,0), y1 = (int)projections(n1,1),
36619 x2 = (int)projections(n2,0), y2 = (int)projections(n2,1),
36620 x3 = (int)projections(n3,0), y3 = (int)projections(n3,1);
36622 z0 = vertices(n0,2) + Z + _focale,
36623 z1 = vertices(n1,2) + Z + _focale,
36624 z2 = vertices(n2,2) + Z + _focale,
36625 z3 = vertices(n3,2) + Z + _focale;
36627 switch (render_type) {
36629 draw_point(x0,y0,pcolor,opacity).draw_point(x1,y1,pcolor,opacity).
36630 draw_point(x2,y2,pcolor,opacity).draw_point(x3,y3,pcolor,opacity);
36631 #ifdef cimg_use_board
36633 board.setPenColorRGBi(color[0],color[1],color[2],(
unsigned char)(opacity*255));
36634 board.drawCircle((
float)x0,
height()-(
float)y0,0);
36635 board.drawCircle((
float)x1,
height()-(
float)y1,0);
36636 board.drawCircle((
float)x2,
height()-(
float)y2,0);
36637 board.drawCircle((
float)x3,
height()-(
float)y3,0);
36643 draw_line(zbuffer,x0,y0,z0,x1,y1,z1,pcolor,opacity).draw_line(zbuffer,x1,y1,z1,x2,y2,z2,pcolor,opacity).
36644 draw_line(zbuffer,x2,y2,z2,x3,y3,z3,pcolor,opacity).draw_line(zbuffer,x3,y3,z3,x0,y0,z0,pcolor,opacity);
36646 draw_line(x0,y0,x1,y1,pcolor,opacity).draw_line(x1,y1,x2,y2,pcolor,opacity).
36647 draw_line(x2,y2,x3,y3,pcolor,opacity).draw_line(x3,y3,x0,y0,pcolor,opacity);
36648 #ifdef cimg_use_board
36650 board.setPenColorRGBi(color[0],color[1],color[2],(
unsigned char)(opacity*255));
36651 board.drawLine((
float)x0,
height()-(
float)y0,(
float)x1,
height()-(
float)y1);
36652 board.drawLine((
float)x1,
height()-(
float)y1,(
float)x2,
height()-(
float)y2);
36653 board.drawLine((
float)x2,
height()-(
float)y2,(
float)x3,
height()-(
float)y3);
36654 board.drawLine((
float)x3,
height()-(
float)y3,(
float)x0,
height()-(
float)y0);
36660 draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity).
36661 draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,pcolor,opacity);
36663 draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity).draw_triangle(x0,y0,x2,y2,x3,y3,pcolor,opacity);
36664 #ifdef cimg_use_board
36666 board.setPenColorRGBi(color[0],color[1],color[2],(
unsigned char)(opacity*255));
36667 board.fillTriangle((
float)x0,
height()-(
float)y0,
36668 (
float)x1,
height()-(
float)y1,
36669 (
float)x2,
height()-(
float)y2);
36670 board.fillTriangle((
float)x0,
height()-(
float)y0,
36671 (
float)x2,
height()-(
float)y2,
36672 (
float)x3,
height()-(
float)y3);
36678 draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity,lightprops(l)).
36679 draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,pcolor,opacity,lightprops(l));
36681 _draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity,lightprops(l)).
36682 _draw_triangle(x0,y0,x2,y2,x3,y3,pcolor,opacity,lightprops(l));
36683 #ifdef cimg_use_board
36685 const float lp =
cimg::min(lightprops(l),1);
36686 board.setPenColorRGBi((
unsigned char)(color[0]*lp),
36687 (
unsigned char)(color[1]*lp),
36688 (
unsigned char)(color[2]*lp),(
unsigned char)(opacity*255));
36689 board.fillTriangle((
float)x0,
height()-(
float)y0,
36690 (
float)x1,
height()-(
float)y1,
36691 (
float)x2,
height()-(
float)y2);
36692 board.fillTriangle((
float)x0,
height()-(
float)y0,
36693 (
float)x2,
height()-(
float)y2,
36694 (
float)x3,
height()-(
float)y3);
36700 lightprop0 = lightprops(n0), lightprop1 = lightprops(n1),
36701 lightprop2 = lightprops(n2), lightprop3 = lightprops(n3);
36703 draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,lightprop0,lightprop1,lightprop2,opacity).
36704 draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,pcolor,lightprop0,lightprop2,lightprop3,opacity);
36706 draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,lightprop0,lightprop1,lightprop2,opacity).
36707 draw_triangle(x0,y0,x2,y2,x3,y3,pcolor,lightprop0,lightprop2,lightprop3,opacity);
36708 #ifdef cimg_use_board
36710 board.setPenColorRGBi((
unsigned char)(color[0]),
36711 (
unsigned char)(color[1]),
36712 (
unsigned char)(color[2]),
36713 (
unsigned char)(opacity*255));
36714 board.fillGouraudTriangle((
float)x0,
height()-(
float)y0,lightprop0,
36715 (
float)x1,
height()-(
float)y1,lightprop1,
36716 (
float)x2,
height()-(
float)y2,lightprop2);
36717 board.fillGouraudTriangle((
float)x0,
height()-(
float)y0,lightprop0,
36718 (
float)x2,
height()-(
float)y2,lightprop2,
36719 (
float)x3,
height()-(
float)y3,lightprop3);
36725 lx0 = (
unsigned int)lightprops(n0,0), ly0 = (
unsigned int)lightprops(n0,1),
36726 lx1 = (
unsigned int)lightprops(n1,0), ly1 = (
unsigned int)lightprops(n1,1),
36727 lx2 = (
unsigned int)lightprops(n2,0), ly2 = (
unsigned int)lightprops(n2,1),
36728 lx3 = (
unsigned int)lightprops(n3,0), ly3 = (
unsigned int)lightprops(n3,1);
36730 draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity).
36731 draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,pcolor,light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opacity);
36733 draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity).
36734 draw_triangle(x0,y0,x2,y2,x3,y3,pcolor,light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opacity);
36735 #ifdef cimg_use_board
36738 l0 = light_texture((
int)(light_texture.width()/2*(1+lx0)), (int)(light_texture.height()/2*(1+ly0))),
36739 l1 = light_texture((
int)(light_texture.width()/2*(1+lx1)), (int)(light_texture.height()/2*(1+ly1))),
36740 l2 = light_texture((
int)(light_texture.width()/2*(1+lx2)), (int)(light_texture.height()/2*(1+ly2))),
36741 l3 = light_texture((
int)(light_texture.width()/2*(1+lx3)), (int)(light_texture.height()/2*(1+ly3)));
36742 board.setPenColorRGBi((
unsigned char)(color[0]),
36743 (
unsigned char)(color[1]),
36744 (
unsigned char)(color[2]),
36745 (
unsigned char)(opacity*255));
36746 board.fillGouraudTriangle((
float)x0,
height()-(
float)y0,l0,
36747 (
float)x1,
height()-(
float)y1,l1,
36748 (
float)x2,
height()-(
float)y2,l2);
36749 board.fillGouraudTriangle((
float)x0,
height()-(
float)y0,l0,
36750 (
float)x2,
height()-(
float)y2,l2,
36751 (
float)x3,
height()-(
float)y3,l3);
36759 throw CImgArgumentException(_cimg_instance
36760 "draw_object3d(): Undefined texture for triangle primitive [%u].",
36761 cimg_instance,n_primitive);
36763 n0 = (
unsigned int)primitive[0],
36764 n1 = (
unsigned int)primitive[1],
36765 n2 = (
unsigned int)primitive[2],
36766 tx0 = (
unsigned int)primitive[3],
36767 ty0 = (
unsigned int)primitive[4],
36768 tx1 = (
unsigned int)primitive[5],
36769 ty1 = (
unsigned int)primitive[6],
36770 tx2 = (
unsigned int)primitive[7],
36771 ty2 = (
unsigned int)primitive[8];
36773 x0 = (int)projections(n0,0), y0 = (int)projections(n0,1),
36774 x1 = (int)projections(n1,0), y1 = (int)projections(n1,1),
36775 x2 = (int)projections(n2,0), y2 = (int)projections(n2,1);
36777 z0 = vertices(n0,2) + Z + _focale,
36778 z1 = vertices(n1,2) + Z + _focale,
36779 z2 = vertices(n2,2) + Z + _focale;
36780 switch (render_type) {
36782 draw_point(x0,y0,color.get_vector_at(tx0,ty0)._data,opacity).
36783 draw_point(x1,y1,color.get_vector_at(tx1,ty1)._data,opacity).
36784 draw_point(x2,y2,color.get_vector_at(tx2,ty2)._data,opacity);
36785 #ifdef cimg_use_board
36787 board.setPenColorRGBi(128,128,128,(
unsigned char)(opacity*255));
36788 board.drawCircle((
float)x0,
height()-(
float)y0,0);
36789 board.drawCircle((
float)x1,
height()-(
float)y1,0);
36790 board.drawCircle((
float)x2,
height()-(
float)y2,0);
36796 draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity).
36797 draw_line(zbuffer,x0,y0,z0,x2,y2,z2,color,tx0,ty0,tx2,ty2,opacity).
36798 draw_line(zbuffer,x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity);
36800 draw_line(x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity).
36801 draw_line(x0,y0,z0,x2,y2,z2,color,tx0,ty0,tx2,ty2,opacity).
36802 draw_line(x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity);
36803 #ifdef cimg_use_board
36805 board.setPenColorRGBi(128,128,128,(
unsigned char)(opacity*255));
36806 board.drawLine((
float)x0,
height()-(
float)y0,(
float)x1,
height()-(
float)y1);
36807 board.drawLine((
float)x0,
height()-(
float)y0,(
float)x2,
height()-(
float)y2);
36808 board.drawLine((
float)x1,
height()-(
float)y1,(
float)x2,
height()-(
float)y2);
36813 if (zbuffer)
draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity);
36814 else draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity);
36815 #ifdef cimg_use_board
36817 board.setPenColorRGBi(128,128,128,(
unsigned char)(opacity*255));
36818 board.fillTriangle((
float)x0,
height()-(
float)y0,
36819 (
float)x1,
height()-(
float)y1,
36820 (
float)x2,
height()-(
float)y2);
36826 draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l));
36827 else draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l));
36828 #ifdef cimg_use_board
36830 const float lp =
cimg::min(lightprops(l),1);
36831 board.setPenColorRGBi((
unsigned char)(128*lp),
36832 (
unsigned char)(128*lp),
36833 (
unsigned char)(128*lp),
36834 (
unsigned char)(opacity*255));
36835 board.fillTriangle((
float)x0,
height()-(
float)y0,
36836 (
float)x1,
height()-(
float)y1,
36837 (
float)x2,
height()-(
float)y2);
36843 draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,
36844 lightprops(n0),lightprops(n1),lightprops(n2),opacity);
36846 draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,
36847 lightprops(n0),lightprops(n1),lightprops(n2),opacity);
36848 #ifdef cimg_use_board
36850 board.setPenColorRGBi(128,128,128,(
unsigned char)(opacity*255));
36851 board.fillGouraudTriangle((
float)x0,
height()-(
float)y0,lightprops(n0),
36852 (
float)x1,
height()-(
float)y1,lightprops(n1),
36853 (
float)x2,
height()-(
float)y2,lightprops(n2));
36859 draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,light_texture,
36860 (
unsigned int)lightprops(n0,0),(
unsigned int)lightprops(n0,1),
36861 (
unsigned int)lightprops(n1,0),(
unsigned int)lightprops(n1,1),
36862 (
unsigned int)lightprops(n2,0),(
unsigned int)lightprops(n2,1),
36865 draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,light_texture,
36866 (
unsigned int)lightprops(n0,0),(
unsigned int)lightprops(n0,1),
36867 (
unsigned int)lightprops(n1,0),(
unsigned int)lightprops(n1,1),
36868 (
unsigned int)lightprops(n2,0),(
unsigned int)lightprops(n2,1),
36870 #ifdef cimg_use_board
36873 l0 = light_texture((
int)(light_texture.width()/2*(1+lightprops(n0,0))),
36874 (int)(light_texture.height()/2*(1+lightprops(n0,1)))),
36875 l1 = light_texture((
int)(light_texture.width()/2*(1+lightprops(n1,0))),
36876 (int)(light_texture.height()/2*(1+lightprops(n1,1)))),
36877 l2 = light_texture((
int)(light_texture.width()/2*(1+lightprops(n2,0))),
36878 (int)(light_texture.height()/2*(1+lightprops(n2,1))));
36879 board.setPenColorRGBi(128,128,128,(
unsigned char)(opacity*255));
36880 board.fillGouraudTriangle((
float)x0,
height()-(
float)y0,l0,
36881 (
float)x1,
height()-(
float)y1,l1,
36882 (
float)x2,
height()-(
float)y2,l2);
36890 throw CImgArgumentException(_cimg_instance
36891 "draw_object3d(): Undefined texture for quadrangle primitive [%u].",
36892 cimg_instance,n_primitive);
36894 n0 = (
unsigned int)primitive[0],
36895 n1 = (
unsigned int)primitive[1],
36896 n2 = (
unsigned int)primitive[2],
36897 n3 = (
unsigned int)primitive[3],
36898 tx0 = (
unsigned int)primitive[4],
36899 ty0 = (
unsigned int)primitive[5],
36900 tx1 = (
unsigned int)primitive[6],
36901 ty1 = (
unsigned int)primitive[7],
36902 tx2 = (
unsigned int)primitive[8],
36903 ty2 = (
unsigned int)primitive[9],
36904 tx3 = (
unsigned int)primitive[10],
36905 ty3 = (
unsigned int)primitive[11];
36907 x0 = (int)projections(n0,0), y0 = (int)projections(n0,1),
36908 x1 = (int)projections(n1,0), y1 = (int)projections(n1,1),
36909 x2 = (int)projections(n2,0), y2 = (int)projections(n2,1),
36910 x3 = (int)projections(n3,0), y3 = (int)projections(n3,1);
36912 z0 = vertices(n0,2) + Z + _focale,
36913 z1 = vertices(n1,2) + Z + _focale,
36914 z2 = vertices(n2,2) + Z + _focale,
36915 z3 = vertices(n3,2) + Z + _focale;
36917 switch (render_type) {
36919 draw_point(x0,y0,color.get_vector_at(tx0,ty0)._data,opacity).
36920 draw_point(x1,y1,color.get_vector_at(tx1,ty1)._data,opacity).
36921 draw_point(x2,y2,color.get_vector_at(tx2,ty2)._data,opacity).
36922 draw_point(x3,y3,color.get_vector_at(tx3,ty3)._data,opacity);
36923 #ifdef cimg_use_board
36925 board.setPenColorRGBi(128,128,128,(
unsigned char)(opacity*255));
36926 board.drawCircle((
float)x0,
height()-(
float)y0,0);
36927 board.drawCircle((
float)x1,
height()-(
float)y1,0);
36928 board.drawCircle((
float)x2,
height()-(
float)y2,0);
36929 board.drawCircle((
float)x3,
height()-(
float)y3,0);
36935 draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity).
36936 draw_line(zbuffer,x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity).
36937 draw_line(zbuffer,x2,y2,z2,x3,y3,z3,color,tx2,ty2,tx3,ty3,opacity).
36938 draw_line(zbuffer,x3,y3,z3,x0,y0,z0,color,tx3,ty3,tx0,ty0,opacity);
36940 draw_line(x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity).
36941 draw_line(x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity).
36942 draw_line(x2,y2,z2,x3,y3,z3,color,tx2,ty2,tx3,ty3,opacity).
36943 draw_line(x3,y3,z3,x0,y0,z0,color,tx3,ty3,tx0,ty0,opacity);
36944 #ifdef cimg_use_board
36946 board.setPenColorRGBi(128,128,128,(
unsigned char)(opacity*255));
36947 board.drawLine((
float)x0,
height()-(
float)y0,(
float)x1,
height()-(
float)y1);
36948 board.drawLine((
float)x1,
height()-(
float)y1,(
float)x2,
height()-(
float)y2);
36949 board.drawLine((
float)x2,
height()-(
float)y2,(
float)x3,
height()-(
float)y3);
36950 board.drawLine((
float)x3,
height()-(
float)y3,(
float)x0,
height()-(
float)y0);
36956 draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity).
36957 draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity);
36959 draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity).
36960 draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity);
36961 #ifdef cimg_use_board
36963 board.setPenColorRGBi(128,128,128,(
unsigned char)(opacity*255));
36964 board.fillTriangle((
float)x0,
height()-(
float)y0,
36965 (
float)x1,
height()-(
float)y1,
36966 (
float)x2,
height()-(
float)y2);
36967 board.fillTriangle((
float)x0,
height()-(
float)y0,
36968 (
float)x2,
height()-(
float)y2,
36969 (
float)x3,
height()-(
float)y3);
36975 draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)).
36976 draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity,lightprops(l));
36978 draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)).
36979 draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity,lightprops(l));
36980 #ifdef cimg_use_board
36982 const float lp =
cimg::min(lightprops(l),1);
36983 board.setPenColorRGBi((
unsigned char)(128*lp),
36984 (
unsigned char)(128*lp),
36985 (
unsigned char)(128*lp),
36986 (
unsigned char)(opacity*255));
36987 board.fillTriangle((
float)x0,
height()-(
float)y0,
36988 (
float)x1,
height()-(
float)y1,
36989 (
float)x2,
height()-(
float)y2);
36990 board.fillTriangle((
float)x0,
height()-(
float)y0,
36991 (
float)x2,
height()-(
float)y2,
36992 (
float)x3,
height()-(
float)y3);
36998 lightprop0 = lightprops(n0), lightprop1 = lightprops(n1),
36999 lightprop2 = lightprops(n2), lightprop3 = lightprops(n3);
37001 draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,
37002 lightprop0,lightprop1,lightprop2,opacity).
37003 draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,
37004 lightprop0,lightprop2,lightprop3,opacity);
37006 draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,
37007 lightprop0,lightprop1,lightprop2,opacity).
37008 draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,
37009 lightprop0,lightprop2,lightprop3,opacity);
37010 #ifdef cimg_use_board
37012 board.setPenColorRGBi(128,128,128,(
unsigned char)(opacity*255));
37013 board.fillGouraudTriangle((
float)x0,
height()-(
float)y0,lightprop0,
37014 (
float)x1,
height()-(
float)y1,lightprop1,
37015 (
float)x2,
height()-(
float)y2,lightprop2);
37016 board.fillGouraudTriangle((
float)x0,
height()-(
float)y0,lightprop0,
37017 (
float)x2,
height()-(
float)y2,lightprop2,
37018 (
float)x3,
height()-(
float)y3,lightprop3);
37024 lx0 = (
unsigned int)lightprops(n0,0), ly0 = (
unsigned int)lightprops(n0,1),
37025 lx1 = (
unsigned int)lightprops(n1,0), ly1 = (
unsigned int)lightprops(n1,1),
37026 lx2 = (
unsigned int)lightprops(n2,0), ly2 = (
unsigned int)lightprops(n2,1),
37027 lx3 = (
unsigned int)lightprops(n3,0), ly3 = (
unsigned int)lightprops(n3,1);
37029 draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,
37030 light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity).
37031 draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,
37032 light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opacity);
37034 draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,
37035 light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity).
37036 draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,
37037 light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opacity);
37038 #ifdef cimg_use_board
37041 l0 = light_texture((
int)(light_texture.width()/2*(1+lx0)), (int)(light_texture.height()/2*(1+ly0))),
37042 l1 = light_texture((
int)(light_texture.width()/2*(1+lx1)), (int)(light_texture.height()/2*(1+ly1))),
37043 l2 = light_texture((
int)(light_texture.width()/2*(1+lx2)), (int)(light_texture.height()/2*(1+ly2))),
37044 l3 = light_texture((
int)(light_texture.width()/2*(1+lx3)), (int)(light_texture.height()/2*(1+ly3)));
37045 board.setPenColorRGBi(128,128,128,(
unsigned char)(opacity*255));
37046 board.fillGouraudTriangle((
float)x0,
height()-(
float)y0,l0,
37047 (
float)x1,
height()-(
float)y1,l1,
37048 (
float)x2,
height()-(
float)y2,l2);
37049 board.fillGouraudTriangle((
float)x0,
height()-(
float)y0,l0,
37050 (
float)x2,
height()-(
float)y2,l2,
37051 (
float)x3,
height()-(
float)y3,l3);
37060 if (render_type==5) cimg::mutex(10,0);
37078 const unsigned int feature_type=2,
unsigned int *
const XYZ=0) {
37079 return get_select(disp,feature_type,XYZ).move_to(*
this);
37084 const unsigned int feature_type=2,
unsigned int *
const XYZ=0) {
37085 return get_select(title,feature_type,XYZ).move_to(*
this);
37090 const unsigned int feature_type=2,
unsigned int *
const XYZ=0)
const {
37091 return _get_select(disp,0,feature_type,XYZ,0,0,0,
true,
false);
37096 const unsigned int feature_type=2,
unsigned int *
const XYZ=0)
const {
37098 return _get_select(disp,title,feature_type,XYZ,0,0,0,
true,
false);
37102 const unsigned int feature_type,
unsigned int *
const XYZ,
37103 const int origX,
const int origY,
const int origZ,
37104 const bool reset_view3d,
37105 const bool force_display_z_coord)
const {
37108 disp.
assign(cimg_fitscreen(_width,_height,_depth),title?title:0,1);
37109 if (!title) disp.
set_title(
"CImg<%s> (%ux%ux%ux%u)",
pixel_type(),_width,_height,_depth,_spectrum);
37110 }
else if (title) disp.
set_title(
"%s",title);
37112 const unsigned int old_normalization = disp.
normalization();
37114 disp._normalization = 0;
37117 unsigned char foreground_color[] = { 255,255,255 }, background_color[] = { 0,0,0 };
37119 int area = 0, starting_area = 0, clicked_area = 0, phase = 0,
37120 X0 = (int)((XYZ?XYZ[0]:(_width-1)/2)%_width),
37121 Y0 = (
int)((XYZ?XYZ[1]:(_height-1)/2)%_height),
37122 Z0 = (
int)((XYZ?XYZ[2]:(_depth-1)/2)%_depth),
37123 X1 =-1, Y1 = -1, Z1 = -1,
37124 X3d = -1, Y3d = -1,
37125 oX3d = X3d, oY3d = -1,
37126 omx = -1, omy = -1;
37127 float X = -1, Y = -1, Z = -1;
37128 unsigned int old_button = 0, key = 0;
37130 bool shape_selected =
false, text_down =
false, visible_cursor =
true;
37131 static CImg<floatT> pose3d;
37132 static bool is_view3d =
false, is_axes =
true;
37133 if (reset_view3d) { pose3d.assign(); is_view3d =
false; }
37134 CImg<floatT> points3d, opacities3d, sel_opacities3d;
37135 CImgList<uintT> primitives3d, sel_primitives3d;
37136 CImgList<ucharT> colors3d, sel_colors3d;
37137 CImg<ucharT> visu, visu0, view3d;
37138 char text[1024] = { 0 };
37140 while (!key && !disp.
is_closed() && !shape_selected) {
37148 mX = mx<0?-1.0f:(float)mx*(
width()+(
depth()>1?
depth():0))/disp.width(),
37149 mY = my<0?-1.0f:(float)my*(height()+(
depth()>1?
depth():0))/disp.height();
37152 if (mX>=0 && mY>=0 && mX<
width() && mY<
height()) { area = 1; X = mX; Y = mY; Z = (float)(phase?Z1:Z0); }
37153 if (mX>=0 && mX<
width() && mY>=
height()) { area = 2; X = mX; Z = mY - _height; Y = (float)(phase?Y1:Y0); }
37154 if (mY>=0 && mX>=
width() && mY<
height()) { area = 3; Y = mY; Z = mX - _width; X = (float)(phase?X1:X0); }
37156 if (disp.
button()) {
if (!clicked_area) clicked_area = area; }
else clicked_area = 0;
37158 switch (key = disp.
key()) {
37164 if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { disp.
set_wheel(1); key = 0; }
break;
37166 if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { disp.
set_wheel(-1); key = 0; }
break;
37167 case cimg::keyA :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
37168 is_axes = !is_axes; disp.
set_key(key,
false); key = 0; visu0.assign();
37170 case cimg::keyD :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
37172 resize(CImgDisplay::_fitscreen(3*disp.
width()/2,3*disp.
height()/2,1,128,-100,
false),
37173 CImgDisplay::_fitscreen(3*disp.
width()/2,3*disp.
height()/2,1,128,-100,
true),
false).
37174 _is_resized =
true;
37175 disp.
set_key(key,
false); key = 0; visu0.assign();
37177 case cimg::keyC :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
37179 resize(cimg_fitscreen(2*disp.
width()/3,2*disp.
height()/3,1),
false)._is_resized =
true;
37180 disp.
set_key(key,
false); key = 0; visu0.assign();
37182 case cimg::keyR :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
37183 disp.
set_fullscreen(
false).
resize(cimg_fitscreen(_width,_height,_depth),
false)._is_resized =
true;
37184 disp.
set_key(key,
false); key = 0; visu0.assign();
37186 case cimg::keyF :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
37188 disp.
set_key(key,
false); key = 0; visu0.assign();
37190 case cimg::keyV :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
37191 is_view3d = !is_view3d; disp.
set_key(key,
false); key = 0; visu0.assign();
37193 case cimg::keyS :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
37194 static unsigned int snap_number = 0;
37195 char filename[32] = { 0 };
37198 cimg_snprintf(filename,
sizeof(filename),cimg_appname
"_%.4u.bmp",snap_number++);
37199 if ((file=std::fopen(filename,
"r"))!=0)
cimg::fclose(file);
37202 (+visu0).
draw_text(0,0,
" Saving snapshot... ",foreground_color,background_color,0.7f,13).display(disp);
37203 visu0.save(filename);
37204 (+visu0).
draw_text(0,0,
" Snapshot '%s' saved. ",foreground_color,background_color,0.7f,13,filename).
37207 disp.
set_key(key,
false); key = 0;
37209 case cimg::keyO :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
37210 static unsigned int snap_number = 0;
37211 char filename[32] = { 0 };
37214 #ifdef cimg_use_zlib
37215 cimg_snprintf(filename,
sizeof(filename),cimg_appname
"_%.4u.cimgz",snap_number++);
37217 cimg_snprintf(filename,
sizeof(filename),cimg_appname
"_%.4u.cimg",snap_number++);
37219 if ((file=std::fopen(filename,
"r"))!=0)
cimg::fclose(file);
37221 (+visu0).
draw_text(0,0,
" Saving instance... ",foreground_color,background_color,0.7f,13).display(disp);
37223 (+visu0).
draw_text(0,0,
" Instance '%s' saved. ",foreground_color,background_color,0.7f,13,filename).
37225 disp.
set_key(key,
false); key = 0;
37232 mx = my = -1; X = Y = Z = -1;
37235 case 1 :
case 2 :
case 3 :
37236 if (disp.
button()&1 && phase<2 && clicked_area==area) {
37237 if (_depth>1 && (X1!=(
int)X || Y1!=(
int)Y || Z1!=(
int)Z)) visu0.assign();
37238 X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z;
37240 if (!(disp.
button()&1) && phase>=2 && clicked_area!=area) {
37241 switch (starting_area) {
37242 case 1 :
if (Z1!=(
int)Z) visu0.assign(); Z1 = (int)Z;
break;
37243 case 2 :
if (Y1!=(
int)Y) visu0.assign(); Y1 = (int)Y;
break;
37244 case 3 :
if (X1!=(
int)X) visu0.assign(); X1 = (int)X;
break;
37247 if (disp.
button()&2 && clicked_area==area) {
37249 if (_depth>1 && (X1!=(
int)X || Y1!=(
int)Y || Z1!=(
int)Z)) visu0.assign();
37250 X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z;
37252 if (_depth>1 && (X0!=(
int)X || Y0!=(int)Y || Z0!=(
int)Z)) visu0.assign();
37253 X0 = (int)X; Y0 = (int)Y; Z0 = (int)Z;
37257 X = (float)X0; Y = (float)Y0; Z = (float)Z0; phase = area = clicked_area = starting_area = 0;
37260 if (disp.
wheel()) {
37261 if (_depth>1 && !disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT() &&
37262 !disp.is_keySHIFTLEFT() && !disp.is_keySHIFTRIGHT() &&
37263 !disp.is_keyALT() && !disp.is_keyALTGR()) {
37266 if (phase) Z = (float)(Z1+=disp.
wheel());
else Z = (float)(Z0+=disp.
wheel());
37267 visu0.assign();
break;
37269 if (phase) Y = (float)(Y1+=disp.
wheel());
else Y = (float)(Y0+=disp.
wheel());
37270 visu0.assign();
break;
37272 if (phase) X = (float)(X1+=disp.
wheel());
else X = (float)(X0+=disp.
wheel());
37273 visu0.assign();
break;
37278 if ((disp.
button()&1)!=old_button) {
37281 if (area==clicked_area) {
37282 X0 = X1 = (int)X; Y0 = Y1 = (int)Y; Z0 = Z1 = (int)Z; starting_area = area; ++phase;
37285 if (area==starting_area) {
37286 X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z; ++phase;
37287 }
else if (!(disp.
button()&1)) { X = (float)X0; Y = (float)Y0; Z = (float)Z0; phase = 0; visu0.assign(); }
37289 case 2 : ++phase;
break;
37291 old_button = disp.
button()&1;
37296 if (is_view3d && points3d) {
37297 X3d = mx - _width*disp.
width()/(_width+(_depth>1?_depth:0));
37298 Y3d = my - _height*disp.
height()/(_height+(_depth>1?_depth:0));
37299 if (oX3d<0) { oX3d = X3d; oY3d = Y3d; }
37301 if ((disp.
button()&3)==3) { pose3d.assign(); view3d.assign(); oX3d = oY3d = X3d = Y3d = -1; }
37302 else if (disp.
button()&1 && pose3d && (oX3d!=X3d || oY3d!=Y3d)) {
37304 R = 0.45f*
cimg::min(view3d._width,view3d._height),
37306 u0 = (float)(oX3d-view3d.width()/2),
37307 v0 = (
float)(oY3d-view3d.height()/2),
37308 u1 = (
float)(X3d-view3d.width()/2),
37309 v1 = (
float)(Y3d-view3d.height()/2),
37310 n0 = (
float)std::sqrt(u0*u0+v0*v0),
37311 n1 = (float)std::sqrt(u1*u1+v1*v1),
37312 nu0 = n0>R?(u0*R/n0):u0,
37313 nv0 = n0>R?(v0*R/n0):v0,
37314 nw0 = (float)
std::
sqrt(cimg::
max(0,R2-nu0*nu0-nv0*nv0)),
37315 nu1 = n1>R?(u1*R/n1):u1,
37316 nv1 = n1>R?(v1*R/n1):v1,
37317 nw1 = (float)
std::
sqrt(cimg::
max(0,R2-nu1*nu1-nv1*nv1)),
37318 u = nv0*nw1 - nw0*nv1,
37319 v = nw0*nu1 - nu0*nw1,
37320 w = nv0*nu1 - nu0*nv1,
37321 n = (float)
std::
sqrt(u*u+v*v+w*w),
37322 alpha = (float)
std::
asin(n/R2);
37325 }
else if (disp.
button()&2 && pose3d && oY3d!=Y3d) {
37326 pose3d(3,2)-=(oY3d - Y3d)*1.5f; view3d.assign();
37328 if (disp.
wheel()) {
37329 pose3d(3,2)-=disp.
wheel()*15; view3d.assign(); disp.
set_wheel();
37331 if (disp.
button()&4 && pose3d && (oX3d!=X3d || oY3d!=Y3d)) {
37332 pose3d(3,0)-=oX3d - X3d; pose3d(3,1)-=oY3d - Y3d; view3d.assign();
37334 oX3d = X3d; oY3d = Y3d;
37336 mx = my = -1; X = Y = Z = -1;
37341 if (!feature_type) shape_selected = phase?
true:
false;
37343 if (_depth>1) shape_selected = (phase==3)?
true:
false;
37344 else shape_selected = (phase==2)?
true:
false;
37348 if (X0<0) X0 = 0;
if (X0>=
width()) X0 =
width() - 1;
37349 if (Y0<0) Y0 = 0;
if (Y0>=
height()) Y0 =
height() - 1;
37350 if (Z0<0) Z0 = 0;
if (Z0>=
depth()) Z0 =
depth() - 1;
37351 if (X1<1) X1 = 0;
if (X1>=
width()) X1 =
width() - 1;
37352 if (Y1<0) Y1 = 0;
if (Y1>=
height()) Y1 =
height() - 1;
37353 if (Z1<0) Z1 = 0;
if (Z1>=
depth()) Z1 =
depth() - 1;
37356 if (mx!=omx || my!=omy || !visu0 || (_depth>1 && !view3d)) {
37359 __get_select(disp,old_normalization,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0).move_to(visu0).resize(disp);
37364 if (is_view3d && _depth>1 && !view3d) {
37366 _x3d = (
unsigned int)
cimg::round((
float)_width*visu0._width/(_width+_depth),1,1),
37367 _y3d = (
unsigned int)
cimg::round((
float)_height*visu0._height/(_height+_depth),1,1),
37368 x3d = _x3d>=visu0._width?visu0._width-1:_x3d,
37369 y3d = _y3d>=visu0._height?visu0._height-1:_y3d;
37370 CImg<ucharT>(1,2,1,1,64,128).
resize(visu0._width-x3d,visu0._height-y3d,1,visu0._spectrum,3).move_to(view3d);
37373 points3d.append(CImg<floatT>(8,3,1,1,
37374 0,_width-1,_width-1,0,0,_width-1,_width-1,0,
37375 0,0,_height-1,_height-1,0,0,_height-1,_height-1,
37376 0,0,0,0,_depth-1,_depth-1,_depth-1,_depth-1),
'x');
37383 colors3d.insert(12,CImg<ucharT>::vector(255,255,255));
37384 opacities3d.assign(primitives3d.width(),1,1,1,0.5f);
37386 opacities3d[0] = opacities3d[1] = opacities3d[2] = 0.8f;
37387 sel_primitives3d.assign();
37388 sel_colors3d.assign();
37389 sel_opacities3d.assign();
37391 if (feature_type==2) {
37392 points3d.append(CImg<floatT>(8,3,1,1,
37393 X0,X1,X1,X0,X0,X1,X1,X0,
37394 Y0,Y0,Y1,Y1,Y0,Y0,Y1,Y1,
37395 Z0,Z0,Z0,Z0,Z1,Z1,Z1,Z1),
'x');
37396 sel_primitives3d.assign();
37410 points3d.append(CImg<floatT>(2,3,1,1,
37416 sel_colors3d.assign(sel_primitives3d._width,CImg<ucharT>::vector(255,255,255));
37417 sel_opacities3d.assign(sel_primitives3d._width,1,1,1,0.8f);
37419 points3d.shift_object3d(-0.5f*(_width-1),-0.5f*(_height-1),-0.5f*(_depth-1)).resize_object3d();
37420 points3d*=0.75f*
cimg::min(view3d._width,view3d._height);
37423 if (!pose3d) CImg<floatT>(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0).
move_to(pose3d);
37424 CImg<floatT> zbuffer3d(view3d._width,view3d._height,1,1,0);
37425 const CImg<floatT> rotated_points3d = pose3d.get_crop(0,0,2,2)*points3d;
37426 if (sel_primitives3d)
37427 view3d.draw_object3d(pose3d(3,0) + 0.5f*view3d._width,
37428 pose3d(3,1) + 0.5f*view3d._height,
37430 rotated_points3d,sel_primitives3d,sel_colors3d,sel_opacities3d,
37431 2,
true,500,0,0,0,0,0,zbuffer3d);
37432 view3d.draw_object3d(pose3d(3,0) + 0.5f*view3d._width,
37433 pose3d(3,1) + 0.5f*view3d._height,
37435 rotated_points3d,primitives3d,colors3d,opacities3d,
37436 2,
true,500,0,0,0,0,0,zbuffer3d);
37437 visu0.draw_image(x3d,y3d,view3d);
37441 if (X<0 || Y<0 || Z<0) {
if (!visible_cursor) { disp.
show_mouse(); visible_cursor =
true; }}
37443 if (is_axes) {
if (visible_cursor) { disp.
hide_mouse(); visible_cursor =
false; }}
37444 else {
if (!visible_cursor) { disp.
show_mouse(); visible_cursor =
true; }}
37445 const int d = (_depth>1)?_depth:0;
37449 _xp = (int)X*w/W, xp = _xp + (_xp*W/w!=(
int)X?1:0),
37450 _yp = (
int)Y*h/H, yp = _yp + (_yp*H/h!=(int)Y?1:0),
37451 _xn = (int)(X+1)*w/W-1, xn = _xn + ((_xn+1)*W/w!=(
int)X+1?1:0),
37452 _yn = (
int)(Y+1)*h/H-1, yn = _yn + ((_yn+1)*H/h!=(
int)Y+1?1:0),
37453 _zxp = ((
int)Z+width())*w/W, zxp = _zxp + (_zxp*W/w!=(
int)Z+width()?1:0),
37454 _zyp = ((
int)Z+height())*h/H, zyp = _zyp + (_zyp*H/h!=(
int)Z+height()?1:0),
37455 _zxn = ((
int)Z+width()+1)*w/W-1, zxn = _zxn + ((_zxn+1)*W/w!=(
int)Z+width()+1?1:0),
37456 _zyn = ((
int)Z+height()+1)*h/H-1, zyn = _zyn + ((_zyn+1)*H/h!=(
int)Z+height()+1?1:0),
37457 _xM = width()*w/W-1, xM = _xM + ((_xM+1)*W/w!=width()?1:0),
37458 _yM = height()*h/H-1, yM = _yM + ((_yM+1)*H/h!=height()?1:0),
37461 zxc = (zxp + zxn)/2,
37462 zyc = (zyp + zyn)/2,
37465 zxf = (
int)((Z+width())*w/W),
37466 zyf = (
int)((Z+height())*h/H);
37469 visu.draw_line(0,yf,visu.width()-1,yf,foreground_color,0.7f,0xFF00FF00).
37470 draw_line(0,yf,visu.width()-1,yf,background_color,0.7f,0x00FF00FF).
37471 draw_line(xf,0,xf,visu.height()-1,foreground_color,0.7f,0xFF00FF00).
37472 draw_line(xf,0,xf,visu.height()-1,background_color,0.7f,0x00FF00FF);
37474 visu.draw_line(zxf,0,zxf,yM,foreground_color,0.7f,0xFF00FF00).
37475 draw_line(zxf,0,zxf,yM,background_color,0.7f,0x00FF00FF).
37476 draw_line(0,zyf,xM,zyf,foreground_color,0.7f,0xFF00FF00).
37477 draw_line(0,zyf,xM,zyf,background_color,0.7f,0x00FF00FF);
37481 if (xn-xp>=4 && yn-yp>=4) visu.draw_rectangle(xp,yp,xn,yn,foreground_color,0.2f).
37485 if (yn-yp>=4 && zxn-zxp>=4) visu.draw_rectangle(zxp,yp,zxn,yn,background_color,0.2f).
37488 if (xn-xp>=4 && zyn-zyp>=4) visu.draw_rectangle(xp,zyp,xn,zyn,background_color,0.2f).
37496 _xp0 = X0*w/W, xp0 = _xp0 + (_xp0*W/w!=X0?1:0),
37497 _yp0 = Y0*h/H, yp0 = _yp0 + (_yp0*H/h!=Y0?1:0),
37498 _xn0 = (X0+1)*w/W-1, xn0 = _xn0 + ((_xn0+1)*W/w!=X0+1?1:0),
37499 _yn0 = (Y0+1)*h/H-1, yn0 = _yn0 + ((_yn0+1)*H/h!=Y0+1?1:0),
37500 _zxp0 = (Z0+
width())*w/W, zxp0 = _zxp0 + (_zxp0*W/w!=Z0+
width()?1:0),
37501 _zyp0 = (Z0+
height())*h/H, zyp0 = _zyp0 + (_zyp0*H/h!=Z0+
height()?1:0),
37502 _zxn0 = (Z0+
width()+1)*w/W-1, zxn0 = _zxn0 + ((_zxn0+1)*W/w!=Z0+
width()+1?1:0),
37503 _zyn0 = (Z0+
height()+1)*h/H-1, zyn0 = _zyn0 + ((_zyn0+1)*H/h!=Z0+
height()+1?1:0),
37504 xc0 = (xp0 + xn0)/2,
37505 yc0 = (yp0 + yn0)/2,
37506 zxc0 = (zxp0 + zxn0)/2,
37507 zyc0 = (zyp0 + zyn0)/2;
37509 switch (feature_type) {
37511 visu.draw_arrow(xc0,yc0,xc,yc,background_color,0.9f,30,5,0x55555555).
37512 draw_arrow(xc0,yc0,xc,yc,foreground_color,0.9f,30,5,0xAAAAAAAA);
37514 visu.draw_arrow(zxc0,yc0,zxc,yc,background_color,0.9f,30,5,0x55555555).
37515 draw_arrow(zxc0,yc0,zxc,yc,foreground_color,0.9f,30,5,0xAAAAAAAA).
37516 draw_arrow(xc0,zyc0,xc,zyc,background_color,0.9f,30,5,0x55555555).
37517 draw_arrow(xc0,zyc0,xc,zyc,foreground_color,0.9f,30,5,0xAAAAAAAA);
37521 visu.draw_rectangle(X0<X1?xp0:xp,Y0<Y1?yp0:yp,X0<X1?xn:xn0,Y0<Y1?yn:yn0,background_color,0.2f).
37522 draw_rectangle(X0<X1?xp0:xp,Y0<Y1?yp0:yp,X0<X1?xn:xn0,Y0<Y1?yn:yn0,foreground_color,0.9f,0xAAAAAAAA).
37523 draw_rectangle(X0<X1?xp0:xp,Y0<Y1?yp0:yp,X0<X1?xn:xn0,Y0<Y1?yn:yn0,background_color,0.9f,0x55555555);
37525 visu.draw_rectangle(Z0<Z1?zxp0:zxp,Y0<Y1?yp0:yp,Z0<Z1?zxn:zxn0,Y0<Y1?yn:yn0,background_color,0.2f).
37526 draw_rectangle(Z0<Z1?zxp0:zxp,Y0<Y1?yp0:yp,Z0<Z1?zxn:zxn0,Y0<Y1?yn:yn0,
37527 foreground_color,0.9f,0xAAAAAAAA).
37528 draw_rectangle(Z0<Z1?zxp0:zxp,Y0<Y1?yp0:yp,Z0<Z1?zxn:zxn0,Y0<Y1?yn:yn0,
37529 background_color,0.9f,0x55555555).
37530 draw_rectangle(X0<X1?xp0:xp,Z0<Z1?zyp0:zyp,X0<X1?xn:xn0,Z0<Z1?zyn:zyn0,
37531 background_color,0.2f).
37532 draw_rectangle(X0<X1?xp0:xp,Z0<Z1?zyp0:zyp,X0<X1?xn:xn0,Z0<Z1?zyn:zyn0,
37533 foreground_color,0.9f,0xAAAAAAAA).
37534 draw_rectangle(X0<X1?xp0:xp,Z0<Z1?zyp0:zyp,X0<X1?xn:xn0,Z0<Z1?zyn:zyn0,
37535 background_color,0.9f,0x55555555);
37539 visu.draw_ellipse(xc0,yc0,(
float)cimg::abs(xc-xc0),(
float)cimg::abs(yc-yc0),0,background_color,0.2f).
37540 draw_ellipse(xc0,yc0,(
float)cimg::abs(xc-xc0),(
float)cimg::abs(yc-yc0),0,foreground_color,0.9f,~0U).
37543 visu.draw_ellipse(zxc0,yc0,(
float)cimg::abs(zxc-zxc0),(
float)cimg::abs(yc-yc0),0,
37544 background_color,0.2f).
37545 draw_ellipse(zxc0,yc0,(
float)cimg::abs(zxc-zxc0),(
float)cimg::abs(yc-yc0),0,
37546 foreground_color,0.9f,~0U).
37548 draw_ellipse(xc0,zyc0,(
float)cimg::abs(xc-xc0),(
float)cimg::abs(zyc-zyc0),0,
37549 background_color,0.2f).
37550 draw_ellipse(xc0,zyc0,(
float)cimg::abs(xc-xc0),(
float)cimg::abs(zyc-zyc0),0,
37551 foreground_color,0.9f,~0U).
37559 if (my>=0 && my<13) text_down =
true;
else if (my>=visu.height()-13) text_down =
false;
37560 if (!feature_type || !phase) {
37562 if (_depth>1 || force_display_z_coord)
37563 cimg_snprintf(text,
sizeof(text),
" Point (%d,%d,%d) = [ ",origX+(
int)X,origY+(
int)Y,origZ+(
int)Z);
37564 else cimg_snprintf(text,
sizeof(text),
" Point (%d,%d) = [ ",origX+(
int)X,origY+(
int)Y);
37565 char *ctext = text + std::strlen(text), *
const ltext = text + 512;
37566 for (
unsigned int c = 0; c<_spectrum && ctext<ltext; ++c) {
37567 cimg_snprintf(ctext,
sizeof(text)/2,cimg::type<T>::format(),
37568 cimg::type<T>::format((*
this)((
int)X,(
int)Y,(
int)Z,c)));
37569 ctext = text + std::strlen(text);
37570 *(ctext++) =
' '; *ctext = 0;
37572 std::strcpy(text + std::strlen(text),
"] ");
37574 }
else switch (feature_type) {
37576 const double dX = (double)(X0 - X1), dY = (double)(Y0 - Y1), dZ = (double)(Z0 - Z1),
37577 norm = std::sqrt(dX*dX+dY*dY+dZ*dZ);
37578 if (_depth>1 || force_display_z_coord)
37579 cimg_snprintf(text,
sizeof(text),
" Vect (%d,%d,%d)-(%d,%d,%d), Norm = %g ",
37580 origX+X0,origY+Y0,origZ+Z0,origX+X1,origY+Y1,origZ+Z1,norm);
37581 else cimg_snprintf(text,
sizeof(text),
" Vect (%d,%d)-(%d,%d), Norm = %g ",
37582 origX+X0,origY+Y0,origX+X1,origY+Y1,norm);
37585 if (_depth>1 || force_display_z_coord)
37586 cimg_snprintf(text,
sizeof(text),
" Box (%d,%d,%d)-(%d,%d,%d), Size = (%d,%d,%d) ",
37587 origX+(X0<X1?X0:X1),origY+(Y0<Y1?Y0:Y1),origZ+(Z0<Z1?Z0:Z1),
37588 origX+(X0<X1?X1:X0),origY+(Y0<Y1?Y1:Y0),origZ+(Z0<Z1?Z1:Z0),
37589 1+cimg::abs(X0-X1),1+cimg::abs(Y0-Y1),1+cimg::abs(Z0-Z1));
37590 else cimg_snprintf(text,
sizeof(text),
" Box (%d,%d)-(%d,%d), Size = (%d,%d) ",
37591 origX+(X0<X1?X0:X1),origY+(Y0<Y1?Y0:Y1),origX+(X0<X1?X1:X0),origY+(Y0<Y1?Y1:Y0),
37592 1+cimg::abs(X0-X1),1+cimg::abs(Y0-Y1));
37595 if (_depth>1 || force_display_z_coord)
37596 cimg_snprintf(text,
sizeof(text),
" Ellipse (%d,%d,%d)-(%d,%d,%d), Radii = (%d,%d,%d) ",
37597 origX+X0,origY+Y0,origZ+Z0,origX+X1,origY+Y1,origZ+Z1,
37598 1+cimg::abs(X0-X1),1+cimg::abs(Y0-Y1),1+cimg::abs(Z0-Z1));
37599 else cimg_snprintf(text,
sizeof(text),
" Ellipse (%d,%d)-(%d,%d), Radii = (%d,%d) ",
37600 origX+X0,origY+Y0,origX+X1,origY+Y1,1+cimg::abs(X0-X1),1+cimg::abs(Y0-Y1));
37602 if (phase || (mx>=0 && my>=0))
37603 visu.draw_text(0,text_down?visu.height()-13:0,text,foreground_color,background_color,0.7f,13);
37607 }
else if (!shape_selected) disp.
wait();
37608 if (disp.
is_resized()) { disp.
resize(
false)._is_resized =
false; old_is_resized =
true; visu0.assign(); }
37609 omx = mx; omy = my;
37613 CImg<intT> res(1,feature_type==0?3:6,1,1,-1);
37614 if (XYZ) { XYZ[0] = (
unsigned int)X0; XYZ[1] = (
unsigned int)Y0; XYZ[2] = (
unsigned int)Z0; }
37615 if (shape_selected) {
37616 if (feature_type==2) {
37621 if (X1<0 || Y1<0 || Z1<0) X0 = Y0 = Z0 = X1 = Y1 = Z1 = -1;
37622 switch (feature_type) {
37623 case 1 :
case 2 : res[0] = X0; res[1] = Y0; res[2] = Z0; res[3] = X1; res[4] = Y1; res[5] = Z1;
break;
37626 default : res[0] = X0; res[1] = Y0; res[2] = Z0;
37631 disp._normalization = old_normalization;
37632 disp._is_resized = old_is_resized;
37633 if (key!=~0U) disp.
set_key(key);
37638 CImg<ucharT> __get_select(
const CImgDisplay& disp,
const int normalization,
37639 const int x,
const int y,
const int z)
const {
37640 if (
is_empty())
return CImg<ucharT>(1,1,1,1,0);
37642 CImg<Tuchar> img2d;
37643 if (_depth>1) crop.get_projections2d(x,y,z).move_to(img2d);
37646 if (cimg::type<T>::is_float()) {
37648 cimg_for(img2d,ptr,Tuchar)
37649 if (cimg::type<T>::is_inf(*ptr)) { is_inf =
true;
break; }
37650 else if (cimg::type<T>::is_nan(*ptr)) {
is_nan =
true;
break; }
37652 T m0 = cimg::type<T>::max(), M0 = cimg::type<T>::min();
37653 if (!normalization) { m0 = 0; M0 = 255; }
37654 else if (normalization==2) { m0 = (T)disp._min; M0 = (T)disp._max; }
37656 cimg_for(img2d,ptr,Tuchar)
37657 if (!cimg::type<T>::is_inf(*ptr) && !cimg::type<T>::
is_nan(*ptr)) {
37658 if (*ptr<m0) m0 = *ptr;
if (*ptr>M0) M0 = *ptr;
37661 val_minf = (normalization==1 || normalization==3)?m0-(M0-m0)*20-1:m0,
37662 val_pinf = (normalization==1 || normalization==3)?M0+(M0-m0)*20+1:M0;
37664 cimg_for(img2d,ptr,Tuchar)
37665 if (cimg::type<T>::
is_nan(*ptr)) *ptr = val_minf;
37667 cimg_for(img2d,ptr,Tuchar)
37668 if (cimg::type<T>::is_inf(*ptr)) *ptr = (
float)*ptr<0?val_minf:val_pinf;
37672 switch (normalization) {
37673 case 1 : img2d.normalize(0,255);
break;
37675 const float m = disp._min, M = disp._max;
37676 (img2d-=m)*=255.0f/(M-m>0?M-m:1);
37679 if (cimg::type<T>::is_float()) img2d.normalize(0,255);
37681 const float m = (float)cimg::type<T>::min(), M = (float)cimg::type<T>::max();
37682 (img2d-=m)*=255.0f/(M-m>0?M-m:1);
37686 if (img2d.spectrum()==2) img2d.channels(0,2);
37692 const unsigned int plot_type=1,
const unsigned int vertex_type=1,
37693 const char *
const labelx=0,
const double xmin=0,
const double xmax=0,
37694 const char *
const labely=0,
const double ymin=0,
const double ymax=0)
const {
37697 "select_graph(): Empty instance.",
37701 const unsigned long siz = (
unsigned long)_width*_height*_depth;
37702 const unsigned int old_normalization = disp.
normalization();
37705 double nymin = ymin, nymax = ymax, nxmin = xmin, nxmax = xmax;
37706 if (nymin==nymax) { nymin = (Tfloat)
min_max(nymax);
const double dy = nymax - nymin; nymin-=dy/20; nymax+=dy/20; }
37707 if (nymin==nymax) { --nymin; ++nymax; }
37708 if (nxmin==nxmax && nxmin==0) { nxmin = 0; nxmax = siz - 1.0; }
37710 const unsigned char black[] = { 0, 0, 0 }, white[] = { 255, 255, 255 }, gray[] = { 220, 220, 220 };
37711 const unsigned char gray2[] = { 110, 110, 110 }, ngray[] = { 35, 35, 35 };
37712 static unsigned int odimv = 0;
37714 if (odimv!=_spectrum) {
37717 if (_spectrum==1) { colormap[0] = colormap[1] = 120; colormap[2] = 200; }
37719 colormap(0,0) = 220; colormap(1,0) = 10; colormap(2,0) = 10;
37720 if (_spectrum>1) { colormap(0,1) = 10; colormap(1,1) = 220; colormap(2,1) = 10; }
37721 if (_spectrum>2) { colormap(0,2) = 10; colormap(1,2) = 10; colormap(2,2) = 220; }
37726 int x0 = -1, x1 = -1, y0 = -1, y1 = -1, omouse_x = -2, omouse_y = -2;
37727 const unsigned int one = plot_type==3?0:1;
37728 unsigned int okey = 0, obutton = 0;
37729 char message[1024] = { 0 };
37730 CImg_3x3(I,
unsigned char);
37732 for (
bool selected =
false; !selected && !disp.
is_closed() && !okey && !disp.
wheel(); ) {
37734 const unsigned int key = disp.
key(), button = disp.
button();
37738 visu0.assign(disp.
width(),disp.
height(),1,3,220);
37739 const int gdimx = disp.
width() - 32, gdimy = disp.
height() - 32;
37740 if (gdimx>0 && gdimy>0) {
37741 graph.assign(gdimx,gdimy,1,3,255);
37743 if (siz>1) graph.draw_grid(gdimx/(
float)(siz - one),gdimy/(
float)(siz - one),0,0,
37744 false,
true,black,0.2f,0x33333333,0x33333333);
37745 }
else graph.draw_grid(-10,-10,0,0,
false,
true,black,0.2f,0x33333333,0x33333333);
37747 graph.draw_graph(
get_shared_channel(c),&colormap(0,c),(plot_type!=3 || _spectrum==1)?1:0.6f,
37748 plot_type,vertex_type,nymax,nymin);
37750 axes.assign(gdimx,gdimy,1,1,0);
37752 dx = (float)cimg::abs(nxmax-nxmin), dy = (float)cimg::abs(nymax-nymin),
37753 px = (float)std::pow(10.0,(
int)std::log10(dx?dx:1)-2.0),
37754 py = (float)std::pow(10.0,(
int)std::log10(dy?dy:1)-2.0);
37756 seqx = dx<=0?CImg<Tdouble>::vector(nxmin):
37760 const bool allow_zero = (nxmin*nxmax>0) || (nymin*nymax>0);
37761 axes.draw_axes(seqx,seqy,white,1,~0U,~0U,13,allow_zero);
37762 if (nymin>0) axes.draw_axis(seqx,gdimy-1,gray,1,~0U,13,allow_zero);
37763 if (nymax<0) axes.draw_axis(seqx,0,gray,1,~0U,13,allow_zero);
37764 if (nxmin>0) axes.draw_axis(0,seqy,gray,1,~0U,13,allow_zero);
37765 if (nxmax<0) axes.draw_axis(gdimx-1,seqy,gray,1,~0U,13,allow_zero);
37767 cimg_for3x3(axes,x,y,0,0,I,
unsigned char)
37769 if (Icc==255) cimg_forC(graph,c) graph(x,y,c) = 0;
37770 else cimg_forC(graph,c) graph(x,y,c) = (
unsigned char)(2*graph(x,y,c)/3);
37772 else if (Ipc || Inc || Icp || Icn || Ipp || Inn || Ipn || Inp)
37773 cimg_forC(graph,c) graph(x,y,c) = (graph(x,y,c)+511)/3;
37775 visu0.draw_image(16,16,graph);
37776 visu0.draw_line(15,15,16+gdimx,15,gray2).draw_line(16+gdimx,15,16+gdimx,16+gdimy,gray2).
37777 draw_line(16+gdimx,16+gdimy,15,16+gdimy,white).draw_line(15,16+gdimy,15,15,white);
37778 }
else graph.assign();
37779 text.assign().draw_text(0,0,labelx?labelx:
"X-axis",white,ngray,1,13).resize(-100,-100,1,3);
37780 visu0.draw_image((visu0.width()-text.width())/2,visu0.height()-14,~text);
37781 text.assign().draw_text(0,0,labely?labely:
"Y-axis",white,ngray,1,13).rotate(-90).resize(-100,-100,1,3);
37782 visu0.draw_image(1,(visu0.height()-text.height())/2,~text);
37788 visu.assign(visu0);
37789 if (graph && x0>=0 && x1>=0) {
37791 nx0 = x0<=x1?x0:x1,
37792 nx1 = x0<=x1?x1:x0,
37793 ny0 = y0<=y1?y0:y1,
37794 ny1 = y0<=y1?y1:y0,
37795 sx0 = 16 + nx0*(visu.width()-32)/
cimg::max(1U,siz-one),
37796 sx1 = 15 + (nx1+1)*(visu.width()-32)/
cimg::max(1U,siz-one),
37799 if (y0>=0 && y1>=0)
37800 visu.draw_rectangle(sx0,sy0,sx1,sy1,gray,0.5f).draw_rectangle(sx0,sy0,sx1,sy1,black,0.5f,0xCCCCCCCCU);
37801 else visu.draw_rectangle(sx0,0,sx1,visu.height()-17,gray,0.5f).
37802 draw_line(sx0,16,sx0,visu.height()-17,black,0.5f,0xCCCCCCCCU).
37803 draw_line(sx1,16,sx1,visu.height()-17,black,0.5f,0xCCCCCCCCU);
37805 if (mouse_x>=16 && mouse_y>=16 && mouse_x<visu.width()-16 && mouse_y<visu.height()-16) {
37806 if (graph) visu.draw_line(mouse_x,16,mouse_x,visu.height()-17,black,0.5f,0x55555555U);
37807 const unsigned int x = (
unsigned int)
cimg::round((mouse_x-16.0f)*(siz-one)/(disp.
width()-32),1,one?0:-1);
37808 const double cx = nxmin + x*(nxmax-nxmin)/
cimg::max(1U,siz-1);
37810 cimg_snprintf(message,
sizeof(message),
"Value[%u:%g] = ( %g %g %g ... %g %g %g )",x,cx,
37811 (
double)(*
this)(x,0,0,0),(
double)(*
this)(x,0,0,1),(
double)(*
this)(x,0,0,2),
37812 (
double)(*
this)(x,0,0,_spectrum-4),(
double)(*
this)(x,0,0,_spectrum-3),
37813 (
double)(*
this)(x,0,0,_spectrum-1));
37815 cimg_snprintf(message,
sizeof(message),
"Value[%u:%g] = ( ",x,cx);
37816 cimg_forC(*
this,c) std::sprintf(message + std::strlen(message),
"%g ",(
double)(*
this)(x,0,0,c));
37817 std::sprintf(message + std::strlen(message),
")");
37819 if (x0>=0 && x1>=0) {
37821 nx0 = x0<=x1?x0:x1,
37822 nx1 = x0<=x1?x1:x0,
37823 ny0 = y0<=y1?y0:y1,
37824 ny1 = y0<=y1?y1:y0;
37826 cx0 = nxmin + nx0*(nxmax-nxmin)/
cimg::max(1U,siz-1),
37827 cx1 = nxmin + (nx1+one)*(nxmax-nxmin)/
cimg::max(1U,siz-1),
37828 cy0 = nymax - ny0*(nymax-nymin)/(visu._height-32),
37829 cy1 = nymax - ny1*(nymax-nymin)/(visu._height-32);
37830 if (y0>=0 && y1>=0)
37831 std::sprintf(message + std::strlen(message),
" - Range ( %u:%g, %g ) - ( %u:%g, %g )",
37832 x0,cx0,cy0,x1+one,cx1,cy1);
37834 std::sprintf(message + std::strlen(message),
" - Range [ %u:%g - %u:%g ]",
37835 x0,cx0,x1+one,cx1);
37837 text.assign().draw_text(0,0,message,white,ngray,1,13).resize(-100,-100,1,3);
37838 visu.draw_image((visu.width()-text.width())/2,1,~text);
37840 visu.display(disp);
37844 switch (okey = key) {
37849 case cimg::keyD :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
37851 resize(CImgDisplay::_fitscreen(3*disp.
width()/2,3*disp.
height()/2,1,128,-100,
false),
37852 CImgDisplay::_fitscreen(3*disp.
width()/2,3*disp.
height()/2,1,128,-100,
true),
false).
37853 _is_resized =
true;
37854 disp.
set_key(key,
false); okey = 0;
37856 case cimg::keyC :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
37858 resize(cimg_fitscreen(2*disp.
width()/3,2*disp.
height()/3,1),
false)._is_resized =
true;
37859 disp.
set_key(key,
false); okey = 0;
37861 case cimg::keyR :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
37865 disp.
set_key(key,
false); okey = 0;
37867 case cimg::keyF :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
37869 disp.
set_key(key,
false); okey = 0;
37871 case cimg::keyS :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
37872 static unsigned int snap_number = 0;
37873 if (visu || visu0) {
37875 char filename[32] = { 0 };
37878 cimg_snprintf(filename,
sizeof(filename),cimg_appname
"_%.4u.bmp",snap_number++);
37879 if ((file=std::fopen(filename,
"r"))!=0)
cimg::fclose(file);
37881 (+screen).
draw_text(0,0,
" Saving snapshot... ",black,gray,1,13).display(disp);
37882 screen.save(filename);
37883 (+screen).
draw_text(0,0,
" Snapshot '%s' saved. ",black,gray,1,13,filename).display(disp);
37885 disp.
set_key(key,
false); okey = 0;
37887 case cimg::keyO :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
37888 static unsigned int snap_number = 0;
37889 if (visu || visu0) {
37891 char filename[32] = { 0 };
37894 #ifdef cimg_use_zlib
37895 cimg_snprintf(filename,
sizeof(filename),cimg_appname
"_%.4u.cimgz",snap_number++);
37897 cimg_snprintf(filename,
sizeof(filename),cimg_appname
"_%.4u.cimg",snap_number++);
37899 if ((file=std::fopen(filename,
"r"))!=0)
cimg::fclose(file);
37901 (+screen).
draw_text(0,0,
" Saving instance... ",black,gray,1,13).display(disp);
37903 (+screen).
draw_text(0,0,
" Instance '%s' saved. ",black,gray,1,13,filename).display(disp);
37905 disp.
set_key(key,
false); okey = 0;
37910 if (obutton!=button || omouse_x!=mouse_x || omouse_y!=mouse_y) {
37914 mx = (mouse_x -16)*(
int)(siz-one)/(disp.
width()-32),
37915 cx = mx<0?0:(mx>=(
int)(siz-one)?(
int)(siz-1-one):mx),
37917 cy = my<=0?0:(my>=(disp.
height()-32)?(disp.
height()-32):my);
37919 if (!obutton) { x0 = cx; y0 = -1; }
else { x1 = cx; y1 = -1; }
37921 else if (button&2) {
37922 if (!obutton) { x0 = cx; y0 = cy; }
else { x1 = cx; y1 = cy; }
37924 else if (obutton) { x1 = x1>=0?cx:-1; y1 = y1>=0?cy:-1; selected =
true; }
37925 }
else if (!button && obutton) selected =
true;
37926 obutton = button; omouse_x = mouse_x; omouse_y = mouse_y;
37929 if (visu && visu0) disp.
wait();
37932 disp._normalization = old_normalization;
37936 return CImg<intT>(4,1,1,1,x0,y0,x1>=0?x1+(int)one:-1,y1);
37948 "load(): Specified filename is (null).",
37952 char filename_local[1024] = { 0 };
37954 std::remove(filename_local);
37962 #ifdef cimg_load_plugin
37963 cimg_load_plugin(filename);
37965 #ifdef cimg_load_plugin1
37966 cimg_load_plugin1(filename);
37968 #ifdef cimg_load_plugin2
37969 cimg_load_plugin2(filename);
37971 #ifdef cimg_load_plugin3
37972 cimg_load_plugin3(filename);
37974 #ifdef cimg_load_plugin4
37975 cimg_load_plugin4(filename);
37977 #ifdef cimg_load_plugin5
37978 cimg_load_plugin5(filename);
37980 #ifdef cimg_load_plugin6
37981 cimg_load_plugin6(filename);
37983 #ifdef cimg_load_plugin7
37984 cimg_load_plugin7(filename);
37986 #ifdef cimg_load_plugin8
37987 cimg_load_plugin8(filename);
38067 std::FILE *file = 0;
38073 "load(): Failed to open file '%s'.",
38098 "load(): Failed to recognize format of file '%s'.",
38118 return _load_ascii(0,filename);
38128 return _load_ascii(file,0);
38136 CImg<T>& _load_ascii(std::FILE *
const file,
const char *
const filename) {
38137 if (!file && !filename)
38139 "load_ascii(): Specified filename is (null).",
38142 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"rb");
38143 char line[256] = { 0 };
38144 int err = std::fscanf(nfile,
"%255[^\n]",line);
38145 unsigned int dx = 0, dy = 1, dz = 1, dc = 1;
38146 std::sscanf(line,
"%u%*c%u%*c%u%*c%u",&dx,&dy,&dz,&dc);
38147 err = std::fscanf(nfile,
"%*[^0-9.eE+-]");
38148 if (!dx || !dy || !dz || !dc) {
38150 throw CImgIOException(_cimg_instance
38151 "load_ascii(): Invalid ascii header in file '%s', image dimensions are set "
38152 "to (%u,%u,%u,%u).",
38154 filename?filename:
"(FILE*)",dx,dy,dz,dc);
38157 const unsigned long siz =
size();
38158 unsigned long off = 0;
38161 for (err = 1, off = 0; off<siz && err==1; ++off) {
38162 err = std::fscanf(nfile,
"%lf%*[^0-9.eE+-]",&val);
38167 "load_ascii(): Only %lu/%lu values read from file '%s'.",
38169 off-1,siz,filename?filename:
"(FILE*)");
38180 return _load_dlm(0,filename);
38190 return _load_dlm(file,0);
38198 CImg<T>& _load_dlm(std::FILE *
const file,
const char *
const filename) {
38199 if (!file && !filename)
38201 "load_dlm(): Specified filename is (null).",
38204 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"r");
38205 char delimiter[256] = { 0 }, tmp[256] = { 0 };
38206 unsigned int cdx = 0, dx = 0, dy = 0;
38210 while ((err = std::fscanf(nfile,
"%lf%255[^0-9.+-]",&val,delimiter))>0) {
38211 if (err>0) (*this)(cdx++,dy) = (T)val;
38212 if (cdx>=_width)
resize(3*_width/2,_height,1,1,0);
38214 if (!
std::sscanf(delimiter,"%255[^\n]%c",tmp,&c) || c=='\n') {
38216 if (++dy>=_height)
resize(_width,3*_height/2,1,1,0);
38220 if (cdx && err==1) { dx = cdx; ++dy; }
38223 throw CImgIOException(_cimg_instance
38224 "load_dlm(): Invalid DLM file '%s'.",
38226 filename?filename:
"(FILE*)");
38238 return _load_bmp(0,filename);
38248 return _load_bmp(file,0);
38256 CImg<T>& _load_bmp(std::FILE *
const file,
const char *
const filename) {
38257 if (!file && !filename)
38259 "load_bmp(): Specified filename is (null).",
38262 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"rb");
38263 unsigned char header[64] = { 0 };
38265 if (*header!=
'B' || header[1]!=
'M') {
38267 throw CImgIOException(_cimg_instance
38268 "load_bmp(): Invalid BMP file '%s'.",
38270 filename?filename:
"(FILE*)");
38275 file_size = header[0x02] + (header[0x03]<<8) + (header[0x04]<<16) + (header[0x05]<<24),
38276 offset = header[0x0A] + (header[0x0B]<<8) + (header[0x0C]<<16) + (header[0x0D]<<24),
38277 header_size = header[0x0E] + (header[0x0F]<<8) + (header[0x10]<<16) + (header[0x11]<<24),
38278 dx = header[0x12] + (header[0x13]<<8) + (header[0x14]<<16) + (header[0x15]<<24),
38279 dy = header[0x16] + (header[0x17]<<8) + (header[0x18]<<16) + (header[0x19]<<24),
38280 compression = header[0x1E] + (header[0x1F]<<8) + (header[0x20]<<16) + (header[0x21]<<24),
38281 nb_colors = header[0x2E] + (header[0x2F]<<8) + (header[0x30]<<16) + (header[0x31]<<24),
38282 bpp = header[0x1C] + (header[0x1D]<<8);
38284 if (!file_size || file_size==offset) {
38285 std::fseek(nfile,0,SEEK_END);
38286 file_size = (int)std::ftell(nfile);
38287 std::fseek(nfile,54,SEEK_SET);
38289 if (header_size>40) std::fseek(nfile, header_size - 40, SEEK_CUR);
38292 cimg_iobuffer = 12*1024*1024,
38293 dx_bytes = (bpp==1)?(dx/8+(dx%8?1:0)):((bpp==4)?(dx/2+(dx%2?1:0)):(dx*bpp/8)),
38294 align_bytes = (4-dx_bytes%4)%4,
38295 buf_size =
cimg::min(cimg::abs(dy)*(dx_bytes + align_bytes),file_size - offset);
38297 CImg<intT> colormap;
38298 if (bpp<16) {
if (!nb_colors) nb_colors = 1<<bpp; }
else nb_colors = 0;
38299 if (nb_colors) { colormap.assign(nb_colors);
cimg::fread(colormap._data,nb_colors,nfile); }
38300 const int xoffset = offset - 14 - header_size - 4*nb_colors;
38301 if (xoffset>0) std::fseek(nfile,xoffset,SEEK_CUR);
38303 CImg<ucharT> buffer;
38304 if (buf_size<cimg_iobuffer) { buffer.assign(buf_size);
cimg::fread(buffer._data,buf_size,nfile); }
38305 else buffer.assign(dx_bytes + align_bytes);
38306 unsigned char *ptrs = buffer;
38311 throw CImgIOException(_cimg_instance
38312 "load_bmp(): Unable to load compressed data from '(*FILE)' inputs.",
38321 assign(dx,cimg::abs(dy),1,3);
38324 for (
int y =
height()-1; y>=0; --y) {
38325 if (buf_size>=cimg_iobuffer) {
38327 std::fseek(nfile,align_bytes,SEEK_CUR);
38329 unsigned char mask = 0x80, val = 0;
38330 cimg_forX(*
this,x) {
38331 if (mask==0x80) val = *(ptrs++);
38332 const unsigned char *col = (
unsigned char*)(colormap._data + (val&mask?1:0));
38333 (*this)(x,y,2) = (T)*(col++);
38334 (*this)(x,y,1) = (T)*(col++);
38335 (*this)(x,y,0) = (T)*(col++);
38342 for (
int y =
height()-1; y>=0; --y) {
38343 if (buf_size>=cimg_iobuffer) {
38345 std::fseek(nfile,align_bytes,SEEK_CUR);
38347 unsigned char mask = 0xF0, val = 0;
38348 cimg_forX(*
this,x) {
38349 if (mask==0xF0) val = *(ptrs++);
38350 const unsigned char color = (
unsigned char)((mask<16)?(val&mask):((val&mask)>>4));
38351 const unsigned char *col = (
unsigned char*)(colormap._data + color);
38352 (*this)(x,y,2) = (T)*(col++);
38353 (*this)(x,y,1) = (T)*(col++);
38354 (*this)(x,y,0) = (T)*(col++);
38361 for (
int y =
height()-1; y>=0; --y) {
38362 if (buf_size>=cimg_iobuffer) {
38364 std::fseek(nfile,align_bytes,SEEK_CUR);
38366 cimg_forX(*
this,x) {
38367 const unsigned char *col = (
unsigned char*)(colormap._data + *(ptrs++));
38368 (*this)(x,y,2) = (T)*(col++);
38369 (*this)(x,y,1) = (T)*(col++);
38370 (*this)(x,y,0) = (T)*(col++);
38376 for (
int y =
height()-1; y>=0; --y) {
38377 if (buf_size>=cimg_iobuffer) {
38379 std::fseek(nfile,align_bytes,SEEK_CUR);
38381 cimg_forX(*
this,x) {
38382 const unsigned char c1 = *(ptrs++), c2 = *(ptrs++);
38383 const unsigned short col = (
unsigned short)(c1|(c2<<8));
38384 (*this)(x,y,2) = (T)(col&0x1F);
38385 (*this)(x,y,1) = (T)((col>>5)&0x1F);
38386 (*this)(x,y,0) = (T)((col>>10)&0x1F);
38392 for (
int y =
height()-1; y>=0; --y) {
38393 if (buf_size>=cimg_iobuffer) {
38395 std::fseek(nfile,align_bytes,SEEK_CUR);
38397 cimg_forX(*
this,x) {
38398 (*this)(x,y,2) = (T)*(ptrs++);
38399 (*this)(x,y,1) = (T)*(ptrs++);
38400 (*this)(x,y,0) = (T)*(ptrs++);
38406 for (
int y =
height()-1; y>=0; --y) {
38407 if (buf_size>=cimg_iobuffer) {
38409 std::fseek(nfile,align_bytes,SEEK_CUR);
38411 cimg_forX(*
this,x) {
38412 (*this)(x,y,2) = (T)*(ptrs++);
38413 (*this)(x,y,1) = (T)*(ptrs++);
38414 (*this)(x,y,0) = (T)*(ptrs++);
38431 return _load_jpeg(0,filename);
38441 return _load_jpeg(file,0);
38450 #ifdef cimg_use_jpeg
38451 struct _cimg_error_mgr {
38452 struct jpeg_error_mgr original;
38453 jmp_buf setjmp_buffer;
38454 char message[JMSG_LENGTH_MAX];
38457 typedef struct _cimg_error_mgr *_cimg_error_ptr;
38459 METHODDEF(
void) _cimg_jpeg_error_exit(j_common_ptr cinfo) {
38460 _cimg_error_ptr c_err = (_cimg_error_ptr) cinfo->err;
38461 (*cinfo->err->format_message)(cinfo,c_err->message);
38462 jpeg_destroy(cinfo);
38463 longjmp(c_err->setjmp_buffer,1);
38467 CImg<T>& _load_jpeg(std::FILE *
const file,
const char *
const filename) {
38468 if (!file && !filename)
38469 throw CImgArgumentException(_cimg_instance
38470 "load_jpeg(): Specified filename is (null).",
38473 #ifndef cimg_use_jpeg
38475 throw CImgIOException(_cimg_instance
38476 "load_jpeg(): Unable to load data from '(FILE*)' unless libjpeg is enabled.",
38481 struct jpeg_decompress_struct cinfo;
38482 struct _cimg_error_mgr jerr;
38483 cinfo.err = jpeg_std_error(&jerr.original);
38484 jerr.original.error_exit = _cimg_jpeg_error_exit;
38486 if (setjmp(jerr.setjmp_buffer)) {
38487 throw CImgIOException(_cimg_instance
38488 "load_jpeg(): Error message returned by libjpeg: %s.",
38489 cimg_instance,jerr.message);
38492 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"rb");
38493 jpeg_create_decompress(&cinfo);
38494 jpeg_stdio_src(&cinfo,nfile);
38495 jpeg_read_header(&cinfo,TRUE);
38496 jpeg_start_decompress(&cinfo);
38498 if (cinfo.output_components!=1 && cinfo.output_components!=3 && cinfo.output_components!=4) {
38503 throw CImgIOException(_cimg_instance
38504 "load_jpeg(): Failed to load JPEG data from file '%s'.",
38505 cimg_instance,filename?filename:
"(FILE*)");
38507 CImg<ucharT> buffer(cinfo.output_width*cinfo.output_components);
38508 JSAMPROW row_pointer[1];
38509 assign(cinfo.output_width,cinfo.output_height,1,cinfo.output_components);
38510 T *ptr_r = _data, *ptr_g = _data + 1UL*_width*_height, *ptr_b = _data + 2UL*_width*_height,
38511 *ptr_a = _data + 3UL*_width*_height;
38512 while (cinfo.output_scanline<cinfo.output_height) {
38513 *row_pointer = buffer._data;
38514 if (jpeg_read_scanlines(&cinfo,row_pointer,1)!=1) {
38516 "load_jpeg(): Incomplete data in file '%s'.",
38517 cimg_instance,filename?filename:
"(FILE*)");
38520 const unsigned char *ptrs = buffer._data;
38521 switch (_spectrum) {
38523 cimg_forX(*
this,x) *(ptr_r++) = (T)*(ptrs++);
38526 cimg_forX(*
this,x) {
38527 *(ptr_r++) = (T)*(ptrs++);
38528 *(ptr_g++) = (T)*(ptrs++);
38529 *(ptr_b++) = (T)*(ptrs++);
38533 cimg_forX(*
this,x) {
38534 *(ptr_r++) = (T)*(ptrs++);
38535 *(ptr_g++) = (T)*(ptrs++);
38536 *(ptr_b++) = (T)*(ptrs++);
38537 *(ptr_a++) = (T)*(ptrs++);
38542 jpeg_finish_decompress(&cinfo);
38543 jpeg_destroy_decompress(&cinfo);
38558 "load_magick(): Specified filename is (null).",
38560 #ifdef cimg_use_magick
38561 Magick::Image image(filename);
38562 const unsigned int W = image.size().width(), H = image.size().height();
38563 switch (image.type()) {
38564 case Magick::PaletteMatteType :
38565 case Magick::TrueColorMatteType :
38566 case Magick::ColorSeparationType : {
38568 T *ptr_r =
data(0,0,0,0), *ptr_g =
data(0,0,0,1), *ptr_b =
data(0,0,0,2), *ptr_a =
data(0,0,0,3);
38569 Magick::PixelPacket *pixels = image.getPixels(0,0,W,H);
38570 for (
unsigned long off = (
unsigned long)W*H; off; --off) {
38571 *(ptr_r++) = (T)(pixels->red);
38572 *(ptr_g++) = (T)(pixels->green);
38573 *(ptr_b++) = (T)(pixels->blue);
38574 *(ptr_a++) = (T)(pixels->opacity);
38578 case Magick::PaletteType :
38579 case Magick::TrueColorType : {
38581 T *ptr_r =
data(0,0,0,0), *ptr_g =
data(0,0,0,1), *ptr_b =
data(0,0,0,2);
38582 Magick::PixelPacket *pixels = image.getPixels(0,0,W,H);
38583 for (
unsigned long off = (
unsigned long)W*H; off; --off) {
38584 *(ptr_r++) = (T)(pixels->red);
38585 *(ptr_g++) = (T)(pixels->green);
38586 *(ptr_b++) = (T)(pixels->blue);
38590 case Magick::GrayscaleMatteType : {
38592 T *ptr_r =
data(0,0,0,0), *ptr_a =
data(0,0,0,1);
38593 Magick::PixelPacket *pixels = image.getPixels(0,0,W,H);
38594 for (
unsigned long off = (
unsigned long)W*H; off; --off) {
38595 *(ptr_r++) = (T)(pixels->red);
38596 *(ptr_a++) = (T)(pixels->opacity);
38602 T *ptr_r =
data(0,0,0,0);
38603 Magick::PixelPacket *pixels = image.getPixels(0,0,W,H);
38604 for (
unsigned long off = (
unsigned long)W*H; off; --off) {
38605 *(ptr_r++) = (T)(pixels->red);
38613 "load_magick(): Unable to load file '%s' unless libMagick++ is enabled.",
38629 return _load_png(0,filename);
38639 return _load_png(file,0);
38648 CImg<T>& _load_png(std::FILE *
const file,
const char *
const filename) {
38649 if (!file && !filename)
38651 "load_png(): Specified filename is (null).",
38654 #ifndef cimg_use_png
38657 "load_png(): Unable to load data from '(FILE*)' unless libpng is enabled.",
38663 const char *
volatile nfilename = filename;
38664 std::FILE *
volatile nfile = file?file:
cimg::fopen(nfilename,
"rb");
38666 unsigned char pngCheck[8] = { 0 };
38668 if (png_sig_cmp(pngCheck,0,8)) {
38670 throw CImgIOException(_cimg_instance
38671 "load_png(): Invalid PNG file '%s'.",
38673 nfilename?nfilename:
"(FILE*)");
38677 png_voidp user_error_ptr = 0;
38678 png_error_ptr user_error_fn = 0, user_warning_fn = 0;
38679 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,user_error_ptr,user_error_fn,user_warning_fn);
38682 throw CImgIOException(_cimg_instance
38683 "load_png(): Failed to initialize 'png_ptr' structure for file '%s'.",
38685 nfilename?nfilename:
"(FILE*)");
38687 png_infop info_ptr = png_create_info_struct(png_ptr);
38690 png_destroy_read_struct(&png_ptr,(png_infopp)0,(png_infopp)0);
38691 throw CImgIOException(_cimg_instance
38692 "load_png(): Failed to initialize 'info_ptr' structure for file '%s'.",
38694 nfilename?nfilename:
"(FILE*)");
38696 png_infop end_info = png_create_info_struct(png_ptr);
38699 png_destroy_read_struct(&png_ptr,&info_ptr,(png_infopp)0);
38700 throw CImgIOException(_cimg_instance
38701 "load_png(): Failed to initialize 'end_info' structure for file '%s'.",
38703 nfilename?nfilename:
"(FILE*)");
38707 if (setjmp(png_jmpbuf(png_ptr))) {
38709 png_destroy_read_struct(&png_ptr, &end_info, (png_infopp)0);
38710 throw CImgIOException(_cimg_instance
38711 "load_png(): Encountered unknown fatal error in libpng for file '%s'.",
38713 nfilename?nfilename:
"(FILE*)");
38715 png_init_io(png_ptr, nfile);
38716 png_set_sig_bytes(png_ptr, 8);
38719 png_read_info(png_ptr,info_ptr);
38721 int bit_depth, color_type, interlace_type;
38722 bool is_gray =
false;
38723 png_get_IHDR(png_ptr,info_ptr,&W,&H,&bit_depth,&color_type,&interlace_type,(
int*)0,(
int*)0);
38726 if (color_type==PNG_COLOR_TYPE_PALETTE) {
38727 png_set_palette_to_rgb(png_ptr);
38728 color_type = PNG_COLOR_TYPE_RGB;
38731 if (color_type==PNG_COLOR_TYPE_GRAY && bit_depth<8) {
38732 png_set_expand_gray_1_2_4_to_8(png_ptr);
38736 if (png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS)) {
38737 png_set_tRNS_to_alpha(png_ptr);
38738 color_type |= PNG_COLOR_MASK_ALPHA;
38740 if (color_type==PNG_COLOR_TYPE_GRAY || color_type==PNG_COLOR_TYPE_GRAY_ALPHA) {
38741 png_set_gray_to_rgb(png_ptr);
38742 color_type |= PNG_COLOR_MASK_COLOR;
38745 if (color_type==PNG_COLOR_TYPE_RGB)
38746 png_set_filler(png_ptr,0xffffU,PNG_FILLER_AFTER);
38748 png_read_update_info(png_ptr,info_ptr);
38749 if (bit_depth!=8 && bit_depth!=16) {
38751 png_destroy_read_struct(&png_ptr,&end_info,(png_infopp)0);
38752 throw CImgIOException(_cimg_instance
38753 "load_png(): Invalid bit depth %u in file '%s'.",
38755 bit_depth,nfilename?nfilename:
"(FILE*)");
38757 const int byte_depth = bit_depth>>3;
38760 png_bytep *
const imgData =
new png_bytep[H];
38761 for (
unsigned int row = 0;
row<H; ++
row) imgData[
row] =
new png_byte[byte_depth*4*W];
38762 png_read_image(png_ptr,imgData);
38763 png_read_end(png_ptr,end_info);
38766 if (color_type!=PNG_COLOR_TYPE_RGB && color_type!=PNG_COLOR_TYPE_RGB_ALPHA) {
38768 png_destroy_read_struct(&png_ptr,&end_info,(png_infopp)0);
38769 throw CImgIOException(_cimg_instance
38770 "load_png(): Invalid color coding type %u in file '%s'.",
38772 color_type,nfilename?nfilename:
"(FILE*)");
38774 const bool is_alpha = (color_type==PNG_COLOR_TYPE_RGBA);
38775 assign(W,H,1,(is_gray?1:3) + (is_alpha?1:0));
38777 *ptr_r =
data(0,0,0,0),
38778 *ptr_g = is_gray?0:
data(0,0,0,1),
38779 *ptr_b = is_gray?0:
data(0,0,0,2),
38780 *ptr_a = !is_alpha?0:
data(0,0,0,is_gray?1:3);
38781 switch (bit_depth) {
38783 cimg_forY(*
this,y) {
38784 const unsigned char *ptrs = (
unsigned char*)imgData[y];
38785 cimg_forX(*
this,x) {
38786 *(ptr_r++) = (T)*(ptrs++);
38787 if (ptr_g) *(ptr_g++) = (T)*(ptrs++);
else ++ptrs;
38788 if (ptr_b) *(ptr_b++) = (T)*(ptrs++);
else ++ptrs;
38789 if (ptr_a) *(ptr_a++) = (T)*(ptrs++);
else ++ptrs;
38794 cimg_forY(*
this,y) {
38795 const unsigned short *ptrs = (
unsigned short*)(imgData[y]);
38797 cimg_forX(*
this,x) {
38798 *(ptr_r++) = (T)*(ptrs++);
38799 if (ptr_g) *(ptr_g++) = (T)*(ptrs++);
else ++ptrs;
38800 if (ptr_b) *(ptr_b++) = (T)*(ptrs++);
else ++ptrs;
38801 if (ptr_a) *(ptr_a++) = (T)*(ptrs++);
else ++ptrs;
38806 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
38809 cimg_forY(*
this,n) delete[] imgData[n];
38811 if (!file) cimg::fclose(nfile);
38821 return _load_pnm(0,filename);
38831 return _load_pnm(file,0);
38839 CImg<T>& _load_pnm(std::FILE *
const file,
const char *
const filename) {
38840 if (!file && !filename)
38842 "load_pnm(): Specified filename is (null).",
38845 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"rb");
38846 unsigned int ppm_type, W, H, D = 1, colormax = 255;
38848 int err, rval, gval, bval;
38849 const long cimg_iobuffer = 12*1024*1024;
38850 while ((err=std::fscanf(nfile,
"%16383[^\n]",item.data()))!=EOF && (*item==
'#' || !err)) std::fgetc(nfile);
38851 if (std::sscanf(item,
" P%u",&ppm_type)!=1) {
38854 "load_pnm(): PNM header not found in file '%s'.",
38856 filename?filename:
"(FILE*)");
38858 while ((err=std::fscanf(nfile,
" %16383[^\n]",item.data()))!=EOF && (*item==
'#' || !err)) std::fgetc(nfile);
38859 if ((err=std::sscanf(item,
" %u %u %u %u",&W,&H,&D,&colormax))<2) {
38861 throw CImgIOException(_cimg_instance
38862 "load_pnm(): WIDTH and HEIGHT fields undefined in file '%s'.",
38864 filename?filename:
"(FILE*)");
38866 if (ppm_type!=1 && ppm_type!=4) {
38867 if (err==2 || (err==3 && (ppm_type==5 || ppm_type==7 || ppm_type==8 || ppm_type==9))) {
38868 while ((err=std::fscanf(nfile,
" %16383[^\n]",item.data()))!=EOF && (*item==
'#' || !err)) std::fgetc(nfile);
38869 if (std::sscanf(item,
"%u",&colormax)!=1)
38871 "load_pnm(): COLORMAX field is undefined in file '%s'.",
38873 filename?filename:
"(FILE*)");
38874 }
else { colormax = D; D = 1; }
38878 switch (ppm_type) {
38882 cimg_foroff(*
this,off) {
if (std::fscanf(nfile,
"%d",&rval)>0) *(ptrd++) = (T)(rval?0:255);
else break; }
38887 cimg_foroff(*
this,off) {
if (std::fscanf(nfile,
"%d",&rval)>0) *(ptrd++) = (T)rval;
else break; }
38891 T *ptrd =
data(0,0,0,0), *ptr_g =
data(0,0,0,1), *ptr_b =
data(0,0,0,2);
38892 cimg_forXY(*
this,x,y) {
38893 if (std::fscanf(nfile,
"%d %d %d",&rval,&gval,&bval)==3) {
38894 *(ptrd++) = (T)rval; *(ptr_g++) = (T)gval; *(ptr_b++) = (T)bval;
38901 T *ptrd =
data(0,0,0,0);
38902 unsigned int w = 0, h = 0, d = 0;
38903 for (
long to_read = (
long)((W/8 + (W%8?1:0))*H*D); to_read>0; ) {
38904 raw.assign(
cimg::min(to_read,cimg_iobuffer));
38906 to_read-=raw._width;
38907 const unsigned char *ptrs = raw._data;
38908 unsigned char mask = 0, val = 0;
38909 for (
unsigned long off = (
unsigned long)raw._width; off || mask; mask>>=1) {
38910 if (!mask) {
if (off--) val = *(ptrs++); mask = 128; }
38911 *(ptrd++) = (T)((val&mask)?0:255);
38912 if (++w==W) { w = 0; mask = 0;
if (++h==H) { h = 0;
if (++d==D)
break; }}
38916 case 5 :
case 7 : {
38917 if (colormax<256) {
38920 T *ptrd =
data(0,0,0,0);
38921 for (
long to_read = (
long)
size(); to_read>0; ) {
38922 raw.assign(
cimg::min(to_read,cimg_iobuffer));
38924 to_read-=raw._width;
38925 const unsigned char *ptrs = raw._data;
38926 for (
unsigned long off = (
unsigned long)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++);
38931 T *ptrd =
data(0,0,0,0);
38932 for (
long to_read = (
long)
size(); to_read>0; ) {
38933 raw.assign(
cimg::min(to_read,cimg_iobuffer/2));
38936 to_read-=raw._width;
38937 const unsigned short *ptrs = raw._data;
38938 for (
unsigned long off = (
unsigned long)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++);
38943 if (colormax<256) {
38947 *ptr_r =
data(0,0,0,0),
38948 *ptr_g =
data(0,0,0,1),
38949 *ptr_b =
data(0,0,0,2);
38950 for (
long to_read = (
long)
size(); to_read>0; ) {
38951 raw.assign(
cimg::min(to_read,cimg_iobuffer));
38953 to_read-=raw._width;
38954 const unsigned char *ptrs = raw._data;
38955 for (
unsigned long off = (
unsigned long)raw._width/3; off; --off) {
38956 *(ptr_r++) = (T)*(ptrs++);
38957 *(ptr_g++) = (T)*(ptrs++);
38958 *(ptr_b++) = (T)*(ptrs++);
38965 *ptr_r =
data(0,0,0,0),
38966 *ptr_g =
data(0,0,0,1),
38967 *ptr_b =
data(0,0,0,2);
38968 for (
long to_read = (
int)
size(); to_read>0; ) {
38969 raw.assign(
cimg::min(to_read,cimg_iobuffer/2));
38972 to_read-=raw._width;
38973 const unsigned short *ptrs = raw._data;
38974 for (
unsigned long off = (
unsigned long)raw._width/3; off; --off) {
38975 *(ptr_r++) = (T)*(ptrs++);
38976 *(ptr_g++) = (T)*(ptrs++);
38977 *(ptr_b++) = (T)*(ptrs++);
38985 T *ptrd =
data(0,0,0,0);
38986 for (
long to_read = (
long)
size(); to_read>0; ) {
38987 raw.assign(
cimg::min(to_read,cimg_iobuffer));
38989 to_read-=raw._width;
38990 const int *ptrs = raw._data;
38991 for (
unsigned long off = (
unsigned long)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++);
38997 T *ptrd =
data(0,0,0,0);
38998 for (
long to_read = (
long)
size(); to_read>0; ) {
38999 raw.assign(
cimg::min(to_read,cimg_iobuffer));
39001 to_read-=raw._width;
39002 const float *ptrs = raw._data;
39003 for (
unsigned long off = (
unsigned long)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++);
39009 throw CImgIOException(_cimg_instance
39010 "load_pnm(): PNM type 'P%d' found, but type is not supported.",
39012 filename?filename:
"(FILE*)",ppm_type);
39023 return _load_pfm(0,filename);
39033 return _load_pfm(file,0);
39041 CImg<T>& _load_pfm(std::FILE *
const file,
const char *
const filename) {
39042 if (!file && !filename)
39044 "load_pfm(): Specified filename is (null).",
39047 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"rb");
39050 int W = 0, H = 0, err = 0;
39052 while ((err=std::fscanf(nfile,
"%16383[^\n]",item.data()))!=EOF && (*item==
'#' || !err)) std::fgetc(nfile);
39053 if (std::sscanf(item,
" P%c",&pfm_type)!=1) {
39056 "load_pfm(): PFM header not found in file '%s'.",
39058 filename?filename:
"(FILE*)");
39060 while ((err=std::fscanf(nfile,
" %16383[^\n]",item.data()))!=EOF && (*item==
'#' || !err)) std::fgetc(nfile);
39061 if ((err=std::sscanf(item,
" %d %d",&W,&H))<2) {
39063 throw CImgIOException(_cimg_instance
39064 "load_pfm(): WIDTH and HEIGHT fields are undefined in file '%s'.",
39066 filename?filename:
"(FILE*)");
39069 while ((err=std::fscanf(nfile,
" %16383[^\n]",item.data()))!=EOF && (*item==
'#' || !err)) std::fgetc(nfile);
39070 if (std::sscanf(item,
"%lf",&scale)!=1)
39072 "load_pfm(): SCALE field is undefined in file '%s'.",
39074 filename?filename:
"(FILE*)");
39077 const bool is_color = (pfm_type==
'F'), is_inverted = (scale>0)!=
cimg::endianness();
39080 CImg<floatT> buf(3*W);
39081 T *ptr_r =
data(0,0,0,0), *ptr_g =
data(0,0,0,1), *ptr_b =
data(0,0,0,2);
39082 cimg_forY(*
this,y) {
39085 const float *ptrs = buf._data;
39086 cimg_forX(*
this,x) {
39087 *(ptr_r++) = (T)*(ptrs++);
39088 *(ptr_g++) = (T)*(ptrs++);
39089 *(ptr_b++) = (T)*(ptrs++);
39094 CImg<floatT> buf(W);
39095 T *ptrd =
data(0,0,0,0);
39096 cimg_forY(*
this,y) {
39099 const float *ptrs = buf._data;
39100 cimg_forX(*
this,x) *(ptrd++) = (T)*(ptrs++);
39113 CImg<T>&
load_rgb(
const char *
const filename,
const unsigned int dimw,
const unsigned int dimh=1) {
39114 return _load_rgb(0,filename,dimw,dimh);
39123 CImg<T>&
load_rgb(std::FILE *
const file,
const unsigned int dimw,
const unsigned int dimh=1) {
39124 return _load_rgb(file,0,dimw,dimh);
39132 CImg<T>& _load_rgb(std::FILE *
const file,
const char *
const filename,
39133 const unsigned int dimw,
const unsigned int dimh) {
39134 if (!file && !filename)
39136 "load_rgb(): Specified filename is (null).",
39139 if (!dimw || !dimh)
return assign();
39140 const long cimg_iobuffer = 12*1024*1024;
39141 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"rb");
39145 *ptr_r =
data(0,0,0,0),
39146 *ptr_g =
data(0,0,0,1),
39147 *ptr_b =
data(0,0,0,2);
39148 for (
long to_read = (
long)
size(); to_read>0; ) {
39149 raw.assign(
cimg::min(to_read,cimg_iobuffer));
39151 to_read-=raw._width;
39152 const unsigned char *ptrs = raw._data;
39153 for (
unsigned long off = raw._width/3UL; off; --off) {
39154 *(ptr_r++) = (T)*(ptrs++);
39155 *(ptr_g++) = (T)*(ptrs++);
39156 *(ptr_b++) = (T)*(ptrs++);
39169 CImg<T>&
load_rgba(
const char *
const filename,
const unsigned int dimw,
const unsigned int dimh=1) {
39170 return _load_rgba(0,filename,dimw,dimh);
39180 return _load_rgba(file,0,dimw,dimh);
39188 CImg<T>& _load_rgba(std::FILE *
const file,
const char *
const filename,
39189 const unsigned int dimw,
const unsigned int dimh) {
39190 if (!file && !filename)
39192 "load_rgba(): Specified filename is (null).",
39195 if (!dimw || !dimh)
return assign();
39196 const long cimg_iobuffer = 12*1024*1024;
39197 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"rb");
39201 *ptr_r =
data(0,0,0,0),
39202 *ptr_g =
data(0,0,0,1),
39203 *ptr_b =
data(0,0,0,2),
39204 *ptr_a =
data(0,0,0,3);
39205 for (
long to_read = (
long)
size(); to_read>0; ) {
39206 raw.assign(
cimg::min(to_read,cimg_iobuffer));
39208 to_read-=raw._width;
39209 const unsigned char *ptrs = raw._data;
39210 for (
unsigned long off = raw._width/4UL; off; --off) {
39211 *(ptr_r++) = (T)*(ptrs++);
39212 *(ptr_g++) = (T)*(ptrs++);
39213 *(ptr_b++) = (T)*(ptrs++);
39214 *(ptr_a++) = (T)*(ptrs++);
39237 const unsigned int first_frame=0,
const unsigned int last_frame=~0U,
39238 const unsigned int step_frame=1) {
39241 "load_tiff(): Specified filename is (null).",
39245 nfirst_frame = first_frame<last_frame?first_frame:last_frame,
39246 nstep_frame = step_frame?step_frame:1;
39247 unsigned int nlast_frame = first_frame<last_frame?last_frame:first_frame;
39249 #ifndef cimg_use_tiff
39250 if (nfirst_frame || nlast_frame!=~0U || nstep_frame>1)
39252 "load_tiff(): Unable to read sub-images from file '%s' unless libtiff is enabled.",
39257 TIFF *tif = TIFFOpen(filename,
"r");
39259 unsigned int nb_images = 0;
39260 do ++nb_images;
while (TIFFReadDirectory(tif));
39261 if (nfirst_frame>=nb_images || (nlast_frame!=~0U && nlast_frame>=nb_images))
39263 "load_tiff(): File '%s' contains %u image(s) while specified frame range is [%u,%u] (step %u).",
39265 filename,nb_images,nfirst_frame,nlast_frame,nstep_frame);
39267 if (nfirst_frame>=nb_images)
return assign();
39268 if (nlast_frame>=nb_images) nlast_frame = nb_images-1;
39269 TIFFSetDirectory(tif,0);
39271 for (
unsigned int l = nfirst_frame; l<=nlast_frame; l+=nstep_frame) {
39272 frame._load_tiff(tif,l);
39273 if (l==nfirst_frame)
39274 assign(frame._width,frame._height,1+(nlast_frame-nfirst_frame)/nstep_frame,frame._spectrum);
39275 if (frame._width>_width || frame._height>_height || frame._spectrum>_spectrum)
39278 cimg::max(frame._spectrum,_spectrum),0);
39279 draw_image(0,0,(l-nfirst_frame)/nstep_frame,frame);
39283 "load_tiff(): Failed to open file '%s'.",
39292 const unsigned int first_frame=0,
const unsigned int last_frame=~0U,
39293 const unsigned int step_frame=1) {
39298 #ifdef cimg_use_tiff
39299 template<
typename t>
39300 void _load_tiff_tiled_contig(TIFF *
const tif,
const uint16 samplesperpixel,
39301 const uint32 nx,
const uint32 ny,
const uint32 tw,
const uint32 th) {
39302 t *
const buf = (t*)_TIFFmalloc(TIFFTileSize(tif));
39304 for (
unsigned int row = 0;
row<ny;
row+=th)
39305 for (
unsigned int col = 0; col<nx; col+=tw) {
39306 if (TIFFReadTile(tif,buf,col,
row,0,0)<0) {
39307 _TIFFfree(buf); TIFFClose(tif);
39309 "load_tiff(): Invalid tile in file '%s'.",
39311 TIFFFileName(tif));
39313 const t *ptr = buf;
39314 for (
unsigned int rr =
row; rr<
cimg::min((
unsigned int)(
row+th),(
unsigned int)ny); ++rr)
39315 for (
unsigned int cc = col; cc<
cimg::min((
unsigned int)(col+tw),(
unsigned int)nx); ++cc)
39316 for (
unsigned int vv = 0; vv<samplesperpixel; ++vv)
39317 (*
this)(cc,rr,vv) = (T)(ptr[(rr-
row)*th*samplesperpixel + (cc-col)*samplesperpixel + vv]);
39323 template<
typename t>
39324 void _load_tiff_tiled_separate(TIFF *
const tif,
const uint16 samplesperpixel,
39325 const uint32 nx,
const uint32 ny,
const uint32 tw,
const uint32 th) {
39326 t *
const buf = (t*)_TIFFmalloc(TIFFTileSize(tif));
39328 for (
unsigned int vv = 0; vv<samplesperpixel; ++vv)
39329 for (
unsigned int row = 0;
row<ny;
row+=th)
39330 for (
unsigned int col = 0; col<nx; col+=tw) {
39331 if (TIFFReadTile(tif,buf,col,
row,0,vv)<0) {
39332 _TIFFfree(buf); TIFFClose(tif);
39333 throw CImgIOException(_cimg_instance
39334 "load_tiff(): Invalid tile in file '%s'.",
39336 TIFFFileName(tif));
39338 const t *ptr = buf;
39339 for (
unsigned int rr =
row; rr<
cimg::min((
unsigned int)(
row+th),(
unsigned int)ny); ++rr)
39340 for (
unsigned int cc = col; cc<
cimg::min((
unsigned int)(col+tw),(
unsigned int)nx); ++cc)
39341 (*
this)(cc,rr,vv) = (T)*(ptr++);
39347 template<
typename t>
39348 void _load_tiff_contig(TIFF *
const tif,
const uint16 samplesperpixel,
const uint32 nx,
const uint32 ny) {
39349 t *
const buf = (t*)_TIFFmalloc(TIFFStripSize(tif));
39351 uint32
row, rowsperstrip = (uint32)-1;
39352 TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rowsperstrip);
39353 for (row = 0; row<ny; row+= rowsperstrip) {
39354 uint32 nrow = (row+rowsperstrip>ny?ny-row:rowsperstrip);
39355 tstrip_t strip = TIFFComputeStrip(tif, row, 0);
39356 if ((TIFFReadEncodedStrip(tif,strip,buf,-1))<0) {
39357 _TIFFfree(buf); TIFFClose(tif);
39358 throw CImgIOException(_cimg_instance
39359 "load_tiff(): Invalid strip in file '%s'.",
39361 TIFFFileName(tif));
39363 const t *ptr = buf;
39364 for (
unsigned int rr = 0; rr<nrow; ++rr)
39365 for (
unsigned int cc = 0; cc<nx; ++cc)
39366 for (
unsigned int vv = 0; vv<samplesperpixel; ++vv) (*
this)(cc,row+rr,vv) = (T)*(ptr++);
39372 template<
typename t>
39373 void _load_tiff_separate(TIFF *
const tif,
const uint16 samplesperpixel,
const uint32 nx,
const uint32 ny) {
39374 t *buf = (t*)_TIFFmalloc(TIFFStripSize(tif));
39376 uint32
row, rowsperstrip = (uint32)-1;
39377 TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rowsperstrip);
39378 for (
unsigned int vv = 0; vv<samplesperpixel; ++vv)
39379 for (row = 0; row<ny; row+= rowsperstrip) {
39380 uint32 nrow = (row+rowsperstrip>ny?ny-row:rowsperstrip);
39381 tstrip_t strip = TIFFComputeStrip(tif, row, vv);
39382 if ((TIFFReadEncodedStrip(tif,strip,buf,-1))<0) {
39383 _TIFFfree(buf); TIFFClose(tif);
39384 throw CImgIOException(_cimg_instance
39385 "load_tiff(): Invalid strip in file '%s'.",
39387 TIFFFileName(tif));
39389 const t *ptr = buf;
39390 for (
unsigned int rr = 0;rr<nrow; ++rr)
39391 for (
unsigned int cc = 0; cc<nx; ++cc)
39392 (*
this)(cc,row+rr,vv) = (T)*(ptr++);
39398 CImg<T>& _load_tiff(TIFF *
const tif,
const unsigned int directory) {
39399 if (!TIFFSetDirectory(tif,directory))
return assign();
39400 uint16 samplesperpixel = 1, bitspersample = 8, photo = 0;
39401 uint16 sampleformat = 1;
39402 uint32 nx = 1, ny = 1;
39403 const char *
const filename = TIFFFileName(tif);
39404 const bool is_spp = (bool)TIFFGetField(tif,TIFFTAG_SAMPLESPERPIXEL,&samplesperpixel);
39405 TIFFGetField(tif,TIFFTAG_IMAGEWIDTH,&nx);
39406 TIFFGetField(tif,TIFFTAG_IMAGELENGTH,&ny);
39407 TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &sampleformat);
39408 TIFFGetFieldDefaulted(tif,TIFFTAG_BITSPERSAMPLE,&bitspersample);
39409 TIFFGetField(tif,TIFFTAG_PHOTOMETRIC,&photo);
39411 const unsigned int spectrum = is_spp?samplesperpixel:photo==3?3:1;
39412 assign(nx,ny,1,spectrum);
39414 if (photo>=3 && sampleformat==1 && bitspersample==8 && (samplesperpixel==3 || samplesperpixel==4)) {
39416 uint32 *
const raster = (uint32*)_TIFFmalloc(nx*ny*
sizeof(uint32));
39418 _TIFFfree(raster); TIFFClose(tif);
39419 throw CImgException(_cimg_instance
39420 "load_tiff(): Failed to allocate memory (%s) for file '%s'.",
39422 cimg::strbuffersize(nx*ny*
sizeof(uint32)),filename);
39424 TIFFReadRGBAImage(tif,nx,ny,raster,0);
39425 switch (spectrum) {
39427 cimg_forXY(*
this,x,y) (*this)(x,y) = (T)(float)((raster[nx*(ny-1-y)+x] + 128)/257);
39430 cimg_forXY(*
this,x,y) {
39431 (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny-1-y)+x]);
39432 (*this)(x,y,1) = (T)(float)TIFFGetG(raster[nx*(ny-1-y)+x]);
39433 (*this)(x,y,2) = (T)(float)TIFFGetB(raster[nx*(ny-1-y)+x]);
39437 cimg_forXY(*
this,x,y) {
39438 (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny-1-y)+x]);
39439 (*this)(x,y,1) = (T)(float)TIFFGetG(raster[nx*(ny-1-y)+x]);
39440 (*this)(x,y,2) = (T)(float)TIFFGetB(raster[nx*(ny-1-y)+x]);
39441 (*this)(x,y,3) = (T)(float)TIFFGetA(raster[nx*(ny-1-y)+x]);
39448 TIFFGetField(tif,TIFFTAG_PLANARCONFIG,&config);
39449 if (TIFFIsTiled(tif)) {
39450 uint32 tw = 1, th = 1;
39451 TIFFGetField(tif,TIFFTAG_TILEWIDTH,&tw);
39452 TIFFGetField(tif,TIFFTAG_TILELENGTH,&th);
39453 if (config==PLANARCONFIG_CONTIG)
switch (bitspersample) {
39455 if (sampleformat==SAMPLEFORMAT_UINT)
39456 _load_tiff_tiled_contig<unsigned char>(tif,samplesperpixel,nx,ny,tw,th);
39457 else _load_tiff_tiled_contig<signed char>(tif,samplesperpixel,nx,ny,tw,th);
39460 if (sampleformat==SAMPLEFORMAT_UINT)
39461 _load_tiff_tiled_contig<unsigned short>(tif,samplesperpixel,nx,ny,tw,th);
39462 else _load_tiff_tiled_contig<short>(tif,samplesperpixel,nx,ny,tw,th);
39465 if (sampleformat==SAMPLEFORMAT_UINT)
39466 _load_tiff_tiled_contig<unsigned int>(tif,samplesperpixel,nx,ny,tw,th);
39467 else if (sampleformat==SAMPLEFORMAT_INT)
39468 _load_tiff_tiled_contig<int>(tif,samplesperpixel,nx,ny,tw,th);
39469 else _load_tiff_tiled_contig<float>(tif,samplesperpixel,nx,ny,tw,th);
39471 }
else switch (bitspersample) {
39473 if (sampleformat==SAMPLEFORMAT_UINT)
39474 _load_tiff_tiled_separate<unsigned char>(tif,samplesperpixel,nx,ny,tw,th);
39475 else _load_tiff_tiled_separate<signed char>(tif,samplesperpixel,nx,ny,tw,th);
39478 if (sampleformat==SAMPLEFORMAT_UINT)
39479 _load_tiff_tiled_separate<unsigned short>(tif,samplesperpixel,nx,ny,tw,th);
39480 else _load_tiff_tiled_separate<short>(tif,samplesperpixel,nx,ny,tw,th);
39483 if (sampleformat==SAMPLEFORMAT_UINT)
39484 _load_tiff_tiled_separate<unsigned int>(tif,samplesperpixel,nx,ny,tw,th);
39485 else if (sampleformat==SAMPLEFORMAT_INT)
39486 _load_tiff_tiled_separate<int>(tif,samplesperpixel,nx,ny,tw,th);
39487 else _load_tiff_tiled_separate<float>(tif,samplesperpixel,nx,ny,tw,th);
39491 if (config==PLANARCONFIG_CONTIG)
switch (bitspersample) {
39493 if (sampleformat==SAMPLEFORMAT_UINT)
39494 _load_tiff_contig<unsigned char>(tif,samplesperpixel,nx,ny);
39495 else _load_tiff_contig<signed char>(tif,samplesperpixel,nx,ny);
39498 if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_contig<unsigned short>(tif,samplesperpixel,nx,ny);
39499 else _load_tiff_contig<short>(tif,samplesperpixel,nx,ny);
39502 if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_contig<unsigned int>(tif,samplesperpixel,nx,ny);
39503 else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_contig<int>(tif,samplesperpixel,nx,ny);
39504 else _load_tiff_contig<float>(tif,samplesperpixel,nx,ny);
39506 }
else switch (bitspersample) {
39508 if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate<unsigned char>(tif,samplesperpixel,nx,ny);
39509 else _load_tiff_separate<signed char>(tif,samplesperpixel,nx,ny);
39512 if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate<unsigned short>(tif,samplesperpixel,nx,ny);
39513 else _load_tiff_separate<short>(tif,samplesperpixel,nx,ny);
39516 if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate<unsigned int>(tif,samplesperpixel,nx,ny);
39517 else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_separate<int>(tif,samplesperpixel,nx,ny);
39518 else _load_tiff_separate<float>(tif,samplesperpixel,nx,ny);
39535 "load_minc2(): Specified filename is (null).",
39537 #ifndef cimg_use_minc2
39540 minc::minc_1_reader rdr;
39541 rdr.open(filename);
39542 assign(rdr.ndim(1)?rdr.ndim(1):1,
39543 rdr.ndim(2)?rdr.ndim(2):1,
39544 rdr.ndim(3)?rdr.ndim(3):1,
39545 rdr.ndim(4)?rdr.ndim(4):1);
39546 if(
typeid(T)==
typeid(
unsigned char))
39547 rdr.setup_read_byte();
39548 else if(
typeid(T)==
typeid(
int))
39549 rdr.setup_read_int();
39550 else if(
typeid(T)==
typeid(
double))
39551 rdr.setup_read_double();
39553 rdr.setup_read_float();
39554 minc::load_standard_volume(rdr, this->_data);
39570 return _load_analyze(0,filename,voxel_size);
39580 return _load_analyze(file,0,voxel_size);
39588 CImg<T>& _load_analyze(std::FILE *
const file,
const char *
const filename,
float *
const voxel_size=0) {
39589 if (!file && !filename)
39591 "load_analyze(): Specified filename is (null).",
39594 std::FILE *nfile_header = 0, *nfile = 0;
39596 char body[1024] = { 0 };
39600 std::sprintf(body + std::strlen(body),
".img");
39604 std::sprintf(body + std::strlen(body),
".hdr");
39606 }
else nfile_header = nfile =
cimg::fopen(filename,
"rb");
39607 }
else nfile_header = nfile = file;
39608 if (!nfile || !nfile_header)
39609 throw CImgIOException(_cimg_instance
39610 "load_analyze(): Invalid Analyze7.5 or NIFTI header in file '%s'.",
39612 filename?filename:
"(FILE*)");
39615 bool endian =
false;
39616 unsigned int header_size;
39619 throw CImgIOException(_cimg_instance
39620 "load_analyze(): Invalid zero-sized header in file '%s'.",
39622 filename?filename:
"(FILE*)");
39625 unsigned char *
const header =
new unsigned char[header_size];
39626 cimg::fread(header+4,header_size-4,nfile_header);
39627 if (!file && nfile_header!=nfile)
cimg::fclose(nfile_header);
39635 unsigned short *dim = (
unsigned short*)(header+40), dimx = 1, dimy = 1, dimz = 1, dimv = 1;
39638 "load_analyze(): File '%s' defines an image with zero dimensions.",
39640 filename?filename:
"(FILE*)");
39644 "load_analyze(): File '%s' defines an image with %u dimensions, reading only the 4 first.",
39646 filename?filename:
"(FILE*)",dim[0]);
39648 if (dim[0]>=1) dimx = dim[1];
39649 if (dim[0]>=2) dimy = dim[2];
39650 if (dim[0]>=3) dimz = dim[3];
39651 if (dim[0]>=4) dimv = dim[4];
39652 float scalefactor = *(
float*)(header+112);
if (scalefactor==0) scalefactor=1;
39653 const unsigned short datatype = *(
short*)(header+70);
39655 const float *vsize = (
float*)(header+76);
39656 voxel_size[0] = vsize[1]; voxel_size[1] = vsize[2]; voxel_size[2] = vsize[3];
39661 assign(dimx,dimy,dimz,dimv);
39662 switch (datatype) {
39664 unsigned char *
const buffer =
new unsigned char[dimx*dimy*dimz*dimv];
39666 cimg_foroff(*
this,off) _data[off] = (T)(buffer[off]*scalefactor);
39670 short *
const buffer =
new short[dimx*dimy*dimz*dimv];
39673 cimg_foroff(*
this,off) _data[off] = (T)(buffer[off]*scalefactor);
39677 int *
const buffer =
new int[dimx*dimy*dimz*dimv];
39680 cimg_foroff(*
this,off) _data[off] = (T)(buffer[off]*scalefactor);
39684 float *
const buffer =
new float[dimx*dimy*dimz*dimv];
39687 cimg_foroff(*
this,off) _data[off] = (T)(buffer[off]*scalefactor);
39691 double *
const buffer =
new double[dimx*dimy*dimz*dimv];
39694 cimg_foroff(*
this,off) _data[off] = (T)(buffer[off]*scalefactor);
39698 if (!file) cimg::fclose(nfile);
39699 throw CImgIOException(_cimg_instance
39702 datatype,filename?filename:"(FILE*)");
39704 if (!file) cimg::fclose(nfile);
39714 CImg<T>&
load_cimg(const
char *const filename, const
char axis='z', const
float align=0) {
39717 if (list._width==1)
return list[0].
move_to(*
this);
39730 if (list._width==1)
return list[0].
move_to(*
this);
39756 const unsigned int n0,
const unsigned int n1,
39757 const unsigned int x0,
const unsigned int y0,
39758 const unsigned int z0,
const unsigned int c0,
39759 const unsigned int x1,
const unsigned int y1,
39760 const unsigned int z1,
const unsigned int c1,
39761 const char axis=
'z',
const float align=0) {
39763 list.
load_cimg(filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1);
39764 if (list._width==1)
return list[0].
move_to(*
this);
39770 const unsigned int n0,
const unsigned int n1,
39771 const unsigned int x0,
const unsigned int y0,
39772 const unsigned int z0,
const unsigned int c0,
39773 const unsigned int x1,
const unsigned int y1,
39774 const unsigned int z1,
const unsigned int c1,
39775 const char axis=
'z',
const float align=0) {
39776 return CImg<T>().
load_cimg(filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1,axis,align);
39781 const unsigned int n0,
const unsigned int n1,
39782 const unsigned int x0,
const unsigned int y0,
39783 const unsigned int z0,
const unsigned int c0,
39784 const unsigned int x1,
const unsigned int y1,
39785 const unsigned int z1,
const unsigned int c1,
39786 const char axis=
'z',
const float align=0) {
39788 list.
load_cimg(file,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1);
39789 if (list._width==1)
return list[0].
move_to(*
this);
39795 const unsigned int n0,
const unsigned int n1,
39796 const unsigned int x0,
const unsigned int y0,
39797 const unsigned int z0,
const unsigned int c0,
39798 const unsigned int x1,
const unsigned int y1,
39799 const unsigned int z1,
const unsigned int c1,
39800 const char axis=
'z',
const float align=0) {
39801 return CImg<T>().
load_cimg(file,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1,axis,align);
39810 return _load_inr(0,filename,voxel_size);
39820 return _load_inr(file,0,voxel_size);
39828 static void _load_inr_header(std::FILE *file,
int out[8],
float *
const voxel_size) {
39829 char item[1024] = { 0 }, tmp1[64] = { 0 }, tmp2[64] = { 0 };
39830 out[0] = std::fscanf(file,
"%63s",item);
39831 out[0] = out[1] = out[2] = out[3] = out[5] = 1; out[4] = out[6] = out[7] = -1;
39833 throw CImgIOException(
"CImg<%s>::load_inr(): INRIMAGE-4 header not found.",
39836 while (std::fscanf(file,
" %63[^\n]%*c",item)!=EOF && std::strncmp(item,
"##}",3)) {
39837 std::sscanf(item,
" XDIM%*[^0-9]%d",out);
39838 std::sscanf(item,
" YDIM%*[^0-9]%d",out+1);
39839 std::sscanf(item,
" ZDIM%*[^0-9]%d",out+2);
39840 std::sscanf(item,
" VDIM%*[^0-9]%d",out+3);
39841 std::sscanf(item,
" PIXSIZE%*[^0-9]%d",out+6);
39843 std::sscanf(item,
" VX%*[^0-9.+-]%f",voxel_size);
39844 std::sscanf(item,
" VY%*[^0-9.+-]%f",voxel_size+1);
39845 std::sscanf(item,
" VZ%*[^0-9.+-]%f",voxel_size+2);
39847 if (std::sscanf(item,
" CPU%*[ =]%s",tmp1)) out[7]=
cimg::strncasecmp(tmp1,
"sun",3)?0:1;
39848 switch (std::sscanf(item,
" TYPE%*[ =]%s %s",tmp1,tmp2)) {
39850 case 2 : out[5] =
cimg::strncasecmp(tmp1,
"unsigned",8)?1:0; std::strncpy(tmp1,tmp2,
sizeof(tmp1)-1);
39855 if (out[4]>=0)
break;
39857 throw CImgIOException(
"CImg<%s>::load_inr(): Invalid pixel type '%s' defined in header.",
39862 if(out[0]<0 || out[1]<0 || out[2]<0 || out[3]<0)
39863 throw CImgIOException(
"CImg<%s>::load_inr(): Invalid dimensions (%d,%d,%d,%d) defined in header.",
39865 out[0],out[1],out[2],out[3]);
39866 if(out[4]<0 || out[5]<0)
39867 throw CImgIOException(
"CImg<%s>::load_inr(): Incomplete pixel type defined in header.",
39870 throw CImgIOException(
"CImg<%s>::load_inr(): Incomplete PIXSIZE field defined in header.",
39873 throw CImgIOException(
"CImg<%s>::load_inr(): Big/Little Endian coding type undefined in header.",
39877 CImg<T>& _load_inr(std::FILE *
const file,
const char *
const filename,
float *
const voxel_size) {
39878 #define _cimg_load_inr_case(Tf,sign,pixsize,Ts) \
39879 if (!loaded && fopt[6]==pixsize && fopt[4]==Tf && fopt[5]==sign) { \
39880 Ts *xval, *const val = new Ts[fopt[0]*fopt[3]]; \
39881 cimg_forYZ(*this,y,z) { \
39882 cimg::fread(val,fopt[0]*fopt[3],nfile); \
39883 if (fopt[7]!=endian) cimg::invert_endianness(val,fopt[0]*fopt[3]); \
39884 xval = val; cimg_forX(*this,x) cimg_forC(*this,c) (*this)(x,y,z,c) = (T)*(xval++); \
39890 if (!file && !filename)
39891 throw CImgArgumentException(_cimg_instance
39892 "load_inr(): Specified filename is (null).",
39895 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"rb");
39897 bool loaded =
false;
39898 if (voxel_size) voxel_size[0] = voxel_size[1] = voxel_size[2] = 1;
39899 _load_inr_header(nfile,fopt,voxel_size);
39900 assign(fopt[0],fopt[1],fopt[2],fopt[3]);
39901 _cimg_load_inr_case(0,0,8,
unsigned char);
39902 _cimg_load_inr_case(0,1,8,
char);
39903 _cimg_load_inr_case(0,0,16,
unsigned short);
39904 _cimg_load_inr_case(0,1,16,
short);
39905 _cimg_load_inr_case(0,0,32,
unsigned int);
39906 _cimg_load_inr_case(0,1,32,
int);
39907 _cimg_load_inr_case(1,0,32,
float);
39908 _cimg_load_inr_case(1,1,32,
float);
39909 _cimg_load_inr_case(1,0,64,
double);
39910 _cimg_load_inr_case(1,1,64,
double);
39913 throw CImgIOException(_cimg_instance
39914 "load_inr(): Unknown pixel type defined in file '%s'.",
39916 filename?filename:
"(FILE*)");
39929 "load_exr(): Specified filename is (null).",
39932 #ifndef cimg_use_openexr
39935 Imf::RgbaInputFile file(filename);
39936 Imath::Box2i dw = file.dataWindow();
39938 inwidth = dw.max.x - dw.min.x + 1,
39939 inheight = dw.max.y - dw.min.y + 1;
39940 Imf::Array2D<Imf::Rgba> pixels;
39941 pixels.resizeErase(inheight,inwidth);
39942 file.setFrameBuffer(&pixels[0][0] - dw.min.x - dw.min.y*inwidth, 1, inwidth);
39943 file.readPixels(dw.min.y, dw.max.y);
39944 assign(inwidth,inheight,1,4);
39945 T *ptr_r =
data(0,0,0,0), *ptr_g =
data(0,0,0,1), *ptr_b =
data(0,0,0,2), *ptr_a =
data(0,0,0,3);
39946 cimg_forXY(*
this,x,y) {
39947 *(ptr_r++) = (T)pixels[y][x].r;
39948 *(ptr_g++) = (T)pixels[y][x].g;
39949 *(ptr_b++) = (T)pixels[y][x].b;
39950 *(ptr_a++) = (T)pixels[y][x].a;
39966 return _load_pandore(0,filename);
39976 return _load_pandore(file,0);
39984 CImg<T>& _load_pandore(std::FILE *
const file,
const char *
const filename) {
39985 #define __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,ndim,stype) \
39986 cimg::fread(dims,nbdim,nfile); \
39987 if (endian) cimg::invert_endianness(dims,nbdim); \
39988 assign(nwidth,nheight,ndepth,ndim); \
39989 const unsigned int siz = size(); \
39990 stype *buffer = new stype[siz]; \
39991 cimg::fread(buffer,siz,nfile); \
39992 if (endian) cimg::invert_endianness(buffer,siz); \
39994 cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); \
39998 #define _cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype1,stype2,stype3,ltype) { \
39999 if (sizeof(stype1)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype1); } \
40000 else if (sizeof(stype2)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype2); } \
40001 else if (sizeof(stype3)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype3); } \
40002 else throw CImgIOException(_cimg_instance \
40003 "load_pandore(): Unknown pixel datatype in file '%s'.", \
40005 filename?filename:"(FILE*)"); }
40007 if (!file && !filename)
40009 "load_pandore(): Specified filename is (null).",
40012 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"rb");
40013 char header[32] = { 0 };
40017 throw CImgIOException(_cimg_instance
40018 "load_pandore(): PANDORE header not found in file '%s'.",
40020 filename?filename:
"(FILE*)");
40022 unsigned int imageid, dims[8] = { 0 };
40024 const bool endian = (imageid>255);
40029 case 2: _cimg_load_pandore_case(2,dims[1],1,1,1,
unsigned char,
unsigned char,
unsigned char,1);
break;
40030 case 3: _cimg_load_pandore_case(2,dims[1],1,1,1,
long,
int,
short,4);
break;
40031 case 4: _cimg_load_pandore_case(2,dims[1],1,1,1,
double,
float,
float,4);
break;
40032 case 5: _cimg_load_pandore_case(3,dims[2],dims[1],1,1,
unsigned char,
unsigned char,
unsigned char,1);
break;
40033 case 6: _cimg_load_pandore_case(3,dims[2],dims[1],1,1,
long,
int,
short,4);
break;
40034 case 7: _cimg_load_pandore_case(3,dims[2],dims[1],1,1,
double,
float,
float,4);
break;
40035 case 8: _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,
unsigned char,
unsigned char,
unsigned char,1);
break;
40036 case 9: _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,
long,
int,
short,4);
break;
40037 case 10: _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,
double,
float,
float,4);
break;
40042 const unsigned siz =
size();
40044 unsigned char *buffer =
new unsigned char[siz];
40047 cimg_foroff(*
this,off) *(ptrd++) = (T)*(buffer++);
40051 if (dims[2]<65536) {
40052 unsigned short *buffer =
new unsigned short[siz];
40056 cimg_foroff(*
this,off) *(ptrd++) = (T)*(buffer++);
40060 unsigned int *buffer =
new unsigned int[siz];
40064 cimg_foroff(*
this,off) *(ptrd++) = (T)*(buffer++);
40074 assign(dims[2],dims[1],1,1);
40075 const unsigned int siz =
size();
40077 unsigned char *buffer =
new unsigned char[siz];
40080 cimg_foroff(*
this,off) *(ptrd++) = (T)*(buffer++);
40084 if (dims[3]<65536) {
40085 unsigned short *buffer =
new unsigned short[siz];
40089 cimg_foroff(*
this,off) *(ptrd++) = (T)*(buffer++);
40093 unsigned long *buffer =
new unsigned long[siz];
40097 cimg_foroff(*
this,off) *(ptrd++) = (T)*(buffer++);
40107 assign(dims[3],dims[2],dims[1],1);
40108 const unsigned int siz =
size();
40110 unsigned char *buffer =
new unsigned char[siz];
40113 cimg_foroff(*
this,off) *(ptrd++) = (T)*(buffer++);
40117 if (dims[4]<65536) {
40118 unsigned short *buffer =
new unsigned short[siz];
40122 cimg_foroff(*
this,off) *(ptrd++) = (T)*(buffer++);
40126 unsigned int *buffer =
new unsigned int[siz];
40130 cimg_foroff(*
this,off) *(ptrd++) = (T)*(buffer++);
40137 case 16: _cimg_load_pandore_case(4,dims[2],dims[1],1,3,
unsigned char,
unsigned char,
unsigned char,1);
break;
40138 case 17: _cimg_load_pandore_case(4,dims[2],dims[1],1,3,
long,
int,
short,4);
break;
40139 case 18: _cimg_load_pandore_case(4,dims[2],dims[1],1,3,
double,
float,
float,4);
break;
40140 case 19: _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,
unsigned char,
unsigned char,
unsigned char,1);
break;
40141 case 20: _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,
long,
int,
short,4);
break;
40142 case 21: _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,
double,
float,
float,4);
break;
40143 case 22: _cimg_load_pandore_case(2,dims[1],1,1,dims[0],
unsigned char,
unsigned char,
unsigned char,1);
break;
40144 case 23: _cimg_load_pandore_case(2,dims[1],1,1,dims[0],
long,
int,
short,4);
40145 case 24: _cimg_load_pandore_case(2,dims[1],1,1,dims[0],
unsigned long,
unsigned int,
unsigned short,4);
break;
40146 case 25: _cimg_load_pandore_case(2,dims[1],1,1,dims[0],
double,
float,
float,4);
break;
40147 case 26: _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],
unsigned char,
unsigned char,
unsigned char,1);
break;
40148 case 27: _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],
long,
int,
short,4);
break;
40149 case 28: _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],
unsigned long,
unsigned int,
unsigned short,4);
break;
40150 case 29: _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],
double,
float,
float,4);
break;
40151 case 30: _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],
unsigned char,
unsigned char,
unsigned char,1);
40153 case 31: _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],
long,
int,
short,4);
break;
40154 case 32: _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],
unsigned long,
unsigned int,
unsigned short,4);
40156 case 33: _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],
double,
float,
float,4);
break;
40158 int ptbuf[4] = { 0 };
40161 assign(1); (*this)(0) = (T)ptbuf[0];
40164 int ptbuf[4] = { 0 };
40167 assign(2); (*this)(0) = (T)ptbuf[1]; (*this)(1) = (T)ptbuf[0];
40170 int ptbuf[4] = { 0 };
40173 assign(3); (*this)(0) = (T)ptbuf[2]; (*this)(1) = (T)ptbuf[1]; (*this)(2) = (T)ptbuf[0];
40176 if (!file) cimg::fclose(nfile);
40177 throw CImgIOException(_cimg_instance
40180 imageid,filename?filename:"(FILE*)");
40182 if (!file) cimg::fclose(nfile);
40195 if (list._width==1)
return list[0].
move_to(*
this);
40216 const unsigned int size_x=0,
const unsigned int size_y=1,
40217 const unsigned int size_z=1,
const unsigned int size_c=1,
40219 const unsigned long offset=0) {
40220 return _load_raw(0,filename,size_x,size_y,size_z,size_c,is_multiplexed,
invert_endianness,offset);
40225 const unsigned int size_x=0,
const unsigned int size_y=1,
40226 const unsigned int size_z=1,
const unsigned int size_c=1,
40228 const unsigned long offset=0) {
40234 const unsigned int size_x=0,
const unsigned int size_y=1,
40235 const unsigned int size_z=1,
const unsigned int size_c=1,
40237 const unsigned long offset=0) {
40238 return _load_raw(file,0,size_x,size_y,size_z,size_c,is_multiplexed,
invert_endianness,offset);
40243 const unsigned int size_x=0,
const unsigned int size_y=1,
40244 const unsigned int size_z=1,
const unsigned int size_c=1,
40246 const unsigned long offset=0) {
40250 CImg<T>& _load_raw(std::FILE *
const file,
const char *
const filename,
40251 const unsigned int size_x,
const unsigned int size_y,
40252 const unsigned int size_z,
const unsigned int size_c,
40254 const unsigned long offset) {
40255 if (!file && !filename)
40257 "load_raw(): Specified filename is (null).",
40259 unsigned int siz = size_x*size_y*size_z*size_c,
40260 _size_x = size_x, _size_y = size_y, _size_z = size_z, _size_c = size_c;
40261 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"rb");
40263 const long fpos = std::ftell(nfile);
40265 "load_raw(): Cannot determine size of input file '%s'.",
40266 cimg_instance,filename?filename:
"(FILE*)");
40267 std::fseek(nfile,0,SEEK_END);
40268 siz = _size_y = (
unsigned int)std::ftell(nfile)/
sizeof(T);
40269 _size_x = _size_z = _size_c = 1;
40270 std::fseek(nfile,fpos,SEEK_SET);
40272 std::fseek(nfile,(
long)offset,SEEK_SET);
40273 assign(_size_x,_size_y,_size_z,_size_c,0);
40274 if (!is_multiplexed || size_c==1) {
40278 CImg<T> buf(1,1,1,_size_c);
40279 cimg_forXYZ(*
this,x,y,z) {
40301 const unsigned int first_frame=0,
const unsigned int last_frame=~0U,
40302 const unsigned int step_frame=1,
const bool pixel_format=
true,
const bool resume=
false,
40303 const char axis=
'z',
const float align=0) {
40304 return get_load_ffmpeg(filename,first_frame,last_frame,step_frame,pixel_format,resume,axis,align).move_to(*
this);
40309 const unsigned int first_frame=0,
const unsigned int last_frame=~0U,
40310 const unsigned int step_frame=1,
const bool pixel_format=
true,
40311 const bool resume=
false,
40312 const char axis=
'z',
const float align=0) {
40329 const unsigned int size_x,
const unsigned int size_y=1,
40330 const unsigned int first_frame=0,
const unsigned int last_frame=~0U,
40331 const unsigned int step_frame=1,
const bool yuv2rgb=
true,
const char axis=
'z') {
40332 return get_load_yuv(filename,size_x,size_y,first_frame,last_frame,step_frame,yuv2rgb,axis).move_to(*
this);
40337 const unsigned int size_x,
const unsigned int size_y=1,
40338 const unsigned int first_frame=0,
const unsigned int last_frame=~0U,
40339 const unsigned int step_frame=1,
const bool yuv2rgb=
true,
const char axis=
'z') {
40340 return CImgList<T>().
load_yuv(filename,size_x,size_y,first_frame,last_frame,step_frame,yuv2rgb).get_append(axis);
40345 const unsigned int size_x,
const unsigned int size_y=1,
40346 const unsigned int first_frame=0,
const unsigned int last_frame=~0U,
40347 const unsigned int step_frame=1,
const bool yuv2rgb=
true,
const char axis=
'z') {
40348 return get_load_yuv(file,size_x,size_y,first_frame,last_frame,step_frame,yuv2rgb,axis).move_to(*
this);
40353 const unsigned int size_x,
const unsigned int size_y=1,
40354 const unsigned int first_frame=0,
const unsigned int last_frame=~0U,
40355 const unsigned int step_frame=1,
const bool yuv2rgb=
true,
const char axis=
'z') {
40356 return CImgList<T>().
load_yuv(file,size_x,size_y,first_frame,last_frame,step_frame,yuv2rgb).get_append(axis);
40365 template<
typename tf,
typename tc>
40367 return _load_off(primitives,colors,0,filename);
40371 template<
typename tf,
typename tc>
40377 template<
typename tf,
typename tc>
40379 return _load_off(primitives,colors,file,0);
40383 template<
typename tf,
typename tc>
40388 template<
typename tf,
typename tc>
40390 std::FILE *
const file,
const char *
const filename) {
40391 if (!file && !filename)
40393 "load_off(): Specified filename is (null).",
40396 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"r");
40397 unsigned int nb_points = 0, nb_primitives = 0, nb_read = 0;
40398 char line[256] = { 0 };
40402 do { err = std::fscanf(nfile,
"%255[^\n] ",line); }
while (!err || (err==1 && *line==
'#'));
40405 throw CImgIOException(_cimg_instance
40406 "load_off(): OFF header not found in file '%s'.",
40408 filename?filename:
"(FILE*)");
40410 do { err = std::fscanf(nfile,
"%255[^\n] ",line); }
while (!err || (err==1 && *line==
'#'));
40411 if ((err = std::sscanf(line,
"%u%u%*[^\n] ",&nb_points,&nb_primitives))!=2) {
40413 throw CImgIOException(_cimg_instance
40414 "load_off(): Invalid number of vertices or primitives specified in file '%s'.",
40416 filename?filename:
"(FILE*)");
40421 float X = 0, Y = 0, Z = 0;
40422 cimg_forX(*
this,l) {
40423 do { err = std::fscanf(nfile,
"%255[^\n] ",line); }
while (!err || (err==1 && *line==
'#'));
40424 if ((err = std::sscanf(line,
"%f%f%f%*[^\n] ",&X,&Y,&Z))!=3) {
40426 throw CImgIOException(_cimg_instance
40427 "load_off(): Failed to read vertex %u/%u in file '%s'.",
40429 l+1,nb_points,filename?filename:
"(FILE*)");
40431 (*this)(l,0) = (T)X; (*this)(l,1) = (T)Y; (*this)(l,2) = (T)Z;
40437 bool stop_flag = false;
40438 while (!stop_flag) {
40439 float c0 = 0.7f, c1 = 0.7f, c2 = 0.7f;
40440 unsigned int prim = 0, i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, i6 = 0, i7 = 0;
40442 if ((err = std::fscanf(nfile,
"%u",&prim))!=1) stop_flag =
true;
40447 if ((err = std::fscanf(nfile,
"%u%255[^\n] ",&i0,line))<2) {
40449 "load_off(): Failed to read primitive %u/%u from file '%s'.",
40451 nb_read,nb_primitives,filename?filename:
"(FILE*)");
40453 err = std::fscanf(nfile,
"%*[^\n] ");
40455 err = std::sscanf(line,
"%f%f%f",&c0,&c1,&c2);
40461 if ((err = std::fscanf(nfile,
"%u%u%255[^\n] ",&i0,&i1,line))<2) {
40463 "load_off(): Failed to read primitive %u/%u from file '%s'.",
40465 nb_read,nb_primitives,filename?filename:
"(FILE*)");
40467 err = std::fscanf(nfile,
"%*[^\n] ");
40469 err = std::sscanf(line,
"%f%f%f",&c0,&c1,&c2);
40475 if ((err = std::fscanf(nfile,
"%u%u%u%255[^\n] ",&i0,&i1,&i2,line))<3) {
40477 "load_off(): Failed to read primitive %u/%u from file '%s'.",
40479 nb_read,nb_primitives,filename?filename:
"(FILE*)");
40481 err = std::fscanf(nfile,
"%*[^\n] ");
40483 err = std::sscanf(line,
"%f%f%f",&c0,&c1,&c2);
40489 if ((err = std::fscanf(nfile,
"%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,line))<4) {
40491 "load_off(): Failed to read primitive %u/%u from file '%s'.",
40493 nb_read,nb_primitives,filename?filename:
"(FILE*)");
40495 err = std::fscanf(nfile,
"%*[^\n] ");
40497 err = std::sscanf(line,
"%f%f%f",&c0,&c1,&c2);
40503 if ((err = std::fscanf(nfile,
"%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,line))<5) {
40505 "load_off(): Failed to read primitive %u/%u from file '%s'.",
40507 nb_read,nb_primitives,filename?filename:
"(FILE*)");
40509 err = std::fscanf(nfile,
"%*[^\n] ");
40511 err = std::sscanf(line,
"%f%f%f",&c0,&c1,&c2);
40514 colors.
insert(2,CImg<tc>::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)));
40519 if ((err = std::fscanf(nfile,
"%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,line))<6) {
40521 "load_off(): Failed to read primitive %u/%u from file '%s'.",
40523 nb_read,nb_primitives,filename?filename:
"(FILE*)");
40525 err = std::fscanf(nfile,
"%*[^\n] ");
40527 err = std::sscanf(line,
"%f%f%f",&c0,&c1,&c2);
40530 colors.
insert(2,CImg<tc>::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)));
40535 if ((err = std::fscanf(nfile,
"%u%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,&i6,line))<7) {
40537 "load_off(): Failed to read primitive %u/%u from file '%s'.",
40539 nb_read,nb_primitives,filename?filename:
"(FILE*)");
40541 err = std::fscanf(nfile,
"%*[^\n] ");
40543 err = std::sscanf(line,
"%f%f%f",&c0,&c1,&c2);
40547 colors.
insert(3,CImg<tc>::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)));
40548 ++(++nb_primitives);
40552 if ((err = std::fscanf(nfile,
"%u%u%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,&i6,&i7,line))<7) {
40554 "load_off(): Failed to read primitive %u/%u from file '%s'.",
40556 nb_read,nb_primitives,filename?filename:
"(FILE*)");
40558 err = std::fscanf(nfile,
"%*[^\n] ");
40560 err = std::sscanf(line,
"%f%f%f",&c0,&c1,&c2);
40564 colors.
insert(3,CImg<tc>::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)));
40565 ++(++nb_primitives);
40570 "load_off(): Failed to read primitive %u/%u (%u vertices) from file '%s'.",
40572 nb_read,nb_primitives,prim,filename?filename:
"(FILE*)");
40574 err = std::fscanf(nfile,
"%*[^\n] ");
40579 if (primitives._width!=nb_primitives)
40581 "load_off(): Only %u/%u primitives read from file '%s'.",
40583 primitives._width,nb_primitives,filename?filename:
"(FILE*)");
40610 const char axis=
'z',
const float align=0) {
40616 const char axis=
'z',
const float align=0) {
40627 "load_graphicsmagick_external(): Specified filename is (null).",
40630 char command[1024] = { 0 }, filetmp[512] = { 0 };
40631 std::FILE *file = 0;
40634 cimg_snprintf(command,
sizeof(command),
"%s convert \"%s\" pnm:-",
40636 file = popen(command,
"r");
40640 try {
load_pnm(file); }
catch (...) {
40644 "load_graphicsmagick_external(): Failed to load file '%s' with external command 'gm'.",
40653 cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s.pnm",
40655 if ((file=std::fopen(filetmp,
"rb"))!=0)
cimg::fclose(file);
40657 cimg_snprintf(command,
sizeof(command),
"%s convert \"%s\" \"%s\"",
40661 if (!(file = std::fopen(filetmp,
"rb"))) {
40664 "load_graphicsmagick_external(): Failed to load file '%s' with external command 'gm'.",
40670 std::remove(filetmp);
40686 "load_gzip_external(): Specified filename is (null).",
40689 char command[1024] = { 0 }, filetmp[512] = { 0 }, body[512] = { 0 };
40694 std::FILE *file = 0;
40697 if (*ext2) cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s.%s",
40699 else cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s",
40702 if (*ext) cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s.%s",
40704 else cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s",
40707 if ((file=std::fopen(filetmp,
"rb"))!=0)
cimg::fclose(file);
40709 cimg_snprintf(command,
sizeof(command),
"%s -c \"%s\" > \"%s\"",
40714 if (!(file = std::fopen(filetmp,
"rb"))) {
40717 "load_gzip_external(): Failed to load file '%s' with external command 'gunzip'.",
40723 std::remove(filetmp);
40739 "load_imagemagick_external(): Specified filename is (null).",
40742 char command[1024] = { 0 }, filetmp[512] = { 0 };
40743 std::FILE *file = 0;
40746 cimg_snprintf(command,
sizeof(command),
"%s%s \"%s\" pnm:-",
40749 s_filename.
data());
40750 file = popen(command,
"r");
40754 try {
load_pnm(file); }
catch (...) {
40758 "load_imagemagick_external(): Failed to load file '%s' with "
40759 "external command 'convert'.",
40768 cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s.pnm",
40770 if ((file=std::fopen(filetmp,
"rb"))!=0)
cimg::fclose(file);
40772 cimg_snprintf(command,
sizeof(command),
"%s%s \"%s\" \"%s\"",
40777 if (!(file = std::fopen(filetmp,
"rb"))) {
40780 "load_imagemagick_external(): Failed to load file '%s' with external command 'convert'.",
40786 std::remove(filetmp);
40802 "load_medcon_external(): Specified filename is (null).",
40805 char command[1024] = { 0 }, filetmp[512] = { 0 }, body[512] = { 0 };
40807 std::FILE *file = 0;
40809 cimg_snprintf(filetmp,
sizeof(filetmp),
"%s.hdr",cimg::filenamerand());
40810 if ((file=std::fopen(filetmp,
"rb"))!=0)
cimg::fclose(file);
40812 cimg_snprintf(command,
sizeof(command),
"%s -w -c anlz -o \"%s\" -f \"%s\"",
40819 cimg_snprintf(command,
sizeof(command),
"%s.hdr",body);
40820 file = std::fopen(command,
"rb");
40822 cimg_snprintf(command,
sizeof(command),
"m000-%s.hdr",body);
40823 file = std::fopen(command,
"rb");
40826 "load_medcon_external(): Failed to load file '%s' with external command 'medcon'.",
40833 std::remove(command);
40835 cimg_snprintf(command,
sizeof(command),
"%s.img",body);
40836 std::remove(command);
40852 "load_dcraw_external(): Specified filename is (null).",
40855 char command[1024] = { 0 }, filetmp[512] = { 0 };
40856 std::FILE *file = 0;
40859 cimg_snprintf(command,
sizeof(command),
"%s -w -4 -c \"%s\"",
40861 file = popen(command,
"r");
40865 try {
load_pnm(file); }
catch (...) {
40869 "load_dcraw_external(): Failed to load file '%s' with external command 'dcraw'.",
40878 cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s.ppm",
40880 if ((file=std::fopen(filetmp,
"rb"))!=0)
cimg::fclose(file);
40882 cimg_snprintf(command,
sizeof(command),
"%s -w -4 -c \"%s\" > \"%s\"",
40885 if (!(file = std::fopen(filetmp,
"rb"))) {
40888 "load_dcraw_external(): Failed to load file '%s' with external command 'dcraw'.",
40894 std::remove(filetmp);
40910 const bool release_camera=
true,
const unsigned int capture_width=0,
40911 const unsigned int capture_height=0) {
40912 #ifdef cimg_use_opencv
40913 if (camera_index>255)
40915 "load_camera(): Invalid request for camera #%u "
40916 "(no more than 256 cameras can be managed).",
40919 static CvCapture *capture[256] = { 0 };
40920 if (release_camera) {
40921 if (capture[camera_index]) cvReleaseCapture(&(capture[camera_index]));
40922 capture[camera_index] = 0;
40925 if (!capture[camera_index]) {
40926 capture[camera_index] = cvCreateCameraCapture(camera_index);
40927 if (!capture[camera_index]) {
40929 "load_camera(): Failed to initialize camera #%u.",
40934 if (capture_width) cvSetCaptureProperty(capture[camera_index],CV_CAP_PROP_FRAME_WIDTH,capture_width);
40935 if (capture_height) cvSetCaptureProperty(capture[camera_index],CV_CAP_PROP_FRAME_HEIGHT,capture_height);
40936 const IplImage *img = 0;
40937 for (
unsigned int i = 0; i<skip_frames; ++i) img = cvQueryFrame(capture[camera_index]);
40938 img = cvQueryFrame(capture[camera_index]);
40940 const int step = (int)(img->widthStep - 3*img->width);
40941 assign(img->width,img->height,1,3);
40942 const unsigned char* ptrs = (
unsigned char*)img->imageData;
40943 T *ptr_r =
data(0,0,0,0), *ptr_g =
data(0,0,0,1), *ptr_b =
data(0,0,0,2);
40944 if (step>0) cimg_forY(*
this,y) {
40945 cimg_forX(*
this,x) { *(ptr_b++) = (T)*(ptrs++); *(ptr_g++) = (T)*(ptrs++); *(ptr_r++) = (T)*(ptrs++); }
40947 }
else for (
unsigned long siz = (
unsigned long)img->width*img->height; siz; --siz) {
40948 *(ptr_b++) = (T)*(ptrs++); *(ptr_g++) = (T)*(ptrs++); *(ptr_r++) = (T)*(ptrs++);
40953 cimg::unused(camera_index,skip_frames,release_camera,capture_width,capture_height);
40955 "load_camera(): This function requires the OpenCV library to run "
40956 "(macro 'cimg_use_opencv' must be defined).",
40963 const bool release_camera=
true,
40964 const unsigned int capture_width=0,
const unsigned int capture_height=0) {
40965 return CImg<T>().
load_camera(camera_index,skip_frames,release_camera,capture_width,capture_height);
40975 "load_other(): Specified filename is (null).",
40993 "load_other(): Failed to open file '%s'.",
40999 "load_other(): Failed to recognize format of file '%s'.",
41027 const CImg<T>&
print(
const char *
const title=0,
const bool display_stats=
true)
const {
41028 int xm = 0, ym = 0, zm = 0, vm = 0, xM = 0, yM = 0, zM = 0, vM = 0;
41030 if (!
is_empty() && display_stats) {
41032 xm = (int)st[4]; ym = (int)st[5], zm = (
int)st[6], vm = (int)st[7];
41033 xM = (int)st[8]; yM = (int)st[9], zM = (
int)st[10], vM = (int)st[11];
41035 const unsigned long siz =
size(), msiz = siz*
sizeof(T), siz1 = siz-1,
41036 mdisp = msiz<8*1024?0:(msiz<8*1024*1024?1:2), width1 = _width-1;
41038 char _title[64] = { 0 };
41039 if (!title) cimg_snprintf(_title,
sizeof(_title),
"CImg<%s>",
pixel_type());
41041 std::fprintf(
cimg::output(),
"%s%s%s%s: %sthis%s = %p, %ssize%s = (%u,%u,%u,%u) [%lu %s], %sdata%s = (%s*)%p",
41042 cimg::t_magenta,cimg::t_bold,title?title:_title,cimg::t_normal,
41043 cimg::t_bold,cimg::t_normal,(
void*)
this,
41044 cimg::t_bold,cimg::t_normal,_width,_height,_depth,_spectrum,
41045 mdisp==0?msiz:(mdisp==1?(msiz>>10):(msiz>>20)),
41046 mdisp==0?
"b":(mdisp==1?
"Kio":
"Mio"),
41048 if (_data) std::fprintf(
cimg::output(),
"..%p (%s) = [ ",(
void*)((
char*)
end()-1),_is_shared?
"shared":
"non-shared");
41049 else std::fprintf(
cimg::output(),
" (%s) = [ ",_is_shared?
"shared":
"non-shared");
41051 if (!
is_empty()) cimg_foroff(*
this,off) {
41053 if (off!=siz1) std::fprintf(
cimg::output(),
"%s",off%_width==width1?
" ; ":
" ");
41054 if (off==7 && siz>16) { off = siz1-8; std::fprintf(
cimg::output(),
"... "); }
41058 " ], %smin%s = %g, %smax%s = %g, %smean%s = %g, %sstd%s = %g, %scoords_min%s = (%u,%u,%u,%u), "
41059 "%scoords_max%s = (%u,%u,%u,%u).\n",
41060 cimg::t_bold,cimg::t_normal,st[0],
41061 cimg::t_bold,cimg::t_normal,st[1],
41062 cimg::t_bold,cimg::t_normal,st[2],
41063 cimg::t_bold,cimg::t_normal,std::sqrt(st[3]),
41064 cimg::t_bold,cimg::t_normal,xm,ym,zm,vm,
41065 cimg::t_bold,cimg::t_normal,xM,yM,zM,vM);
41086 return _display(disp,0,display_info,XYZ,
false);
41094 const CImg<T>&
display(
const char *
const title=0,
const bool display_info=
true,
unsigned int *
const XYZ=0)
const {
41096 return _display(disp,title,display_info,XYZ,
false);
41100 const bool display_info,
unsigned int *
const XYZ,
41101 const bool exit_on_simpleclick)
const {
41102 unsigned int oldw = 0, oldh = 0, _XYZ[3] = { 0 }, key = 0;
41103 int x0 = 0, y0 = 0, z0 = 0, x1 =
width()-1, y1 =
height()-1, z1 =
depth()-1;
41106 disp.
assign(cimg_fitscreen(_width,_height,_depth),title?title:0,1);
41107 if (!title) disp.
set_title(
"CImg<%s> (%ux%ux%ux%u)",
pixel_type(),_width,_height,_depth,_spectrum);
41109 }
else if (title) disp.
set_title(
"%s",title);
41113 if (display_info)
print(dtitle);
41116 for (
bool reset_view =
true, resize_disp =
false, is_first_select =
true; !key && !disp.
is_closed(); ) {
41118 if (XYZ) { _XYZ[0] = XYZ[0]; _XYZ[1] = XYZ[1]; _XYZ[2] = XYZ[2]; }
41119 else { _XYZ[0] = (x0 + x1)/2; _XYZ[1] = (y0 + y1)/2; _XYZ[2] = (z0 + z1)/2; }
41122 reset_view =
false;
41124 if (!x0 && !y0 && !z0 && x1==
width()-1 && y1==
height()-1 && z1==
depth()-1) {
41125 if (
is_empty()) zoom.assign(1,1,1,1,0);
else zoom.assign();
41126 }
else zoom =
get_crop(x0,y0,z0,x1,y1,z1);
41129 dx = 1 + x1 - x0, dy = 1 + y1 - y0, dz = 1 + z1 - z0,
41130 tw = dx + (dz>1?dz:0), th = dy + (dz>1?dz:0);
41133 ttw = tw*disp.
width()/oldw, tth = th*disp.
height()/oldh,
41137 resize_disp =
false;
41139 oldw = tw; oldh = th;
41142 go_up =
false, go_down =
false, go_left =
false, go_right =
false,
41143 go_inc =
false, go_dec =
false, go_in =
false, go_out =
false,
41144 go_in_center =
false;
41145 const CImg<T>& visu = zoom?zoom:*
this;
41148 if (_width>1 && visu._width==1) disp.
set_title(
"%s | x=%u",disp._title,x0);
41149 if (_height>1 && visu._height==1) disp.
set_title(
"%s | y=%u",disp._title,y0);
41150 if (_depth>1 && visu._depth==1) disp.
set_title(
"%s | z=%u",disp._title,z0);
41152 if (!is_first_select) { _XYZ[0] = (x1-x0)/2; _XYZ[1] = (y1-y0)/2; _XYZ[2] = (z1-z0)/2; }
41153 const CImg<intT> selection = visu._get_select(disp,0,2,_XYZ,x0,y0,z0,is_first_select,_depth>1);
41154 is_first_select =
false;
41156 if (disp.
wheel()) {
41157 if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41158 go_out = !(go_in = disp.
wheel()>0); go_in_center =
false;
41159 }
else if (disp.is_keySHIFTLEFT() || disp.is_keySHIFTRIGHT()) { go_left = !(go_right = disp.
wheel()>0); }
41160 else if (disp.is_keyALT() || disp.is_keyALTGR() || _depth==1) { go_down = !(go_up = disp.
wheel()>0); }
41165 sx0 = selection(0), sy0 = selection(1), sz0 = selection(2),
41166 sx1 = selection(3), sy1 = selection(4), sz1 = selection(5);
41167 if (sx0>=0 && sy0>=0 && sz0>=0 && sx1>=0 && sy1>=0 && sz1>=0) {
41168 x1 = x0 + sx1; y1 = y0 + sy1; z1 = z0 + sz1;
41169 x0+=sx0; y0+=sy0; z0+=sz0;
41170 if (sx0==sx1 && sy0==sy1 && sz0==sz1) {
41171 if (exit_on_simpleclick && (!zoom ||
is_empty()))
break;
else reset_view =
true;
41173 resize_disp =
true;
41174 }
else switch (key = disp.
key()) {
41183 case cimg::keyP :
if (visu._depth>1 && (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT())) {
41186 w1 = visu._width*disp.
width()/(visu._width+(visu._depth>1?visu._depth:0)),
41187 h1 = visu._height*disp.
height()/(visu._height+(visu._depth>1?visu._depth:0));
41188 float frame_timing = 5;
41189 bool is_stopped =
false;
41191 for (
unsigned int timer = 0; !key && !disp.
is_closed() && !disp.
button(); ) {
41194 visu.get_slice((
int)_XYZ[2]).display(disp.
set_title(
"%s | z=%d",dtitle.data(),_XYZ[2]));
41195 (++_XYZ[2])%=visu._depth;
41197 if (!is_stopped) {
if (++timer>(
unsigned int)frame_timing) timer = 0; }
else timer = ~0U;
41199 switch (key = disp.
key()) {
41209 (_XYZ[2]+=visu._depth-2)%=visu._depth; timer = 0; key = 0;
break;
41210 case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41212 resize(CImgDisplay::_fitscreen(3*disp.
width()/2,3*disp.
height()/2,1,128,-100,
false),
41213 CImgDisplay::_fitscreen(3*disp.
width()/2,3*disp.
height()/2,1,128,-100,
true),
false);
41214 disp.
set_key(key,
false); key = 0;
41216 case cimg::keyC :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41218 resize(cimg_fitscreen(2*disp.
width()/3,2*disp.
height()/3,1),
false).set_key(key,
false); key = 0;
41220 case cimg::keyR :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41222 resize(cimg_fitscreen(_width,_height,_depth),
false).set_key(key,
false); key = 0;
41224 case cimg::keyF :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41226 toggle_fullscreen().
set_key(key,
false); key = 0;
41229 frame_timing = frame_timing<1?1:(frame_timing>39?39:frame_timing);
41233 w2 = (visu._width + (visu._depth>1?visu._depth:0))*disp.
width()/visu._width,
41234 h2 = (visu._height + (visu._depth>1?visu._depth:0))*disp.
height()/visu._height;
41238 case cimg::keyHOME : reset_view = resize_disp =
true; key = 0;
break;
41239 case cimg::keyPADADD : go_in =
true; go_in_center =
true; key = 0;
break;
41245 case cimg::keyPAD7 : go_up = go_left =
true; key = 0;
break;
41246 case cimg::keyPAD9 : go_up = go_right =
true; key = 0;
break;
41247 case cimg::keyPAD1 : go_down = go_left =
true; key = 0;
break;
41248 case cimg::keyPAD3 : go_down = go_right =
true; key = 0;
break;
41256 mX = mx*(_width+(_depth>1?_depth:0))/disp.
width(),
41257 mY = my*(_height+(_depth>1?_depth:0))/disp.
height();
41258 int X = _XYZ[0], Y = _XYZ[1], Z = _XYZ[2];
41260 X = x0 + mX*(1+x1-x0)/_width; Y = y0 + mY*(1+y1-y0)/_height; Z = _XYZ[2];
41263 X = x0 + mX*(1+x1-x0)/_width; Z = z0 + (mY-_height)*(1+z1-z0)/_depth; Y = _XYZ[1];
41266 Y = y0 + mY*(1+y1-y0)/_height; Z = z0 + (mX-_width)*(1+z1-z0)/_depth; X = _XYZ[0];
41268 if (x1-x0>4) { x0 = X - 3*(X-x0)/4; x1 = X + 3*(x1-X)/4; }
41269 if (y1-y0>4) { y0 = Y - 3*(Y-y0)/4; y1 = Y + 3*(y1-Y)/4; }
41270 if (z1-z0>4) { z0 = Z - 3*(Z-z0)/4; z1 = Z + 3*(z1-Z)/4; }
41274 delta_x = (x1-x0)/8, delta_y = (y1-y0)/8, delta_z = (z1-z0)/8,
41275 ndelta_x = delta_x?delta_x:(_width>1?1:0),
41276 ndelta_y = delta_y?delta_y:(_height>1?1:0),
41277 ndelta_z = delta_z?delta_z:(_depth>1?1:0);
41278 x0-=ndelta_x; y0-=ndelta_y; z0-=ndelta_z;
41279 x1+=ndelta_x; y1+=ndelta_y; z1+=ndelta_z;
41280 if (x0<0) { x1-=x0; x0 = 0;
if (x1>=
width()) x1 =
width() - 1; }
41281 if (y0<0) { y1-=y0; y0 = 0;
if (y1>=
height()) y1 =
height() - 1; }
41282 if (z0<0) { z1-=z0; z0 = 0;
if (z1>=
depth()) z1 =
depth() - 1; }
41283 if (x1>=
width()) { x0-=(x1-
width()+1); x1 =
width()-1;
if (x0<0) x0 = 0; }
41285 if (z1>=
depth()) { z0-=(z1-
depth()+1); z1 =
depth()-1;
if (z0<0) z0 = 0; }
41288 const int delta = (x1-x0)/4, ndelta = delta?delta:(_width>1?1:0);
41289 if (x0-ndelta>=0) { x0-=ndelta; x1-=ndelta; }
41290 else { x1-=x0; x0 = 0; }
41293 const int delta = (x1-x0)/4, ndelta = delta?delta:(_width>1?1:0);
41294 if (x1+ndelta<
width()) { x0+=ndelta; x1+=ndelta; }
41295 else { x0+=(
width()-1-x1); x1 =
width()-1; }
41298 const int delta = (y1-y0)/4, ndelta = delta?delta:(_height>1?1:0);
41299 if (y0-ndelta>=0) { y0-=ndelta; y1-=ndelta; }
41300 else { y1-=y0; y0 = 0; }
41303 const int delta = (y1-y0)/4, ndelta = delta?delta:(_height>1?1:0);
41304 if (y1+ndelta<
height()) { y0+=ndelta; y1+=ndelta; }
41308 const int delta = (z1-z0)/4, ndelta = delta?delta:(_depth>1?1:0);
41309 if (z0-ndelta>=0) { z0-=ndelta; z1-=ndelta; }
41310 else { z1-=z0; z0 = 0; }
41313 const int delta = (z1-z0)/4, ndelta = delta?delta:(_depth>1?1:0);
41314 if (z1+ndelta<
depth()) { z0+=ndelta; z1+=ndelta; }
41315 else { z0+=(
depth()-1-z1); z1 =
depth()-1; }
41320 if (XYZ) { XYZ[0] = _XYZ[0]; XYZ[1] = _XYZ[1]; XYZ[2] = _XYZ[2]; }
41344 template<
typename tp,
typename tf,
typename tc,
typename to>
41349 const to& opacities,
41350 const bool centering=
true,
41351 const int render_static=4,
const int render_motion=1,
41352 const bool is_double_sided=
true,
const float focale=700,
41353 const float light_x=0,
const float light_y=0,
const float light_z=-5e8f,
41354 const float specular_lightness=0.2f,
const float specular_shininess=0.1f,
41355 const bool display_axes=
true,
float *
const pose_matrix=0)
const {
41356 return _display_object3d(disp,0,vertices,primitives,colors,opacities,centering,render_static,
41357 render_motion,is_double_sided,focale,
41358 light_x,light_y,light_z,specular_lightness,specular_shininess,
41359 display_axes,pose_matrix);
41363 template<
typename tp,
typename tf,
typename tc,
typename to>
41368 const to& opacities,
41369 const bool centering=
true,
41370 const int render_static=4,
const int render_motion=1,
41371 const bool is_double_sided=
true,
const float focale=700,
41372 const float light_x=0,
const float light_y=0,
const float light_z=-5e8f,
41373 const float specular_lightness=0.2f,
const float specular_shininess=0.1f,
41374 const bool display_axes=
true,
float *
const pose_matrix=0)
const {
41376 return _display_object3d(disp,title,vertices,primitives,colors,opacities,centering,render_static,
41377 render_motion,is_double_sided,focale,
41378 light_x,light_y,light_z,specular_lightness,specular_shininess,
41379 display_axes,pose_matrix);
41383 template<
typename tp,
typename tf,
typename tc>
41388 const bool centering=
true,
41389 const int render_static=4,
const int render_motion=1,
41390 const bool is_double_sided=
true,
const float focale=700,
41391 const float light_x=0,
const float light_y=0,
const float light_z=-5e8f,
41392 const float specular_lightness=0.2f,
const float specular_shininess=0.1f,
41393 const bool display_axes=
true,
float *
const pose_matrix=0)
const {
41395 render_static,render_motion,is_double_sided,focale,
41396 light_x,light_y,light_z,specular_lightness,specular_shininess,
41397 display_axes,pose_matrix);
41401 template<
typename tp,
typename tf,
typename tc>
41406 const bool centering=
true,
41407 const int render_static=4,
const int render_motion=1,
41408 const bool is_double_sided=
true,
const float focale=700,
41409 const float light_x=0,
const float light_y=0,
const float light_z=-5e8f,
41410 const float specular_lightness=0.2f,
const float specular_shininess=0.1f,
41411 const bool display_axes=
true,
float *
const pose_matrix=0)
const {
41413 render_static,render_motion,is_double_sided,focale,
41414 light_x,light_y,light_z,specular_lightness,specular_shininess,
41415 display_axes,pose_matrix);
41419 template<
typename tp,
typename tf>
41423 const bool centering=
true,
41424 const int render_static=4,
const int render_motion=1,
41425 const bool is_double_sided=
true,
const float focale=700,
41426 const float light_x=0,
const float light_y=0,
const float light_z=-5e8f,
41427 const float specular_lightness=0.2f,
const float specular_shininess=0.1f,
41428 const bool display_axes=
true,
float *
const pose_matrix=0)
const {
41430 render_static,render_motion,is_double_sided,focale,
41431 light_x,light_y,light_z,specular_lightness,specular_shininess,
41432 display_axes,pose_matrix);
41437 template<
typename tp,
typename tf>
41441 const bool centering=
true,
41442 const int render_static=4,
const int render_motion=1,
41443 const bool is_double_sided=
true,
const float focale=700,
41444 const float light_x=0,
const float light_y=0,
const float light_z=-5e8f,
41445 const float specular_lightness=0.2f,
const float specular_shininess=0.1f,
41446 const bool display_axes=
true,
float *
const pose_matrix=0)
const {
41448 render_static,render_motion,is_double_sided,focale,
41449 light_x,light_y,light_z,specular_lightness,specular_shininess,
41450 display_axes,pose_matrix);
41454 template<
typename tp>
41457 const bool centering=
true,
41458 const int render_static=4,
const int render_motion=1,
41459 const bool is_double_sided=
true,
const float focale=700,
41460 const float light_x=0,
const float light_y=0,
const float light_z=-5e8f,
41461 const float specular_lightness=0.2f,
const float specular_shininess=0.1f,
41462 const bool display_axes=
true,
float *
const pose_matrix=0)
const {
41464 render_static,render_motion,is_double_sided,focale,
41465 light_x,light_y,light_z,specular_lightness,specular_shininess,
41466 display_axes,pose_matrix);
41470 template<
typename tp>
41473 const bool centering=
true,
41474 const int render_static=4,
const int render_motion=1,
41475 const bool is_double_sided=
true,
const float focale=700,
41476 const float light_x=0,
const float light_y=0,
const float light_z=-5e8f,
41477 const float specular_lightness=0.2f,
const float specular_shininess=0.1f,
41478 const bool display_axes=
true,
float *
const pose_matrix=0)
const {
41480 render_static,render_motion,is_double_sided,focale,
41481 light_x,light_y,light_z,specular_lightness,specular_shininess,
41482 display_axes,pose_matrix);
41485 template<
typename tp,
typename tf,
typename tc,
typename to>
41490 const to& opacities,
41491 const bool centering,
41492 const int render_static,
const int render_motion,
41493 const bool is_double_sided,
const float focale,
41494 const float light_x,
const float light_y,
const float light_z,
41495 const float specular_lightness,
const float specular_shininess,
41496 const bool display_axes,
float *
const pose_matrix)
const {
41497 typedef typename cimg::superset<tp,float>::type tpfloat;
41502 _display_object3d(disp,title,vertices,primitives,colors,opacities,centering,
41503 render_static,render_motion,is_double_sided,focale,
41504 light_x,light_y,light_z,specular_lightness,specular_shininess,
41505 display_axes,pose_matrix);
41508 1,(colors && colors[0].
size()==1)?1:3,3).
41509 _display_object3d(disp,title,vertices,primitives,colors,opacities,centering,
41510 render_static,render_motion,is_double_sided,focale,
41511 light_x,light_y,light_z,specular_lightness,specular_shininess,
41512 display_axes,pose_matrix);
41513 }
else {
if (disp) disp.
resize(*
this,
false); }
41514 char error_message[1024] = { 0 };
41515 if (!vertices.is_object3d(primitives,colors,opacities,
true,error_message))
41516 throw CImgArgumentException(_cimg_instance
41517 "display_object3d(): Invalid specified 3d object (%u,%u) (%s).",
41518 cimg_instance,vertices._width,primitives._width,error_message);
41519 if (vertices._width && !primitives) {
41520 CImgList<tf> nprimitives(vertices._width,1,1,1,1);
41521 cimglist_for(nprimitives,l) nprimitives(l,0) = l;
41522 return _display_object3d(disp,title,vertices,nprimitives,colors,opacities,centering,
41523 render_static,render_motion,is_double_sided,focale,
41524 light_x,light_y,light_z,specular_lightness,specular_shininess,
41525 display_axes,pose_matrix);
41528 disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,3);
41529 if (!title) disp.set_title(
"CImg<%s> (%u vertices, %u primitives)",
41530 pixel_type(),vertices._width,primitives._width);
41531 }
else if (title) disp.set_title(
"%s",title);
41536 rotated_vertices(vertices._width,3),
41537 bbox_vertices, rotated_bbox_vertices,
41538 axes_vertices, rotated_axes_vertices,
41539 bbox_opacities, axes_opacities;
41540 CImgList<uintT> bbox_primitives, axes_primitives;
41541 CImgList<tf> reverse_primitives;
41542 CImgList<T> bbox_colors, bbox_colors2, axes_colors;
41543 unsigned int ns_width = 0, ns_height = 0;
41544 int _is_double_sided = (int)is_double_sided;
41545 bool ndisplay_axes = display_axes;
41547 background_color(1,1,1,_spectrum,0),
41548 foreground_color(1,1,1,_spectrum,255);
41550 Xoff = 0, Yoff = 0, Zoff = 0, sprite_scale = 1,
41551 xm = 0, xM = vertices?vertices.get_shared_row(0).max_min(xm):0,
41552 ym = 0, yM = vertices?vertices.get_shared_row(1).max_min(ym):0,
41553 zm = 0, zM = vertices?vertices.get_shared_row(2).max_min(zm):0;
41554 const float delta =
cimg::max(xM-xm,yM-ym,zM-zm);
41556 rotated_bbox_vertices = bbox_vertices.assign(8,3,1,1,
41557 xm,xM,xM,xm,xm,xM,xM,xm,
41558 ym,ym,yM,yM,ym,ym,yM,yM,
41559 zm,zm,zm,zm,zM,zM,zM,zM);
41560 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);
41561 bbox_colors.assign(6,_spectrum,1,1,1,background_color[0]);
41562 bbox_colors2.assign(6,_spectrum,1,1,1,foreground_color[0]);
41563 bbox_opacities.assign(bbox_colors._width,1,1,1,0.3f);
41565 rotated_axes_vertices = axes_vertices.assign(7,3,1,1,
41569 axes_opacities.assign(3,1,1,1,1);
41570 axes_colors.assign(3,_spectrum,1,1,1,foreground_color[0]);
41571 axes_primitives.assign(3,1,2,1,1, 0,1, 0,2, 0,3);
41574 CImg<T> visu0(*
this), visu;
41575 CImg<tpfloat> zbuffer(visu0.width(),visu0.height(),1,1,0);
41576 bool init_pose =
true, clicked =
false, redraw =
true;
41577 unsigned int key = 0;
41579 x0 = 0, y0 = 0, x1 = 0, y1 = 0,
41580 nrender_static = render_static,
41581 nrender_motion = render_motion;
41582 disp.show().flush();
41584 while (!disp.is_closed() && !key) {
41589 ratio = delta>0?(2.0f*
cimg::min(disp.width(),disp.height())/(3.0f*delta)):1,
41590 dx = (xM + xm)/2, dy = (yM + ym)/2, dz = (zM + zm)/2;
41592 CImg<floatT>(4,3,1,1, ratio,0.,0.,-ratio*dx, 0.,ratio,0.,-ratio*dy, 0.,0.,ratio,-ratio*dz).
move_to(pose);
41593 else CImg<floatT>(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0).
move_to(pose);
41595 CImg<floatT> pose0(pose_matrix,4,3,1,1,
false);
41596 pose0.resize(4,4,1,1,0); pose.resize(4,4,1,1,0);
41597 pose0(3,3) = pose(3,3) = 1;
41598 (pose0*pose).
get_crop(0,0,3,2).move_to(pose);
41599 Xoff = pose_matrix[12]; Yoff = pose_matrix[13]; Zoff = pose_matrix[14]; sprite_scale = pose_matrix[15];
41600 }
else { Xoff = Yoff = Zoff = 0; sprite_scale = 1; }
41608 r00 = pose(0,0), r10 = pose(1,0), r20 = pose(2,0), r30 = pose(3,0),
41609 r01 = pose(0,1), r11 = pose(1,1), r21 = pose(2,1), r31 = pose(3,1),
41610 r02 = pose(0,2), r12 = pose(1,2), r22 = pose(2,2), r32 = pose(3,2);
41611 if ((clicked && nrender_motion>=0) || (!clicked && nrender_static>=0))
41612 cimg_forX(vertices,l) {
41613 const float x = (float)vertices(l,0), y = (float)vertices(l,1), z = (float)vertices(l,2);
41614 rotated_vertices(l,0) = r00*x + r10*y + r20*z + r30;
41615 rotated_vertices(l,1) = r01*x + r11*y + r21*z + r31;
41616 rotated_vertices(l,2) = r02*x + r12*y + r22*z + r32;
41618 else cimg_forX(bbox_vertices,l) {
41619 const float x = bbox_vertices(l,0), y = bbox_vertices(l,1), z = bbox_vertices(l,2);
41620 rotated_bbox_vertices(l,0) = r00*x + r10*y + r20*z + r30;
41621 rotated_bbox_vertices(l,1) = r01*x + r11*y + r21*z + r31;
41622 rotated_bbox_vertices(l,2) = r02*x + r12*y + r22*z + r32;
41626 #ifdef cimg_use_openmp
41627 const bool render_with_zbuffer =
true;
41629 const bool render_with_zbuffer = !clicked && nrender_static>0;
41632 if ((clicked && nrender_motion<0) || (!clicked && nrender_static<0))
41633 visu.draw_object3d(Xoff + visu._width/2.0f,Yoff + visu._height/2.0f,Zoff,
41634 rotated_bbox_vertices,bbox_primitives,bbox_colors,bbox_opacities,2,
false,focale).
41635 draw_object3d(Xoff + visu._width/2.0f,Yoff + visu._height/2.0f,Zoff,
41636 rotated_bbox_vertices,bbox_primitives,bbox_colors2,1,
false,focale);
41638 Xoff + visu._width/2.0f,Yoff + visu._height/2.0f,Zoff,
41639 rotated_vertices,reverse_primitives?reverse_primitives:primitives,
41640 colors,opacities,clicked?nrender_motion:nrender_static,_is_double_sided==1,focale,
41641 width()/2.0f+light_x,
height()/2.0f+light_y,light_z+Zoff,
41642 specular_lightness,specular_shininess,sprite_scale);
41644 if (ndisplay_axes) {
41646 n = (float)std::sqrt(1e-8 + r00*r00 + r01*r01 + r02*r02),
41647 _r00 = r00/n, _r10 = r10/n, _r20 = r20/n,
41648 _r01 = r01/n, _r11 = r11/n, _r21 = r21/n,
41649 _r02 = r01/n, _r12 = r12/n, _r22 = r22/n,
41650 Xaxes = 25, Yaxes = visu._height - 38.0f;
41651 cimg_forX(axes_vertices,l) {
41653 x = axes_vertices(l,0),
41654 y = axes_vertices(l,1),
41655 z = axes_vertices(l,2);
41656 rotated_axes_vertices(l,0) = _r00*x + _r10*y + _r20*z;
41657 rotated_axes_vertices(l,1) = _r01*x + _r11*y + _r21*z;
41658 rotated_axes_vertices(l,2) = _r02*x + _r12*y + _r22*z;
41660 axes_opacities(0,0) = (rotated_axes_vertices(1,2)>0)?0.5f:1.0f;
41661 axes_opacities(1,0) = (rotated_axes_vertices(2,2)>0)?0.5f:1.0f;
41662 axes_opacities(2,0) = (rotated_axes_vertices(3,2)>0)?0.5f:1.0f;
41663 visu.draw_object3d(Xaxes,Yaxes,0,rotated_axes_vertices,axes_primitives,
41664 axes_colors,axes_opacities,1,
false,focale).
41665 draw_text((
int)(Xaxes+rotated_axes_vertices(4,0)),
41666 (
int)(Yaxes+rotated_axes_vertices(4,1)),
41667 "X",axes_colors[0]._data,0,axes_opacities(0,0),13).
41668 draw_text((
int)(Xaxes+rotated_axes_vertices(5,0)),
41669 (
int)(Yaxes+rotated_axes_vertices(5,1)),
41670 "Y",axes_colors[1]._data,0,axes_opacities(1,0),13).
41671 draw_text((
int)(Xaxes+rotated_axes_vertices(6,0)),
41672 (
int)(Yaxes+rotated_axes_vertices(6,1)),
41673 "Z",axes_colors[2]._data,0,axes_opacities(2,0),13);
41675 visu.display(disp);
41676 if (!clicked || nrender_motion==nrender_static) redraw =
false;
41681 if ((disp.button() || disp.wheel()) && disp.mouse_x()>=0 && disp.mouse_y()>=0) {
41683 if (!clicked) { x0 = x1 = disp.mouse_x(); y0 = y1 = disp.mouse_y();
if (!disp.wheel()) clicked =
true; }
41684 else { x1 = disp.mouse_x(); y1 = disp.mouse_y(); }
41685 if (disp.button()&1) {
41687 R = 0.45f*
cimg::min(disp.width(),disp.height()),
41689 u0 = (
float)(x0-disp.width()/2),
41690 v0 = (
float)(y0-disp.height()/2),
41691 u1 = (
float)(x1-disp.width()/2),
41692 v1 = (
float)(y1-disp.height()/2),
41693 n0 = (
float)std::sqrt(u0*u0+v0*v0),
41694 n1 = (float)std::sqrt(u1*u1+v1*v1),
41695 nu0 = n0>R?(u0*R/n0):u0,
41696 nv0 = n0>R?(v0*R/n0):v0,
41697 nw0 = (float)
std::
sqrt(cimg::
max(0,R2-nu0*nu0-nv0*nv0)),
41698 nu1 = n1>R?(u1*R/n1):u1,
41699 nv1 = n1>R?(v1*R/n1):v1,
41700 nw1 = (float)
std::
sqrt(cimg::
max(0,R2-nu1*nu1-nv1*nv1)),
41701 u = nv0*nw1-nw0*nv1,
41702 v = nw0*nu1-nu0*nw1,
41703 w = nv0*nu1-nu0*nv1,
41704 n = (float)
std::
sqrt(u*u+v*v+w*w),
41705 alpha = (float)
std::
asin(n/R2);
41709 if (disp.button()&2) {
41710 if (focale>0) Zoff-=(y0-y1)*focale/400;
41711 else {
const float s = std::exp((y0-y1)/400.0f); pose*=s; sprite_scale*=s; }
41714 if (disp.wheel()) {
41715 if (focale>0) Zoff-=disp.wheel()*focale/20;
41716 else {
const float s = std::exp(disp.wheel()/20.0f); pose*=s; sprite_scale*=s; }
41719 if (disp.button()&4) { Xoff+=(x1-x0); Yoff+=(y1-y0); x0 = x1; y0 = y1; }
41720 if ((disp.button()&1) && (disp.button()&2)) {
41721 init_pose =
true; disp.set_button(); x0 = x1; y0 = y1;
41722 pose = CImg<floatT>(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0);
41724 }
else if (clicked) { x0 = x1; y0 = y1; clicked =
false; redraw =
true; }
41726 switch (key = disp.key()) {
41731 case cimg::keyD:
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41732 disp.set_fullscreen(
false).
41733 resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,
false),
41734 CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,
true),
false).
41735 _is_resized =
true;
41736 disp.set_key(key,
false); key = 0;
41738 case cimg::keyC :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41739 disp.set_fullscreen(
false).
41740 resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),
false)._is_resized =
true;
41741 disp.set_key(key,
false); key = 0;
41743 case cimg::keyR :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41744 disp.set_fullscreen(
false).resize(cimg_fitscreen(_width,_height,_depth),
false)._is_resized =
true;
41745 disp.set_key(key,
false); key = 0;
41747 case cimg::keyF :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41748 if (!ns_width || !ns_height ||
41749 ns_width>(
unsigned int)disp.screen_width() || ns_height>(
unsigned int)disp.screen_height()) {
41750 ns_width = disp.screen_width()*3U/4;
41751 ns_height = disp.screen_height()*3U/4;
41753 if (disp.is_fullscreen()) disp.resize(ns_width,ns_height,
false);
41755 ns_width = (
unsigned int)disp.width(); ns_height = disp.height();
41756 disp.resize(disp.screen_width(),disp.screen_height(),
false);
41758 disp.toggle_fullscreen()._is_resized =
true;
41759 disp.set_key(key,
false); key = 0;
41761 case cimg::keyT :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41763 if (--_is_double_sided==-2) _is_double_sided = 1;
41764 if (_is_double_sided>=0) reverse_primitives.assign();
41766 disp.set_key(key,
false); key = 0; redraw =
true;
41768 case cimg::keyZ :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41769 if (zbuffer) zbuffer.assign();
41770 else zbuffer.assign(visu0.width(),visu0.height(),1,1,0);
41771 disp.set_key(key,
false); key = 0; redraw =
true;
41773 case cimg::keyA :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41774 ndisplay_axes = !ndisplay_axes;
41775 disp.set_key(key,
false); key = 0; redraw =
true;
41777 case cimg::keyF1 :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41778 nrender_motion = (nrender_static==0 && nrender_motion!=0)?0:-1; nrender_static = 0;
41779 disp.set_key(key,
false); key = 0; redraw =
true;
41781 case cimg::keyF2 :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41782 nrender_motion = (nrender_static==1 && nrender_motion!=1)?1:-1; nrender_static = 1;
41783 disp.set_key(key,
false); key = 0; redraw =
true;
41785 case cimg::keyF3 :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41786 nrender_motion = (nrender_static==2 && nrender_motion!=2)?2:-1; nrender_static = 2;
41787 disp.set_key(key,
false); key = 0; redraw =
true;
41789 case cimg::keyF4 :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41790 nrender_motion = (nrender_static==3 && nrender_motion!=3)?3:-1; nrender_static = 3;
41791 disp.set_key(key,
false); key = 0; redraw =
true;
41793 case cimg::keyF5 :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41795 nrender_motion = (nrender_static==4 && nrender_motion!=4)?4:-1; nrender_static = 4;
41796 disp.set_key(key,
false); key = 0; redraw =
true;
41798 case cimg::keyF6 :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41799 nrender_motion = (nrender_static==5 && nrender_motion!=5)?5:-1; nrender_static = 5;
41800 disp.set_key(key,
false); key = 0; redraw =
true;
41802 case cimg::keyS :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41803 static unsigned int snap_number = 0;
41804 char filename[32] = { 0 };
41807 cimg_snprintf(filename,
sizeof(filename),cimg_appname
"_%.4u.bmp",snap_number++);
41808 if ((file=std::fopen(filename,
"r"))!=0)
cimg::fclose(file);
41810 (+visu).
draw_text(0,0,
" Saving snapshot... ",
41811 foreground_color._data,background_color._data,0.7f,13).display(disp);
41812 visu.save(filename);
41813 (+visu).
draw_text(0,0,
" Snapshot '%s' saved. ",
41814 foreground_color._data,background_color._data,0.7f,13,filename).display(disp);
41815 disp.set_key(key,
false); key = 0;
41817 case cimg::keyG :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41818 static unsigned int snap_number = 0;
41819 char filename[32] = { 0 };
41822 cimg_snprintf(filename,
sizeof(filename),cimg_appname
"_%.4u.off",snap_number++);
41823 if ((file=std::fopen(filename,
"r"))!=0)
cimg::fclose(file);
41825 (+visu).
draw_text(0,0,
" Saving object... ",
41826 foreground_color._data,background_color._data,0.7f,13).display(disp);
41827 vertices.save_off(reverse_primitives?reverse_primitives:primitives,colors,filename);
41828 (+visu).
draw_text(0,0,
" Object '%s' saved. ",
41829 foreground_color._data,background_color._data,0.7f,13,filename).display(disp);
41830 disp.set_key(key,
false); key = 0;
41832 case cimg::keyO :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41833 static unsigned int snap_number = 0;
41834 char filename[32] = { 0 };
41837 #ifdef cimg_use_zlib
41838 cimg_snprintf(filename,
sizeof(filename),cimg_appname
"_%.4u.cimgz",snap_number++);
41840 cimg_snprintf(filename,
sizeof(filename),cimg_appname
"_%.4u.cimg",snap_number++);
41842 if ((file=std::fopen(filename,
"r"))!=0)
cimg::fclose(file);
41844 (+visu).
draw_text(0,0,
" Saving object... ",
41845 foreground_color._data,background_color._data,0.7f,13).display(disp);
41846 vertices.get_object3dtoCImg3d(reverse_primitives?reverse_primitives:primitives,colors,opacities).
41848 (+visu).
draw_text(0,0,
" Object '%s' saved. ",
41849 foreground_color._data,background_color._data,0.7f,13,filename).display(disp);
41850 disp.set_key(key,
false); key = 0;
41852 #ifdef cimg_use_board
41853 case cimg::keyP :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41854 static unsigned int snap_number = 0;
41855 char filename[32] = { 0 };
41858 cimg_snprintf(filename,
sizeof(filename),cimg_appname
"_%.4u.eps",snap_number++);
41859 if ((file=std::fopen(filename,
"r"))!=0)
cimg::fclose(file);
41861 (+visu).
draw_text(0,0,
" Saving EPS snapshot... ",
41862 foreground_color._data,background_color._data,0.7f,13).display(disp);
41863 LibBoard::Board board;
41864 (+visu)._draw_object3d(&board,zbuffer.fill(0),
41865 Xoff + visu._width/2.0f,Yoff + visu._height/2.0f,Zoff,
41866 rotated_vertices,reverse_primitives?reverse_primitives:primitives,
41867 colors,opacities,clicked?nrender_motion:nrender_static,
41868 _is_double_sided==1,focale,
41869 visu.width()/2.0f+light_x,visu.height()/2.0f+light_y,light_z+Zoff,
41870 specular_lightness,specular_shininess,
41872 board.saveEPS(filename);
41873 (+visu).
draw_text(0,0,
" Object '%s' saved. ",
41874 foreground_color._data,background_color._data,0.7f,13,filename).display(disp);
41875 disp.set_key(key,
false); key = 0;
41877 case cimg::keyV :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
41878 static unsigned int snap_number = 0;
41879 char filename[32] = { 0 };
41882 cimg_snprintf(filename,
sizeof(filename),cimg_appname
"_%.4u.svg",snap_number++);
41883 if ((file=std::fopen(filename,
"r"))!=0)
cimg::fclose(file);
41885 (+visu).
draw_text(0,0,
" Saving SVG snapshot... ",
41886 foreground_color._data,background_color._data,0.7f,13).display(disp);
41887 LibBoard::Board board;
41888 (+visu)._draw_object3d(&board,zbuffer.fill(0),
41889 Xoff + visu._width/2.0f,Yoff + visu._height/2.0f,Zoff,
41890 rotated_vertices,reverse_primitives?reverse_primitives:primitives,
41891 colors,opacities,clicked?nrender_motion:nrender_static,
41892 _is_double_sided==1,focale,
41893 visu.width()/2.0f+light_x,visu.height()/2.0f+light_y,light_z+Zoff,
41894 specular_lightness,specular_shininess,
41896 board.saveSVG(filename);
41897 (+visu).
draw_text(0,0,
" Object '%s' saved. ",
41898 foreground_color._data,background_color._data,0.7f,13,filename).display(disp);
41899 disp.set_key(key,
false); key = 0;
41903 if (disp.is_resized()) {
41904 disp.resize(
false); visu0 =
get_resize(disp,1);
41905 if (zbuffer) zbuffer.assign(disp.width(),disp.height());
41910 std::memcpy(pose_matrix,pose._data,12*
sizeof(
float));
41911 pose_matrix[12] = Xoff; pose_matrix[13] = Yoff; pose_matrix[14] = Zoff; pose_matrix[15] = sprite_scale;
41913 disp.set_button().set_key(key);
41930 const unsigned int plot_type=1,
const unsigned int vertex_type=1,
41931 const char *
const labelx=0,
const double xmin=0,
const double xmax=0,
41932 const char *
const labely=0,
const double ymin=0,
const double ymax=0)
const {
41933 return _display_graph(disp,0,plot_type,vertex_type,labelx,xmin,xmax,labely,ymin,ymax);
41938 const unsigned int plot_type=1,
const unsigned int vertex_type=1,
41939 const char *
const labelx=0,
const double xmin=0,
const double xmax=0,
41940 const char *
const labely=0,
const double ymin=0,
const double ymax=0)
const {
41942 return _display_graph(disp,title,plot_type,vertex_type,labelx,xmin,xmax,labely,ymin,ymax);
41946 const unsigned int plot_type=1,
const unsigned int vertex_type=1,
41947 const char *
const labelx=0,
const double xmin=0,
const double xmax=0,
41948 const char *
const labely=0,
const double ymin=0,
const double ymax=0)
const {
41951 "display_graph(): Empty instance.",
41954 set_title(title?
"%s":
"CImg<%s>",title?title:
pixel_type());
41955 const unsigned long siz = (
unsigned long)_width*_height*_depth, siz1 =
cimg::max(1U,siz-1);
41956 const unsigned int old_normalization = disp.
normalization();
41957 disp.
show().
flush()._normalization = 0;
41959 double y0 = ymin, y1 = ymax, nxmin = xmin, nxmax = xmax;
41960 if (nxmin==nxmax) { nxmin = 0; nxmax = siz1; }
41963 for (
bool reset_view =
true; !key && !disp.
is_closed(); ) {
41964 if (reset_view) { x0 = 0; x1 =
width()*
height()*
depth()-1; y0 = ymin; y1 = ymax; reset_view =
false; }
41965 CImg<T> zoom(x1-x0+1,1,1,
spectrum());
41967 if (y0==y1) { y0 = zoom.min_max(y1);
const double dy = y1 - y0; y0-=dy/20; y1+=dy/20; }
41968 if (y0==y1) { --y0; ++y1; }
41970 const CImg<intT> selection = zoom.get_select_graph(disp,plot_type,vertex_type,
41972 nxmin + x0*(nxmax-nxmin)/siz1,
41973 nxmin + x1*(nxmax-nxmin)/siz1,
41976 if (selection[0]>=0) {
41977 if (selection[2]<0) reset_view =
true;
41979 x1 = x0 + selection[2]; x0+=selection[0];
41980 if (selection[1]>=0 && selection[3]>=0) {
41981 y0 = y1 - selection[3]*(y1-y0)/(disp.
height()-32);
41982 y1-=selection[1]*(y1-y0)/(disp.
height()-32);
41986 bool go_in =
false, go_out =
false, go_left =
false, go_right =
false, go_up =
false, go_down =
false;
41987 switch (key = disp.
key()) {
42002 if (disp.
wheel()) {
42003 if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) go_out = !(go_in = disp.
wheel()>0);
42004 else if (disp.is_keySHIFTLEFT() || disp.is_keySHIFTRIGHT()) go_left = !(go_right = disp.
wheel()>0);
42005 else go_up = !(go_down = disp.
wheel()<0);
42012 mx = (mouse_x-16)*xsiz/(disp.
width()-32),
42013 cx = x0 + (mx<0?0:(mx>=xsiz?xsiz:mx));
42015 x0 = cx - 7*(cx-x0)/8; x1 = cx + 7*(x1-cx)/8;
42016 if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
42019 my = (mouse_y-16)*ysiz/(disp.
height()-32),
42020 cy = y1 - (my<0?0:(my>=ysiz?ysiz:my));
42021 y0 = cy - 7*(cy-y0)/8; y1 = cy + 7*(y1-cy)/8;
42022 }
else y0 = y1 = 0;
42026 if (x0>0 || x1<(
int)siz1) {
42027 const int delta_x = (x1-x0)/8, ndelta_x = delta_x?delta_x:(siz>1?1:0);
42028 const double ndelta_y = (y1-y0)/8;
42029 x0-=ndelta_x; x1+=ndelta_x;
42030 y0-=ndelta_y; y1+=ndelta_y;
42031 if (x0<0) { x1-=x0; x0 = 0;
if (x1>=(
int)siz) x1 = (
int)siz1; }
42032 if (x1>=(
int)siz) { x0-=(x1-siz1); x1 = (int)siz1;
if (x0<0) x0 = 0; }
42036 const int delta = (x1-x0)/5, ndelta = delta?delta:1;
42037 if (x0-ndelta>=0) { x0-=ndelta; x1-=ndelta; }
42038 else { x1-=x0; x0 = 0; }
42042 const int delta = (x1-x0)/5, ndelta = delta?delta:1;
42043 if (x1+ndelta<(
int)siz) { x0+=ndelta; x1+=ndelta; }
42044 else { x0+=(siz1-x1); x1 = siz1; }
42048 const double delta = (y1-y0)/10, ndelta = delta?delta:1;
42049 y0+=ndelta; y1+=ndelta;
42053 const double delta = (y1-y0)/10, ndelta = delta?delta:1;
42054 y0-=ndelta; y1-=ndelta;
42059 disp._normalization = old_normalization;
42073 const CImg<T>&
save(
const char *
const filename,
const int number=-1,
const unsigned int digits=6)
const {
42076 "save(): Specified filename is (null).",
42079 const bool is_stdout = *filename==
'-' && (!filename[1] || filename[1]==
'.');
42081 char nfilename[1024] = { 0 };
42082 const char *
const fn = is_stdout?filename:(number>=0)?
cimg::number_filename(filename,number,digits,nfilename):
42085 #ifdef cimg_save_plugin
42086 cimg_save_plugin(fn);
42088 #ifdef cimg_save_plugin1
42089 cimg_save_plugin1(fn);
42091 #ifdef cimg_save_plugin2
42092 cimg_save_plugin2(fn);
42094 #ifdef cimg_save_plugin3
42095 cimg_save_plugin3(fn);
42097 #ifdef cimg_save_plugin4
42098 cimg_save_plugin4(fn);
42100 #ifdef cimg_save_plugin5
42101 cimg_save_plugin5(fn);
42103 #ifdef cimg_save_plugin6
42104 cimg_save_plugin6(fn);
42106 #ifdef cimg_save_plugin7
42107 cimg_save_plugin7(fn);
42109 #ifdef cimg_save_plugin8
42110 cimg_save_plugin8(fn);
42187 return _save_ascii(0,filename);
42192 return _save_ascii(file,0);
42195 const CImg<T>& _save_ascii(std::FILE *
const file,
const char *
const filename)
const {
42196 if (!file && !filename)
42198 "save_ascii(): Specified filename is (null).",
42200 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"w");
42201 std::fprintf(nfile,
"%u %u %u %u\n",_width,_height,_depth,_spectrum);
42202 const T* ptrs = _data;
42203 cimg_forYZC(*
this,y,z,c) {
42204 cimg_forX(*
this,x)
std::fprintf(nfile,"%.16g ",(
double)*(ptrs++));
42205 std::fputc('\n',nfile);
42207 if (!file) cimg::fclose(nfile);
42216 return _save_cpp(0,filename);
42221 return _save_cpp(file,0);
42224 const CImg<T>& _save_cpp(std::FILE *
const file,
const char *
const filename)
const {
42225 if (!file && !filename)
42227 "save_cpp(): Specified filename is (null).",
42229 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"w");
42230 char varname[1024] = { 0 };
42231 if (filename) std::sscanf(
cimg::basename(filename),
"%1023[a-zA-Z0-9_]",varname);
42232 if (!*varname) cimg_snprintf(varname,
sizeof(varname),
"unnamed");
42233 std::fprintf(nfile,
42234 "/* Define image '%s' of size %ux%ux%ux%u and type '%s' */\n"
42235 "%s data_%s[] = { %s\n ",
42238 if (!
is_empty())
for (
unsigned long off = 0, siz =
size()-1; off<=siz; ++off) {
42239 std::fprintf(nfile,cimg::type<T>::format(),cimg::type<T>::format((*
this)[off]));
42240 if (off==siz) std::fprintf(nfile,
" };\n");
42241 else if (!((off+1)%16)) std::fprintf(nfile,
",\n ");
42242 else std::fprintf(nfile,
", ");
42253 return _save_dlm(0,filename);
42258 return _save_dlm(file,0);
42261 const CImg<T>& _save_dlm(std::FILE *
const file,
const char *
const filename)
const {
42262 if (!file && !filename)
42264 "save_dlm(): Specified filename is (null).",
42269 "save_dlm(): Instance is volumetric, values along Z will be unrolled in file '%s'.",
42271 filename?filename:
"(FILE*)");
42274 "save_dlm(): Instance is multispectral, values along C will be unrolled in file '%s'.",
42276 filename?filename:
"(FILE*)");
42278 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"w");
42279 const T* ptrs = _data;
42280 cimg_forYZC(*
this,y,z,c) {
42281 cimg_forX(*
this,x)
std::fprintf(nfile,"%.16g%s",(
double)*(ptrs++),(x==width()-1)?"":",");
42282 std::fputc('\n',nfile);
42284 if (!file) cimg::fclose(nfile);
42293 return _save_bmp(0,filename);
42298 return _save_bmp(file,0);
42301 const CImg<T>& _save_bmp(std::FILE *
const file,
const char *
const filename)
const {
42302 if (!file && !filename)
42304 "save_bmp(): Specified filename is (null).",
42309 "save_bmp(): Instance is volumetric, only the first slice will be saved in file '%s'.",
42311 filename?filename:
"(FILE*)");
42314 "save_bmp(): Instance is multispectral, only the three first channels will be saved in file '%s'.",
42316 filename?filename:
"(FILE*)");
42318 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"wb");
42319 unsigned char header[54] = { 0 }, align_buf[4] = { 0 };
42321 align = (4 - (3*_width)%4)%4,
42322 buf_size = (3*_width + align)*
height(),
42323 file_size = 54 + buf_size;
42324 header[0] =
'B'; header[1] =
'M';
42325 header[0x02] = file_size&0xFF;
42326 header[0x03] = (file_size>>8)&0xFF;
42327 header[0x04] = (file_size>>16)&0xFF;
42328 header[0x05] = (file_size>>24)&0xFF;
42329 header[0x0A] = 0x36;
42330 header[0x0E] = 0x28;
42331 header[0x12] = _width&0xFF;
42332 header[0x13] = (_width>>8)&0xFF;
42333 header[0x14] = (_width>>16)&0xFF;
42334 header[0x15] = (_width>>24)&0xFF;
42335 header[0x16] = _height&0xFF;
42336 header[0x17] = (_height>>8)&0xFF;
42337 header[0x18] = (_height>>16)&0xFF;
42338 header[0x19] = (_height>>24)&0xFF;
42343 header[0x22] = buf_size&0xFF;
42344 header[0x23] = (buf_size>>8)&0xFF;
42345 header[0x24] = (buf_size>>16)&0xFF;
42346 header[0x25] = (buf_size>>24)&0xFF;
42347 header[0x27] = 0x1;
42348 header[0x2B] = 0x1;
42352 *ptr_r =
data(0,_height-1,0,0),
42353 *ptr_g = (_spectrum>=2)?
data(0,_height-1,0,1):0,
42354 *ptr_b = (_spectrum>=3)?
data(0,_height-1,0,2):0;
42356 switch (_spectrum) {
42358 cimg_forY(*
this,y) {
42359 cimg_forX(*
this,x) {
42360 const unsigned char val = (
unsigned char)*(ptr_r++);
42361 std::fputc(val,nfile); std::fputc(val,nfile); std::fputc(val,nfile);
42368 cimg_forY(*
this,y) {
42369 cimg_forX(*
this,x) {
42370 std::fputc(0,nfile);
42371 std::fputc((
unsigned char)(*(ptr_g++)),nfile);
42372 std::fputc((
unsigned char)(*(ptr_r++)),nfile);
42375 ptr_r-=2*_width; ptr_g-=2*_width;
42379 cimg_forY(*
this,y) {
42380 cimg_forX(*
this,x) {
42381 std::fputc((
unsigned char)(*(ptr_b++)),nfile);
42382 std::fputc((
unsigned char)(*(ptr_g++)),nfile);
42383 std::fputc((
unsigned char)(*(ptr_r++)),nfile);
42386 ptr_r-=2*_width; ptr_g-=2*_width; ptr_b-=2*_width;
42400 return _save_jpeg(0,filename,quality);
42405 return _save_jpeg(file,0,quality);
42408 const CImg<T>& _save_jpeg(std::FILE *
const file,
const char *
const filename,
const unsigned int quality)
const {
42409 if (!file && !filename)
42411 "save_jpeg(): Specified filename is (null).",
42416 "save_jpeg(): Instance is volumetric, only the first slice will be saved in file '%s'.",
42418 filename?filename:
"(FILE*)");
42420 #ifndef cimg_use_jpeg
42421 if (!file)
return save_other(filename,quality);
42422 else throw CImgIOException(_cimg_instance
42423 "save_jpeg(): Unable to save data in '(*FILE)' unless libjpeg is enabled.",
42426 unsigned int dimbuf = 0;
42427 J_COLOR_SPACE colortype = JCS_RGB;
42429 switch(_spectrum) {
42430 case 1 : dimbuf = 1; colortype = JCS_GRAYSCALE;
break;
42431 case 2 : dimbuf = 3; colortype = JCS_RGB;
break;
42432 case 3 : dimbuf = 3; colortype = JCS_RGB;
break;
42433 default : dimbuf = 4; colortype = JCS_CMYK;
break;
42437 struct jpeg_compress_struct cinfo;
42438 struct jpeg_error_mgr jerr;
42439 cinfo.err = jpeg_std_error(&jerr);
42440 jpeg_create_compress(&cinfo);
42441 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"wb");
42442 jpeg_stdio_dest(&cinfo,nfile);
42443 cinfo.image_width = _width;
42444 cinfo.image_height = _height;
42445 cinfo.input_components = dimbuf;
42446 cinfo.in_color_space = colortype;
42447 jpeg_set_defaults(&cinfo);
42448 jpeg_set_quality(&cinfo,quality<100?quality:100,TRUE);
42449 jpeg_start_compress(&cinfo,TRUE);
42451 JSAMPROW row_pointer[1];
42452 CImg<ucharT> buffer((
unsigned long)_width*dimbuf);
42454 while (cinfo.next_scanline<cinfo.image_height) {
42455 unsigned char *ptrd = buffer._data;
42458 switch (_spectrum) {
42460 const T *ptr_g =
data(0, cinfo.next_scanline);
42461 for(
unsigned int b = 0; b < cinfo.image_width; b++)
42462 *(ptrd++) = (
unsigned char)*(ptr_g++);
42465 const T *ptr_r =
data(0,cinfo.next_scanline,0,0),
42466 *ptr_g =
data(0,cinfo.next_scanline,0,1);
42467 for(
unsigned int b = 0; b < cinfo.image_width; ++b) {
42468 *(ptrd++) = (
unsigned char)*(ptr_r++);
42469 *(ptrd++) = (
unsigned char)*(ptr_g++);
42474 const T *ptr_r =
data(0,cinfo.next_scanline,0,0),
42475 *ptr_g =
data(0,cinfo.next_scanline,0,1),
42476 *ptr_b =
data(0,cinfo.next_scanline,0,2);
42477 for(
unsigned int b = 0; b < cinfo.image_width; ++b) {
42478 *(ptrd++) = (
unsigned char)*(ptr_r++);
42479 *(ptrd++) = (
unsigned char)*(ptr_g++);
42480 *(ptrd++) = (
unsigned char)*(ptr_b++);
42484 const T *ptr_r =
data(0,cinfo.next_scanline,0,0),
42485 *ptr_g =
data(0,cinfo.next_scanline,0,1),
42486 *ptr_b =
data(0,cinfo.next_scanline,0,2),
42487 *ptr_a =
data(0,cinfo.next_scanline,0,3);
42488 for(
unsigned int b = 0; b < cinfo.image_width; ++b) {
42489 *(ptrd++) = (
unsigned char)*(ptr_r++);
42490 *(ptrd++) = (
unsigned char)*(ptr_g++);
42491 *(ptrd++) = (
unsigned char)*(ptr_b++);
42492 *(ptrd++) = (
unsigned char)*(ptr_a++);
42496 *row_pointer = buffer._data;
42497 jpeg_write_scanlines(&cinfo,row_pointer,1);
42499 jpeg_finish_compress(&cinfo);
42501 jpeg_destroy_compress(&cinfo);
42514 "save_magick(): Specified filename is (null).",
42518 #ifdef cimg_use_magick
42519 double stmin, stmax = (double)
max_min(stmin);
42522 "save_magick(): Instance is volumetric, only the first slice will be saved in file '%s'.",
42528 "save_magick(): Instance is multispectral, only the three first channels will be "
42529 "saved in file '%s'.",
42533 if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536)
42535 "save_magick(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.",
42537 filename,stmin,stmax);
42539 Magick::Image image(Magick::Geometry(_width,_height),
"black");
42540 image.type(Magick::TrueColorType);
42541 image.depth(bytes_per_pixel?(8*bytes_per_pixel):(stmax>=256?16:8));
42543 *ptr_r =
data(0,0,0,0),
42544 *ptr_g = _spectrum>1?
data(0,0,0,1):0,
42545 *ptr_b = _spectrum>2?
data(0,0,0,2):0;
42546 Magick::PixelPacket *pixels = image.getPixels(0,0,_width,_height);
42547 switch (_spectrum) {
42549 for (
unsigned long off = (
unsigned long)_width*_height; off; --off) {
42550 pixels->red = pixels->green = pixels->blue = (Magick::Quantum)*(ptr_r++);
42555 for (
unsigned long off = (
unsigned long)_width*_height; off; --off) {
42556 pixels->red = (Magick::Quantum)*(ptr_r++);
42557 pixels->green = (Magick::Quantum)*(ptr_g++);
42558 pixels->blue = 0; ++pixels;
42562 for (
unsigned long off = (
unsigned long)_width*_height; off; --off) {
42563 pixels->red = (Magick::Quantum)*(ptr_r++);
42564 pixels->green = (Magick::Quantum)*(ptr_g++);
42565 pixels->blue = (Magick::Quantum)*(ptr_b++);
42569 image.syncPixels();
42570 image.write(filename);
42575 "save_magick(): Unable to save file '%s' unless libMagick++ is enabled.",
42586 const CImg<T>&
save_png(
const char *
const filename,
const unsigned int bytes_per_pixel=0)
const {
42587 return _save_png(0,filename,bytes_per_pixel);
42592 return _save_png(file,0,bytes_per_pixel);
42595 const CImg<T>& _save_png(std::FILE *
const file,
const char *
const filename,
42596 const unsigned int bytes_per_pixel=0)
const {
42597 if (!file && !filename)
42599 "save_png(): Specified filename is (null).",
42603 #ifndef cimg_use_png
42606 else throw CImgIOException(_cimg_instance
42607 "save_png(): Unable to save data in '(*FILE)' unless libpng is enabled.",
42610 const char *
volatile nfilename = filename;
42611 std::FILE *
volatile nfile = file?file:
cimg::fopen(nfilename,
"wb");
42612 volatile double stmin, stmax = (double)
max_min(stmin);
42616 "save_png(): Instance is volumetric, only the first slice will be saved in file '%s'.",
42622 "save_png(): Instance is multispectral, only the three first channels will be saved in file '%s'.",
42626 if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536)
42628 "save_png(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.",
42630 filename,stmin,stmax);
42633 png_voidp user_error_ptr = 0;
42634 png_error_ptr user_error_fn = 0, user_warning_fn = 0;
42635 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,user_error_ptr, user_error_fn,
42639 throw CImgIOException(_cimg_instance
42640 "save_png(): Failed to initialize 'png_ptr' structure when saving file '%s'.",
42642 nfilename?nfilename:
"(FILE*)");
42644 png_infop info_ptr = png_create_info_struct(png_ptr);
42646 png_destroy_write_struct(&png_ptr,(png_infopp)0);
42648 throw CImgIOException(_cimg_instance
42649 "save_png(): Failed to initialize 'info_ptr' structure when saving file '%s'.",
42651 nfilename?nfilename:
"(FILE*)");
42653 if (setjmp(png_jmpbuf(png_ptr))) {
42654 png_destroy_write_struct(&png_ptr, &info_ptr);
42656 throw CImgIOException(_cimg_instance
42657 "save_png(): Encountered unknown fatal error in libpng when saving file '%s'.",
42659 nfilename?nfilename:
"(FILE*)");
42661 png_init_io(png_ptr, nfile);
42663 const int bit_depth = bytes_per_pixel?(bytes_per_pixel*8):(stmax>=256?16:8);
42667 case 1 : color_type = PNG_COLOR_TYPE_GRAY;
break;
42668 case 2 : color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
break;
42669 case 3 : color_type = PNG_COLOR_TYPE_RGB;
break;
42670 default : color_type = PNG_COLOR_TYPE_RGB_ALPHA;
42672 const int interlace_type = PNG_INTERLACE_NONE;
42673 const int compression_type = PNG_COMPRESSION_TYPE_DEFAULT;
42674 const int filter_method = PNG_FILTER_TYPE_DEFAULT;
42675 png_set_IHDR(png_ptr,info_ptr,_width,_height,bit_depth,color_type,interlace_type,compression_type,filter_method);
42676 png_write_info(png_ptr,info_ptr);
42677 const int byte_depth = bit_depth>>3;
42679 const int pixel_bit_depth_flag = numChan * (bit_depth-1);
42682 png_bytep *
const imgData =
new png_byte*[_height];
42683 for (
unsigned int row = 0; row<_height; ++
row) imgData[row] =
new png_byte[byte_depth*numChan*_width];
42684 const T *pC0 =
data(0,0,0,0);
42685 switch (pixel_bit_depth_flag) {
42687 cimg_forY(*
this,y) {
42688 unsigned char *ptrd = imgData[y];
42689 cimg_forX(*
this,x) *(ptrd++) = (
unsigned char)*(pC0++);
42693 const T *pC1 =
data(0,0,0,1);
42694 cimg_forY(*
this,y) {
42695 unsigned char *ptrd = imgData[y];
42696 cimg_forX(*
this,x) {
42697 *(ptrd++) = (
unsigned char)*(pC0++);
42698 *(ptrd++) = (
unsigned char)*(pC1++);
42703 const T *pC1 =
data(0,0,0,1), *pC2 =
data(0,0,0,2);
42704 cimg_forY(*
this,y) {
42705 unsigned char *ptrd = imgData[y];
42706 cimg_forX(*
this,x) {
42707 *(ptrd++) = (
unsigned char)*(pC0++);
42708 *(ptrd++) = (
unsigned char)*(pC1++);
42709 *(ptrd++) = (
unsigned char)*(pC2++);
42714 const T *pC1 =
data(0,0,0,1), *pC2 =
data(0,0,0,2), *pC3 =
data(0,0,0,3);
42715 cimg_forY(*
this,y){
42716 unsigned char *ptrd = imgData[y];
42717 cimg_forX(*
this,x){
42718 *(ptrd++) = (
unsigned char)*(pC0++);
42719 *(ptrd++) = (
unsigned char)*(pC1++);
42720 *(ptrd++) = (
unsigned char)*(pC2++);
42721 *(ptrd++) = (
unsigned char)*(pC3++);
42726 cimg_forY(*
this,y){
42727 unsigned short *ptrd = (
unsigned short*)(imgData[y]);
42728 cimg_forX(*
this,x) *(ptrd++) = (
unsigned short)*(pC0++);
42733 const T *pC1 =
data(0,0,0,1);
42734 cimg_forY(*
this,y){
42735 unsigned short *ptrd = (
unsigned short*)(imgData[y]);
42736 cimg_forX(*
this,x) {
42737 *(ptrd++) = (
unsigned short)*(pC0++);
42738 *(ptrd++) = (
unsigned short)*(pC1++);
42744 const T *pC1 =
data(0,0,0,1), *pC2 =
data(0,0,0,2);
42745 cimg_forY(*
this,y) {
42746 unsigned short *ptrd = (
unsigned short*)(imgData[y]);
42747 cimg_forX(*
this,x) {
42748 *(ptrd++) = (
unsigned short)*(pC0++);
42749 *(ptrd++) = (
unsigned short)*(pC1++);
42750 *(ptrd++) = (
unsigned short)*(pC2++);
42756 const T *pC1 =
data(0,0,0,1), *pC2 =
data(0,0,0,2), *pC3 =
data(0,0,0,3);
42757 cimg_forY(*
this,y) {
42758 unsigned short *ptrd = (
unsigned short*)(imgData[y]);
42759 cimg_forX(*
this,x) {
42760 *(ptrd++) = (
unsigned short)*(pC0++);
42761 *(ptrd++) = (
unsigned short)*(pC1++);
42762 *(ptrd++) = (
unsigned short)*(pC2++);
42763 *(ptrd++) = (
unsigned short)*(pC3++);
42770 throw CImgIOException(_cimg_instance
42771 "save_png(): Encountered unknown fatal error in libpng when saving file '%s'.",
42773 nfilename?nfilename:
"(FILE*)");
42775 png_write_image(png_ptr,imgData);
42776 png_write_end(png_ptr,info_ptr);
42777 png_destroy_write_struct(&png_ptr, &info_ptr);
42780 cimg_forY(*
this,n) delete[] imgData[n];
42783 if (!file) cimg::fclose(nfile);
42793 const CImg<T>&
save_pnm(
const char *
const filename,
const unsigned int bytes_per_pixel=0)
const {
42794 return _save_pnm(0,filename,bytes_per_pixel);
42799 return _save_pnm(file,0,bytes_per_pixel);
42802 const CImg<T>& _save_pnm(std::FILE *
const file,
const char *
const filename,
42803 const unsigned int bytes_per_pixel=0)
const {
42804 if (!file && !filename)
42806 "save_pnm(): Specified filename is (null).",
42810 double stmin, stmax = (double)
max_min(stmin);
42813 "save_pnm(): Instance is volumetric, only the first slice will be saved in file '%s'.",
42815 filename?filename:
"(FILE*)");
42818 "save_pnm(): Instance is multispectral, only the three first channels will be saved in file '%s'.",
42820 filename?filename:
"(FILE*)");
42821 if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536)
42823 "save_pnm(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.",
42825 stmin,stmax,filename?filename:
"(FILE*)");
42827 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"wb");
42829 *ptr_r =
data(0,0,0,0),
42830 *ptr_g = (_spectrum>=2)?
data(0,0,0,1):0,
42831 *ptr_b = (_spectrum>=3)?
data(0,0,0,2):0;
42832 const unsigned long buf_size =
cimg::min(1024*1024UL,_width*_height*(_spectrum==1?1UL:3UL));
42834 std::fprintf(nfile,
"P%c\n%u %u\n%u\n",
42835 (_spectrum==1?
'5':
'6'),_width,_height,stmax<256?255:(stmax<4096?4095:65535));
42837 switch (_spectrum) {
42839 if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) {
42840 CImg<ucharT> buf(buf_size);
42841 for (
long to_write = (
long)_width*_height; to_write>0; ) {
42842 const unsigned long N =
cimg::min((
unsigned long)to_write,buf_size);
42843 unsigned char *ptrd = buf._data;
42844 for (
unsigned long i = N; i>0; --i) *(ptrd++) = (
unsigned char)*(ptr_r++);
42849 CImg<ushortT> buf(buf_size);
42850 for (
long to_write = (
long)_width*_height; to_write>0; ) {
42851 const unsigned long N =
cimg::min((
unsigned long)to_write,buf_size);
42852 unsigned short *ptrd = buf._data;
42853 for (
unsigned long i = N; i>0; --i) *(ptrd++) = (
unsigned short)*(ptr_r++);
42861 if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) {
42862 CImg<ucharT> buf(buf_size);
42863 for (
long to_write = (
long)_width*_height; to_write>0; ) {
42864 const unsigned long N =
cimg::min((
unsigned long)to_write,buf_size/3);
42865 unsigned char *ptrd = buf._data;
42866 for (
unsigned long i = N; i>0; --i) {
42867 *(ptrd++) = (
unsigned char)*(ptr_r++);
42868 *(ptrd++) = (
unsigned char)*(ptr_g++);
42875 CImg<ushortT> buf(buf_size);
42876 for (
long to_write = (
long)_width*_height; to_write>0; ) {
42877 const unsigned long N =
cimg::min((
unsigned long)to_write,buf_size/3);
42878 unsigned short *ptrd = buf._data;
42879 for (
unsigned long i = N; i>0; --i) {
42880 *(ptrd++) = (
unsigned short)*(ptr_r++);
42881 *(ptrd++) = (
unsigned short)*(ptr_g++);
42891 if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) {
42892 CImg<ucharT> buf(buf_size);
42893 for (
long to_write = (
long)_width*_height; to_write>0; ) {
42894 const unsigned long N =
cimg::min((
unsigned long)to_write,buf_size/3);
42895 unsigned char *ptrd = buf._data;
42896 for (
unsigned long i = N; i>0; --i) {
42897 *(ptrd++) = (
unsigned char)*(ptr_r++);
42898 *(ptrd++) = (
unsigned char)*(ptr_g++);
42899 *(ptrd++) = (
unsigned char)*(ptr_b++);
42905 CImg<ushortT> buf(buf_size);
42906 for (
long to_write = (
long)_width*_height; to_write>0; ) {
42907 const unsigned long N =
cimg::min((
unsigned long)to_write,buf_size/3);
42908 unsigned short *ptrd = buf._data;
42909 for (
unsigned long i = N; i>0; --i) {
42910 *(ptrd++) = (
unsigned short)*(ptr_r++);
42911 *(ptrd++) = (
unsigned short)*(ptr_g++);
42912 *(ptrd++) = (
unsigned short)*(ptr_b++);
42930 return _save_pnk(0,filename);
42935 return _save_pnk(file,0);
42938 const CImg<T>& _save_pnk(std::FILE *
const file,
const char *
const filename)
const {
42939 if (!file && !filename)
42941 "save_pnk(): Specified filename is (null).",
42946 "save_pnk(): Instance is multispectral, only the first channel will be saved in file '%s'.",
42948 filename?filename:
"(FILE*)");
42950 const unsigned long buf_size =
cimg::min(1024*1024LU,_width*_height*_depth);
42951 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"wb");
42952 const T *ptr =
data(0,0,0,0);
42954 if (!cimg::type<T>::is_float() &&
sizeof(T)==1 && _depth<2)
42955 _save_pnm(file,filename,0);
42956 else if (!cimg::type<T>::is_float() &&
sizeof(T)==1) {
42957 std::fprintf(nfile,
"P5\n%u %u %u\n255\n",_width,_height,_depth);
42958 CImg<ucharT> buf(buf_size);
42959 for (
long to_write = (
long)_width*_height*_depth; to_write>0; ) {
42960 const unsigned long N =
cimg::min((
unsigned long)to_write,buf_size);
42961 unsigned char *ptrd = buf._data;
42962 for (
unsigned long i = N; i>0; --i) *(ptrd++) = (
unsigned char)*(ptr++);
42966 }
else if (!cimg::type<T>::is_float()) {
42967 if (_depth>1) std::fprintf(nfile,
"P8\n%u %u %u\n%d\n",_width,_height,_depth,(
int)
max());
42968 else std::fprintf(nfile,
"P8\n%u %u\n%d\n",_width,_height,(
int)
max());
42969 CImg<intT> buf(buf_size);
42970 for (
long to_write = (
long)_width*_height*_depth; to_write>0; ) {
42971 const unsigned long N =
cimg::min((
unsigned long)to_write,buf_size);
42972 int *ptrd = buf._data;
42973 for (
unsigned long i = N; i>0; --i) *(ptrd++) = (int)*(ptr++);
42978 if (_depth>1) std::fprintf(nfile,
"P9\n%u %u %u\n%g\n",_width,_height,_depth,(
double)
max());
42979 else std::fprintf(nfile,
"P9\n%u %u\n%g\n",_width,_height,(
double)
max());
42980 CImg<floatT> buf(buf_size);
42981 for (
long to_write = (
long)_width*_height*_depth; to_write>0; ) {
42982 const unsigned long N =
cimg::min((
unsigned long)to_write,buf_size);
42983 float *ptrd = buf._data;
42984 for (
unsigned long i = N; i>0; --i) *(ptrd++) = (float)*(ptr++);
42999 return get_mirror(
'y')._save_pfm(0,filename);
43007 const CImg<T>& _save_pfm(std::FILE *
const file,
const char *
const filename)
const {
43008 if (!file && !filename)
43010 "save_pfm(): Specified filename is (null).",
43015 "save_pfm(): Instance is volumetric, only the first slice will be saved in file '%s'.",
43017 filename?filename:
"(FILE*)");
43020 "save_pfm(): image instance is multispectral, only the three first channels will be saved "
43023 filename?filename:
"(FILE*)");
43025 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"wb");
43027 *ptr_r =
data(0,0,0,0),
43028 *ptr_g = (_spectrum>=2)?
data(0,0,0,1):0,
43029 *ptr_b = (_spectrum>=3)?
data(0,0,0,2):0;
43030 const unsigned int buf_size =
cimg::min(1024*1024U,_width*_height*(_spectrum==1?1:3));
43032 std::fprintf(nfile,
"P%c\n%u %u\n1.0\n",
43033 (_spectrum==1?
'f':
'F'),_width,_height);
43035 switch (_spectrum) {
43037 CImg<floatT> buf(buf_size);
43038 for (
long to_write = (
long)_width*_height; to_write>0; ) {
43039 const unsigned long N =
cimg::min((
unsigned long)to_write,buf_size);
43040 float *ptrd = buf._data;
43041 for (
unsigned long i = N; i>0; --i) *(ptrd++) = (float)*(ptr_r++);
43048 CImg<floatT> buf(buf_size);
43049 for (
long to_write = (
long)_width*_height; to_write>0; ) {
43050 const unsigned int N =
cimg::min((
unsigned int)to_write,buf_size/3);
43051 float *ptrd = buf._data;
43052 for (
unsigned long i = N; i>0; --i) {
43053 *(ptrd++) = (
float)*(ptr_r++);
43054 *(ptrd++) = (
float)*(ptr_g++);
43063 CImg<floatT> buf(buf_size);
43064 for (
long to_write = (
long)_width*_height; to_write>0; ) {
43065 const unsigned int N =
cimg::min((
unsigned int)to_write,buf_size/3);
43066 float *ptrd = buf._data;
43067 for (
unsigned long i = N; i>0; --i) {
43068 *(ptrd++) = (
float)*(ptr_r++);
43069 *(ptrd++) = (
float)*(ptr_g++);
43070 *(ptrd++) = (
float)*(ptr_b++);
43087 return _save_rgb(0,filename);
43092 return _save_rgb(file,0);
43095 const CImg<T>& _save_rgb(std::FILE *
const file,
const char *
const filename)
const {
43096 if (!file && !filename)
43098 "save_rgb(): Specified filename is (null).",
43103 "save_rgb(): image instance has not exactly 3 channels, for file '%s'.",
43105 filename?filename:
"(FILE*)");
43107 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"wb");
43108 const unsigned long wh = (
unsigned long)_width*_height;
43109 unsigned char *
const buffer =
new unsigned char[3*wh], *nbuffer = buffer;
43111 *ptr1 =
data(0,0,0,0),
43112 *ptr2 = _spectrum>1?
data(0,0,0,1):0,
43113 *ptr3 = _spectrum>2?data(0,0,0,2):0;
43114 switch (_spectrum) {
43116 for (
unsigned long k = 0; k<wh; ++k) {
43117 const unsigned char val = (
unsigned char)*(ptr1++);
43118 *(nbuffer++) = val;
43119 *(nbuffer++) = val;
43120 *(nbuffer++) = val;
43124 for (
unsigned long k = 0; k<wh; ++k) {
43125 *(nbuffer++) = (
unsigned char)(*(ptr1++));
43126 *(nbuffer++) = (
unsigned char)(*(ptr2++));
43131 for (
unsigned long k = 0; k<wh; ++k) {
43132 *(nbuffer++) = (
unsigned char)(*(ptr1++));
43133 *(nbuffer++) = (
unsigned char)(*(ptr2++));
43134 *(nbuffer++) = (
unsigned char)(*(ptr3++));
43149 return _save_rgba(0,filename);
43154 return _save_rgba(file,0);
43157 const CImg<T>& _save_rgba(std::FILE *
const file,
const char *
const filename)
const {
43158 if (!file && !filename)
43160 "save_rgba(): Specified filename is (null).",
43165 "save_rgba(): image instance has not exactly 4 channels, for file '%s'.",
43167 filename?filename:
"(FILE*)");
43169 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"wb");
43170 const unsigned long wh = (
unsigned long)_width*_height;
43171 unsigned char *
const buffer =
new unsigned char[4*wh], *nbuffer = buffer;
43173 *ptr1 =
data(0,0,0,0),
43174 *ptr2 = _spectrum>1?
data(0,0,0,1):0,
43175 *ptr3 = _spectrum>2?data(0,0,0,2):0,
43176 *ptr4 = _spectrum>3?data(0,0,0,3):0;
43177 switch (_spectrum) {
43179 for (
unsigned long k = 0; k<wh; ++k) {
43180 const unsigned char val = (
unsigned char)*(ptr1++);
43181 *(nbuffer++) = val;
43182 *(nbuffer++) = val;
43183 *(nbuffer++) = val;
43184 *(nbuffer++) = 255;
43188 for (
unsigned long k = 0; k<wh; ++k) {
43189 *(nbuffer++) = (
unsigned char)(*(ptr1++));
43190 *(nbuffer++) = (
unsigned char)(*(ptr2++));
43192 *(nbuffer++) = 255;
43196 for (
unsigned long k = 0; k<wh; ++k) {
43197 *(nbuffer++) = (
unsigned char)(*(ptr1++));
43198 *(nbuffer++) = (
unsigned char)(*(ptr2++));
43199 *(nbuffer++) = (
unsigned char)(*(ptr3++));
43200 *(nbuffer++) = 255;
43204 for (
unsigned long k = 0; k<wh; ++k) {
43205 *(nbuffer++) = (
unsigned char)(*(ptr1++));
43206 *(nbuffer++) = (
unsigned char)(*(ptr2++));
43207 *(nbuffer++) = (
unsigned char)(*(ptr3++));
43208 *(nbuffer++) = (
unsigned char)(*(ptr4++));
43232 const CImg<T>&
save_tiff(
const char *
const filename,
const unsigned int compression_type=0)
const {
43235 "save_tiff(): Specified filename is (null).",
43239 #ifdef cimg_use_tiff
43240 TIFF *tif = TIFFOpen(filename,
"w");
43242 cimg_forZ(*
this,z)
get_slice(z)._save_tiff(tif,z,compression_type);
43245 "save_tiff(): Failed to open file '%s' for writing.",
43255 #ifdef cimg_use_tiff
43257 #define _cimg_save_tiff(types,typed,compression_type) if (!std::strcmp(types,pixel_type())) { \
43258 const typed foo = (typed)0; return _save_tiff(tif,directory,foo,compression_type); }
43261 template<
typename t>
43262 const CImg<T>& _save_tiff(TIFF *tif,
const unsigned int directory,
const t& pixel_t,
43263 const unsigned int compression_type)
const {
43264 if (
is_empty() || !tif || pixel_t)
return *
this;
43265 const char *
const filename = TIFFFileName(tif);
43266 uint32 rowsperstrip = (uint32)-1;
43267 uint16 spp = _spectrum, bpp =
sizeof(t)*8, photometric;
43268 if (spp==3 || spp==4) photometric = PHOTOMETRIC_RGB;
43269 else photometric = PHOTOMETRIC_MINISBLACK;
43270 TIFFSetDirectory(tif,directory);
43271 TIFFSetField(tif,TIFFTAG_IMAGEWIDTH,_width);
43272 TIFFSetField(tif,TIFFTAG_IMAGELENGTH,_height);
43273 TIFFSetField(tif,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT);
43274 TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,spp);
43277 else TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,2);
43278 TIFFSetField(tif,TIFFTAG_BITSPERSAMPLE,bpp);
43279 TIFFSetField(tif,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG);
43280 TIFFSetField(tif,TIFFTAG_PHOTOMETRIC,photometric);
43281 TIFFSetField(tif,TIFFTAG_COMPRESSION,compression_type?(compression_type-1):COMPRESSION_NONE);
43282 rowsperstrip = TIFFDefaultStripSize(tif,rowsperstrip);
43283 TIFFSetField(tif,TIFFTAG_ROWSPERSTRIP,rowsperstrip);
43284 TIFFSetField(tif,TIFFTAG_FILLORDER,FILLORDER_MSB2LSB);
43285 TIFFSetField(tif,TIFFTAG_SOFTWARE,
"CImg");
43286 t *
const buf = (t*)_TIFFmalloc(TIFFStripSize(tif));
43288 for (
unsigned int row = 0; row<_height; row+=rowsperstrip) {
43289 uint32 nrow = (row + rowsperstrip>_height?_height-row:rowsperstrip);
43290 tstrip_t strip = TIFFComputeStrip(tif,row,0);
43292 for (
unsigned int rr = 0; rr<nrow; ++rr)
43293 for (
unsigned int cc = 0; cc<_width; ++cc)
43294 for (
unsigned int vv = 0; vv<spp; ++vv)
43295 buf[i++] = (t)(*this)(cc,row + rr,0,vv);
43296 if (TIFFWriteEncodedStrip(tif,strip,buf,i*
sizeof(t))<0)
43298 "save_tiff(): Invalid strip writing when saving file '%s'.",
43300 filename?filename:
"(FILE*)");
43304 TIFFWriteDirectory(tif);
43308 const CImg<T>& _save_tiff(TIFF *tif,
const unsigned int directory,
const unsigned int compression_type)
const {
43309 _cimg_save_tiff(
"bool",
unsigned char,compression_type);
43310 _cimg_save_tiff(
"char",
char,compression_type);
43311 _cimg_save_tiff(
"unsigned char",
unsigned char,compression_type);
43312 _cimg_save_tiff(
"short",
short,compression_type);
43313 _cimg_save_tiff(
"unsigned short",
unsigned short,compression_type);
43314 _cimg_save_tiff(
"int",
int,compression_type);
43315 _cimg_save_tiff(
"unsigned int",
unsigned int,compression_type);
43316 _cimg_save_tiff(
"long",
int,compression_type);
43317 _cimg_save_tiff(
"unsigned long",
unsigned int,compression_type);
43318 _cimg_save_tiff(
"float",
float,compression_type);
43319 _cimg_save_tiff(
"double",
float,compression_type);
43320 const char *
const filename = TIFFFileName(tif);
43321 throw CImgInstanceException(_cimg_instance
43322 "save_tiff(): Unsupported pixel type '%s' for file '%s'.",
43335 const char *
const imitate_file=0)
const {
43338 "save_minc2(): Specified filename is (null).",
43342 #ifndef cimg_use_minc2
43346 minc::minc_1_writer wtr;
43348 wtr.open(filename, imitate_file);
43350 minc::minc_info di;
43351 if(
width()) di.push_back(minc::dim_info(
width(),
width()*0.5, -1, minc::dim_info::DIM_X));
43352 if(
height()) di.push_back(minc::dim_info(
height(),
height()*0.5, -1, minc::dim_info::DIM_Y));
43353 if(
depth()) di.push_back(minc::dim_info(
depth(),
depth()*0.5, -1, minc::dim_info::DIM_Z));
43355 wtr.open(filename, di, 1, NC_FLOAT, 0);
43357 if(
typeid(T)==
typeid(
unsigned char))
43358 wtr.setup_write_byte();
43359 else if(
typeid(T)==
typeid(
int))
43360 wtr.setup_write_int();
43361 else if(
typeid(T)==
typeid(
double))
43362 wtr.setup_write_double();
43364 wtr.setup_write_float();
43365 minc::save_standard_volume(wtr, this->_data);
43378 "save_analyze(): Specified filename is (null).",
43383 char header[348] = { 0 }, hname[1024] = { 0 }, iname[1024] = { 0 };
43386 std::memset(header,0,348);
43388 cimg_snprintf(hname,
sizeof(hname),
"%s.hdr",filename);
43389 cimg_snprintf(iname,
sizeof(iname),
"%s.img",filename);
43392 std::strcpy(hname,filename);
43393 std::strncpy(iname,filename,
sizeof(iname)-1);
43394 std::sprintf(iname + std::strlen(iname)-3,
"img");
43397 std::strcpy(hname,filename);
43398 std::strncpy(iname,filename,
sizeof(iname)-1);
43399 std::sprintf(hname + std::strlen(iname)-3,
"hdr");
43402 std::strncpy(hname,filename,
sizeof(hname)-1); *iname = 0;
43404 int *
const iheader = (
int*)header;
43406 std::strcpy(header + 4,
"CImg");
43407 std::strcpy(header + 14,
" ");
43408 ((
short*)(header + 36))[0] = 4096;
43409 ((
char*)(header + 38))[0] = 114;
43410 ((
short*)(header + 40))[0] = 4;
43411 ((
short*)(header + 40))[1] = _width;
43412 ((
short*)(header + 40))[2] = _height;
43413 ((
short*)(header + 40))[3] = _depth;
43414 ((
short*)(header + 40))[4] = _spectrum;
43428 "save_analyze(): Unsupported pixel type '%s' for file '%s'.",
43432 ((
short*)(header+70))[0] = datatype;
43433 ((
short*)(header+72))[0] =
sizeof(T);
43434 ((
float*)(header+112))[0] = 1;
43435 ((
float*)(header+76))[0] = 0;
43437 ((
float*)(header+76))[1] = voxel_size[0];
43438 ((
float*)(header+76))[2] = voxel_size[1];
43439 ((
float*)(header+76))[3] = voxel_size[2];
43440 }
else ((
float*)(header+76))[1] = ((
float*)(header+76))[2] = ((
float*)(header+76))[3] = 1;
43475 const unsigned int n0,
43476 const unsigned int x0,
const unsigned int y0,
43477 const unsigned int z0,
const unsigned int c0)
const {
43484 const unsigned int n0,
43485 const unsigned int x0,
const unsigned int y0,
43486 const unsigned int z0,
const unsigned int c0)
const {
43503 const unsigned int dx,
const unsigned int dy=1,
43504 const unsigned int dz=1,
const unsigned int dc=1) {
43514 const unsigned int dx,
const unsigned int dy=1,
43515 const unsigned int dz=1,
const unsigned int dc=1) {
43525 return _save_inr(0,filename,voxel_size);
43530 return _save_inr(file,0,voxel_size);
43533 const CImg<T>& _save_inr(std::FILE *
const file,
const char *
const filename,
const float *
const voxel_size)
const {
43534 if (!file && !filename)
43536 "save_inr(): Specified filename is (null).",
43541 const char *inrtype =
"unsigned fixed\nPIXSIZE=8 bits\nSCALE=2**0";
43543 inrtype =
"unsigned fixed\nPIXSIZE=8 bits\nSCALE=2**0"; inrpixsize = 1;
43546 inrtype =
"fixed\nPIXSIZE=8 bits\nSCALE=2**0"; inrpixsize = 1;
43549 inrtype =
"unsigned fixed\nPIXSIZE=16 bits\nSCALE=2**0";inrpixsize = 2;
43552 inrtype =
"fixed\nPIXSIZE=16 bits\nSCALE=2**0"; inrpixsize = 2;
43555 inrtype =
"unsigned fixed\nPIXSIZE=32 bits\nSCALE=2**0";inrpixsize = 4;
43558 inrtype =
"fixed\nPIXSIZE=32 bits\nSCALE=2**0"; inrpixsize = 4;
43561 inrtype =
"float\nPIXSIZE=32 bits"; inrpixsize = 4;
43564 inrtype =
"float\nPIXSIZE=64 bits"; inrpixsize = 8;
43567 throw CImgIOException(_cimg_instance
43568 "save_inr(): Unsupported pixel type '%s' for file '%s'",
43572 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"wb");
43573 char header[257] = { 0 };
43574 int err = cimg_snprintf(header,
sizeof(header),
"#INRIMAGE-4#{\nXDIM=%u\nYDIM=%u\nZDIM=%u\nVDIM=%u\n",
43575 _width,_height,_depth,_spectrum);
43576 if (voxel_size) err+=std::sprintf(header + err,
"VX=%g\nVY=%g\nVZ=%g\n",voxel_size[0],voxel_size[1],voxel_size[2]);
43577 err+=std::sprintf(header + err,
"TYPE=%s\nCPU=%s\n",inrtype,
cimg::endianness()?
"sun":
"decm");
43578 std::memset(header + err,
'\n',252 - err);
43579 std::memcpy(header + 252,
"##}\n",4);
43581 cimg_forXYZ(*
this,x,y,z) cimg_forC(*this,c) cimg::fwrite(&((*this)(x,y,z,c)),1,nfile);
43582 if (!file) cimg::fclose(nfile);
43594 "save_exr(): Specified filename is (null).",
43599 "save_exr(): Instance is volumetric, only the first slice will be saved in file '%s'.",
43603 #ifndef cimg_use_openexr
43606 Imf::Rgba *
const ptrd0 =
new Imf::Rgba[(
unsigned long)_width*_height], *ptrd = ptrd0, rgba;
43607 switch (_spectrum) {
43609 for (
const T *ptr_r =
data(), *
const ptr_e = ptr_r + (
unsigned long)_width*_height; ptr_r<ptr_e;) {
43610 rgba.r = rgba.g = rgba.b = (half)(*(ptr_r++));
43616 for (
const T *ptr_r =
data(), *ptr_g =
data(0,0,0,1),
43617 *
const ptr_e = ptr_r + (
unsigned long)_width*_height; ptr_r<ptr_e; ) {
43618 rgba.r = (half)(*(ptr_r++));
43619 rgba.g = (half)(*(ptr_g++));
43626 for (
const T *ptr_r =
data(), *ptr_g =
data(0,0,0,1), *ptr_b =
data(0,0,0,2),
43627 *
const ptr_e = ptr_r + (
unsigned long)_width*_height; ptr_r<ptr_e;) {
43628 rgba.r = (half)(*(ptr_r++));
43629 rgba.g = (half)(*(ptr_g++));
43630 rgba.b = (half)(*(ptr_b++));
43636 for (
const T *ptr_r =
data(), *ptr_g =
data(0,0,0,1), *ptr_b =
data(0,0,0,2), *ptr_a =
data(0,0,0,3),
43637 *
const ptr_e = ptr_r + (
unsigned long)_width*_height; ptr_r<ptr_e;) {
43638 rgba.r = (half)(*(ptr_r++));
43639 rgba.g = (half)(*(ptr_g++));
43640 rgba.b = (half)(*(ptr_b++));
43641 rgba.a = (half)(*(ptr_a++));
43646 Imf::RgbaOutputFile outFile(filename,_width,_height,
43647 _spectrum==1?Imf::WRITE_Y:_spectrum==2?Imf::WRITE_YA:_spectrum==3?
43648 Imf::WRITE_RGB:Imf::WRITE_RGBA);
43649 outFile.setFrameBuffer(ptrd0,1,_width);
43650 outFile.writePixels(_height);
43664 return _save_pandore(0,filename,colorspace);
43673 return _save_pandore(file,0,colorspace);
43676 unsigned int _save_pandore_header_length(
unsigned int id,
unsigned int *dims,
const unsigned int colorspace)
const {
43677 unsigned int nbdims = 0;
43678 if (
id==2 ||
id==3 ||
id==4) {
43679 dims[0] = 1; dims[1] = _width; nbdims = 2;
43681 if (
id==5 ||
id==6 ||
id==7) {
43682 dims[0] = 1; dims[1] = _height; dims[2] = _width; nbdims=3;
43684 if (
id==8 ||
id==9 ||
id==10) {
43685 dims[0] = _spectrum; dims[1] = _depth; dims[2] = _height; dims[3] = _width; nbdims = 4;
43687 if (
id==16 ||
id==17 ||
id==18) {
43688 dims[0] = 3; dims[1] = _height; dims[2] = _width; dims[3] = colorspace; nbdims = 4;
43690 if (
id==19 ||
id==20 ||
id==21) {
43691 dims[0] = 3; dims[1] = _depth; dims[2] = _height; dims[3] = _width; dims[4] = colorspace; nbdims = 5;
43693 if (
id==22 ||
id==23 ||
id==25) {
43694 dims[0] = _spectrum; dims[1] = _width; nbdims = 2;
43696 if (
id==26 ||
id==27 ||
id==29) {
43697 dims[0] = _spectrum; dims[1] = _height; dims[2] = _width; nbdims=3;
43699 if (
id==30 ||
id==31 ||
id==33) {
43700 dims[0] = _spectrum; dims[1] = _depth; dims[2] = _height; dims[3] = _width; nbdims = 4;
43705 const CImg<T>& _save_pandore(std::FILE *
const file,
const char *
const filename,
43706 const unsigned int colorspace)
const {
43708 #define __cimg_save_pandore_case(dtype) \
43709 dtype *buffer = new dtype[size()]; \
43710 const T *ptrs = _data; \
43711 cimg_foroff(*this,off) *(buffer++) = (dtype)(*(ptrs++)); \
43713 cimg::fwrite(buffer,size(),nfile); \
43716 #define _cimg_save_pandore_case(sy,sz,sv,stype,id) \
43717 if (!saved && (sy?(sy==_height):true) && (sz?(sz==_depth):true) && \
43718 (sv?(sv==_spectrum):true) && !std::strcmp(stype,pixel_type())) { \
43719 unsigned int *iheader = (unsigned int*)(header+12); \
43720 nbdims = _save_pandore_header_length((*iheader=id),dims,colorspace); \
43721 cimg::fwrite(header,36,nfile); \
43722 if (sizeof(unsigned long)==4) { unsigned long ndims[5] = { 0 }; \
43723 for (int d = 0; d<5; ++d) ndims[d] = (unsigned long)dims[d]; cimg::fwrite(ndims,nbdims,nfile); } \
43724 else if (sizeof(unsigned int)==4) { unsigned int ndims[5] = { 0 }; \
43725 for (int d = 0; d<5; ++d) ndims[d] = (unsigned int)dims[d]; cimg::fwrite(ndims,nbdims,nfile); } \
43726 else if (sizeof(unsigned short)==4) { unsigned short ndims[5] = { 0 }; \
43727 for (int d = 0; d<5; ++d) ndims[d] = (unsigned short)dims[d]; cimg::fwrite(ndims,nbdims,nfile); } \
43728 else throw CImgIOException(_cimg_instance \
43729 "save_pandore(): Unsupported datatype for file '%s'.",\
43731 filename?filename:"(FILE*)"); \
43732 if (id==2 || id==5 || id==8 || id==16 || id==19 || id==22 || id==26 || id==30) { \
43733 __cimg_save_pandore_case(unsigned char); \
43734 } else if (id==3 || id==6 || id==9 || id==17 || id==20 || id==23 || id==27 || id==31) { \
43735 if (sizeof(unsigned long)==4) { __cimg_save_pandore_case(unsigned long); } \
43736 else if (sizeof(unsigned int)==4) { __cimg_save_pandore_case(unsigned int); } \
43737 else if (sizeof(unsigned short)==4) { __cimg_save_pandore_case(unsigned short); } \
43738 else throw CImgIOException(_cimg_instance \
43739 "save_pandore(): Unsupported datatype for file '%s'.",\
43741 filename?filename:"(FILE*)"); \
43742 } else if (id==4 || id==7 || id==10 || id==18 || id==21 || id==25 || id==29 || id==33) { \
43743 if (sizeof(double)==4) { __cimg_save_pandore_case(double); } \
43744 else if (sizeof(float)==4) { __cimg_save_pandore_case(float); } \
43745 else throw CImgIOException(_cimg_instance \
43746 "save_pandore(): Unsupported datatype for file '%s'.",\
43748 filename?filename:"(FILE*)"); \
43753 if (!file && !filename)
43754 throw CImgArgumentException(_cimg_instance
43755 "save_pandore(): Specified filename is (null).",
43759 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"wb");
43760 unsigned char header[36] = {
'P',
'A',
'N',
'D',
'O',
'R',
'E',
'0',
'4',0,0,0,
43761 0,0,0,0,
'C',
'I',
'm',
'g',0,0,0,0,0,
'N',
'o',
' ',
'd',
'a',
't',
'e',0,0,0,0 };
43762 unsigned int nbdims, dims[5] = { 0 };
43763 bool saved =
false;
43764 _cimg_save_pandore_case(1,1,1,
"unsigned char",2);
43765 _cimg_save_pandore_case(1,1,1,
"char",3);
43766 _cimg_save_pandore_case(1,1,1,
"short",3);
43767 _cimg_save_pandore_case(1,1,1,
"unsigned short",3);
43768 _cimg_save_pandore_case(1,1,1,
"unsigned int",3);
43769 _cimg_save_pandore_case(1,1,1,
"int",3);
43770 _cimg_save_pandore_case(1,1,1,
"unsigned long",4);
43771 _cimg_save_pandore_case(1,1,1,
"long",3);
43772 _cimg_save_pandore_case(1,1,1,
"float",4);
43773 _cimg_save_pandore_case(1,1,1,
"double",4);
43775 _cimg_save_pandore_case(0,1,1,
"unsigned char",5);
43776 _cimg_save_pandore_case(0,1,1,
"char",6);
43777 _cimg_save_pandore_case(0,1,1,
"short",6);
43778 _cimg_save_pandore_case(0,1,1,
"unsigned short",6);
43779 _cimg_save_pandore_case(0,1,1,
"unsigned int",6);
43780 _cimg_save_pandore_case(0,1,1,
"int",6);
43781 _cimg_save_pandore_case(0,1,1,
"unsigned long",7);
43782 _cimg_save_pandore_case(0,1,1,
"long",6);
43783 _cimg_save_pandore_case(0,1,1,
"float",7);
43784 _cimg_save_pandore_case(0,1,1,
"double",7);
43786 _cimg_save_pandore_case(0,0,1,
"unsigned char",8);
43787 _cimg_save_pandore_case(0,0,1,
"char",9);
43788 _cimg_save_pandore_case(0,0,1,
"short",9);
43789 _cimg_save_pandore_case(0,0,1,
"unsigned short",9);
43790 _cimg_save_pandore_case(0,0,1,
"unsigned int",9);
43791 _cimg_save_pandore_case(0,0,1,
"int",9);
43792 _cimg_save_pandore_case(0,0,1,
"unsigned long",10);
43793 _cimg_save_pandore_case(0,0,1,
"long",9);
43794 _cimg_save_pandore_case(0,0,1,
"float",10);
43795 _cimg_save_pandore_case(0,0,1,
"double",10);
43797 _cimg_save_pandore_case(0,1,3,
"unsigned char",16);
43798 _cimg_save_pandore_case(0,1,3,
"char",17);
43799 _cimg_save_pandore_case(0,1,3,
"short",17);
43800 _cimg_save_pandore_case(0,1,3,
"unsigned short",17);
43801 _cimg_save_pandore_case(0,1,3,
"unsigned int",17);
43802 _cimg_save_pandore_case(0,1,3,
"int",17);
43803 _cimg_save_pandore_case(0,1,3,
"unsigned long",18);
43804 _cimg_save_pandore_case(0,1,3,
"long",17);
43805 _cimg_save_pandore_case(0,1,3,
"float",18);
43806 _cimg_save_pandore_case(0,1,3,
"double",18);
43808 _cimg_save_pandore_case(0,0,3,
"unsigned char",19);
43809 _cimg_save_pandore_case(0,0,3,
"char",20);
43810 _cimg_save_pandore_case(0,0,3,
"short",20);
43811 _cimg_save_pandore_case(0,0,3,
"unsigned short",20);
43812 _cimg_save_pandore_case(0,0,3,
"unsigned int",20);
43813 _cimg_save_pandore_case(0,0,3,
"int",20);
43814 _cimg_save_pandore_case(0,0,3,
"unsigned long",21);
43815 _cimg_save_pandore_case(0,0,3,
"long",20);
43816 _cimg_save_pandore_case(0,0,3,
"float",21);
43817 _cimg_save_pandore_case(0,0,3,
"double",21);
43819 _cimg_save_pandore_case(1,1,0,
"unsigned char",22);
43820 _cimg_save_pandore_case(1,1,0,
"char",23);
43821 _cimg_save_pandore_case(1,1,0,
"short",23);
43822 _cimg_save_pandore_case(1,1,0,
"unsigned short",23);
43823 _cimg_save_pandore_case(1,1,0,
"unsigned int",23);
43824 _cimg_save_pandore_case(1,1,0,
"int",23);
43825 _cimg_save_pandore_case(1,1,0,
"unsigned long",25);
43826 _cimg_save_pandore_case(1,1,0,
"long",23);
43827 _cimg_save_pandore_case(1,1,0,
"float",25);
43828 _cimg_save_pandore_case(1,1,0,
"double",25);
43830 _cimg_save_pandore_case(0,1,0,
"unsigned char",26);
43831 _cimg_save_pandore_case(0,1,0,
"char",27);
43832 _cimg_save_pandore_case(0,1,0,
"short",27);
43833 _cimg_save_pandore_case(0,1,0,
"unsigned short",27);
43834 _cimg_save_pandore_case(0,1,0,
"unsigned int",27);
43835 _cimg_save_pandore_case(0,1,0,
"int",27);
43836 _cimg_save_pandore_case(0,1,0,
"unsigned long",29);
43837 _cimg_save_pandore_case(0,1,0,
"long",27);
43838 _cimg_save_pandore_case(0,1,0,
"float",29);
43839 _cimg_save_pandore_case(0,1,0,
"double",29);
43841 _cimg_save_pandore_case(0,0,0,
"unsigned char",30);
43842 _cimg_save_pandore_case(0,0,0,
"char",31);
43843 _cimg_save_pandore_case(0,0,0,
"short",31);
43844 _cimg_save_pandore_case(0,0,0,
"unsigned short",31);
43845 _cimg_save_pandore_case(0,0,0,
"unsigned int",31);
43846 _cimg_save_pandore_case(0,0,0,
"int",31);
43847 _cimg_save_pandore_case(0,0,0,
"unsigned long",33);
43848 _cimg_save_pandore_case(0,0,0,
"long",31);
43849 _cimg_save_pandore_case(0,0,0,
"float",33);
43850 _cimg_save_pandore_case(0,0,0,
"double",33);
43864 return _save_raw(0,filename,is_multiplexed);
43873 return _save_raw(file,0,is_multiplexed);
43876 const CImg<T>& _save_raw(std::FILE *
const file,
const char *
const filename,
const bool is_multiplexed)
const {
43877 if (!file && !filename)
43879 "save_raw(): Specified filename is (null).",
43883 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"wb");
43886 CImg<T> buf(_spectrum);
43887 cimg_forXYZ(*
this,x,y,z) {
43888 cimg_forC(*
this,c) buf[c] = (*this)(x,y,z,c);
43889 cimg::fwrite(buf._data,_spectrum,nfile);
43892 if (!file) cimg::fclose(nfile);
43909 const
unsigned int bitrate=2048)
const {
43912 "save_ffmpeg(): Specified filename is (null).",
43916 "save_ffmpeg(): Invalid specified framerate 0, for file '%s'.",
43921 #ifndef cimg_use_ffmpeg
43938 get_split(
'z').save_yuv(filename,is_rgb);
43963 template<
typename tf,
typename tc>
43965 const char *
const filename)
const {
43966 return _save_off(primitives,colors,0,filename);
43974 template<
typename tf,
typename tc>
43976 std::FILE *
const file)
const {
43977 return _save_off(primitives,colors,file,0);
43980 template<
typename tf,
typename tc>
43982 std::FILE *
const file,
const char *
const filename)
const {
43983 if (!file && !filename)
43985 "save_off(): Specified filename is (null).",
43989 "save_off(): Empty instance, for file '%s'.",
43991 filename?filename:
"(FILE*)");
43994 char error_message[1024] = { 0 };
43995 if (!
is_object3d(primitives,colors,opacities,
true,error_message))
43996 throw CImgInstanceException(_cimg_instance
43997 "save_off(): Invalid specified 3d object, for file '%s' (%s).",
43999 filename?filename:
"(FILE*)",error_message);
44001 const CImg<tc> default_color(1,3,1,1,200);
44002 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"w");
44003 unsigned int supported_primitives = 0;
44004 cimglist_for(primitives,l) if (primitives[l].size()!=5) ++supported_primitives;
44005 std::fprintf(nfile,"OFF\n%u %u %u\n",_width,supported_primitives,3*primitives._width);
44006 cimg_forX(*this,i)
std::fprintf(nfile,"%f %f %f\n",
44007 (
float)((*this)(i,0)),(
float)((*this)(i,1)),(
float)((*this)(i,2)));
44008 cimglist_for(primitives,l) {
44009 const CImg<tc>& color = l<colors.
width()?colors[l]:default_color;
44010 const unsigned int psiz = primitives[l].
size(), csiz = color.size();
44011 const float r = color[0]/255.0f, g = (csiz>1?color[1]:r)/255.0f, b = (csiz>2?color[2]:g)/255.0f;
44013 case 1 : std::fprintf(nfile,
"1 %u %f %f %f\n",
44014 (
unsigned int)primitives(l,0),r,g,b);
break;
44015 case 2 : std::fprintf(nfile,
"2 %u %u %f %f %f\n",
44016 (
unsigned int)primitives(l,0),(
unsigned int)primitives(l,1),r,g,b);
break;
44017 case 3 : std::fprintf(nfile,
"3 %u %u %u %f %f %f\n",
44018 (
unsigned int)primitives(l,0),(
unsigned int)primitives(l,2),
44019 (
unsigned int)primitives(l,1),r,g,b);
break;
44020 case 4 : std::fprintf(nfile,
"4 %u %u %u %u %f %f %f\n",
44021 (
unsigned int)primitives(l,0),(
unsigned int)primitives(l,3),
44022 (
unsigned int)primitives(l,2),(
unsigned int)primitives(l,1),r,g,b);
break;
44023 case 5 : std::fprintf(nfile,
"2 %u %u %f %f %f\n",
44024 (
unsigned int)primitives(l,0),(
unsigned int)primitives(l,1),r,g,b);
break;
44026 const unsigned int xt = (
unsigned int)primitives(l,2), yt = (
unsigned int)primitives(l,3);
44028 rt = color.atXY(xt,yt,0)/255.0f,
44029 gt = (csiz>1?color.atXY(xt,yt,1):r)/255.0f,
44030 bt = (csiz>2?color.atXY(xt,yt,2):g)/255.0f;
44031 std::fprintf(nfile,
"2 %u %u %f %f %f\n",
44032 (
unsigned int)primitives(l,0),(
unsigned int)primitives(l,1),rt,gt,bt);
44035 const unsigned int xt = (
unsigned int)primitives(l,3), yt = (
unsigned int)primitives(l,4);
44037 rt = color.atXY(xt,yt,0)/255.0f,
44038 gt = (csiz>1?color.atXY(xt,yt,1):r)/255.0f,
44039 bt = (csiz>2?color.atXY(xt,yt,2):g)/255.0f;
44040 std::fprintf(nfile,
"3 %u %u %u %f %f %f\n",
44041 (
unsigned int)primitives(l,0),(
unsigned int)primitives(l,2),
44042 (
unsigned int)primitives(l,1),rt,gt,bt);
44045 const unsigned int xt = (
unsigned int)primitives(l,4), yt = (
unsigned int)primitives(l,5);
44047 rt = color.atXY(xt,yt,0)/255.0f,
44048 gt = (csiz>1?color.atXY(xt,yt,1):r)/255.0f,
44049 bt = (csiz>2?color.atXY(xt,yt,2):g)/255.0f;
44050 std::fprintf(nfile,
"4 %u %u %u %u %f %f %f\n",
44051 (
unsigned int)primitives(l,0),(
unsigned int)primitives(l,3),
44052 (
unsigned int)primitives(l,2),(
unsigned int)primitives(l,1),rt,gt,bt);
44073 const unsigned int fps=25,
const unsigned int bitrate=2048)
const {
44076 "save_ffmpeg_external(): Specified filename is (null).",
44096 "save_gzip_external(): Specified filename is (null).",
44100 char command[1024] = { 0 }, filetmp[512] = { 0 }, body[512] = { 0 };
44107 if (*ext2) cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s.%s",
44109 else cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s.cimg",
44112 if (*ext) cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s.%s",
44114 else cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s.cimg",
44117 if ((file=std::fopen(filetmp,
"rb"))!=0)
cimg::fclose(file);
44120 cimg_snprintf(command,
sizeof(command),
"%s -c \"%s\" > \"%s\"",
44125 file = std::fopen(filename,
"rb");
44128 "save_gzip_external(): Failed to save file '%s' with external command 'gzip'.",
44133 std::remove(filetmp);
44148 "save_graphicsmagick_external(): Specified filename is (null).",
44152 #ifdef cimg_use_png
44153 #define _cimg_sge_ext1 "png"
44154 #define _cimg_sge_ext2 "png"
44156 #define _cimg_sge_ext1 "pgm"
44157 #define _cimg_sge_ext2 "ppm"
44159 char command[1024] = { 0 }, filetmp[512] = { 0 };
44162 cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s.%s",
44164 _spectrum==1?_cimg_sge_ext1:_cimg_sge_ext2);
44165 if ((file=std::fopen(filetmp,
"rb"))!=0)
cimg::fclose(file);
44167 #ifdef cimg_use_png
44172 cimg_snprintf(command,
sizeof(command),
"%s convert -quality %u \"%s\" \"%s\"",
44177 file = std::fopen(filename,
"rb");
44180 "save_graphicsmagick_external(): Failed to save file '%s' with external command 'gm'.",
44185 std::remove(filetmp);
44200 "save_imagemagick_external(): Specified filename is (null).",
44204 #ifdef cimg_use_png
44205 #define _cimg_sie_ext1 "png"
44206 #define _cimg_sie_ext2 "png"
44208 #define _cimg_sie_ext1 "pgm"
44209 #define _cimg_sie_ext2 "ppm"
44211 char command[1024] = { 0 }, filetmp[512] = { 0 };
44215 cimg_file_separator,cimg::filenamerand(),_spectrum==1?_cimg_sie_ext1:_cimg_sie_ext2);
44216 if ((file=std::fopen(filetmp,
"rb"))!=0)
cimg::fclose(file);
44218 #ifdef cimg_use_png
44223 cimg_snprintf(command,
sizeof(command),
"%s -quality %u \"%s\" \"%s\"",
44228 file = std::fopen(filename,
"rb");
44231 "save_imagemagick_external(): Failed to save file '%s' with external command 'convert'.",
44236 std::remove(filetmp);
44250 "save_medcon_external(): Specified filename is (null).",
44254 char command[1024] = { 0 }, filetmp[512] = { 0 }, body[512] = { 0 };
44257 cimg_snprintf(filetmp,
sizeof(filetmp),
"%s.hdr",cimg::filenamerand());
44258 if ((file=std::fopen(filetmp,
"rb"))!=0)
cimg::fclose(file);
44261 cimg_snprintf(command,
sizeof(command),
"%s -w -c dicom -o \"%s\" -f \"%s\"",
44266 std::remove(filetmp);
44268 cimg_snprintf(filetmp,
sizeof(filetmp),
"%s.img",body);
44269 std::remove(filetmp);
44271 file = std::fopen(filename,
"rb");
44273 cimg_snprintf(command,
sizeof(command),
"m000-%s",filename);
44274 file = std::fopen(command,
"rb");
44278 "save_medcon_external(): Failed to save file '%s' with external command 'medcon'.",
44284 std::rename(command,filename);
44304 "save_other(): Specified filename is (null).",
44309 bool is_saved =
true;
44324 "save_other(): Failed to save file '%s'. Format is not natively supported, "
44325 "and no external commands succeeded.",
44332 static CImg<T> _logo40x38() {
44334 const unsigned char *ptrs = cimg::logo40x38;
44335 T *ptr1 = res.data(0,0,0,0), *ptr2 = res.data(0,0,0,1), *ptr3 = res.data(0,0,0,2);
44336 for (
unsigned long off = 0; off<(
unsigned long)res._width*res._height;) {
44337 const unsigned char n = *(ptrs++), r = *(ptrs++), g = *(ptrs++), b = *(ptrs++);
44338 for (
unsigned int l = 0; l<n; ++off, ++l) { *(ptr1++) = (T)r; *(ptr2++) = (T)g; *(ptr3++) = (T)b; }
44358 template<
typename T>
44360 unsigned int _width, _allocated_width;
44399 typedef typename cimg::superset<T,bool>::type Tbool;
44400 typedef typename cimg::superset<T,unsigned char>::type Tuchar;
44401 typedef typename cimg::superset<T,char>::type Tchar;
44402 typedef typename cimg::superset<T,unsigned short>::type Tushort;
44403 typedef typename cimg::superset<T,short>::type Tshort;
44404 typedef typename cimg::superset<T,unsigned int>::type Tuint;
44405 typedef typename cimg::superset<T,int>::type Tint;
44406 typedef typename cimg::superset<T,unsigned long>::type Tulong;
44407 typedef typename cimg::superset<T,long>::type Tlong;
44408 typedef typename cimg::superset<T,float>::type Tfloat;
44409 typedef typename cimg::superset<T,double>::type Tdouble;
44410 typedef typename cimg::last<T,bool>::type boolT;
44411 typedef typename cimg::last<T,unsigned char>::type ucharT;
44412 typedef typename cimg::last<T,char>::type charT;
44413 typedef typename cimg::last<T,unsigned short>::type ushortT;
44414 typedef typename cimg::last<T,short>::type shortT;
44415 typedef typename cimg::last<T,unsigned int>::type uintT;
44416 typedef typename cimg::last<T,int>::type intT;
44417 typedef typename cimg::last<T,unsigned long>::type ulongT;
44418 typedef typename cimg::last<T,long>::type longT;
44419 typedef typename cimg::last<T,float>::type floatT;
44420 typedef typename cimg::last<T,double>::type doubleT;
44428 #ifdef cimglist_plugin
44429 #include cimglist_plugin
44431 #ifdef cimglist_plugin1
44432 #include cimglist_plugin1
44434 #ifdef cimglist_plugin2
44435 #include cimglist_plugin2
44437 #ifdef cimglist_plugin3
44438 #include cimglist_plugin3
44440 #ifdef cimglist_plugin4
44441 #include cimglist_plugin4
44443 #ifdef cimglist_plugin5
44444 #include cimglist_plugin5
44446 #ifdef cimglist_plugin6
44447 #include cimglist_plugin6
44449 #ifdef cimglist_plugin7
44450 #include cimglist_plugin7
44452 #ifdef cimglist_plugin8
44453 #include cimglist_plugin8
44484 _width(0),_allocated_width(0),_data(0) {}
44495 else { _allocated_width = 0; _data = 0; }
44507 CImgList(
const unsigned int n,
const unsigned int width,
const unsigned int height=1,
44508 const unsigned int depth=1,
const unsigned int spectrum=1):
44509 _width(0),_allocated_width(0),_data(0) {
44523 CImgList(
const unsigned int n,
const unsigned int width,
const unsigned int height,
44524 const unsigned int depth,
const unsigned int spectrum,
const T val):
44525 _width(0),_allocated_width(0),_data(0) {
44542 CImgList(
const unsigned int n,
const unsigned int width,
const unsigned int height,
44543 const unsigned int depth,
const unsigned int spectrum,
const int val0,
const int val1, ...):
44544 _width(0),_allocated_width(0),_data(0) {
44545 #define _CImgList_stdarg(t) { \
44546 assign(n,width,height,depth,spectrum); \
44547 const unsigned long siz = (unsigned long)width*height*depth*spectrum, nsiz = siz*n; \
44548 T *ptrd = _data->_data; \
44550 va_start(ap,val1); \
44551 for (unsigned long l = 0, s = 0, i = 0; i<nsiz; ++i) { \
44552 *(ptrd++) = (T)(i==0?val0:(i==1?val1:va_arg(ap,t))); \
44553 if ((++s)==siz) { ptrd = _data[++l]._data; s = 0; } \
44557 _CImgList_stdarg(
int);
44572 CImgList(
const unsigned int n,
const unsigned int width,
const unsigned int height,
44573 const unsigned int depth,
const unsigned int spectrum,
const double val0,
const double val1, ...):
44574 _width(0),_allocated_width(0),_data(0) {
44575 _CImgList_stdarg(
double);
44584 template<
typename t>
44586 _width(0),_allocated_width(0),_data(0) {
44588 cimglist_apply(*
this,assign)(img,
is_shared);
44596 template<
typename t>
44598 _width(0),_allocated_width(0),_data(0) {
44609 template<
typename t1,
typename t2>
44611 _width(0),_allocated_width(0),_data(0) {
44623 template<
typename t1,
typename t2,
typename t3>
44625 _width(0),_allocated_width(0),_data(0) {
44638 template<
typename t1,
typename t2,
typename t3,
typename t4>
44641 _width(0),_allocated_width(0),_data(0) {
44656 template<
typename t1,
typename t2,
typename t3,
typename t4,
typename t5>
44659 _width(0),_allocated_width(0),_data(0) {
44675 template<
typename t1,
typename t2,
typename t3,
typename t4,
typename t5,
typename t6>
44678 _width(0),_allocated_width(0),_data(0) {
44695 template<
typename t1,
typename t2,
typename t3,
typename t4,
typename t5,
typename t6,
typename t7>
44698 _width(0),_allocated_width(0),_data(0) {
44717 template<
typename t1,
typename t2,
typename t3,
typename t4,
typename t5,
typename t6,
typename t7,
typename t8>
44721 _width(0),_allocated_width(0),_data(0) {
44733 template<
typename t>
44736 cimglist_for(*
this,l) _data[l].assign(list[l],
false);
44742 cimglist_for(*
this,l) _data[l].assign(list[l],list[l]._is_shared);
44750 template<
typename t>
44753 cimglist_for(*
this,l) _data[l].assign(list[l],is_shared);
44760 explicit CImgList(
const char *
const filename):_width(0),_allocated_width(0),_data(0) {
44779 cimglist_for(*
this,l) res[l].assign(_data[l],
true);
44786 cimglist_for(*
this,l) res[l].assign(_data[l],
true);
44796 _width = _allocated_width = 0;
44815 if (!n)
return assign();
44816 if (_allocated_width<n || _allocated_width>(n<<2)) {
44829 const unsigned int depth=1,
const unsigned int spectrum=1) {
44840 const unsigned int depth,
const unsigned int spectrum,
const T val) {
44851 const unsigned int depth,
const unsigned int spectrum,
const int val0,
const int val1, ...) {
44852 _CImgList_stdarg(
int);
44861 const unsigned int depth,
const unsigned int spectrum,
44862 const double val0,
const double val1, ...) {
44863 _CImgList_stdarg(
double);
44871 template<
typename t>
44874 cimglist_apply(*
this,assign)(img,
is_shared);
44882 template<
typename t>
44893 template<
typename t1,
typename t2>
44904 template<
typename t1,
typename t2,
typename t3>
44915 template<
typename t1,
typename t2,
typename t3,
typename t4>
44928 template<
typename t1,
typename t2,
typename t3,
typename t4,
typename t5>
44941 template<
typename t1,
typename t2,
typename t3,
typename t4,
typename t5,
typename t6>
44954 template<
typename t1,
typename t2,
typename t3,
typename t4,
typename t5,
typename t6,
typename t7>
44968 template<
typename t1,
typename t2,
typename t3,
typename t4,
typename t5,
typename t6,
typename t7,
typename t8>
44983 template<
typename t>
44987 cimglist_for(*
this,l) _data[l].assign(list[l],
false);
44993 if (
this==&list)
return *
this;
44995 cimglist_for(res,l) res[l].assign(list[l],
is_shared);
44996 return res.move_to(*
this);
45004 return load(filename);
45020 template<
typename t>
45022 list.assign(_width);
45023 bool is_one_shared_element =
false;
45024 cimglist_for(*
this,l) is_one_shared_element|=_data[l]._is_shared;
45025 if (is_one_shared_element) cimglist_for(*
this,l) list[l].assign(_data[l]);
45026 else cimglist_for(*
this,l) _data[l].move_to(list[l]);
45038 template<
typename t>
45041 const unsigned int npos = pos>list._width?list._width:pos;
45042 list.insert(_width,npos);
45043 bool is_one_shared_element =
false;
45044 cimglist_for(*
this,l) is_one_shared_element|=_data[l]._is_shared;
45045 if (is_one_shared_element) cimglist_for(*
this,l) list[npos+l].assign(_data[l]);
45046 else cimglist_for(*
this,l) _data[l].move_to(list[npos+l]);
45058 cimg::swap(_allocated_width,list._allocated_width);
45072 return _empty.assign();
45087 #if cimg_verbosity>=3
45090 "operator(): Invalid image request, at position [%u].",
45104 return const_cast<CImgList<T>*
>(
this)->
operator()(pos);
45116 T&
operator()(
const unsigned int pos,
const unsigned int x,
const unsigned int y=0,
45117 const unsigned int z=0,
const unsigned int c=0) {
45118 return (*
this)[pos](x,y,z,c);
45122 const T&
operator()(
const unsigned int pos,
const unsigned int x,
const unsigned int y=0,
45123 const unsigned int z=0,
const unsigned int c=0)
const {
45124 return (*
this)[pos](x,y,z,c);
45145 template<
typename t>
45155 template<
typename t>
45170 return assign(filename);
45198 template<
typename t>
45200 return insert(img);
45204 template<
typename t>
45206 return (+*
this).
insert(img);
45213 template<
typename t>
45215 return insert(list);
45219 template<
typename t>
45221 return (+*
this).
insert(list);
45266 return (
int)_width;
45295 #if cimg_verbosity>=3
45299 "data(): Invalid pointer request, at position [%u].",
45302 return _data + pos;
45305 const CImg<T> *
data(
const unsigned int l)
const {
45306 return const_cast<CImgList<T>*
>(
this)->
data(l);
45335 return _data + _width;
45340 return _data + _width;
45359 return *(_data + _width - 1);
45364 return *(_data + _width - 1);
45374 "at(): Empty instance.",
45375 cimglist_instance);
45377 return _data[pos<0?0:pos>=(int)_width?(
int)_width-1:pos];
45390 T&
atNXYZC(
const int pos,
const int x,
const int y,
const int z,
const int c,
const T out_value) {
45391 return (pos<0 || pos>=(
int)_width)?(
cimg::temporary(out_value)=out_value):_data[pos].
atXYZC(x,y,z,c,out_value);
45395 T
atNXYZC(
const int pos,
const int x,
const int y,
const int z,
const int c,
const T out_value)
const {
45396 return (pos<0 || pos>=(
int)_width)?out_value:_data[pos].atXYZC(x,y,z,c,out_value);
45408 T&
atNXYZC(
const int pos,
const int x,
const int y,
const int z,
const int c) {
45411 "atNXYZC(): Empty instance.",
45412 cimglist_instance);
45414 return _atNXYZC(pos,x,y,z,c);
45418 T
atNXYZC(
const int pos,
const int x,
const int y,
const int z,
const int c)
const {
45421 "atNXYZC(): Empty instance.",
45422 cimglist_instance);
45424 return _atNXYZC(pos,x,y,z,c);
45427 T& _atNXYZC(
const int pos,
const int x,
const int y,
const int z,
const int c) {
45428 return _data[pos<0?0:(pos>=(int)_width?(
int)_width-1:pos)].
atXYZC(x,y,z,c);
45431 T _atNXYZC(
const int pos,
const int x,
const int y,
const int z,
const int c)
const {
45432 return _data[pos<0?0:(pos>=(int)_width?(
int)_width-1:pos)].
atXYZC(x,y,z,c);
45445 T&
atNXYZ(
const int pos,
const int x,
const int y,
const int z,
const int c,
const T out_value) {
45446 return (pos<0 || pos>=(
int)_width)?(
cimg::temporary(out_value)=out_value):_data[pos].
atXYZ(x,y,z,c,out_value);
45450 T
atNXYZ(
const int pos,
const int x,
const int y,
const int z,
const int c,
const T out_value)
const {
45451 return (pos<0 || pos>=(
int)_width)?out_value:_data[pos].atXYZ(x,y,z,c,out_value);
45463 T&
atNXYZ(
const int pos,
const int x,
const int y,
const int z,
const int c=0) {
45466 "atNXYZ(): Empty instance.",
45467 cimglist_instance);
45469 return _atNXYZ(pos,x,y,z,c);
45473 T
atNXYZ(
const int pos,
const int x,
const int y,
const int z,
const int c=0)
const {
45476 "atNXYZ(): Empty instance.",
45477 cimglist_instance);
45479 return _atNXYZ(pos,x,y,z,c);
45482 T& _atNXYZ(
const int pos,
const int x,
const int y,
const int z,
const int c=0) {
45483 return _data[pos<0?0:(pos>=(int)_width?(
int)_width-1:pos)].
atXYZ(x,y,z,c);
45486 T _atNXYZ(
const int pos,
const int x,
const int y,
const int z,
const int c=0)
const {
45487 return _data[pos<0?0:(pos>=(int)_width?(
int)_width-1:pos)].
atXYZ(x,y,z,c);
45500 T&
atNXY(
const int pos,
const int x,
const int y,
const int z,
const int c,
const T out_value) {
45501 return (pos<0 || pos>=(
int)_width)?(
cimg::temporary(out_value)=out_value):_data[pos].
atXY(x,y,z,c,out_value);
45505 T
atNXY(
const int pos,
const int x,
const int y,
const int z,
const int c,
const T out_value)
const {
45506 return (pos<0 || pos>=(
int)_width)?out_value:_data[pos].atXY(x,y,z,c,out_value);
45518 T&
atNXY(
const int pos,
const int x,
const int y,
const int z=0,
const int c=0) {
45521 "atNXY(): Empty instance.",
45522 cimglist_instance);
45524 return _atNXY(pos,x,y,z,c);
45528 T
atNXY(
const int pos,
const int x,
const int y,
const int z=0,
const int c=0)
const {
45531 "atNXY(): Empty instance.",
45532 cimglist_instance);
45534 return _atNXY(pos,x,y,z,c);
45537 T& _atNXY(
const int pos,
const int x,
const int y,
const int z=0,
const int c=0) {
45538 return _data[pos<0?0:(pos>=(int)_width?(
int)_width-1:pos)].
atXY(x,y,z,c);
45541 T _atNXY(
const int pos,
const int x,
const int y,
const int z=0,
const int c=0)
const {
45542 return _data[pos<0?0:(pos>=(int)_width?(
int)_width-1:pos)].
atXY(x,y,z,c);
45555 T&
atNX(
const int pos,
const int x,
const int y,
const int z,
const int c,
const T out_value) {
45556 return (pos<0 || pos>=(
int)_width)?(
cimg::temporary(out_value)=out_value):_data[pos].
atX(x,y,z,c,out_value);
45560 T
atNX(
const int pos,
const int x,
const int y,
const int z,
const int c,
const T out_value)
const {
45561 return (pos<0 || pos>=(
int)_width)?out_value:_data[pos].atX(x,y,z,c,out_value);
45573 T&
atNX(
const int pos,
const int x,
const int y=0,
const int z=0,
const int c=0) {
45576 "atNX(): Empty instance.",
45577 cimglist_instance);
45579 return _atNX(pos,x,y,z,c);
45583 T
atNX(
const int pos,
const int x,
const int y=0,
const int z=0,
const int c=0)
const {
45586 "atNX(): Empty instance.",
45587 cimglist_instance);
45589 return _atNX(pos,x,y,z,c);
45592 T& _atNX(
const int pos,
const int x,
const int y=0,
const int z=0,
const int c=0) {
45593 return _data[pos<0?0:(pos>=(int)_width?(
int)_width-1:pos)].
atX(x,y,z,c);
45596 T _atNX(
const int pos,
const int x,
const int y=0,
const int z=0,
const int c=0)
const {
45597 return _data[pos<0?0:(pos>=(int)_width?(
int)_width-1:pos)].
atX(x,y,z,c);
45610 T&
atN(
const int pos,
const int x,
const int y,
const int z,
const int c,
const T out_value) {
45611 return (pos<0 || pos>=(
int)_width)?(
cimg::temporary(out_value)=out_value):(*
this)(pos,x,y,z,c);
45615 T
atN(
const int pos,
const int x,
const int y,
const int z,
const int c,
const T out_value)
const {
45616 return (pos<0 || pos>=(
int)_width)?out_value:(*this)(pos,x,y,z,c);
45628 T&
atN(
const int pos,
const int x=0,
const int y=0,
const int z=0,
const int c=0) {
45631 "atN(): Empty instance.",
45632 cimglist_instance);
45633 return _atN(pos,x,y,z,c);
45637 T
atN(
const int pos,
const int x=0,
const int y=0,
const int z=0,
const int c=0)
const {
45640 "atN(): Empty instance.",
45641 cimglist_instance);
45642 return _atN(pos,x,y,z,c);
45645 T& _atN(
const int pos,
const int x=0,
const int y=0,
const int z=0,
const int c=0) {
45646 return _data[pos<0?0:(pos>=(int)_width?(
int)_width-1:pos)](x,y,z,c);
45649 T _atN(
const int pos,
const int x=0,
const int y=0,
const int z=0,
const int c=0)
const {
45650 return _data[pos<0?0:(pos>=(int)_width?(
int)_width-1:pos)](x,y,z,c);
45662 for (
unsigned int l = 0; l<_width-1; ++l) {
45663 CImg<charT> item = _data[l].value_string(separator,0);
45664 item.
back() = separator;
45667 _data[_width-1].value_string(separator,0).move_to(items);
45669 if (max_size) { res.
crop(0,max_size); res(max_size) = 0; }
45684 return (!_data || !_width);
45692 return _width==size_n;
45699 template<
typename t>
45701 return is_sameN(list._width);
45706 #define _cimglist_def_is_same1(axis) \
45707 bool is_same##axis(const unsigned int val) const { \
45709 for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis(val); return res; \
45711 bool is_sameN##axis(const unsigned int n, const unsigned int val) const { \
45712 return is_sameN(n) && is_same##axis(val); \
45715 #define _cimglist_def_is_same2(axis1,axis2) \
45716 bool is_same##axis1##axis2(const unsigned int val1, const unsigned int val2) const { \
45718 for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis1##axis2(val1,val2); return res; \
45720 bool is_sameN##axis1##axis2(const unsigned int n, const unsigned int val1, const unsigned int val2) const { \
45721 return is_sameN(n) && is_same##axis1##axis2(val1,val2); \
45724 #define _cimglist_def_is_same3(axis1,axis2,axis3) \
45725 bool is_same##axis1##axis2##axis3(const unsigned int val1, const unsigned int val2, \
45726 const unsigned int val3) const { \
45728 for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis1##axis2##axis3(val1,val2,val3); \
45731 bool is_sameN##axis1##axis2##axis3(const unsigned int n, const unsigned int val1, \
45732 const unsigned int val2, const unsigned int val3) const { \
45733 return is_sameN(n) && is_same##axis1##axis2##axis3(val1,val2,val3); \
45736 #define _cimglist_def_is_same(axis) \
45737 template<typename t> bool is_same##axis(const CImg<t>& img) const { \
45738 bool res = true; for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis(img); return res; \
45740 template<typename t> bool is_same##axis(const CImgList<t>& list) const { \
45741 const unsigned int lmin = cimg::min(_width,list._width); \
45742 bool res = true; for (unsigned int l = 0; l<lmin && res; ++l) res = _data[l].is_same##axis(list[l]); return res; \
45744 template<typename t> bool is_sameN##axis(const unsigned int n, const CImg<t>& img) const { \
45745 return (is_sameN(n) && is_same##axis(img)); \
45747 template<typename t> bool is_sameN##axis(const CImgList<t>& list) const { \
45748 return (is_sameN(list) && is_same##axis(list)); \
45751 _cimglist_def_is_same(XY)
45752 _cimglist_def_is_same(XZ)
45753 _cimglist_def_is_same(XC)
45754 _cimglist_def_is_same(YZ)
45755 _cimglist_def_is_same(YC)
45756 _cimglist_def_is_same(XYZ)
45757 _cimglist_def_is_same(XYC)
45758 _cimglist_def_is_same(YZC)
45759 _cimglist_def_is_same(XYZC)
45760 _cimglist_def_is_same1(X)
45761 _cimglist_def_is_same1(Y)
45762 _cimglist_def_is_same1(Z)
45763 _cimglist_def_is_same1(C)
45764 _cimglist_def_is_same2(X,Y)
45765 _cimglist_def_is_same2(X,Z)
45766 _cimglist_def_is_same2(X,C)
45767 _cimglist_def_is_same2(Y,Z)
45768 _cimglist_def_is_same2(Y,C)
45769 _cimglist_def_is_same2(Z,C)
45770 _cimglist_def_is_same3(X,Y,Z)
45771 _cimglist_def_is_same3(X,Y,C)
45772 _cimglist_def_is_same3(X,Z,C)
45773 _cimglist_def_is_same3(Y,Z,C)
45782 bool is_sameXYZC(const
unsigned int dx, const
unsigned int dy,
45783 const
unsigned int dz, const
unsigned int dc)
const {
45785 for (
unsigned int l = 0; l<_width && res; ++l) res = _data[l].
is_sameXYZC(dx,dy,dz,dc);
45798 const unsigned int dx,
const unsigned int dy,
45799 const unsigned int dz,
const unsigned int dc)
const {
45811 bool containsNXYZC(
const int n,
const int x=0,
const int y=0,
const int z=0,
const int c=0)
const {
45813 return n>=0 && n<(int)_width && x>=0 && x<_data[n].width() && y>=0 && y<_data[n].height() &&
45814 z>=0 && z<_data[n].depth() && c>=0 && c<_data[n].spectrum();
45823 return n>=0 && n<(int)_width;
45836 template<
typename t>
45837 bool contains(
const T& pixel, t& n, t& x, t&y, t& z, t& c)
const {
45839 cimglist_for(*
this,l)
if (_data[l].
contains(pixel,x,y,z,c)) { n = (t)l;
return true; }
45852 template<
typename t>
45853 bool contains(
const T& pixel, t& n, t& x, t&y, t& z)
const {
45866 template<
typename t>
45879 template<
typename t>
45891 template<
typename t>
45902 unsigned int n, x, y, z, c;
45912 template<
typename t>
45915 const CImg<T> *
const ptr = &img;
45916 cimglist_for(*
this,i)
if (_data+i==ptr) { n = (t)i;
return true; }
45942 "min(): Empty instance.",
45943 cimglist_instance);
45944 T *ptr_min = _data->_data;
45945 T min_value = *ptr_min;
45946 cimglist_for(*
this,l) {
45947 const CImg<T>& img = _data[l];
45948 cimg_for(img,ptrs,T)
if (*ptrs<min_value) min_value = *(ptr_min=ptrs);
45957 "min(): Empty instance.",
45958 cimglist_instance);
45959 const T *ptr_min = _data->_data;
45960 T min_value = *ptr_min;
45961 cimglist_for(*
this,l) {
45962 const CImg<T>& img = _data[l];
45963 cimg_for(img,ptrs,T)
if (*ptrs<min_value) min_value = *(ptr_min=ptrs);
45974 "max(): Empty instance.",
45975 cimglist_instance);
45976 T *ptr_max = _data->_data;
45977 T max_value = *ptr_max;
45978 cimglist_for(*
this,l) {
45979 const CImg<T>& img = _data[l];
45980 cimg_for(img,ptrs,T)
if (*ptrs>max_value) max_value = *(ptr_max=ptrs);
45989 "max(): Empty instance.",
45990 cimglist_instance);
45991 const T *ptr_max = _data->_data;
45992 T max_value = *ptr_max;
45993 cimglist_for(*
this,l) {
45994 const CImg<T>& img = _data[l];
45995 cimg_for(img,ptrs,T)
if (*ptrs>max_value) max_value = *(ptr_max=ptrs);
46004 template<
typename t>
46008 "min_max(): Empty instance.",
46009 cimglist_instance);
46010 T *ptr_min = _data->_data;
46011 T min_value = *ptr_min, max_value = min_value;
46012 cimglist_for(*
this,l) {
46013 const CImg<T>& img = _data[l];
46014 cimg_for(img,ptrs,T) {
46015 const T val = *ptrs;
46016 if (val<min_value) { min_value = val; ptr_min = ptrs; }
46017 if (val>max_value) max_value = val;
46020 max_val = (t)max_value;
46028 template<
typename t>
46032 "min_max(): Empty instance.",
46033 cimglist_instance);
46034 const T *ptr_min = _data->_data;
46035 T min_value = *ptr_min, max_value = min_value;
46036 cimglist_for(*
this,l) {
46037 const CImg<T>& img = _data[l];
46038 cimg_for(img,ptrs,T) {
46039 const T val = *ptrs;
46040 if (val<min_value) { min_value = val; ptr_min = ptrs; }
46041 if (val>max_value) max_value = val;
46044 max_val = (t)max_value;
46052 template<
typename t>
46056 "max_min(): Empty instance.",
46057 cimglist_instance);
46058 T *ptr_max = _data->_data;
46059 T min_value = *ptr_max, max_value = min_value;
46060 cimglist_for(*
this,l) {
46061 const CImg<T>& img = _data[l];
46062 cimg_for(img,ptrs,T) {
46063 const T val = *ptrs;
46064 if (val>max_value) { max_value = val; ptr_max = ptrs; }
46065 if (val<min_value) min_value = val;
46068 min_val = (t)min_value;
46073 template<
typename t>
46077 "max_min(): Empty instance.",
46078 cimglist_instance);
46079 const T *ptr_max = _data->_data;
46080 T min_value = *ptr_max, max_value = min_value;
46081 cimglist_for(*
this,l) {
46082 const CImg<T>& img = _data[l];
46083 cimg_for(img,ptrs,T) {
46084 const T val = *ptrs;
46085 if (val>max_value) { max_value = val; ptr_max = ptrs; }
46086 if (val<min_value) min_value = val;
46089 min_val = (t)min_value;
46106 template<
typename t>
46108 const unsigned int npos = pos==~0U?_width:pos;
46111 "insert(): Invalid insertion request of specified image (%u,%u,%u,%u,%p) "
46114 img._width,img._height,img._depth,img._spectrum,img._data,npos);
46117 "insert(): Invalid insertion request of specified shared image "
46118 "CImg<%s>(%u,%u,%u,%u,%p) at position %u (pixel types are different).",
46120 img.pixel_type(),img._width,img._height,img._depth,img._spectrum,img._data,npos);
46122 CImg<T> *
const new_data = (++_width>_allocated_width)?
new CImg<T>[_allocated_width?(_allocated_width<<=1):
46123 (_allocated_width=16)]:0;
46129 if (npos) std::memcpy(new_data,_data,
sizeof(
CImg<T>)*npos);
46130 if (npos!=_width-1) std::memcpy(new_data+npos+1,_data+npos,
sizeof(
CImg<T>)*(_width-1-npos));
46131 std::memset(_data,0,
sizeof(
CImg<T>)*(_width-1));
46134 }
else if (npos!=_width-1)
46135 std::memmove(_data+npos+1,_data+npos,
sizeof(
CImg<T>)*(_width-1-npos));
46136 _data[npos]._width = _data[npos]._height = _data[npos]._depth = _data[npos]._spectrum = 0; _data[npos]._data = 0;
46144 const unsigned int npos = pos==~0U?_width:pos;
46147 "insert(): Invalid insertion request of specified image (%u,%u,%u,%u,%p) "
46150 img._width,img._height,img._depth,img._spectrum,img._data,npos);
46151 CImg<T> *
const new_data = (++_width>_allocated_width)?
new CImg<T>[_allocated_width?(_allocated_width<<=1):
46152 (_allocated_width=16)]:0;
46156 _data->_width = img._width;
46157 _data->_height = img._height;
46158 _data->_depth = img._depth;
46159 _data->_spectrum = img._spectrum;
46160 _data->_is_shared =
true;
46161 _data->_data = img._data;
46162 }
else *_data = img;
46166 if (npos) std::memcpy(new_data,_data,
sizeof(
CImg<T>)*npos);
46167 if (npos!=_width-1) std::memcpy(new_data+npos+1,_data+npos,
sizeof(
CImg<T>)*(_width-1-npos));
46169 new_data[npos]._width = img._width;
46170 new_data[npos]._height = img._height;
46171 new_data[npos]._depth = img._depth;
46172 new_data[npos]._spectrum = img._spectrum;
46173 new_data[npos]._is_shared =
true;
46174 new_data[npos]._data = img._data;
46176 new_data[npos]._width = new_data[npos]._height = new_data[npos]._depth = new_data[npos]._spectrum = 0;
46177 new_data[npos]._data = 0;
46178 new_data[npos] = img;
46180 std::memset(_data,0,
sizeof(
CImg<T>)*(_width-1));
46184 if (npos!=_width-1) std::memmove(_data+npos+1,_data+npos,
sizeof(
CImg<T>)*(_width-1-npos));
46186 _data[npos]._width = img._width;
46187 _data[npos]._height = img._height;
46188 _data[npos]._depth = img._depth;
46189 _data[npos]._spectrum = img._spectrum;
46190 _data[npos]._is_shared =
true;
46191 _data[npos]._data = img._data;
46193 _data[npos]._width = _data[npos]._height = _data[npos]._depth = _data[npos]._spectrum = 0;
46194 _data[npos]._data = 0;
46203 template<
typename t>
46215 if (!n)
return *
this;
46216 const unsigned int npos = pos==~0U?_width:pos;
46217 for (
unsigned int i = 0; i<n; ++i) insert(empty,npos+i);
46223 return (+*
this).
insert(n,pos);
46233 template<
typename t>
46236 if (!n)
return *
this;
46237 const unsigned int npos = pos==~0U?_width:pos;
46239 for (
unsigned int i = 1; i<n; ++i) insert(_data[npos],npos+i,
is_shared);
46244 template<
typename t>
46256 template<
typename t>
46258 const unsigned int npos = pos==~0U?_width:pos;
46259 if ((
void*)
this!=(
void*)&list) cimglist_for(list,l) insert(list[l],npos+l,
is_shared);
46265 template<
typename t>
46277 template<
typename t>
46280 if (!n)
return *
this;
46281 const unsigned int npos = pos==~0U?_width:pos;
46282 for (
unsigned int i = 0; i<n; ++i) insert(list,npos,
is_shared);
46287 template<
typename t>
46300 npos1 = pos1<pos2?pos1:pos2,
46301 tpos2 = pos1<pos2?pos2:pos1,
46302 npos2 = tpos2<_width?tpos2:_width-1;
46305 "remove(): Invalid remove request at positions %u->%u.",
46311 "remove(): Invalid remove request at positions %u->%u.",
46315 for (
unsigned int k = npos1; k<=npos2; ++k) _data[k].
assign();
46316 const unsigned int nb = 1 + npos2 - npos1;
46317 if (!(_width-=nb))
return assign();
46318 if (_width>(_allocated_width>>2) || _allocated_width<=16) {
46319 if (npos1!=_width) std::memmove(_data+npos1,_data+npos2+1,
sizeof(
CImg<T>)*(_width - npos1));
46320 std::memset(_data + _width,0,
sizeof(
CImg<T>)*nb);
46322 _allocated_width>>=2;
46323 while (_allocated_width>16 && _width<(_allocated_width>>1)) _allocated_width>>=1;
46325 if (npos1) std::memcpy(new_data,_data,
sizeof(
CImg<T>)*npos1);
46326 if (npos1!=_width) std::memcpy(new_data+npos1,_data+npos2+1,
sizeof(
CImg<T>)*(_width-npos1));
46327 if (_width!=_allocated_width) std::memset(new_data+_width,0,
sizeof(_allocated_width - _width));
46328 std::memset(_data,0,
sizeof(
CImg<T>)*(_width+nb));
46338 return (+*
this).
remove(pos1,pos2);
46346 return remove(pos,pos);
46351 return (+*
this).
remove(pos);
46358 return remove(_width-1);
46363 return (+*
this).
remove();
46368 for (
unsigned int l = 0; l<_width/2; ++l) (*
this)[l].
swap((*
this)[_width-1-l]);
46383 return get_images(pos0,pos1).
move_to(*
this);
46388 if (pos0>pos1 || pos1>=_width)
46390 "images(): Specified sub-list indices (%u->%u) are out of bounds.",
46394 cimglist_for(res,l) res[l].assign(_data[pos0+l]);
46404 if (pos0>pos1 || pos1>=_width)
46406 "get_shared_images(): Specified sub-list indices (%u->%u) are out of bounds.",
46410 cimglist_for(res,l) res[l].assign(_data[pos0+l],_data[pos0+l]?
true:
false);
46416 if (pos0>pos1 || pos1>=_width)
46418 "get_shared_images(): Specified sub-list indices (%u->%u) are out of bounds.",
46422 cimglist_for(res,l) res[l].assign(_data[pos0+l],_data[pos0+l]?
true:
false);
46433 if (_width==1)
return +((*this)[0]);
46434 unsigned int dx = 0, dy = 0, dz = 0, dc = 0, pos = 0;
46438 cimglist_for(*
this,l) {
46439 const CImg<T>& img = (*this)[l];
46447 res.assign(dx,dy,dz,dc,0);
46448 if (res) cimglist_for(*
this,l) {
46449 const CImg<T>& img = (*this)[l];
46450 if (img) res.draw_image(pos,
46451 (
int)(align*(dy-img._height)),
46452 (
int)(align*(dz-img._depth)),
46453 (
int)(align*(dc-img._spectrum)),
46459 cimglist_for(*
this,l) {
46460 const CImg<T>& img = (*this)[l];
46468 res.assign(dx,dy,dz,dc,0);
46469 if (res) cimglist_for(*
this,l) {
46470 const CImg<T>& img = (*this)[l];
46471 if (img) res.draw_image((
int)(align*(dx-img._width)),
46473 (
int)(align*(dz-img._depth)),
46474 (
int)(align*(dc-img._spectrum)),
46480 cimglist_for(*
this,l) {
46481 const CImg<T>& img = (*this)[l];
46489 res.assign(dx,dy,dz,dc,0);
46490 if (res) cimglist_for(*
this,l) {
46491 const CImg<T>& img = (*this)[l];
46492 if (img) res.draw_image((
int)(align*(dx-img._width)),
46493 (
int)(align*(dy-img._height)),
46495 (
int)(align*(dc-img._spectrum)),
46501 cimglist_for(*
this,l) {
46502 const CImg<T>& img = (*this)[l];
46510 res.assign(dx,dy,dz,dc,0);
46511 if (res) cimglist_for(*
this,l) {
46512 const CImg<T>& img = (*this)[l];
46513 if (img) res.draw_image((
int)(align*(dx-img._width)),
46514 (
int)(align*(dy-img._height)),
46515 (
int)(align*(dz-img._depth)),
46518 pos+=img._spectrum;
46531 return get_split(axis,nb).move_to(*
this);
46537 cimglist_for(*
this,l) _data[l].get_split(axis,nb).move_to(res,~0U);
46545 template<
typename t>
46547 return insert(img);
46554 template<
typename t>
46556 return insert(img,0);
46563 template<
typename t>
46565 return insert(list);
46572 template<
typename t>
46574 return insert(list,0);
46581 return remove(_width-1);
46596 return remove(iter-_data);
46615 const char axis=
'x',
const float align=0)
const {
46616 return _get_select(disp,0,feature_type,axis,align,0,
false,
false,
false);
46628 const char axis=
'x',
const float align=0)
const {
46630 return _get_select(disp,title,feature_type,axis,align,0,
false,
false,
false);
46634 const char axis,
const float align,
46635 const unsigned int orig,
const bool resize_disp,
46636 const bool exit_on_rightbutton,
const bool exit_on_wheel)
const {
46639 "select(): Empty instance.",
46640 cimglist_instance);
46644 unsigned int max_width = 0, max_height = 0, sum_width = 0, sum_height = 0;
46645 cimglist_for(*
this,l) {
46646 const CImg<T>& img = _data[l];
46648 w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,
false),
46649 h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,
true);
46650 if (w>max_width) max_width = w;
46651 if (h>max_height) max_height = h;
46652 sum_width+=w; sum_height+=h;
46656 const CImg<uintT> indices0 = _indices>
'x';
46660 if (axis==
'x') disp.
assign(cimg_fitscreen(sum_width,max_height,1),title?title:0,1);
46661 else disp.
assign(cimg_fitscreen(max_width,sum_height,1),title?title:0,1);
46663 }
else if (title) disp.
set_title(
"%s",title);
46665 if (axis==
'x') disp.
resize(cimg_fitscreen(sum_width,max_height,1),
false);
46666 else disp.
resize(cimg_fitscreen(max_width,sum_height,1),
false);
46669 const unsigned int old_normalization = disp.
normalization();
46671 disp._normalization = 0;
46673 const unsigned char foreground_color[] = { 255,255,255 }, background_color[] = { 0,0,0 };
46676 CImg<ucharT> visu0, visu;
46677 CImg<uintT> indices;
46678 CImg<intT> positions(_width,4,1,1,-1);
46679 int oindice0 = -1, oindice1 = -1, indice0 = -1, indice1 = -1;
46680 bool is_clicked =
false, is_selected =
false, text_down =
false, update_display =
true;
46681 unsigned int key = 0;
46682 while (!is_selected && !disp.
is_closed() && !key) {
46686 visu0.assign(disp._width,disp._height,1,3,0); visu.assign();
46687 (indices0.get_resize(axis==
'x'?visu0._width:visu0._height,1)).
move_to(indices);
46688 unsigned int ind = 0;
46689 if (axis==
'x')
for (
unsigned int x = 0; x<visu0._width; ) {
46690 const unsigned int x0 = x;
46692 while (x<indices._width && indices[x++]==ind) {}
46694 onexone(1,1,1,1,0),
46695 &src = _data[ind]?_data[ind]:onexone;
46697 src.__get_select(disp,old_normalization,(src._width-1)/2,(src._height-1)/2,(src._depth-1)/2).move_to(res);
46698 const unsigned int h = CImgDisplay::_fitscreen(res._width,res._height,1,128,-85,
true);
46699 res.resize(x - x0,
cimg::max(32U,h*disp._height/max_height),1,res._spectrum==1?3:-100);
46700 positions(ind,0) = positions(ind,2) = (int)x0;
46701 positions(ind,1) = positions(ind,3) = (int)(align*(visu0.height()-res.height()));
46702 positions(ind,2)+=res._width;
46703 positions(ind,3)+=res._height - 1;
46704 visu0.draw_image(positions(ind,0),positions(ind,1),res);
46705 }
else for (
unsigned int y = 0; y<visu0._height; ) {
46706 const unsigned int y0 = y;
46708 while (y<visu0._height && indices[++y]==ind) {}
46711 _img2d = src._depth>1?src.get_projections2d((src._width-1)/2,(src._height-1)/2,(src._depth-1)/2):
46713 &img2d = _img2d?_img2d:src;
46714 CImg<ucharT> res = old_normalization==1 ||
46715 (old_normalization==3 && cimg::type<T>::string()!=cimg::type<unsigned char>::string())?
46716 CImg<ucharT>(img2d.get_normalize(0,255)):
46717 CImg<ucharT>(img2d);
46718 if (res._spectrum>3) res.channels(0,2);
46719 const unsigned int w = CImgDisplay::_fitscreen(res._width,res._height,1,128,-85,
false);
46720 res.resize(
cimg::max(32U,w*disp._width/max_width),y - y0,1,res._spectrum==1?3:-100);
46721 positions(ind,0) = positions(ind,2) = (int)(align*(visu0.width()-res.width()));
46722 positions(ind,1) = positions(ind,3) = (int)y0;
46723 positions(ind,2)+=res._width - 1;
46724 positions(ind,3)+=res._height;
46725 visu0.draw_image(positions(ind,0),positions(ind,1),res);
46727 if (axis==
'x') --positions(ind,2);
else --positions(ind,3);
46728 update_display =
true;
46731 if (!visu || oindice0!=indice0 || oindice1!=indice1) {
46732 if (indice0>=0 && indice1>=0) {
46733 visu.assign(visu0,
false);
46735 for (
int ind = indm; ind<=indM; ++ind) if (positions(ind,0)>=0) {
46736 visu.draw_rectangle(positions(ind,0),positions(ind,1),positions(ind,2),positions(ind,3),
46737 background_color,0.2f);
46738 if ((axis==
'x' && positions(ind,2) - positions(ind,0)>=8) ||
46739 (axis!=
'x' && positions(ind,3) - positions(ind,1)>=8))
46740 visu.draw_rectangle(positions(ind,0),positions(ind,1),positions(ind,2),positions(ind,3),
46741 foreground_color,0.9f,0xAAAAAAAA);
46743 const int yt = (int)text_down?visu.height()-13:0;
46744 if (is_clicked) visu.draw_text(0,yt,
" Images #%u - #%u, Size = %u",
46745 foreground_color,background_color,0.7f,13,
46746 orig + indm,orig + indM,indM - indm + 1);
46747 else visu.draw_text(0,yt,
" Image #%u (%u,%u,%u,%u)",foreground_color,background_color,0.7f,13,
46749 _data[orig+indice0]._width,
46750 _data[orig+indice0]._height,
46751 _data[orig+indice0]._depth,
46752 _data[orig+indice0]._spectrum);
46753 update_display =
true;
46754 }
else visu.assign();
46756 if (!visu) { visu.assign(visu0,
true); update_display =
true; }
46757 if (update_display) { visu.display(disp); update_display =
false; }
46765 indice = (int)indices(axis==
'x'?xm:ym);
46767 if (!is_clicked) { is_clicked =
true; oindice0 = indice0; indice0 = indice; }
46768 oindice1 = indice1; indice1 = indice;
46769 if (!feature_type) is_selected =
true;
46771 if (!is_clicked) { oindice0 = oindice1 = indice0; indice0 = indice1 = indice; }
46772 else is_selected =
true;
46776 if (!(disp.
button()&1)) { is_clicked = is_selected =
false; indice0 = indice1 = -1; }
46778 }
else indice0 = indice1 = -1;
46781 if (disp.
button()&4) { is_clicked = is_selected =
false; indice0 = indice1 = -1; }
46782 if (disp.
button()&2 && exit_on_rightbutton) { is_selected =
true; indice1 = indice0 = -1; }
46783 if (disp.
wheel() && exit_on_wheel) is_selected =
true;
46785 switch (key = disp.
key()) {
46790 case cimg::keyD :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
46792 resize(CImgDisplay::_fitscreen(3*disp.
width()/2,3*disp.
height()/2,1,128,-100,
false),
46793 CImgDisplay::_fitscreen(3*disp.
width()/2,3*disp.
height()/2,1,128,-100,
true),
false).
46794 _is_resized =
true;
46795 disp.
set_key(key,
false); key = 0; visu0.assign();
46797 case cimg::keyC :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
46799 resize(cimg_fitscreen(2*disp.
width()/3,2*disp.
height()/3,1),
false)._is_resized =
true;
46800 disp.
set_key(key,
false); key = 0; visu0.assign();
46802 case cimg::keyR :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
46804 resize(cimg_fitscreen(axis==
'x'?sum_width:max_width,axis==
'x'?max_height:sum_height,1),
false).
46805 _is_resized =
true;
46806 disp.
set_key(key,
false); key = 0; visu0.assign();
46808 case cimg::keyF :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
46810 disp.
set_key(key,
false); key = 0; visu0.assign();
46812 case cimg::keyS :
if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
46813 static unsigned int snap_number = 0;
46814 char filename[32] = { 0 };
46817 cimg_snprintf(filename,
sizeof(filename),cimg_appname
"_%.4u.bmp",snap_number++);
46818 if ((file=std::fopen(filename,
"r"))!=0)
cimg::fclose(file);
46821 (+visu0).
draw_text(0,0,
" Saving snapshot... ",
46822 foreground_color,background_color,0.7f,13).display(disp);
46823 visu0.save(filename);
46824 (+visu0).
draw_text(0,0,
" Snapshot '%s' saved. ",
46825 foreground_color,background_color,0.7f,13,filename).display(disp);
46830 if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
46831 static unsigned int snap_number = 0;
46832 char filename[32] = { 0 };
46835 #ifdef cimg_use_zlib
46836 cimg_snprintf(filename,
sizeof(filename),cimg_appname
"_%.4u.cimgz",snap_number++);
46838 cimg_snprintf(filename,
sizeof(filename),cimg_appname
"_%.4u.cimg",snap_number++);
46840 if ((file=std::fopen(filename,
"r"))!=0)
cimg::fclose(file);
46842 (+visu0).
draw_text(0,0,
" Saving instance... ",
46843 foreground_color,background_color,0.7f,13).display(disp);
46845 (+visu0).
draw_text(0,0,
" Instance '%s' saved. ",
46846 foreground_color,background_color,0.7f,13,filename).display(disp);
46851 if (ym>=0 && ym<13) {
if (!text_down) { visu.assign(); text_down =
true; }}
46852 else if (ym>=visu.height()-13) {
if(text_down) { visu.assign(); text_down =
false; }}
46854 CImg<intT> res(1,2,1,1,-1);
46857 else res.fill(indice0);
46860 disp._normalization = old_normalization;
46861 disp._is_resized = old_is_resized;
46873 "load(): Specified filename is (null).",
46874 cimglist_instance);
46877 char filename_local[1024] = { 0 };
46879 std::remove(filename_local);
46887 #ifdef cimglist_load_plugin
46888 cimglist_load_plugin(filename);
46890 #ifdef cimglist_load_plugin1
46891 cimglist_load_plugin1(filename);
46893 #ifdef cimglist_load_plugin2
46894 cimglist_load_plugin2(filename);
46896 #ifdef cimglist_load_plugin3
46897 cimglist_load_plugin3(filename);
46899 #ifdef cimglist_load_plugin4
46900 cimglist_load_plugin4(filename);
46902 #ifdef cimglist_load_plugin5
46903 cimglist_load_plugin5(filename);
46905 #ifdef cimglist_load_plugin6
46906 cimglist_load_plugin6(filename);
46908 #ifdef cimglist_load_plugin7
46909 cimglist_load_plugin7(filename);
46911 #ifdef cimglist_load_plugin8
46912 cimglist_load_plugin8(filename);
46954 "load(): Failed to open file '%s'.",
46960 _data->load(filename);
46964 "load(): Failed to recognize format of file '%s'.",
46983 return _load_cimg(0,filename);
46996 return _load_cimg(file,0);
47004 CImgList<T>& _load_cimg(std::FILE *
const file,
const char *
const filename) {
47005 #ifdef cimg_use_zlib
47006 #define _cimgz_load_cimg_case(Tss) { \
47007 Bytef *const cbuf = new Bytef[csiz]; \
47008 cimg::fread(cbuf,csiz,nfile); \
47009 raw.assign(W,H,D,C); \
47010 unsigned long destlen = (unsigned long)raw.size()*sizeof(Tss); \
47011 uncompress((Bytef*)raw._data,&destlen,cbuf,csiz); \
47013 const Tss *ptrs = raw._data; \
47014 for (unsigned long off = raw.size(); off; --off) *(ptrd++) = (T)*(ptrs++); \
47017 #define _cimgz_load_cimg_case(Tss) \
47018 throw CImgIOException(_cimglist_instance \
47019 "load_cimg(): Unable to load compressed data from file '%s' unless zlib is enabled.", \
47020 cimglist_instance, \
47021 filename?filename:"(FILE*)");
47024 #define _cimg_load_cimg_case(Ts,Tss) \
47025 if (!loaded && !cimg::strcasecmp(Ts,str_pixeltype)) { \
47026 for (unsigned int l = 0; l<N; ++l) { \
47027 j = 0; while ((i=std::fgetc(nfile))!='\n' && i>=0) tmp[j++] = (char)i; tmp[j] = 0; \
47028 W = H = D = C = 0; csiz = 0; \
47029 if ((err = std::sscanf(tmp,"%u %u %u %u #%u",&W,&H,&D,&C,&csiz))<4) \
47030 throw CImgIOException(_cimglist_instance \
47031 "load_cimg(): Invalid specified size (%u,%u,%u,%u) of image %u in file '%s'", \
47032 cimglist_instance, \
47033 W,H,D,C,l,filename?filename:("(FILE*)")); \
47036 CImg<T> &img = _data[l]; \
47037 img.assign(W,H,D,C); \
47038 T *ptrd = img._data; \
47039 if (err==5) _cimgz_load_cimg_case(Tss) \
47040 else for (long to_read = (long)img.size(); to_read>0; ) { \
47041 raw.assign(cimg::min(to_read,cimg_iobuffer)); \
47042 cimg::fread(raw._data,raw._width,nfile); \
47043 if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw._width); \
47044 to_read-=raw._width; \
47045 const Tss *ptrs = raw._data; \
47046 for (unsigned long off = (unsigned long)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); \
47053 if (!filename && !file)
47055 "load_cimg(): Specified filename is (null).",
47056 cimglist_instance);
47058 const int cimg_iobuffer = 12*1024*1024;
47059 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"rb");
47061 char tmp[256] = { 0 }, str_pixeltype[256] = { 0 }, str_endian[256] = { 0 };
47062 unsigned int j, err, N = 0, W, H, D, C, csiz;
47065 j = 0;
while ((i=std::fgetc(nfile))!=
'\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0;
47066 }
while (*tmp==
'#' && i!=EOF);
47067 err = std::sscanf(tmp,
"%u%*c%255[A-Za-z_]%*c%255[sA-Za-z_ ]",&N,str_pixeltype,str_endian);
47070 throw CImgIOException(_cimglist_instance
47071 "load_cimg(): CImg header not found in file '%s'.",
47073 filename?filename:
"(FILE*)");
47078 _cimg_load_cimg_case(
"bool",
bool);
47079 _cimg_load_cimg_case(
"unsigned_char",
unsigned char);
47080 _cimg_load_cimg_case(
"uchar",
unsigned char);
47081 _cimg_load_cimg_case(
"char",
char);
47082 _cimg_load_cimg_case(
"unsigned_short",
unsigned short);
47083 _cimg_load_cimg_case(
"ushort",
unsigned short);
47084 _cimg_load_cimg_case(
"short",
short);
47085 _cimg_load_cimg_case(
"unsigned_int",
unsigned int);
47086 _cimg_load_cimg_case(
"uint",
unsigned int);
47087 _cimg_load_cimg_case(
"int",
int);
47088 _cimg_load_cimg_case(
"unsigned_long",
unsigned long);
47089 _cimg_load_cimg_case(
"ulong",
unsigned long);
47090 _cimg_load_cimg_case(
"long",
long);
47091 _cimg_load_cimg_case(
"float",
float);
47092 _cimg_load_cimg_case(
"double",
double);
47095 throw CImgIOException(_cimglist_instance
47096 "load_cimg(): Unsupported pixel type '%s' for file '%s'.",
47098 str_pixeltype,filename?filename:
"(FILE*)");
47119 const unsigned int n0,
const unsigned int n1,
47120 const unsigned int x0,
const unsigned int y0,
47121 const unsigned int z0,
const unsigned int c0,
47122 const unsigned int x1,
const unsigned int y1,
47123 const unsigned int z1,
const unsigned int c1) {
47124 return _load_cimg(0,filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1);
47129 const unsigned int n0,
const unsigned int n1,
47130 const unsigned int x0,
const unsigned int y0,
47131 const unsigned int z0,
const unsigned int c0,
47132 const unsigned int x1,
const unsigned int y1,
47133 const unsigned int z1,
const unsigned int c1) {
47134 return CImgList<T>().
load_cimg(filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1);
47139 const unsigned int n0,
const unsigned int n1,
47140 const unsigned int x0,
const unsigned int y0,
47141 const unsigned int z0,
const unsigned int c0,
47142 const unsigned int x1,
const unsigned int y1,
47143 const unsigned int z1,
const unsigned int c1) {
47144 return _load_cimg(file,0,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1);
47149 const unsigned int n0,
const unsigned int n1,
47150 const unsigned int x0,
const unsigned int y0,
47151 const unsigned int z0,
const unsigned int c0,
47152 const unsigned int x1,
const unsigned int y1,
47153 const unsigned int z1,
const unsigned int c1) {
47154 return CImgList<T>().
load_cimg(file,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1);
47157 CImgList<T>& _load_cimg(std::FILE *
const file,
const char *
const filename,
47158 const unsigned int n0,
const unsigned int n1,
47159 const unsigned int x0,
const unsigned int y0,
47160 const unsigned int z0,
const unsigned int c0,
47161 const unsigned int x1,
const unsigned int y1,
47162 const unsigned int z1,
const unsigned int c1) {
47163 #define _cimg_load_cimg_case2(Ts,Tss) \
47164 if (!loaded && !cimg::strcasecmp(Ts,str_pixeltype)) { \
47165 for (unsigned int l = 0; l<=nn1; ++l) { \
47166 j = 0; while ((i=std::fgetc(nfile))!='\n' && i>=0) tmp[j++] = (char)i; tmp[j] = 0; \
47167 W = H = D = C = 0; \
47168 if (std::sscanf(tmp,"%u %u %u %u",&W,&H,&D,&C)!=4) \
47169 throw CImgIOException(_cimglist_instance \
47170 "load_cimg(): Invalid specified size (%u,%u,%u,%u) of image %u in file '%s'", \
47171 cimglist_instance, \
47172 W,H,D,C,l,filename?filename:"(FILE*)"); \
47174 if (l<nn0 || nx0>=W || ny0>=H || nz0>=D || nc0>=C) std::fseek(nfile,W*H*D*C*sizeof(Tss),SEEK_CUR); \
47176 const unsigned int \
47177 _nx1 = nx1==~0U?W-1:nx1, \
47178 _ny1 = ny1==~0U?H-1:ny1, \
47179 _nz1 = nz1==~0U?D-1:nz1, \
47180 _nc1 = nc1==~0U?C-1:nc1; \
47181 if (_nx1>=W || _ny1>=H || _nz1>=D || _nc1>=C) \
47182 throw CImgArgumentException(_cimglist_instance \
47183 "load_cimg(): Invalid specified coordinates " \
47184 "[%u](%u,%u,%u,%u) -> [%u](%u,%u,%u,%u) " \
47185 "because image [%u] in file '%s' has size (%u,%u,%u,%u).", \
47186 cimglist_instance, \
47187 n0,x0,y0,z0,c0,n1,x1,y1,z1,c1,l,filename?filename:"(FILE*)",W,H,D,C); \
47188 CImg<Tss> raw(1 + _nx1 - nx0); \
47189 CImg<T> &img = _data[l - nn0]; \
47190 img.assign(1 + _nx1 - nx0,1 + _ny1 - ny0,1 + _nz1 - nz0,1 + _nc1 - nc0); \
47191 T *ptrd = img._data; \
47192 const unsigned int skipvb = nc0*W*H*D*sizeof(Tss); \
47193 if (skipvb) std::fseek(nfile,skipvb,SEEK_CUR); \
47194 for (unsigned int c = 1 + _nc1 - nc0; c; --c) { \
47195 const unsigned int skipzb = nz0*W*H*sizeof(Tss); \
47196 if (skipzb) std::fseek(nfile,skipzb,SEEK_CUR); \
47197 for (unsigned int z = 1 + _nz1 - nz0; z; --z) { \
47198 const unsigned int skipyb = ny0*W*sizeof(Tss); \
47199 if (skipyb) std::fseek(nfile,skipyb,SEEK_CUR); \
47200 for (unsigned int y = 1 + _ny1 - ny0; y; --y) { \
47201 const unsigned int skipxb = nx0*sizeof(Tss); \
47202 if (skipxb) std::fseek(nfile,skipxb,SEEK_CUR); \
47203 cimg::fread(raw._data,raw._width,nfile); \
47204 if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw._width); \
47205 const Tss *ptrs = raw._data; \
47206 for (unsigned int off = raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); \
47207 const unsigned int skipxe = (W-1-_nx1)*sizeof(Tss); \
47208 if (skipxe) std::fseek(nfile,skipxe,SEEK_CUR); \
47210 const unsigned int skipye = (H-1-_ny1)*W*sizeof(Tss); \
47211 if (skipye) std::fseek(nfile,skipye,SEEK_CUR); \
47213 const unsigned int skipze = (D-1-_nz1)*W*H*sizeof(Tss); \
47214 if (skipze) std::fseek(nfile,skipze,SEEK_CUR); \
47216 const unsigned int skipve = (C-1-_nc1)*W*H*D*sizeof(Tss); \
47217 if (skipve) std::fseek(nfile,skipve,SEEK_CUR); \
47224 if (!filename && !file)
47226 "load_cimg(): Specified filename is (null).",
47227 cimglist_instance);
47235 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"rb");
47237 char tmp[256] = { 0 }, str_pixeltype[256] = { 0 }, str_endian[256] = { 0 };
47238 unsigned int j, err, N, W, H, D, C;
47240 j = 0;
while((i=std::fgetc(nfile))!=
'\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0;
47241 err = std::sscanf(tmp,
"%u%*c%255[A-Za-z_]%*c%255[sA-Za-z_ ]",&N,str_pixeltype,str_endian);
47244 throw CImgIOException(_cimglist_instance
47245 "load_cimg(): CImg header not found in file '%s'.",
47247 filename?filename:
"(FILE*)");
47251 nn1 = n1==~0U?N-1:n1;
47253 throw CImgArgumentException(_cimglist_instance
47254 "load_cimg(): Invalid specified coordinates [%u](%u,%u,%u,%u) -> [%u](%u,%u,%u,%u) "
47255 "because file '%s' contains only %u images.",
47257 n0,x0,y0,z0,c0,n1,x1,y1,z1,c1,filename?filename:
"(FILE*)",N);
47259 _cimg_load_cimg_case2(
"bool",
bool);
47260 _cimg_load_cimg_case2(
"unsigned_char",
unsigned char);
47261 _cimg_load_cimg_case2(
"uchar",
unsigned char);
47262 _cimg_load_cimg_case2(
"char",
char);
47263 _cimg_load_cimg_case2(
"unsigned_short",
unsigned short);
47264 _cimg_load_cimg_case2(
"ushort",
unsigned short);
47265 _cimg_load_cimg_case2(
"short",
short);
47266 _cimg_load_cimg_case2(
"unsigned_int",
unsigned int);
47267 _cimg_load_cimg_case2(
"uint",
unsigned int);
47268 _cimg_load_cimg_case2(
"int",
int);
47269 _cimg_load_cimg_case2(
"unsigned_long",
unsigned long);
47270 _cimg_load_cimg_case2(
"ulong",
unsigned long);
47271 _cimg_load_cimg_case2(
"long",
long);
47272 _cimg_load_cimg_case2(
"float",
float);
47273 _cimg_load_cimg_case2(
"double",
double);
47276 throw CImgIOException(_cimglist_instance
47277 "load_cimg(): Unsupported pixel type '%s' for file '%s'.",
47279 str_pixeltype,filename?filename:
"(FILE*)");
47292 "load_parrec(): Specified filename is (null).",
47293 cimglist_instance);
47295 char body[1024] = { 0 }, filenamepar[1024] = { 0 }, filenamerec[1024] = { 0 };
47297 if (!std::strcmp(ext,
"par")) {
47298 std::strncpy(filenamepar,filename,
sizeof(filenamepar)-1);
47299 cimg_snprintf(filenamerec,
sizeof(filenamerec),
"%s.rec",body);
47301 if (!std::strcmp(ext,
"PAR")) {
47302 std::strncpy(filenamepar,filename,
sizeof(filenamepar)-1);
47303 cimg_snprintf(filenamerec,
sizeof(filenamerec),
"%s.REC",body);
47305 if (!std::strcmp(ext,
"rec")) {
47306 std::strncpy(filenamerec,filename,
sizeof(filenamerec)-1);
47307 cimg_snprintf(filenamepar,
sizeof(filenamepar),
"%s.par",body);
47309 if (!std::strcmp(ext,
"REC")) {
47310 std::strncpy(filenamerec,filename,
sizeof(filenamerec)-1);
47311 cimg_snprintf(filenamepar,
sizeof(filenamepar),
"%s.PAR",body);
47319 char line[256] = { 0 };
47320 do { err=std::fscanf(file,
"%255[^\n]%*c",line); }
while (err!=EOF && (*line==
'#' || *line==
'.'));
47322 unsigned int sn,size_x,size_y,pixsize;
47324 err = std::fscanf(file,
"%u%*u%*u%*u%*u%*u%*u%u%*u%u%u%g%g%g%*[^\n]",&sn,&pixsize,&size_x,&size_y,&ri,&rs,&ss);
47326 CImg<floatT>::vector((
float)sn,(
float)pixsize,(
float)size_x,(
float)size_y,ri,rs,ss,0).move_to(st_slices);
47327 unsigned int i;
for (i = 0; i<st_global._width && sn<=st_global[i][2]; ++i) {}
47331 if (size_x>vec[0]) vec[0] = size_x;
47332 if (size_y>vec[1]) vec[1] = size_y;
47335 st_slices[st_slices._width-1][7] = (float)i;
47340 std::FILE *file2 =
cimg::fopen(filenamerec,
"rb");
47341 cimglist_for(st_global,l) {
47346 cimglist_for(st_slices,l) {
47349 sn = (
unsigned int)vec[0] - 1,
47350 pixsize = (
unsigned int)vec[1],
47351 size_x = (
unsigned int)vec[2],
47352 size_y = (
unsigned int)vec[3],
47353 imn = (
unsigned int)vec[7];
47354 const float ri = vec[4], rs = vec[5], ss = vec[6];
47361 cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss));
47368 cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss));
47375 cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss));
47381 "load_parrec(): Unsupported %d-bits pixel type for file '%s'.",
47390 "load_parrec(): Failed to recognize valid PAR-REC data in file '%s'.",
47412 const unsigned int size_x,
const unsigned int size_y,
47413 const unsigned int first_frame=0,
const unsigned int last_frame=~0U,
47414 const unsigned int step_frame=1,
const bool yuv2rgb=
true) {
47415 return _load_yuv(0,filename,size_x,size_y,first_frame,last_frame,step_frame,yuv2rgb);
47420 const unsigned int size_x,
const unsigned int size_y=1,
47421 const unsigned int first_frame=0,
const unsigned int last_frame=~0U,
47422 const unsigned int step_frame=1,
const bool yuv2rgb=
true) {
47423 return CImgList<T>().
load_yuv(filename,size_x,size_y,first_frame,last_frame,step_frame,yuv2rgb);
47428 const unsigned int size_x,
const unsigned int size_y,
47429 const unsigned int first_frame=0,
const unsigned int last_frame=~0U,
47430 const unsigned int step_frame=1,
const bool yuv2rgb=
true) {
47431 return _load_yuv(file,0,size_x,size_y,first_frame,last_frame,step_frame,yuv2rgb);
47436 const unsigned int size_x,
const unsigned int size_y=1,
47437 const unsigned int first_frame=0,
const unsigned int last_frame=~0U,
47438 const unsigned int step_frame=1,
const bool yuv2rgb=
true) {
47439 return CImgList<T>().
load_yuv(file,size_x,size_y,first_frame,last_frame,step_frame,yuv2rgb);
47442 CImgList<T>& _load_yuv(std::FILE *
const file,
const char *
const filename,
47443 const unsigned int size_x,
const unsigned int size_y,
47444 const unsigned int first_frame,
const unsigned int last_frame,
47445 const unsigned int step_frame,
const bool yuv2rgb) {
47446 if (!filename && !file)
47448 "load_yuv(): Specified filename is (null).",
47449 cimglist_instance);
47450 if (size_x%2 || size_y%2)
47452 "load_yuv(): Invalid odd XY dimensions %ux%u in file '%s'.",
47454 size_x,size_y,filename?filename:
"(FILE*)");
47455 if (!size_x || !size_y)
47457 "load_yuv(): Invalid sequence size (%u,%u) in file '%s'.",
47459 size_x,size_y,filename?filename:
"(FILE*)");
47462 nfirst_frame = first_frame<last_frame?first_frame:last_frame,
47463 nlast_frame = first_frame<last_frame?last_frame:first_frame,
47464 nstep_frame = step_frame?step_frame:1;
47466 CImg<ucharT> tmp(size_x,size_y,1,3), UV(size_x/2,size_y/2,1,2);
47467 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"rb");
47468 bool stop_flag =
false;
47470 if (nfirst_frame) {
47471 err = std::fseek(nfile,nfirst_frame*(size_x*size_y + size_x*size_y/2),SEEK_CUR);
47475 "load_yuv(): File '%s' doesn't contain frame number %u.",
47477 filename?filename:
"(FILE*)",nfirst_frame);
47480 unsigned int frame;
47481 for (frame = nfirst_frame; !stop_flag && frame<=nlast_frame; frame+=nstep_frame) {
47484 err = (int)std::fread((
void*)(tmp._data),1,(
unsigned long)tmp._width*tmp._height,nfile);
47485 if (err!=(
int)(tmp._width*tmp._height)) {
47489 "load_yuv(): File '%s' contains incomplete data or given image dimensions "
47490 "(%u,%u) are incorrect.",
47492 filename?filename:
"(FILE*)",size_x,size_y);
47496 err = (int)std::fread((
void*)(UV._data),1,(
size_t)(UV.size()),nfile);
47497 if (err!=(
int)(UV.size())) {
47501 "load_yuv(): File '%s' contains incomplete data or given image dimensions (%u,%u) "
47504 filename?filename:
"(FILE*)",size_x,size_y);
47506 cimg_forXY(UV,x,y) {
47507 const int x2 = x*2, y2 = y*2;
47508 tmp(x2,y2,1) = tmp(x2+1,y2,1) = tmp(x2,y2+1,1) = tmp(x2+1,y2+1,1) = UV(x,y,0);
47509 tmp(x2,y2,2) = tmp(x2+1,y2,2) = tmp(x2,y2+1,2) = tmp(x2+1,y2+1,2) = UV(x,y,1);
47511 if (yuv2rgb) tmp.YCbCrtoRGB();
47513 if (nstep_frame>1) std::fseek(nfile,(nstep_frame-1)*(size_x*size_y + size_x*size_y/2),SEEK_CUR);
47517 if (stop_flag && nlast_frame!=~0U && frame!=nlast_frame)
47519 "load_yuv(): Frame %d not reached since only %u frames were found in file '%s'.",
47521 nlast_frame,frame-1,filename?filename:
"(FILE*)");
47539 const unsigned int first_frame=0,
const unsigned int last_frame=~0U,
47540 const unsigned int step_frame=1,
const bool pixel_format=
true,
const bool resume=
false) {
47543 "load_ffmpeg(): Specified filename is (null).",
47544 cimglist_instance);
47547 nfirst_frame = first_frame<last_frame?first_frame:last_frame,
47548 nlast_frame = first_frame<last_frame?last_frame:first_frame,
47549 nstep_frame = step_frame?step_frame:1;
47552 #ifndef cimg_use_ffmpeg
47553 if ((nfirst_frame || nlast_frame!=~0U || nstep_frame>1) || (resume && (pixel_format || !pixel_format)))
47555 "load_ffmpeg(): Unable to load sub-frames from file '%s' unless libffmpeg "
47562 const PixelFormat ffmpeg_pixfmt = pixel_format?PIX_FMT_RGB24:PIX_FMT_GRAY8;
47563 avcodec_register_all();
47565 static AVFormatContext *format_ctx = 0;
47566 static AVCodecContext *codec_ctx = 0;
47567 static AVCodec *codec = 0;
47568 static AVFrame *avframe = avcodec_alloc_frame(), *converted_frame = avcodec_alloc_frame();
47569 static int vstream = 0;
47572 if (!format_ctx || !codec_ctx || !codec || !avframe || !converted_frame)
47574 "load_ffmpeg(): Failed to resume loading of file '%s', "
47575 "due to unallocated FFMPEG structures.",
47580 if (format_ctx) avformat_close_input(&format_ctx);
47581 if (avformat_open_input(&format_ctx,filename,0,0)!=0)
47583 "load_ffmpeg(): Failed to open file '%s'.",
47587 if (!avframe || !converted_frame || avformat_find_stream_info(format_ctx,NULL)<0) {
47588 avformat_close_input(&format_ctx); format_ctx = 0;
47591 #if cimg_verbosity>=3
47592 dump_format(format_ctx,0,0,0);
47597 if (!first_frame && !last_frame && !step_frame) {
47598 for (vstream = 0; vstream<(int)(format_ctx->nb_streams); ++vstream)
47599 if (format_ctx->streams[vstream]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
break;
47600 if (vstream==(
int)format_ctx->nb_streams)
assign();
47606 for (nb_frames = 0; av_read_frame(format_ctx,&packet)>=0; av_free_packet(&packet))
47607 if (packet.stream_index==vstream) {
47613 framew = format_ctx->streams[vstream]->codec->width,
47614 frameh = format_ctx->streams[vstream]->codec->height;
47616 num = (float)(format_ctx->streams[vstream]->r_frame_rate).num,
47617 den = (float)(format_ctx->streams[vstream]->r_frame_rate).den,
47621 (*this)[0].assign(1,4).fill((T)nb_frames,(T)framew,(T)frameh,(T)fps);
47622 (*this)[1] = (timestamps>
'y');
47624 avformat_close_input(&format_ctx); format_ctx = 0;
47628 for (vstream = 0; vstream<(int)(format_ctx->nb_streams) &&
47629 format_ctx->streams[vstream]->codec->codec_type!=AVMEDIA_TYPE_VIDEO; ) ++vstream;
47630 if (vstream==(
int)format_ctx->nb_streams) {
47631 avformat_close_input(&format_ctx); format_ctx = 0;
47634 codec_ctx = format_ctx->streams[vstream]->codec;
47635 codec = avcodec_find_decoder(codec_ctx->codec_id);
47639 if (avcodec_open2(codec_ctx,codec,NULL)<0) {
47645 const unsigned int numBytes = avpicture_get_size(ffmpeg_pixfmt,codec_ctx->width,codec_ctx->height);
47646 uint8_t *
const buffer =
new uint8_t[numBytes];
47647 avpicture_fill((AVPicture *)converted_frame,buffer,ffmpeg_pixfmt,codec_ctx->width,codec_ctx->height);
47648 const T foo = (T)0;
47650 for (
unsigned int frame = 0, next_frame = nfirst_frame;
47651 frame<=nlast_frame && av_read_frame(format_ctx,&packet)>=0; ) {
47652 if (packet.stream_index==(
int)vstream) {
47654 #if defined(AV_VERSION_INT)
47655 #if LIBAVCODEC_VERSION_INT<AV_VERSION_INT(52,26,0)
47656 avcodec_decode_video(codec_ctx,avframe,&decoded,packet.data, packet.size);
47658 avcodec_decode_video2(codec_ctx,avframe,&decoded,&packet);
47661 avcodec_decode_video(codec_ctx,avframe,&decoded,packet.data, packet.size);
47664 if (frame==next_frame) {
47665 SwsContext *c = sws_getContext(codec_ctx->width,codec_ctx->height,codec_ctx->pix_fmt,codec_ctx->width,
47666 codec_ctx->height,ffmpeg_pixfmt,1,0,0,0);
47667 sws_scale(c,avframe->data,avframe->linesize,0,codec_ctx->height,
47668 converted_frame->data,converted_frame->linesize);
47669 if (ffmpeg_pixfmt==PIX_FMT_RGB24) {
47670 CImg<ucharT> next_image(*converted_frame->data,3,codec_ctx->width,codec_ctx->height,1,
true);
47671 next_image._get_permute_axes(
"yzcx",foo).move_to(*
this);
47673 CImg<ucharT> next_image(*converted_frame->data,1,codec_ctx->width,codec_ctx->height,1,
true);
47674 next_image._get_permute_axes(
"yzcx",foo).move_to(*
this);
47676 next_frame+=nstep_frame;
47680 av_free_packet(&packet);
47681 if (next_frame>nlast_frame)
break;
47691 const unsigned int first_frame=0,
const unsigned int last_frame=~0U,
47692 const unsigned int step_frame=1,
const bool pixel_format=
true) {
47703 "load_ffmpeg_external(): Specified filename is (null).",
47704 cimglist_instance);
47706 char command[1024] = { 0 }, filetmp[512] = { 0 }, filetmp2[512] = { 0 };
47707 std::FILE *file = 0;
47709 cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s",
cimg::temporary_path(),cimg_file_separator,cimg::filenamerand());
47710 cimg_snprintf(filetmp2,
sizeof(filetmp2),
"%s_000001.ppm",filetmp);
47711 if ((file=std::fopen(filetmp2,
"rb"))!=0)
cimg::fclose(file);
47713 cimg_snprintf(filetmp2,
sizeof(filetmp2),
"%s_%%6d.ppm",filetmp);
47715 cimg_snprintf(command,
sizeof(command),
"%s -i \"%s\" \"%s\" >/dev/null 2>&1",
47720 cimg_snprintf(command,
sizeof(command),
"\"%s -i \"%s\" \"%s\"\" >NUL 2>&1",
47729 unsigned int i = 1;
47730 for (
bool stop_flag =
false; !stop_flag; ++i) {
47731 cimg_snprintf(filetmp2,
sizeof(filetmp2),
"%s_%.6u.ppm",filetmp,i);
47733 try { img.load_pnm(filetmp2); }
47735 if (img) { img.move_to(*
this); std::remove(filetmp2); }
47740 "load_ffmpeg_external(): Failed to open file '%s' with external command 'ffmpeg'.",
47759 "load_gif_external(): Specified filename is (null).",
47760 cimglist_instance);
47762 if (!_load_gif_external(filename,
false))
47763 if (!_load_gif_external(filename,
true))
47767 "load_gif_external(): Failed to open file '%s'.",
47768 cimglist_instance,filename);
47772 CImgList<T>& _load_gif_external(
const char *
const filename,
const bool use_graphicsmagick=
false) {
47773 char command[1024] = { 0 }, filetmp[512] = { 0 }, filetmp2[512] = { 0 };
47774 std::FILE *file = 0;
47776 cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s",
cimg::temporary_path(),cimg_file_separator,cimg::filenamerand());
47777 if (use_graphicsmagick) cimg_snprintf(filetmp2,
sizeof(filetmp2),
"%s.png.0",filetmp);
47778 else cimg_snprintf(filetmp2,
sizeof(filetmp2),
"%s-0.png",filetmp);
47779 if ((file=std::fopen(filetmp2,
"rb"))!=0)
cimg::fclose(file);
47782 if (use_graphicsmagick) cimg_snprintf(command,
sizeof(command),
"%s convert \"%s\" \"%s.png\" >/dev/null 2>&1",
47786 else cimg_snprintf(command,
sizeof(command),
"%s \"%s\" \"%s.png\" >/dev/null 2>&1",
47791 if (use_graphicsmagick) cimg_snprintf(command,
sizeof(command),
"\"%s convert \"%s\" \"%s.png\"\" >NUL 2>&1",
47795 else cimg_snprintf(command,
sizeof(command),
"\"%s \"%s\" \"%s.png\"\" >NUL 2>&1",
47806 cimg_snprintf(filetmp2,
sizeof(filetmp2),
"%s.png",filetmp);
47808 try { img.load_png(filetmp2); }
47809 catch (CImgException&) { }
47810 if (img) { img.move_to(*
this); std::remove(filetmp2); }
47812 unsigned int i = 0;
47813 for (
bool stop_flag =
false; !stop_flag; ++i) {
47814 if (use_graphicsmagick) cimg_snprintf(filetmp2,
sizeof(filetmp2),
"%s.png.%u",filetmp,i);
47815 else cimg_snprintf(filetmp2,
sizeof(filetmp2),
"%s-%u.png",filetmp,i);
47817 try { img.load_png(filetmp2); }
47818 catch (CImgException&) { stop_flag =
true; }
47819 if (img) { img.move_to(*
this); std::remove(filetmp2); }
47838 "load_gzip_external(): Specified filename is (null).",
47839 cimglist_instance);
47841 char command[1024] = { 0 }, filetmp[512] = { 0 }, body[512] = { 0 };
47845 std::FILE *file = 0;
47848 if (*ext2) cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s.%s",
47850 else cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s",
47853 if (*ext) cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s.%s",
47855 else cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s",
47858 if ((file=std::fopen(filetmp,
"rb"))!=0)
cimg::fclose(file);
47860 cimg_snprintf(command,
sizeof(command),
"%s -c \"%s\" > \"%s\"",
47865 if (!(file = std::fopen(filetmp,
"rb"))) {
47868 "load_gzip_external(): Failed to open file '%s'.",
47874 std::remove(filetmp);
47890 template<
typename tf,
typename tc>
47893 return get_load_off(filename,primitives,colors).move_to(*
this);
47897 template<
typename tf,
typename tc>
47911 const unsigned int first_frame=0,
const unsigned int last_frame=~0U,
47912 const unsigned int step_frame=1) {
47914 nfirst_frame = first_frame<last_frame?first_frame:last_frame,
47915 nstep_frame = step_frame?step_frame:1;
47916 unsigned int nlast_frame = first_frame<last_frame?last_frame:first_frame;
47917 #ifndef cimg_use_tiff
47918 if (nfirst_frame || nlast_frame!=~0U || nstep_frame!=1)
47920 "load_tiff(): Unable to load sub-images from file '%s' unless libtiff is enabled.",
47926 TIFF *tif = TIFFOpen(filename,
"r");
47928 unsigned int nb_images = 0;
47929 do ++nb_images;
while (TIFFReadDirectory(tif));
47930 if (nfirst_frame>=nb_images || (nlast_frame!=~0U && nlast_frame>=nb_images))
47932 "load_tiff(): Invalid specified frame range is [%u,%u] (step %u) since "
47933 "file '%s' contains %u image(s).",
47935 nfirst_frame,nlast_frame,nstep_frame,filename,nb_images);
47937 if (nfirst_frame>=nb_images)
return assign();
47938 if (nlast_frame>=nb_images) nlast_frame = nb_images-1;
47939 assign(1+(nlast_frame-nfirst_frame)/nstep_frame);
47940 TIFFSetDirectory(tif,0);
47941 #if cimg_verbosity>=3
47942 TIFFSetWarningHandler(0);
47943 TIFFSetErrorHandler(0);
47945 cimglist_for(*
this,l) _data[l]._load_tiff(tif,nfirst_frame + l*nstep_frame);
47948 "load_tiff(): Failed to open file '%s'.",
47957 const unsigned int first_frame=0,
const unsigned int last_frame=~0U,
47958 const unsigned int step_frame=1) {
47975 unsigned int msiz = 0;
47976 cimglist_for(*
this,l) msiz+=_data[l].size();
47978 const unsigned int mdisp = msiz<8*1024?0:(msiz<8*1024*1024?1:2);
47979 char _title[64] = { 0 };
47980 if (!title) cimg_snprintf(_title,
sizeof(_title),
"CImgList<%s>",
pixel_type());
47981 std::fprintf(
cimg::output(),
"%s%s%s%s: %sthis%s = %p, %ssize%s = %u/%u [%u %s], %sdata%s = (CImg<%s>*)%p",
47982 cimg::t_magenta,cimg::t_bold,title?title:_title,cimg::t_normal,
47983 cimg::t_bold,cimg::t_normal,(
void*)
this,
47984 cimg::t_bold,cimg::t_normal,_width,_allocated_width,
47985 mdisp==0?msiz:(mdisp==1?(msiz>>10):(msiz>>20)),
47986 mdisp==0?
"b":(mdisp==1?
"Kio":
"Mio"),
47988 if (_data) std::fprintf(
cimg::output(),
"..%p.\n",(
void*)((
char*)
end()-1));
47991 char tmp[16] = { 0 };
47992 cimglist_for(*
this,ll) {
47993 cimg_snprintf(tmp,
sizeof(tmp),
"[%d]",ll);
47995 _data[ll].print(tmp,display_stats);
47996 if (ll==3 && _width>8) { ll = _width-5; std::fprintf(
cimg::output(),
" ...\n"); }
48013 disp.
display(*
this,axis,align);
48029 const char axis=
'x',
const float align=0,
48030 unsigned int *
const XYZ=0)
const {
48031 bool is_exit =
false;
48032 return _display(disp,0,display_info,axis,align,XYZ,0,
true,is_exit);
48043 const char axis=
'x',
const float align=0,
48044 unsigned int *
const XYZ=0)
const {
48046 bool is_exit =
false;
48047 return _display(disp,title,display_info,axis,align,XYZ,0,
true,is_exit);
48051 const char axis,
const float align,
unsigned int *
const XYZ,
48052 const unsigned int orig,
const bool is_first_call,
bool &is_exit)
const {
48055 "display(): Empty instance.",
48056 cimglist_instance);
48059 unsigned int sum_width = 0, max_height = 0;
48060 cimglist_for(*
this,l) {
48061 const CImg<T> &img = _data[l];
48063 w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,
false),
48064 h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,
true);
48066 if (h>max_height) max_height = h;
48068 disp.
assign(cimg_fitscreen(sum_width,max_height,1),title?title:0,1);
48070 unsigned int max_width = 0, sum_height = 0;
48071 cimglist_for(*
this,l) {
48072 const CImg<T> &img = _data[l];
48074 w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,
false),
48075 h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,
true);
48076 if (w>max_width) max_width = w;
48079 disp.
assign(cimg_fitscreen(max_width,sum_height,1),title?title:0,1);
48082 }
else if (title) disp.
set_title(
"%s",title);
48088 const unsigned int dw = disp._width, dh = disp._height;
48089 if (!is_first_call)
48090 disp.
resize(cimg_fitscreen(_data[0]._width,_data[0]._height,_data[0]._depth),
false).
48091 set_title(
"%s (%ux%ux%ux%u)",
48092 dtitle.data(),_data[0]._width,_data[0]._height,_data[0]._depth,_data[0]._spectrum);
48093 _data[0]._display(disp,0,
false,XYZ,!is_first_call);
48094 if (disp.
key()) is_exit =
true;
48095 disp.
resize(cimg_fitscreen(dw,dh,1),
false).
set_title(
"%s",dtitle.data());
48097 bool disp_resize = !is_first_call;
48098 while (!disp.
is_closed() && !is_exit) {
48099 const CImg<intT> s = _get_select(disp,0,
true,axis,align,orig,disp_resize,!is_first_call,
true);
48100 disp_resize =
true;
48104 }
else if (disp.
wheel()) {
48105 const int wheel = disp.
wheel();
48107 if (!is_first_call && wheel<0)
break;
48108 if (wheel>0 && _width>=4) {
48111 ind0 = (
unsigned int)
cimg::max(0,s[0] - (
int)delta),
48113 if ((ind0!=0 || ind1!=_width-1) && ind1 - ind0>=3)
48114 get_shared_images(ind0,ind1)._display(disp,0,
false,axis,align,XYZ,orig + ind0,
false,is_exit);
48116 }
else if (s[0]!=0 || s[1]!=
width()-1)
48117 get_shared_images(s[0],s[1])._display(disp,0,
false,axis,align,XYZ,orig+s[0],
false,is_exit);
48129 const CImgList<T>&
save(
const char *
const filename,
const int number=-1,
const unsigned int digits=6)
const {
48132 "save(): Specified filename is (null).",
48133 cimglist_instance);
48135 const bool is_stdout = *filename==
'-' && (!filename[1] || filename[1]==
'.');
48137 char nfilename[1024] = { 0 };
48138 const char *
const fn = is_stdout?filename:number>=0?
cimg::number_filename(filename,number,digits,nfilename):
48141 #ifdef cimglist_save_plugin
48142 cimglist_save_plugin(fn);
48144 #ifdef cimglist_save_plugin1
48145 cimglist_save_plugin1(fn);
48147 #ifdef cimglist_save_plugin2
48148 cimglist_save_plugin2(fn);
48150 #ifdef cimglist_save_plugin3
48151 cimglist_save_plugin3(fn);
48153 #ifdef cimglist_save_plugin4
48154 cimglist_save_plugin4(fn);
48156 #ifdef cimglist_save_plugin5
48157 cimglist_save_plugin5(fn);
48159 #ifdef cimglist_save_plugin6
48160 cimglist_save_plugin6(fn);
48162 #ifdef cimglist_save_plugin7
48163 cimglist_save_plugin7(fn);
48165 #ifdef cimglist_save_plugin8
48166 cimglist_save_plugin8(fn);
48194 #ifdef cimg_use_tiff
48200 if (_width==1) _data[0].save(fn,-1);
48201 else cimglist_for(*
this,l) { _data[l].save(fn,is_stdout?-1:l);
if (is_stdout) std::fputc(EOF,stdout); }
48214 #ifdef cimg_use_tiff
48252 const unsigned int nb_loops=0) {
48253 char command[1024] = { 0 }, filetmp[512] = { 0 }, filetmp2[512] = { 0 };
48255 std::FILE *file = 0;
48257 #ifdef cimg_use_png
48258 #define _cimg_save_gif_ext "png"
48260 #define _cimg_save_gif_ext "ppm"
48264 cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s",
cimg::temporary_path(),cimg_file_separator,cimg::filenamerand());
48265 cimg_snprintf(filetmp2,
sizeof(filetmp2),
"%s_000001." _cimg_save_gif_ext,filetmp);
48266 if ((file=std::fopen(filetmp2,
"rb"))!=0)
cimg::fclose(file);
48268 cimglist_for(*
this,l) {
48269 cimg_snprintf(filetmp2,
sizeof(filetmp2),
"%s_%.6u." _cimg_save_gif_ext,filetmp,l+1);
48271 if (_data[l]._depth>1 || _data[l]._spectrum!=3) _data[l].get_resize(-100,-100,1,3).save(filetmp2);
48272 else _data[l].save(filetmp2);
48276 cimg_snprintf(command,
sizeof(command),
"%s -delay 1x%u -loop %u",
48279 cimg_snprintf(command,
sizeof(command),
"\"%s\" >/dev/null 2>&1",
48283 cimg_snprintf(command,
sizeof(command),
"\"%s -delay 1x%u -loop %u",
48286 cimg_snprintf(command,
sizeof(command),
"\"%s\"\" >NUL 2>&1",
48291 cimg_for(_command,p,
char)
if (!*p) *p =
' ';
48292 _command.
back() = 0;
48295 file = std::fopen(filename,
"rb");
48298 "save_gif_external(): Failed to save file '%s' with external command 'convert'.",
48302 cimglist_for_in(*
this,1,filenames._width-1,l) std::remove(filenames[l]);
48314 const unsigned int bitrate=2048)
const {
48317 "save_ffmpeg(): Specified filename is (null).",
48318 cimglist_instance);
48321 "save_ffmpeg(): Invalid specified framerate 0, for file '%s'.",
48326 cimglist_for(*
this,l)
if (!_data[l].
is_sameXYZ(_data[0]))
48328 "save_ffmpeg(): Invalid instance dimensions, for file '%s'.",
48332 #ifndef cimg_use_ffmpeg
48335 avcodec_register_all();
48338 frame_dimx = _data[0].width(),
48339 frame_dimy = _data[0].height(),
48340 frame_dimv = _data[0].spectrum();
48341 if (frame_dimv!=1 && frame_dimv!=3)
48343 "save_ffmpeg(): Image[0] (%u,%u,%u,%u,%p) has not 1 or 3 channels, for file '%s'.",
48345 _data[0]._width,_data[0]._height,_data[0]._depth,_data[0]._spectrum,_data,filename);
48347 PixelFormat dest_pxl_fmt = PIX_FMT_YUV420P;
48348 PixelFormat src_pxl_fmt = (frame_dimv==3)?PIX_FMT_RGB24:PIX_FMT_GRAY8;
48350 int sws_flags = SWS_FAST_BILINEAR;
48351 AVOutputFormat *fmt = 0;
48352 #if defined(AV_VERSION_INT)
48353 #if LIBAVFORMAT_VERSION_INT<AV_VERSION_INT(52,45,0)
48354 fmt = guess_format(0,filename,0);
48355 if (!fmt) fmt = guess_format(
"mpeg",0,0);
48357 fmt = av_guess_format(0,filename,0);
48358 if (!fmt) fmt = av_guess_format(
"mpeg",0,0);
48361 fmt = guess_format(0,filename,0);
48362 if (!fmt) fmt = guess_format(
"mpeg",0,0);
48367 "save_ffmpeg(): Unable to determine codec for file '%s'.",
48371 AVFormatContext *oc = 0;
48372 #if defined(AV_VERSION_INT)
48373 #if LIBAVFORMAT_VERSION_INT<AV_VERSION_INT(52,36,0)
48374 oc = av_alloc_format_context();
48376 oc = avformat_alloc_context();
48379 oc = av_alloc_format_context();
48383 "save_ffmpeg(): Failed to allocate FFMPEG structure for format context, for file '%s'.",
48387 AVCodec *codec = 0;
48388 AVFrame *picture = 0;
48389 AVFrame *tmp_pict = 0;
48391 std::sprintf(oc->filename,
"%s",filename);
48394 AVStream *video_str = 0;
48395 if (fmt->video_codec!=CODEC_ID_NONE) {
48396 video_str = avformat_new_stream(oc,NULL);
48400 "save_ffmpeg(): Failed to allocate FFMPEG structure for video stream, for file '%s'.",
48407 "save_ffmpeg(): Failed to identify proper codec, for file '%s'.",
48412 AVCodecContext *c = video_str->codec;
48413 c->codec_id = fmt->video_codec;
48414 c->codec_type = AVMEDIA_TYPE_VIDEO;
48415 c->bit_rate = 1024*bitrate;
48416 c->width = frame_dimx;
48417 c->height = frame_dimy;
48418 c->time_base.num = 1;
48419 c->time_base.den = fps;
48421 c->pix_fmt = dest_pxl_fmt;
48422 if (c->codec_id==CODEC_ID_MPEG2VIDEO) c->max_b_frames = 2;
48423 if (c->codec_id==CODEC_ID_MPEG1VIDEO) c->mb_decision = 2;
48426 codec = avcodec_find_encoder(c->codec_id);
48430 "save_ffmpeg(): No valid codec found for file '%s'.",
48434 if (avcodec_open2(c,codec,NULL)<0)
48436 "save_ffmpeg(): Failed to open codec for file '%s'.",
48440 tmp_pict = avcodec_alloc_frame();
48442 avcodec_close(video_str->codec);
48445 "save_ffmpeg(): Failed to allocate memory for file '%s'.",
48449 tmp_pict->linesize[0] = (src_pxl_fmt==PIX_FMT_RGB24)?3*frame_dimx:frame_dimx;
48451 int tmp_size = avpicture_get_size(src_pxl_fmt,frame_dimx,frame_dimy);
48452 uint8_t *tmp_buffer = (uint8_t*)av_malloc(tmp_size);
48455 avcodec_close(video_str->codec);
48458 "save_ffmpeg(): Failed to allocate memory for file '%s'.",
48464 avpicture_fill((AVPicture*)tmp_pict,tmp_buffer,src_pxl_fmt,frame_dimx,frame_dimy);
48465 picture = avcodec_alloc_frame();
48467 av_free(tmp_pict->data[0]);
48469 avcodec_close(video_str->codec);
48472 "save_ffmpeg(): Failed to allocate memory for file '%s'.",
48477 int size = avpicture_get_size(c->pix_fmt,frame_dimx,frame_dimy);
48478 uint8_t *buffer = (uint8_t*)av_malloc(size);
48481 av_free(tmp_pict->data[0]);
48483 avcodec_close(video_str->codec);
48486 "save_ffmpeg(): Failed to allocate memory for file '%s'.",
48492 avpicture_fill((AVPicture*)picture,buffer,c->pix_fmt,frame_dimx,frame_dimy);
48495 if (!(fmt->flags&AVFMT_NOFILE)) {
48496 if (avio_open(&oc->pb,filename,AVIO_FLAG_WRITE)<0)
48498 "save_ffmpeg(): Failed to open file '%s'.",
48503 if (avformat_write_header(oc,NULL)<0)
48505 "save_ffmpeg(): Failed to write header in file '%s'.",
48509 SwsContext *img_convert_context = 0;
48510 img_convert_context = sws_getContext(frame_dimx,frame_dimy,src_pxl_fmt,
48511 c->width,c->height,c->pix_fmt,sws_flags,0,0,0);
48512 if (!img_convert_context) {
48514 av_free(picture->data);
48516 av_free(tmp_pict->data[0]);
48518 avcodec_close(video_str->codec);
48521 "save_ffmpeg(): Failed to get conversion context for file '%s'.",
48525 int ret = 0, out_size;
48526 uint8_t *video_outbuf = 0;
48527 int video_outbuf_size = 1000000;
48528 video_outbuf = (uint8_t*)av_malloc(video_outbuf_size);
48529 if (!video_outbuf) {
48531 av_free(picture->data);
48533 av_free(tmp_pict->data[0]);
48535 avcodec_close(video_str->codec);
48538 "save_ffmpeg(): Failed to allocate memory, for file '%s'.",
48544 cimglist_for(*
this,i) {
48545 CImg<uint8_t> currentIm = _data[i], red, green, blue, gray;
48546 if (src_pxl_fmt==PIX_FMT_RGB24) {
48547 red = currentIm.get_shared_channel(0);
48548 green = currentIm.get_shared_channel(1);
48549 blue = currentIm.get_shared_channel(2);
48550 cimg_forXY(currentIm,X,Y) {
48551 tmp_pict->data[0][Y*tmp_pict->linesize[0] + 3*X] = red(X,Y);
48552 tmp_pict->data[0][Y*tmp_pict->linesize[0] + 3*X + 1] = green(X,Y);
48553 tmp_pict->data[0][Y*tmp_pict->linesize[0] + 3*X + 2] = blue(X,Y);
48556 gray = currentIm.get_shared_channel(0);
48557 cimg_forXY(currentIm,X,Y) tmp_pict->data[0][Y*tmp_pict->linesize[0] + X] = gray(X,Y);
48559 if (!video_str)
break;
48560 if (sws_scale(img_convert_context,tmp_pict->data,tmp_pict->linesize,0,
48561 c->height,picture->data,picture->linesize)<0)
break;
48565 av_init_packet(&pkt);
48566 out_size = avcodec_encode_video2(c,&pkt,picture,&got_packet);
48568 pkt.pts = av_rescale_q(c->coded_frame->pts,c->time_base,video_str->time_base);
48569 if (c->coded_frame->key_frame) pkt.flags|=AV_PKT_FLAG_KEY;
48570 pkt.stream_index = video_str->index;
48571 pkt.data = video_outbuf;
48572 pkt.size = out_size;
48573 ret = av_write_frame(oc,&pkt);
48574 }
else if (out_size<0)
break;
48580 avcodec_close(video_str->codec);
48581 av_free(picture->data[0]);
48583 av_free(tmp_pict->data[0]);
48586 if (av_write_trailer(oc)<0)
48588 "save_ffmpeg(): Failed to write trailer for file '%s'.",
48592 av_freep(&oc->streams[0]->codec);
48593 av_freep(&oc->streams[0]);
48594 if (!(fmt->flags&AVFMT_NOFILE)) {
48603 av_free(video_outbuf);
48608 const CImgList<T>& _save_yuv(std::FILE *
const file,
const char *
const filename,
const bool is_rgb)
const {
48609 if (!file && !filename)
48611 "save_yuv(): Specified filename is (null).",
48612 cimglist_instance);
48614 if ((*
this)[0].
width()%2 || (*
this)[0].
height()%2)
48615 throw CImgInstanceException(_cimglist_instance
48616 "save_yuv(): Invalid odd instance dimensions (%u,%u) for file '%s'.",
48619 filename?filename:
"(FILE*)");
48621 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"wb");
48622 cimglist_for(*
this,l) {
48623 CImg<ucharT> YCbCr((*
this)[l]);
48624 if (is_rgb) YCbCr.RGBtoYCbCr();
48625 cimg::fwrite(YCbCr._data,(
unsigned long)YCbCr._width*YCbCr._height,nfile);
48626 cimg::fwrite(YCbCr.get_resize(YCbCr._width/2, YCbCr._height/2,1,3,3).data(0,0,0,1),
48627 (
unsigned long)YCbCr._width*YCbCr._height/2,nfile);
48639 return _save_yuv(0,filename,is_rgb);
48648 return _save_yuv(file,0,is_rgb);
48651 const CImgList<T>& _save_cimg(std::FILE *
const file,
const char *
const filename,
const bool is_compressed)
const {
48652 if (!file && !filename)
48654 "save_cimg(): Specified filename is (null).",
48655 cimglist_instance);
48656 #ifndef cimg_use_zlib
48659 "save_cimg(): Unable to save compressed data in file '%s' unless zlib is enabled, "
48660 "saving them uncompressed.",
48662 filename?filename:
"(FILE*)");
48664 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"wb");
48666 if (std::strstr(ptype,
"unsigned")==ptype) std::fprintf(nfile,
"%u unsigned_%s %s_endian\n",_width,ptype+9,etype);
48667 else std::fprintf(nfile,
"%u %s %s_endian\n",_width,ptype,etype);
48668 cimglist_for(*
this,l) {
48669 const CImg<T>& img = _data[l];
48670 std::fprintf(nfile,
"%u %u %u %u",img._width,img._height,img._depth,img._spectrum);
48675 bool failed_to_compress =
true;
48676 if (is_compressed) {
48677 #ifdef cimg_use_zlib
48678 const unsigned long siz =
sizeof(T)*ref.size();
48679 unsigned long csiz = siz + siz/100 + 16;
48680 Bytef *
const cbuf =
new Bytef[csiz];
48681 if (compress(cbuf,&csiz,(Bytef*)ref._data,siz))
48683 "save_cimg(): Failed to save compressed data for file '%s', saving them uncompressed.",
48685 filename?filename:
"(FILE*)");
48687 std::fprintf(nfile,
" #%lu\n",csiz);
48690 failed_to_compress =
false;
48694 if (failed_to_compress) {
48695 std::fputc(
'\n',nfile);
48698 }
else std::fputc(
'\n',nfile);
48710 return _save_cimg(0,filename,is_compressed);
48719 return _save_cimg(file,0,is_compressed);
48722 const CImgList<T>& _save_cimg(std::FILE *
const file,
const char *
const filename,
48723 const unsigned int n0,
48724 const unsigned int x0,
const unsigned int y0,
48725 const unsigned int z0,
const unsigned int c0)
const {
48726 #define _cimg_save_cimg_case(Ts,Tss) \
48727 if (!saved && !cimg::strcasecmp(Ts,str_pixeltype)) { \
48728 for (unsigned int l = 0; l<lmax; ++l) { \
48729 j = 0; while((i=std::fgetc(nfile))!='\n') tmp[j++]=(char)i; tmp[j] = 0; \
48730 W = H = D = C = 0; \
48731 if (std::sscanf(tmp,"%u %u %u %u",&W,&H,&D,&C)!=4) \
48732 throw CImgIOException(_cimglist_instance \
48733 "save_cimg(): Invalid size (%u,%u,%u,%u) of image[%u], for file '%s'.", \
48734 cimglist_instance, \
48735 W,H,D,C,l,filename?filename:"(FILE*)"); \
48737 if (l<n0 || x0>=W || y0>=H || z0>=D || c0>=D) std::fseek(nfile,W*H*D*C*sizeof(Tss),SEEK_CUR); \
48739 const CImg<T>& img = (*this)[l - n0]; \
48740 const T *ptrs = img._data; \
48741 const unsigned int \
48742 x1 = x0 + img._width - 1, \
48743 y1 = y0 + img._height - 1, \
48744 z1 = z0 + img._depth - 1, \
48745 c1 = c0 + img._spectrum - 1, \
48746 nx1 = x1>=W?W-1:x1, \
48747 ny1 = y1>=H?H-1:y1, \
48748 nz1 = z1>=D?D-1:z1, \
48749 nc1 = c1>=C?C-1:c1; \
48750 CImg<Tss> raw(1+nx1-x0); \
48751 const unsigned int skipvb = c0*W*H*D*sizeof(Tss); \
48752 if (skipvb) std::fseek(nfile,skipvb,SEEK_CUR); \
48753 for (unsigned int v = 1 + nc1 - c0; v; --v) { \
48754 const unsigned int skipzb = z0*W*H*sizeof(Tss); \
48755 if (skipzb) std::fseek(nfile,skipzb,SEEK_CUR); \
48756 for (unsigned int z = 1 + nz1 - z0; z; --z) { \
48757 const unsigned int skipyb = y0*W*sizeof(Tss); \
48758 if (skipyb) std::fseek(nfile,skipyb,SEEK_CUR); \
48759 for (unsigned int y = 1 + ny1 - y0; y; --y) { \
48760 const unsigned int skipxb = x0*sizeof(Tss); \
48761 if (skipxb) std::fseek(nfile,skipxb,SEEK_CUR); \
48762 raw.assign(ptrs, raw._width); \
48763 ptrs+=img._width; \
48764 if (endian) cimg::invert_endianness(raw._data,raw._width); \
48765 cimg::fwrite(raw._data,raw._width,nfile); \
48766 const unsigned int skipxe = (W - 1 - nx1)*sizeof(Tss); \
48767 if (skipxe) std::fseek(nfile,skipxe,SEEK_CUR); \
48769 const unsigned int skipye = (H - 1 - ny1)*W*sizeof(Tss); \
48770 if (skipye) std::fseek(nfile,skipye,SEEK_CUR); \
48772 const unsigned int skipze = (D - 1 - nz1)*W*H*sizeof(Tss); \
48773 if (skipze) std::fseek(nfile,skipze,SEEK_CUR); \
48775 const unsigned int skipve = (C - 1 - nc1)*W*H*D*sizeof(Tss); \
48776 if (skipve) std::fseek(nfile,skipve,SEEK_CUR); \
48783 if (!file && !filename)
48785 "save_cimg(): Specified filename is (null).",
48786 cimglist_instance);
48789 "save_cimg(): Empty instance, for file '%s'.",
48791 filename?filename:
"(FILE*)");
48793 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"rb+");
48795 char tmp[256] = { 0 }, str_pixeltype[256] = { 0 }, str_endian[256] = { 0 };
48796 unsigned int j, err, N, W, H, D, C;
48798 j = 0;
while((i=std::fgetc(nfile))!=
'\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0;
48799 err = std::sscanf(tmp,
"%u%*c%255[A-Za-z_]%*c%255[sA-Za-z_ ]",&N,str_pixeltype,str_endian);
48802 throw CImgIOException(_cimglist_instance
48803 "save_cimg(): CImg header not found in file '%s'.",
48805 filename?filename:
"(FILE*)");
48809 const unsigned int lmax =
cimg::min(N,n0+_width);
48810 _cimg_save_cimg_case(
"bool",
bool);
48811 _cimg_save_cimg_case(
"unsigned_char",
unsigned char);
48812 _cimg_save_cimg_case(
"uchar",
unsigned char);
48813 _cimg_save_cimg_case(
"char",
char);
48814 _cimg_save_cimg_case(
"unsigned_short",
unsigned short);
48815 _cimg_save_cimg_case(
"ushort",
unsigned short);
48816 _cimg_save_cimg_case(
"short",
short);
48817 _cimg_save_cimg_case(
"unsigned_int",
unsigned int);
48818 _cimg_save_cimg_case(
"uint",
unsigned int);
48819 _cimg_save_cimg_case(
"int",
int);
48820 _cimg_save_cimg_case(
"unsigned_long",
unsigned long);
48821 _cimg_save_cimg_case(
"ulong",
unsigned long);
48822 _cimg_save_cimg_case(
"long",
long);
48823 _cimg_save_cimg_case(
"float",
float);
48824 _cimg_save_cimg_case(
"double",
double);
48827 throw CImgIOException(_cimglist_instance
48828 "save_cimg(): Unsupported data type '%s' for file '%s'.",
48830 filename?filename:
"(FILE*)",str_pixeltype);
48846 const unsigned int n0,
48847 const unsigned int x0,
const unsigned int y0,
48848 const unsigned int z0,
const unsigned int c0)
const {
48849 return _save_cimg(0,filename,n0,x0,y0,z0,c0);
48862 const unsigned int n0,
48863 const unsigned int x0,
const unsigned int y0,
48864 const unsigned int z0,
const unsigned int c0)
const {
48865 return _save_cimg(file,0,n0,x0,y0,z0,c0);
48868 static void _save_empty_cimg(std::FILE *
const file,
const char *
const filename,
48869 const unsigned int nb,
48870 const unsigned int dx,
const unsigned int dy,
48871 const unsigned int dz,
const unsigned int dc) {
48872 std::FILE *
const nfile = file?file:
cimg::fopen(filename,
"wb");
48873 const unsigned long siz = (
unsigned long)dx*dy*dz*dc*
sizeof(T);
48874 std::fprintf(nfile,
"%u %s\n",nb,
pixel_type());
48875 for (
unsigned int i=nb; i; --i) {
48876 std::fprintf(nfile,
"%u %u %u %u\n",dx,dy,dz,dc);
48877 for (
unsigned long off=siz; off; --off) std::fputc(0,nfile);
48892 const unsigned int nb,
48893 const unsigned int dx,
const unsigned int dy=1,
48894 const unsigned int dz=1,
const unsigned int dc=1) {
48895 return _save_empty_cimg(0,filename,nb,dx,dy,dz,dc);
48908 const unsigned int nb,
48909 const unsigned int dx,
const unsigned int dy=1,
48910 const unsigned int dz=1,
const unsigned int dc=1) {
48911 return _save_empty_cimg(file,0,nb,dx,dy,dz,dc);
48922 "save_tiff(): Specified filename is (null).",
48923 cimglist_instance);
48926 #ifndef cimg_use_tiff
48927 if (_width==1) _data[0].save_tiff(filename,compression_type);
48928 else cimglist_for(*
this,l) {
48929 char nfilename[1024] = { 0 };
48931 _data[l].save_tiff(nfilename,compression_type);
48934 TIFF *tif = TIFFOpen(filename,
"w");
48936 for (
unsigned int dir = 0, l = 0; l<_width; ++l) {
48937 const CImg<T>& img = (*this)[l];
48939 if (img._depth==1) img._save_tiff(tif,dir++,compression_type);
48940 else cimg_forZ(img,z) img.get_slice(z)._save_tiff(tif,dir++,compression_type);
48946 "save_tiff(): Failed to open stream for file '%s'.",
48961 "save_gzip_external(): Specified filename is (null).",
48962 cimglist_instance);
48964 char command[1024] = { 0 }, filetmp[512] = { 0 }, body[512] = { 0 };
48971 if (*ext2) cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s.%s",
48973 else cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s.cimg",
48976 if (*ext) cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s.%s",
48978 else cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s.cimg",
48981 if ((file=std::fopen(filetmp,
"rb"))!=0)
cimg::fclose(file);
48984 if (is_saveable(body)) {
48986 cimg_snprintf(command,
sizeof(command),
"%s -c \"%s\" > \"%s\"",
48991 file = std::fopen(filename,
"rb");
48994 "save_gzip_external(): Failed to save file '%s' with external command 'gzip'.",
48998 std::remove(filetmp);
49000 char nfilename[1024] = { 0 };
49001 cimglist_for(*
this,l) {
49003 if (*ext) std::sprintf(nfilename + std::strlen(nfilename),
".%s",ext);
49004 _data[l].save_gzip_external(nfilename);
49018 const unsigned int fps=25,
const unsigned int bitrate=2048)
const {
49021 "save_ffmpeg_external(): Specified filename is (null).",
49022 cimglist_instance);
49027 *
const _codec = codec?codec:!
cimg::strcasecmp(ext,
"flv")?
"flv":
"mpeg2video";
49029 char command[1024] = { 0 }, filetmp[512] = { 0 }, filetmp2[512] = { 0 };
49031 std::FILE *file = 0;
49032 cimglist_for(*
this,l)
if (!_data[l].
is_sameXYZ(_data[0]))
49034 "save_ffmpeg_external(): Invalid instance dimensions for file '%s'.",
49038 cimg_snprintf(filetmp,
sizeof(filetmp),
"%s%c%s",
cimg::temporary_path(),cimg_file_separator,cimg::filenamerand());
49039 cimg_snprintf(filetmp2,
sizeof(filetmp2),
"%s_000001.ppm",filetmp);
49040 if ((file=std::fopen(filetmp2,
"rb"))!=0)
cimg::fclose(file);
49042 cimglist_for(*
this,l) {
49043 cimg_snprintf(filetmp2,
sizeof(filetmp2),
"%s_%.6u.ppm",filetmp,l+1);
49045 if (_data[l]._depth>1 || _data[l]._spectrum!=3) _data[l].get_resize(-100,-100,1,3).save_pnm(filetmp2);
49046 else _data[l].save_pnm(filetmp2);
49049 cimg_snprintf(command,
sizeof(command),
"%s -i \"%s_%%6d.ppm\" -vcodec %s -b %uk -r %u -y \"%s\" >/dev/null 2>&1",
49052 _codec,bitrate,fps,
49055 cimg_snprintf(command,
sizeof(command),
"\"%s -i \"%s_%%6d.ppm\" -vcodec %s -b %uk -r %u -y \"%s\"\" >NUL 2>&1",
49058 _codec,bitrate,fps,
49062 file = std::fopen(filename,
"rb");
49065 "save_ffmpeg_external(): Failed to save file '%s' with external command 'ffmpeg'.",
49069 cimglist_for(*
this,l) std::remove(filenames[l]);
49084 return get_crop_font().
move_to(*
this);
49092 cimglist_for(*
this,l) {
49093 const CImg<T>& letter = (*this)[l];
49094 int xmin = letter._width, xmax = 0;
49095 cimg_forXY(letter,x,y)
if (letter(x,y)) {
if (x<xmin) xmin = x;
if (x>xmax) xmax = x; }
49096 if (xmin>xmax)
CImg<T>(letter._width,letter._height,1,letter._spectrum,0).
move_to(res);
49097 else letter.get_crop(xmin,0,xmax,letter._height-1).move_to(res);
49099 res[
' '].resize(res[
'f']._width,-100,-100,-100,0);
49100 if (
' '+256<res.size()) res[
' '+256].
resize(res[
'f']._width,-100,-100,-100,0);
49114 const char *data_fonts[] = { cimg::data_font12x13, cimg::data_font20x23, cimg::data_font47x53, 0 };
49115 const unsigned int data_widths[] = { 12,20,47,90 }, data_heights[] = { 13,23,53,103 },
49116 data_Ms[] = { 86,79,57,47 };
49117 const unsigned int data_ind = font_height<=13?0:font_height<=23?1:font_height<=53?2:3;
49121 const unsigned int w = data_widths[data_ind], h = data_heights[data_ind], M = data_Ms[data_ind];
49122 base_font.assign(256*w,h);
49123 const char *data_font = data_fonts[data_ind];
49124 unsigned char *ptrd = base_font;
49125 const unsigned char *
const ptrde = base_font.end();
49131 (
unsigned int)std::strlen(cimg::_data_font90x103[0]),1,1,1,
true),
49133 (
unsigned int)std::strlen(cimg::_data_font90x103[1])+1,1,1,1,
true))>
'x').
49135 data_font = data90x103.data();
49139 for (
const char *ptrs = data_font; *ptrs; ++ptrs) {
49140 const int c = *ptrs-M-32, v = c>=0?255:0, n = c>=0?c:-c;
49141 if (ptrd+n<=ptrde) { std::memset(ptrd,v,n); ptrd+=n; }
49142 else { std::memset(ptrd,v,ptrde-ptrd);
break; }
49148 static bool is_variable_widths[16] = { 0 };
49149 unsigned int ind = ~0U;
49150 for (
int i = 0; i<16; ++i)
49151 if (!fonts[i] || (is_variable_widths[i]==is_variable_width && font_height==fonts[i][0]._height)) {
49156 std::memmove(is_variable_widths,is_variable_widths+1,15*
sizeof(
bool));
49163 const unsigned int padding_x = font_height<33?1:font_height<53?2:font_height<103?3:4;
49164 is_variable_widths[ind] = is_variable_width;
49165 font = base_font.get_split(
'x',256);
49166 if (font_height!=font[0]._height)
49167 cimglist_for(font,l)
49168 font[l].resize(
cimg::max(1U,font[l]._width*font_height/font[l]._height),font_height,-100,-100,
49169 font[0]._height>font_height?2:5);
49170 if (is_variable_width) font.crop_font();
49171 cimglist_for(font,l) font[l].resize(font[l]._width + padding_x,-100,1,1,0,0,0.5);
49172 font.insert(256,0);
49173 cimglist_for_in(font,0,255,l) font[l].assign(font[l+256]._width,font[l+256]._height,1,3,1);
49186 if (_width==1) insert(1);
49189 "FFT(): Instance has more than 2 images",
49190 cimglist_instance);
49207 if (_width==1) insert(1);
49210 "FFT(): Instance has more than 2 images",
49211 cimglist_instance);
49226 cimglist_for(*
this,l) {
49228 switch (p.size()) {
49229 case 2:
case 3:
cimg::swap(p[0],p[1]);
break;
49230 case 6:
cimg::swap(p[0],p[1],p[2],p[4],p[3],p[5]);
break;
49231 case 9:
cimg::swap(p[0],p[1],p[3],p[5],p[4],p[6]);
break;
49232 case 4:
cimg::swap(p[0],p[1],p[2],p[3]);
break;
49233 case 12:
cimg::swap(p[0],p[1],p[2],p[3],p[4],p[6],p[5],p[7],p[8],p[10],p[9],p[11]);
break;
49258 inline unsigned long tictoc(
const bool is_tic) {
49260 static CImg<unsigned long> times(64);
49261 static unsigned int pos = 0;
49265 if (pos>=times._width)
49266 throw CImgArgumentException(
"cimg::tic(): Too much calls to 'cimg::tic()' without calls to 'cimg::toc()'.");
49272 throw CImgArgumentException(
"cimg::toc(): No previous call to 'cimg::tic()' has been made.");
49273 const unsigned long
49275 dt = t1>=t0?(t1-t0):cimg::type<unsigned long>::max();
49277 edays = (
unsigned int)(dt/86400000.0),
49278 ehours = (
unsigned int)((dt - edays*86400000.0)/3600000.0),
49279 emin = (
unsigned int)((dt - edays*86400000.0 - ehours*3600000.0)/60000.0),
49280 esec = (
unsigned int)((dt - edays*86400000.0 - ehours*3600000.0 - emin*60000.0)/1000.0),
49281 ems = (
unsigned int)(dt - edays*86400000.0 - ehours*3600000.0 - emin*60000.0 - esec*1000.0);
49282 if (!edays && !ehours && !emin && !esec)
49283 std::fprintf(
cimg::output(),
"%s[CImg]%*sElapsed time: %u ms%s\n",
49284 cimg::t_red,1+2*pos,
"",ems,cimg::t_normal);
49286 if (!edays && !ehours && !emin)
49287 std::fprintf(
cimg::output(),
"%s[CImg]%*sElapsed time: %u sec %u ms%s\n",
49288 cimg::t_red,1+2*pos,
"",esec,ems,cimg::t_normal);
49290 if (!edays && !ehours)
49291 std::fprintf(
cimg::output(),
"%s[CImg]%*sElapsed time: %u min %u sec %u ms%s\n",
49292 cimg::t_red,1+2*pos,
"",emin,esec,ems,cimg::t_normal);
49295 std::fprintf(
cimg::output(),
"%s[CImg]%*sElapsed time: %u hours %u min %u sec %u ms%s\n",
49296 cimg::t_red,1+2*pos,
"",ehours,emin,esec,ems,cimg::t_normal);
49298 std::fprintf(
cimg::output(),
"%s[CImg]%*sElapsed time: %u days %u hours %u min %u sec %u ms%s\n",
49299 cimg::t_red,1+2*pos,
"",edays,ehours,emin,esec,ems,cimg::t_normal);
49327 template<
typename t>
49328 inline int dialog(
const char *
const title,
const char *
const msg,
49329 const char *
const button1_label,
const char *
const button2_label,
49330 const char *
const button3_label,
const char *
const button4_label,
49331 const char *
const button5_label,
const char *
const button6_label,
49332 const CImg<t>& logo,
const bool is_centered =
false) {
49333 #if cimg_display==0
49334 cimg::unused(title,msg,button1_label,button2_label,button3_label,button4_label,button5_label,button6_label,
49335 logo._data,is_centered);
49338 const unsigned char
49339 black[] = { 0,0,0 }, white[] = { 255,255,255 }, gray[] = { 200,200,200 }, gray2[] = { 150,150,150 };
49350 if (!buttons._width)
49352 cimglist_for(buttons,l) buttons[l].resize(-100,-100,1,3);
49354 unsigned int bw = 0, bh = 0;
49355 cimglist_for(buttons,l) { bw =
cimg::max(bw,buttons[l]._width); bh =
cimg::max(bh,buttons[l]._height); }
49357 if (bw<64) bw = 64;
49358 if (bw>128) bw = 128;
49359 if (bh<24) bh = 24;
49360 if (bh>48) bh = 48;
49363 button.draw_rectangle(0,0,bw-1,bh-1,gray);
49364 button.draw_line(0,0,bw-1,0,white).draw_line(0,bh-1,0,0,white);
49365 button.draw_line(bw-1,0,bw-1,bh-1,black).draw_line(bw-1,bh-1,0,bh-1,black);
49366 button.draw_line(1,bh-2,bw-2,bh-2,gray2).draw_line(bw-2,bh-2,bw-2,1,gray2);
49368 sbutton.draw_rectangle(0,0,bw-1,bh-1,gray);
49369 sbutton.draw_line(0,0,bw-1,0,black).draw_line(bw-1,0,bw-1,bh-1,black);
49370 sbutton.draw_line(bw-1,bh-1,0,bh-1,black).draw_line(0,bh-1,0,0,black);
49371 sbutton.draw_line(1,1,bw-2,1,white).draw_line(1,bh-2,1,1,white);
49372 sbutton.draw_line(bw-2,1,bw-2,bh-2,black).draw_line(bw-2,bh-2,1,bh-2,black);
49373 sbutton.draw_line(2,bh-3,bw-3,bh-3,gray2).draw_line(bw-3,bh-3,bw-3,2,gray2);
49374 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);
49375 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);
49377 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);
49378 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);
49379 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);
49381 cimglist_for(buttons,ll) {
49392 ((
CImg<unsigned char>().
draw_text(0,0,
"%s",gray,0,1,13,msg)*=-1)+=200).
resize(-100,-100,1,3).move_to(canvas);
49395 bwall = (buttons._width-1)*(12+bw) + bw,
49396 w =
cimg::max(196U,36+logo._width+canvas._width,24+bwall),
49397 h =
cimg::max(96U,36+canvas._height+bh,36+logo._height+bh),
49398 lx = 12 + (canvas._data?0:((w-24-logo._width)/2)),
49399 ly = (h-12-bh-logo._height)/2,
49400 tx = lx+logo._width+12,
49401 ty = (h-12-bh-canvas._height)/2,
49408 draw_line(0,0,w-1,0,white).draw_line(0,h-1,0,0,white).
49409 draw_line(w-1,0,w-1,h-1,black).draw_line(w-1,h-1,0,h-1,black).
49414 draw_line(0,0,w-1,0,white).draw_line(0,h-1,0,0,white).
49415 draw_line(w-1,0,w-1,h-1,black).draw_line(w-1,h-1,0,h-1,black);
49416 if (logo._data) canvas.draw_image(lx,ly,logo);
49418 unsigned int xbuttons[6] = { 0 };
49419 cimglist_for(buttons,lll) { xbuttons[lll] = bx+(bw+12)*lll; canvas.draw_image(xbuttons[lll],by,buttons[lll]); }
49422 CImgDisplay disp(canvas,title?title:
" ",0,
false,is_centered?
true:
false);
49425 bool stop_flag =
false, refresh =
false;
49426 int oselected = -1, oclicked = -1, selected = -1, clicked = -1;
49427 while (!disp.
is_closed() && !stop_flag) {
49434 else canvas.display(disp);
49442 oclicked = clicked;
49444 cimglist_for(buttons,l)
49446 disp.
mouse_x()>=(int)xbuttons[l] && disp.
mouse_x()<(int)(xbuttons[l]+bw)) {
49447 clicked = selected = l;
49450 if (clicked!=oclicked) refresh =
true;
49451 }
else if (clicked>=0) stop_flag =
true;
49454 oselected = selected;
49455 switch (disp.
key()) {
49456 case cimg::keyESC : selected=-1; stop_flag =
true;
break;
49457 case cimg::keyENTER :
if (selected<0) selected = 0; stop_flag =
true;
break;
49462 case cimg::keyARROWUP : selected = (selected+buttons._width-1)%buttons._width;
break;
49465 if (selected!=oselected) refresh =
true;
49468 if (!disp) selected = -1;
49474 inline int dialog(
const char *
const title,
const char *
const msg,
49475 const char *
const button1_label,
const char *
const button2_label,
const char *
const button3_label,
49476 const char *
const button4_label,
const char *
const button5_label,
const char *
const button6_label,
49477 const bool is_centered) {
49478 return dialog(title,msg,button1_label,button2_label,button3_label,button4_label,button5_label,button6_label,
49498 inline double eval(
const char *
const expression,
const double x,
const double y,
const double z,
const double c) {
49500 return empty.eval(expression,x,y,z,c);
49503 template<
typename t>
49506 return empty.eval(expression,xyzc);
49518 #ifdef _cimg_redefine_False
49521 #ifdef _cimg_redefine_True
49524 #ifdef _cimg_redefine_None
49527 #ifdef _cimg_redefine_min
49528 #define min(a,b) (((a)<(b))?(a):(b))
49530 #ifdef _cimg_redefine_max
49531 #define max(a,b) (((a)>(b))?(a):(b))
49533 #ifdef _cimg_redefine_PI
49534 #define PI 3.141592653589793238462643383
CImg< T > & front()
Return reference to the first image of the list.
CImg< _cimg_Tt > get_erode(const CImg< t > &mask, const unsigned int boundary_conditions=1, const bool is_normalized=false) const
Erode image by a structuring element .
const CImgList< T > & save(const char *const filename, const int number=-1, const unsigned int digits=6) const
Save list into a file.
static void wait(CImgDisplay &disp1, CImgDisplay &disp2, CImgDisplay &disp3, CImgDisplay &disp4, CImgDisplay &disp5)
Wait for any event occuring either on the display disp1, disp2, disp3, disp4 or disp5.
CImgDisplay & assign()
Destructor - Empty constructor .
CImg< T > get_rol(const CImg< t > &img) const
Compute the bitwise left rotation of each pixel value .
const unsigned int keyCTRLLEFT
Keycode for the CTRLLEFT key (architecture-dependent).
const CImg< T > & save_rgb(const char *const filename) const
Save image as a RGB file.
CImg< T > get_resize(const CImgDisplay &disp, const int interpolation_type=1, const unsigned int boundary_conditions=0, const float centering_x=0, const float centering_y=0, const float centering_z=0, const float centering_c=0) const
Resize image to dimensions of a display window .
CImg< T > & resize_tripleXY()
Resize image to triple-size, using the Scale3X algorithm.
CImg< T > get_shared_row(const unsigned int y0, const unsigned int z0=0, const unsigned int c0=0)
Return a shared-memory image referencing one row of the image instance.
CImg< T > & load_camera(const unsigned int camera_index=0, const unsigned int skip_frames=0, const bool release_camera=true, const unsigned int capture_width=0, const unsigned int capture_height=0)
Load image from a camera stream, using OpenCV.
CImgList< T > get_split(const T value, const bool keep_values, const bool is_shared) const
Split image into a list of one-column vectors, according to a specified splitting value...
CImgList< T > & reverse_object3d()
Reverse primitives orientations of a 3d object.
CImg< T > & draw_triangle(CImg< tz > &zbuffer, const int x0, const int y0, const float z0, const int x1, const int y1, const float z1, const int x2, const int y2, const float z2, const tc *const color, const CImg< tl > &light, const int lx0, const int ly0, const int lx1, const int ly1, const int lx2, const int ly2, const float opacity=1)
Draw a Phong-shaded 2d triangle, with z-buffering.
CImg< T > & draw_object3d(const float x0, const float y0, const float z0, const CImg< tp > &vertices, const CImgList< tf > &primitives, const CImgList< tc > &colors, const unsigned int render_type, const bool is_double_sided, const float focale, const float lightx, const float lighty, const float lightz, const float specular_lightness, const float specular_shininess, CImg< tz > &zbuffer)
Draw a 3d object .
const CImg< T > & display_object3d(CImgDisplay &disp, const CImg< tp > &vertices, const CImgList< tf > &primitives, const CImgList< tc > &colors, const bool centering=true, const int render_static=4, const int render_motion=1, const bool is_double_sided=true, const float focale=700, const float light_x=0, const float light_y=0, const float light_z=-5e8f, const float specular_lightness=0.2f, const float specular_shininess=0.1f, const bool display_axes=true, float *const pose_matrix=0) const
Display object 3d in an interactive window .
CImg< T > operator^(const CImg< t > &img) const
Bitwise XOR operator.
const CImg< T > & save_off(const CImgList< tf > &primitives, const CImgList< tc > &colors, std::FILE *const file) const
Save 3d object as an Object File Format (.off) file .
CImg< T > & atan2(const CImg< t > &img)
Compute the arctangent2 of each pixel value.
CImg< T > operator++(int)
In-place increment operator (postfix).
const_iterator end() const
Return a CImg::iterator pointing next to the last pixel value .
const unsigned int keyF5
Keycode for the F5 key (architecture-dependent).
CImg< T > get_resize(const int size_x, const int size_y=-100, const int size_z=-100, const int size_c=-100, const int interpolation_type=1, const unsigned int boundary_conditions=0, const float centering_x=0, const float centering_y=0, const float centering_z=0, const float centering_c=0) const
Resize image to new dimensions .
CImg< T > & solve(const CImg< t > &A)
Solve a system of linear equations.
CImgList< T > & push_front(const CImg< t > &img)
Insert image at the front of the list.
const unsigned int keyZ
Keycode for the Z key (architecture-dependent).
const CImgList< T > & save_yuv(std::FILE *const file, const bool is_rgb=true) const
Save image sequence into a YUV file.
CImg< T > get_column(const int x0) const
Return specified image column.
CImg< T > & operator=(const CImgDisplay &disp)
Copy the content of a display window to the current image instance.
CImg< T > get_rand(const T val_min, const T val_max) const
Fill image with random values in specified range .
CImg< T > & LabtoRGB()
Convert pixel values from Lab to RGB color spaces.
CImg< T > & draw_triangle(CImg< tz > &zbuffer, const int x0, const int y0, const float z0, const int x1, const int y1, const float z1, const int x2, const int y2, const float z2, const CImg< tc > &texture, const int tx0, const int ty0, const int tx1, const int ty1, const int tx2, const int ty2, const float opacity=1, const float brightness=1)
Draw a textured 2d triangle, with perspective correction and z-buffering.
CImg< T > & draw_triangle(const int x0, const int y0, const float z0, const int x1, const int y1, const float z1, const int x2, const int y2, const float z2, const CImg< tc > &texture, const int tx0, const int ty0, const int tx1, const int ty1, const int tx2, const int ty2, const CImg< tl > &light, const int lx0, const int ly0, const int lx1, const int ly1, const int lx2, const int ly2, const float opacity=1)
Draw a textured Phong-shaded 2d triangle, with perspective correction.
CImg< Tfloat > get_displacement(const CImg< T > &source, const float smoothness=0.1f, const float precision=5.0f, const unsigned int nb_scales=0, const unsigned int iteration_max=10000, const bool is_backward=false) const
Estimate displacement field between two images .
CImg< Tfloat > get_tan() const
Compute the tangent of each pixel value .
CImg< T > & tanh()
Compute the hyperbolic tangent of each pixel value.
CImg< T > & operator/=(const t value)
In-place division operator.
T & atXYZ(const int x, const int y, const int z, const int c=0)
Access to a pixel value, using Neumann boundary conditions for the X,Y and Z-coordinates.
const CImg< T > & save_rgba(const char *const filename) const
Save image as a RGBA file.
CImgList< T > get_insert(const CImg< t > &img, const unsigned int pos=~0U, const bool is_shared=false) const
Insert a copy of the image img into the current image list, at position pos .
CImg< T > & draw_triangle(const int x0, const int y0, const int x1, const int y1, const int x2, const int y2, const CImg< tc > &texture, const int tx0, const int ty0, const int tx1, const int ty1, const int tx2, const int ty2, const float opacity=1, const float brightness=1)
Draw a textured 2d triangle.
CImg< T > & operator-=(const t value)
In-place substraction operator.
Tfloat cubic_atXY(const float fx, const float fy, const int z, const int c, const T out_value) const
Return pixel value, using cubic interpolation and Dirichlet boundary conditions for the X and Y-coord...
CImg< T > & move_to(CImg< T > &img)
Transfer content of an image instance into another one .
const CImgList< T > get_shared_images(const unsigned int pos0, const unsigned int pos1) const
Return a shared sublist .
CImg< T > get_row(const int y0) const
Return specified image row.
CImg< T > & RGBtoYUV()
Convert pixel values from RGB to YUV color spaces.
CImg< T > get_vector_at(const unsigned int x, const unsigned int y=0, const unsigned int z=0) const
Get vector-valued pixel located at specified position.
CImg< T > & load_raw(const char *const filename, const unsigned int size_x=0, const unsigned int size_y=1, const unsigned int size_z=1, const unsigned int size_c=1, const bool is_multiplexed=false, const bool invert_endianness=false, const unsigned long offset=0)
Load image from a raw binary file.
T & atXY(const int x, const int y, const int z, const int c, const T out_value)
Access to a pixel value, using Dirichlet boundary conditions for the X and Y-coordinates.
CImgList< T > & assign(const unsigned int n, const unsigned int width, const unsigned int height, const unsigned int depth, const unsigned int spectrum, const int val0, const int val1,...)
Construct list with images of specified size, and initialize pixel values from a sequence of integers...
bool is_sameX(const CImg< t > &img) const
Test if image width is equal to specified value.
static void save_empty_cimg(std::FILE *const file, const unsigned int dx, const unsigned int dy=1, const unsigned int dz=1, const unsigned int dc=1)
Save blank image as a .cimg file .
CImgList< T > & pop_front()
Remove first image.
CImg< T > & operator>>=(const CImg< t > &img)
In-place bitwise right shift operator.
Tfloat cubic_atXY(const float fx, const float fy, const int z=0, const int c=0) const
Return pixel value, using cubic interpolation and Neumann boundary conditions for the X and Y-coordin...
const CImg< T > & save_imagemagick_external(const char *const filename, const unsigned int quality=100) const
Save image using ImageMagick's external binary.
CImg< T > get_blur_bilateral(const CImg< t > &guide, const float sigma_s, const float sigma_r, const int bgrid_s=-33, const int bgrid_r=32, const bool interpolation_type=true) const
Blur image using the bilateral filter .
Tfloat cubic_atX(const float fx, const int y, const int z, const int c, const T out_value, const Tfloat min_value, const Tfloat max_value) const
Return damped pixel value, using cubic interpolation and Dirichlet boundary conditions for the X-coor...
CImg< T > & BayertoRGB(const unsigned int interpolation_type=3)
Convert Bayer-coded scalar image to a RGB color image.
static CImg< T > matrix(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4, const T &a5, const T &a6, const T &a7, const T &a8, const T &a9, const T &a10, const T &a11, const T &a12, const T &a13, const T &a14, const T &a15, const T &a16, const T &a17, const T &a18, const T &a19, const T &a20, const T &a21, const T &a22, const T &a23, const T &a24)
Return a 5x5 matrix containing specified coefficients.
static void wait(CImgDisplay &disp1, CImgDisplay &disp2, CImgDisplay &disp3, CImgDisplay &disp4, CImgDisplay &disp5, CImgDisplay &disp6, CImgDisplay &disp7, CImgDisplay &disp8, CImgDisplay &disp9)
Wait for any event occuring either on the display disp1, disp2, disp3, disp4, ... disp9...
CImg< T > & operator+=(const CImg< t > &img)
In-place addition operator.
const char * basename(const char *const str)
Return the basename of a filename.
CImgList< T > & insert(const CImg< t > &img, const unsigned int pos=~0U, const bool is_shared=false)
Insert a copy of the image img into the current image list, at position pos.
CImg< T > & fill(const T val0, const T val1, const T val2, const T val3)
Fill sequentially all pixel values with specified values .
CImgList< T > get_reverse() const
Reverse list order .
CImg< _cimg_Tt > get_min(const CImg< t > &img) const
Pointwise min operator between two images .
static void wait(CImgDisplay &disp1, CImgDisplay &disp2, CImgDisplay &disp3, CImgDisplay &disp4)
Wait for any event occuring either on the display disp1, disp2, disp3 or disp4.
CImg< T > operator+() const
Return a non-shared copy of the image instance.
CImg< T > get_permute_axes(const char *const order) const
Permute axes order .
const CImg< T > & display_object3d(const char *const title, const CImg< tp > &vertices, const CImgList< tf > &primitives, const CImgList< tc > &colors, const to &opacities, const bool centering=true, const int render_static=4, const int render_motion=1, const bool is_double_sided=true, const float focale=700, const float light_x=0, const float light_y=0, const float light_z=-5e8f, const float specular_lightness=0.2f, const float specular_shininess=0.1f, const bool display_axes=true, float *const pose_matrix=0) const
Display object 3d in an interactive window .
cimg::superset< t1, t2 >::type min(const t1 &a, const t2 &b)
Return the minimum between two values.
CImg< T > & draw_object3d(const float x0, const float y0, const float z0, const CImg< tp > &vertices, const CImgList< tf > &primitives, const CImgList< tc > &colors, const CImgList< to > &opacities, const unsigned int render_type, const bool is_double_sided, const float focale, const float lightx, const float lighty, const float lightz, const float specular_lightness, const float specular_shininess, CImg< tz > &zbuffer)
Draw a 3d object .
CImg< T > & sin()
Compute the sine of each pixel value.
CImg< T > & object3dtoCImg3d(const bool full_check=true)
Convert 3d object into a CImg3d representation .
const unsigned int keyDELETE
Keycode for the DELETE key (architecture-dependent).
bool contains(const T &pixel, t &n, t &x, t &y, t &z) const
Test if one of the image list contains the specified referenced value.
CImg< T > & XYZtoLab()
Convert pixel values from XYZ_709 to Lab color spaces.
CImg< T > operator^(const t value) const
Bitwise XOR operator.
const T & operator()(const unsigned int pos, const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) const
Return a reference to one pixel value of one image of the list .
static CImgList< T > get_load_ffmpeg(const char *const filename, const unsigned int first_frame=0, const unsigned int last_frame=~0U, const unsigned int step_frame=1, const bool pixel_format=true)
Load an image from a video file, using ffmpeg libraries .
CImg< T > & div(const CImg< t > &img)
In-place pointwise division.
CImg< t > & move_to(CImg< t > &img)
Transfer content of an image instance into another one.
CImgDisplay & set_mouse(const int pos_x, const int pos_y)
Move mouse pointer to a specified location.
cimg::superset< t1, t2 >::type max(const t1 &a, const t2 &b)
Return the maximum between two values.
CImgList< T > & assign(const CImgList< T > &list, const bool is_shared=false)
Construct list as a copy of an existing list and force shared state of elements .
CImg< T > get_invert_endianness() const
Invert endianness of all pixel values .
CImg< T > & mirror(const char axis)
Mirror image content along specified axis.
CImg< T > & draw_gaussian(const float xc, const float sigma, const tc *const color, const float opacity=1)
Draw a 1d gaussian function.
CImg< T > & RGBtoxyY()
Convert pixel values from RGB to xyY color spaces.
CImgList< T > & load_cimg(const char *const filename, const unsigned int n0, const unsigned int n1, const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int c0, const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int c1)
Load a sublist list from a (non compressed) .cimg file.
CImg< T > & draw_grid(const float delta_x, const float delta_y, const float offsetx, const float offsety, const bool invertx, const bool inverty, const tc *const color, const float opacity=1, const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U)
Draw 2d grid .
CImg< T > & min(const char *const expression)
Pointwise min operator between an image and an expression.
static CImg< T > get_load_ffmpeg_external(const char *const filename, const char axis='z', const float align=0)
Load image sequence using FFMPEG's external tool 'ffmpeg' .
CImg< T > & fillC(const unsigned int x, const unsigned int y, const unsigned int z, const int a0,...)
Fill pixel values along the C-axis at a specified pixel position.
CImg< T > & assign(const t *const values, const unsigned int size_x, const unsigned int size_y=1, const unsigned int size_z=1, const unsigned int size_c=1)
Construct image with specified size and initialize pixel values from a memory buffer ...
CImg< intT > get_select(const char *const title, const unsigned int feature_type=2, unsigned int *const XYZ=0) const
Simple interface to select a shape from an image .
static CImg< floatT > cylinder3d(CImgList< tf > &primitives, const float radius=50, const float size_z=100, const unsigned int subdivisions=24)
Generate a 3d cylinder.
CImg< T > get_blur_bilateral(const CImg< t > &guide, const float sigma_x, const float sigma_y, const float sigma_z, const float sigma_r, const int bgrid_x, const int bgrid_y, const int bgrid_z, const int bgrid_r, const bool interpolation_type=true) const
Blur image, with the joint bilateral filter .
static unsigned int keycode(const char *const keycode)
Return keycode corresponding to the specified string.
CImg< intT > get_select(const char *const title, const bool feature_type=true, const char axis='x', const float align=0) const
Display a simple interactive interface to select images or sublists.
CImg< T > & load_jpeg(std::FILE *const file)
Load image from a JPEG file .
CImg< T > & operator&=(const t value)
In-place bitwise AND operator.
const CImgList< T > & display(CImgDisplay &disp, const char axis='x', const float align=0) const
Display the current CImgList instance in an existing CImgDisplay window (by reference).
CImg< T > & stats(const unsigned int variance_method=1)
Compute statistics vector from the pixel values .
CImg< T > & operator<<=(const t value)
In-place bitwise left shift operator.
CImg< T > & draw_graph(const CImg< t > &data, const tc *const color, const float opacity=1, const unsigned int plot_type=1, const int vertex_type=1, const double ymin=0, const double ymax=0, const unsigned int pattern=~0U)
Draw 1d graph.
CImg< T > & XYZtoRGB()
Convert pixel values from XYZ_709 to RGB color spaces.
unsigned int size() const
Return the size of the list, i.e. the number of images contained in it.
CImg< Tfloat > get_RGBtoHSV() const
Convert pixel values from RGB to HSV color spaces .
T mod(const T &x, const T &m)
Return the modulo of a value.
CImg< T > & fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, const T val7, const T val8, const T val9, const T val10, const T val11, const T val12, const T val13)
Fill sequentially all pixel values with specified values .
static void wait(CImgDisplay &disp1, CImgDisplay &disp2, CImgDisplay &disp3, CImgDisplay &disp4, CImgDisplay &disp5, CImgDisplay &disp6, CImgDisplay &disp7, CImgDisplay &disp8, CImgDisplay &disp9, CImgDisplay &disp10)
Wait for any event occuring either on the display disp1, disp2, disp3, disp4, ... disp10...
const CImg< T > & save_rgba(std::FILE *const file) const
Save image as a RGBA file .
int mouse_y() const
Return Y-coordinate of the mouse pointer.
CImg< T > & tan()
Compute the tangent of each pixel value.
static const CImgList< ucharT > & font(const unsigned int font_height, const bool is_variable_width=true)
Return a CImg pre-defined font with desired size.
const CImg< T > & display_graph(CImgDisplay &disp, const unsigned int plot_type=1, const unsigned int vertex_type=1, const char *const labelx=0, const double xmin=0, const double xmax=0, const char *const labely=0, const double ymin=0, const double ymax=0) const
Display 1d graph in an interactive window.
static CImg< T > get_load_magick(const char *const filename)
Load image from a file, using Magick++ library .
CImgDisplay & operator=(const CImgDisplay &disp)
Construct a display as a copy of another one .
const char * title() const
Return title of the associated window as a C-string.
CImgList< Tfloat > get_eigen() const
Compute eigenvalues and eigenvectors of the instance image, viewed as a matrix.
CImg< T > & load_bmp(std::FILE *const file)
Load image from a BMP file .
CImgList(const char *const filename)
Construct list by reading the content of a file.
CImg< charT > value_string(const char separator=',', const unsigned int max_size=0) const
Return a C-string containing the values of all images in the instance list.
CImg< T > & correlate(const CImg< t > &mask, const unsigned int boundary_conditions=1, const bool is_normalized=false)
Correlate image by a mask.
T * data()
Return a pointer to the first pixel value.
CImg< T > & LabtoXYZ()
Convert pixel values from Lab to XYZ_709 color spaces.
const CImg< T > & symmetric_eigen(CImg< t > &val, CImg< t > &vec) const
Compute eigenvalues and eigenvectors of the instance image, viewed as a symmetric matrix...
const T & min() const
Return a reference to the minimum pixel value .
const CImg< T > & save_dlm(const char *const filename) const
Save image as a DLM file.
CImg< T > & object3dtoCImg3d(const CImgList< tp > &primitives, const bool full_check=true)
Convert 3d object into a CImg3d representation .
CImgList(const CImgList< t > &list)
Construct list copy.
bool is_sameXZ(const CImg< t > &img) const
Test if image width and depth are the same as that of another image.
const char * wget_path(const char *const user_path=0, const bool reinit_path=false)
Get/set path to the wget binary.
CImg< Tfloat > get_RGBtoYUV() const
Convert pixel values from RGB to YUV color spaces .
CImg< T > get_channel(const int c0) const
Return specified image channel.
static CImg< floatT > plane3d(CImgList< tf > &primitives, const float size_x=100, const float size_y=100, const unsigned int subdivisions_x=10, const unsigned int subdivisions_y=10)
Generate a 3d XY-plane.
static CImgList< T > get_load_gzip_external(const char *const filename)
Load a gzipped list, using external tool 'gunzip' .
CImg< T > & load_pandore(const char *const filename)
Load image from a PANDORE-5 file.
static CImg< floatT > cone3d(CImgList< tf > &primitives, const float radius=50, const float size_z=100, const unsigned int subdivisions=24)
Generate a 3d cone.
CImg< T > & draw_image(const int x0, const int y0, const int z0, const CImg< ti > &sprite, const CImg< tm > &mask, const float opacity=1, const float mask_max_value=1)
Draw a masked image .
unsigned long nearest_pow2(const T x)
Return the nearest power of 2 higher than given value.
CImgList< Tfloat > get_FFT(const char axis, const bool is_invert=false) const
Compute 1d Fast Fourier Transform, along a specified axis.
static const CImg< Tuchar > & default_LUT256()
Return colormap "default", containing 256 colors entries in RGB.
CImg< T > & load_dcraw_external(const char *const filename)
Load image from a RAW Color Camera file, using external tool 'dcraw'.
CImg< T > & operator&=(const CImg< t > &img)
In-place bitwise AND operator.
CImg< T > & blur(const float sigma_x, const float sigma_y, const float sigma_z, const bool boundary_conditions=true, const bool is_gaussian=false)
Blur image.
CImg< T > & RGBtoHSL()
Convert pixel values from RGB to HSL color spaces.
CImgList< T > get_split(const bool is_shared) const
Split the image into a list of one-column vectors each having same values.
CImg< T > & draw_axis(const int x, const CImg< t > &values_y, const tc *const color, const float opacity=1, const unsigned int pattern=~0U, const unsigned int font_height=13, const bool allow_zero=true)
Draw a labeled vertical axis.
static CImg< T > sequence(const unsigned int N, const T a0, const T a1)
Return a N-numbered sequence vector from a0 to a1.
CImg< T > & draw_arrow(const int x0, const int y0, const int x1, const int y1, const tc *const color, const float opacity=1, const float angle=30, const float length=-10, const unsigned int pattern=~0U)
Draw a 2d arrow.
CImg< T > & draw_rectangle(const int x0, const int y0, const int z0, const int c0, const int x1, const int y1, const int z1, const int c1, const T val, const float opacity=1)
Draw a filled 4d rectangle.
CImg< T > & draw_spline(const int x0, const int y0, const float u0, const float v0, const int x1, const int y1, const float u1, const float v1, const CImg< t > &texture, const int tx0, const int ty0, const int tx1, const int ty1, const float opacity=1, const float precision=4, const unsigned int pattern=~0U, const bool init_hatch=true)
Draw a textured 2d spline.
CImg< T > operator&(const CImg< t > &img) const
Bitwise AND operator.
CImg< T > get_noise(const double sigma, const unsigned int noise_type=0) const
Add random noise to pixel values .
const CImg< T > & save_analyze(const char *const filename, const float *const voxel_size=0) const
Save image as an ANALYZE7.5 or NIFTI file.
static CImg< T > get_load_analyze(std::FILE *const file, float *const voxel_size=0)
Load image from an ANALYZE7.5/NIFTI file .
const CImg< T > & save_cimg(std::FILE *const file, const bool is_compressed=false) const
Save image as a .cimg file .
T & atXY(const int x, const int y, const int z=0, const int c=0)
Access to a pixel value, using Neumann boundary conditions for the X and Y-coordinates.
static CImg< floatT > isoline3d(CImgList< tf > &primitives, const char *const expression, const float isovalue, const float x0, const float y0, const float x1, const float y1, const int size_x=256, const int size_y=256)
Compute isolines of a function, as a 3d object .
static CImg< floatT > isoline3d(CImgList< tf > &primitives, const tfunc &func, const float isovalue, const float x0, const float y0, const float x1, const float y1, const int size_x=256, const int size_y=256)
Compute 0-isolines of a function, as a 3d object.
CImg< T > get_identity_matrix() const
Replace the image by an identity matrix .
const CImg< T > & save_raw(const char *const filename, const bool is_multiplexed=false) const
Save image as a raw data file.
const unsigned int keyHOME
Keycode for the HOME key (architecture-dependent).
CImg< T > & draw_image(const int x0, const int y0, const int z0, const int c0, const CImg< ti > &sprite, const CImg< tm > &mask, const float opacity=1, const float mask_max_value=1)
Draw a masked image.
CImg< T > & min(const T val)
Pointwise min operator between instance image and a value.
static CImg< T > get_load_png(const char *const filename)
Load image from a PNG file .
CImg< T > & operator|=(const CImg< t > &img)
In-place bitwise OR operator.
CImg< T > & operator^=(const char *const expression)
In-place bitwise XOR operator.
static CImg< T > get_load_pfm(std::FILE *const file)
Load image from a PFM file .
CImg< T > & max(const char *const expression)
Pointwise max operator between an image and an expression.
CImg< T > & draw_line(CImg< tz > &zbuffer, const int x0, const int y0, const float z0, const int x1, const int y1, const float z1, const tc *const color, const float opacity=1, const unsigned int pattern=~0U, const bool init_hatch=true)
Draw a 2d line, with z-buffering.
CImg< T > & RGBtosRGB()
Convert pixel values from RGB to sRGB color spaces.
int depth() const
Return the number of image slices.
const CImg< T > & save_graphicsmagick_external(const char *const filename, const unsigned int quality=100) const
Save image using GraphicsMagick's external binary.
int fwrite(const T *ptr, const unsigned long nmemb, std::FILE *stream)
Write data to file.
static void wait(CImgDisplay &disp1, CImgDisplay &disp2)
Wait for any event occuring either on the display disp1 or disp2.
bool operator!=(const char *const expression) const
Test if all pixel values of an image are different from a specified expression.
Tfloat linear_atXY(const float fx, const float fy, const int z, const int c, const T out_value) const
Return pixel value, using linear interpolation and Dirichlet boundary conditions for the X and Y-coor...
CImg< T > & sort(const bool is_increasing=true, const char axis=0)
Sort pixel values.
CImg< T > & distance_eikonal(const unsigned int nb_iterations, const float band_size=0, const float time_step=0.5f)
Compute distance function to 0-valued isophotes, using the Eikonal PDE.
CImg< T > & draw_rectangle(const int x0, const int y0, const int z0, const int x1, const int y1, const int z1, const tc *const color, const float opacity=1)
Draw a filled 3d rectangle.
int window_y() const
Return Y-coordinate of the associated window.
CImgList< T > get_remove() const
Remove last image .
CImg< T > & fillX(const unsigned int y, const unsigned int z, const unsigned int c, const int a0,...)
Fill pixel values along the X-axis at a specified pixel position.
CImg< T > & draw_line(CImg< tz > &zbuffer, const int x0, const int y0, const float z0, const int x1, const int y1, const float z1, const CImg< tc > &texture, const int tx0, const int ty0, const int tx1, const int ty1, const float opacity=1, const unsigned int pattern=~0U, const bool init_hatch=true)
Draw a textured 2d line, with perspective correction and z-buffering.
const unsigned int keyPAD5
Keycode for the PAD5 key (architecture-dependent).
CImgDisplay & set_wheel()
Flush all mouse wheel events.
CImgList(const CImg< t1 > &img1, const CImg< t2 > &img2, const CImg< t3 > &img3, const bool is_shared=false)
Construct list from three images.
CImg< T > get_resize_halfXY() const
Resize image to half-size along XY axes, using an optimized filter .
static CImg< T > diagonal(const T &a0)
Return a 1x1 diagonal matrix containing specified coefficients.
bool is_sameXYZ(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z) const
Test if image width, height and depth are equal to specified values.
CImg(const CImg< T > &img)
Construct image copy .
static CImg< T > get_load_minc2(const char *const filename)
Load image from a MINC2 file .
CImg< Tfloat > get_cos() const
Compute the cosine of each pixel value .
const CImg< T > & save_ffmpeg(const char *const filename, const unsigned int fps=25, const unsigned int bitrate=2048) const
Save image as a video file, using the FFmpeg library.
CImgList< Tfloat > get_SVD(const bool sorting=true, const unsigned int max_iteration=40, const float lambda=0) const
Compute the SVD of the instance image, viewed as a general matrix.
Tfloat cubic_atXYZ(const float fx, const float fy, const float fz, const int c, const T out_value, const Tfloat min_value, const Tfloat max_value) const
Return damped pixel value, using cubic interpolation and Dirichlet boundary conditions for the XYZ-co...
CImg< T > & operator|=(const char *const expression)
In-place bitwise OR operator.
T & atXYZC(const int x, const int y, const int z, const int c, const T out_value)
Access to a pixel value, using Dirichlet boundary conditions.
const_iterator begin() const
Return iterator to the first image of the list .
const unsigned int keyPAD9
Keycode for the PAD9 key (architecture-dependent).
static CImg< T > get_load_rgba(const char *const filename, const unsigned int dimw, const unsigned int dimh=1)
Load image from a RGBA file .
Tdouble det() const
Compute the determinant of the image, viewed as a matrix.
CImg< Tfloat > get_RGBtoLab() const
Convert pixel values from RGB to Lab color spaces .
static CImg< T > diagonal(const T &a0, const T &a1)
Return a 2x2 diagonal matrix containing specified coefficients.
CImg< T > & load_graphicsmagick_external(const char *const filename)
Load image using GraphicsMagick's external tool 'gm'.
static const char * pixel_type()
Return the type of image pixel values as a C string.
const CImgList< T > & display(const char *const title=0, const bool display_info=true, const char axis='x', const float align=0, unsigned int *const XYZ=0) const
Display the current CImgList instance in a new display window.
CImg< T > get_fill(const T val0, const T val1, const T val2) const
Fill sequentially all pixel values with specified values .
T atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) const
Access to pixel value with Neumann boundary conditions for the 2 first coordinates (pos...
CImg(const CImg< t > &img)
Construct image copy.
CImg< floatT > get_isosurface3d(CImgList< tf > &primitives, const float isovalue, const int size_x=-100, const int size_y=-100, const int size_z=-100) const
Generate an isosurface of the image instance as a 3d object.
bool is_key() const
Return true if any key is being pressed on the associated window, false otherwise.
CImg< T > & identity_matrix()
Replace the image by an identity matrix.
CImgList< T > get_remove(const unsigned int pos) const
Remove image at index pos from the image list .
CImg< T > & assign(const CImg< t > &img, const char *const dimensions, const T value)
Construct image with dimensions borrowed from another image and initialize pixel values ...
CImg< T > & matrix()
Resize image to become a scalar square matrix.
CImg< T > get_fill(const T val) const
Fill all pixel values with specified value .
CImgList< T > & assign(const unsigned int n, const unsigned int width, const unsigned int height=1, const unsigned int depth=1, const unsigned int spectrum=1)
Construct list containing images of specified size .
const CImg< T > & print(const char *const title=0, const bool display_stats=true) const
Display informations about the image data.
CImg< T > & RGBtoYCbCr()
Convert pixel values from RGB to YCbCr color spaces.
CImg< T > & load_ascii(const char *const filename)
Load image from an ascii file.
CImgList(const unsigned int n)
Construct list containing empty images.
static CImg< T > get_load_imagemagick_external(const char *const filename)
Load image using ImageMagick's external tool 'convert' .
CImgList< _cimg_Tt > operator,(const CImgList< t > &list) const
Construct an image list from image instance and an input image list.
CImg< T > & RGBtoXYZ()
Convert pixel values from RGB to XYZ_709 color spaces.
CImg< T > & assign(const T *const values, const unsigned int size_x, const unsigned int size_y=1, const unsigned int size_z=1, const unsigned int size_c=1)
Construct image with specified size and initialize pixel values from a memory buffer ...
const unsigned int keySPACE
Keycode for the SPACE key (architecture-dependent).
CImg< T > & resize(const CImgDisplay &disp, const int interpolation_type=1, const unsigned int boundary_conditions=0, const float centering_x=0, const float centering_y=0, const float centering_z=0, const float centering_c=0)
Resize image to dimensions of a display window.
CImg< Tfloat > operator%(const char *const expression) const
Modulo operator.
CImg< T > get_blur_anisotropic(const CImg< t > &G, const float amplitude=60, const float dl=0.8f, const float da=30, const float gauss_prec=2, const unsigned int interpolation_type=0, const bool is_fast_approx=true) const
Blur image anisotropically, directed by a field of diffusion tensors .
static const CImg< Tuchar > & hot_LUT256()
Return colormap "hot", containing 256 colors entries in RGB.
CImg< T > get_diagonal() const
Resize image to become a diagonal matrix .
const CImg< T > & save(const char *const filename, const int number=-1, const unsigned int digits=6) const
Save image as a file.
CImg< _cimg_Tt > get_div(const CImg< t > &img) const
In-place pointwise division .
CImg< T > & back()
Return a reference to the last image of the list .
CImgDisplay & flush()
Flush all display events.
CImg< T > operator^(const char *const expression) const
Bitwise XOR operator.
static CImg< T > get_load_tiff(const char *const filename, const unsigned int first_frame=0, const unsigned int last_frame=~0U, const unsigned int step_frame=1)
Load image from a TIFF file .
const CImg< T > & save_off(const CImgList< tf > &primitives, const CImgList< tc > &colors, const char *const filename) const
Save 3d object as an Object File Format (.off) file.
Tfloat cubic_atXY(const float fx, const float fy, const int z, const int c, const Tfloat min_value, const Tfloat max_value) const
Return damped pixel value, using cubic interpolation and Neumann boundary conditions for the X...
CImg< T > get_rotate(const float angle, const float cx, const float cy, const float zoom, const unsigned int interpolation=1, const unsigned int boundary=3) const
Rotate image with arbitrary angle, around a center point .
CImg< T > get_slices(const int z0, const int z1) const
Return specified range of image slices.
CImg< T > & erode(const CImg< t > &mask, const unsigned int boundary_conditions=1, const bool is_normalized=false)
Erode image by a structuring element.
const unsigned int keyPAD3
Keycode for the PAD3 key (architecture-dependent).
CImg< T > & xyYtoXYZ()
Convert pixel values from xyY pixels to XYZ_709 color spaces.
CImg< T > & fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, const T val7, const T val8)
Fill sequentially all pixel values with specified values .
CImgList< T > get_crop_font() const
Crop font along the X-axis .
CImg< _cimg_Tt > get_max(const CImg< t > &img) const
Pointwise max operator between two images .
static CImgList< T > get_load_cimg(const char *const filename, const unsigned int n0, const unsigned int n1, const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int c0, const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int c1)
Load a sublist list from a (non compressed) .cimg file .
CImg< T > & draw_rectangle(const int x0, const int y0, const int z0, const int x1, const int y1, const int z1, const tc *const color, const float opacity, const unsigned int pattern)
Draw an outlined 3d rectangle .
CImg< T > & RGBtoCMYK()
Convert pixel values from RGB to CMYK color spaces.
const_iterator begin() const
Return a CImg::iterator pointing to the first value of the pixel buffer .
CImg< T > & load_medcon_external(const char *const filename)
Load image from a DICOM file, using XMedcon's external tool 'medcon'.
CImg< T > & HSVtoRGB()
Convert pixel values from HSV to RGB color spaces.
const CImg< T > & save_cpp(std::FILE *const file) const
Save image as a .cpp source file .
int system(const char *const command, const char *const module_name=0)
static const CImg< Tuchar > & cube_LUT256()
Return colormap "cube", containing 256 colors entries in RGB.
CImg< T > & draw_line(const int x0, const int y0, const int x1, const int y1, const CImg< tc > &texture, const int tx0, const int ty0, const int tx1, const int ty1, const float opacity=1, const unsigned int pattern=~0U, const bool init_hatch=true)
Draw a textured 2d line.
CImg< Tfloat > get_cosh() const
Compute the hyperbolic cosine of each pixel value .
CImg< T > & draw_polygon(const CImg< t > &points, const tc *const color, const float opacity, const unsigned int pattern)
Draw a outlined 2d polygon .
CImg< T > get_erode(const unsigned int s) const
Erode the image by a square structuring element of specified size .
unsigned long toc()
End tic/toc timer and displays elapsed time from last call to tic().
CImg< T > & operator%=(const t value)
In-place modulo operator.
CImgDisplay & show()
Show (closed) associated window on the screen.
CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, const char *const values, const bool repeat_values)
Construct image with specified size and initialize pixel values from a value string.
CImgList< T > & operator,(const CImg< t > &img)
Return a copy of the list instance, where image img has been inserted at the end. ...
CImgList< T > & erase(const iterator iter)
Remove image pointed by iterator.
CImg< T > & crop(const int x0, const int x1, const bool boundary_conditions=false)
Crop image region .
static CImg< T > get_load_graphicsmagick_external(const char *const filename)
Load image using GraphicsMagick's external tool 'gm' .
CImg< Tfloat > get_exp() const
Compute the exponential of each pixel value .
CImg< T > & min(const CImg< t > &img)
Pointwise min operator between two images.
CImg< T > & fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, const T val7, const T val8, const T val9)
Fill sequentially all pixel values with specified values .
CImg< Tfloat > get_distance_eikonal(const T value, const CImg< t > &metric) const
Compute distance map to one source point, according to a custom metric (use fast marching algorithm)...
CImg< T > & draw_image(const int x0, const int y0, const int z0, const int c0, const CImg< t > &sprite, const float opacity=1)
Draw an image.
CImgList< T > & push_back(const CImgList< t > &list)
Insert list at the end of the current list.
CImgList< T > & assign(const CImg< t1 > &img1, const CImg< t2 > &img2, const CImg< t3 > &img3, const CImg< t4 > &img4, const CImg< t5 > &img5, const bool is_shared=false)
Construct list from five images .
static CImg< T > get_load_dcraw_external(const char *const filename)
Load image from a RAW Color Camera file, using external tool 'dcraw' .
CImgList(const CImg< t1 > &img1, const CImg< t2 > &img2, const CImg< t3 > &img3, const CImg< t4 > &img4, const CImg< t5 > &img5, const CImg< t6 > &img6, const CImg< t7 > &img7, const bool is_shared=false)
Construct list from seven images.
CImg< T > get_sort(const bool is_increasing=true, const char axis=0) const
Sort pixel values .
CImg< T > get_mirror(const char axis) const
Mirror image content along specified axis .
CImg< T > & draw_triangle(const int x0, const int y0, const int x1, const int y1, const int x2, const int y2, const tc *const color, const CImg< tl > &light, const int lx0, const int ly0, const int lx1, const int ly1, const int lx2, const int ly2, const float opacity=1)
Draw a Phong-shaded 2d triangle.
CImg< T > & distance_eikonal(const T value, const CImg< t > &metric)
Compute distance map to one source point, according to a custom metric (use fast marching algorithm)...
CImg< T > get_discard(const T value) const
Discard specified value in the image buffer .
CImgList< T > & assign(const CImg< t1 > &img1, const CImg< t2 > &img2, const CImg< t3 > &img3, const CImg< t4 > &img4, const bool is_shared=false)
Construct list from four images .
T & operator()(const unsigned int x)
Access to a pixel value.
CImg< _cimg_Ttfloat > get_convolve(const CImg< t > &mask, const unsigned int boundary_conditions=1, const bool is_normalized=false) const
Convolve image by a mask .
CImg< T > & load_rgb(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1)
Load image from a RGB file .
CImg< T > & draw_quiver(const CImg< t1 > &flow, const t2 *const color, const float opacity=1, const unsigned int sampling=25, const float factor=-20, const bool is_arrow=true, const unsigned int pattern=~0U)
Draw a 2d vector field.
static CImg< T > get_load_ascii(std::FILE *const file)
Loadimage from an ascii file .
static CImg< floatT > torus3d(CImgList< tf > &primitives, const float radius1=100, const float radius2=30, const unsigned int subdivisions1=24, const unsigned int subdivisions2=12)
Generate a 3d torus.
const T & max_min(t &min_val) const
Return a reference to the maximum pixel value as well as the minimum pixel value .
CImgDisplay & move(const int pos_x, const int pos_y)
Move associated window to a new location.
const CImg< T > & display_graph(const char *const title=0, const unsigned int plot_type=1, const unsigned int vertex_type=1, const char *const labelx=0, const double xmin=0, const double xmax=0, const char *const labely=0, const double ymin=0, const double ymax=0) const
Display 1d graph in an interactive window .
static CImg< T > vector(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4, const T &a5, const T &a6, const T &a7, const T &a8, const T &a9, const T &a10)
Return a 1x11 image containing specified values.
const CImg< T > & save_png(const char *const filename, const unsigned int bytes_per_pixel=0) const
Save image as a PNG file.
CImgList(const unsigned int n, const CImg< t > &img, const bool is_shared=false)
Construct list containing copies of an input image.
CImgDisplay & set_key()
Flush all key events.
T & at(const int offset)
Access to a pixel value at a specified offset, using Neumann boundary conditions. ...
bool contains(const T &pixel, t &x, t &y) const
Test if pixel value is inside image bounds and get its X and Y-coordinates.
const CImg< T > get_shared_row(const unsigned int y0, const unsigned int z0=0, const unsigned int c0=0) const
Return a shared-memory image referencing one row of the image instance .
CImg< T > get_rows(const int y0, const int y1) const
Return specified range of image rows.
const unsigned int keyD
Keycode for the D key (architecture-dependent).
CImg< T > & rows(const int y0, const int y1)
Return specified range of image rows .
CImg< T > & draw_line(const int x0, const int y0, const float z0, const int x1, const int y1, const float z1, const CImg< tc > &texture, const int tx0, const int ty0, const int tx1, const int ty1, const float opacity=1, const unsigned int pattern=~0U, const bool init_hatch=true)
Draw a textured 2d line, with perspective correction.
bool is_sameYZ(const unsigned int size_y, const unsigned int size_z) const
Test if image height and depth are equal to specified values.
CImg< doubleT > eval(const char *const expression, const CImg< t > &xyzc) const
Evaluate math formula on a set of variables.
CImgList< T > & insert(const CImg< T > &img, const unsigned int pos=~0U, const bool is_shared=false)
Insert a copy of the image img into the current image list, at position pos .
bool is_resized() const
Return true if associated window has been resized on the screen, false otherwise. ...
const CImg< T > & back() const
Return a reference to the last image of the list.
CImg< Tuchar > get_CMYKtoRGB() const
Convert pixel values from CMYK to RGB color spaces .
CImgList< T > & load_off(const char *const filename, CImgList< tf > &primitives, CImgList< tc > &colors)
Load a 3d object from a .OFF file.
CImg< Tfloat > get_structure_tensors(const unsigned int scheme=2) const
Compute the structure tensor field of an image .
static CImg< T > get_load_raw(const char *const filename, const unsigned int size_x=0, const unsigned int size_y=1, const unsigned int size_z=1, const unsigned int size_c=1, const bool is_multiplexed=false, const bool invert_endianness=false, const unsigned long offset=0)
Load image from a raw binary file .
std::FILE * output(std::FILE *file=0)
Get/set default output stream for the library messages.
CImg< Tfloat > get_resize_object3d(const float sx, const float sy=-100, const float sz=-100) const
Resize 3d object .
CImg< T > get_shared_channels(const unsigned int c0, const unsigned int c1)
Return a shared-memory image referencing a range of channels of the image instance.
T atXYZC(const int x, const int y, const int z, const int c) const
Access to a pixel value, using Neumann boundary conditions .
CImg< Tfloat > get_resize_object3d() const
Resize 3d object to unit size .
CImg< T > & draw_grid(const CImg< tx > &values_x, const CImg< ty > &values_y, const tc *const color, const float opacity=1, const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U)
Draw 2d grid.
CImgList< T > & load_cimg(const char *const filename)
Load a list from a .cimg file.
CImg< T > & pow(const double p)
Raise each pixel value to a specified power.
CImg< T > & load_ffmpeg_external(const char *const filename, const char axis='z', const float align=0)
Load image sequence using FFMPEG's external tool 'ffmpeg'.
CImg< _cimg_Tt > operator+(const CImg< t > &img) const
Addition operator.
CImg< T > & draw_triangle(const int x0, const int y0, const float z0, const int x1, const int y1, const float z1, const int x2, const int y2, const float z2, const CImg< tc > &texture, const int tx0, const int ty0, const int tx1, const int ty1, const int tx2, const int ty2, const float opacity=1, const float brightness=1)
Draw a 2d textured triangle, with perspective correction.
CImg< T > & operator|=(const t value)
In-place bitwise OR operator.
Tfloat linear_atXYZC(const float fx, const float fy, const float fz, const float fc, const T out_value) const
Return pixel value, using linear interpolation and Dirichlet boundary conditions for all X...
CImgDisplay & display(const CImgList< T > &list, const char axis='x', const float align=0)
Display list of images on associated window.
CImg< T > get_rol(const char *const expression) const
Compute the bitwise left rotation of each pixel value .
CImg< T > & operator*=(const char *const expression)
In-place multiplication operator.
CImg< T > & clear()
Construct empty image .
Contains all classes and functions of the library.
Tdouble MSE(const CImg< t > &img) const
Compute the MSE (Mean-Squared Error) between two images.
CImg< Tuchar > get_LabtoRGB() const
Convert pixel values from Lab to RGB color spaces .
CImg< T > & channels(const int c0, const int c1)
Return specified range of image channels .
const unsigned int key2
Keycode for the 2 key (architecture-dependent).
CImgList< T > & load_ffmpeg_external(const char *const filename)
Load an image from a video file using the external tool 'ffmpeg'.
CImg< T > get_crop(const int x0, const int x1, const bool boundary_conditions=false) const
Crop image region .
CImg< T > & sinh()
Compute the hyperbolic sine of each pixel value.
CImg< _cimg_Ttfloat > get_solve_tridiagonal(const CImg< t > &A) const
Solve a tridiagonal system of linear equations .
CImg< T > & operator^=(const t value)
In-place bitwise XOR operator.
CImg< T > & RGBtoBayer()
Convert RGB color image to a Bayer-coded scalar image.
T & atNXYZ(const int pos, const int x, const int y, const int z, const int c, const T out_value)
Access pixel value with Dirichlet boundary conditions for the 3 first coordinates (pos...
CImg< Tfloat > get_pseudoinvert() const
Compute the Moore-Penrose pseudo-inverse of the instance image, viewed as a matrix ...
CImgList< T > & push_back(const CImg< t > &img)
Insert image at the end of the list.
const CImg< T > * const_iterator
Simple const iterator type, to loop through each image of a const list instance.
T atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) const
Access to pixel value with Neumann boundary conditions for the 4 first coordinates (pos...
CImgList< T > & assign(const CImg< t1 > &img1, const CImg< t2 > &img2, const CImg< t3 > &img3, const bool is_shared=false)
Construct list from three images .
CImgDisplay & resize(const CImg< T > &img, const bool force_redraw=true)
Resize display to the size of an input image.
CImg< T > & append_object3d(CImgList< tf > &primitives, const CImg< tp > &obj_vertices, const CImgList< tff > &obj_primitives)
Merge two 3d objects together.
Tfloat cubic_atXYZ(const float fx, const float fy, const float fz, const int c=0) const
Return pixel value, using cubic interpolation and Neumann boundary conditions for the X...
const unsigned int keyTAB
Keycode for the TAB key (architecture-dependent).
CImgList(const unsigned int n, const unsigned int width, const unsigned int height=1, const unsigned int depth=1, const unsigned int spectrum=1)
Construct list containing images of specified size.
const unsigned int keyPAGEUP
Keycode for the PAGEUP key (architecture-dependent).
CImg< T > & load(const char *const filename)
Load image from a file.
CImg< ulongT > get_histogram(const unsigned int nb_levels) const
Compute the histogram of pixel values .
CImg< T > & log10()
Compute the base-10 logarithm of each pixel value.
CImg< T > & load_rgba(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1)
Load image from a RGBA file .
CImg< T > get_watershed(const CImg< t > &priority, const bool fill_lines=true) const
Compute watershed transform .
T & max()
Return a reference to the maximum pixel value.
CImg< T > get_rotate(const float angle, const unsigned int interpolation=1, const unsigned int boundary=0) const
Rotate image with arbitrary angle .
static int screen_width()
Return width of the screen (current resolution along the X-axis).
const CImgList< T > & save_ffmpeg(const char *const filename, const unsigned int fps=25, const unsigned int bitrate=2048) const
Save image sequence, using FFMPEG library.
CImg< T > & draw_text(const int x0, const int y0, const char *const text, const tc *const foreground_color, const int, const float opacity, const CImgList< t > &font,...)
Draw a text string .
const unsigned int keyINSERT
Keycode for the INSERT key (architecture-dependent).
CImg< typename cimg::superset< t, long >::type > get_distance_dijkstra(const T value, const CImg< t > &metric, const bool is_high_connectivity, CImg< to > &return_path) const
Compute distance map to a specified value, according to a custom metric (use dijkstra algorithm)...
CImg< T > & operator/=(const char *const expression)
In-place division operator.
CImg< T > & at(const int pos)
Return pos-th image of the list.
CImg< T > & invert(const bool use_LU=true)
Invert the instance image, viewed as a matrix.
CImgList< T > get_split(const char axis, const int nb=0) const
Split image into a list along specified axis.
const CImg< T > & display(CImgDisplay &disp, const bool display_info, unsigned int *const XYZ=0) const
Display image into a CImgDisplay window, in an interactive way.
static CImgDisplay & empty()
Return a reference to an empty display.
CImg< T > get_discard(const CImg< t > &values) const
Discard specified sequence of values in the image buffer .
CImg< T > & fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, const T val7)
Fill sequentially all pixel values with specified values .
static const CImg< Tuchar > & cool_LUT256()
Return colormap "cool", containing 256 colors entries in RGB.
T * iterator
Simple iterator type, to loop through each pixel value of an image instance.
CImg< T > & draw_rectangle(const int x0, const int y0, const int x1, const int y1, const tc *const color, const float opacity=1)
Draw a filled 2d rectangle.
CImg< Tuchar > get_HSLtoRGB() const
Convert pixel values from HSL to RGB color spaces .
CImg< T > & solve_tridiagonal(const CImg< t > &A)
Solve a tridiagonal system of linear equations.
static void wait(CImgDisplay &disp1, CImgDisplay &disp2, CImgDisplay &disp3, CImgDisplay &disp4, CImgDisplay &disp5, CImgDisplay &disp6, CImgDisplay &disp7)
Wait for any event occuring either on the display disp1, disp2, disp3, disp4, ... disp7...
CImg< T > & noise(const double sigma, const unsigned int noise_type=0)
Add random noise to pixel values.
const CImg< T > * data() const
Return pointer to the first image of the list .
CImg< T > & sequence(const T a0, const T a1)
Fill image with a linear sequence of values.
T ror(const T a, const unsigned int n=1)
Bitwise-rotate value on the right.
Tfloat cubic_atXYZ(const float fx, const float fy, const float fz, const int c, const T out_value) const
Return pixel value, using cubic interpolation and Dirichlet boundary conditions for the X...
const T & min() const
Return a reference to the minimum pixel value of the instance list .
CImg< T > & threshold(const T value, const bool soft_threshold=false, const bool strict_threshold=false)
Threshold pixel values.
T & max_min(t &min_val)
Return a reference to the maximum pixel value as well as the minimum pixel value. ...
CImg< Tfloat > get_acos() const
Compute the arccosine of each pixel value .
CImg< T > & fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, const T val7, const T val8, const T val9, const T val10)
Fill sequentially all pixel values with specified values .
static CImg< T > tensor(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4, const T &a5)
Return a 3x3 symmetric matrix containing specified coefficients.
static CImgList< T > get_load_parrec(const char *const filename)
Load a list from a PAR/REC (Philips) file .
CImg< T > & draw_triangle(CImg< tz > &zbuffer, const int x0, const int y0, const float z0, const int x1, const int y1, const float z1, const int x2, const int y2, const float z2, const CImg< tc > &texture, const int tx0, const int ty0, const int tx1, const int ty1, const int tx2, const int ty2, const float brightness0, const float brightness1, const float brightness2, const float opacity=1)
Draw a textured Gouraud-shaded 2d triangle, with perspective correction and z-buffering ...
const unsigned int keyPAD1
Keycode for the PAD1 key (architecture-dependent).
CImg< T > & CMYKtoRGB()
Convert pixel values from CMYK to RGB color spaces.
static void wait(CImgDisplay &disp1, CImgDisplay &disp2, CImgDisplay &disp3)
Wait for any event occuring either on the display disp1, disp2 or disp3.
bool is_sameXY(const CImgDisplay &disp) const
Test if image width and height are the same as that of an existing display window.
CImg< T > & draw_image(const CImg< t > &sprite, const float opacity=1)
Draw an image .
const CImg< T > & save_tiff(const char *const filename, const unsigned int compression_type=0) const
Save image as a TIFF file.
CImg< T > & assign(const CImg< t > &img, const char *const dimensions)
Construct image with dimensions borrowed from another image .
bool operator==(const t value) const
Test if all pixels of an image have the same value.
const CImg< T > & display_object3d(CImgDisplay &disp, const CImg< tp > &vertices, const bool centering=true, const int render_static=4, const int render_motion=1, const bool is_double_sided=true, const float focale=700, const float light_x=0, const float light_y=0, const float light_z=-5e8f, const float specular_lightness=0.2f, const float specular_shininess=0.1f, const bool display_axes=true, float *const pose_matrix=0) const
Display object 3d in an interactive window .
const CImg< T > & save_jpeg(const char *const filename, const unsigned int quality=100) const
Save image as a JPEG file.
bool containsXYZC(const int x, const int y=0, const int z=0, const int c=0) const
Test if specified coordinates are inside image bounds.
CImgList< Tfloat > get_FFT(const bool is_invert=false) const
Compute n-d Fast Fourier Transform.
CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, const T value)
Construct image with specified size and initialize pixel values.
CImg< T > & operator^=(const CImg< t > &img)
In-place bitwise XOR operator.
CImg< T > & equalize(const unsigned int nb_levels, const T min_value, const T max_value)
Equalize histogram of pixel values.
const unsigned int key6
Keycode for the 6 key (architecture-dependent).
const unsigned int keyL
Keycode for the L key (architecture-dependent).
T rol(const T a, const unsigned int n=1)
Bitwise-rotate value on the left.
CImg< T > & draw_image(const int x0, const int y0, const int z0, const CImg< t > &sprite, const float opacity=1)
Draw an image .
const char * gzip_path(const char *const user_path=0, const bool reinit_path=false)
Get/set path to the gzip binary.
const CImg< T > & display_object3d(const char *const title, const CImg< tp > &vertices, const bool centering=true, const int render_static=4, const int render_motion=1, const bool is_double_sided=true, const float focale=700, const float light_x=0, const float light_y=0, const float light_z=-5e8f, const float specular_lightness=0.2f, const float specular_shininess=0.1f, const bool display_axes=true, float *const pose_matrix=0) const
Display object 3d in an interactive window .
const unsigned int keyW
Keycode for the W key (architecture-dependent).
CImg< T > & autocrop(const CImg< t > &color, const char *const axes="zyx")
Autocrop image region, regarding the specified background color .
static CImg< T > get_load_pandore(const char *const filename)
Load image from a PANDORE-5 file .
bool is_fullscreen() const
Return true if current display is in fullscreen mode, false otherwise.
CImg< T > & load_raw(std::FILE *const file, const unsigned int size_x=0, const unsigned int size_y=1, const unsigned int size_z=1, const unsigned int size_c=1, const bool is_multiplexed=false, const bool invert_endianness=false, const unsigned long offset=0)
Load image from a raw binary file .
CImgList< T > & operator=(const CImg< t > &img)
Construct list from one image .
CImgList< T > & pop_back()
Remove last image.
iterator end()
Return iterator to one position after the last image of the list.
CImg()
Construct empty image.
Instances of CImgException are thrown when errors are encountered in a function call.
static CImgList< T > & empty()
Return a reference to an empty list.
CImg< T > & permute_axes(const char *const order)
Permute axes order.
static CImg< T > vector(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4, const T &a5)
Return a 1x6 image containing specified values.
CImgList(const CImgDisplay &disp)
Construct list from the content of a display window.
volatile bool & is_key(const char *const keycode)
Return true if key specified by given keycode is being pressed on the associated window, false otherwise.
const double PI
Value of the mathematical constant PI.
CImg< T > * data()
Return pointer to the first image of the list.
const T & max() const
Return a reference to the maximum pixel value of the instance list .
bool is_sameX(const unsigned int size_x) const
Test if image width is equal to specified value.
CImg< T > & distance_dijkstra(const T value, const CImg< t > &metric, const bool is_high_connectivity, CImg< to > &return_path)
Compute distance to a specified value, according to a custom metric (use dijkstra algorithm)...
CImg< T > get_equalize(const unsigned int nblevels) const
Equalize histogram of pixel values .
const CImg< T > & texturize_object3d(CImgList< tp > &primitives, CImgList< tc > &colors, const CImg< tt > &texture, const CImg< tx > &coords=CImg< tx >::empty()) const
Texturize primitives of a 3d object.
std::FILE * fopen(const char *const path, const char *const mode)
Open a file.
CImg< T > & draw_image(const int x0, const CImg< ti > &sprite, const CImg< tm > &mask, const float opacity=1, const float mask_max_value=1)
Draw a image .
const unsigned int keyO
Keycode for the O key (architecture-dependent).
CImg< floatT > get_projections3d(CImgList< tf > &primitives, CImgList< tc > &colors, const unsigned int x0, const unsigned int y0, const unsigned int z0, const bool normalize_colors=false) const
Generate the 3d projection planes of the image instance.
const char * curl_path(const char *const user_path=0, const bool reinit_path=false)
Get/set path to the curl binary.
static CImgList< T > get_load_off(const char *const filename, CImgList< tf > &primitives, CImgList< tc > &colors)
Load a 3d object from a .OFF file .
CImg< T > & load_analyze(std::FILE *const file, float *const voxel_size=0)
Load image from an ANALYZE7.5/NIFTI file .
const CImgList< T > & save_tiff(const char *const filename, const unsigned int compression_type=0) const
Save list as a TIFF file.
CImgList< t > & move_to(CImgList< t > &list, const unsigned int pos=~0U)
Transfer content of an image instance into a new image in an image list.
const unsigned int keyY
Keycode for the Y key (architecture-dependent).
T & operator()(const unsigned int pos, const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0)
Return a reference to one pixel value of one image of the list.
Tfloat linear_atXYZ(const float fx, const float fy, const float fz, const int c, const T out_value) const
Return pixel value, using linear interpolation and Dirichlet boundary conditions for the X...
static CImg< T > get_load_dlm(std::FILE *const file)
Load image from a DLM file .
static CImg< T > vector(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4, const T &a5, const T &a6, const T &a7)
Return a 1x8 image containing specified values.
CImg< T > & crop(const int x0, const int y0, const int z0, const int x1, const int y1, const int z1, const bool boundary_conditions=false)
Crop image region .
static CImg< T > get_load_parrec(const char *const filename, const char axis='c', const float align=0)
Load image from a PAR-REC (Philips) file .
CImg< T > & load_yuv(std::FILE *const file, const unsigned int size_x, const unsigned int size_y=1, const unsigned int first_frame=0, const unsigned int last_frame=~0U, const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z')
Load image sequence from a YUV file .
CImgList(const CImg< t1 > &img1, const CImg< t2 > &img2, const CImg< t3 > &img3, const CImg< t4 > &img4, const CImg< t5 > &img5, const CImg< t6 > &img6, const bool is_shared=false)
Construct list from six images.
CImg< floatT > get_isoline3d(CImgList< tf > &primitives, const float isovalue, const int size_x=-100, const int size_y=-100) const
Generate a isoline of the image instance as a 3d object.
Tfloat cubic_atX(const float fx, const int y, const int z, const int c, const Tfloat min_value, const Tfloat max_value) const
Return damped pixel value, using cubic interpolation and Neumann boundary conditions for the X-coordi...
CImg< T > operator|(const CImg< t > &img) const
Bitwise OR operator.
CImgList< T > get_insert(const unsigned int n, const CImg< t > &img, const unsigned int pos=~0U, const bool is_shared=false) const
Insert n copies of the image img into the current image list, at position pos .
T atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) const
Return pixel value with Neumann boundary conditions for the first coordinate (pos) ...
static CImg< T > tensor(const T &a0)
Return a 1x1 symmetric matrix containing specified coefficients.
CImg< T > & load_minc2(const char *const filename)
Load image from a MINC2 file.
CImg< T > & load_rgb(const char *const filename, const unsigned int dimw, const unsigned int dimh=1)
Load image from a RGB file.
CImg< T > & draw_gaussian(const int xc, const int yc, const float r1, const float r2, const float ru, const float rv, const tc *const color, const float opacity=1)
Draw a 2d gaussian function .
CImg< T > operator>>(const char *const expression) const
Bitwise right shift operator.
int fread(T *const ptr, const unsigned long nmemb, std::FILE *stream)
Read data from file.
static CImg< T > get_load_ffmpeg(const char *const filename, const unsigned int first_frame=0, const unsigned int last_frame=~0U, const unsigned int step_frame=1, const bool pixel_format=true, const bool resume=false, const char axis='z', const float align=0)
Load image sequence using FFMPEG av's libraries .
CImg< T > & row(const int y0)
Return specified image row .
CImg< Tfloat > operator-(const char *const expression) const
Substraction operator.
const CImgList< T > & save_ffmpeg_external(const char *const filename, const char *const codec=0, const unsigned int fps=25, const unsigned int bitrate=2048) const
Save image sequence, using the external tool 'ffmpeg'.
int wheel() const
Return current state of the mouse wheel.
bool is_sameZC(const CImg< t > &img) const
Test if image depth and spectrum are the same as that of another image.
CImgList(const CImgList< t > &list, const bool is_shared)
Construct list copy, and force the shared state of the list elements.
static CImg< T > get_load_dlm(const char *const filename)
Load image from a DLM file .
CImg< T > & quantize(const unsigned int nb_levels, const bool keep_range=true)
Uniformly quantize pixel values.
CImg< T > & draw_image(const int x0, const int y0, const CImg< ti > &sprite, const CImg< tm > &mask, const float opacity=1, const float mask_max_value=1)
Draw a image .
unsigned int prand(const double z)
Return a random variable following a Poisson distribution of parameter z.
CImg< T > & draw_triangle(CImg< tz > &zbuffer, const int x0, const int y0, const float z0, const int x1, const int y1, const float z1, const int x2, const int y2, const float z2, const tc *const color, const float opacity=1, const float brightness=1)
Draw a filled 2d triangle, with z-buffering.
const unsigned int keyPAD6
Keycode for the PAD6 key (architecture-dependent).
CImg< T > get_fill(const char *const values, const bool repeat_values) const
Fill sequentially pixel values according to a given expression .
CImg< T > & load_pfm(const char *const filename)
Load image from a PFM file.
CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, const int value0, const int value1,...)
Construct image with specified size and initialize pixel values from a sequence of integers...
CImg< T > operator>>(const CImg< t > &img) const
Bitwise right shift operator.
Tdouble mean() const
Return the average pixel value.
CImg< T > get_matrix() const
Resize image to become a scalar square matrix .
CImg< Tfloat > get_sin() const
Compute the sine of each pixel value .
CImg< Tfloat > get_sinh() const
Compute the hyperbolic sine of each pixel value .
const CImg< T > & save_other(const char *const filename, const unsigned int quality=100) const
bool is_sameXZC(const CImg< t > &img) const
Test if image width, depth and spectrum are the same as that of another image.
static CImg< T > tensor(const T &a0, const T &a1, const T &a2)
Return a 2x2 symmetric matrix tensor containing specified coefficients.
const unsigned int key1
Keycode for the 1 key (architecture-dependent).
CImg< typename CImg< t >::Tuint > get_index(const CImg< t > &colormap, const float dithering=1, const bool map_indexes=true) const
Index multi-valued pixels regarding to a specified colormap .
CImg< T > get_resize_doubleXY() const
Resize image to double-size, using the Scale2X algorithm .
CImgList< T > & insert(const CImgList< t > &list, const unsigned int pos=~0U, const bool is_shared=false)
Insert a copy of the image list list into the current image list, starting from position pos...
CImgList< T > & clear()
Destructor .
const CImg< T > & display_object3d(const char *const title, const CImg< tp > &vertices, const CImgList< tf > &primitives, const bool centering=true, const int render_static=4, const int render_motion=1, const bool is_double_sided=true, const float focale=700, const float light_x=0, const float light_y=0, const float light_z=-5e8f, const float specular_lightness=0.2f, const float specular_shininess=0.1f, const bool display_axes=true, float *const pose_matrix=0) const
Display object 3d in an interactive window .
CImg< T > & operator=(const CImg< t > &img)
Copy an image into the current image instance.
CImg< T > & map(const CImg< t > &colormap, const unsigned int boundary_conditions=0)
Map predefined colormap on the scalar (indexed) image instance.
bool is_overlapped(const CImg< t > &img) const
Test if pixel buffers of instance and input images overlap.
static CImg< T > get_load_yuv(const char *const filename, const unsigned int size_x, const unsigned int size_y=1, const unsigned int first_frame=0, const unsigned int last_frame=~0U, const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z')
Load image sequence from a YUV file .
CImgList< T > & assign(const CImg< t > &img, const bool is_shared=false)
Construct list from one image .
CImg< T > & select(CImgDisplay &disp, const unsigned int feature_type=2, unsigned int *const XYZ=0)
Launch simple interface to select a shape from an image.
CImg< T > & structure_tensors(const unsigned int scheme=2)
Compute the structure tensor field of an image.
CImg< T > & object3dtoCImg3d(const CImgList< tp > &primitives, const CImgList< tc > &colors, const to &opacities, const bool full_check=true)
Convert 3d object into a CImg3d representation.
CImgList< T > & swap(CImgList< T > &list)
Swap all fields between two list instances.
T & atXYZC(const int x, const int y, const int z, const int c)
Access to a pixel value, using Neumann boundary conditions.
CImg< T > get_fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5) const
Fill sequentially all pixel values with specified values .
static void wait_all()
Wait for any window event occuring in any opened CImgDisplay.
CImgDisplay(const CImg< T > &img, const char *const title=0, const unsigned int normalization=3, const bool is_fullscreen=false, const bool is_closed=false)
Construct a display from an image.
static CImg< T > get_load_cimg(const char *const filename, const char axis='z', const float align=0)
Load image from a .cimg[z] file .
CImgDisplay & set_button()
Simulate a mouse button release event.
CImg< T > & columns(const int x0, const int x1)
Return specified range of image columns.
CImg< T > & vanvliet(const float sigma, const int order, const char axis='x', const bool boundary_conditions=true)
Van Vliet recursive Gaussian filter.
CImg< T > & label(const bool is_high_connectivity=false, const Tfloat tolerance=0)
Label connected components.
CImgDisplay & hide_mouse()
Hide mouse pointer.
CImg< T > operator>(const char axis) const
Return image corresponding to the appending of all images of the instance list along specified axis...
CImg< T > & operator/=(const CImg< t > &img)
In-place division operator.
int width() const
Return the size of the list, i.e. the number of images contained in it.
const unsigned int keyF7
Keycode for the F7 key (architecture-dependent).
const CImg< T > & display(CImgDisplay &disp) const
Display image into a CImgDisplay window.
static const CImg< Tuchar > & jet_LUT256()
Return colormap "jet", containing 256 colors entries in RGB.
const CImg< T > & save_minc2(const char *const filename, const char *const imitate_file=0) const
Save image as a MINC2 file.
CImgList< t > & move_to(CImgList< t > &list, const unsigned int pos)
Transfer the content of the list instance at a specified position in another list.
CImg< T > get_autocrop(const T value, const char *const axes="czyx") const
Autocrop image region, regarding the specified background value .
Tdouble variance_noise(const unsigned int variance_method=2) const
Return estimated variance of the noise.
CImg< T > & draw_ellipse(const int x0, const int y0, const CImg< t > &tensor, const tc *const color, const float opacity=1)
Draw a filled 2d ellipse .
const unsigned int key3
Keycode for the 3 key (architecture-dependent).
CImgList< T > & images(const unsigned int pos0, const unsigned int pos1)
Return a sublist.
CImg< unsigned long > get_label(const bool is_high_connectivity=false, const Tfloat tolerance=0) const
Label connected components .
const unsigned int keyV
Keycode for the V key (architecture-dependent).
static CImg< T > vector(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4, const T &a5, const T &a6, const T &a7, const T &a8, const T &a9, const T &a10, const T &a11, const T &a12, const T &a13)
Return a 1x14 image containing specified values.
CImg< T > get_transpose() const
Transpose the image, viewed as a matrix .
CImg< Tfloat > operator+(const char *const expression) const
Addition operator.
CImg< T > & load_inr(const char *const filename, float *const voxel_size=0)
Load image from an INRIMAGE-4 file.
CImgList< T > & reverse()
Reverse list order.
CImg< T > & fillC(const unsigned int x, const unsigned int y, const unsigned int z, const double a0,...)
Fill pixel values along the C-axis at a specified pixel position .
const T & max() const
Return a reference to the maximum pixel value .
CImg< T > get_warp(const CImg< t > &warp, const bool is_relative=false, const unsigned int interpolation=1, const unsigned int boundary_conditions=0) const
Warp image content by a warping field .
Tdouble sum() const
Return the sum of all the pixel values.
CImg< T > & draw_spline(const int x0, const int y0, const int z0, const float u0, const float v0, const float w0, const int x1, const int y1, const int z1, const float u1, const float v1, const float w1, const tc *const color, const float opacity=1, const float precision=4, const unsigned int pattern=~0U, const bool init_hatch=true)
Draw a 3d spline .
int mouse_x() const
Return X-coordinate of the mouse pointer.
static CImg< T > vector(const T &a0, const T &a1, const T &a2, const T &a3)
Return a 1x4 image containing specified values.
CImg< T > get_append(const char axis, const float align=0) const
Return a single image which is the appending of all images of the current CImgList instance...
T & back()
Return a reference to the last pixel value.
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 T val7, const T val8, const T val9, const T val10, const T val11, const T val12) const
Fill sequentially all pixel values with specified values .
CImg< Tfloat > get_asin() const
Compute the arcsine of each pixel value .
const char * graphicsmagick_path(const char *const user_path=0, const bool reinit_path=false)
Get/set path to the GraphicsMagick's gm binary.
T atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) const
Access to pixel value with Neumann boundary conditions for the 3 first coordinates (pos...
CImg< T > & load_other(const char *const filename)
Load image using various non-native ways.
CImg< T > & operator*=(const t value)
In-place multiplication operator.
const unsigned int keyCTRLRIGHT
Keycode for the CTRLRIGHT key (architecture-dependent).
CImg< floatT > get_object3dtoCImg3d(const CImgList< tp > &primitives, const CImgList< tc > &colors, const to &opacities, const bool full_check=true) const
Convert 3d object into a CImg3d representation .
static CImgList< T > get_load_gif_external(const char *const filename)
Load gif file, using ImageMagick or GraphicsMagick's external tools .
CImg< _cimg_Tt > operator-(const t value) const
Substraction operator.
CImg< T > & ror(const CImg< t > &img)
Compute the bitwise right rotation of each pixel value.
CImg< T > & autocrop(const T value, const char *const axes="czyx")
Autocrop image region, regarding the specified background value.
void strunescape(char *const str)
Replace escape sequences in C-strings by their binary ascii values.
CImg< Tuchar > get_CMYtoRGB() const
Convert pixel values from CMY to RGB color spaces .
T value_type
Pixel value type.
CImgList< Tfloat > get_hessian(const char *const axes=0) const
Return image hessian.
T & min()
Return a reference to the minimum pixel value of the instance list.
const CImg< T > get_shared_slices(const unsigned int z0, const unsigned int z1, const unsigned int c0=0) const
Return a shared memory image referencing a range of slices of the image instance .
const CImg< T > & front() const
Return reference to the first image of the list .
CImg< Tfloat > get_laplacian() const
Compute image laplacian .
CImgList(const CImg< t1 > &img1, const CImg< t2 > &img2, const CImg< t3 > &img3, const CImg< t4 > &img4, const bool is_shared=false)
Construct list from four images.
bool is_shared() const
Test shared state of the pixel buffer.
bool is_inf() const
Test if image instance contains a 'inf' value.
double log2(const double x)
Return base-2 logarithm of a value.
T minmod(const T a, const T b)
Return the min-mod of two values.
static CImg< floatT > isosurface3d(CImgList< tf > &primitives, const tfunc &func, const float isovalue, const float x0, const float y0, const float z0, const float x1, const float y1, const float z1, const int size_x=32, const int size_y=32, const int size_z=32)
Compute isosurface of a function, as a 3d object.
bool is_key_sequence(const unsigned int *const keycodes_sequence, const unsigned int length, const bool remove_sequence=false)
Return true if specified key sequence has been typed on the associated window, false otherwise...
CImg< T > & draw_object3d(const float x0, const float y0, const float z0, const CImg< tp > &vertices, const CImgList< tf > &primitives, const CImgList< tc > &colors, const CImgList< to > &opacities, const unsigned int render_type=4, const bool is_double_sided=false, const float focale=700, const float lightx=0, const float lighty=0, const float lightz=-5e8, const float specular_lightness=0.2f, const float specular_shininess=0.1f)
Draw a 3d object .
iterator begin()
Return iterator to the first image of the list.
T & atNXY(const int pos, const int x, const int y, const int z, const int c, const T out_value)
Access to pixel value with Dirichlet boundary conditions for the 3 first coordinates (pos...
CImg< T > & load_inr(std::FILE *const file, float *const voxel_size=0)
Load image from an INRIMAGE-4 file .
CImg< T > & draw_fill(const int x, const int y, const int z, const tc *const color, const float opacity, CImg< t > ®ion, const float sigma=0, const bool is_high_connexity=false)
Draw filled 3d region with the flood fill algorithm.
CImgDisplay & assign(const CImg< T > &img, const char *const title=0, const unsigned int normalization=3, const bool is_fullscreen=false, const bool is_closed=false)
Construct a display from an image .
static CImgList< T > get_load_tiff(const char *const filename, const unsigned int first_frame=0, const unsigned int last_frame=~0U, const unsigned int step_frame=1)
Load a multi-page TIFF file .
CImg< T > & fill(const T val)
Fill all pixel values with specified value.
const CImgList< T > & save_yuv(const char *const filename=0, const bool is_rgb=true) const
Save list as a YUV image sequence file.
CImg< ulongT > get_histogram(const unsigned int nb_levels, const T min_value, const T max_value) const
Compute the histogram of pixel values .
Tfloat linear_atXYZ(const float fx, const float fy=0, const float fz=0, const int c=0) const
Return pixel value, using linear interpolation and Neumann boundary conditions for the X...
bool is_sameYC(const unsigned int size_y, const unsigned int size_c) const
Test if image height and spectrum are equal to specified values.
CImg< T > & dilate(const CImg< t > &mask, const unsigned int boundary_conditions=1, const bool is_normalized=false)
Dilate image by a structuring element.
const CImgList< T > & save_cimg(const char *const filename, const bool is_compressed=false) const
Save list into a .cimg file.
CImg< T > & draw_rectangle(const int x0, const int y0, const int x1, const int y1, const tc *const color, const float opacity, const unsigned int pattern)
Draw a outlined 2d rectangle .
CImg< T > & load_jpeg(const char *const filename)
Load image from a JPEG file.
bool is_sameY(const unsigned int size_y) const
Test if image height is equal to specified value.
void info()
Print informations about environement variables.
CImgList< T > & assign(const unsigned int n, const unsigned int width, const unsigned int height, const unsigned int depth, const unsigned int spectrum, const T val)
Construct list containing images of specified size, and initialize pixel values . ...
CImg< T > get_sequence(const T a0, const T a1) const
Fill image with a linear sequence of values .
Tfloat cubic_atX(const float fx, const int y, const int z, const int c, const T out_value) const
Return pixel value, using cubic interpolation and Dirichlet boundary conditions for the X-coordinate...
const unsigned int keyK
Keycode for the K key (architecture-dependent).
static CImg< T > get_load_rgb(const char *const filename, const unsigned int dimw, const unsigned int dimh=1)
Load image from a RGB file .
static CImg< T > get_load_bmp(std::FILE *const file)
Load image from a BMP file .
CImg< T > get_ror(const unsigned int n=1) const
Compute the bitwise right rotation of each pixel value .
CImg(const char *const filename)
Construct image from reading an image file.
CImgDisplay & assign(const CImgList< T > &list, const char *const title=0, const unsigned int normalization=3, const bool is_fullscreen=false, const bool is_closed=false)
Construct a display from an image list .
CImg< T > & draw_spline(const CImg< tp > &points, const CImg< tt > &tangents, const tc *const color, const float opacity=1, const bool is_closed_set=false, const float precision=4, const unsigned int pattern=~0U, const bool init_hatch=true)
Draw a set of consecutive splines.
CImgList< T > get_remove(const unsigned int pos1, const unsigned int pos2) const
Remove all images between from indexes .
T sqr(const T val)
Return square of a value.
static CImg< T > vector(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4)
Return a 1x5 image containing specified values.
CImg< T > & draw_circle(const int x0, const int y0, int radius, const tc *const color, const float opacity, const unsigned int pattern)
Draw an outlined 2d circle.
bool is_sameXZC(const unsigned int size_x, const unsigned int size_z, const unsigned int size_c) const
Test if image width, depth and spectrum are equal to specified values.
static void save_empty_cimg(std::FILE *const file, const unsigned int nb, const unsigned int dx, const unsigned int dy=1, const unsigned int dz=1, const unsigned int dc=1)
Save empty .cimg file with specified dimensions.
CImg(const CImg< t > &img, const char *const dimensions, const T value)
Construct image with dimensions borrowed from another image and initialize pixel values.
CImgList< T > & insert(const unsigned int n, const CImgList< t > &list, const unsigned int pos=~0U, const bool is_shared=false)
Insert n copies of the list list at position pos of the current list.
const CImgList< T > & display(CImgDisplay &disp, const bool display_info, const char axis='x', const float align=0, unsigned int *const XYZ=0) const
Display the current CImgList instance in a new display window.
CImg< T > & normalize()
Normalize multi-valued pixels of the image instance, with respect to their L2-norm.
CImg< T > & xyYtoRGB()
Convert pixel values from xyY to RGB color spaces.
static CImg< T > vector(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4, const T &a5, const T &a6, const T &a7, const T &a8, const T &a9, const T &a10, const T &a11, const T &a12)
Return a 1x13 image containing specified values.
CImg< T > & equalize(const unsigned int nb_levels)
Equalize histogram of pixel values .
CImg< T > & draw_spline(const CImg< tp > &points, const tc *const color, const float opacity=1, const bool is_closed_set=false, const float precision=4, const unsigned int pattern=~0U, const bool init_hatch=true)
Draw a set of consecutive splines .
CImg< _cimg_Tt > operator%(const CImg< t > &img) const
Modulo operator.
CImg< T > & rol(const unsigned int n=1)
Compute the bitwise left rotation of each pixel value.
const CImg< T > & SVD(CImg< t > &U, CImg< t > &S, CImg< t > &V, const bool sorting=true, const unsigned int max_iteration=40, const float lambda=0) const
Compute the SVD of the instance image, viewed as a general matrix.
const CImg< T > & eigen(CImg< t > &val, CImg< t > &vec) const
Compute eigenvalues and eigenvectors of the instance image, viewed as a matrix.
CImg< Tuchar > get_CMYtoCMYK() const
Convert pixel values from CMY to CMYK color spaces .
CImg< T > operator>>(const t value) const
Bitwise right shift operator.
CImg< Tfloat > get_sinc() const
Compute the sinc of each pixel value .
CImg< Tfloat > get_pow(const char *const expression) const
Raise each pixel value to a power, specified from an expression .
CImg< _cimg_Tt > operator/(const CImg< t > &img) const
Division operator.
CImg< T > get_erode(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) const
Erode image by a rectangular structuring element of specified size .
CImg< T > & fillY(const unsigned int x, const unsigned int z, const unsigned int c, const int a0,...)
Fill pixel values along the Y-axis at a specified pixel position.
CImg< Tfloat > operator/(const char *const expression) const
Division operator.
CImg< T > & discard(const CImg< t > &values)
Discard specified sequence of values in the image buffer.
CImg< T > & norm(const int norm_type=2)
Compute L2-norm of each multi-valued pixel of the image instance.
CImgList< T > & operator=(const char *const filename)
Construct list by reading the content of a file .
int width() const
Return the number of image columns.
CImgList< T > & push_front(const CImgList< t > &list)
Insert list at the front of the current list.
CImgList< T > & assign(const unsigned int n, const unsigned int width, const unsigned int height, const unsigned int depth, const unsigned int spectrum, const double val0, const double val1,...)
Construct list with images of specified size, and initialize pixel values from a sequence of doubles ...
CImg< T > get_autocrop(const T *const color=0, const char *const axes="zyx") const
Autocrop image region, regarding the specified background color .
CImg< T > & draw_triangle(const int x0, const int y0, const int x1, const int y1, const int x2, const int y2, const tc1 *const color1, const tc2 *const color2, const tc3 *const color3, const float opacity=1)
Draw a color-interpolated 2d triangle.
CImg< T > & cosh()
Compute the hyperbolic cosine of each pixel value.
const CImg< T > get_shared_channels(const unsigned int c0, const unsigned int c1) const
Return a shared-memory image referencing a range of channels of the image instance ...
bool is_sameYZC(const CImg< t > &img) const
Test if image height, depth and spectrum are the same as that of another image.
CImg(const unsigned int size_x, const unsigned int size_y=1, const unsigned int size_z=1, const unsigned int size_c=1)
Construct image with specified size.
static CImg< T > get_load_pnm(std::FILE *const file)
Load image from a PNM file .
const CImgList< T > & save_cimg(const char *const filename, const unsigned int n0, const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int c0) const
Insert the image instance into into an existing .cimg file, at specified coordinates.
CImgList< T > & assign(const CImg< t1 > &img1, const CImg< t2 > &img2, const bool is_shared=false)
Construct list from two images .
static void FFT(CImg< T > &real, CImg< T > &imag, const char axis, const bool is_invert=false)
Compute 1d Fast Fourier Transform, along a specified axis.
const T * data() const
Return a pointer to the first pixel value .
const unsigned int keyQ
Keycode for the Q key (architecture-dependent).
static CImg< T > get_load_bmp(const char *const filename)
Load image from a BMP file .
CImgList< T > & assign(const CImg< t1 > &img1, const CImg< t2 > &img2, const CImg< t3 > &img3, const CImg< t4 > &img4, const CImg< t5 > &img5, const CImg< t6 > &img6, const CImg< t7 > &img7, const CImg< t8 > &img8, const bool is_shared=false)
Construct list from eight images .
CImg< T > operator~() const
Bitwise inversion operator.
CImg< T > & asin()
Compute the arcsine of each pixel value.
char * number_filename(const char *const filename, const int number, const unsigned int digits, char *const str)
Generate a numbered version of a filename.
CImg< T > & ror(const char *const expression)
Compute the bitwise right rotation of each pixel value.
CImg< T > & blur_bilateral(const CImg< t > &guide, const float sigma_s, const float sigma_r, const int bgrid_s=-33, const int bgrid_r=32, const bool interpolation_type=true)
Blur image using the joint bilateral filter.
CImgList()
Default constructor.
CImg< T > & RGBtoLab()
Convert pixel values from RGB to Lab color spaces.
CImg< T > & operator>>=(const t value)
In-place bitwise right shift operator.
const unsigned int keyF2
Keycode for the F2 key (architecture-dependent).
const unsigned int keyF10
Keycode for the F10 key (architecture-dependent).
char * load_network_external(const char *const filename, char *const filename_local)
Load file from network as a local temporary file.
CImg< floatT > get_object3dtoCImg3d(const bool full_check=true) const
Convert 3d object into a CImg3d representation .
CImg< T > & draw_polygon(const CImg< t > &points, const tc *const color, const float opacity=1)
Draw a filled 2d polygon.
CImg< T > & assign(const CImg< t > &img)
Construct image copy .
const unsigned int key8
Keycode for the 8 key (architecture-dependent).
CImgList< T > get_shared_images(const unsigned int pos0, const unsigned int pos1)
Return a shared sublist.
T atNX(const int pos, const int x, const int y, const int z, const int c, const T out_value) const
Access to pixel value with Dirichlet boundary conditions for the 2 first coordinates (pos...
int xln(const int x)
Return 1 + log_10(x) of a value x.
CImg< T > & log2()
Compute the base-2 logarithm of each pixel value.
bool is_sameXY(const unsigned int size_x, const unsigned int size_y) const
Test if image width and height are equal to specified values.
CImg< Tfloat > get_dijkstra(const unsigned int starting_node, const unsigned int ending_node=~0U) const
Return minimal path in a graph, using the Dijkstra algorithm .
unsigned int wait(const unsigned int milliseconds)
Wait for a given number of milliseconds since the last call to wait().
CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, const double value0, const double value1,...)
Construct image with specified size and initialize pixel values from a sequence of doubles...
const char * temporary_path(const char *const user_path=0, const bool reinit_path=false)
Get/set path to store temporary files.
CImg< T > & draw_spline(const int x0, const int y0, const float u0, const float v0, const int x1, const int y1, const float u1, const float v1, const tc *const color, const float opacity=1, const float precision=0.25, const unsigned int pattern=~0U, const bool init_hatch=true)
Draw a 2d spline.
const unsigned int keyPAUSE
Keycode for the PAUSE key (architecture-dependent).
CImg< Tfloat > get_RGBtosRGB() const
Convert pixel values from RGB to sRGB color spaces .
CImg< T > get_blur_patch(const float sigma_s, const float sigma_p, const unsigned int patch_size=3, const unsigned int lookup_size=4, const float smoothness=0, const bool is_fast_approx=true) const
Blur image using patch-based space .
CImg< T > & log()
Compute the logarithm of each pixel value.
bool is_object3d(const CImgList< tp > &primitives, const CImgList< tc > &colors, const to &opacities, const bool full_check=true, char *const error_message=0) const
Test if the set {*this,primitives,colors,opacities} defines a valid 3d object.
static const CImg< Tuchar > & HSV_LUT256()
Return colormap "HSV", containing 256 colors entries in RGB.
static CImg< T > diagonal(const T &a0, const T &a1, const T &a2, const T &a3)
Return a 4x4 diagonal matrix containing specified coefficients.
CImg< T > & histogram(const unsigned int nb_levels, const T min_value, const T max_value)
Compute the histogram of pixel values.
T atXY(const int x, const int y, const int z, const int c, const T out_value) const
Access to a pixel value, using Dirichlet boundary conditions for the X and Y coordinates ...
CImgList< T > & remove(const unsigned int pos1, const unsigned int pos2)
Remove all images between from indexes.
CImg< T > & draw_image(const int x0, const CImg< t > &sprite, const float opacity=1)
Draw an image .
const unsigned int keyPAD7
Keycode for the PAD7 key (architecture-dependent).
const unsigned int keyAPPLEFT
Keycode for the APPLEFT key (architecture-dependent).
CImg< Tfloat > get_normalize(const T min_value, const T max_value) const
Linearly normalize pixel values .
CImg< T > get_fill(const CImg< t > &values, const bool repeat_values=true) const
Fill sequentially pixel values according to the values found in another image .
CImg(const CImgDisplay &disp)
Construct image from a display window.
CImg< T > & ror(const unsigned int n=1)
Compute the bitwise right rotation of each pixel value.
CImg< T > & draw_text(const int x0, const int y0, const char *const text, const tc1 *const foreground_color, const tc2 *const background_color, const float opacity=1, const unsigned int font_height=13,...)
Draw a text string .
CImgList< T > get_split(const char axis, const int nb=0) const
Return a list where each image has been split along the specified axis .
CImg< T > & draw_circle(const int x0, const int y0, int radius, const tc *const color, const float opacity=1)
Draw a filled 2d circle.
const unsigned int keyPAD8
Keycode for the PAD8 key (architecture-dependent).
static CImg< floatT > streamline(const char *const expression, const float x, const float y, const float z, const float L=256, const float dl=0.1f, const unsigned int interpolation_type=2, const bool is_backward_tracking=true, const bool is_oriented_only=false, const float x0=0, const float y0=0, const float z0=0, const float x1=0, const float y1=0, const float z1=0)
Return stream line of a 3d vector field .
CImg< Tfloat > get_RGBtoHSI() const
Convert pixel values from RGB to HSI color spaces .
CImg< T > & operator>>=(const char *const expression)
In-place bitwise right shift operator.
bool is_sameYZC(const unsigned int size_y, const unsigned int size_z, const unsigned int size_c) const
Test if image height, depth and spectrum are equal to specified values.
const unsigned int keyF8
Keycode for the F8 key (architecture-dependent).
const char * split_filename(const char *const filename, char *const body=0)
Split filename into two C-strings body and extension.
static CImg< T > get_load_off(CImgList< tf > &primitives, CImgList< tc > &colors, std::FILE *const file)
Load 3d object from a .OFF file .
const unsigned int keyR
Keycode for the R key (architecture-dependent).
CImg< Tfloat > get_atan() const
Compute the arctangent of each pixel value .
void warn(const char *const format,...)
Display a warning message on the default output stream.
int window_width() const
Return width of the associated window.
CImg< Tfloat > get_deriche(const float sigma, const int order=0, const char axis='x', const bool boundary_conditions=true) const
Apply recursive Deriche filter .
CImg< T > & haar(const char axis, const bool invert=false, const unsigned int nb_scales=1)
Compute Haar multiscale wavelet transform.
unsigned long time()
Return the value of a system timer, with a millisecond precision.
CImg< T > & HSLtoRGB()
Convert pixel values from HSL to RGB color spaces.
CImg< T > operator<<(const t value) const
Bitwise left shift operator.
CImg< T > & load_dlm(std::FILE *const file)
Load image from a DLM file .
CImg< T > & crop(const int x0, const int y0, const int x1, const int y1, const bool boundary_conditions=false)
Crop image region .
CImg< T > & assign(const char *const filename)
Construct image from reading an image file .
CImg< T > get_shared_slice(const unsigned int z0, const unsigned int c0=0)
Return a shared-memory image referencing one slice of the image instance.
CImg< T > get_columns(const int x0, const int x1) const
Return specified range of image columns .
CImg< T > & fillZ(const unsigned int x, const unsigned int y, const unsigned int c, const double a0,...)
Fill pixel values along the Z-axis at a specified pixel position .
CImg< T > & load_rgba(const char *const filename, const unsigned int dimw, const unsigned int dimh=1)
Load image from a RGBA file.
CImgList< T > & load(const char *const filename)
Load a list from a file.
CImg< T > * data(const unsigned int l)
Return pointer to the pos-th image of the list.
CImgList(const unsigned int n, const unsigned int width, const unsigned int height, const unsigned int depth, const unsigned int spectrum, const double val0, const double val1,...)
Construct list containing images of specified size, and initialize pixel values from a sequence of do...
CImgList< T > & operator,(const CImgList< t > &list) const
Return a copy of the list instance, where all elements of input list have been inserted at the end ...
CImg< T > & draw_quiver(const CImg< t1 > &flow, const CImg< t2 > &color, const float opacity=1, const unsigned int sampling=25, const float factor=-20, const bool is_arrow=true, const unsigned int pattern=~0U)
Draw a 2d vector field, using a field of colors.
CImg< T > & draw_triangle(const int x0, const int y0, const int x1, const int y1, const int x2, const int y2, const tc *const color, const float opacity, const unsigned int pattern)
Draw a outlined 2d triangle.
CImg< T > & operator=(const char *const expression)
Assign pixels values from a specified expression.
CImg< T > & unroll(const char axis)
Unroll pixel values along specified axis.
CImg< T > get_unroll(const char axis) const
Unroll pixel values along specified axis .
CImg< Tuchar > get_xyYtoRGB() const
Convert pixel values from xyY to RGB color spaces .
CImgList< T > & load_tiff(const char *const filename, const unsigned int first_frame=0, const unsigned int last_frame=~0U, const unsigned int step_frame=1)
Load images from a TIFF file.
CImg< T > & load_png(const char *const filename)
Load image from a PNG file.
const CImg< T > & save_pfm(std::FILE *const file) const
Save image as a PFM file .
unsigned int & exception_mode(const unsigned int mode)
Set current exception mode.
const CImg< T > & save_inr(std::FILE *const file, const float *const voxel_size=0) const
Save image as an INRIMAGE-4 file .
bool is_sameXY(const CImg< t > &img) const
Test if image width and height are the same as that of another image.
static CImg< T > string(const char *const str, const bool is_last_zero=true, const bool is_shared=false)
Return an image containing the ascii codes of the specified string.
CImg< T > & load_analyze(const char *const filename, float *const voxel_size=0)
Load image from an ANALYZE7.5/NIFTI file.
CImg< Tfloat > get_max(const char *const expression) const
Pointwise max operator between an image and an expression .
T * data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0)
Return a pointer to a located pixel value.
const unsigned int keyESC
Keycode for the ESC key (architecture-dependent).
CImg< T > & load_imagemagick_external(const char *const filename)
Load image using ImageMagick's external tool 'convert'.
CImgList< T > & assign(const unsigned int n, const CImg< t > &img, const bool is_shared=false)
Construct list containing copies of an input image .
static CImg< T > get_load_jpeg(const char *const filename)
Load image from a JPEG file .
const unsigned int keyB
Keycode for the B key (architecture-dependent).
T & atNXYZC(const int pos, const int x, const int y, const int z, const int c, const T out_value)
Access to pixel value with Dirichlet boundary conditions.
T & atNXYZ(const int pos, const int x, const int y, const int z, const int c=0)
Access to pixel value with Neumann boundary conditions for the 4 first coordinates (pos...
T & atNXY(const int pos, const int x, const int y, const int z=0, const int c=0)
Access to pixel value with Neumann boundary conditions for the 3 first coordinates (pos...
const T & min_max(t &max_val) const
Return a reference to the minimum pixel value as well as the maximum pixel value .
const CImg< T > & display_object3d(CImgDisplay &disp, const CImg< tp > &vertices, const CImgList< tf > &primitives, const bool centering=true, const int render_static=4, const int render_motion=1, const bool is_double_sided=true, const float focale=700, const float light_x=0, const float light_y=0, const float light_z=-5e8f, const float specular_lightness=0.2f, const float specular_shininess=0.1f, const bool display_axes=true, float *const pose_matrix=0) const
Display object 3d in an interactive window .
CImg< T > & operator+=(const char *const expression)
In-place addition operator.
float frames_per_second()
Return the current refresh rate, in frames per second.
CImg< Tuchar > get_YUVtoRGB() const
Convert pixel values from YUV to RGB color spaces .
CImgList< T > & FFT(const bool invert=false)
Compute a n-d Fast Fourier Transform.
CImg< Tfloat > get_log10() const
Compute the base-10 logarithm of each pixel value .
CImg< T > & load_pnm(std::FILE *const file)
Load image from a PNM file .
CImg< T > & draw_object3d(const float x0, const float y0, const float z0, const CImg< tp > &vertices, const CImgList< tf > &primitives, const CImgList< tc > &colors, const CImg< to > &opacities, const unsigned int render_type, const bool is_double_sided, const float focale, const float lightx, const float lighty, const float lightz, const float specular_lightness, const float specular_shininess, CImg< tz > &zbuffer)
Draw a 3d object .
unsigned int button() const
Return current state of the mouse buttons.
long offset(const int x, const int y=0, const int z=0, const int c=0) const
Return the offset to a located pixel value, with respect to the beginning of the pixel buffer...
bool contains(const T &pixel) const
Test if pixel value is inside image bounds.
CImgList< T > get_insert(const unsigned int n, const CImgList< t > &list, const unsigned int pos=~0U, const bool is_shared=false) const
Insert n copies of the list list at position pos of the current list .
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 T val7, const T val8, const T val9, const T val10, const T val11, const T val12, const T val13) const
Fill sequentially all pixel values with specified values .
CImg< T > get_max(const T val) const
Pointwise max operator between instance image and a value .
CImg< T > & draw_triangle(CImg< tz > &zbuffer, const int x0, const int y0, const float z0, const int x1, const int y1, const float z1, const int x2, const int y2, const float z2, const CImg< tc > &texture, const int tx0, const int ty0, const int tx1, const int ty1, const int tx2, const int ty2, const CImg< tl > &light, const int lx0, const int ly0, const int lx1, const int ly1, const int lx2, const int ly2, const float opacity=1)
Draw a textured Phong-shaded 2d triangle, with perspective correction and z-buffering.
CImgList< T > & assign(const CImgList< t > &list, const bool is_shared=false)
Construct list as a copy of an existing list and force the shared state of the list elements ...
CImgDisplay(const CImgList< T > &list, const char *const title=0, const unsigned int normalization=3, const bool is_fullscreen=false, const bool is_closed=false)
Construct a display from an image list.
CImg< T > & CMYKtoCMY()
Convert pixel values from CMYK to CMY color spaces.
CImg< T > & pow(const CImg< t > &img)
Raise each pixel value to a power, pointwisely specified from another image.
CImg< T > & blur_bilateral(const CImg< t > &guide, const float sigma_x, const float sigma_y, const float sigma_z, const float sigma_r, const int bgrid_x, const int bgrid_y, const int bgrid_z, const int bgrid_r, const bool interpolation_type=true)
Blur image, with the joint bilateral filter.
const unsigned int keyPAD4
Keycode for the PAD4 key (architecture-dependent).
int window_height() const
Return height of the associated window.
CImg< T > operator&(const t value) const
Bitwise AND operator.
CImgDisplay & close()
Close (visible) associated window and make it disappear from the screen.
static CImg< T > get_load_camera(const unsigned int camera_index=0, const unsigned int skip_frames=0, const bool release_camera=true, const unsigned int capture_width=0, const unsigned int capture_height=0)
Load image from a camera stream, using OpenCV .
CImg< T > & draw_text(const int x0, const int y0, const char *const text, const tc1 *const foreground_color, const tc2 *const background_color, const float opacity, const CImgList< t > &font,...)
Draw a text string.
CImg< T > * iterator
Simple iterator type, to loop through each image of a list.
CImg< T > & blur_patch(const float sigma_s, const float sigma_p, const unsigned int patch_size=3, const unsigned int lookup_size=4, const float smoothness=0, const bool is_fast_approx=true)
Blur image using patch-based space.
CImg< T > get_ror(const char *const expression) const
Compute the bitwise right rotation of each pixel value .
CImg< unsigned long > get_label(const CImg< t > &connectivity_mask, const Tfloat tolerance=0) const
Label connected components .
CImg< intT > get_select(CImgDisplay &disp, const bool feature_type=true, const char axis='x', const float align=0) const
Display a simple interactive interface to select images or sublists.
static CImg< T > get_load_inr(std::FILE *const file, float *voxel_size=0)
Load image from an INRIMAGE-4 file .
const CImg< T > & save_medcon_external(const char *const filename) const
Save image as a Dicom file.
CImg< T > get_mirror(const char *const axes) const
Mirror image content along specified axes .
CImg< T > & YCbCrtoRGB()
Convert pixel values from RGB to YCbCr color spaces.
Tfloat cubic_atXY(const float fx, const float fy, const int z, const int c, const T out_value, const Tfloat min_value, const Tfloat max_value) const
Return damped pixel value, using cubic interpolation and Dirichlet boundary conditions for the X...
const unsigned int keyEND
Keycode for the END key (architecture-dependent).
const unsigned int keyE
Keycode for the E key (architecture-dependent).
CImg< T > & cos()
Compute the cosine of each pixel value.
T abs(const T a)
Return absolute value of a value.
const CImgDisplay & snapshot(CImg< T > &img) const
Take a snapshot of the associated window content.
const unsigned int keyARROWRIGHT
Keycode for the ARROWRIGHT key (architecture-dependent).
bool strpare(char *const str, const char delimiter=' ', const bool is_symmetric=false, const bool is_iterative=false)
Remove delimiters on the start and/or end of a C-string.
const T * const_iterator
Simple const iterator type, to loop through each pixel value of a const image instance.
const CImg< T > & save_pnk(std::FILE *const file) const
Save image as a PNK file .
CImg< T > get_vector() const
Unroll pixel values along axis y .
CImg< Tfloat > get_pow(const double p) const
Raise each pixel value to a specified power .
bool is_sameXZ(const unsigned int size_x, const unsigned int size_z) const
Test if image width and depth are equal to specified values.
CImg< T > & assign(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, const T value)
Construct image with specified size and initialize pixel values .
bool containsN(const int n) const
Test if list contains image with specified indice.
static CImg< T > get_load_gzip_external(const char *const filename)
Load gzipped image file, using external tool 'gunzip' .
CImg< intT > get_select(CImgDisplay &disp, const unsigned int feature_type=2, unsigned int *const XYZ=0) const
Simple interface to select a shape from an image .
CImg< T > & column(const int x0)
Return specified image column .
const CImg< T > get_shared_points(const unsigned int x0, const unsigned int x1, const unsigned int y0=0, const unsigned int z0=0, const unsigned int c0=0) const
Return a shared-memory image referencing a range of pixels of the image instance .
const T & back() const
Return a reference to the last pixel value .
CImgDisplay & display(const CImg< T > &img)
Display image on associated window.
const char * what() const
Return a C-string containing the error message associated to the thrown exception.
const char * ffmpeg_path(const char *const user_path=0, const bool reinit_path=false)
Get/set path to the FFMPEG's ffmpeg binary.
CImg< T > get_dilate(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) const
Dilate image by a rectangular structuring element of specified size .
CImg< T > get_crop(const int x0, const int y0, const int z0, const int c0, const int x1, const int y1, const int z1, const int c1, const bool boundary_conditions=false) const
Crop image region .
unsigned int normalization() const
Return normalization type of the display.
static CImg< T > get_load_pfm(const char *const filename)
Load image from a PFM file .
CImg< Tuchar > get_XYZtoRGB() const
Convert pixel values from XYZ_709 to RGB color spaces .
static CImg< T > get_load_cimg(std::FILE *const file, const unsigned int n0, const unsigned int n1, const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int c0, const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int c1, const char axis='z', const float align=0)
Load sub-images of a .cimg file .
CImgList< T > get_images(const unsigned int pos0, const unsigned int pos1) const
Return a sublist .
T atX(const int x, const int y=0, const int z=0, const int c=0) const
Access to a pixel value, using Neumann boundary conditions for the X-coordinate . ...
CImg< T > & shift_object3d(const float tx, const float ty=0, const float tz=0)
Shift 3d object's vertices.
CImg< T > & draw_text(const int x0, const int y0, const char *const text, const int, const tc *const background_color, const float opacity=1, const unsigned int font_height=13,...)
Draw a text string .
T atXYZC(const int x, const int y, const int z, const int c, const T out_value) const
Access to a pixel value, using Dirichlet boundary conditions .
CImg< Tfloat > get_vanvliet(const float sigma, const int order, const char axis='x', const bool boundary_conditions=true) const
Blur image using Van Vliet recursive Gaussian filter. .
void swap(T &a, T &b)
Exchange values of variables a and b.
static CImg< T > vector(const T &a0)
Return a 1x1 image containing specified value.
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
Sharpen image .
T atXYZ(const int x, const int y, const int z, const int c, const T out_value) const
Access to a pixel value, using Dirichlet boundary conditions for the X,Y and Z-coordinates ...
double rand()
Return a random variable between [0,1] with respect to an uniform distribution.
const unsigned int keyPADADD
Keycode for the PADADD key (architecture-dependent).
CImgDisplay & set_button(const unsigned int button, const bool is_pressed=true)
Simulate a mouse button press or release event.
bool is_sameZC(const unsigned int size_z, const unsigned int size_c) const
Test if image depth and spectrum are equal to specified values.
CImgList< Tfloat > get_gradient(const char *const axes=0, const int scheme=3) const
Return image gradient.
CImg< T > & draw_image(const CImg< ti > &sprite, const CImg< tm > &mask, const float opacity=1, const float mask_max_value=1)
Draw an image.
bool is_empty() const
Return true if display is empty, false otherwise.
const unsigned int keyALT
Keycode for the ALT key (architecture-dependent).
bool is_sameYZ(const CImg< t > &img) const
Test if image height and depth are the same as that of another image.
const char * file_type(std::FILE *const file, const char *const filename)
Try to guess format from an image file.
CImg< T > & vector()
Unroll pixel values along axis y.
static CImg< T > get_load_other(const char *const filename)
Load image using various non-native ways .
const unsigned int keyF12
Keycode for the F12 key (architecture-dependent).
CImg< T > & RGBtoHSV()
Convert pixel values from RGB to HSV color spaces.
Tdouble variance(const unsigned int variance_method=1) const
Return the variance of the pixel values.
static CImg< floatT > streamline(const tfunc &func, const float x, const float y, const float z, const float L=256, const float dl=0.1f, const unsigned int interpolation_type=2, const bool is_backward_tracking=false, const bool is_oriented_only=false, const float x0=0, const float y0=0, const float z0=0, const float x1=0, const float y1=0, const float z1=0)
Return stream line of a 3d vector field.
T value_type
Pixel value type.
bool is_sameC(const unsigned int size_c) const
Test if image spectrum is equal to specified value.
CImg< T > & set_linear_atXY(const T &value, const float fx, const float fy=0, const int z=0, const int c=0, const bool is_added=false)
Set pixel value, using linear interpolation for the X and Y-coordinates.
const CImg< T > & save_pandore(std::FILE *const file, const unsigned int colorspace=0) const
Save image as a Pandore-5 file .
CImg< T > get_resize(const CImg< t > &src, const int interpolation_type=1, const unsigned int boundary_conditions=0, const float centering_x=0, const float centering_y=0, const float centering_z=0, const float centering_c=0) const
Resize image to dimensions of another image .
CImg< T > get_channels(const int c0, const int c1) const
Return specified range of image channels.
CImg< _cimg_Tt > operator*(const t value) const
Multiplication operator.
CImg< T > & projections2d(const unsigned int x0, const unsigned int y0, const unsigned int z0)
Construct a 2d representation of a 3d image, with XY,XZ and YZ views .
T & atX(const int x, const int y=0, const int z=0, const int c=0)
Access to a pixel value, using Neumann boundary conditions for the X-coordinate.
CImg< T > & rand(const T val_min, const T val_max)
Fill image with random values in specified range.
CImg< T > & draw_image(const int x0, const int y0, const CImg< t > &sprite, const float opacity=1)
Draw an image .
CImg< T > & draw_object3d(const float x0, const float y0, const float z0, const CImg< tp > &vertices, const CImgList< tf > &primitives, const CImgList< tc > &colors, const CImg< to > &opacities, const unsigned int render_type=4, const bool is_double_sided=false, const float focale=700, const float lightx=0, const float lighty=0, const float lightz=-5e8, const float specular_lightness=0.2f, const float specular_shininess=0.1f)
Draw a 3d object.
const CImg< T > * data(const unsigned int l) const
Return pointer to the pos-th image of the list .
CImg(const CImg< t > &img, const char *const dimensions)
Construct image with dimensions borrowed from another image.
static CImg< T > rotation_matrix(const float x, const float y, const float z, const float w, const bool is_quaternion=false)
Return a 3x3 rotation matrix along the (x,y,z)-axis with an angle w.
const unsigned int keyARROWUP
Keycode for the ARROWUP key (architecture-dependent).
CImg< T > & fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, const T val7, const T val8, const T val9, const T val10, const T val11, const T val12, const T val13, const T val14)
Fill sequentially all pixel values with specified values .
CImgDisplay & operator=(const CImgList< t > &list)
Display list of images on associated window.
const CImg< T > get_shared_channel(const unsigned int c0) const
Return a shared-memory image referencing one channel of the image instance .
CImg< Tuchar > get_RGBtoCMY() const
Convert pixel values from RGB to CMY color spaces .
CImg< T > & CImg3dtoobject3d(CImgList< tp > &primitives, CImgList< tc > &colors, CImgList< to > &opacities, const bool full_check=true)
Convert CImg3d representation into a 3d object.
T & atX(const int x, const int y, const int z, const int c, const T out_value)
Access to a pixel value, using Dirichlet boundary conditions for the X-coordinate.
CImgList< T > & assign(const CImg< t1 > &img1, const CImg< t2 > &img2, const CImg< t3 > &img3, const CImg< t4 > &img4, const CImg< t5 > &img5, const CImg< t6 > &img6, const bool is_shared=false)
Construct list from six images .
Tdouble PSNR(const CImg< t > &img, const Tdouble max_value=255) const
Compute the PSNR (Peak Signal-to-Noise Ratio) between two images.
bool is_CImg3d(const bool full_check=true, char *const error_message=0) const
Test if image instance represents a valid serialization of a 3d object.
static CImg< T > get_load_cimg(const char *const filename, const unsigned int n0, const unsigned int n1, const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int c0, const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int c1, const char axis='z', const float align=0)
Load sub-images of a .cimg file .
CImg< T > & draw_point(const int x0, const int y0, const int z0, const tc *const color, const float opacity=1)
Draw a 3d point.
const CImg< T > & save_ascii(const char *const filename) const
Save image as an ascii file.
T sign(const T x)
Return the sign of a value.
const unsigned int keyP
Keycode for the P key (architecture-dependent).
T atNXYZC(const int pos, const int x, const int y, const int z, const int c, const T out_value) const
Access to pixel value with Dirichlet boundary conditions .
CImg< T > & fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6)
Fill sequentially all pixel values with specified values .
CImg< T > & sqrt()
Compute the square root of each pixel value.
CImg< Tfloat > get_distance_eikonal(const unsigned int nb_iterations, const float band_size=0, const float time_step=0.5f) const
Compute distance function to 0-valued isophotes, using the Eikonal PDE .
T & max_min(t &min_val)
Return a reference to the minimum pixel value of the instance list and return the minimum value as we...
const CImg< T > & operator()(const unsigned int pos) const
Return a reference to one image of the list.
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 T val7) const
Fill sequentially all pixel values with specified values .
CImg< Tfloat > get_sRGBtoRGB() const
Convert pixel values from sRGB to RGB color spaces .
static const char * pixel_type()
Return the type of image pixel values as a C string.
static CImg< T > matrix(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4, const T &a5, const T &a6, const T &a7, const T &a8, const T &a9, const T &a10, const T &a11, const T &a12, const T &a13, const T &a14, const T &a15)
Return a 4x4 matrix containing specified coefficients.
static CImg< T > get_load_inr(const char *const filename, float *const voxel_size=0)
Load image from an INRIMAGE-4 file .
CImg< T > & operator+=(const t value)
In-place addition operator.
static CImg< T > get_load_off(CImgList< tf > &primitives, CImgList< tc > &colors, const char *const filename)
Load 3d object from a .OFF file .
const CImg< T > & save_raw(std::FILE *const file, const bool is_multiplexed=false) const
Save image as a raw data file .
iterator begin()
Return a CImg::iterator pointing to the first pixel value.
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 T val7, const T val8, const T val9, const T val10) const
Fill sequentially all pixel values with specified values .
CImg< T > & assign()
Construct empty image .
CImgDisplay & wait(const unsigned int milliseconds)
Wait for a given number of milliseconds since the last call to wait().
CImg< T > & resize_halfXY()
Resize image to half-size along XY axes, using an optimized filter.
CImg< T > & dilate(const unsigned int sx, const unsigned int sy, const unsigned int sz=1)
Dilate image by a rectangular structuring element of specified size.
CImg< T > & watershed(const CImg< t > &priority, const bool fill_lines=true)
Compute watershed transform.
CImg< T > & sqr()
Compute the square value of each pixel value.
Class representing an image (up to 4 dimensions wide), each pixel being of type T.
Tfloat linear_atXY(const float fx, const float fy, const int z=0, const int c=0) const
Return pixel value, using linear interpolation and Neumann boundary conditions for the X and Y-coordi...
CImgList< T > & load_gzip_external(const char *const filename)
Load a gzipped list, using external tool 'gunzip'.
int strncasecmp(const char *const str1, const char *const str2, const int l)
Compare the first l characters of two C-strings, ignoring the case.
const unsigned int keyA
Keycode for the A key (architecture-dependent).
T & min_max(t &max_val)
Return a reference to the minimum pixel value of the instance list and return the maximum vvalue as w...
double sinc(const double x)
Return the sinc of a given value.
CImgList< T > & assign(const CImgDisplay &disp)
Construct list from the content of a display window .
CImg< T > get_crop(const int x0, const int y0, const int z0, const int x1, const int y1, const int z1, const bool boundary_conditions=false) const
Crop image region .
CImgDisplay & resize(const int width, const int height, const bool force_redraw=true)
Resize display to the specified size.
static CImg< floatT > isosurface3d(CImgList< tf > &primitives, const char *const expression, const float isovalue, const float x0, const float y0, const float z0, const float x1, const float y1, const float z1, const int dx=32, const int dy=32, const int dz=32)
Compute isosurface of a function, as a 3d object .
CImg< T > & autocrop(const T *const color=0, const char *const axes="zyx")
Autocrop image region, regarding the specified background color.
Tdouble trace() const
Compute the trace of the image, viewed as a matrix.
CImg< Tfloat > get_XYZtoLab() const
Convert pixel values from XYZ_709 to Lab color spaces .
const unsigned int keyS
Keycode for the S key (architecture-dependent).
const CImg< T > & save_magick(const char *const filename, const unsigned int bytes_per_pixel=0) const
Save image, using built-in ImageMagick++ library.
CImg< charT > value_string(const char separator=',', const unsigned int max_size=0) const
Return a C-string containing a list of all values of the image instance.
CImg< T > operator-() const
Replace each pixel by its opposite value.
CImg< T > & load_pnm(const char *const filename)
Load image from a PNM file.
CImg< Tfloat > get_abs() const
Compute the absolute value of each pixel value .
const CImg< T > get_shared() const
Return a shared-memory version of the image instance .
Tfloat linear_atX(const float fx, const int y=0, const int z=0, const int c=0) const
Return pixel value, using linear interpolation and Neumann boundary conditions for the X-coordinate...
const CImgList< T > get_shared() const
Return a list with elements being shared copies of images in the list instance .
CImg< T > & assign(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, const double value0, const double value1,...)
Construct image with specified size and initialize pixel values from a sequence of doubles ...
CImg< T > & resize_object3d(const float sx, const float sy=-100, const float sz=-100)
Resize 3d object.
static void save_empty_cimg(const char *const filename, const unsigned int nb, const unsigned int dx, const unsigned int dy=1, const unsigned int dz=1, const unsigned int dc=1)
Save empty (non-compressed) .cimg file with specified dimensions.
CImgList< T > get_insert(const CImgList< t > &list, const unsigned int pos=~0U, const bool is_shared=false) const
Insert a copy of the image list list into the current image list, starting from position pos ...
bool contains(const T &pixel, t &n, t &x) const
Test if one of the image list contains the specified referenced value.
unsigned int key(const unsigned int pos=0) const
Return one entry from the pressed keys history.
CImg< T > get_tensor() const
Resize image to become a symmetric tensor .
CImg< T > & draw_point(const CImg< t > &points, const tc *const color, const float opacity=1)
CImg< T > & draw_triangle(const int x0, const int y0, const int x1, const int y1, const int x2, const int y2, const CImg< tc > &texture, const int tx0, const int ty0, const int tx1, const int ty1, const int tx2, const int ty2, const float brightness0, const float brightness1, const float brightness2, const float opacity=1)
Draw a textured Gouraud-shaded 2d triangle.
CImg< _cimg_Tt > operator/(const t value) const
Division operator.
CImg< intT > get_select_graph(CImgDisplay &disp, const unsigned int plot_type=1, const unsigned int vertex_type=1, const char *const labelx=0, const double xmin=0, const double xmax=0, const char *const labely=0, const double ymin=0, const double ymax=0) const
Select sub-graph in a graph.
CImg< Tfloat > get_RGBtoxyY() const
Convert pixel values from RGB to xyY color spaces .
static CImgList< T > get_load(const char *const filename)
Load a list from a file .
CImg< Tfloat > get_RGBtoCMYK() const
Convert pixel values from RGB to CMYK color spaces .
CImg< T > & XYZtoxyY()
Convert pixel values from XYZ_709 to xyY color spaces.
const CImg< T > & display_object3d(CImgDisplay &disp, const CImg< tp > &vertices, const CImgList< tf > &primitives, const CImgList< tc > &colors, const to &opacities, const bool centering=true, const int render_static=4, const int render_motion=1, const bool is_double_sided=true, const float focale=700, const float light_x=0, const float light_y=0, const float light_z=-5e8f, const float specular_lightness=0.2f, const float specular_shininess=0.1f, const bool display_axes=true, float *const pose_matrix=0) const
Display object 3d in an interactive window.
static void _cimg_recursive_apply(T *data, const Tfloat filter[], const int N, const unsigned long off, const int order, const bool boundary_conditions)
CImg< T > & blur(const float sigma, const bool boundary_conditions=true, const bool is_gaussian=false)
Blur image isotropically.
CImg< Tfloat > get_LabtoXYZ() const
Convert pixel values from Lab to XYZ_709 color spaces .
CImg< T > get_equalize(const unsigned int nblevels, const T val_min, const T val_max) const
Equalize histogram of pixel values .
bool is_sameXC(const CImg< t > &img) const
Test if image width and spectrum are the same as that of another image.
CImg< Tfloat > get_HSItoRGB() const
Convert pixel values from HSI to RGB color spaces .
CImg< T > & object3dtoCImg3d(const CImgList< tp > &primitives, const CImgList< tc > &colors, const bool full_check=true)
Convert 3d object into a CImg3d representation .
CImg< T > & assign(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, const int value0, const int value1,...)
Construct image with specified size and initialize pixel values from a sequence of integers ...
CImg< T > & operator()(const unsigned int pos)
Return a reference to one image element of the list.
CImgList(const CImg< t1 > &img1, const CImg< t2 > &img2, const CImg< t3 > &img3, const CImg< t4 > &img4, const CImg< t5 > &img5, const bool is_shared=false)
Construct list from five images.
CImgDisplay & set_title(const char *const format,...)
Set title of the associated window.
CImg< T > & dilate(const unsigned int s)
Dilate image by a square structuring element of specified size.
CImg< floatT > get_object3dtoCImg3d(const CImgList< tp > &primitives, const CImgList< tc > &colors, const bool full_check=true) const
Convert 3d object into a CImg3d representation .
CImg< T > & set_tensor_at(const CImg< t > &ten, const unsigned int x=0, const unsigned int y=0, const unsigned int z=0)
Set tensor-valued pixel at specified position.
bool contains(const T &pixel, t &x) const
Test if pixel value is inside image bounds and get its X-coordinate.
bool operator==(const CImg< t > &img) const
Test if two images have the same size and values.
double atof(const char *const str)
Read value in a C-string.
const char * option(const char *const name, const int argc, const char *const *const argv, const char *const defaut, const char *const usage, const bool reset_static)
Return options specified on the command line.
CImgList< T > get_insert(const unsigned int n, const unsigned int pos=~0U) const
Insert n empty images img into the current image list, at position pos .
const CImg< T > & save_jpeg(std::FILE *const file, const unsigned int quality=100) const
Save image as a JPEG file .
CImg< T > get_autocrop(const CImg< t > &color, const char *const axes="zyx") const
Autocrop image region, regarding the specified background color .
const unsigned int keyMENU
Keycode for the MENU key (architecture-dependent).
CImg< Tfloat > get_atan2(const CImg< t > &img) const
Compute the arctangent2 of each pixel value .
bool contains(const CImg< T > &img, t &n) const
Test if the list contains the image 'img'.
CImg< T > get_fill(const T val0, const T val1, const T val2, const T val3) const
Fill sequentially all pixel values with specified values .
CImgList(const unsigned int n, const unsigned int width, const unsigned int height, const unsigned int depth, const unsigned int spectrum, const T val)
Construct list containing images of specified size, and initialize pixel values.
CImg< T > & fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5)
Fill sequentially all pixel values with specified values .
CImg< T > get_fill(const T val0, const T val1, const T val2, const T val3, const T val4) const
Fill sequentially all pixel values with specified values .
const CImg< T > & save_ffmpeg_external(const char *const filename, const char *const codec=0, const unsigned int fps=25, const unsigned int bitrate=2048) const
Save volumetric image as a video, using ffmpeg external binary.
CImg< T > get_RGBtoBayer() const
Convert RGB color image to a Bayer-coded scalar image .
CImg< T > & label(const CImg< t > &connectivity_mask, const Tfloat tolerance=0)
Label connected components .
Tdouble variance_mean(const unsigned int variance_method, t &mean) const
Return the variance as well as the average of the pixel values.
const unsigned int keyPADSUB
Keycode for the PADSUB key (architecture-dependent).
const CImg< T > & save_pnm(const char *const filename, const unsigned int bytes_per_pixel=0) const
Save image as a PNM file.
static bool is_saveable(const char *const filename)
Tell if an image list can be saved as one single file.
bool is_empty() const
Return true if list is empty.
bool is_sameXYC(const CImg< t > &img) const
Test if image width, height and spectrum are the same as that of another image.
bool is_sameYC(const CImg< t > &img) const
Test if image height and spectrum are the same as that of another image.
CImg< T > & laplacian()
Compute image laplacian.
static CImg< T > get_load_pandore(std::FILE *const file)
Load image from a PANDORE-5 file .
CImg< T > & RGBtoHSI()
Convert pixel values from RGB to HSI color spaces.
double grand()
Return a random variable following a gaussian distribution and a standard deviation of 1...
CImg< T > get_dilate(const unsigned int s) const
Dilate image by a square structuring element of specified size .
CImg< T > & sinc()
Compute the sinc of each pixel value.
CImg< T > get_shared_points(const unsigned int x0, const unsigned int x1, const unsigned int y0=0, const unsigned int z0=0, const unsigned int c0=0)
Return a shared-memory image referencing a range of pixels of the image instance. ...
CImg< T > & slice(const int z0)
Return specified image slice .
void sleep(const unsigned int milliseconds)
Sleep for a given numbers of milliseconds.
CImg< T > & draw_axis(const CImg< t > &values_x, const int y, const tc *const color, const float opacity=1, const unsigned int pattern=~0U, const unsigned int font_height=13, const bool allow_zero=true)
Draw a labeled horizontal axis.
CImg< T > & fillY(const unsigned int x, const unsigned int z, const unsigned int c, const double a0,...)
Fill pixel values along the Y-axis at a specified pixel position .
CImg< floatT > get_elevation3d(CImgList< tf > &primitives, CImgList< tc > &colors, const CImg< te > &elevation) const
Generate a 3d elevation of the image instance.
CImg(const CImg< t > &img, const bool is_shared)
Advanced copy constructor.
CImg< T > & erode(const unsigned int sx, const unsigned int sy, const unsigned int sz=1)
Erode image by a rectangular structuring element of specified size.
bool is_sameY(const CImgDisplay &disp) const
Test if image height is equal to specified value.
CImg< Tfloat > get_norm(const int norm_type=2) const
Compute L2-norm of each multi-valued pixel of the image instance .
const unsigned int key0
Keycode for the 0 key (architecture-dependent).
Tdouble magnitude(const int magnitude_type=2) const
Compute norm of the image, viewed as a matrix.
int strcasecmp(const char *const str1, const char *const str2)
Compare two C-strings, ignoring the case.
CImg< T > & load_yuv(const char *const filename, const unsigned int size_x, const unsigned int size_y=1, const unsigned int first_frame=0, const unsigned int last_frame=~0U, const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z')
Load image sequence from a YUV file.
bool is_sameXYZC(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c) const
Test if image width, height, depth and spectrum are equal to specified values.
int height() const
Return the number of image rows.
const_iterator end() const
Return iterator to one position after the last image of the list .
CImg< T > & diagonal()
Resize image to become a diagonal matrix.
CImg< T > & max(const T val)
Pointwise max operator between instance image and a value.
static CImg< T > vector(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4, const T &a5, const T &a6, const T &a7, const T &a8, const T &a9, const T &a10, const T &a11, const T &a12, const T &a13, const T &a14)
Return a 1x15 image containing specified values.
const CImg< T > & save_png(std::FILE *const file, const unsigned int bytes_per_pixel=0) const
Save image as a PNG file .
const CImg< T > & display(const char *const title=0, const bool display_info=true, unsigned int *const XYZ=0) const
Display image into an interactive window.
CImg< Tfloat > get_distance(const T value, const unsigned int metric=2) const
Compute distance to a specified value .
const unsigned int keyARROWLEFT
Keycode for the ARROWLEFT key (architecture-dependent).
CImg< T > & histogram(const unsigned int nb_levels)
Compute the histogram of pixel values .
CImg< T > & channel(const int c0)
Return specified image channel .
CImg< T > & operator-=(const CImg< t > &img)
In-place substraction operator.
const CImg< T > & save_yuv(std::FILE *const file, const bool is_rgb=true) const
Save image as a .yuv video file .
CImg< T > & assign(const t *const values, const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, const bool is_shared)
Construct image with specified size and initialize pixel values from a memory buffer ...
CImg< floatT > get_object3dtoCImg3d(const CImgList< tp > &primitives, const bool full_check=true) const
Convert 3d object into a CImg3d representation .
const unsigned int keyPAD0
Keycode for the PAD0 key (architecture-dependent).
CImg(const t *const values, const unsigned int size_x, const unsigned int size_y=1, const unsigned int size_z=1, const unsigned int size_c=1, const bool is_shared=false)
Construct image with specified size and initialize pixel values from a memory buffer.
static int screen_height()
Return height of the screen (current resolution along the Y-axis).
static void wait(CImgDisplay &disp1, CImgDisplay &disp2, CImgDisplay &disp3, CImgDisplay &disp4, CImgDisplay &disp5, CImgDisplay &disp6, CImgDisplay &disp7, CImgDisplay &disp8)
Wait for any event occuring either on the display disp1, disp2, disp3, disp4, ... disp8...
CImg< T > & load_ascii(std::FILE *const file)
Load image from an ascii file .
bool is_sameZ(const unsigned int size_z) const
Test if image depth is equal to specified value.
const T & max_min(t &min_val) const
Return a reference to the minimum pixel value of the instance list and return the minimum value as we...
int dialog(const char *const title, const char *const msg, const char *const button1_label="OK", const char *const button2_label=0, const char *const button3_label=0, const char *const button4_label=0, const char *const button5_label=0, const char *const button6_label=0, const bool centering=false)
Display a simple dialog box, and wait for the user's response .
CImg< T > get_ror(const CImg< t > &img) const
Compute the bitwise right rotation of each pixel value .
bool contains(const T &pixel, t &x, t &y, t &z, t &c) const
Test if pixel value is inside image bounds and get its X,Y,Z and C-coordinates.
CImg< _cimg_Tt > get_cross(const CImg< t > &img) const
Compute the cross product between two 1x3 images, viewed as 3d vectors .
CImg< T > & sort(CImg< t > &permutations, const bool is_increasing=true)
Sort pixel values and get sorting permutations.
CImg< T > & draw_image(const int x0, const int y0, const int z0, const int c0, const CImg< T > &sprite, const float opacity=1)
Draw an image .
Represent a list of images CImg.
const unsigned int keyF4
Keycode for the F4 key (architecture-dependent).
const unsigned int keyPADMUL
Keycode for the PADMUL key (architecture-dependent).
static CImg< T > get_load_pnm(const char *const filename)
Load image from a PNM file .
CImgDisplay & resize(const CImgDisplay &disp, const bool force_redraw=true)
Resize display to the size of another CImgDisplay instance.
T & max()
Return a reference to the maximum pixel value of the instance list.
const CImg< T > & save_rgb(std::FILE *const file) const
Save image as a RGB file .
T & at(const int offset, const T out_value)
Access to a pixel value at a specified offset, using Dirichlet boundary conditions.
CImg< T > & resize_doubleXY()
Resize image to double-size, using the Scale2X algorithm.
CImg< T > get_shared_slices(const unsigned int z0, const unsigned int z1, const unsigned int c0=0)
Return a shared memory image referencing a range of slices of the image instance. ...
CImg< T > & operator++()
In-place increment operator (prefix).
T kth_smallest(const unsigned int k) const
Return the kth smallest pixel value.
CImg< T > & assign(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, const char *const values, const bool repeat_values)
Construct image with specified size and initialize pixel values from a value string ...
CImgList< T > & insert(const unsigned int n, const CImg< t > &img, const unsigned int pos=~0U, const bool is_shared=false)
Insert n copies of the image img into the current image list, at position pos.
CImg< T > & operator=(const CImg< T > &img)
Copy an image into the current image instance .
CImg< T > & draw_line(const int x0, const int y0, const int z0, const int x1, const int y1, const int z1, const tc *const color, const float opacity=1, const unsigned int pattern=~0U, const bool init_hatch=true)
Draw a 3d line.
CImg< T > & pow(const char *const expression)
Raise each pixel value to a power, specified from an expression.
static CImgList< T > get_load_yuv(std::FILE *const file, const unsigned int size_x, const unsigned int size_y=1, const unsigned int first_frame=0, const unsigned int last_frame=~0U, const unsigned int step_frame=1, const bool yuv2rgb=true)
Load a list from an image sequence YUV file .
double crand()
Return a random variable between [-1,1] with respect to an uniform distribution.
CImg< Tfloat > get_CMYKtoCMY() const
Convert pixel values from CMYK to CMY color spaces .
static CImgList< T > get_load_cimg(const char *const filename)
Load a list from a .cimg file .
CImg< Tdouble > get_stats(const unsigned int variance_method=1) const
Compute statistics vector from the pixel values.
CImg< _cimg_Tt > operator-(const CImg< t > &img) const
Substraction operator.
CImg< T > & rotate(const float angle, const float cx, const float cy, const float zoom, const unsigned int interpolation=1, const unsigned int boundary=3)
Rotate image with arbitrary angle, around a center point.
static CImg< T > vector(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4, const T &a5, const T &a6, const T &a7, const T &a8)
Return a 1x9 image containing specified values.
bool contains(const T &pixel, t &n, t &x, t &y, t &z, t &c) const
Test if one image of the list contains the specified referenced value.
bool is_sameXYZC(const CImg< t > &img) const
Test if image width, height, depth and spectrum are the same as that of another image.
static CImg< T > matrix(const T &a0)
Return a 1x1 matrix containing specified coefficients.
CImg< T > & select(const char *const title, const unsigned int feature_type=2, unsigned int *const XYZ=0)
Simple interface to select a shape from an image .
bool endianness()
Return the endianness of the current architecture.
CImgDisplay & assign(const CImgDisplay &disp)
Construct a display as a copy of another one .
CImg< T > & operator--()
In-place decrement operator (prefix).
static CImg< T > vector(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4, const T &a5, const T &a6, const T &a7, const T &a8, const T &a9, const T &a10, const T &a11, const T &a12, const T &a13, const T &a14, const T &a15)
Return a 1x16 image containing specified values.
CImg< T > & draw_mandelbrot(const int x0, const int y0, const int x1, const int y1, const CImg< tc > &colormap, const float opacity=1, const double z0r=-2, const double z0i=-2, const double z1r=2, const double z1i=2, const unsigned int iteration_max=255, const bool is_normalized_iteration=false, const bool is_julia_set=false, const double param_r=0, const double param_i=0)
Draw a quadratic Mandelbrot or Julia 2d fractal.
static CImg< T > get_load_analyze(const char *const filename, float *const voxel_size=0)
Load image from an ANALYZE7.5/NIFTI file .
CImg< T > & operator%=(const CImg< t > &img)
In-place modulo operator.
T & min_max(t &max_val)
Return a reference to the minimum pixel value as well as the maximum pixel value. ...
bool containsNXYZC(const int n, const int x=0, const int y=0, const int z=0, const int c=0) const
Test if list contains one particular pixel location.
CImg< T > & draw_mandelbrot(const CImg< tc > &colormap, const float opacity=1, const double z0r=-2, const double z0i=-2, const double z1r=2, const double z1i=2, const unsigned int iteration_max=255, const bool is_normalized_iteration=false, const bool is_julia_set=false, const double param_r=0, const double param_i=0)
Draw a quadratic Mandelbrot or Julia 2d fractal .
CImg< T > & load_cimg(std::FILE *const file, const char axis='z', const float align=0)
Load image from a .cimg[z] file .
CImg< Tfloat > operator*(const char *const expression) const
Multiplication operator.
const char * imagemagick_path(const char *const user_path=0, const bool reinit_path=false)
Get/set path to the Program Files/ directory (Windows only).
CImg< Tfloat > get_XYZtoxyY() const
Convert pixel values from XYZ_709 to xyY color spaces .
bool is_sameZ(const CImg< t > &img) const
Test if image depth is equal to specified value.
CImg< T > & load_png(std::FILE *const file)
Load image from a PNG file .
CImg< T > & fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, const T val7, const T val8, const T val9, const T val10, const T val11, const T val12)
Fill sequentially all pixel values with specified values .
CImgList< T > operator+() const
Return a non-shared copy of a list.
CImg< T > & blur_anisotropic(const CImg< t > &G, const float amplitude=60, const float dl=0.8f, const float da=30, const float gauss_prec=2, const unsigned int interpolation_type=0, const bool is_fast_approx=1)
Blur image anisotropically, directed by a field of diffusion tensors.
T & atNXYZC(const int pos, const int x, const int y, const int z, const int c)
Access to pixel value with Neumann boundary conditions.
CImg< _cimg_Ttfloat > get_correlate(const CImg< t > &mask, const unsigned int boundary_conditions=1, const bool is_normalized=false) const
Correlate image by a mask .
unsigned long size() const
Return the total number of pixel values.
CImg< T > & draw_axes(const float x0, const float x1, const float y0, const float y1, const tc *const color, const float opacity=1, const int subdivisionx=-60, const int subdivisiony=-60, const float precisionx=0, const float precisiony=0, const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U, const unsigned int font_height=13)
Draw labeled horizontal and vertical axes .
CImg< T > & draw_ellipse(const int x0, const int y0, const CImg< t > &tensor, const tc *const color, const float opacity, const unsigned int pattern)
Draw an outlined 2d ellipse .
CImg< T > & load_ffmpeg(const char *const filename, const unsigned int first_frame=0, const unsigned int last_frame=~0U, const unsigned int step_frame=1, const bool pixel_format=true, const bool resume=false, const char axis='z', const float align=0)
Load image sequence using FFMPEG av's libraries.
static CImg< T > get_load_raw(std::FILE *const file, const unsigned int size_x=0, const unsigned int size_y=1, const unsigned int size_z=1, const unsigned int size_c=1, const bool is_multiplexed=false, const bool invert_endianness=false, const unsigned long offset=0)
Load image from a raw binary file .
CImg< Tfloat > get_tanh() const
Compute the hyperbolic tangent of each pixel value .
CImgList< T > & load_yuv(const char *const filename, const unsigned int size_x, const unsigned int size_y, const unsigned int first_frame=0, const unsigned int last_frame=~0U, const unsigned int step_frame=1, const bool yuv2rgb=true)
Load a list from a YUV image sequence file.
Allow to create windows, display images on them and manage user events (keyboard, mouse and windows e...
CImg< _cimg_Ttfloat > get_solve(const CImg< t > &A) const
Solve a system of linear equations .
T atX(const int x, const int y, const int z, const int c, const T out_value) const
Access to a pixel value, using Dirichlet boundary conditions for the X-coordinate ...
CImg< T > & shift(const int delta_x, const int delta_y=0, const int delta_z=0, const int delta_c=0, const int boundary_conditions=0)
Shift image content.
CImg< T > get_rol(const unsigned int n=1) const
Compute the bitwise left rotation of each pixel value .
CImgList< T > & crop_font()
Crop font along the X-axis.
CImg< T > & distance_dijkstra(const T value, const CImg< t > &metric, const bool is_high_connectivity=false)
Compute distance map to a specified value, according to a custom metric (use dijkstra algorithm)...
Tfloat cubic_atXYZ(const float fx, const float fy, const float fz, const int c, const Tfloat min_value, const Tfloat max_value) const
Return damped pixel value, using cubic interpolation and Neumann boundary conditions for the XYZ-coor...
static CImg< T > matrix(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4, const T &a5, const T &a6, const T &a7, const T &a8)
Return a 3x3 matrix containing specified coefficients.
CImgList< T > & load_ffmpeg(const char *const filename, const unsigned int first_frame=0, const unsigned int last_frame=~0U, const unsigned int step_frame=1, const bool pixel_format=true, const bool resume=false)
Load an image from a video file, using ffmpeg libraries.
CImg< T > get_quantize(const unsigned int n, const bool keep_range=true) const
Uniformly quantize pixel values .
CImg< T > get_append(const CImg< T > &img, const char axis='x', const float align=0) const
Append two images along specified axis .
CImg< T > & draw_triangle(const int x0, const int y0, const float z0, const int x1, const int y1, const float z1, const int x2, const int y2, const float z2, const CImg< tc > &texture, const int tx0, const int ty0, const int tx1, const int ty1, const int tx2, const int ty2, const float brightness0, const float brightness1, const float brightness2, const float opacity=1)
Draw a textured Gouraud-shaded 2d triangle, with perspective correction .
int fclose(std::FILE *file)
Close a file.
void fempty(std::FILE *const file, const char *const filename)
Create an empty file.
CImg< Tfloat > get_sign() const
Compute the sign of each pixel value .
CImg< Tfloat > get_blur(const float sigma_x, const float sigma_y, const float sigma_z, const bool boundary_conditions=true, const bool is_gaussian=false) const
Blur image .
T & atN(const int pos, const int x, const int y, const int z, const int c, const T out_value)
Access to pixel value with Dirichlet boundary conditions for the first coordinate (pos)...
const CImg< T > & save_bmp(const char *const filename) const
Save image as a BMP file.
CImgList< T > & split(const char axis, const int nb=0)
Return a list where each image has been split along the specified axis.
CImg(const CImg< T > &img, const bool is_shared)
Advanced copy constructor .
CImg< Tfloat > get_pow(const CImg< t > &img) const
Raise each pixel value to a power, pointwisely specified from another image .
CImg< _cimg_Tt > operator+(const t value) const
Addition operator.
int spectrum() const
Return the number of image channels.
CImg< T > & YUVtoRGB()
Convert pixel values from YUV to RGB color spaces.
CImgList< T > & operator,(const CImgList< t > &list)
Return a copy of the list instance, where all elements of input list list have been inserted at the e...
CImg< T > & mirror(const char *const axes)
Mirror image content along specified axes.
CImg< Tuchar > get_HSVtoRGB() const
Convert pixel values from HSV to RGB color spaces .
bool operator==(const char *const expression) const
Test if all pixel values of an image follow a specified expression.
CImg< T > get_projections2d(const unsigned int x0, const unsigned int y0, const unsigned int z0) const
Generate a 2d representation of a 3d image, with XY,XZ and YZ views.
CImgDisplay & toggle_fullscreen(const bool force_redraw=true)
Toggle fullscreen mode.
CImg< T > & operator*=(const CImg< t > &img)
In-place multiplication operator.
const unsigned int keyCAPSLOCK
Keycode for the CAPSLOCK key (architecture-dependent).
static void wait(CImgDisplay &disp1)
Wait for any event occuring on the display disp1.
CImg< T > & load_parrec(const char *const filename, const char axis='c', const float align=0)
Load image from a PAR-REC (Philips) file.
Tfloat linear_atXYZC(const float fx, const float fy=0, const float fz=0, const float fc=0) const
Return pixel value, using linear interpolation and Neumann boundary conditions for all X...
CImgDisplay & operator=(const CImg< t > &img)
Display image on associated window.
static CImgList< T > get_load_cimg(std::FILE *const file, const unsigned int n0, const unsigned int n1, const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int c0, const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int c1)
Load a sub-image list from a (non compressed) .cimg file .
const CImg< T > & display_object3d(const char *const title, const CImg< tp > &vertices, const CImgList< tf > &primitives, const CImgList< tc > &colors, const bool centering=true, const int render_static=4, const int render_motion=1, const bool is_double_sided=true, const float focale=700, const float light_x=0, const float light_y=0, const float light_z=-5e8f, const float specular_lightness=0.2f, const float specular_shininess=0.1f, const bool display_axes=true, float *const pose_matrix=0) const
Display object 3d in an interactive window .
CImg< T > & load_tiff(const char *const filename, const unsigned int first_frame=0, const unsigned int last_frame=~0U, const unsigned int step_frame=1)
Load image from a TIFF file.
static CImg< T > matrix(const T &a0, const T &a1, const T &a2, const T &a3)
Return a 2x2 matrix containing specified coefficients.
CImg< T > & draw_triangle(const int x0, const int y0, const int x1, const int y1, const int x2, const int y2, const tc *const color, const float brightness0, const float brightness1, const float brightness2, const float opacity=1)
Draw a Gouraud-shaded 2d triangle.
const unsigned int keyENTER
Keycode for the ENTER key (architecture-dependent).
const unsigned int keyF6
Keycode for the F6 key (architecture-dependent).
CImg< T > & draw_gaussian(const float xc, const float yc, const float sigma, const tc *const color, const float opacity=1)
Draw a 2d gaussian function .
static CImg< T > get_load_cimg(std::FILE *const file, const char axis='z', const float align=0)
Load image from a .cimg[z] file .
T & atNX(const int pos, const int x, const int y, const int z, const int c, const T out_value)
Access to pixel value with Dirichlet boundary conditions for the 2 first coordinates (pos...
CImgDisplay & resize(const bool force_redraw=true)
Resize display to the size of the associated window.
CImg< T > get_round(const double y=1, const unsigned int rounding_type=0) const
Round pixel values .
CImgDisplay & assign(const unsigned int width, const unsigned int height, const char *const title=0, const unsigned int normalization=3, const bool is_fullscreen=false, const bool is_closed=false)
Construct a display with specified dimensions .
CImg< T > & normalize(const T min_value, const T max_value)
Linearly normalize pixel values.
_cimg_iskey_def(ESC)
Return true if the ESC key is being pressed on the associated window, false otherwise.
CImg< T > & draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float angle, const tc *const color, const float opacity=1)
Draw a filled 2d ellipse.
const CImgList< T > & save_cimg(std::FILE *const file, const unsigned int n0, const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int c0) const
Insert the image instance into into an existing .cimg file, at specified coordinates.
CImg< T > & draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float angle, const tc *const color, const float opacity, const unsigned int pattern)
Draw an outlined 2d ellipse.
CImg< T > & invert_endianness()
Invert endianness of all pixel values.
static const CImg< Tuchar > & flag_LUT256()
Return colormap "flag", containing 256 colors entries in RGB.
T & atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0)
Return pixel value with Neumann boundary conditions for the first coordinate (pos).
bool is_sameXYC(const unsigned int size_x, const unsigned int size_y, const unsigned int size_c) const
Test if image width, height and spectrum are equal to specified values.
CImg< T > & fill(const T val0, const T val1, const T val2)
Fill sequentially all pixel values with specified values .
const CImg< T > & save_bmp(std::FILE *const file) const
Save image as a BMP file .
CImg< T > get_slice(const int z0) const
Return specified image slice.
Tfloat cubic_atX(const float fx, const int y=0, const int z=0, const int c=0) const
Return pixel value, using cubic interpolation and Neumann boundary conditions for the X-coordinate...
CImg< T > & load_bmp(const char *const filename)
Load image from a BMP file.
static CImg< floatT > sphere3d(CImgList< tf > &primitives, const float radius=50, const unsigned int subdivisions=3)
Generate a 3d sphere.
CImg< Tuchar > get_RGBtoYCbCr() const
Convert pixel values from RGB to YCbCr color spaces .
const CImg< T > & save_yuv(const char *const filename, const bool is_rgb=true) const
Save image as a .yuv video file.
CImg< T > & load_cimg(const char *const filename, const char axis='z', const float align=0)
Load image from a .cimg[z] file.
CImg< T > & fillX(const unsigned int y, const unsigned int z, const unsigned int c, const double a0,...)
Fill pixel values along the X-axis at a specified pixel position .
CImgDisplay & set_fullscreen(const bool is_fullscreen, const bool force_redraw=true)
Enable or disable fullscreen mode.
CImg< T > & deriche(const float sigma, const int order=0, const char axis='x', const bool boundary_conditions=true)
Apply recursive Deriche filter.
CImgList< T > & assign(const unsigned int n)
Construct list containing empty images .
const CImgList< T > & print(const char *const title=0, const bool display_stats=true) const
Print informations about the list on the standard output.
CImgList< Tfloat > get_symmetric_eigen() const
Compute eigenvalues and eigenvectors of the instance image, viewed as a symmetric matrix...
bool is_closed() const
Return true if display is closed (i.e. not visible on the screen), false otherwise.
CImgList< T > get_reverse_object3d() const
Reverse primitives orientations of a 3d object .
CImgDisplay(const CImgDisplay &disp)
Construct a display as a copy of an existing one.
CImg< T > & draw_text(const int x0, const int y0, const char *const text, const int, const tc *const background_color, const float opacity, const CImgList< t > &font,...)
Draw a text string .
CImg< T > & operator-=(const char *const expression)
In-place substraction operator.
CImgList(const unsigned int n, const unsigned int width, const unsigned int height, const unsigned int depth, const unsigned int spectrum, const int val0, const int val1,...)
Construct list containing images of specified size, and initialize pixel values from a sequence of in...
static CImg< T > identity_matrix(const unsigned int N)
Return a NxN identity matrix.
static CImg< T > vector(const T &a0, const T &a1)
Return a 1x2 image containing specified values.
CImg< T > & rotate(const float angle, const unsigned int interpolation=1, const unsigned int boundary=0)
Rotate image with arbitrary angle.
static CImg< T > get_load(const char *const filename)
Load image from a file .
CImg< T > & convolve(const CImg< t > &mask, const unsigned int boundary_conditions=1, const bool is_normalized=false)
Convolve image by a mask.
const CImg< T > & save_pandore(const char *const filename, const unsigned int colorspace=0) const
Save image as a Pandore-5 file.
const unsigned int key9
Keycode for the 9 key (architecture-dependent).
CImg< T > get_matrix_at(const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) const
Get (square) matrix-valued pixel located at specified position.
CImgDisplay & render(const CImg< T > &img)
Render image into internal display buffer.
static CImg< floatT > elevation3d(CImgList< tf > &primitives, const tfunc &func, const float x0, const float y0, const float x1, const float y1, const int size_x=256, const int size_y=256)
Compute 3d elevation of a function as a 3d object.
CImg< Tfloat > get_RGBtoXYZ() const
Convert pixel values from RGB to XYZ_709 color spaces .
CImg< T > & operator%=(const char *const expression)
In-place modulo operator.
CImg< Tfloat > get_shift_object3d() const
Shift 3d object's vertices, so that it becomes centered .
const CImg< T > & save_cimg(std::FILE *const file, const unsigned int n0, const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int c0) const
Save image as a sub-image into an existing .cimg file .
CImg< Tfloat > get_shift_object3d(const float tx, const float ty=0, const float tz=0) const
Shift 3d object's vertices .
CImg< T > resize_object3d()
Resize 3d object to unit size.
static CImg< T > get_load_rgba(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1)
Load image from a RGBA file .
T round(const T x, const double y=1, const int rounding_type=0)
Return rounded value.
T atNXYZC(const int pos, const int x, const int y, const int z, const int c) const
Access to pixel value with Neumann boundary conditions .
CImg< T > & acos()
Compute the arccosine of each pixel value.
CImgList< T > & operator=(const CImgList< T > &list)
Construct list from another list .
CImg< T > & fill(const char *const expression, const bool repeat_flag)
Fill sequentially pixel values according to a given expression.
static CImg< T > get_load_ascii(const char *const filename)
Load image from an ascii file .
CImgDisplay & wait()
Wait for any user event occuring on the current display.
const unsigned int keyF1
Keycode for the F1 key (architecture-dependent).
const unsigned int keyPADDIV
Keycode for the PADDDIV key (architecture-dependent).
CImg< T > & discard(const T value)
Discard specified value in the image buffer.
CImg< T > & resize(const CImg< t > &src, const int interpolation_type=1, const unsigned int boundary_conditions=0, const float centering_x=0, const float centering_y=0, const float centering_z=0, const float centering_c=0)
Resize image to dimensions of another image.
static const CImg< Tuchar > & lines_LUT256()
Return colormap "lines", containing 256 colors entries in RGB.
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 T val7, const T val8, const T val9) const
Fill sequentially all pixel values with specified values .
CImg< T > & load_cimg(std::FILE *const file, const unsigned int n0, const unsigned int n1, const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int c0, const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int c1, const char axis='z', const float align=0)
Load sub-images of a .cimg file .
const CImgList< T > & save_cimg(std::FILE *file, const bool is_compressed=false) const
Save list into a .cimg file.
bool contains(const CImg< T > &img) const
Test if the list contains the image img.
CImg< T > & draw_point(const int x0, const int y0, const tc *const color, const float opacity=1)
Draw a 2d point .
CImgDisplay & set_key(const unsigned int keycode, const bool is_pressed=true)
Simulate a keyboard press/release event.
const unsigned int keyC
Keycode for the C key (architecture-dependent).
int width() const
Return display width.
static CImgList< T > get_load_ffmpeg_external(const char *const filename)
Load an image from a video file using the external tool 'ffmpeg' .
const unsigned int keyJ
Keycode for the J key (architecture-dependent).
static CImg< floatT > box3d(CImgList< tf > &primitives, const float size_x=200, const float size_y=100, const float size_z=100)
Generate a 3d box object.
bool is_sameNXYZC(const unsigned int n, const unsigned int dx, const unsigned int dy, const unsigned int dz, const unsigned int dc) const
Test if list dimensions match specified arguments.
CImg< T > operator|(const t value) const
Bitwise OR operator.
CImg< T > & operator=(const T value)
Assign a value to all image pixels.
CImg< Tfloat > get_xyYtoXYZ() const
Convert pixel values from xyY pixels to XYZ_709 color spaces .
CImg< T > & draw_line(const CImg< t > &points, const tc *const color, const float opacity=1, const unsigned int pattern=~0U, const bool init_hatch=true)
Draw a set of consecutive lines.
const CImg< T > & save_ascii(std::FILE *const file) const
Save image as an ascii file .
CImg< t > get_map(const CImg< t > &colormap, const unsigned int boundary_conditions=0) const
Map predefined colormap on the scalar (indexed) image instance .
CImg< T > get_tensor_at(const unsigned int x, const unsigned int y=0, const unsigned int z=0) const
Get tensor-valued pixel located at specified position.
static CImgList< T > get_load_cimg(std::FILE *const file)
Load a list from a .cimg file .
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 T val7, const T val8) const
Fill sequentially all pixel values with specified values .
T at(const int offset) const
Access to a pixel value at a specified offset, using Neumann boundary conditions .
CImg< T > & pseudoinvert()
Compute the Moore-Penrose pseudo-inverse of the instance image, viewed as a matrix.
CImg< T > & set_linear_atXYZ(const T &value, const float fx, const float fy=0, const float fz=0, const int c=0, const bool is_added=false)
Set pixel value, using linear interpolation for the X,Y and Z-coordinates.
const unsigned int keyI
Keycode for the I key (architecture-dependent).
T atXY(const int x, const int y, const int z=0, const int c=0) const
Access to a pixel value, using Neumann boundary conditions for the X and Y-coordinates ...
static CImg< T > vector(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4, const T &a5, const T &a6, const T &a7, const T &a8, const T &a9)
Return a 1x10 image containing specified values.
CImgList< T > operator<(const char axis) const
Split image along specified axis.
static CImg< T > get_load_exr(const char *const filename)
Load image from a EXR file .
static void wait(CImgDisplay &disp1, CImgDisplay &disp2, CImgDisplay &disp3, CImgDisplay &disp4, CImgDisplay &disp5, CImgDisplay &disp6)
Wait for any event occuring either on the display disp1, disp2, disp3, disp4, ... disp6...
const unsigned int keyH
Keycode for the H key (architecture-dependent).
CImg< T > & blur_median(const unsigned int n, const float threshold=0)
Blur image with the median filter.
CImg< T > & warp(const CImg< t > &warp, const bool is_relative=false, const unsigned int interpolation=1, const unsigned int boundary_conditions=0)
Warp image content by a warping field.
static void save_empty_cimg(const char *const filename, const unsigned int dx, const unsigned int dy=1, const unsigned int dz=1, const unsigned int dc=1)
Save blank image as a .cimg file.
CImg< T > & fill(const CImg< t > &values, const bool repeat_values=true)
Fill sequentially pixel values according to the values found in another image.
CImg< T > operator--(int)
In-place decrement operator (postfix).
const char * medcon_path(const char *const user_path=0, const bool reinit_path=false)
Get/set path to the XMedcon's medcon binary.
CImgList< T > & load_gif_external(const char *const filename)
Load gif file, using ImageMagick or GraphicsMagick's external tools.
int height() const
Return display height.
T atXYZ(const int x, const int y, const int z, const int c=0) const
Access to a pixel value, using Neumann boundary conditions for the X,Y and Z-coordinates ...
CImg< T > & dijkstra(const unsigned int starting_node, const unsigned int ending_node=~0U)
Return minimal path in a graph, using the Dijkstra algorithm.
static CImg< T > diagonal(const T &a0, const T &a1, const T &a2)
Return a 3x3 diagonal matrix containing specified coefficients.
CImg< T > & crop(const int x0, const int y0, const int z0, const int c0, const int x1, const int y1, const int z1, const int c1, const bool boundary_conditions=false)
Crop image region.
const CImg< T > & save_pfm(const char *const filename) const
Save image as a PFM file.
bool is_sameN(const CImgList< t > &list) const
Test if number of image elements is equal between two images lists.
CImg< Tfloat > get_sqrt() const
Compute the square root of each pixel value .
CImg< T > & mul(const CImg< t > &img)
In-place pointwise multiplication.
CImg< T > & shift_object3d()
Shift 3d object's vertices, so that it becomes centered.
static CImgList< T > get_load_yuv(const char *const filename, const unsigned int size_x, const unsigned int size_y=1, const unsigned int first_frame=0, const unsigned int last_frame=~0U, const unsigned int step_frame=1, const bool yuv2rgb=true)
Load a list from a YUV image sequence file .
static CImg< floatT > ellipsoid3d(CImgList< tf > &primitives, const CImg< t > &tensor, const unsigned int subdivisions=3)
Generate a 3d ellipsoid.
CImg< T > & fillZ(const unsigned int x, const unsigned int y, const unsigned int c, const int a0,...)
Fill pixel values along the Z-axis at a specified pixel position.
CImg< T > get_shared_channel(const unsigned int c0)
Return a shared-memory image referencing one channel of the image instance.
CImg< T > & append(const CImg< t > &img, const char axis='x', const float align=0)
Append two images along specified axis.
CImg< T > get_CImg3dtoobject3d(CImgList< tp > &primitives, CImgList< tc > &colors, CImgList< to > &opacities, const bool full_check=true) const
Convert CImg3d representation into a 3d object .
CImg< T > & cross(const CImg< t > &img)
Compute the cross product between two 1x3 images, viewed as 3d vectors.
CImg< T > & tensor()
Resize image to become a symmetric tensor.
CImg< T > & blur_anisotropic(const float amplitude, const float sharpness=0.7f, const float anisotropy=0.6f, const float alpha=0.6f, const float sigma=1.1f, const float dl=0.8f, const float da=30, const float gauss_prec=2, const unsigned int interpolation_type=0, const bool is_fast_approx=true)
Blur image anisotropically, in an edge-preserving way.
CImg< T > & diffusion_tensors(const float sharpness=0.7f, const float anisotropy=0.6f, const float alpha=0.6f, const float sigma=1.1f, const bool is_sqrt=false)
Compute field of diffusion tensors for edge-preserving smoothing.
T & atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0)
Access to pixel value with Neumann boundary conditions for the 2 first coordinates (pos...
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 T val7, const T val8, const T val9, const T val10, const T val11, const T val12, const T val13, const T val14) const
Fill sequentially all pixel values with specified values .
CImg< T > & load_dlm(const char *const filename)
Load image from a DLM file.
CImg< T > get_shared()
Return a shared-memory version of the image instance.
CImg< T > & load_gif_external(const char *const filename, const char axis='z', const float align=0)
Load gif file, using Imagemagick or GraphicsMagicks's external tools.
CImgList< _cimg_Tt > operator,(const CImg< t > &img) const
Construct an image list from two images.
unsigned int released_key(const unsigned int pos=0) const
Return one entry from the released keys history.
bool contains(const T &pixel) const
Test if one of the image list contains the specified referenced value.
CImg< T > & rol(const CImg< t > &img)
Compute the bitwise left rotation of each pixel value.
const unsigned int key4
Keycode for the 4 key (architecture-dependent).
CImg< Tfloat > get_distance_dijkstra(const T value, const CImg< t > &metric, const bool is_high_connectivity=false) const
Compute distance map to a specified value, according to a custom metric (use dijkstra algorithm)...
CImg< T > & fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, const T val7, const T val8, const T val9, const T val10, const T val11, const T val12, const T val13, const T val14, const T val15)
Fill sequentially all pixel values with specified values .
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 T val7, const T val8, const T val9, const T val10, const T val11, const T val12, const T val13, const T val14, const T val15) const
Fill sequentially all pixel values with specified values .
static void FFT(CImg< T > &real, CImg< T > &imag, const bool is_invert=false, const unsigned int nb_threads=0)
Compute n-d Fast Fourier Transform.
const CImg< T > & save_inr(const char *const filename, const float *const voxel_size=0) const
Save image as an INRIMAGE-4 file.
const unsigned int keyN
Keycode for the N key (architecture-dependent).
static CImg< T > get_load_rgb(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1)
Load image from a RGB file .
Tfloat linear_atX(const float fx, const int y, const int z, const int c, const T out_value) const
Return pixel value, using linear interpolation and Dirichlet boundary conditions for the X-coordinate...
static CImg< T > get_load_yuv(std::FILE *const file, const unsigned int size_x, const unsigned int size_y=1, const unsigned int first_frame=0, const unsigned int last_frame=~0U, const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z')
Load image sequence from a YUV file .
CImg< T > & exp()
Compute the exponential of each pixel value.
CImg< Tfloat > get_RGBtoHSL() const
Convert pixel values from RGB to HSL color spaces .
const CImg< T > & save_pnk(const char *const filename) const
Save image as a PNK file.
CImg< _cimg_Tt > get_mul(const CImg< t > &img) const
In-place pointwise multiplication .
const unsigned int keyPAGEDOWN
Keycode for the PAGEDOWN key (architecture-dependent).
unsigned long tic()
Start tic/toc timer for time measurement between code instructions.
static CImg< T > vector(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4, const T &a5, const T &a6, const T &a7, const T &a8, const T &a9, const T &a10, const T &a11)
Return a 1x12 image containing specified values.
double eval(const char *const expression, const double x=0, const double y=0, const double z=0, const double c=0)
Evaluate math expression.
CImg< T > & assign(const T *const values, const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, const bool is_shared)
Construct image with specified size and initialize pixel values from a memory buffer ...
CImg< Tuchar > get_YCbCrtoRGB() const
Convert pixel values from RGB to YCbCr color spaces .
CImg< T > & displacement(const CImg< T > &source, const float smoothness=0.1f, const float precision=5.0f, const unsigned int nb_scales=0, const unsigned int iteration_max=10000, const bool is_backward=false)
Estimate displacement field between two images.
const unsigned int keyBACKSPACE
Keycode for the BACKSPACE key (architecture-dependent).
CImg< T > & append(const CImg< T > &img, const char axis='x', const float align=0)
Append two images along specified axis .
T & front()
Return a reference to the first pixel value.
const unsigned int keyX
Keycode for the X key (architecture-dependent).
CImg< T > & assign(const CImg< t > &img, const bool is_shared)
In-place version of the advanced copy constructor.
CImg< T > & sharpen(const float amplitude, const bool sharpen_type=false, const float edge=1, const float alpha=0, const float sigma=0)
Sharpen image.
CImgList< Tfloat > get_FFT(const bool invert=false) const
Compute a n-d Fast Fourier Transform .
bool contains(const T &pixel, t &n) const
Test if one of the image list contains the specified referenced value.
CImg< T > get_blur_median(const unsigned int n, const float threshold=0) const
Blur image with the median filter .
bool is_nan() const
Test if image instance contains a 'nan' value.
CImgList(const CImgList< T > &list)
Construct list copy .
CImgList< T > & load_yuv(std::FILE *const file, const unsigned int size_x, const unsigned int size_y, const unsigned int first_frame=0, const unsigned int last_frame=~0U, const unsigned int step_frame=1, const bool yuv2rgb=true)
Load a list from an image sequence YUV file .
const CImg< T > & save_gzip_external(const char *const filename) const
Save image using gzip external binary.
bool is_sameXC(const unsigned int size_x, const unsigned int size_c) const
Test if image width and spectrum are equal to specified values.
const CImg< T > & save_cimg(const char *const filename, const bool is_compressed=false) const
Save image as a .cimg file.
CImg< T > & fill(const T val0, const T val1)
Fill sequentially all pixel values with specified values.
CImg< T > & sRGBtoRGB()
Convert pixel values from sRGB to RGB color spaces.
static CImg< T > get_load_png(std::FILE *const file)
Load image from a PNG file .
const unsigned int keySHIFTRIGHT
Keycode for the SHIFTRIGHT key (architecture-dependent).
CImg< T > & RGBtoCMY()
Convert pixel values from RGB to CMY color spaces.
CImg< T > operator|(const char *const expression) const
Bitwise OR operator.
CImg< T > & haar(const bool invert=false, const unsigned int nb_scales=1)
Compute Haar multiscale wavelet transform .
CImg< Tfloat > get_normalize() const
Normalize multi-valued pixels of the image instance, with respect to their L2-norm ...
const CImg< T > & save_pnm(std::FILE *const file, const unsigned int bytes_per_pixel=0) const
Save image as a PNM file .
CImg< Tfloat > get_distance(const T value, const CImg< t > &metric_mask) const
Compute chamfer distance to a specified value, with a custom metric .
CImgList< T > & load_parrec(const char *const filename)
Load a list from a PAR/REC (Philips) file.
CImg< T > & erode(const unsigned int s)
Erode the image by a square structuring element of specified size.
const CImg< T > get_shared_slice(const unsigned int z0, const unsigned int c0=0) const
Return a shared-memory image referencing one slice of the image instance .
iterator end()
Return a CImg::iterator pointing next to the last pixel value.
CImgDisplay()
Construct an empty display.
bool contains(const T &pixel, t &x, t &y, t &z) const
Test if pixel value is inside image bounds and get its X,Y and Z-coordinates.
CImg< T > & fill(const T val0, const T val1, const T val2, const T val3, const T val4)
Fill sequentially all pixel values with specified values .
CImg< T > & rol(const char *const expression)
Compute the bitwise left rotation of each pixel value.
CImg< T > & cut(const T min_value, const T max_value)
Cut pixel values in specified range.
const unsigned int keyF3
Keycode for the F3 key (architecture-dependent).
bool is_event() const
Return true if any event has occured on the associated window, false otherwise.
CImg< T > & draw_axes(const CImg< tx > &values_x, const CImg< ty > &values_y, const tc *const color, const float opacity=1, const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U, const unsigned int font_height=13, const bool allow_zero=true)
Draw labeled horizontal and vertical axes.
bool is_key(const unsigned int keycode) const
Return true if key specified by given keycode is being pressed on the associated window, false otherwise.
const unsigned int key7
Keycode for the 7 key (architecture-dependent).
CImg< T > & HSItoRGB()
Convert pixel values from HSI to RGB color spaces.
CImg< T > & draw_gaussian(const float xc, const float yc, const float zc, const CImg< t > &tensor, const tc *const color, const float opacity=1)
Draw a 3d gaussian function .
T & temporary(const T &)
Return a reference to a temporary variable of type T.
CImgList(const CImg< t1 > &img1, const CImg< t2 > &img2, const bool is_shared=false)
Construct list from two images.
CImg< _cimg_Tt > get_append(const CImg< T > &img, const char axis='x', const float align=0) const
Append two images along specified axis .
CImgList< T > & operator=(const CImgList< t > &list)
Construct list from another list.
CImg(const T *const values, const unsigned int size_x, const unsigned int size_y=1, const unsigned int size_z=1, const unsigned int size_c=1, const bool is_shared=false)
Construct image with specified size and initialize pixel values from a memory buffer ...
CImg< Tfloat > get_log2() const
Compute the base-10 logarithm of each pixel value .
CImg< floatT > get_streamline(const float x, const float y, const float z, const float L=256, const float dl=0.1f, const unsigned int interpolation_type=2, const bool is_backward_tracking=false, const bool is_oriented_only=false) const
Return stream line of a 2d or 3d vector field.
CImg< T > & load_cimg(const char *const filename, const unsigned int n0, const unsigned int n1, const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int c0, const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int c1, const char axis='z', const float align=0)
Load sub-images of a .cimg file.
int window_x() const
Return X-coordinate of the associated window.
CImg< T > & load_off(CImgList< tf > &primitives, CImgList< tc > &colors, std::FILE *const file)
Load 3d object from a .OFF file .
Tdouble dot(const CImg< t > &img) const
Compute the dot product between instance and argument, viewed as matrices.
CImgList< T > & load_cimg(std::FILE *const file)
Load a list from a .cimg file.
CImgList< T > get_split(const CImg< t > &values, const bool keep_values, const bool is_shared) const
Split image into a list of one-column vectors, according to a specified splitting value sequence...
CImg< T > & load_pfm(std::FILE *const file)
Load image from a PFM file .
CImg< T > & draw_line(const int x0, const int y0, const int x1, const int y1, const tc *const color, const float opacity=1, const unsigned int pattern=~0U, const bool init_hatch=true)
Draw a 2d line.
CImg< T > & draw_triangle(const int x0, const int y0, const int x1, const int y1, const int x2, const int y2, const CImg< tc > &texture, const int tx0, const int ty0, const int tx1, const int ty1, const int tx2, const int ty2, const CImg< tl > &light, const int lx0, const int ly0, const int lx1, const int ly1, const int lx2, const int ly2, const float opacity=1)
Draw a textured Phong-shaded 2d triangle.
bool is_sameXYZ(const CImg< t > &img) const
Test if image width, height and depth are the same as that of another image.
CImgList(const CImg< t1 > &img1, const CImg< t2 > &img2, const CImg< t3 > &img3, const CImg< t4 > &img4, const CImg< t5 > &img5, const CImg< t6 > &img6, const CImg< t7 > &img7, const CImg< t8 > &img8, const bool is_shared=false)
Construct list from eight images.
void unused(const T &,...)
Avoid warning messages due to unused parameters. Do nothing actually.
const unsigned int keyM
Keycode for the M key (architecture-dependent).
CImg< T > & resize(const int size_x, const int size_y=-100, const int size_z=-100, const int size_c=-100, const int interpolation_type=1, const unsigned int boundary_conditions=0, const float centering_x=0, const float centering_y=0, const float centering_z=0, const float centering_c=0)
Resize image to new dimensions.
CImg< Tuchar > get_BayertoRGB(const unsigned int interpolation_type=3) const
Convert Bayer-coded scalar image to a RGB color image .
CImg< T > get_crop(const int x0, const int y0, const int x1, const int y1, const bool boundary_conditions=false) const
Crop image region .
const T & min_max(t &max_val) const
Return a reference to the minimum pixel value of the instance list and return the maximum vvalue as w...
const unsigned int keyPAD2
Keycode for the PAD2 key (architecture-dependent).
CImg< Tfloat > get_log() const
Compute the logarithm of each pixel value .
T median() const
Return the median pixel value.
CImg< Tfloat > get_haar(const bool invert=false, const unsigned int nb_scales=1) const
Compute Haar multiscale wavelet transform .
CImgList< T > & operator=(const CImgDisplay &disp)
Construct list from the content of a display window .
CImg< T > & set_vector_at(const CImg< t > &vec, const unsigned int x, const unsigned int y=0, const unsigned int z=0)
Set vector-valued pixel at specified position.
CImg< T > & round(const double y=1, const int rounding_type=0)
Round pixel values.
const unsigned int keyU
Keycode for the U key (architecture-dependent).
void invert_endianness(T *const buffer, const unsigned long size)
Reverse endianness of all elements in a memory buffer.
static CImg< T > get_load_jpeg(std::FILE *const file)
Load image from a JPEG file .
CImgList< T > & assign()
Destructor .
CImgList< T > operator,(const CImg< t > &img) const
Return a copy of the list instance, where image img has been inserted at the end .
CImg< T > & assign(const unsigned int size_x, const unsigned int size_y=1, const unsigned int size_z=1, const unsigned int size_c=1)
Construct image with specified size .
CImg< T > & draw_object3d(const float x0, const float y0, const float z0, const CImg< tp > &vertices, const CImgList< tf > &primitives, const CImgList< tc > &colors, const unsigned int render_type=4, const bool is_double_sided=false, const float focale=700, const float lightx=0, const float lighty=0, const float lightz=-5e8, const float specular_lightness=0.2f, const float specular_shininess=0.1f)
Draw a 3d object .
T atNXYZ(const int pos, const int x, const int y, const int z, const int c, const T out_value) const
Access pixel value with Dirichlet boundary conditions for the 3 first coordinates (pos...
CImgList< t > & move_to(CImgList< t > &list)
Transfer the content of the list instance to another list.
CImgDisplay & show_mouse()
Show mouse pointer.
CImgList< T > & FFT(const char axis, const bool invert=false)
Compute a 1d Fast Fourier Transform, along specified axis.
const CImg< T > & save_dlm(std::FILE *const file) const
Save image as a DLM file .
CImg< T > & transpose()
Transpose the image, viewed as a matrix.
const unsigned int key5
Keycode for the 5 key (architecture-dependent).
CImg< T > & max(const CImg< t > &img)
Pointwise max operator between two images.
CImg< T > & draw_plasma(const float alpha=1, const float beta=0, const unsigned int scale=8)
Draw a random plasma texture.
bool is_empty() const
Test if image instance is empty.
CImg< T > & load_magick(const char *const filename)
Load image from a file, using Magick++ library.
const unsigned int keyF
Keycode for the F key (architecture-dependent).
bool operator!=(const t value) const
Test if pixels of an image are all different from a value.
CImg< T > operator&(const char *const expression) const
Bitwise AND operator.
CImg< Tfloat > get_sqr() const
Compute the square value of each pixel value .
CImg< T > & load_pandore(std::FILE *const file)
Load image from a PANDORE-5 file .
CImg< T > & draw_text(const int x0, const int y0, const char *const text, const tc *const foreground_color, const int background_color=0, const float opacity=1, const unsigned int font_height=13,...)
Draw a text string .
const unsigned int keyF9
Keycode for the F9 key (architecture-dependent).
CImg< T > & draw_gaussian(const float xc, const float yc, const CImg< t > &tensor, const tc *const color, const float opacity=1)
Draw a 2d gaussian function.
CImgList(const CImg< t > &img, const bool is_shared=false)
Construct list from one image.
CImgList< T > & insert(const unsigned int n, const unsigned int pos=~0U)
Insert n empty images img into the current image list, at position pos.
CImg< T > get_shared_rows(const unsigned int y0, const unsigned int y1, const unsigned int z0=0, const unsigned int c0=0)
Return a shared-memory image referencing a range of rows of the image instance.
CImg< T > & atan()
Compute the arctangent of each pixel value.
CImg< T > & draw_triangle(CImg< tz > &zbuffer, const int x0, const int y0, const float z0, const int x1, const int y1, const float z1, const int x2, const int y2, const float z2, const tc *const color, const float brightness0, const float brightness1, const float brightness2, const float opacity=1)
Draw a Gouraud-shaded 2d triangle, with z-buffering .
static CImg< T > vector(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4, const T &a5, const T &a6)
Return a 1x7 image containing specified values.
double eval(const char *const expression, const double x=0, const double y=0, const double z=0, const double c=0) const
Evaluate math formula.
CImg< T > get_cut(const T min_value, const T max_value) const
Cut pixel values in specified range .
const CImg< T > get_shared_rows(const unsigned int y0, const unsigned int y1, const unsigned int z0=0, const unsigned int c0=0) const
Return a shared-memory image referencing a range of rows of the image instance .
CImg< T > get_sort(CImg< t > &permutations, const bool is_increasing=true) const
Sort pixel values and get sorting permutations .
CImg< T > get_blur_anisotropic(const float amplitude, const float sharpness=0.7f, const float anisotropy=0.6f, const float alpha=0.6f, const float sigma=1.1f, const float dl=0.8f, const float da=30, const float gauss_prec=2, const unsigned int interpolation_type=0, const bool is_fast_approx=true) const
Blur image anisotropically, in an edge-preserving way .
T at(const int offset, const T out_value) const
Access to a pixel value at a specified offset, using Dirichlet boundary conditions ...
CImg< _cimg_Tt > operator%(const t value) const
Modulo operator.
CImg< T > & abs()
Compute the absolute value of each pixel value.
CImgDisplay & set_wheel(const int amplitude)
Simulate a wheel event.
static CImg< T > dijkstra(const tf &distance, const unsigned int nb_nodes, const unsigned int starting_node, const unsigned int ending_node, CImg< t > &previous_node)
Compute minimal path in a graph, using the Dijkstra algorithm.
CImg< T > & operator&=(const char *const expression)
In-place bitwise AND operator.
static CImg< T > get_load_gif_external(const char *const filename, const char axis='z', const float align=0)
Load gif file, using ImageMagick or GraphicsMagick's external tool 'convert' .
CImg< Tfloat > get_min(const char *const expression) const
Pointwise min operator between an image and an expression .
bool is_sameC(const CImg< t > &img) const
Test if image spectrum is equal to specified value.
CImg< Tfloat > get_blur(const float sigma, const bool boundary_conditions=true, const bool is_gaussian=false) const
Blur image isotropically .
CImg< T > & set_matrix_at(const CImg< t > &mat, const unsigned int x=0, const unsigned int y=0, const unsigned int z=0)
Set (square) matrix-valued pixel at specified position.
const CImgList< T > & save_gzip_external(const char *const filename) const
Save list as a gzipped file, using external tool 'gzip'.
const char * dcraw_path(const char *const user_path=0, const bool reinit_path=false)
Get/set path to the dcraw binary.
CImg< T > & distance(const T value, const unsigned int metric=2)
Compute Euclidean distance function to a specified value.
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
Fill sequentially all pixel values with specified values .
CImg< T > & fill(const T val0, const T val1, const T val2, const T val3, const T val4, const T val5, const T val6, const T val7, const T val8, const T val9, const T val10, const T val11)
Fill sequentially all pixel values with specified values .
CImgList< Tfloat > get_FFT(const char axis, const bool invert=false) const
Compute a 1-D Fast Fourier Transform, along specified axis .
T & min()
Return a reference to the minimum pixel value.
static CImg< T > get_load_medcon_external(const char *const filename)
Load image from a DICOM file, using XMedcon's external tool 'medcon' .
~CImgDisplay()
Destructor.
static CImg< T > vector(const T &a0, const T &a1, const T &a2)
Return a 1x3 image containing specified values.
const T & front() const
Return a reference to the first pixel value .
CImgList< T > & assign(const char *const filename)
Construct list by reading the content of a file .
CImg< T > get_threshold(const T value, const bool soft_threshold=false, const bool strict_threshold=false) const
Threshold pixel values .
const unsigned int keyT
Keycode for the T key (architecture-dependent).
const unsigned int keyG
Keycode for the G key (architecture-dependent).
const CImg< T > & save_cpp(const char *const filename) const
Save image as a .cpp source file.
CImg< T > & index(const CImg< t > &colormap, const float dithering=1, const bool map_indexes=false)
Index multi-valued pixels regarding to a specified colormap.
CImgDisplay & set_normalization(const unsigned int normalization)
Set normalization type.
CImgList< T > & assign(const CImg< t1 > &img1, const CImg< t2 > &img2, const CImg< t3 > &img3, const CImg< t4 > &img4, const CImg< t5 > &img5, const CImg< t6 > &img6, const CImg< t7 > &img7, const bool is_shared=false)
Construct list from seven images .
CImg< T > get_shift(const int delta_x, const int delta_y=0, const int delta_z=0, const int delta_c=0, const int boundary_conditions=0) const
Shift image content .
CImg< _cimg_Tt > get_dilate(const CImg< t > &mask, const unsigned int boundary_conditions=1, const bool is_normalized=false) const
Dilate image by a structuring element .
CImg< T > get_dijkstra(const unsigned int starting_node, const unsigned int ending_node, CImg< t > &previous_node) const
Return minimal path in a graph, using the Dijkstra algorithm .
const unsigned int keyAPPRIGHT
Keycode for the APPRIGHT key (architecture-dependent).
const unsigned int keySHIFTLEFT
Keycode for the SHIFTLEFT key (architecture-dependent).
CImg< _cimg_Tt > operator*(const CImg< t > &img) const
Multiplication operator.
bool contains(const T &pixel, t &n, t &x, t &y) const
Test if one of the image list contains the specified referenced value.
static CImg< T > diagonal(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4)
Return a 5x5 diagonal matrix containing specified coefficients.
CImg< T > & load_off(CImgList< tf > &primitives, CImgList< tc > &colors, const char *const filename)
Load 3d object from a .OFF file.
CImg< T > & load_gzip_external(const char *const filename)
Load gzipped image file, using external tool 'gunzip'.
const CImg< T > & save_exr(const char *const filename) const
Save image as an OpenEXR file.
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 T val7, const T val8, const T val9, const T val10, const T val11) const
Fill sequentially all pixel values with specified values .
CImg< Tfloat > get_haar(const char axis, const bool invert=false, const unsigned int nb_scales=1) const
Compute Haar multiscale wavelet transform .
CImg< T > & CMYtoRGB()
Convert pixel values from CMY to RGB color spaces.
CImg< T > get_min(const T val) const
Pointwise min operator between instance image and a value .
CImg< T > & assign(const CImgDisplay &disp)
Construct image from a display window .
CImg< T > & dijkstra(const unsigned int starting_node, const unsigned int ending_node, CImg< t > &previous_node)
Return minimal path in a graph, using the Dijkstra algorithm.
char uncase(const char x)
Convert ascii character to lower case.
CImg< T > & sign()
Compute the sign of each pixel value.
const CImg< T > & save_cimg(const char *const filename, const unsigned int n0, const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int c0) const
Save image as a sub-image into an existing .cimg file.
CImg< Tfloat > get_diffusion_tensors(const float sharpness=0.7f, const float anisotropy=0.6f, const float alpha=0.6f, const float sigma=1.1f, const bool is_sqrt=false) const
Compute field of diffusion tensors for edge-preserving smoothing .
CImg< T > & CMYtoCMYK()
Convert pixel values from CMY to CMYK color spaces.
static CImg< T > & empty()
Return a reference to an empty image.
bool operator!=(const CImg< t > &img) const
Test if two images have different sizes or values.
bool is_moved() const
Return true if associated window has been moved on the screen, false otherwise.
CImg< T > get_resize_tripleXY() const
Resize image to triple-size, using the Scale3X algorithm .
bool is_sameY(const CImg< t > &img) const
Test if image height is equal to specified value.
CImg< T > & slices(const int z0, const int z1)
Return specified range of image slices .
CImg< T > & draw_fill(const int x, const int y, const tc *const color, const float opacity=1, const float sigma=0, const bool is_high_connexity=false)
Draw filled 2d region with the flood fill algorithm .
CImgDisplay(const unsigned int width, const unsigned int height, const char *const title=0, const unsigned int normalization=3, const bool is_fullscreen=false, const bool is_closed=false)
Construct a display with specified dimensions.
static CImg< T > dijkstra(const tf &distance, const unsigned int nb_nodes, const unsigned int starting_node, const unsigned int ending_node=~0U)
Return minimal path in a graph, using the Dijkstra algorithm.
CImgList< T > get_shared()
Return a list with elements being shared copies of images in the list instance.
CImg< T > & draw_fill(const int x, const int y, const int z, const tc *const color, const float opacity=1, const float sigma=0, const bool is_high_connexity=false)
Draw filled 3d region with the flood fill algorithm .
T atN(const int pos, const int x, const int y, const int z, const int c, const T out_value) const
Access to pixel value with Dirichlet boundary conditions for the first coordinate (pos) ...
CImg< Tfloat > get_invert(const bool use_LU=true) const
Invert the instance image, viewed as a matrix .
const unsigned int keyF11
Keycode for the F11 key (architecture-dependent).
CImg< T > get_fill(const T val0, const T val1) const
Fill sequentially all pixel values with specified values .
CImg< T > & draw_triangle(const int x0, const int y0, const int x1, const int y1, const int x2, const int y2, const tc *const color, const float opacity=1)
Draw a filled 2d triangle.
static CImg< floatT > elevation3d(CImgList< tf > &primitives, const char *const expression, const float x0, const float y0, const float x1, const float y1, const int size_x=256, const int size_y=256)
Compute 3d elevation of a function, as a 3d object .
const CImgList< T > & save_gif_external(const char *const filename, const unsigned int fps=25, const unsigned int nb_loops=0)
Save image sequence as a GIF animated file.
bool is_sameN(const unsigned int size_n) const
Test if number of image elements is equal to specified value.
const unsigned int keyARROWDOWN
Keycode for the ARROWDOWN key (architecture-dependent).
CImg< T > & draw_gaussian(const float xc, const float yc, const float zc, const float sigma, const tc *const color, const float opacity=1)
Draw a 3d gaussian function .
T & atXYZ(const int x, const int y, const int z, const int c, const T out_value)
Access to a pixel value, using Dirichlet boundary conditions for the X,Y and Z-coordinates.
CImgList< T > & load_cimg(std::FILE *const file, const unsigned int n0, const unsigned int n1, const unsigned int x0, const unsigned int y0, const unsigned int z0, const unsigned int c0, const unsigned int x1, const unsigned int y1, const unsigned int z1, const unsigned int c1)
Load a sub-image list from a (non compressed) .cimg file .
const unsigned int keyALTGR
Keycode for the ALTGR key (architecture-dependent).
bool is_sameX(const CImgDisplay &disp) const
Test if image width is equal to specified value.
CImgDisplay & paint()
Paint internal display buffer on associated window.
T atNXY(const int pos, const int x, const int y, const int z, const int c, const T out_value) const
Access to pixel value with Dirichlet boundary conditions for the 3 first coordinates (pos...
CImg< T > & swap(CImg< T > &img)
Swap fields of two image instances.
CImg< T > & load_exr(const char *const filename)
Load image from a EXR file.
const char * gunzip_path(const char *const user_path=0, const bool reinit_path=false)
Get/set path to the gzip binary.