#define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */ #define _XOPEN_SOURCE 500 /* Make sure putenv is in stdlib.h, strcaseeq is in nstring.h */ #include #include #include #include #ifdef HAVE_JPEG #include #endif #include "pm_config.h" #include "pm.h" #include "mallocvar.h" #include "pm_c_util.h" #include "nstring.h" #include "global_variables.h" #include "cameratopam.h" #include "util.h" #include "decode.h" #include "bayer.h" #include "ljpeg.h" #include "dng.h" #include "stdio_nofail.h" #include "camera.h" #if HAVE_INT64 typedef int64_t INT64; static bool const have64BitArithmetic = true; #else /* We define INT64 to something that lets the code compile, but we should not execute any INT64 code, because it will get the wrong result. */ typedef int INT64; static bool const have64BitArithmetic = false; #endif #ifndef LONG_BIT #define LONG_BIT (8 * sizeof (long)) #endif #define FORC3 for (c=0; c < 3; c++) #define FORC4 for (c=0; c < colors; c++) static void merror (const void *ptr, const char *where) { if (ptr == NULL) pm_error ("Out of memory in %s", where); } static void adobeCopyPixel(Image const image, unsigned int const row, unsigned int const col, unsigned short ** const rp, bool const useSecondary) { unsigned r=row, c=col; if (fuji_secondary && useSecondary) ++(*rp); if (filters) { if (fuji_width) { r = row + fuji_width - 1 - (col >> 1); c = row + ((col+1) >> 1); } if (r < height && c < width) BAYER(r,c) = **rp < 0x1000 ? curve[**rp] : **rp; *rp += 1 + fuji_secondary; } else { unsigned int c; for (c = 0; c < tiff_samples; ++c) { image[row*width+col][c] = **rp < 0x1000 ? curve[**rp] : **rp; ++(*rp); } } if (fuji_secondary && useSecondary) --(*rp); } void adobe_dng_load_raw_lj(Image const image) { int save, twide, trow=0, tcol=0, jrow, jcol; struct jhead jh; unsigned short *rp; while (1) { save = ftell_nofail(ifp); fseek_nofail (ifp, get4(ifp), SEEK_SET); if (!ljpeg_start (ifp, &jh)) break; if (trow >= raw_height) break; if (jh.high > raw_height-trow) jh.high = raw_height-trow; twide = jh.wide; if (filters) twide *= jh.clrs; else colors = jh.clrs; if (fuji_secondary) twide /= 2; if (twide > raw_width-tcol) twide = raw_width-tcol; for (jrow=0; jrow < jh.high; jrow++) { ljpeg_row(ifp, &jh); for (rp=jh.row, jcol=0; jcol < twide; jcol++) adobeCopyPixel(image, trow+jrow, tcol+jcol, &rp, use_secondary); } fseek_nofail (ifp, save+4, SEEK_SET); if ((tcol += twide) >= raw_width) { tcol = 0; trow += jh.high; } free (jh.row); } } void adobe_dng_load_raw_nc(Image const image) { unsigned short *pixel, *rp; int row, col; pixel = calloc (raw_width * tiff_samples, sizeof *pixel); merror (pixel, "adobe_dng_load_raw_nc()"); for (row=0; row < raw_height; row++) { read_shorts (ifp, pixel, raw_width * tiff_samples); for (rp=pixel, col=0; col < raw_width; col++) adobeCopyPixel(image, row, col, &rp, use_secondary); } free (pixel); } static int nikon_curve_offset; void nikon_compressed_load_raw(Image const image) { static const unsigned char nikon_tree[] = { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, 5,4,3,6,2,7,1,0,8,9,11,10,12 }; int csize, row, col, i, diff; unsigned short vpred[4], hpred[2], *curve; init_decoder(); make_decoder (nikon_tree, 0); fseek_nofail (ifp, nikon_curve_offset, SEEK_SET); read_shorts (ifp, vpred, 4); csize = get2(ifp); curve = calloc (csize, sizeof *curve); merror (curve, "nikon_compressed_load_raw()"); read_shorts (ifp, curve, csize); fseek_nofail (ifp, data_offset, SEEK_SET); getbits(ifp, -1); for (row=0; row < height; row++) for (col=0; col < raw_width; col++) { diff = ljpeg_diff (ifp, first_decode); if (col < 2) { i = 2*(row & 1) + (col & 1); vpred[i] += diff; hpred[col] = vpred[i]; } else hpred[col & 1] += diff; if ((unsigned) (col-left_margin) >= width) continue; diff = hpred[col & 1]; if (diff >= csize) diff = csize-1; BAYER(row,col-left_margin) = curve[diff]; } maximum = curve[csize-1]; free (curve); } void nikon_load_raw(Image const image) { int irow, row, col, i; getbits(ifp, -1); for (irow=0; irow < height; irow++) { row = irow; if (model[0] == 'E') { row = irow * 2 % height + irow / (height/2); if (row == 1 && atoi(model+1) < 5000) { fseek_nofail (ifp, 0, SEEK_END); fseek_nofail (ifp, ftell_nofail(ifp)/2, SEEK_SET); getbits(ifp, -1); } } for (col=0; col < raw_width; col++) { i = getbits(ifp, 12); if ((unsigned) (col-left_margin) < width) BAYER(row,col-left_margin) = i; if (tiff_data_compression == 34713 && (col % 10) == 9) getbits(ifp, 8); } } } /* Figure out if a NEF file is compressed. These fancy heuristics are only needed for the D100, thanks to a bug in some cameras that tags all images as "compressed". */ int nikon_is_compressed() { unsigned char test[256]; int i; if (tiff_data_compression != 34713) return 0; if (strcmp(model,"D100")) return 1; fseek_nofail (ifp, data_offset, SEEK_SET); fread_nofail (test, 1, 256, ifp); for (i=15; i < 256; i+=16) if (test[i]) return 1; return 0; } /* Returns 1 for a Coolpix 990, 0 for a Coolpix 995. */ int nikon_e990() { int i, histo[256]; const unsigned char often[] = { 0x00, 0x55, 0xaa, 0xff }; memset (histo, 0, sizeof histo); fseek_nofail (ifp, 2064*1540*3/4, SEEK_SET); for (i=0; i < 2000; i++) histo[fgetc_nofail(ifp)]++; for (i=0; i < 4; i++) if (histo[often[i]] > 400) return 1; return 0; } /* Returns 1 for a Coolpix 2100, 0 for anything else. */ int nikon_e2100() { unsigned char t[12]; int i; fseek_nofail (ifp, 0, SEEK_SET); for (i=0; i < 1024; i++) { fread_nofail (t, 1, 12, ifp); if (((t[2] & t[4] & t[7] & t[9]) >> 4 & t[1] & t[6] & t[8] & t[11] & 3) != 3) return 0; } return 1; } /* Separates a Pentax Optio 33WR from a Nikon E3700. */ int pentax_optio33() { int i, sum[] = { 0, 0 }; unsigned char tail[952]; fseek_nofail (ifp, -sizeof tail, SEEK_END); fread_nofail (tail, 1, sizeof tail, ifp); for (i=0; i < sizeof tail; i++) sum[(i>>2) & 1] += tail[i]; return sum[0] < sum[1]*4; } /* Separates a Minolta DiMAGE Z2 from a Nikon E4300. */ int minolta_z2() { int i; char tail[424]; fseek_nofail (ifp, -sizeof tail, SEEK_END); fread_nofail (tail, 1, sizeof tail, ifp); for (i=0; i < sizeof tail; i++) if (tail[i]) return 1; return 0; } void nikon_e2100_load_raw(Image const image) { unsigned char data[3432], *dp; unsigned short pixel[2288], *pix; int row, col; for (row=0; row <= height; row+=2) { if (row == height) { fseek_nofail (ifp, ((width==1616) << 13) - (-ftell_nofail(ifp) & -2048), SEEK_SET); row = 1; } fread_nofail (data, 1, width*3/2, ifp); for (dp=data, pix=pixel; pix < pixel+width; dp+=12, pix+=8) { pix[0] = (dp[2] >> 4) + (dp[ 3] << 4); pix[1] = (dp[2] << 8) + dp[ 1]; pix[2] = (dp[7] >> 4) + (dp[ 0] << 4); pix[3] = (dp[7] << 8) + dp[ 6]; pix[4] = (dp[4] >> 4) + (dp[ 5] << 4); pix[5] = (dp[4] << 8) + dp[11]; pix[6] = (dp[9] >> 4) + (dp[10] << 4); pix[7] = (dp[9] << 8) + dp[ 8]; } for (col=0; col < width; col++) BAYER(row,col) = (pixel[col] & 0xfff); } } void nikon_e950_load_raw(Image const image) { int irow, row, col; getbits(ifp, -1); for (irow=0; irow < height; irow++) { row = irow * 2 % height; for (col=0; col < width; col++) BAYER(row,col) = getbits(ifp, 10); for (col=28; col--; ) getbits(ifp, 8); } maximum = 0x3dd; } /* The Fuji Super CCD is just a Bayer grid rotated 45 degrees. */ void fuji_s2_load_raw(Image const image) { unsigned short pixel[2944]; int row, col, r, c; fseek_nofail (ifp, (2944*24+32)*2, SEEK_CUR); for (row=0; row < 2144; row++) { read_shorts(ifp, pixel, 2944); for (col=0; col < 2880; col++) { r = row + ((col+1) >> 1); c = 2143 - row + (col >> 1); BAYER(r,c) = pixel[col]; } } } void fuji_s3_load_raw(Image const image) { unsigned short pixel[4352]; int row, col, r, c; fseek_nofail (ifp, (4352*2+32)*2, SEEK_CUR); for (row=0; row < 1440; row++) { read_shorts(ifp, pixel, 4352); for (col=0; col < 4288; col++) { r = 2143 + row - (col >> 1); c = row + ((col+1) >> 1); BAYER(r,c) = pixel[col]; } } } static void fuji_common_load_raw(Image const image, unsigned int const ncol, unsigned int const icol, unsigned int const nrow) { unsigned short pixel[2048]; unsigned int row; for (row = 0; row < nrow; ++row) { unsigned int col; read_shorts(ifp, pixel, ncol); for (col = 0; col <= icol; ++col) { int const r = icol - col + (row >> 1); int const c = col + ((row+1) >> 1); BAYER(r,c) = pixel[col]; } } } void fuji_s5000_load_raw(Image const image) { fseek_nofail (ifp, (1472*4+24)*2, SEEK_CUR); fuji_common_load_raw(image, 1472, 1423, 2152); } void fuji_s7000_load_raw(Image const image) { fuji_common_load_raw(image, 2048, 2047, 3080); } /* The Fuji Super CCD SR has two photodiodes for each pixel. The secondary has about 1/16 the sensitivity of the primary, but this ratio may vary. */ void fuji_f700_load_raw(Image const image) { unsigned short pixel[2944]; int row, col, r, c, val; for (row=0; row < 2168; row++) { read_shorts(ifp, pixel, 2944); for (col=0; col < 1440; col++) { r = 1439 - col + (row >> 1); c = col + ((row+1) >> 1); val = pixel[col+16 + use_secondary*1472]; BAYER(r,c) = val; } } } void rollei_load_raw(Image const image) { unsigned char pixel[10]; unsigned iten=0, isix, i, buffer=0, row, col, todo[16]; isix = raw_width * raw_height * 5 / 8; while (fread_or_eof_nofail (pixel, 1, 10, ifp) == 10) { for (i=0; i < 10; i+=2) { todo[i] = iten++; todo[i+1] = pixel[i] << 8 | pixel[i+1]; buffer = pixel[i] >> 2 | buffer << 6; } for ( ; i < 16; i+=2) { todo[i] = isix++; todo[i+1] = buffer >> (14-i)*5; } for (i=0; i < 16; i+=2) { row = todo[i] / raw_width - top_margin; col = todo[i] % raw_width - left_margin; if (row < height && col < width) BAYER(row,col) = (todo[i+1] & 0x3ff); } } maximum = 0x3ff; } void phase_one_load_raw(Image const image) { int row, col, a, b; unsigned short *pixel, akey, bkey; fseek_nofail (ifp, 8, SEEK_CUR); fseek_nofail (ifp, get4(ifp) + 296, SEEK_CUR); akey = get2(ifp); bkey = get2(ifp); fseek_nofail (ifp, data_offset + 12 + top_margin*raw_width*2, SEEK_SET); pixel = calloc (raw_width, sizeof *pixel); merror (pixel, "phase_one_load_raw()"); for (row=0; row < height; row++) { read_shorts(ifp, pixel, raw_width); for (col=0; col < raw_width; col+=2) { a = pixel[col+0] ^ akey; b = pixel[col+1] ^ bkey; pixel[col+0] = (b & 0xaaaa) | (a & 0x5555); pixel[col+1] = (a & 0xaaaa) | (b & 0x5555); } for (col=0; col < width; col++) BAYER(row,col) = pixel[col+left_margin]; } free (pixel); } void ixpress_load_raw(Image const image) { unsigned short pixel[4090]; int row, col; order = 0x4949; fseek_nofail (ifp, 304 + 6*2*4090, SEEK_SET); for (row=height; --row >= 0; ) { read_shorts(ifp, pixel, 4090); for (col=0; col < width; col++) BAYER(row,col) = pixel[width-1-col]; } } void leaf_load_raw(Image const image) { unsigned short *pixel; int r, c, row, col; pixel = calloc (raw_width, sizeof *pixel); merror (pixel, "leaf_load_raw()"); for (r=0; r < height-32; r+=32) FORC3 for (row=r; row < r+32; row++) { read_shorts(ifp, pixel, raw_width); for (col=0; col < width; col++) image[row*width+col][c] = pixel[col]; } free (pixel); } /* For this function only, raw_width is in bytes, not pixels! */ void packed_12_load_raw(Image const image) { int row, col; getbits(ifp, -1); for (row=0; row < height; row++) { for (col=0; col < width; col++) BAYER(row,col) = getbits(ifp, 12); for (col = width*3/2; col < raw_width; col++) getbits(ifp, 8); } } void unpacked_load_raw(Image const image) { unsigned short *pixel; int row, col; pixel = calloc (raw_width, sizeof *pixel); merror (pixel, "unpacked_load_raw()"); for (row=0; row < height; row++) { read_shorts(ifp, pixel, raw_width); for (col=0; col < width; col++) BAYER(row,col) = pixel[col]; } free (pixel); } void olympus_e300_load_raw(Image const image) { unsigned char *data, *dp; unsigned short *pixel, *pix; int dwide, row, col; dwide = raw_width * 16 / 10; data = malloc (dwide + raw_width*2); merror (data, "olympus_e300_load_raw()"); pixel = (unsigned short *) (data + dwide); for (row=0; row < height; row++) { fread_nofail (data, 1, dwide, ifp); for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=3, pix+=2) { if (((dp-data) & 15) == 15) dp++; 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] & 0xfff); } free (data); } void olympus_cseries_load_raw(Image const image) { int irow, row, col; for (irow=0; irow < height; irow++) { row = irow * 2 % height + irow / (height/2); if (row < 2) { fseek_nofail (ifp, data_offset - row*(-width*height*3/4 & -2048), SEEK_SET); getbits(ifp, -1); } for (col=0; col < width; col++) BAYER(row,col) = getbits(ifp, 12); } } void eight_bit_load_raw(Image const image) { unsigned char *pixel; int row, col; pixel = calloc (raw_width, sizeof *pixel); merror (pixel, "eight_bit_load_raw()"); for (row=0; row < height; row++) { fread_nofail (pixel, 1, raw_width, ifp); for (col=0; col < width; col++) BAYER(row,col) = pixel[col]; } free (pixel); maximum = 0xff; } void casio_qv5700_load_raw(Image const image) { unsigned char data[3232], *dp; unsigned short pixel[2576], *pix; int row, col; for (row=0; row < height; row++) { fread_nofail (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 nucore_load_raw(Image const image) { unsigned short *pixel; int irow, row, col; pixel = calloc (width, 2); merror (pixel, "nucore_load_raw()"); for (irow=0; irow < height; irow++) { read_shorts(ifp, pixel, width); row = irow/2 + height/2 * (irow & 1); for (col=0; col < width; col++) BAYER(row,col) = pixel[col]; } free (pixel); } static int radc_token (int tree) { int t; static struct decode *dstart[18], *dindex; static const int *s, source[] = { 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, 2,0, 2,1, 2,3, 3,2, 4,4, 5,6, 6,7, 7,5, 7,8, 2,1, 2,4, 3,0, 3,2, 3,3, 4,7, 5,5, 6,6, 6,8, 2,3, 3,1, 3,2, 3,4, 3,5, 3,6, 4,7, 5,0, 5,8, 2,3, 2,6, 3,0, 3,1, 4,4, 4,5, 4,7, 5,2, 5,8, 2,4, 2,7, 3,3, 3,6, 4,1, 4,2, 4,5, 5,0, 5,8, 2,6, 3,1, 3,3, 3,5, 3,7, 3,8, 4,0, 5,2, 5,4, 2,0, 2,1, 3,2, 3,3, 4,4, 4,5, 5,6, 5,7, 4,8, 1,0, 2,2, 2,-2, 1,-3, 1,3, 2,-17, 2,-5, 2,5, 2,17, 2,-7, 2,2, 2,9, 2,18, 2,-18, 2,-9, 2,-2, 2,7, 2,-28, 2,28, 3,-49, 3,-9, 3,9, 4,49, 5,-79, 5,79, 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 (model[2] == '4') return (getbits(ifp, 5) << 3) + 4; /* DC40 */ else return (getbits(ifp, 6) << 2) + 2; /* DC50 */ } for (dindex = dstart[tree]; dindex->branch[0]; ) dindex = dindex->branch[getbits(ifp, 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 kodak_radc_load_raw(Image const image) { int row, col, tree, nreps, rep, step, c, s, r, x, y, val; unsigned int i; short last[3] = { 16,16,16 }, mul[3], buf[3][3][386]; init_decoder(); getbits(ifp, -1); for (i = 0; i < ARRAY_SIZE(buf); ++i) { unsigned int j; for (j = 0; j < ARRAY_SIZE(buf[0]); ++j) { unsigned int k; for (k = 0; k < ARRAY_SIZE(buf[0][0]); ++k) buf[i][j][k] = 2048; } } for (row=0; row < height; row+=4) { unsigned int i; for (i = 0; i < 3; ++i) mul[i] = getbits(ifp, 6); FORC3 { val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c]; s = val > 65564 ? 10:12; x = ~(-1 << (s-1)); val <<= 12-s; for (i=0; i < ARRAY_SIZE(buf[c][0]); i++) buf[c][0][i] = (buf[c][0][i] * val + x) >> s; last[c] = mul[c]; for (r=0; r <= !c; r++) { buf[c][1][width/2] = buf[c][2][width/2] = mul[c] << 7; for (tree=1, col=width/2; col > 0; ) { if ((tree = radc_token(tree))) { col -= 2; if (tree == 8) FORYX buf[c][y][x] = radc_token(tree+10) * mul[c]; else FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR; } else do { nreps = (col > 2) ? radc_token(9) + 1 : 1; for (rep=0; rep < 8 && rep < nreps && col > 0; rep++) { col -= 2; FORYX buf[c][y][x] = PREDICTOR; if (rep & 1) { step = radc_token(10) << 4; FORYX buf[c][y][x] += step; } } } while (nreps == 9); } for (y=0; y < 2; y++) for (x=0; x < width/2; x++) { val = (buf[c][y+1][x] << 4) / mul[c]; if (val < 0) val = 0; if (c) BAYER(row+y*2+c-1,x*2+2-c) = val; else BAYER(row+r*2+y,x*2+y) = val; } memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c); } } for (y=row; y < row+4; y++) for (x=0; x < width; x++) if ((x+y) & 1) { val = (BAYER(y,x)-2048)*2 + (BAYER(y,x-1)+BAYER(y,x+1))/2; if (val < 0) val = 0; BAYER(y,x) = val; } } maximum = 0x1fff; /* wild guess */ } #undef FORYX #undef PREDICTOR #ifndef HAVE_JPEG void kodak_jpeg_load_raw(Image const Image) {} #else static bool fill_input_buffer (j_decompress_ptr cinfo) { static char jpeg_buffer[4096]; size_t nbytes; nbytes = fread_or_eof_nofail (jpeg_buffer, 1, 4096, ifp); swab (jpeg_buffer, jpeg_buffer, nbytes); cinfo->src->next_input_byte = jpeg_buffer; cinfo->src->bytes_in_buffer = nbytes; return TRUE; } void kodak_jpeg_load_raw(Image const image) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPARRAY buf; JSAMPLE (*pixel)[3]; int row, col; cinfo.err = jpeg_std_error (&jerr); jpeg_create_decompress (&cinfo); jpeg_stdio_src (&cinfo, ifp); cinfo.src->fill_input_buffer = fill_input_buffer; jpeg_read_header (&cinfo, TRUE); jpeg_start_decompress (&cinfo); if ((cinfo.output_width != width ) || (cinfo.output_height*2 != height ) || (cinfo.output_components != 3 )) { pm_error ("incorrect JPEG dimensions"); } buf = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, width*3, 1); while (cinfo.output_scanline < cinfo.output_height) { row = cinfo.output_scanline * 2; jpeg_read_scanlines (&cinfo, buf, 1); pixel = (void *) buf[0]; for (col=0; col < width; col+=2) { BAYER(row+0,col+0) = pixel[col+0][1] << 1; BAYER(row+1,col+1) = pixel[col+1][1] << 1; BAYER(row+0,col+1) = pixel[col][0] + pixel[col+1][0]; BAYER(row+1,col+0) = pixel[col][2] + pixel[col+1][2]; } } jpeg_finish_decompress (&cinfo); jpeg_destroy_decompress (&cinfo); maximum = 0xff << 1; } #endif void kodak_dc120_load_raw(Image const image) { static const int mul[4] = { 162, 192, 187, 92 }; static const int add[4] = { 0, 636, 424, 212 }; unsigned char pixel[848]; int row, shift, col; for (row=0; row < height; row++) { fread_nofail (pixel, 848, 1, ifp); shift = row * mul[row & 3] + add[row & 3]; for (col=0; col < width; col++) BAYER(row,col) = (unsigned short) pixel[(col + shift) % 848]; } maximum = 0xff; } void kodak_dc20_coeff (float const juice) { static const float my_coeff[3][4] = { { 2.25, 0.75, -1.75, -0.25 }, { -0.25, 0.75, 0.75, -0.25 }, { -0.25, -1.75, 0.75, 2.25 } }; static const float flat[3][4] = { { 1, 0, 0, 0 }, { 0, 0.5, 0.5, 0 }, { 0, 0, 0, 1 } }; int r, g; for (r=0; r < 3; r++) for (g=0; g < 4; g++) coeff[r][g] = my_coeff[r][g] * juice + flat[r][g] * (1-juice); use_coeff = 1; } void kodak_easy_load_raw(Image const image) { unsigned char *pixel; unsigned row, col, icol; if (raw_width > width) black = 0; pixel = calloc (raw_width, sizeof *pixel); merror (pixel, "kodak_easy_load_raw()"); for (row=0; row < height; row++) { fread_nofail (pixel, 1, raw_width, ifp); for (col=0; col < raw_width; col++) { icol = col - left_margin; if (icol < width) BAYER(row,icol) = (unsigned short) curve[pixel[col]]; else black += curve[pixel[col]]; } } free (pixel); if (raw_width > width) black /= (raw_width - width) * height; if (!strncmp(model,"DC2",3)) black = 0; maximum = curve[0xff]; } void kodak_compressed_load_raw(Image const image) { unsigned char c, blen[256]; unsigned short raw[6]; unsigned row, col, len, save, i, israw=0, bits=0, pred[2]; INT64 bitbuf=0; int diff; assert(have64BitArithmetic); for (row=0; row < height; row++) for (col=0; col < width; col++) { if ((col & 255) == 0) { /* Get the bit-lengths of the */ len = width - col; /* next 256 pixel values */ if (len > 256) len = 256; save = ftell_nofail(ifp); for (israw=i=0; i < len; i+=2) { c = fgetc_nofail(ifp); if ((blen[i+0] = c & 15) > 12 || (blen[i+1] = c >> 4) > 12 ) israw = 1; } bitbuf = bits = pred[0] = pred[1] = 0; if (len % 8 == 4) { bitbuf = fgetc_nofail(ifp) << 8; bitbuf += fgetc_nofail(ifp); bits = 16; } if (israw) fseek_nofail (ifp, save, SEEK_SET); } if (israw) { /* If the data is not compressed */ switch (col & 7) { case 0: read_shorts(ifp, raw, 6); diff = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12; break; case 1: diff = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12; break; default: diff = raw[(col & 7) - 2] & 0xfff; } } else { /* If the data is compressed */ len = blen[col & 255]; /* Number of bits for this pixel */ if (bits < len) { /* Got enough bits in the buffer? */ for (i=0; i < 32; i+=8) bitbuf += (INT64) fgetc_nofail(ifp) << (bits+(i^8)); bits += 32; } diff = bitbuf & (0xffff >> (16-len)); /* Pull bits from buffer */ bitbuf >>= len; bits -= len; if ((diff & (1 << (len-1))) == 0) diff -= (1 << len) - 1; pred[col & 1] += diff; diff = pred[col & 1]; } BAYER(row,col) = curve[diff]; } } void kodak_yuv_load_raw(Image const image) { unsigned char 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]; unsigned short *ip; assert(have64BitArithmetic); 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_nofail(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_nofail(ifp) << 8; bitbuf += fgetc_nofail(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_nofail(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++) { ip = image[(row+(i >> 1))*width + col+(i & 1)]; rgb[0] = y[i] + cr; rgb[1] = y[i]; rgb[2] = y[i] + cb; FORC3 if (rgb[c] > 0) ip[c] = curve[rgb[c]]; } } maximum = 0xe74; } static void sony_decrypt (unsigned *data, int len, int start, int key) { static uint32_t pad[128]; unsigned int p; unsigned int i; if (start) { for (p=0; p < 4; p++) pad[p] = key = key * 48828125 + 1; pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31; for (p=4; p < 127; p++) pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31; /* Convert to big-endian */ for (p=0; p < 127; p++) { union { unsigned char bytes[4]; uint32_t word; } u; u.bytes[0] = pad[p] >> 24; u.bytes[1] = pad[p] >> 16; u.bytes[2] = pad[p] >> 8; u.bytes[3] = pad[p] >> 0; pad[p] = u.word; } } for (i = 0, p = 0; i < len; ++i, ++p) { *data++ ^= pad[p & 0x7f] = pad[(p+1) & 0x7f] ^ pad[(p+65) & 0x7f]; } } void sony_load_raw(Image const image) { unsigned char head[40]; struct pixel { unsigned char bytes[2]; }; struct pixel * pixelrow; unsigned i, key, row, col; fseek_nofail (ifp, 200896, SEEK_SET); fseek_nofail (ifp, (unsigned) fgetc_nofail(ifp)*4 - 1, SEEK_CUR); order = 0x4d4d; key = get4(ifp); fseek_nofail (ifp, 164600, SEEK_SET); fread_nofail (head, 1, 40, ifp); sony_decrypt ((void *) head, 10, 1, key); for (i=26; i-- > 22; ) key = key << 8 | head[i]; fseek_nofail (ifp, data_offset, SEEK_SET); MALLOCARRAY(pixelrow, raw_width); merror (pixelrow, "sony_load_raw()"); for (row=0; row < height; row++) { fread_nofail (pixelrow, 2, raw_width, ifp); sony_decrypt ((void *) pixelrow, raw_width/2, !row, key); for (col=9; col < left_margin; col++) black += pixelrow[col].bytes[0] * 256 + pixelrow[col].bytes[1]; for (col=0; col < width; col++) BAYER(row,col) = pixelrow[col+left_margin].bytes[0] * 256 + pixelrow[col+left_margin].bytes[1]; } free (pixelrow); if (left_margin > 9) black /= (left_margin-9) * height; maximum = 0x3ff0; } void parse_minolta(FILE * const ifp) { int save, tag, len, offset, high=0, wide=0; fseek_nofail (ifp, 4, SEEK_SET); offset = get4(ifp) + 8; while ((save=ftell_nofail(ifp)) < offset) { tag = get4(ifp); len = get4(ifp); switch (tag) { case 0x505244: /* PRD */ fseek_nofail (ifp, 8, SEEK_CUR); high = get2(ifp); wide = get2(ifp); break; case 0x574247: /* WBG */ get4(ifp); camera_red = get2(ifp); camera_red /= get2(ifp); camera_blue = get2(ifp); camera_blue = get2(ifp) / camera_blue; break; case 0x545457: /* TTW */ parse_tiff(ifp, ftell_nofail(ifp)); } fseek_nofail (ifp, save+len+8, SEEK_SET); } raw_height = high; raw_width = wide; data_offset = offset; } /* CIFF block 0x1030 contains an 8x8 white sample. Load this into white[][] for use in scale_colors(). */ static void ciff_block_1030() { static const unsigned short key[] = { 0x410, 0x45f3 }; int i, bpp, row, col, vbits=0; unsigned long bitbuf=0; get2(ifp); if (get4(ifp) != 0x80008) return; if (get4(ifp) == 0) return; bpp = get2(ifp); if (bpp != 10 && bpp != 12) return; for (i=row=0; row < 8; row++) for (col=0; col < 8; col++) { if (vbits < bpp) { bitbuf = bitbuf << 16 | (get2(ifp) ^ key[i++ & 1]); vbits += 16; } white[row][col] = bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp); vbits -= bpp; } } /* Parse a CIFF file, better known as Canon CRW format. */ void parse_ciff(FILE * const ifp, int const offset, int const length) { int tboff, nrecs, i, 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 }; unsigned short key[] = { 0x410, 0x45f3 }; if (strcmp(model,"Canon PowerShot G6") && strcmp(model,"Canon PowerShot S70") && strcmp(model,"Canon PowerShot Pro1")) key[0] = key[1] = 0; fseek_nofail (ifp, offset+length-4, SEEK_SET); tboff = get4(ifp) + offset; fseek_nofail (ifp, tboff, SEEK_SET); nrecs = get2(ifp); for (i = 0; i < nrecs; i++) { type = get2(ifp); len = get4(ifp); roff = get4(ifp); aoff = offset + roff; save = ftell_nofail(ifp); if (type == 0x080a) { /* Get the camera make and model */ fseek_nofail (ifp, aoff, SEEK_SET); fread_nofail (make, 64, 1, ifp); fseek_nofail (ifp, aoff+strlen(make)+1, SEEK_SET); fread_nofail (model, 64, 1, ifp); } if (type == 0x102a) { /* Find the White Balance index */ fseek_nofail (ifp, aoff+14, SEEK_SET); /* 0=auto, 1=daylight, 2=cloudy ... */ wbi = get2(ifp); 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_nofail (ifp, aoff+120, SEEK_SET); white[0][1] = get2(ifp); white[0][0] = get2(ifp); white[1][0] = get2(ifp); white[1][1] = get2(ifp); } else { fseek_nofail (ifp, aoff+100, SEEK_SET); goto common; } } if (type == 0x0032) { /* Get white balance (D30 & G3) */ if (!strcmp(model,"Canon EOS D30")) { fseek_nofail (ifp, aoff+72, SEEK_SET); common: camera_red = get2(ifp) ^ key[0]; camera_red =(get2(ifp) ^ key[1]) / camera_red; camera_blue = get2(ifp) ^ key[0]; camera_blue /= get2(ifp) ^ key[1]; } else if (!strcmp(model,"Canon PowerShot G6") || !strcmp(model,"Canon PowerShot S70")) { fseek_nofail (ifp, aoff+96 + remap_s70[wbi]*8, SEEK_SET); goto common; } else if (!strcmp(model,"Canon PowerShot Pro1")) { fseek_nofail (ifp, aoff+96 + wbi*8, SEEK_SET); goto common; } else { fseek_nofail (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_nofail (ifp, aoff+2 + wbi*8, SEEK_SET); camera_red = get2(ifp); camera_red /= get2(ifp); camera_blue = get2(ifp); camera_blue = get2(ifp) / camera_blue; } if (type == 0x1030 && (wbi == 6 || wbi == 15)) { fseek_nofail (ifp, aoff, SEEK_SET); /* Get white sample */ ciff_block_1030(); } if (type == 0x1031) { /* Get the raw width and height */ fseek_nofail (ifp, aoff+2, SEEK_SET); raw_width = get2(ifp); raw_height = get2(ifp); } if (type == 0x180e) { /* Get the timestamp */ fseek_nofail (ifp, aoff, SEEK_SET); timestamp = get4(ifp); } if (type == 0x580e) timestamp = len; if (type == 0x1810) { /* Get the rotation */ fseek_nofail (ifp, aoff+12, SEEK_SET); flip = get4(ifp); } if (type == 0x1835) { /* Get the decoder table */ fseek_nofail (ifp, aoff, SEEK_SET); crw_init_tables (get4(ifp)); } if (type >> 8 == 0x28 || type >> 8 == 0x30) /* Get sub-tables */ parse_ciff(ifp, aoff, len); fseek_nofail (ifp, save, SEEK_SET); } if (wbi == 0 && !strcmp(model,"Canon EOS D30")) camera_red = -1; /* Use my auto WB for this photo */ } void parse_rollei(FILE * const ifp) { char line[128], *val; int tx=0, ty=0; struct tm t; time_t ts; fseek_nofail (ifp, 0, SEEK_SET); do { fgets_nofail (line, 128, ifp); if ((val = strchr(line,'='))) *val++ = 0; else val = line + strlen(line); if (!strcmp(line,"DAT")) sscanf (val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year); if (!strcmp(line,"TIM")) sscanf (val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec); if (!strcmp(line,"HDR")) data_offset = atoi(val); if (!strcmp(line,"X ")) raw_width = atoi(val); if (!strcmp(line,"Y ")) raw_height = atoi(val); if (!strcmp(line,"TX ")) tx = atoi(val); if (!strcmp(line,"TY ")) ty = atoi(val); } while (strncmp(line,"EOHD",4)); t.tm_year -= 1900; t.tm_mon -= 1; putenv((char*)"TZ="); if ((ts = mktime(&t)) > 0) timestamp = ts; data_offset += tx * ty * 2; strcpy (make, "Rollei"); strcpy (model,"d530flex"); } void parse_mos(FILE * const ifp, int const offset) { char data[40]; int skip, from, i, neut[4]; fseek_nofail (ifp, offset, SEEK_SET); while (1) { fread_nofail (data, 1, 8, ifp); if (strcmp(data,"PKTS")) break; fread_nofail (data, 1, 40, ifp); skip = get4(ifp); from = ftell_nofail(ifp); if (!strcmp(data,"NeutObj_neutrals")) { for (i=0; i < 4; i++) fscanf (ifp, "%d", neut+i); camera_red = (float) neut[2] / neut[1]; camera_blue = (float) neut[2] / neut[3]; } parse_mos(ifp, from); fseek_nofail (ifp, skip+from, SEEK_SET); } } void nikon_e950_coeff() { int r, g; static const float my_coeff[3][4] = { { -1.936280, 1.800443, -1.448486, 2.584324 }, { 1.405365, -0.524955, -0.289090, 0.408680 }, { -1.204965, 1.082304, 2.941367, -1.818705 } }; for (r=0; r < 3; r++) for (g=0; g < 4; g++) coeff[r][g] = my_coeff[r][g]; use_coeff = 1; } static double getrat() { double num = get4(ifp); return num / get4(ifp); } static void parse_makernote(FILE * const ifp) { unsigned base=0, offset=0, entries, tag, type, len, save; static const int size[] = { 1,1,1,2,4,8,1,1,2,4,8,4,8 }; 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_nofail (buf, 1, 10, ifp); if (!strncmp (buf,"KC" ,2) || /* these aren't TIFF format */ !strncmp (buf,"MLY",3)) return; if (!strcmp (buf,"Nikon")) { base = ftell_nofail(ifp); order = get2(ifp); if (get2(ifp) != 42) goto quit; offset = get4(ifp); fseek_nofail (ifp, offset-8, SEEK_CUR); } else if (!strncmp (buf,"FUJIFILM",8) || !strcmp (buf,"Panasonic")) { order = 0x4949; fseek_nofail (ifp, 2, SEEK_CUR); } else if (!strcmp (buf,"OLYMP") || !strcmp (buf,"LEICA") || !strcmp (buf,"EPSON")) fseek_nofail (ifp, -2, SEEK_CUR); else if (!strcmp (buf,"AOC") || !strcmp (buf,"QVC")) fseek_nofail (ifp, -4, SEEK_CUR); else fseek_nofail (ifp, -10, SEEK_CUR); entries = get2(ifp); while (entries--) { tag = get2(ifp); type = get2(ifp); len = get4(ifp); save = ftell_nofail(ifp); if (len * size[type < 13 ? type:0] > 4) fseek_nofail (ifp, get4(ifp)+base, SEEK_SET); if (tag == 0xc && len == 4) { camera_red = getrat(); camera_blue = getrat(); } if (tag == 0x14 && len == 2560 && type == 7) { fseek_nofail (ifp, 1248, SEEK_CUR); goto get2_256; } if (strstr(make,"PENTAX")) { if (tag == 0x1b) tag = 0x1018; if (tag == 0x1c) tag = 0x1017; } if (tag == 0x8c) nikon_curve_offset = ftell_nofail(ifp) + 2112; if (tag == 0x96) nikon_curve_offset = ftell_nofail(ifp) + 2; if (tag == 0x97) { if (!strcmp(model,"NIKON D100 ")) { fseek_nofail (ifp, 72, SEEK_CUR); camera_red = get2(ifp) / 256.0; camera_blue = get2(ifp) / 256.0; } else if (!strcmp(model,"NIKON D2H")) { fseek_nofail (ifp, 10, SEEK_CUR); goto get2_rggb; } else if (!strcmp(model,"NIKON D70")) { fseek_nofail (ifp, 20, SEEK_CUR); camera_red = get2(ifp); camera_red /= get2(ifp); camera_blue = get2(ifp); camera_blue/= get2(ifp); } } if (tag == 0xe0 && len == 17) { get2(ifp); raw_width = get2(ifp); raw_height = get2(ifp); } if (tag == 0x200 && len == 4) black = (get2(ifp)+get2(ifp)+get2(ifp)+get2(ifp))/4; if (tag == 0x201 && len == 4) { camera_red = get2(ifp); camera_red /= get2(ifp); camera_blue = get2(ifp); camera_blue = get2(ifp) / camera_blue; } if (tag == 0x401 && len == 4) { black = (get4(ifp)+get4(ifp)+get4(ifp)+get4(ifp))/4; } if (tag == 0xe80 && len == 256 && type == 7) { fseek_nofail (ifp, 48, SEEK_CUR); camera_red = get2(ifp) * 508 * 1.078 / 0x10000; camera_blue = get2(ifp) * 382 * 1.173 / 0x10000; } if (tag == 0xf00 && len == 614 && type == 7) { fseek_nofail (ifp, 188, SEEK_CUR); goto get2_256; } if (tag == 0x1017) camera_red = get2(ifp) / 256.0; if (tag == 0x1018) camera_blue = get2(ifp) / 256.0; if (tag == 0x2011 && len == 2) { get2_256: order = 0x4d4d; camera_red = get2(ifp) / 256.0; camera_blue = get2(ifp) / 256.0; } if (tag == 0x4001) { fseek_nofail (ifp, strstr(model,"EOS-1D") ? 68:50, SEEK_CUR); get2_rggb: camera_red = get2(ifp); camera_red /= get2(ifp); camera_blue = get2(ifp); camera_blue = get2(ifp) / camera_blue; } fseek_nofail (ifp, save+4, SEEK_SET); } quit: order = sorder; } static void get_timestamp(FILE * const ifp) { /* Since the TIFF DateTime string has no timezone information, assume that the camera's clock was set to Universal Time. */ struct tm t; time_t ts; if (fscanf (ifp, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon, &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6) return; t.tm_year -= 1900; t.tm_mon -= 1; putenv((char*)"TZ=UTC"); /* Remove this to assume local time */ if ((ts = mktime(&t)) > 0) timestamp = ts; } static void parse_exif(FILE * const ifp, int base) { int entries, tag, len, val, save; entries = get2(ifp); while (entries--) { tag = get2(ifp); /* type = */ get2(ifp); len = get4(ifp); val = get4(ifp); save = ftell_nofail(ifp); fseek_nofail (ifp, base+val, SEEK_SET); if (tag == 0x9003 || tag == 0x9004) get_timestamp(ifp); if (tag == 0x927c) { if (!strncmp(make,"SONY",4)) data_offset = base+val+len; else parse_makernote(ifp); } fseek_nofail (ifp, save, SEEK_SET); } } static int parse_tiff_ifd(FILE * const ifp, int base, int level) { unsigned entries, tag, type, len, plen=16, save; int done=0, use_cm=0, cfa, i, j, c; static const int size[] = { 1,1,1,2,4,8,1,1,2,4,8,4,8 }; char software[64]; static const int flip_map[] = { 0,1,3,2,4,6,7,5 }; unsigned char cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256]; unsigned short scale[4]; double dblack, cc[4][4], cm[4][3]; double ab[]={ 1,1,1,1 }, asn[] = { 0,0,0,0 }, xyz[] = { 1,1,1 }; for (j=0; j < 4; j++) for (i=0; i < 4; i++) cc[j][i] = i == j; entries = get2(ifp); if (entries > 512) return 1; while (entries--) { tag = get2(ifp); type = get2(ifp); len = get4(ifp); save = ftell_nofail(ifp); if (tag > 50700 && tag < 50800) done = 1; if (len * size[type < 13 ? type:0] > 4) fseek_nofail (ifp, get4(ifp)+base, SEEK_SET); switch (tag) { case 0x11: camera_red = get4(ifp) / 256.0; break; case 0x12: camera_blue = get4(ifp) / 256.0; break; case 0x100: /* ImageWidth */ if (strcmp(make,"Canon") || level) raw_width = type==3 ? get2(ifp) : get4(ifp); break; case 0x101: /* ImageHeight */ if (strcmp(make,"Canon") || level) raw_height = type==3 ? get2(ifp) : get4(ifp); break; case 0x102: /* Bits per sample */ fuji_secondary = len == 2; if (level) maximum = (1 << get2(ifp)) - 1; break; case 0x103: /* Compression */ tiff_data_compression = get2(ifp); break; case 0x106: /* Kodak color format */ kodak_data_compression = get2(ifp); break; case 0x10f: /* Make */ fgets_nofail (make, 64, ifp); break; case 0x110: /* Model */ fgets_nofail (model, 64, ifp); break; case 0x111: /* StripOffset */ data_offset = get4(ifp); break; case 0x112: /* Orientation */ flip = flip_map[(get2(ifp)-1) & 7]; break; case 0x115: /* SamplesPerPixel */ tiff_samples = get2(ifp); break; case 0x131: /* Software tag */ fgets_nofail (software, 64, ifp); if (!strncmp(software,"Adobe",5)) make[0] = 0; break; case 0x132: /* DateTime tag */ get_timestamp(ifp); break; case 0x144: /* TileOffsets */ if (level) { data_offset = ftell_nofail(ifp); } else { strcpy (make, "Leaf"); data_offset = get4(ifp); } break; case 0x14a: /* SubIFD tag */ if (len > 2 && !is_dng && !strcmp(make,"Kodak")) len = 2; while (len--) { i = ftell_nofail(ifp); fseek_nofail (ifp, get4(ifp)+base, SEEK_SET); if (parse_tiff_ifd(ifp, base, level+1)) break; fseek_nofail (ifp, i+4, SEEK_SET); } break; case 33405: /* Model2 */ fgets_nofail (model2, 64, ifp); break; case 33422: /* CFAPattern */ if ((plen=len) > 16) plen = 16; fread_nofail (cfa_pat, 1, plen, ifp); for (colors=cfa=i=0; i < plen; i++) { colors += !(cfa & (1 << cfa_pat[i])); cfa |= 1 << cfa_pat[i]; } if (cfa == 070) memcpy (cfa_pc,"\003\004\005",3); /* CMY */ if (cfa == 072) memcpy (cfa_pc,"\005\003\004\001",4); /* GMCY */ goto guess_cfa_pc; case 34665: /* EXIF tag */ fseek_nofail (ifp, get4(ifp)+base, SEEK_SET); parse_exif(ifp, base); break; case 50706: /* DNGVersion */ is_dng = 1; if (flip == 7) flip = 4; /* Adobe didn't read the TIFF spec. */ break; case 50710: /* CFAPlaneColor */ if (len > 4) len = 4; colors = len; fread_nofail (cfa_pc, 1, colors, ifp); guess_cfa_pc: FORC4 tab[cfa_pc[c]] = c; for (i=16; i--; ) filters = filters << 2 | tab[cfa_pat[i % plen]]; break; case 50711: /* CFALayout */ if (get2(ifp) == 2) { fuji_width = (raw_width+1)/2; filters = 0x49494949; } break; case 0x123: case 0x90d: case 50712: /* LinearizationTable */ if (len > 0x1000) len = 0x1000; read_shorts(ifp, curve, len); for (i=len; i < 0x1000; i++) maximum = curve[i] = curve[i-1]; break; case 50714: /* BlackLevel */ case 50715: /* BlackLevelDeltaH */ case 50716: /* BlackLevelDeltaV */ for (dblack=i=0; i < len; i++) dblack += getrat(); black += dblack/len + 0.5; break; case 50717: /* WhiteLevel */ maximum = get2(ifp); break; case 50718: /* DefaultScale */ for (i=0; i < 4; i++) scale[i] = get4(ifp); if (scale[1]*scale[2] == 2*scale[0]*scale[3]) ymag = 2; break; case 50721: /* ColorMatrix1 */ case 50722: /* ColorMatrix2 */ FORC4 for (j=0; j < 3; j++) cm[c][j] = getrat(); use_cm = 1; break; case 50723: /* CameraCalibration1 */ case 50724: /* CameraCalibration2 */ for (i=0; i < colors; i++) FORC4 cc[i][c] = getrat(); case 50727: /* AnalogBalance */ FORC4 ab[c] = getrat(); break; case 50728: /* AsShotNeutral */ FORC4 asn[c] = getrat(); break; case 50729: /* AsShotWhiteXY */ xyz[0] = getrat(); xyz[1] = getrat(); xyz[2] = 1 - xyz[0] - xyz[1]; } fseek_nofail (ifp, save+4, SEEK_SET); } for (i=0; i < colors; i++) FORC4 cc[i][c] *= ab[i]; if (use_cm) dng_coeff (cc, cm, xyz); if (asn[0]) FORC4 pre_mul[c] = 1 / asn[c]; if (!use_cm) FORC4 pre_mul[c] /= cc[c][c]; if (is_dng || level) return done; if ((raw_height & 1) && !strncmp (make,"OLYMPUS",7)) raw_height++; if (make[0] == 0 && raw_width == 680 && raw_height == 680) { strcpy (make, "Imacon"); strcpy (model,"Ixpress"); } return done; } void parse_tiff(FILE * const ifp, int base) { int doff; fseek_nofail (ifp, base, SEEK_SET); order = get2(ifp); if (order != 0x4949 && order != 0x4d4d) return; get2(ifp); while ((doff = get4(ifp))) { fseek_nofail (ifp, doff+base, SEEK_SET); if (parse_tiff_ifd(ifp, base, 0)) break; } if (!is_dng && !strncmp(make,"Kodak",5)) { fseek_nofail (ifp, 12+base, SEEK_SET); parse_tiff_ifd(ifp, base, 2); } } /* Many cameras have a "debug mode" that writes JPEG and raw at the same time. The raw file has no header, so try to to open the matching JPEG file and read its metadata. */ void parse_external_jpeg(const char * const ifname) { const char *file, *ext; char * jfile; char * jext; char * jname; ext = strrchr (ifname, '.'); file = strrchr (ifname, '/'); if (!file) file = strrchr (ifname, '\\'); if (!file) file = ifname-1; file++; if (strlen(ext) != 4 || ext-file != 8) return; jname = malloc (strlen(ifname) + 1); merror (jname, "parse_external()"); strcpy (jname, ifname); jfile = jname + (file - ifname); jext = jname + (ext - ifname); if (!strcaseeq (ext, ".jpg")) { strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg"); memcpy (jfile, file+4, 4); memcpy (jfile+4, file, 4); } else while (isdigit(*--jext)) { if (*jext != '9') { (*jext)++; break; } *jext = '0'; } if (strcmp (jname, ifname)) { FILE * ifP; ifP = fopen (jname, "rb"); if (ifP) { if (verbose) pm_message ("Reading metadata from %s...", jname); parse_tiff(ifP, 12); fclose (ifP); } } if (!timestamp) pm_message ( "Failed to read metadata from %s", jname); free (jname); }