Newer
Older
59001
59002
59003
59004
59005
59006
59007
59008
59009
59010
59011
59012
59013
59014
59015
59016
59017
59018
59019
59020
59021
59022
59023
59024
59025
59026
59027
59028
59029
59030
59031
59032
59033
59034
59035
59036
59037
59038
59039
59040
59041
59042
59043
59044
59045
59046
59047
59048
59049
59050
59051
59052
59053
59054
59055
59056
59057
59058
59059
59060
59061
59062
59063
59064
59065
59066
59067
59068
59069
59070
59071
59072
59073
59074
59075
59076
59077
59078
59079
59080
59081
59082
59083
59084
59085
59086
59087
59088
59089
59090
59091
59092
59093
59094
59095
59096
59097
59098
59099
59100
59101
59102
59103
59104
59105
59106
59107
59108
59109
59110
59111
59112
59113
59114
59115
59116
59117
59118
59119
59120
59121
59122
59123
59124
59125
59126
59127
59128
59129
59130
59131
59132
59133
59134
59135
59136
59137
59138
59139
59140
59141
59142
59143
59144
59145
59146
59147
59148
59149
59150
59151
59152
59153
59154
59155
59156
59157
59158
59159
59160
59161
59162
59163
59164
59165
59166
59167
59168
59169
59170
59171
59172
59173
59174
59175
59176
59177
59178
59179
59180
59181
59182
59183
59184
59185
59186
59187
59188
59189
59190
59191
59192
59193
59194
59195
59196
59197
59198
59199
59200
59201
59202
59203
59204
59205
59206
59207
59208
59209
59210
59211
59212
59213
59214
59215
59216
59217
59218
59219
59220
59221
59222
59223
59224
59225
59226
59227
59228
59229
59230
59231
59232
59233
59234
59235
59236
59237
59238
59239
59240
59241
59242
59243
59244
59245
59246
59247
59248
59249
59250
59251
59252
59253
59254
59255
59256
59257
59258
59259
59260
59261
59262
59263
59264
59265
59266
59267
59268
59269
59270
59271
59272
59273
59274
59275
59276
59277
59278
59279
59280
59281
59282
59283
59284
59285
59286
59287
59288
59289
59290
59291
59292
59293
59294
59295
59296
59297
59298
59299
59300
59301
59302
59303
59304
59305
59306
59307
59308
59309
59310
59311
59312
59313
59314
59315
59316
59317
59318
59319
59320
59321
59322
59323
59324
59325
59326
59327
59328
59329
59330
59331
59332
59333
59334
59335
59336
59337
59338
59339
59340
59341
59342
59343
59344
59345
59346
59347
59348
59349
59350
59351
59352
59353
59354
59355
59356
59357
59358
59359
59360
59361
59362
59363
59364
59365
59366
59367
59368
59369
59370
59371
59372
59373
59374
59375
59376
59377
59378
59379
59380
59381
59382
59383
59384
59385
59386
59387
59388
59389
59390
59391
59392
59393
59394
59395
59396
59397
59398
59399
59400
59401
59402
59403
59404
59405
59406
59407
59408
59409
59410
59411
59412
59413
59414
59415
59416
59417
59418
59419
59420
59421
59422
59423
59424
59425
59426
59427
59428
59429
59430
59431
59432
59433
59434
59435
59436
59437
59438
59439
59440
59441
59442
59443
59444
59445
59446
59447
59448
59449
59450
59451
59452
59453
59454
59455
59456
59457
59458
59459
59460
59461
59462
59463
59464
59465
59466
59467
59468
59469
59470
59471
59472
59473
59474
59475
59476
59477
59478
59479
59480
59481
59482
59483
59484
59485
59486
59487
59488
59489
59490
59491
59492
59493
59494
59495
59496
59497
59498
59499
59500
59501
59502
59503
59504
59505
59506
59507
59508
59509
59510
59511
59512
59513
59514
59515
59516
59517
59518
59519
59520
59521
59522
59523
59524
59525
59526
59527
59528
59529
59530
59531
59532
59533
59534
59535
59536
59537
59538
59539
59540
59541
59542
59543
59544
59545
59546
59547
59548
59549
59550
59551
59552
59553
59554
59555
59556
59557
59558
59559
59560
59561
59562
59563
59564
59565
59566
59567
59568
59569
59570
59571
59572
59573
59574
59575
59576
59577
59578
59579
59580
59581
59582
59583
59584
59585
59586
59587
59588
59589
59590
59591
59592
59593
59594
59595
59596
59597
59598
59599
59600
59601
59602
59603
59604
59605
59606
59607
59608
59609
59610
59611
59612
59613
59614
59615
59616
59617
59618
59619
59620
59621
59622
59623
59624
59625
59626
59627
59628
59629
59630
59631
59632
59633
59634
59635
59636
59637
59638
59639
59640
59641
59642
59643
59644
59645
59646
59647
59648
59649
59650
59651
59652
59653
59654
59655
59656
59657
59658
59659
59660
59661
59662
59663
59664
59665
59666
59667
59668
59669
59670
59671
59672
59673
59674
59675
59676
59677
59678
59679
59680
59681
59682
59683
59684
59685
59686
59687
59688
59689
59690
59691
59692
59693
59694
59695
59696
59697
59698
59699
59700
59701
59702
59703
59704
59705
59706
59707
59708
59709
59710
59711
59712
59713
59714
59715
59716
59717
59718
59719
59720
59721
59722
59723
59724
59725
59726
59727
59728
59729
59730
59731
59732
59733
59734
59735
59736
59737
59738
59739
59740
59741
59742
59743
59744
59745
59746
59747
59748
59749
59750
59751
59752
59753
59754
59755
59756
59757
59758
59759
59760
59761
59762
59763
59764
59765
59766
59767
59768
59769
59770
59771
59772
59773
59774
59775
59776
59777
59778
59779
59780
59781
59782
59783
59784
59785
59786
59787
59788
59789
59790
59791
59792
59793
59794
59795
59796
59797
59798
59799
59800
59801
59802
59803
59804
59805
59806
59807
59808
59809
59810
59811
59812
59813
59814
59815
59816
59817
59818
59819
59820
59821
59822
59823
59824
59825
59826
59827
59828
59829
59830
59831
59832
59833
59834
59835
59836
59837
59838
59839
59840
59841
59842
59843
59844
59845
59846
59847
59848
59849
59850
59851
59852
59853
59854
59855
59856
59857
59858
59859
59860
59861
59862
59863
59864
59865
59866
59867
59868
59869
59870
59871
59872
59873
59874
59875
59876
59877
59878
59879
59880
59881
59882
59883
59884
59885
59886
59887
59888
59889
59890
59891
59892
59893
59894
59895
59896
59897
59898
59899
59900
59901
59902
59903
59904
59905
59906
59907
59908
59909
59910
59911
59912
59913
59914
59915
59916
59917
59918
59919
59920
59921
59922
59923
59924
59925
59926
59927
59928
59929
59930
59931
59932
59933
59934
59935
59936
59937
59938
59939
59940
59941
59942
59943
59944
59945
59946
59947
59948
59949
59950
59951
59952
59953
59954
59955
59956
59957
59958
59959
59960
59961
59962
59963
59964
59965
59966
59967
59968
59969
59970
59971
59972
59973
59974
59975
59976
59977
59978
59979
59980
59981
59982
59983
59984
59985
59986
59987
59988
59989
59990
59991
59992
59993
59994
59995
59996
59997
59998
59999
60000
}
static CImg<char> s_path;
cimg::mutex(7);
if (reinit_path) s_path.assign();
if (user_path) {
if (!s_path) s_path.assign(1024);
std::strncpy(s_path,user_path,1023);
} else if (!s_path) {
s_path.assign(1024);
bool path_found = false;
CImg<char> tmp(1024), filename_tmp(256);
std::FILE *file = 0;
cimg_snprintf(filename_tmp,filename_tmp._width,"%s.tmp",cimg::filenamerand());
char *tmpPath = std::getenv("TMP");
if (!tmpPath) { tmpPath = std::getenv("TEMP"); winformat_string(tmpPath); }
if (tmpPath) _cimg_test_temporary_path(tmpPath);
#if cimg_OS==2
_cimg_test_temporary_path("C:\\WINNT\\Temp");
_cimg_test_temporary_path("C:\\WINDOWS\\Temp");
_cimg_test_temporary_path("C:\\Temp");
_cimg_test_temporary_path("C:");
_cimg_test_temporary_path("D:\\WINNT\\Temp");
_cimg_test_temporary_path("D:\\WINDOWS\\Temp");
_cimg_test_temporary_path("D:\\Temp");
_cimg_test_temporary_path("D:");
#else
_cimg_test_temporary_path("/tmp");
_cimg_test_temporary_path("/var/tmp");
#endif
if (!path_found) {
*s_path = 0;
std::strncpy(tmp,filename_tmp,tmp._width - 1);
if ((file=std_fopen(tmp,"wb"))!=0) { cimg::fclose(file); std::remove(tmp); path_found = true; }
}
if (!path_found) {
cimg::mutex(7,0);
throw CImgIOException("cimg::temporary_path(): Failed to locate path for writing temporary files.\n");
}
}
cimg::mutex(7,0);
return s_path;
}
//! Get/set path to the <i>Program Files/</i> directory (Windows only).
/**
\param user_path Specified path, or \c 0 to get the path currently used.
\param reinit_path Force path to be recalculated (may take some time).
\return Path containing the program files.
**/
#if cimg_OS==2
inline const char* programfiles_path(const char *const user_path, const bool reinit_path) {
static CImg<char> s_path;
cimg::mutex(7);
if (reinit_path) s_path.assign();
if (user_path) {
if (!s_path) s_path.assign(1024);
std::strncpy(s_path,user_path,1023);
} else if (!s_path) {
s_path.assign(MAX_PATH);
*s_path = 0;
// Note: in the following line, 0x26 = CSIDL_PROGRAM_FILES (not defined on every compiler).
#if !defined(__INTEL_COMPILER)
if (!SHGetSpecialFolderPathA(0,s_path,0x0026,false)) {
const char *const pfPath = std::getenv("PROGRAMFILES");
if (pfPath) std::strncpy(s_path,pfPath,MAX_PATH - 1);
else std::strcpy(s_path,"C:\\PROGRA~1");
}
#else
std::strcpy(s_path,"C:\\PROGRA~1");
#endif
}
cimg::mutex(7,0);
return s_path;
}
#endif
//! Get/set path to the ImageMagick's \c convert binary.
/**
\param user_path Specified path, or \c 0 to get the path currently used.
\param reinit_path Force path to be recalculated (may take some time).
\return Path containing the \c convert binary.
**/
inline const char* imagemagick_path(const char *const user_path, const bool reinit_path) {
static CImg<char> s_path;
cimg::mutex(7);
if (reinit_path) s_path.assign();
if (user_path) {
if (!s_path) s_path.assign(1024);
std::strncpy(s_path,user_path,1023);
} else if (!s_path) {
s_path.assign(1024);
bool path_found = false;
std::FILE *file = 0;
#if cimg_OS==2
const char *const pf_path = programfiles_path();
if (!path_found) {
std::strcpy(s_path,".\\convert.exe");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=10 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%.2d-\\convert.exe",pf_path,k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 9; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d-Q\\convert.exe",pf_path,k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d\\convert.exe",pf_path,k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=10 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\convert.exe",pf_path,k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 9; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\convert.exe",pf_path,k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d\\VISUA~1\\BIN\\convert.exe",pf_path,k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=10 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%.2d-\\convert.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 9; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d-Q\\convert.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d\\convert.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=10 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\convert.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 9; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\convert.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d\\VISUA~1\\BIN\\convert.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=10 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%.2d-\\convert.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 9; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d-Q\\convert.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d\\convert.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=10 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\convert.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 9; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\convert.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d\\VISUA~1\\BIN\\convert.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"convert.exe");
#else
if (!path_found) {
std::strcpy(s_path,"./convert");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"convert");
#endif
winformat_string(s_path);
}
cimg::mutex(7,0);
return s_path;
}
//! Get/set path to the GraphicsMagick's \c gm binary.
/**
\param user_path Specified path, or \c 0 to get the path currently used.
\param reinit_path Force path to be recalculated (may take some time).
\return Path containing the \c gm binary.
**/
inline const char* graphicsmagick_path(const char *const user_path, const bool reinit_path) {
static CImg<char> s_path;
cimg::mutex(7);
if (reinit_path) s_path.assign();
if (user_path) {
if (!s_path) s_path.assign(1024);
std::strncpy(s_path,user_path,1023);
} else if (!s_path) {
s_path.assign(1024);
bool path_found = false;
std::FILE *file = 0;
#if cimg_OS==2
const char *const pf_path = programfiles_path();
if (!path_found) {
std::strcpy(s_path,".\\gm.exe");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=10 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%.2d-\\gm.exe",pf_path,k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 9; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d-Q\\gm.exe",pf_path,k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d\\gm.exe",pf_path,k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=10 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",pf_path,k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 9; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",pf_path,k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",pf_path,k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=10 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%.2d-\\gm.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 9; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d-Q\\gm.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d\\gm.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=10 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 9; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=10 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%.2d-\\gm.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 9; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d-Q\\gm.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d\\gm.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=10 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 9; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
for (int k = 32; k>=0 && !path_found; --k) {
cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",k);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"gm.exe");
#else
if (!path_found) {
std::strcpy(s_path,"./gm");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"gm");
#endif
winformat_string(s_path);
}
cimg::mutex(7,0);
return s_path;
}
//! Get/set path to the XMedcon's \c medcon binary.
/**
\param user_path Specified path, or \c 0 to get the path currently used.
\param reinit_path Force path to be recalculated (may take some time).
\return Path containing the \c medcon binary.
**/
inline const char* medcon_path(const char *const user_path, const bool reinit_path) {
static CImg<char> s_path;
cimg::mutex(7);
if (reinit_path) s_path.assign();
if (user_path) {
if (!s_path) s_path.assign(1024);
std::strncpy(s_path,user_path,1023);
} else if (!s_path) {
s_path.assign(1024);
bool path_found = false;
std::FILE *file = 0;
#if cimg_OS==2
const char *const pf_path = programfiles_path();
if (!path_found) {
std::strcpy(s_path,".\\medcon.exe");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) {
cimg_snprintf(s_path,s_path._width,"%s\\XMedCon\\bin\\medcon.bat",pf_path);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) {
cimg_snprintf(s_path,s_path._width,"%s\\XMedCon\\bin\\medcon.exe",pf_path);
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) {
std::strcpy(s_path,"C:\\XMedCon\\bin\\medcon.exe");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"medcon.exe");
#else
if (!path_found) {
std::strcpy(s_path,"./medcon");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"medcon");
#endif
winformat_string(s_path);
}
cimg::mutex(7,0);
return s_path;
}
//! Get/set path to the FFMPEG's \c ffmpeg binary.
/**
\param user_path Specified path, or \c 0 to get the path currently used.
\param reinit_path Force path to be recalculated (may take some time).
\return Path containing the \c ffmpeg binary.
**/
inline const char *ffmpeg_path(const char *const user_path, const bool reinit_path) {
static CImg<char> s_path;
cimg::mutex(7);
if (reinit_path) s_path.assign();
if (user_path) {
if (!s_path) s_path.assign(1024);
std::strncpy(s_path,user_path,1023);
} else if (!s_path) {
s_path.assign(1024);
bool path_found = false;
std::FILE *file = 0;
#if cimg_OS==2
if (!path_found) {
std::strcpy(s_path,".\\ffmpeg.exe");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"ffmpeg.exe");
#else
if (!path_found) {
std::strcpy(s_path,"./ffmpeg");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"ffmpeg");
#endif
winformat_string(s_path);
}
cimg::mutex(7,0);
return s_path;
}
//! Get/set path to the \c gzip binary.
/**
\param user_path Specified path, or \c 0 to get the path currently used.
\param reinit_path Force path to be recalculated (may take some time).
\return Path containing the \c gzip binary.
**/
inline const char *gzip_path(const char *const user_path, const bool reinit_path) {
static CImg<char> s_path;
cimg::mutex(7);
if (reinit_path) s_path.assign();
if (user_path) {
if (!s_path) s_path.assign(1024);
std::strncpy(s_path,user_path,1023);
} else if (!s_path) {
s_path.assign(1024);
bool path_found = false;
std::FILE *file = 0;
#if cimg_OS==2
if (!path_found) {
std::strcpy(s_path,".\\gzip.exe");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"gzip.exe");
#else
if (!path_found) {
std::strcpy(s_path,"./gzip");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"gzip");
#endif
winformat_string(s_path);
}
cimg::mutex(7,0);
return s_path;
}
//! Get/set path to the \c gunzip binary.
/**
\param user_path Specified path, or \c 0 to get the path currently used.
\param reinit_path Force path to be recalculated (may take some time).
\return Path containing the \c gunzip binary.
**/
inline const char *gunzip_path(const char *const user_path, const bool reinit_path) {
static CImg<char> s_path;
cimg::mutex(7);
if (reinit_path) s_path.assign();
if (user_path) {
if (!s_path) s_path.assign(1024);
std::strncpy(s_path,user_path,1023);
} else if (!s_path) {
s_path.assign(1024);
bool path_found = false;
std::FILE *file = 0;
#if cimg_OS==2
if (!path_found) {
std::strcpy(s_path,".\\gunzip.exe");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"gunzip.exe");
#else
if (!path_found) {
std::strcpy(s_path,"./gunzip");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"gunzip");
#endif
winformat_string(s_path);
}
cimg::mutex(7,0);
return s_path;
}
//! Get/set path to the \c dcraw binary.
/**
\param user_path Specified path, or \c 0 to get the path currently used.
\param reinit_path Force path to be recalculated (may take some time).
\return Path containing the \c dcraw binary.
**/
inline const char *dcraw_path(const char *const user_path, const bool reinit_path) {
static CImg<char> s_path;
cimg::mutex(7);
if (reinit_path) s_path.assign();
if (user_path) {
if (!s_path) s_path.assign(1024);
std::strncpy(s_path,user_path,1023);
} else if (!s_path) {
s_path.assign(1024);
bool path_found = false;
std::FILE *file = 0;
#if cimg_OS==2
if (!path_found) {
std::strcpy(s_path,".\\dcraw.exe");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"dcraw.exe");
#else
if (!path_found) {
std::strcpy(s_path,"./dcraw");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"dcraw");
#endif
winformat_string(s_path);
}
cimg::mutex(7,0);
return s_path;
}
//! Get/set path to the \c wget binary.
/**
\param user_path Specified path, or \c 0 to get the path currently used.
\param reinit_path Force path to be recalculated (may take some time).
\return Path containing the \c wget binary.
**/
inline const char *wget_path(const char *const user_path, const bool reinit_path) {
static CImg<char> s_path;
cimg::mutex(7);
if (reinit_path) s_path.assign();
if (user_path) {
if (!s_path) s_path.assign(1024);
std::strncpy(s_path,user_path,1023);
} else if (!s_path) {
s_path.assign(1024);
bool path_found = false;
std::FILE *file = 0;
#if cimg_OS==2
if (!path_found) {
std::strcpy(s_path,".\\wget.exe");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"wget.exe");
#else
if (!path_found) {
std::strcpy(s_path,"./wget");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"wget");
#endif
winformat_string(s_path);
}
cimg::mutex(7,0);
return s_path;
}
//! Get/set path to the \c curl binary.
/**
\param user_path Specified path, or \c 0 to get the path currently used.
\param reinit_path Force path to be recalculated (may take some time).
\return Path containing the \c curl binary.
**/
inline const char *curl_path(const char *const user_path, const bool reinit_path) {
static CImg<char> s_path;
cimg::mutex(7);
if (reinit_path) s_path.assign();
if (user_path) {
if (!s_path) s_path.assign(1024);
std::strncpy(s_path,user_path,1023);
} else if (!s_path) {
s_path.assign(1024);
bool path_found = false;
std::FILE *file = 0;
#if cimg_OS==2
if (!path_found) {
std::strcpy(s_path,".\\curl.exe");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"curl.exe");
#else
if (!path_found) {
std::strcpy(s_path,"./curl");
if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
}
if (!path_found) std::strcpy(s_path,"curl");
#endif
winformat_string(s_path);
}
cimg::mutex(7,0);
return s_path;
}
// [internal] Sorting function, used by cimg::files().
inline int _sort_files(const void* a, const void* b) {
const CImg<char> &sa = *(CImg<char>*)a, &sb = *(CImg<char>*)b;
return std::strcmp(sa._data,sb._data);
}
//! Return list of files/directories in specified directory.
/**
\param path Path to the directory. Set to 0 for current directory.
\param is_pattern Tell if specified path has a matching pattern in it.
\param mode Output type, can be primary { 0=files only | 1=folders only | 2=files + folders }.
\param include_path Tell if \c path must be included in resulting filenames.
\return A list of filenames.
**/
inline CImgList<char> files(const char *const path, const bool is_pattern=false,
const unsigned int mode=2, const bool include_path=false) {
if (!path || !*path) return files("*",true,mode,include_path);
CImgList<char> res;
// If path is a valid folder name, ignore argument 'is_pattern'.
const bool _is_pattern = is_pattern && !cimg::is_directory(path);
bool is_root = false, is_current = false;
cimg::unused(is_root,is_current);
// Clean format of input path.
CImg<char> pattern, _path = CImg<char>::string(path);
#if cimg_OS==2
for (char *ps = _path; *ps; ++ps) if (*ps=='\\') *ps='/';
#endif
char *pd = _path;
for (char *ps = pd; *ps; ++ps) { if (*ps!='/' || *ps!=*(ps+1)) *(pd++) = *ps; }
*pd = 0;
unsigned int lp = (unsigned int)std::strlen(_path);
if (!_is_pattern && lp && _path[lp - 1]=='/') {
_path[lp - 1] = 0; --lp;
#if cimg_OS!=2
is_root = !*_path;
#endif
}
// Separate folder path and matching pattern.
if (_is_pattern) {
const unsigned int bpos = (unsigned int)(cimg::basename(_path,'/') - _path.data());
CImg<char>::string(_path).move_to(pattern);
if (bpos) {
_path[bpos - 1] = 0; // End 'path' at last slash.
#if cimg_OS!=2
is_root = !*_path;
#endif
} else { // No path to folder specified, assuming current folder.
is_current = true; *_path = 0;
}
lp = (unsigned int)std::strlen(_path);
}
// Windows version.
#if cimg_OS==2
if (!_is_pattern) {
pattern.assign(lp + 3);
std::memcpy(pattern,_path,lp);
pattern[lp] = '/'; pattern[lp + 1] = '*'; pattern[lp + 2] = 0;
}
WIN32_FIND_DATAA file_data;
const HANDLE dir = FindFirstFileA(pattern.data(),&file_data);
if (dir==INVALID_HANDLE_VALUE) return CImgList<char>::const_empty();
do {
const char *const filename = file_data.cFileName;
if (*filename!='.' || (filename[1] && (filename[1]!='.' || filename[2]))) {
const unsigned int lf = (unsigned int)std::strlen(filename);
const bool is_directory = (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)!=0;
if ((!mode && !is_directory) || (mode==1 && is_directory) || mode>=2) {
if (include_path) {
CImg<char> full_filename((lp?lp+1:0) + lf + 1);
if (lp) { std::memcpy(full_filename,_path,lp); full_filename[lp] = '/'; }
std::memcpy(full_filename._data + (lp?lp + 1:0),filename,lf + 1);
full_filename.move_to(res);
} else CImg<char>(filename,lf + 1).move_to(res);
}
}
} while (FindNextFileA(dir,&file_data));
FindClose(dir);
// Unix version (posix).
#elif cimg_OS == 1
DIR *const dir = opendir(is_root?"/":is_current?".":_path.data());
if (!dir) return CImgList<char>::const_empty();
struct dirent *ent;
while ((ent=readdir(dir))!=0) {
const char *const filename = ent->d_name;
if (*filename!='.' || (filename[1] && (filename[1]!='.' || filename[2]))) {
const unsigned int lf = (unsigned int)std::strlen(filename);
CImg<char> full_filename(lp + lf + 2);
if (!is_current) {
full_filename.assign(lp + lf + 2);
if (lp) std::memcpy(full_filename,_path,lp);
full_filename[lp] = '/';
std::memcpy(full_filename._data + lp + 1,filename,lf + 1);
} else full_filename.assign(filename,lf + 1);
struct stat st;
if (stat(full_filename,&st)==-1) continue;
const bool is_directory = (st.st_mode & S_IFDIR)!=0;
if ((!mode && !is_directory) || (mode==1 && is_directory) || mode==2) {
if (include_path) {
if (!_is_pattern || (_is_pattern && !fnmatch(pattern,full_filename,0)))
full_filename.move_to(res);
} else {
if (!_is_pattern || (_is_pattern && !fnmatch(pattern,full_filename,0)))
CImg<char>(filename,lf + 1).move_to(res);
}
}
}
}
closedir(dir);
#endif
// Sort resulting list by lexicographic order.
if (res._width>=2) std::qsort(res._data,res._width,sizeof(CImg<char>),_sort_files);
return res;
}
//! Try to guess format from an image file.
/**
\param file Input file (can be \c 0 if \c filename is set).
\param filename Filename, as a C-string (can be \c 0 if \c file is set).
\return C-string containing the guessed file format, or \c 0 if nothing has been guessed.
**/
inline const char *ftype(std::FILE *const file, const char *const filename) {
if (!file && !filename)
throw CImgArgumentException("cimg::ftype(): Specified filename is (null).");
static const char
*const _pnm = "pnm",
*const _pfm = "pfm",
*const _bmp = "bmp",
*const _gif = "gif",
*const _jpg = "jpg",
*const _off = "off",
*const _pan = "pan",
*const _png = "png",
*const _tif = "tif",
*const _inr = "inr",
*const _dcm = "dcm";
const char *f_type = 0;
CImg<char> header;
const unsigned int omode = cimg::exception_mode();
cimg::exception_mode(0);
try {
header._load_raw(file,filename,512,1,1,1,false,false,0);
const unsigned char *const uheader = (unsigned char*)header._data;
if (!std::strncmp(header,"OFF\n",4)) f_type = _off; // OFF.
else if (!std::strncmp(header,"#INRIMAGE",9)) f_type = _inr; // INRIMAGE.
else if (!std::strncmp(header,"PANDORE",7)) f_type = _pan; // PANDORE.
else if (!std::strncmp(header.data() + 128,"DICM",4)) f_type = _dcm; // DICOM.
else if (uheader[0]==0xFF && uheader[1]==0xD8 && uheader[2]==0xFF) f_type = _jpg; // JPEG.
else if (header[0]=='B' && header[1]=='M') f_type = _bmp; // BMP.
else if (header[0]=='G' && header[1]=='I' && header[2]=='F' && header[3]=='8' && header[5]=='a' && // GIF.
(header[4]=='7' || header[4]=='9')) f_type = _gif;
else if (uheader[0]==0x89 && uheader[1]==0x50 && uheader[2]==0x4E && uheader[3]==0x47 && // PNG.
uheader[4]==0x0D && uheader[5]==0x0A && uheader[6]==0x1A && uheader[7]==0x0A) f_type = _png;
else if ((uheader[0]==0x49 && uheader[1]==0x49) || (uheader[0]==0x4D && uheader[1]==0x4D)) f_type = _tif; // TIFF.
else { // PNM or PFM.
CImgList<char> _header = header.get_split(CImg<char>::vector('\n'),0,false);
cimglist_for(_header,l) {
if (_header(l,0)=='#') continue;
if (_header[l]._height==2 && _header(l,0)=='P') {
const char c = _header(l,1);
if (c=='f' || c=='F') { f_type = _pfm; break; }
if (c>='1' && c<='9') { f_type = _pnm; break; }
}
f_type = 0; break;
}
}
} catch (CImgIOException&) { }
cimg::exception_mode(omode);
return f_type;
}
//! Load file from network as a local temporary file.
/**
\param filename Filename, as a C-string.
\param[out] filename_local C-string containing the path to a local copy of \c filename.
\param timeout Maximum time (in seconds) authorized for downloading the file from the URL.
\param try_fallback When using libcurl, tells using system calls as fallbacks in case of libcurl failure.
\return Value of \c filename_local.
\note Use the \c libcurl library, or the external binaries \c wget or \c curl to perform the download.
**/
inline char *load_network(const char *const url, char *const filename_local,
const unsigned int timeout, const bool try_fallback,
const char *const referer) {
if (!url)
throw CImgArgumentException("cimg::load_network(): Specified URL is (null).");
if (!filename_local)
throw CImgArgumentException("cimg::load_network(): Specified destination string is (null).");
const char *const __ext = cimg::split_filename(url), *const _ext = (*__ext && __ext>url)?__ext - 1:__ext;
CImg<char> ext = CImg<char>::string(_ext);
std::FILE *file = 0;
*filename_local = 0;
if (ext._width>16 || !cimg::strncasecmp(ext,"cgi",3)) *ext = 0;
else cimg::strwindows_reserved(ext);
do {
cimg_snprintf(filename_local,256,"%s%c%s%s",
cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext._data);
if ((file=std_fopen(filename_local,"rb"))!=0) cimg::fclose(file);
} while (file);
#ifdef cimg_use_curl
const unsigned int omode = cimg::exception_mode();
cimg::exception_mode(0);
try {
CURL *curl = 0;
CURLcode res;
curl = curl_easy_init();
if (curl) {
file = cimg::fopen(filename_local,"wb");
curl_easy_setopt(curl,CURLOPT_URL,url);
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,0);
curl_easy_setopt(curl,CURLOPT_WRITEDATA,file);
curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,0L);
curl_easy_setopt(curl,CURLOPT_SSL_VERIFYHOST,0L);
curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1L);
if (timeout) curl_easy_setopt(curl,CURLOPT_TIMEOUT,(long)timeout);
if (std::strchr(url,'?')) curl_easy_setopt(curl,CURLOPT_HTTPGET,1L);
if (referer) curl_easy_setopt(curl,CURLOPT_REFERER,referer);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
cimg::fseek(file,0,SEEK_END); // Check if file size is 0.
const cimg_ulong siz = cimg::ftell(file);
cimg::fclose(file);
if (siz>0 && res==CURLE_OK) {
cimg::exception_mode(omode);
return filename_local;
} else std::remove(filename_local);
}
} catch (...) { }
cimg::exception_mode(omode);
if (!try_fallback) throw CImgIOException("cimg::load_network(): Failed to load file '%s' with libcurl.",url);
#endif
CImg<char> command((unsigned int)std::strlen(url) + 64);
cimg::unused(try_fallback);
// Try with 'curl' first.
if (timeout) {
if (referer)
cimg_snprintf(command,command._width,"%s -e %s -m %u -f --silent --compressed -o \"%s\" \"%s\"",
cimg::curl_path(),referer,timeout,filename_local,url);
else
cimg_snprintf(command,command._width,"%s -m %u -f --silent --compressed -o \"%s\" \"%s\"",
cimg::curl_path(),timeout,filename_local,url);
} else {
if (referer)
cimg_snprintf(command,command._width,"%s -e %s -f --silent --compressed -o \"%s\" \"%s\"",
cimg::curl_path(),referer,filename_local,url);
else
cimg_snprintf(command,command._width,"%s -f --silent --compressed -o \"%s\" \"%s\"",
cimg::curl_path(),filename_local,url);
}
cimg::system(command);
if (!(file = std_fopen(filename_local,"rb"))) {
// Try with 'wget' otherwise.
if (timeout) {
if (referer)
cimg_snprintf(command,command._width,"%s --referer=%s -T %u -q -r -l 0 --no-cache -O \"%s\" \"%s\"",
cimg::wget_path(),referer,timeout,filename_local,url);
else
cimg_snprintf(command,command._width,"%s -T %u -q -r -l 0 --no-cache -O \"%s\" \"%s\"",
cimg::wget_path(),timeout,filename_local,url);
} else {
if (referer)
cimg_snprintf(command,command._width,"%s --referer=%s -q -r -l 0 --no-cache -O \"%s\" \"%s\"",
cimg::wget_path(),referer,filename_local,url);
else
cimg_snprintf(command,command._width,"%s -q -r -l 0 --no-cache -O \"%s\" \"%s\"",
cimg::wget_path(),filename_local,url);
}
cimg::system(command);
if (!(file = std_fopen(filename_local,"rb")))
throw CImgIOException("cimg::load_network(): Failed to load file '%s' with external commands "
"'wget' or 'curl'.",url);
cimg::fclose(file);
// Try gunzip it.
cimg_snprintf(command,command._width,"%s.gz",filename_local);
std::rename(filename_local,command);
cimg_snprintf(command,command._width,"%s --quiet \"%s.gz\"",
gunzip_path(),filename_local);
cimg::system(command);
file = std_fopen(filename_local,"rb");
if (!file) {
cimg_snprintf(command,command._width,"%s.gz",filename_local);
std::rename(command,filename_local);
file = std_fopen(filename_local,"rb");
}
}
cimg::fseek(file,0,SEEK_END); // Check if file size is 0.
if (std::ftell(file)<=0)
throw CImgIOException("cimg::load_network(): Failed to load URL '%s' with external commands "
"'wget' or 'curl'.",url);
cimg::fclose(file);
return filename_local;
}
// Implement a tic/toc mechanism to display elapsed time of algorithms.
inline cimg_ulong tictoc(const bool is_tic) {
cimg::mutex(2);
static CImg<cimg_ulong> times(64);
static unsigned int pos = 0;
const cimg_ulong t1 = cimg::time();
if (is_tic) { // Tic.
times[pos++] = t1;
if (pos>=times._width)
throw CImgArgumentException("cimg::tic(): Too much calls to 'cimg::tic()' without calls to 'cimg::toc()'.");
cimg::mutex(2,0);
return t1;
}
// Toc.
if (!pos)
throw CImgArgumentException("cimg::toc(): No previous call to 'cimg::tic()' has been made.");
const cimg_ulong
t0 = times[--pos],
dt = t1>=t0?(t1 - t0):cimg::type<cimg_ulong>::max();
const unsigned int
edays = (unsigned int)(dt/86400000.0),
ehours = (unsigned int)((dt - edays*86400000.0)/3600000.0),
emin = (unsigned int)((dt - edays*86400000.0 - ehours*3600000.0)/60000.0),
esec = (unsigned int)((dt - edays*86400000.0 - ehours*3600000.0 - emin*60000.0)/1000.0),
ems = (unsigned int)(dt - edays*86400000.0 - ehours*3600000.0 - emin*60000.0 - esec*1000.0);
if (!edays && !ehours && !emin && !esec)
std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u ms%s\n",
cimg::t_red,1 + 2*pos,"",ems,cimg::t_normal);
else {
if (!edays && !ehours && !emin)
std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u sec %u ms%s\n",
cimg::t_red,1 + 2*pos,"",esec,ems,cimg::t_normal);
else {
if (!edays && !ehours)
std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u min %u sec %u ms%s\n",
cimg::t_red,1 + 2*pos,"",emin,esec,ems,cimg::t_normal);
else{
if (!edays)
std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u hours %u min %u sec %u ms%s\n",
cimg::t_red,1 + 2*pos,"",ehours,emin,esec,ems,cimg::t_normal);
else{
std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u days %u hours %u min %u sec %u ms%s\n",
cimg::t_red,1 + 2*pos,"",edays,ehours,emin,esec,ems,cimg::t_normal);
}
}
}
}
cimg::mutex(2,0);
return dt;
}
// Return a temporary string describing the size of a memory buffer.
inline const char *strbuffersize(const cimg_ulong size) {
static CImg<char> res(256);
cimg::mutex(5);
if (size<1024LU) cimg_snprintf(res,res._width,"%lu byte%s",(unsigned long)size,size>1?"s":"");
else if (size<1024*1024LU) { const float nsize = size/1024.0f; cimg_snprintf(res,res._width,"%.1f Kio",nsize); }
else if (size<1024*1024*1024LU) {
const float nsize = size/(1024*1024.0f); cimg_snprintf(res,res._width,"%.1f Mio",nsize);
} else { const float nsize = size/(1024*1024*1024.0f); cimg_snprintf(res,res._width,"%.1f Gio",nsize); }
cimg::mutex(5,0);
return res;
}
//! Display a simple dialog box, and wait for the user's response.
/**
\param title Title of the dialog window.
\param msg Main message displayed inside the dialog window.
\param button1_label Label of the 1st button.
\param button2_label Label of the 2nd button (\c 0 to hide button).
\param button3_label Label of the 3rd button (\c 0 to hide button).
\param button4_label Label of the 4th button (\c 0 to hide button).
\param button5_label Label of the 5th button (\c 0 to hide button).
\param button6_label Label of the 6th button (\c 0 to hide button).
\param logo Image logo displayed at the left of the main message.
\param is_centered Tells if the dialog window must be centered on the screen.
\return Indice of clicked button (from \c 0 to \c 5), or \c -1 if the dialog window has been closed by the user.
\note
- Up to 6 buttons can be defined in the dialog window.
- The function returns when a user clicked one of the button or closed the dialog window.
- If a button text is set to 0, the corresponding button (and the followings) will not appear in the dialog box.
At least one button must be specified.
**/
template<typename t>
inline int dialog(const char *const title, const char *const msg,
const char *const button1_label, const char *const button2_label,
const char *const button3_label, const char *const button4_label,
const char *const button5_label, const char *const button6_label,
const CImg<t>& logo, const bool is_centered=false) {
#if cimg_display==0
cimg::unused(title,msg,button1_label,button2_label,button3_label,button4_label,button5_label,button6_label,
logo._data,is_centered);
throw CImgIOException("cimg::dialog(): No display available.");
#else
static const unsigned char
black[] = { 0,0,0 }, white[] = { 255,255,255 }, gray[] = { 200,200,200 }, gray2[] = { 150,150,150 };
// Create buttons and canvas graphics
CImgList<unsigned char> buttons, cbuttons, sbuttons;
if (button1_label) { CImg<unsigned char>().draw_text(0,0,button1_label,black,gray,1,13).move_to(buttons);
if (button2_label) { CImg<unsigned char>().draw_text(0,0,button2_label,black,gray,1,13).move_to(buttons);
if (button3_label) { CImg<unsigned char>().draw_text(0,0,button3_label,black,gray,1,13).move_to(buttons);
if (button4_label) { CImg<unsigned char>().draw_text(0,0,button4_label,black,gray,1,13).move_to(buttons);
if (button5_label) { CImg<unsigned char>().draw_text(0,0,button5_label,black,gray,1,13).move_to(buttons);
if (button6_label) { CImg<unsigned char>().draw_text(0,0,button6_label,black,gray,1,13).move_to(buttons);
}}}}}}
if (!buttons._width)
throw CImgArgumentException("cimg::dialog(): No buttons have been defined.");
cimglist_for(buttons,l) buttons[l].resize(-100,-100,1,3);
unsigned int bw = 0, bh = 0;
cimglist_for(buttons,l) { bw = std::max(bw,buttons[l]._width); bh = std::max(bh,buttons[l]._height); }
bw+=8; bh+=8;
if (bw<64) bw = 64;
if (bw>128) bw = 128;
if (bh<24) bh = 24;
if (bh>48) bh = 48;
CImg<unsigned char> button(bw,bh,1,3);
button.draw_rectangle(0,0,bw - 1,bh - 1,gray);
button.draw_line(0,0,bw - 1,0,white).draw_line(0,bh - 1,0,0,white);
button.draw_line(bw - 1,0,bw - 1,bh - 1,black).draw_line(bw - 1,bh - 1,0,bh - 1,black);
button.draw_line(1,bh - 2,bw - 2,bh - 2,gray2).draw_line(bw - 2,bh - 2,bw - 2,1,gray2);
CImg<unsigned char> sbutton(bw,bh,1,3);
sbutton.draw_rectangle(0,0,bw - 1,bh - 1,gray);
sbutton.draw_line(0,0,bw - 1,0,black).draw_line(bw - 1,0,bw - 1,bh - 1,black);
sbutton.draw_line(bw - 1,bh - 1,0,bh - 1,black).draw_line(0,bh - 1,0,0,black);
sbutton.draw_line(1,1,bw - 2,1,white).draw_line(1,bh - 2,1,1,white);
sbutton.draw_line(bw - 2,1,bw - 2,bh - 2,black).draw_line(bw - 2,bh - 2,1,bh - 2,black);
sbutton.draw_line(2,bh - 3,bw - 3,bh - 3,gray2).draw_line(bw - 3,bh - 3,bw - 3,2,gray2);
sbutton.draw_line(4,4,bw - 5,4,black,1,0xAAAAAAAA,true).draw_line(bw - 5,4,bw - 5,bh - 5,black,1,0xAAAAAAAA,false);
sbutton.draw_line(bw - 5,bh - 5,4,bh - 5,black,1,0xAAAAAAAA,false).draw_line(4,bh - 5,4,4,black,1,0xAAAAAAAA,false);
CImg<unsigned char> cbutton(bw,bh,1,3);