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