Commit 43dec7889fc305d2dab2e19da474e33c27774061

Authored by David Mayerich
1 parent b3a38641

added code for sifting BSQ files in memory, updated CImg

stim/envi/bsq.h
... ... @@ -26,7 +26,7 @@ class bsq: public binary<T> {
26 26  
27 27  
28 28 protected:
29   -
  29 +
30 30 std::vector<double> w; //band wavelengths
31 31 unsigned int offset;
32 32  
... ... @@ -51,7 +51,7 @@ public:
51 51 using binary<T>::read_line_01;
52 52 using binary<T>::read_plane_2;
53 53 //using binary<T>::getSlice;
54   -
  54 +
55 55  
56 56 /// Open a data file for reading using the class interface.
57 57  
... ... @@ -60,7 +60,7 @@ public:
60 60 /// @param Y is the number of samples (lines) along dimension 2
61 61 /// @param B is the number of samples (bands) along dimension 3
62 62 /// @param header_offset is the number of bytes (if any) in the binary header
63   - /// @param wavelengths is an optional STL vector of size B specifying a numerical label for each band
  63 + /// @param wavelengths is an STL vector of size B specifying a numerical label for each band
64 64 bool open(std::string filename, unsigned int X, unsigned int Y, unsigned int B, unsigned int header_offset, std::vector<double> wavelengths){
65 65  
66 66 //copy the wavelengths to the BSQ file structure
... ... @@ -69,7 +69,6 @@ public:
69 69 offset = header_offset;
70 70  
71 71 return open(filename, vec<unsigned int>(X, Y, B), header_offset);
72   -
73 72 }
74 73  
75 74 /// Retrieve a single band (based on index) and stores it in pre-allocated memory.
... ... @@ -91,7 +90,7 @@ public:
91 90 return band_index(p, (unsigned int)wavelength);
92 91  
93 92 unsigned int XY = X() * Y(); //calculate the number of pixels in a band
94   - unsigned page = 0;
  93 + unsigned page = 0;
95 94  
96 95  
97 96 //get the two neighboring bands (above and below 'wavelength')
... ... @@ -165,13 +164,13 @@ public:
165 164 file.seekg((bandnum - 1) * sizeof(T), std::ios::cur); //go to the next band
166 165 }
167 166  
168   - return true;
  167 + return true;
169 168 }
170 169  
171 170 /// Perform baseline correction given a list of baseline points and stores the result in a new BSQ file.
172 171  
173 172 /// @param outname is the name of the output file used to store the resulting baseline-corrected data.
174   - /// @param wls is the list of baseline points based on band labels.
  173 + /// @param wls is the list of baseline points based on band labels.
175 174 bool baseline(std::string outname, std::vector<double> wls )
176 175 {
177 176 unsigned N = wls.size(); //get the number of baseline points
... ... @@ -194,8 +193,8 @@ public:
194 193 T * c; //pointer to the current image
195 194  
196 195 a = (T*)malloc( S ); //memory allocation
197   - b = (T*)malloc( S );
198   - c = (T*)malloc( S );
  196 + b = (T*)malloc( S );
  197 + c = (T*)malloc( S );
199 198  
200 199 if (a == NULL || b == NULL || c == NULL){
201 200 std::cout<<"ERROR: error allocating memory";
... ... @@ -203,13 +202,13 @@ public:
203 202 }
204 203  
205 204  
206   - //initialize lownum, highnum, low, high
  205 + //initialize lownum, highnum, low, high
207 206 ai=w[0];
208 207  
209 208 //if no baseline point is specified at band 0,
210 209 //set the baseline point at band 0 to 0
211 210 if(wls[0] != w[0]){
212   - bi = wls[control];
  211 + bi = wls[control];
213 212 memset(a, (char)0, S);
214 213 }
215 214 //else get the low band
... ... @@ -221,7 +220,7 @@ public:
221 220 //get the high band
222 221 band(b, bi);
223 222  
224   - //correct every band
  223 + //correct every band
225 224 for(unsigned cii = 0; cii < B; cii++){
226 225  
227 226 //update baseline points, if necessary
... ... @@ -253,21 +252,21 @@ public:
253 252 //get the current band
254 253 band_index(c, cii);
255 254 ci = w[cii];
256   -
  255 +
257 256 //perform the baseline correction
258 257 for(unsigned i=0; i < XY; i++){
259 258 double r = (double) (ci - ai) / (double) (bi - ai);
260 259 c[i] =(T) ( c[i] - (b[i] - a[i]) * r - a[i] );
261 260 }
262   -
  261 +
263 262 target.write(reinterpret_cast<const char*>(c), S); //write the corrected data into destination
264 263  
265 264 thread_data = (double)cii / B * 100;
266   -
267   - }
  265 +
  266 + }
268 267  
269 268 //header.save(headername); //save the new header file
270   -
  269 +
271 270 free(a);
272 271 free(b);
273 272 free(c);
... ... @@ -295,7 +294,7 @@ public:
295 294 T * c; //pointer to the current image
296 295  
297 296 b = (T*)malloc( S ); //memory allocation
298   - c = (T*)malloc( S );
  297 + c = (T*)malloc( S );
299 298  
300 299 band(b, w); //get the certain band into memory
301 300  
... ... @@ -314,17 +313,17 @@ public:
314 313 thread_data = (double)j / B * 100;
315 314 }
316 315  
317   -
  316 +
318 317  
319 318 //header.save(headername); //save the new header file
320   -
  319 +
321 320 free(b);
322 321 free(c);
323 322 target.close();
324 323 thread_data = 100; //make sure that the progress bar is full
325 324 return true;
326 325 }
327   -
  326 +
328 327 /// Convert the current BSQ file to a BIP file with the specified file name.
329 328  
330 329 /// @param outname is the name of the output BIP file to be saved to disk.
... ... @@ -356,10 +355,10 @@ public:
356 355 //simplify image resolution
357 356 unsigned int L = X() * Z() * sizeof(T); //calculate the number of bytes of a ZX slice
358 357 unsigned int jump = (Y() - 1) * X() * sizeof(T);
359   -
  358 +
360 359 std::ofstream target(outname.c_str(), std::ios::binary);
361 360 std::string headername = outname + ".hdr";
362   -
  361 +
363 362 unsigned int xz_bytes = X() * Z() * sizeof(T);
364 363 T * xz_slice; //pointer to the current spectrum
365 364 xz_slice = (T*)malloc(xz_bytes);
... ... @@ -372,16 +371,16 @@ public:
372 371 file.read((char *)(xz_slice + z * X()), sizeof(T) * X()); //read a line
373 372 file.seekg(jump, std::ios::cur); //seek to the next band
374 373  
375   -
  374 +
376 375 thread_data = (double)(y * Z() + z) / (Z() * Y()) * 100; //update the progress counter
377   - }
378   - target.write(reinterpret_cast<const char*>(xz_slice), xz_bytes); //write the generated XZ slice to the target file
  376 + }
  377 + target.write(reinterpret_cast<const char*>(xz_slice), xz_bytes); //write the generated XZ slice to the target file
379 378 }
380 379  
381 380  
382   -
  381 +
383 382 thread_data = 100;
384   -
  383 +
385 384 free(xz_slice);
386 385 target.close();
387 386  
... ... @@ -425,7 +424,7 @@ public:
425 424 rp = (T*) malloc(S);
426 425  
427 426 band(lp, lb);
428   - band(rp, rb);
  427 + band(rp, rb);
429 428  
430 429 baseline_band(lb, rb, lp, rp, bandwavelength, result);
431 430  
... ... @@ -496,7 +495,7 @@ public:
496 495 }
497 496 baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part
498 497 baseline_band(lb, rb, lp, rp, w[ai], cur);
499   - for(unsigned j = 0; j < XY; j++){
  498 + for(unsigned j = 0; j < XY; j++){
500 499 result[j] += (w[ai] - lab) * (cur[j] + cur2[j]) / 2.0;
501 500 }
502 501  
... ... @@ -507,7 +506,7 @@ public:
507 506 baseline_band(lb, rb, lp, rp, w[ai], cur2);
508 507 for(unsigned j = 0; j < XY; j++)
509 508 {
510   - result[j] += (w[ai] - w[ai-1]) * (cur[j] + cur2[j]) / 2.0;
  509 + result[j] += (w[ai] - w[ai-1]) * (cur[j] + cur2[j]) / 2.0;
511 510 }
512 511 std::swap(cur,cur2); //swap the band pointers
513 512 }
... ... @@ -530,9 +529,9 @@ public:
530 529 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
531 530 bool ph_to_ph(double lb1, double rb1, double pos1, double lb2, double rb2, double pos2, T * result){
532 531  
533   - T* p1 = (T*)malloc(X() * Y() * sizeof(T));
534   - T* p2 = (T*)malloc(X() * Y() * sizeof(T));
535   -
  532 + T* p1 = (T*)malloc(X() * Y() * sizeof(T));
  533 + T* p2 = (T*)malloc(X() * Y() * sizeof(T));
  534 +
536 535 //get the two peak band
537 536 height(lb1, rb1, pos1, p1);
538 537 height(lb2, rb2, pos2, p2);
... ... @@ -546,9 +545,9 @@ public:
546 545  
547 546 free(p1);
548 547 free(p2);
549   - return true;
  548 + return true;
550 549 }
551   -
  550 +
552 551 /// Compute the ratio between a peak area and peak height.
553 552  
554 553 /// @param lb1 is the label value for the left baseline point for the first peak (numerator)
... ... @@ -560,10 +559,10 @@ public:
560 559 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
561 560 bool pa_to_ph(double lb1, double rb1, double lab1, double rab1,
562 561 double lb2, double rb2, double pos, T* result){
563   -
564   - T* p1 = (T*)malloc(X() * Y() * sizeof(T));
565   - T* p2 = (T*)malloc(X() * Y() * sizeof(T));
566   -
  562 +
  563 + T* p1 = (T*)malloc(X() * Y() * sizeof(T));
  564 + T* p2 = (T*)malloc(X() * Y() * sizeof(T));
  565 +
567 566 //get the area and the peak band
568 567 area(lb1, rb1, lab1, rab1, p1);
569 568 height(lb2, rb2, pos, p2);
... ... @@ -577,9 +576,9 @@ public:
577 576  
578 577 free(p1);
579 578 free(p2);
580   - return true;
581   - }
582   -
  579 + return true;
  580 + }
  581 +
583 582 /// Compute the ratio between two peak areas.
584 583  
585 584 /// @param lb1 is the label value for the left baseline point for the first peak (numerator)
... ... @@ -589,14 +588,14 @@ public:
589 588 /// @param lb2 is the label value for the left baseline point for the second peak (denominator)
590 589 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
591 590 /// @param lab2 is the label value for the left bound (start of the integration) of the second peak (denominator)
592   - /// @param rab2 is the label value for the right bound (end of the integration) of the second peak (denominator)
  591 + /// @param rab2 is the label value for the right bound (end of the integration) of the second peak (denominator)
593 592 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
594 593 bool pa_to_pa(double lb1, double rb1, double lab1, double rab1,
595 594 double lb2, double rb2, double lab2, double rab2, T* result){
596   -
597   - T* p1 = (T*)malloc(X() * Y() * sizeof(T));
598   - T* p2 = (T*)malloc(X() * Y() * sizeof(T));
599   -
  595 +
  596 + T* p1 = (T*)malloc(X() * Y() * sizeof(T));
  597 + T* p2 = (T*)malloc(X() * Y() * sizeof(T));
  598 +
600 599 //get the area and the peak band
601 600 area(lb1, rb1, lab1, rab1, p1);
602 601 area(lb2, rb2, lab2, rab2, p2);
... ... @@ -610,8 +609,8 @@ public:
610 609  
611 610 free(p1);
612 611 free(p2);
613   - return true;
614   - }
  612 + return true;
  613 + }
615 614  
616 615 /// Compute the definite integral of a baseline corrected peak.
617 616  
... ... @@ -671,7 +670,7 @@ public:
671 670 }
672 671 baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part
673 672 baseline_band(lb, rb, lp, rp, w[ai], cur);
674   - for(unsigned j = 0; j < XY; j++){
  673 + for(unsigned j = 0; j < XY; j++){
675 674 result[j] += (w[ai] - lab) * (w[ai] + lab) * (cur[j] + cur2[j]) / 4.0;
676 675 }
677 676  
... ... @@ -682,7 +681,7 @@ public:
682 681 baseline_band(lb, rb, lp, rp, w[ai], cur2);
683 682 for(unsigned j = 0; j < XY; j++)
684 683 {
685   - result[j] += (w[ai] - w[ai-1]) * (w[ai] + w[ai-1]) * (cur[j] + cur2[j]) / 4.0;
  684 + result[j] += (w[ai] - w[ai-1]) * (w[ai] + w[ai-1]) * (cur[j] + cur2[j]) / 4.0;
686 685 }
687 686 std::swap(cur,cur2); //swap the band pointers
688 687 }
... ... @@ -702,9 +701,9 @@ public:
702 701 /// @param rab is the label for the end of the peak
703 702 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
704 703 bool cpoint(double lb, double rb, double lab, double rab, T* result){
705   - T* p1 = (T*)malloc(X() * Y() * sizeof(T));
706   - T* p2 = (T*)malloc(X() * Y() * sizeof(T));
707   -
  704 + T* p1 = (T*)malloc(X() * Y() * sizeof(T));
  705 + T* p2 = (T*)malloc(X() * Y() * sizeof(T));
  706 +
708 707 //get the area and the peak band
709 708 x_area(lb, rb, lab, rab, p1);
710 709 area(lb, rb, lab, rab, p2);
... ... @@ -718,7 +717,7 @@ public:
718 717  
719 718 free(p1);
720 719 free(p2);
721   - return true;
  720 + return true;
722 721 }
723 722  
724 723 /// Create a mask based on a given band and threshold value.
... ... @@ -777,7 +776,80 @@ public:
777 776 return true;
778 777 }
779 778  
  779 + /// Saves only those pixels in a band corresponding to the mask value != 0
  780 + /// @param array is a pointer to the destination array used to store the data
  781 + /// @param i is the band index
  782 + /// @p is a pointer to the mask data
  783 + bool sift_band(T* values, unsigned long b, unsigned char* p){
  784 + unsigned long long XY = X() * Y(); //Number of XY pixels
  785 + unsigned long long L = XY * sizeof(T); //size of XY plane (in bytes)
  786 +
  787 + unsigned long long vi = 0; //create an index into the values array
  788 +
  789 + unsigned long long start, end; //start and end indices of a block of masked pixels in the band
  790 + bool reading = false;
  791 + unsigned long long l, i; //length of the masked region
  792 +
  793 + for(unsigned long long xy = 0; xy < XY; xy++){ //for each pixel in the band
  794 +
  795 + if(reading){ //if we are currently iterating through a block of masked pixels
  796 + if(p[xy]) end++; //if the current pixel is part of that block, increment the end index
  797 + else{ //otherwise, terminate the block
  798 + reading = false; //stop reading
  799 + i = b * XY + start;
  800 + file.seekg( i * sizeof(T) + header); //skip all of the unmasked pixels up to this point
  801 + l = (end - start);
  802 + file.read((char *)&values[vi], l * sizeof(T)); //write the values between start and end to the values array
  803 + vi += l; //increment the pointer into the values array
  804 + }
  805 + }
  806 + else{ //if we are currently iterating through a block of empty pixels
  807 + if(p[xy]){ //if the next pixel is masked, start a new block for reading
  808 + reading = true;
  809 + start = xy; //set the start and end indices to the beginning of this new block
  810 + end = start + 1;
  811 + }
  812 + }
  813 + }
  814 +
  815 + return true;
  816 + }
  817 +
  818 + /// Saves only those spectra corresponding to mask value != 0 to pre-allocated memory
  819 + /// @param matrix is the destination for the sifted pixels
  820 + /// @param p is the mask file used for sifting
  821 + bool sift(T* matrix, unsigned char* p){
  822 +
  823 + // open a band (XY plane)
  824 + unsigned long XY = X() * Y(); //Number of XY pixels
  825 + unsigned long L = XY * sizeof(T); //size of XY pixels
  826 +
  827 + //count the number of masked pixels
  828 + unsigned long P = 0; //allocate space for the number of pixels
  829 + for(unsigned long xy = 0; xy < XY; xy++){ //count the number of pixels
  830 + if(p[xy] != 0) P++;
  831 + }
  832 +
  833 + T* bandvals = (T*) malloc(sizeof(T) * P); //allocate a temporary array to store the pixels for a single band
  834 + memset(matrix, 0, sizeof(T) * P * Z());
  835 + for (unsigned long z = 0; z < Z(); z++){ //for each band
  836 +
  837 + if(!sift_band(bandvals, z, p)){
  838 + std::cout<<"ERROR sifting band index "<<z<<std::endl;
  839 + exit(1);
  840 + }
  841 +
  842 + for(unsigned long p = 0; p < P; p++) //for each pixel in the array representing a single band
  843 + matrix[p * Z() + z] = bandvals[p]; //copy it to the appropriate location in the matrix
  844 + }
  845 +
  846 + free(bandvals); //clean up temporary memory
  847 + return true;
  848 + }
  849 +
780 850 /// Saves to disk only those spectra corresponding to mask values != 0
  851 + /// @param outfile is the name of the sifted ENVI file to be written to disk
  852 + /// @param unsigned char* p is the mask file used for sifting
781 853 bool sift(std::string outfile, unsigned char* p){
782 854 std::ofstream target(outfile.c_str(), std::ios::binary);
783 855 // open a band (XY plane)
... ... @@ -912,7 +984,7 @@ public:
912 984 for (unsigned j = 0; j < XY; j++){ //loop through temp, averaging valid pixels
913 985 if (mask[j] != 0){
914 986 p[i] += temp[j] / (T)count;
915   - }
  987 + }
916 988 }
917 989 }
918 990 free(temp);
... ... @@ -930,7 +1002,7 @@ public:
930 1002 unsigned int B = Z();
931 1003 T* bandi = (T*)malloc(sizeof(T) * xy);
932 1004 T* bandj = (T*)malloc(sizeof(T) * xy);
933   -
  1005 +
934 1006 //count vaild pixels in a band
935 1007 unsigned count = 0;
936 1008 for (unsigned j = 0; j < xy; j++){
... ... @@ -1004,11 +1076,11 @@ public:
1004 1076 for (unsigned y = 0; y < lines; y++)
1005 1077 {
1006 1078 file.read((char *)(temp + y * samples), sizeof(T) * samples);
1007   - file.seekg(jumpl, std::ios::cur); //go to the next band
  1079 + file.seekg(jumpl, std::ios::cur); //go to the next band
1008 1080  
1009 1081 thread_data = (double)(z * lines + y) / (Z() * lines) * 100;
1010 1082 }
1011   - out.write(reinterpret_cast<const char*>(temp), L); //write slice data into target file
  1083 + out.write(reinterpret_cast<const char*>(temp), L); //write slice data into target file
1012 1084 file.seekg(jumpb, std::ios::cur);
1013 1085 }
1014 1086 free(temp);
... ... @@ -1030,4 +1102,4 @@ public:
1030 1102  
1031 1103 #endif
1032 1104  
1033   -
  1105 +
... ...
stim/envi/envi.h
... ... @@ -465,7 +465,26 @@ public:
465 465 return false;
466 466 }
467 467  
  468 + /// sift copies all spectra corresponding to nonzero values of a mask into a pre-allocated matrix
  469 + /// @param matrix is the destination for the pixel data
  470 + /// @param p is the mask
  471 + bool sift(void* matrix, unsigned char* p){
  472 +
  473 + if (header.interleave == envi_header::BSQ){ //if the infile is bsq file
  474 + if (header.data_type == envi_header::float32)
  475 + return ((bsq<float>*)file)->sift((float*)matrix, p);
  476 + else if (header.data_type == envi_header::float64)
  477 + return ((bsq<double>*)file)->sift((double*)matrix, p);
  478 + else
  479 + std::cout << "ERROR: unidentified data type" << std::endl;
  480 + }
  481 + return false;
  482 +
  483 + }
  484 +
468 485 /// sift-mask saves in an array only those spectra corresponding to nonzero values of the mask.
  486 + /// @param outfile is the name of the sifted output file
  487 + /// @param p is the mask
