1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062
|
/*-----------------------------------------------------------------------
This file is part of aaphoto.
aaphoto is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
aaphoto is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
------------------------------------------------------------------------*/
//#define __BMP_ONLY__
// ---------------------------------------------------
// ----------- Auto Adjust Photo ---------------------
// ----------- András Horváth (C) 2006-2010 ----------
// ----------- Hungary, http://log69.com -------------
// ---------------------------------------------------
/*
aaphoto Changelog:
--------------------
2010/09/18 - aaphoto v0.38.2 - new aaRGB v0.61.2 version update
- bugfix: an ugly misconception in my paralleled code caused weird behavior when using more threads
- bugfix: BMP image writer function didn't zero out the BMP align bytes in file buffer
therefore the same output differed in some cases
- bugfix: PNG image reader function stored the unreliable values of pixel resolution
when the type was unknown
2010/07/18 - aaphoto v0.38 - additional verbose message showing presence of alpha channel in PNG images
- bugfix: fix compile with only BMP support
- fix some warning messages during build
- removing unnecessary __WIN32__ macro
2010/05/10 - aaphoto v0.37 - OpenMP support added for multi processing, all possible time intensive codes paralleled
__OPENMP__ directive and -fopenmp option are needed at compile time (supported since GCC v4.2)
(not available on windows platform yet)
- new -t, --threads switch added for manually setting the number of working threads
- new aaRGB v0.61 version update
- bugfix: exif info was missed out after last version's change in JPEG handling
- improvement in exif handling and verbose messages
- refining additional verbose messages
- removing pgx file type support because it is outdated
- some changes in documentation
- some minor code cleanup and bugfixes
2010/03/16 - aaphoto v0.36 - bugfix: fix for tmpfile() patches of libjasper and libjpeg (windows platform only)
when running more than one instances of aaphoto at a time, they all used the same
temporary files and therefore the images became corrupt
- bugfix: it doesn't ask for administrative privileges anymore while running in an admin account
under vista and windows 7 (windows platform only)
- bugfix: the --rotate180 switch didn't turn the middle line in images with odd heights
- JPEG format handling entirely rewritten to be able to handle extra parameters in this format
separately, now libjpeg is used directly instead of libjasper for reading / writing JPEG images
so libjpeg is a new dependency from now on, formerly only libjasper was depended on it
- original DPI values of images are restored in BMP, JPEG and PNG formats during conversion
- refining program messages
- printing the time elapsed in seconds since program start in verbose mode if not zero
- printing extra info of bitmap dimension, resolution and color depth in verbose mode
2010/02/25 - aaphoto v0.35 - bugfix: possible buffer overflows fixed
2010/02/19 - aaphoto v0.34 - __UNIX__ macro removed from Makefile, not needed anymore
- bugfix: static binary update with patches of libjasper and libjpeg
1) sleep() function missing on mingw32 platform
2) bad implementation of tmpfile() function on windows platform
it tries to create temporary files in the root of current directory
instead of the system temporary path so that causes failure for unprivileged users
who don't have permissions to write there
- update: changes in new version of libpng 1.4.0, aaio.c updated as necessary
png_check_sig() function replaced with png_sig_cmp()
setjmp(png_ptr->jmpbuf) has been deprecated, changed to setjmp(png_jmpbuf(png_ptr))
see more at http://www.libpng.org/pub/png/src/libpng-1.2.x-to-1.4.x-summary.txt
2010/01/10 - aaphoto v0.33 - some changes in documentation
- bugfix: unfreed space caused memory leak
- bugfix: uninitialized variable caused --resize to misbehave
- fix: change of return values in procedures to reflect standard exit codes
now it has a sense to run something like "aaphoto image.jpg && echo OK"
formerly return codes meant opposite
- fix a warning message during compile time, an include was missing
- boundary check of fixed size arrays added for safety reasons
- the --speed switch removed, it made the code less platform independent and was fussy anyway
- error messages printed to stderr instead of stdout from now
- more verbose error message on failure of image load
2009/10/18 - aaphoto v0.32 - new aaRGB v0.60 version update
- new --noexif switch added for the ability to save new image without exif info
- new --bmp switch added for BMP format output
- new -o, --output switch added for alternate directory output
2009/08/23 - aaphoto v0.31 - bugfix: __BMP_ONLY__ directive fix in source code
- bugfix: writing of BMP images could result in corrupt BMP structure
- code cleanup in BMP write function
- parameters of switches also work with spaces between them
- new aaRGB v0.59 version update
2009/02/22 - aaphoto v0.30 - implementation of PNG format (RGB and Gray images read / write with alpha channel support)
- bugfix: reading corrupt exif info in JPEG files could get into an infinite loop
- bugfix: length of exif info was determined wrongly
- rework of the parameters and switches parsing part
- lots of code cleanup
- most of the comments in code translated into english
- print messages get flushed out with fflush now during process
- the --info switch removed
- the -o switch removed for safety reasons, --overwrite still available
- the -h switch added for unix compatibility
- the -j1 and -j2 switch removed, --jpg and --jp2 still available
- the --png switch is now new for PNG output
- the -s switch changed from --speed to --silent for compatibility reasons
- the --mute switch changed to -s, --silent and --quiet for unix / posix compatibility
- the -V, --verbose switch is now new for more detailed output during image process
- the --test switch now turns the --autoadjust switch on by default
- the -d, --description and -l, --license switches removed
- new aaRGB v0.58 version update
2008/02/02 - aaphoto v0.29 - bugfix: color space variable was not defined during the load of BMP format
- bugfix: BMP format handling fixed for JPEG conversion
- grayscale images can also be used as an input
- change: file name buffer increased (for processing files in folders)
- Exif meta data information is now restored during conversion in JPEG images
2007/08/11 - aaphoto v0.28 - new aaRGB v0.57 version update
- bugfix: removing extra slashes from the end of folders
2007/07/04 - aaphoto v0.27 - new aaRGB v0.56 version update v0.56 with "Apply only on selection" function
2007/05/26 - aaphoto v0.26 - bugfix: Win32 version crashed during JPEG-2000 conversion
2007/05/19 - aaphoto v0.25 - expanding functions: Rotate 90, 180, 270, Flip x, Flip y
2007/05/01 - aaphoto v0.24 - improving timing values
- input parameter can be folders too beside files
- bitmap info parameter now working with bmp too
- simplifying parameter input: no --autoadjust parameter needed from now, default is on
2007/04/03 - aaphoto v0.23 - new aaRGB v0.55 version update
2007/04/01 - aaphoto v0.22 - new aaRGB v0.54 version update
2007/03/30 - aaphoto v0.21 - bmp_only macro created in source code for other platforms
- bug fixes
2007/03/29 - aaphoto v0.20 - new aaRGB v0.53 version update
2007/02/25 - aaphoto v0.19 - extra information output within image for testing purposes
2007/02/22 - aaphoto v0.18 - custom code for BMP input/output (helps in testing)
2007/01/24 - aaphoto v0.17 - JasPer coder implemented for further image formats
2007/01/04 - aaphoto v0.16 - stable working command-line version for linux environment with BMP format support
aaphoto end of Changelog.
*/
// global constants and variables
#define max_char 1024
#define max_file_name_buffer 4096 * 1024
int file_counter;
char *file_name;
unsigned char *file_name_buffer;
long file_name_counter;
long file_name_buffer_pointer;
unsigned char *bitmap_buffer;
unsigned long bitmap_width;
unsigned long bitmap_height;
double xdpi;
double ydpi;
int udpi;
int bitmap_format_bmp_clrspc_type;
int bitmap_format_jpg_clrspc_type;
int bitmap_format_jpg_file_type;
int bitmap_format_png_clrspc_type;
int bitmap_format_png_interlace_type;
int bitmap_format_png_compression_type;
int bitmap_format_png_filter_type;
char *exif_buffer;
long exif_buffer_length;
long exif_file_length;
int exif_flag;
int opt_help;
int opt_version;
int opt_autoadjust;
int opt_overwrite;
int opt_jpg;
int opt_jp2;
int opt_png;
int opt_bmp;
int opt_resize;
int opt_resize_percent;
int opt_rotate90;
int opt_rotate180;
int opt_rotate270;
int opt_flipx;
int opt_flipy;
int opt_output;
char opt_output_path [max_char];
int opt_quality;
int opt_threads;
int opt_verbose;
int opt_recursive;
int opt_quiet;
int opt_test;
int opt_noexif;
int char_temp_x;
int char_temp_y;
int mytime;
// OpenMP
int max_cpus;
int max_threads;
int max_num_threads;
int opt_openmp;
#ifdef __OPENMP__
#include <omp.h>
#endif
// file name separation character
char slsh='/';
#ifndef __BMP_ONLY__
#include <jasper/jasper.h>
#include <png.h>
#include <jpeglib.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <dirent.h>
#include <time.h>
//#include <stddir.h>
#include "aaio.c"
#include "aargb.c"
#include "aaresize.c"
void PRINT_VERSION(void){
char *helpinfo[] = {
"Auto Adjust Photo\n"
"Copyright (C) 2006-2010 Andras Horvath\n"
"E-mail: mail@log69.com - suggestions & feedbacks are welcome\n"
"URL: http://log69.com - the official site\n"
"aaphoto (command-line) version - v0.38.2\n"
"aaRGB (color-correction engine) version - v0.61.2\n"
"last update = 18/09/2010\n"
"\n"
#ifndef __BMP_ONLY__
"The following libraries are used by this program:\n"
"libjpeg - IJG JPEG software, http://www.ijg.org/\n"
"libjasper - JasPer software, http://www.ece.uvic.ca/~mdadams/jasper/\n"
"libpng - PNG software, http://www.libpng.org/\n"
"libz - Compression library, http://www.zlib.net/\n"
#endif
#ifdef __BMP_ONLY__
"BMP_ONLY version. Only BMP format is supported here.\n"
#endif
"\n\0"
}; STRING_PRINT(*helpinfo);
}
void PRINT_DESCRIPTION(void){
char *helpinfo[] = {
"[DESCRIPTION]\n"
"Auto Adjust Photo is a tiny command-line image manipulation tool "
"for automatic color correction of photos. "
"It tries to make the picture look better. "
"The program does this by analyzing the input image and then sets the "
"most optimal contrast, gamma, color balance and saturation for it.\n"
"\n\0"
}; STRING_PRINT(*helpinfo);
}
void PRINT_LICENSE(void){
char *helpinfo[] = {
"[LICENSE]\n"
"This program is free software; you can redistribute it and/or modify "
"it under the terms of the GNU General Public License as published by "
"the Free Software Foundation; either version 3 of the License, or "
"(at your option) any later version.\n"
"\n"
"This program is distributed in the hope that it will be useful, "
"but WITHOUT ANY WARRANTY; without even the implied warranty of "
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "
"GNU General Public License for more details.\n"
"\n"
"You should have received a copy of the GNU General Public License "
"along with this program. If not, see <http://www.gnu.org/licenses/>.\n"
"\n\0"
}; STRING_PRINT(*helpinfo);
}
void PRINT_HELP(void){
char *helpinfo[] = {
"[HELP]\n"
"USAGE: aaphoto [options] [source files]\n"
"\n"
"The following image types are supported (thanks to JasPer, JPEG and PNG):\n"
"mif, pnm / pgm / ppm, bmp, ras, jp2, jpc, jpg, png\n"
"\n"
"Quality settings can be applied only to jp2, jpc, jpg formats\n"
"\n"
"The following options are supported:\n"
" -h --help Print this help\n"
" -v --version Print version information\n"
" -a --autoadjust Auto adjust the colors of the image\n"
" -o --output Set output directory\n"
" --overwrite Overwrite mode, the original source file is replaced\n"
" --jpg JPEG image output\n"
" --jp2 JPEG 2000 image output\n"
" --png PNG image output with alpha channel support\n"
" --bmp BMP image output\n"
" -r --resize Resize image taking the longer side in % or pixels\n"
" --rotate90 Rotate image with 90 degrees clockwise\n"
" --rotate180 Rotate image with 180 degrees\n"
" --rotate270 Rotate image with 90 degrees counter-clockwise\n"
" --flipx Mirror image horizontally\n"
" --flipy Mirror image vertically\n"
" --noexif Save image without EXIF info\n"
" -q --quality Set image quality from 1 to 100\n"
" -t --threads Set number of working threads (default: autodetect)\n"
" -s --silent Silent mode, no information printed during operation\n"
" --quiet ...same as above\n"
" -V --verbose Print verbose information about processing\n"
//" -R --recursive Process images recursively\n"
" --test Print detailed test information into image\n"
"\n"
"EXAMPLES:\n"
" aaphoto image.jpg\n"
" aaphoto -a -r600 -q85 *.jpg\n"
" aaphoto mydir\n"
" aaphoto -V --resize70% image.png\n"
" aaphoto --quality60 image.jp2\n"
"\n"
"REMARKS:\n"
"- auto adjust parameter is set by default if no other parameters are given\n"
"- _new file name will be generated without --overwrite parameter\n"
"- on directory input every file will be processed in it but not recursively\n"
"- order of parameters does not matter\n"
"- resizing can be set in percentage too\n"
"- resize parameter should be less or equal than original\n"
"- resize uses the best (and slowest) resampling method\n"
"- default jpeg compression quality is 95%\n"
"- EXIF information is restored in jpeg images by default\n"
"\n\0"
}; STRING_PRINT(*helpinfo);
}
int MAIN_RESIZE(void)
{
// if there is an Alpha channel too beside RGB (clrspc_type says)
// then we use the alpha flag to indicate it to the resize function
int alpha_flag = 0;
if ((bitmap_format_png_clrspc_type == 4) || (bitmap_format_png_clrspc_type == 6)){
alpha_flag = 1; }
if (opt_resize){
unsigned long opr = opt_resize;
// calculating resize in percentage
if (opt_resize_percent){
if (bitmap_width > bitmap_height) { opr = bitmap_width * opr / 100; }
else { opr = bitmap_height * opr / 100; }
}
// if the new size is bigger or equal than the original size, then no process is done
if (!((opr > bitmap_width) && (opr > bitmap_height))){
unsigned long new_width, new_height;
if (bitmap_width > bitmap_height){
new_width = opr;
new_height = bitmap_height * opr / bitmap_width;
}
else{
new_width = bitmap_width * opr / bitmap_height;
new_height = opr;
}
if (new_width < 1) new_width = 1;
if (new_height < 1) new_height = 1;
if (RESIZE(&bitmap_buffer, &bitmap_width, &bitmap_height, new_width, new_height, alpha_flag)){
STRING_PRINT("\n"); STRING_PRINTE("error: memory allocation error\n"); return 1; }
}
// else {
// STRING_PRINT("\n"); STRING_PRINTE("error: resize parameter too big, "
// "target size should be less or equal than original\n"); return 1; }
}
// Rotate and Flip calls
if (opt_rotate90) { if (ROTATE90(&bitmap_buffer, &bitmap_width, &bitmap_height, alpha_flag))
{ STRING_PRINT("\n"); STRING_PRINTE("error: memory allocation error\n"); return 1; } }
if (opt_rotate180) { if (ROTATE180(&bitmap_buffer, &bitmap_width, &bitmap_height, alpha_flag))
{ STRING_PRINT("\n"); STRING_PRINTE("error: memory allocation error\n"); return 1; } }
if (opt_rotate270) { if (ROTATE270(&bitmap_buffer, &bitmap_width, &bitmap_height, alpha_flag))
{ STRING_PRINT("\n"); STRING_PRINTE("error: memory allocation error\n"); return 1; } }
if (opt_flipx) { if (FLIPX(&bitmap_buffer, &bitmap_width, &bitmap_height, alpha_flag))
{ STRING_PRINT("\n"); STRING_PRINTE("error: memory allocation error\n"); return 1; } }
if (opt_flipy) { if (FLIPY(&bitmap_buffer, &bitmap_width, &bitmap_height, alpha_flag))
{ STRING_PRINT("\n"); STRING_PRINTE("error: memory allocation error\n"); return 1; } }
return 0;
}
void MAIN_AARGB(void)
{
// AARGB_NORMAL(bitmap_buffer, bitmap_width, bitmap_height);
AARGB_MAIN(bitmap_buffer, bitmap_width, bitmap_height, 0, 0, bitmap_width-1, bitmap_height-1, 0, 0, opt_test);
}
int MAIN_RUN(char *file_name)
{
// we store the unix time here (seconds)
mytime = time(NULL);
/* print info */ STRING_PRINTV("verbose mode on\n");
/* print info */ STRING_PRINTV("available processors ");
/* print info */ STRING_PRINTVD(max_cpus);
/* print info */ STRING_PRINTV2("\n");
if (opt_openmp){
/* print info */ STRING_PRINTV("requested threads ");
/* print info */ STRING_PRINTVD(max_threads);
/* print info */ STRING_PRINTV2("\n"); }
else{
/* print info */ STRING_PRINTV("no multi processing support\n"); }
/* print info */ if (!(opt_verbose)) STRING_PRINT(file_name);
// /* print info */ STRING_PRINTV(file_name); STRING_PRINTV2("\n");
/* print info */ STRING_PRINTV(file_name); if (opt_verbose) STRING_PRINT("\n");
/* print info */ STRING_PRINTV("loading\n");
// try to load image
int result = 0;
result = BITMAP_LOAD(file_name);
switch (result) {
case 2:
STRING_PRINT("\n");
STRING_PRINTE("error: file ");
STRING_PRINTE(file_name);
STRING_PRINTE(" does not exist\n");
return 1;
break;
case 1:
STRING_PRINT("\n");
STRING_PRINTE("error: file ");
STRING_PRINTE(file_name);
STRING_PRINTE(" cannot be loaded\n");
return 1;
break;
}
// determine new file name
char file_name_new [max_char];
int res;
res = GET_FILE_NAME_NEW(file_name, file_name_new);
if (res > 0){
if (res == 1){
// error code 1 for existing file name
STRING_PRINT("\n"); \
STRING_PRINTE("error: file already exists with the new name "); \
STRING_PRINTE(file_name_new); STRING_PRINTE("\n"); return 1; }
else {
// error code 255 for array boundary error
STRING_PRINT("\n"); \
STRING_PRINTE("error: file name error at file ");
STRING_PRINTE(file_name);
STRING_PRINTE("\n");
return 1; }
}
/* print info */ if (!(opt_verbose)) STRING_PRINT(" .");
if (opt_autoadjust){
/* print info */ STRING_PRINTV("auto adjusting colors\n");
MAIN_AARGB();
}
/* print info */ if (!(opt_verbose)) STRING_PRINT(" .");
if ((opt_resize) || (opt_rotate90) || (opt_rotate180) || (opt_rotate270) || (opt_flipx) || (opt_flipy))
{ if (MAIN_RESIZE()) return 1; }
/* print info */ if (!(opt_verbose)) STRING_PRINT(" .");
/* print info */ STRING_PRINTV("saving\n");
if (BITMAP_SAVE(file_name_new)){ STRING_PRINT("\n");
STRING_PRINTE("error: file ");
STRING_PRINTE(file_name);
STRING_PRINTE(" cannot be saved\n");
return 1; }
/* print info */ if (!(opt_verbose)) STRING_PRINT(" done\n");
/* print info */ STRING_PRINTV("done\n");
return 0;
}
int MAIN_ARGUMENTS_READ(int argc, char **argv)
{
opt_help = 0;
opt_version = 0;
opt_autoadjust = 0;
opt_overwrite = 0;
opt_noexif = 0;
opt_jpg = 0;
opt_jp2 = 0;
opt_png = 0;
opt_bmp = 0;
opt_resize = 0;
opt_rotate90 = 0;
opt_rotate180 = 0;
opt_rotate270 = 0;
opt_flipx = 0;
opt_flipy = 0;
opt_resize_percent = 0;
opt_output = 0;
opt_quality = 0;
opt_threads = 0;
opt_verbose = 0;
opt_recursive = 0;
opt_quiet = 0;
opt_test = 0;
int result = 0; // we store the result value of the MAIN_RUN function
int opt_wrong = 1;
int opt_wrong_total = 0;
int opt_counter = 0;
int opt_quality_space_flag = 0;
int opt_threads_space_flag = 0;
int opt_resize_space_flag = 0;
int opt_output_space_flag = 0;
if (argc >= 2) {
argc--;
char *myarg;
while (argc--){
//printf("%s\n", *argv);
opt_wrong = 1;
myarg = *argv++;
myarg = *argv;
if ((myarg[0] == '-') || (opt_quality_space_flag) || (opt_threads_space_flag) || (opt_resize_space_flag) || (opt_output_space_flag)) {
// checking switches
if ((!STRING_COMPARE(myarg, "-h\0")) || (!STRING_COMPARE(myarg, "--help\0"))){
opt_wrong = 0; opt_help = 1; }
if ((!STRING_COMPARE(myarg, "-v\0")) || (!STRING_COMPARE(myarg, "--version\0"))){
opt_wrong = 0; opt_version = 1; }
if ((!STRING_COMPARE(myarg, "-a\0")) || (!STRING_COMPARE(myarg, "--autoadjust\0"))){
opt_wrong = 0; opt_autoadjust = 1; }
if (!STRING_COMPARE(myarg, "--overwrite\0")){
opt_wrong = 0; opt_overwrite = 1; }
if (!STRING_COMPARE(myarg, "--noexif\0")){
opt_wrong = 0; opt_noexif = 1; }
if (!STRING_COMPARE(myarg, "--jpg\0")){
opt_wrong = 0; opt_jpg = 1; }
if (!STRING_COMPARE(myarg, "--jp2\0")){
opt_wrong = 0; opt_jp2 = 1; }
if (!STRING_COMPARE(myarg, "--png\0")){
opt_wrong = 0; opt_png = 1; }
if (!STRING_COMPARE(myarg, "--bmp\0")){
opt_wrong = 0; opt_bmp = 1; }
// if ((!STRING_COMPARE(myarg, "-R\0")) || (!STRING_COMPARE(myarg, "--recursive\0"))){
// opt_wrong = 0; opt_recursive = 1; }
if ((!STRING_COMPARE(myarg, "-s\0")) || (!STRING_COMPARE(myarg, "--silent\0")) || \
(!STRING_COMPARE(myarg, "--quiet\0"))){
opt_wrong = 0; opt_quiet = 1; }
if ((!STRING_COMPARE(myarg, "-V\0")) || (!STRING_COMPARE(myarg, "--verbose\0"))){
opt_wrong = 0; opt_verbose = 1; }
if (!STRING_COMPARE(myarg, "--test\0")){
opt_wrong = 0; opt_test = 1; opt_autoadjust = 1; }
// checking --output switch
// check if there was space between the --output switch and its parameter
// and if the parameter needs to be parsed separately
if (opt_output_space_flag){
opt_output_space_flag = 0;
int char_offs = 0;
int i = 0;
char output_ending = '\0';
while ((myarg[char_offs+i] != 0) && (i < max_char)){
opt_output_path[i] = myarg[char_offs+i];
output_ending = opt_output_path[i];
i++;
}
// check if output path ends with slash character
// if not, then append it
if (output_ending != slsh){
opt_output_path [i] = slsh;
i++;
}
opt_output_path [i] = 0;
// check if specified output directory is a dir and if it exists
DIR * dp;
dp = opendir(opt_output_path);
if (dp == NULL){
STRING_PRINTE("error: bad directory parameter\n"); return 1; }
opt_output = 1;
opt_wrong = 0;
}
if ((!STRING_COMPARE_FIX(myarg, "-o", 2)) || (!STRING_COMPARE_FIX(myarg, "--output", 8))){
int char_offs;
if (!STRING_COMPARE_FIX(myarg, "--output", 8)){
char_offs = 8;
}
else{
char_offs = 2;
}
int i = 0;
// check if there is space between the switch and its parameter
if (myarg[char_offs+i] == 0){
opt_output_space_flag = 1;
opt_wrong = 0;
}
else{
char output_ending = '\0';
while ((myarg[char_offs+i] != 0) && (i < max_char)){
opt_output_path[i] = myarg[char_offs+i];
output_ending = opt_output_path[i];
i++;
}
// check if output path ends with slash character
// if not, then append it
if (output_ending != slsh){
opt_output_path [i] = slsh;
i++;
}
opt_output_path [i] = 0;
// check if specified output directory is a dir and if it exists
DIR * dp;
dp = opendir(opt_output_path);
if (dp == NULL){
STRING_PRINTE("error: bad directory parameter\n"); return 1; }
opt_output = 1;
opt_wrong = 0;
}
}
// checking --quality switch
// check if there was space between the --quality switch and its parameter
// and if the parameter needs to be parsed separately
if (opt_quality_space_flag){
opt_quality_space_flag = 0;
char num [8+1] = "";
int num_max = 8;
int num_offs = 0;
int i = 0;
while ((myarg[num_offs+i] != 0) && (i < num_max)){
num[i] = myarg[num_offs+i];
i++;
}
num [i] = 0;
if (i >= num_max){ STRING_PRINTE("error: bad parameters\n"); return 1; }
if (STRING_CONVERT_TO_INTEGER(num, &opt_quality)){
STRING_PRINTE("error: bad parameters\n"); return 1; }
if ((opt_quality >= 1) && (opt_quality <= 100)){ opt_wrong = 0; }
else{ STRING_PRINTE("error: bad parameters\n"); return 1; }
}
if ((!STRING_COMPARE_FIX(myarg, "-q", 2)) || (!STRING_COMPARE_FIX(myarg, "--quality", 9))){
char num [8+1] = "";
int num_max = 8;
int num_offs;
if (!STRING_COMPARE_FIX(myarg, "--quality", 9)){
num_offs = 9;
}
else{
num_offs = 2;
}
int i = 0;
// check if there is space between the switch and its parameter
if (myarg[num_offs+i] == 0){
opt_quality_space_flag = 1;
opt_wrong = 0;
}
else{
while ((myarg[num_offs+i] != 0) && (i < num_max)){
num[i] = myarg[num_offs+i];
i++;
}
num [i] = 0;
if (i >= num_max){ STRING_PRINTE("error: bad parameters\n"); return 1; }
if (STRING_CONVERT_TO_INTEGER(num, &opt_quality)){
STRING_PRINTE("error: bad parameters\n"); return 1; }
if ((opt_quality >= 1) && (opt_quality <= 100)){ opt_wrong = 0; }
else{ STRING_PRINTE("error: bad parameters\n"); return 1; }
}
}
// checking --threads switch
// check if there was space between the --threads switch and its parameter
// and if the parameter needs to be parsed separately
if (opt_threads_space_flag){
opt_threads_space_flag = 0;
char num [8+1] = "";
int num_max = 8;
int num_offs = 0;
int i = 0;
while ((myarg[num_offs+i] != 0) && (i < num_max)){
num[i] = myarg[num_offs+i];
i++;
}
num [i] = 0;
if (i >= num_max){ STRING_PRINTE("error: bad parameters\n"); return 1; }
if (STRING_CONVERT_TO_INTEGER(num, &opt_threads)){
STRING_PRINTE("error: bad parameters\n"); return 1; }
if ((opt_threads >= 1) && (opt_threads <= max_num_threads)){ opt_wrong = 0; }
else{
STRING_PRINTE("error: bad parameters, threads value must be between 1 and ");
STRING_PRINTED(max_num_threads);
STRING_PRINTE("\n");
return 1; }
max_threads = opt_threads;
}
if ((!STRING_COMPARE_FIX(myarg, "-t", 2)) || (!STRING_COMPARE_FIX(myarg, "--threads", 9))){
char num [8+1] = "";
int num_max = 8;
int num_offs;
if (!STRING_COMPARE_FIX(myarg, "--threads", 9)){
num_offs = 9;
}
else{
num_offs = 2;
}
int i = 0;
// check if there is space between the switch and its parameter
if (myarg[num_offs+i] == 0){
opt_threads_space_flag = 1;
opt_wrong = 0;
}
else{
while ((myarg[num_offs+i] != 0) && (i < num_max)){
num[i] = myarg[num_offs+i];
i++;
}
num [i] = 0;
if (i >= num_max){ STRING_PRINTE("error: bad parameters\n"); return 1; }
if (STRING_CONVERT_TO_INTEGER(num, &opt_threads)){
STRING_PRINTE("error: bad parameters\n"); return 1; }
if ((opt_threads >= 1) && (opt_threads <= max_num_threads)){ opt_wrong = 0; }
else{
STRING_PRINTE("error: bad parameters, threads value must be between 1 and ");
STRING_PRINTED(max_num_threads);
STRING_PRINTE("\n");
return 1; }
max_threads = opt_threads;
}
}
// checking --resize switch
// check if there was space between the --resize switch and its parameter
// and if the parameter needs to be parsed separately
if (opt_resize_space_flag){
opt_resize_space_flag = 0;
char num [16+1] = "";
int num_max = 16;
int num_offs = 0;
int i = 0;
while ((myarg[num_offs+i] != 0) && (myarg[num_offs+i] != '%') && (i < num_max)){
num[i] = myarg[num_offs+i];
i++;
}
num [i] = 0;
if (i >= num_max){ STRING_PRINTE("error: bad parameters\n"); return 1; }
// is the resize value given in percentage?
if (myarg[num_offs+i] == '%') opt_resize_percent = 1;
if (STRING_CONVERT_TO_INTEGER(num, &opt_resize)){
STRING_PRINTE("error: bad parameters\n"); return 1; }
if (opt_resize_percent){
if ((opt_resize >= 1) && (opt_resize <= 100)){ opt_wrong = 0; }
else{ STRING_PRINTE("error: bad parameters\n"); return 1; }
}
else{
if ((opt_resize >= 1) && (opt_resize <= 100000)){ opt_wrong = 0; }
else{ STRING_PRINTE("error: bad parameters\n"); return 1; }
}
}
if ((!STRING_COMPARE_FIX(myarg, "-r", 2)) || (!STRING_COMPARE_FIX(myarg, "--resize", 8))){
char num [16+1] = "";
int num_max = 16;
int num_offs;
if (!STRING_COMPARE_FIX(myarg, "--resize", 8)){
num_offs = 8;
}
else{
num_offs = 2;
}
int i = 0;
// check if there is space between the switch and its parameter
if (myarg[num_offs+i] == 0){
opt_resize_space_flag = 1;
opt_wrong = 0;
}
else{
while ((myarg[num_offs+i] != 0) && (myarg[num_offs+i] != '%') && (i < num_max)){
num[i] = myarg[num_offs+i];
i++;
}
num [i] = 0;
if (i >= num_max){ STRING_PRINTE("error: bad parameters\n"); return 1; }
// is the resize value given in percentage?
if (myarg[num_offs+i] == '%') opt_resize_percent = 1;
if (STRING_CONVERT_TO_INTEGER(num, &opt_resize)){
STRING_PRINTE("error: bad parameters\n"); return 1; }
if (opt_resize_percent){
if ((opt_resize >= 1) && (opt_resize <= 100)){ opt_wrong = 0; }
else{ STRING_PRINTE("error: bad parameters\n"); return 1; }
}
else{
if ((opt_resize >= 1) && (opt_resize <= 100000)){ opt_wrong = 0; }
else{ STRING_PRINTE("error: bad parameters\n"); return 1; }
}
}
}
// checking --rotate and --flip switches
if (!STRING_COMPARE(myarg, "--rotate90\0")){ opt_wrong = 0; opt_rotate90 = 1; }
if (!STRING_COMPARE(myarg, "--rotate180\0")){ opt_wrong = 0; opt_rotate180 = 1; }
if (!STRING_COMPARE(myarg, "--rotate270\0")){ opt_wrong = 0; opt_rotate270 = 1; }
if (!STRING_COMPARE(myarg, "--flipx\0")){ opt_wrong = 0; opt_flipx = 1; }
if (!STRING_COMPARE(myarg, "--flipy\0")){ opt_wrong = 0; opt_flipy = 1; }
// we remember if there were switches but given in bad way
if (opt_wrong){ opt_wrong_total = 1; }
else{ opt_counter++; }
}
else {
// expanding the file list that contains the files to be processed one by one
FILE_LIST_ADD(myarg);
}
}
// error message if bad parameters
// error message also when missing extra parameter
if ((opt_wrong_total) || (opt_quality_space_flag) || (opt_threads_space_flag) || (opt_resize_space_flag) || (opt_output_space_flag)){
STRING_PRINTE("error: bad parameters\n"); return 1; }
else{
// check if only 1 type of output format is specified on input
int format_cnt = 0;
if (opt_jpg) format_cnt++;
if (opt_jp2) format_cnt++;
if (opt_png) format_cnt++;
if (opt_bmp) format_cnt++;
if (format_cnt > 1){
STRING_PRINTE("error: only one output format allowed\n");
return 1; }
// managing info switches
if (opt_version) { PRINT_VERSION(); PRINT_LICENSE(); }
if (opt_help) { PRINT_DESCRIPTION(); PRINT_HELP(); }
// AUTOADJUST DEFAULT = 1 IF NO OTHER PARAMETER EXCEPT FILE NAME
// if no parameters given except file names, then the --autoadjust parameter is 1 by default
if ((opt_counter <= 0) && (file_name_counter > 0)) { opt_autoadjust = 1; opt_counter++; }
// Main processing work of the switches (load -> process -> save)
// ------------------------------------------------------------------
// checking switches that need file name as input
if ((opt_autoadjust != 0) ||
(opt_overwrite != 0) ||
(opt_noexif != 0) ||
(opt_jpg != 0) ||
(opt_jp2 != 0) ||
(opt_png != 0) ||
(opt_bmp != 0) ||
(opt_resize != 0) ||
(opt_rotate90 != 0) ||
(opt_rotate180 != 0) ||
(opt_rotate270 != 0) ||
(opt_flipx != 0) ||
(opt_flipy != 0) ||
(opt_output != 0) ||
(opt_quality != 0) ||
(opt_recursive != 0) ||
(opt_test != 0)){
// were there any file names given as input?
if (file_name_counter > 0){
// if there are more than 1 files to read, then no error messages are print during process
//if (file_name_counter > 1) opt_quiet = 1;
// if the number of input files is greater than 0, then we process them one by one
char tt[max_char];
int c = 0;
int d;
int i;
for (i=0; i<file_name_counter; i++){
d = 0;
while (file_name_buffer[c] != 0){
if (d >= max_char) return 255;
if (c >= max_file_name_buffer) return 255;
tt[d] = file_name_buffer[c];
d++;
c++;
}
tt[d] = 0; d++; c++;
// --------------------------------------------------------
if (MAIN_RUN(tt)) { result = 1; }
// --------------------------------------------------------
}
}
// error here, because no input file names were given
else {
STRING_PRINTE("error: file name missing\n");
return 1;
}
}
}
}
// if no switches or file names or any parameters were given,
// -saying it other way the argument counter = 1 which is the command name itself-
// then print something
else {
//PRINT_VERSION();
//PRINT_DESCRIPTION();
//PRINT_LICENSE();
//PRINT_HELP();
STRING_PRINTE("No parameters given. Use -h (--help) for more information\n");
}
return result;
}
int MAIN_INIT(void)
{
// we store the unix time here (seconds)
mytime = time(NULL);
// OpenMP
// defining the maximum number of threads, this is important to set it in the beginning already
// cause fixed arrays will have to be defined knowing that value
max_cpus = 1;
max_threads = 1;
max_num_threads = 1024;
opt_openmp = 0;
#ifdef __OPENMP__
// is there openmp support?
opt_openmp = 1;
// getting the number of available processors to know maximum number of threads
max_cpus = omp_get_num_procs();
max_threads = max_cpus;
// set it to minimum 1
if (max_threads < 1){ max_threads = 1; }
#endif
// number of files
file_counter = 0;
// number of files stored in file_name_buffer
file_name_counter = 0;
// pointer pointing to the end of the file names read from the files that are stored in file_name_buffer
// saying it other way, it is the offset pointer pointing to the next file name
file_name_buffer_pointer = 0;
// allocating memory
file_name_buffer = malloc(max_file_name_buffer);
if (file_name_buffer == 0){
STRING_PRINTE("error: memory allocation failure\n"); return 1; }
#ifndef __BMP_ONLY__
bitmap_format_png_interlace_type = PNG_INTERLACE_NONE;
bitmap_format_png_compression_type = PNG_COMPRESSION_TYPE_DEFAULT;
bitmap_format_png_filter_type = PNG_FILTER_TYPE_DEFAULT;
#endif
// set default image resolution
// 2835 dots per meter is equal to 72 dots per inch
xdpi = 2835;
ydpi = 2835;
udpi = 1;
return 0;
}
int main(int argc, char **argv)
{
if (MAIN_INIT()) return 1;
int result = 0;
if (MAIN_ARGUMENTS_READ(argc, argv)){ result = 1; }
free(file_name_buffer);
return result;
}
|