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 
20 /* ----------------------------------------------------- */
21 /* ----------- STRING CONVERT TO LOWER CASE ------------ */
22 /* ----------------------------------------------------- */
STRING_CONVERT_TO_LCASE(char * strin,char * strout)23 void STRING_CONVERT_TO_LCASE(char *strin, char *strout)
24 {
25 	int i;
26 	for (i=0; strin[i]!=0; i++){
27 		if (i < max_char-1){
28 			strout[i]=tolower(strin[i]); }
29 	}
30 	strout[i]=0;
31 }
32 
33 
34 
35 
36 /* -------------------------------------------------- */
37 /* ----------- STRING CONVERT TO INTEGER ------------ */
38 /* -------------------------------------------------- */
STRING_CONVERT_TO_INTEGER(char * str,int * number)39 int STRING_CONVERT_TO_INTEGER(char *str, int *number)
40 {
41 	int i, c, d;
42 	int xx = 0;
43 	int yy;
44 	int num;
45 	int num_max = 8;
46 	i = 0;
47 	while ((str[i]) && (i < num_max)){ i++; }
48 	if (i >= num_max) return 1;
49 	c = i;
50 	num = 0;
51 	if (c > 0){
52 		d = 1;
53 		for (i=1; i<=c; i++){
54 
55 			yy = 1;
56 			if (str[c-i] == '0') { xx = 0; yy = 0; }
57 			if (str[c-i] == '1') { xx = 1; yy = 0; }
58 			if (str[c-i] == '2') { xx = 2; yy = 0; }
59 			if (str[c-i] == '3') { xx = 3; yy = 0; }
60 			if (str[c-i] == '4') { xx = 4; yy = 0; }
61 			if (str[c-i] == '5') { xx = 5; yy = 0; }
62 			if (str[c-i] == '6') { xx = 6; yy = 0; }
63 			if (str[c-i] == '7') { xx = 7; yy = 0; }
64 			if (str[c-i] == '8') { xx = 8; yy = 0; }
65 			if (str[c-i] == '9') { xx = 9; yy = 0; }
66 			if (yy) return 1;
67 
68 			num += xx * d;
69 			d *= 10;
70 		}
71 	}
72 	else{ return 1; }
73 
74 	*number = num;
75 	return 0;
76 }
77 
78 
79 
80 
81 /* ------------------------------------- */
82 /* ----------- STRING PRINT ------------ */
83 /* ------------------------------------- */
84 /* print text to stdout */
STRING_PRINT(const char str[])85 void STRING_PRINT(const char str[])
86 {
87 	if (!(opt_quiet)){
88 		fprintf(stdout, "%s", str);
89 		fflush(stdout);
90 	}
91 }
92 
93 
94 
95 
96 /* ------------------------------------- */
97 /* -------- STRING PRINT ERROR --------- */
98 /* ------------------------------------- */
99 /* print text to stderr */
STRING_PRINTE(const char str[])100 void STRING_PRINTE(const char str[])
101 {
102 /*	if (!(opt_quiet)){ */
103 		fprintf(stderr, "%s", str);
104 		fflush(stderr);
105 /*	} */
106 }
107 
108 
109 
110 
111 /* ------------------------------------- */
112 /* ------- STRING PRINT VERBOSE -------- */
113 /* ------------------------------------- */
114 /* print time and text to stdout if in verbose mode */
STRING_PRINTV(const char str[])115 void STRING_PRINTV(const char str[])
116 {
117     if(opt_verbose){
118 	if (!(opt_quiet)){
119 		/* print time since start in seconds if bigger than 1 */
120 		/* and decrement the time by 1 because the program may start in a middle of a second, that i don't know */
121 		int t = time(NULL) - mytime;
122 		if (t > 1){ printf("(%d) ", t-1); }
123 		/* print text */
124 		fprintf(stdout, "%s", str);
125 		fflush(stdout);
126 	}
127     }
128 }
129 
STRING_PRINTV2(const char str[])130 void STRING_PRINTV2(const char str[])
131 {
132     if(opt_verbose){
133 	if (!(opt_quiet)){
134 		/* print text */
135 		fprintf(stdout, "%s", str);
136 		fflush(stdout);
137 	}
138     }
139 }
140 
141 
142 
143 
144 /* -------------------------------------- */
145 /* ----------- STRING PRINTVD ----------- */
146 /* -------------------------------------- */
147 /* print decimal number to stdout */
STRING_PRINTVD(int num)148 void STRING_PRINTVD(int num)
149 {
150 	if(opt_verbose){
151 		if (!(opt_quiet)){
152        			fprintf(stdout, "%d", num);
153 			fflush(stdout);
154 		}
155 	}
156 }
157 
158 
159 
160 
161 /* -------------------------------------- */
162 /* ----------- STRING PRINTED ----------- */
163 /* -------------------------------------- */
164 /* print decimal number to stderr */
STRING_PRINTED(int num)165 void STRING_PRINTED(int num)
166 {
167 	if (!(opt_quiet)){
168 		fprintf(stderr, "%d", num);
169 		fflush(stderr);
170 	}
171 }
172 
173 
174 
175 
176 /* -------------------------------------- */
177 /* ----------- STRING PRINTF ------------ */
178 /* -------------------------------------- */
179 /* print floating number to stdout */
STRING_PRINTF(double num)180 void STRING_PRINTF(double num)
181 {
182 	if (!(opt_quiet)){
183        		fprintf(stdout, "%.2f", num);
184 		fflush(stdout);
185 	}
186 }
187 
188 
189 
190 
191 /* --------------------------------------- */
192 /* ----------- STRING COMPARE ------------ */
193 /* --------------------------------------- */
194 /* compare two string values */
195 /* result is 0 if true */
STRING_COMPARE(char * str1,char * str2)196 int STRING_COMPARE(char *str1, char *str2)
197 {
198 	int i = 0;
199 	int result = 0;
200 	while ((str1[i]) && (str2[i])) {
201 		if (str1[i] != str2[i]) result = 1;
202 		i++;
203 	}
204 	if (str1[i] != str2[i]) result = 1;
205 	return result;
206 }
207 
208 
209 
210 
211 /* --------------------------------------------------------- */
212 /* ----------- STRING COMPARE WITH FIXED LENGTH ------------ */
213 /* --------------------------------------------------------- */
STRING_COMPARE_FIX(char * str1,char * str2,int count)214 int STRING_COMPARE_FIX(char *str1, char *str2, int count)
215 {
216 	int result = 0;
217 	int i;
218 	for (i=0; i<count; i++)
219 		if (str1[i] != str2[i]) result = 1;
220 	return result;
221 }
222 
223 
224 
225 
226 /* -------------------------------------- */
227 /* ----------- GET FILE NAME ------------ */
228 /* -------------------------------------- */
229 /* get file name from path */
GET_FILE_NAME(char * strin,char * strout)230 void GET_FILE_NAME(char *strin, char *strout)
231 {
232 	/* check length of string */
233 	long len;
234 	long i, c;
235 	for (i=0; strin[i]!='\0'; i++);
236 	len = i;
237 	/* check only path */
238 	c = 0;
239 	i = len-1;
240 	while ((i >= 0) && (strin[i] != slsh)) { c++; i--; }
241 	/*if (i >= 0) { */
242 		for (i=0; i<c; i++) {
243 			if (i < max_char) {
244 				strout[i] = strin[i+len-c]; }
245 		}
246 		strout[i] = 0;
247 	/*} */
248 }
249 
250 
251 
252 
253 /* ------------------------------------------- */
254 /* ----------- GET FILE NAME ONLY ------------ */
255 /* ------------------------------------------- */
256 /* get only the file name of the path */
GET_FILE_NAME_ONLY(char * strin,char * strout)257 void GET_FILE_NAME_ONLY(char *strin, char *strout)
258 {
259 	/* check length of string */
260 	long len;
261 	long i, c, st;
262 	for (i=0; strin[i]!='\0'; i++);
263 	len = i;
264 	/* check only path */
265 	i = len-1;
266 	while ((i >= 0) && (strin[i] != slsh)) { i--; }
267     st = i + 1;
268 	/* check extension of file */
269 	c = 0;
270 	i = len-1;
271 	while ((i >= 0) && (strin[i] != '.')) { i--; }
272 	c = i - 1;
273 	if (c >= st) {
274 		for (i=0; i<c-st+1; i++) {
275 			if (i < max_char-1) {
276 				strout[i] = strin[i+st]; }
277 			}
278 		strout[i] = 0;
279 	}
280 	else {
281 		strout[0] = 0;
282 	}
283 }
284 
285 
286 
287 
288 /* ------------------------------------------- */
289 /* ----------- GET FILE EXTENSION ------------ */
290 /* ------------------------------------------- */
291 /* get extenstion of the file in path */
GET_FILE_EXTENSION(char * strin,char * strout)292 void GET_FILE_EXTENSION(char *strin, char *strout)
293 {
294 	/* check length of string */
295 	long len;
296 	long i, c;
297 	for (i=0; strin[i]!='\0'; i++);
298 	len = i;
299 	/* check extension of file */
300 	c = 0;
301 	i = len-1;
302 	while ((i >= 0) && (strin[i] != '.')) { c++; i--; }
303 	c++;
304 	if (c > 0) {
305 		for (i=0; i<c; i++) {
306 			if (i < max_char-1) {
307 				strout[i] = strin[i+len-c]; } }
308 		strout[i] = 0;
309 	}
310 	else {
311 		strout[0] = 0;
312 	}
313 }
314 
315 
316 
317 
318 /* ------------------------------------------ */
319 /* ------------- GET FILE PATH -------------- */
320 /* ------------------------------------------ */
321 /* get file path */
GET_FILE_PATH(char * strin,char * strout)322 void GET_FILE_PATH(char *strin, char *strout)
323 {
324 	/* check length of string */
325 	long len;
326 	long i, c;
327 	for (i=0; strin[i]!='\0'; i++);
328 	len = i;
329 	/* check only path */
330 	c = 0;
331 	i = len-1;
332 	while ((i >= 0) && (strin[i] != slsh)) { c++; i--; }
333 	if (i >= 0) {
334 		for (i=0; i<len-c; i++) {
335 			if (i < max_char-1) {
336 				strout[i] = strin[i]; }
337 		}
338 		strout[i] = 0;
339 	}
340 	else {
341 		strout[0] = 0;
342 	}
343 }
344 
345 
346 
347 
348 /* ---------------------------------------- */
349 /* ------------ FILE EXIST? --------------- */
350 /* ---------------------------------------- */
FILE_EXIST(char * file_name)351 int FILE_EXIST(char *file_name)
352 {
353 	FILE *fhandle;
354 	fhandle = fopen(file_name, "rb");
355 	if (fhandle == 0) return 0;
356 	fclose(fhandle);
357 	return 1;
358 }
359 
360 
361 
362 
363 /* ---------------------------------------------- */
364 /* ------------- GET FILE NAME NEW -------------- */
365 /* ---------------------------------------------- */
366 /* put together the new output file name */
GET_FILE_NAME_NEW(char * strin,char * strout)367 int GET_FILE_NAME_NEW(char *strin, char *strout)
368 {
369 	char fpath [max_char];
370 	char fname [max_char];
371 	char fext  [max_char];
372 	char fextj1 [] = ".jpg\0";
373 	char fextj2 [] = ".jp2\0";
374 	char fextj3 [] = ".png\0";
375 	char fextj4 [] = ".bmp\0";
376 	char fnew   [] = "_new";
377 	long i, c;
378 
379 	GET_FILE_PATH(strin, fpath);
380 	GET_FILE_NAME_ONLY(strin, fname);
381 	GET_FILE_EXTENSION(strin, fext);
382 
383 	c = 0;
384 
385 	if (!(opt_output))
386 	{
387 		i = 0;
388 		while (fpath[i] != '\0')
389 		{
390 			if (c >= max_char) return 255;
391 			strout[c] = fpath[i];
392 			i++; c++;
393 		}
394 	}
395 	else
396 	{
397 		i = 0;
398 		while (opt_output_path[i] != '\0')
399 		{
400 			if (c >= max_char) return 255;
401 			strout[c] = opt_output_path[i];
402 			i++; c++;
403 		}
404 	}
405 
406 	i = 0;
407 	while (fname[i] != '\0')
408 	{
409 		if (c >= max_char) return 255;
410 		strout[c] = fname[i];
411 		i++; c++;
412 	}
413 
414 	if (!(opt_overwrite))
415 	{
416 		i = 0;
417 		while (fnew[i] != '\0')
418 		{
419 			if (c >= max_char) return 255;
420 			strout[c] = fnew[i];
421 			i++; c++;
422 		}
423 	}
424 
425 	i = 0;
426 	while (fext[i] != '\0')
427 	{
428 		if (c >= max_char) return 255;
429 		if ((!opt_jpg) && (!opt_jp2) && (!opt_png) && (!opt_bmp)) strout[c] = fext[i];
430 		if (opt_jpg) strout[c] = fextj1[i];
431 		if (opt_jp2) strout[c] = fextj2[i];
432 		if (opt_png) strout[c] = fextj3[i];
433 		if (opt_bmp) strout[c] = fextj4[i];
434 		i++; c++;
435 	}
436 	if (c >= max_char) return 255;
437 	strout[c] = fext[i];
438 
439 	if (opt_jpg) bitmap_format_jpg_file_type = 6;
440 	if (opt_jp2) bitmap_format_jpg_file_type = 4;
441 
442 	if (!(opt_overwrite) && (FILE_EXIST(strout))) return 1;
443 
444 	return 0;
445 
446 }
447 
448 
449 
450 
451 /* -------------------------------------------- */
452 /* ------------- GET FILE FORMAT -------------- */
453 /* -------------------------------------------- */
GET_FILE_FORMAT(char * file_name)454 int GET_FILE_FORMAT(char *file_name)
455 {
456 	int res;
457 	char fext[max_char];
458 	char fextl[max_char];
459 
460 	/* JasPer format codes (0-7) */
461 	/* --------------------------- */
462 	/* 0 - mif */
463 	/* 1 - pnm / pgm / ppm */
464 	/* 2 - bmp */
465 	/* 3 - ras */
466 	/* 4 - jp2 */
467 	/* 5 - jpc */
468 	/* 6 - jpg */
469 	/* 7 - pgx */
470 	/* 8 - png */
471 
472 	GET_FILE_EXTENSION(file_name, fext);
473 
474 	STRING_CONVERT_TO_LCASE(fext, fextl);
475 
476 	res = -1;
477 
478 	if (!STRING_COMPARE(fextl, ".mif"))  res = 0;
479 	if (!STRING_COMPARE(fextl, ".pnm"))  res = 1;
480 	if (!STRING_COMPARE(fextl, ".pgm"))  res = 1;
481 	if (!STRING_COMPARE(fextl, ".ppm"))  res = 1;
482 	if (!STRING_COMPARE(fextl, ".bmp"))  res = 2;
483 	if (!STRING_COMPARE(fextl, ".ras"))  res = 3;
484 	if (!STRING_COMPARE(fextl, ".jp2"))  res = 4;
485 	if (!STRING_COMPARE(fextl, ".jpc"))  res = 5;
486 	if (!STRING_COMPARE(fextl, ".jpg"))  res = 6;
487 	if (!STRING_COMPARE(fextl, ".jpeg"))  res = 6;
488 	if (!STRING_COMPARE(fextl, ".jpe"))  res = 6;
489 /*	if (!STRING_COMPARE(fextl, ".pgx"))  res = 7; */
490 	if (!STRING_COMPARE(fextl, ".png"))  res = 8;
491 
492 	return res;
493 }
494 
495 
496 
497 
498 /* ----------------------------------------- */
499 /* ----------- FILE LIST ADD --------------- */
500 /* ----------------------------------------- */
FILE_LIST_ADD(char * file_name)501 int FILE_LIST_ADD(char *file_name)
502 {
503 	/* isn't the file name buffer full yet? */
504 	if (file_name_buffer_pointer + max_char < max_file_name_buffer){
505 
506 /*
507         char fpath [max_char];
508 		char fname [max_char];
509 		char fext  [max_char];
510 		GET_FILE_PATH(file_name, fpath);
511 		GET_FILE_NAME_ONLY(file_name, fname);
512 		GET_FILE_EXTENSION(file_name, fext);
513 */
514 
515         DIR *                   dp;
516         DIR *                   dp2;
517         const struct dirent *   ent;
518         int                     cnt;
519 
520 	/* if the name points to a directory */
521         dp = opendir(file_name);
522         if (dp != NULL){
523 
524             /* list files in directory */
525             cnt = 0;
526             while (ent = readdir(dp), ent != NULL)
527             {
528 		int i, i2, res, flag;
529             	char file_name_new [max_char];
530 
531                 res = 0;
532 	            if (!STRING_COMPARE((char*)(ent->d_name), "."))  res = 1;
533 	            if (!STRING_COMPARE((char*)(ent->d_name), "..")) res = 1;
534                 if (res == 0){
535 
536                 cnt++;
537 
538 		/* create new file name with path */
539        		i = 0;
540        		while (file_name[i]){
541 		    if (i >= max_char) return 255;
542                     file_name_new[i] = file_name[i]; i++; }
543 
544 		/* remove '/' characters from the end of directory names when more than 1 */
545                 flag = 0;
546                 while ((i > 1) && (flag == 0)) {
547                     if (file_name_new[i-1] == slsh) { i--; }
548                     else { flag = 1; } }
549 		/* add '/' character to directory path */
550                 file_name_new[i] = slsh;
551 
552 		/* add found file name to directory path */
553                 i++;
554           	i2 = 0;
555            	while (ent->d_name[i2]){
556                     file_name_new[i] = ent->d_name[i2]; i++; i2++; }
557                 file_name_new[i] = 0;
558 
559 
560 		/* if new name is not a dir, then store file name */
561                 dp2 = opendir(file_name_new);
562                 if (dp2 != NULL){ closedir(dp2); }
563                 else{
564 			int i, len;
565 
566             		i = 0;
567             		while (file_name_new[i]){ i++; }
568         	    	len = i;
569         			for (i=0; i<len; i++){
570         				file_name_buffer[file_name_buffer_pointer] = file_name_new[i];
571         				file_name_buffer_pointer++;
572         			}
573         			file_name_buffer[file_name_buffer_pointer] = '\0';
574         			file_name_buffer_pointer++;
575         			file_name_counter++;
576 
577                     /* printf("%s\n", file_name_new); */
578                 }
579 
580                 }
581 
582             }
583             closedir(dp);
584             dp = NULL;
585         }
586 
587 	/* the name is a file, so i store it */
588         else{
589 		int i, len;
590 
591     		i = 0;
592     		while (file_name[i]){ i++; }
593 	    	len = i;
594 			for (i=0; i<len; i++){
595 				file_name_buffer[file_name_buffer_pointer] = file_name[i];
596 				file_name_buffer_pointer++;
597 			}
598 			file_name_buffer[file_name_buffer_pointer] = '\0';
599 			file_name_buffer_pointer++;
600 			file_name_counter++;
601         }
602 
603     }
604     else { return 1; }
605 	return 0;
606 
607 }
608 
609 
610 
611 
612 /* -----------------------------------
613              --- EXIF ---
614    -----------------------------------
615     char *exif_buffer;
616     long  exif_buffer_length;
617     long  exif_file_length;
618     int   exif_flag;
619 
620     http://en.wikipedia.org/wiki/JPEG
621     http://www.media.mit.edu/pia/Research/deepview/exif.html
622   ------------------------------------
623   ------------------------------------
624 */
625 
626 
627 /* -------------------------------------- */
628 /* ----------- EXIF CLEAR --------------- */
629 /* -------------------------------------- */
630 /* clear exif information and deallocate memory */
EXIF_CLEAR()631 int EXIF_CLEAR()
632 {
633     if (exif_flag) {
634 	/* print info */ STRING_PRINTV("freeing exif buffer\n");
635         free(exif_buffer);
636         exif_buffer_length = 0;
637         exif_flag = 0;
638     }
639     return 0;
640 }
641 
642 
643 
644 
645 /* ------------------------------------ */
646 /* ----------- EXIF GET --------------- */
647 /* ------------------------------------ */
648 /* read exif information from file and store it in memory */
EXIF_GET(char * file_name)649 int EXIF_GET(char *file_name)
650 {
651     int exif_ok, exif_bad;
652     long exif_start, exif_offset;
653     int ch1, ch2;
654     FILE *fhandle;
655 
656     exif_flag = 0;
657 
658     /* if --noexif flag was specified, then i don't store exif from image */
659     if (opt_noexif) { return 1; }
660 
661     /* print info */ STRING_PRINTV("checking exif info\n");
662 
663     /* open file for reading */
664     fhandle = fopen(file_name, "rb");
665     if (fhandle == 0) return 1;
666     /* determine the length of file */
667     fseek(fhandle, 0, SEEK_END);
668     exif_file_length = ftell(fhandle);
669     fseek(fhandle, 0, SEEK_SET);
670 
671 
672     /* examine exif information and check its length */
673     exif_start = 0;
674     exif_offset = 0;
675     ch1 = 0;
676     ch2 = 0;
677 
678     /* FFD8 JPEG indicator */
679     fseek(fhandle, 0, SEEK_SET);
680     ch1 = fgetc(fhandle);
681     ch2 = fgetc(fhandle);
682     if ((ch1 != 0xff) || (ch2 != 0xd8)) {
683     	fclose(fhandle);
684         return 1;
685     }
686 
687     /* seek for beginning of exif info (start offset = 2) */
688     exif_start = 2;
689     exif_ok = 0;
690     exif_bad = 0;
691     while ((exif_ok == 0) && (exif_bad == 0)) {
692 
693         /* FFE1 Exif indicator */
694         fseek(fhandle, exif_start + 0, SEEK_SET);
695         ch1 = fgetc(fhandle);
696         ch2 = fgetc(fhandle);
697 	/* if indicator does not start with FF */
698 	/* (the id tag of the next block within JPEG format) */
699 	/* then exit, because this is an error */
700         if (ch1 != 0xff) { exif_bad = 1; }
701         else {
702 	    /* search for FFE1 exif array indicator */
703             if ((ch1 != 0xff) || (ch2 != 0xe1)) {
704 
705 		/* check length of exif array */
706                 fseek(fhandle, exif_start + 2, SEEK_SET);
707                 ch1 = fgetc(fhandle);
708                 ch2 = fgetc(fhandle);
709                 exif_offset = (long)(ch1) * 256 + (long)(ch2);
710                 exif_start += 2 + exif_offset;
711 		/* exit if pointer reaches the end of file */
712 		if (exif_start >= exif_file_length) { exif_bad = 1; }
713 
714             }
715             else {
716 
717                 exif_ok = 1;
718 
719 		/* check 'Exif00' pattern 45 78 69 66 00 00 */
720                 fseek(fhandle, exif_start + 4, SEEK_SET);
721                 ch1 = fgetc(fhandle);
722                 ch2 = fgetc(fhandle);
723                 if ((ch1 != 0x45) || (ch2 != 0x78)) {
724                     exif_ok = 0;
725                 }
726                 fseek(fhandle, exif_start + 6, SEEK_SET);
727                 ch1 = fgetc(fhandle);
728                 ch2 = fgetc(fhandle);
729                 if ((ch1 != 0x69) || (ch2 != 0x66)) {
730                     exif_ok = 0;
731                 }
732                 fseek(fhandle, exif_start + 8, SEEK_SET);
733                 ch1 = fgetc(fhandle);
734                 ch2 = fgetc(fhandle);
735                 if ((ch1 != 0x00) || (ch2 != 0x00)) {
736                     exif_ok = 0;
737                 }
738 
739                 /* check length of exif array */
740                 if (exif_ok == 1) {
741                     fseek(fhandle, exif_start + 2, SEEK_SET);
742                     ch1 = fgetc(fhandle);
743                     ch2 = fgetc(fhandle);
744 		    /* exif length = exif pointer + 2 */
745 		    /* with the extra 2 bytes we take the FFE1 exif marker too into the buffer */
746                     exif_buffer_length = (long)(ch1) * 256 + (long)(ch2) + 2;
747                 }
748 		else {
749 			exif_bad = 1;
750 		}
751 
752             }
753         }
754 
755     }
756 
757     if (exif_ok == 0) {
758     	fclose(fhandle);
759         return 1;
760     }
761 
762     /* allocate memory for file load */
763     /* print info */ STRING_PRINTV("allocating memory for exif buffer\n");
764     exif_buffer = malloc(exif_buffer_length * sizeof (*exif_buffer));
765     if (exif_buffer == 0) {
766         fclose(fhandle);
767         return 1;
768     }
769 
770     /* load exif part of file into memory */
771     /* print info */ STRING_PRINTV("reading exif info\n");
772     fseek(fhandle, exif_start, SEEK_SET);
773     if (fread(exif_buffer, 1, exif_buffer_length, fhandle) == 0) {
774     	fclose(fhandle);
775         return 1;
776     }
777 
778     /* close file */
779     fclose(fhandle);
780     exif_flag = 1;
781     return 0;
782 }
783 
784 
785 
786 
787 /* ------------------------------------ */
788 /* ----------- EXIF PUT --------------- */
789 /* ------------------------------------ */
790 /* put exif information back to the file from memory (if there was any) */
EXIF_PUT(char * file_name)791 int EXIF_PUT(char *file_name)
792 {
793     if (exif_flag) {
794     	FILE *fhandle;
795 
796 	/* print info */ STRING_PRINTV("writing exif info ");
797 	/* print info */ STRING_PRINTVD((int)(exif_buffer_length));
798 	/* print info */ STRING_PRINTV2(" bytes\n");
799 
800 	/* open file for writing */
801     	fhandle = fopen(file_name, "wb+");
802     	if (fhandle == 0) return 1;
803 	/* write FFD8 JPEG indicator into the first 2 bytes */
804         if (fputc(0xff, fhandle) == 0) return 1;
805         if (fputc(0xd8, fhandle) == 0) return 1;
806 	/* write out the rest of the exif info */
807 	/* here the exif info has to be written with 2 bytes less from the end */
808 	/* because the JPEG writer wants to add the FFD8 marker himself too */
809 	/* so this prevents FFD8 to be 2 times wrongly */
810         if (fwrite(exif_buffer, 1, exif_buffer_length - 2, fhandle) == 0) return 1;
811         fclose(fhandle);
812 
813     }
814     return 0;
815 }
816 
817 
818 
819 
820 /* ------------------------------------ */
821 /* ----------- EXIF CORRECT ----------- */
822 /* ------------------------------------ */
823 /* correct the last 2 bytes of the exif data back from FFD8 to FFD9 */
824 /* cause when we put the exif back to the file, we put 2 bytes less */
825 /* and the jpeg writer can append the jpeg file starting with FFD8 */
826 /* so these 2 bytes needs to be changed back to FFD9 */
EXIF_CORRECT(char * file_name)827 int EXIF_CORRECT(char *file_name)
828 {
829     if (exif_flag) {
830 
831 	/* open file for writing */
832     	FILE *fhandle;
833     	fhandle = fopen(file_name, "rb+");
834     	if (fhandle == 0) return 1;
835 	/* write FFD9 EXIF END indicator to the end of exif data */
836 	fseek(fhandle, exif_buffer_length + 0, SEEK_SET);
837         if (fputc(0xff, fhandle) == 0) return 1;
838         if (fputc(0xd9, fhandle) == 0) return 1;
839         fclose(fhandle);
840 
841     }
842     return 0;
843 }
844 
845 
846 
847 
848 /* -------------------------------------------------- */
849 /* ----------- BITMAP READ IN BMP FORMAT ------------ */
850 /* -------------------------------------------------- */
BITMAP_READ_BMP(char * file_name)851 int BITMAP_READ_BMP(char *file_name)
852 {
853 	unsigned long f_bm;
854 	unsigned long f_bitcount;
855 	unsigned long f_compressed;
856 	unsigned long f_headersize;
857 	unsigned long f_offs;
858 	unsigned long f_width;
859 	unsigned long f_height;
860 	unsigned long f_xpixelpermeter;
861 	unsigned long f_ypixelpermeter;
862     	unsigned long addr, addr2;
863     	unsigned long addr_offset;
864 	unsigned long bw, bh;
865 	unsigned long file_length;
866 	unsigned char *file_buffer;
867 	unsigned long i, x, y;
868 	FILE *fhandle;
869 
870 	/* print info */ STRING_PRINTV("bmp initializations\n");
871 
872 	/* open file for reading */
873 	/* print info */ STRING_PRINTV("opening file for reading\n");
874 	fhandle = fopen(file_name, "rb");
875 	if (fhandle == 0) return 1;
876 	/* check length of file */
877 	fseek(fhandle, 0, SEEK_END);
878 	file_length = ftell(fhandle);
879 	fseek(fhandle, 0, SEEK_SET);
880 	/* allocate memory for file load */
881 	/* print info */ STRING_PRINTV("allocating memory for bmp object\n");
882 	file_buffer = malloc(file_length * sizeof (*file_buffer));
883 	if (file_buffer == 0) return 1;
884 	/* load file into memory */
885 	/* print info */ STRING_PRINTV("reading image file\n");
886 	if (fread(file_buffer, 1, file_length, fhandle) == 0) {
887 		/* print info */ STRING_PRINTV("freeing bmp object\n");
888 		free(file_buffer); return 1; }
889 	/* close file */
890 	fclose(fhandle);
891 
892 
893 	/* read BMP indicator */
894 	f_bm = 0;
895 	f_bm += file_buffer[0] << 0;
896 	f_bm += file_buffer[1] << 8;
897 	f_bitcount = 0;
898 	f_bitcount += file_buffer[28] << 0;
899 	f_bitcount += file_buffer[29] << 8;
900 	f_compressed = 0;
901 	f_compressed += file_buffer[30] << 0;
902 	f_compressed += file_buffer[31] << 8;
903 	f_compressed += file_buffer[32] << 16;
904 	f_compressed += file_buffer[33] << 24;
905 
906 	/* check BMP format (BMP header + uncompressed + 24 bit colors) */
907 	if ((f_bm == 0x00004d42) && ((f_bitcount == 24) || (f_bitcount == 8)) && (f_compressed == 0)) {
908         bitmap_format_bmp_clrspc_type = f_bitcount;
909 
910         if (f_bitcount == 8){
911 		int gray_flag;
912 
913 		/* offset pointing to color palette */
914 	    	f_headersize = 14;
915 	    	f_headersize += file_buffer[14] << 0;
916 	    	f_headersize += file_buffer[15] << 8;
917 	    	f_headersize += file_buffer[16] << 16;
918 	    	f_headersize += file_buffer[17] << 24;
919 		/* check whether the 8 bit image contains only gray colors? */
920 		gray_flag = 1;
921 
922 		#ifdef __OPENMP__
923 		#pragma omp parallel for num_threads(max_threads)
924 		#endif
925 		for (i=0; i<256; i++){
926 			if ((file_buffer[i*4+f_headersize+0] != file_buffer[i*4+f_headersize+1]) ||
927 				(file_buffer[i*4+f_headersize+1] != file_buffer[i*4+f_headersize+2])){ gray_flag = 0; }
928 		}
929 		/* if not gray then exit, because minimim bitdepth of colors to correct is 24 (or 8 bit gray) */
930 		if (gray_flag == 0) {
931 			/* print info */ STRING_PRINTV("freeing bmp object\n");
932 			free(file_buffer); return 1; }
933 		}
934 
935 		/* offset pointing to RGB datas */
936 		f_offs = 0;
937 		f_offs += file_buffer[10] << 0;
938 		f_offs += file_buffer[11] << 8;
939 		f_offs += file_buffer[12] << 16;
940 		f_offs += file_buffer[13] << 24;
941 		/* width of image in pixels */
942 		f_width = 0;
943 		f_width += file_buffer[18] << 0;
944 		f_width += file_buffer[19] << 8;
945 		f_width += file_buffer[20] << 16;
946 		f_width += file_buffer[21] << 24;
947 		/* height of image in pixels */
948 		f_height = 0;
949 		f_height += file_buffer[22] << 0;
950 		f_height += file_buffer[23] << 8;
951 		f_height += file_buffer[24] << 16;
952 		f_height += file_buffer[25] << 24;
953 		/* x pixel per meter value */
954 		f_xpixelpermeter = 0;
955 		f_xpixelpermeter += file_buffer[38] << 0;
956 		f_xpixelpermeter += file_buffer[39] << 8;
957 		f_xpixelpermeter += file_buffer[40] << 16;
958 		f_xpixelpermeter += file_buffer[41] << 24;
959 		/* y pixel per meter value */
960 		f_ypixelpermeter = 0;
961 		f_ypixelpermeter += file_buffer[42] << 0;
962 		f_ypixelpermeter += file_buffer[43] << 8;
963 		f_ypixelpermeter += file_buffer[44] << 16;
964 		f_ypixelpermeter += file_buffer[45] << 24;
965 
966 		bw = f_width;
967 		bh = f_height;
968 		bitmap_width = f_width;
969 		bitmap_height = f_height;
970 		xdpi = f_xpixelpermeter;
971 		ydpi = f_ypixelpermeter;
972 
973 		/* print info */ STRING_PRINTV("dimension is "); STRING_PRINTVD(bitmap_width);
974 		/* print info */ STRING_PRINTV2(" x "); STRING_PRINTVD(bitmap_height); STRING_PRINTV2(" pixels\n");
975 		/* print info */ STRING_PRINTV("resolution is "); STRING_PRINTVD(xdpi);
976 		/* print info */ STRING_PRINTV2(" x "); STRING_PRINTVD(ydpi); STRING_PRINTV2(" pixels per meter\n");
977 		/* print info */ STRING_PRINTV("colors have "); STRING_PRINTVD(f_bitcount);
978 		/* print info */ STRING_PRINTV2(" bit depth\n");
979 
980 #ifndef __BMP_ONLY__
981         if (f_bitcount == 8) { bitmap_format_jpg_clrspc_type = 8; }
982         if (f_bitcount == 24){ bitmap_format_jpg_clrspc_type = 24; }
983         if (f_bitcount == 8) { bitmap_format_png_clrspc_type = 0; }
984         if (f_bitcount == 24){ bitmap_format_png_clrspc_type = 2; }
985 #endif
986 
987 	/* allocate memory for the unpacked RGB colors */
988 	/* print info */ STRING_PRINTV("allocating memory for uncompressed bitmap image\n");
989     	bitmap_buffer = malloc(bw * bh * 3 * sizeof(*bitmap_buffer));
990     	if (bitmap_buffer == 0) return 1;
991 
992 	    /* print info */ STRING_PRINTV("copying colors from bmp object to bitmap buffer\n");
993             if (f_bitcount == 8){
994        		addr_offset = f_width % 4;
995                	if (addr_offset) addr_offset = 4 - addr_offset;
996 		#ifdef __OPENMP__
997 		#pragma omp parallel for private(x, y, addr, addr2) num_threads(max_threads)
998 		#endif
999     	    	for (y=0; y<=bh-1; y++){
1000     	    		addr2 = y * bw * 1 + y * addr_offset;
1001     	    		for (x=0; x<=bw-1; x++){
1002     	    			addr = f_offs + addr2 + x * 1;
1003     	    			bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 0] = file_buffer[addr + 0];
1004     	    			bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 1] = file_buffer[addr + 0];
1005     	    			bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 2] = file_buffer[addr + 0];
1006     	    		}
1007     	    	}
1008             }
1009             else{
1010        		addr_offset = (f_width) * 3 % 4;
1011                	if (addr_offset) addr_offset = 4 - addr_offset;
1012 		#ifdef __OPENMP__
1013 		#pragma omp parallel for private(x, y, addr, addr2) num_threads(max_threads)
1014 		#endif
1015     	    	for (y=0; y<=bh-1; y++){
1016     	    		addr2 = y * bw * 3 + y * addr_offset;
1017     	    		for (x=0; x<=bw-1; x++){
1018     	    			addr = f_offs + addr2 + x * 3;
1019     	    			bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 0] = file_buffer[addr + 2];
1020     	    			bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 1] = file_buffer[addr + 1];
1021     	    			bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 2] = file_buffer[addr + 0];
1022     	    		}
1023     	    	}
1024             }
1025 
1026 	    /* print info */ STRING_PRINTV("freeing bmp object\n");
1027             free(file_buffer);
1028 	    return 0;
1029 	}
1030 
1031 	/* free memory */
1032 	/* print info */ STRING_PRINTV("freeing bmp object\n");
1033 	free(file_buffer);
1034 
1035 	return 1;
1036 }
1037 
1038 
1039 
1040 
1041 /* -------------------------------------------------- */
1042 /* ---------- BITMAP WRITE IN BMP FORMAT ------------ */
1043 /* -------------------------------------------------- */
BITMAP_WRITE_BMP(char * file_name)1044 int BITMAP_WRITE_BMP(char *file_name)
1045 {
1046 	unsigned long f_offs;
1047 	unsigned long addr, addr2;
1048 	unsigned long addr_offset;
1049 	unsigned long bw, bh;
1050 	unsigned long f_xpixelpermeter;
1051 	unsigned long f_ypixelpermeter;
1052 	unsigned long temp;
1053 	unsigned long file_length;
1054 	unsigned char *file_buffer;
1055 	unsigned long col;
1056 	unsigned long i, x, y;
1057 	FILE *fhandle;
1058 
1059 	/* print info */ STRING_PRINTV("bmp initializations\n");
1060 
1061 	bw = bitmap_width;
1062 	bh = bitmap_height;
1063 
1064 	f_xpixelpermeter = xdpi;
1065 	f_ypixelpermeter = ydpi;
1066 
1067 	/* allocate memory for unpacked RGB colors (3 plus bytes more in every width because of the BMP's 4 byte align adjust) */
1068 	/* print info */ STRING_PRINTV("allocating memory for bmp object\n");
1069 	if (bitmap_format_bmp_clrspc_type == 8) {
1070 	    	addr_offset = bw % 4;
1071 	        if (addr_offset) addr_offset = 4 - addr_offset;
1072 		file_length = 54 + 4 * 256 + (bw + addr_offset) * bh;
1073 	}
1074 	else {
1075 	    	addr_offset = (bw * 3) % 4;
1076        		if (addr_offset) addr_offset = 4 - addr_offset;
1077 		file_length = 54 + (bw * 3 + addr_offset) * bh;
1078 	}
1079 
1080 	file_buffer = calloc(file_length, sizeof (*file_buffer));
1081 	if (file_buffer == 0) return 1;
1082 
1083 	/* write BMP indicator */
1084 	file_buffer[0] = 0x42;
1085 	file_buffer[1] = 0x4d;
1086 
1087 	/* file length marker */
1088 	file_buffer[2] = (file_length & 0x000000ff) >> 0;
1089 	file_buffer[3] = (file_length & 0x0000ff00) >> 8;
1090 	file_buffer[4] = (file_length & 0x00ff0000) >> 16;
1091 	file_buffer[5] = (file_length & 0xff000000) >> 24;
1092 
1093 	/* zero */
1094 	file_buffer[6] = 0;
1095 	file_buffer[7] = 0;
1096 	file_buffer[8] = 0;
1097 	file_buffer[9] = 0;
1098 
1099 	if (bitmap_format_bmp_clrspc_type == 8) {
1100 	    	/* bitmap offset (standard = 54) */
1101     		file_buffer[10] = 54;
1102 	    	file_buffer[11] = 4; /* + 4 * 256 pieces of RGB gray colors = 0x0400 */
1103     		file_buffer[12] = 0;
1104 	    	file_buffer[13] = 0;
1105     		/* number of bits per pixel */
1106 	    	file_buffer[28] = 8;
1107     		file_buffer[29] = 0;
1108 	}
1109 	else {
1110 	    	/* bitmap offset (standard = 54) */
1111     		file_buffer[10] = 54;
1112 		file_buffer[11] = 0;
1113 		file_buffer[12] = 0;
1114 		file_buffer[13] = 0;
1115     		/* number of bits per pixel */
1116 		file_buffer[28] = 24;
1117 		file_buffer[29] = 0;
1118 	}
1119 
1120 	/* bitmap info header (standard = 40) */
1121 	file_buffer[14] = 40;
1122 	file_buffer[15] = 0;
1123 	file_buffer[16] = 0;
1124 	file_buffer[17] = 0;
1125 	/* width of image in pixels */
1126 	file_buffer[18] = (bw & 0x000000ff) >> 0;
1127 	file_buffer[19] = (bw & 0x0000ff00) >> 8;
1128 	file_buffer[20] = (bw & 0x00ff0000) >> 16;
1129 	file_buffer[21] = (bw & 0xff000000) >> 24;
1130 	/* height of image in pixels */
1131 	file_buffer[22] = (bh & 0x000000ff) >> 0;
1132 	file_buffer[23] = (bh & 0x0000ff00) >> 8;
1133 	file_buffer[24] = (bh & 0x00ff0000) >> 16;
1134 	file_buffer[25] = (bh & 0xff000000) >> 24;
1135 	/* number of planes */
1136 	file_buffer[26] = 1;
1137 	file_buffer[27] = 0;
1138 	/* compression (standard = 0) */
1139 	file_buffer[30] = 0;
1140 	file_buffer[31] = 0;
1141 	file_buffer[32] = 0;
1142 	file_buffer[33] = 0;
1143 	/* size of bitmap image in bytes */
1144 	if (bitmap_format_bmp_clrspc_type == 8) { temp = (bw + addr_offset) * bh; }
1145 	else                                    { temp = (bw * 3 + addr_offset) * bh; }
1146 	file_buffer[34] = (temp & 0x000000ff) >> 0;
1147 	file_buffer[35] = (temp & 0x0000ff00) >> 8;
1148 	file_buffer[36] = (temp & 0x00ff0000) >> 16;
1149 	file_buffer[37] = (temp & 0xff000000) >> 24;
1150 	/* x pixel per meter value */
1151 	file_buffer[38] = (f_xpixelpermeter & 0x000000ff) >> 0;
1152 	file_buffer[39] = (f_xpixelpermeter & 0x0000ff00) >> 8;
1153 	file_buffer[40] = (f_xpixelpermeter & 0x00ff0000) >> 16;
1154 	file_buffer[41] = (f_xpixelpermeter & 0xff000000) >> 24;
1155 	/* y pixel per meter value */
1156 	file_buffer[42] = (f_ypixelpermeter & 0x000000ff) >> 0;
1157 	file_buffer[43] = (f_ypixelpermeter & 0x0000ff00) >> 8;
1158 	file_buffer[44] = (f_ypixelpermeter & 0x00ff0000) >> 16;
1159 	file_buffer[45] = (f_ypixelpermeter & 0xff000000) >> 24;
1160 
1161 	for (i=46; i<54; i++) file_buffer[i] = 0;
1162 
1163 	/* print info */ STRING_PRINTV("copying colors from bitmap buffer to bmp object\n");
1164 	if (bitmap_format_bmp_clrspc_type == 8) {
1165 		#ifdef __OPENMP__
1166 		#pragma omp parallel for num_threads(max_threads)
1167 		#endif
1168 		for (i=0; i<256; i++){
1169 			file_buffer[54 + i*4 + 0] = i;
1170 			file_buffer[54 + i*4 + 1] = i;
1171 			file_buffer[54 + i*4 + 2] = i;
1172 			file_buffer[54 + i*4 + 3] = 0;
1173         	}
1174 
1175 	    	f_offs = 54 + 4 * 256;
1176     		addr = 0;
1177 		#ifdef __OPENMP__
1178 		#pragma omp parallel for private(x, y, addr, addr2, col) num_threads(max_threads)
1179 		#endif
1180     		for (y=0; y<=bh-1; y++){
1181     			addr2 = y * (bw + addr_offset);
1182 	    		for (x=0; x<=bw-1; x++){
1183     				addr = f_offs + addr2 + x;
1184 				col  = bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 0];
1185 				col += bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 1];
1186 				col += bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 2];
1187     				file_buffer[addr + 0] = col / 3;
1188     			}
1189     		}
1190 	}
1191 
1192 	else {
1193 	    	f_offs = 54;
1194     		addr = 0;
1195 		#ifdef __OPENMP__
1196 		#pragma omp parallel for private(x, y, addr, addr2) num_threads(max_threads)
1197 		#endif
1198     		for (y=0; y<=bh-1; y++){
1199     			addr2 = y * (bw * 3 + addr_offset);
1200 	    		for (x=0; x<=bw-1; x++){
1201     				addr = f_offs + addr2 + x * 3;
1202     				file_buffer[addr + 0] = bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 2];
1203     				file_buffer[addr + 1] = bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 1];
1204 	    			file_buffer[addr + 2] = bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 0];
1205     			}
1206 	    	}
1207 	}
1208 
1209 
1210 	/* open file for writing */
1211 	/* print info */ STRING_PRINTV("opening file for writing\n");
1212 	fhandle = fopen(file_name, "wb");
1213 	if (fhandle == 0) return 1;
1214 	/* write and flush file from memory */
1215 	/* print info */ STRING_PRINTV("writing image file\n");
1216 	if (fwrite(file_buffer, 1, file_length, fhandle) == 0) return 1;
1217 	/* close file */
1218 	fclose(fhandle);
1219 
1220 	/* print info */ STRING_PRINTV("freeing bmp object\n");
1221 	free(file_buffer);
1222 
1223 	return 0;
1224 }
1225 
1226 
1227 #ifndef __BMP_ONLY__
1228 
1229 /* -------------------------------------------------- */
1230 /* --------- BITMAP READ IN JASPER FORMAT ----------- */
1231 /* -------------------------------------------------- */
BITMAP_READ_JASPER(char * file_name)1232 int BITMAP_READ_JASPER(char *file_name)
1233 {
1234 	int i, j, channel;
1235         int num_of_channels;
1236 	int dx, dy, clr_spc;
1237 	int clrspc_type;
1238 
1239     	jas_stream_t *stream;
1240  	jas_image_t *image;
1241     	jas_matrix_t *data;
1242 
1243     	/* initialize jasper library */
1244 	/* print info */ STRING_PRINTV("jasper initializations\n");
1245 	jas_init();
1246 
1247 	/* load file and decode format */
1248 	/* print info */ STRING_PRINTV("opening file for reading\n");
1249 	stream  = jas_stream_fopen(file_name, "rb");
1250     	if (stream == NULL) return 1;
1251 
1252 	/* store bitmap format */
1253     	bitmap_format_jpg_file_type = jas_image_getfmt(stream);
1254 
1255 	/* print info */ STRING_PRINTV("decoding jasper image\n");
1256     	image = jas_image_decode(stream, -1, NULL);
1257     	jas_stream_close(stream);
1258 	if (image == NULL) return 1;
1259     	bitmap_width = jas_image_width(image);
1260 	bitmap_height = jas_image_height(image);
1261     	clrspc_type = jas_image_clrspc(image);
1262 
1263         if (clrspc_type == JAS_CLRSPC_SGRAY)     { bitmap_format_jpg_clrspc_type = 8;  }
1264         if (clrspc_type == JAS_CLRSPC_SRGB)      { bitmap_format_jpg_clrspc_type = 24; }
1265 
1266         if (bitmap_format_jpg_clrspc_type == 8)  { bitmap_format_png_clrspc_type = 0;  }
1267         if (bitmap_format_jpg_clrspc_type == 24) { bitmap_format_png_clrspc_type = 2;  }
1268         if (bitmap_format_jpg_clrspc_type == 8)  { bitmap_format_bmp_clrspc_type = 8;  }
1269         if (bitmap_format_jpg_clrspc_type == 24) { bitmap_format_bmp_clrspc_type = 24; }
1270 
1271 	/* allocate memory */
1272 	/* print info */ STRING_PRINTV("allocating memory for uncompressed bitmap image\n");
1273 	bitmap_buffer = malloc(bitmap_width * bitmap_height * 3 * sizeof(*bitmap_buffer));
1274 	if (bitmap_buffer == 0) return 1;
1275 
1276 	/* print info */ STRING_PRINTV("dimension is "); STRING_PRINTVD(bitmap_width);
1277 	/* print info */ STRING_PRINTV2(" x "); STRING_PRINTVD(bitmap_height); STRING_PRINTV2(" pixels\n");
1278 	/* print info */ STRING_PRINTV("colors have "); STRING_PRINTVD(bitmap_format_jpg_clrspc_type);
1279 	/* print info */ STRING_PRINTV2(" bit depth\n");
1280 
1281 	/* check file whether it conatins 24-bit RGB or 8-bit colors */
1282         clr_spc = jas_clrspc_fam(clrspc_type);
1283 	if ((clr_spc != JAS_CLRSPC_FAM_RGB) && (clr_spc != JAS_CLRSPC_FAM_GRAY)) return 1;
1284 	if (jas_image_cmptprec(image, 0) != 8) return 1;
1285 
1286 	/* create jasper matrix */
1287 	dx = bitmap_width;
1288 	dy = bitmap_height;
1289 	data = jas_matrix_create(dy,dx);
1290 
1291 	/* read datas out of jasper object and copy it to a memory block */
1292 
1293 	/* determine number of channels: GRAY = 1, RGB = 3 */
1294         num_of_channels = 1;
1295         if (clr_spc == JAS_CLRSPC_FAM_GRAY) { num_of_channels = 1; }
1296         if (clr_spc == JAS_CLRSPC_FAM_RGB) { num_of_channels = 3; }
1297 
1298 	/* copy RGB colors to bitmap memory */
1299 	/* print info */ STRING_PRINTV("copying colors from jasper object to bitmap buffer\n");
1300 	for (channel=0; channel<num_of_channels; channel++){
1301 		jas_image_readcmpt(image, channel, 0, 0, dx, dy, data);
1302 		jas_image_setcmpttype(image, channel, JAS_IMAGE_CT_RGB_R+channel);
1303 
1304 		#ifdef __OPENMP__
1305 		#pragma omp parallel for private(i, j) num_threads(max_threads)
1306 		#endif
1307 	    	for (j=0; j<dy; j++){
1308 	    		for (i=0; i<dx; i++){
1309 	    			int idx=(j * dx + i) * 3;
1310 				if (num_of_channels == 1){
1311 					bitmap_buffer[idx+0] = jas_matrix_get(data, j, i);
1312 					bitmap_buffer[idx+1] = jas_matrix_get(data, j, i);
1313 					bitmap_buffer[idx+2] = jas_matrix_get(data, j, i); }
1314 				else{
1315 					bitmap_buffer[idx+channel] = jas_matrix_get(data, j, i); }
1316 			}
1317 		}
1318 	}
1319 
1320 	    /* free previously allocated objects */
1321 	    /* print info */ STRING_PRINTV("freeing jasper object\n");
1322 	    jas_image_destroy(image);
1323 	    jas_matrix_destroy(data);
1324 	    jas_image_clearfmts();
1325 /*	    jas_cleanup(); */
1326 
1327 	return 0;
1328 }
1329 
1330 
1331 
1332 
1333 /* -------------------------------------------------- */
1334 /* --------- BITMAP WRITE IN JASPER FORMAT ---------- */
1335 /* -------------------------------------------------- */
BITMAP_WRITE_JASPER(char * file_name)1336 int BITMAP_WRITE_JASPER(char *file_name)
1337 {
1338 	char *opt = "";
1339 	char opt2[max_char];
1340 	int fmt, clrspc_type;
1341 	long channel;
1342 	long idx;
1343 	long dx,dy;
1344 	long i, j;
1345 
1346 	jas_stream_t *stream;
1347  	jas_image_t *image;
1348 	jas_image_cmptparm_t cmptparm[3];
1349 	jas_matrix_t *data;
1350 
1351 	/* initialize jasper library */
1352 	/* print info */ STRING_PRINTV("jasper initializations\n");
1353 	jas_init();
1354 
1355 	/* create jasper matrix */
1356 	dx = bitmap_width;
1357 	dy = bitmap_height;
1358 	data=jas_matrix_create(dy,dx);
1359 
1360         clrspc_type = 0;
1361         if (bitmap_format_jpg_clrspc_type == 8)  { clrspc_type = JAS_CLRSPC_SGRAY; }
1362         if (bitmap_format_jpg_clrspc_type == 24) { clrspc_type = JAS_CLRSPC_SRGB;  }
1363 
1364 	/* create new jasper imgae object */
1365 	for (i=0; i<3; i++){
1366 		cmptparm[i].tlx		= 0;
1367 		cmptparm[i].tly		= 0;
1368 		cmptparm[i].hstep	= 1;
1369 		cmptparm[i].vstep	= 1;
1370 		cmptparm[i].height	= dy;
1371 		cmptparm[i].width	= dx;
1372 		/* number of bits per channel */
1373 		cmptparm[i].prec	= 8;
1374 		cmptparm[i].sgnd	= 0;
1375 	}
1376 	image = jas_image_create(3, cmptparm, clrspc_type);
1377 
1378 	/* read data out of memory block and copy it into jasper object */
1379 	/* print info */ STRING_PRINTV("copying colors from bitmap buffer to jasper object\n");
1380 	for (channel=0; channel<3; channel++){
1381 		#ifdef __OPENMP__
1382 		#pragma omp parallel for private(i, j, idx) num_threads(max_threads)
1383 		#endif
1384 		for (j=0; j<dy; j++){
1385 			for (i=0; i<dx; i++){
1386 				idx=(j * dx + i) * 3;
1387 				jas_matrix_set(data, j, i, bitmap_buffer[idx+channel]);
1388 	    		}
1389 		}
1390 		jas_image_writecmpt(image, channel, 0, 0, dx, dy, data);
1391 		jas_image_setcmpttype(image, channel, JAS_IMAGE_CT_RGB_R+channel);
1392 	}
1393 
1394 /*	int fmt = GET_FILE_FORMAT(file_name); */
1395 /*	if ((fmt < 0) || (fmt > 7)) return 1; */
1396 	fmt = bitmap_format_jpg_file_type;
1397 
1398 	/* set quality value */
1399 	if (opt_quality < 0)  { opt_quality = 0;   }
1400 	if (opt_quality > 100){ opt_quality = 100; }
1401 	if (!(opt_quality)){
1402 		if (fmt == 4) opt = "rate=0.95";
1403 		if (fmt == 5) opt = "rate=0.95";
1404 		if (fmt == 6) opt = "quality=95";
1405 	}
1406 	else{
1407 		if ((fmt == 4) || (fmt == 5)){
1408 	    		opt = "rate=1.00\0";
1409 	    		for (i=0; opt[i]!='\0'; i++){ opt2[i] = opt[i]; } opt2[i] = opt[i];
1410 	    		if (opt_quality < 100){
1411 	    			opt2[5] = '0';
1412 	    			opt2[7] = '0' + (opt_quality / 10);
1413 	    			opt2[8] = '0' + (opt_quality % 10);
1414 	    		}
1415 	    		opt = opt2;
1416 	    	}
1417 	    	if (fmt == 6){
1418 	    		opt = "quality=100\0";
1419 	    		for (i=0; opt[i]!='\0'; i++){ opt2[i] = opt[i]; } opt2[i] = opt[i];
1420 	    		if (opt_quality < 100){
1421 	    			opt2[10] = '\0';
1422 	    			opt2[8] = '0' + (opt_quality / 10);
1423 	    			opt2[9] = '0' + (opt_quality % 10);
1424 	    		}
1425 	    		opt = opt2;
1426 	    	}
1427 	    }
1428 
1429 	    /* open file for writing and encode format */
1430 	    /* print info */ STRING_PRINTV("opening file for writing\n");
1431     	    stream = jas_stream_fopen(file_name,"w+b");
1432 
1433 	    /* print info */ STRING_PRINTV("encoding jasper image\n");
1434 	    jas_image_encode(image, stream, fmt, opt);
1435 
1436 	    /* write file */
1437 	    /* print info */ STRING_PRINTV("writing image file\n");
1438 	    jas_stream_flush(stream);
1439 	    jas_stream_close(stream);
1440 
1441 	    /* free previously allocated objects */
1442 	    /* print info */ STRING_PRINTV("freeing jasper object\n");
1443 	    jas_image_destroy(image);
1444 	    jas_matrix_destroy(data);
1445 	    jas_image_clearfmts();
1446 /*	    jas_cleanup(); */
1447 
1448 	return 0;
1449 }
1450 
1451 
1452 
1453 
1454 /* ----------------------------------------------- */
1455 /* --------- BITMAP READ IN PNG FORMAT ----------- */
1456 /* ----------------------------------------------- */
1457 /* source code examples for PNG read taken from: */
1458 /* http://www.libpng.org/pub/png/book/chapter13.html */
BITMAP_READ_PNG(char * file_name)1459 int BITMAP_READ_PNG(char *file_name)
1460 {
1461 	FILE *fhandle;
1462 	unsigned long x, y;
1463 	long offs1, offs2;
1464 	unsigned long   rowbytes;
1465 	unsigned char **row_pointers;
1466 	unsigned long	i;
1467 	int alpha_flag;
1468 	png_uint_32 res_x, res_y;
1469 	int unit_type;
1470 	png_uint_32 png_width, png_height;
1471 	int bit_depth;
1472 	png_structp png_ptr;
1473 	png_infop info_ptr;
1474 	unsigned char sig[8];
1475 
1476 
1477         /* open file for reading */
1478 	/* print info */ STRING_PRINTV("opening file for reading\n");
1479         fhandle = fopen(file_name, "rb");
1480         if (fhandle == 0) return 1;
1481 
1482 	/* check PNG signature */
1483 	if (fread(sig, 1, 8, fhandle) != 8) return 1;
1484 
1485 /*	libpng version change to 1.4.0 */
1486 /*	if (!png_check_sig(sig, 8)) return 1; */
1487 	if (png_sig_cmp(sig, 0, 8)) return 1;
1488 
1489 
1490 	/* print info */ STRING_PRINTV("png initializations\n");
1491 	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1492 	/* out of memory */
1493 	if (!png_ptr) return 1;
1494 
1495 	info_ptr = png_create_info_struct(png_ptr);
1496 	if (!info_ptr) {
1497         	png_destroy_read_struct(&png_ptr, NULL, NULL);
1498         	return 1;
1499 	}
1500 
1501 /*	libpng version change to 1.4.0 */
1502 /*	if (setjmp(png_ptr->jmpbuf)) { */
1503 	if (setjmp(png_jmpbuf(png_ptr))) {
1504 		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1505 		return 1;
1506 	}
1507 
1508 	png_init_io(png_ptr, fhandle);
1509 	png_set_sig_bytes(png_ptr, 8);
1510 	png_read_info(png_ptr, info_ptr);
1511 
1512 	/* get image header info */
1513 	png_get_IHDR(png_ptr, info_ptr, &png_width, &png_height, &bit_depth, \
1514 		&bitmap_format_png_clrspc_type, &bitmap_format_png_interlace_type, \
1515 		&bitmap_format_png_compression_type, &bitmap_format_png_filter_type);
1516 
1517 	bitmap_width = png_width;
1518 	bitmap_height = png_height;
1519 
1520 	/* get image resolution */
1521 	png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type);
1522 
1523 	if (unit_type == 0) { res_x = 0; res_y = 0; }
1524 
1525 	xdpi = res_x;
1526 	ydpi = res_y;
1527 	udpi = unit_type;
1528 
1529 	/* print info */ STRING_PRINTV("dimension is "); STRING_PRINTVD(bitmap_width);
1530 	/* print info */ STRING_PRINTV2(" x "); STRING_PRINTVD(bitmap_height); STRING_PRINTV2(" pixels\n");
1531 	/* print info */ if (udpi == 1)	{
1532 	/* print info */ STRING_PRINTV("resolution is "); STRING_PRINTVD(xdpi);
1533 	/* print info */ STRING_PRINTV2(" x "); STRING_PRINTVD(ydpi);
1534 	/* print info */ STRING_PRINTV2(" pixels per meter\n"); }
1535 	/* print info */ else {
1536 	/* print info */ STRING_PRINTV2("resolution is of unknown type\n"); }
1537 	/* print info */ STRING_PRINTV("colors have "); STRING_PRINTVD(bit_depth);
1538 	/* print info */ STRING_PRINTV2(" bit depth\n");
1539 
1540 	/* bitmap depth must be 8 bit color, RGB or Grayscale */
1541 	if (bit_depth != 8) {
1542 		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1543 		return 1;
1544 	}
1545 
1546 	/* check color types */
1547 	/* 0 - Gray */
1548 	/* 2 - RGB */
1549 	/* 4 - Gray + Alpha */
1550 	/* 6 - RGB + Alpha */
1551         if (bitmap_format_png_clrspc_type != 0 &&
1552 	    bitmap_format_png_clrspc_type != 2 &&
1553 	    bitmap_format_png_clrspc_type != 4 &&
1554 	    bitmap_format_png_clrspc_type != 6) {
1555 		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1556 		return 1;
1557 	}
1558 
1559 	/* set color types */
1560         if (bitmap_format_png_clrspc_type == 0 || bitmap_format_png_clrspc_type == 4) {
1561 		bitmap_format_jpg_clrspc_type = 8;
1562 		bitmap_format_bmp_clrspc_type = 8; }
1563         if (bitmap_format_png_clrspc_type == 2 || bitmap_format_png_clrspc_type == 6) {
1564 		bitmap_format_jpg_clrspc_type = 24;
1565 		bitmap_format_bmp_clrspc_type = 24; }
1566 
1567 	/* if there is Alpha channel, then allocate bigger memory for it */
1568 	/* RGB + Alpha needs 5 times of the pixels because the bytes need to be rearranged */
1569 	alpha_flag = 0;
1570         if (bitmap_format_png_clrspc_type == 4) { alpha_flag = 1; }
1571         if (bitmap_format_png_clrspc_type == 6) { alpha_flag = 2; }
1572 
1573 	if (alpha_flag){ /* print info */ STRING_PRINTV("alpha channel exists\n"); }
1574 	else           { /* print info */ STRING_PRINTV("no alpha channel\n");     }
1575 
1576 	/* print info */ STRING_PRINTV("allocating memory for uncompressed bitmap image\n");
1577 	bitmap_buffer = malloc(bitmap_width * bitmap_height * (3 + alpha_flag) * sizeof (*bitmap_buffer));
1578 	if (bitmap_buffer == 0) {
1579 		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1580 		return 1;
1581 	}
1582 
1583 
1584 	png_read_update_info(png_ptr, info_ptr);
1585 	rowbytes = png_get_rowbytes(png_ptr, info_ptr);
1586 
1587 	row_pointers = malloc(bitmap_height * sizeof (long));
1588 	if (row_pointers == 0) { return 1; }
1589 
1590 	/* print info */ STRING_PRINTV("creating row pointers for bitmap buffer\n");
1591 	#ifdef __OPENMP__
1592 	#pragma omp parallel for num_threads(max_threads)
1593 	#endif
1594 	for (i = 0; i < bitmap_height; i++) {
1595 		row_pointers[i] = (unsigned char*) (bitmap_buffer + i*rowbytes);
1596 	}
1597 
1598 	/* print info */ STRING_PRINTV("reading image file and copy colors to bitmap buffer\n");
1599 	png_read_image(png_ptr, row_pointers);
1600 	png_read_end(png_ptr, NULL);
1601 
1602 	/* destroy png structure and free memory */
1603 	/* print info */ STRING_PRINTV("freeing png object\n");
1604 	if (png_ptr && info_ptr) {
1605 		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1606 		png_ptr = NULL;
1607 		info_ptr = NULL;
1608 	}
1609 
1610 
1611 
1612 	/* if it's Grayscale, then we pack the gray bytes to same RGB bytes */
1613 	/* because the aaRGB function expects RGB bytes */
1614 	/* if it's RGB picture with Alpha channel, then we pack the */
1615 	/* RGB bytes to the begining of the allocated memory */
1616 	/* and the Alpha bytes to the end */
1617 	/* so it will be compatible in case of JPG output too */
1618 	/* only the alpha channel will be lost */
1619 	/* cause JPG does not support alpha */
1620 
1621 
1622 	/* print info */ STRING_PRINTV("converting colors to different format\n");
1623 	/* Gray */
1624         if (bitmap_format_png_clrspc_type == 0){
1625 		/* copy Gray bytes to be RGB bytes */
1626 		offs1 = bitmap_width * bitmap_height * 1 - 1;
1627 		offs2 = bitmap_width * bitmap_height * 3 - 3;
1628 		for (y=0; y < bitmap_height; y++){
1629 			for (x=0; x < bitmap_width; x++){
1630 				bitmap_buffer[offs2 + 0] = bitmap_buffer[offs1];
1631 				bitmap_buffer[offs2 + 1] = bitmap_buffer[offs1];
1632 				bitmap_buffer[offs2 + 2] = bitmap_buffer[offs1];
1633 				offs1--;
1634 				offs2 = offs2 - 3;
1635 			}
1636 		}
1637 	}
1638 	/* RGB */
1639         if (bitmap_format_png_clrspc_type == 2){
1640 		/* do nothing */
1641 	}
1642 	/* Gray + Alpha */
1643         if (bitmap_format_png_clrspc_type == 4){
1644 		/* move Alpha bytes to the end */
1645 		offs1 = bitmap_width * bitmap_height * 2 - 1;
1646 		offs2 = bitmap_width * bitmap_height * 4 - 1;
1647 		for (y=0; y < bitmap_height; y++){
1648 			for (x=0; x < bitmap_width; x++){
1649 				bitmap_buffer[offs2] = bitmap_buffer[offs1];
1650 				offs1 = offs1 - 2;
1651 				offs2--;
1652 			}
1653 		}
1654 		/* copy Gray bytes to be RGB bytes */
1655 		offs1 = bitmap_width * bitmap_height * 2 - 2;
1656 		offs2 = offs2 - 2;
1657 		for (y=0; y < bitmap_height; y++){
1658 			for (x=0; x < bitmap_width; x++){
1659 				bitmap_buffer[offs2 + 0] = bitmap_buffer[offs1];
1660 				bitmap_buffer[offs2 + 1] = bitmap_buffer[offs1];
1661 				bitmap_buffer[offs2 + 2] = bitmap_buffer[offs1];
1662 				offs1 = offs1 - 2;
1663 				offs2 = offs2 - 3;
1664 			}
1665 		}
1666 	}
1667 	/* RGB + Alpha */
1668         if (bitmap_format_png_clrspc_type == 6){
1669 		/* move Alpha bytes to the 5. endpart */
1670 		offs1 = bitmap_width * bitmap_height * 4 - 1;
1671 		offs2 = bitmap_width * bitmap_height * 5 - 1;
1672 		for (y=0; y < bitmap_height; y++){
1673 			for (x=0; x < bitmap_width; x++){
1674 				bitmap_buffer[offs2] = bitmap_buffer[offs1];
1675 				offs1 = offs1 - 4;
1676 				offs2--;
1677 			}
1678 		}
1679 		/* transfer RGBA bytes into RGB bytes */
1680 		offs1 = 0;
1681 		offs2 = 0;
1682 		for (y=0; y < bitmap_height; y++){
1683 			for (x=0; x < bitmap_width; x++){
1684 				bitmap_buffer[offs2 + 0] = bitmap_buffer[offs1 + 0];
1685 				bitmap_buffer[offs2 + 1] = bitmap_buffer[offs1 + 1];
1686 				bitmap_buffer[offs2 + 2] = bitmap_buffer[offs1 + 2];
1687 				offs1 = offs1 + 4;
1688 				offs2 = offs2 + 3;
1689 			}
1690 		}
1691 		/* move Alpha bytes back to the 4. part */
1692 		offs1 = bitmap_width * bitmap_height * 5 - 1;
1693 		offs2 = bitmap_width * bitmap_height * 4 - 1;
1694 		for (y=0; y < bitmap_height; y++){
1695 			for (x=0; x < bitmap_width; x++){
1696 				bitmap_buffer[offs2] = bitmap_buffer[offs1];
1697 				offs1--;
1698 				offs2--;
1699 			}
1700 		}
1701 	}
1702 
1703 	free (row_pointers);
1704 	return 0;
1705 }
1706 
1707 
1708 
1709 
1710 /* ------------------------------------------------ */
1711 /* --------- BITMAP WRITE IN PNG FORMAT ----------- */
1712 /* ------------------------------------------------ */
1713 /* source code examples for PNG write taken from: */
1714 /* http://www.libpng.org/pub/png/book/chapter15.html */
BITMAP_WRITE_PNG(char * file_name)1715 int BITMAP_WRITE_PNG(char *file_name)
1716 {
1717         unsigned long   rowbytes;
1718 	unsigned long	i;
1719 	unsigned char **row_pointers;
1720         FILE *fhandle;
1721 	png_structp png_ptr;
1722 	png_infop info_ptr;
1723 
1724 	unsigned long x, y;
1725 	long offs1, offs2;
1726 	long col;
1727 
1728 	/* repack the Gray and RGB bytes with the Alpha bytes */
1729 	/* print info */ STRING_PRINTV("converting colors to different format\n");
1730 
1731 	/* Gray */
1732         if (bitmap_format_png_clrspc_type == 0){
1733 		/* copy RGB bytes back as Gray bytes */
1734 		offs1 = 0;
1735 		offs2 = 0;
1736 		for (y=0; y < bitmap_height; y++){
1737 			for (x=0; x < bitmap_width; x++){
1738 				col = 0;
1739 				col += bitmap_buffer[offs2 + 0];
1740 				col += bitmap_buffer[offs2 + 1];
1741 				col += bitmap_buffer[offs2 + 2];
1742 				col /= 3;
1743 				bitmap_buffer[offs1] = col;
1744 				offs1++;
1745 				offs2 = offs2 + 3;
1746 			}
1747 		}
1748 	}
1749 	/* RGB */
1750         if (bitmap_format_png_clrspc_type == 2){
1751 		/* do nothing */
1752 	}
1753 	/* Gray + Alpha */
1754         if (bitmap_format_png_clrspc_type == 4){
1755 		/* copy RGB bytes back as Gray bytes */
1756 		offs1 = 0;
1757 		offs2 = 0;
1758 		for (y=0; y < bitmap_height; y++){
1759 			for (x=0; x < bitmap_width; x++){
1760 				col = 0;
1761 				col += bitmap_buffer[offs2 + 0];
1762 				col += bitmap_buffer[offs2 + 1];
1763 				col += bitmap_buffer[offs2 + 2];
1764 				col /= 3;
1765 				bitmap_buffer[offs1] = col;
1766 				offs1 = offs1 + 2;
1767 				offs2 = offs2 + 3;
1768 			}
1769 		}
1770 		/* copy Alpha bytes back */
1771 		offs1 = bitmap_width * bitmap_height * 3 + 0;
1772 		offs2 = 1;
1773 		for (y=0; y < bitmap_height; y++){
1774 			for (x=0; x < bitmap_width; x++){
1775 				bitmap_buffer[offs2] = bitmap_buffer[offs1];
1776 				offs1++;
1777 				offs2 = offs2 + 2;
1778 			}
1779 		}
1780 	}
1781 	/* RGB + Alpha */
1782         if (bitmap_format_png_clrspc_type == 6){
1783 		/* move Alpha bytes back from the 4. to the 5. endpart */
1784 		offs1 = bitmap_width * bitmap_height * 4 - 1;
1785 		offs2 = bitmap_width * bitmap_height * 5 - 1;
1786 		for (y=0; y < bitmap_height; y++){
1787 			for (x=0; x < bitmap_width; x++){
1788 				bitmap_buffer[offs2] = bitmap_buffer[offs1];
1789 				offs1--;
1790 				offs2--;
1791 			}
1792 		}
1793 		/* transfer RGB bytes into RGBA bytes */
1794 		offs1 = bitmap_width * bitmap_height * 3 - 3;
1795 		offs2 = bitmap_width * bitmap_height * 4 - 4;
1796 		for (y=0; y < bitmap_height; y++){
1797 			for (x=0; x < bitmap_width; x++){
1798 				bitmap_buffer[offs2 + 2] = bitmap_buffer[offs1 + 2];
1799 				bitmap_buffer[offs2 + 1] = bitmap_buffer[offs1 + 1];
1800 				bitmap_buffer[offs2 + 0] = bitmap_buffer[offs1 + 0];
1801 				offs1 = offs1 - 3;
1802 				offs2 = offs2 - 4;
1803 			}
1804 		}
1805 		/* move Alpha bytes back from the 5. endpart to RGBA */
1806 		offs1 = bitmap_width * bitmap_height * 5 - 1;
1807 		offs2 = bitmap_width * bitmap_height * 4 - 1;
1808 		for (y=0; y < bitmap_height; y++){
1809 			for (x=0; x < bitmap_width; x++){
1810 				bitmap_buffer[offs2] = bitmap_buffer[offs1];
1811 				offs1--;
1812 				offs2 = offs2 - 4;
1813 			}
1814 		}
1815 	}
1816 
1817 
1818 	/* print info */ STRING_PRINTV("png initializations\n");
1819 	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1820 	/* out of memory */
1821 	if (!png_ptr) return 1;
1822 
1823 	info_ptr = png_create_info_struct(png_ptr);
1824 	if (!info_ptr) {
1825 		png_destroy_write_struct(&png_ptr, NULL);
1826 		return 1;
1827 	}
1828 
1829 /*	libpng version change to 1.4.0 */
1830 /*	if (setjmp(png_ptr->jmpbuf)) { */
1831 	if (setjmp(png_jmpbuf(png_ptr))) {
1832 		png_destroy_write_struct(&png_ptr, &info_ptr);
1833 		return 1;
1834 	}
1835 
1836         /* open file for writing */
1837 	/* print info */ STRING_PRINTV("opening file for writing\n");
1838         fhandle = fopen(file_name, "wb");
1839         if (fhandle == 0) return 1;
1840 
1841 	png_init_io(png_ptr, fhandle);
1842 /*	png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);*/
1843 /*	set the compression level manually */
1844 	png_set_compression_level(png_ptr, 5);
1845 
1846 	/* set image header */
1847 	png_set_IHDR(png_ptr, info_ptr, bitmap_width, bitmap_height,
1848 /*		8, bitmap_format_png_clrspc_type, bitmap_format_png_interlace_type, */
1849 /*		bitmap_format_png_compression_type, bitmap_format_png_filter_type); */
1850 		8, bitmap_format_png_clrspc_type, PNG_INTERLACE_NONE,
1851 		PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1852 
1853         /* set image resolution */
1854         png_set_pHYs(png_ptr, info_ptr, xdpi, ydpi, udpi);
1855 
1856 
1857 	png_write_info(png_ptr, info_ptr);
1858 /*	png_set_packing(png_ptr); */
1859 
1860 
1861         png_read_update_info(png_ptr, info_ptr);
1862         rowbytes = png_get_rowbytes(png_ptr, info_ptr);
1863 
1864 	row_pointers = malloc(bitmap_height * sizeof (long));
1865 	if (row_pointers == 0) { return 1; }
1866 
1867 	/* print info */ STRING_PRINTV("creating row pointers for bitmap buffer\n");
1868 	#ifdef __OPENMP__
1869 	#pragma omp parallel for num_threads(max_threads)
1870 	#endif
1871         for (i = 0; i < bitmap_height; i++) {
1872                 row_pointers[i] = (unsigned char*) (bitmap_buffer + i*rowbytes);
1873         }
1874 
1875 	/* print info */ STRING_PRINTV("copying colors from bitmap buffer and write image file\n");
1876 	png_write_image(png_ptr, row_pointers);
1877 	png_write_end(png_ptr, NULL);
1878 
1879 	/* print info */ STRING_PRINTV("freeing png object\n");
1880 	if (png_ptr && info_ptr)
1881 		png_destroy_write_struct(&png_ptr, &info_ptr);
1882 
1883 	free (row_pointers);
1884 	return 0;
1885 }
1886 
1887 
1888 
1889 
1890 /* ------------------------------------------------ */
1891 /* --------- BITMAP READ IN JPEG FORMAT ----------- */
1892 /* ------------------------------------------------ */
1893 /* source code examples for reading JPEG taken from libjpeg's example.c */
BITMAP_READ_JPEG(char * file_name)1894 int BITMAP_READ_JPEG(char *file_name)
1895 {
1896 	struct jpeg_decompress_struct cinfo;
1897 	struct jpeg_error_mgr jerr;
1898 	FILE *infile;
1899 	JSAMPARRAY buffer;
1900 	int row_stride;
1901 
1902 	EXIF_GET(file_name);
1903 
1904 	/* print info */ STRING_PRINTV("jpeg initializations\n");
1905 
1906 	/* print info */ STRING_PRINTV("opening file for reading\n");
1907 	if ((infile = fopen(file_name, "rb")) == NULL) { return 1; }
1908 
1909 	cinfo.err = jpeg_std_error(&jerr);
1910 	jpeg_create_decompress(&cinfo);
1911 	jpeg_stdio_src(&cinfo, infile);
1912 	(void) jpeg_read_header(&cinfo, TRUE);
1913 
1914 	 /* print info */ STRING_PRINTV("decoding jpeg image\n");
1915 	(void) jpeg_start_decompress(&cinfo);
1916 
1917 	row_stride = cinfo.output_width * cinfo.output_components;
1918 	buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
1919 
1920 	/* print info */ STRING_PRINTV("allocating memory for uncompressed bitmap image\n");
1921 	bitmap_width = cinfo.output_width;
1922 	bitmap_height = cinfo.output_height;
1923 	bitmap_buffer = malloc(bitmap_width * bitmap_height * 3 * sizeof (*bitmap_buffer));
1924 	if (bitmap_buffer == 0) return 1;
1925 
1926 	xdpi = cinfo.X_density;
1927 	ydpi = cinfo.Y_density;
1928 	udpi = 0;
1929 	/* unit = 0, no units */
1930 	/* unit = 1, unit is pixels per inch */
1931 	/* unit = 2, unit is pixels per centimetre */
1932 	/* convert the unit to meter, cause BMP and PNG stores it as meter too with unit being 1 */
1933 	if (cinfo.density_unit == 1){ xdpi = xdpi * 1000 / 25.4; ydpi = ydpi * 1000 / 25.4; udpi = 1; }
1934 	if (cinfo.density_unit == 2){ xdpi = xdpi * 100; ydpi = ydpi * 100; udpi = 1; }
1935 
1936 	/* determine colorspace type */
1937 	if (cinfo.output_components == 1) { bitmap_format_jpg_clrspc_type = 8; }
1938 	if (cinfo.output_components == 3) { bitmap_format_jpg_clrspc_type = 24; }
1939         if (bitmap_format_jpg_clrspc_type == 8)  { bitmap_format_png_clrspc_type = 0;  }
1940         if (bitmap_format_jpg_clrspc_type == 24) { bitmap_format_png_clrspc_type = 2;  }
1941         if (bitmap_format_jpg_clrspc_type == 8)  { bitmap_format_bmp_clrspc_type = 8;  }
1942         if (bitmap_format_jpg_clrspc_type == 24) { bitmap_format_bmp_clrspc_type = 24; }
1943 
1944 	/* print info */ STRING_PRINTV("dimension is "); STRING_PRINTVD(bitmap_width);
1945 	/* print info */ STRING_PRINTV2(" x "); STRING_PRINTVD(bitmap_height); STRING_PRINTV2(" pixels\n");
1946 	/* print info */ STRING_PRINTV("resolution is "); STRING_PRINTVD(xdpi);
1947 	/* print info */ STRING_PRINTV2(" x "); STRING_PRINTVD(ydpi);
1948 	/* print info */ if (udpi == 1)	{ STRING_PRINTV2(" pixels per meter\n"); }
1949 	/* print info */ else		{ STRING_PRINTV2(" with unknown type\n"); }
1950 	/* print info */ STRING_PRINTV("colors have "); STRING_PRINTVD(bitmap_format_jpg_clrspc_type);
1951 	/* print info */ STRING_PRINTV2(" bit depth\n");
1952 
1953 	/* print info */ STRING_PRINTV("copying colors from jpeg object to bitmap buffer\n");
1954 	while (cinfo.output_scanline < cinfo.output_height) {
1955 		unsigned int i;
1956 
1957 		(void) jpeg_read_scanlines(&cinfo, buffer, 1);
1958 /*		put_scanline_someplace(buffer[0], row_stride); */
1959 
1960 		if (cinfo.output_components == 3){
1961 			#ifdef __OPENMP__
1962 			#pragma omp parallel for num_threads(max_threads)
1963 			#endif
1964 			for (i=0; i<cinfo.output_width; i++){
1965 				bitmap_buffer[0 + i*3 + (cinfo.output_scanline-1) * cinfo.output_width*3] = *(*buffer + 0 + i*3);
1966 				bitmap_buffer[1 + i*3 + (cinfo.output_scanline-1) * cinfo.output_width*3] = *(*buffer + 1 + i*3);
1967 				bitmap_buffer[2 + i*3 + (cinfo.output_scanline-1) * cinfo.output_width*3] = *(*buffer + 2 + i*3);
1968 			}
1969 		}
1970 		else{
1971 			#ifdef __OPENMP__
1972 			#pragma omp parallel for num_threads(max_threads)
1973 			#endif
1974 			for (i=0; i<cinfo.output_width; i++){
1975 				bitmap_buffer[0 + i*3 + (cinfo.output_scanline-1) * cinfo.output_width*3] = *(*buffer + 0 + i);
1976 				bitmap_buffer[1 + i*3 + (cinfo.output_scanline-1) * cinfo.output_width*3] = *(*buffer + 0 + i);
1977 				bitmap_buffer[2 + i*3 + (cinfo.output_scanline-1) * cinfo.output_width*3] = *(*buffer + 0 + i);
1978 			}
1979 		}
1980 	}
1981 
1982 	/* print info */ STRING_PRINTV("freeing jpeg object\n");
1983 	(void) jpeg_finish_decompress(&cinfo);
1984 	jpeg_destroy_decompress(&cinfo);
1985 	fclose(infile);
1986 
1987 	return 0;
1988 }
1989 
1990 
1991 
1992 
1993 /* ------------------------------------------------- */
1994 /* --------- BITMAP WRITE IN JPEG FORMAT ----------- */
1995 /* ------------------------------------------------- */
1996 /* source code examples for writing JPEG taken from libjpeg's example.c */
BITMAP_WRITE_JPEG(char * file_name)1997 int BITMAP_WRITE_JPEG(char *file_name)
1998 {
1999 	struct jpeg_compress_struct cinfo;
2000 	struct jpeg_error_mgr jerr;
2001 	FILE *outfile;
2002 	JSAMPROW row_pointer[1];
2003 	int row_stride;
2004 
2005 	/* write back exif info if there exists any */
2006 	EXIF_PUT(file_name);
2007 
2008 	/* print info */ STRING_PRINTV("jpeg initializations\n");
2009 
2010 	cinfo.err = jpeg_std_error(&jerr);
2011         jpeg_create_compress(&cinfo);
2012 
2013 	/* print info */ STRING_PRINTV("opening file for writing\n");
2014 	/* if there was exif info, then open file in append mode */
2015 	/* otherwise open it in write mode */
2016 	if (exif_flag){
2017 		if ((outfile = fopen(file_name, "a+b")) == NULL) { return 1; } }
2018 	else{
2019 		if ((outfile = fopen(file_name, "wb")) == NULL) { return 1; } }
2020 
2021 	jpeg_stdio_dest(&cinfo, outfile);
2022 
2023 	cinfo.image_width = bitmap_width;
2024 	cinfo.image_height = bitmap_height;
2025 	if (bitmap_format_jpg_clrspc_type == 8){
2026 		cinfo.input_components = 1;
2027 		cinfo.in_color_space = JCS_GRAYSCALE;
2028 	}
2029 	if (bitmap_format_jpg_clrspc_type == 24){
2030 		cinfo.input_components = 3;
2031 		cinfo.in_color_space = JCS_RGB;
2032 	}
2033 
2034 	jpeg_set_defaults(&cinfo);
2035 
2036 	/* set image resolution */
2037 	if (udpi == 0){
2038 		/* unknown unit */
2039 		cinfo.X_density = xdpi;
2040 		cinfo.Y_density = ydpi;
2041 		cinfo.density_unit = 0;
2042 	}
2043 	if (udpi == 1){
2044 		/* convert from pixel per meter to inch with rounding up to the nearest decimal */
2045 		int xnew = (int)(xdpi * 25.4 / 100);
2046 		int ynew = (int)(ydpi * 25.4 / 100);
2047 		if ((xnew % 10) > 5){ xnew += 5; }
2048 		if ((ynew % 10) > 5){ ynew += 5; }
2049 		xnew /= 10;
2050 		ynew /= 10;
2051 		cinfo.X_density = xnew;
2052 		cinfo.Y_density = ynew;
2053 		cinfo.density_unit = 1;
2054 	}
2055 
2056 	/* set default quality to 95 if unset */
2057 	if (opt_quality < 0)  { opt_quality = 0;   }
2058 	if (opt_quality > 100){ opt_quality = 100; }
2059 	if (!(opt_quality))   { opt_quality = 95;  }
2060 	jpeg_set_quality(&cinfo, opt_quality, TRUE);
2061 
2062 	/* print info */ STRING_PRINTV("encoding jpeg image\n");
2063 	jpeg_start_compress(&cinfo, TRUE);
2064 
2065 	row_stride = bitmap_width * cinfo.input_components;
2066 
2067 	/* if image is 1 component Gray, then copy RGB bytes back as Gray bytes */
2068 	if (cinfo.input_components == 1){
2069                 int offs1 = 0;
2070                 int offs2 = 0;
2071 		unsigned int col, x, y;
2072 		/* this cycle cannot be paralleled because of writing back to the same memory */
2073                 for (y=0; y < bitmap_height; y++){
2074                         for (x=0; x < bitmap_width; x++){
2075                                 col = 0;
2076                                 col += bitmap_buffer[offs2 + 0];
2077                                 col += bitmap_buffer[offs2 + 1];
2078                                 col += bitmap_buffer[offs2 + 2];
2079                                 col /= 3;
2080                                 bitmap_buffer[offs1] = col;
2081                                 offs1++;
2082                                 offs2 += 3;
2083                         }
2084                 }
2085 	}
2086 
2087 	/* print info */ STRING_PRINTV("copying colors from bitmap buffer to jpeg object\n");
2088 	while (cinfo.next_scanline < cinfo.image_height) {
2089 		row_pointer[0] = &bitmap_buffer[cinfo.next_scanline * row_stride];
2090 		(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
2091 	}
2092 
2093 	/* print info */ STRING_PRINTV("freeing jpeg object\n");
2094 	jpeg_finish_compress(&cinfo);
2095 	fclose(outfile);
2096 	jpeg_destroy_compress(&cinfo);
2097 
2098 
2099 	/* correct the end of exif data in file and free exif buffer if there was any */
2100 	EXIF_CORRECT(file_name);
2101 	EXIF_CLEAR();
2102 
2103 	return 0;
2104 }
2105 
2106 #endif
2107 
2108 
2109 
2110 /* --------------------------------------- */
2111 /* ----------- BITMAP LOAD --------------- */
2112 /* --------------------------------------- */
2113 /* load image and unpack it into memory (memory will be allocated) */
BITMAP_LOAD(char * file_name)2114 int BITMAP_LOAD(char *file_name)
2115 {
2116     FILE *fhandle;
2117 
2118     /* clear exif flag at new file */
2119     exif_flag = 0;
2120 
2121 	/* does file exist? */
2122 	fhandle = fopen(file_name, "rb");
2123 	if (fhandle == 0) {
2124 		return 2;
2125 	}
2126 	fclose(fhandle);
2127 
2128     /* print info */ STRING_PRINTV("file exists\n");
2129     /* if it's a BMP format, then load BMP with custom procedure (and not jasper) */
2130     if (GET_FILE_FORMAT(file_name) == 2){
2131         if (BITMAP_READ_BMP(file_name)) return 1;
2132     }
2133     else{
2134 
2135 #ifdef __BMP_ONLY__
2136     STRING_PRINT("\n"); STRING_PRINTE("BMP_ONLY version. Only BMP format is supported here.n");
2137     return 1;
2138 #endif
2139 #ifndef __BMP_ONLY__
2140 
2141 
2142 	/* if it's a PNG format, then load that one */
2143         if (GET_FILE_FORMAT(file_name) == 8){
2144             if (BITMAP_READ_PNG(file_name)) return 1;
2145             return 0;
2146         }
2147 
2148 	/* if it's a JPEG, then save exif info and load image with libjpeg (and not libjasper) */
2149         if (GET_FILE_FORMAT(file_name) == 6){
2150             if (BITMAP_READ_JPEG(file_name)) return 1;
2151             return 0;
2152         }
2153 
2154 	/* in every other case, load jasper format */
2155 	/* because anyway there are no other supported formats */
2156 	/* and jasper will signal if it's not one of its supported ones */
2157         if (BITMAP_READ_JASPER(file_name)) return 1;
2158         return 0;
2159 
2160 
2161 #endif
2162     }
2163 
2164 	return 0;
2165 }
2166 
2167 
2168 
2169 
2170 /* --------------------------------------- */
2171 /* ----------- BITMAP SAVE --------------- */
2172 /* --------------------------------------- */
2173 /* pack the image file and save it from memory (memory will be freed) */
BITMAP_SAVE(char * file_name)2174 int BITMAP_SAVE(char *file_name)
2175 {
2176     /* if the format is not JPEG, then clear exif info (memory is freed) */
2177     if (GET_FILE_FORMAT(file_name) != 6){ EXIF_CLEAR(); }
2178 
2179     /* if it's a BMP format, then save BMP with custom procedure (and not with jasper) */
2180     if (GET_FILE_FORMAT(file_name) == 2){
2181         if (BITMAP_WRITE_BMP(file_name)) { free(bitmap_buffer); return 1; }
2182 
2183 	/* free memory on success */
2184 	/* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
2185 	free(bitmap_buffer);
2186 	return 0;
2187     }
2188     else{
2189 
2190 #ifdef __BMP_ONLY__
2191     STRING_PRINT("\n"); STRING_PRINTE("BMP_ONLY version. Only BMP format is supported here.n");
2192     /* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
2193     free(bitmap_buffer);
2194     return 1;
2195 #endif
2196 #ifndef __BMP_ONLY__
2197 
2198 
2199     /* if it's a PNG, then save PNG */
2200     if (GET_FILE_FORMAT(file_name) == 8){
2201         if (BITMAP_WRITE_PNG(file_name)) {
2202    	    /* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
2203 	    free(bitmap_buffer); return 1; }
2204 
2205 	/* free memory on success */
2206 	/* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
2207 	free(bitmap_buffer);
2208 	return 0;
2209     }
2210 
2211     /* if it's a JPEG, then save it */
2212     if (GET_FILE_FORMAT(file_name) == 6){
2213         if (BITMAP_WRITE_JPEG(file_name)) {
2214 	    /* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
2215 	    free(bitmap_buffer); return 1; }
2216 
2217 	/* free memory on success */
2218 	/* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
2219 	free(bitmap_buffer);
2220 	return 0;
2221     }
2222 
2223 
2224     /* in every other case, save jasper format */
2225     /* because anyway there are no other supported formats */
2226     /* and jasper will signal if it's not one of its supported ones */
2227     if (BITMAP_WRITE_JASPER(file_name)) {
2228 	    /* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
2229 	    free(bitmap_buffer); return 1; }
2230 
2231     /* free memory on success */
2232     /* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
2233     free(bitmap_buffer);
2234     return 0;
2235 
2236 #endif
2237     }
2238 
2239 }
2240 
2241