update
[kdegraphics.git] / strigi-analyzer / raw / parse.c
blobc51b1f96dc18c9769559910610f789bf8842dfc0
1 /*
2 Raw Photo Parser
3 Copyright 2004 by Dave Coffin, dcoffin a cybercom o net
5 This program extracts thumbnail images (preferably JPEGs)
6 from any raw digital camera formats that have them, and
7 shows table contents.
9 $Revision: 1.36 $
10 $Date: 2005/05/10 21:43:10 $
13 /* Hacked for thumbnail extraction in KDE by
14 Steffen Hansen <hansen@kde.org>
16 Based on parse.c and parts of dcraw.c by Dave Coffin
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <ctype.h>
23 #include <time.h>
24 #include <sys/types.h>
26 #ifdef WIN32
27 #include <winsock2.h>
28 typedef __int64 INT64;
29 typedef unsigned short ushort;
30 #else
31 #include <netinet/in.h>
32 typedef long long INT64;
33 #endif
36 TIFF and CIFF data blocks can be quite large.
37 Display only the first DLEN bytes.
39 #ifndef DLEN
40 #define DLEN 768
41 #endif
43 typedef unsigned char uchar;
44 /*typedef unsigned short ushort;*/
46 FILE *ifp;
47 short order;
48 char *fname;
49 char make[128], model[128], model2[128], thumb_head[128];
50 int width, height, offset, length, bps, is_dng;
51 int thumb_offset, thumb_length, thumb_layers;
52 float cam_mul[4], pre_mul[4], coeff[3][4];
53 #define camera_red cam_mul[0]
54 #define camera_blue cam_mul[2]
55 /*float flash_used, canon_5814;*/
56 time_t timestamp;
57 /*int data_offset, meta_offset*/
58 int raw_height, raw_width, top_margin, left_margin;
59 static int flip = 0;
61 struct decode {
62 struct decode *branch[2];
63 int leaf;
64 } first_decode[640], *free_decode;
66 #define CLASS
68 #define FORC3 for (c=0; c < 3; c++)
69 #define FORC4 for (c=0; c < 4; c++)
70 #define FORCC for (c=0; c < colors; c++)
73 Get a 2-byte integer, making no assumptions about CPU byte order.
74 Nor should we assume that the compiler evaluates left-to-right.
76 ushort get2()
78 uchar a, b;
80 a = fgetc(ifp); b = fgetc(ifp);
82 if (order == 0x4949) /* "II" means little-endian */
83 return a | b << 8;
84 else /* "MM" means big-endian */
85 return a << 8 | b;
89 Same for a 4-byte integer.
91 int get4()
93 uchar a, b, c, d;
95 a = fgetc(ifp); b = fgetc(ifp);
96 c = fgetc(ifp); d = fgetc(ifp);
98 if (order == 0x4949)
99 return a | b << 8 | c << 16 | d << 24;
100 else
101 return a << 24 | b << 16 | c << 8 | d;
104 void tiff_dump(int base, int tag, int type, int count, int level)
106 int save, j, num, den;
107 uchar c;
108 int size[] = { 1,1,1,2,4,8,1,1,2,4,8,4,8 };
110 if (count * size[type < 13 ? type:0] > 4)
111 fseek (ifp, get4()+base, SEEK_SET);
112 save = ftell(ifp);
113 fseek (ifp, save, SEEK_SET);
116 void nikon_decrypt (uchar ci, uchar cj, int tag, int i, int size, uchar *buf)
120 int parse_tiff_ifd (int base, int level);
122 void nef_parse_makernote (base)
124 int offset=0, entries, tag, type, count, val, save;
125 unsigned serial=0, key=0;
126 uchar buf91[630], buf97[608], buf98[31];
127 short sorder;
128 char buf[10];
131 The MakerNote might have its own TIFF header (possibly with
132 its own byte-order!), or it might just be a table.
134 sorder = order;
135 fread (buf, 1, 10, ifp);
136 if (!strcmp (buf,"Nikon")) { /* starts with "Nikon\0\2\0\0\0" ? */
137 base = ftell(ifp);
138 order = get2(); /* might differ from file-wide byteorder */
139 val = get2(); /* should be 42 decimal */
140 offset = get4();
141 fseek (ifp, offset-8, SEEK_CUR);
142 } else if (!strncmp (buf,"FUJIFILM",8) ||
143 !strcmp (buf,"Panasonic")) {
144 order = 0x4949;
145 fseek (ifp, 2, SEEK_CUR);
146 } else if (!strcmp (buf,"OLYMP") ||
147 !strcmp (buf,"LEICA") ||
148 !strcmp (buf,"EPSON"))
149 fseek (ifp, -2, SEEK_CUR);
150 else if (!strcmp (buf,"AOC"))
151 fseek (ifp, -4, SEEK_CUR);
152 else
153 fseek (ifp, -10, SEEK_CUR);
155 entries = get2();
156 if (entries > 100) return;
157 while (entries--) {
158 save = ftell(ifp);
159 tag = get2();
160 type = get2();
161 count= get4();
162 tiff_dump (base, tag, type, count, 2);
163 if (tag == 0x1d)
164 fscanf (ifp, "%d", &serial);
165 if (tag == 0x91)
166 fread (buf91, sizeof buf91, 1, ifp);
167 if (tag == 0x97)
168 fread (buf97, sizeof buf97, 1, ifp);
169 if (tag == 0x98)
170 fread (buf98, sizeof buf98, 1, ifp);
171 if (tag == 0xa7)
172 key = fgetc(ifp)^fgetc(ifp)^fgetc(ifp)^fgetc(ifp);
174 if (tag == 0x100 && type == 7 && !strncmp(make,"OLYMPUS",7)) {
175 thumb_offset = ftell(ifp);
176 thumb_length = count;
178 if (tag == 0x280 && type == 1) { /* EPSON */
179 strncpy (thumb_head, "\xff", sizeof(thumb_head) );
180 thumb_offset = ftell(ifp)+1;
181 thumb_length = count-1;
183 if (strstr(make,"Minolta") || strstr(make,"MINOLTA")) {
184 switch (tag) {
185 case 0x81:
186 thumb_offset = ftell(ifp);
187 thumb_length = count;
188 break;
189 case 0x88:
190 thumb_offset = get4() + base;
191 break;
192 case 0x89:
193 thumb_length = get4();
196 if (!strcmp (buf,"OLYMP") && tag >> 8 == 0x20)
197 parse_tiff_ifd (base, 3);
198 fseek (ifp, save+12, SEEK_SET);
200 nikon_decrypt (serial, key, 0x91, 4, sizeof buf91, buf91);
201 nikon_decrypt (serial, key, 0x97, 284, sizeof buf97, buf97);
202 nikon_decrypt (serial, key, 0x98, 4, sizeof buf98, buf98);
203 order = sorder;
206 void nef_parse_exif(int base)
208 int entries, tag, type, count, save;
210 entries = get2();
211 while (entries--) {
212 save = ftell(ifp);
213 tag = get2();
214 type = get2();
215 count= get4();
216 tiff_dump (base, tag, type, count, 1);
217 if (tag == 0x927c)
218 nef_parse_makernote (base);
219 fseek (ifp, save+12, SEEK_SET);
223 int parse_tiff_ifd (int base, int level)
225 int entries, tag, type, count, slen, save, save2, val, i;
226 int comp=0;
227 static const int flip_map[] = { 0,1,3,2,4,6,7,5 };
229 entries = get2();
230 if (entries > 255) return 1;
231 while (entries--) {
232 save = ftell(ifp);
233 tag = get2();
234 type = get2();
235 count= get4();
236 slen = count;
237 if (slen > 128) slen = 128;
239 tiff_dump (base, tag, type, count, level);
241 save2 = ftell(ifp);
242 if (type == 3) /* short int */
243 val = get2();
244 else
245 val = get4();
246 fseek (ifp, save2, SEEK_SET);
248 if (tag > 50700 && tag < 50800)
249 is_dng = 1;
251 if (level == 3) { /* Olympus E-1 and E-300 */
252 if (type == 4) {
253 if (tag == 0x101)
254 thumb_offset = val;
255 else if (tag == 0x102)
256 thumb_length = val;
258 goto cont;
260 switch (tag) {
261 case 0x100: /* ImageWidth */
262 if (!width) width = val;
263 break;
264 case 0x101: /* ImageHeight */
265 if (!height) height = val;
266 break;
267 case 0x102: /* Bits per sample */
268 if (bps) break;
269 bps = val;
270 if (count == 1)
271 thumb_layers = 1;
272 break;
273 case 0x103: /* Compression */
274 comp = val;
275 break;
276 case 0x10f: /* Make tag */
277 fgets (make, slen, ifp);
278 break;
279 case 0x110: /* Model tag */
280 fgets (model, slen, ifp);
281 break;
282 case 33405: /* Model2 tag */
283 fgets (model2, slen, ifp);
284 break;
285 case 0x111: /* StripOffset */
286 if (!offset || is_dng) offset = val;
287 break;
288 case 0x112: /* Orientation */
289 flip = flip_map[(val-1) & 7];
290 break;
291 case 0x117: /* StripByteCounts */
292 if (!length || is_dng) length = val;
293 if (offset > val && !strncmp(make,"KODAK",5) && !is_dng)
294 offset -= val;
295 break;
296 case 0x14a: /* SubIFD tag */
297 save2 = ftell(ifp);
298 for (i=0; i < count; i++) {
299 fseek (ifp, save2 + i*4, SEEK_SET);
300 fseek (ifp, get4()+base, SEEK_SET);
301 parse_tiff_ifd (base, level+1);
303 break;
304 case 0x201:
305 if (strncmp(make,"OLYMPUS",7) || !thumb_offset)
306 thumb_offset = val;
307 break;
308 case 0x202:
309 if (strncmp(make,"OLYMPUS",7) || !thumb_length)
310 thumb_length = val;
311 break;
312 case 34665:
313 fseek (ifp, get4()+base, SEEK_SET);
314 nef_parse_exif (base);
315 break;
316 case 50706:
317 is_dng = 1;
319 cont:
320 fseek (ifp, save+12, SEEK_SET);
322 if ((comp == 6 && !strcmp(make,"Canon")) ||
323 (comp == 7 && is_dng)) {
324 thumb_offset = offset;
325 thumb_length = length;
327 return 0;
331 Parse a TIFF file looking for camera model and decompress offsets.
333 void parse_tiff (int base)
335 int doff, spp=3, ifd=0;
337 width = height = offset = length = bps = is_dng = 0;
338 fseek (ifp, base, SEEK_SET);
339 order = get2();
340 if (order != 0x4949 && order != 0x4d4d) return;
341 get2();
342 while ((doff = get4())) {
343 fseek (ifp, doff+base, SEEK_SET);
344 printf ("IFD #%d:\n", ifd++);
345 if (parse_tiff_ifd (base, 0)) break;
347 if (is_dng) return;
349 if (strncmp(make,"KODAK",5))
350 thumb_layers = 0;
351 if (!strncmp(make,"Kodak",5)) {
352 fseek (ifp, 12+base, SEEK_SET);
353 puts ("\nSpecial Kodak image directory:");
354 parse_tiff_ifd (base, 0);
356 if (!strncmp(model,"DCS460A",7)) {
357 spp = 1;
358 thumb_layers = 0;
360 if (!thumb_length && offset) {
361 thumb_offset = offset;
362 sprintf (thumb_head, "P%d %d %d %d\n",
363 spp > 1 ? 6:5, width, height, (1 << bps) - 1);
364 thumb_length = width * height * spp * ((bps+7)/8);
368 void parse_minolta()
370 int data_offset, save, tag, len;
372 fseek (ifp, 4, SEEK_SET);
373 data_offset = get4() + 8;
374 while ((save=ftell(ifp)) < data_offset) {
375 tag = get4();
376 len = get4();
377 printf ("Tag %c%c%c offset %06x length %06x\n",
378 tag>>16, tag>>8, tag, save, len);
379 switch (tag) {
380 case 0x545457: /* TTW */
381 parse_tiff (ftell(ifp));
383 fseek (ifp, save+len+8, SEEK_SET);
385 strncpy (thumb_head, "\xff", sizeof(thumb_head) );
386 thumb_offset++;
387 thumb_length--;
391 Parse a CIFF file, better known as Canon CRW format.
393 void parse_ciff (int offset, int length, int level /*unused*/)
395 int tboff, nrecs, i, c, type, len, roff, aoff, save, wbi=-1;
396 static const int remap[] = { 1,2,3,4,5,1 };
397 static const int remap_10d[] = { 0,1,3,4,5,6,0,0,2,8 };
398 static const int remap_s70[] = { 0,1,2,9,4,3,6,7,8,9,10,0,0,0,7,0,0,8 };
399 ushort key[] = { 0x410, 0x45f3 };
401 if (strcmp(model,"Canon PowerShot G6") &&
402 strcmp(model,"Canon PowerShot S60") &&
403 strcmp(model,"Canon PowerShot S70") &&
404 strcmp(model,"Canon PowerShot Pro1"))
405 key[0] = key[1] = 0;
406 fseek (ifp, offset+length-4, SEEK_SET);
407 tboff = get4() + offset;
408 fseek (ifp, tboff, SEEK_SET);
409 nrecs = get2();
410 if (nrecs > 100) return;
411 for (i = 0; i < nrecs; i++) {
412 type = get2();
413 len = get4();
414 roff = get4();
415 aoff = offset + roff;
416 save = ftell(ifp);
417 if (type == 0x080a) { /* Get the camera make and model */
418 fseek (ifp, aoff, SEEK_SET);
419 fread (make, 64, 1, ifp);
420 fseek (ifp, aoff+strlen(make)+1, SEEK_SET);
421 fread (model, 64, 1, ifp);
423 if (type == 0x102a) { /* Find the White Balance index */
424 fseek (ifp, aoff+14, SEEK_SET); /* 0=auto, 1=daylight, 2=cloudy ... */
425 wbi = get2();
426 if (((!strcmp(model,"Canon EOS DIGITAL REBEL") ||
427 !strcmp(model,"Canon EOS 300D DIGITAL"))) && wbi == 6)
428 wbi++;
430 if (type == 0x102c) { /* Get white balance (G2) */
431 if (!strcmp(model,"Canon PowerShot G1") ||
432 !strcmp(model,"Canon PowerShot Pro90 IS")) {
433 fseek (ifp, aoff+120, SEEK_SET);
434 FORC4 cam_mul[c ^ 2] = get2();
435 } else {
436 fseek (ifp, aoff+100, SEEK_SET);
437 goto common;
440 if (type == 0x0032) { /* Get white balance (D30 & G3) */
441 if (!strcmp(model,"Canon EOS D30")) {
442 fseek (ifp, aoff+72, SEEK_SET);
443 common:
444 camera_red = get2() ^ key[0];
445 camera_red =(get2() ^ key[1]) / camera_red;
446 camera_blue = get2() ^ key[0];
447 camera_blue /= get2() ^ key[1];
448 } else if (!strcmp(model,"Canon PowerShot G6") ||
449 !strcmp(model,"Canon PowerShot S60") ||
450 !strcmp(model,"Canon PowerShot S70")) {
451 fseek (ifp, aoff+96 + remap_s70[wbi]*8, SEEK_SET);
452 goto common;
453 } else if (!strcmp(model,"Canon PowerShot Pro1")) {
454 fseek (ifp, aoff+96 + wbi*8, SEEK_SET);
455 goto common;
456 } else {
457 fseek (ifp, aoff+80 + (wbi < 6 ? remap[wbi]*8 : 0), SEEK_SET);
458 if (!camera_red)
459 goto common;
462 if (type == 0x10a9) { /* Get white balance (D60) */
463 if (!strcmp(model,"Canon EOS 10D"))
464 wbi = remap_10d[wbi];
465 fseek (ifp, aoff+2 + wbi*8, SEEK_SET);
466 camera_red = get2();
467 camera_red /= get2();
468 camera_blue = get2();
469 camera_blue = get2() / camera_blue;
471 /* Skip this for now /steffen */
472 #if 0
473 if (type == 0x1030 && (wbi == 6 || wbi == 15)) {
474 fseek (ifp, aoff, SEEK_SET); /* Get white sample */
475 ciff_block_1030();
477 #endif
478 if (type == 0x1031) { /* Get the raw width and height */
479 fseek (ifp, aoff+2, SEEK_SET);
480 raw_width = get2();
481 raw_height = get2();
483 if (type == 0x180e) { /* Get the timestamp */
484 fseek (ifp, aoff, SEEK_SET);
485 timestamp = get4();
487 if (type == 0x580e)
488 timestamp = len;
489 #if 0
490 if (type == 0x5813)
491 flash_used = *((float *) &len);
492 if (type == 0x5814)
493 canon_5814 = *((float *) &len);
494 #endif
495 if (type == 0x1810) { /* Get the rotation */
496 fseek (ifp, aoff+12, SEEK_SET);
497 flip = get4();
499 /* Skip this for now /steffen */
500 #if 0
501 if (type == 0x1835) { /* Get the decoder table */
502 fseek (ifp, aoff, SEEK_SET);
503 crw_init_tables (get4());
505 #endif
506 if (type == 0x2007) { /* Found the JPEG thumbnail */
507 thumb_offset = aoff;
508 thumb_length = len;
510 if (type >> 8 == 0x28 || type >> 8 == 0x30) /* Get sub-tables */
511 parse_ciff(aoff, len, level+1);
512 fseek (ifp, save, SEEK_SET);
514 if (wbi == 0 && !strcmp(model,"Canon EOS D30"))
515 camera_red = -1; /* Use my auto WB for this photo */
519 void parse_mos(int level)
521 uchar data[256];
522 int i, j, skip, save;
523 char *cp;
525 save = ftell(ifp);
526 while (1) {
527 fread (data, 1, 8, ifp);
528 if (strcmp(data,"PKTS")) break;
529 strcpy (model, "Valeo");
530 fread (data, 1, 40, ifp);
531 skip = get4();
532 if (!strcmp(data,"icc_camera_to_tone_matrix")) {
533 for (i=0; i < skip/4; i++) {
534 j = get4();
536 continue;
538 if (!strcmp(data,"JPEG_preview_data")) {
539 thumb_head[0] = 0;
540 thumb_offset = ftell(ifp);
541 thumb_length = skip;
543 fread (data, 1, sizeof data, ifp);
544 fseek (ifp, -sizeof data, SEEK_CUR);
545 data[sizeof data - 1] = 0;
546 while ((cp=index(data,'\n')))
547 *cp = ' ';
548 parse_mos(level+2);
549 fseek (ifp, skip, SEEK_CUR);
551 fseek (ifp, save, SEEK_SET);
554 void parse_rollei()
556 char line[128], *val;
558 fseek (ifp, 0, SEEK_SET);
559 do {
560 fgets (line, 128, ifp);
561 fputs (line, stdout);
562 if ((val = strchr(line,'=')))
563 *val++ = 0;
564 else
565 val = line + strlen(line);
566 if (!strcmp(line,"HDR"))
567 thumb_offset = atoi(val);
568 if (!strcmp(line,"TX "))
569 width = atoi(val);
570 if (!strcmp(line,"TY "))
571 height = atoi(val);
572 } while (strncmp(line,"EOHD",4));
573 strcpy (make, "Rollei");
574 strcpy (model, "d530flex");
575 thumb_length = width*height*2;
578 void rollei_decode (FILE *tfp)
580 ushort data;
581 int row, col;
583 fseek (ifp, thumb_offset, SEEK_SET);
584 fprintf (tfp, "P6\n%d %d\n255\n", width, height);
585 for (row=0; row < height; row++)
586 for (col=0; col < width; col++) {
587 fread (&data, 2, 1, ifp);
588 data = ntohs(data);
589 putc (data << 3, tfp);
590 putc (data >> 5 << 2, tfp);
591 putc (data >> 11 << 3, tfp);
595 void get_utf8 (int offset, char *buf, int len)
597 ushort c;
598 char *cp;
600 fseek (ifp, offset, SEEK_SET);
601 for (cp=buf; (c = get2()) && cp+3 < buf+len; ) {
602 if (c < 0x80)
603 *cp++ = c;
604 else if (c < 0x800) {
605 *cp++ = 0xc0 + (c >> 6);
606 *cp++ = 0x80 + (c & 0x3f);
607 } else {
608 *cp++ = 0xe0 + (c >> 12);
609 *cp++ = 0x80 + (c >> 6 & 0x3f);
610 *cp++ = 0x80 + (c & 0x3f);
613 *cp = 0;
616 ushort sget2 (uchar *s)
618 return s[0] + (s[1]<<8);
621 int sget4 (uchar *s)
623 return s[0] + (s[1]<<8) + (s[2]<<16) + (s[3]<<24);
626 void parse_foveon()
628 int entries, img=0, off, len, tag, save, i, j, k, pent, poff[256][2];
629 char name[128], value[128], camf[0x20000], *pos, *cp, *dp;
630 unsigned val, key, type, num, ndim, dim[3];
632 order = 0x4949; /* Little-endian */
633 fseek (ifp, -4, SEEK_END);
634 fseek (ifp, get4(), SEEK_SET);
635 if (get4() != 0x64434553) { /* SECd */
636 printf ("Bad Section identifier at %6x\n", (int)ftell(ifp)-4);
637 return;
639 get4();
640 entries = get4();
641 while (entries--) {
642 off = get4();
643 len = get4();
644 tag = get4();
645 save = ftell(ifp);
646 fseek (ifp, off, SEEK_SET);
647 if (get4() != (0x20434553 | (tag << 24))) {
648 printf ("Bad Section identifier at %6x\n", off);
649 goto next;
651 val = get4();
652 switch (tag) {
653 case 0x32414d49: /* IMA2 */
654 case 0x47414d49: /* IMAG */
655 if (++img == 2) { /* second image */
656 thumb_offset = off;
657 thumb_length = 1;
659 printf ("type %d, " , get4());
660 printf ("format %2d, " , get4());
661 printf ("columns %4d, " , get4());
662 printf ("rows %4d, " , get4());
663 printf ("rowsize %d\n" , get4());
664 break;
665 case 0x464d4143: /* CAMF */
666 printf ("type %d, ", get4());
667 get4();
668 for (i=0; i < 4; i++)
669 putchar(fgetc(ifp));
670 val = get4();
671 printf (" version %d.%d:\n",val >> 16, val & 0xffff);
672 key = get4();
673 if ((len -= 28) > 0x20000)
674 len = 0x20000;
675 fread (camf, 1, len, ifp);
676 for (i=0; i < len; i++) {
677 key = (key * 1597 + 51749) % 244944;
678 val = key * (INT64) 301593171 >> 24;
679 camf[i] ^= ((((key << 8) - val) >> 1) + val) >> 17;
681 for (pos=camf; (unsigned) (pos-camf) < len; pos += sget4(pos+8)) {
682 if (strncmp (pos, "CMb", 3)) {
683 printf("Bad CAMF tag \"%.4s\"\n", pos);
684 break;
686 val = sget4(pos+4);
687 printf (" %4.4s version %d.%d: ", pos, val >> 16, val & 0xffff);
688 switch (pos[3]) {
689 case 'M':
690 cp = pos + sget4(pos+16);
691 type = sget4(cp);
692 ndim = sget4(cp+4);
693 dim[0] = dim[1] = dim[2] = 1;
694 printf ("%d-dimensonal array %s of type %d:\n Key: (",
695 ndim, pos+sget4(pos+12), sget4(cp));
696 dp = pos + sget4(cp+8);
697 for (i=ndim; i--; ) {
698 cp += 12;
699 dim[i] = sget4(cp);
700 printf ("%s %d%s", pos+sget4(cp+4), dim[i], i ? ", ":")\n");
702 for (i=0; i < dim[2]; i++) {
703 for (j=0; j < dim[1]; j++) {
704 printf (" ");
705 for (k=0; k < dim[0]; k++)
706 switch (type) {
707 case 0:
708 case 6:
709 printf ("%7d", sget2(dp));
710 dp += 2;
711 break;
712 case 1:
713 case 2:
714 printf (" %d", sget4(dp));
715 dp += 4;
716 break;
717 case 3: {
718 union { int ival; float fval; } __t;
719 __t.ival = sget4(dp);
720 printf (" %9f", __t.fval);
721 dp += 4;
724 printf ("\n");
726 printf ("\n");
728 break;
729 case 'P':
730 val = sget4(pos+16);
731 num = sget4(pos+val);
732 printf ("%s, %d parameters:\n", pos+sget4(pos+12), num);
733 cp = pos+val+8 + num*8;
734 for (i=0; i < num; i++) {
735 val += 8;
736 printf (" %s = %s\n", cp+sget4(pos+val), cp+sget4(pos+val+4));
738 break;
739 case 'T':
740 cp = pos + sget4(pos+16);
741 printf ("%s = %.*s\n", pos+sget4(pos+12), sget4(cp), cp+4);
742 break;
743 default:
744 printf ("\n");
747 break;
748 case 0x504f5250: /* PROP */
749 printf ("entries %d, ", pent=get4());
750 printf ("charset %d, ", get4());
751 get4();
752 printf ("nchars %d\n", get4());
753 off += pent*8 + 24;
754 if (pent > 256) pent=256;
755 for (i=0; i < pent*2; i++)
756 poff[0][i] = off + get4()*2;
757 for (i=0; i < pent; i++) {
758 get_utf8 (poff[i][0], name, 128);
759 get_utf8 (poff[i][1], value, 128);
760 printf (" %s = %s\n", name, value);
761 if (!strcmp (name,"CAMMANUF"))
762 strncpy (make, value, sizeof(make));
763 if (!strcmp (name,"CAMMODEL"))
764 strncpy (model, value, sizeof(value));
767 next:
768 fseek (ifp, save, SEEK_SET);
772 void foveon_tree (unsigned huff[1024], unsigned code)
774 struct decode *cur;
775 int i, len;
777 cur = free_decode++;
778 if (code) {
779 for (i=0; i < 1024; i++)
780 if (huff[i] == code) {
781 cur->leaf = i;
782 return;
785 if ((len = code >> 27) > 26) return;
786 code = (len+1) << 27 | (code & 0x3ffffff) << 1;
788 cur->branch[0] = free_decode;
789 foveon_tree (huff, code);
790 cur->branch[1] = free_decode;
791 foveon_tree (huff, code+1);
794 void foveon_decode (FILE *tfp)
796 int bwide, row, col, bit=-1, c, i;
797 char *buf;
798 struct decode *dindex;
799 short pred[3];
800 unsigned huff[1024], bitbuf=0;
802 fseek (ifp, thumb_offset+16, SEEK_SET);
803 width = get4();
804 height = get4();
805 bwide = get4();
806 fprintf (tfp, "P6\n%d %d\n255\n", width, height);
807 if (bwide > 0) {
808 buf = malloc(bwide);
809 for (row=0; row < height; row++) {
810 fread (buf, 1, bwide, ifp);
811 fwrite (buf, 3, width, tfp);
813 free (buf);
814 return;
816 for (i=0; i < 256; i++)
817 huff[i] = get4();
818 memset (first_decode, 0, sizeof first_decode);
819 free_decode = first_decode;
820 foveon_tree (huff, 0);
822 for (row=0; row < height; row++) {
823 memset (pred, 0, sizeof pred);
824 if (!bit) get4();
825 for (col=bit=0; col < width; col++) {
826 for (c=0; c < 3; c++) {
827 for (dindex=first_decode; dindex->branch[0]; ) {
828 if ((bit = (bit-1) & 31) == 31)
829 for (i=0; i < 4; i++)
830 bitbuf = (bitbuf << 8) + fgetc(ifp);
831 dindex = dindex->branch[bitbuf >> bit & 1];
833 pred[c] += dindex->leaf;
834 fputc (pred[c], tfp);
840 void kodak_yuv_decode (FILE *tfp)
842 uchar c, blen[384];
843 unsigned col, len, bits=0;
844 int row;
845 INT64 bitbuf=0;
846 int i, li=0, si, diff, six[6], y[4], cb=0, cr=0, rgb[3];
847 ushort *out, *op;
849 fseek (ifp, thumb_offset, SEEK_SET);
850 width = (width+1) & -2;
851 height = (height+1) & -2;
852 fprintf (tfp, "P6\n%d %d\n65535\n", width, height);
853 out = malloc (width * 12);
854 if (!out) {
855 fprintf (stderr, "kodak_yuv_decode() malloc failed!\n");
856 exit(1);
859 for (row=0; row < height; row+=2) {
860 for (col=0; col < width; col+=2) {
861 if ((col & 127) == 0) {
862 len = (width - col + 1) * 3 & -4;
863 if (len > 384) len = 384;
864 for (i=0; i < len; ) {
865 c = fgetc(ifp);
866 blen[i++] = c & 15;
867 blen[i++] = c >> 4;
869 li = bitbuf = bits = y[1] = y[3] = cb = cr = 0;
870 if (len % 8 == 4) {
871 bitbuf = fgetc(ifp) << 8;
872 bitbuf += fgetc(ifp);
873 bits = 16;
876 for (si=0; si < 6; si++) {
877 len = blen[li++];
878 if (bits < len) {
879 for (i=0; i < 32; i+=8)
880 bitbuf += (INT64) fgetc(ifp) << (bits+(i^8));
881 bits += 32;
883 diff = bitbuf & (0xffff >> (16-len));
884 bitbuf >>= len;
885 bits -= len;
886 if ((diff & (1 << (len-1))) == 0)
887 diff -= (1 << len) - 1;
888 six[si] = diff;
890 y[0] = six[0] + y[1];
891 y[1] = six[1] + y[0];
892 y[2] = six[2] + y[3];
893 y[3] = six[3] + y[2];
894 cb += six[4];
895 cr += six[5];
896 for (i=0; i < 4; i++) {
897 op = out + ((i >> 1)*width + col+(i & 1)) * 3;
898 rgb[0] = y[i] + 1.40200/2 * cr;
899 rgb[1] = y[i] - 0.34414/2 * cb - 0.71414/2 * cr;
900 rgb[2] = y[i] + 1.77200/2 * cb;
901 for (c=0; c < 3; c++)
902 if (rgb[c] > 0) op[c] = htons(rgb[c]);
905 fwrite (out, sizeof *out, width*6, tfp);
907 free(out);
910 void parse_phase_one (int base)
912 unsigned entries, tag, type, len, data, save;
913 char str[256];
915 fseek (ifp, base + 8, SEEK_SET);
916 fseek (ifp, base + get4(), SEEK_SET);
917 entries = get4();
918 get4();
919 while (entries--) {
920 tag = get4();
921 type = get4();
922 len = get4();
923 data = get4();
924 save = ftell(ifp);
925 printf ("Phase One tag=0x%x, type=%d, len=%2d, data = 0x%x\n",
926 tag, type, len, data);
927 if (type == 1 && len < 256) {
928 fseek (ifp, base + data, SEEK_SET);
929 fread (str, 256, 1, ifp);
930 puts (str);
932 if (tag == 0x110) {
933 thumb_offset = data + base;
934 thumb_length = len;
936 fseek (ifp, save, SEEK_SET);
938 strcpy (make, "Phase One");
939 strcpy (model, "unknown");
942 void parse_jpeg (int offset)
944 int len, save, hlen;
946 fseek (ifp, offset, SEEK_SET);
947 if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) return;
949 while (fgetc(ifp) == 0xff && fgetc(ifp) >> 4 != 0xd) {
950 order = 0x4d4d;
951 len = get2() - 2;
952 save = ftell(ifp);
953 order = get2();
954 hlen = get4();
955 if (get4() == 0x48454150) /* "HEAP" */
956 parse_ciff (save+hlen, len-hlen, 0);
957 parse_tiff (save+6);
958 fseek (ifp, save+len, SEEK_SET);
963 #ifndef _GNU_SOURCE
964 char *memmem (char *haystack, size_t haystacklen,
965 char *needle, size_t needlelen)
967 char *c;
968 for (c = haystack; c <= haystack + haystacklen - needlelen; c++)
969 if (!memcmp (c, needle, needlelen))
970 return c;
971 return NULL;
973 #endif
976 Identify which camera created this file, and set global variables
977 accordingly.
978 Return nonzero if the file cannot be decoded or no thumbnail is found
980 int identify(FILE* tfp)
982 char head[32], *thumb, *rgb, *cp;
983 unsigned hlen, fsize, toff, tlen, lsize;
984 int i;
986 make[0] = model[0] = model2[0] = is_dng = 0;
987 thumb_head[0] = thumb_offset = thumb_length = thumb_layers = 0;
988 order = get2();
989 hlen = get4();
990 fseek (ifp, 0, SEEK_SET);
991 fread (head, 1, 32, ifp);
992 fseek (ifp, 0, SEEK_END);
993 fsize = ftell(ifp);
994 if ((cp = memmem (head, 32, "MMMMRawT", 8)) ||
995 (cp = memmem (head, 32, "IIIITwaR", 8)))
996 parse_phase_one (cp - head);
997 else if (order == 0x4949 || order == 0x4d4d) {
998 if (!memcmp(head+6,"HEAPCCDR",8)) {
999 parse_ciff (hlen, fsize - hlen, 0);
1000 fseek (ifp, hlen, SEEK_SET);
1001 } else
1002 parse_tiff (0);
1003 } else if (!memcmp (head, "\0MRM", 4))
1004 parse_minolta();
1005 else if (!memcmp (head, "\xff\xd8\xff\xe1", 4) &&
1006 !memcmp (head+6, "Exif", 4)) {
1007 parse_tiff (12);
1008 thumb_length = 0;
1009 } else if (!memcmp (head, "FUJIFILM", 8)) {
1010 fseek (ifp, 84, SEEK_SET);
1011 toff = get4();
1012 tlen = get4();
1013 thumb_offset = toff;
1014 thumb_length = tlen;
1015 } else if (!memcmp (head, "DSC-Image", 9))
1016 parse_rollei();
1017 else if (!memcmp (head, "FOVb", 4))
1018 parse_foveon();
1019 fseek (ifp, 8, SEEK_SET);
1020 parse_mos(0);
1021 fseek (ifp, 3472, SEEK_SET);
1022 parse_mos(0);
1023 parse_jpeg(0);
1025 if (!thumb_length) {
1026 fprintf (stderr, "Thumbnail image not found\n");
1027 return -1;
1030 if (is_dng) goto dng_skip;
1031 if (!strncmp(model,"DCS Pro",7)) {
1032 kodak_yuv_decode (tfp);
1033 goto done;
1035 if (!strcmp(make,"Rollei")) {
1036 rollei_decode (tfp);
1037 goto done;
1039 if (!strcmp(make,"SIGMA")) {
1040 foveon_decode (tfp);
1041 goto done;
1043 dng_skip:
1044 thumb = (char *) malloc(thumb_length);
1045 if (!thumb) {
1046 fprintf (stderr, "Cannot allocate %d bytes!!\n", thumb_length);
1047 exit(1);
1049 fseek (ifp, thumb_offset, SEEK_SET);
1050 fread (thumb, 1, thumb_length, ifp);
1051 if (thumb_layers && !is_dng) {
1052 rgb = (char *) malloc(thumb_length);
1053 if (!rgb) {
1054 fprintf (stderr, "Cannot allocate %d bytes!!\n", thumb_length);
1055 return -1;
1057 lsize = thumb_length/3;
1058 for (i=0; i < thumb_length; i++)
1059 rgb[(i%lsize)*3 + i/lsize] = thumb[i];
1060 free(thumb);
1061 thumb = rgb;
1063 fputs (thumb_head, tfp);
1064 fwrite(thumb, 1, thumb_length, tfp);
1065 free (thumb);
1066 done:
1067 fprintf (stderr, "Thumbnail image written, make=%s, model=%s\n",&(make[0]),&(model[0]));
1068 return 0;
1071 int extract_thumbnail( FILE* input, FILE* output, int* orientation )
1073 /* Coffin's code has different meaning for orientation
1074 values than TIFF, so we map them to TIFF values */
1075 static const int flip_map[] = { 0,1,3,2,4,7,5,6 };
1076 int rc;
1077 ifp = input;
1078 rc = identify(output);
1079 switch ((flip+3600) % 360) {
1080 case 270: flip = 5; break;
1081 case 180: flip = 3; break;
1082 case 90: flip = 6;
1084 if( orientation ) *orientation = flip_map[flip%7];
1085 return rc;