diff options
Diffstat (limited to 'kfile-plugins/raw/parse.c')
-rw-r--r-- | kfile-plugins/raw/parse.c | 1080 |
1 files changed, 0 insertions, 1080 deletions
diff --git a/kfile-plugins/raw/parse.c b/kfile-plugins/raw/parse.c deleted file mode 100644 index a256f04e..00000000 --- a/kfile-plugins/raw/parse.c +++ /dev/null @@ -1,1080 +0,0 @@ -/* - Raw Photo Parser - Copyright 2004 by Dave Coffin, dcoffin a cybercom o net - - This program extracts thumbnail images (preferably JPEGs) - from any raw digital camera formats that have them, and - shows table contents. - - $Revision: 1.36 $ - $Date: 2005/05/10 21:43:10 $ - */ - -/* Hacked for thumbnail extraction in KDE by - Steffen Hansen <[email protected]> - - Based on parse.c and parts of dcraw.c by Dave Coffin -*/ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <ctype.h> -#include <time.h> -#include <sys/types.h> - -#ifdef WIN32 -#include <winsock2.h> -typedef __int64 INT64; -#else -#include <netinet/in.h> -typedef long long INT64; -#endif - -/* - TIFF and CIFF data blocks can be quite large. - Display only the first DLEN bytes. - */ -#ifndef DLEN -#define DLEN 768 -#endif - -typedef unsigned char uchar; -/*typedef unsigned short ushort;*/ - -FILE *ifp; -short order; -char *fname; -char make[128], model[128], model2[128], thumb_head[128]; -int width, height, offset, length, bps, is_dng; -int thumb_offset, thumb_length, thumb_layers; -float cam_mul[4], pre_mul[4], coeff[3][4]; -#define camera_red cam_mul[0] -#define camera_blue cam_mul[2] -/*float flash_used, canon_5814;*/ -time_t timestamp; -/*int data_offset, meta_offset*/ -int raw_height, raw_width, top_margin, left_margin; -static int flip = 0; - -struct decode { - struct decode *branch[2]; - int leaf; -} first_decode[640], *free_decode; - -#define CLASS - -#define FORC3 for (c=0; c < 3; c++) -#define FORC4 for (c=0; c < 4; c++) -#define FORCC for (c=0; c < colors; c++) - -/* - Get a 2-byte integer, making no assumptions about CPU byte order. - Nor should we assume that the compiler evaluates left-to-right. - */ -ushort get2() -{ - uchar a, b; - - a = fgetc(ifp); b = fgetc(ifp); - - if (order == 0x4949) /* "II" means little-endian */ - return a | b << 8; - else /* "MM" means big-endian */ - return a << 8 | b; -} - -/* - Same for a 4-byte integer. - */ -int get4() -{ - uchar a, b, c, d; - - a = fgetc(ifp); b = fgetc(ifp); - c = fgetc(ifp); d = fgetc(ifp); - - if (order == 0x4949) - return a | b << 8 | c << 16 | d << 24; - else - return a << 24 | b << 16 | c << 8 | d; -} - -void tiff_dump(int base, int tag, int type, int count, int level) -{ - int save, j, num, den; - uchar c; - int size[] = { 1,1,1,2,4,8,1,1,2,4,8,4,8 }; - - if (count * size[type < 13 ? type:0] > 4) - fseek (ifp, get4()+base, SEEK_SET); - save = ftell(ifp); - fseek (ifp, save, SEEK_SET); -} - -void nikon_decrypt (uchar ci, uchar cj, int tag, int i, int size, uchar *buf) -{ -} - -int parse_tiff_ifd (int base, int level); - -void nef_parse_makernote (base) -{ - int offset=0, entries, tag, type, count, val, save; - unsigned serial=0, key=0; - uchar buf91[630], buf97[608], buf98[31]; - short sorder; - char buf[10]; - -/* - The MakerNote might have its own TIFF header (possibly with - its own byte-order!), or it might just be a table. - */ - sorder = order; - fread (buf, 1, 10, ifp); - if (!strcmp (buf,"Nikon")) { /* starts with "Nikon\0\2\0\0\0" ? */ - base = ftell(ifp); - order = get2(); /* might differ from file-wide byteorder */ - val = get2(); /* should be 42 decimal */ - offset = get4(); - fseek (ifp, offset-8, SEEK_CUR); - } else if (!strncmp (buf,"FUJIFILM",8) || - !strcmp (buf,"Panasonic")) { - order = 0x4949; - fseek (ifp, 2, SEEK_CUR); - } else if (!strcmp (buf,"OLYMP") || - !strcmp (buf,"LEICA") || - !strcmp (buf,"EPSON")) - fseek (ifp, -2, SEEK_CUR); - else if (!strcmp (buf,"AOC")) - fseek (ifp, -4, SEEK_CUR); - else - fseek (ifp, -10, SEEK_CUR); - - entries = get2(); - if (entries > 100) return; - while (entries--) { - save = ftell(ifp); - tag = get2(); - type = get2(); - count= get4(); - tiff_dump (base, tag, type, count, 2); - if (tag == 0x1d) - fscanf (ifp, "%d", &serial); - if (tag == 0x91) - fread (buf91, sizeof buf91, 1, ifp); - if (tag == 0x97) - fread (buf97, sizeof buf97, 1, ifp); - if (tag == 0x98) - fread (buf98, sizeof buf98, 1, ifp); - if (tag == 0xa7) - key = fgetc(ifp)^fgetc(ifp)^fgetc(ifp)^fgetc(ifp); - - if (tag == 0x100 && type == 7 && !strncmp(make,"OLYMPUS",7)) { - thumb_offset = ftell(ifp); - thumb_length = count; - } - if (tag == 0x280 && type == 1) { /* EPSON */ - strncpy (thumb_head, "\xff", sizeof(thumb_head) ); - thumb_offset = ftell(ifp)+1; - thumb_length = count-1; - } - if (strstr(make,"Minolta") || strstr(make,"MINOLTA")) { - switch (tag) { - case 0x81: - thumb_offset = ftell(ifp); - thumb_length = count; - break; - case 0x88: - thumb_offset = get4() + base; - break; - case 0x89: - thumb_length = get4(); - } - } - if (!strcmp (buf,"OLYMP") && tag >> 8 == 0x20) - parse_tiff_ifd (base, 3); - fseek (ifp, save+12, SEEK_SET); - } - nikon_decrypt (serial, key, 0x91, 4, sizeof buf91, buf91); - nikon_decrypt (serial, key, 0x97, 284, sizeof buf97, buf97); - nikon_decrypt (serial, key, 0x98, 4, sizeof buf98, buf98); - order = sorder; -} - -void nef_parse_exif(int base) -{ - int entries, tag, type, count, save; - - entries = get2(); - while (entries--) { - save = ftell(ifp); - tag = get2(); - type = get2(); - count= get4(); - tiff_dump (base, tag, type, count, 1); - if (tag == 0x927c) - nef_parse_makernote (base); - fseek (ifp, save+12, SEEK_SET); - } -} - -int parse_tiff_ifd (int base, int level) -{ - int entries, tag, type, count, slen, save, save2, val, i; - int comp=0; - static const int flip_map[] = { 0,1,3,2,4,6,7,5 }; - - entries = get2(); - if (entries > 255) return 1; - while (entries--) { - save = ftell(ifp); - tag = get2(); - type = get2(); - count= get4(); - slen = count; - if (slen > 128) slen = 128; - - tiff_dump (base, tag, type, count, level); - - save2 = ftell(ifp); - if (type == 3) /* short int */ - val = get2(); - else - val = get4(); - fseek (ifp, save2, SEEK_SET); - - if (tag > 50700 && tag < 50800) - is_dng = 1; - - if (level == 3) { /* Olympus E-1 and E-300 */ - if (type == 4) { - if (tag == 0x101) - thumb_offset = val; - else if (tag == 0x102) - thumb_length = val; - } - goto cont; - } - switch (tag) { - case 0x100: /* ImageWidth */ - if (!width) width = val; - break; - case 0x101: /* ImageHeight */ - if (!height) height = val; - break; - case 0x102: /* Bits per sample */ - if (bps) break; - bps = val; - if (count == 1) - thumb_layers = 1; - break; - case 0x103: /* Compression */ - comp = val; - break; - case 0x10f: /* Make tag */ - fgets (make, slen, ifp); - break; - case 0x110: /* Model tag */ - fgets (model, slen, ifp); - break; - case 33405: /* Model2 tag */ - fgets (model2, slen, ifp); - break; - case 0x111: /* StripOffset */ - if (!offset || is_dng) offset = val; - break; - case 0x112: /* Qt::Orientation */ - flip = flip_map[(val-1) & 7]; - break; - case 0x117: /* StripByteCounts */ - if (!length || is_dng) length = val; - if (offset > val && !strncmp(make,"KODAK",5) && !is_dng) - offset -= val; - break; - case 0x14a: /* SubIFD tag */ - save2 = ftell(ifp); - for (i=0; i < count; i++) { - fseek (ifp, save2 + i*4, SEEK_SET); - fseek (ifp, get4()+base, SEEK_SET); - parse_tiff_ifd (base, level+1); - } - break; - case 0x201: - if (strncmp(make,"OLYMPUS",7) || !thumb_offset) - thumb_offset = val; - break; - case 0x202: - if (strncmp(make,"OLYMPUS",7) || !thumb_length) - thumb_length = val; - break; - case 34665: - fseek (ifp, get4()+base, SEEK_SET); - nef_parse_exif (base); - break; - case 50706: - is_dng = 1; - } -cont: - fseek (ifp, save+12, SEEK_SET); - } - if ((comp == 6 && !strcmp(make,"Canon")) || - (comp == 7 && is_dng)) { - thumb_offset = offset; - thumb_length = length; - } - return 0; -} - -/* - Parse a TIFF file looking for camera model and decompress offsets. - */ -void parse_tiff (int base) -{ - int doff, spp=3, ifd=0; - - width = height = offset = length = bps = is_dng = 0; - fseek (ifp, base, SEEK_SET); - order = get2(); - if (order != 0x4949 && order != 0x4d4d) return; - get2(); - while ((doff = get4())) { - fseek (ifp, doff+base, SEEK_SET); - printf ("IFD #%d:\n", ifd++); - if (parse_tiff_ifd (base, 0)) break; - } - if (is_dng) return; - - if (strncmp(make,"KODAK",5)) - thumb_layers = 0; - if (!strncmp(make,"Kodak",5)) { - fseek (ifp, 12+base, SEEK_SET); - puts ("\nSpecial Kodak image directory:"); - parse_tiff_ifd (base, 0); - } - if (!strncmp(model,"DCS460A",7)) { - spp = 1; - thumb_layers = 0; - } - if (!thumb_length && offset) { - thumb_offset = offset; - sprintf (thumb_head, "P%d %d %d %d\n", - spp > 1 ? 6:5, width, height, (1 << bps) - 1); - thumb_length = width * height * spp * ((bps+7)/8); - } -} - -void parse_minolta() -{ - int data_offset, save, tag, len; - - fseek (ifp, 4, SEEK_SET); - data_offset = get4() + 8; - while ((save=ftell(ifp)) < data_offset) { - tag = get4(); - len = get4(); - printf ("Tag %c%c%c offset %06x length %06x\n", - tag>>16, tag>>8, tag, save, len); - switch (tag) { - case 0x545457: /* TTW */ - parse_tiff (ftell(ifp)); - } - fseek (ifp, save+len+8, SEEK_SET); - } - strncpy (thumb_head, "\xff", sizeof(thumb_head) ); - thumb_offset++; - thumb_length--; -} - -/* - Parse a CIFF file, better known as Canon CRW format. - */ -void parse_ciff (int offset, int length, int level /*unused*/) -{ - int tboff, nrecs, i, c, type, len, roff, aoff, save, wbi=-1; - static const int remap[] = { 1,2,3,4,5,1 }; - static const int remap_10d[] = { 0,1,3,4,5,6,0,0,2,8 }; - static const int remap_s70[] = { 0,1,2,9,4,3,6,7,8,9,10,0,0,0,7,0,0,8 }; - ushort key[] = { 0x410, 0x45f3 }; - - if (strcmp(model,"Canon PowerShot G6") && - strcmp(model,"Canon PowerShot S60") && - strcmp(model,"Canon PowerShot S70") && - strcmp(model,"Canon PowerShot Pro1")) - key[0] = key[1] = 0; - fseek (ifp, offset+length-4, SEEK_SET); - tboff = get4() + offset; - fseek (ifp, tboff, SEEK_SET); - nrecs = get2(); - if (nrecs > 100) return; - for (i = 0; i < nrecs; i++) { - type = get2(); - len = get4(); - roff = get4(); - aoff = offset + roff; - save = ftell(ifp); - if (type == 0x080a) { /* Get the camera make and model */ - fseek (ifp, aoff, SEEK_SET); - fread (make, 64, 1, ifp); - fseek (ifp, aoff+strlen(make)+1, SEEK_SET); - fread (model, 64, 1, ifp); - } - if (type == 0x102a) { /* Find the White Balance index */ - fseek (ifp, aoff+14, SEEK_SET); /* 0=auto, 1=daylight, 2=cloudy ... */ - wbi = get2(); - if (((!strcmp(model,"Canon EOS DIGITAL REBEL") || - !strcmp(model,"Canon EOS 300D DIGITAL"))) && wbi == 6) - wbi++; - } - if (type == 0x102c) { /* Get white balance (G2) */ - if (!strcmp(model,"Canon PowerShot G1") || - !strcmp(model,"Canon PowerShot Pro90 IS")) { - fseek (ifp, aoff+120, SEEK_SET); - FORC4 cam_mul[c ^ 2] = get2(); - } else { - fseek (ifp, aoff+100, SEEK_SET); - goto common; - } - } - if (type == 0x0032) { /* Get white balance (D30 & G3) */ - if (!strcmp(model,"Canon EOS D30")) { - fseek (ifp, aoff+72, SEEK_SET); -common: - camera_red = get2() ^ key[0]; - camera_red =(get2() ^ key[1]) / camera_red; - camera_blue = get2() ^ key[0]; - camera_blue /= get2() ^ key[1]; - } else if (!strcmp(model,"Canon PowerShot G6") || - !strcmp(model,"Canon PowerShot S60") || - !strcmp(model,"Canon PowerShot S70")) { - fseek (ifp, aoff+96 + remap_s70[wbi]*8, SEEK_SET); - goto common; - } else if (!strcmp(model,"Canon PowerShot Pro1")) { - fseek (ifp, aoff+96 + wbi*8, SEEK_SET); - goto common; - } else { - fseek (ifp, aoff+80 + (wbi < 6 ? remap[wbi]*8 : 0), SEEK_SET); - if (!camera_red) - goto common; - } - } - if (type == 0x10a9) { /* Get white balance (D60) */ - if (!strcmp(model,"Canon EOS 10D")) - wbi = remap_10d[wbi]; - fseek (ifp, aoff+2 + wbi*8, SEEK_SET); - camera_red = get2(); - camera_red /= get2(); - camera_blue = get2(); - camera_blue = get2() / camera_blue; - } - /* Skip this for now /steffen */ -#if 0 - if (type == 0x1030 && (wbi == 6 || wbi == 15)) { - fseek (ifp, aoff, SEEK_SET); /* Get white sample */ - ciff_block_1030(); - } -#endif - if (type == 0x1031) { /* Get the raw width and height */ - fseek (ifp, aoff+2, SEEK_SET); - raw_width = get2(); - raw_height = get2(); - } - if (type == 0x180e) { /* Get the timestamp */ - fseek (ifp, aoff, SEEK_SET); - timestamp = get4(); - } - if (type == 0x580e) - timestamp = len; -#if 0 - if (type == 0x5813) - flash_used = *((float *) &len); - if (type == 0x5814) - canon_5814 = *((float *) &len); -#endif - if (type == 0x1810) { /* Get the rotation */ - fseek (ifp, aoff+12, SEEK_SET); - flip = get4(); - } - /* Skip this for now /steffen */ -#if 0 - if (type == 0x1835) { /* Get the decoder table */ - fseek (ifp, aoff, SEEK_SET); - crw_init_tables (get4()); - } -#endif - if (type == 0x2007) { /* Found the JPEG thumbnail */ - thumb_offset = aoff; - thumb_length = len; - } - if (type >> 8 == 0x28 || type >> 8 == 0x30) /* Get sub-tables */ - parse_ciff(aoff, len, level+1); - fseek (ifp, save, SEEK_SET); - } - if (wbi == 0 && !strcmp(model,"Canon EOS D30")) - camera_red = -1; /* Use my auto WB for this photo */ -} - - -void parse_mos(int level) -{ - uchar data[256]; - int i, j, skip, save; - char *cp; - - save = ftell(ifp); - while (1) { - fread (data, 1, 8, ifp); - if (strcmp(data,"PKTS")) break; - strcpy (model, "Valeo"); - fread (data, 1, 40, ifp); - skip = get4(); - if (!strcmp(data,"icc_camera_to_tone_matrix")) { - for (i=0; i < skip/4; i++) { - j = get4(); - } - continue; - } - if (!strcmp(data,"JPEG_preview_data")) { - thumb_head[0] = 0; - thumb_offset = ftell(ifp); - thumb_length = skip; - } - fread (data, 1, sizeof data, ifp); - fseek (ifp, -sizeof data, SEEK_CUR); - data[sizeof data - 1] = 0; - while ((cp=index(data,'\n'))) - *cp = ' '; - parse_mos(level+2); - fseek (ifp, skip, SEEK_CUR); - } - fseek (ifp, save, SEEK_SET); -} - -void parse_rollei() -{ - char line[128], *val; - - fseek (ifp, 0, SEEK_SET); - do { - fgets (line, 128, ifp); - fputs (line, stdout); - if ((val = strchr(line,'='))) - *val++ = 0; - else - val = line + strlen(line); - if (!strcmp(line,"HDR")) - thumb_offset = atoi(val); - if (!strcmp(line,"TX ")) - width = atoi(val); - if (!strcmp(line,"TY ")) - height = atoi(val); - } while (strncmp(line,"EOHD",4)); - strcpy (make, "Rollei"); - strcpy (model, "d530flex"); - thumb_length = width*height*2; -} - -void rollei_decode (FILE *tfp) -{ - ushort data; - int row, col; - - fseek (ifp, thumb_offset, SEEK_SET); - fprintf (tfp, "P6\n%d %d\n255\n", width, height); - for (row=0; row < height; row++) - for (col=0; col < width; col++) { - fread (&data, 2, 1, ifp); - data = ntohs(data); - putc (data << 3, tfp); - putc (data >> 5 << 2, tfp); - putc (data >> 11 << 3, tfp); - } -} - -void get_utf8 (int offset, char *buf, int len) -{ - ushort c; - char *cp; - - fseek (ifp, offset, SEEK_SET); - for (cp=buf; (c = get2()) && cp+3 < buf+len; ) { - if (c < 0x80) - *cp++ = c; - else if (c < 0x800) { - *cp++ = 0xc0 + (c >> 6); - *cp++ = 0x80 + (c & 0x3f); - } else { - *cp++ = 0xe0 + (c >> 12); - *cp++ = 0x80 + (c >> 6 & 0x3f); - *cp++ = 0x80 + (c & 0x3f); - } - } - *cp = 0; -} - -ushort sget2 (uchar *s) -{ - return s[0] + (s[1]<<8); -} - -int sget4 (uchar *s) -{ - return s[0] + (s[1]<<8) + (s[2]<<16) + (s[3]<<24); -} - -void parse_foveon() -{ - int entries, img=0, off, len, tag, save, i, j, k, pent, poff[256][2]; - char name[128], value[128], camf[0x20000], *pos, *cp, *dp; - unsigned val, key, type, num, ndim, dim[3]; - - order = 0x4949; /* Little-endian */ - fseek (ifp, -4, SEEK_END); - fseek (ifp, get4(), SEEK_SET); - if (get4() != 0x64434553) { /* SECd */ - printf ("Bad Section identifier at %6x\n", (int)ftell(ifp)-4); - return; - } - get4(); - entries = get4(); - while (entries--) { - off = get4(); - len = get4(); - tag = get4(); - save = ftell(ifp); - fseek (ifp, off, SEEK_SET); - if (get4() != (0x20434553 | (tag << 24))) { - printf ("Bad Section identifier at %6x\n", off); - goto next; - } - val = get4(); - switch (tag) { - case 0x32414d49: /* IMA2 */ - case 0x47414d49: /* IMAG */ - if (++img == 2) { /* second image */ - thumb_offset = off; - thumb_length = 1; - } - printf ("type %d, " , get4()); - printf ("format %2d, " , get4()); - printf ("columns %4d, " , get4()); - printf ("rows %4d, " , get4()); - printf ("rowsize %d\n" , get4()); - break; - case 0x464d4143: /* CAMF */ - printf ("type %d, ", get4()); - get4(); - for (i=0; i < 4; i++) - putchar(fgetc(ifp)); - val = get4(); - printf (" version %d.%d:\n",val >> 16, val & 0xffff); - key = get4(); - if ((len -= 28) > 0x20000) - len = 0x20000; - fread (camf, 1, len, ifp); - for (i=0; i < len; i++) { - key = (key * 1597 + 51749) % 244944; - val = key * (INT64) 301593171 >> 24; - camf[i] ^= ((((key << 8) - val) >> 1) + val) >> 17; - } - for (pos=camf; (unsigned) (pos-camf) < len; pos += sget4(pos+8)) { - if (strncmp (pos, "CMb", 3)) { - printf("Bad CAMF tag \"%.4s\"\n", pos); - break; - } - val = sget4(pos+4); - printf (" %4.4s version %d.%d: ", pos, val >> 16, val & 0xffff); - switch (pos[3]) { - case 'M': - cp = pos + sget4(pos+16); - type = sget4(cp); - ndim = sget4(cp+4); - dim[0] = dim[1] = dim[2] = 1; - printf ("%d-dimensonal array %s of type %d:\n Key: (", - ndim, pos+sget4(pos+12), sget4(cp)); - dp = pos + sget4(cp+8); - for (i=ndim; i--; ) { - cp += 12; - dim[i] = sget4(cp); - printf ("%s %d%s", pos+sget4(cp+4), dim[i], i ? ", ":")\n"); - } - for (i=0; i < dim[2]; i++) { - for (j=0; j < dim[1]; j++) { - printf (" "); - for (k=0; k < dim[0]; k++) - switch (type) { - case 0: - case 6: - printf ("%7d", sget2(dp)); - dp += 2; - break; - case 1: - case 2: - printf (" %d", sget4(dp)); - dp += 4; - break; - case 3: { - union { int ival; float fval; } __t; - __t.ival = sget4(dp); - printf (" %9f", __t.fval); - dp += 4; - } - } - printf ("\n"); - } - printf ("\n"); - } - break; - case 'P': - val = sget4(pos+16); - num = sget4(pos+val); - printf ("%s, %d parameters:\n", pos+sget4(pos+12), num); - cp = pos+val+8 + num*8; - for (i=0; i < num; i++) { - val += 8; - printf (" %s = %s\n", cp+sget4(pos+val), cp+sget4(pos+val+4)); - } - break; - case 'T': - cp = pos + sget4(pos+16); - printf ("%s = %.*s\n", pos+sget4(pos+12), sget4(cp), cp+4); - break; - default: - printf ("\n"); - } - } - break; - case 0x504f5250: /* PROP */ - printf ("entries %d, ", pent=get4()); - printf ("charset %d, ", get4()); - get4(); - printf ("nchars %d\n", get4()); - off += pent*8 + 24; - if (pent > 256) pent=256; - for (i=0; i < pent*2; i++) - poff[0][i] = off + get4()*2; - for (i=0; i < pent; i++) { - get_utf8 (poff[i][0], name, 128); - get_utf8 (poff[i][1], value, 128); - printf (" %s = %s\n", name, value); - if (!strcmp (name,"CAMMANUF")) - strncpy (make, value, sizeof(make)); - if (!strcmp (name,"CAMMODEL")) - strncpy (model, value, sizeof(value)); - } - } -next: - fseek (ifp, save, SEEK_SET); - } -} - -void foveon_tree (unsigned huff[1024], unsigned code) -{ - struct decode *cur; - int i, len; - - cur = free_decode++; - if (code) { - for (i=0; i < 1024; i++) - if (huff[i] == code) { - cur->leaf = i; - return; - } - } - if ((len = code >> 27) > 26) return; - code = (len+1) << 27 | (code & 0x3ffffff) << 1; - - cur->branch[0] = free_decode; - foveon_tree (huff, code); - cur->branch[1] = free_decode; - foveon_tree (huff, code+1); -} - -void foveon_decode (FILE *tfp) -{ - int bwide, row, col, bit=-1, c, i; - char *buf; - struct decode *dindex; - short pred[3]; - unsigned huff[1024], bitbuf=0; - - fseek (ifp, thumb_offset+16, SEEK_SET); - width = get4(); - height = get4(); - bwide = get4(); - fprintf (tfp, "P6\n%d %d\n255\n", width, height); - if (bwide > 0) { - buf = malloc(bwide); - for (row=0; row < height; row++) { - fread (buf, 1, bwide, ifp); - fwrite (buf, 3, width, tfp); - } - free (buf); - return; - } - for (i=0; i < 256; i++) - huff[i] = get4(); - memset (first_decode, 0, sizeof first_decode); - free_decode = first_decode; - foveon_tree (huff, 0); - - for (row=0; row < height; row++) { - memset (pred, 0, sizeof pred); - if (!bit) get4(); - for (col=bit=0; col < width; col++) { - for (c=0; c < 3; c++) { - for (dindex=first_decode; dindex->branch[0]; ) { - if ((bit = (bit-1) & 31) == 31) - for (i=0; i < 4; i++) - bitbuf = (bitbuf << 8) + fgetc(ifp); - dindex = dindex->branch[bitbuf >> bit & 1]; - } - pred[c] += dindex->leaf; - fputc (pred[c], tfp); - } - } - } -} - -void kodak_yuv_decode (FILE *tfp) -{ - uchar c, blen[384]; - unsigned row, col, len, bits=0; - INT64 bitbuf=0; - int i, li=0, si, diff, six[6], y[4], cb=0, cr=0, rgb[3]; - ushort *out, *op; - - fseek (ifp, thumb_offset, SEEK_SET); - width = (width+1) & -2; - height = (height+1) & -2; - fprintf (tfp, "P6\n%d %d\n65535\n", width, height); - out = malloc (width * 12); - if (!out) { - fprintf (stderr, "kodak_yuv_decode() malloc failed!\n"); - exit(1); - } - - for (row=0; row < height; row+=2) { - for (col=0; col < width; col+=2) { - if ((col & 127) == 0) { - len = (width - col + 1) * 3 & -4; - if (len > 384) len = 384; - for (i=0; i < len; ) { - c = fgetc(ifp); - blen[i++] = c & 15; - blen[i++] = c >> 4; - } - li = bitbuf = bits = y[1] = y[3] = cb = cr = 0; - if (len % 8 == 4) { - bitbuf = fgetc(ifp) << 8; - bitbuf += fgetc(ifp); - bits = 16; - } - } - for (si=0; si < 6; si++) { - len = blen[li++]; - if (bits < len) { - for (i=0; i < 32; i+=8) - bitbuf += (INT64) fgetc(ifp) << (bits+(i^8)); - bits += 32; - } - diff = bitbuf & (0xffff >> (16-len)); - bitbuf >>= len; - bits -= len; - if ((diff & (1 << (len-1))) == 0) - diff -= (1 << len) - 1; - six[si] = diff; - } - y[0] = six[0] + y[1]; - y[1] = six[1] + y[0]; - y[2] = six[2] + y[3]; - y[3] = six[3] + y[2]; - cb += six[4]; - cr += six[5]; - for (i=0; i < 4; i++) { - op = out + ((i >> 1)*width + col+(i & 1)) * 3; - rgb[0] = y[i] + 1.40200/2 * cr; - rgb[1] = y[i] - 0.34414/2 * cb - 0.71414/2 * cr; - rgb[2] = y[i] + 1.77200/2 * cb; - for (c=0; c < 3; c++) - if (rgb[c] > 0) op[c] = htons(rgb[c]); - } - } - fwrite (out, sizeof *out, width*6, tfp); - } - free(out); -} - -void parse_phase_one (int base) -{ - unsigned entries, tag, type, len, data, save; - char str[256]; - - fseek (ifp, base + 8, SEEK_SET); - fseek (ifp, base + get4(), SEEK_SET); - entries = get4(); - get4(); - while (entries--) { - tag = get4(); - type = get4(); - len = get4(); - data = get4(); - save = ftell(ifp); - printf ("Phase One tag=0x%x, type=%d, len=%2d, data = 0x%x\n", - tag, type, len, data); - if (type == 1 && len < 256) { - fseek (ifp, base + data, SEEK_SET); - fread (str, 256, 1, ifp); - puts (str); - } - if (tag == 0x110) { - thumb_offset = data + base; - thumb_length = len; - } - fseek (ifp, save, SEEK_SET); - } - strcpy (make, "Phase One"); - strcpy (model, "unknown"); -} - -void parse_jpeg (int offset) -{ - int len, save, hlen; - - fseek (ifp, offset, SEEK_SET); - if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) return; - - while (fgetc(ifp) == 0xff && fgetc(ifp) >> 4 != 0xd) { - order = 0x4d4d; - len = get2() - 2; - save = ftell(ifp); - order = get2(); - hlen = get4(); - if (get4() == 0x48454150) /* "HEAP" */ - parse_ciff (save+hlen, len-hlen, 0); - parse_tiff (save+6); - fseek (ifp, save+len, SEEK_SET); - } -} - -char *raw_memmem (char *haystack, size_t haystacklen, - char *needle, size_t needlelen) -{ - char *c; - for (c = haystack; c <= haystack + haystacklen - needlelen; c++) - if (!memcmp (c, needle, needlelen)) - return c; - return NULL; -} - -/* - Identify which camera created this file, and set global variables - accordingly. - Return nonzero if the file cannot be decoded or no thumbnail is found - */ -int identify(FILE* tfp) -{ - char head[32], *thumb, *rgb, *cp; - unsigned hlen, fsize, toff, tlen, lsize, i; - - make[0] = model[0] = model2[0] = is_dng = 0; - thumb_head[0] = thumb_offset = thumb_length = thumb_layers = 0; - order = get2(); - hlen = get4(); - fseek (ifp, 0, SEEK_SET); - fread (head, 1, 32, ifp); - fseek (ifp, 0, SEEK_END); - fsize = ftell(ifp); - if ((cp = raw_memmem (head, 32, "MMMMRawT", 8)) || - (cp = raw_memmem (head, 32, "IIIITwaR", 8))) - parse_phase_one (cp - head); - else if (order == 0x4949 || order == 0x4d4d) { - if (!memcmp(head+6,"HEAPCCDR",8)) { - parse_ciff (hlen, fsize - hlen, 0); - fseek (ifp, hlen, SEEK_SET); - } else - parse_tiff (0); - } else if (!memcmp (head, "\0MRM", 4)) - parse_minolta(); - else if (!memcmp (head, "\xff\xd8\xff\xe1", 4) && - !memcmp (head+6, "Exif", 4)) { - parse_tiff (12); - thumb_length = 0; - } else if (!memcmp (head, "FUJIFILM", 8)) { - fseek (ifp, 84, SEEK_SET); - toff = get4(); - tlen = get4(); - thumb_offset = toff; - thumb_length = tlen; - } else if (!memcmp (head, "DSC-Image", 9)) - parse_rollei(); - else if (!memcmp (head, "FOVb", 4)) - parse_foveon(); - fseek (ifp, 8, SEEK_SET); - parse_mos(0); - fseek (ifp, 3472, SEEK_SET); - parse_mos(0); - parse_jpeg(0); - - if (!thumb_length) { - fprintf (stderr, "Thumbnail image not found\n"); - return -1; - } - - if (is_dng) goto dng_skip; - if (!strncmp(model,"DCS Pro",7)) { - kodak_yuv_decode (tfp); - goto done; - } - if (!strcmp(make,"Rollei")) { - rollei_decode (tfp); - goto done; - } - if (!strcmp(make,"SIGMA")) { - foveon_decode (tfp); - goto done; - } -dng_skip: - thumb = (char *) malloc(thumb_length); - if (!thumb) { - fprintf (stderr, "Cannot allocate %d bytes!!\n", thumb_length); - exit(1); - } - fseek (ifp, thumb_offset, SEEK_SET); - fread (thumb, 1, thumb_length, ifp); - if (thumb_layers && !is_dng) { - rgb = (char *) malloc(thumb_length); - if (!rgb) { - fprintf (stderr, "Cannot allocate %d bytes!!\n", thumb_length); - return -1; - } - lsize = thumb_length/3; - for (i=0; i < thumb_length; i++) - rgb[(i%lsize)*3 + i/lsize] = thumb[i]; - free(thumb); - thumb = rgb; - } - fputs (thumb_head, tfp); - fwrite(thumb, 1, thumb_length, tfp); - free (thumb); -done: - fprintf (stderr, "Thumbnail image written, make=%s, model=%s\n",&(make[0]),&(model[0])); - return 0; -} - -int extract_thumbnail( FILE* input, FILE* output, int* orientation ) -{ - /* Coffin's code has different meaning for orientation - values than TIFF, so we map them to TIFF values */ - static const int flip_map[] = { 0,1,3,2,4,7,5,6 }; - int rc; - ifp = input; - rc = identify(output); - switch ((flip+3600) % 360) { - case 270: flip = 5; break; - case 180: flip = 3; break; - case 90: flip = 6; - } - if( orientation ) *orientation = flip_map[flip%7]; - return rc; -} |