469 488 bool sift(std::string outfile, unsigned char* p)
470 489 {
471 490  
... ...
stim/image/CImg.h
Changes suppressed. Click to show
... ... @@ -54,7 +54,7 @@
54 54  
55 55 // Set version number of the library.
56 56 #ifndef cimg_version
57   -#define cimg_version 165
  57 +#define cimg_version 169
58 58  
59 59 /*-----------------------------------------------------------
60 60 #
... ... @@ -75,6 +75,7 @@
75 75 #include <cstdarg>
76 76 #include <cstring>
77 77 #include <cmath>
  78 +#include <cfloat>
78 79 #include <climits>
79 80 #include <ctime>
80 81 #include <exception>
... ... @@ -122,16 +123,30 @@
122 123 #pragma warning(disable:4820)
123 124 #pragma warning(disable:4996)
124 125 #define _CRT_SECURE_NO_DEPRECATE 1
  126 +#define _CRT_SECURE_NO_WARNINGS 1
125 127 #define _CRT_NONSTDC_NO_DEPRECATE 1
126   -#define cimg_snprintf cimg::c99_snprintf
127   -#define cimg_vsnprintf cimg::c99_vsnprintf
128 128 #endif
129 129  
130   -#ifndef cimg_snprintf
  130 +// Define correct string functions for each compiler and OS.
  131 +#if cimg_OS==2 && defined(_MSC_VER)
  132 +#define cimg_sscanf std::sscanf
  133 +#define cimg_sprintf std::sprintf
  134 +#define cimg_snprintf cimg::_snprintf
  135 +#define cimg_vsnprintf cimg::_vsnprintf
  136 +#else
131 137 #include <stdio.h>
  138 +#if defined(__MACOSX__) || defined(__APPLE__)
  139 +#define cimg_sscanf cimg::_sscanf
  140 +#define cimg_sprintf cimg::_sprintf
  141 +#define cimg_snprintf cimg::_snprintf
  142 +#define cimg_vsnprintf cimg::_vsnprintf
  143 +#else
  144 +#define cimg_sscanf std::sscanf
  145 +#define cimg_sprintf std::sprintf
132 146 #define cimg_snprintf snprintf
133 147 #define cimg_vsnprintf vsnprintf
134 148 #endif
  149 +#endif
135 150  
136 151 // Include OS-specific headers.
137 152 #if cimg_OS==1
... ... @@ -145,6 +160,9 @@
145 160 #ifndef NOMINMAX
146 161 #define NOMINMAX
147 162 #endif
  163 +#ifndef WIN32_LEAN_AND_MEAN
  164 +#define WIN32_LEAN_AND_MEAN
  165 +#endif
148 166 #include <windows.h>
149 167 #ifndef _WIN32_IE
150 168 #define _WIN32_IE 0x0400
... ... @@ -154,15 +172,28 @@
154 172 #include <io.h>
155 173 #endif
156 174  
157   -// Look for C++11 features
  175 +// Look for C++11 features.
158 176 #if !defined(cimg_use_cpp11) && __cplusplus>201100
159   -#define cimg_use_cpp11
  177 +#define cimg_use_cpp11 1
160 178 #endif
161   -#ifdef cimg_use_cpp11
  179 +#if defined(cimg_use_cpp11) && cimg_use_cpp11!=0
162 180 #include <initializer_list>
163 181 #include <utility>
164 182 #endif
165 183  
  184 +// Configure the 'abort' signal handler (does nothing by default).
  185 +// A typical signal handler can be defined in your own source like this:
  186 +// Without OpenMP support: #define cimg_test_abort() if (is_abort) throw CImgAbortException("")
  187 +//
  188 +// or
  189 +//
  190 +// With OpenMP support: #define cimg_test_abort() if (!omp_get_thread_num() && is_abort) throw CImgAbortException("")
  191 +//
  192 +// where 'is_abort' is a boolean variable.
  193 +#ifndef cimg_test_abort
  194 +#define cimg_test_abort()
  195 +#endif
  196 +
166 197 // Configure filename separator.
167 198 //
168 199 // Filename separator is set by default to '/', except for Windows where it is '\'.
... ... @@ -186,7 +217,11 @@
186 217 //
187 218 // Define 'cimg_use_vt100' to allow output of color messages on VT100-compatible terminals.
188 219 #ifndef cimg_verbosity
  220 +#if cimg_OS==2
189 221 #define cimg_verbosity 2
  222 +#else
  223 +#define cimg_verbosity 1
  224 +#endif
190 225 #elif !(cimg_verbosity==0 || cimg_verbosity==1 || cimg_verbosity==2 || cimg_verbosity==3 || cimg_verbosity==4)
191 226 #error CImg Library: Configuration variable 'cimg_verbosity' is badly defined.
192 227 #error (should be { 0=quiet | 1=console | 2=dialog | 3=console+warnings | 4=dialog+warnings }).
... ... @@ -201,11 +236,7 @@
201 236 #if cimg_OS==0
202 237 #define cimg_display 0
203 238 #elif cimg_OS==1
204   -#if defined(__MACOSX__) || defined(__APPLE__)
205   -#define cimg_display 1
206   -#else
207 239 #define cimg_display 1
208   -#endif
209 240 #elif cimg_OS==2
210 241 #define cimg_display 2
211 242 #endif
... ... @@ -471,26 +502,6 @@ extern &quot;C&quot; {
471 502 #define cimg_usage(usage) cimg_library_suffixed::cimg::option((char*)0,argc,argv,(char*)0,usage,false)
472 503 #define cimg_help(str) cimg_library_suffixed::cimg::option((char*)0,argc,argv,str,(char*)0)
473 504 #define cimg_option(name,defaut,usage) cimg_library_suffixed::cimg::option(name,argc,argv,defaut,usage)
474   -#define cimg_argument(pos) \
475   - cimg_library_suffixed::cimg::argument(pos,argc,argv)
476   -#define cimg_argument1(pos,s0) \
477   - cimg_library_suffixed::cimg::argument(pos,argc,argv,1,s0)
478   -#define cimg_argument2(pos,s0,s1) \
479   - cimg_library_suffixed::cimg::argument(pos,argc,argv,2,s0,s1)
480   -#define cimg_argument3(pos,s0,s1,s2) \
481   - cimg_library_suffixed::cimg::argument(pos,argc,argv,3,s0,s1,s2)
482   -#define cimg_argument4(pos,s0,s1,s2,s3) \
483   - cimg_library_suffixed::cimg::argument(pos,argc,argv,4,s0,s1,s2,s3)
484   -#define cimg_argument5(pos,s0,s1,s2,s3,s4) \
485   - cimg_library_suffixed::cimg::argument(pos,argc,argv,5,s0,s1,s2,s3,s4)
486   -#define cimg_argument6(pos,s0,s1,s2,s3,s4,s5) \
487   - cimg_library_suffixed::cimg::argument(pos,argc,argv,6,s0,s1,s2,s3,s4,s5)
488   -#define cimg_argument7(pos,s0,s1,s2,s3,s4,s5,s6) \
489   - cimg_library_suffixed::cimg::argument(pos,argc,argv,7,s0,s1,s2,s3,s4,s5,s6)
490   -#define cimg_argument8(pos,s0,s1,s2,s3,s4,s5,s6,s7) \
491   - cimg_library_suffixed::cimg::argument(pos,argc,argv,8,s0,s1,s2,s3,s4,s5,s6,s7)
492   -#define cimg_argument9(pos,s0,s1,s2,s3,s4,s5,s6,s7,s8) \
493   - cimg_library_suffixed::cimg::argument(pos,argc,argv,9,s0,s1,s2,s3,s4,s5,s6,s7,s8)
494 505  
495 506 // Macros to define and manipulate local neighborhoods.
496 507 #define CImg_2x2(I,T) T I[4]; \
... ... @@ -2069,26 +2080,26 @@ namespace cimg_library_suffixed {
2069 2080  
2070 2081 // Declare cimg:: namespace.
2071 2082 // This is an uncomplete namespace definition here. It only contains some
2072   - // necessary stuffs to ensure a correct declaration order of the classes and functions
  2083 + // necessary stuff to ensure a correct declaration order of the classes and functions
2073 2084 // defined afterwards.
2074 2085 namespace cimg {
2075 2086  
2076 2087 // Define ascii sequences for colored terminal output.
2077 2088 #ifdef cimg_use_vt100
2078   - const char t_normal[] = { 0x1b, '[', '0', ';', '0', ';', '0', 'm', 0 };
2079   - const char t_black[] = { 0x1b, '[', '0', ';', '3', '0', ';', '5', '9', 'm', 0 };
2080   - const char t_red[] = { 0x1b, '[', '0', ';', '3', '1', ';', '5', '9', 'm', 0 };
2081   - const char t_green[] = { 0x1b, '[', '0', ';', '3', '2', ';', '5', '9', 'm', 0 };
2082   - const char t_yellow[] = { 0x1b, '[', '0', ';', '3', '3', ';', '5', '9', 'm', 0 };
2083   - const char t_blue[] = { 0x1b, '[', '0', ';', '3', '4', ';', '5', '9', 'm', 0 };
2084   - const char t_magenta[] = { 0x1b, '[', '0', ';', '3', '5', ';', '5', '9', 'm', 0 };
2085   - const char t_cyan[] = { 0x1b, '[', '0', ';', '3', '6', ';', '5', '9', 'm', 0 };
2086   - const char t_white[] = { 0x1b, '[', '0', ';', '3', '7', ';', '5', '9', 'm', 0 };
2087   - const char t_bold[] = { 0x1b, '[', '1', 'm', 0 };
2088   - const char t_underscore[] = { 0x1b, '[', '4', 'm', 0 };
  2089 + static const char t_normal[] = { 0x1b, '[', '0', ';', '0', ';', '0', 'm', 0 };
  2090 + static const char t_black[] = { 0x1b, '[', '0', ';', '3', '0', ';', '5', '9', 'm', 0 };
  2091 + static const char t_red[] = { 0x1b, '[', '0', ';', '3', '1', ';', '5', '9', 'm', 0 };
  2092 + static const char t_green[] = { 0x1b, '[', '0', ';', '3', '2', ';', '5', '9', 'm', 0 };
  2093 + static const char t_yellow[] = { 0x1b, '[', '0', ';', '3', '3', ';', '5', '9', 'm', 0 };
  2094 + static const char t_blue[] = { 0x1b, '[', '0', ';', '3', '4', ';', '5', '9', 'm', 0 };
  2095 + static const char t_magenta[] = { 0x1b, '[', '0', ';', '3', '5', ';', '5', '9', 'm', 0 };
  2096 + static const char t_cyan[] = { 0x1b, '[', '0', ';', '3', '6', ';', '5', '9', 'm', 0 };
  2097 + static const char t_white[] = { 0x1b, '[', '0', ';', '3', '7', ';', '5', '9', 'm', 0 };
  2098 + static const char t_bold[] = { 0x1b, '[', '1', 'm', 0 };
  2099 + static const char t_underscore[] = { 0x1b, '[', '4', 'm', 0 };
2089 2100 #else
2090   - const char t_normal[] = { 0 };
2091   - const char *const t_black = cimg::t_normal,
  2101 + static const char t_normal[] = { 0 };
  2102 + static const char *const t_black = cimg::t_normal,
2092 2103 *const t_red = cimg::t_normal,
2093 2104 *const t_green = cimg::t_normal,
2094 2105 *const t_yellow = cimg::t_normal,
... ... @@ -2114,30 +2125,68 @@ namespace cimg_library_suffixed {
2114 2125  
2115 2126 inline unsigned int& _exception_mode(const unsigned int value, const bool is_set) {
2116 2127 static unsigned int mode = cimg_verbosity;
2117   - cimg::mutex(0);
2118   - if (is_set) mode = value;
2119   - cimg::mutex(0,0);
  2128 + if (is_set) { cimg::mutex(0); mode = value<4?value:4; cimg::mutex(0,0); }
2120 2129 return mode;
2121 2130 }
2122 2131  
2123 2132 // Mandatory because Microsoft's _snprintf() and _vsnprintf() do not add the '\0' character
2124 2133 // at the end of the string.
2125 2134 #if cimg_OS==2 && defined(_MSC_VER)
2126   - inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap) {
2127   - int count = -1;
  2135 + inline int _snprintf(char *const s, const size_t size, const char *const format, ...) {
  2136 + va_list ap;
  2137 + va_start(ap,format);
  2138 + const int result = _vsnprintf(s,size,format,ap);
  2139 + va_end(ap);
  2140 + return result;
  2141 + }
  2142 +
  2143 + inline int _vsnprintf(char *const s, const size_t size, const char *const format, va_list ap) {
  2144 + int result = -1;
2128 2145 cimg::mutex(6);
2129   - if (size) count = _vsnprintf_s(str,size,_TRUNCATE,format,ap);
2130   - if (count==-1) count = _vscprintf(format,ap);
  2146 + if (size) result = _vsnprintf_s(s,size,_TRUNCATE,format,ap);
  2147 + if (result==-1) result = _vscprintf(format,ap);
2131 2148 cimg::mutex(6,0);
2132   - return count;
  2149 + return result;
2133 2150 }
2134   - inline int c99_snprintf(char* str, size_t size, const char* format, ...) {
2135   - int count;
2136   - va_list ap;
2137   - va_start(ap, format);
2138   - count = c99_vsnprintf(str,size,format,ap);
2139   - va_end(ap);
2140   - return count;
  2151 +
  2152 + // Mutex-protected version of sscanf, sprintf and snprintf.
  2153 + // Used only MacOSX, as it seems those functions are not re-entrant on MacOSX.
  2154 +#elif defined(__MACOSX__) || defined(__APPLE__)
  2155 + inline int _sscanf(const char *const s, const char *const format, ...) {
  2156 + cimg::mutex(6);
  2157 + va_list args;
  2158 + va_start(args,format);
  2159 + const int result = std::vsscanf(s,format,args);
  2160 + va_end(args);
  2161 + cimg::mutex(6,0);
  2162 + return result;
  2163 + }
  2164 +
  2165 + inline int _sprintf(char *const s, const char *const format, ...) {
  2166 + cimg::mutex(6);
  2167 + va_list args;
  2168 + va_start(args,format);
  2169 + const int result = std::vsprintf(s,format,args);
  2170 + va_end(args);
  2171 + cimg::mutex(6,0);
  2172 + return result;
  2173 + }
  2174 +
  2175 + inline int _snprintf(char *const s, const size_t n, const char *const format, ...) {
  2176 + cimg::mutex(6);
  2177 + va_list args;
  2178 + va_start(args,format);
  2179 + const int result = std::vsnprintf(s,n,format,args);
  2180 + va_end(args);
  2181 + cimg::mutex(6,0);
  2182 + return result;
  2183 + }
  2184 +
  2185 + inline int _vsnprintf(char *const s, const size_t size, const char* format, va_list ap) {
  2186 + cimg::mutex(6);
  2187 + const int result = std::vsnprintf(s,size,format,ap);
  2188 + cimg::mutex(6,0);
  2189 + return result;
2141 2190 }
2142 2191 #endif
2143 2192  
... ... @@ -2163,6 +2212,31 @@ namespace cimg_library_suffixed {
2163 2212 return _exception_mode(0,false);
2164 2213 }
2165 2214  
  2215 + //! Set current \CImg openmp mode.
  2216 + /**
  2217 + The way openmp-based methods are handled by \CImg can be changed dynamically, using this function.
  2218 + \param mode Desired openmp mode. Possible values are:
  2219 + - \c 0: Never parallelize (quiet mode).
  2220 + - \c 1: Always parallelize.
  2221 + - \c 2: Adaptive parallelization mode (default behavior).
  2222 + **/
  2223 + inline unsigned int& _openmp_mode(const unsigned int value, const bool is_set) {
  2224 + static unsigned int mode = 2;
  2225 + if (is_set) { cimg::mutex(0); mode = value<2?value:2; cimg::mutex(0,0); }
  2226 + return mode;
  2227 + }
  2228 +
  2229 + inline unsigned int& openmp_mode(const unsigned int mode) {
  2230 + return _openmp_mode(mode,true);
  2231 + }
  2232 +
  2233 + //! Return current \CImg openmp mode.
  2234 + inline unsigned int& openmp_mode() {
  2235 + return _openmp_mode(0,false);
  2236 + }
  2237 +
  2238 +#define cimg_openmp_if(cond) if (cimg::openmp_mode()==1 || (cimg::openmp_mode()>1 && (cond)))
  2239 +
2166 2240 // Display a simple dialog box, and wait for the user's response.
2167 2241 inline int dialog(const char *const title, const char *const msg, const char *const button1_label="OK",
2168 2242 const char *const button2_label=0, const char *const button3_label=0,
... ... @@ -2172,6 +2246,7 @@ namespace cimg_library_suffixed {
2172 2246 // Evaluate math expression.
2173 2247 inline double eval(const char *const expression,
2174 2248 const double x=0, const double y=0, const double z=0, const double c=0);
  2249 +
2175 2250 }
2176 2251  
2177 2252 /*---------------------------------------
... ... @@ -2183,9 +2258,12 @@ namespace cimg_library_suffixed {
2183 2258 /**
2184 2259 \par Overview
2185 2260  
2186   - CImgException is the base class of all exceptions thrown by \CImg.
  2261 + CImgException is the base class of all exceptions thrown by \CImg (except \b CImgAbortException).
2187 2262 CImgException is never thrown itself. Derived classes that specify the type of errord are thrown instead.
2188   - These derived classes can be:
  2263 + These classes can be:
  2264 +
  2265 + - \b CImgAbortException: Thrown when a computationally-intensive function is aborted by an external signal.
  2266 + This is the only \c non-derived exception class.
2189 2267  
2190 2268 - \b CImgArgumentException: Thrown when one argument of a called \CImg function is invalid.
2191 2269 This is probably one of the most thrown exception by \CImg.
... ... @@ -2243,28 +2321,65 @@ namespace cimg_library_suffixed {
2243 2321 **/
2244 2322 struct CImgException : public std::exception {
2245 2323 #define _cimg_exception_err(etype,disp_flag) \
2246   - std::va_list ap; va_start(ap,format); cimg_vsnprintf(_message,16384,format,ap); va_end(ap); \
2247   - if (cimg::exception_mode()) { \
2248   - std::fprintf(cimg::output(),"\n%s[CImg] *** %s ***%s %s\n",cimg::t_red,etype,cimg::t_normal,_message); \
2249   - if (cimg_display && disp_flag && !(cimg::exception_mode()%2)) try { cimg::dialog(etype,_message,"Abort"); } \
2250   - catch (CImgException&) {} \
2251   - if (cimg::exception_mode()>=3) cimg_library_suffixed::cimg::info(); \
2252   - }
  2324 + std::va_list ap, ap2; \
  2325 + va_start(ap,format); va_start(ap2,format); \
  2326 + int size = cimg_vsnprintf(0,0,format,ap2); \
  2327 + if (size++>=0) { \
  2328 + delete[] _message; \
  2329 + _message = new char[size]; \
  2330 + cimg_vsnprintf(_message,size,format,ap); \
  2331 + if (cimg::exception_mode()) { \
  2332 + std::fprintf(cimg::output(),"\n%s[CImg] *** %s ***%s %s\n",cimg::t_red,etype,cimg::t_normal,_message); \
  2333 + if (cimg_display && disp_flag && !(cimg::exception_mode()%2)) try { cimg::dialog(etype,_message,"Abort"); } \
  2334 + catch (CImgException&) {} \
  2335 + if (cimg::exception_mode()>=3) cimg_library_suffixed::cimg::info(); \
  2336 + } \
  2337 + } \
  2338 + va_end(ap); va_end(ap2); \
2253 2339  
2254 2340 char *_message;
2255   - CImgException() { _message = new char[16384]; *_message = 0; }
2256   - CImgException(const char *const format, ...) {
2257   - _message = new char[16384]; *_message = 0; _cimg_exception_err("CImgException",true);
  2341 + CImgException() { _message = new char[1]; *_message = 0; }
  2342 + CImgException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgException",true); }
  2343 + CImgException(const CImgException& e) {
  2344 + const int size = std::strlen(e._message);
  2345 + _message = new char[size + 1];
  2346 + std::strncpy(_message,e._message,size);
  2347 + _message[size] = 0;
2258 2348 }
2259 2349 ~CImgException() throw() { delete[] _message; }
  2350 + CImgException& operator=(const CImgException& e) {
  2351 + const int size = std::strlen(e._message);
  2352 + _message = new char[size + 1];
  2353 + std::strncpy(_message,e._message,size);
  2354 + _message[size] = 0;
  2355 + return *this;
  2356 + }
2260 2357 //! Return a C-string containing the error message associated to the thrown exception.
2261 2358 const char *what() const throw() { return _message; }
2262 2359 };
2263 2360  
2264   - // The CImgInstanceException class is used to throw an exception related
2265   - // to an invalid instance encountered in a library function call.
2266   - struct CImgInstanceException : public CImgException {
2267   - CImgInstanceException(const char *const format, ...) { _cimg_exception_err("CImgInstanceException",true); }
  2361 + // The CImgAbortException class is used to throw an exception when
  2362 + // a computationally-intensive function has been aborted by an external signal.
  2363 + struct CImgAbortException : public std::exception {
  2364 + char *_message;
  2365 + CImgAbortException() { _message = new char[1]; *_message = 0; }
  2366 + CImgAbortException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgAbortException",true); }
  2367 + CImgAbortException(const CImgAbortException& e) {
  2368 + const int size = std::strlen(e._message);
  2369 + _message = new char[size + 1];
  2370 + std::strncpy(_message,e._message,size);
  2371 + _message[size] = 0;
  2372 + }
  2373 + ~CImgAbortException() throw() { delete[] _message; }
  2374 + CImgAbortException& operator=(const CImgAbortException& e) {
  2375 + const int size = std::strlen(e._message);
  2376 + _message = new char[size + 1];
  2377 + std::strncpy(_message,e._message,size);
  2378 + _message[size] = 0;
  2379 + return *this;
  2380 + }
  2381 + //! Return a C-string containing the error message associated to the thrown exception.
  2382 + const char *what() const throw() { return _message; }
2268 2383 };
2269 2384  
2270 2385 // The CImgArgumentException class is used to throw an exception related
... ... @@ -2273,18 +2388,24 @@ namespace cimg_library_suffixed {
2273 2388 CImgArgumentException(const char *const format, ...) { _cimg_exception_err("CImgArgumentException",true); }
2274 2389 };
2275 2390  
2276   - // The CImgIOException class is used to throw an exception related
2277   - // to input/output file problems encountered in a library function call.
2278   - struct CImgIOException : public CImgException {
2279   - CImgIOException(const char *const format, ...) { _cimg_exception_err("CImgIOException",true); }
2280   - };
2281   -
2282 2391 // The CImgDisplayException class is used to throw an exception related
2283 2392 // to display problems encountered in a library function call.
2284 2393 struct CImgDisplayException : public CImgException {
2285 2394 CImgDisplayException(const char *const format, ...) { _cimg_exception_err("CImgDisplayException",false); }
2286 2395 };
2287 2396  
  2397 + // The CImgInstanceException class is used to throw an exception related
  2398 + // to an invalid instance encountered in a library function call.
  2399 + struct CImgInstanceException : public CImgException {
  2400 + CImgInstanceException(const char *const format, ...) { _cimg_exception_err("CImgInstanceException",true); }
  2401 + };
  2402 +
  2403 + // The CImgIOException class is used to throw an exception related
  2404 + // to input/output file problems encountered in a library function call.
  2405 + struct CImgIOException : public CImgException {
  2406 + CImgIOException(const char *const format, ...) { _cimg_exception_err("CImgIOException",true); }
  2407 + };
  2408 +
2288 2409 // The CImgWarningException class is used to throw an exception for warnings
2289 2410 // encountered in a library function call.
2290 2411 struct CImgWarningException : public CImgException {
... ... @@ -2497,10 +2618,22 @@ namespace cimg_library_suffixed {
2497 2618 return !(val==val);
2498 2619 #endif
2499 2620 }
2500   - static double min() { return -1.7E308; }
2501   - static double max() { return 1.7E308; }
2502   - static double inf() { return max()*max(); }
2503   - static double nan() { const double val_nan = -std::sqrt(-1.0); return val_nan; }
  2621 + static double min() { return -DBL_MAX; }
  2622 + static double max() { return DBL_MAX; }
  2623 + static double inf() {
  2624 +#ifdef INFINITY
  2625 + return (double)INFINITY;
  2626 +#else
  2627 + return max()*max();
  2628 +#endif
  2629 + }
  2630 + static double nan() {
  2631 +#ifdef NAN
  2632 + return (double)NAN;
  2633 +#else
  2634 + const double val_nan = -std::sqrt(-1.0); return val_nan;
  2635 +#endif
  2636 + }
2504 2637 static double cut(const double val) { return val<min()?min():val>max()?max():val; }
2505 2638 static const char* format() { return "%.16g"; }
2506 2639 static double format(const double val) { return val; }
... ... @@ -2523,8 +2656,8 @@ namespace cimg_library_suffixed {
2523 2656 return !(val==val);
2524 2657 #endif
2525 2658 }
2526   - static float min() { return -3.4E38f; }
2527   - static float max() { return 3.4E38f; }
  2659 + static float min() { return -FLT_MAX; }
  2660 + static float max() { return FLT_MAX; }
2528 2661 static float inf() { return (float)cimg::type<double>::inf(); }
2529 2662 static float nan() { return (float)cimg::type<double>::nan(); }
2530 2663 static float cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(float)val; }
... ... @@ -2532,6 +2665,32 @@ namespace cimg_library_suffixed {
2532 2665 static double format(const float val) { return (double)val; }
2533 2666 };
2534 2667  
  2668 + template<> struct type<long double> {
  2669 + static const char* string() { static const char *const s = "long double"; return s; }
  2670 + static bool is_float() { return true; }
  2671 + static bool is_inf(const long double val) {
  2672 +#ifdef isinf
  2673 + return (bool)isinf(val);
  2674 +#else
  2675 + return !is_nan(val) && (val<cimg::type<long double>::min() || val>cimg::type<long double>::max());
  2676 +#endif
  2677 + }
  2678 + static bool is_nan(const long double val) {
  2679 +#ifdef isnan
  2680 + return (bool)isnan(val);
  2681 +#else
  2682 + return !(val==val);
  2683 +#endif
  2684 + }
  2685 + static long double min() { return -LDBL_MAX; }
  2686 + static long double max() { return LDBL_MAX; }
  2687 + static long double inf() { return max()*max(); }
  2688 + static long double nan() { const long double val_nan = -std::sqrt(-1.0L); return val_nan; }
  2689 + static long double cut(const long double val) { return val<min()?min():val>max()?max():val; }
  2690 + static const char* format() { return "%.16g"; }
  2691 + static double format(const long double val) { return (double)val; }
  2692 + };
  2693 +
2535 2694 template<typename T, typename t> struct superset { typedef T type; };
2536 2695 template<> struct superset<bool,unsigned char> { typedef unsigned char type; };
2537 2696 template<> struct superset<bool,char> { typedef char type; };
... ... @@ -3015,7 +3174,7 @@ namespace cimg_library_suffixed {
3015 3174 const double PI = 3.14159265358979323846; //!< Value of the mathematical constant PI
3016 3175  
3017 3176 // Define a 12x13 font (small size).
3018   - const char *const data_font12x13 =
  3177 + static const char *const data_font12x13 =
3019 3178 " .wjwlwmyuw>wjwkwbwjwkwRxuwmwjwkwmyuwJwjwlx`w Fw mwlwlwuwnwuynwuwmyTwlwkwuwmwuwnwlwkwuwmwuw_wuxl"
3020 3179 "wlwkwuwnwuynwuwTwlwlwtwnwtwnw my Qw +wlw b{ \\w Wx`xTw_w[wbxawSwkw nynwky<x1w `y ,w Xwuw CxlwiwlwmyuwbwuwUwiwlwbwiwrwqw^wuwmxuwnwiwlwmy"
3021 3180 "uwJwiwlw^wnwEymymymymy1w^wkxnxtxnw<| gybwkwuwjwtwowmxswnxnwkxlxkw:wlymxlymykwn{myo{nymy2ykwqwqwm{myozn{o{mzpwrwpwkwkwswowkwqwqxswnyozlyozmzp}pwrwqwqwq"
... ... @@ -3055,7 +3214,7 @@ namespace cimg_library_suffixed {
3055 3214 "wlxm";
3056 3215  
3057 3216 // Define a 20x23 font (normal size).
3058   - const char *const data_font20x23 =
  3217 + static const char *const data_font20x23 =
3059 3218 " 9q\\q^r_rnp`qnq`plp7q\\q^q_qmqbq\\q^q_qmqHqmp_q\\q^r_rnp`qnq7q\\q^q_qmq_q \"r "
3060 3219 " 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 "
3061 3220 " 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"
... ... @@ -3123,7 +3282,7 @@ namespace cimg_library_suffixed {
3123 3282 "r^q *q kr i";
3124 3283  
3125 3284 // Define a 47x53 font (extra-large size).
3126   - const char *const data_font47x53 =
  3285 + static const char *const data_font47x53 =
3127 3286 " "
3128 3287 " 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] "
3129 3288 " U]*\\2a4`V\\8^U^5a F]*\\1\\X\\4^U^=]*\\"
... ... @@ -3316,7 +3475,7 @@ namespace cimg_library_suffixed {
3316 3475 " F]']2] +]']2^ D]']3_ E]']1] \"]']2^ 8] H";
3317 3476  
3318 3477 // Define a 90x103 font (huge size).
3319   - const char *const _data_font90x103[] = { // Defined as an array to avoid MS compiler limit about constant string (65Kb).
  3478 + static const char *const _data_font90x103[] = { // Defined as an array to avoid MS compiler limit about constant string (65Kb).
3320 3479 // Start of first string.
3321 3480 " "
3322 3481 " "
... ... @@ -3856,7 +4015,7 @@ namespace cimg_library_suffixed {
3856 4015 " D" };
3857 4016  
3858 4017 // Define a 40x38 'danger' color logo (used by cimg::dialog()).
3859   - const unsigned char logo40x38[4576] = {
  4018 + static const unsigned char logo40x38[4576] = {
3860 4019 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,
3861 4020 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,
3862 4021 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,
... ... @@ -3882,23 +4041,6 @@ namespace cimg_library_suffixed {
3882 4041 0,4,123,123,123,10,200,200,200,1,123,123,0,24,0,0,0,5,123,123,123,12,200,200,200,27,123,123,123,14,200,200,200,25,
3883 4042 123,123,123,86,200,200,200,91,49,124,118,124,71,32,124,95,49,56,114,52,82,121,0 };
3884 4043  
3885   - // Mutex-protected version of sscanf.
3886   - // Used only MacOSX, as it seems std::sscanf() is not re-entrant on MacOSX.
3887   -#if (__MACOSX__) || defined(__APPLE__)
3888   -#define cimg_sscanf cimg::_sscanf
3889   - inline int _sscanf(const char *s, const char *format, ...) {
3890   - cimg::mutex(13);
3891   - va_list args;
3892   - va_start(args, format);
3893   - const int result = std::vsscanf(s,format,args);
3894   - va_end(args);
3895   - cimg::mutex(13,0);
3896   - return result;
3897   - }
3898   -#else
3899   -#define cimg_sscanf std::sscanf
3900   -#endif
3901   -
3902 4044 //! Get/set default output stream for the \CImg library messages.
3903 4045 /**
3904 4046 \param file Desired output stream. Set to \c 0 to get the currently used output stream only.
... ... @@ -3980,7 +4122,7 @@ namespace cimg_library_suffixed {
3980 4122 return -1;
3981 4123 #else
3982 4124 #if cimg_OS==1
3983   - const unsigned int l = std::strlen(command);
  4125 + const unsigned int l = (unsigned int)std::strlen(command);
3984 4126 if (l) {
3985 4127 char *const ncommand = new char[l + 16];
3986 4128 std::strncpy(ncommand,command,l);
... ... @@ -4243,8 +4385,9 @@ namespace cimg_library_suffixed {
4243 4385 _rand(seed,true);
4244 4386 }
4245 4387  
4246   - inline double rand() {
4247   - return cimg::_rand()/16777215.;
  4388 + inline double rand(const double val_min, const double val_max) {
  4389 + const double val = cimg::_rand()/16777215.;
  4390 + return val_min + (val_max - val_min)*val;
4248 4391 }
4249 4392  
4250 4393 #else
... ... @@ -4265,19 +4408,20 @@ namespace cimg_library_suffixed {
4265 4408 std::srand(seed);
4266 4409 }
4267 4410  
4268   - //! Return a random variable between [0,1] with respect to an uniform distribution.
  4411 + //! Return a random variable uniformely distributed between [val_min,val_max].
4269 4412 /**
4270 4413 **/
4271   - inline double rand() {
4272   - return (double)std::rand()/RAND_MAX;
  4414 + inline double rand(const double val_min, const double val_max) {
  4415 + const double val = (double)std::rand()/RAND_MAX;
  4416 + return val_min + (val_max - val_min)*val;
4273 4417 }
4274 4418 #endif
4275 4419  
4276   - //! Return a random variable between [-1,1] with respect to an uniform distribution.
  4420 + //! Return a random variable uniformely distributed between [0,val_max].
4277 4421 /**
4278   - **/
4279   - inline double crand() {
4280   - return 1 - 2*cimg::rand();
  4422 + **/
  4423 + inline double rand(const double val_max=1) {
  4424 + return cimg::rand(0,val_max);
4281 4425 }
4282 4426  
4283 4427 //! Return a random variable following a gaussian distribution and a standard deviation of 1.
... ... @@ -4286,8 +4430,8 @@ namespace cimg_library_suffixed {
4286 4430 inline double grand() {
4287 4431 double x1, w;
4288 4432 do {
4289   - const double x2 = 2*cimg::rand() - 1.0;
4290   - x1 = 2*cimg::rand() - 1.0;
  4433 + const double x2 = cimg::rand(-1,1);
  4434 + x1 = cimg::rand(-1,1);
4291 4435 w = x1*x1 + x2*x2;
4292 4436 } while (w<=0 || w>=1.0);
4293 4437 return x1*std::sqrt((-2*std::log(w))/w);
... ... @@ -4319,6 +4463,10 @@ namespace cimg_library_suffixed {
4319 4463 return (double)rol((long)a,n);
4320 4464 }
4321 4465  
  4466 + inline double rol(const long double a, const unsigned int n=1) {
  4467 + return (double)rol((long)a,n);
  4468 + }
  4469 +
4322 4470 //! Bitwise-rotate value on the right.
4323 4471 template<typename T>
4324 4472 inline T ror(const T& a, const unsigned int n=1) {
... ... @@ -4333,6 +4481,10 @@ namespace cimg_library_suffixed {
4333 4481 return (double)ror((long)a,n);
4334 4482 }
4335 4483  
  4484 + inline double ror(const long double a, const unsigned int n=1) {
  4485 + return (double)ror((long)a,n);
  4486 + }
  4487 +
4336 4488 //! Return absolute value of a value.
4337 4489 template<typename T>
4338 4490 inline T abs(const T& a) {
... ... @@ -4515,11 +4667,12 @@ namespace cimg_library_suffixed {
4515 4667 else { const double tmp = absa/absb; return absb==0?0:absb*std::sqrt(1.0 + tmp*tmp); }
4516 4668 }
4517 4669  
4518   - inline bool _is_self_expr(const char *expression) {
4519   - if (!expression || *expression=='>' || *expression=='<') return false;
4520   - for (const char *s = expression; *s; ++s)
4521   - if ((*s=='i' || *s=='j') && (s[1]=='(' || s[1]=='[')) return true;
4522   - return false;
  4670 + //! Return sqrt(x^2 + y^2).
  4671 + inline double hypot(const double x, const double y) {
  4672 + double nx = cimg::abs(x), ny = cimg::abs(y), t;
  4673 + if (nx<ny) { t = nx; nx = ny; } else t = ny;
  4674 + if (nx>0) { t/=nx; return nx*std::sqrt(1+t*t); }
  4675 + return 0;
4523 4676 }
4524 4677  
4525 4678 //! Convert ascii character to lower case.
... ... @@ -4575,6 +4728,51 @@ namespace cimg_library_suffixed {
4575 4728 return cimg::strncasecmp(str1,str2,1 + (l1<l2?l1:l2));
4576 4729 }
4577 4730  
  4731 + //! Ellipsize a string.
  4732 + /**
  4733 + \param str C-string.
  4734 + \param l Max number of characters.
  4735 + \param is_ending Tell if the dots are placed at the end or at the center of the ellipsized string.
  4736 + **/
  4737 + inline char *strellipsize(char *const str, const unsigned int l=64,
  4738 + const bool is_ending=true) {
  4739 + if (!str) return str;
  4740 + const unsigned int nl = l<5?5:l, ls = (unsigned int)std::strlen(str);
  4741 + if (ls<=nl) return str;
  4742 + if (is_ending) std::strcpy(str + nl - 5,"(...)");
  4743 + else {
  4744 + const unsigned int ll = (nl - 5)/2 + 1 - (nl%2), lr = nl - ll - 5;
  4745 + std::strcpy(str + ll,"(...)");
  4746 + std::memmove(str + ll + 5,str + ls - lr,lr);
  4747 + }
  4748 + str[nl] = 0;
  4749 + return str;
  4750 + }
  4751 +
  4752 + //! Ellipsize a string.
  4753 + /**
  4754 + \param str C-string.
  4755 + \param res output C-string.
  4756 + \param l Max number of characters.
  4757 + \param is_ending Tell if the dots are placed at the end or at the center of the ellipsized string.
  4758 + **/
  4759 + inline char *strellipsize(const char *const str, char *const res, const unsigned int l=64,
  4760 + const bool is_ending=true) {
  4761 + const unsigned int nl = l<5?5:l, ls = (unsigned int)std::strlen(str);
  4762 + if (ls<=nl) { std::strcpy(res,str); return res; }
  4763 + if (is_ending) {
  4764 + std::strncpy(res,str,nl - 5);
  4765 + std::strcpy(res + nl -5,"(...)");
  4766 + } else {
  4767 + const unsigned int ll = (nl - 5)/2 + 1 - (nl%2), lr = nl - ll - 5;
  4768 + std::strncpy(res,str,ll);
  4769 + std::strcpy(res + ll,"(...)");
  4770 + std::strncpy(res + ll + 5,str + ls - lr,lr);
  4771 + }
  4772 + res[nl] = 0;
  4773 + return res;
  4774 + }
  4775 +
4578 4776 //! Remove delimiters on the start and/or end of a C-string.
4579 4777 /**
4580 4778 \param[in,out] str C-string to work with (modified at output).
... ... @@ -4638,7 +4836,7 @@ namespace cimg_library_suffixed {
4638 4836 *nd = (char)val; break;
4639 4837 case 'x' :
4640 4838 cimg_sscanf(++ns,"%x",&val);
4641   - while ((*ns>='0' && *ns<='7') || (*ns>='a' && *ns<='f') || (*ns>='A' && *ns<='F')) ++ns;
  4839 + while ((*ns>='0' && *ns<='9') || (*ns>='a' && *ns<='f') || (*ns>='A' && *ns<='F')) ++ns;
4642 4840 *nd = (char)val; break;
4643 4841 default : *nd = *(ns++);
4644 4842 } else *nd = *(ns++);
... ... @@ -4650,20 +4848,20 @@ namespace cimg_library_suffixed {
4650 4848 // Return string that identifies the running OS.
4651 4849 inline const char *stros() {
4652 4850 #if defined(linux) || defined(__linux) || defined(__linux__)
4653   - const char *const str = "Linux";
  4851 + static const char *const str = "Linux";
4654 4852 #elif defined(sun) || defined(__sun)
4655   - const char *const str = "Sun OS";
  4853 + static const char *const str = "Sun OS";
4656 4854 #elif defined(BSD) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined (__DragonFly__)
4657   - const char *const str = "BSD";
  4855 + static const char *const str = "BSD";
4658 4856 #elif defined(sgi) || defined(__sgi)
4659   - const char *const str = "Irix";
  4857 + static const char *const str = "Irix";
4660 4858 #elif defined(__MACOSX__) || defined(__APPLE__)
4661   - const char *const str = "Mac OS";
  4859 + static const char *const str = "Mac OS";
4662 4860 #elif defined(unix) || defined(__unix) || defined(__unix__)
4663   - const char *const str = "Generic Unix";
  4861 + static const char *const str = "Generic Unix";
4664 4862 #elif defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || \
4665 4863 defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
4666   - const char *const str = "Windows";
  4864 + static const char *const str = "Windows";
4667 4865 #else
4668 4866 const char
4669 4867 *const _str1 = std::getenv("OSTYPE"),
... ... @@ -4683,11 +4881,12 @@ namespace cimg_library_suffixed {
4683 4881 // Return a random filename.
4684 4882 inline const char* filenamerand() {
4685 4883 cimg::mutex(6);
4686   - static char randomid[9] = { 0 };
  4884 + static char randomid[9];
4687 4885 cimg::srand();
4688 4886 for (unsigned int k = 0; k<8; ++k) {
4689   - const int v = (int)std::rand()%3;
4690   - randomid[k] = (char)(v==0?('0' + (std::rand()%10)):(v==1?('a' + (std::rand()%26)):('A' + (std::rand()%26))));
  4887 + const int v = (int)cimg::rand(65535)%3;
  4888 + randomid[k] = (char)(v==0?('0' + ((int)cimg::rand(65535)%10)):
  4889 + (v==1?('a' + ((int)cimg::rand(65535)%26)):('A' + ((int)cimg::rand(65535)%26))));
4691 4890 }
4692 4891 cimg::mutex(6,0);
4693 4892 return randomid;
... ... @@ -4815,7 +5014,7 @@ namespace cimg_library_suffixed {
4815 5014 Can be { 0=year | 1=month | 2=day | 3=day of week | 4=hour | 5=minute | 6=second }
4816 5015 **/
4817 5016 inline int date(const unsigned int attr) {
4818   - int res = -1;
  5017 + int res;
4819 5018 cimg::mutex(6);
4820 5019 #if cimg_OS==2
4821 5020 SYSTEMTIME st;
... ... @@ -4892,7 +5091,7 @@ namespace cimg_library_suffixed {
4892 5091 const char *const ext = cimg::split_filename(filename,body);
4893 5092 if (*ext) cimg_snprintf(format,1024,"%%s_%%.%ud.%%s",digits);
4894 5093 else cimg_snprintf(format,1024,"%%s_%%.%ud",digits);
4895   - std::sprintf(str,format,body,number,ext);
  5094 + cimg_sprintf(str,format,body,number,ext);
4896 5095 delete[] format; delete[] body;
4897 5096 return str;
4898 5097 }
... ... @@ -4970,7 +5169,8 @@ namespace cimg_library_suffixed {
4970 5169  
4971 5170 // Load file from network as a local temporary file.
4972 5171 inline char *load_network(const char *const url, char *const filename_local,
4973   - const unsigned int timeout=0, const bool try_fallback=false);
  5172 + const unsigned int timeout=0, const bool try_fallback=false,
  5173 + const char *const referer=0);
4974 5174  
4975 5175 //! Return options specified on the command line.
4976 5176 inline const char* option(const char *const name, const int argc, const char *const *const argv,
... ... @@ -5033,8 +5233,8 @@ namespace cimg_library_suffixed {
5033 5233 const char defaut, const char *const usage=0) {
5034 5234 const char *const s = cimg::option(name,argc,argv,(char*)0);
5035 5235 const char res = s?*s:defaut;
5036   - char tmp[8] = { 0 };
5037   - *tmp = res;
  5236 + char tmp[8];
  5237 + *tmp = res; tmp[1] = 0;
5038 5238 cimg::option(name,0,0,tmp,usage);
5039 5239 return res;
5040 5240 }
... ... @@ -5061,25 +5261,6 @@ namespace cimg_library_suffixed {
5061 5261 return res;
5062 5262 }
5063 5263  
5064   - inline const char* argument(const unsigned int nb, const int argc, const char *const *const argv,
5065   - const unsigned int nb_singles=0, ...) {
5066   - for (int k = 1, pos = 0; k<argc;) {
5067   - const char *const item = argv[k];
5068   - bool option = (*item=='-'), single_option = false;
5069   - if (option) {
5070   - va_list ap;
5071   - va_start(ap,nb_singles);
5072   - for (unsigned int i = 0; i<nb_singles; ++i) if (!cimg::strcasecmp(item,va_arg(ap,char*))) {
5073   - single_option = true; break;
5074   - }
5075   - va_end(ap);
5076   - }
5077   - if (option) { ++k; if (!single_option) ++k; }
5078   - else { if (pos++==(int)nb) return item; else ++k; }
5079   - }
5080   - return 0;
5081   - }
5082   -
5083 5264 //! Print information about \CImg environement variables.
5084 5265 /**
5085 5266 \note Output is done on the default output stream.
... ... @@ -5372,6 +5553,7 @@ namespace cimg_library_suffixed {
5372 5553 _cimg_create_ext_operators(long)
5373 5554 _cimg_create_ext_operators(float)
5374 5555 _cimg_create_ext_operators(double)
  5556 + _cimg_create_ext_operators(long double)
5375 5557  
5376 5558 template<typename T>
5377 5559 inline CImg<_cimg_Tfloat> operator+(const char *const expression, const CImg<T>& img) {
... ... @@ -5380,7 +5562,7 @@ namespace cimg_library_suffixed {
5380 5562  
5381 5563 template<typename T>
5382 5564 inline CImg<_cimg_Tfloat> operator-(const char *const expression, const CImg<T>& img) {
5383   - return CImg<_cimg_Tfloat>(img._width,img._height,img._depth,img._spectrum,expression,true)-=img;
  5565 + return CImg<_cimg_Tfloat>(img,false).fill(expression,true)-=img;
5384 5566 }
5385 5567  
5386 5568 template<typename T>
... ... @@ -5410,12 +5592,12 @@ namespace cimg_library_suffixed {
5410 5592  
5411 5593 template<typename T>
5412 5594 inline bool operator==(const char *const expression, const CImg<T>& img) {
5413   - return img == expression;
  5595 + return img==expression;
5414 5596 }
5415 5597  
5416 5598 template<typename T>
5417 5599 inline bool operator!=(const char *const expression, const CImg<T>& img) {
5418   - return img != expression;
  5600 + return img!=expression;
5419 5601 }
5420 5602  
5421 5603 template<typename T>
... ... @@ -5528,7 +5710,7 @@ namespace cimg_library_suffixed {
5528 5710 # Define the CImgDisplay structure
5529 5711 #
5530 5712 ----------------------------------*/
5531   - //! Allow to create windows, display images on them and manage user events (keyboard, mouse and windows events).
  5713 + //! Allow the creation of windows, display images on them and manage user events (keyboard, mouse and windows events).
5532 5714 /**
5533 5715 CImgDisplay methods rely on a low-level graphic library to perform: it can be either \b X-Window
5534 5716 (X11, for Unix-based systems) or \b GDI32 (for Windows-based systems).
... ... @@ -5802,6 +5984,12 @@ namespace cimg_library_suffixed {
5802 5984 return _empty.assign();
5803 5985 }
5804 5986  
  5987 + //! Return a reference to an empty display \const.
  5988 + static const CImgDisplay& const_empty() {
  5989 + static const CImgDisplay _empty;
  5990 + return _empty;
  5991 + }
  5992 +
5805 5993 #define cimg_fitscreen(dx,dy,dz) CImgDisplay::_fitscreen(dx,dy,dz,128,-85,false), \
5806 5994 CImgDisplay::_fitscreen(dx,dy,dz,128,-85,true)
5807 5995 static unsigned int _fitscreen(const unsigned int dx, const unsigned int dy, const unsigned int dz,
... ... @@ -6191,7 +6379,7 @@ namespace cimg_library_suffixed {
6191 6379 in fullscreen mode.
6192 6380 **/
6193 6381 const char *title() const {
6194   - return _title;
  6382 + return _title?_title:"";
6195 6383 }
6196 6384  
6197 6385 //! Return width of the associated window.
... ... @@ -7136,7 +7324,7 @@ namespace cimg_library_suffixed {
7136 7324 XEvent event;
7137 7325 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,0);
7138 7326 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,0);
7139   - if (!arg) for (;;) {
  7327 + if (!arg) for ( ; ; ) {
7140 7328 cimg_lock_display();
7141 7329 bool event_flag = XCheckTypedEvent(dpy,ClientMessage,&event);
7142 7330 if (!event_flag) event_flag = XCheckMaskEvent(dpy,
... ... @@ -7397,7 +7585,7 @@ namespace cimg_library_suffixed {
7397 7585  
7398 7586 // Allocate space for window title
7399 7587 const char *const nptitle = ptitle?ptitle:"";
7400   - const unsigned int s = std::strlen(nptitle) + 1;
  7588 + const unsigned int s = (unsigned int)std::strlen(nptitle) + 1;
7401 7589 char *const tmp_title = s?new char[s]:0;
7402 7590 if (s) std::memcpy(tmp_title,nptitle,s*sizeof(char));
7403 7591  
... ... @@ -7535,7 +7723,7 @@ namespace cimg_library_suffixed {
7535 7723 // Remove display window from event thread list.
7536 7724 unsigned int i;
7537 7725 for (i = 0; i<cimg::X11_attr().nb_wins && cimg::X11_attr().wins[i]!=this; ++i) {}
7538   - for (; i<cimg::X11_attr().nb_wins - 1; ++i) cimg::X11_attr().wins[i] = cimg::X11_attr().wins[i + 1];
  7726 + for ( ; i<cimg::X11_attr().nb_wins - 1; ++i) cimg::X11_attr().wins[i] = cimg::X11_attr().wins[i + 1];
7539 7727 --cimg::X11_attr().nb_wins;
7540 7728  
7541 7729 // Destroy window, image, colormap and title.
... ... @@ -7630,24 +7818,27 @@ namespace cimg_library_suffixed {
7630 7818 tmpdimy = (nheight>0)?nheight:(-nheight*height()/100),
7631 7819 dimx = tmpdimx?tmpdimx:1,
7632 7820 dimy = tmpdimy?tmpdimy:1;
7633   - cimg_lock_display();
7634   - if (_window_width!=dimx || _window_height!=dimy) {
7635   - XWindowAttributes attr;
7636   - for (unsigned int i = 0; i<10; ++i) {
7637   - XResizeWindow(dpy,_window,dimx,dimy);
7638   - XGetWindowAttributes(dpy,_window,&attr);
7639   - if (attr.width==(int)dimx && attr.height==(int)dimy) break;
7640   - cimg::wait(5);
  7821 + if (_width!=dimx || _height!=dimy || _window_width!=dimx || _window_height!=dimy) {
  7822 + show();
  7823 + cimg_lock_display();
  7824 + if (_window_width!=dimx || _window_height!=dimy) {
  7825 + XWindowAttributes attr;
  7826 + for (unsigned int i = 0; i<10; ++i) {
  7827 + XResizeWindow(dpy,_window,dimx,dimy);
  7828 + XGetWindowAttributes(dpy,_window,&attr);
  7829 + if (attr.width==(int)dimx && attr.height==(int)dimy) break;
  7830 + cimg::wait(5);
  7831 + }
7641 7832 }
  7833 + if (_width!=dimx || _height!=dimy) switch (cimg::X11_attr().nb_bits) {
  7834 + case 8 : { unsigned char pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); } break;
  7835 + case 16 : { unsigned short pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); } break;
  7836 + default : { unsigned int pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); }
  7837 + }
  7838 + _window_width = _width = dimx; _window_height = _height = dimy;
  7839 + cimg_unlock_display();
7642 7840 }
7643   - if (_width!=dimx || _height!=dimy) switch (cimg::X11_attr().nb_bits) {
7644   - case 8 : { unsigned char pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); } break;
7645   - case 16 : { unsigned short pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); } break;
7646   - default : { unsigned int pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); }
7647   - }
7648   - _window_width = _width = dimx; _window_height = _height = dimy;
7649 7841 _is_resized = false;
7650   - cimg_unlock_display();
7651 7842 if (_is_fullscreen) move((screen_width() - _width)/2,(screen_height() - _height)/2);
7652 7843 if (force_redraw) return paint();
7653 7844 return *this;
... ... @@ -7692,13 +7883,15 @@ namespace cimg_library_suffixed {
7692 7883  
7693 7884 CImgDisplay& move(const int posx, const int posy) {
7694 7885 if (is_empty()) return *this;
7695   - show();
7696   - Display *const dpy = cimg::X11_attr().display;
7697   - cimg_lock_display();
7698   - XMoveWindow(dpy,_window,posx,posy);
7699   - _window_x = posx; _window_y = posy;
  7886 + if (_window_x!=posx || _window_y!=posy) {
  7887 + show();
  7888 + Display *const dpy = cimg::X11_attr().display;
  7889 + cimg_lock_display();
  7890 + XMoveWindow(dpy,_window,posx,posy);
  7891 + _window_x = posx; _window_y = posy;
  7892 + cimg_unlock_display();
  7893 + }
7700 7894 _is_moved = false;
7701   - cimg_unlock_display();
7702 7895 return paint();
7703 7896 }
7704 7897  
... ... @@ -7715,7 +7908,7 @@ namespace cimg_library_suffixed {
7715 7908 if (is_empty()) return *this;
7716 7909 Display *const dpy = cimg::X11_attr().display;
7717 7910 cimg_lock_display();
7718   - const char pix_data[8] = { 0 };
  7911 + static const char pix_data[8] = { 0 };
7719 7912 XColor col;
7720 7913 col.red = col.green = col.blue = 0;
7721 7914 Pixmap pix = XCreateBitmapFromData(dpy,_window,pix_data,8,8);
... ... @@ -7747,7 +7940,7 @@ namespace cimg_library_suffixed {
7747 7940 va_end(ap);
7748 7941 if (!std::strcmp(_title,tmp)) { delete[] tmp; return *this; }
7749 7942 delete[] _title;
7750   - const unsigned int s = std::strlen(tmp) + 1;
  7943 + const unsigned int s = (unsigned int)std::strlen(tmp) + 1;
7751 7944 _title = new char[s];
7752 7945 std::memcpy(_title,tmp,s*sizeof(char));
7753 7946 Display *const dpy = cimg::X11_attr().display;
... ... @@ -8269,7 +8462,9 @@ namespace cimg_library_suffixed {
8269 8462 } break;
8270 8463 case WM_PAINT :
8271 8464 disp->paint();
  8465 + cimg::mutex(15);
8272 8466 if (disp->_is_cursor_visible) while (ShowCursor(TRUE)<0); else while (ShowCursor(FALSE)>=0);
  8467 + cimg::mutex(15,0);
8273 8468 break;
8274 8469 case WM_ERASEBKGND :
8275 8470 // return 0;
... ... @@ -8299,12 +8494,16 @@ namespace cimg_library_suffixed {
8299 8494 disp->_mouse_x = disp->_mouse_y = -1;
8300 8495 disp->_is_event = true;
8301 8496 SetEvent(cimg::Win32_attr().wait_event);
  8497 + cimg::mutex(15);
8302 8498 if (disp->_is_cursor_visible) while (ShowCursor(TRUE)<0); else while (ShowCursor(FALSE)>=0);
  8499 + cimg::mutex(15,0);
8303 8500 } break;
8304 8501 case WM_MOUSELEAVE : {
8305 8502 disp->_mouse_x = disp->_mouse_y = -1;
8306 8503 disp->_is_mouse_tracked = false;
  8504 + cimg::mutex(15);
8307 8505 while (ShowCursor(TRUE)<0);
  8506 + cimg::mutex(15,0);
8308 8507 } break;
8309 8508 case WM_LBUTTONDOWN :
8310 8509 disp->set_button(1);
... ... @@ -8563,24 +8762,27 @@ namespace cimg_library_suffixed {
8563 8762 tmpdimy = (nheight>0)?nheight:(-nheight*_height/100),
8564 8763 dimx = tmpdimx?tmpdimx:1,
8565 8764 dimy = tmpdimy?tmpdimy:1;
8566   - if (_window_width!=dimx || _window_height!=dimy) {
8567   - RECT rect; rect.left = rect.top = 0; rect.right = (LONG)dimx - 1; rect.bottom = (LONG)dimy - 1;
8568   - AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false);
8569   - const int cwidth = rect.right - rect.left + 1, cheight = rect.bottom - rect.top + 1;
8570   - SetWindowPos(_window,0,0,0,cwidth,cheight,SWP_NOMOVE | SWP_NOZORDER | SWP_NOCOPYBITS);
8571   - }
8572   - if (_width!=dimx || _height!=dimy) {
8573   - unsigned int *const ndata = new unsigned int[dimx*dimy];
8574   - if (force_redraw) _render_resize(_data,_width,_height,ndata,dimx,dimy);
8575   - else std::memset(ndata,0x80,sizeof(unsigned int)*dimx*dimy);
8576   - delete[] _data;
8577   - _data = ndata;
8578   - _bmi.bmiHeader.biWidth = (LONG)dimx;
8579   - _bmi.bmiHeader.biHeight = -(int)dimy;
8580   - _width = dimx;
8581   - _height = dimy;
  8765 + if (_width!=dimx || _height!=dimy || _window_width!=dimx || _window_height!=dimy) {
  8766 + if (_window_width!=dimx || _window_height!=dimy) {
  8767 + RECT rect; rect.left = rect.top = 0; rect.right = (LONG)dimx - 1; rect.bottom = (LONG)dimy - 1;
  8768 + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false);
  8769 + const int cwidth = rect.right - rect.left + 1, cheight = rect.bottom - rect.top + 1;
  8770 + SetWindowPos(_window,0,0,0,cwidth,cheight,SWP_NOMOVE | SWP_NOZORDER | SWP_NOCOPYBITS);
  8771 + }
  8772 + if (_width!=dimx || _height!=dimy) {
  8773 + unsigned int *const ndata = new unsigned int[dimx*dimy];
  8774 + if (force_redraw) _render_resize(_data,_width,_height,ndata,dimx,dimy);
  8775 + else std::memset(ndata,0x80,sizeof(unsigned int)*dimx*dimy);
  8776 + delete[] _data;
  8777 + _data = ndata;
  8778 + _bmi.bmiHeader.biWidth = (LONG)dimx;
  8779 + _bmi.bmiHeader.biHeight = -(int)dimy;
  8780 + _width = dimx;
  8781 + _height = dimy;
  8782 + }
  8783 + _window_width = dimx; _window_height = dimy;
  8784 + show();
8582 8785 }
8583   - _window_width = dimx; _window_height = dimy;
8584 8786 _is_resized = false;
8585 8787 if (_is_fullscreen) move((screen_width() - width())/2,(screen_height() - height())/2);
8586 8788 if (force_redraw) return paint();
... ... @@ -8623,19 +8825,22 @@ namespace cimg_library_suffixed {
8623 8825  
8624 8826 CImgDisplay& move(const int posx, const int posy) {
8625 8827 if (is_empty()) return *this;
8626   - if (!_is_fullscreen) {
8627   - RECT rect;
8628   - rect.left = rect.top = 0; rect.right = (LONG)_window_width - 1; rect.bottom = (LONG)_window_height - 1;
8629   - AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false);
8630   - const int
8631   - border1 = (int)((rect.right - rect.left + 1 -_width)/2),
8632   - border2 = (int)(rect.bottom - rect.top + 1 - _height - border1);
8633   - SetWindowPos(_window,0,posx - border1,posy - border2,0,0,SWP_NOSIZE | SWP_NOZORDER);
8634   - } else SetWindowPos(_window,0,posx,posy,0,0,SWP_NOSIZE | SWP_NOZORDER);
8635   - _window_x = posx;
8636   - _window_y = posy;
  8828 + if (_window_x!=posx || _window_y!=posy) {
  8829 + if (!_is_fullscreen) {
  8830 + RECT rect;
  8831 + rect.left = rect.top = 0; rect.right = (LONG)_window_width - 1; rect.bottom = (LONG)_window_height - 1;
  8832 + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false);
  8833 + const int
  8834 + border1 = (int)((rect.right - rect.left + 1 -_width)/2),
  8835 + border2 = (int)(rect.bottom - rect.top + 1 - _height - border1);
  8836 + SetWindowPos(_window,0,posx - border1,posy - border2,0,0,SWP_NOSIZE | SWP_NOZORDER);
  8837 + } else SetWindowPos(_window,0,posx,posy,0,0,SWP_NOSIZE | SWP_NOZORDER);
  8838 + _window_x = posx;
  8839 + _window_y = posy;
  8840 + show();
  8841 + }
8637 8842 _is_moved = false;
8638   - return show();
  8843 + return *this;
8639 8844 }
8640 8845  
8641 8846 CImgDisplay& show_mouse() {
... ... @@ -8651,7 +8856,7 @@ namespace cimg_library_suffixed {
8651 8856 }
8652 8857  
8653 8858 CImgDisplay& set_mouse(const int posx, const int posy) {
8654   - if (_is_closed || posx<0 || posy<0) return *this;
  8859 + if (is_empty() || _is_closed || posx<0 || posy<0) return *this;
8655 8860 _update_window_pos();
8656 8861 const int res = (int)SetCursorPos(_window_x + posx,_window_y + posy);
8657 8862 if (res) { _mouse_x = posx; _mouse_y = posy; }
... ... @@ -8891,10 +9096,8 @@ namespace cimg_library_suffixed {
8891 9096 - Construct images from C-style arrays:
8892 9097 - <tt>CImg<int> img(data_buffer,256,256);</tt> constructs a 256x256 greyscale image from a \c int* buffer
8893 9098 \c data_buffer (of size 256x256=65536).
8894   - - <tt>CImg<unsigned char> img(data_buffer,256,256,1,3,false);</tt> constructs a 256x256 color image
  9099 + - <tt>CImg<unsigned char> img(data_buffer,256,256,1,3);</tt> constructs a 256x256 color image
8895 9100 from a \c unsigned \c char* buffer \c data_buffer (where R,G,B channels follow each others).
8896   - - <tt>CImg<unsigned char> img(data_buffer,256,256,1,3,true);</tt> constructs a 256x256 color image
8897   - from a \c unsigned \c char* buffer \c data_buffer (where R,G,B channels are multiplexed).
8898 9101  
8899 9102 The complete list of constructors can be found <a href="#constructors">here</a>.
8900 9103  
... ... @@ -8903,7 +9106,7 @@ namespace cimg_library_suffixed {
8903 9106 The \c CImg<T> class contains a lot of functions that operates on images.
8904 9107 Some of the most useful are:
8905 9108  
8906   - - operator()(): allows to access or write pixel values.
  9109 + - operator()(): Read or write pixel values.
8907 9110 - display(): displays the image in a new window.
8908 9111 **/
8909 9112 template<typename T>
... ... @@ -8977,6 +9180,13 @@ namespace cimg_library_suffixed {
8977 9180 typedef typename cimg::last<T,long>::type longT;
8978 9181 typedef typename cimg::last<T,float>::type floatT;
8979 9182 typedef typename cimg::last<T,double>::type doubleT;
  9183 +#if cimg_OS==2
  9184 + typedef typename cimg::last<T,UINT_PTR>::type uptrT; // Unsigned integer type that can store a pointer.
  9185 + typedef typename cimg::last<T,INT_PTR>::type ptrT; // Signed integer type that can store a pointer.
  9186 +#else
  9187 + typedef typename cimg::last<T,unsigned long>::type uptrT;
  9188 + typedef typename cimg::last<T,long>::type ptrT;
  9189 +#endif
8980 9190  
8981 9191 //@}
8982 9192 //---------------------------
... ... @@ -9165,7 +9375,7 @@ namespace cimg_library_suffixed {
9165 9375 *(ptrd++) = (T)a0; \
9166 9376 if (_siz--) { \
9167 9377 *(ptrd++) = (T)a1; \
9168   - for (; _siz; --_siz) *(ptrd++) = (T)va_arg(ap,t); \
  9378 + for ( ; _siz; --_siz) *(ptrd++) = (T)va_arg(ap,t); \
9169 9379 } \
9170 9380 va_end(ap); \
9171 9381 } \
... ... @@ -9174,7 +9384,7 @@ namespace cimg_library_suffixed {
9174 9384 _CImg_stdarg(*this,value0,value1,(unsigned long)size_x*size_y*size_z*size_c,int);
9175 9385 }
9176 9386  
9177   -#ifdef cimg_use_cpp11
  9387 +#if defined(cimg_use_cpp11) && cimg_use_cpp11!=0
9178 9388 //! Construct image with specified size and initialize pixel values from an initializer list of integers.
9179 9389 /**
9180 9390 Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c,
... ... @@ -9423,7 +9633,8 @@ namespace cimg_library_suffixed {
9423 9633 cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c),
9424 9634 size_x,size_y,size_z,size_c);
9425 9635 }
9426   - std::memcpy(_data,values,siz*sizeof(T)); }
  9636 + std::memcpy(_data,values,siz*sizeof(T));
  9637 + }
9427 9638 } else { _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; }
9428 9639 }
9429 9640  
... ... @@ -9629,7 +9840,7 @@ namespace cimg_library_suffixed {
9629 9840  
9630 9841 // Constructor and assignment operator for rvalue references (c++11).
9631 9842 // This avoids an additional image copy for methods returning new images. Can save RAM for big images !
9632   -#ifdef cimg_use_cpp11
  9843 +#if defined(cimg_use_cpp11) && cimg_use_cpp11!=0
9633 9844 CImg(CImg<T>&& img):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
9634 9845 swap(img);
9635 9846 }
... ... @@ -9954,10 +10165,7 @@ namespace cimg_library_suffixed {
9954 10165 \endcode
9955 10166 **/
9956 10167 CImg<T>& swap(CImg<T>& img) {
9957   - cimg::swap(_width,img._width);
9958   - cimg::swap(_height,img._height);
9959   - cimg::swap(_depth,img._depth);
9960   - cimg::swap(_spectrum,img._spectrum);
  10168 + cimg::swap(_width,img._width,_height,img._height,_depth,img._depth,_spectrum,img._spectrum);
9961 10169 cimg::swap(_data,img._data);
9962 10170 cimg::swap(_is_shared,img._is_shared);
9963 10171 return img;
... ... @@ -9977,6 +10185,12 @@ namespace cimg_library_suffixed {
9977 10185 return _empty.assign();
9978 10186 }
9979 10187  
  10188 + //! Return a reference to an empty image \const.
  10189 + static const CImg<T>& const_empty() {
  10190 + static const CImg<T> _empty;