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