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
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
24 #include <sys/types.h>
28 typedef __int64 INT64
;
29 typedef unsigned short ushort
;
31 #include <netinet/in.h>
32 typedef long long INT64
;
36 TIFF and CIFF data blocks can be quite large.
37 Display only the first DLEN bytes.
43 typedef unsigned char uchar
;
44 /*typedef unsigned short ushort;*/
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;*/
57 /*int data_offset, meta_offset*/
58 int raw_height
, raw_width
, top_margin
, left_margin
;
62 struct decode
*branch
[2];
64 } first_decode
[640], *free_decode
;
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.
80 a
= fgetc(ifp
); b
= fgetc(ifp
);
82 if (order
== 0x4949) /* "II" means little-endian */
84 else /* "MM" means big-endian */
89 Same for a 4-byte integer.
95 a
= fgetc(ifp
); b
= fgetc(ifp
);
96 c
= fgetc(ifp
); d
= fgetc(ifp
);
99 return a
| b
<< 8 | c
<< 16 | d
<< 24;
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
;
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
);
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];
131 The MakerNote might have its own TIFF header (possibly with
132 its own byte-order!), or it might just be a table.
135 fread (buf
, 1, 10, ifp
);
136 if (!strcmp (buf
,"Nikon")) { /* starts with "Nikon\0\2\0\0\0" ? */
138 order
= get2(); /* might differ from file-wide byteorder */
139 val
= get2(); /* should be 42 decimal */
141 fseek (ifp
, offset
-8, SEEK_CUR
);
142 } else if (!strncmp (buf
,"FUJIFILM",8) ||
143 !strcmp (buf
,"Panasonic")) {
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
);
153 fseek (ifp
, -10, SEEK_CUR
);
156 if (entries
> 100) return;
162 tiff_dump (base
, tag
, type
, count
, 2);
164 fscanf (ifp
, "%d", &serial
);
166 fread (buf91
, sizeof buf91
, 1, ifp
);
168 fread (buf97
, sizeof buf97
, 1, ifp
);
170 fread (buf98
, sizeof buf98
, 1, ifp
);
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")) {
186 thumb_offset
= ftell(ifp
);
187 thumb_length
= count
;
190 thumb_offset
= get4() + base
;
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
);
206 void nef_parse_exif(int base
)
208 int entries
, tag
, type
, count
, save
;
216 tiff_dump (base
, tag
, type
, count
, 1);
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
;
227 static const int flip_map
[] = { 0,1,3,2,4,6,7,5 };
230 if (entries
> 255) return 1;
237 if (slen
> 128) slen
= 128;
239 tiff_dump (base
, tag
, type
, count
, level
);
242 if (type
== 3) /* short int */
246 fseek (ifp
, save2
, SEEK_SET
);
248 if (tag
> 50700 && tag
< 50800)
251 if (level
== 3) { /* Olympus E-1 and E-300 */
255 else if (tag
== 0x102)
261 case 0x100: /* ImageWidth */
262 if (!width
) width
= val
;
264 case 0x101: /* ImageHeight */
265 if (!height
) height
= val
;
267 case 0x102: /* Bits per sample */
273 case 0x103: /* Compression */
276 case 0x10f: /* Make tag */
277 fgets (make
, slen
, ifp
);
279 case 0x110: /* Model tag */
280 fgets (model
, slen
, ifp
);
282 case 33405: /* Model2 tag */
283 fgets (model2
, slen
, ifp
);
285 case 0x111: /* StripOffset */
286 if (!offset
|| is_dng
) offset
= val
;
288 case 0x112: /* Orientation */
289 flip
= flip_map
[(val
-1) & 7];
291 case 0x117: /* StripByteCounts */
292 if (!length
|| is_dng
) length
= val
;
293 if (offset
> val
&& !strncmp(make
,"KODAK",5) && !is_dng
)
296 case 0x14a: /* SubIFD tag */
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);
305 if (strncmp(make
,"OLYMPUS",7) || !thumb_offset
)
309 if (strncmp(make
,"OLYMPUS",7) || !thumb_length
)
313 fseek (ifp
, get4()+base
, SEEK_SET
);
314 nef_parse_exif (base
);
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
;
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
);
340 if (order
!= 0x4949 && order
!= 0x4d4d) return;
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;
349 if (strncmp(make
,"KODAK",5))
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)) {
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);
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
) {
377 printf ("Tag %c%c%c offset %06x length %06x\n",
378 tag
>>16, tag
>>8, tag
, save
, len
);
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
) );
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"))
406 fseek (ifp
, offset
+length
-4, SEEK_SET
);
407 tboff
= get4() + offset
;
408 fseek (ifp
, tboff
, SEEK_SET
);
410 if (nrecs
> 100) return;
411 for (i
= 0; i
< nrecs
; i
++) {
415 aoff
= offset
+ roff
;
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 ... */
426 if (((!strcmp(model
,"Canon EOS DIGITAL REBEL") ||
427 !strcmp(model
,"Canon EOS 300D DIGITAL"))) && wbi
== 6)
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();
436 fseek (ifp
, aoff
+100, SEEK_SET
);
440 if (type
== 0x0032) { /* Get white balance (D30 & G3) */
441 if (!strcmp(model
,"Canon EOS D30")) {
442 fseek (ifp
, aoff
+72, SEEK_SET
);
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
);
453 } else if (!strcmp(model
,"Canon PowerShot Pro1")) {
454 fseek (ifp
, aoff
+96 + wbi
*8, SEEK_SET
);
457 fseek (ifp
, aoff
+80 + (wbi
< 6 ? remap
[wbi
]*8 : 0), SEEK_SET
);
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
);
467 camera_red
/= get2();
468 camera_blue
= get2();
469 camera_blue
= get2() / camera_blue
;
471 /* Skip this for now /steffen */
473 if (type
== 0x1030 && (wbi
== 6 || wbi
== 15)) {
474 fseek (ifp
, aoff
, SEEK_SET
); /* Get white sample */
478 if (type
== 0x1031) { /* Get the raw width and height */
479 fseek (ifp
, aoff
+2, SEEK_SET
);
483 if (type
== 0x180e) { /* Get the timestamp */
484 fseek (ifp
, aoff
, SEEK_SET
);
491 flash_used
= *((float *) &len
);
493 canon_5814
= *((float *) &len
);
495 if (type
== 0x1810) { /* Get the rotation */
496 fseek (ifp
, aoff
+12, SEEK_SET
);
499 /* Skip this for now /steffen */
501 if (type
== 0x1835) { /* Get the decoder table */
502 fseek (ifp
, aoff
, SEEK_SET
);
503 crw_init_tables (get4());
506 if (type
== 0x2007) { /* Found the JPEG thumbnail */
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
)
522 int i
, j
, skip
, save
;
527 fread (data
, 1, 8, ifp
);
528 if (strcmp(data
,"PKTS")) break;
529 strcpy (model
, "Valeo");
530 fread (data
, 1, 40, ifp
);
532 if (!strcmp(data
,"icc_camera_to_tone_matrix")) {
533 for (i
=0; i
< skip
/4; i
++) {
538 if (!strcmp(data
,"JPEG_preview_data")) {
540 thumb_offset
= ftell(ifp
);
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')))
549 fseek (ifp
, skip
, SEEK_CUR
);
551 fseek (ifp
, save
, SEEK_SET
);
556 char line
[128], *val
;
558 fseek (ifp
, 0, SEEK_SET
);
560 fgets (line
, 128, ifp
);
561 fputs (line
, stdout
);
562 if ((val
= strchr(line
,'=')))
565 val
= line
+ strlen(line
);
566 if (!strcmp(line
,"HDR"))
567 thumb_offset
= atoi(val
);
568 if (!strcmp(line
,"TX "))
570 if (!strcmp(line
,"TY "))
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
)
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
);
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
)
600 fseek (ifp
, offset
, SEEK_SET
);
601 for (cp
=buf
; (c
= get2()) && cp
+3 < buf
+len
; ) {
604 else if (c
< 0x800) {
605 *cp
++ = 0xc0 + (c
>> 6);
606 *cp
++ = 0x80 + (c
& 0x3f);
608 *cp
++ = 0xe0 + (c
>> 12);
609 *cp
++ = 0x80 + (c
>> 6 & 0x3f);
610 *cp
++ = 0x80 + (c
& 0x3f);
616 ushort
sget2 (uchar
*s
)
618 return s
[0] + (s
[1]<<8);
623 return s
[0] + (s
[1]<<8) + (s
[2]<<16) + (s
[3]<<24);
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);
646 fseek (ifp
, off
, SEEK_SET
);
647 if (get4() != (0x20434553 | (tag
<< 24))) {
648 printf ("Bad Section identifier at %6x\n", off
);
653 case 0x32414d49: /* IMA2 */
654 case 0x47414d49: /* IMAG */
655 if (++img
== 2) { /* second image */
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());
665 case 0x464d4143: /* CAMF */
666 printf ("type %d, ", get4());
668 for (i
=0; i
< 4; i
++)
671 printf (" version %d.%d:\n",val
>> 16, val
& 0xffff);
673 if ((len
-= 28) > 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
);
687 printf (" %4.4s version %d.%d: ", pos
, val
>> 16, val
& 0xffff);
690 cp
= pos
+ sget4(pos
+16);
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
--; ) {
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
++) {
705 for (k
=0; k
< dim
[0]; k
++)
709 printf ("%7d", sget2(dp
));
714 printf (" %d", sget4(dp
));
718 union { int ival
; float fval
; } __t
;
719 __t
.ival
= sget4(dp
);
720 printf (" %9f", __t
.fval
);
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
++) {
736 printf (" %s = %s\n", cp
+sget4(pos
+val
), cp
+sget4(pos
+val
+4));
740 cp
= pos
+ sget4(pos
+16);
741 printf ("%s = %.*s\n", pos
+sget4(pos
+12), sget4(cp
), cp
+4);
748 case 0x504f5250: /* PROP */
749 printf ("entries %d, ", pent
=get4());
750 printf ("charset %d, ", get4());
752 printf ("nchars %d\n", get4());
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
));
768 fseek (ifp
, save
, SEEK_SET
);
772 void foveon_tree (unsigned huff
[1024], unsigned code
)
779 for (i
=0; i
< 1024; i
++)
780 if (huff
[i
] == code
) {
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
;
798 struct decode
*dindex
;
800 unsigned huff
[1024], bitbuf
=0;
802 fseek (ifp
, thumb_offset
+16, SEEK_SET
);
806 fprintf (tfp
, "P6\n%d %d\n255\n", width
, height
);
809 for (row
=0; row
< height
; row
++) {
810 fread (buf
, 1, bwide
, ifp
);
811 fwrite (buf
, 3, width
, tfp
);
816 for (i
=0; i
< 256; i
++)
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
);
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
)
843 unsigned col
, len
, bits
=0;
846 int i
, li
=0, si
, diff
, six
[6], y
[4], cb
=0, cr
=0, rgb
[3];
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);
855 fprintf (stderr
, "kodak_yuv_decode() malloc failed!\n");
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
; ) {
869 li
= bitbuf
= bits
= y
[1] = y
[3] = cb
= cr
= 0;
871 bitbuf
= fgetc(ifp
) << 8;
872 bitbuf
+= fgetc(ifp
);
876 for (si
=0; si
< 6; si
++) {
879 for (i
=0; i
< 32; i
+=8)
880 bitbuf
+= (INT64
) fgetc(ifp
) << (bits
+(i
^8));
883 diff
= bitbuf
& (0xffff >> (16-len
));
886 if ((diff
& (1 << (len
-1))) == 0)
887 diff
-= (1 << len
) - 1;
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];
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
);
910 void parse_phase_one (int base
)
912 unsigned entries
, tag
, type
, len
, data
, save
;
915 fseek (ifp
, base
+ 8, SEEK_SET
);
916 fseek (ifp
, base
+ get4(), SEEK_SET
);
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
);
933 thumb_offset
= data
+ base
;
936 fseek (ifp
, save
, SEEK_SET
);
938 strcpy (make
, "Phase One");
939 strcpy (model
, "unknown");
942 void parse_jpeg (int offset
)
946 fseek (ifp
, offset
, SEEK_SET
);
947 if (fgetc(ifp
) != 0xff || fgetc(ifp
) != 0xd8) return;
949 while (fgetc(ifp
) == 0xff && fgetc(ifp
) >> 4 != 0xd) {
955 if (get4() == 0x48454150) /* "HEAP" */
956 parse_ciff (save
+hlen
, len
-hlen
, 0);
958 fseek (ifp
, save
+len
, SEEK_SET
);
964 char *memmem (char *haystack
, size_t haystacklen
,
965 char *needle
, size_t needlelen
)
968 for (c
= haystack
; c
<= haystack
+ haystacklen
- needlelen
; c
++)
969 if (!memcmp (c
, needle
, needlelen
))
976 Identify which camera created this file, and set global variables
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
;
986 make
[0] = model
[0] = model2
[0] = is_dng
= 0;
987 thumb_head
[0] = thumb_offset
= thumb_length
= thumb_layers
= 0;
990 fseek (ifp
, 0, SEEK_SET
);
991 fread (head
, 1, 32, ifp
);
992 fseek (ifp
, 0, SEEK_END
);
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
);
1003 } else if (!memcmp (head
, "\0MRM", 4))
1005 else if (!memcmp (head
, "\xff\xd8\xff\xe1", 4) &&
1006 !memcmp (head
+6, "Exif", 4)) {
1009 } else if (!memcmp (head
, "FUJIFILM", 8)) {
1010 fseek (ifp
, 84, SEEK_SET
);
1013 thumb_offset
= toff
;
1014 thumb_length
= tlen
;
1015 } else if (!memcmp (head
, "DSC-Image", 9))
1017 else if (!memcmp (head
, "FOVb", 4))
1019 fseek (ifp
, 8, SEEK_SET
);
1021 fseek (ifp
, 3472, SEEK_SET
);
1025 if (!thumb_length
) {
1026 fprintf (stderr
, "Thumbnail image not found\n");
1030 if (is_dng
) goto dng_skip
;
1031 if (!strncmp(model
,"DCS Pro",7)) {
1032 kodak_yuv_decode (tfp
);
1035 if (!strcmp(make
,"Rollei")) {
1036 rollei_decode (tfp
);
1039 if (!strcmp(make
,"SIGMA")) {
1040 foveon_decode (tfp
);
1044 thumb
= (char *) malloc(thumb_length
);
1046 fprintf (stderr
, "Cannot allocate %d bytes!!\n", thumb_length
);
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
);
1054 fprintf (stderr
, "Cannot allocate %d bytes!!\n", thumb_length
);
1057 lsize
= thumb_length
/3;
1058 for (i
=0; i
< thumb_length
; i
++)
1059 rgb
[(i
%lsize
)*3 + i
/lsize
] = thumb
[i
];
1063 fputs (thumb_head
, tfp
);
1064 fwrite(thumb
, 1, thumb_length
, tfp
);
1067 fprintf (stderr
, "Thumbnail image written, make=%s, model=%s\n",&(make
[0]),&(model
[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 };
1078 rc
= identify(output
);
1079 switch ((flip
+3600) % 360) {
1080 case 270: flip
= 5; break;
1081 case 180: flip
= 3; break;
1084 if( orientation
) *orientation
= flip_map
[flip
%7];