--- ufraw-0.15/dcraw.h 2008-12-16 06:38:05.000000000 +0100 +++ ufraw/dcraw.h 2009-08-30 17:55:45.000000000 +0200 @@ -1,7 +1,7 @@ /* dcraw.h - Dave Coffin's raw photo decoder - header for C++ adaptation - Copyright 1997-2008 by Dave Coffin, dcoffin a cybercom o net - Copyright 2004-2008 by Udi Fuchs, udifuchs a gmail o com + Copyright 1997-2009 by Dave Coffin, dcoffin a cybercom o net + Copyright 2004-2009 by Udi Fuchs, udifuchs a gmail o com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,9 +36,10 @@ class DCRaw { public: /* All dcraw's global variables are members of this class. */ -FILE *ifp; +FILE *ifp, *ofp; short order; -char *ifname, *ifname_display, *meta_data; +/*const*/ char *ifname, *ifname_display; +char *meta_data; char cdesc[5], desc[512], make[64], model[64], model2[64], artist[64]; float flash_used, canon_ev, iso_speed, shutter, aperture, focal_len; time_t timestamp; @@ -48,14 +49,14 @@ unsigned thumb_length, meta_length, profile_length; unsigned thumb_misc, *oprof, fuji_layout, shot_select, multi_out; unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress; -unsigned black, maximum, mix_green, raw_color, use_gamma, zero_is_bad; +unsigned black, maximum, mix_green, raw_color, zero_is_bad; unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error; unsigned tile_width, tile_length, gpsdata[32], load_flags; ushort raw_height, raw_width, height, width, top_margin, left_margin; ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height; int flip, tiff_flip, colors; -double pixel_aspect, aber[4]; -ushort (*image)[4], white[8][8], curve[0x4001], cr2_slice[3], sraw_mul[4]; +double pixel_aspect, aber[4], gamm[6]; +ushort (*image)[4], white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4]; float bright, user_mul[4], threshold; int half_size, four_color_rgb, document_mode, highlight; int verbose, use_auto_wb, use_camera_wb, use_camera_matrix; @@ -64,7 +65,7 @@ unsigned greybox[4]; float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4]; int histogram[4][0x2000]; -void (DCRaw::*write_thumb)(FILE *), (DCRaw::*write_fun)(FILE *); +void (DCRaw::*write_thumb)(), (DCRaw::*write_fun)(); void (DCRaw::*load_raw)(), (DCRaw::*thumb_load_raw)(); jmp_buf failure; @@ -73,11 +74,11 @@ int leaf; } first_decode[2048], *second_decode, *free_decode; -struct { +struct tiff_ifd { int width, height, bps, comp, phint, offset, flip, samples, bytes; } tiff_ifd[10]; -struct { +struct ph1 { int format, key_off, black, black_off, split_col, tag_21a; float tag_210; } ph1; @@ -104,7 +105,7 @@ // dcraw only calls fscanf for single variables int fscanf(FILE *stream, const char *format, void *ptr); // calling with more variables would triger a link error -int fscanf(FILE *stream, const char *format, void *ptr1, void *ptr2, ...); +//int fscanf(FILE *stream, const char *format, void *ptr1, void *ptr2, ...); /* Initialization of the variables is done here */ DCRaw(); @@ -112,8 +113,8 @@ void dcraw_message(int code, const char *format, ...); /* All dcraw functions with the CLASS prefix are members of this class. */ int fc (int row, int col); -void derror(); void merror (void *ptr, const char *where); +void derror(); ushort sget2 (uchar *s); ushort get2(); unsigned sget4 (uchar *s); @@ -122,7 +123,7 @@ float int_to_float (int i); double getreal (int type); void read_shorts (ushort *pixel, unsigned count); -void canon_black (double dark[2]); +void canon_black (double dark[2], int nblack); void canon_600_fixed_wb (int temp); int canon_600_color (int ratio[2], int mar); void canon_600_auto_wb(); @@ -130,63 +131,55 @@ void canon_600_load_raw(); void remove_zeroes(); int canon_s2is(); -void canon_a5_load_raw(); -unsigned getbits (int nbits); -void init_decoder(); -uchar * make_decoder (const uchar *source, int level); -void crw_init_tables (unsigned table); +unsigned getbithuff (int nbits, ushort *huff); +ushort * make_decoder_ref (const uchar **source); +ushort * make_decoder (const uchar *source); +void crw_init_tables (unsigned table, ushort *huff[2]); int canon_has_lowbits(); void canon_compressed_load_raw(); int ljpeg_start (struct jhead *jh, int info_only); -int ljpeg_diff (struct decode *dindex); +void ljpeg_end (struct jhead *jh); +int ljpeg_diff (ushort *huff); ushort * ljpeg_row (int jrow, struct jhead *jh); void lossless_jpeg_load_raw(); void canon_sraw_load_raw(); void adobe_copy_pixel (int row, int col, ushort **rp); void adobe_dng_load_raw_lj(); void adobe_dng_load_raw_nc(); -void pentax_k10_load_raw(); +void pentax_load_raw(); void nikon_compressed_load_raw(); int nikon_is_compressed(); int nikon_e995(); int nikon_e2100(); void nikon_3700(); int minolta_z2(); -void nikon_e900_load_raw(); void fuji_load_raw(); -void jpeg_thumb (FILE *tfp); -void ppm_thumb (FILE *tfp); -void layer_thumb (FILE *tfp); -void rollei_thumb (FILE *tfp); +void ppm_thumb (); +void layer_thumb (); +void rollei_thumb (); void rollei_load_raw(); int bayer (unsigned row, unsigned col); void phase_one_flat_field (int is_float, int nc); void phase_one_correct(); void phase_one_load_raw(); -unsigned ph1_bits (int nbits); +unsigned ph1_bithuff (int nbits, ushort *huff); void phase_one_load_raw_c(); void hasselblad_load_raw(); void leaf_hdr_load_raw(); void sinar_4shot_load_raw(); void imacon_full_load_raw(); -void packed_12_load_raw(); +void packed_load_raw(); void unpacked_load_raw(); void nokia_load_raw(); unsigned pana_bits (int nbits); void panasonic_load_raw(); -void olympus_e300_load_raw(); -void olympus_e410_load_raw(); -void olympus_cseries_load_raw(); +void olympus_load_raw(); void minolta_rd175_load_raw(); -void eight_bit_load_raw(); -void casio_qv5700_load_raw(); void quicktake_100_load_raw(); -const int * make_decoder_int (const int *source, int level); -int radc_token (int tree); void kodak_radc_load_raw(); void kodak_jpeg_load_raw(); void kodak_dc120_load_raw(); -void kodak_easy_load_raw(); +void eight_bit_load_raw(); void kodak_yrgb_load_raw(); void kodak_262_load_raw(); int kodak_65000_decode (short *out, int bsize); @@ -204,7 +197,7 @@ void fill_holes (int holes); void smal_v9_load_raw(); void foveon_decoder (unsigned size, unsigned code); -void foveon_thumb (FILE *tfp); +void foveon_thumb (); void foveon_load_camf(); void foveon_load_raw(); const char * foveon_camf_param (const char *block, const char *param); @@ -216,8 +209,9 @@ (short **curvep, float dq[3], float div[3], float filt); int foveon_apply_curve (short *curve, int i); void foveon_interpolate(); -void bad_pixels(char *fname); +void bad_pixels(const char *fname); void subtract(const char *fname); +void gamma_curve (double pwr, double ts, int mode, int imax); void pseudoinverse (double (*in)[3], double (*out)[3], int size); void cam_xyz_coeff (double cam_xyz[4][3]); void colorcheck(); @@ -243,8 +237,8 @@ void romm_coeff (float romm_cam[3][3]); void parse_mos (int offset); void linear_table (unsigned len); -int parse_tiff_ifd (int base); void parse_kodak_ifd (int base); +int parse_tiff_ifd (int base); void parse_tiff (int base); void parse_minolta (int base); void parse_external_jpeg(); @@ -263,19 +257,19 @@ void adobe_coeff (const char *make, const char *model); void simple_coeff (int index); short guess_byte_order (int words); +float find_green (int bps, int bite, int off0, int off1); void identify(); +#ifndef NO_LCMS void apply_profile (const char *input, const char *output); +#endif void convert_to_rgb(); void fuji_rotate(); void stretch(); int flip_index (int row, int col); -void gamma_lut (uchar lut[0x10000]); void tiff_set (ushort *ntag, ushort tag, ushort type, int count, int val); void tiff_head (struct tiff_hdr *th, int full); -void write_ppm_tiff (FILE *ofp); -void write_ppm (FILE *ofp); -void write_ppm16 (FILE *ofp); -void write_psd (FILE *ofp); +void jpeg_thumb (); +void write_ppm_tiff (); int main (int argc, const char **argv); }; --- ufraw-0.15/dcraw.cc 2008-12-23 08:19:41.000000000 +0100 +++ ufraw/dcraw.cc 2009-09-27 16:05:46.000000000 +0200 @@ -1,7 +1,7 @@ /* dcraw.cc - Dave Coffin's raw photo decoder - C++ adaptation - Copyright 1997-2008 by Dave Coffin, dcoffin a cybercom o net - Copyright 2004-2008 by Udi Fuchs, udifuchs a gmail o com + Copyright 1997-2009 by Dave Coffin, dcoffin a cybercom o net + Copyright 2004-2009 by Udi Fuchs, udifuchs a gmail o com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -11,19 +11,20 @@ This is a adaptation of Dave Coffin's original dcraw.c to C++. It can work as either a command-line tool or called by other programs. - $Revision: 1.409 $ - $Date: 2008/12/11 06:56:09 $ + $Revision: 1.431 $ + $Date: 2009/09/22 16:06:07 $ */ #ifdef HAVE_CONFIG_H /*For UFRaw config system - NKBJ*/ #include "config.h" #endif -#define DCRAW_VERSION "8.89" +#define DCRAW_VERSION "8.98" -//#define _GNU_SOURCE +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif #define _USE_MATH_DEFINES - #include #include #include @@ -58,7 +59,7 @@ #include /*For _(String) definition - NKBJ*/ #endif /*fseeko() is handled by the configuration system - NKBJ*/ -//#if defined(DJGPP) || defined(__MINGW32__) +//#ifdef DJGPP //#define fseeko fseek //#define ftello ftell //#else @@ -122,6 +123,7 @@ CLASS DCRaw() { shot_select=0, multi_out=0, aber[0] = aber[1] = aber[2] = aber[3] = 1; +gamm[0] = 0.45, gamm[1] = 4.5, gamm[2] = gamm[3] = gamm[4] = gamm[5] = 0; bright=1, user_mul[0] = user_mul[1] = user_mul[2] = user_mul[3] = 0; threshold=0, half_size=0, four_color_rgb=0, document_mode=0, highlight=0; verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=-1; @@ -328,7 +330,7 @@ dcraw_message (DCRAW_WARNING,_("Corrupt data near 0x%lx\n"), ftell(ifp)); #endif } - data_error = 1; + data_error++; } ushort CLASS sget2 (uchar *s) @@ -405,13 +407,13 @@ swab ((const char *)pixel, (char *)pixel, count*2); /*mingw support UF*/ } -void CLASS canon_black (double dark[2]) +void CLASS canon_black (double dark[2], int nblack) { int c, diff, row, col; - if (raw_width < width+4) return; - FORC(2) dark[c] /= (raw_width-width-2) * height >> 1; - if ((diff = (int)(dark[0] - dark[1]))) + if (!nblack) return; + FORC(2) dark[c] /= nblack >> 1; + if ((diff = dark[0] - dark[1])) for (row=0; row < height; row++) for (col=1; col < width; col+=2) BAYER(row,col) += diff; @@ -604,34 +606,11 @@ return 0; } -void CLASS canon_a5_load_raw() -{ - ushort data[2565], *dp, pixel; - int vbits=0, buf=0, row, col, bc=0; - - order = 0x4949; - for (row=-top_margin; row < raw_height-top_margin; row++) { - read_shorts (dp=data, raw_width * 10 / 16); - for (col=-left_margin; col < raw_width-left_margin; col++) { - if ((vbits -= 10) < 0) - buf = (vbits += 16, (buf << 16) + *dp++); - pixel = buf >> vbits & 0x3ff; - if ((unsigned) row < height && (unsigned) col < width) - BAYER(row,col) = pixel; - else if (col > 1-left_margin && col != width) - black += (bc++,pixel); - } - } - if (bc) black /= bc; - maximum = 0x3ff; - if (raw_width > 1600) remove_zeroes(); -} - /* getbits(-1) initializes the buffer getbits(n) where 0 <= n <= 25 returns an n-bit integer */ -unsigned CLASS getbits (int nbits) +unsigned CLASS getbithuff (int nbits, ushort *huff) { // TODO: The following static variables are not thread-safe static unsigned bitbuf=0; @@ -640,22 +619,24 @@ if (nbits == -1) return bitbuf = vbits = reset = 0; - if (nbits == 0 || reset) return 0; - while (vbits < nbits) { - if ((c = fgetc(ifp)) == EOF) derror(); - if ((reset = zero_after_ff && c == 0xff && fgetc(ifp))) return 0; + if (nbits == 0 || vbits < 0) return 0; + while (!reset && vbits < nbits && (c = fgetc(ifp)) != EOF && + !(reset = zero_after_ff && c == 0xff && fgetc(ifp))) { bitbuf = (bitbuf << 8) + (uchar) c; vbits += 8; } - vbits -= nbits; - return bitbuf << (32-nbits-vbits) >> (32-nbits); + c = bitbuf << (32-vbits) >> (32-nbits); + if (huff) { + vbits -= huff[c] >> 8; + c = (uchar) huff[c]; + } else + vbits -= nbits; + if (vbits < 0) derror(); + return c; } -void CLASS init_decoder() -{ - memset (first_decode, 0, sizeof first_decode); - free_decode = first_decode; -} +#define getbits(n) getbithuff(n,0) +#define gethuff(h) getbithuff(*h,h+1) /* Construct a decode tree according the specification in *source. @@ -683,34 +664,31 @@ 1111110 0x0b 1111111 0xff */ -uchar * CLASS make_decoder (const uchar *source, int level) +ushort * CLASS make_decoder_ref (const uchar **source) { - struct decode *cur; - // TODO: The following static variable is not thread-safe - static int leaf; - int i, next; + int max, len, h, i, j; + const uchar *count; + ushort *huff; - if (level==0) leaf=0; - cur = free_decode++; - if (free_decode > first_decode+2048) { - dcraw_message (DCRAW_ERROR,_("%s: decoder table overflow\n"), ifname_display); - longjmp (failure, 2); - } - for (i=next=0; i <= leaf && next < 16; ) - i += source[next++]; - if (i > leaf) { - if (level < next) { - cur->branch[0] = free_decode; - make_decoder (source, level+1); - cur->branch[1] = free_decode; - make_decoder (source, level+1); - } else - cur->leaf = source[16 + leaf++]; - } - return (uchar *) source + 16 + leaf; + count = (*source += 16) - 17; + for (max=16; max && !count[max]; max--) {}; + huff = (ushort *) calloc (1 + (1 << max), sizeof *huff); + merror (huff, "make_decoder()"); + huff[0] = max; + for (h=len=1; len <= max; len++) + for (i=0; i < count[len]; i++, ++*source) + for (j=0; j < 1 << (max-len); j++) + if (h <= 1 << max) + huff[h++] = len << 8 | **source; + return huff; } -void CLASS crw_init_tables (unsigned table) +ushort * CLASS make_decoder (const uchar *source) +{ + return make_decoder_ref (&source); +} + +void CLASS crw_init_tables (unsigned table, ushort *huff[2]) { static const uchar first_tree[3][29] = { { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, @@ -768,10 +746,8 @@ 0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff } }; if (table > 2) table = 2; - init_decoder(); - make_decoder ( first_tree[table], 0); - second_decode = free_decode; - make_decoder (second_tree[table], 0); + huff[0] = make_decoder ( first_tree[table]); + huff[1] = make_decoder (second_tree[table]); } /* @@ -797,15 +773,13 @@ void CLASS canon_compressed_load_raw() { - ushort *pixel, *prow; - int nblocks, lowbits, i, row, r, col, save, val; + ushort *pixel, *prow, *huff[2]; + int nblocks, lowbits, i, c, row, r, col, save, val, nblack=0; unsigned irow, icol; - struct decode *decode, *dindex; int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2]; double dark[2] = { 0,0 }; - uchar c; - crw_init_tables (tiff_compress); + crw_init_tables (tiff_compress, huff); pixel = (ushort *) calloc (raw_width*8, sizeof *pixel); merror (pixel, "canon_compressed_load_raw()"); lowbits = canon_has_lowbits(); @@ -817,12 +791,8 @@ nblocks = MIN (8, raw_height-row) * raw_width >> 6; for (block=0; block < nblocks; block++) { memset (diffbuf, 0, sizeof diffbuf); - decode = first_decode; for (i=0; i < 64; i++ ) { - for (dindex=decode; dindex->branch[0]; ) - dindex = dindex->branch[getbits(1)]; - leaf = dindex->leaf; - decode = second_decode; + leaf = gethuff(huff[i > 0]); if (leaf == 0 && i) break; if (leaf == 0xff) continue; i += leaf >> 4; @@ -862,13 +832,15 @@ icol = col - left_margin; if (icol < width) BAYER(irow,icol) = pixel[r*raw_width+col]; - else if (col > 1) - dark[icol & 1] += pixel[r*raw_width+col]; + else if (col > 1 && (unsigned) (col-left_margin+2) > + (unsigned) (width+3)) + dark[icol & 1] += (nblack++,pixel[r*raw_width+col]); } } } free (pixel); - canon_black (dark); + FORC(2) free (huff[c]); + canon_black (dark, nblack); } /* @@ -877,18 +849,16 @@ */ struct jhead { int bits, high, wide, clrs, sraw, psv, restart, vpred[6]; - struct CLASS decode *huff[6]; - ushort *row; + ushort *huff[6], *free[4], *row; }; int CLASS ljpeg_start (struct jhead *jh, int info_only) { int c, tag, len; - uchar data[0x10000], *dp; + uchar data[0x10000]; + const uchar *dp; - init_decoder(); memset (jh, 0, sizeof *jh); - FORC(6) jh->huff[c] = free_decode; jh->restart = INT_MAX; fread (data, 2, 1, ifp); if (data[1] != 0xd8) return 0; @@ -910,10 +880,8 @@ break; case 0xffc4: if (info_only) break; - for (dp = data; dp < data+len && *dp < 4; ) { - jh->huff[*dp] = free_decode; - dp = make_decoder (++dp, 0); - } + for (dp = data; dp < data+len && (c = *dp++) < 4; ) + jh->free[c] = jh->huff[c] = make_decoder_ref (&dp); break; case 0xffda: jh->psv = data[1+data[0]*2]; @@ -924,6 +892,7 @@ } } while (tag != 0xffda); if (info_only) return 1; + FORC(5) if (!jh->huff[c+1]) jh->huff[c+1] = jh->huff[c]; if (jh->sraw) { FORC(4) jh->huff[2+c] = jh->huff[1]; FORC(jh->sraw) jh->huff[1+c] = jh->huff[0]; @@ -933,13 +902,18 @@ return zero_after_ff = 1; } -int CLASS ljpeg_diff (struct decode *dindex) +void CLASS ljpeg_end (struct jhead *jh) +{ + int c; + FORC4 if (jh->free[c]) free (jh->free[c]); + free (jh->row); +} + +int CLASS ljpeg_diff (ushort *huff) { int len, diff; - while (dindex->branch[0]) - dindex = dindex->branch[getbits(1)]; - len = dindex->leaf; + len = gethuff(huff); if (len == 16 && (!dng_version || dng_version >= 0x1010000)) return -32768; diff = getbits(len); @@ -955,9 +929,11 @@ if (jrow * jh->wide % jh->restart == 0) { FORC(6) jh->vpred[c] = 1 << (jh->bits-1); - if (jrow) + if (jrow) { + fseek (ifp, -2, SEEK_CUR); do mark = (mark << 8) + (c = fgetc(ifp)); while (c != EOF && mark >> 4 != 0xffd); + } getbits(-1); } FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1); @@ -987,7 +963,7 @@ void CLASS lossless_jpeg_load_raw() { - int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0; + int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0, nblack=0; double dark[2] = { 0,0 }; struct jhead jh; int min=INT_MAX; @@ -1017,15 +993,16 @@ if ((unsigned) (col-left_margin) < width) { BAYER(row-top_margin,col-left_margin) = val; if (min > val) min = val; - } else if (col > 1) - dark[(col-left_margin) & 1] += val; + } else if (col > 1 && (unsigned) (col-left_margin+2) > + (unsigned) (width+3)) + dark[(col-left_margin) & 1] += (nblack++,val); } if (++col >= raw_width) col = (row++,0); } } - free (jh.row); - canon_black (dark); + ljpeg_end (&jh); + canon_black (dark, nblack); if (!strcasecmp(make,"KODAK")) black = min; } @@ -1035,6 +1012,8 @@ struct jhead jh; short *rp=0, (*ip)[4]; int jwide, slice, scol, ecol, row, col, jrow=0, jcol=0, pix[3], c; + int v[3]={0,0,0}, ver, hue; + char *cp; if (!ljpeg_start (&jh, 0)) return; jwide = (jh.wide >>= 1) * jh.clrs; @@ -1056,6 +1035,12 @@ } } } + for (cp=model2; *cp && !isdigit(*cp); cp++) {}; + sscanf (cp, "%d.%d.%d", v, v+1, v+2); + ver = (v[0]*1000 + v[1])*1000 + v[2]; + hue = (jh.sraw+1) << 2; + if (unique_id == 0x80000218 && ver > 1000006 && ver < 3000000) + hue = jh.sraw << 1; ip = (short (*)[4]) image; rp = ip[0]; for (row=0; row < height; row++, ip+=width) { @@ -1077,15 +1062,15 @@ pix[2] = rp[0] + rp[1] - 512; pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12) - 512; } else { - rp[1] += jh.sraw+1; - rp[2] += jh.sraw+1; - pix[0] = rp[0] + (( 200*rp[1] + 22929*rp[2]) >> 12); - pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 12); - pix[2] = rp[0] + ((29040*rp[1] - 101*rp[2]) >> 12); + rp[1] = (rp[1] << 2) + hue; + rp[2] = (rp[2] << 2) + hue; + pix[0] = rp[0] + (( 200*rp[1] + 22929*rp[2]) >> 14); + pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 14); + pix[2] = rp[0] + ((29040*rp[1] - 101*rp[2]) >> 14); } FORC3 rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10); } - free (jh.row); + ljpeg_end (&jh); maximum = 0x3fff; } @@ -1138,7 +1123,7 @@ fseek (ifp, save+4, SEEK_SET); if ((tcol += tile_width) >= raw_width) trow += tile_length + (tcol = 0); - free (jh.row); + ljpeg_end (&jh); } } @@ -1163,24 +1148,28 @@ free (pixel); } -void CLASS pentax_k10_load_raw() +void CLASS pentax_load_raw() { - static const uchar pentax_tree[] = - { 0,2,3,1,1,1,1,1,1,2,0,0,0,0,0,0, - 3,4,2,5,1,6,0,7,8,9,10,11,12 }; - int row, col, diff; + ushort bit[2][13], huff[4097]; + int row, col, diff, c, i; ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2]; - init_decoder(); - make_decoder (pentax_tree, 0); + fseek (ifp, meta_offset, SEEK_SET); + FORC(13) bit[0][c] = get2(); + FORC(13) bit[1][c] = fgetc(ifp); + FORC(13) + for (i=bit[0][c]; i <= ((bit[0][c]+(4096 >> bit[1][c])-1) & 4095); ) + huff[++i] = bit[1][c] << 8 | c; + huff[0] = 12; + fseek (ifp, data_offset, SEEK_SET); getbits(-1); - for (row=0; row < height; row++) + for (row=0; row < raw_height; row++) for (col=0; col < raw_width; col++) { - diff = ljpeg_diff (first_decode); + diff = ljpeg_diff (huff); if (col < 2) hpred[col] = vpred[row & 1][col] += diff; else hpred[col & 1] += diff; - if (col < width) - BAYER(row,col) = hpred[col & 1]; + if ((unsigned) (row-top_margin) < height && col < width) + BAYER(row-top_margin,col) = hpred[col & 1]; if (hpred[col & 1] >> 12) derror(); } } @@ -1200,17 +1189,16 @@ 8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 }, { 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0, /* 14-bit lossless */ 7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } }; - struct decode *dindex; - ushort ver0, ver1, vpred[2][2], hpred[2], csize; - int i, min, max, step=0, huff=0, split=0, row, col, len, shl, diff; + ushort *huff, ver0, ver1, vpred[2][2], hpred[2], csize; + int i, min, max, step=0, tree=0, split=0, row, col, len, shl, diff; fseek (ifp, meta_offset, SEEK_SET); ver0 = fgetc(ifp); ver1 = fgetc(ifp); if (ver0 == 0x49 || ver1 == 0x58) fseek (ifp, 2110, SEEK_CUR); - if (ver0 == 0x46) huff = 2; - if (tiff_bps == 14) huff += 3; + if (ver0 == 0x46) tree = 2; + if (tiff_bps == 14) tree += 3; read_shorts (vpred[0], 4); max = 1 << tiff_bps & 0x7fff; if ((csize = get2()) > 1) @@ -1226,21 +1214,19 @@ } else if (ver0 != 0x46 && csize <= 0x4001) read_shorts (curve, max=csize); while (curve[max-2] == curve[max-1]) max--; - init_decoder(); - make_decoder (nikon_tree[huff], 0); + huff = make_decoder (nikon_tree[tree]); fseek (ifp, data_offset, SEEK_SET); getbits(-1); for (min=row=0; row < height; row++) { if (split && row == split) { - init_decoder(); - make_decoder (nikon_tree[huff+1], 0); + free (huff); + huff = make_decoder (nikon_tree[tree+1]); max += (min = 16) << 1; } for (col=0; col < raw_width; col++) { - for (dindex=first_decode; dindex->branch[0]; ) - dindex = dindex->branch[getbits(1)]; - len = dindex->leaf & 15; - shl = dindex->leaf >> 4; + i = gethuff(huff); + len = i & 15; + shl = i >> 4; diff = ((getbits(len-shl) << 1) + 1) << shl >> 1; if ((diff & (1 << (len-1))) == 0) diff -= (1 << len) - !shl; @@ -1251,6 +1237,7 @@ BAYER(row,col-left_margin) = curve[LIM((short)hpred[col & 1],0,0x3fff)]; } } + free (huff); } /* @@ -1344,23 +1331,6 @@ return nz > 20; } -/* Here raw_width is in bytes, not pixels. */ -void CLASS nikon_e900_load_raw() -{ - int offset=0, irow, row, col; - - for (irow=0; irow < height; irow++) { - row = irow * 2 % height; - if (row == 1) - offset = - (-offset & -4096); - fseek (ifp, offset, SEEK_SET); - offset += raw_width; - getbits(-1); - for (col=0; col < width; col++) - BAYER(row,col) = getbits(10); - } -} - /* The Fuji Super CCD is just a Bayer grid rotated 45 degrees. */ @@ -1390,21 +1360,21 @@ free (pixel); } -//void CLASS jpeg_thumb (FILE *tfp); +//void CLASS jpeg_thumb(); -void CLASS ppm_thumb (FILE *tfp) +void CLASS ppm_thumb() { char *thumb; thumb_length = thumb_width*thumb_height*3; thumb = (char *) malloc (thumb_length); merror (thumb, "ppm_thumb()"); - fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height); + fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height); fread (thumb, 1, thumb_length, ifp); - fwrite (thumb, 1, thumb_length, tfp); + fwrite (thumb, 1, thumb_length, ofp); free (thumb); } -void CLASS layer_thumb (FILE *tfp) +void CLASS layer_thumb() { unsigned i; int c; @@ -1414,15 +1384,15 @@ thumb_length = thumb_width*thumb_height; thumb = (char *) calloc (colors, thumb_length); merror (thumb, "layer_thumb()"); - fprintf (tfp, "P%d\n%d %d\n255\n", + fprintf (ofp, "P%d\n%d %d\n255\n", 5 + (colors >> 1), thumb_width, thumb_height); fread (thumb, thumb_length, colors, ifp); for (i=0; i < thumb_length; i++) - FORCC putc (thumb[i+thumb_length*(map[thumb_misc >> 8][c]-'0')], tfp); + FORCC putc (thumb[i+thumb_length*(map[thumb_misc >> 8][c]-'0')], ofp); free (thumb); } -void CLASS rollei_thumb (FILE *tfp) +void CLASS rollei_thumb() { unsigned i; ushort *thumb; @@ -1430,12 +1400,12 @@ thumb_length = thumb_width * thumb_height; thumb = (ushort *) calloc (thumb_length, 2); merror (thumb, "rollei_thumb()"); - fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height); + fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height); read_shorts (thumb, thumb_length); for (i=0; i < thumb_length; i++) { - putc (thumb[i] << 3, tfp); - putc (thumb[i] >> 5 << 2, tfp); - putc (thumb[i] >> 11 << 3, tfp); + putc (thumb[i] << 3, ofp); + putc (thumb[i] >> 5 << 2, ofp); + putc (thumb[i] >> 11 << 3, ofp); } free (thumb); } @@ -1525,7 +1495,7 @@ { {-1,-1}, {-1,1}, {1,-1}, {1,1}, {-2,0}, {0,-2}, {0,2}, {2,0}, {-2,-2}, {-2,2}, {2,-2}, {2,2} }; float poly[8], num, cfrac, frac, mult[2], *yval[2]; - ushort curve[0x10000], *xval[2]; + ushort *xval[2]; if (half_size || !meta_length) return; dcraw_message (DCRAW_VERBOSE,_("Phase One correction...\n")); @@ -1667,21 +1637,30 @@ phase_one_correct(); } -unsigned CLASS ph1_bits (int nbits) +unsigned CLASS ph1_bithuff (int nbits, ushort *huff) { // TODO: The following static variables are not thread-safe static UINT64 bitbuf=0; static int vbits=0; + unsigned c; if (nbits == -1) return bitbuf = vbits = 0; if (nbits == 0) return 0; - if ((vbits -= nbits) < 0) { + if (vbits < nbits) { bitbuf = bitbuf << 32 | get4(); vbits += 32; } - return bitbuf << (64-nbits-vbits) >> (64-nbits); + c = bitbuf << (64-vbits) >> (64-nbits); + if (huff) { + vbits -= huff[c] >> 8; + return (uchar) huff[c]; + } + vbits -= nbits; + return c; } +#define ph1_bits(n) ph1_bithuff(n,0) +#define ph1_huff(h) ph1_bithuff(*h,h+1) void CLASS phase_one_load_raw_c() { @@ -1737,30 +1716,27 @@ void CLASS hasselblad_load_raw() { struct jhead jh; - struct decode *dindex; - int row, col, pred[2], len[2], diff, i; + int row, col, pred[2], len[2], diff, c; if (!ljpeg_start (&jh, 0)) return; - free (jh.row); + order = 0x4949; ph1_bits(-1); for (row=-top_margin; row < height; row++) { pred[0] = pred[1] = 0x8000; for (col=-left_margin; col < raw_width-left_margin; col+=2) { - for (i=0; i < 2; i++) { - for (dindex=jh.huff[0]; dindex->branch[0]; ) - dindex = dindex->branch[ph1_bits(1)]; - len[i] = dindex->leaf; - } - for (i=0; i < 2; i++) { - diff = ph1_bits(len[i]); - if ((diff & (1 << (len[i]-1))) == 0) - diff -= (1 << len[i]) - 1; - pred[i] += diff; - if (row >= 0 && (unsigned)(col+i) < width) - BAYER(row,col+i) = pred[i]; + FORC(2) len[c] = ph1_huff(jh.huff[0]); + FORC(2) { + diff = ph1_bits(len[c]); + if ((diff & (1 << (len[c]-1))) == 0) + diff -= (1 << len[c]) - 1; + if (diff == 65535) diff = -32768; + pred[c] += diff; + if (row >= 0 && (unsigned)(col+c) < width) + BAYER(row,col+c) = pred[c]; } } } + ljpeg_end (&jh); maximum = 0xffff; } @@ -1837,42 +1813,50 @@ read_shorts (image[row*width+col], 3); } -void CLASS packed_12_load_raw() +void CLASS packed_load_raw() { - int vbits=0, rbits=0, irow, row, col; + int vbits=0, bwide, pwide, rbits, bite, half, irow, row, col, val, i; UINT64 bitbuf=0; - if (raw_width * 2 >= width * 3) { /* If raw_width is in bytes, */ - rbits = raw_width * 8; - raw_width = raw_width * 2 / 3; /* convert it to pixels and */ - rbits -= raw_width * 12; /* save the remainder. */ - } - order = load_flags & 1 ? 0x4949 : 0x4d4d; + if ((ushort)(raw_width * 8) >= width * tiff_bps) /* Is raw_width in bytes? */ + pwide = (bwide = raw_width) * 8 / tiff_bps; + else bwide = (pwide = raw_width) * tiff_bps / 8; + rbits = bwide * 8 - pwide * tiff_bps; + if (load_flags & 1) bwide = bwide * 16 / 15; + fseek (ifp, top_margin*bwide, SEEK_CUR); + bite = 8 + (load_flags & 24); + half = (height+1) >> 1; for (irow=0; irow < height; irow++) { row = irow; if (load_flags & 2 && - (row = irow * 2 % height + irow / (height/2)) == 1 && + (row = irow % half * 2 + irow / half) == 1 && load_flags & 4) { if (vbits=0, tiff_compress) - fseek (ifp, data_offset - (-width*height*3/4 & -2048), SEEK_SET); + fseek (ifp, data_offset - (-half*bwide & -2048), SEEK_SET); else { fseek (ifp, 0, SEEK_END); - fseek (ifp, ftell(ifp)/2, SEEK_SET); + fseek (ifp, ftell(ifp) >> 3 << 2, SEEK_SET); } } - for (col=0; col < raw_width; col++) { - if ((vbits -= 12) < 0) { - bitbuf = bitbuf << 32 | get4(); - vbits += 32; - } - if ((unsigned) (col-left_margin) < width) - BAYER(row,col-left_margin) = bitbuf << (52-vbits) >> 52; - if (load_flags & 8 && (col % 10) == 9) - if (vbits=0, bitbuf & 255) derror(); + for (col=0; col < pwide; col++) { + for (vbits -= tiff_bps; vbits < 0; vbits += bite) { + bitbuf <<= bite; + for (i=0; i < bite; i+=8) + bitbuf |= (unsigned) (fgetc(ifp) << i); + } + val = bitbuf << (64-tiff_bps-vbits) >> (64-tiff_bps); + i = (col ^ (bite == 24)) - left_margin; + if ((unsigned) i < width) + BAYER(row,i) = val << (load_flags >> 6); + else if (load_flags & 32) + black += val; + if (load_flags & 1 && (col % 10) == 9 && + fgetc(ifp) && col < width+left_margin) derror(); } vbits -= rbits; } - if (!strcmp(make,"OLYMPUS")) black >>= 4; + if (load_flags & 32 && pwide > width) + black /= (pwide - width) * height; } void CLASS unpacked_load_raw() @@ -1956,56 +1940,32 @@ } } -void CLASS olympus_e300_load_raw() +void CLASS olympus_load_raw() { - uchar *data, *dp; - ushort *pixel, *pix; - int dwide, row, col; - - dwide = raw_width * 16 / 10; - fseek (ifp, dwide*top_margin, SEEK_CUR); - data = (uchar *) malloc (dwide + raw_width*2); - merror (data, "olympus_e300_load_raw()"); - pixel = (ushort *) (data + dwide); - for (row=0; row < height; row++) { - if ((int)fread (data, 1, dwide, ifp) < dwide) derror(); - for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=3, pix+=2) { - if (((dp-data) & 15) == 15) - if (*dp++ && pix < pixel+width+left_margin) derror(); - pix[0] = dp[1] << 8 | dp[0]; - pix[1] = dp[2] << 4 | dp[1] >> 4; - } - for (col=0; col < width; col++) - BAYER(row,col) = (pixel[col+left_margin] & 0xfff); - } - free (data); - maximum >>= 4; - black >>= 4; -} - -void CLASS olympus_e410_load_raw() -{ - int row, col, nbits, sign, low, high, i, w, n, nw; + ushort huff[4096]; + int row, col, nbits, sign, low, high, i, c, w, n, nw; int acarry[2][3], *carry, pred, diff; + huff[n=0] = 0xc0c; + for (i=12; i--; ) + FORC(2048 >> i) huff[++n] = (i+1) << 8 | i; fseek (ifp, 7, SEEK_CUR); getbits(-1); for (row=0; row < height; row++) { memset (acarry, 0, sizeof acarry); - for (col=0; col < width; col++) { + for (col=0; col < raw_width; col++) { carry = acarry[col & 1]; i = 2 * (carry[2] < 3); for (nbits=2+i; (ushort) carry[0] >> (nbits+i); nbits++) {}; - sign = getbits(1) * -1; - low = getbits(2); - for (high=0; high < 12; high++) - if (getbits(1)) break; - if (high == 12) + low = (sign = getbits(3)) & 3; + sign = sign << 29 >> 31; + if ((high = getbithuff(12,huff)) == 12) high = getbits(16-nbits) >> 1; carry[0] = (high << nbits) | getbits(nbits); diff = (carry[0] ^ sign) + carry[1]; carry[1] = (diff*3 + carry[1]) >> 5; carry[2] = carry[0] > 16 ? 0 : carry[2]+1; + if (col >= width) continue; if (row < 2 && col < 2) pred = 0; else if (row < 2) pred = BAYER(row,col-2); else if (col < 2) pred = BAYER(row-2,col); @@ -2052,26 +2012,6 @@ maximum = 0xff << 1; } -void CLASS casio_qv5700_load_raw() -{ - uchar data[3232], *dp; - ushort pixel[2576], *pix; - int row, col; - - for (row=0; row < height; row++) { - fread (data, 1, 3232, ifp); - for (dp=data, pix=pixel; dp < data+3220; dp+=5, pix+=4) { - pix[0] = (dp[0] << 2) + (dp[1] >> 6); - pix[1] = (dp[1] << 4) + (dp[2] >> 4); - pix[2] = (dp[2] << 6) + (dp[3] >> 2); - pix[3] = (dp[3] << 8) + (dp[4] ); - } - for (col=0; col < width; col++) - BAYER(row,col) = (pixel[col] & 0x3ff); - } - maximum = 0x3fc; -} - void CLASS quicktake_100_load_raw() { uchar pixel[484][644]; @@ -2139,29 +2079,16 @@ maximum = 0x3ff; } -const int * CLASS make_decoder_int (const int *source, int level) -{ - struct decode *cur; +#define radc_token(tree) ((signed char) getbithuff(8,huff[tree])) - cur = free_decode++; - if (level < source[0]) { - cur->branch[0] = free_decode; - source = make_decoder_int (source, level+1); - cur->branch[1] = free_decode; - source = make_decoder_int (source, level+1); - } else { - cur->leaf = source[1]; - source += 2; - } - return source; -} +#define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--) + +#define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \ +: (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4) -int CLASS radc_token (int tree) +void CLASS kodak_radc_load_raw() { - int t; - // TODO: The following static variables are not thread-safe - static struct decode *dstart[18], *dindex; - static const int *s, source[] = { + static const char src[] = { 1,1, 2,3, 3,4, 4,2, 5,7, 6,5, 7,6, 7,8, 1,0, 2,1, 3,3, 4,4, 5,2, 6,7, 7,6, 8,5, 8,8, 2,1, 2,3, 3,0, 3,2, 3,4, 4,6, 5,5, 6,7, 6,8, @@ -2181,34 +2108,21 @@ 2,-1, 2,13, 2,26, 3,39, 4,-16, 5,55, 6,-37, 6,76, 2,-26, 2,-13, 2,1, 3,-39, 4,16, 5,-55, 6,-76, 6,37 }; - - if (free_decode == first_decode) - for (s=source, t=0; t < 18; t++) { - dstart[t] = free_decode; - s = make_decoder_int (s, 0); - } - if (tree == 18) { - if (kodak_cbpp == 243) - return (getbits(6) << 2) + 2; /* most DC50 photos */ - else - return (getbits(5) << 3) + 4; /* DC40, Fotoman Pixtura */ - } - for (dindex = dstart[tree]; dindex->branch[0]; ) - dindex = dindex->branch[getbits(1)]; - return dindex->leaf; -} - -#define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--) - -#define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \ -: (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4) - -void CLASS kodak_radc_load_raw() -{ + ushort huff[19][256]; int row, col, tree, nreps, rep, step, i, c, s, r, x, y, val; short last[3] = { 16,16,16 }, mul[3], buf[3][3][386]; + static const ushort pt[] = + { 0,0, 1280,1344, 2320,3616, 3328,8000, 4095,16383, 65535,16383 }; - init_decoder(); + for (i=2; i < 12; i+=2) + for (c=pt[i-2]; c <= pt[i]; c++) + curve[c] = (float) + (c-pt[i-2]) / (pt[i]-pt[i-2]) * (pt[i+1]-pt[i-1]) + pt[i-1] + 0.5; + for (s=i=0; i < (int) sizeof src; i+=2) + FORC(256 >> src[i]) + huff[0][s++] = src[i] << 8 | (uchar) src[i+1]; + s = kodak_cbpp == 243 ? 2 : 3; + FORC(256) huff[18][c] = (8-s) << 8 | c >> s << s | 1 << (s-1); getbits(-1); for (i=0; i < (int) sizeof(buf)/(int) sizeof(short); i++) buf[0][0][i] = 2048; @@ -2228,7 +2142,7 @@ if ((tree = radc_token(tree))) { col -= 2; if (tree == 8) - FORYX buf[c][y][x] = radc_token(tree+10) * mul[c]; + FORYX buf[c][y][x] = (uchar) radc_token(18) * mul[c]; else FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR; } else @@ -2264,8 +2178,9 @@ BAYER(y,x) = val; } } - maximum = 0xfff; - use_gamma = 0; + for (i=0; i < iheight*iwidth*4; i++) + image[0][i] = curve[image[0][i]]; + maximum = 0x3fff; } #undef FORYX @@ -2390,11 +2305,11 @@ rgb[1] = y-((cb + cr + 2) >> 2); rgb[2] = rgb[1] + cb; rgb[0] = rgb[1] + cr; - FORC3 image[row*width+col][c] = LIM(rgb[c],0,255); + FORC3 image[row*width+col][c] = curve[LIM(rgb[c],0,255)]; } } free (pixel); - use_gamma = 0; + maximum = curve[0xff]; } void CLASS kodak_262_load_raw() @@ -2402,22 +2317,17 @@ static const uchar kodak_tree[2][26] = { { 0,1,5,1,1,2,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 }, { 0,3,1,1,1,1,1,2,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 } }; - struct decode *decode[2]; + ushort *huff[2]; uchar *pixel; - int *strip, ns, i, row, col, chess, pi=0, pi1, pi2, pred, val; + int *strip, ns, c, row, col, chess, pi=0, pi1, pi2, pred, val; - init_decoder(); - for (i=0; i < 2; i++) { - decode[i] = free_decode; - make_decoder (kodak_tree[i], 0); - } + FORC(2) huff[c] = make_decoder (kodak_tree[c]); ns = (raw_height+63) >> 5; pixel = (uchar *) malloc (raw_width*32 + ns*4); merror (pixel, "kodak_262_load_raw()"); strip = (int *) (pixel + raw_width*32); order = 0x4d4d; - for (i=0; i < ns; i++) - strip[i] = get4(); + FORC(ns) strip[c] = get4(); for (row=0; row < raw_height; row++) { if ((row & 31) == 0) { fseek (ifp, strip[row >> 5], SEEK_SET); @@ -2433,7 +2343,7 @@ if (pi2 < 0) pi2 = pi1; if (pi1 < 0 && col > 1) pi1 = pi2 = pi-2; pred = (pi1 < 0) ? 0 : (pixel[pi1] + pixel[pi2]) >> 1; - pixel[pi] = val = pred + ljpeg_diff (decode[chess]); + pixel[pi] = val = pred + ljpeg_diff (huff[chess]); if (val >> 8) derror(); val = curve[pixel[pi++]]; if ((unsigned) (col-left_margin) < width) @@ -2442,6 +2352,7 @@ } } free (pixel); + FORC(2) free (huff[c]); if (raw_width > width) black /= (raw_width - width) * height; } @@ -2614,16 +2525,19 @@ void CLASS sony_arw_load_raw() { - int col, row, len, diff, sum=0; + ushort huff[32768]; + static const ushort tab[18] = + { 0xf11,0xf10,0xe0f,0xd0e,0xc0d,0xb0c,0xa0b,0x90a,0x809, + 0x708,0x607,0x506,0x405,0x304,0x303,0x300,0x202,0x201 }; + int i, c, n, col, row, len, diff, sum=0; + for (n=i=0; i < 18; i++) + FORC(32768 >> (tab[i] >> 8)) huff[n++] = tab[i]; getbits(-1); for (col = raw_width; col--; ) for (row=0; row < raw_height+1; row+=2) { if (row == raw_height) row = 1; - len = 4 - getbits(2); - if (len == 3 && getbits(1)) len = 0; - if (len == 4) - while (len < 17 && !getbits(1)) len++; + len = getbithuff(15,huff); diff = getbits(len); if ((diff & (1 << (len-1))) == 0) diff -= (1 << len) - 1; @@ -2638,34 +2552,28 @@ ushort pix[16]; int row, col, val, max, min, imax, imin, sh, bit, i; - data = (uchar *) malloc (raw_width*tiff_bps >> 3); + data = (uchar *) malloc (raw_width); merror (data, "sony_arw2_load_raw()"); for (row=0; row < height; row++) { - fread (data, 1, raw_width*tiff_bps >> 3, ifp); - if (tiff_bps == 8) { - for (dp=data, col=0; col < width-30; dp+=16) { - max = 0x7ff & (val = sget4(dp)); - min = 0x7ff & val >> 11; - imax = 0x0f & val >> 22; - imin = 0x0f & val >> 26; - for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++) {}; - for (bit=30, i=0; i < 16; i++) - if (i == imax) pix[i] = max; - else if (i == imin) pix[i] = min; - else { - pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min; - if (pix[i] > 0x7ff) pix[i] = 0x7ff; - bit += 7; - } - for (i=0; i < 16; i++, col+=2) - BAYER(row,col) = curve[pix[i] << 1] >> 1; - col -= col & 1 ? 1:31; - } - } else if (tiff_bps == 12) - for (dp=data, col=0; col < width; dp+=3, col+=2) { - BAYER(row,col) = ((dp[1] << 8 | dp[0]) & 0xfff) << 1; - BAYER(row,col+1) = (dp[2] << 4 | dp[1] >> 4) << 1; - } + fread (data, 1, raw_width, ifp); + for (dp=data, col=0; col < width-30; dp+=16) { + max = 0x7ff & (val = sget4(dp)); + min = 0x7ff & val >> 11; + imax = 0x0f & val >> 22; + imin = 0x0f & val >> 26; + for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++) {}; + for (bit=30, i=0; i < 16; i++) + if (i == imax) pix[i] = max; + else if (i == imin) pix[i] = min; + else { + pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min; + if (pix[i] > 0x7ff) pix[i] = 0x7ff; + bit += 7; + } + for (i=0; i < 16; i++, col+=2) + BAYER(row,col) = curve[pix[i] << 1] >> 1; + col -= col & 1 ? 1:31; + } } free (data); } @@ -2749,7 +2657,6 @@ seg[1][0] = raw_width * raw_height; seg[1][1] = INT_MAX; smal_decode_segment (seg, 0); - use_gamma = 0; } int CLASS median4 (int *p) @@ -2823,7 +2730,8 @@ if (!code) { for (i=0; i < size; i++) huff[i] = get4(); - init_decoder(); + memset (first_decode, 0, sizeof first_decode); + free_decode = first_decode; } cur = free_decode++; if (free_decode > first_decode+2048) { @@ -2845,7 +2753,7 @@ foveon_decoder (size, code+1); } -void CLASS foveon_thumb (FILE *tfp) +void CLASS foveon_thumb() { int bwide; unsigned row, col, bitbuf=0, bit=1, c, i; @@ -2854,14 +2762,14 @@ short pred[3]; bwide = get4(); - fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height); + fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height); if (bwide > 0) { if (bwide < thumb_width*3) return; buf = (char *) malloc (bwide); merror (buf, "foveon_thumb()"); for (row=0; row < thumb_height; row++) { fread (buf, 1, bwide, ifp); - fwrite (buf, 3, thumb_width, tfp); + fwrite (buf, 3, thumb_width, ofp); } free (buf); return; @@ -2880,7 +2788,7 @@ dindex = dindex->branch[bitbuf >> bit & 1]; } pred[c] += dindex->leaf; - fputc (pred[c], tfp); + fputc (pred[c], ofp); } } } @@ -3459,15 +3367,15 @@ Seach from the current directory up to the root looking for a ".badpixels" file, and fix those pixels now. */ -void CLASS bad_pixels (char *fname) +void CLASS bad_pixels (const char *cfname) { FILE *fp=0; - char *cp, line[128]; + char *fname, *cp, line[128]; int len, time, row, col, r, c, rad, tot, n, fixed=0; if (!filters) return; - if (fname) - fp = fopen (fname, "r"); + if (cfname) + fp = fopen (cfname, "r"); else { for (len=32 ; ; len *= 2) { fname = (char *) malloc (len); @@ -3555,6 +3463,41 @@ black = 0; } +void CLASS gamma_curve (double pwr, double ts, int mode, int imax) +{ + int i; + double g[6], bnd[2]={0,0}, r; + + g[0] = pwr; + g[1] = ts; + g[2] = g[3] = g[4] = 0; + bnd[g[1] >= 1] = 1; + if (g[1] && (g[1]-1)*(g[0]-1) <= 0) { + for (i=0; i < 48; i++) { + g[2] = (bnd[0] + bnd[1])/2; + if (g[0]) bnd[(pow(g[2]/g[1],-g[0]) - 1)/g[0] - 1/g[2] > -1] = g[2]; + else bnd[g[2]/exp(1-1/g[2]) < g[1]] = g[2]; + } + g[3] = g[2] / g[1]; + if (g[0]) g[4] = g[2] * (1/g[0] - 1); + } + if (g[0]) g[5] = 1 / (g[1]*SQR(g[3])/2 - g[4]*(1 - g[3]) + + (1 - pow(g[3],1+g[0]))*(1 + g[4])/(1 + g[0])) - 1; + else g[5] = 1 / (g[1]*SQR(g[3])/2 + 1 + - g[2] - g[3] - g[2]*g[3]*(log(g[3]) - 1)) - 1; + if (!mode--) { + memcpy (gamm, g, sizeof gamm); + return; + } + for (i=0; i < 0x10000; i++) { + curve[i] = 0xffff; + if ((r = (double) i / imax) < 1) + curve[i] = 0x10000 * ( mode + ? (r < g[3] ? r*g[1] : (g[0] ? pow( r,g[0])*(1+g[4])-g[4] : log(r)*g[2]+1)) + : (r < g[2] ? r/g[1] : (g[0] ? pow((r+g[4])/(1+g[4]),1/g[0]) : exp((r-1)/g[2])))); + } +} + void CLASS pseudoinverse (double (*in)[3], double (*out)[3], int size) { double work[3][6], num; @@ -3613,31 +3556,7 @@ #define NSQ 24 // Coordinates of the GretagMacbeth ColorChecker squares // width, height, 1st_column, 1st_row - static const int cut[NSQ][4] = { - { 241, 231, 234, 274 }, - { 251, 235, 534, 274 }, - { 255, 239, 838, 272 }, - { 255, 240, 1146, 274 }, - { 251, 237, 1452, 278 }, - { 243, 238, 1758, 288 }, - { 253, 253, 218, 558 }, - { 255, 249, 524, 562 }, - { 261, 253, 830, 562 }, - { 260, 255, 1144, 564 }, - { 261, 255, 1450, 566 }, - { 247, 247, 1764, 576 }, - { 255, 251, 212, 862 }, - { 259, 259, 518, 862 }, - { 263, 261, 826, 864 }, - { 265, 263, 1138, 866 }, - { 265, 257, 1450, 872 }, - { 257, 255, 1762, 874 }, - { 257, 253, 212, 1164 }, - { 262, 251, 516, 1172 }, - { 263, 257, 826, 1172 }, - { 263, 255, 1136, 1176 }, - { 255, 252, 1452, 1182 }, - { 257, 253, 1760, 1180 } }; + int cut[NSQ][4]; // you must set these // ColorChecker Chart under 6500-kelvin illumination static const double gmb_xyY[NSQ][3] = { { 0.400, 0.350, 10.1 }, // Dark Skin @@ -3733,7 +3652,7 @@ if ((nc = colors) == 3 && filters) nc++; FORC(nc) { /* denoise R,G1,B,G3 individually */ for (i=0; i < size; i++) - fimg[i] = sqrt((unsigned) (image[i][c] << (scale+16))); + fimg[i] = 256 * sqrt(image[i][c] << scale); for (hpass=lev=0; lev < 5; lev++) { lpass = size*((lev & 1)+1); for (row=0; row < iheight; row++) { @@ -4313,7 +4232,7 @@ #undef TS /* End of functions copied to dcraw_indi.c (UF) */ -void CLASS median_filter () +void CLASS median_filter() { ushort (*pix)[4]; int pass, c, i, j, k, med[9]; @@ -4585,6 +4504,16 @@ wbi = (get2(),get2()); shot_order = (get2(),get2()); } + if ((tag == 4 || tag == 0x114) && !strncmp(make,"KONICA",6)) { + fseek (ifp, tag == 4 ? 140:160, SEEK_CUR); + switch (get2()) { + case 72: flip = 0; break; + case 76: flip = 6; break; + case 82: flip = 5; break; + } + } + if (tag == 7 && type == 2 && len > 20) + fgets (model2, 64, ifp); if (tag == 8 && type == 4) shot_order = get4(); if (tag == 9 && !strcmp(make,"Canon")) @@ -4684,6 +4613,8 @@ black = (get2()+get2()+get2()+get2())/4; if (tag == 0x201 && len == 4) goto get2_rggb; + if (tag == 0x220 && len == 53) + meta_offset = ftell(ifp) + 14; if (tag == 0x401 && len == 4) { black = (get4()+get4()+get4()+get4())/4; } @@ -4732,7 +4663,7 @@ if ((tag | 0x70) == 0x2070 && type == 4) fseek (ifp, get4()+base, SEEK_SET); if (tag == 0x2010 && type != 7) - load_raw = &CLASS olympus_e410_load_raw; + load_raw = &CLASS olympus_load_raw; if (tag == 0x2020) parse_thumb_note (base, 257, 258); if (tag == 0x2040) @@ -4926,7 +4857,8 @@ { unsigned entries, tag, type, len, save; int i, c, wbi=-2, wbtemp=6500; - float mul[3], num; + static float mul[3]; float num; + static const unsigned wbtag[]={ 0xfa25,0xfa28,0xfa27,0xfa29,-1,-1,0xfa2a }; entries = get2(); if (entries > 1024) return; @@ -4949,6 +4881,9 @@ } if (tag == 2317) linear_table (len); if (tag == 6020) iso_speed = getint(type); + if (tag == 0xfa0d) wbi = fgetc(ifp); + if ((unsigned) wbi < 7 && tag == wbtag[wbi]) + FORC3 cam_mul[c] = get4(); fseek (ifp, save, SEEK_SET); } } @@ -5114,6 +5049,9 @@ case 29443: FORC4 cam_mul[c ^ (c < 2)] = get2(); break; + case 29459: + FORC4 cam_mul[c ^ (c >> 1)] = get2(); + break; case 33405: /* Model2 */ fgets (model2, 64, ifp); break; @@ -5129,6 +5067,7 @@ if (cfa == 072) memcpy (cfa_pc,"\005\003\004\001",4); /* GMCY */ goto guess_cfa_pc; case 33424: + case 65024: fseek (ifp, get4()+base, SEEK_SET); parse_kodak_ifd (base); break; @@ -5192,6 +5131,7 @@ ima_len = len; break; case 46279: + if (!ima_len) break; fseek (ifp, 78, SEEK_CUR); raw_width = get4(); raw_height = get4(); @@ -5229,6 +5169,9 @@ sscanf (cp+8, "%f %f %f", cam_mul, cam_mul+1, cam_mul+2); free (cbuf); break; + case 50458: + if (!make[0]) strcpy (make, "Hasselblad"); + break; case 50459: /* Hasselblad tag */ i = order; j = ftell(ifp); @@ -5243,6 +5186,7 @@ case 50706: /* DNGVersion */ FORC4 dng_version = (dng_version << 8) + fgetc(ifp); if (!make[0]) strcpy (make, "DNG"); + is_raw = 1; break; case 50710: /* CFAPlaneColor */ if (len > 4) len = 4; @@ -5318,11 +5262,15 @@ width = getint(type) - left_margin; break; case 64772: /* Kodak P-series */ + if (len < 13) break; fseek (ifp, 16, SEEK_CUR); data_offset = get4(); fseek (ifp, 28, SEEK_CUR); data_offset += get4(); - load_raw = &CLASS packed_12_load_raw; + load_raw = &CLASS packed_load_raw; + break; + case 65026: + if (type == 2) fgets (model2, 64, ifp); } fseek (ifp, save, SEEK_SET); } @@ -5386,6 +5334,7 @@ max_samp = tiff_ifd[i].samples; if (max_samp > 3) max_samp = 3; if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) && + (tiff_ifd[i].width | tiff_ifd[i].height) < 0x10000 && tiff_ifd[i].width*tiff_ifd[i].height > raw_width*raw_height) { raw_width = tiff_ifd[i].width; raw_height = tiff_ifd[i].height; @@ -5404,34 +5353,42 @@ case 0: case 1: switch (tiff_bps) { case 8: load_raw = &CLASS eight_bit_load_raw; break; - case 12: load_raw = &CLASS packed_12_load_raw; + case 12: load_raw = &CLASS packed_load_raw; if (tiff_ifd[raw].phint == 2) load_flags = 6; if (strncmp(make,"PENTAX",6)) break; case 14: case 16: load_raw = &CLASS unpacked_load_raw; break; } - if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8) - load_raw = &CLASS olympus_e300_load_raw; + if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8) { + tiff_bps = 12; + maximum = 0xffff; + load_raw = &CLASS packed_load_raw; + load_flags = 273; + } break; case 6: case 7: case 99: load_raw = &CLASS lossless_jpeg_load_raw; break; case 262: load_raw = &CLASS kodak_262_load_raw; break; case 32767: - load_raw = &CLASS sony_arw2_load_raw; - if (tiff_ifd[raw].bytes*8 == (int)(raw_width*raw_height*tiff_bps)) - break; - raw_height += 8; - load_raw = &CLASS sony_arw_load_raw; break; + if (tiff_ifd[raw].bytes*8 != (int)(raw_width*raw_height*tiff_bps)) { + raw_height += 8; + load_raw = &CLASS sony_arw_load_raw; break; + } + if (tiff_bps == 8) { + tiff_bps = 12; + load_raw = &CLASS sony_arw2_load_raw; break; + } + load_flags = 79; case 32769: - load_flags = 8; + load_flags++; case 32773: - load_raw = &CLASS packed_12_load_raw; break; + load_raw = &CLASS packed_load_raw; break; case 34713: load_raw = &CLASS nikon_compressed_load_raw; break; case 65535: - load_raw = &CLASS pentax_k10_load_raw; break; + load_raw = &CLASS pentax_load_raw; break; case 65000: switch (tiff_ifd[raw].phint) { case 2: load_raw = &CLASS kodak_rgb_load_raw; filters = 0; break; @@ -5441,12 +5398,12 @@ case 32867: break; default: is_raw = 0; } - if (!dng_version && tiff_samples == 3) - if (tiff_ifd[raw].bytes && tiff_bps != 14 && tiff_bps != 2048) + if (!dng_version) + if ( (tiff_samples == 3 && tiff_ifd[raw].bytes && + tiff_bps != 14 && tiff_bps != 2048) + || (tiff_bps == 8 && !strstr(make,"KODAK") && !strstr(make,"Kodak") && + !strstr(model2,"DEBUG RAW"))) is_raw = 0; - if (!dng_version && tiff_bps == 8 && tiff_compress == 1 && - tiff_ifd[raw].phint == 1) is_raw = 0; - if (tiff_bps == 8 && tiff_samples == 4) is_raw = 0; for (i=0; i < (int) tiff_nifds; i++) if (i != raw && tiff_ifd[i].samples == max_samp && tiff_ifd[i].width * tiff_ifd[i].height / SQR(tiff_ifd[i].bps+1) > @@ -5519,8 +5476,8 @@ */ void CLASS parse_external_jpeg() { - const char *file; - char *ext, *jname, *jfile, *jext; + const char *file, *ext; + char *jname, *jfile, *jext; FILE *save=ifp; ext = strrchr (ifname, '.'); @@ -5530,14 +5487,16 @@ file++; if (!ext || strlen(ext) != 4 || ext-file != 8) return; jname = (char *) malloc (strlen(ifname) + 1); - merror (jname, "parse_external()"); + merror (jname, "parse_external_jpeg()"); strcpy (jname, ifname); jfile = file - ifname + jname; jext = ext - ifname + jname; if (strcasecmp (ext, ".jpg")) { strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg"); - memcpy (jfile, file+4, 4); - memcpy (jfile+4, file, 4); + if (isdigit(*file)) { + memcpy (jfile, file+4, 4); + memcpy (jfile+4, file, 4); + } } else while (isdigit(*--jext)) { if (*jext != '9') { @@ -5898,10 +5857,10 @@ end = ftell(ifp) + size; if (!memcmp(tag,"RIFF",4) || !memcmp(tag,"LIST",4)) { get4(); - while ((unsigned) ftell(ifp) < end) + while ((unsigned)(ftell(ifp)+7) < end) parse_riff(); } else if (!memcmp(tag,"nctg",4)) { - while ((unsigned) ftell(ifp) < end) { + while ((unsigned)(ftell(ifp)+7) < end) { i = get2(); size = get2(); if ((i+1) >> 1 == 10 && size == 20) @@ -6089,7 +6048,7 @@ } /* - Thanks to Adobe for providing these excellent CAM -> XYZ matrices! + All matrices are from Adobe DNG Converter unless otherwise noted. */ void CLASS adobe_coeff (const char *make, const char *model) { @@ -6097,8 +6056,10 @@ const char *prefix; short black, maximum, trans[12]; } table[] = { + { "AGFAPHOTO DC-833m", 0, 0, /* DJC */ + { 11438,-3762,-1115,-2409,9914,2497,-1227,2295,5300 } }, { "Apple QuickTake", 0, 0, /* DJC */ - { 17576,-3191,-3318,5210,6733,-1942,9031,1280,-124 } }, + { 21392,-5653,-3353,2406,8010,-415,7166,1427,2078 } }, { "Canon EOS D2000", 0, 0, { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } }, { "Canon EOS D6000", 0, 0, @@ -6111,6 +6072,8 @@ { 4716,603,-830,-7798,15474,2480,-1496,1937,6651 } }, { "Canon EOS 5D", 0, 0xe6c, { 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 } }, + { "Canon EOS 7D", 0, 0x3510, /* DJC */ + { 7956,-1490,-850,-2896,10428,2469,-827,1800,5680 } }, { "Canon EOS 10D", 0, 0xfa0, { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, { "Canon EOS 20Da", 0, 0, @@ -6131,6 +6094,8 @@ { 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } }, { "Canon EOS 450D", 0, 0x390d, { 5784,-262,-821,-7539,15064,2672,-1982,2681,7427 } }, + { "Canon EOS 500D", 0, 0x3479, + { 4763,712,-646,-6821,14399,2640,-1921,3276,6561 } }, { "Canon EOS 1000D", 0, 0xe43, { 6771,-1139,-977,-7818,15123,2928,-1244,1437,7533 } }, { "Canon EOS-1Ds Mark III", 0, 0x3bb0, @@ -6149,12 +6114,16 @@ { 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } }, { "Canon EOS", 0, 0, { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, + { "Canon PowerShot A530", 0, 0, + { 0 } }, /* don't want the A5 matrix */ { "Canon PowerShot A50", 0, 0, { -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } }, { "Canon PowerShot A5", 0, 0, { -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 } }, { "Canon PowerShot G10", 0, 0, { 11093,-3906,-1028,-5047,12492,2879,-1003,1750,5561 } }, + { "Canon PowerShot G11", 0, 0, + { 0 } }, /* don't want the G1 matrix */ { "Canon PowerShot G1", 0, 0, { -4778,9467,2172,4743,-1141,4344,-5146,9908,6077,-1566,11051,557 } }, { "Canon PowerShot G2", 0, 0, @@ -6185,6 +6154,8 @@ { 8795,-2482,-797,-7804,15403,2573,-1422,1996,7082 } }, { "Canon PowerShot S70", 0, 0, { 9976,-3810,-832,-7115,14463,2906,-901,989,7889 } }, + { "Canon PowerShot A470", 0, 0, /* DJC */ + { 12513,-4407,-1242,-2680,10276,2405,-878,2215,4734 } }, { "Canon PowerShot A610", 0, 0, /* DJC */ { 15591,-6402,-1592,-5365,13198,2168,-1300,1824,5075 } }, { "Canon PowerShot A620", 0, 0, /* DJC */ @@ -6199,6 +6170,12 @@ { 14573,-5482,-1546,-1266,9799,1468,-1040,1912,3810 } }, { "Canon PowerShot S3 IS", 0, 0, /* DJC */ { 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } }, + { "Canon PowerShot SX1 IS", 0, 0, + { 6578,-259,-502,-5974,13030,3309,-308,1058,4970 } }, + { "Canon PowerShot SX110 IS", 0, 0, /* DJC */ + { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } }, + { "CASIO EX-S20", 0, 0, /* DJC */ + { 11634,-3924,-1128,-4968,12954,2015,-1588,2648,7206 } }, { "CINE 650", 0, 0, { 3390,480,-500,-800,3610,340,-550,2336,1192 } }, { "CINE 660", 0, 0, @@ -6299,6 +6276,10 @@ { 10511,-3836,-1102,-6946,14587,2558,-1481,1792,6246 } }, { "KODAK P880", 0, 0xfff, { 12805,-4662,-1376,-7480,15267,2360,-1626,2194,7904 } }, + { "KODAK EasyShare Z980", 0, 0, + { 11313,-3559,-1101,-3893,11891,2257,-1214,2398,4908 } }, + { "KODAK EASYSHARE Z1015", 0, 0xef1, + { 11265,-4286,-992,-4694,12343,2647,-1090,1523,5447 } }, { "Leaf CMost", 0, 0, { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } }, { "Leaf Valeo 6", 0, 0, @@ -6333,6 +6314,8 @@ { 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 } }, { "MINOLTA DYNAX 7", 0, 0xffb, { 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } }, + { "MOTOROLA PIXL", 0, 0, /* DJC */ + { 8898,-989,-1033,-3292,11619,1674,-661,3178,5216 } }, { "NIKON D100", 0, 0, { 5902,-933,-782,-8983,16719,2354,-1402,1455,6464 } }, { "NIKON D1H", 0, 0, @@ -6341,14 +6324,26 @@ { 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 } }, { "NIKON D1", 0, 0, /* multiplied by 2.218750, 1.0, 1.148438 */ { 16772,-4726,-2141,-7611,15713,1972,-2846,3494,9521 } }, + { "NIKON D200", 0, 0xfbc, + { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } }, { "NIKON D2H", 0, 0, { 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } }, { "NIKON D2X", 0, 0, { 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 } }, + { "NIKON D3000", 0, 0, + { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } }, + { "NIKON D300", 0, 0, + { 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } }, + { "NIKON D3X", 0, 0, + { 7171,-1986,-648,-8085,15555,2718,-2170,2512,7457 } }, + { "NIKON D3", 0, 0, + { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } }, { "NIKON D40X", 0, 0, { 8819,-2543,-911,-9025,16928,2151,-1329,1213,8449 } }, { "NIKON D40", 0, 0, { 6992,-1668,-806,-8138,15748,2543,-874,850,7897 } }, + { "NIKON D5000", 0, 0xf00, + { 7309,-1403,-519,-8474,16008,2622,-2433,2826,8064 } }, { "NIKON D50", 0, 0, { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, { "NIKON D60", 0, 0, @@ -6361,12 +6356,6 @@ { 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 } }, { "NIKON D90", 0, 0xf00, { 7309,-1403,-519,-8474,16008,2622,-2434,2826,8064 } }, - { "NIKON D200", 0, 0xfbc, - { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } }, - { "NIKON D300", 0, 0, - { 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } }, - { "NIKON D3", 0, 0, - { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } }, { "NIKON E950", 0, 0x3dd, /* DJC */ { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } }, { "NIKON E995", 0, 0, /* copied from E5000 */ @@ -6413,6 +6402,8 @@ { 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } }, { "OLYMPUS E-330", 0, 0, { 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } }, + { "OLYMPUS E-30", 0, 0xfbc, + { 8144,-1861,-1111,-7763,15894,1929,-1865,2542,7607 } }, { "OLYMPUS E-3", 0, 0xf99, { 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } }, { "OLYMPUS E-400", 0, 0xfff0, @@ -6421,12 +6412,18 @@ { 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } }, { "OLYMPUS E-420", 0, 0xfd7, { 8746,-2425,-1095,-7594,15612,2073,-1780,2309,7416 } }, - { "OLYMPUS E-500", 0, 0, + { "OLYMPUS E-450", 0, 0xfd2, + { 8745,-2425,-1095,-7594,15613,2073,-1780,2309,7416 } }, + { "OLYMPUS E-500", 0, 0xfff0, { 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 } }, { "OLYMPUS E-510", 0, 0xf6a, { 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } }, { "OLYMPUS E-520", 0, 0xfd2, { 8344,-2322,-1020,-7596,15635,2048,-1748,2269,7287 } }, + { "OLYMPUS E-620", 0, 0xfb9, + { 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } }, + { "OLYMPUS E-P1", 0, 0xffd, + { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } }, { "OLYMPUS SP350", 0, 0, { 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 } }, { "OLYMPUS SP3", 0, 0, @@ -6461,6 +6458,10 @@ { 9186,-2678,-907,-8693,16517,2260,-1129,1094,8524 } }, { "PENTAX K2000", 0, 0, { 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } }, + { "PENTAX K-m", 0, 0, + { 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } }, + { "PENTAX K-7", 0, 0, + { 9142,-2947,-678,-8648,16967,1663,-2224,2898,8615 } }, { "Panasonic DMC-FZ8", 0, 0xf7f0, { 8986,-2755,-802,-6341,13575,3077,-1476,2144,6379 } }, { "Panasonic DMC-FZ18", 0, 0, @@ -6469,6 +6470,8 @@ { 10109,-3488,-993,-5412,12812,2916,-1305,2140,5543 } }, { "Panasonic DMC-FZ30", 0, 0xf94c, { 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } }, + { "Panasonic DMC-FZ35", 147, 0xfff, + { 9938,-2780,-890,-4604,12393,2480,-1117,2304,4620 } }, { "Panasonic DMC-FZ50", 0, 0xfff0, /* aka "LEICA V-LUX1" */ { 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } }, { "Panasonic DMC-L10", 15, 0xf96, @@ -6487,6 +6490,10 @@ { 9082,-2907,-925,-6119,13377,3058,-1797,2641,5609 } }, { "Panasonic DMC-G1", 15, 0xfff, { 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } }, + { "Panasonic DMC-GF1", 15, 0xf92, + { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } }, + { "Panasonic DMC-GH1", 15, 0xf92, + { 6299,-1466,-532,-6535,13852,2969,-2331,3112,5984 } }, { "Phase One H 20", 0, 0, /* DJC */ { 1313,1855,-109,-6715,15908,808,-327,1840,6020 } }, { "Phase One P 2", 0, 0, @@ -6495,8 +6502,12 @@ { 4516,-245,-37,-7020,14976,2173,-3206,4671,7087 } }, { "Phase One P 45", 0, 0, { 5053,-24,-117,-5684,14076,1702,-2619,4492,5849 } }, + { "Phase One P65", 0, 0, /* DJC */ + { 8522,1268,-1916,-7706,16350,1358,-2397,4344,4923 } }, { "SAMSUNG GX-1", 0, 0, { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } }, + { "SAMSUNG S85", 0, 0, /* DJC */ + { 11885,-3968,-1473,-4214,12299,1916,-835,1655,5549 } }, { "Sinar", 0, 0, /* DJC */ { 16442,-2956,-2422,-2877,12128,750,-1136,6066,4559 } }, { "SONY DSC-F828", 491, 0, @@ -6509,12 +6520,20 @@ { 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } }, { "SONY DSLR-A200", 0, 0, { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } }, + { "SONY DSLR-A230", 0, 0, /* copied */ + { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } }, { "SONY DSLR-A300", 0, 0, { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } }, + { "SONY DSLR-A330", 0, 0, + { 9847,-3091,-929,-8485,16346,2225,-714,595,7103 } }, { "SONY DSLR-A350", 0, 0xffc, { 6038,-1484,-578,-9146,16746,2513,-875,746,7217 } }, + { "SONY DSLR-A380", 0, 0, + { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } }, { "SONY DSLR-A700", 254, 0x1ffe, { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } }, + { "SONY DSLR-A850", 256, 0x1ffe, + { 5209,-1072,-397,-8845,16121,2919,-1618,1802,8654 } }, { "SONY DSLR-A900", 254, 0x1ffe, { 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } } }; @@ -6527,10 +6546,12 @@ if (!strncmp (name, table[i].prefix, strlen(table[i].prefix))) { if (table[i].black) black = (ushort) table[i].black; if (table[i].maximum) maximum = (ushort) table[i].maximum; - for (j=0; j < 4; j++) - for (k=0; k < 3; k++) - cam_xyz[j][k] = table[i].trans[3*j+k] / 10000.0; - cam_xyz_coeff (cam_xyz); + if (table[i].trans[0]) { + for (j=0; j < 4; j++) + for (k=0; k < 3; k++) + cam_xyz[j][k] = table[i].trans[3*j+k] / 10000.0; + cam_xyz_coeff (cam_xyz); + } break; } } @@ -6574,6 +6595,31 @@ return sum[0] < sum[1] ? 0x4d4d : 0x4949; } +float CLASS find_green (int bps, int bite, int off0, int off1) +{ + UINT64 bitbuf=0; + int vbits, col, i, c; + ushort img[2][2064]; + double sum[]={0,0}; + + FORC(2) { + fseek (ifp, c ? off1:off0, SEEK_SET); + for (vbits=col=0; col < width; col++) { + for (vbits -= bps; vbits < 0; vbits += bite) { + bitbuf <<= bite; + for (i=0; i < bite; i+=8) + bitbuf |= (unsigned) (fgetc(ifp) << i); + } + img[c][col] = bitbuf << (64-bps-vbits) >> (64-bps); + } + } + FORC(width-1) { + sum[ c & 1] += ABS(img[0][c]-img[1][c+1]); + sum[~c & 1] += ABS(img[1][c]-img[0][c+1]); + } + return 100 * log(sum[0]/sum[1]); +} + /* Identify which camera created this file, and set global variables accordingly. @@ -6581,7 +6627,8 @@ void CLASS identify() { char head[32], *cp; - unsigned hlen, fsize, i, c, is_canon; + int hlen, i, c, is_canon; + unsigned fsize; struct jhead jh; static const struct { unsigned fsize; @@ -6598,7 +6645,6 @@ { 6166488, "Kodak", "C603" ,0 }, { 9116448, "Kodak", "C603y" ,0 }, { 311696, "ST Micro", "STV680 VGA" ,0 }, /* SPYz */ - { 614400, "Kodak", "KAI-0340" ,0 }, { 787456, "Creative", "PC-CAM 600" ,0 }, { 1138688, "Minolta", "RD175" ,0 }, { 3840000, "Foculus", "531C" ,0 }, @@ -6618,12 +6664,14 @@ { 6653280, "Canon", "PowerShot A530" ,0 }, { 6573120, "Canon", "PowerShot A610" ,0 }, { 9219600, "Canon", "PowerShot A620" ,0 }, + { 9243240, "Canon", "PowerShot A470" ,0 }, { 10341600, "Canon", "PowerShot A720" ,0 }, { 10383120, "Canon", "PowerShot A630" ,0 }, { 12945240, "Canon", "PowerShot A640" ,0 }, { 15636240, "Canon", "PowerShot A650" ,0 }, { 5298000, "Canon", "PowerShot SD300" ,0 }, { 7710960, "Canon", "PowerShot S3 IS" ,0 }, + { 15467760, "Canon", "PowerShot SX110 IS",0 }, { 5939200, "OLYMPUS", "C770UZ" ,0 }, { 1581060, "NIKON", "E900" ,1 }, /* or E900s,E910 */ { 2465792, "NIKON", "E950" ,1 }, /* or E800,E700 */ @@ -6640,9 +6688,13 @@ { 6054400, "CASIO", "QV-R41" ,1 }, { 7530816, "CASIO", "QV-R51" ,1 }, { 7684000, "CASIO", "QV-4000" ,1 }, + { 2937856, "CASIO", "EX-S20" ,1 }, { 4948608, "CASIO", "EX-S100" ,1 }, { 7542528, "CASIO", "EX-Z50" ,1 }, { 7753344, "CASIO", "EX-Z55" ,1 }, + { 7816704, "CASIO", "EX-Z60" ,1 }, + { 10843712, "CASIO", "EX-Z75" ,1 }, + { 12310144, "CASIO", "EX-Z850" ,1 }, { 7426656, "CASIO", "EX-P505" ,1 }, { 9313536, "CASIO", "EX-P600" ,1 }, { 10979200, "CASIO", "EX-P700" ,1 }, @@ -6650,13 +6702,16 @@ { 4841984, "PENTAX", "Optio S" ,1 }, { 6114240, "PENTAX", "Optio S4" ,1 }, /* or S4i, CASIO EX-Z4 */ { 10702848, "PENTAX", "Optio 750Z" ,1 }, + { 15980544, "AGFAPHOTO","DC-833m" ,1 }, + { 16098048, "SAMSUNG", "S85" ,1 }, + { 16215552, "SAMSUNG", "S85" ,1 }, { 12582980, "Sinar", "" ,0 }, { 33292868, "Sinar", "" ,0 }, { 44390468, "Sinar", "" ,0 } }; static const char *corp[] = { "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX", "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One", - "SAMSUNG", "Mamiya" }; + "SAMSUNG", "Mamiya", "MOTOROLA" }; tiff_flip = flip = filters = (unsigned)-1; /* 0 is valid, so -1 is unknown */ raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0; @@ -6672,7 +6727,7 @@ kodak_cbpp = zero_after_ff = dng_version = load_flags = 0; timestamp = shot_order = tiff_samples = black = is_foveon = 0; mix_green = profile_length = data_error = zero_is_bad = 0; - pixel_aspect = is_raw = raw_color = use_gamma = 1; + pixel_aspect = is_raw = raw_color = 1; tile_width = tile_length = INT_MAX; for (i=0; i < 4; i++) { cam_mul[i] = i == 1; @@ -6681,7 +6736,6 @@ FORC3 rgb_cam[c][i] = c == i; } colors = 3; - tiff_bps = 12; for (i=0; i < 0x4000; i++) curve[i] = i; tone_curve_offset = tone_curve_size = 0; /*UF*/ order = 0; // Suppress a valgrind error @@ -6767,7 +6821,7 @@ else if (!memcmp (head,"CI",2)) parse_cine(); else - for (i=0; i < sizeof table / sizeof *table; i++) + for (i=0; i < (int) sizeof table / (int) sizeof *table; i++) if (fsize == table[i].fsize) { strcpy (make, table[i].make ); strcpy (model, table[i].model); @@ -6777,11 +6831,14 @@ if (make[0] == 0) parse_smal (0, fsize); if (make[0] == 0) parse_jpeg (is_raw = 0); - for (i=0; i < sizeof corp / sizeof *corp; i++) + for (i=0; i < (int) sizeof corp / (int) sizeof *corp; i++) if (strstr (make, corp[i])) /* Simplify company names */ strcpy (make, corp[i]); - if (!strncmp (make,"KODAK",5)) - make[16] = model[16] = 0; + if (!strncmp (make,"KODAK",5) && + ((cp = strstr(model," DIGITAL CAMERA")) || + (cp = strstr(model," Digital Camera")) || + (cp = strstr(model,"FILE VERSION")))) + *cp = 0; cp = make + strlen(make); /* Remove trailing spaces */ while (*--cp == ' ') *cp = 0; cp = model + strlen(model); @@ -6794,7 +6851,6 @@ desc[511] = artist[63] = make[63] = model[63] = model2[63] = 0; if (!is_raw) goto notraw; - if (!maximum) maximum = (1 << tiff_bps) - 1; if (!height) height = raw_height; if (!width) width = raw_width; if (fuji_width) { @@ -6806,6 +6862,9 @@ { height = 2616; width = 3896; } if (height == 3136 && width == 4864) /* Pentax K20D */ { height = 3124; width = 4688; } + if (height == 3136 && width == 4736) /* Pentax K-7 */ + { height = 3122; width = 4684; + top_margin = 2; filters = 0x16161616; } if (height == 3014 && width == 4096) /* Ricoh GX200 */ width = 4014; if (dng_version) { @@ -6823,12 +6882,12 @@ &CLASS lossless_jpeg_load_raw : &CLASS canon_compressed_load_raw; if (!strcmp(make,"NIKON")) { if (!load_raw) - load_raw = &CLASS packed_12_load_raw; + load_raw = &CLASS packed_load_raw; if (model[0] == 'E') load_flags |= !data_offset << 2 | 2; } if (!strcmp(make,"CASIO")) { - load_raw = &CLASS packed_12_load_raw; + load_raw = &CLASS packed_load_raw; maximum = 0xf7f; } @@ -6863,20 +6922,20 @@ pixel_aspect = 256/235.0; colors = 4; filters = 0x1e4e1e4e; - load_raw = &CLASS canon_a5_load_raw; + goto canon_a5; } else if (!strcmp(model,"PowerShot A50")) { height = 968; width = 1290; raw_width = 1320; colors = 4; filters = 0x1b4e4b1e; - load_raw = &CLASS canon_a5_load_raw; + goto canon_a5; } else if (!strcmp(model,"PowerShot Pro70")) { height = 1024; width = 1552; colors = 4; filters = 0x1e4b4e1b; - load_raw = &CLASS canon_a5_load_raw; + goto canon_a5; } else if (!strcmp(model,"PowerShot SD300")) { height = 1752; width = 2344; @@ -6884,7 +6943,7 @@ raw_width = 2400; top_margin = 12; left_margin = 12; - load_raw = &CLASS canon_a5_load_raw; + goto canon_a5; } else if (!strcmp(model,"PowerShot A460")) { height = 1960; width = 2616; @@ -6892,7 +6951,7 @@ raw_width = 2664; top_margin = 4; left_margin = 4; - load_raw = &CLASS canon_a5_load_raw; + goto canon_a5; } else if (!strcmp(model,"PowerShot A530")) { height = 1984; width = 2620; @@ -6900,8 +6959,7 @@ raw_width = 2672; top_margin = 6; left_margin = 10; - load_raw = &CLASS canon_a5_load_raw; - raw_color = 0; + goto canon_a5; } else if (!strcmp(model,"PowerShot A610")) { if (canon_s2is()) strcpy (model+10, "S2 IS"); height = 1960; @@ -6910,7 +6968,7 @@ raw_width = 2672; top_margin = 8; left_margin = 12; - load_raw = &CLASS canon_a5_load_raw; + goto canon_a5; } else if (!strcmp(model,"PowerShot A620")) { height = 2328; width = 3112; @@ -6918,7 +6976,15 @@ raw_width = 3152; top_margin = 12; left_margin = 36; - load_raw = &CLASS canon_a5_load_raw; + goto canon_a5; + } else if (!strcmp(model,"PowerShot A470")) { + height = 2328; + width = 3096; + raw_height = 2346; + raw_width = 3152; + top_margin = 6; + left_margin = 12; + goto canon_a5; } else if (!strcmp(model,"PowerShot A720")) { height = 2472; width = 3298; @@ -6926,7 +6992,7 @@ raw_width = 3336; top_margin = 5; left_margin = 6; - load_raw = &CLASS canon_a5_load_raw; + goto canon_a5; } else if (!strcmp(model,"PowerShot A630")) { height = 2472; width = 3288; @@ -6934,7 +7000,7 @@ raw_width = 3344; top_margin = 6; left_margin = 12; - load_raw = &CLASS canon_a5_load_raw; + goto canon_a5; } else if (!strcmp(model,"PowerShot A640")) { height = 2760; width = 3672; @@ -6942,7 +7008,7 @@ raw_width = 3736; top_margin = 6; left_margin = 12; - load_raw = &CLASS canon_a5_load_raw; + goto canon_a5; } else if (!strcmp(model,"PowerShot A650")) { height = 3024; width = 4032; @@ -6950,7 +7016,7 @@ raw_width = 4104; top_margin = 12; left_margin = 48; - load_raw = &CLASS canon_a5_load_raw; + goto canon_a5; } else if (!strcmp(model,"PowerShot S3 IS")) { height = 2128; width = 2840; @@ -6958,7 +7024,21 @@ raw_width = 2888; top_margin = 8; left_margin = 44; - load_raw = &CLASS canon_a5_load_raw; +canon_a5: + tiff_bps = 10; + load_raw = &CLASS packed_load_raw; + load_flags = 40; + if (raw_width > 1600) zero_is_bad = 1; + } else if (!strcmp(model,"PowerShot SX110 IS")) { + height = 2760; + width = 3684; + raw_height = 2772; + raw_width = 3720; + top_margin = 12; + left_margin = 6; + load_raw = &CLASS packed_load_raw; + load_flags = 40; + zero_is_bad = 1; } else if (!strcmp(model,"PowerShot Pro90 IS")) { width = 1896; colors = 4; @@ -7017,6 +7097,11 @@ top_margin = 12; left_margin = 74; goto canon_cr2; + } else if (is_canon && raw_width == 3744) { + height = 2760; + width = 3684; + top_margin = 16; + left_margin = 8; } else if (is_canon && raw_width == 3944) { height = 2602; width = 3908; @@ -7041,6 +7126,10 @@ width = 4032; top_margin = 12; left_margin = 48; + } else if (is_canon && raw_width == 4152) { + top_margin = 12; + left_margin = 192; + goto canon_cr2; } else if (is_canon && raw_width == 4312) { top_margin = 18; left_margin = 22; @@ -7059,12 +7148,14 @@ left_margin = 12; filters = 0x49494949; } else if (is_canon && raw_width == 1208) { - top_margin = 51; + top_margin = unique_id == 0x80000261 ? 51:26; left_margin = 62; raw_width = width *= 4; + if (unique_id == 0x80000252) + adobe_coeff ("Canon","EOS 500D"); goto canon_cr2; - } else if (is_canon && raw_width == 1448) { - top_margin = 51; + } else if (is_canon && raw_width == 1340) { + top_margin = 51; left_margin = 158; raw_width = width *= 4; goto canon_cr2; @@ -7092,13 +7183,16 @@ pixel_aspect = 0.5; } else if (!strcmp(model,"D40X") || !strcmp(model,"D60") || - !strcmp(model,"D80")) { + !strcmp(model,"D80") || + !strcmp(model,"D3000")) { height -= 3; width -= 4; } else if (!strcmp(model,"D3") || !strcmp(model,"D700")) { width -= 4; left_margin = 2; + } else if (!strcmp(model,"D5000")) { + width -= 42; } else if (!strncmp(model,"D40",3) || !strncmp(model,"D50",3) || !strncmp(model,"D70",3)) { @@ -7107,8 +7201,8 @@ width -= 42; } else if (!strcmp(model,"D100")) { if (tiff_compress == 34713 && !nikon_is_compressed()) { - load_raw = &CLASS packed_12_load_raw; - load_flags |= 8; + load_raw = &CLASS packed_load_raw; + load_flags |= 1; raw_width = (width += 3) + 3; } } else if (!strcmp(model,"D200")) { @@ -7121,16 +7215,15 @@ } else if (!strncmp(model,"D2X",3)) { if (width == 3264) width -= 32; else width -= 8; - } else if (!strcmp(model,"D300")) { + } else if (!strncmp(model,"D300",4)) { width -= 32; } else if (!strcmp(model,"COOLPIX P6000")) { - load_flags = 1; + load_flags = 24; filters = 0x94949494; } else if (fsize == 1581060) { height = 963; width = 1287; raw_width = 1632; - load_raw = &CLASS nikon_e900_load_raw; maximum = 0x3f4; colors = 4; filters = 0x1e1e1e1e; @@ -7138,20 +7231,24 @@ pre_mul[0] = 1.2085; pre_mul[1] = 1.0943; pre_mul[3] = 1.1103; + goto e900; } else if (fsize == 2465792) { height = 1203; width = 1616; raw_width = 2048; - load_raw = &CLASS nikon_e900_load_raw; colors = 4; filters = 0x4b4b4b4b; adobe_coeff ("NIKON","E950"); +e900: + tiff_bps = 10; + load_raw = &CLASS packed_load_raw; + load_flags = 6; } else if (fsize == 4771840) { height = 1540; width = 2064; colors = 4; filters = 0xe1e1e1e1; - load_raw = &CLASS packed_12_load_raw; + load_raw = &CLASS packed_load_raw; load_flags = 6; if (!timestamp && nikon_e995()) strcpy (model, "E995"); @@ -7166,7 +7263,7 @@ if (!timestamp && !nikon_e2100()) goto cp_e2500; height = 1206; width = 1616; - load_flags = 7; + load_flags = 30; } else if (!strcmp(model,"E2500")) { cp_e2500: strcpy (model, "E2500"); @@ -7177,18 +7274,23 @@ } else if (fsize == 4775936) { height = 1542; width = 2064; - load_raw = &CLASS packed_12_load_raw; - load_flags = 7; - pre_mul[0] = 1.818; - pre_mul[2] = 1.618; + load_raw = &CLASS packed_load_raw; + load_flags = 30; if (!timestamp) nikon_3700(); if (model[0] == 'E' && atoi(model+1) < 3700) filters = 0x49494949; if (!strcmp(model,"Optio 33WR")) { flip = 1; filters = 0x16161616; - pre_mul[0] = 1.331; - pre_mul[2] = 1.820; + } + if (make[0] == 'O') { + i = find_green (12, 32, 0, fsize/2); + c = find_green (12, 32, 0, 3096); + if (abs(i) < abs(c)) { + SWAP(i,c); + load_flags = 24; + } + if (i < 0) filters = 0x61616161; } } else if (fsize == 5869568) { height = 1710; @@ -7198,8 +7300,8 @@ strcpy (make, "Minolta"); strcpy (model,"DiMAGE Z2"); } - load_raw = &CLASS packed_12_load_raw; - load_flags = 6 + (make[0] == 'M'); + load_raw = &CLASS packed_load_raw; + load_flags = 6 + 24*(make[0] == 'M'); } else if (!strcmp(model,"E4500")) { height = 1708; width = 2288; @@ -7214,8 +7316,8 @@ height = 2118; width = 2832; maximum = 0xf83; - load_raw = &CLASS packed_12_load_raw; - load_flags = 7; + load_raw = &CLASS packed_load_raw; + load_flags = 30; } else if (!strcmp(model,"FinePix S5100") || !strcmp(model,"FinePix S5500")) { height -= top_margin = 6; @@ -7260,13 +7362,14 @@ if (!strncmp(model,"DiMAGE A",8)) { if (!strcmp(model,"DiMAGE A200")) filters = 0x49494949; - load_raw = &CLASS packed_12_load_raw; + tiff_bps = 12; + load_raw = &CLASS packed_load_raw; } else if (!strncmp(model,"ALPHA",5) || !strncmp(model,"DYNAX",5) || !strncmp(model,"MAXXUM",6)) { sprintf (model+20, "DYNAX %-10s", model+6+(model[0]=='M')); adobe_coeff (make, model+20); - load_raw = &CLASS packed_12_load_raw; + load_raw = &CLASS packed_load_raw; } else if (!strncmp(model,"DiMAGE G",8)) { if (model[8] == '4') { height = 1716; @@ -7287,6 +7390,10 @@ maximum = 0x3df; order = 0x4d4d; } +#if 0 + } else if (!strcmp(model,"*ist D")) { + data_error = -1; +#endif } else if (!strcmp(model,"*ist DS")) { height -= 2; } else if (!strcmp(model,"K20D")) { @@ -7298,30 +7405,38 @@ load_raw = &CLASS eight_bit_load_raw; cam_mul[0] *= 4; cam_mul[2] *= 4; - pre_mul[0] = 1.391; - pre_mul[2] = 1.188; } else { height = 1544; width = 2068; raw_width = 3136; - load_raw = &CLASS packed_12_load_raw; + load_raw = &CLASS packed_load_raw; maximum = 0xf7c; - pre_mul[0] = 1.137; - pre_mul[2] = 1.453; } } else if (fsize == 6114240) { height = 1737; width = 2324; raw_width = 3520; - load_raw = &CLASS packed_12_load_raw; + load_raw = &CLASS packed_load_raw; maximum = 0xf7a; - pre_mul[0] = 1.980; - pre_mul[2] = 1.570; } else if (!strcmp(model,"Optio 750Z")) { height = 2302; width = 3072; - load_raw = &CLASS packed_12_load_raw; - load_flags = 7; + load_raw = &CLASS packed_load_raw; + load_flags = 30; + } else if (!strcmp(model,"DC-833m")) { + height = 2448; + width = 3264; + order = 0x4949; + filters = 0x61616161; + load_raw = &CLASS unpacked_load_raw; + maximum = 0xfc00; + } else if (!strncmp(model,"S85",3)) { + height = 2448; + width = 3264; + raw_width = fsize/height/2; + order = 0x4d4d; + load_raw = &CLASS unpacked_load_raw; + maximum = 0xffff; } else if (!strcmp(model,"STV680 VGA")) { height = 484; width = 644; @@ -7329,16 +7444,6 @@ flip = 2; filters = 0x16161616; black = 16; - pre_mul[0] = 1.097; - pre_mul[2] = 1.128; - } else if (!strcmp(model,"KAI-0340")) { - height = 477; - width = 640; - order = 0x4949; - data_offset = 3840; - load_raw = &CLASS unpacked_load_raw; - pre_mul[0] = 1.561; - pre_mul[2] = 2.454; } else if (!strcmp(model,"N95")) { height = raw_height - (top_margin = 2); } else if (!strcmp(model,"531C")) { @@ -7346,7 +7451,6 @@ width = 1600; load_raw = &CLASS unpacked_load_raw; filters = 0x49494949; - pre_mul[1] = 1.218; } else if (!strcmp(model,"F-080C")) { height = 768; width = 1024; @@ -7399,8 +7503,6 @@ filters = 0x61616161; load_raw = &CLASS unpacked_load_raw; maximum = 0x3ff; - pre_mul[0] = 1.717; - pre_mul[2] = 1.138; fseek (ifp, 0x300000, SEEK_SET); if ((order = guess_byte_order(0x10000)) == 0x4d4d) { height -= (top_margin = 16); @@ -7418,6 +7520,11 @@ top_margin = 4; left_margin = 7; filters = 0x61616161; + } else if (raw_width == 4090) { + strcpy (model, "V96C"); + height -= (top_margin = 6); + width -= (left_margin = 3) + 7; + filters = 0x61616161; } } else if (!strcmp(make,"Sinar")) { if (!memcmp(head,"8BPS",4)) { @@ -7513,14 +7620,14 @@ zero_is_bad = 1; adobe_coeff ("Panasonic","DMC-FZ18"); break; case 3690: - height += 36; + height -= 2; left_margin = (ushort)-14; - filters = 0x49494949; maximum = 0xf7f0; case 3770: width = 3672; - if ((height -= 39) == 2760) + if (--height == 2798 && (height = 2760)) top_margin = 15; + else filters = 0x49494949; left_margin += 17; zero_is_bad = 1; adobe_coeff ("Panasonic","DMC-FZ50"); break; @@ -7530,6 +7637,7 @@ adobe_coeff ("Panasonic","DMC-L10"); break; case 3724: width -= 14; + if (height == 2450) height -= 2; case 3836: width -= 42; lx3: filters = 0x16161616; @@ -7545,9 +7653,20 @@ width = 3982; if (height == 2250) goto lx3; width = 4018; + filters = 0x16161616; + if (!strncmp(model,"DMC-FZ3",7)) { + height -= 2; + adobe_coeff ("Panasonic","DMC-FZ35"); break; + } filters = 0x49494949; + if (!strcmp(model,"DMC-GH1")) break; zero_is_bad = 1; adobe_coeff ("Panasonic","DMC-G1"); break; + case 4172: + case 4396: + width -= 28; + filters = 0x49494949; + adobe_coeff ("Panasonic","DMC-GH1"); break; case 4290: height += 38; left_margin = (ushort)-14; @@ -7568,12 +7687,14 @@ height = 1718; width = 2304; filters = 0x16161616; - load_raw = &CLASS packed_12_load_raw; - load_flags = 7; + load_raw = &CLASS packed_load_raw; + load_flags = 30; } else if (!strcmp(make,"OLYMPUS")) { height += height & 1; filters = exif_cfa; - if (load_raw == &CLASS olympus_e410_load_raw) { + if (width == 4100) width -= 4; + if (load_raw == &CLASS olympus_load_raw) { + tiff_bps = 12; black >>= 4; } else if (!strcmp(model,"E-10") || !strncmp(model,"E-20",4)) { @@ -7599,7 +7720,7 @@ width = 3072; filters = 0x61616161; data_offset = 0x1a00; - load_raw = &CLASS packed_12_load_raw; + load_raw = &CLASS packed_load_raw; } else if (!strcmp(model,"DSC-F828")) { width = 3288; left_margin = 5; @@ -7619,18 +7740,30 @@ order = 0x4d4d; } else if (!strcmp(model,"DSLR-A100")) { height--; + width = ++raw_width; + filters = 0x61616161; } else if (!strcmp(model,"DSLR-A350")) { height -= 4; + } else if (!strcmp(model,"PIXL")) { + height -= top_margin = 4; + width -= left_margin = 32; + gamma_curve (0, 7, 1, 255); } else if (!strcmp(model,"C603v")) { height = 480; width = 640; - goto c603v; + if (fsize < 614400 || find_green (16, 16, 3840, 5120) < 25) goto c603v; + strcpy (model,"KAI-0340"); + height -= 3; + data_offset = 3840; + order = 0x4949; + load_raw = &CLASS unpacked_load_raw; } else if (!strcmp(model,"C603y")) { height = 2134; width = 2848; c603v: filters = 0; load_raw = &CLASS kodak_yrgb_load_raw; + gamma_curve (0, 3.875, 1, 255); } else if (!strcmp(model,"C603")) { raw_height = height = 2152; raw_width = width = 2864; @@ -7647,8 +7780,18 @@ if ((data_offset = fsize - raw_height*raw_width)) { fseek (ifp, 168, SEEK_SET); read_shorts (curve, 256); - } else use_gamma = 0; + } else gamma_curve (0, 3.875, 1, 255); load_raw = &CLASS eight_bit_load_raw; + } else if (!strcmp(model,"EASYSHARE Z1015 IS")) { + height = 2742; + width = 3664; + goto ezshare; + } else if (!strcmp(model,"EasyShare Z980")) { + height = 3006; + width = 4016; +ezshare: + data_offset = 0x15000; + load_raw = &CLASS packed_load_raw; } else if (!strcasecmp(make,"KODAK")) { if (filters == UINT_MAX) filters = 0x61616161; if (!strncmp(model,"NC2000",6)) { @@ -7663,7 +7806,8 @@ } else if (!strcmp(model,"DCS420")) { width -= 4; left_margin = 2; - } else if (!strcmp(model,"DCS460")) { + } else if (!strncmp(model,"DCS460 ",7)) { + model[6] = 0; width -= 4; left_margin = 2; } else if (!strcmp(model,"DCS460A")) { @@ -7679,6 +7823,8 @@ colors = 1; filters = 0; } + if (!strcmp(model+4,"20X")) + strcpy (cdesc, "MYCY"); if (strstr(model,"DC25")) { strcpy (model, "DC25"); data_offset = 15424; @@ -7739,14 +7885,21 @@ filters = 0x61616161; simple_coeff(2); } else if (!strcmp(model,"QuickTake 100")) { - data_offset = 736; + fseek (ifp, 544, SEEK_SET); + height = get2(); + width = get2(); + data_offset = (get4(),get2()) == 30 ? 738:736; + if (height > width) { + SWAP(height,width); + fseek (ifp, data_offset-6, SEEK_SET); + flip = ~get2() & 3 ? 5:6; + } load_raw = &CLASS quicktake_100_load_raw; - goto qt_common; + filters = 0x61616161; } else if (!strcmp(model,"QuickTake 150")) { data_offset = 738 - head[5]; if (head[5]) strcpy (model+10, "200"); load_raw = &CLASS kodak_radc_load_raw; -qt_common: height = 480; width = 640; filters = 0x61616161; @@ -7766,15 +7919,11 @@ } filters = 0x16161616; load_raw = &CLASS rollei_load_raw; - pre_mul[0] = 1.8; - pre_mul[2] = 1.3; } else if (!strcmp(model,"PC-CAM 600")) { height = 768; data_offset = width = 1024; filters = 0x49494949; load_raw = &CLASS eight_bit_load_raw; - pre_mul[0] = 1.14; - pre_mul[2] = 2.73; } else if (!strcmp(model,"QV-2000UX")) { height = 1208; width = 1632; @@ -7793,7 +7942,8 @@ } else if (!strcmp(model,"QV-5700")) { height = 1924; width = 2576; - load_raw = &CLASS casio_qv5700_load_raw; + raw_width = 3232; + tiff_bps = 10; } else if (!strcmp(model,"QV-R41")) { height = 1720; width = 2312; @@ -7803,50 +7953,59 @@ height = 1926; width = 2580; raw_width = 3904; - pre_mul[0] = 1.340; - pre_mul[2] = 1.672; + } else if (!strcmp(model,"EX-S20")) { + height = 1208; + width = 1620; + raw_width = 2432; + flip = 3; } else if (!strcmp(model,"EX-S100")) { height = 1544; width = 2058; raw_width = 3136; - pre_mul[0] = 1.631; - pre_mul[2] = 1.106; } else if (!strcmp(model,"EX-Z50")) { height = 1931; width = 2570; raw_width = 3904; - pre_mul[0] = 2.529; - pre_mul[2] = 1.185; } else if (!strcmp(model,"EX-Z55")) { height = 1960; width = 2570; raw_width = 3904; - pre_mul[0] = 1.520; - pre_mul[2] = 1.316; + } else if (!strcmp(model,"EX-Z60")) { + height = 2145; + width = 2833; + raw_width = 3584; + filters = 0x16161616; + tiff_bps = 10; + } else if (!strcmp(model,"EX-Z75")) { + height = 2321; + width = 3089; + raw_width = 4672; + maximum = 0xfff; + } else if (!strcmp(model,"EX-Z850")) { + height = 2468; + width = 3279; + raw_width = 4928; + maximum = 0xfff; } else if (!strcmp(model,"EX-P505")) { height = 1928; width = 2568; raw_width = 3852; maximum = 0xfff; - pre_mul[0] = 2.07; - pre_mul[2] = 1.88; } else if (fsize == 9313536) { /* EX-P600 or QV-R61 */ height = 2142; width = 2844; raw_width = 4288; - pre_mul[0] = 1.797; - pre_mul[2] = 1.219; } else if (!strcmp(model,"EX-P700")) { height = 2318; width = 3082; raw_width = 4672; - pre_mul[0] = 1.758; - pre_mul[2] = 1.504; } if (!model[0]) sprintf (model, "%dx%d", width, height); if (filters == UINT_MAX) filters = 0x94949494; if (raw_color) adobe_coeff (make, model); + if (load_raw == &CLASS kodak_radc_load_raw) + if (raw_color) adobe_coeff ("Apple","Quicktake"); if (thumb_offset && !thumb_height) { fseek (ifp, thumb_offset, SEEK_SET); if (ljpeg_start (&jh, 1)) { @@ -7855,6 +8014,8 @@ } } dng_skip: + if (!tiff_bps) tiff_bps = 12; + if (!maximum) maximum = (1 << tiff_bps) - 1; if (!load_raw || height < 22) is_raw = 0; #ifndef HAVE_LIBJPEG if (load_raw == &CLASS kodak_jpeg_load_raw) { @@ -7973,6 +8134,7 @@ static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc }; unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 }; + gamma_curve (gamm[0], gamm[1], 0, 0); memcpy (out_cam, rgb_cam, sizeof out_cam); raw_color |= colors == 1 || document_mode || output_color < 1 || output_color > 5; @@ -7990,12 +8152,7 @@ memcpy (oprof+32, pbody, sizeof pbody); oprof[pbody[5]/4+2] = strlen(name[output_color-1]) + 1; memcpy ((char *)oprof+pbody[8]+8, pwhite, sizeof pwhite); - if (output_bps == 8) -#ifdef SRGB_GAMMA - pcurve[3] = 0x2330000; -#else - pcurve[3] = 0x1f00000; -#endif + pcurve[3] = (short)(256/gamm[5]+0.5) << 16; for (i=4; i < 7; i++) memcpy ((char *)oprof+pbody[i*3+2], pcurve, sizeof pcurve); pseudoinverse ((double (*)[3]) out_rgb[output_color-1], inverse, 3); @@ -8123,33 +8280,6 @@ return row * iwidth + col; } -void CLASS gamma_lut (uchar lut[0x10000]) -{ - int perc, c, val, total, i; - float white=0, r; - - perc = (int)(width * height * 0.01); /* 99th percentile white level */ - if (fuji_width) perc /= 2; - if ((highlight & ~2) || no_auto_bright) perc = -1; - FORCC { - for (val=0x2000, total=0; --val > 32; ) - if ((total += histogram[c][val]) > perc) break; - if (white < val) white = val; - } - white *= 8 / bright; - for (i=0; i < 0x10000; i++) { - r = i / white; - val = (int)(256 * ( !use_gamma ? r : -#ifdef SRGB_GAMMA - r <= 0.00304 ? r*12.92 : pow(r,2.5/6)*1.055-0.055 )); -#else - r <= 0.018 ? r*4.5 : pow(r,0.45)*1.099-0.099 )); -#endif - if (val > 255) val = 255; - lut[i] = val; - } -} - struct tiff_tag { ushort tag, type; int count; @@ -8265,7 +8395,7 @@ strncpy (th->artist, artist, 64); } -void CLASS jpeg_thumb (FILE *tfp) +void CLASS jpeg_thumb() { char *thumb; ushort exif[5]; @@ -8274,26 +8404,36 @@ thumb = (char *) malloc (thumb_length); merror (thumb, "jpeg_thumb()"); fread (thumb, 1, thumb_length, ifp); - fputc (0xff, tfp); - fputc (0xd8, tfp); + fputc (0xff, ofp); + fputc (0xd8, ofp); if (strcmp (thumb+6, "Exif")) { memcpy (exif, "\xff\xe1 Exif\0\0", 10); exif[1] = htons (8 + sizeof th); - fwrite (exif, 1, sizeof exif, tfp); + fwrite (exif, 1, sizeof exif, ofp); tiff_head (&th, 0); - fwrite (&th, 1, sizeof th, tfp); + fwrite (&th, 1, sizeof th, ofp); } - fwrite (thumb+2, 1, thumb_length-2, tfp); + fwrite (thumb+2, 1, thumb_length-2, ofp); free (thumb); } -void CLASS write_ppm_tiff (FILE *ofp) +void CLASS write_ppm_tiff() { struct tiff_hdr th; - uchar *ppm, lut[0x10000]; + uchar *ppm; ushort *ppm2; int c, row, col, soff, rstep, cstep; + int perc, val, total, white=0x2000; + perc = width * height * 0.01; /* 99th percentile white level */ + if (fuji_width) perc /= 2; + if (!((highlight & ~2) || no_auto_bright)) + for (white=c=0; c < colors; c++) { + for (val=0x2000, total=0; --val > 32; ) + if ((total += histogram[c][val]) > perc) break; + if (white < val) white = val; + } + gamma_curve (gamm[0], gamm[1], 2, (white << 3)/bright); iheight = height; iwidth = width; if (flip & 4) SWAP(height,width); @@ -8312,16 +8452,14 @@ else fprintf (ofp, "P%d\n%d %d\n%d\n", colors/2+5, width, height, (1 << output_bps)-1); - - if (output_bps == 8) gamma_lut (lut); soff = flip_index (0, 0); cstep = flip_index (0, 1) - soff; rstep = flip_index (1, 0) - flip_index (0, width); for (row=0; row < height; row++, soff += rstep) { for (col=0; col < width; col++, soff += cstep) if (output_bps == 8) - FORCC ppm [col*colors+c] = lut[image[soff][c]]; - else FORCC ppm2[col*colors+c] = image[soff][c]; + FORCC ppm [col*colors+c] = curve[image[soff][c]] >> 8; + else FORCC ppm2[col*colors+c] = curve[image[soff][c]]; if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa) swab ((const char *)ppm2, (char *)ppm2, width*colors*2); /*mingw UF*/ fwrite (ppm, colors*output_bps/8, width, ofp); @@ -8337,16 +8475,15 @@ static int timestamp_only=0, thumbnail_only=0, identify_only=0; static int user_qual=-1, user_black=-1, user_sat=-1, user_flip=-1; static int use_fuji_rotate=1, write_to_stdout=0, quality, i, c; - static char opm, opt, *ofname, *cp, *bpfile=0; - static const char *sp, *dark_frame=0, *write_ext; + static const char *sp, *bpfile=0, *dark_frame=0, *write_ext; + static char opm, opt, *ofname, *cp; static struct utimbuf ut; - static FILE *ofp; #ifndef NO_LCMS static const char *cam_profile=0, *out_profile=0; #endif #ifndef LOCALTIME - putenv (const_cast("TZ=UTC")); + putenv ((char *) "TZ=UTC"); #endif #ifdef LOCALEDIR setlocale (LC_CTYPE, ""); @@ -8388,12 +8525,14 @@ puts(_("-j Don't stretch or rotate raw pixels")); puts(_("-W Don't automatically brighten the image")); puts(_("-b Adjust brightness (default = 1.0)")); + puts(_("-g

Set custom gamma curve (default = 2.222 4.5)")); puts(_("-q [0-3] Set the interpolation quality")); puts(_("-h Half-size color image (twice as fast as \"-q 0\")")); puts(_("-f Interpolate RGGB as four colors")); puts(_("-m Apply a 3x3 median filter to R-G and B-G")); puts(_("-s [0..N-1] Select one raw image or \"all\" from each file")); - puts(_("-4 Write 16-bit linear instead of 8-bit with gamma")); + puts(_("-6 Write 16-bit instead of 8-bit")); + puts(_("-4 Linear 16-bit, same as \"-6 -W -g 1 1\"")); puts(_("-T Write TIFF instead of PPM")); puts(""); return 1; @@ -8401,8 +8540,8 @@ argv[argc] = ""; for (arg=1; (((opm = argv[arg][0]) - 2) | 2) == '+'; ) { opt = argv[arg++][1]; - if ((cp = strchr (sp="nbrkStqmHAC", opt))) - for (i=0; i < "11411111142"[cp-sp]-'0'; i++) + if ((cp = (char *) strchr (sp="nbrkStqmHACg", opt))) + for (i=0; i < "114111111422"[cp-sp]-'0'; i++) if (!isdigit(argv[arg+i][0])) { dcraw_message (DCRAW_ERROR,_("Non-numeric argument to \"-%c\"\n"), opt); return 1; @@ -8414,6 +8553,9 @@ FORC4 user_mul[c] = atof(argv[arg++]); break; case 'C': aber[0] = 1 / atof(argv[arg++]); aber[2] = 1 / atof(argv[arg++]); break; + case 'g': gamm[0] = atof(argv[arg++]); + gamm[1] = atof(argv[arg++]); + if (gamm[0]) gamm[0] = 1/gamm[0]; break; case 'k': user_black = atoi(argv[arg++]); break; case 'S': user_sat = atoi(argv[arg++]); break; case 't': user_flip = atoi(argv[arg++]); break; @@ -8451,7 +8593,9 @@ case 'j': use_fuji_rotate = 0; break; case 'W': no_auto_bright = 1; break; case 'T': output_tiff = 1; break; - case '4': output_bps = 16; break; + case '4': gamm[0] = gamm[1] = + no_auto_bright = 1; + case '6': output_bps = 16; break; default: dcraw_message (DCRAW_ERROR,_("Unknown option \"-%c\".\n"), opt); return 1; @@ -8487,7 +8631,7 @@ status = 1; goto cleanup; } - ifname = const_cast(argv[arg]); + ifname = const_cast(argv[arg]); ifname_display = ifname; if (!(ifp = fopen (ifname, "rb"))) { perror (ifname); @@ -8685,7 +8829,7 @@ } } dcraw_message (DCRAW_VERBOSE,_("Writing data to %s ...\n"), ofname); - (*this.*write_fun)(ofp); + (*this.*write_fun)(); fclose(ifp); if (ofp != stdout) fclose(ofp); cleanup: