From: Good Guy Date: Sun, 21 May 2017 00:35:21 +0000 (-0600) Subject: file probe prefs, updated dcraw, bugs - garbage, accel, ffmpeg/giphy.gif X-Git-Url: https://git.cinelerra-gg.org/git/?a=commitdiff_plain;h=24db15d85f2e4c986ff91f992e815747c55948f3;p=goodguy%2Fhistory.git file probe prefs, updated dcraw, bugs - garbage, accel, ffmpeg/giphy.gif --- diff --git a/cinelerra-5.1/cinelerra/Makefile b/cinelerra-5.1/cinelerra/Makefile index 56290860..93fd8b61 100644 --- a/cinelerra-5.1/cinelerra/Makefile +++ b/cinelerra-5.1/cinelerra/Makefile @@ -226,6 +226,7 @@ OBJS = \ $(OBJDIR)/pluginvclient.o \ $(OBJDIR)/preferences.o \ $(OBJDIR)/preferencesthread.o \ + $(OBJDIR)/probeprefs.o \ $(OBJDIR)/question.o \ $(OBJDIR)/quit.o \ $(OBJDIR)/recconfirmdelete.o \ @@ -445,7 +446,7 @@ $(OBJDIR)/sha1.o: sha1.C sha1.h $(CXX) `cat $(OBJDIR)/c_flags` -O3 -c $< -o $@ $(DCRAW): dcraw.c - $(GCC) `cat $(OBJDIR)/c_flags` -Wno-misleading-indentation dcraw.c -c -o $*.o + $(GCC) `cat $(OBJDIR)/c_flags` -O4 -Wno-misleading-indentation dcraw.c -c -o $*.o $(THEME_DATA): cd $(OBJDIR) && \ diff --git a/cinelerra-5.1/cinelerra/dcraw.c b/cinelerra-5.1/cinelerra/dcraw.c index 4d0e3826..52c3f920 100644 --- a/cinelerra-5.1/cinelerra/dcraw.c +++ b/cinelerra-5.1/cinelerra/dcraw.c @@ -1,6 +1,6 @@ /* dcraw.c -- Dave Coffin's raw photo decoder - Copyright 1997-2012 by Dave Coffin, dcoffin a cybercom o net + Copyright 1997-2016 by Dave Coffin, dcoffin a cybercom o net This is a command-line ANSI C program to convert raw photos from any digital camera on any computer running any operating system. @@ -19,12 +19,11 @@ *If you have not modified dcraw.c in any way, a link to my homepage qualifies as "full source code". - $Revision: 1.454 $ - $Date: 2012/12/23 19:25:36 $ + $Revision: 1.477 $ + $Date: 2016/05/10 21:30:43 $ */ -#define DCRAW_VERSION "9.17" -#define LOCALTIME +#define DCRAW_VERSION "9.27" #ifndef _GNU_SOURCE #define _GNU_SOURCE @@ -43,31 +42,9 @@ #include #include - // CINELERRA #define NODEPS - - -#ifdef NODEPS -#define NO_JASPER -#define NO_JPEG -#define NO_LCMS -#endif -#ifndef NO_JASPER -#include /* Decode RED camera movies */ -#endif -#ifndef NO_JPEG -#include /* Decode compressed Kodak DC120 photos */ -#endif /* and Adobe Lossy DNGs */ -#ifndef NO_LCMS -#include /* Support color profiles */ -#endif -#ifdef LOCALEDIR -#include -#define _(String) gettext(String) -#else -#define _(String) (String) -#endif +#define LOCALTIME #if defined(DJGPP) || defined(__MINGW32__) #define fseeko fseek @@ -95,13 +72,25 @@ typedef long long INT64; typedef unsigned long long UINT64; #endif -#ifdef LJPEG_DECODE -#error Please compile dcraw.c by itself. -#error Do not link it with ljpeg_decode. +#ifdef NODEPS +#define NO_JASPER +#define NO_JPEG +#define NO_LCMS #endif - -#ifndef LONG_BIT -#define LONG_BIT (8 * sizeof (long)) +#ifndef NO_JASPER +#include /* Decode Red camera movies */ +#endif +#ifndef NO_JPEG +#include /* Decode compressed Kodak DC120 photos */ +#endif /* and Adobe Lossy DNGs */ +#ifndef NO_LCMS +#include /* Support color profiles */ +#endif +#ifdef LOCALEDIR +#include +#define _(String) gettext(String) +#else +#define _(String) (String) #endif #if !defined(uchar) @@ -123,71 +112,74 @@ float **dcraw_data; int dcraw_alpha; float dcraw_matrix[9]; +// CINELERRA +#define CLASS +struct jhead; +struct tiff_tag; +struct tiff_hdr; - - - - -FILE *ifp, *ofp; -short order; -const char *ifname; -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; -unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id; -off_t strip_offset, data_offset; -off_t thumb_offset, meta_offset, profile_offset; -unsigned thumb_length, meta_length, profile_length; -unsigned thumb_misc, *oprof, fuji_layout, shot_select=0, multi_out=0; -unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress; -unsigned black, cblack[4], 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; -ushort *raw_image, (*image)[4]; -ushort white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4]; +#include "dcraw.h" // CINELERRA -static int mask[8][4], flip, tiff_flip, colors; - - -double pixel_aspect, aber[4]={1,1,1,1}, gamm[6]={ 0.45,4.5,0,0,0,0 }; -float bright=1, user_mul[4]={0,0,0,0}, threshold=0; -int half_size=0, four_color_rgb=0, document_mode=0, highlight=0; -int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=-1; -int output_color=1, output_bps=8, output_tiff=0, med_passes=0; -int no_auto_bright=0; -unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX }; -float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4]; -const double xyz_rgb[3][3] = { /* XYZ from RGB */ +static FILE *ifp, *ofp; +static short order; +static const char *ifname; +static char *meta_data, xtrans[6][6], xtrans_abs[6][6]; +static char cdesc[5], desc[512], make[64], model[64], model2[64], artist[64]; +static float flash_used, canon_ev, iso_speed, shutter, aperture, focal_len; +static time_t timestamp; +static off_t strip_offset, data_offset; +static off_t thumb_offset, meta_offset, profile_offset; +static unsigned shot_order, kodak_cbpp, exif_cfa, unique_id; +static unsigned thumb_length, meta_length, profile_length; +static unsigned thumb_misc, *oprof, fuji_layout; +static unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress; +static unsigned black, maximum, mix_green, raw_color, zero_is_bad; +static unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error; +static unsigned tile_width, tile_length, gpsdata[32], load_flags; +static unsigned flip, tiff_flip, filters, colors; +static ushort raw_height, raw_width, height, width, top_margin, left_margin; +static ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height; +static ushort *raw_image, (*image)[4], cblack[4102]; +static ushort white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4]; + +static unsigned shot_select=0, multi_out=0; +static double pixel_aspect, aber[4]={1,1,1,1}, gamm[6]={ 0.45,4.5,0,0,0,0 }; +static float bright=1, user_mul[4]={0,0,0,0}, threshold=0; +static int mask[8][4]; +static int half_size=0, four_color_rgb=0, document_mode=0, highlight=0; +static int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=1; +static int output_color=1, output_bps=8, output_tiff=0, med_passes=0; +static int no_auto_bright=0; +static unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX }; +static float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4]; +static const double xyz_rgb[3][3] = { /* XYZ from RGB */ { 0.412453, 0.357580, 0.180423 }, { 0.212671, 0.715160, 0.072169 }, { 0.019334, 0.119193, 0.950227 } }; -const float d65_white[3] = { 0.950456, 1, 1.088754 }; -int histogram[4][0x2000]; -void (*write_thumb)(), (*write_fun)(); -void (*load_raw)(), (*thumb_load_raw)(); -jmp_buf failure; +static const float d65_white[3] = { 0.950456, 1, 1.088754 }; +static int histogram[4][0x2000]; +static void (*write_thumb)(), (*write_fun)(); +static void (*load_raw)(), (*thumb_load_raw)(); +static jmp_buf failure; -struct decode { +static struct decode { struct decode *branch[2]; int leaf; -} first_decode[2048], *second_decode, *free_decode; +} first_decode[2048], /* *second_decode, CINELERRA */ *free_decode; -struct tiff_ifd { +static struct tiff_ifd { int width, height, bps, comp, phint, offset, flip, samples, bytes; int tile_width, tile_length; + float shutter; } tiff_ifd[10]; -struct ph1 { - int format, key_off, black, black_off, split_col, tag_21a; +static struct ph1 { + int format, key_off, tag_21a; + int black, split_col, black_col, split_row, black_row; float tag_210; } ph1; -#define CLASS - #define FORC(cnt) for (c=0; c < cnt; c++) #define FORC3 FORC(3) #define FORC4 FORC(4) @@ -199,7 +191,7 @@ struct ph1 { #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define LIM(x,min,max) MAX(min,MIN(x,max)) #define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y)) -#define CLIP(x) LIM(x,0,65535) +#define CLIP(x) LIM((int)(x),0,65535) #define SWAP(a,b) { a=a+b; b=a-b; a=a-b; } /* @@ -272,20 +264,39 @@ int CLASS fcol (int row, int col) { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 }, { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 }, { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } }; - static const char filter2[6][6] = - { { 1,1,0,1,1,2 }, - { 1,1,2,1,1,0 }, - { 2,0,1,0,2,1 }, - { 1,1,2,1,1,0 }, - { 1,1,0,1,1,2 }, - { 0,2,1,2,0,1 } }; if (filters == 1) return filter[(row+top_margin)&15][(col+left_margin)&15]; - if (filters == 2) return filter2[(row+6) % 6][(col+6) % 6]; + if (filters == 9) return xtrans[(row+6) % 6][(col+6) % 6]; return FC(row,col); } -#ifndef __GLIBC__ +// CINELERRA +static void reset() +{ + shot_select=0; + multi_out=0; + aber[0]=1; aber[1]=1; aber[2]=1; aber[3]=1; + gamm[0]=0.45; gamm[1]=4.5; gamm[2]=0; gamm[3]=0; gamm[4]=0; gamm[5]=0; + bright=1; + user_mul[0]=0; user_mul[1]=0; user_mul[2]=0; 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; + output_color=1; + output_bps=8; + output_tiff=0; + med_passes=0; + no_auto_bright=0; + greybox[0]=0; greybox[1]=0; greybox[2]=UINT_MAX; greybox[3]=UINT_MAX; +} + +#if 0 char *my_memmem (char *haystack, size_t haystacklen, char *needle, size_t needlelen) { @@ -296,6 +307,15 @@ char *my_memmem (char *haystack, size_t haystacklen, return 0; } #define memmem my_memmem +char *my_strcasestr (char *haystack, const char *needle) +{ + char *c; + for (c = haystack; *c; c++) + if (!strncasecmp(c, needle, strlen(needle))) + return c; + return 0; +} +#define strcasestr my_strcasestr #endif void CLASS merror (void *ptr, const char *where) @@ -391,6 +411,61 @@ void CLASS read_shorts (ushort *pixel, int count) swab (pixel, pixel, count*2); } +void CLASS cubic_spline (const int *x_, const int *y_, const int len) +{ + float **A, *b, *c, *d, *x, *y; + int i, j; + + A = (float **) calloc (((2*len + 4)*sizeof **A + sizeof *A), 2*len); + if (!A) return; + A[0] = (float *) (A + 2*len); + for (i = 1; i < 2*len; i++) + A[i] = A[0] + 2*len*i; + y = len + (x = i + (d = i + (c = i + (b = A[0] + i*i)))); + for (i = 0; i < len; i++) { + x[i] = x_[i] / 65535.0; + y[i] = y_[i] / 65535.0; + } + for (i = len-1; i > 0; i--) { + b[i] = (y[i] - y[i-1]) / (x[i] - x[i-1]); + d[i-1] = x[i] - x[i-1]; + } + for (i = 1; i < len-1; i++) { + A[i][i] = 2 * (d[i-1] + d[i]); + if (i > 1) { + A[i][i-1] = d[i-1]; + A[i-1][i] = d[i-1]; + } + A[i][len-1] = 6 * (b[i+1] - b[i]); + } + for(i = 1; i < len-2; i++) { + float v = A[i+1][i] / A[i][i]; + for(j = 1; j <= len-1; j++) + A[i+1][j] -= v * A[i][j]; + } + for(i = len-2; i > 0; i--) { + float acc = 0; + for(j = i; j <= len-2; j++) + acc += A[i][j]*c[j]; + c[i] = (A[i][len-1] - acc) / A[i][i]; + } + for (i = 0; i < 0x10000; i++) { + float x_out = (float)(i / 65535.0); + float y_out = 0; + for (j = 0; j < len-1; j++) { + if (x[j] <= x_out && x_out <= x[j+1]) { + float v = x_out - x[j]; + y_out = y[j] + + ((y[j+1] - y[j]) / d[j] - (2 * d[j] * c[j] + c[j+1] * d[j])/6) * v + + (c[j] * 0.5) * v*v + ((c[j+1] - c[j]) / (6 * d[j])) * v*v*v; + } + } + curve[i] = y_out < 0.0 ? 0 : (y_out >= 1.0 ? 65535 : + (ushort)(y_out * 65535.0 + 0.5)); + } + free (A); +} + void CLASS canon_600_fixed_wb (int temp) { static const short mul[4][5] = { @@ -560,17 +635,14 @@ int CLASS canon_s2is() return 0; } -/* - getbits(-1) initializes the buffer - getbits(n) where 0 <= n <= 25 returns an n-bit integer - */ unsigned CLASS getbithuff (int nbits, ushort *huff) { static unsigned bitbuf=0; static int vbits=0, reset=0; unsigned c; - if (nbits == -1) + if (nbits > 25) return 0; + if (nbits < 0) return bitbuf = vbits = reset = 0; if (nbits == 0 || vbits < 0) return 0; while (!reset && vbits < nbits && (c = fgetc(ifp)) != EOF && @@ -779,27 +851,22 @@ void CLASS canon_load_raw() FORC(2) free (huff[c]); } -/* - Not a full implementation of Lossless JPEG, just - enough to decode Canon, Kodak and Adobe DNG images. - */ struct jhead { - int bits, high, wide, clrs, sraw, psv, restart, vpred[6]; - ushort *huff[6], *free[4], *row; + int algo, bits, high, wide, clrs, sraw, psv, restart, vpred[6]; + ushort quant[64], idct[64], *huff[20], *free[20], *row; }; int CLASS ljpeg_start (struct jhead *jh, int info_only) { - int c, tag, len; + ushort c, tag, len; uchar data[0x10000]; const uchar *dp; memset (jh, 0, sizeof *jh); jh->restart = INT_MAX; - fread (data, 2, 1, ifp); - if (data[1] != 0xd8) return 0; + if ((fgetc(ifp),fgetc(ifp)) != 0xd8) return 0; do { - fread (data, 2, 2, ifp); + if (!fread (data, 2, 2, ifp)) return 0; tag = data[0] << 8 | data[1]; len = (data[2] << 8 | data[3]) - 2; if (tag <= 0xff00) return 0; @@ -807,7 +874,9 @@ int CLASS ljpeg_start (struct jhead *jh, int info_only) switch (tag) { case 0xffc3: jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3; + case 0xffc1: case 0xffc0: + jh->algo = tag & 0xff; jh->bits = data[0]; jh->high = data[1] << 8 | data[2]; jh->wide = data[3] << 8 | data[4]; @@ -816,19 +885,25 @@ int CLASS ljpeg_start (struct jhead *jh, int info_only) break; case 0xffc4: if (info_only) break; - for (dp = data; dp < data+len && (c = *dp++) < 4; ) + for (dp = data; dp < data+len && !((c = *dp++) & -20); ) jh->free[c] = jh->huff[c] = make_decoder_ref (&dp); break; case 0xffda: jh->psv = data[1+data[0]*2]; jh->bits -= data[3+data[0]*2] & 15; break; + case 0xffdb: + FORC(64) jh->quant[c] = data[c*2+1] << 8 | data[c*2+2]; + break; case 0xffdd: jh->restart = data[0] << 8 | data[1]; } } while (tag != 0xffda); + if (jh->bits > 16 || jh->clrs > 6 || + !jh->bits || !jh->high || !jh->wide || !jh->clrs) return 0; if (info_only) return 1; - FORC(5) if (!jh->huff[c+1]) jh->huff[c+1] = jh->huff[c]; + if (!jh->huff[0]) return 0; + FORC(19) 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]; @@ -914,16 +989,16 @@ void CLASS lossless_jpeg_load_raw() val = curve[*rp++]; if (cr2_slice[0]) { jidx = jrow*jwide + jcol; - i = jidx / (cr2_slice[1]*jh.high); + i = jidx / (cr2_slice[1]*raw_height); if ((j = i >= cr2_slice[0])) i = cr2_slice[0]; - jidx -= i * (cr2_slice[1]*jh.high); + jidx -= i * (cr2_slice[1]*raw_height); row = jidx / cr2_slice[1+j]; col = jidx % cr2_slice[1+j] + i*cr2_slice[1]; } if (raw_width == 3984 && (col -= 2) < 0) col += (row--,raw_width); - if (row >= 0) RAW(row,col) = val; + if ((unsigned) row < raw_height) RAW(row,col) = val; if (++col >= raw_width) col = (row++,0); } @@ -939,7 +1014,7 @@ void CLASS canon_sraw_load_raw() int v[3]={0,0,0}, ver, hue; char *cp; - if (!ljpeg_start (&jh, 0)) return; + if (!ljpeg_start (&jh, 0) || jh.clrs < 4) return; jwide = (jh.wide >>= 1) * jh.clrs; for (ecol=slice=0; slice <= cr2_slice[0]; slice++) { @@ -968,7 +1043,7 @@ void CLASS canon_sraw_load_raw() ip = (short (*)[4]) image; rp = ip[0]; for (row=0; row < height; row++, ip+=width) { - if (row & (jh.sraw >> 1)) { + if (row & (jh.sraw >> 1)) { //CINELERRA for (col=0; col < width; col+=2) for (c=1; c < 3; c++) if (row == height-1) @@ -1008,23 +1083,59 @@ void CLASS adobe_copy_pixel (unsigned row, unsigned col, ushort **rp) { int c; - if (is_raw == 2 && shot_select) (*rp)++; + if (tiff_samples == 2 && shot_select) (*rp)++; if (raw_image) { if (row < raw_height && col < raw_width) RAW(row,col) = curve[**rp]; - *rp += is_raw; + *rp += tiff_samples; } else { if (row < height && col < width) FORC(tiff_samples) image[row*width+col][c] = curve[(*rp)[c]]; *rp += tiff_samples; } - if (is_raw == 2 && shot_select) (*rp)--; + if (tiff_samples == 2 && shot_select) (*rp)--; +} + +void CLASS ljpeg_idct (struct jhead *jh) +{ + int c, i, j, len, skip, coef; + float work[3][8][8]; + static float cs[106] = { 0 }; + static const uchar zigzag[80] = + { 0, 1, 8,16, 9, 2, 3,10,17,24,32,25,18,11, 4, 5,12,19,26,33, + 40,48,41,34,27,20,13, 6, 7,14,21,28,35,42,49,56,57,50,43,36, + 29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54, + 47,55,62,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63 }; + + if (!cs[0]) + FORC(106) cs[c] = cos((c & 31)*M_PI/16)/2; + memset (work, 0, sizeof work); + work[0][0][0] = jh->vpred[0] += ljpeg_diff (jh->huff[0]) * jh->quant[0]; + for (i=1; i < 64; i++ ) { + len = gethuff (jh->huff[16]); + i += skip = len >> 4; + if (!(len &= 15) && skip < 15) break; + coef = getbits(len); + if ((coef & (1 << (len-1))) == 0) + coef -= (1 << len) - 1; + ((float *)work)[zigzag[i]] = coef * jh->quant[i]; + } + FORC(8) work[0][0][c] *= M_SQRT1_2; + FORC(8) work[0][c][0] *= M_SQRT1_2; + for (i=0; i < 8; i++) + for (j=0; j < 8; j++) + FORC(8) work[1][i][j] += work[0][i][c] * cs[(j*2+1)*c]; + for (i=0; i < 8; i++) + for (j=0; j < 8; j++) + FORC(8) work[2][i][j] += work[1][c][j] * cs[(i*2+1)*c]; + + FORC(64) jh->idct[c] = CLIP(((float *)work[2])[c]+0.5); } void CLASS lossless_dng_load_raw() { - unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col; + unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col, i, j; struct jhead jh; ushort *rp; @@ -1035,14 +1146,32 @@ void CLASS lossless_dng_load_raw() if (!ljpeg_start (&jh, 0)) break; jwide = jh.wide; if (filters) jwide *= jh.clrs; - jwide /= is_raw; - for (row=col=jrow=0; jrow < jh.high; jrow++) { - rp = ljpeg_row (jrow, &jh); - for (jcol=0; jcol < jwide; jcol++) { - adobe_copy_pixel (trow+row, tcol+col, &rp); - if (++col >= tile_width || col >= raw_width) - row += 1 + (col = 0); - } + jwide /= MIN (is_raw, tiff_samples); + switch (jh.algo) { + case 0xc1: + jh.vpred[0] = 16384; + getbits(-1); + for (jrow=0; jrow+7 < jh.high; jrow += 8) { + for (jcol=0; jcol+7 < jh.wide; jcol += 8) { + ljpeg_idct (&jh); + rp = jh.idct; + row = trow + jcol/tile_width + jrow*2; + col = tcol + jcol%tile_width; + for (i=0; i < 16; i+=2) + for (j=0; j < 8; j++) + adobe_copy_pixel (row+i, col+j, &rp); + } + } + break; + case 0xc3: + for (row=col=jrow=0; jrow < jh.high; jrow++) { + rp = ljpeg_row (jrow, &jh); + for (jcol=0; jcol < jwide; jcol++) { + adobe_copy_pixel (trow+row, tcol+col, &rp); + if (++col >= tile_width || col >= raw_width) + row += 1 + (col = 0); + } + } } fseek (ifp, save+4, SEEK_SET); if ((tcol += tile_width) >= raw_width) @@ -1056,7 +1185,7 @@ void CLASS packed_dng_load_raw() ushort *pixel, *rp; int row, col; - pixel = (ushort *) calloc (raw_width * tiff_samples, sizeof *pixel); + pixel = (ushort *) calloc (raw_width, tiff_samples*sizeof *pixel); merror (pixel, "packed_dng_load_raw()"); for (row=0; row < raw_height; row++) { if (tiff_bps == 16) @@ -1164,6 +1293,25 @@ void CLASS nikon_load_raw() free (huff); } +void CLASS nikon_yuv_load_raw() +{ + int row, col, yuv[4], rgb[3], b, c; + UINT64 bitbuf=0; + + for (row=0; row < raw_height; row++) + for (col=0; col < raw_width; col++) { + if (!(b = col & 1)) { + bitbuf = 0; + FORC(6) bitbuf |= (UINT64) fgetc(ifp) << c*8; + FORC(4) yuv[c] = (bitbuf >> c*12 & 0xfff) - (c >> 1 << 11); + } + rgb[0] = yuv[b] + 1.370705*yuv[3]; + rgb[1] = yuv[b] - 0.337633*yuv[2] - 0.698001*yuv[3]; + rgb[2] = yuv[b] + 1.732446*yuv[2]; + FORC3 image[row*width+col][c] = curve[LIM(rgb[c],0,0xfff)] / cam_mul[c]; + } +} + /* Returns 1 for a Coolpix 995, 0 for anything else. */ @@ -1208,10 +1356,10 @@ void CLASS nikon_3700() int bits; char make[12], model[15]; } table[] = { - { 0x00, "PENTAX", "Optio 33WR" }, - { 0x03, "NIKON", "E3200" }, - { 0x32, "NIKON", "E3700" }, - { 0x33, "OLYMPUS", "C740UZ" } }; + { 0x00, "Pentax", "Optio 33WR" }, + { 0x03, "Nikon", "E3200" }, + { 0x32, "Nikon", "E3700" }, + { 0x33, "Olympus", "C740UZ" } }; fseek (ifp, 3072, SEEK_SET); fread (dp, 1, 24, ifp); @@ -1257,7 +1405,7 @@ void CLASS ppm16_thumb() int i; char *thumb; thumb_length = thumb_width*thumb_height*3; - thumb = (char *) calloc (thumb_length,2); + thumb = (char *) calloc (thumb_length, 2); merror (thumb, "ppm16_thumb()"); read_shorts ((ushort *) thumb, thumb_length); for (i=0; i < thumb_length; i++) @@ -1332,14 +1480,16 @@ int CLASS raw (unsigned row, unsigned col) void CLASS phase_one_flat_field (int is_float, int nc) { ushort head[8]; - unsigned wide, y, x, c, rend, cend, row, col; + unsigned wide, high, y, x, c, rend, cend, row, col; float *mrow, num, mult[4]; read_shorts (head, 8); - wide = head[2] / head[4]; + if (head[2] * head[3] * head[4] * head[5] == 0) return; + wide = head[2] / head[4] + (head[2] % head[4] != 0); + high = head[3] / head[5] + (head[3] % head[5] != 0); mrow = (float *) calloc (nc*wide, sizeof *mrow); merror (mrow, "phase_one_flat_field()"); - for (y=0; y < head[3] / head[5]; y++) { + for (y=0; y < high; y++) { for (x=0; x < wide; x++) for (c=0; c < nc; c+=2) { num = is_float ? getreal(11) : get2()/32768.0; @@ -1348,14 +1498,18 @@ void CLASS phase_one_flat_field (int is_float, int nc) } if (y==0) continue; rend = head[1] + y*head[5]; - for (row = rend-head[5]; row < raw_height && row < rend; row++) { + for (row = rend-head[5]; + row < raw_height && row < rend && + row < head[1]+head[3]-head[5]; row++) { for (x=1; x < wide; x++) { for (c=0; c < nc; c+=2) { mult[c] = mrow[c*wide+x-1]; mult[c+1] = (mrow[c*wide+x] - mult[c]) / head[4]; } cend = head[0] + x*head[4]; - for (col = cend-head[4]; col < raw_width && col < cend; col++) { + for (col = cend-head[4]; + col < raw_width && + col < cend && col < head[0]+head[2]-head[4]; col++) { c = nc > 2 ? FC(row-top_margin,col-left_margin) : 0; if (!(c & 1)) { c = RAW(row,col) * mult[c]; @@ -1383,6 +1537,7 @@ void CLASS phase_one_correct() {-2,-2}, {-2,2}, {2,-2}, {2,2} }; float poly[8], num, cfrac, frac, mult[2], *yval[2]; ushort *xval[2]; + int qmult_applied = 0, qlin_applied = 0; if (half_size || !meta_length) return; if (verbose) fprintf (stderr,_("Phase One correction...\n")); @@ -1422,7 +1577,7 @@ void CLASS phase_one_correct() row = get2(); type = get2(); get2(); if (col >= raw_width) continue; - if (type == 131) /* Bad column */ + if (type == 131 || type == 137) /* Bad column */ for (row=0; row < raw_height; row++) if (FC(row-top_margin,col-left_margin) == 1) { for (sum=i=0; i < 4; i++) @@ -1459,6 +1614,83 @@ void CLASS phase_one_correct() mindiff = diff; off_412 = ftell(ifp) - 38; } + } else if (tag == 0x41f && !qlin_applied) { /* Quadrant linearization */ + ushort lc[2][2][16], ref[16]; + int qr, qc; + for (qr = 0; qr < 2; qr++) + for (qc = 0; qc < 2; qc++) + for (i = 0; i < 16; i++) + lc[qr][qc][i] = get4(); + for (i = 0; i < 16; i++) { + int v = 0; + for (qr = 0; qr < 2; qr++) + for (qc = 0; qc < 2; qc++) + v += lc[qr][qc][i]; + ref[i] = (v + 2) >> 2; + } + for (qr = 0; qr < 2; qr++) { + for (qc = 0; qc < 2; qc++) { + int cx[19], cf[19]; + for (i = 0; i < 16; i++) { + cx[1+i] = lc[qr][qc][i]; + cf[1+i] = ref[i]; + } + cx[0] = cf[0] = 0; + cx[17] = cf[17] = ((unsigned) ref[15] * 65535) / lc[qr][qc][15]; + cx[18] = cf[18] = 65535; + cubic_spline(cx, cf, 19); + for (row = (qr ? ph1.split_row : 0); + row < (qr ? raw_height : ph1.split_row); row++) + for (col = (qc ? ph1.split_col : 0); + col < (qc ? raw_width : ph1.split_col); col++) + RAW(row,col) = curve[RAW(row,col)]; + } + } + qlin_applied = 1; + } else if (tag == 0x41e && !qmult_applied) { /* Quadrant multipliers */ + float qmult[2][2] = { { 1, 1 }, { 1, 1 } }; + get4(); get4(); get4(); get4(); + qmult[0][0] = 1.0 + getreal(11); + get4(); get4(); get4(); get4(); get4(); + qmult[0][1] = 1.0 + getreal(11); + get4(); get4(); get4(); + qmult[1][0] = 1.0 + getreal(11); + get4(); get4(); get4(); + qmult[1][1] = 1.0 + getreal(11); + for (row=0; row < raw_height; row++) + for (col=0; col < raw_width; col++) { + i = qmult[row >= ph1.split_row][col >= ph1.split_col] * RAW(row,col); + RAW(row,col) = LIM(i,0,65535); + } + qmult_applied = 1; + } else if (tag == 0x431 && !qmult_applied) { /* Quadrant combined */ + ushort lc[2][2][7], ref[7]; + int qr, qc; + for (i = 0; i < 7; i++) + ref[i] = get4(); + for (qr = 0; qr < 2; qr++) + for (qc = 0; qc < 2; qc++) + for (i = 0; i < 7; i++) + lc[qr][qc][i] = get4(); + for (qr = 0; qr < 2; qr++) { + for (qc = 0; qc < 2; qc++) { + int cx[9], cf[9]; + for (i = 0; i < 7; i++) { + cx[1+i] = ref[i]; + cf[1+i] = ((unsigned) ref[i] * lc[qr][qc][i]) / 10000; + } + cx[0] = cf[0] = 0; + cx[8] = cf[8] = 65535; + cubic_spline(cx, cf, 9); + for (row = (qr ? ph1.split_row : 0); + row < (qr ? raw_height : ph1.split_row); row++) + for (col = (qc ? ph1.split_col : 0); + col < (qc ? raw_width : ph1.split_col); col++) + RAW(row,col) = curve[RAW(row,col)]; + } + } + qmult_applied = 1; + qlin_applied = 1; } fseek (ifp, save, SEEK_SET); } @@ -1545,18 +1777,22 @@ void CLASS phase_one_load_raw_c() static const int length[] = { 8,7,6,9,11,10,5,12,14,13 }; int *offset, len[2], pred[2], row, col, i, j; ushort *pixel; - short (*black)[2]; + short (*cblack)[2], (*rblack)[2]; - pixel = (ushort *) calloc (raw_width + raw_height*4, 2); + pixel = (ushort *) calloc (raw_width*3 + raw_height*4, 2); merror (pixel, "phase_one_load_raw_c()"); offset = (int *) (pixel + raw_width); fseek (ifp, strip_offset, SEEK_SET); for (row=0; row < raw_height; row++) offset[row] = get4(); - black = (short (*)[2]) offset + raw_height; - fseek (ifp, ph1.black_off, SEEK_SET); - if (ph1.black_off) - read_shorts ((ushort *) black[0], raw_height*2); + cblack = (short (*)[2]) (offset + raw_height); + fseek (ifp, ph1.black_col, SEEK_SET); + if (ph1.black_col) + read_shorts ((ushort *) cblack[0], raw_height*2); + rblack = cblack + raw_height; + fseek (ifp, ph1.black_row, SEEK_SET); + if (ph1.black_row) + read_shorts ((ushort *) rblack[0], raw_width*2); for (i=0; i < 256; i++) curve[i] = i*i / 3.969 + 0.5; for (row=0; row < raw_height; row++) { @@ -1580,8 +1816,10 @@ void CLASS phase_one_load_raw_c() pixel[col] = curve[pixel[col]]; } for (col=0; col < raw_width; col++) { - i = (pixel[col] << 2) - ph1.black + black[row][col >= ph1.split_col]; - if (i > 0) RAW(row,col) = i; + i = (pixel[col] << 2*(ph1.format != 8)) - ph1.black + + cblack[row][col >= ph1.split_col] + + rblack[col][row >= ph1.split_row]; + if (i > 0) RAW(row,col) = i; } } free (pixel); @@ -1591,26 +1829,57 @@ void CLASS phase_one_load_raw_c() void CLASS hasselblad_load_raw() { struct jhead jh; - int row, col, pred[2], len[2], diff, c; + int shot, row, col, *back[5], len[2], diff[12], pred, sh, f, s, c; + unsigned upix, urow, ucol; + ushort *ip; if (!ljpeg_start (&jh, 0)) return; order = 0x4949; ph1_bits(-1); + back[4] = (int *) calloc (raw_width, 3*sizeof **back); + merror (back[4], "hasselblad_load_raw()"); + FORC3 back[c] = back[4] + c*raw_width; + cblack[6] >>= sh = tiff_samples > 1; + shot = LIM(shot_select, 1, tiff_samples) - 1; for (row=0; row < raw_height; row++) { - pred[0] = pred[1] = 0x8000 + load_flags; + FORC4 back[(c+3) & 3] = back[c]; for (col=0; col < raw_width; col+=2) { - 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; - RAW(row,col+c) = pred[c] += diff; + for (s=0; s < tiff_samples*2; s+=2) { + FORC(2) len[c] = ph1_huff(jh.huff[0]); + FORC(2) { + diff[s+c] = ph1_bits(len[c]); + if ((diff[s+c] & (1 << (len[c]-1))) == 0) + diff[s+c] -= (1 << len[c]) - 1; + if (diff[s+c] == 65535) diff[s+c] = -32768; + } + } + for (s=col; s < col+2; s++) { + pred = 0x8000 + load_flags; + if (col) pred = back[2][s-2]; + if (col && row > 1) switch (jh.psv) { + case 11: pred += back[0][s]/2 - back[0][s-2]/2; break; + } + f = (row & 1)*3 ^ ((col+s) & 1); + FORC (tiff_samples) { + pred += diff[(s & 1)*tiff_samples+c]; + upix = pred >> sh & 0xffff; + if (raw_image && c == shot) + RAW(row,s) = upix; + if (image) { + urow = row-top_margin + (c & 1); + ucol = col-left_margin - ((c >> 1) & 1); + ip = &image[urow*width+ucol][f]; + if (urow < height && ucol < width) + *ip = c < 4 ? upix : (*ip + upix) >> 1; + } + } + back[2][s] = pred; } } } + free (back[4]); ljpeg_end (&jh); - maximum = 0xffff; + if (image) mix_green = 1; } void CLASS leaf_hdr_load_raw() @@ -1660,20 +1929,13 @@ void CLASS sinar_4shot_load_raw() ushort *pixel; unsigned shot, row, col, r, c; - if ((shot = shot_select) || half_size) { - if (shot) shot--; - if (shot > 3) shot = 3; + if (raw_image) { + shot = LIM (shot_select, 1, 4) - 1; fseek (ifp, data_offset + shot*4, SEEK_SET); fseek (ifp, get4(), SEEK_SET); unpacked_load_raw(); return; } - free (raw_image); - raw_image = 0; - free (image); - image = (ushort (*)[4]) - calloc ((iheight=height)*(iwidth=width), sizeof *image); - merror (image, "sinar_4shot_load_raw()"); pixel = (ushort *) calloc (raw_width, sizeof *pixel); merror (pixel, "sinar_4shot_load_raw()"); for (shot=0; shot < 4; shot++) { @@ -1684,18 +1946,19 @@ void CLASS sinar_4shot_load_raw() if ((r = row-top_margin - (shot >> 1 & 1)) >= height) continue; for (col=0; col < raw_width; col++) { if ((c = col-left_margin - (shot & 1)) >= width) continue; - image[r*width+c][FC(row,col)] = pixel[col]; + image[r*width+c][(row & 1)*3 ^ (~col & 1)] = pixel[col]; } } } free (pixel); - shrink = filters = 0; + mix_green = 1; } void CLASS imacon_full_load_raw() { int row, col; + if (!image) return; for (row=0; row < height; row++) for (col=0; col < width; col++) read_shorts (image[row*width+col], 3); @@ -1703,13 +1966,12 @@ void CLASS imacon_full_load_raw() void CLASS packed_load_raw() { - int vbits=0, bwide, pwide, rbits, bite, half, irow, row, col, val, i; + int vbits=0, bwide, rbits, bite, half, irow, row, col, val, i; UINT64 bitbuf=0; - if (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; + bwide = raw_width * tiff_bps / 8; + bwide += bwide & load_flags >> 7; + rbits = bwide * 8 - raw_width * tiff_bps; if (load_flags & 1) bwide = bwide * 16 / 15; bite = 8 + (load_flags & 24); half = (raw_height+1) >> 1; @@ -1725,16 +1987,16 @@ void CLASS packed_load_raw() fseek (ifp, ftell(ifp) >> 3 << 2, SEEK_SET); } } - for (col=0; col < pwide; col++) { + for (col=0; col < raw_width; 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); - RAW(row,col ^ (load_flags >> 6)) = val; - if (load_flags & 1 && (col % 10) == 9 && - fgetc(ifp) && col < width+left_margin) derror(); + RAW(row,col ^ (load_flags >> 6 & 1)) = val; + if (load_flags & 1 && (col % 10) == 9 && fgetc(ifp) && + row < height+top_margin && col < width+left_margin) derror(); } vbits -= rbits; } @@ -1744,9 +2006,10 @@ void CLASS nokia_load_raw() { uchar *data, *dp; int rev, dwide, row, col, c; + double sum[]={0,0}; rev = 3 * (order == 0x4949); - dwide = raw_width * 5 / 4; + dwide = (raw_width * 5 + 1) / 4; data = (uchar *) malloc (dwide*2); merror (data, "nokia_load_raw()"); for (row=0; row < raw_height; row++) { @@ -1757,6 +2020,33 @@ void CLASS nokia_load_raw() } free (data); maximum = 0x3ff; + if (strcmp(make,"OmniVision")) return; + row = raw_height/2; + FORC(width-1) { + sum[ c & 1] += SQR(RAW(row,c)-RAW(row+1,c+1)); + sum[~c & 1] += SQR(RAW(row+1,c)-RAW(row,c+1)); + } + if (sum[1] > sum[0]) filters = 0x4b4b4b4b; +} + +void CLASS canon_rmf_load_raw() +{ + int row, col, bits, orow, ocol, c; + + for (row=0; row < raw_height; row++) + for (col=0; col < raw_width-2; col+=3) { + bits = get4(); + FORC3 { + orow = row; + if ((ocol = col+c-4) < 0) { + ocol += raw_width; + if ((orow -= 2) < 0) + orow += raw_height; + } + RAW(orow,ocol) = curve[bits >> (10*c+2) & 0x3ff]; + } + } + maximum = curve[0x3ff]; } unsigned CLASS pana_bits (int nbits) @@ -1967,7 +2257,7 @@ 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], *bp; + 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 }; @@ -1977,12 +2267,12 @@ void CLASS kodak_radc_load_raw() (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 < sizeof src; i+=2) FORC(256 >> src[i]) - huff[0][s++] = src[i] << 8 | (uchar) src[i+1]; + ((ushort *)huff)[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 ( bp=&buf[0][0][0],i=sizeof(buf)/sizeof(*bp); --i>=0; ++bp ) - *bp = 2048; + for (i=0; i < sizeof(buf)/sizeof(short); i++) + ((short *)buf)[i] = 2048; for (row=0; row < height; row+=4) { FORC3 mul[c] = getbits(6); FORC3 { @@ -1991,8 +2281,7 @@ void CLASS kodak_radc_load_raw() x = ~(-1 << (s-1)); val <<= 12-s; for (i=0; i < sizeof(buf[0])/sizeof(short); i++) - for ( bp=&buf[c][0][0],i=sizeof(buf[0])/sizeof(*bp); --i>=0; ++bp ) - *bp = (*bp * val + x) >> s; + ((short *)buf[c])[i] = (((short *)buf[c])[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; @@ -2102,6 +2391,8 @@ void CLASS kodak_jpeg_load_raw() maximum = 0xff << 1; } +void CLASS gamma_curve (double pwr, double ts, int mode, int imax); + void CLASS lossy_dng_load_raw() { struct jpeg_decompress_struct cinfo; @@ -2110,29 +2401,34 @@ void CLASS lossy_dng_load_raw() JSAMPLE (*pixel)[3]; unsigned sorder=order, ntags, opcode, deg, i, j, c; unsigned save=data_offset-4, trow=0, tcol=0, row, col; - ushort curve[3][256]; + ushort cur[3][256]; double coeff[9], tot; - fseek (ifp, meta_offset, SEEK_SET); - order = 0x4d4d; - ntags = get4(); - while (ntags--) { - opcode = get4(); get4(); get4(); - if (opcode != 8) - { fseek (ifp, get4(), SEEK_CUR); continue; } - fseek (ifp, 20, SEEK_CUR); - if ((c = get4()) > 2) break; - fseek (ifp, 12, SEEK_CUR); - if ((deg = get4()) > 8) break; - for (i=0; i <= deg && i < 9; i++) - coeff[i] = getreal(12); - for (i=0; i < 256; i++) { - for (tot=j=0; j <= deg; j++) - tot += coeff[j] * pow(i/255.0, j); - curve[c][i] = tot*0xffff; + if (meta_offset) { + fseek (ifp, meta_offset, SEEK_SET); + order = 0x4d4d; + ntags = get4(); + while (ntags--) { + opcode = get4(); get4(); get4(); + if (opcode != 8) + { fseek (ifp, get4(), SEEK_CUR); continue; } + fseek (ifp, 20, SEEK_CUR); + if ((c = get4()) > 2) break; + fseek (ifp, 12, SEEK_CUR); + if ((deg = get4()) > 8) break; + for (i=0; i <= deg && i < 9; i++) + coeff[i] = getreal(12); + for (i=0; i < 256; i++) { + for (tot=j=0; j <= deg; j++) + tot += coeff[j] * pow(i/255.0, j); + cur[c][i] = tot*0xffff; + } } + order = sorder; + } else { + gamma_curve (1/2.4, 12.92, 1, 255); + FORC3 memcpy (cur[c], curve, sizeof cur[0]); } - order = sorder; cinfo.err = jpeg_std_error (&jerr); jpeg_create_decompress (&cinfo); while (trow < raw_height) { @@ -2149,7 +2445,7 @@ void CLASS lossy_dng_load_raw() jpeg_read_scanlines (&cinfo, buf, 1); pixel = (JSAMPLE (*)[3]) buf[0]; for (col=0; col < cinfo.output_width && tcol+col < width; col++) { - FORC3 image[row*width+tcol+col][c] = curve[c][pixel[col][c]]; + FORC3 image[row*width+tcol+col][c] = cur[c][pixel[col][c]]; } } jpeg_abort_decompress (&cinfo); @@ -2193,21 +2489,46 @@ void CLASS eight_bit_load_raw() maximum = curve[0xff]; } -void CLASS kodak_yrgb_load_raw() +void CLASS kodak_c330_load_raw() +{ + uchar *pixel; + int row, col, y, cb, cr, rgb[3], c; + + pixel = (uchar *) calloc (raw_width, 2*sizeof *pixel); + merror (pixel, "kodak_c330_load_raw()"); + for (row=0; row < height; row++) { + if (fread (pixel, raw_width, 2, ifp) < 2) derror(); + if (load_flags && (row & 31) == 31) + fseek (ifp, raw_width*32, SEEK_CUR); + for (col=0; col < width; col++) { + y = pixel[col*2]; + cb = pixel[(col*2 & -4) | 1] - 128; + cr = pixel[(col*2 & -4) | 3] - 128; + rgb[1] = y - ((cb + cr + 2) >> 2); + rgb[2] = rgb[1] + cb; + rgb[0] = rgb[1] + cr; + FORC3 image[row*width+col][c] = curve[LIM(rgb[c],0,255)]; + } + } + free (pixel); + maximum = curve[0xff]; +} + +void CLASS kodak_c603_load_raw() { uchar *pixel; int row, col, y, cb, cr, rgb[3], c; pixel = (uchar *) calloc (raw_width, 3*sizeof *pixel); - merror (pixel, "kodak_yrgb_load_raw()"); + merror (pixel, "kodak_c603_load_raw()"); for (row=0; row < height; row++) { if (~row & 1) if (fread (pixel, raw_width, 3, ifp) < 3) derror(); - for (col=0; col < raw_width; col++) { + for (col=0; col < width; col++) { y = pixel[width*2*(row & 1) + col]; cb = pixel[width + (col & -2)] - 128; cr = pixel[width + (col & -2)+1] - 128; - rgb[1] = y-((cb + cr + 2) >> 2); + rgb[1] = y - ((cb + cr + 2) >> 2); rgb[2] = rgb[1] + cb; rgb[0] = rgb[1] + cr; FORC3 image[row*width+col][c] = curve[LIM(rgb[c],0,255)]; @@ -2326,6 +2647,7 @@ void CLASS kodak_ycbcr_load_raw() int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3]; ushort *ip; + if (!image) return; for (row=0; row < height; row+=2) for (col=0; col < width; col+=128) { len = MIN (128, width-col); @@ -2353,8 +2675,6 @@ void CLASS kodak_rgb_load_raw() int row, col, len, c, i, rgb[3]; ushort *ip=image[0]; - if (raw_image) free (raw_image); - raw_image = 0; for (row=0; row < height; row++) for (col=0; col < width; col+=256) { len = MIN (256, width-col); @@ -2377,7 +2697,7 @@ void CLASS kodak_thumb_load_raw() void CLASS sony_decrypt (unsigned *data, int len, int start, int key) { - static unsigned pad[128], p = 0; + static unsigned pad[128], p; if (start) { for (p=0; p < 4; p++) @@ -2388,10 +2708,8 @@ void CLASS sony_decrypt (unsigned *data, int len, int start, int key) for (p=0; p < 127; p++) pad[p] = htonl(pad[p]); } - while (len--) { - *data++ ^= pad[p & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127]; - p++; - } + while (len-- && p++) + *data++ ^= pad[(p-1) & 127] = pad[p & 127] ^ pad[(p+64) & 127]; } void CLASS sony_load_raw() @@ -2406,14 +2724,14 @@ void CLASS sony_load_raw() key = get4(); fseek (ifp, 164600, SEEK_SET); fread (head, 1, 40, ifp); - sony_decrypt ((unsigned int *) head, 10, 1, key); + sony_decrypt ((unsigned *) head, 10, 1, key); for (i=26; i-- > 22; ) key = key << 8 | head[i]; fseek (ifp, data_offset, SEEK_SET); for (row=0; row < raw_height; row++) { pixel = raw_image + row*raw_width; if (fread (pixel, 2, raw_width, ifp) < raw_width) derror(); - sony_decrypt ((unsigned int *) pixel, raw_width/2, !row, key); + sony_decrypt ((unsigned *) pixel, raw_width/2, !row, key); for (col=0; col < raw_width; col++) if ((pixel[col] = ntohs(pixel[col])) >> 14) derror(); } @@ -2422,23 +2740,20 @@ void CLASS sony_load_raw() void CLASS sony_arw_load_raw() { - ushort huff[32768]; + ushort huff[32770]; 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; + int i, c, n, col, row, sum=0; + huff[0] = 15; for (n=i=0; i < 18; i++) - FORC(32768 >> (tab[i] >> 8)) huff[n++] = tab[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 = getbithuff(15,huff); - diff = getbits(len); - if ((diff & (1 << (len-1))) == 0) - diff -= (1 << len) - 1; - if ((sum += diff) >> 12) derror(); + if ((sum += ljpeg_diff(huff)) >> 12) derror(); if (row < height) RAW(row,col) = sum; } } @@ -2449,7 +2764,7 @@ void CLASS sony_arw2_load_raw() ushort pix[16]; int row, col, val, max, min, imax, imin, sh, bit, i; - data = (uchar *) malloc (raw_width); + data = (uchar *) malloc (raw_width+1); merror (data, "sony_arw2_load_raw()"); for (row=0; row < height; row++) { fread (data, 1, raw_width, ifp); @@ -2475,12 +2790,115 @@ void CLASS sony_arw2_load_raw() free (data); } +void CLASS samsung_load_raw() +{ + int row, col, c, i, dir, op[4], len[4]; + + order = 0x4949; + for (row=0; row < raw_height; row++) { + fseek (ifp, strip_offset+row*4, SEEK_SET); + fseek (ifp, data_offset+get4(), SEEK_SET); + ph1_bits(-1); + FORC4 len[c] = row < 2 ? 7:4; + for (col=0; col < raw_width; col+=16) { + dir = ph1_bits(1); + FORC4 op[c] = ph1_bits(2); + FORC4 switch (op[c]) { + case 3: len[c] = ph1_bits(4); break; + case 2: len[c]--; break; + case 1: len[c]++; + } + for (c=0; c < 16; c+=2) { + i = len[((c & 1) << 1) | (c >> 3)]; + RAW(row,col+c) = ((signed) ph1_bits(i) << (32-i) >> (32-i)) + + (dir ? RAW(row+(~c | -2),col+c) : col ? RAW(row,col+(c | -2)) : 128); + if (c == 14) c = -1; + } + } + } + for (row=0; row < raw_height-1; row+=2) + for (col=0; col < raw_width-1; col+=2) + SWAP (RAW(row,col+1), RAW(row+1,col)); +} + +void CLASS samsung2_load_raw() +{ + static const ushort tab[14] = + { 0x304,0x307,0x206,0x205,0x403,0x600,0x709, + 0x80a,0x90b,0xa0c,0xa0d,0x501,0x408,0x402 }; + ushort huff[1026], vpred[2][2] = {{0,0},{0,0}}, hpred[2]; + int i, c, n, row, col, diff; + + huff[0] = 10; + for (n=i=0; i < 14; i++) + FORC(1024 >> (tab[i] >> 8)) huff[++n] = tab[i]; + getbits(-1); + for (row=0; row < raw_height; row++) + for (col=0; col < raw_width; col++) { + diff = ljpeg_diff (huff); + if (col < 2) hpred[col] = vpred[row & 1][col] += diff; + else hpred[col & 1] += diff; + RAW(row,col) = hpred[col & 1]; + if (hpred[col & 1] >> tiff_bps) derror(); + } +} + +void CLASS samsung3_load_raw() +{ + int opt, init, mag, pmode, row, tab, col, pred, diff, i, c; + ushort lent[3][2], len[4], *prow[2]; + + order = 0x4949; + fseek (ifp, 9, SEEK_CUR); + opt = fgetc(ifp); + init = (get2(),get2()); + for (row=0; row < raw_height; row++) { + fseek (ifp, (data_offset-ftell(ifp)) & 15, SEEK_CUR); + ph1_bits(-1); + mag = 0; pmode = 7; + FORC(6) ((ushort *)lent)[c] = row < 2 ? 7:4; + prow[ row & 1] = &RAW(row-1,1-((row & 1) << 1)); // green + prow[~row & 1] = &RAW(row-2,0); // red and blue + for (tab=0; tab+15 < raw_width; tab+=16) { + if (~opt & 4 && !(tab & 63)) { + i = ph1_bits(2); + mag = i < 3 ? mag-'2'+"204"[i] : ph1_bits(12); + } + if (opt & 2) + pmode = 7 - 4*ph1_bits(1); + else if (!ph1_bits(1)) + pmode = ph1_bits(3); + if (opt & 1 || !ph1_bits(1)) { + FORC4 len[c] = ph1_bits(2); + FORC4 { + i = ((row & 1) << 1 | (c & 1)) % 3; + len[c] = len[c] < 3 ? lent[i][0]-'1'+"120"[len[c]] : ph1_bits(4); + lent[i][0] = lent[i][1]; + lent[i][1] = len[c]; + } + } + FORC(16) { + col = tab + (((c & 7) << 1)^(c >> 3)^(row & 1)); + pred = (pmode == 7 || row < 2) + ? (tab ? RAW(row,tab-2+(col & 1)) : init) + : (prow[col & 1][col-'4'+"0224468"[pmode]] + + prow[col & 1][col-'4'+"0244668"[pmode]] + 1) >> 1; + diff = ph1_bits (i = len[c >> 2]); + if (diff >> (i-1)) diff -= 1 << i; + diff = diff * (mag*2+1) + mag; + RAW(row,col) = pred + diff; + } + } + } +} + #define HOLE(row) ((holes >> (((row) - raw_height) & 7)) & 1) /* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */ void CLASS smal_decode_segment (unsigned seg[2][2], int holes) { - uchar hist[3][13] = { +// CINELERRA + uchar hist[3][18] = { { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 }, { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 }, { 3, 3, 0, 0, 63, 47, 31, 15, 0 } }; @@ -2491,6 +2909,8 @@ void CLASS smal_decode_segment (unsigned seg[2][2], int holes) fseek (ifp, seg[0][1]+1, SEEK_SET); getbits(-1); + if (seg[1][0] > raw_width*raw_height) + seg[1][0] = raw_width*raw_height; for (pix=seg[0][0]; pix < seg[1][0]; pix++) { for (s=0; s < 3; s++) { data = data << nbits | getbits(nbits); @@ -2596,10 +3016,10 @@ void CLASS smal_v9_load_raw() fseek (ifp, 67, SEEK_SET); offset = get4(); - nseg = fgetc(ifp); + nseg = (uchar) fgetc(ifp); fseek (ifp, offset, SEEK_SET); for (i=0; i < nseg*2; i++) - seg[0][i] = get4() + data_offset*(i & 1); + ((unsigned *)seg)[i] = get4() + data_offset*(i & 1); fseek (ifp, 78, SEEK_SET); holes = fgetc(ifp); fseek (ifp, 88, SEEK_SET); @@ -2627,7 +3047,7 @@ void CLASS redcine_load_raw() if (!jimg) longjmp (failure, 3); jmat = jas_matrix_create (height/2, width/2); merror (jmat, "redcine_load_raw()"); - img = (ushort *) calloc ((height+2)*(width+2), 2); + img = (ushort *) calloc ((height+2), (width+2)*2); merror (img, "redcine_load_raw()"); FORC4 { jas_image_readcmpt (jimg, c, 0, 0, width/2, height/2, jmat); @@ -2785,7 +3205,7 @@ void CLASS foveon_huff (ushort *huff) void CLASS foveon_dp_load_raw() { unsigned c, roff[4], row, col, diff; - ushort huff[258], vpred[2][2], hpred[2]; + ushort huff[512], vpred[2][2], hpred[2]; fseek (ifp, 8, SEEK_CUR); foveon_huff (huff); @@ -2838,7 +3258,7 @@ void CLASS foveon_load_camf() meta_data[j++] = hpred[0] >> 4; meta_data[j++] = hpred[0] << 4 | hpred[1] >> 8; meta_data[j++] = hpred[1]; - } + } } } } else @@ -2998,7 +3418,7 @@ void CLASS foveon_interpolate() foveon_camf_param ("IncludeBlocks", "ColorDQ") ? "ColorDQ" : "ColorDQCamRGB"); if (foveon_camf_param ("IncludeBlocks", "ColumnFilter")) - foveon_fixed (&cfilt, 1, "ColumnFilter"); + foveon_fixed (&cfilt, 1, "ColumnFilter"); memset (ddft, 0, sizeof ddft); if (!foveon_camf_param ("IncludeBlocks", "DarkDrift") @@ -3061,14 +3481,11 @@ void CLASS foveon_interpolate() black = (float (*)[3]) calloc (height, sizeof *black); for (row=0; row < height; row++) { - float *dp0 = &ddft[0][0][0]; - float *dp1 = &ddft[1][0][0]; - float *dp2 = &ddft[2][0][0]; - for( i=6; --i>=0; ++dp0,++dp1,++dp2 ) - *dp0 = *dp1 + row / (height-1.0) * (*dp2 - *dp1); - pix = image[row*width]; + for (i=0; i < 6; i++) + ((float *)ddft[0])[i] = ((float *)ddft[1])[i] + + row / (height-1.0) * (((float *)ddft[2])[i] - ((float *)ddft[1])[i]); FORC3 black[row][c] = - ( foveon_avg (image[row*width]+c, dscr[0], cfilt) + + ( foveon_avg (image[row*width]+c, dscr[0], cfilt) + foveon_avg (image[row*width]+c, dscr[1], cfilt) * 3 - ddft[0][c][0] ) / 4 - ddft[0][c][1]; } @@ -3110,11 +3527,9 @@ void CLASS foveon_interpolate() FORC3 black[row][c] += fsum[c]/2 + total[c]/(total[3]*100.0); for (row=0; row < height; row++) { - float *dp0 = &ddft[0][0][0]; - float *dp1 = &ddft[1][0][0]; - float *dp2 = &ddft[2][0][0]; - for( i=6; --i>=0; ++dp0,++dp1,++dp2 ) - *dp0 = *dp1 + row / (height-1.0) * (*dp2 - *dp1); + for (i=0; i < 6; i++) + ((float *)ddft[0])[i] = ((float *)ddft[1])[i] + + row / (height-1.0) * (((float *)ddft[2])[i] - ((float *)ddft[1])[i]); pix = image[row*width]; memcpy (prev, pix, sizeof prev); frow = row / (height-1.0) * (dim[2]-1); @@ -3153,7 +3568,7 @@ void CLASS foveon_interpolate() free (sgrow); free (sgain); - if ((badpix = (unsigned int *) foveon_camf_matrix (dim, "BadPixels"))) { + if ((badpix = (unsigned *) foveon_camf_matrix (dim, "BadPixels"))) { for (i=0; i < dim[0]; i++) { col = (badpix[i] >> 8 & 0xfff) - keep[0]; row = (badpix[i] >> 20 ) - keep[1]; @@ -3295,7 +3710,7 @@ void CLASS foveon_interpolate() } /* Smooth the image bottom-to-top and save at 1/4 scale */ - shrink = (short (*)[3]) calloc ((width/4) * (height/4), sizeof *shrink); + shrink = (short (*)[3]) calloc ((height/4), (width/4)*sizeof *shrink); merror (shrink, "foveon_interpolate()"); for (row = height/4; row--; ) for (col=0; col < width/4; col++) { @@ -3398,11 +3813,11 @@ void CLASS crop_masked_pixels() for (col=0; col < width; col++) BAYER2(row,col) = RAW(row+top_margin,col+left_margin); } - if (mask[0][3]) goto mask_set; + if (mask[0][3] > 0) goto mask_set; if (load_raw == &CLASS canon_load_raw || load_raw == &CLASS lossless_jpeg_load_raw) { - mask[0][1] = mask[1][1] = 2; - mask[0][3] = -2; + mask[0][1] = mask[1][1] += 2; + mask[0][3] -= 2; goto sides; } if (load_raw == &CLASS canon_600_load_raw || @@ -3424,8 +3839,8 @@ sides: mask_set: memset (mblack, 0, sizeof mblack); for (zero=m=0; m < 8; m++) - for (row=mask[m][0]; row < mask[m][2]; row++) - for (col=mask[m][1]; col < mask[m][3]; col++) { + for (row=MAX(mask[m][0],0); row < MIN(mask[m][2],raw_height); row++) + for (col=MAX(mask[m][1],0); col < MIN(mask[m][3],raw_width); col++) { c = FC(row-top_margin,col-left_margin); mblack[c] += val = RAW(row,col); mblack[4+c]++; @@ -3435,8 +3850,10 @@ mask_set: black = (mblack[0]+mblack[1]+mblack[2]+mblack[3]) / (mblack[4]+mblack[5]+mblack[6]+mblack[7]) - 4; canon_600_correct(); - } else if (zero < mblack[4] && mblack[5] && mblack[6] && mblack[7]) + } else if (zero < mblack[4] && mblack[5] && mblack[6] && mblack[7]) { FORC4 cblack[c] = mblack[c] / mblack[4+c]; + cblack[4] = cblack[5] = cblack[6] = 0; + } } void CLASS remove_zeroes() @@ -3625,7 +4042,7 @@ void CLASS pseudoinverse (double (*in)[3], double (*out)[3], int size) out[i][j] += work[j][k+3] * in[i][k]; } -void CLASS cam_xyz_coeff (double cam_xyz[4][3]) +void CLASS cam_xyz_coeff (float rgb_cam[3][4], double cam_xyz[4][3]) { double cam_rgb[4][3], inverse[4][3], num; int i, j, k; @@ -3643,7 +4060,7 @@ void CLASS cam_xyz_coeff (double cam_xyz[4][3]) pre_mul[i] = 1 / num; } pseudoinverse (cam_rgb, inverse, colors); - for (raw_color = i=0; i < 3; i++) + for (i=0; i < 3; i++) for (j=0; j < colors; j++) rgb_cam[i][j] = inverse[j][i]; } @@ -3682,8 +4099,8 @@ void CLASS colorcheck() { 0.310, 0.316, 9.0 }, // Neutral 3.5 { 0.310, 0.316, 3.1 } }; // Black double gmb_cam[NSQ][4], gmb_xyz[NSQ][3]; - double inverse[NSQ][3], cam_xyz[4][3], num; - int c, i, j, k, sq, row, col, count[4]; + double inverse[NSQ][3], cam_xyz[4][3], balance[4], num; + int c, i, j, k, sq, row, col, pass, count[4]; memset (gmb_cam, 0, sizeof gmb_cam); for (sq=0; sq < NSQ; sq++) { @@ -3692,7 +4109,8 @@ void CLASS colorcheck() for (col=cut[sq][2]; col < cut[sq][2]+cut[sq][0]; col++) { c = FC(row,col); if (c >= colors) c -= 2; - gmb_cam[sq][c] += BAYER(row,col); + gmb_cam[sq][c] += BAYER2(row,col); + BAYER2(row,col) = black + (BAYER2(row,col)-black)/2; count[c]++; } FORCC gmb_cam[sq][c] = gmb_cam[sq][c]/count[c] - black; @@ -3702,11 +4120,16 @@ void CLASS colorcheck() (1 - gmb_xyY[sq][0] - gmb_xyY[sq][1]) / gmb_xyY[sq][1]; } pseudoinverse (gmb_xyz, inverse, NSQ); - for (i=0; i < colors; i++) - for (j=0; j < 3; j++) - for (cam_xyz[i][j] = k=0; k < NSQ; k++) - cam_xyz[i][j] += gmb_cam[k][i] * inverse[k][j]; - cam_xyz_coeff (cam_xyz); + for (pass=0; pass < 2; pass++) { + for (raw_color = i=0; i < colors; i++) + for (j=0; j < 3; j++) + for (cam_xyz[i][j] = k=0; k < NSQ; k++) + cam_xyz[i][j] += gmb_cam[k][i] * inverse[k][j]; + cam_xyz_coeff (rgb_cam, cam_xyz); + FORCC balance[c] = pre_mul[c] * gmb_cam[20][c]; + for (sq=0; sq < NSQ; sq++) + FORCC gmb_cam[sq][c] *= balance[c]; + } if (verbose) { printf (" { \"%s %s\", %d,\n\t{", make, model, black); num = 10000 / (cam_xyz[1][0] + cam_xyz[1][1] + cam_xyz[1][2]); @@ -3859,6 +4282,7 @@ skip_block: ; else fprintf (stderr,_("%s: Cannot use camera white balance.\n"), ifname); } + if (pre_mul[1] == 0) pre_mul[1] = 1; if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1; dark = black; sat = maximum; @@ -3878,13 +4302,20 @@ skip_block: ; FORC4 fprintf (stderr, " %f", pre_mul[c]); fputc ('\n', stderr); } + if (filters > 1000 && (cblack[4]+1)/2 == 1 && (cblack[5]+1)/2 == 1) { + FORC4 cblack[FC(c/2,c%2)] += + cblack[6 + c/2 % cblack[4] * cblack[5] + c%2 % cblack[5]]; + cblack[4] = cblack[5] = 0; + } size = iheight*iwidth; for (i=0; i < size*4; i++) { - val = image[0][i]; - if (!val) continue; + if (!(val = ((ushort *)image)[i])) continue; + if (cblack[4] && cblack[5]) + val -= cblack[6 + i/4 / iwidth % cblack[4] * cblack[5] + + i/4 % iwidth % cblack[5]]; val -= cblack[i & 3]; val *= scale_mul[i & 3]; - image[0][i] = CLIP(val); + ((ushort *)image)[i] = CLIP(val); } if ((aber[0] != 1 || aber[2] != 1) && colors == 3) { if (verbose) @@ -3923,8 +4354,20 @@ void CLASS pre_interpolate() if (half_size) { height = iheight; width = iwidth; + if (filters == 9) { + for (row=0; row < 3; row++) + for (col=1; col < 4; col++) + if (!(image[row*width+col][0] | image[row*width+col][2])) + goto break2; break2: + for ( ; row < height; row+=3) + for (col=(col-1)%3+1; col < width-1; col+=3) { + img = image + row*width+col; + for (c=0; c < 3; c+=2) + img[0][c] = (img[-1][c] + img[1][c]) >> 1; + } + } } else { - img = (ushort (*)[4]) calloc (height*width, sizeof *img); + img = (ushort (*)[4]) calloc (height, width*sizeof *img); merror (img, "pre_interpolate()"); for (row=0; row < height; row++) for (col=0; col < width; col++) { @@ -3937,8 +4380,8 @@ void CLASS pre_interpolate() } } if (filters > 1000 && colors == 3) { - if (four_color_rgb && colors++) - mix_green = !half_size; + mix_green = four_color_rgb ^ half_size; + if (four_color_rgb | half_size) colors++; else { for (row = FC(1,0) >> 1; row < height; row+=2) for (col = FC(row,1) & 1; col < width; col+=2) @@ -3978,7 +4421,7 @@ void CLASS lin_interpolate() ushort *pix; if (verbose) fprintf (stderr,_("Bilinear interpolation...\n")); - if (filters == 2) size = 6; + if (filters == 9) size = 6; border_interpolate(1); for (row=0; row < size; row++) for (col=0; col < size; col++) { @@ -4059,7 +4502,7 @@ void CLASS vng_interpolate() if (verbose) fprintf (stderr,_("VNG interpolation...\n")); if (filters == 1) prow = pcol = 16; - if (filters == 2) prow = pcol = 6; + if (filters == 9) prow = pcol = 6; ip = (int *) calloc (prow*pcol, 1280); merror (ip, "vng_interpolate()"); for (row=0; row < prow; row++) /* Precalculate for VNG */ @@ -4205,36 +4648,289 @@ void CLASS ppg_interpolate() } } +void CLASS cielab (ushort rgb[3], short lab[3]) +{ + int c, i, j, k; + float r, xyz[3]; + static float cbrt[0x10000], xyz_cam[3][4]; + + if (!rgb) { + for (i=0; i < 0x10000; i++) { + r = i / 65535.0; + cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0; + } + for (i=0; i < 3; i++) + for (j=0; j < colors; j++) + for (xyz_cam[i][j] = k=0; k < 3; k++) + xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i]; + return; + } + xyz[0] = xyz[1] = xyz[2] = 0.5; + FORCC { + xyz[0] += xyz_cam[0][c] * rgb[c]; + xyz[1] += xyz_cam[1][c] * rgb[c]; + xyz[2] += xyz_cam[2][c] * rgb[c]; + } + xyz[0] = cbrt[CLIP((int) xyz[0])]; + xyz[1] = cbrt[CLIP((int) xyz[1])]; + xyz[2] = cbrt[CLIP((int) xyz[2])]; + lab[0] = 64 * (116 * xyz[1] - 16); + lab[1] = 64 * 500 * (xyz[0] - xyz[1]); + lab[2] = 64 * 200 * (xyz[1] - xyz[2]); +} + +#define TS 512 /* Tile Size */ +#define fcol(row,col) xtrans[(row+6) % 6][(col+6) % 6] + +/* + Frank Markesteijn's algorithm for Fuji X-Trans sensors + */ +void CLASS xtrans_interpolate (int passes) +{ + int c, d, f, g, h, i, v, ng, row, col, top, left, mrow, mcol; + int val, ndir, pass, hm[8], avg[4], color[3][8]; + static const short orth[12] = { 1,0,0,1,-1,0,0,-1,1,0,0,1 }, + patt[2][16] = { { 0,1,0,-1,2,0,-1,0,1,1,1,-1,0,0,0,0 }, + { 0,1,0,-2,1,0,-2,0,1,1,-2,-2,1,-1,-1,1 } }, + dir[4] = { 1,TS,TS+1,TS-1 }; + short allhex[3][3][2][8], *hex; +// CINELERRA + ushort min, max, sgrow=0, sgcol=0; + ushort (*rgb)[TS][TS][3], (*rix)[3], (*pix)[4]; + short (*lab) [TS][3], (*lix)[3]; + float (*drv)[TS][TS], diff[6], tr; + char (*homo)[TS][TS], *buffer; + + if (verbose) + fprintf (stderr,_("%d-pass X-Trans interpolation...\n"), passes); + + cielab (0,0); + ndir = 4 << (passes > 1); + buffer = (char *) malloc (TS*TS*(ndir*11+6)); + merror (buffer, "xtrans_interpolate()"); + rgb = (ushort(*)[TS][TS][3]) buffer; + lab = (short (*) [TS][3])(buffer + TS*TS*(ndir*6)); + drv = (float (*)[TS][TS]) (buffer + TS*TS*(ndir*6+6)); + homo = (char (*)[TS][TS]) (buffer + TS*TS*(ndir*10+6)); + +/* Map a green hexagon around each non-green pixel and vice versa: */ + for (row=0; row < 3; row++) + for (col=0; col < 3; col++) + for (ng=d=0; d < 10; d+=2) { + g = fcol(row,col) == 1; + if (fcol(row+orth[d],col+orth[d+2]) == 1) ng=0; else ng++; + if (ng == 4) { sgrow = row; sgcol = col; } + if (ng == g+1) FORC(8) { + v = orth[d ]*patt[g][c*2] + orth[d+1]*patt[g][c*2+1]; + h = orth[d+2]*patt[g][c*2] + orth[d+3]*patt[g][c*2+1]; + allhex[row][col][0][c^(g*2 & d)] = h + v*width; + allhex[row][col][1][c^(g*2 & d)] = h + v*TS; + } + } + +/* Set green1 and green3 to the minimum and maximum allowed values: */ + for (row=2; row < height-2; row++) + for (min=~(max=0), col=2; col < width-2; col++) { + if (fcol(row,col) == 1 && (min=~(max=0))) continue; + pix = image + row*width + col; + hex = allhex[row % 3][col % 3][0]; + if (!max) FORC(6) { + val = pix[hex[c]][1]; + if (min > val) min = val; + if (max < val) max = val; + } + pix[0][1] = min; + pix[0][3] = max; + switch ((row-sgrow) % 3) { + case 1: if (row < height-3) { row++; col--; } break; + case 2: if ((min=~(max=0)) && (col+=2) < width-3 && row > 2) row--; + } + } + + for (top=3; top < height-19; top += TS-16) + for (left=3; left < width-19; left += TS-16) { + mrow = MIN (top+TS, height-3); + mcol = MIN (left+TS, width-3); + for (row=top; row < mrow; row++) + for (col=left; col < mcol; col++) + memcpy (rgb[0][row-top][col-left], image[row*width+col], 6); + FORC3 memcpy (rgb[c+1], rgb[0], sizeof *rgb); + +/* Interpolate green horizontally, vertically, and along both diagonals: */ + for (row=top; row < mrow; row++) + for (col=left; col < mcol; col++) { + if ((f = fcol(row,col)) == 1) continue; + pix = image + row*width + col; + hex = allhex[row % 3][col % 3][0]; + color[1][0] = 174 * (pix[ hex[1]][1] + pix[ hex[0]][1]) - + 46 * (pix[2*hex[1]][1] + pix[2*hex[0]][1]); + color[1][1] = 223 * pix[ hex[3]][1] + pix[ hex[2]][1] * 33 + + 92 * (pix[ 0 ][f] - pix[ -hex[2]][f]); + FORC(2) color[1][2+c] = + 164 * pix[hex[4+c]][1] + 92 * pix[-2*hex[4+c]][1] + 33 * + (2*pix[0][f] - pix[3*hex[4+c]][f] - pix[-3*hex[4+c]][f]); + FORC4 rgb[c^!((row-sgrow) % 3)][row-top][col-left][1] = + LIM(color[1][c] >> 8,pix[0][1],pix[0][3]); + } + + for (pass=0; pass < passes; pass++) { + if (pass == 1) + memcpy (rgb+=4, buffer, 4*sizeof *rgb); + +/* Recalculate green from interpolated values of closer pixels: */ + if (pass) { + for (row=top+2; row < mrow-2; row++) + for (col=left+2; col < mcol-2; col++) { + if ((f = fcol(row,col)) == 1) continue; + pix = image + row*width + col; + hex = allhex[row % 3][col % 3][1]; + for (d=3; d < 6; d++) { + rix = &rgb[(d-2)^!((row-sgrow) % 3)][row-top][col-left]; + val = rix[-2*hex[d]][1] + 2*rix[hex[d]][1] + - rix[-2*hex[d]][f] - 2*rix[hex[d]][f] + 3*rix[0][f]; + rix[0][1] = LIM(val/3,pix[0][1],pix[0][3]); + } + } + } + +/* Interpolate red and blue values for solitary green pixels: */ + for (row=(top-sgrow+4)/3*3+sgrow; row < mrow-2; row+=3) + for (col=(left-sgcol+4)/3*3+sgcol; col < mcol-2; col+=3) { + rix = &rgb[0][row-top][col-left]; + h = fcol(row,col+1); + memset (diff, 0, sizeof diff); + for (i=1, d=0; d < 6; d++, i^=TS^1, h^=2) { + for (c=0; c < 2; c++, h^=2) { + g = 2*rix[0][1] - rix[i< 1) + diff[d] += SQR (rix[i< 1 && (d & 1)) + if (diff[d-1] < diff[d]) + FORC(2) color[c*2][d] = color[c*2][d-1]; + if (d < 2 || (d & 1)) { + FORC(2) rix[0][c*2] = CLIP(color[c*2][d]/2); + rix += TS*TS; + } + } + } + +/* Interpolate red for blue pixels and vice versa: */ + for (row=top+3; row < mrow-3; row++) + for (col=left+3; col < mcol-3; col++) { + if ((f = 2-fcol(row,col)) == 1) continue; + rix = &rgb[0][row-top][col-left]; + c = (row-sgrow) % 3 ? TS:1; + h = 3 * (c ^ TS ^ 1); + for (d=0; d < 4; d++, rix += TS*TS) { + i = d > 1 || ((d ^ c) & 1) || + ((ABS(rix[0][1]-rix[c][1])+ABS(rix[0][1]-rix[-c][1])) < + 2*(ABS(rix[0][1]-rix[h][1])+ABS(rix[0][1]-rix[-h][1]))) ? c:h; + rix[0][f] = CLIP((rix[i][f] + rix[-i][f] + + 2*rix[0][1] - rix[i][1] - rix[-i][1])/2); + } + } + +/* Fill in red and blue for 2x2 blocks of green: */ + for (row=top+2; row < mrow-2; row++) if ((row-sgrow) % 3) + for (col=left+2; col < mcol-2; col++) if ((col-sgcol) % 3) { + rix = &rgb[0][row-top][col-left]; + hex = allhex[row % 3][col % 3][1]; + for (d=0; d < ndir; d+=2, rix += TS*TS) + if (hex[d] + hex[d+1]) { + g = 3*rix[0][1] - 2*rix[hex[d]][1] - rix[hex[d+1]][1]; + for (c=0; c < 4; c+=2) rix[0][c] = + CLIP((g + 2*rix[hex[d]][c] + rix[hex[d+1]][c])/3); + } else { + g = 2*rix[0][1] - rix[hex[d]][1] - rix[hex[d+1]][1]; + for (c=0; c < 4; c+=2) rix[0][c] = + CLIP((g + rix[hex[d]][c] + rix[hex[d+1]][c])/2); + } + } + } + rgb = (ushort(*)[TS][TS][3]) buffer; + mrow -= top; + mcol -= left; + +/* Convert to CIELab and differentiate in all directions: */ + for (d=0; d < ndir; d++) { + for (row=2; row < mrow-2; row++) + for (col=2; col < mcol-2; col++) + cielab (rgb[d][row][col], lab[row][col]); + for (f=dir[d & 3],row=3; row < mrow-3; row++) + for (col=3; col < mcol-3; col++) { + lix = &lab[row][col]; + g = 2*lix[0][0] - lix[f][0] - lix[-f][0]; + drv[d][row][col] = SQR(g) + + SQR((2*lix[0][1] - lix[f][1] - lix[-f][1] + g*500/232)) + + SQR((2*lix[0][2] - lix[f][2] - lix[-f][2] - g*500/580)); + } + } + +/* Build homogeneity maps from the derivatives: */ + memset(homo, 0, ndir*TS*TS); + for (row=4; row < mrow-4; row++) + for (col=4; col < mcol-4; col++) { + for (tr=FLT_MAX, d=0; d < ndir; d++) + if (tr > drv[d][row][col]) + tr = drv[d][row][col]; + tr *= 8; + for (d=0; d < ndir; d++) + for (v=-1; v <= 1; v++) + for (h=-1; h <= 1; h++) + if (drv[d][row+v][col+h] <= tr) + homo[d][row][col]++; + } + +/* Average the most homogenous pixels for the final result: */ + if (height-top < TS+4) mrow = height-top+2; + if (width-left < TS+4) mcol = width-left+2; + for (row = MIN(top,8); row < mrow-8; row++) + for (col = MIN(left,8); col < mcol-8; col++) { + for (d=0; d < ndir; d++) + for (hm[d]=0, v=-2; v <= 2; v++) + for (h=-2; h <= 2; h++) + hm[d] += homo[d][row+v][col+h]; + for (d=0; d < ndir-4; d++) + if (hm[d] < hm[d+4]) hm[d ] = 0; else + if (hm[d] > hm[d+4]) hm[d+4] = 0; + for (max=hm[0],d=1; d < ndir; d++) + if (max < hm[d]) max = hm[d]; + max -= max >> 3; + memset (avg, 0, sizeof avg); + for (d=0; d < ndir; d++) + if (hm[d] >= max) { + FORC3 avg[c] += rgb[d][row][col][c]; + avg[3]++; + } + FORC3 image[(row+top)*width+col+left][c] = avg[c]/avg[3]; + } + } + free(buffer); + border_interpolate(8); +} +#undef fcol + /* Adaptive Homogeneity-Directed interpolation is based on the work of Keigo Hirakawa, Thomas Parks, and Paul Lee. */ -#define TS 256 /* Tile Size */ - void CLASS ahd_interpolate() { - int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2]; - ushort (*pix)[4], (*rix)[3]; + int i, j, top, left, row, col, tr, tc, c, d, val, hm[2]; static const int dir[4] = { -1, 1, -TS, TS }; unsigned ldiff[2][4], abdiff[2][4], leps, abeps; - float r, cbrt[0x10000], xyz[3], xyz_cam[3][4]; - ushort (*rgb)[TS][TS][3]; + ushort (*rgb)[TS][TS][3], (*rix)[3], (*pix)[4]; short (*lab)[TS][TS][3], (*lix)[3]; char (*homo)[TS][TS], *buffer; if (verbose) fprintf (stderr,_("AHD interpolation...\n")); - for (i=0; i < 0x10000; i++) { - r = i / 65535.0; - cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0; - } - for (i=0; i < 3; i++) - for (j=0; j < colors; j++) - for (xyz_cam[i][j] = k=0; k < 3; k++) - xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i]; - + cielab (0,0); border_interpolate(5); - buffer = (char *) malloc (26*TS*TS); /* 1664 kB */ + buffer = (char *) malloc (26*TS*TS); merror (buffer, "ahd_interpolate()"); rgb = (ushort(*)[TS][TS][3]) buffer; lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS); @@ -4244,7 +4940,7 @@ void CLASS ahd_interpolate() for (left=2; left < width-5; left += TS-6) { /* Interpolate green horizontally and vertically: */ - for (row = top; row < top+TS && row < height-2; row++) { + for (row=top; row < top+TS && row < height-2; row++) { col = left + (FC(row,left) & 1); for (c = FC(row,col); col < left+TS && col < width-2; col+=2) { pix = image + row*width+col; @@ -4278,18 +4974,7 @@ void CLASS ahd_interpolate() rix[0][c] = CLIP(val); c = FC(row,col); rix[0][c] = pix[0][c]; - xyz[0] = xyz[1] = xyz[2] = 0.5; - FORCC { - xyz[0] += xyz_cam[0][c] * rix[0][c]; - xyz[1] += xyz_cam[1][c] * rix[0][c]; - xyz[2] += xyz_cam[2][c] * rix[0][c]; - } - xyz[0] = cbrt[CLIP((int) xyz[0])]; - xyz[1] = cbrt[CLIP((int) xyz[1])]; - xyz[2] = cbrt[CLIP((int) xyz[2])]; - lix[0][0] = 64 * (116 * xyz[1] - 16); - lix[0][1] = 64 * 500 * (xyz[0] - xyz[1]); - lix[0][2] = 64 * 200 * (xyz[1] - xyz[2]); + cielab (rix[0],lix[0]); } /* Build homogeneity maps from the CIELab images: */ memset (homo, 0, 2*TS*TS); @@ -4419,7 +5104,7 @@ void CLASS recover_highlights() if (pre_mul[kc] < pre_mul[c]) kc = c; high = height / SCALE; wide = width / SCALE; - map = (float *) calloc (high*wide, sizeof *map); + map = (float *) calloc (high, wide*sizeof *map); merror (map, "recover_highlights()"); FORCC if (c != kc) { memset (map, 0, high*wide*sizeof *map); @@ -4486,7 +5171,7 @@ void CLASS tiff_get (unsigned base, *type = get2(); *len = get4(); *save = ftell(ifp) + 4; - if (*len * ("11124811248488"[*type < 14 ? *type:0]-'0') > 4) + if (*len * ("11124811248484"[*type < 14 ? *type:0]-'0') > 4) fseek (ifp, get4()+base, SEEK_SET); } @@ -4573,10 +5258,12 @@ void CLASS parse_makernote (int base, int uptag) if (get2() != 42) goto quit; offset = get4(); fseek (ifp, offset-8, SEEK_CUR); - } else if (!strcmp (buf,"OLYMPUS")) { + } else if (!strcmp (buf,"OLYMPUS") || + !strcmp (buf,"PENTAX ")) { base = ftell(ifp)-10; fseek (ifp, -2, SEEK_CUR); - order = get2(); get2(); + order = get2(); + if (buf[0] == 'O') get2(); } else if (!strncmp (buf,"SONY",4) || !strcmp (buf,"Panasonic")) { goto nf; @@ -4630,10 +5317,8 @@ nf: order = 0x4949; shot_order = get4(); if (tag == 9 && !strcmp(make,"Canon")) fread (artist, 64, 1, ifp); - if (tag == 0xc && len == 4) { - cam_mul[0] = getreal(type); - cam_mul[2] = getreal(type); - } + if (tag == 0xc && len == 4) + FORC3 cam_mul[(c << 1 | c >> 1) & 3] = getreal(type); if (tag == 0xd && type == 7 && get2() == 0xaaaa) { for (c=i=2; (ushort) c != 0xbbbb && i < len; i++) c = c << 8 | fgetc(ifp); @@ -4669,6 +5354,13 @@ nf: order = 0x4949; if (tag == 0x1d) while ((c = fgetc(ifp)) && c != EOF) serial = serial*10 + (isdigit(c) ? c - '0' : c % 10); + if (tag == 0x29 && type == 1) { + c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0; + fseek (ifp, 8 + c*32, SEEK_CUR); + FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get4(); + } + if (tag == 0x3d && type == 3 && len == 4) + FORC4 cblack[c ^ c >> 1] = get2() >> (14-tiff_bps); if (tag == 0x81 && type == 4) { data_offset = get4(); fseek (ifp, data_offset + 41, SEEK_SET); @@ -4676,11 +5368,6 @@ nf: order = 0x4949; raw_width = get2(); filters = 0x61616161; } - if (tag == 0x29 && type == 1) { - c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0; - fseek (ifp, 8 + c*32, SEEK_CUR); - FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get4(); - } if ((tag == 0x81 && type == 7) || (tag == 0x100 && type == 7) || (tag == 0x280 && type == 1)) { @@ -4703,7 +5390,8 @@ nf: order = 0x4949; break; case 102: fseek (ifp, 6, SEEK_CUR); - goto get2_rggb; + FORC4 cam_mul[c ^ (c >> 1)] = get2(); + break; case 103: fseek (ifp, 16, SEEK_CUR); FORC4 cam_mul[c] = get2(); @@ -4737,7 +5425,7 @@ nf: order = 0x4949; if (tag == 0x200 && len == 4) FORC4 cblack[c ^ c >> 1] = get2(); if (tag == 0x201 && len == 4) - goto get2_rggb; + FORC4 cam_mul[c ^ (c >> 1)] = get2(); if (tag == 0x220 && type == 7) meta_offset = ftell(ifp); if (tag == 0x401 && type == 4 && len == 4) @@ -4781,11 +5469,9 @@ get2_256: cam_mul[0] = get2() / 256.0; cam_mul[2] = get2() / 256.0; } - if ((tag | 0x70) == 0x2070 && type == 4) + if ((tag | 0x70) == 0x2070 && (type == 4 || type == 13)) fseek (ifp, get4()+base, SEEK_SET); - if (tag == 0x2010 && type != 7) - load_raw = &CLASS olympus_load_raw; - if (tag == 0x2020) + if (tag == 0x2020 && !strncmp(buf,"OLYMP",5)) parse_thumb_note (base, 257, 258); if (tag == 0x2040) parse_makernote (base, 0x2040); @@ -4796,16 +5482,21 @@ get2_256: if (tag == 0x4001 && len > 500) { i = len == 582 ? 50 : len == 653 ? 68 : len == 5120 ? 142 : 126; fseek (ifp, i, SEEK_CUR); -get2_rggb: FORC4 cam_mul[c ^ (c >> 1)] = get2(); - i = len >> 3 == 164 ? 112:22; - fseek (ifp, i, SEEK_CUR); - FORC4 sraw_mul[c ^ (c >> 1)] = get2(); + for (i+=18; i <= len; i+=10) { + get2(); + FORC4 sraw_mul[c ^ (c >> 1)] = get2(); + if (sraw_mul[1] == 1170) break; + } } + if (tag == 0x4021 && get4() && get4()) + FORC4 cam_mul[c] = 1024; if (tag == 0xa021) FORC4 cam_mul[c ^ (c >> 1)] = get4(); if (tag == 0xa028) FORC4 cam_mul[c ^ (c >> 1)] -= get4(); + if (tag == 0xb001) + unique_id = get2(); next: fseek (ifp, save, SEEK_SET); } @@ -4849,12 +5540,14 @@ void CLASS parse_exif (int base) while (entries--) { tiff_get (base, &tag, &type, &len, &save); switch (tag) { - case 33434: shutter = getreal(type); break; + case 33434: tiff_ifd[tiff_nifds-1].shutter = + shutter = getreal(type); break; case 33437: aperture = getreal(type); break; case 34855: iso_speed = get2(); break; case 36867: case 36868: get_timestamp(0); break; case 37377: if ((expo = -getreal(type)) < 128) + tiff_ifd[tiff_nifds-1].shutter = shutter = pow (2, expo); break; case 37378: aperture = pow (2, getreal(type)/2); break; case 37386: focal_len = getreal(type); break; @@ -4913,7 +5606,8 @@ void CLASS parse_mos (int offset) { "","DCB2","Volare","Cantare","CMost","Valeo 6","Valeo 11","Valeo 22", "Valeo 11p","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65", "Aptus 54S","Aptus 65S","Aptus 75S","AFi 5","AFi 6","AFi 7", - "","","","","","","","","","","","","","","","","","AFi-II 12" }; + "AFi-II 7","Aptus-II 7","","Aptus-II 6","","","Aptus-II 10","Aptus-II 5", + "","","","","Aptus-II 10R","Aptus-II 8","","Aptus-II 12","","AFi-II 12" }; float romm_cam[3][3]; fseek (ifp, offset, SEEK_SET); @@ -4938,12 +5632,12 @@ void CLASS parse_mos (int offset) } if (!strcmp(data,"icc_camera_to_tone_matrix")) { for (i=0; i < 9; i++) - romm_cam[0][i] = int_to_float(get4()); + ((float *)romm_cam)[i] = int_to_float(get4()); romm_coeff (romm_cam); } if (!strcmp(data,"CaptProf_color_matrix")) { for (i=0; i < 9; i++) - fscanf (ifp, "%f", &romm_cam[0][i]); + fscanf (ifp, "%f", (float *)romm_cam + i); romm_coeff (romm_cam); } if (!strcmp(data,"CaptProf_number_of_planes")) @@ -5001,6 +5695,8 @@ void CLASS parse_kodak_ifd (int base) wbi = -2; } if (tag == 2118) wbtemp = getint(type); + if (tag == 2120 + wbi && wbi >= 0) + FORC3 cam_mul[c] = 2048.0 / getreal(type); if (tag == 2130 + wbi) FORC3 mul[c] = getreal(type); if (tag == 2140 + wbi && wbi >= 0) @@ -5027,7 +5723,6 @@ int CLASS parse_tiff_ifd (int base) { unsigned entries, tag, type, len, plen=16, save; int ifd, use_cm=0, cfa, i, j, c, ima_len=0; - int blrr=1, blrc=1, dblack[] = { 0,0,0,0 }; char software[64], *cbuf, *cp; uchar cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256]; double cc[4][4], cm[4][3], cam_xyz[4][3], num; @@ -5051,7 +5746,7 @@ int CLASS parse_tiff_ifd (int base) case 5: width = get2(); break; case 6: height = get2(); break; case 7: width += get2(); break; - case 9: filters = get2(); break; + case 9: if ((i = get2())) filters = i; break; case 17: case 18: if (type == 3 && len == 1) cam_mul[(tag-17)*2] = get2() / 256.0; @@ -5059,8 +5754,12 @@ int CLASS parse_tiff_ifd (int base) case 23: if (type == 3) iso_speed = get2(); break; + case 28: case 29: case 30: + cblack[tag-28] = get2(); + cblack[3] = cblack[1]; + break; case 36: case 37: case 38: - cam_mul[tag-0x24] = get2(); + cam_mul[tag-36] = get2(); break; case 39: if (len < 50 || cam_mul[0]) break; @@ -5073,6 +5772,7 @@ int CLASS parse_tiff_ifd (int base) thumb_length = len; break; case 61440: /* Fuji HS10 table */ + fseek (ifp, get4()+base, SEEK_SET); parse_tiff_ifd (base); break; case 2: case 256: case 61441: /* ImageWidth */ @@ -5085,11 +5785,14 @@ int CLASS parse_tiff_ifd (int base) case 61443: tiff_ifd[ifd].samples = len & 7; tiff_ifd[ifd].bps = getint(type); + if (tiff_bps < tiff_ifd[ifd].bps) + tiff_bps = tiff_ifd[ifd].bps; break; case 61446: raw_height = 0; + if (tiff_ifd[ifd].bps > 12) break; load_raw = &CLASS packed_load_raw; - load_flags = get4() && (filters=0x16161616) ? 24:80; + load_flags = get4() ? 24:80; break; case 259: /* Compression */ tiff_ifd[ifd].comp = getint(type); @@ -5124,6 +5827,10 @@ int CLASS parse_tiff_ifd (int base) tiff_ifd[ifd].samples = jh.clrs; if (!(jh.sraw || (jh.clrs & 1))) tiff_ifd[ifd].width *= jh.clrs; + if ((tiff_ifd[ifd].width > 4*tiff_ifd[ifd].height) & ~jh.clrs) { + tiff_ifd[ifd].width /= 2; + tiff_ifd[ifd].height *= 2; + } i = order; parse_tiff (tiff_ifd[ifd].offset + 12); order = i; @@ -5168,6 +5875,8 @@ int CLASS parse_tiff_ifd (int base) break; case 324: /* TileOffsets */ tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4(); + if (len == 1) + tiff_ifd[ifd].tile_width = tiff_ifd[ifd].tile_length = 0; if (len == 4) { load_raw = &CLASS sinar_4shot_load_raw; is_raw = 5; @@ -5214,11 +5923,19 @@ int CLASS parse_tiff_ifd (int base) case 33405: /* Model2 */ fgets (model2, 64, ifp); break; + case 33421: /* CFARepeatPatternDim */ + if (get2() == 6 && get2() == 6) + filters = 9; + break; case 33422: /* CFAPattern */ + if (filters == 9) { + FORC(36) ((char *)xtrans)[c] = fgetc(ifp) & 3; + break; + } case 64777: /* Kodak P-series */ if ((plen=len) > 16) plen = 16; fread (cfa_pat, 1, plen, ifp); - for (colors=cfa=i=0; i < plen; i++) { + for (colors=cfa=i=0; i < plen && colors < 4; i++) { colors += !(cfa & (1 << cfa_pat[i])); cfa |= 1 << cfa_pat[i]; } @@ -5231,7 +5948,7 @@ int CLASS parse_tiff_ifd (int base) parse_kodak_ifd (base); break; case 33434: /* ExposureTime */ - shutter = getreal(type); + tiff_ifd[ifd].shutter = shutter = getreal(type); break; case 33437: /* FNumber */ aperture = getreal(type); @@ -5284,6 +6001,14 @@ int CLASS parse_tiff_ifd (int base) FORC3 rgb_cam[i][c] = getreal(type); } break; + case 40976: + strip_offset = get4(); + switch (tiff_ifd[ifd].comp) { + case 32770: load_raw = &CLASS samsung_load_raw; break; + case 32772: load_raw = &CLASS samsung2_load_raw; break; + case 32773: load_raw = &CLASS samsung3_load_raw; break; + } + break; case 46275: /* Imacon tags */ strcpy (make, "Imacon"); data_offset = ftell(ifp); @@ -5351,7 +6076,16 @@ int CLASS parse_tiff_ifd (int base) if (!make[0]) strcpy (make, "DNG"); is_raw = 1; break; + case 50708: /* UniqueCameraModel */ + if (model[0]) break; + fgets (make, 64, ifp); + if ((cp = strchr(make,' '))) { + strcpy(model,cp+1); + *cp = 0; + } + break; case 50710: /* CFAPlaneColor */ + if (filters == 9) break; if (len > 4) len = 4; colors = len; fread (cfa_pc, 1, colors, ifp); @@ -5360,39 +6094,33 @@ guess_cfa_pc: cdesc[c] = 0; for (i=16; i--; ) filters = filters << 2 | tab[cfa_pat[i % plen]]; + filters -= !filters; break; case 50711: /* CFALayout */ - if (get2() == 2) { - fuji_width = 1; - filters = 0x49494949; - } + if (get2() == 2) fuji_width = 1; break; case 291: case 50712: /* LinearizationTable */ linear_table (len); break; case 50713: /* BlackLevelRepeatDim */ - blrr = get2(); - blrc = get2(); + cblack[4] = get2(); + cblack[5] = get2(); + if (cblack[4] * cblack[5] > sizeof cblack / sizeof *cblack - 6) + cblack[4] = cblack[5] = 1; break; case 61450: - blrr = blrc = 2; + cblack[4] = cblack[5] = MIN(sqrt(len),64); case 50714: /* BlackLevel */ - black = getreal(type); - if (!filters || !~filters) break; - dblack[0] = black; - dblack[1] = (blrc == 2) ? getreal(type):dblack[0]; - dblack[2] = (blrr == 2) ? getreal(type):dblack[0]; - dblack[3] = (blrc == 2 && blrr == 2) ? getreal(type):dblack[1]; - if (colors == 3) - filters |= ((filters >> 2 & 0x22222222) | - (filters << 2 & 0x88888888)) & filters << 1; - FORC4 cblack[filters >> (c << 1) & 3] = dblack[c]; + if (!(cblack[4] * cblack[5])) + cblack[4] = cblack[5] = 1; + FORC (cblack[4] * cblack[5]) + cblack[6+c] = getreal(type); black = 0; break; case 50715: /* BlackLevelDeltaH */ case 50716: /* BlackLevelDeltaV */ - for (num=i=0; i < len; i++) + for (num=i=0; i < (len & 0xffff); i++) num += getreal(type); black += num/len + 0.5; break; @@ -5443,7 +6171,7 @@ guess_cfa_pc: break; case 50830: /* MaskedAreas */ for (i=0; i < len && i < 32; i++) - mask[0][i] = getint(type); + ((int *)mask)[i] = getint(type); black = 0; break; case 51009: /* OpcodeList2 */ @@ -5482,7 +6210,7 @@ guess_cfa_pc: FORCC for (i=0; i < 3; i++) for (cam_xyz[c][i]=j=0; j < colors; j++) cam_xyz[c][i] += cc[c][j] * cm[j][i] * xyz[i]; - cam_xyz_coeff (cam_xyz); + cam_xyz_coeff (cmatrix, cam_xyz); } if (asn[0]) { cam_mul[3] = 0; @@ -5510,7 +6238,7 @@ int CLASS parse_tiff (int base) void CLASS apply_tiff() { - int max_samp=0, raw=-1, thm=-1, i; + int max_samp=0, ties=0, os, ns, raw=-1, thm=-1, i; struct jhead jh; thumb_misc = 16; @@ -5522,13 +6250,25 @@ void CLASS apply_tiff() thumb_height = jh.high; } } + for (i=tiff_nifds; i--; ) { + if (tiff_ifd[i].shutter) + shutter = tiff_ifd[i].shutter; + tiff_ifd[i].shutter = shutter; + } for (i=0; i < tiff_nifds; i++) { if (max_samp < tiff_ifd[i].samples) max_samp = tiff_ifd[i].samples; if (max_samp > 3) max_samp = 3; + os = raw_width*raw_height; + ns = tiff_ifd[i].width*tiff_ifd[i].height; + if (tiff_bps) { + os *= tiff_bps; + ns *= tiff_ifd[i].bps; + } 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) { + ns && ((ns > os && (ties = 1)) || + (ns == os && shot_select == ties++))) { raw_width = tiff_ifd[i].width; raw_height = tiff_ifd[i].height; tiff_bps = tiff_ifd[i].bps; @@ -5538,9 +6278,11 @@ void CLASS apply_tiff() tiff_samples = tiff_ifd[i].samples; tile_width = tiff_ifd[i].tile_width; tile_length = tiff_ifd[i].tile_length; + shutter = tiff_ifd[i].shutter; raw = i; } } + if (is_raw == 1 && ties) is_raw = ties; if (!tile_width ) tile_width = INT_MAX; if (!tile_length) tile_length = INT_MAX; for (i=tiff_nifds; i--; ) @@ -5562,6 +6304,9 @@ void CLASS apply_tiff() case 32770: case 32773: goto slr; case 0: case 1: + if (!strncmp(make,"OLYMPUS",7) && + tiff_ifd[raw].bytes*2 == raw_width*raw_height*3) + load_flags = 24; if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8) { load_flags = 81; tiff_bps = 12; @@ -5572,7 +6317,10 @@ void CLASS apply_tiff() load_flags = 6; load_raw = &CLASS packed_load_raw; break; case 14: load_flags = 0; - case 16: load_raw = &CLASS unpacked_load_raw; break; + case 16: load_raw = &CLASS unpacked_load_raw; + if (!strncmp(make,"OLYMPUS",7) && + tiff_ifd[raw].bytes*7 > raw_width*raw_height) + load_raw = &CLASS olympus_load_raw; } break; case 6: case 7: case 99: @@ -5583,14 +6331,20 @@ void CLASS apply_tiff() if ((raw_width+9)/10*16*raw_height == tiff_ifd[raw].bytes) { load_raw = &CLASS packed_load_raw; load_flags = 1; + } else if (raw_width*raw_height*3 == tiff_ifd[raw].bytes*2) { + load_raw = &CLASS packed_load_raw; + if (model[0] == 'N') load_flags = 80; + } else if (raw_width*raw_height*3 == tiff_ifd[raw].bytes) { + load_raw = &CLASS nikon_yuv_load_raw; + gamma_curve (1/2.4, 12.92, 1, 4095); + memset (cblack, 0, sizeof cblack); + filters = 0; } else if (raw_width*raw_height*2 == tiff_ifd[raw].bytes) { load_raw = &CLASS unpacked_load_raw; load_flags = 4; order = 0x4d4d; } else load_raw = &CLASS nikon_load_raw; break; - case 34892: - load_raw = &CLASS lossy_dng_load_raw; break; case 65535: load_raw = &CLASS pentax_load_raw; break; case 65000: @@ -5599,20 +6353,19 @@ void CLASS apply_tiff() case 6: load_raw = &CLASS kodak_ycbcr_load_raw; filters = 0; break; case 32803: load_raw = &CLASS kodak_65000_load_raw; } - case 32867: break; + case 32867: case 34892: break; default: is_raw = 0; } if (!dng_version) - if ( (tiff_samples == 3 && tiff_ifd[raw].bytes && - tiff_bps != 14 && tiff_bps != 2048 && - tiff_compress != 32769 && tiff_compress != 32770) - || (tiff_bps == 8 && !strstr(make,"KODAK") && !strstr(make,"Kodak") && - !strstr(model2,"DEBUG RAW"))) + if ( (tiff_samples == 3 && tiff_ifd[raw].bytes && tiff_bps != 14 && + (tiff_compress & -16) != 32768) + || (tiff_bps == 8 && strncmp(make,"Phase",5) && + !strcasestr(make,"Kodak") && !strstr(model2,"DEBUG RAW"))) is_raw = 0; for (i=0; i < 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) > - thumb_width * thumb_height / SQR(thumb_misc+1) + tiff_ifd[i].width * tiff_ifd[i].height / (SQR(tiff_ifd[i].bps)+1) > + thumb_width * thumb_height / (SQR(thumb_misc)+1) && tiff_ifd[i].comp != 34892) { thumb_width = tiff_ifd[i].width; thumb_height = tiff_ifd[i].height; @@ -5748,16 +6501,14 @@ void CLASS ciff_block_1030() bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]); vbits += 16; } - white[row][col] = - bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp); - vbits -= bpp; + white[row][col] = bitbuf >> (vbits -= bpp) & ~(-1 << bpp); } } /* Parse a CIFF file, better known as Canon CRW format. */ -void CLASS parse_ciff (int offset, int length) +void CLASS parse_ciff (int offset, int length, int depth) { int tboff, nrecs, c, type, len, save, wbi=-1; ushort key[] = { 0x410, 0x45f3 }; @@ -5766,15 +6517,14 @@ void CLASS parse_ciff (int offset, int length) tboff = get4() + offset; fseek (ifp, tboff, SEEK_SET); nrecs = get2(); - if (nrecs > 100) return; + if ((nrecs | depth) > 127) return; while (nrecs--) { type = get2(); len = get4(); save = ftell(ifp) + 4; fseek (ifp, offset+get4(), SEEK_SET); if ((((type >> 8) + 8) | 8) == 0x38) - parse_ciff (ftell(ifp), len); /* Parse a sub-table */ - + parse_ciff (ftell(ifp), len, depth+1); /* Parse a sub-table */ if (type == 0x0810) fread (artist, 64, 1, ifp); if (type == 0x080a) { @@ -5783,7 +6533,9 @@ void CLASS parse_ciff (int offset, int length) fread (model, 64, 1, ifp); } if (type == 0x1810) { - fseek (ifp, 12, SEEK_CUR); + width = get4(); + height = get4(); + pixel_aspect = int_to_float(get4()); flip = get4(); } if (type == 0x1835) /* Get the decoder table */ @@ -5933,8 +6685,9 @@ void CLASS parse_sinar_ia() void CLASS parse_phase_one (int base) { +//CINELERRA unsigned entries, tag, /*type,*/ len, data, save, i, c; - float romm_cam[3][3], *fp; + float romm_cam[3][3]; char *cp; memset (&ph1, 0, sizeof ph1); @@ -5946,6 +6699,7 @@ void CLASS parse_phase_one (int base) get4(); while (entries--) { tag = get4(); +//CINELERRA /*type =*/ get4(); len = get4(); data = get4(); @@ -5954,8 +6708,8 @@ void CLASS parse_phase_one (int base) switch (tag) { case 0x100: flip = "0653"[data & 3]-'0'; break; case 0x106: - for( i=9,fp=&romm_cam[0][0]; --i>=0; ++fp ) - *fp = getreal(11); + for (i=0; i < 9; i++) + ((float *)romm_cam)[i] = getreal(11); romm_coeff (romm_cam); break; case 0x107: @@ -5977,7 +6731,9 @@ void CLASS parse_phase_one (int base) case 0x21c: strip_offset = data+base; break; case 0x21d: ph1.black = data; break; case 0x222: ph1.split_col = data; break; - case 0x223: ph1.black_off = data+base; break; + case 0x223: ph1.black_col = data+base; break; + case 0x224: ph1.split_row = data; break; + case 0x225: ph1.black_row = data+base; break; case 0x301: model[63] = 0; fread (model, 1, 63, ifp); @@ -6018,12 +6774,16 @@ void CLASS parse_fuji (int offset) } else if (tag == 0x130) { fuji_layout = fgetc(ifp) >> 7; fuji_width = !(fgetc(ifp) & 8); + } else if (tag == 0x131) { + filters = 9; + FORC(36) xtrans_abs[0][35-c] = fgetc(ifp) & 3; } else if (tag == 0x2ff0) { FORC4 cam_mul[c ^ 1] = get2(); } else if (tag == 0xc000) { c = order; order = 0x4949; - if ((width = get4()) > 10000) width = get4(); + while ((tag = get4()) > raw_width); + width = tag; height = get4(); order = c; } @@ -6044,7 +6804,7 @@ int CLASS parse_jpeg (int offset) order = 0x4d4d; len = get2() - 2; save = ftell(ifp); - if (mark == 0xc0 || mark == 0xc3) { + if (mark == 0xc0 || mark == 0xc3 || mark == 0xc9) { fgetc(ifp); raw_height = get2(); raw_width = get2(); @@ -6052,7 +6812,7 @@ int CLASS parse_jpeg (int offset) order = get2(); hlen = get4(); if (get4() == 0x48454150) /* "HEAP" */ - parse_ciff (save+hlen, len-hlen); + parse_ciff (save+hlen, len-hlen, 0); if (parse_tiff (save+6)) apply_tiff(); fseek (ifp, save+len, SEEK_SET); } @@ -6073,7 +6833,7 @@ void CLASS parse_riff() end = ftell(ifp) + size; if (!memcmp(tag,"RIFF",4) || !memcmp(tag,"LIST",4)) { get4(); - while (ftell(ifp)+7 < end) + while (ftell(ifp)+7 < end && !feof(ifp)) parse_riff(); } else if (!memcmp(tag,"nctg",4)) { while (ftell(ifp)+7 < end) { @@ -6099,6 +6859,26 @@ void CLASS parse_riff() fseek (ifp, size, SEEK_CUR); } +void CLASS parse_qt (int end) +{ + unsigned save, size; + char tag[4]; + + order = 0x4d4d; + while (ftell(ifp)+7 < end) { + save = ftell(ifp); + if ((size = get4()) < 8) return; + fread (tag, 4, 1, ifp); + if (!memcmp(tag,"moov",4) || + !memcmp(tag,"udta",4) || + !memcmp(tag,"CNTH",4)) + parse_qt (save+size); + if (!memcmp(tag,"CNDA",4)) + parse_jpeg (ftell(ifp)); + fseek (ifp, save+size, SEEK_SET); + } +} + void CLASS parse_smal (int offset, int fsize) { int ver; @@ -6242,6 +7022,7 @@ void CLASS parse_foveon() raw_width = wide; raw_height = high; data_offset = off+28; + is_foveon = 1; } fseek (ifp, off+28, SEEK_SET); if (fgetc(ifp) == 0xff && fgetc(ifp) == 0xd8 @@ -6267,7 +7048,7 @@ void CLASS parse_foveon() off += pent*8 + 24; if ((unsigned) pent > 256) pent=256; for (i=0; i < pent*2; i++) - poff[0][i] = off + get4()*2; + ((int *)poff)[i] = off + get4()*2; for (i=0; i < pent; i++) { foveon_gets (poff[i][0], name, 64); foveon_gets (poff[i][1], value, 64); @@ -6294,7 +7075,6 @@ void CLASS parse_foveon() } fseek (ifp, save, SEEK_SET); } - is_foveon = 1; } /* @@ -6306,7 +7086,7 @@ void CLASS adobe_coeff (const char *make, const char *model) const char *prefix; short black, maximum, trans[12]; } table[] = { - { "AGFAPHOTO DC-833m", 0, 0, /* DJC */ + { "AgfaPhoto DC-833m", 0, 0, /* DJC */ { 11438,-3762,-1115,-2409,9914,2497,-1227,2295,5300 } }, { "Apple QuickTake", 0, 0, /* DJC */ { 21392,-5653,-3353,2406,8010,-415,7166,1427,2078 } }, @@ -6318,6 +7098,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } }, { "Canon EOS D60", 0, 0xfa0, { 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } }, + { "Canon EOS 5DS", 0, 0x3c96, + { 6250,-711,-808,-5153,12794,2636,-1249,2198,5610 } }, { "Canon EOS 5D Mark III", 0, 0x3c80, { 6722,-635,-963,-4287,12460,2028,-908,2162,5668 } }, { "Canon EOS 5D Mark II", 0, 0x3cf0, @@ -6326,6 +7108,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 } }, { "Canon EOS 6D", 0, 0x3c82, { 7034,-804,-1014,-4420,12564,2058,-851,1994,5758 } }, + { "Canon EOS 7D Mark II", 0, 0x3510, + { 7268,-1082,-969,-4186,11839,2663,-825,2029,5839 } }, { "Canon EOS 7D", 0, 0x3510, { 6844,-996,-856,-3876,11761,2396,-593,1772,6198 } }, { "Canon EOS 10D", 0, 0xfa0, @@ -6342,6 +7126,12 @@ void CLASS adobe_coeff (const char *make, const char *model) { 4920,616,-593,-6493,13964,2784,-1774,3178,7005 } }, { "Canon EOS 60D", 0, 0x2ff7, { 6719,-994,-925,-4408,12426,2211,-887,2129,6051 } }, + { "Canon EOS 70D", 0, 0x3bc7, + { 7034,-804,-1014,-4420,12564,2058,-851,1994,5758 } }, + { "Canon EOS 80D", 0, 0, + { 7457,-671,-937,-4849,12495,2643,-1213,2354,5492 } }, + { "Canon EOS 100D", 0, 0x350f, + { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } }, { "Canon EOS 300D", 0, 0xfa0, { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, { "Canon EOS 350D", 0, 0xfff, @@ -6358,10 +7148,24 @@ void CLASS adobe_coeff (const char *make, const char *model) { 6461,-907,-882,-4300,12184,2378,-819,1944,5931 } }, { "Canon EOS 650D", 0, 0x354d, { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } }, + { "Canon EOS 700D", 0, 0x3c00, + { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } }, + { "Canon EOS 750D", 0, 0x368e, + { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } }, + { "Canon EOS 760D", 0, 0x350f, + { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } }, { "Canon EOS 1000D", 0, 0xe43, { 6771,-1139,-977,-7818,15123,2928,-1244,1437,7533 } }, { "Canon EOS 1100D", 0, 0x3510, { 6444,-904,-893,-4563,12308,2535,-903,2016,6728 } }, + { "Canon EOS 1200D", 0, 0x37c2, + { 6461,-907,-882,-4300,12184,2378,-819,1944,5931 } }, + { "Canon EOS 1300D", 0, 0x3510, + { 6939,-1016,-866,-4428,12473,2177,-1175,2178,6162 } }, + { "Canon EOS M3", 0, 0, + { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } }, + { "Canon EOS M10", 0, 0, + { 6400,-480,-888,-5294,13416,2047,-1296,2203,6137 } }, { "Canon EOS M", 0, 0, { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } }, { "Canon EOS-1Ds Mark III", 0, 0x3bb0, @@ -6378,12 +7182,16 @@ void CLASS adobe_coeff (const char *make, const char *model) { 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 } }, { "Canon EOS-1DS", 0, 0xe20, { 4374,3631,-1743,-7520,15212,2472,-2892,3632,8161 } }, + { "Canon EOS-1D C", 0, 0x3c4e, + { 6847,-614,-1014,-4669,12737,2139,-1197,2488,6846 } }, + { "Canon EOS-1D X Mark II", 0, 0, + { 7596,-978,-967,-4808,12571,2503,-1398,2567,5752 } }, { "Canon EOS-1D X", 0, 0x3c4e, { 6847,-614,-1014,-4669,12737,2139,-1197,2488,6846 } }, { "Canon EOS-1D", 0, 0xe20, { 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } }, - { "Canon EOS", 0, 0, - { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, + { "Canon EOS C500", 853, 0, /* DJC */ + { 17851,-10604,922,-7425,16662,763,-3660,3636,22278 } }, { "Canon PowerShot A530", 0, 0, { 0 } }, /* don't want the A5 matrix */ { "Canon PowerShot A50", 0, 0, @@ -6398,18 +7206,28 @@ void CLASS adobe_coeff (const char *make, const char *model) { 13244,-5501,-1248,-1508,9858,1935,-270,1083,4366 } }, { "Canon PowerShot G15", 0, 0, { 7474,-2301,-567,-4056,11456,2975,-222,716,4181 } }, + { "Canon PowerShot G16", 0, 0, + { 8020,-2687,-682,-3704,11879,2052,-965,1921,5556 } }, { "Canon PowerShot G1 X", 0, 0, { 7378,-1255,-1043,-4088,12251,2048,-876,1946,5805 } }, { "Canon PowerShot G1", 0, 0, { -4778,9467,2172,4743,-1141,4344,-5146,9908,6077,-1566,11051,557 } }, { "Canon PowerShot G2", 0, 0, { 9087,-2693,-1049,-6715,14382,2537,-2291,2819,7790 } }, + { "Canon PowerShot G3 X", 0, 0, + { 9701,-3857,-921,-3149,11537,1817,-786,1817,5147 } }, { "Canon PowerShot G3", 0, 0, { 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } }, + { "Canon PowerShot G5 X", 0, 0, + { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } }, { "Canon PowerShot G5", 0, 0, { 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } }, { "Canon PowerShot G6", 0, 0, { 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } }, + { "Canon PowerShot G7 X", 0, 0, + { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } }, + { "Canon PowerShot G9 X", 0, 0, + { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } }, { "Canon PowerShot G9", 0, 0, { 7368,-2141,-598,-5621,13254,2625,-1418,1696,5743 } }, { "Canon PowerShot Pro1", 0, 0, @@ -6438,10 +7256,16 @@ void CLASS adobe_coeff (const char *make, const char *model) { 7968,-2565,-636,-2873,10697,2513,180,667,4211 } }, { "Canon PowerShot S110", 0, 0, { 8039,-2643,-654,-3783,11230,2930,-206,690,4194 } }, + { "Canon PowerShot S120", 0, 0, + { 6961,-1685,-695,-4625,12945,1836,-1114,2152,5518 } }, { "Canon PowerShot SX1 IS", 0, 0, { 6578,-259,-502,-5974,13030,3309,-308,1058,4970 } }, { "Canon PowerShot SX50 HS", 0, 0, { 12432,-4753,-1247,-2110,10691,1629,-412,1623,4926 } }, + { "Canon PowerShot SX60 HS", 0, 0, + { 13161,-5451,-1344,-1989,10654,1531,-47,1271,4955 } }, + { "Canon PowerShot A3300", 0, 0, /* DJC */ + { 10826,-3654,-1023,-3215,11310,1906,0,999,4960 } }, { "Canon PowerShot A470", 0, 0, /* DJC */ { 12513,-4407,-1242,-2680,10276,2405,-878,2215,4734 } }, { "Canon PowerShot A610", 0, 0, /* DJC */ @@ -6462,11 +7286,13 @@ void CLASS adobe_coeff (const char *make, const char *model) { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } }, { "Canon PowerShot SX220", 0, 0, /* DJC */ { 13898,-5076,-1447,-1405,10109,1297,-244,1860,3687 } }, - { "CASIO EX-S20", 0, 0, /* DJC */ + { "Canon IXUS 160", 0, 0, /* DJC */ + { 11657,-3781,-1136,-3544,11262,2283,-160,1219,4700 } }, + { "Casio EX-S20", 0, 0, /* DJC */ { 11634,-3924,-1128,-4968,12954,2015,-1588,2648,7206 } }, - { "CASIO EX-Z750", 0, 0, /* DJC */ + { "Casio EX-Z750", 0, 0, /* DJC */ { 10819,-3873,-1099,-4903,13730,1175,-1755,3751,4632 } }, - { "CASIO EX-Z10", 128, 0xfff, /* DJC */ + { "Casio EX-Z10", 128, 0xfff, /* DJC */ { 9790,-3338,-603,-2321,10222,2099,-344,1273,4799 } }, { "CINE 650", 0, 0, { 3390,480,-500,-800,3610,340,-550,2336,1192 } }, @@ -6476,93 +7302,129 @@ void CLASS adobe_coeff (const char *make, const char *model) { 20183,-4295,-423,-3940,15330,3985,-280,4870,9800 } }, { "Contax N Digital", 0, 0xf1e, { 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 } }, - { "EPSON R-D1", 0, 0, + { "DXO ONE", 0, 0, + { 6596,-2079,-562,-4782,13016,1933,-970,1581,5181 } }, + { "Epson R-D1", 0, 0, { 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } }, - { "FUJIFILM E550", 0, 0, + { "Fujifilm E550", 0, 0, { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } }, - { "FUJIFILM E900", 0, 0, + { "Fujifilm E900", 0, 0, { 9183,-2526,-1078,-7461,15071,2574,-2022,2440,8639 } }, - { "FUJIFILM F5", 0, 0, + { "Fujifilm F5", 0, 0, { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } }, - { "FUJIFILM F6", 0, 0, + { "Fujifilm F6", 0, 0, { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } }, - { "FUJIFILM F77", 0, 0xfe9, + { "Fujifilm F77", 0, 0xfe9, { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } }, - { "FUJIFILM F7", 0, 0, + { "Fujifilm F7", 0, 0, { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } }, - { "FUJIFILM F8", 0, 0, + { "Fujifilm F8", 0, 0, { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } }, - { "FUJIFILM S100FS", 514, 0, + { "Fujifilm S100FS", 514, 0, { 11521,-4355,-1065,-6524,13767,3058,-1466,1984,6045 } }, - { "FUJIFILM S200EXR", 512, 0x3fff, - { 11401,-4498,-1312,-5088,12751,2613,-838,1568,5941 } }, - { "FUJIFILM S20Pro", 0, 0, + { "Fujifilm S1", 0, 0, + { 12297,-4882,-1202,-2106,10691,1623,-88,1312,4790 } }, + { "Fujifilm S20Pro", 0, 0, { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } }, - { "FUJIFILM S2Pro", 128, 0, + { "Fujifilm S20", 512, 0x3fff, + { 11401,-4498,-1312,-5088,12751,2613,-838,1568,5941 } }, + { "Fujifilm S2Pro", 128, 0, { 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 } }, - { "FUJIFILM S3Pro", 0, 0, + { "Fujifilm S3Pro", 0, 0, { 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } }, - { "FUJIFILM S5Pro", 0, 0, + { "Fujifilm S5Pro", 0, 0, { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } }, - { "FUJIFILM S5000", 0, 0, + { "Fujifilm S5000", 0, 0, { 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } }, - { "FUJIFILM S5100", 0, 0, + { "Fujifilm S5100", 0, 0, { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } }, - { "FUJIFILM S5500", 0, 0, + { "Fujifilm S5500", 0, 0, { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } }, - { "FUJIFILM S5200", 0, 0, + { "Fujifilm S5200", 0, 0, { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } }, - { "FUJIFILM S5600", 0, 0, + { "Fujifilm S5600", 0, 0, { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } }, - { "FUJIFILM S6", 0, 0, + { "Fujifilm S6", 0, 0, { 12628,-4887,-1401,-6861,14996,1962,-2198,2782,7091 } }, - { "FUJIFILM S7000", 0, 0, + { "Fujifilm S7000", 0, 0, { 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } }, - { "FUJIFILM S9000", 0, 0, + { "Fujifilm S9000", 0, 0, { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } }, - { "FUJIFILM S9500", 0, 0, + { "Fujifilm S9500", 0, 0, { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } }, - { "FUJIFILM S9100", 0, 0, + { "Fujifilm S9100", 0, 0, { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } }, - { "FUJIFILM S9600", 0, 0, + { "Fujifilm S9600", 0, 0, { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } }, - { "FUJIFILM IS-1", 0, 0, + { "Fujifilm SL1000", 0, 0, + { 11705,-4262,-1107,-2282,10791,1709,-555,1713,4945 } }, + { "Fujifilm IS-1", 0, 0, { 21461,-10807,-1441,-2332,10599,1999,289,875,7703 } }, - { "FUJIFILM IS Pro", 0, 0, + { "Fujifilm IS Pro", 0, 0, { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } }, - { "FUJIFILM HS10 HS11", 0, 0xf68, + { "Fujifilm HS10 HS11", 0, 0xf68, { 12440,-3954,-1183,-1123,9674,1708,-83,1614,4086 } }, - { "FUJIFILM HS20EXR", 0, 0, + { "Fujifilm HS2", 0, 0, { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } }, - { "FUJIFILM HS3", 0, 0, + { "Fujifilm HS3", 0, 0, { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } }, - { "FUJIFILM X100", 0, 0, + { "Fujifilm HS50EXR", 0, 0, + { 12085,-4727,-953,-3257,11489,2002,-511,2046,4592 } }, + { "Fujifilm F900EXR", 0, 0, + { 12085,-4727,-953,-3257,11489,2002,-511,2046,4592 } }, + { "Fujifilm X100S", 0, 0, + { 10592,-4262,-1008,-3514,11355,2465,-870,2025,6386 } }, + { "Fujifilm X100T", 0, 0, + { 10592,-4262,-1008,-3514,11355,2465,-870,2025,6386 } }, + { "Fujifilm X100", 0, 0, { 12161,-4457,-1069,-5034,12874,2400,-795,1724,6904 } }, - { "FUJIFILM X10", 0, 0, + { "Fujifilm X10", 0, 0, { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } }, - { "FUJIFILM X-Pro1", 0, 0, + { "Fujifilm X20", 0, 0, + { 11768,-4971,-1133,-4904,12927,2183,-480,1723,4605 } }, + { "Fujifilm X30", 0, 0, + { 12328,-5256,-1144,-4469,12927,1675,-87,1291,4351 } }, + { "Fujifilm X70", 0, 0, + { 10450,-4329,-878,-3217,11105,2421,-752,1758,6519 } }, + { "Fujifilm X-Pro1", 0, 0, + { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } }, + { "Fujifilm X-Pro2", 0, 0, + { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, + { "Fujifilm X-A1", 0, 0, + { 11086,-4555,-839,-3512,11310,2517,-815,1341,5940 } }, + { "Fujifilm X-A2", 0, 0, + { 10763,-4560,-917,-3346,11311,2322,-475,1135,5843 } }, + { "Fujifilm X-E1", 0, 0, { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } }, - { "FUJIFILM X-E1", 0, 0, + { "Fujifilm X-E2S", 0, 0, + { 11562,-5118,-961,-3022,11007,2311,-525,1569,6097 } }, + { "Fujifilm X-E2", 0, 0, + { 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 } }, + { "Fujifilm X-M1", 0, 0, { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } }, - { "FUJIFILM XF1", 0, 0, + { "Fujifilm X-S1", 0, 0, { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } }, - { "FUJIFILM X-S1", 0, 0, + { "Fujifilm X-T1", 0, 0, /* also X-T10 */ + { 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 } }, + { "Fujifilm XF1", 0, 0, { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } }, + { "Fujifilm XQ", 0, 0, /* XQ1 and XQ2 */ + { 9252,-2704,-1064,-5893,14265,1717,-1101,2341,4349 } }, { "Imacon Ixpress", 0, 0, /* DJC */ { 7025,-1415,-704,-5188,13765,1424,-1248,2742,6038 } }, - { "KODAK NC2000", 0, 0, + { "Kodak NC2000", 0, 0, { 13891,-6055,-803,-465,9919,642,2121,82,1291 } }, { "Kodak DCS315C", 8, 0, { 17523,-4827,-2510,756,8546,-137,6113,1649,2250 } }, { "Kodak DCS330C", 8, 0, { 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 } }, - { "KODAK DCS420", 0, 0, + { "Kodak DCS420", 0, 0, { 10868,-1852,-644,-1537,11083,484,2343,628,2216 } }, - { "KODAK DCS460", 0, 0, + { "Kodak DCS460", 0, 0, { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } }, - { "KODAK EOSDCS1", 0, 0, + { "Kodak EOSDCS1", 0, 0, { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } }, - { "KODAK EOSDCS3B", 0, 0, + { "Kodak EOSDCS3B", 0, 0, { 9898,-2700,-940,-2478,12219,206,1985,634,1031 } }, { "Kodak DCS520C", 178, 0, { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } }, @@ -6588,19 +7450,19 @@ void CLASS adobe_coeff (const char *make, const char *model) { 16414,-6060,-1470,-3555,13037,473,2545,122,4948 } }, { "Kodak ProBack", 0, 0, { 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 } }, - { "KODAK P712", 0, 0, + { "Kodak P712", 0, 0, { 9658,-3314,-823,-5163,12695,2768,-1342,1843,6044 } }, - { "KODAK P850", 0, 0xf7c, + { "Kodak P850", 0, 0xf7c, { 10511,-3836,-1102,-6946,14587,2558,-1481,1792,6246 } }, - { "KODAK P880", 0, 0xfff, + { "Kodak P880", 0, 0xfff, { 12805,-4662,-1376,-7480,15267,2360,-1626,2194,7904 } }, - { "KODAK EasyShare Z980", 0, 0, + { "Kodak EasyShare Z980", 0, 0, { 11313,-3559,-1101,-3893,11891,2257,-1214,2398,4908 } }, - { "KODAK EasyShare Z981", 0, 0, + { "Kodak EasyShare Z981", 0, 0, { 12729,-4717,-1188,-1367,9187,2582,274,860,4411 } }, - { "KODAK EasyShare Z990", 0, 0xfed, + { "Kodak EasyShare Z990", 0, 0xfed, { 11749,-4048,-1309,-1867,10572,1489,-138,1449,4522 } }, - { "KODAK EASYSHARE Z1015", 0, 0xef1, + { "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 } }, @@ -6626,287 +7488,397 @@ void CLASS adobe_coeff (const char *make, const char *model) { 9144,-2777,-998,-6676,14556,2281,-2470,3019,7744 } }, { "Minolta DiMAGE A1", 0, 0xf8b, { 9274,-2547,-1167,-8220,16323,1943,-2273,2720,8340 } }, - { "MINOLTA DiMAGE A200", 0, 0, + { "Minolta DiMAGE A200", 0, 0, { 8560,-2487,-986,-8112,15535,2771,-1209,1324,7743 } }, { "Minolta DiMAGE A2", 0, 0xf8f, { 9097,-2726,-1053,-8073,15506,2762,-966,981,7763 } }, { "Minolta DiMAGE Z2", 0, 0, /* DJC */ { 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } }, - { "MINOLTA DYNAX 5", 0, 0xffb, + { "Minolta DYNAX 5", 0, 0xffb, { 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 } }, - { "MINOLTA DYNAX 7", 0, 0xffb, + { "Minolta DYNAX 7", 0, 0xffb, { 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } }, - { "MOTOROLA PIXL", 0, 0, /* DJC */ + { "Motorola PIXL", 0, 0, /* DJC */ { 8898,-989,-1033,-3292,11619,1674,-661,3178,5216 } }, - { "NIKON D100", 0, 0, + { "Nikon D100", 0, 0, { 5902,-933,-782,-8983,16719,2354,-1402,1455,6464 } }, - { "NIKON D1H", 0, 0, + { "Nikon D1H", 0, 0, { 7577,-2166,-926,-7454,15592,1934,-2377,2808,8606 } }, - { "NIKON D1X", 0, 0, + { "Nikon D1X", 0, 0, { 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 } }, - { "NIKON D1", 0, 0, /* multiplied by 2.218750, 1.0, 1.148438 */ + { "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, + { "Nikon D200", 0, 0xfbc, { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } }, - { "NIKON D2H", 0, 0, + { "Nikon D2H", 0, 0, { 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } }, - { "NIKON D2X", 0, 0, + { "Nikon D2X", 0, 0, { 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 } }, - { "NIKON D3000", 0, 0, + { "Nikon D3000", 0, 0, { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } }, - { "NIKON D3100", 0, 0, + { "Nikon D3100", 0, 0, { 7911,-2167,-813,-5327,13150,2408,-1288,2483,7968 } }, - { "NIKON D3200", 0, 0xfb9, + { "Nikon D3200", 0, 0xfb9, { 7013,-1408,-635,-5268,12902,2640,-1470,2801,7379 } }, - { "NIKON D300", 0, 0, + { "Nikon D3300", 0, 0, + { 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 } }, + { "Nikon D300", 0, 0, { 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } }, - { "NIKON D3X", 0, 0, + { "Nikon D3X", 0, 0, { 7171,-1986,-648,-8085,15555,2718,-2170,2512,7457 } }, - { "NIKON D3S", 0, 0, + { "Nikon D3S", 0, 0, { 8828,-2406,-694,-4874,12603,2541,-660,1509,7587 } }, - { "NIKON D3", 0, 0, + { "Nikon D3", 0, 0, { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } }, - { "NIKON D40X", 0, 0, + { "Nikon D40X", 0, 0, { 8819,-2543,-911,-9025,16928,2151,-1329,1213,8449 } }, - { "NIKON D40", 0, 0, + { "Nikon D40", 0, 0, { 6992,-1668,-806,-8138,15748,2543,-874,850,7897 } }, - { "NIKON D4", 0, 0, + { "Nikon D4S", 0, 0, + { 8598,-2848,-857,-5618,13606,2195,-1002,1773,7137 } }, + { "Nikon D4", 0, 0, { 8598,-2848,-857,-5618,13606,2195,-1002,1773,7137 } }, - { "NIKON D5000", 0, 0xf00, + { "Nikon Df", 0, 0, + { 8598,-2848,-857,-5618,13606,2195,-1002,1773,7137 } }, + { "Nikon D5000", 0, 0xf00, { 7309,-1403,-519,-8474,16008,2622,-2433,2826,8064 } }, - { "NIKON D5100", 0, 0x3de6, + { "Nikon D5100", 0, 0x3de6, { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } }, - { "NIKON D50", 0, 0, + { "Nikon D5200", 0, 0, + { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } }, + { "Nikon D5300", 0, 0, + { 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 } }, + { "Nikon D5500", 0, 0, + { 8821,-2938,-785,-4178,12142,2287,-824,1651,6860 } }, + { "Nikon D500", 0, 0, + { 8813,-3210,-1036,-4703,12868,2021,-1054,1940,6129 } }, + { "Nikon D50", 0, 0, { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, - { "NIKON D600", 0, 0x3e07, + { "Nikon D5", 0, 0, + { 9200,-3522,-992,-5755,13803,2117,-753,1486,6338 } }, + { "Nikon D600", 0, 0x3e07, + { 8178,-2245,-609,-4857,12394,2776,-1207,2086,7298 } }, + { "Nikon D610", 0, 0, { 8178,-2245,-609,-4857,12394,2776,-1207,2086,7298 } }, - { "NIKON D60", 0, 0, + { "Nikon D60", 0, 0, { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } }, - { "NIKON D7000", 0, 0, + { "Nikon D7000", 0, 0, { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } }, - { "NIKON D700", 0, 0, + { "Nikon D7100", 0, 0, + { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } }, + { "Nikon D7200", 0, 0, + { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } }, + { "Nikon D750", 0, 0, + { 9020,-2890,-715,-4535,12436,2348,-934,1919,7086 } }, + { "Nikon D700", 0, 0, { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } }, - { "NIKON D70", 0, 0, + { "Nikon D70", 0, 0, { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, - { "NIKON D800", 0, 0, + { "Nikon D810", 0, 0, + { 9369,-3195,-791,-4488,12430,2301,-893,1796,6872 } }, + { "Nikon D800", 0, 0, { 7866,-2108,-555,-4869,12483,2681,-1176,2069,7501 } }, - { "NIKON D80", 0, 0, + { "Nikon D80", 0, 0, { 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 } }, - { "NIKON D90", 0, 0xf00, + { "Nikon D90", 0, 0xf00, { 7309,-1403,-519,-8474,16008,2622,-2434,2826,8064 } }, - { "NIKON E950", 0, 0x3dd, /* DJC */ + { "Nikon E700", 0, 0x3dd, /* DJC */ + { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } }, + { "Nikon E800", 0, 0x3dd, /* DJC */ { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } }, - { "NIKON E995", 0, 0, /* copied from E5000 */ + { "Nikon E950", 0, 0x3dd, /* DJC */ + { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } }, + { "Nikon E995", 0, 0, /* copied from E5000 */ { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, - { "NIKON E2100", 0, 0, /* copied from Z2, new white balance */ + { "Nikon E2100", 0, 0, /* copied from Z2, new white balance */ { 13142,-4152,-1596,-4655,12374,2282,-1769,2696,6711} }, - { "NIKON E2500", 0, 0, + { "Nikon E2500", 0, 0, { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, - { "NIKON E3200", 0, 0, /* DJC */ + { "Nikon E3200", 0, 0, /* DJC */ { 9846,-2085,-1019,-3278,11109,2170,-774,2134,5745 } }, - { "NIKON E4300", 0, 0, /* copied from Minolta DiMAGE Z2 */ + { "Nikon E4300", 0, 0, /* copied from Minolta DiMAGE Z2 */ { 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } }, - { "NIKON E4500", 0, 0, + { "Nikon E4500", 0, 0, { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, - { "NIKON E5000", 0, 0, + { "Nikon E5000", 0, 0, { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, - { "NIKON E5400", 0, 0, + { "Nikon E5400", 0, 0, { 9349,-2987,-1001,-7919,15766,2266,-2098,2680,6839 } }, - { "NIKON E5700", 0, 0, + { "Nikon E5700", 0, 0, { -5368,11478,2368,5537,-113,3148,-4969,10021,5782,778,9028,211 } }, - { "NIKON E8400", 0, 0, + { "Nikon E8400", 0, 0, { 7842,-2320,-992,-8154,15718,2599,-1098,1342,7560 } }, - { "NIKON E8700", 0, 0, + { "Nikon E8700", 0, 0, { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } }, - { "NIKON E8800", 0, 0, + { "Nikon E8800", 0, 0, { 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } }, - { "NIKON COOLPIX P6000", 0, 0, + { "Nikon COOLPIX A", 0, 0, + { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } }, + { "Nikon COOLPIX P330", 200, 0, + { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } }, + { "Nikon COOLPIX P340", 200, 0, + { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } }, + { "Nikon COOLPIX P6000", 0, 0, { 9698,-3367,-914,-4706,12584,2368,-837,968,5801 } }, - { "NIKON COOLPIX P7000", 0, 0, + { "Nikon COOLPIX P7000", 0, 0, { 11432,-3679,-1111,-3169,11239,2202,-791,1380,4455 } }, - { "NIKON COOLPIX P7100", 0, 0, + { "Nikon COOLPIX P7100", 0, 0, { 11053,-4269,-1024,-1976,10182,2088,-526,1263,4469 } }, - { "NIKON COOLPIX P7700", 200, 0, + { "Nikon COOLPIX P7700", 200, 0, + { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } }, + { "Nikon COOLPIX P7800", 200, 0, { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } }, - { "NIKON 1 V2", 0, 0, + { "Nikon 1 V3", 0, 0, + { 5958,-1559,-571,-4021,11453,2939,-634,1548,5087 } }, + { "Nikon 1 J4", 0, 0, + { 5958,-1559,-571,-4021,11453,2939,-634,1548,5087 } }, + { "Nikon 1 J5", 0, 0, + { 7520,-2518,-645,-3844,12102,1945,-913,2249,6835 } }, + { "Nikon 1 S2", 200, 0, + { 6612,-1342,-618,-3338,11055,2623,-174,1792,5075 } }, + { "Nikon 1 V2", 0, 0, + { 6588,-1305,-693,-3277,10987,2634,-355,2016,5106 } }, + { "Nikon 1 J3", 0, 0, { 6588,-1305,-693,-3277,10987,2634,-355,2016,5106 } }, - { "NIKON 1 ", 0, 0, + { "Nikon 1 AW1", 0, 0, + { 6588,-1305,-693,-3277,10987,2634,-355,2016,5106 } }, + { "Nikon 1 ", 0, 0, /* J1, J2, S1, V1 */ { 8994,-2667,-865,-4594,12324,2552,-699,1786,6260 } }, - { "OLYMPUS C5050", 0, 0, + { "Olympus AIR A01", 0, 0, + { 8992,-3093,-639,-2563,10721,2122,-437,1270,5473 } }, + { "Olympus C5050", 0, 0, { 10508,-3124,-1273,-6079,14294,1901,-1653,2306,6237 } }, - { "OLYMPUS C5060", 0, 0, + { "Olympus C5060", 0, 0, { 10445,-3362,-1307,-7662,15690,2058,-1135,1176,7602 } }, - { "OLYMPUS C7070", 0, 0, + { "Olympus C7070", 0, 0, { 10252,-3531,-1095,-7114,14850,2436,-1451,1723,6365 } }, - { "OLYMPUS C70", 0, 0, + { "Olympus C70", 0, 0, { 10793,-3791,-1146,-7498,15177,2488,-1390,1577,7321 } }, - { "OLYMPUS C80", 0, 0, + { "Olympus C80", 0, 0, { 8606,-2509,-1014,-8238,15714,2703,-942,979,7760 } }, - { "OLYMPUS E-10", 0, 0xffc, + { "Olympus E-10", 0, 0xffc, { 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } }, - { "OLYMPUS E-1", 0, 0, + { "Olympus E-1", 0, 0, { 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } }, - { "OLYMPUS E-20", 0, 0xffc, + { "Olympus E-20", 0, 0xffc, { 13173,-4732,-1499,-5807,14036,1895,-2045,2452,7142 } }, - { "OLYMPUS E-300", 0, 0, + { "Olympus E-300", 0, 0, { 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } }, - { "OLYMPUS E-330", 0, 0, + { "Olympus E-330", 0, 0, { 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } }, - { "OLYMPUS E-30", 0, 0xfbc, + { "Olympus E-30", 0, 0xfbc, { 8144,-1861,-1111,-7763,15894,1929,-1865,2542,7607 } }, - { "OLYMPUS E-3", 0, 0xf99, + { "Olympus E-3", 0, 0xf99, { 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } }, - { "OLYMPUS E-400", 0, 0, + { "Olympus E-400", 0, 0, { 6169,-1483,-21,-7107,14761,2536,-2904,3580,8568 } }, - { "OLYMPUS E-410", 0, 0xf6a, + { "Olympus E-410", 0, 0xf6a, { 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } }, - { "OLYMPUS E-420", 0, 0xfd7, + { "Olympus E-420", 0, 0xfd7, { 8746,-2425,-1095,-7594,15612,2073,-1780,2309,7416 } }, - { "OLYMPUS E-450", 0, 0xfd2, + { "Olympus E-450", 0, 0xfd2, { 8745,-2425,-1095,-7594,15613,2073,-1780,2309,7416 } }, - { "OLYMPUS E-500", 0, 0, + { "Olympus E-500", 0, 0, { 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 } }, - { "OLYMPUS E-510", 0, 0xf6a, + { "Olympus E-510", 0, 0xf6a, { 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } }, - { "OLYMPUS E-520", 0, 0xfd2, + { "Olympus E-520", 0, 0xfd2, { 8344,-2322,-1020,-7596,15635,2048,-1748,2269,7287 } }, - { "OLYMPUS E-5", 0, 0xeec, + { "Olympus E-5", 0, 0xeec, { 11200,-3783,-1325,-4576,12593,2206,-695,1742,7504 } }, - { "OLYMPUS E-600", 0, 0xfaf, + { "Olympus E-600", 0, 0xfaf, { 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } }, - { "OLYMPUS E-620", 0, 0xfaf, + { "Olympus E-620", 0, 0xfaf, { 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } }, - { "OLYMPUS E-P1", 0, 0xffd, + { "Olympus E-P1", 0, 0xffd, { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } }, - { "OLYMPUS E-P2", 0, 0xffd, + { "Olympus E-P2", 0, 0xffd, { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } }, - { "OLYMPUS E-P3", 0, 0, + { "Olympus E-P3", 0, 0, { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } }, - { "OLYMPUS E-PL1s", 0, 0, + { "Olympus E-P5", 0, 0, + { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, + { "Olympus E-PL1s", 0, 0, { 11409,-3872,-1393,-4572,12757,2003,-709,1810,7415 } }, - { "OLYMPUS E-PL1", 0, 0, + { "Olympus E-PL1", 0, 0, { 11408,-4289,-1215,-4286,12385,2118,-387,1467,7787 } }, - { "OLYMPUS E-PL2", 0, 0, + { "Olympus E-PL2", 0, 0xcf3, { 15030,-5552,-1806,-3987,12387,1767,-592,1670,7023 } }, - { "OLYMPUS E-PL3", 0, 0, + { "Olympus E-PL3", 0, 0, { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } }, - { "OLYMPUS E-PL5", 0, 0xfcb, + { "Olympus E-PL5", 0, 0xfcb, + { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, + { "Olympus E-PL6", 0, 0, { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, - { "OLYMPUS E-PM1", 0, 0, + { "Olympus E-PL7", 0, 0, + { 9197,-3190,-659,-2606,10830,2039,-458,1250,5458 } }, + { "Olympus E-PM1", 0, 0, { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } }, - { "OLYMPUS E-PM2", 0, 0, + { "Olympus E-PM2", 0, 0, { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, - { "OLYMPUS E-M5", 0, 0xfe1, + { "Olympus E-M10", 0, 0, /* also E-M10 Mark II */ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, - { "OLYMPUS SP350", 0, 0, + { "Olympus E-M1", 0, 0, + { 7687,-1984,-606,-4327,11928,2721,-1381,2339,6452 } }, + { "Olympus E-M5MarkII", 0, 0, + { 9422,-3258,-711,-2655,10898,2015,-512,1354,5512 } }, + { "Olympus E-M5", 0, 0xfe1, + { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, + { "Olympus PEN-F", 0, 0, + { 9476,-3182,-765,-2613,10958,1893,-449,1315,5268 } }, + { "Olympus SH-2", 0, 0, + { 10156,-3425,-1077,-2611,11177,1624,-385,1592,5080 } }, + { "Olympus SP350", 0, 0, { 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 } }, - { "OLYMPUS SP3", 0, 0, + { "Olympus SP3", 0, 0, { 11766,-4445,-1067,-6901,14421,2707,-1029,1217,7572 } }, - { "OLYMPUS SP500UZ", 0, 0xfff, + { "Olympus SP500UZ", 0, 0xfff, { 9493,-3415,-666,-5211,12334,3260,-1548,2262,6482 } }, - { "OLYMPUS SP510UZ", 0, 0xffe, + { "Olympus SP510UZ", 0, 0xffe, { 10593,-3607,-1010,-5881,13127,3084,-1200,1805,6721 } }, - { "OLYMPUS SP550UZ", 0, 0xffe, + { "Olympus SP550UZ", 0, 0xffe, { 11597,-4006,-1049,-5432,12799,2957,-1029,1750,6516 } }, - { "OLYMPUS SP560UZ", 0, 0xff9, + { "Olympus SP560UZ", 0, 0xff9, { 10915,-3677,-982,-5587,12986,2911,-1168,1968,6223 } }, - { "OLYMPUS SP570UZ", 0, 0, + { "Olympus SP570UZ", 0, 0, { 11522,-4044,-1146,-4736,12172,2904,-988,1829,6039 } }, - { "OLYMPUS XZ-1", 0, 0, + { "Olympus STYLUS1", 0, 0, + { 8360,-2420,-880,-3928,12353,1739,-1381,2416,5173 } }, + { "Olympus TG-4", 0, 0, + { 11426,-4159,-1126,-2066,10678,1593,-120,1327,4998 } }, + { "Olympus XZ-10", 0, 0, + { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } }, + { "Olympus XZ-1", 0, 0, { 10901,-4095,-1074,-1141,9208,2293,-62,1417,5158 } }, - { "OLYMPUS XZ-2", 0, 0, + { "Olympus XZ-2", 0, 0, { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } }, - { "PENTAX *ist DL2", 0, 0, + { "OmniVision", 0, 0, /* DJC */ + { 12782,-4059,-379,-478,9066,1413,1340,1513,5176 } }, + { "Pentax *ist DL2", 0, 0, { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } }, - { "PENTAX *ist DL", 0, 0, + { "Pentax *ist DL", 0, 0, { 10829,-2838,-1115,-8339,15817,2696,-837,680,11939 } }, - { "PENTAX *ist DS2", 0, 0, + { "Pentax *ist DS2", 0, 0, { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } }, - { "PENTAX *ist DS", 0, 0, + { "Pentax *ist DS", 0, 0, { 10371,-2333,-1206,-8688,16231,2602,-1230,1116,11282 } }, - { "PENTAX *ist D", 0, 0, + { "Pentax *ist D", 0, 0, { 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 } }, - { "PENTAX K10D", 0, 0, + { "Pentax K10D", 0, 0, { 9566,-2863,-803,-7170,15172,2112,-818,803,9705 } }, - { "PENTAX K1", 0, 0, + { "Pentax K1", 0, 0, { 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 } }, - { "PENTAX K20D", 0, 0, + { "Pentax K20D", 0, 0, { 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } }, - { "PENTAX K200D", 0, 0, + { "Pentax K200D", 0, 0, { 9186,-2678,-907,-8693,16517,2260,-1129,1094,8524 } }, - { "PENTAX K2000", 0, 0, + { "Pentax K2000", 0, 0, { 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } }, - { "PENTAX K-m", 0, 0, + { "Pentax K-m", 0, 0, { 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } }, - { "PENTAX K-x", 0, 0, + { "Pentax K-x", 0, 0, { 8843,-2837,-625,-5025,12644,2668,-411,1234,7410 } }, - { "PENTAX K-r", 0, 0, + { "Pentax K-r", 0, 0, { 9895,-3077,-850,-5304,13035,2521,-883,1768,6936 } }, - { "PENTAX K-5 II", 0, 0, + { "Pentax K-1", 0, 0, + { 8566,-2746,-1201,-3612,12204,1550,-893,1680,6264 } }, + { "Pentax K-30", 0, 0, + { 8710,-2632,-1167,-3995,12301,1881,-981,1719,6535 } }, + { "Pentax K-3 II", 0, 0, + { 8626,-2607,-1155,-3995,12301,1881,-1039,1822,6925 } }, + { "Pentax K-3", 0, 0, + { 7415,-2052,-721,-5186,12788,2682,-1446,2157,6773 } }, + { "Pentax K-5 II", 0, 0, { 8170,-2725,-639,-4440,12017,2744,-771,1465,6599 } }, - { "PENTAX K-5", 0, 0, + { "Pentax K-5", 0, 0, { 8713,-2833,-743,-4342,11900,2772,-722,1543,6247 } }, - { "PENTAX K-7", 0, 0, + { "Pentax K-7", 0, 0, { 9142,-2947,-678,-8648,16967,1663,-2224,2898,8615 } }, - { "PENTAX 645D", 0, 0x3e00, + { "Pentax K-S1", 0, 0, + { 8512,-3211,-787,-4167,11966,2487,-638,1288,6054 } }, + { "Pentax K-S2", 0, 0, + { 8662,-3280,-798,-3928,11771,2444,-586,1232,6054 } }, + { "Pentax Q-S1", 0, 0, + { 12995,-5593,-1107,-1879,10139,2027,-64,1233,4919 } }, + { "Pentax 645D", 0, 0x3e00, { 10646,-3593,-1158,-3329,11699,1831,-667,2874,6287 } }, + { "Panasonic DMC-CM1", 15, 0, + { 8770,-3194,-820,-2871,11281,1803,-513,1552,4434 } }, { "Panasonic DMC-FZ8", 0, 0xf7f, { 8986,-2755,-802,-6341,13575,3077,-1476,2144,6379 } }, { "Panasonic DMC-FZ18", 0, 0, { 9932,-3060,-935,-5809,13331,2753,-1267,2155,5575 } }, { "Panasonic DMC-FZ28", 15, 0xf96, { 10109,-3488,-993,-5412,12812,2916,-1305,2140,5543 } }, + { "Panasonic DMC-FZ330", 15, 0, + { 8378,-2798,-769,-3068,11410,1877,-538,1792,4623 } }, + { "Panasonic DMC-FZ300", 15, 0, + { 8378,-2798,-769,-3068,11410,1877,-538,1792,4623 } }, { "Panasonic DMC-FZ30", 0, 0xf94, { 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } }, - { "Panasonic DMC-FZ3", 143, 0, + { "Panasonic DMC-FZ3", 15, 0, { 9938,-2780,-890,-4604,12393,2480,-1117,2304,4620 } }, - { "Panasonic DMC-FZ4", 143, 0, + { "Panasonic DMC-FZ4", 15, 0, { 13639,-5535,-1371,-1698,9633,2430,316,1152,4108 } }, { "Panasonic DMC-FZ50", 0, 0, { 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } }, - { "LEICA V-LUX1", 0, 0, + { "Panasonic DMC-FZ7", 15, 0, + { 11532,-4324,-1066,-2375,10847,1749,-564,1699,4351 } }, + { "Leica V-LUX1", 0, 0, { 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } }, { "Panasonic DMC-L10", 15, 0xf96, { 8025,-1942,-1050,-7920,15904,2100,-2456,3005,7039 } }, { "Panasonic DMC-L1", 0, 0xf7f, { 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } }, - { "LEICA DIGILUX 3", 0, 0xf7f, + { "Leica DIGILUX 3", 0, 0xf7f, { 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } }, { "Panasonic DMC-LC1", 0, 0, { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } }, - { "LEICA DIGILUX 2", 0, 0, + { "Leica DIGILUX 2", 0, 0, { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } }, + { "Panasonic DMC-LX100", 15, 0, + { 8844,-3538,-768,-3709,11762,2200,-698,1792,5220 } }, + { "Leica D-LUX (Typ 109)", 15, 0, + { 8844,-3538,-768,-3709,11762,2200,-698,1792,5220 } }, + { "Panasonic DMC-LF1", 15, 0, + { 9379,-3267,-816,-3227,11560,1881,-926,1928,5340 } }, + { "Leica C (Typ 112)", 15, 0, + { 9379,-3267,-816,-3227,11560,1881,-926,1928,5340 } }, { "Panasonic DMC-LX1", 0, 0xf7f, { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } }, - { "LEICA D-LUX2", 0, 0xf7f, + { "Leica D-LUX2", 0, 0xf7f, { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } }, { "Panasonic DMC-LX2", 0, 0, { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } }, - { "LEICA D-LUX3", 0, 0, + { "Leica D-LUX3", 0, 0, { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } }, { "Panasonic DMC-LX3", 15, 0, { 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } }, - { "LEICA D-LUX 4", 15, 0, + { "Leica D-LUX 4", 15, 0, { 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } }, - { "Panasonic DMC-LX5", 143, 0, + { "Panasonic DMC-LX5", 15, 0, { 10909,-4295,-948,-1333,9306,2399,22,1738,4582 } }, - { "LEICA D-LUX 5", 143, 0, + { "Leica D-LUX 5", 15, 0, { 10909,-4295,-948,-1333,9306,2399,22,1738,4582 } }, - { "Panasonic DMC-LX7", 143, 0, + { "Panasonic DMC-LX7", 15, 0, { 10148,-3743,-991,-2837,11366,1659,-701,1893,4899 } }, - { "LEICA D-LUX 6", 143, 0, + { "Leica D-LUX 6", 15, 0, { 10148,-3743,-991,-2837,11366,1659,-701,1893,4899 } }, - { "Panasonic DMC-FZ100", 143, 0xfff, + { "Panasonic DMC-FZ1000", 15, 0, + { 7830,-2696,-763,-3325,11667,1866,-641,1712,4824 } }, + { "Leica V-LUX (Typ 114)", 15, 0, + { 7830,-2696,-763,-3325,11667,1866,-641,1712,4824 } }, + { "Panasonic DMC-FZ100", 15, 0xfff, { 16197,-6146,-1761,-2393,10765,1869,366,2238,5248 } }, - { "LEICA V-LUX 2", 143, 0xfff, + { "Leica V-LUX 2", 15, 0xfff, { 16197,-6146,-1761,-2393,10765,1869,366,2238,5248 } }, - { "Panasonic DMC-FZ150", 143, 0xfff, + { "Panasonic DMC-FZ150", 15, 0xfff, { 11904,-4541,-1189,-2355,10899,1662,-296,1586,4289 } }, - { "LEICA V-LUX 3", 143, 0xfff, + { "Leica V-LUX 3", 15, 0xfff, { 11904,-4541,-1189,-2355,10899,1662,-296,1586,4289 } }, - { "Panasonic DMC-FZ200", 143, 0xfff, + { "Panasonic DMC-FZ200", 15, 0xfff, { 8112,-2563,-740,-3730,11784,2197,-941,2075,4933 } }, - { "LEICA V-LUX 4", 143, 0xfff, + { "Leica V-LUX 4", 15, 0xfff, { 8112,-2563,-740,-3730,11784,2197,-941,2075,4933 } }, { "Panasonic DMC-FX150", 15, 0xfff, { 9082,-2907,-925,-6119,13377,3058,-1797,2641,5609 } }, @@ -6916,26 +7888,72 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } }, { "Panasonic DMC-G2", 15, 0xf3c, { 10113,-3400,-1114,-4765,12683,2317,-377,1437,6710 } }, - { "Panasonic DMC-G3", 143, 0xfff, + { "Panasonic DMC-G3", 15, 0xfff, { 6763,-1919,-863,-3868,11515,2684,-1216,2387,5879 } }, - { "Panasonic DMC-G5", 143, 0xfff, + { "Panasonic DMC-G5", 15, 0xfff, { 7798,-2562,-740,-3879,11584,2613,-1055,2248,5434 } }, + { "Panasonic DMC-G6", 15, 0xfff, + { 8294,-2891,-651,-3869,11590,2595,-1183,2267,5352 } }, + { "Panasonic DMC-G7", 15, 0xfff, + { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, { "Panasonic DMC-GF1", 15, 0xf92, { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } }, - { "Panasonic DMC-GF2", 143, 0xfff, + { "Panasonic DMC-GF2", 15, 0xfff, { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } }, - { "Panasonic DMC-GF3", 143, 0xfff, + { "Panasonic DMC-GF3", 15, 0xfff, { 9051,-2468,-1204,-5212,13276,2121,-1197,2510,6890 } }, - { "Panasonic DMC-GF5", 143, 0xfff, + { "Panasonic DMC-GF5", 15, 0xfff, { 8228,-2945,-660,-3938,11792,2430,-1094,2278,5793 } }, + { "Panasonic DMC-GF6", 15, 0, + { 8130,-2801,-946,-3520,11289,2552,-1314,2511,5791 } }, + { "Panasonic DMC-GF7", 15, 0, + { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, + { "Panasonic DMC-GF8", 15, 0, + { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, { "Panasonic DMC-GH1", 15, 0xf92, { 6299,-1466,-532,-6535,13852,2969,-2331,3112,5984 } }, { "Panasonic DMC-GH2", 15, 0xf95, { 7780,-2410,-806,-3913,11724,2484,-1018,2390,5298 } }, - { "Panasonic DMC-GH3", 144, 0, + { "Panasonic DMC-GH3", 15, 0, { 6559,-1752,-491,-3672,11407,2586,-962,1875,5130 } }, - { "Panasonic DMC-GX1", 143, 0, + { "Panasonic DMC-GH4", 15, 0, + { 7122,-2108,-512,-3155,11201,2231,-541,1423,5045 } }, + { "Panasonic DMC-GM1", 15, 0, + { 6770,-1895,-744,-5232,13145,2303,-1664,2691,5703 } }, + { "Panasonic DMC-GM5", 15, 0, + { 8238,-3244,-679,-3921,11814,2384,-836,2022,5852 } }, + { "Panasonic DMC-GX1", 15, 0, { 6763,-1919,-863,-3868,11515,2684,-1216,2387,5879 } }, + { "Panasonic DMC-GX7", 15, 0, + { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, + { "Panasonic DMC-GX8", 15, 0, + { 7564,-2263,-606,-3148,11239,2177,-540,1435,4853 } }, + { "Panasonic DMC-TZ1", 15, 0, + { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, + { "Panasonic DMC-ZS1", 15, 0, + { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, + { "Panasonic DMC-TZ6", 15, 0, + { 8607,-2822,-808,-3755,11930,2049,-820,2060,5224 } }, + { "Panasonic DMC-ZS4", 15, 0, + { 8607,-2822,-808,-3755,11930,2049,-820,2060,5224 } }, + { "Panasonic DMC-TZ7", 15, 0, + { 8802,-3135,-789,-3151,11468,1904,-550,1745,4810 } }, + { "Panasonic DMC-ZS5", 15, 0, + { 8802,-3135,-789,-3151,11468,1904,-550,1745,4810 } }, + { "Panasonic DMC-TZ8", 15, 0, + { 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 } }, + { "Panasonic DMC-ZS6", 15, 0, + { 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 } }, + { "Leica S (Typ 007)", 0, 0, + { 6063,-2234,-231,-5210,13787,1500,-1043,2866,6997 } }, + { "Leica X", 0, 0, /* X and X-U, both (Typ 113) */ + { 7712,-2059,-653,-3882,11494,2726,-710,1332,5958 } }, + { "Leica Q (Typ 116)", 0, 0, + { 11865,-4523,-1441,-5423,14458,935,-1587,2687,4830 } }, + { "Leica M (Typ 262)", 0, 0, + { 6653,-1486,-611,-4221,13303,929,-881,2416,7226 } }, + { "Leica SL (Typ 601)", 0, 0, + { 11865,-4523,-1441,-5423,14458,935,-1587,2687,4830} }, { "Phase One H 20", 0, 0, /* DJC */ { 1313,1855,-109,-6715,15908,808,-327,1840,6020 } }, { "Phase One H 25", 0, 0, @@ -6950,97 +7968,159 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, { "Phase One P65", 0, 0, { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, - { "RED ONE", 704, 0xffff, /* DJC */ + { "Photron BC2-HD", 0, 0, /* DJC */ + { 14603,-4122,-528,-1810,9794,2017,-297,2763,5936 } }, + { "Red One", 704, 0xffff, /* DJC */ { 21014,-7891,-2613,-3056,12201,856,-2203,5125,8042 } }, - { "SAMSUNG EX1", 0, 0x3e00, + { "Ricoh GR II", 0, 0, + { 4630,-834,-423,-4977,12805,2417,-638,1467,6115 } }, + { "Ricoh GR", 0, 0, + { 3708,-543,-160,-5381,12254,3556,-1471,1929,8234 } }, + { "Samsung EX1", 0, 0x3e00, { 8898,-2498,-994,-3144,11328,2066,-760,1381,4576 } }, - { "SAMSUNG EX2F", 0, 0x7ff, + { "Samsung EX2F", 0, 0x7ff, { 10648,-3897,-1055,-2022,10573,1668,-492,1611,4742 } }, - { "SAMSUNG NX2", 0, 0xfff, /* NX20, NX200, NX210 */ + { "Samsung EK-GN120", 0, 0, + { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } }, + { "Samsung NX mini", 0, 0, + { 5222,-1196,-550,-6540,14649,2009,-1666,2819,5657 } }, + { "Samsung NX3300", 0, 0, + { 8060,-2933,-761,-4504,12890,1762,-630,1489,5227 } }, + { "Samsung NX3000", 0, 0, + { 8060,-2933,-761,-4504,12890,1762,-630,1489,5227 } }, + { "Samsung NX30", 0, 0, /* NX30, NX300, NX300M */ + { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } }, + { "Samsung NX2000", 0, 0, + { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } }, + { "Samsung NX2", 0, 0xfff, /* NX20, NX200, NX210 */ { 6933,-2268,-753,-4921,13387,1647,-803,1641,6096 } }, - { "SAMSUNG NX1000", 0, 0, + { "Samsung NX1000", 0, 0, { 6933,-2268,-753,-4921,13387,1647,-803,1641,6096 } }, - { "SAMSUNG NX", 0, 0, /* NX5, NX10, NX11, NX100 */ + { "Samsung NX1100", 0, 0, + { 6933,-2268,-753,-4921,13387,1647,-803,1641,6096 } }, + { "Samsung NX11", 0, 0, + { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } }, + { "Samsung NX10", 0, 0, /* also NX100 */ + { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } }, + { "Samsung NX500", 0, 0, + { 10686,-4042,-1052,-3595,13238,276,-464,1259,5931 } }, + { "Samsung NX5", 0, 0, { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } }, - { "SAMSUNG WB2000", 0, 0xfff, + { "Samsung NX1", 0, 0, + { 10686,-4042,-1052,-3595,13238,276,-464,1259,5931 } }, + { "Samsung WB2000", 0, 0xfff, { 12093,-3557,-1155,-1000,9534,1733,-22,1787,4576 } }, - { "SAMSUNG GX-1", 0, 0, + { "Samsung GX-1", 0, 0, { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } }, - { "SAMSUNG S85", 0, 0xffff, /* DJC */ + { "Samsung GX20", 0, 0, /* copied from Pentax K20D */ + { 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } }, + { "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", 0, 0, + { "Sony DSC-F828", 0, 0, { 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401,3481 } }, - { "SONY DSC-R1", 512, 0, + { "Sony DSC-R1", 0, 0, { 8512,-2641,-694,-8042,15670,2526,-1821,2117,7414 } }, - { "SONY DSC-V3", 0, 0, + { "Sony DSC-V3", 0, 0, { 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } }, - { "SONY DSC-RX100", 200, 0, + { "Sony DSC-RX100M", 0, 0, /* M2, M3, and M4 */ + { 6596,-2079,-562,-4782,13016,1933,-970,1581,5181 } }, + { "Sony DSC-RX100", 0, 0, { 8651,-2754,-1057,-3464,12207,1373,-568,1398,4434 } }, - { "SONY DSC-RX1", 128, 0, + { "Sony DSC-RX10", 0, 0, /* also RX10M2 */ + { 6679,-1825,-745,-5047,13256,1953,-1580,2422,5183 } }, + { "Sony DSC-RX1RM2", 0, 0, + { 6629,-1900,-483,-4618,12349,2550,-622,1381,6514 } }, + { "Sony DSC-RX1", 0, 0, { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } }, - { "SONY DSLR-A100", 0, 0xfeb, + { "Sony DSLR-A100", 0, 0xfeb, { 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } }, - { "SONY DSLR-A290", 0, 0, + { "Sony DSLR-A290", 0, 0, { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } }, - { "SONY DSLR-A2", 0, 0, + { "Sony DSLR-A2", 0, 0, { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } }, - { "SONY DSLR-A300", 0, 0, + { "Sony DSLR-A300", 0, 0, { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } }, - { "SONY DSLR-A330", 0, 0, + { "Sony DSLR-A330", 0, 0, { 9847,-3091,-929,-8485,16346,2225,-714,595,7103 } }, - { "SONY DSLR-A350", 0, 0xffc, + { "Sony DSLR-A350", 0, 0xffc, { 6038,-1484,-578,-9146,16746,2513,-875,746,7217 } }, - { "SONY DSLR-A380", 0, 0, + { "Sony DSLR-A380", 0, 0, { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } }, - { "SONY DSLR-A390", 0, 0, + { "Sony DSLR-A390", 0, 0, { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } }, - { "SONY DSLR-A450", 128, 0xfeb, + { "Sony DSLR-A450", 0, 0xfeb, { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } }, - { "SONY DSLR-A580", 128, 0xfeb, + { "Sony DSLR-A580", 0, 0xfeb, { 5932,-1492,-411,-4813,12285,2856,-741,1524,6739 } }, - { "SONY DSLR-A5", 128, 0xfeb, + { "Sony DSLR-A500", 0, 0xfeb, + { 6046,-1127,-278,-5574,13076,2786,-691,1419,7625 } }, + { "Sony DSLR-A5", 0, 0xfeb, { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } }, - { "SONY DSLR-A700", 126, 0, + { "Sony DSLR-A700", 0, 0, { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } }, - { "SONY DSLR-A850", 128, 0, + { "Sony DSLR-A850", 0, 0, { 5413,-1162,-365,-5665,13098,2866,-608,1179,8440 } }, - { "SONY DSLR-A900", 128, 0, + { "Sony DSLR-A900", 0, 0, { 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } }, - { "SONY NEX-5N", 128, 0, + { "Sony ILCA-68", 0, 0, + { 6435,-1903,-536,-4722,12449,2550,-663,1363,6517 } }, + { "Sony ILCA-77M2", 0, 0, + { 5991,-1732,-443,-4100,11989,2381,-704,1467,5992 } }, + { "Sony ILCE-6300", 0, 0, + { 5973,-1695,-419,-3826,11797,2293,-639,1398,5789 } }, + { "Sony ILCE-7M2", 0, 0, + { 5271,-712,-347,-6153,13653,2763,-1601,2366,7242 } }, + { "Sony ILCE-7S", 0, 0, /* also ILCE-7SM2 */ + { 5838,-1430,-246,-3497,11477,2297,-748,1885,5778 } }, + { "Sony ILCE-7RM2", 0, 0, + { 6629,-1900,-483,-4618,12349,2550,-622,1381,6514 } }, + { "Sony ILCE-7R", 0, 0, + { 4913,-541,-202,-6130,13513,2906,-1564,2151,7183 } }, + { "Sony ILCE-7", 0, 0, + { 5271,-712,-347,-6153,13653,2763,-1601,2366,7242 } }, + { "Sony ILCE", 0, 0, /* 3000, 5000, 5100, 6000, and QX1 */ + { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, + { "Sony NEX-5N", 0, 0, { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, - { "SONY NEX-5R", 128, 0, + { "Sony NEX-5R", 0, 0, + { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, + { "Sony NEX-5T", 0, 0, { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, - { "SONY NEX-3", 138, 0, /* DJC */ + { "Sony NEX-3N", 0, 0, + { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, + { "Sony NEX-3", 138, 0, /* DJC */ { 6907,-1256,-645,-4940,12621,2320,-1710,2581,6230 } }, - { "SONY NEX-5", 116, 0, /* DJC */ + { "Sony NEX-5", 116, 0, /* DJC */ { 6807,-1350,-342,-4216,11649,2567,-1089,2001,6420 } }, - { "SONY NEX-3", 128, 0, /* Adobe */ + { "Sony NEX-3", 0, 0, /* Adobe */ { 6549,-1550,-436,-4880,12435,2753,-854,1868,6976 } }, - { "SONY NEX-5", 128, 0, /* Adobe */ + { "Sony NEX-5", 0, 0, /* Adobe */ { 6549,-1550,-436,-4880,12435,2753,-854,1868,6976 } }, - { "SONY NEX-6", 128, 0, + { "Sony NEX-6", 0, 0, { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, - { "SONY NEX-7", 128, 0, + { "Sony NEX-7", 0, 0, { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, - { "SONY NEX", 128, 0, /* NEX-C3, NEX-F3 */ + { "Sony NEX", 0, 0, /* NEX-C3, NEX-F3 */ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, - { "SONY SLT-A33", 128, 0, + { "Sony SLT-A33", 0, 0, { 6069,-1221,-366,-5221,12779,2734,-1024,2066,6834 } }, - { "SONY SLT-A35", 128, 0, + { "Sony SLT-A35", 0, 0, { 5986,-1618,-415,-4557,11820,3120,-681,1404,6971 } }, - { "SONY SLT-A37", 128, 0, + { "Sony SLT-A37", 0, 0, { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, - { "SONY SLT-A55", 128, 0, + { "Sony SLT-A55", 0, 0, { 5932,-1492,-411,-4813,12285,2856,-741,1524,6739 } }, - { "SONY SLT-A57", 128, 0, + { "Sony SLT-A57", 0, 0, + { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, + { "Sony SLT-A58", 0, 0, { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, - { "SONY SLT-A65", 128, 0, + { "Sony SLT-A65", 0, 0, { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, - { "SONY SLT-A77", 128, 0, + { "Sony SLT-A77", 0, 0, { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, - { "SONY SLT-A99", 128, 0, + { "Sony SLT-A99", 0, 0, { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } }, }; double cam_xyz[4][3]; @@ -7053,10 +8133,9 @@ void CLASS adobe_coeff (const char *make, const char *model) if (table[i].black) black = (ushort) table[i].black; if (table[i].maximum) maximum = (ushort) table[i].maximum; if (table[i].trans[0]) { - double *dp = &cam_xyz[0][0]; - const short *sp = &table[i].trans[0]; - for( j=12; --j>=0; ++dp,++sp ) *dp = *sp / 10000.0; - cam_xyz_coeff (cam_xyz); + for (raw_color = j=0; j < 12; j++) + ((double *)cam_xyz)[j] = table[i].trans[j] / 10000.0; + cam_xyz_coeff (rgb_cam, cam_xyz); } break; } @@ -7132,10 +8211,7 @@ float CLASS find_green (int bps, int bite, int off0, int off1) */ void CLASS identify() { - char head[32], *cp; - int hlen, flen, fsize, zero_fsize=1, i, c, is_canon; - struct jhead jh; - short pana[][6] = { + static const short pana[][6] = { { 3130, 1743, 4, 0, -6, 0 }, { 3130, 2055, 4, 0, -6, 0 }, { 3130, 2319, 4, 0, -6, 0 }, @@ -7158,105 +8234,231 @@ void CLASS identify() { 4290, 2391, 3, 0, -8, -1 }, { 4330, 2439, 17, 15,-44,-19 }, { 4508, 2962, 0, 0, -3, -4 }, - { 4508, 3330, 0, 0, -3, -6 } }; + { 4508, 3330, 0, 0, -3, -6 }, + }; + static const ushort canon[][11] = { + { 1944, 1416, 0, 0, 48, 0 }, + { 2144, 1560, 4, 8, 52, 2, 0, 0, 0, 25 }, + { 2224, 1456, 48, 6, 0, 2 }, + { 2376, 1728, 12, 6, 52, 2 }, + { 2672, 1968, 12, 6, 44, 2 }, + { 3152, 2068, 64, 12, 0, 0, 16 }, + { 3160, 2344, 44, 12, 4, 4 }, + { 3344, 2484, 4, 6, 52, 6 }, + { 3516, 2328, 42, 14, 0, 0 }, + { 3596, 2360, 74, 12, 0, 0 }, + { 3744, 2784, 52, 12, 8, 12 }, + { 3944, 2622, 30, 18, 6, 2 }, + { 3948, 2622, 42, 18, 0, 2 }, + { 3984, 2622, 76, 20, 0, 2, 14 }, + { 4104, 3048, 48, 12, 24, 12 }, + { 4116, 2178, 4, 2, 0, 0 }, + { 4152, 2772, 192, 12, 0, 0 }, + { 4160, 3124, 104, 11, 8, 65 }, + { 4176, 3062, 96, 17, 8, 0, 0, 16, 0, 7, 0x49 }, + { 4192, 3062, 96, 17, 24, 0, 0, 16, 0, 0, 0x49 }, + { 4312, 2876, 22, 18, 0, 2 }, + { 4352, 2874, 62, 18, 0, 0 }, + { 4476, 2954, 90, 34, 0, 0 }, + { 4480, 3348, 12, 10, 36, 12, 0, 0, 0, 18, 0x49 }, + { 4480, 3366, 80, 50, 0, 0 }, + { 4496, 3366, 80, 50, 12, 0 }, + { 4768, 3516, 96, 16, 0, 0, 0, 16 }, + { 4832, 3204, 62, 26, 0, 0 }, + { 4832, 3228, 62, 51, 0, 0 }, + { 5108, 3349, 98, 13, 0, 0 }, + { 5120, 3318, 142, 45, 62, 0 }, + { 5280, 3528, 72, 52, 0, 0 }, + { 5344, 3516, 142, 51, 0, 0 }, + { 5344, 3584, 126,100, 0, 2 }, + { 5360, 3516, 158, 51, 0, 0 }, + { 5568, 3708, 72, 38, 0, 0 }, + { 5632, 3710, 96, 17, 0, 0, 0, 16, 0, 0, 0x49 }, + { 5712, 3774, 62, 20, 10, 2 }, + { 5792, 3804, 158, 51, 0, 0 }, + { 5920, 3950, 122, 80, 2, 0 }, + { 6096, 4056, 72, 34, 0, 0 }, + { 6288, 4056, 264, 34, 0, 0 }, + { 8896, 5920, 160, 64, 0, 0 }, + }; + static const struct { + ushort id; + char model[20]; + } unique[] = { + { 0x168, "EOS 10D" }, { 0x001, "EOS-1D" }, + { 0x175, "EOS 20D" }, { 0x174, "EOS-1D Mark II" }, + { 0x234, "EOS 30D" }, { 0x232, "EOS-1D Mark II N" }, + { 0x190, "EOS 40D" }, { 0x169, "EOS-1D Mark III" }, + { 0x261, "EOS 50D" }, { 0x281, "EOS-1D Mark IV" }, + { 0x287, "EOS 60D" }, { 0x167, "EOS-1DS" }, + { 0x325, "EOS 70D" }, + { 0x350, "EOS 80D" }, { 0x328, "EOS-1D X Mark II" }, + { 0x170, "EOS 300D" }, { 0x188, "EOS-1Ds Mark II" }, + { 0x176, "EOS 450D" }, { 0x215, "EOS-1Ds Mark III" }, + { 0x189, "EOS 350D" }, { 0x324, "EOS-1D C" }, + { 0x236, "EOS 400D" }, { 0x269, "EOS-1D X" }, + { 0x252, "EOS 500D" }, { 0x213, "EOS 5D" }, + { 0x270, "EOS 550D" }, { 0x218, "EOS 5D Mark II" }, + { 0x286, "EOS 600D" }, { 0x285, "EOS 5D Mark III" }, + { 0x301, "EOS 650D" }, { 0x302, "EOS 6D" }, + { 0x326, "EOS 700D" }, { 0x250, "EOS 7D" }, + { 0x393, "EOS 750D" }, { 0x289, "EOS 7D Mark II" }, + { 0x347, "EOS 760D" }, + { 0x254, "EOS 1000D" }, + { 0x288, "EOS 1100D" }, + { 0x327, "EOS 1200D" }, { 0x382, "Canon EOS 5DS" }, + { 0x404, "EOS 1300D" }, { 0x401, "Canon EOS 5DS R" }, + { 0x346, "EOS 100D" }, + }, sonique[] = { + { 0x002, "DSC-R1" }, { 0x100, "DSLR-A100" }, + { 0x101, "DSLR-A900" }, { 0x102, "DSLR-A700" }, + { 0x103, "DSLR-A200" }, { 0x104, "DSLR-A350" }, + { 0x105, "DSLR-A300" }, { 0x108, "DSLR-A330" }, + { 0x109, "DSLR-A230" }, { 0x10a, "DSLR-A290" }, + { 0x10d, "DSLR-A850" }, { 0x111, "DSLR-A550" }, + { 0x112, "DSLR-A500" }, { 0x113, "DSLR-A450" }, + { 0x116, "NEX-5" }, { 0x117, "NEX-3" }, + { 0x118, "SLT-A33" }, { 0x119, "SLT-A55V" }, + { 0x11a, "DSLR-A560" }, { 0x11b, "DSLR-A580" }, + { 0x11c, "NEX-C3" }, { 0x11d, "SLT-A35" }, + { 0x11e, "SLT-A65V" }, { 0x11f, "SLT-A77V" }, + { 0x120, "NEX-5N" }, { 0x121, "NEX-7" }, + { 0x123, "SLT-A37" }, { 0x124, "SLT-A57" }, + { 0x125, "NEX-F3" }, { 0x126, "SLT-A99V" }, + { 0x127, "NEX-6" }, { 0x128, "NEX-5R" }, + { 0x129, "DSC-RX100" }, { 0x12a, "DSC-RX1" }, + { 0x12e, "ILCE-3000" }, { 0x12f, "SLT-A58" }, + { 0x131, "NEX-3N" }, { 0x132, "ILCE-7" }, + { 0x133, "NEX-5T" }, { 0x134, "DSC-RX100M2" }, + { 0x135, "DSC-RX10" }, { 0x136, "DSC-RX1R" }, + { 0x137, "ILCE-7R" }, { 0x138, "ILCE-6000" }, + { 0x139, "ILCE-5000" }, { 0x13d, "DSC-RX100M3" }, + { 0x13e, "ILCE-7S" }, { 0x13f, "ILCA-77M2" }, + { 0x153, "ILCE-5100" }, { 0x154, "ILCE-7M2" }, + { 0x155, "DSC-RX100M4" },{ 0x156, "DSC-RX10M2" }, + { 0x158, "DSC-RX1RM2" }, { 0x15a, "ILCE-QX1" }, + { 0x15b, "ILCE-7RM2" }, { 0x15e, "ILCE-7SM2" }, + { 0x161, "ILCA-68" }, { 0x165, "ILCE-6300" }, + }; static const struct { - int fsize; - char make[12], model[19], withjpeg; + unsigned fsize; + ushort rw, rh; + uchar lm, tm, rm, bm, lf, cf, max, flags; + char make[10], model[20]; + ushort offset; } table[] = { - { 62464, "Kodak", "DC20" ,0 }, - { 124928, "Kodak", "DC20" ,0 }, - { 1652736, "Kodak", "DCS200" ,0 }, - { 4159302, "Kodak", "C330" ,0 }, - { 4162462, "Kodak", "C330" ,0 }, - { 460800, "Kodak", "C603v" ,0 }, - { 614400, "Kodak", "C603v" ,0 }, - { 6163328, "Kodak", "C603" ,0 }, - { 6166488, "Kodak", "C603" ,0 }, - { 9116448, "Kodak", "C603y" ,0 }, - { 311696, "ST Micro", "STV680 VGA" ,0 }, /* SPYz */ - { 787456, "Creative", "PC-CAM 600" ,0 }, - { 1138688, "Minolta", "RD175" ,0 }, - { 3840000, "Foculus", "531C" ,0 }, - { 307200, "Generic", "640x480" ,0 }, - { 786432, "AVT", "F-080C" ,0 }, - { 1447680, "AVT", "F-145C" ,0 }, - { 1920000, "AVT", "F-201C" ,0 }, - { 5067304, "AVT", "F-510C" ,0 }, - { 5067316, "AVT", "F-510C" ,0 }, - { 10134608, "AVT", "F-510C" ,0 }, - { 10134620, "AVT", "F-510C" ,0 }, - { 16157136, "AVT", "F-810C" ,0 }, - { 1409024, "Sony", "XCD-SX910CR" ,0 }, - { 2818048, "Sony", "XCD-SX910CR" ,0 }, - { 3884928, "Micron", "2010" ,0 }, - { 6624000, "Pixelink", "A782" ,0 }, - { 13248000, "Pixelink", "A782" ,0 }, - { 6291456, "RoverShot","3320AF" ,0 }, - { 6553440, "Canon", "PowerShot A460" ,0 }, - { 6653280, "Canon", "PowerShot A530" ,0 }, - { 6573120, "Canon", "PowerShot A610" ,0 }, - { 9219600, "Canon", "PowerShot A620" ,0 }, - { 9243240, "Canon", "PowerShot A470" ,0 }, - { 10341600, "Canon", "PowerShot A720 IS",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 }, - { 15534576, "Canon", "PowerShot SX120 IS",0 }, - { 18653760, "Canon", "PowerShot SX20 IS",0 }, - { 19131120, "Canon", "PowerShot SX220 HS",0 }, - { 21936096, "Canon", "PowerShot SX30 IS",0 }, - { 5939200, "OLYMPUS", "C770UZ" ,0 }, - { 1581060, "NIKON", "E900" ,1 }, /* or E900s,E910 */ - { 2465792, "NIKON", "E950" ,1 }, /* or E800,E700 */ - { 2940928, "NIKON", "E2100" ,1 }, /* or E2500 */ - { 4771840, "NIKON", "E990" ,1 }, /* or E995, Oly C3030Z */ - { 4775936, "NIKON", "E3700" ,1 }, /* or Optio 33WR */ - { 5869568, "NIKON", "E4300" ,1 }, /* or DiMAGE Z2 */ - { 5865472, "NIKON", "E4500" ,1 }, - { 7438336, "NIKON", "E5000" ,1 }, /* or E5700 */ - { 8998912, "NIKON", "COOLPIX S6" ,1 }, - { 1976352, "CASIO", "QV-2000UX" ,1 }, - { 3217760, "CASIO", "QV-3*00EX" ,1 }, - { 6218368, "CASIO", "QV-5700" ,1 }, - { 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 }, - { 7562048, "CASIO", "EX-Z500" ,1 }, - { 7753344, "CASIO", "EX-Z55" ,1 }, - { 7816704, "CASIO", "EX-Z60" ,1 }, - { 10843712, "CASIO", "EX-Z75" ,1 }, - { 10834368, "CASIO", "EX-Z750" ,1 }, - { 12310144, "CASIO", "EX-Z850" ,1 }, - { 12489984, "CASIO", "EX-Z8" ,1 }, - { 15499264, "CASIO", "EX-Z1050" ,1 }, - { 18702336, "CASIO", "EX-ZR100" ,1 }, - { 7426656, "CASIO", "EX-P505" ,1 }, - { 9313536, "CASIO", "EX-P600" ,1 }, - { 10979200, "CASIO", "EX-P700" ,1 }, - { 3178560, "PENTAX", "Optio S" ,1 }, - { 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 }, - { 20487168, "SAMSUNG", "WB550" ,1 }, - { 24000000, "SAMSUNG", "WB550" ,1 }, - { 12582980, "Sinar", "" ,0 }, - { 33292868, "Sinar", "" ,0 }, - { 44390468, "Sinar", "" ,0 } }; + { 786432,1024, 768, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-080C" }, + { 1447680,1392,1040, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-145C" }, + { 1920000,1600,1200, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-201C" }, + { 5067304,2588,1958, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-510C" }, + { 5067316,2588,1958, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-510C",12 }, + { 10134608,2588,1958, 0, 0, 0, 0, 9,0x94,0,0,"AVT","F-510C" }, + { 10134620,2588,1958, 0, 0, 0, 0, 9,0x94,0,0,"AVT","F-510C",12 }, + { 16157136,3272,2469, 0, 0, 0, 0, 9,0x94,0,0,"AVT","F-810C" }, + { 15980544,3264,2448, 0, 0, 0, 0, 8,0x61,0,1,"AgfaPhoto","DC-833m" }, + { 9631728,2532,1902, 0, 0, 0, 0,96,0x61,0,0,"Alcatel","5035D" }, + { 2868726,1384,1036, 0, 0, 0, 0,64,0x49,0,8,"Baumer","TXG14",1078 }, + { 5298000,2400,1766,12,12,44, 2,40,0x94,0,2,"Canon","PowerShot SD300" }, + { 6553440,2664,1968, 4, 4,44, 4,40,0x94,0,2,"Canon","PowerShot A460" }, + { 6573120,2672,1968,12, 8,44, 0,40,0x94,0,2,"Canon","PowerShot A610" }, + { 6653280,2672,1992,10, 6,42, 2,40,0x94,0,2,"Canon","PowerShot A530" }, + { 7710960,2888,2136,44, 8, 4, 0,40,0x94,0,2,"Canon","PowerShot S3 IS" }, + { 9219600,3152,2340,36,12, 4, 0,40,0x94,0,2,"Canon","PowerShot A620" }, + { 9243240,3152,2346,12, 7,44,13,40,0x49,0,2,"Canon","PowerShot A470" }, + { 10341600,3336,2480, 6, 5,32, 3,40,0x94,0,2,"Canon","PowerShot A720 IS" }, + { 10383120,3344,2484,12, 6,44, 6,40,0x94,0,2,"Canon","PowerShot A630" }, + { 12945240,3736,2772,12, 6,52, 6,40,0x94,0,2,"Canon","PowerShot A640" }, + { 15636240,4104,3048,48,12,24,12,40,0x94,0,2,"Canon","PowerShot A650" }, + { 15467760,3720,2772, 6,12,30, 0,40,0x94,0,2,"Canon","PowerShot SX110 IS" }, + { 15534576,3728,2778,12, 9,44, 9,40,0x94,0,2,"Canon","PowerShot SX120 IS" }, + { 18653760,4080,3048,24,12,24,12,40,0x94,0,2,"Canon","PowerShot SX20 IS" }, + { 19131120,4168,3060,92,16, 4, 1,40,0x94,0,2,"Canon","PowerShot SX220 HS" }, + { 21936096,4464,3276,25,10,73,12,40,0x16,0,2,"Canon","PowerShot SX30 IS" }, + { 24724224,4704,3504, 8,16,56, 8,40,0x94,0,2,"Canon","PowerShot A3300 IS" }, + { 30858240,5248,3920, 8,16,56,16,40,0x94,0,2,"Canon","IXUS 160" }, + { 1976352,1632,1211, 0, 2, 0, 1, 0,0x94,0,1,"Casio","QV-2000UX" }, + { 3217760,2080,1547, 0, 0,10, 1, 0,0x94,0,1,"Casio","QV-3*00EX" }, + { 6218368,2585,1924, 0, 0, 9, 0, 0,0x94,0,1,"Casio","QV-5700" }, + { 7816704,2867,2181, 0, 0,34,36, 0,0x16,0,1,"Casio","EX-Z60" }, + { 2937856,1621,1208, 0, 0, 1, 0, 0,0x94,7,13,"Casio","EX-S20" }, + { 4948608,2090,1578, 0, 0,32,34, 0,0x94,7,1,"Casio","EX-S100" }, + { 6054400,2346,1720, 2, 0,32, 0, 0,0x94,7,1,"Casio","QV-R41" }, + { 7426656,2568,1928, 0, 0, 0, 0, 0,0x94,0,1,"Casio","EX-P505" }, + { 7530816,2602,1929, 0, 0,22, 0, 0,0x94,7,1,"Casio","QV-R51" }, + { 7542528,2602,1932, 0, 0,32, 0, 0,0x94,7,1,"Casio","EX-Z50" }, + { 7562048,2602,1937, 0, 0,25, 0, 0,0x16,7,1,"Casio","EX-Z500" }, + { 7753344,2602,1986, 0, 0,32,26, 0,0x94,7,1,"Casio","EX-Z55" }, + { 9313536,2858,2172, 0, 0,14,30, 0,0x94,7,1,"Casio","EX-P600" }, + { 10834368,3114,2319, 0, 0,27, 0, 0,0x94,0,1,"Casio","EX-Z750" }, + { 10843712,3114,2321, 0, 0,25, 0, 0,0x94,0,1,"Casio","EX-Z75" }, + { 10979200,3114,2350, 0, 0,32,32, 0,0x94,7,1,"Casio","EX-P700" }, + { 12310144,3285,2498, 0, 0, 6,30, 0,0x94,0,1,"Casio","EX-Z850" }, + { 12489984,3328,2502, 0, 0,47,35, 0,0x94,0,1,"Casio","EX-Z8" }, + { 15499264,3754,2752, 0, 0,82, 0, 0,0x94,0,1,"Casio","EX-Z1050" }, + { 18702336,4096,3044, 0, 0,24, 0,80,0x94,7,1,"Casio","EX-ZR100" }, + { 7684000,2260,1700, 0, 0, 0, 0,13,0x94,0,1,"Casio","QV-4000" }, + { 787456,1024, 769, 0, 1, 0, 0, 0,0x49,0,0,"Creative","PC-CAM 600" }, + { 28829184,4384,3288, 0, 0, 0, 0,36,0x61,0,0,"DJI" }, + { 15151104,4608,3288, 0, 0, 0, 0, 0,0x94,0,0,"Matrix" }, + { 3840000,1600,1200, 0, 0, 0, 0,65,0x49,0,0,"Foculus","531C" }, + { 307200, 640, 480, 0, 0, 0, 0, 0,0x94,0,0,"Generic" }, + { 62464, 256, 244, 1, 1, 6, 1, 0,0x8d,0,0,"Kodak","DC20" }, + { 124928, 512, 244, 1, 1,10, 1, 0,0x8d,0,0,"Kodak","DC20" }, + { 1652736,1536,1076, 0,52, 0, 0, 0,0x61,0,0,"Kodak","DCS200" }, + { 4159302,2338,1779, 1,33, 1, 2, 0,0x94,0,0,"Kodak","C330" }, + { 4162462,2338,1779, 1,33, 1, 2, 0,0x94,0,0,"Kodak","C330",3160 }, + { 2247168,1232, 912, 0, 0,16, 0, 0,0x00,0,0,"Kodak","C330" }, + { 3370752,1232, 912, 0, 0,16, 0, 0,0x00,0,0,"Kodak","C330" }, + { 6163328,2864,2152, 0, 0, 0, 0, 0,0x94,0,0,"Kodak","C603" }, + { 6166488,2864,2152, 0, 0, 0, 0, 0,0x94,0,0,"Kodak","C603",3160 }, + { 460800, 640, 480, 0, 0, 0, 0, 0,0x00,0,0,"Kodak","C603" }, + { 9116448,2848,2134, 0, 0, 0, 0, 0,0x00,0,0,"Kodak","C603" }, + { 12241200,4040,3030, 2, 0, 0,13, 0,0x49,0,0,"Kodak","12MP" }, + { 12272756,4040,3030, 2, 0, 0,13, 0,0x49,0,0,"Kodak","12MP",31556 }, + { 18000000,4000,3000, 0, 0, 0, 0, 0,0x00,0,0,"Kodak","12MP" }, + { 614400, 640, 480, 0, 3, 0, 0,64,0x94,0,0,"Kodak","KAI-0340" }, + { 15360000,3200,2400, 0, 0, 0, 0,96,0x16,0,0,"Lenovo","A820" }, + { 3884928,1608,1207, 0, 0, 0, 0,96,0x16,0,0,"Micron","2010",3212 }, + { 1138688,1534, 986, 0, 0, 0, 0, 0,0x61,0,0,"Minolta","RD175",513 }, + { 1581060,1305, 969, 0, 0,18, 6, 6,0x1e,4,1,"Nikon","E900" }, + { 2465792,1638,1204, 0, 0,22, 1, 6,0x4b,5,1,"Nikon","E950" }, + { 2940928,1616,1213, 0, 0, 0, 7,30,0x94,0,1,"Nikon","E2100" }, + { 4771840,2064,1541, 0, 0, 0, 1, 6,0xe1,0,1,"Nikon","E990" }, + { 4775936,2064,1542, 0, 0, 0, 0,30,0x94,0,1,"Nikon","E3700" }, + { 5865472,2288,1709, 0, 0, 0, 1, 6,0xb4,0,1,"Nikon","E4500" }, + { 5869568,2288,1710, 0, 0, 0, 0, 6,0x16,0,1,"Nikon","E4300" }, + { 7438336,2576,1925, 0, 0, 0, 1, 6,0xb4,0,1,"Nikon","E5000" }, + { 8998912,2832,2118, 0, 0, 0, 0,30,0x94,7,1,"Nikon","COOLPIX S6" }, + { 5939200,2304,1718, 0, 0, 0, 0,30,0x16,0,0,"Olympus","C770UZ" }, + { 3178560,2064,1540, 0, 0, 0, 0, 0,0x94,0,1,"Pentax","Optio S" }, + { 4841984,2090,1544, 0, 0,22, 0, 0,0x94,7,1,"Pentax","Optio S" }, + { 6114240,2346,1737, 0, 0,22, 0, 0,0x94,7,1,"Pentax","Optio S4" }, + { 10702848,3072,2322, 0, 0, 0,21,30,0x94,0,1,"Pentax","Optio 750Z" }, + { 4147200,1920,1080, 0, 0, 0, 0, 0,0x49,0,0,"Photron","BC2-HD" }, + { 4151666,1920,1080, 0, 0, 0, 0, 0,0x49,0,0,"Photron","BC2-HD",8 }, + { 13248000,2208,3000, 0, 0, 0, 0,13,0x61,0,0,"Pixelink","A782" }, + { 6291456,2048,1536, 0, 0, 0, 0,96,0x61,0,0,"RoverShot","3320AF" }, + { 311696, 644, 484, 0, 0, 0, 0, 0,0x16,0,8,"ST Micro","STV680 VGA" }, + { 16098048,3288,2448, 0, 0,24, 0, 9,0x94,0,1,"Samsung","S85" }, + { 16215552,3312,2448, 0, 0,48, 0, 9,0x94,0,1,"Samsung","S85" }, + { 20487168,3648,2808, 0, 0, 0, 0,13,0x94,5,1,"Samsung","WB550" }, + { 24000000,4000,3000, 0, 0, 0, 0,13,0x94,5,1,"Samsung","WB550" }, + { 12582980,3072,2048, 0, 0, 0, 0,33,0x61,0,0,"Sinar","",68 }, + { 33292868,4080,4080, 0, 0, 0, 0,33,0x61,0,0,"Sinar","",68 }, + { 44390468,4080,5440, 0, 0, 0, 0,33,0x61,0,0,"Sinar","",68 }, + { 1409024,1376,1024, 0, 0, 1, 0, 0,0x49,0,0,"Sony","XCD-SX910CR" }, + { 2818048,1376,1024, 0, 0, 1, 0,97,0x49,0,0,"Sony","XCD-SX910CR" }, + }; static const char *corp[] = - { "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX", - "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One", - "SAMSUNG", "Mamiya", "MOTOROLA", "LEICA" }; + { "AgfaPhoto", "Canon", "Casio", "Epson", "Fujifilm", + "Mamiya", "Minolta", "Motorola", "Kodak", "Konica", "Leica", + "Nikon", "Nokia", "Olympus", "Ricoh", "Pentax", "Phase One", + "Samsung", "Sigma", "Sinar", "Sony" }; + char head[32], *cp; + int hlen, flen, fsize, zero_fsize=1, i, c; + struct jhead jh; - tiff_flip = flip = filters = -1; /* 0 is valid, so -1 is unknown */ + tiff_flip = flip = filters = UINT_MAX; /* unknown */ raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0; maximum = height = width = top_margin = left_margin = 0; cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = 0; @@ -7270,7 +8472,7 @@ void CLASS identify() thumb_offset = thumb_length = thumb_width = thumb_height = 0; load_raw = thumb_load_raw = 0; write_thumb = &CLASS jpeg_thumb; - data_offset = meta_length = tiff_bps = tiff_compress = 0; + data_offset = meta_offset = meta_length = tiff_bps = tiff_compress = 0; 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; @@ -7298,7 +8500,8 @@ void CLASS identify() } else if (order == 0x4949 || order == 0x4d4d) { if (!memcmp (head+6,"HEAPCCDR",8)) { data_offset = hlen; - parse_ciff (hlen, flen - hlen); + parse_ciff (hlen, flen-hlen, 0); + load_raw = &CLASS canon_load_raw; } else if (parse_tiff(0)) apply_tiff(); } else if (!memcmp (head,"\xff\xd8\xff\xe1",4) && !memcmp (head+6,"Exif",4)) { @@ -7346,6 +8549,10 @@ void CLASS identify() } else if (!memcmp (head,"RIFF",4)) { fseek (ifp, 0, SEEK_SET); parse_riff(); + } else if (!memcmp (head+4,"ftypqt ",9)) { + fseek (ifp, 0, SEEK_SET); + parse_qt (fsize); + is_raw = 0; } else if (!memcmp (head,"\0\001\0\001\0@",6)) { fseek (ifp, 6, SEEK_SET); fread (make, 1, 8, ifp); @@ -7359,15 +8566,18 @@ void CLASS identify() filters = 0x61616161; } else if (!memcmp (head,"NOKIARAW",8)) { strcpy (make, "NOKIA"); - strcpy (model, "X2"); order = 0x4949; fseek (ifp, 300, SEEK_SET); data_offset = get4(); i = get4(); width = get2(); height = get2(); - data_offset += i - width * 5 / 4 * height; - load_raw = &CLASS nokia_load_raw; + switch (tiff_bps = i*8 / (width * height)) { + case 8: load_raw = &CLASS eight_bit_load_raw; break; + case 10: load_raw = &CLASS nokia_load_raw; + } + raw_height = height + (top_margin = i / (width * tiff_bps/8) - height); + mask[0][3] = 1; filters = 0x61616161; } else if (!memcmp (head,"ARRI",4)) { order = 0x4949; @@ -7381,9 +8591,20 @@ void CLASS identify() load_raw = &CLASS packed_load_raw; load_flags = 88; filters = 0x61616161; + } else if (!memcmp (head,"XPDS",4)) { + order = 0x4949; + fseek (ifp, 0x800, SEEK_SET); + fread (make, 1, 41, ifp); + raw_height = get2(); + raw_width = get2(); + fseek (ifp, 56, SEEK_CUR); + fread (model, 1, 30, ifp); + data_offset = 0x10000; + load_raw = &CLASS canon_rmf_load_raw; + gamma_curve (0, 12.25, 1, 1023); } else if (!memcmp (head+4,"RED1",4)) { - strcpy (make, "RED"); - strcpy (model,"ONE"); + strcpy (make, "Red"); + strcpy (model,"One"); parse_redcine(); load_raw = &CLASS redcine_load_raw; gamma_curve (1/2.4, 12.92, 1, 4095); @@ -7398,26 +8619,66 @@ void CLASS identify() parse_foveon(); else if (!memcmp (head,"CI",2)) parse_cine(); - else + if (make[0] == 0) for (zero_fsize=i=0; i < sizeof table / sizeof *table; i++) if (fsize == table[i].fsize) { strcpy (make, table[i].make ); strcpy (model, table[i].model); - if (table[i].withjpeg) + flip = table[i].flags >> 2; + zero_is_bad = table[i].flags & 2; + if (table[i].flags & 1) parse_external_jpeg(); + data_offset = table[i].offset; + raw_width = table[i].rw; + raw_height = table[i].rh; + left_margin = table[i].lm; + top_margin = table[i].tm; + width = raw_width - left_margin - table[i].rm; + height = raw_height - top_margin - table[i].bm; + filters = 0x1010101 * table[i].cf; + colors = 4 - !((filters & filters >> 1) & 0x5555); + load_flags = table[i].lf; + switch (tiff_bps = (fsize-data_offset)*8 / (raw_width*raw_height)) { + case 6: + load_raw = &CLASS minolta_rd175_load_raw; break; + case 8: + load_raw = &CLASS eight_bit_load_raw; break; + case 10: case 12: + load_flags |= 128; + load_raw = &CLASS packed_load_raw; break; + case 16: + order = 0x4949 | 0x404 * (load_flags & 1); + tiff_bps -= load_flags >> 4; + tiff_bps -= load_flags = load_flags >> 1 & 7; + load_raw = &CLASS unpacked_load_raw; + } + maximum = (1 << tiff_bps) - (1 << table[i].max); } if (zero_fsize) fsize = 0; if (make[0] == 0) parse_smal (0, flen); - if (make[0] == 0) parse_jpeg (is_raw = 0); + if (make[0] == 0) { + parse_jpeg(0); + if (!(strncmp(model,"ov",2) && strncmp(model,"RP_OV",5)) && + !fseek (ifp, -6404096, SEEK_END) && + fread (head, 1, 32, ifp) && !strcmp(head,"BRCMn")) { + strcpy (make, "OmniVision"); + data_offset = ftell(ifp) + 0x8000-32; + width = raw_width; + raw_width = 2611; + load_raw = &CLASS nokia_load_raw; + filters = 0x16161616; + } else is_raw = 0; + } for (i=0; i < sizeof corp / sizeof *corp; i++) - if (strstr (make, corp[i])) /* Simplify company names */ - strcpy (make, corp[i]); - if (!strncmp (make,"KODAK",5) && - ((cp = strstr(model," DIGITAL CAMERA")) || - (cp = strstr(model," Digital Camera")) || + if (strcasestr (make, corp[i])) /* Simplify company names */ + strcpy (make, corp[i]); + if ((!strcmp(make,"Kodak") || !strcmp(make,"Leica")) && + ((cp = strcasestr(model," DIGITAL CAMERA")) || (cp = strstr(model,"FILE VERSION")))) *cp = 0; + if (!strncasecmp(model,"PENTAX",6)) + strcpy (make, "Pentax"); cp = make + strlen(make); /* Remove trailing spaces */ while (*--cp == ' ') *cp = 0; cp = model + strlen(model); @@ -7444,6 +8705,8 @@ void CLASS identify() { left_margin = 10; width = 4950; filters = 0x16161616; } if (width == 4736 && !strcmp(model,"K-7")) { height = 3122; width = 4684; filters = 0x16161616; top_margin = 2; } + if (width == 6080 && !strcmp(model,"K-3")) + { left_margin = 4; width = 6040; } if (width == 7424 && !strcmp(model,"645D")) { height = 5502; width = 7328; filters = 0x61616161; top_margin = 29; left_margin = 48; } @@ -7451,48 +8714,88 @@ void CLASS identify() width = 4014; if (dng_version) { if (filters == UINT_MAX) filters = 0; - if (filters) is_raw = tiff_samples; - else colors = tiff_samples; - if (tiff_compress == 1) - load_raw = &CLASS packed_dng_load_raw; - if (tiff_compress == 7) - load_raw = &CLASS lossless_dng_load_raw; + if (filters) is_raw *= tiff_samples; + else colors = tiff_samples; + switch (tiff_compress) { + case 0: + case 1: load_raw = &CLASS packed_dng_load_raw; break; + case 7: load_raw = &CLASS lossless_dng_load_raw; break; + case 34892: load_raw = &CLASS lossy_dng_load_raw; break; + default: load_raw = 0; + } goto dng_skip; } - if ((is_canon = !strcmp(make,"Canon"))) - load_raw = memcmp (head+6,"HEAPCCDR",8) ? - &CLASS lossless_jpeg_load_raw : &CLASS canon_load_raw; - if (!strcmp(make,"NIKON")) { + if (!strcmp(make,"Canon") && !fsize && tiff_bps != 15) { + if (!load_raw) + load_raw = &CLASS lossless_jpeg_load_raw; + for (i=0; i < sizeof canon / sizeof *canon; i++) + if (raw_width == canon[i][0] && raw_height == canon[i][1]) { + width = raw_width - (left_margin = canon[i][2]); + height = raw_height - (top_margin = canon[i][3]); + width -= canon[i][4]; + height -= canon[i][5]; + mask[0][1] = canon[i][6]; + mask[0][3] = -canon[i][7]; + mask[1][1] = canon[i][8]; + mask[1][3] = -canon[i][9]; + if (canon[i][10]) filters = canon[i][10] * 0x01010101; + } + if ((unique_id | 0x20000) == 0x2720000) { + left_margin = 8; + top_margin = 16; + } + } + for (i=0; i < sizeof unique / sizeof *unique; i++) + if (unique_id == 0x80000000 + unique[i].id) { + adobe_coeff ("Canon", unique[i].model); + if (model[4] == 'K' && strlen(model) == 8) + strcpy (model, unique[i].model); + } + for (i=0; i < sizeof sonique / sizeof *sonique; i++) + if (unique_id == sonique[i].id) + strcpy (model, sonique[i].model); + if (!strcmp(make,"Nikon")) { if (!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_load_raw; - maximum = 0xf7f; - } /* Set parameters based on camera name (for non-DNG files). */ + if (!strcmp(model,"KAI-0340") + && find_green (16, 16, 3840, 5120) < 25) { + height = 480; + top_margin = filters = 0; + strcpy (model,"C603"); + } + if (!strcmp(make,"Sony") && raw_width > 3888) + black = 128 << (tiff_bps - 12); if (is_foveon) { if (height*2 < width) pixel_aspect = 0.5; if (height > width) pixel_aspect = 2; filters = 0; simple_coeff(0); - } else if (is_canon && tiff_bps == 15) { + } else if (!strcmp(make,"Canon") && tiff_bps == 15) { switch (width) { case 3344: width -= 66; case 3872: width -= 6; } - if (height > width) SWAP(height,width); + if (height > width) { + SWAP(height,width); + SWAP(raw_height,raw_width); + } + if (width == 7200 && height == 3888) { + raw_width = width = 6480; + raw_height = height = 4320; + } filters = 0; + tiff_samples = colors = 3; load_raw = &CLASS canon_sraw_load_raw; } else if (!strcmp(model,"PowerShot 600")) { height = 613; width = 854; raw_width = 896; - pixel_aspect = 607/628.0; colors = 4; filters = 0xe1e4e1e4; load_raw = &CLASS canon_600_load_raw; @@ -7502,362 +8805,34 @@ void CLASS identify() width = 960; raw_width = 992; pixel_aspect = 256/235.0; - colors = 4; filters = 0x1e4e1e4e; goto canon_a5; } else if (!strcmp(model,"PowerShot A50")) { height = 968; width = 1290; raw_width = 1320; - colors = 4; filters = 0x1b4e4b1e; goto canon_a5; } else if (!strcmp(model,"PowerShot Pro70")) { height = 1024; width = 1552; - colors = 4; filters = 0x1e4b4e1b; - goto canon_a5; - } else if (!strcmp(model,"PowerShot SD300")) { - height = 1752; - width = 2344; - raw_height = 1766; - raw_width = 2400; - top_margin = 12; - left_margin = 12; - goto canon_a5; - } else if (!strcmp(model,"PowerShot A460")) { - height = 1960; - width = 2616; - raw_height = 1968; - raw_width = 2664; - top_margin = 4; - left_margin = 4; - goto canon_a5; - } else if (!strcmp(model,"PowerShot A530")) { - height = 1984; - width = 2620; - raw_height = 1992; - raw_width = 2672; - top_margin = 6; - left_margin = 10; - goto canon_a5; - } else if (!strcmp(model,"PowerShot A610")) { - if (canon_s2is()) strcpy (model+10, "S2 IS"); - height = 1960; - width = 2616; - raw_height = 1968; - raw_width = 2672; - top_margin = 8; - left_margin = 12; - goto canon_a5; - } else if (!strcmp(model,"PowerShot A620")) { - height = 2328; - width = 3112; - raw_height = 2340; - raw_width = 3152; - top_margin = 12; - left_margin = 36; - 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 IS")) { - height = 2472; - width = 3298; - raw_height = 2480; - raw_width = 3336; - top_margin = 5; - left_margin = 6; - goto canon_a5; - } else if (!strcmp(model,"PowerShot A630")) { - height = 2472; - width = 3288; - raw_height = 2484; - raw_width = 3344; - top_margin = 6; - left_margin = 12; - goto canon_a5; - } else if (!strcmp(model,"PowerShot A640")) { - height = 2760; - width = 3672; - raw_height = 2772; - raw_width = 3736; - top_margin = 6; - left_margin = 12; - goto canon_a5; - } else if (!strcmp(model,"PowerShot A650")) { - height = 3024; - width = 4032; - raw_height = 3048; - raw_width = 4104; - top_margin = 12; - left_margin = 48; - goto canon_a5; - } else if (!strcmp(model,"PowerShot S3 IS")) { - height = 2128; - width = 2840; - raw_height = 2136; - raw_width = 2888; - top_margin = 8; - left_margin = 44; canon_a5: + colors = 4; 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 SX120 IS")) { - height = 2742; - width = 3664; - raw_height = 2778; - raw_width = 3728; - top_margin = 18; - left_margin = 16; - filters = 0x49494949; - load_raw = &CLASS packed_load_raw; - load_flags = 40; - zero_is_bad = 1; - } else if (!strcmp(model,"PowerShot SX20 IS")) { - height = 3024; - width = 4032; - raw_height = 3048; - raw_width = 4080; - top_margin = 12; - left_margin = 24; - load_raw = &CLASS packed_load_raw; - load_flags = 40; - zero_is_bad = 1; - } else if (!strcmp(model,"PowerShot SX220 HS")) { - height = 3043; - width = 4072; - raw_height = 3060; - raw_width = 4168; - mask[0][0] = top_margin = 16; - mask[0][2] = top_margin + height; - mask[0][3] = left_margin = 92; - load_raw = &CLASS packed_load_raw; - load_flags = 8; - zero_is_bad = 1; - } else if (!strcmp(model,"PowerShot SX30 IS")) { - height = 3254; - width = 4366; - raw_height = 3276; - raw_width = 4464; - top_margin = 10; - left_margin = 25; - filters = 0x16161616; - load_raw = &CLASS packed_load_raw; - load_flags = 40; - zero_is_bad = 1; - } else if (!strcmp(model,"PowerShot Pro90 IS")) { - width = 1896; + } else if (!strcmp(model,"PowerShot Pro90 IS") || + !strcmp(model,"PowerShot G1")) { colors = 4; filters = 0xb4b4b4b4; - } else if (is_canon && raw_width == 2144) { - height = 1550; - width = 2088; - top_margin = 8; - left_margin = 4; - if (!strcmp(model,"PowerShot G1")) { - colors = 4; - filters = 0xb4b4b4b4; - } - } else if (is_canon && raw_width == 2224) { - height = 1448; - width = 2176; - top_margin = 6; - left_margin = 48; - } else if (is_canon && raw_width == 2376) { - height = 1720; - width = 2312; - top_margin = 6; - left_margin = 12; - } else if (is_canon && raw_width == 2672) { - height = 1960; - width = 2616; - top_margin = 6; - left_margin = 12; - } else if (is_canon && raw_width == 3152) { - height = 2056; - width = 3088; - top_margin = 12; - left_margin = 64; - if (unique_id == 0x80000170) - adobe_coeff ("Canon","EOS 300D"); - } else if (is_canon && raw_width == 3160) { - height = 2328; - width = 3112; - top_margin = 12; - left_margin = 44; - } else if (is_canon && raw_width == 3344) { - height = 2472; - width = 3288; - top_margin = 6; - left_margin = 4; + } else if (!strcmp(model,"PowerShot A610")) { + if (canon_s2is()) strcpy (model+10, "S2 IS"); + } else if (!strcmp(model,"PowerShot SX220 HS")) { + mask[1][3] = -4; } else if (!strcmp(model,"EOS D2000C")) { filters = 0x61616161; black = curve[200]; - } else if (is_canon && raw_width == 3516) { - top_margin = 14; - left_margin = 42; - if (unique_id == 0x80000189) - adobe_coeff ("Canon","EOS 350D"); - goto canon_cr2; - } else if (is_canon && raw_width == 3596) { - 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; - if (unique_id > 0x2720000) { - top_margin = 12; - left_margin = 52; - } - } else if (is_canon && raw_width == 3944) { - height = 2602; - width = 3908; - top_margin = 18; - left_margin = 30; - } else if (is_canon && raw_width == 3948) { - top_margin = 18; - left_margin = 42; - height -= 2; - if (unique_id == 0x80000236) - adobe_coeff ("Canon","EOS 400D"); - if (unique_id == 0x80000254) - adobe_coeff ("Canon","EOS 1000D"); - goto canon_cr2; - } else if (is_canon && raw_width == 3984) { - top_margin = 20; - left_margin = 76; - height -= 2; - goto canon_cr2; - } else if (is_canon && raw_width == 4104) { - height = 3024; - 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 == 4160) { - height = 3048; - width = 4048; - top_margin = 11; - left_margin = 104; - } else if (is_canon && raw_width == 4176) { - height = 3045; - width = 4072; - left_margin = 96; - mask[0][0] = top_margin = 17; - mask[0][2] = raw_height; - mask[0][3] = 80; - filters = 0x49494949; - } else if (is_canon && raw_width == 4312) { - top_margin = 18; - left_margin = 22; - height -= 2; - if (unique_id == 0x80000176) - adobe_coeff ("Canon","EOS 450D"); - goto canon_cr2; - } else if (is_canon && raw_width == 4352) { - top_margin = 18; - left_margin = 62; - if (unique_id == 0x80000288) - adobe_coeff ("Canon","EOS 1100D"); - goto canon_cr2; - } else if (is_canon && raw_width == 4476) { - top_margin = 34; - left_margin = 90; - goto canon_cr2; - } else if (is_canon && raw_width == 4480) { - height = 3326; - width = 4432; - top_margin = 10; - left_margin = 12; - filters = 0x49494949; - } else if (is_canon && raw_width == 4496) { - height = 3316; - width = 4404; - top_margin = 50; - left_margin = 80; - } else if (is_canon && raw_width == 4832) { - top_margin = unique_id == 0x80000261 ? 51:26; - left_margin = 62; - if (unique_id == 0x80000252) - adobe_coeff ("Canon","EOS 500D"); - goto canon_cr2; - } else if (is_canon && raw_width == 5108) { - top_margin = 13; - left_margin = 98; - goto canon_cr2; - } else if (is_canon && raw_width == 5120) { - height -= top_margin = 45; - left_margin = 142; - width = 4916; - } else if (is_canon && raw_width == 5280) { - top_margin = 52; - left_margin = 72; - if (unique_id == 0x80000301) - adobe_coeff ("Canon","EOS 650D"); - goto canon_cr2; - } else if (is_canon && raw_width == 5344) { - top_margin = 51; - left_margin = 142; - if (unique_id == 0x80000269) { - top_margin = 100; - left_margin = 126; - height -= 2; - adobe_coeff ("Canon","EOS-1D X"); - } - if (unique_id == 0x80000270) - adobe_coeff ("Canon","EOS 550D"); - if (unique_id == 0x80000286) - adobe_coeff ("Canon","EOS 600D"); - goto canon_cr2; - } else if (is_canon && raw_width == 5360) { - top_margin = 51; - left_margin = 158; - goto canon_cr2; - } else if (is_canon && raw_width == 5568) { - top_margin = 38; - left_margin = 72; - goto canon_cr2; - } else if (is_canon && raw_width == 5712) { - height = 3752; - width = 5640; - top_margin = 20; - left_margin = 62; - } else if (is_canon && raw_width == 5792) { - top_margin = 51; - left_margin = 158; -canon_cr2: - height -= top_margin; - width -= left_margin; - } else if (is_canon && raw_width == 5920) { - height = 3870; - width = 5796; - top_margin = 80; - left_margin = 122; } else if (!strcmp(model,"D1")) { cam_mul[0] *= 256/527.0; cam_mul[2] *= 256/317.0; @@ -7882,13 +8857,15 @@ canon_cr2: !strcmp(model,"D90")) { width -= 42; } else if (!strcmp(model,"D5100") || - !strcmp(model,"D7000")) { + !strcmp(model,"D7000") || + !strcmp(model,"COOLPIX A")) { width -= 44; } else if (!strcmp(model,"D3200") || - !strcmp(model,"D600") || - !strcmp(model,"D800")) { + !strncmp(model,"D6",2) || + !strncmp(model,"D800",4)) { width -= 46; - } else if (!strcmp(model,"D4")) { + } else if (!strcmp(model,"D4") || + !strcmp(model,"Df")) { width -= 52; left_margin = 2; } else if (!strncmp(model,"D40",3) || @@ -7910,9 +8887,7 @@ canon_cr2: else width -= 8; } else if (!strncmp(model,"D300",4)) { width -= 32; - } else if (!strcmp(make,"NIKON") && raw_width == 4032) { - adobe_coeff ("NIKON","COOLPIX P7700"); - } else if (!strncmp(model,"COOLPIX P",9)) { + } else if (!strncmp(model,"COOLPIX P",9) && raw_width != 4032) { load_flags = 24; filters = 0x94949494; if (model[9] == '7' && iso_speed >= 400) @@ -7920,35 +8895,14 @@ canon_cr2: } else if (!strncmp(model,"1 ",2)) { height -= 2; } else if (fsize == 1581060) { - height = 963; - width = 1287; - raw_width = 1632; - maximum = 0x3f4; - colors = 4; - filters = 0x1e1e1e1e; simple_coeff(3); 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; - colors = 4; - filters = 0x4b4b4b4b; - adobe_coeff ("NIKON","E950"); -e900: - tiff_bps = 10; - load_raw = &CLASS packed_load_raw; - load_flags = 6; + } else if (fsize == 3178560) { + cam_mul[0] *= 4; + cam_mul[2] *= 4; } else if (fsize == 4771840) { - height = 1540; - width = 2064; - colors = 4; - filters = 0xe1e1e1e1; - load_raw = &CLASS packed_load_raw; - load_flags = 6; if (!timestamp && nikon_e995()) strcpy (model, "E995"); if (strcmp(model,"E995")) { @@ -7958,23 +8912,16 @@ e900: pre_mul[1] = 1.246; pre_mul[2] = 1.018; } - } else if (!strcmp(model,"E2100")) { - if (!timestamp && !nikon_e2100()) goto cp_e2500; - height = 1206; - width = 1616; - load_flags = 30; - } else if (!strcmp(model,"E2500")) { -cp_e2500: - strcpy (model, "E2500"); - height = 1204; - width = 1616; - colors = 4; - filters = 0x4b4b4b4b; + } else if (fsize == 2940928) { + if (!timestamp && !nikon_e2100()) + strcpy (model,"E2500"); + if (!strcmp(model,"E2500")) { + height -= 2; + load_flags = 6; + colors = 4; + filters = 0x4b4b4b4b; + } } else if (fsize == 4775936) { - height = 1542; - width = 2064; - load_raw = &CLASS packed_load_raw; - load_flags = 30; if (!timestamp) nikon_3700(); if (model[0] == 'E' && atoi(model+1) < 3700) filters = 0x49494949; @@ -7992,32 +8939,21 @@ cp_e2500: if (i < 0) filters = 0x61616161; } } else if (fsize == 5869568) { - height = 1710; - width = 2288; - filters = 0x16161616; if (!timestamp && minolta_z2()) { strcpy (make, "Minolta"); strcpy (model,"DiMAGE Z2"); } - load_raw = &CLASS packed_load_raw; load_flags = 6 + 24*(make[0] == 'M'); - } else if (!strcmp(model,"E4500")) { - height = 1708; - width = 2288; - colors = 4; - filters = 0xb4b4b4b4; - } else if (fsize == 7438336) { - height = 1924; - width = 2576; - colors = 4; - filters = 0xb4b4b4b4; - } else if (fsize == 8998912) { - height = 2118; - width = 2832; - maximum = 0xf83; - load_raw = &CLASS packed_load_raw; - load_flags = 30; - } else if (!strcmp(make,"FUJIFILM")) { + } else if (fsize == 6291456) { + fseek (ifp, 0x300000, SEEK_SET); + if ((order = guess_byte_order(0x10000)) == 0x4d4d) { + height -= (top_margin = 16); + width -= (left_margin = 28); + maximum = 0xf5c0; + strcpy (make, "ISG"); + model[0] = 0; + } + } else if (!strcmp(make,"Fujifilm")) { if (!strcmp(model+7,"S2Pro")) { strcpy (model,"S2Pro"); height = 2144; @@ -8027,22 +8963,20 @@ cp_e2500: maximum = (is_raw == 2 && shot_select) ? 0x2f00 : 0x3e00; top_margin = (raw_height - height) >> 2 << 1; left_margin = (raw_width - width ) >> 2 << 1; - if (width == 2848) filters = 0x16161616; - if (width == 3328) { - width = 3262; - left_margin = 34; - } - if (width == 4952) { + if (width == 2848 || width == 3664) filters = 0x16161616; + if (width == 4032 || width == 4952 || width == 6032) left_margin = 0; + if (width == 3328 && (width -= 66)) left_margin = 34; + if (width == 4936) left_margin = 4; + if (!strcmp(model,"HS50EXR") || + !strcmp(model,"F900EXR")) { + width += 2; left_margin = 0; - filters = 2; + filters = 0x16161616; } if (fuji_layout) raw_width *= is_raw; - } else if (!strcmp(model,"RD175")) { - height = 986; - width = 1534; - data_offset = 513; - filters = 0x61616161; - load_raw = &CLASS minolta_rd175_load_raw; + if (filters == 9) + FORC(36) ((char *)xtrans)[c] = + xtrans_abs[(c/6+top_margin) % 6][(c+left_margin) % 6]; } else if (!strcmp(model,"KD-400Z")) { height = 1712; width = 2312; @@ -8050,9 +8984,9 @@ cp_e2500: goto konica_400z; } else if (!strcmp(model,"KD-510Z")) { goto konica_510z; - } else if (!strcasecmp(make,"MINOLTA")) { - load_raw = &CLASS unpacked_load_raw; - maximum = 0xfff; + } else if (!strcasecmp(make,"Minolta")) { + if (!load_raw && (maximum = 0xfff)) + load_raw = &CLASS unpacked_load_raw; if (!strncmp(model,"DiMAGE A",8)) { if (!strcmp(model,"DiMAGE A200")) filters = 0x49494949; @@ -8089,54 +9023,31 @@ konica_400z: data_error = -1; } else if (!strcmp(model,"*ist DS")) { height -= 2; - } else if (!strcmp(model,"Optio S")) { - if (fsize == 3178560) { - height = 1540; - width = 2064; - load_raw = &CLASS eight_bit_load_raw; - cam_mul[0] *= 4; - cam_mul[2] *= 4; - } else { - height = 1544; - width = 2068; - raw_width = 3136; - load_raw = &CLASS packed_load_raw; - maximum = 0xf7c; - } - } else if (fsize == 6114240) { - height = 1737; - width = 2324; - raw_width = 3520; - load_raw = &CLASS packed_load_raw; - maximum = 0xf7a; - } else if (!strcmp(model,"Optio 750Z")) { - height = 2302; - width = 3072; - 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; - } else if (!strcmp(make,"SAMSUNG") && raw_width == 4704) { + } else if (!strcmp(make,"Samsung") && raw_width == 4704) { height -= top_margin = 8; width -= 2 * (left_margin = 8); load_flags = 32; - } else if (!strcmp(make,"SAMSUNG") && raw_width == 5632) { + } else if (!strcmp(make,"Samsung") && raw_height == 3714) { + height -= top_margin = 18; + left_margin = raw_width - (width = 5536); + if (raw_width != 5600) + left_margin = top_margin = 0; + filters = 0x61616161; + colors = 3; + } else if (!strcmp(make,"Samsung") && raw_width == 5632) { order = 0x4949; height = 3694; top_margin = 2; width = 5574 - (left_margin = 32 + tiff_bps); if (tiff_bps == 12) load_flags = 80; + } else if (!strcmp(make,"Samsung") && raw_width == 5664) { + height -= top_margin = 17; + left_margin = 96; + width = 5544; + filters = 0x49494949; + } else if (!strcmp(make,"Samsung") && raw_width == 6496) { + filters = 0x61616161; + black = 1 << (tiff_bps - 7); } else if (!strcmp(model,"EX1")) { order = 0x4949; height -= 20; @@ -8155,19 +9066,8 @@ konica_400z: width -= 56; top_margin = 8; } - } else if (fsize == 20487168) { - height = 2808; - width = 3648; - goto wb550; - } else if (fsize == 24000000) { - height = 3000; - width = 4000; -wb550: + } else if (strstr(model,"WB550")) { strcpy (model, "WB550"); - order = 0x4d4d; - load_raw = &CLASS unpacked_load_raw; - load_flags = 6; - maximum = 0x3df; } else if (!strcmp(model,"EX2F")) { height = 3045; width = 4070; @@ -8176,85 +9076,11 @@ wb550: filters = 0x49494949; load_raw = &CLASS unpacked_load_raw; } else if (!strcmp(model,"STV680 VGA")) { - height = 484; - width = 644; - load_raw = &CLASS eight_bit_load_raw; - flip = 2; - filters = 0x16161616; black = 16; } else if (!strcmp(model,"N95")) { height = raw_height - (top_margin = 2); - } else if (!strcmp(model,"531C")) { - height = 1200; - width = 1600; - load_raw = &CLASS unpacked_load_raw; - filters = 0x49494949; } else if (!strcmp(model,"640x480")) { - height = 480; - width = 640; - load_raw = &CLASS eight_bit_load_raw; gamma_curve (0.45, 4.5, 1, 255); - } else if (!strcmp(model,"F-080C")) { - height = 768; - width = 1024; - load_raw = &CLASS eight_bit_load_raw; - } else if (!strcmp(model,"F-145C")) { - height = 1040; - width = 1392; - load_raw = &CLASS eight_bit_load_raw; - } else if (!strcmp(model,"F-201C")) { - height = 1200; - width = 1600; - load_raw = &CLASS eight_bit_load_raw; - } else if (!strcmp(model,"F-510C")) { - height = 1958; - width = 2588; - load_raw = fsize < 7500000 ? - &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw; - data_offset = fsize - width*height*(fsize >> 22); - maximum = 0xfff0; - } else if (!strcmp(model,"F-810C")) { - height = 2469; - width = 3272; - load_raw = &CLASS unpacked_load_raw; - maximum = 0xfff0; - } else if (!strcmp(model,"XCD-SX910CR")) { - height = 1024; - width = 1375; - raw_width = 1376; - filters = 0x49494949; - maximum = 0x3ff; - load_raw = fsize < 2000000 ? - &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw; - } else if (!strcmp(model,"2010")) { - height = 1207; - width = 1608; - order = 0x4949; - filters = 0x16161616; - data_offset = 3212; - maximum = 0x3ff; - load_raw = &CLASS unpacked_load_raw; - } else if (!strcmp(model,"A782")) { - height = 3000; - width = 2208; - filters = 0x61616161; - load_raw = fsize < 10000000 ? - &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw; - maximum = 0xffc0; - } else if (!strcmp(model,"3320AF")) { - height = 1536; - raw_width = width = 2048; - filters = 0x61616161; - load_raw = &CLASS unpacked_load_raw; - maximum = 0x3ff; - fseek (ifp, 0x300000, SEEK_SET); - if ((order = guess_byte_order(0x10000)) == 0x4d4d) { - height -= (top_margin = 16); - width -= (left_margin = 28); - maximum = 0xf5c0; - strcpy (make, "ISG"); - model[0] = 0; - } } else if (!strcmp(make,"Hasselblad")) { if (load_raw == &CLASS lossless_jpeg_load_raw) load_raw = &CLASS hasselblad_load_raw; @@ -8264,9 +9090,9 @@ wb550: top_margin = 4; left_margin = 7; filters = 0x61616161; - } else if (raw_width == 7410) { - height = 5502; - width = 7328; + } else if (raw_width == 7410 || raw_width == 8282) { + height -= 84; + width -= 82; top_margin = 4; left_margin = 41; filters = 0x61616161; @@ -8283,15 +9109,13 @@ wb550: width -= (left_margin = 3) + 7; filters = 0x61616161; } - } else if (!strcmp(make,"Sinar")) { - if (!memcmp(head,"8BPS",4)) { - fseek (ifp, 14, SEEK_SET); - height = get4(); - width = get4(); - filters = 0x61616161; - data_offset = 68; + if (tiff_samples > 1) { + is_raw = tiff_samples+1; + if (!shot_select && !half_size) filters = 0; } + } else if (!strcmp(make,"Sinar")) { if (!load_raw) load_raw = &CLASS unpacked_load_raw; + if (is_raw > 1 && !shot_select && !half_size) filters = 0; maximum = 0x3fff; } else if (!strcmp(make,"Leaf")) { maximum = 0x3fff; @@ -8335,7 +9159,7 @@ wb550: width -= 2 * (left_margin = 24); filters = 0x16161616; } - } else if (!strcmp(make,"LEICA") || !strcmp(make,"Panasonic")) { + } else if (!strcmp(make,"Leica") || !strcmp(make,"Panasonic")) { if ((flen - data_offset) / (raw_width*8/7) == raw_height) load_raw = &CLASS panasonic_load_raw; if (!load_raw) { @@ -8359,11 +9183,12 @@ wb550: filters = 0x16161616; load_raw = &CLASS packed_load_raw; load_flags = 30; - } else if (!strcmp(make,"OLYMPUS")) { + } else if (!strcmp(make,"Olympus")) { height += height & 1; - filters = exif_cfa; + if (exif_cfa) filters = exif_cfa; if (width == 4100) width -= 4; if (width == 4080) width -= 24; + if (width == 9280) { width -= 6; height -= 6; } if (load_raw == &CLASS unpacked_load_raw) load_flags = 4; tiff_bps = 12; @@ -8382,9 +9207,8 @@ wb550: thumb_length = flen - (thumb_offset = 0xa39800); thumb_height = 480; thumb_width = 640; - } else if (!strcmp(model,"XZ-2")) { - load_raw = &CLASS packed_load_raw; - load_flags = 24; + } else if (!strcmp(model,"TG-4")) { + width -= 16; } } else if (!strcmp(model,"N Digital")) { height = 2047; @@ -8407,95 +9231,78 @@ wb550: mask[0][1] = 9; data_offset = 787392; load_raw = &CLASS sony_load_raw; - } else if (!strcmp(make,"SONY") && raw_width == 3984) { - adobe_coeff ("SONY","DSC-R1"); + } else if (!strcmp(make,"Sony") && raw_width == 3984) { width = 3925; order = 0x4d4d; - } else if (!strcmp(make,"SONY") && raw_width == 5504) { - width -= 8; - } else if (!strcmp(make,"SONY") && raw_width == 6048) { + } else if (!strcmp(make,"Sony") && raw_width == 4288) { + width -= 32; + } else if (!strcmp(make,"Sony") && raw_width == 4600) { + if (!strcmp(model,"DSLR-A350")) + height -= 4; + black = 0; + } else if (!strcmp(make,"Sony") && raw_width == 4928) { + if (height < 3280) width -= 8; + } else if (!strcmp(make,"Sony") && raw_width == 5504) { + width -= height > 3664 ? 8 : 32; + if (!strncmp(model,"DSC",3)) + black = 200 << (tiff_bps - 12); + } else if (!strcmp(make,"Sony") && raw_width == 6048) { width -= 24; + if (strstr(model,"RX1") || strstr(model,"A99")) + width -= 6; + } else if (!strcmp(make,"Sony") && raw_width == 7392) { + width -= 30; + } else if (!strcmp(make,"Sony") && raw_width == 8000) { + width -= 32; + if (!strncmp(model,"DSC",3)) { + tiff_bps = 14; + load_raw = &CLASS unpacked_load_raw; + black = 512; + } } else if (!strcmp(model,"DSLR-A100")) { if (width == 3880) { height--; width = ++raw_width; } else { + height -= 4; + width -= 4; order = 0x4d4d; load_flags = 2; } 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; - if (fsize < 614400 || find_green (16, 16, 3840, 5120) < 25) goto c603v; - strcpy (model,"KAI-0340"); - height -= 3; - data_offset = 3840; + } else if (!strcmp(model,"C603") || !strcmp(model,"C330") + || !strcmp(model,"12MP")) { 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; - goto c603; - } else if (!strcmp(model,"C330")) { - height = 1744; - width = 2336; - raw_height = 1779; - raw_width = 2338; - top_margin = 33; - left_margin = 1; -c603: - order = 0x4949; - if ((data_offset = fsize - raw_height*raw_width)) { - fseek (ifp, 168, SEEK_SET); + if (filters && data_offset) { + fseek (ifp, data_offset < 4096 ? 168 : 5252, SEEK_SET); read_shorts (curve, 256); } else gamma_curve (0, 3.875, 1, 255); - load_raw = &CLASS eight_bit_load_raw; + load_raw = filters ? &CLASS eight_bit_load_raw : + strcmp(model,"C330") ? &CLASS kodak_c603_load_raw : + &CLASS kodak_c330_load_raw; + load_flags = tiff_bps > 16; + tiff_bps = 8; } else if (!strncasecmp(model,"EasyShare",9)) { data_offset = data_offset < 0x15000 ? 0x15000 : 0x17000; load_raw = &CLASS packed_load_raw; - } else if (!strcasecmp(make,"KODAK")) { + } else if (!strcasecmp(make,"Kodak")) { if (filters == UINT_MAX) filters = 0x61616161; - if (!strncmp(model,"NC2000",6)) { - width -= 4; - left_margin = 2; - } else if (!strcmp(model,"EOSDCS3B")) { - width -= 4; - left_margin = 2; - } else if (!strcmp(model,"EOSDCS1")) { - width -= 4; - left_margin = 2; - } else if (!strcmp(model,"DCS420")) { - width -= 4; - left_margin = 2; - } else if (!strncmp(model,"DCS460 ",7)) { - model[6] = 0; - width -= 4; - left_margin = 2; - } else if (!strcmp(model,"DCS460A")) { + if (!strncmp(model,"NC2000",6) || + !strncmp(model,"EOSDCS",6) || + !strncmp(model,"DCS4",4)) { width -= 4; left_margin = 2; - colors = 1; - filters = 0; + if (model[6] == ' ') model[6] = 0; + if (!strcmp(model,"DCS460A")) goto bw; } else if (!strcmp(model,"DCS660M")) { black = 214; - colors = 1; - filters = 0; + goto bw; } else if (!strcmp(model,"DCS760M")) { - colors = 1; +bw: colors = 1; filters = 0; } if (!strcmp(model+4,"20X")) @@ -8505,7 +9312,7 @@ c603: data_offset = 15424; } if (!strncmp(model,"DC2",3)) { - raw_height = height = 242; + raw_height = 2 + (height = 242); if (flen < 100000) { raw_width = 256; width = 249; pixel_aspect = (4.0*height) / (3.0*width); @@ -8513,7 +9320,7 @@ c603: raw_width = 512; width = 501; pixel_aspect = (493.0*height) / (373.0*width); } - data_offset += raw_width + 1; + top_margin = left_margin = 1; colors = 4; filters = 0x8d8d8d8d; simple_coeff(1); @@ -8527,6 +9334,7 @@ c603: width = 768; data_offset = 1152; load_raw = &CLASS kodak_radc_load_raw; + tiff_bps = 12; } else if (strstr(model,"DC50")) { strcpy (model, "DC50"); height = 512; @@ -8546,10 +9354,6 @@ c603: thumb_offset = 6144; thumb_misc = 360; write_thumb = &CLASS layer_thumb; - height = 1024; - width = 1536; - data_offset = 79872; - load_raw = &CLASS eight_bit_load_raw; black = 17; } } else if (!strcmp(model,"Fotoman Pixtura")) { @@ -8587,118 +9391,10 @@ c603: } filters = 0x16161616; load_raw = &CLASS rollei_load_raw; - } else if (!strcmp(model,"PC-CAM 600")) { - height = 768; - data_offset = width = 1024; - filters = 0x49494949; - load_raw = &CLASS eight_bit_load_raw; - } else if (!strcmp(model,"QV-2000UX")) { - height = 1208; - width = 1632; - data_offset = width * 2; - load_raw = &CLASS eight_bit_load_raw; - } else if (fsize == 3217760) { - height = 1546; - width = 2070; - raw_width = 2080; - load_raw = &CLASS eight_bit_load_raw; - } else if (!strcmp(model,"QV-4000")) { - height = 1700; - width = 2260; - load_raw = &CLASS unpacked_load_raw; - maximum = 0xffff; - } else if (!strcmp(model,"QV-5700")) { - height = 1924; - width = 2576; - raw_width = 3232; - tiff_bps = 10; - } else if (!strcmp(model,"QV-R41")) { - height = 1720; - width = 2312; - raw_width = 3520; - left_margin = 2; - } else if (!strcmp(model,"QV-R51")) { - height = 1926; - width = 2580; - raw_width = 3904; - } 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; - } else if (!strcmp(model,"EX-Z50")) { - height = 1931; - width = 2570; - raw_width = 3904; - } else if (!strcmp(model,"EX-Z500")) { - height = 1937; - width = 2577; - raw_width = 3904; - filters = 0x16161616; - } else if (!strcmp(model,"EX-Z55")) { - height = 1960; - width = 2570; - raw_width = 3904; - } 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-Z750")) { - height = 2319; - width = 3087; - 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-Z8")) { - height = 2467; - width = 3281; - raw_height = 2502; - raw_width = 4992; - maximum = 0xfff; - } else if (fsize == 15499264) { /* EX-Z1050 or EX-Z1080 */ - height = 2752; - width = 3672; - raw_width = 5632; - } else if (!strcmp(model,"EX-ZR100")) { - height = 3044; - width = 4072; - raw_width = 4096; - load_flags = 80; - } else if (!strcmp(model,"EX-P505")) { - height = 1928; - width = 2568; - raw_width = 3852; - maximum = 0xfff; - } else if (fsize == 9313536) { /* EX-P600 or QV-R61 */ - height = 2142; - width = 2844; - raw_width = 4288; - } else if (!strcmp(model,"EX-P700")) { - height = 2318; - width = 3082; - raw_width = 4672; } 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)) { @@ -8707,9 +9403,17 @@ c603: } } dng_skip: + if ((use_camera_matrix & (use_camera_wb || dng_version)) + && cmatrix[0][0] > 0.125) { + memcpy (rgb_cam, cmatrix, sizeof cmatrix); + raw_color = 0; + } + if (raw_color) adobe_coeff (make, model); + if (load_raw == &CLASS kodak_radc_load_raw) + if (raw_color) adobe_coeff ("Apple","Quicktake"); if (fuji_width) { fuji_width = width >> !fuji_layout; - if (~fuji_width & 1) filters = 0x49494949; + filters = fuji_width & 1 ? 0x94949494 : 0x49494949; width = (height >> fuji_layout) + fuji_width; height = width - 1; pixel_aspect = 1; @@ -8719,7 +9423,9 @@ dng_skip: } if (!tiff_bps) tiff_bps = 12; if (!maximum) maximum = (1 << tiff_bps) - 1; - if (!load_raw || height < 22) is_raw = 0; + if (!load_raw || height < 22 || width < 22 || + tiff_bps > 16 || tiff_samples > 6 || colors > 4) + is_raw = 0; #ifdef NO_JASPER if (load_raw == &CLASS redcine_load_raw) { fprintf (stderr,_("%s: You must link dcraw with %s!!\n"), @@ -8739,21 +9445,18 @@ dng_skip: strcpy (cdesc, colors == 3 ? "RGBG":"GMCY"); if (!raw_height) raw_height = height; if (!raw_width ) raw_width = width; - if (filters && colors == 3) + if (filters > 999 && colors == 3) filters |= ((filters >> 2 & 0x22222222) | (filters << 2 & 0x88888888)) & filters << 1; notraw: - if (flip == -1) flip = tiff_flip; - if (flip == -1) flip = 0; - - - + if (flip == UINT_MAX) flip = tiff_flip; + if (flip == UINT_MAX) flip = 0; // CINELERRA if (flip & 4) - sprintf(dcraw_info, "%d %d", height, width); + sprintf(dcraw_info, "%d %d", height, width); else - sprintf(dcraw_info, "%d %d", width, height); + sprintf(dcraw_info, "%d %d", width, height); } #ifndef NO_LCMS @@ -8765,7 +9468,6 @@ void CLASS apply_profile (const char *input, const char *output) FILE *fp; unsigned size; - cmsErrorAction (LCMS_ERROR_SHOW); if (strcmp (input, "embed")) hInProfile = cmsOpenProfileFromFile (input, "r"); else if (profile_length) { @@ -8831,10 +9533,14 @@ void CLASS convert_to_rgb() { { 0.529317, 0.330092, 0.140588 }, { 0.098368, 0.873465, 0.028169 }, { 0.016879, 0.117663, 0.865457 } }; + static const double aces_rgb[3][3] = + { { 0.432996, 0.375380, 0.189317 }, + { 0.089427, 0.816523, 0.102989 }, + { 0.019165, 0.118150, 0.941914 } }; static const double (*out_rgb[])[3] = - { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb }; + { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb, aces_rgb }; static const char *name[] = - { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ" }; + { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ", "ACES" }; static const unsigned phead[] = { 1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, 0, 0, 0x61637370, 0, 0, 0x6e6f6e65, 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d }; @@ -8855,7 +9561,7 @@ void CLASS convert_to_rgb() 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; + output_color < 1 || output_color > 6; if (!raw_color) { oprof = (unsigned *) calloc (phead[0], 1); merror (oprof, "convert_to_rgb()"); @@ -8912,18 +9618,15 @@ void CLASS convert_to_rgb() if (colors == 4 && output_color) colors = 3; if (document_mode && filters) colors = 1; - - - // CINELERRA // Export color matrix to Cinelerra. // It can't be applied before interpolation. -k = 0; -for(i = 0; i < 3; i++) -{ - for(j = 0; j < 3; j++) - dcraw_matrix[k++] = rgb_cam[i][j]; -} + k = 0; + for(i = 0; i < 3; i++) { + for(j = 0; j < 3; j++) + dcraw_matrix[k++] = rgb_cam[i][j]; + } + } void CLASS fuji_rotate() @@ -8941,7 +9644,7 @@ void CLASS fuji_rotate() step = sqrt(0.5); wide = fuji_width / step; high = (height - fuji_width) / step; - img = (ushort (*)[4]) calloc (wide*high, sizeof *img); + img = (ushort (*)[4]) calloc (high, wide*sizeof *img); merror (img, "fuji_rotate()"); for (row=0; row < high; row++) @@ -8974,7 +9677,7 @@ void CLASS stretch() if (verbose) fprintf (stderr,_("Stretching the image...\n")); if (pixel_aspect < 1) { newdim = height / pixel_aspect + 0.5; - img = (ushort (*)[4]) calloc (width*newdim, sizeof *img); + img = (ushort (*)[4]) calloc (width, newdim*sizeof *img); merror (img, "stretch()"); for (rc=row=0; row < newdim; row++, rc+=pixel_aspect) { frac = rc - (c = rc); @@ -8986,7 +9689,7 @@ void CLASS stretch() height = newdim; } else { newdim = width * pixel_aspect + 0.5; - img = (ushort (*)[4]) calloc (height*newdim, sizeof *img); + img = (ushort (*)[4]) calloc (height, newdim*sizeof *img); merror (img, "stretch()"); for (rc=col=0; col < newdim; col++, rc+=1/pixel_aspect) { frac = rc - (c = rc); @@ -9031,21 +9734,25 @@ struct tiff_hdr { char desc[512], make[64], model[64], soft[32], date[20], artist[64]; }; -void CLASS tiff_set (ushort *ntag, +void CLASS tiff_set (struct tiff_hdr *th, ushort *ntag, ushort tag, ushort type, int count, int val) { struct tiff_tag *tt; int c; tt = (struct tiff_tag *)(ntag+1) + (*ntag)++; - tt->tag = tag; - tt->type = type; - tt->count = count; - if (type < 3 && count <= 4) + tt->val.i = val; + if (type == 1 && count <= 4) FORC(4) tt->val.c[c] = val >> (c << 3); - else if (type == 3 && count <= 2) + else if (type == 2) { + count = strnlen((char *)th + val, count-1) + 1; + if (count <= 4) + FORC(4) tt->val.c[c] = ((char *)th)[val+c]; + } else if (type == 3 && count <= 2) FORC(2) tt->val.s[c] = val >> (c << 4); - else tt->val.i = val; + tt->count = count; + tt->type = type; + tt->tag = tag; } #define TOFF(ptr) ((char *)(&(ptr)) - (char *)th) @@ -9059,55 +9766,6 @@ void CLASS tiff_head (struct tiff_hdr *th, int full) th->order = htonl(0x4d4d4949) >> 16; th->magic = 42; th->ifd = 10; - if (full) { - tiff_set (&th->ntag, 254, 4, 1, 0); - tiff_set (&th->ntag, 256, 4, 1, width); - tiff_set (&th->ntag, 257, 4, 1, height); - tiff_set (&th->ntag, 258, 3, colors, output_bps); - if (colors > 2) - th->tag[th->ntag-1].val.i = TOFF(th->bps); - FORC4 th->bps[c] = output_bps; - tiff_set (&th->ntag, 259, 3, 1, 1); - tiff_set (&th->ntag, 262, 3, 1, 1 + (colors > 1)); - } - tiff_set (&th->ntag, 270, 2, 512, TOFF(th->desc)); - tiff_set (&th->ntag, 271, 2, 64, TOFF(th->make)); - tiff_set (&th->ntag, 272, 2, 64, TOFF(th->model)); - if (full) { - if (oprof) psize = ntohl(oprof[0]); - tiff_set (&th->ntag, 273, 4, 1, sizeof *th + psize); - tiff_set (&th->ntag, 277, 3, 1, colors); - tiff_set (&th->ntag, 278, 4, 1, height); - tiff_set (&th->ntag, 279, 4, 1, height*width*colors*output_bps/8); - } else - tiff_set (&th->ntag, 274, 3, 1, "12435867"[flip]-'0'); - tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[0])); - tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[2])); - tiff_set (&th->ntag, 284, 3, 1, 1); - tiff_set (&th->ntag, 296, 3, 1, 2); - tiff_set (&th->ntag, 305, 2, 32, TOFF(th->soft)); - tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date)); - tiff_set (&th->ntag, 315, 2, 64, TOFF(th->artist)); - tiff_set (&th->ntag, 34665, 4, 1, TOFF(th->nexif)); - if (psize) tiff_set (&th->ntag, 34675, 7, psize, sizeof *th); - tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[4])); - tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[6])); - tiff_set (&th->nexif, 34855, 3, 1, iso_speed); - tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[8])); - if (gpsdata[1]) { - tiff_set (&th->ntag, 34853, 4, 1, TOFF(th->ngps)); - tiff_set (&th->ngps, 0, 1, 4, 0x202); - tiff_set (&th->ngps, 1, 2, 2, gpsdata[29]); - tiff_set (&th->ngps, 2, 5, 3, TOFF(th->gps[0])); - tiff_set (&th->ngps, 3, 2, 2, gpsdata[30]); - tiff_set (&th->ngps, 4, 5, 3, TOFF(th->gps[6])); - tiff_set (&th->ngps, 5, 1, 1, gpsdata[31]); - tiff_set (&th->ngps, 6, 5, 1, TOFF(th->gps[18])); - tiff_set (&th->ngps, 7, 5, 3, TOFF(th->gps[12])); - tiff_set (&th->ngps, 18, 2, 12, TOFF(th->gps[20])); - tiff_set (&th->ngps, 29, 2, 12, TOFF(th->gps[23])); - memcpy (th->gps, gpsdata, sizeof th->gps); - } th->rat[0] = th->rat[2] = 300; th->rat[1] = th->rat[3] = 1; FORC(6) th->rat[4+c] = 1000000; @@ -9122,6 +9780,55 @@ void CLASS tiff_head (struct tiff_hdr *th, int full) sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d", t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec); strncpy (th->artist, artist, 64); + if (full) { + tiff_set (th, &th->ntag, 254, 4, 1, 0); + tiff_set (th, &th->ntag, 256, 4, 1, width); + tiff_set (th, &th->ntag, 257, 4, 1, height); + tiff_set (th, &th->ntag, 258, 3, colors, output_bps); + if (colors > 2) + th->tag[th->ntag-1].val.i = TOFF(th->bps); + FORC4 th->bps[c] = output_bps; + tiff_set (th, &th->ntag, 259, 3, 1, 1); + tiff_set (th, &th->ntag, 262, 3, 1, 1 + (colors > 1)); + } + tiff_set (th, &th->ntag, 270, 2, 512, TOFF(th->desc)); + tiff_set (th, &th->ntag, 271, 2, 64, TOFF(th->make)); + tiff_set (th, &th->ntag, 272, 2, 64, TOFF(th->model)); + if (full) { + if (oprof) psize = ntohl(oprof[0]); + tiff_set (th, &th->ntag, 273, 4, 1, sizeof *th + psize); + tiff_set (th, &th->ntag, 277, 3, 1, colors); + tiff_set (th, &th->ntag, 278, 4, 1, height); + tiff_set (th, &th->ntag, 279, 4, 1, height*width*colors*output_bps/8); + } else + tiff_set (th, &th->ntag, 274, 3, 1, "12435867"[flip]-'0'); + tiff_set (th, &th->ntag, 282, 5, 1, TOFF(th->rat[0])); + tiff_set (th, &th->ntag, 283, 5, 1, TOFF(th->rat[2])); + tiff_set (th, &th->ntag, 284, 3, 1, 1); + tiff_set (th, &th->ntag, 296, 3, 1, 2); + tiff_set (th, &th->ntag, 305, 2, 32, TOFF(th->soft)); + tiff_set (th, &th->ntag, 306, 2, 20, TOFF(th->date)); + tiff_set (th, &th->ntag, 315, 2, 64, TOFF(th->artist)); + tiff_set (th, &th->ntag, 34665, 4, 1, TOFF(th->nexif)); + if (psize) tiff_set (th, &th->ntag, 34675, 7, psize, sizeof *th); + tiff_set (th, &th->nexif, 33434, 5, 1, TOFF(th->rat[4])); + tiff_set (th, &th->nexif, 33437, 5, 1, TOFF(th->rat[6])); + tiff_set (th, &th->nexif, 34855, 3, 1, iso_speed); + tiff_set (th, &th->nexif, 37386, 5, 1, TOFF(th->rat[8])); + if (gpsdata[1]) { + tiff_set (th, &th->ntag, 34853, 4, 1, TOFF(th->ngps)); + tiff_set (th, &th->ngps, 0, 1, 4, 0x202); + tiff_set (th, &th->ngps, 1, 2, 2, gpsdata[29]); + tiff_set (th, &th->ngps, 2, 5, 3, TOFF(th->gps[0])); + tiff_set (th, &th->ngps, 3, 2, 2, gpsdata[30]); + tiff_set (th, &th->ngps, 4, 5, 3, TOFF(th->gps[6])); + tiff_set (th, &th->ngps, 5, 1, 1, gpsdata[31]); + tiff_set (th, &th->ngps, 6, 5, 1, TOFF(th->gps[18])); + tiff_set (th, &th->ngps, 7, 5, 3, TOFF(th->gps[12])); + tiff_set (th, &th->ngps, 18, 2, 12, TOFF(th->gps[20])); + tiff_set (th, &th->ngps, 29, 2, 12, TOFF(th->gps[23])); + memcpy (th->gps, gpsdata, sizeof th->gps); + } } void CLASS jpeg_thumb() @@ -9196,11 +9903,6 @@ void CLASS write_ppm_tiff() free (ppm); } - - - - - // CINELERRA void CLASS write_cinelerra (FILE *ofp) { @@ -9240,29 +9942,9 @@ void CLASS write_cinelerra (FILE *ofp) } } - - - - - - - - - - - - // CINELERRA int CLASS dcraw_main (int argc, const char **argv) -//int CLASS main (int argc, const char **argv) { -// CINELERRA -// Globals must be reset - document_mode = 0; - use_camera_wb = 0; - - - int arg, status=0, quality, i, c; int timestamp_only=0, thumbnail_only=0, identify_only=0; int user_qual=-1, user_black=-1, user_sat=-1, user_flip=-1; @@ -9274,6 +9956,9 @@ int CLASS dcraw_main (int argc, const char **argv) const char *cam_profile=0, *out_profile=0; #endif +// CINELERRA + reset(); // Globals must be reset + #ifndef LOCALTIME putenv ((char *) "TZ=UTC"); #endif @@ -9307,7 +9992,7 @@ int CLASS dcraw_main (int argc, const char **argv) puts(_("-n Set threshold for wavelet denoising")); puts(_("-H [0-9] Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)")); puts(_("-t [0-7] Flip image (0=none, 3=180, 5=90CCW, 6=90CW)")); - puts(_("-o [0-5] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ)")); + puts(_("-o [0-6] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ,ACES)")); #ifndef NO_LCMS puts(_("-o Apply output ICC profile from file")); puts(_("-p Apply camera ICC profile from file or \"embed\"")); @@ -9374,12 +10059,12 @@ int CLASS dcraw_main (int argc, const char **argv) case 'i': identify_only = 1; break; case 'c': write_to_stdout = 1; break; case 'v': verbose = 1; break; - case 'h': half_size = 1; /* "-h" implies "-f" */ + case 'h': half_size = 1; break; case 'f': four_color_rgb = 1; break; case 'A': FORC4 greybox[c] = atoi(argv[arg++]); case 'a': use_auto_wb = 1; break; case 'w': use_camera_wb = 1; break; - case 'M': use_camera_matrix = (opm == '+'); break; + case 'M': use_camera_matrix = 3 * (opm == '+'); break; case 'I': read_from_stdin = 1; break; case 'E': document_mode++; case 'D': document_mode++; @@ -9395,16 +10080,13 @@ int CLASS dcraw_main (int argc, const char **argv) return 1; } } - if (use_camera_matrix < 0) - use_camera_matrix = use_camera_wb; if (arg == argc) { fprintf (stderr,_("No files to process.\n")); return 1; } if (write_to_stdout) { // CINELERRA - if (0) { -// if (isatty(1)) { + if (0 && isatty(1)) { fprintf (stderr,_("Will not write an image to the terminal!\n")); return 1; } @@ -9454,15 +10136,9 @@ int CLASS dcraw_main (int argc, const char **argv) } goto next; } - write_fun = &CLASS write_ppm_tiff; - - - // CINELERRA - write_fun = write_cinelerra; - - - +// write_fun = &CLASS write_ppm_tiff; + write_fun = write_cinelerra; if (thumbnail_only) { if ((status = !thumb_offset)) { @@ -9474,6 +10150,7 @@ int CLASS dcraw_main (int argc, const char **argv) height = thumb_height; width = thumb_width; filters = 0; + colors = 3; } else { fseek (ifp, thumb_offset, SEEK_SET); write_fun = write_thumb; @@ -9510,18 +10187,9 @@ int CLASS dcraw_main (int argc, const char **argv) printf (_("Thumb size: %4d x %d\n"), thumb_width, thumb_height); printf (_("Full size: %4d x %d\n"), raw_width, raw_height); } - - - // CINELERRA -// else if (!is_raw) -// fprintf (stderr,_("Cannot decode file %s\n"), ifname); - - - - - - +// else if (!is_raw) +// fprintf (stderr,_("Cannot decode file %s\n"), ifname); if (!is_raw) goto next; shrink = filters && (half_size || (!identify_only && (threshold || aber[0] != 1 || aber[2] != 1))); @@ -9532,9 +10200,7 @@ int CLASS dcraw_main (int argc, const char **argv) if (document_mode == 3) { top_margin = left_margin = fuji_width = 0; height = raw_height; - if (width <= raw_width * 8 / tiff_bps) - width = raw_width * 8 / tiff_bps; - else width = raw_width; + width = raw_width; } iheight = (height + shrink) >> shrink; iwidth = (width + shrink) >> shrink; @@ -9554,9 +10220,15 @@ int CLASS dcraw_main (int argc, const char **argv) printf (_("Output size: %4d x %d\n"), iwidth, iheight); printf (_("Raw colors: %d"), colors); if (filters) { + int fhigh = 2, fwide = 2; + if ((filters ^ (filters >> 8)) & 0xff) fhigh = 4; + if ((filters ^ (filters >> 16)) & 0xffff) fhigh = 8; + if (filters == 1) fhigh = fwide = 16; + if (filters == 9) fhigh = fwide = 6; printf (_("\nFilter pattern: ")); - for (i=0; i < 16; i++) - putchar (cdesc[fcol(i >> 1,i & 1)]); + for (i=0; i < fhigh; i++) + for (c = i && putchar('/') && 0; c < fwide; c++) + putchar (cdesc[fcol(i,c)]); } printf (_("\nDaylight multipliers:")); FORCC printf (" %f", pre_mul[c]); @@ -9565,26 +10237,23 @@ int CLASS dcraw_main (int argc, const char **argv) FORC4 printf (" %f", cam_mul[c]); } putchar ('\n'); - } else + } // CINELERRA +// else // printf (_("%s is a %s %s image.\n"), ifname, make, model); next: fclose(ifp); continue; } - if (use_camera_matrix && cmatrix[0][0] > 0.25) { - memcpy (rgb_cam, cmatrix, sizeof cmatrix); - raw_color = 0; - } if (meta_length) { meta_data = (char *) malloc (meta_length); merror (meta_data, "main()"); } if (filters || colors == 1) { - raw_image = (ushort *) calloc ((raw_height+7)*raw_width, 2); + raw_image = (ushort *) calloc ((raw_height+7), raw_width*2); merror (raw_image, "main()"); } else { - image = (ushort (*)[4]) calloc (iheight*iwidth, sizeof *image); + image = (ushort (*)[4]) calloc (iheight, iwidth*sizeof *image); merror (image, "main()"); } if (verbose) @@ -9600,14 +10269,12 @@ next: if (document_mode == 3) { top_margin = left_margin = fuji_width = 0; height = raw_height; - if (width <= raw_width * 8 / tiff_bps) - width = raw_width * 8 / tiff_bps; - else width = raw_width; + width = raw_width; } iheight = (height + shrink) >> shrink; iwidth = (width + shrink) >> shrink; if (raw_image) { - image = (ushort (*)[4]) calloc (iheight*iwidth, sizeof *image); + image = (ushort (*)[4]) calloc (iheight, iwidth*sizeof *image); merror (image, "main()"); crop_masked_pixels(); free (raw_image); @@ -9621,6 +10288,12 @@ next: FORC3 if (i > cblack[c]) i = cblack[c]; FORC4 cblack[c] -= i; black += i; + i = cblack[6]; + FORC (cblack[4] * cblack[5]) + if (i > cblack[6+c]) i = cblack[6+c]; + FORC (cblack[4] * cblack[5]) + cblack[6+c] -= i; + black += i; if (user_black >= 0) black = user_black; FORC4 cblack[c] += black; if (user_sat > 0) maximum = user_sat; @@ -9638,11 +10311,14 @@ next: if (filters && !document_mode) { if (quality == 0) lin_interpolate(); - else if (quality == 1 || colors > 3 || filters < 1000) + else if (quality == 1 || colors > 3) vng_interpolate(); - else if (quality == 2) + else if (quality == 2 && filters > 1000) ppg_interpolate(); - else ahd_interpolate(); + else if (filters == 9) + xtrans_interpolate (quality*2-3); + else + ahd_interpolate(); } if (mix_green) for (colors=3, i=0; i < height*width; i++) diff --git a/cinelerra-5.1/cinelerra/dcraw.h b/cinelerra-5.1/cinelerra/dcraw.h new file mode 100644 index 00000000..d739dfc0 --- /dev/null +++ b/cinelerra-5.1/cinelerra/dcraw.h @@ -0,0 +1,188 @@ + +/* CINELERRA dcraw.c */ +static int CLASS fcol(int row,int col); +#if 0 +static char *my_memmem(char *haystack,size_t haystacklen,char *needle,size_t needlelen); +static char *my_strcasestr(char *haystack,const char *needle); +#endif +static void CLASS merror(void *ptr,const char *where); +static void CLASS derror(void); +static ushort CLASS sget2(uchar *s); +static ushort CLASS get2(void); +static unsigned CLASS sget4(uchar *s); +static unsigned CLASS get4(void); +static unsigned CLASS getint(int type); +static float CLASS int_to_float(int i); +static double CLASS getreal(int type); +static void CLASS read_shorts(ushort *pixel,int count); +static void CLASS cubic_spline(const int *x_,const int *y_,const int len); +static void CLASS canon_600_fixed_wb(int temp); +static int CLASS canon_600_color(int ratio[2],int mar); +static void CLASS canon_600_auto_wb(void); +static void CLASS canon_600_coeff(void); +static void CLASS canon_600_load_raw(void); +static void CLASS canon_600_correct(void); +static int CLASS canon_s2is(void); +static unsigned CLASS getbithuff(int nbits,ushort *huff); +static ushort *CLASS make_decoder_ref(const uchar **source); +static ushort *CLASS make_decoder(const uchar *source); +static void CLASS crw_init_tables(unsigned table,ushort *huff[2]); +static int CLASS canon_has_lowbits(void); +static void CLASS canon_load_raw(void); +static int CLASS ljpeg_start(struct jhead *jh,int info_only); +static void CLASS ljpeg_end(struct jhead *jh); +static int CLASS ljpeg_diff(ushort *huff); +static ushort *CLASS ljpeg_row(int jrow,struct jhead *jh); +static void CLASS lossless_jpeg_load_raw(void); +static void CLASS canon_sraw_load_raw(void); +static void CLASS adobe_copy_pixel(unsigned row,unsigned col,ushort **rp); +static void CLASS ljpeg_idct(struct jhead *jh); +static void CLASS lossless_dng_load_raw(void); +static void CLASS packed_dng_load_raw(void); +static void CLASS pentax_load_raw(void); +static void CLASS nikon_load_raw(void); +static void CLASS nikon_yuv_load_raw(void); +static int CLASS nikon_e995(void); +static int CLASS nikon_e2100(void); +static void CLASS nikon_3700(void); +static int CLASS minolta_z2(void); +static void CLASS ppm_thumb(void); +static void CLASS ppm16_thumb(void); +static void CLASS layer_thumb(void); +static void CLASS rollei_thumb(void); +static void CLASS rollei_load_raw(void); +static int CLASS raw(unsigned row,unsigned col); +static void CLASS phase_one_flat_field(int is_float,int nc); +static void CLASS phase_one_correct(void); +static void CLASS phase_one_load_raw(void); +static unsigned CLASS ph1_bithuff(int nbits,ushort *huff); +static void CLASS phase_one_load_raw_c(void); +static void CLASS hasselblad_load_raw(void); +static void CLASS leaf_hdr_load_raw(void); +static void CLASS unpacked_load_raw(void); +static void CLASS sinar_4shot_load_raw(void); +static void CLASS imacon_full_load_raw(void); +static void CLASS packed_load_raw(void); +static void CLASS nokia_load_raw(void); +static void CLASS canon_rmf_load_raw(void); +static unsigned CLASS pana_bits(int nbits); +static void CLASS panasonic_load_raw(void); +static void CLASS olympus_load_raw(void); +static void CLASS minolta_rd175_load_raw(void); +static void CLASS quicktake_100_load_raw(void); +static void CLASS kodak_radc_load_raw(void); +static void CLASS kodak_jpeg_load_raw(void); +static void CLASS lossy_dng_load_raw(void); +#ifndef NO_JPEG +static int boolean fill_input_buffer(j_decompress_ptr cinfo); +#endif +static void CLASS kodak_jpeg_load_raw(void); +static void CLASS lossy_dng_load_raw(void); +static void CLASS kodak_dc120_load_raw(void); +static void CLASS eight_bit_load_raw(void); +static void CLASS kodak_c330_load_raw(void); +static void CLASS kodak_c603_load_raw(void); +static void CLASS kodak_262_load_raw(void); +static int CLASS kodak_65000_decode(short *out,int bsize); +static void CLASS kodak_65000_load_raw(void); +static void CLASS kodak_ycbcr_load_raw(void); +static void CLASS kodak_rgb_load_raw(void); +static void CLASS kodak_thumb_load_raw(void); +static void CLASS sony_decrypt(unsigned *data,int len,int start,int key); +static void CLASS sony_load_raw(void); +static void CLASS sony_arw_load_raw(void); +static void CLASS sony_arw2_load_raw(void); +static void CLASS samsung_load_raw(void); +static void CLASS samsung2_load_raw(void); +static void CLASS samsung3_load_raw(void); +static void CLASS smal_decode_segment(unsigned seg[2][2],int holes); +static void CLASS smal_v6_load_raw(void); +static int CLASS median4(int *p); +static void CLASS fill_holes(int holes); +static void CLASS smal_v9_load_raw(void); +static void CLASS redcine_load_raw(void); +static void CLASS foveon_decoder(unsigned size,unsigned code); +static void CLASS foveon_thumb(void); +static void CLASS foveon_sd_load_raw(void); +static void CLASS foveon_huff(ushort *huff); +static void CLASS foveon_dp_load_raw(void); +static void CLASS foveon_load_camf(void); +static const char *CLASS foveon_camf_param(const char *block,const char *param); +static void *CLASS foveon_camf_matrix(unsigned dim[3],const char *name); +static int CLASS foveon_fixed(void *ptr,int size,const char *name); +static float CLASS foveon_avg(short *pix,int range[2],float cfilt); +static short *CLASS foveon_make_curve(double max,double mul,double filt); +static void CLASS foveon_make_curves(short **curvep,float dq[3],float div[3],float filt); +static int CLASS foveon_apply_curve(short *curve,int i); +static void CLASS foveon_interpolate(void); +static void CLASS crop_masked_pixels(void); +static void CLASS remove_zeroes(void); +static void CLASS bad_pixels(const char *cfname); +static void CLASS subtract(const char *fname); +static void CLASS gamma_curve(double pwr,double ts,int mode,int imax); +static void CLASS pseudoinverse (double (*in)[3],double (*out)[3],int size); +static void CLASS cam_xyz_coeff(float rgb_cam[3][4],double cam_xyz[4][3]); +#ifdef COLORCHECK +static void CLASS colorcheck(void); +#endif +static void CLASS hat_transform(float *temp,float *base,int st,int size,int sc); +static void CLASS wavelet_denoise(void); +static void CLASS scale_colors(void); +static void CLASS pre_interpolate(void); +static void CLASS border_interpolate(int border); +static void CLASS lin_interpolate(void); +static void CLASS vng_interpolate(void); +static void CLASS ppg_interpolate(void); +static void CLASS cielab(ushort rgb[3],short lab[3]); +static void CLASS xtrans_interpolate(int passes); +static void CLASS ahd_interpolate(void); +static void CLASS median_filter(void); +static void CLASS blend_highlights(void); +static void CLASS recover_highlights(void); +static void CLASS tiff_get(unsigned base,unsigned *tag,unsigned *type,unsigned *len,unsigned *save); +static void CLASS parse_thumb_note(int base,unsigned toff,unsigned tlen); +static void CLASS parse_makernote(int base,int uptag); +static void CLASS get_timestamp(int reversed); +static void CLASS parse_exif(int base); +static void CLASS parse_gps(int base); +static void CLASS romm_coeff(float romm_cam[3][3]); +static void CLASS parse_mos(int offset); +static void CLASS linear_table(unsigned len); +static void CLASS parse_kodak_ifd(int base); +static int CLASS parse_tiff_ifd(int base); +static int CLASS parse_tiff(int base); +static void CLASS apply_tiff(void); +static void CLASS parse_minolta(int base); +static void CLASS parse_external_jpeg(void); +static void CLASS ciff_block_1030(void); +static void CLASS parse_ciff(int offset,int length,int depth); +static void CLASS parse_rollei(void); +static void CLASS parse_sinar_ia(void); +static void CLASS parse_phase_one(int base); +static void CLASS parse_fuji(int offset); +static int CLASS parse_jpeg(int offset); +static void CLASS parse_riff(void); +static void CLASS parse_qt(int end); +static void CLASS parse_smal(int offset,int fsize); +static void CLASS parse_cine(void); +static void CLASS parse_redcine(void); +static char *CLASS foveon_gets(int offset,char *str,int len); +static void CLASS parse_foveon(void); +static void CLASS adobe_coeff(const char *make,const char *model); +static void CLASS simple_coeff(int index); +static short CLASS guess_byte_order(int words); +static float CLASS find_green(int bps,int bite,int off0,int off1); +static void CLASS identify(void); +#ifndef NO_LCMS +static void CLASS apply_profile(const char *input,const char *output); +#endif +static void CLASS convert_to_rgb(void); +static void CLASS fuji_rotate(void); +static void CLASS stretch(void); +static int CLASS flip_index(int row, int col); +static void CLASS tiff_set(struct tiff_hdr *th,ushort *ntag,ushort tag,ushort type,int count,int val); +static void CLASS tiff_head(struct tiff_hdr *th,int full); +static void CLASS jpeg_thumb(void); +static void CLASS write_ppm_tiff(void); +static void CLASS write_cinelerra(FILE *ofp); + diff --git a/cinelerra-5.1/cinelerra/ffmpeg.C b/cinelerra-5.1/cinelerra/ffmpeg.C index 10ad0503..f2b02c24 100644 --- a/cinelerra-5.1/cinelerra/ffmpeg.C +++ b/cinelerra-5.1/cinelerra/ffmpeg.C @@ -320,11 +320,15 @@ int FFStream::decode_activate() ret = AVERROR(ENOMEM); } if( ret >= 0 ) { + av_codec_set_pkt_timebase(avctx, st->time_base); + if( decoder->capabilities & AV_CODEC_CAP_DR1 ) + avctx->flags |= CODEC_FLAG_EMU_EDGE; avcodec_parameters_to_context(avctx, st->codecpar); ret = avcodec_open2(avctx, decoder, &copts); } - if( ret >= 0 ) + if( ret >= 0 ) { reading = 1; + } else eprintf(_("open decoder failed\n")); } @@ -2079,7 +2083,7 @@ int FFMPEG::decode_activate() } } int64_t nudge = vstart_time > min_nudge ? vstart_time : - astart_time > min_nudge ? astart_time : AV_NOPTS_VALUE; + astart_time > min_nudge ? astart_time : 0; for( int vidx=0; vidxnudge == AV_NOPTS_VALUE ) ffvideo[vidx]->nudge = nudge; diff --git a/cinelerra-5.1/cinelerra/file.C b/cinelerra-5.1/cinelerra/file.C index 8179d0d3..5301f7d1 100644 --- a/cinelerra-5.1/cinelerra/file.C +++ b/cinelerra-5.1/cinelerra/file.C @@ -71,6 +71,7 @@ #include "packagingengine.h" #include "pluginserver.h" #include "preferences.h" +#include "probeprefs.h" #include "samples.h" #include "vframe.h" @@ -359,15 +360,139 @@ int File::delete_oldest() return frame_cache->delete_oldest(); } - - - - - - - - - +// file driver in order of probe precidence +// can be reordered in preferences->interface +const char *File::default_probes[] = { + "FFMPEG_Early", + "Scene", + "DB", +#ifdef HAVE_DV + "DV", +#endif + "SndFile", + "PNG", + "JPEG", + "GIF", + "EXR", + "FLAC", + "CR2", + "TGA", + "TIFF", + "OGG", + "Vorbis", + "MPEG", + "EDL", + "FFMPEG_Late", +}; +const int File::nb_probes = + sizeof(File::default_probes)/sizeof(File::default_probes[0]); + + +int File::probe() +{ + FILE *fp = fopen(this->asset->path, "rb"); + if( !fp ) return FILE_NOT_FOUND; + char data[16]; + memset(data,0,sizeof(data)); + int ret = fread(data, 1, 16, fp); + fclose(fp); + if( !ret ) return FILE_NOT_FOUND; + + for( int i=0; ifile_probes.size(); ++i ) { + ProbePref *pref = preferences->file_probes[i]; + if( !pref->armed ) continue; + if( !strncmp(pref->name,"FFMPEG",6) ) { // FFMPEG Early/Late + if( !FileFFMPEG::check_sig(this->asset) ) continue; + file = new FileFFMPEG(this->asset, this); + return FILE_OK; + } + if( !strcmp(pref->name,"DB") ) { // MediaDB + if( !FileDB::check_sig(this->asset) ) continue; + file = new FileDB(this->asset, this); + return FILE_OK; + } + if( !strcmp(pref->name,"Scene") ) { // scene file + if( !FileScene::check_sig(this->asset, data)) continue; + file = new FileScene(this->asset, this); + return FILE_OK; + } +#ifdef HAVE_DV + if( !strcmp(pref->name,"DV") ) { // libdv + if( !FileDV::check_sig(this->asset) ) continue; + file = new FileDV(this->asset, this); + return FILE_OK; + } +#endif + if( !strcmp(pref->name,"SndFile") ) { // libsndfile + if( !FileSndFile::check_sig(this->asset) ) continue; + file = new FileSndFile(this->asset, this); + return FILE_OK; + } + if( !strcmp(pref->name,"PNG") ) { // PNG file + if( !FilePNG::check_sig(this->asset) ) continue; + file = new FilePNG(this->asset, this); + return FILE_OK; + } + if( !strcmp(pref->name,"JPEG") ) { // JPEG file + if( !FileJPEG::check_sig(this->asset) ) continue; + file = new FileJPEG(this->asset, this); + return FILE_OK; + } + if( !strcmp(pref->name,"GIF") ) { // GIF file + if( !FileGIF::check_sig(this->asset)) continue; + file = new FileGIF(this->asset, this); + return FILE_OK; + } + if( !strcmp(pref->name,"EXR") ) { // EXR file + if( !FileEXR::check_sig(this->asset, data)) continue; + file = new FileEXR(this->asset, this); + return FILE_OK; + } + if( !strcmp(pref->name,"FLAC") ) { // FLAC file + if( !FileFLAC::check_sig(this->asset, data)) continue; + file = new FileFLAC(this->asset, this); + return FILE_OK; + } + if( !strcmp(pref->name,"CR2") ) { // CR2 file + if( !FileCR2::check_sig(this->asset)) continue; + file = new FileCR2(this->asset, this); + return FILE_OK; + } + if( !strcmp(pref->name,"TGA") ) { // TGA file + if( !FileTGA::check_sig(this->asset) ) continue; + file = new FileTGA(this->asset, this); + return FILE_OK; + } + if( !strcmp(pref->name,"TIFF") ) { // TIFF file + if( !FileTIFF::check_sig(this->asset) ) continue; + file = new FileTIFF(this->asset, this); + return FILE_OK; + } + if( !strcmp(pref->name,"OGG") ) { // OGG file + if( !FileOGG::check_sig(this->asset) ) continue; + file = new FileOGG(this->asset, this); + return FILE_OK; + } + if( !strcmp(pref->name,"Vorbis") ) { // VorbisFile file + if( !FileVorbis::check_sig(this->asset) ) continue; + file = new FileVorbis(this->asset, this); + return FILE_OK; + } + if( !strcmp(pref->name,"MPEG") ) { // MPEG file + if( !FileMPEG::check_sig(this->asset) ) continue; + file = new FileMPEG(this->asset, this); + return FILE_OK; + } + if( !strcmp(pref->name,"EDL") ) { // XML file + if( data[0] != '<' ) continue; + if( !strncmp(&data[1],"EDL>",4) || + !strncmp(&data[1],"HTAL>",5) || + !strncmp(&data[1],"?xml",4) ) + return FILE_IS_XML; + } + } + return FILE_UNRECOGNIZED_CODEC; // maybe PCM file ? +} int File::open_file(Preferences *preferences, Asset *asset, @@ -386,138 +511,14 @@ int File::open_file(Preferences *preferences, if(debug) printf("File::open_file %p %d\n", this, __LINE__); - switch(this->asset->format) - { + switch(this->asset->format) { // get the format now // If you add another format to case 0, you also need to add another case for the // file format #define. - case FILE_UNKNOWN: - if(FileDB::check_sig(this->asset)) { -// MediaDb file - file = new FileDB(this->asset, this); - break; - } -// if early probe enabled - if( preferences->ffmpeg_early_probe && - FileFFMPEG::check_sig(this->asset)) { - file = new FileFFMPEG(this->asset, this); - break; - } - - FILE *stream; - if(!(stream = fopen(this->asset->path, "rb"))) { -// file not found - return 1; - } - - char test[16]; memset(test,0,sizeof(test)); // int result = - fread(test, 16, 1, stream); - - if(FileScene::check_sig(this->asset, test)) { -// scene file - fclose(stream); - file = new FileScene(this->asset, this); - break; - } -#ifdef HAVE_DV - if(FileDV::check_sig(this->asset)) { -// libdv - fclose(stream); - file = new FileDV(this->asset, this); - break; - } -#endif - if(FileSndFile::check_sig(this->asset)) { -// libsndfile - fclose(stream); - file = new FileSndFile(this->asset, this); - break; - } - if(FilePNG::check_sig(this->asset)) { -// PNG file - fclose(stream); - file = new FilePNG(this->asset, this); - break; - } - if(FileJPEG::check_sig(this->asset)) { -// JPEG file - fclose(stream); - file = new FileJPEG(this->asset, this); - break; - } - if(FileGIF::check_sig(this->asset)) { -// GIF file - fclose(stream); - file = new FileGIF(this->asset, this); - break; - } - if(FileEXR::check_sig(this->asset, test)) { -// EXR file - fclose(stream); - file = new FileEXR(this->asset, this); - break; - } - if(FileFLAC::check_sig(this->asset, test)) { -// FLAC file - fclose(stream); - file = new FileFLAC(this->asset, this); - break; - } - if(FileCR2::check_sig(this->asset)) { -// CR2 file - fclose(stream); - file = new FileCR2(this->asset, this); - break; - } - if(FileTGA::check_sig(this->asset)) { -// TGA file - fclose(stream); - file = new FileTGA(this->asset, this); - break; - } - if(FileTIFF::check_sig(this->asset)) { -// TIFF file - fclose(stream); - file = new FileTIFF(this->asset, this); - break; - } - if(FileOGG::check_sig(this->asset)) { -// OGG file - fclose(stream); - file = new FileOGG(this->asset, this); - break; - } - if(FileVorbis::check_sig(this->asset)) { -// VorbisFile file - fclose(stream); - file = new FileVorbis(this->asset, this); - break; - } - if(FileMPEG::check_sig(this->asset)) { -// MPEG file - fclose(stream); - file = new FileMPEG(this->asset, this); - break; - } - if( test[0] == '<' && ( - !strncmp(&test[1],"EDL>",4) || - !strncmp(&test[1],"HTAL>",5) || - !strncmp(&test[1],"?xml",4) ) ) { -// XML file - fclose(stream); - return FILE_IS_XML; - } // can't load project file - if( !preferences->ffmpeg_early_probe && - FileFFMPEG::check_sig(this->asset) ) { - fclose(stream); - file = new FileFFMPEG(this->asset, this); - break; - } -// PCM file - fclose(stream); - return FILE_UNRECOGNIZED_CODEC; - break; - + case FILE_UNKNOWN: { + int ret = probe(); + if( ret != FILE_OK ) return ret; + break; } // format already determined case FILE_AC3: file = new FileAC3(this->asset, this); diff --git a/cinelerra-5.1/cinelerra/file.h b/cinelerra-5.1/cinelerra/file.h index 442bdc58..a2ed78d5 100644 --- a/cinelerra-5.1/cinelerra/file.h +++ b/cinelerra-5.1/cinelerra/file.h @@ -58,6 +58,7 @@ public: File(); ~File(); + int probe(); // Get attributes for various file formats. // The dither parameter is carried over from recording, where dither is done at the device. int get_options(FormatTools *format, @@ -329,6 +330,9 @@ public: static const char *get_ladspa_path() { return getenv("CIN_LADSPA"); } static const char *get_locale_path() { return getenv("CIN_LOCALE"); } + static const char *default_probes[]; + static const int nb_probes; + private: void reset_parameters(); diff --git a/cinelerra-5.1/cinelerra/filecr2.C b/cinelerra-5.1/cinelerra/filecr2.C index b7dcff6c..0d36b26f 100644 --- a/cinelerra-5.1/cinelerra/filecr2.C +++ b/cinelerra-5.1/cinelerra/filecr2.C @@ -39,6 +39,14 @@ extern float dcraw_matrix[9]; int dcraw_main (int argc, const char **argv); } +static int dcraw_run(int argc, const char **argv) +{ + static Mutex dcraw_lock; + dcraw_lock.lock("dcraw_run"); + int result = dcraw_main(argc, argv); + dcraw_lock.unlock(); + return result; +} FileCR2::FileCR2(Asset *asset, File *file) : FileList(asset, file, "CR2LIST", ".cr2", FILE_CR2, FILE_CR2_LIST) @@ -96,7 +104,7 @@ int FileCR2::check_sig(Asset *asset) 0 }; - int result = dcraw_main(argc, argv); + int result = dcraw_run(argc, argv); //printf("FileCR2::check_sig %d %d\n", __LINE__, result); @@ -115,7 +123,7 @@ int FileCR2::check_sig(Asset *asset) // 0 // }; // -// int result = dcraw_main(argc, argv); +// int result = dcraw_run(argc, argv); // if(!result) format_to_asset(); // // return result; @@ -133,7 +141,7 @@ printf("FileCR2::read_frame_header %d\n", __LINE__); 0 }; - int result = dcraw_main(argc, argv); + int result = dcraw_run(argc, argv); if(!result) format_to_asset(); printf("FileCR2::read_frame_header %d %d\n", __LINE__, result); @@ -214,7 +222,7 @@ printf("FileCR2::read_frame %d %s\n", __LINE__, path); dcraw_data = (float**)frame->get_rows(); //Timer timer; - int result = dcraw_main(argc, (const char**) argv); + int result = dcraw_run(argc, (const char**) argv); // This was only used by the bayer interpolate plugin, which itself created // too much complexity to use effectively. diff --git a/cinelerra-5.1/cinelerra/fileffmpeg.C b/cinelerra-5.1/cinelerra/fileffmpeg.C index 5542c975..33f3fa47 100644 --- a/cinelerra-5.1/cinelerra/fileffmpeg.C +++ b/cinelerra-5.1/cinelerra/fileffmpeg.C @@ -210,7 +210,6 @@ int FileFFMPEG::select_video_stream(Asset *asset, int vstream) if( !ff || !asset->video_data ) return 1; asset->width = ff->ff_video_width(vstream); asset->height = ff->ff_video_height(vstream); - asset->video_length = ff->ff_video_frames(vstream); if( (asset->video_length = ff->ff_video_frames(vstream)) < 2 ) asset->video_length = asset->video_length < 0 ? 0 : -1; asset->frame_rate = ff->ff_frame_rate(vstream); diff --git a/cinelerra-5.1/cinelerra/garbage.h b/cinelerra-5.1/cinelerra/garbage.h index 8cf8306e..7f44a585 100644 --- a/cinelerra-5.1/cinelerra/garbage.h +++ b/cinelerra-5.1/cinelerra/garbage.h @@ -49,6 +49,8 @@ class Garbage { + Garbage(Garbage &v) {} //disallow copy constructor + Garbage &operator=(Garbage &v) { return *this=v; } //disallow = operator public: Garbage(const char *title); virtual ~Garbage(); diff --git a/cinelerra-5.1/cinelerra/interfaceprefs.C b/cinelerra-5.1/cinelerra/interfaceprefs.C index fb58b22e..1a3f1be5 100644 --- a/cinelerra-5.1/cinelerra/interfaceprefs.C +++ b/cinelerra-5.1/cinelerra/interfaceprefs.C @@ -160,16 +160,17 @@ void InterfacePrefs::create_objects() y += 5; add_subwindow(new BC_Title(x, y, _("Index files"), LARGEFONT, resources->text_default)); + add_subwindow(ffmpeg_marker_files = new IndexFFMPEGMarkerFiles(this, x1, y)); - y += 25; + y += 30; add_subwindow(new BC_Title(x, y + 5, _("Index files go here:"), MEDIUMFONT, resources->text_default)); add_subwindow(ipathtext = new IndexPathText(x + 230, y, pwindow, pwindow->thread->preferences->index_directory)); add_subwindow(ipath = new BrowseButton(mwindow->theme, this, ipathtext, - x + 230 + ipathtext->get_w(), y, + x1 = x + 230 + ipathtext->get_w(), y, pwindow->thread->preferences->index_directory, _("Index Path"), _("Select the directory for index files"), @@ -190,9 +191,6 @@ void InterfacePrefs::create_objects() add_subwindow(deleteall = new DeleteAllIndexes(mwindow, pwindow, 350, y)); - - - y += 35; add_subwindow(new BC_Bar(5, y, get_w() - 10)); y += 5; @@ -292,23 +290,12 @@ void InterfacePrefs::create_objects() const char* InterfacePrefs::behavior_to_text(int mode) { - switch(mode) - { - case MOVE_ALL_EDITS: - return _(MOVE_ALL_EDITS_TITLE); - break; - case MOVE_ONE_EDIT: - return _(MOVE_ONE_EDIT_TITLE); - break; - case MOVE_NO_EDITS: - return _(MOVE_NO_EDITS_TITLE); - break; - case MOVE_EDITS_DISABLED: - return _(MOVE_EDITS_DISABLED_TITLE); - break; - default: - return ""; - break; + switch(mode) { + case MOVE_ALL_EDITS: return _(MOVE_ALL_EDITS_TITLE); + case MOVE_ONE_EDIT: return _(MOVE_ONE_EDIT_TITLE); + case MOVE_NO_EDITS: return _(MOVE_NO_EDITS_TITLE); + case MOVE_EDITS_DISABLED: return _(MOVE_EDITS_DISABLED_TITLE); + default: return ""; } } @@ -329,17 +316,6 @@ int InterfacePrefs::update(int new_value) - - - - - - - - - - - IndexPathText::IndexPathText(int x, int y, PreferencesWindow *pwindow, @@ -403,15 +379,22 @@ int IndexCount::handle_event() +IndexFFMPEGMarkerFiles::IndexFFMPEGMarkerFiles(InterfacePrefs *iface_prefs, int x, int y) + : BC_CheckBox(x, y, + iface_prefs->pwindow->thread->preferences->ffmpeg_marker_indexes, + _("build ffmpeg marker indexes")) +{ + this->iface_prefs = iface_prefs; +} +IndexFFMPEGMarkerFiles::~IndexFFMPEGMarkerFiles() +{ +} - - - - - - - - +int IndexFFMPEGMarkerFiles::handle_event() +{ + iface_prefs->pwindow->thread->preferences->ffmpeg_marker_indexes = get_value(); + return 1; +} diff --git a/cinelerra-5.1/cinelerra/interfaceprefs.h b/cinelerra-5.1/cinelerra/interfaceprefs.h index a16cb750..d4f2b97b 100644 --- a/cinelerra-5.1/cinelerra/interfaceprefs.h +++ b/cinelerra-5.1/cinelerra/interfaceprefs.h @@ -22,9 +22,10 @@ #ifndef INTERFACEPREFS_H #define INTERFACEPREFS_H +class InterfacePrefs; +class IndexPathText; class IndexSize; class IndexCount; -class IndexPathText; class TimeFormatHMS; class TimeFormatHMSF; class TimeFormatSamples; @@ -32,19 +33,33 @@ class TimeFormatFrames; class TimeFormatHex; class TimeFormatFeet; class TimeFormatSeconds; +class TimeFormatFeetSetting; class MeterMinDB; class MeterMaxDB; class MeterVUDB; class MeterVUInt; class ViewBehaviourText; +class ViewBehaviourItem; class ViewTheme; class ViewThumbnails; class ViewThemeItem; class UseTipWindow; +class UseWarnIndecies; +class UseWarnVersion; +class BD_WarnRoot; +class ScanCommercials; +class AndroidRemote; +class PopupMenuBtnup; +class ActivateFocusPolicy; +class DeactivateFocusPolicy; +class AndroidPIN; +class AndroidPort; +class ShBtnPrefs; class StillImageUseDuration; class StillImageDuration; class KeyframeReticle; -class PopupMenuBtnup; +class HairlineItem; +class IndexFFMPEGMarkerFiles; #include "browsebutton.h" #include "deleteallindexes.inc" @@ -70,6 +85,7 @@ public: IndexCount *icount; IndexPathText *ipathtext; DeleteAllIndexes *deleteall; + IndexFFMPEGMarkerFiles *ffmpeg_marker_files; TimeFormatHMS *hms; TimeFormatHMSF *hmsf; @@ -414,4 +430,16 @@ public: int hairline; }; +class IndexFFMPEGMarkerFiles : public BC_CheckBox +{ +public: + IndexFFMPEGMarkerFiles(InterfacePrefs *iface_prefs, int x, int y); + ~IndexFFMPEGMarkerFiles(); + + int handle_event(); + + InterfacePrefs *iface_prefs; +}; + + #endif diff --git a/cinelerra-5.1/cinelerra/mainmenu.C b/cinelerra-5.1/cinelerra/mainmenu.C index 1b75ddfc..a3fb4038 100644 --- a/cinelerra-5.1/cinelerra/mainmenu.C +++ b/cinelerra-5.1/cinelerra/mainmenu.C @@ -616,7 +616,8 @@ Undo::Undo(MWindow *mwindow) : BC_MenuItem(_("Undo"), "z", 'z') } int Undo::handle_event() { - mwindow->undo_entry(mwindow->gui); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->undo_entry(mwindow->gui); return 1; } int Undo::update_caption(const char *new_caption) @@ -636,8 +637,8 @@ Redo::Redo(MWindow *mwindow) : BC_MenuItem(_("Redo"), _("Shift-Z"), 'Z') int Redo::handle_event() { - mwindow->redo_entry(mwindow->gui); - + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->redo_entry(mwindow->gui); return 1; } int Redo::update_caption(const char *new_caption) @@ -657,7 +658,8 @@ CutKeyframes::CutKeyframes(MWindow *mwindow) int CutKeyframes::handle_event() { - mwindow->cut_automation(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->cut_automation(); return 1; } @@ -670,7 +672,8 @@ CopyKeyframes::CopyKeyframes(MWindow *mwindow) int CopyKeyframes::handle_event() { - mwindow->copy_automation(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->copy_automation(); return 1; } @@ -683,7 +686,8 @@ PasteKeyframes::PasteKeyframes(MWindow *mwindow) int PasteKeyframes::handle_event() { - mwindow->paste_automation(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->paste_automation(); return 1; } @@ -696,7 +700,8 @@ ClearKeyframes::ClearKeyframes(MWindow *mwindow) int ClearKeyframes::handle_event() { - mwindow->clear_automation(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->clear_automation(); return 1; } @@ -799,7 +804,8 @@ CutDefaultKeyframe::CutDefaultKeyframe(MWindow *mwindow) int CutDefaultKeyframe::handle_event() { - mwindow->cut_default_keyframe(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->cut_default_keyframe(); return 1; } @@ -812,7 +818,8 @@ CopyDefaultKeyframe::CopyDefaultKeyframe(MWindow *mwindow) int CopyDefaultKeyframe::handle_event() { - mwindow->copy_default_keyframe(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->copy_default_keyframe(); return 1; } @@ -825,7 +832,8 @@ PasteDefaultKeyframe::PasteDefaultKeyframe(MWindow *mwindow) int PasteDefaultKeyframe::handle_event() { - mwindow->paste_default_keyframe(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->paste_default_keyframe(); return 1; } @@ -838,7 +846,8 @@ ClearDefaultKeyframe::ClearDefaultKeyframe(MWindow *mwindow) int ClearDefaultKeyframe::handle_event() { - mwindow->clear_default_keyframe(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->clear_default_keyframe(); return 1; } @@ -850,7 +859,8 @@ Cut::Cut(MWindow *mwindow) int Cut::handle_event() { - mwindow->cut(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->cut(); return 1; } @@ -862,7 +872,8 @@ Copy::Copy(MWindow *mwindow) int Copy::handle_event() { - mwindow->copy(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->copy(); return 1; } @@ -874,7 +885,8 @@ Paste::Paste(MWindow *mwindow) int Paste::handle_event() { - mwindow->paste(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->paste(); return 1; } @@ -886,9 +898,11 @@ Clear::Clear(MWindow *mwindow) int Clear::handle_event() { - mwindow->cwindow->gui->lock_window("Clear::handle_event"); - mwindow->clear_entry(); - mwindow->cwindow->gui->unlock_window(); + if( mwindow->session->current_operation == NO_OPERATION ) { + mwindow->cwindow->gui->lock_window("Clear::handle_event"); + mwindow->clear_entry(); + mwindow->cwindow->gui->unlock_window(); + } return 1; } @@ -901,7 +915,8 @@ PasteSilence::PasteSilence(MWindow *mwindow) int PasteSilence::handle_event() { - mwindow->paste_silence(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->paste_silence(); return 1; } @@ -913,7 +928,8 @@ SelectAll::SelectAll(MWindow *mwindow) int SelectAll::handle_event() { - mwindow->select_all(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->select_all(); return 1; } @@ -959,7 +975,8 @@ MuteSelection::MuteSelection(MWindow *mwindow) int MuteSelection::handle_event() { - mwindow->mute_selection(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->mute_selection(); return 1; } @@ -997,7 +1014,8 @@ AddAudioTrack::AddAudioTrack(MWindow *mwindow) int AddAudioTrack::handle_event() { - mwindow->add_audio_track_entry(0, 0); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->add_audio_track_entry(0, 0); return 1; } @@ -1020,7 +1038,8 @@ DefaultATransition::DefaultATransition(MWindow *mwindow) int DefaultATransition::handle_event() { - mwindow->paste_audio_transition(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->paste_audio_transition(); return 1; } @@ -1064,7 +1083,8 @@ AddVideoTrack::AddVideoTrack(MWindow *mwindow) int AddVideoTrack::handle_event() { - mwindow->add_video_track_entry(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->add_video_track_entry(); return 1; } @@ -1104,7 +1124,8 @@ DefaultVTransition::DefaultVTransition(MWindow *mwindow) int DefaultVTransition::handle_event() { - mwindow->paste_video_transition(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->paste_video_transition(); return 1; } @@ -1143,7 +1164,8 @@ DeleteTrack::DeleteTrack(MWindow *mwindow) int DeleteTrack::handle_event() { - mwindow->delete_track(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->delete_track(); return 1; } @@ -1155,7 +1177,8 @@ MoveTracksUp::MoveTracksUp(MWindow *mwindow) int MoveTracksUp::handle_event() { - mwindow->move_tracks_up(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->move_tracks_up(); return 1; } @@ -1167,7 +1190,8 @@ MoveTracksDown::MoveTracksDown(MWindow *mwindow) int MoveTracksDown::handle_event() { - mwindow->move_tracks_down(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->move_tracks_down(); return 1; } @@ -1201,8 +1225,10 @@ LoopPlayback::LoopPlayback(MWindow *mwindow) int LoopPlayback::handle_event() { - mwindow->toggle_loop_playback(); - set_checked(mwindow->edl->local_session->loop_playback); + if( mwindow->session->current_operation == NO_OPERATION ) { + mwindow->toggle_loop_playback(); + set_checked(mwindow->edl->local_session->loop_playback); + } return 1; } @@ -1220,7 +1246,8 @@ AddSubttlTrack::AddSubttlTrack(MWindow *mwindow) int AddSubttlTrack::handle_event() { - mwindow->add_subttl_track_entry(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->add_subttl_track_entry(); return 1; } @@ -1232,7 +1259,8 @@ PasteSubttl::PasteSubttl(MWindow *mwindow) int PasteSubttl::handle_event() { - mwindow->gui->swindow->paste_subttl(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->gui->swindow->paste_subttl(); return 1; } @@ -1246,9 +1274,11 @@ SetBRenderActive::SetBRenderActive(MWindow *mwindow) int SetBRenderActive::handle_event() { - int v = mwindow->brender_active ? 0 : 1; - set_checked(v); - mwindow->set_brender_active(v); + if( mwindow->session->current_operation == NO_OPERATION ) { + int v = mwindow->brender_active ? 0 : 1; + set_checked(v); + mwindow->set_brender_active(v); + } return 1; } @@ -1419,11 +1449,13 @@ ShowGWindow::ShowGWindow(MWindow *mwindow) } int ShowGWindow::handle_event() { - if( !mwindow->session->show_gwindow ) - mwindow->show_gwindow(); - else - mwindow->hide_gwindow(); - set_checked(mwindow->session->show_gwindow); + if( mwindow->session->current_operation == NO_OPERATION ) { + if( !mwindow->session->show_gwindow ) + mwindow->show_gwindow(); + else + mwindow->hide_gwindow(); + set_checked(mwindow->session->show_gwindow); + } return 1; } @@ -1450,11 +1482,13 @@ TileWindows::TileWindows(MWindow *mwindow, const char *item_title, int config, } int TileWindows::handle_event() { - int window_config = config >= 0 ? config : - mwindow->session->window_config; - if( mwindow->tile_windows(window_config) ) { - mwindow->restart_status = 1; - mwindow->gui->set_done(0); + if( mwindow->session->current_operation == NO_OPERATION ) { + int window_config = config >= 0 ? config : + mwindow->session->window_config; + if( mwindow->tile_windows(window_config) ) { + mwindow->restart_status = 1; + mwindow->gui->set_done(0); + } } return 1; } @@ -1468,7 +1502,8 @@ SplitX::SplitX(MWindow *mwindow) } int SplitX::handle_event() { - mwindow->split_x(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->split_x(); return 1; } @@ -1481,7 +1516,8 @@ SplitY::SplitY(MWindow *mwindow) } int SplitY::handle_event() { - mwindow->split_y(); + if( mwindow->session->current_operation == NO_OPERATION ) + mwindow->split_y(); return 1; } diff --git a/cinelerra-5.1/cinelerra/mwindow.C b/cinelerra-5.1/cinelerra/mwindow.C index 478c845c..ec137687 100644 --- a/cinelerra-5.1/cinelerra/mwindow.C +++ b/cinelerra-5.1/cinelerra/mwindow.C @@ -1461,11 +1461,9 @@ SET_TRACE case FILE_UNRECOGNIZED_CODEC: { // Test index file - IndexFile indexfile(this, new_asset); - result = indexfile.open_index(); - if(!result) - { - indexfile.close_index(); + { IndexFile indexfile(this, new_asset); + if( !(result = indexfile.open_index()) ) + indexfile.close_index(); } // Test existing EDLs @@ -1474,7 +1472,7 @@ SET_TRACE new_edls[j]->assets->get_asset(new_asset->path) : edl->assets->get_asset(new_asset->path); if( old_asset ) { - *new_asset = *old_asset; + new_asset->copy_from(old_asset,1); result = 0; } } diff --git a/cinelerra-5.1/cinelerra/mwindowgui.C b/cinelerra-5.1/cinelerra/mwindowgui.C index 9724470d..ed12ca65 100644 --- a/cinelerra-5.1/cinelerra/mwindowgui.C +++ b/cinelerra-5.1/cinelerra/mwindowgui.C @@ -2272,12 +2272,12 @@ int PaneButton::button_release_event() FFMpegToggle::FFMpegToggle(MWindow *mwindow, MButtons *mbuttons, int x, int y) - : BC_Toggle(x, y, mwindow->theme->ffmpeg_toggle, mwindow->preferences->ffmpeg_early_probe) + : BC_Toggle(x, y, mwindow->theme->ffmpeg_toggle, + mwindow->preferences->get_file_probe_armed("FFMPEG_Early") > 0 ? 1 : 0) { this->mwindow = mwindow; this->mbuttons = mbuttons; - set_tooltip( mwindow->preferences->ffmpeg_early_probe ? - _("Try FFMpeg first") : _("Try FFMpeg last")); + set_tooltip( !get_value() ? _("Try FFMpeg first") : _("Try FFMpeg last") ); } FFMpegToggle::~FFMpegToggle() @@ -2286,9 +2286,11 @@ FFMpegToggle::~FFMpegToggle() int FFMpegToggle::handle_event() { - mwindow->preferences->ffmpeg_early_probe = get_value(); - set_tooltip( mwindow->preferences->ffmpeg_early_probe ? - _("Try FFMpeg first") : _("Try FFMpeg last")); + int ffmpeg_early_probe = get_value(); + set_tooltip( !ffmpeg_early_probe ? _("Try FFMpeg first") : _("Try FFMpeg last")); + mwindow->preferences->set_file_probe_armed("FFMPEG_Early", ffmpeg_early_probe); + mwindow->preferences->set_file_probe_armed("FFMPEG_Late", !ffmpeg_early_probe); + mwindow->show_warning(&mwindow->preferences->warn_indexes, _("Changing the base codecs may require rebuilding indexes.")); return 1; diff --git a/cinelerra-5.1/cinelerra/performanceprefs.C b/cinelerra-5.1/cinelerra/performanceprefs.C index f6b2ab03..8edc41d5 100644 --- a/cinelerra-5.1/cinelerra/performanceprefs.C +++ b/cinelerra-5.1/cinelerra/performanceprefs.C @@ -28,6 +28,7 @@ #include "mwindow.h" #include "performanceprefs.h" #include "preferences.h" +#include "probeprefs.h" #include #include "theme.h" @@ -40,11 +41,13 @@ PerformancePrefs::PerformancePrefs(MWindow *mwindow, PreferencesWindow *pwindow) : PreferencesDialog(mwindow, pwindow) { hot_node = -1; + file_probe_dialog = 0; } PerformancePrefs::~PerformancePrefs() { delete brender_tools; + delete file_probe_dialog; nodes[0].remove_all_objects(); nodes[1].remove_all_objects(); nodes[2].remove_all_objects(); @@ -61,7 +64,7 @@ void PerformancePrefs::create_objects() char string[BCTEXTLEN]; BC_Resources *resources = BC_WindowBase::get_resources(); BC_WindowBase *win; - int maxw, curw, y1; + int maxw, curw; node_list = 0; generate_node_list(); @@ -77,30 +80,25 @@ void PerformancePrefs::create_objects() // // y += get_text_height(LARGEFONT) + 5; - int ybx[2]; - ybx[0] = y; + int y0 = y; win = add_subwindow(new BC_Title(x, y + 5, _("Cache size (MB):"), MEDIUMFONT, resources->text_default)); maxw = win->get_w(); - ybx[1] = y += 30; + int y1 = y += 30; win = add_subwindow(new BC_Title(x, y + 5, _("Seconds to preroll renders:"))); if((curw = win->get_w()) > maxw) maxw = curw; maxw += x + 5; - cache_size = new CICacheSize(maxw, - ybx[0], - pwindow, - this); + cache_size = new CICacheSize(maxw, y0, pwindow, this); cache_size->create_objects(); + int x1 = cache_size->get_x() + cache_size->get_w() + 30; + add_subwindow(file_probes = new PrefsFileProbes(pwindow, this, x1, y0)); + add_subwindow(new BC_Title(x, y + 5, _("Seconds to preroll renders:"))); - PrefsRenderPreroll *preroll = new PrefsRenderPreroll(pwindow, - this, - maxw, - ybx[1]); + PrefsRenderPreroll *preroll = new PrefsRenderPreroll(pwindow, this, maxw, y1); preroll->create_objects(); - int x1 = preroll->get_x() + preroll->get_w() + 20; BC_Title *smp_title = new BC_Title(x1, y + 5, _("Project SMP cpus:")); add_subwindow(smp_title); int x2 = x1 + smp_title->get_w() + 5; @@ -122,13 +120,8 @@ void PerformancePrefs::create_objects() PrefsTrapSigINTR *trap_intr = new PrefsTrapSigINTR(this, x1, y); add_subwindow(trap_intr); add_subwindow(new BC_Title(x2, y, _("(must be root)"), MEDIUMFONT, RED)); - ffmpeg_marker_indexes = new PrefsFFMPEGMarkerIndecies(this, x, y); - add_subwindow(ffmpeg_marker_indexes); y += 30; - ffmpeg_early_probe = new PrefsFFMPEGEarlyProbe(this, x, y); - add_subwindow(ffmpeg_early_probe); - yuv420p_dvdlace = new PrefsYUV420P_DVDlace(pwindow, this, x1, y); add_subwindow(yuv420p_dvdlace); y += 30; @@ -353,6 +346,29 @@ void PerformancePrefs::update_rates() update_node_list(); } +void PerformancePrefs::start_probe_dialog() +{ + if( !file_probe_dialog ) + file_probe_dialog = new FileProbeDialog(pwindow); + file_probe_dialog->start(); +} + +PrefsFileProbes::PrefsFileProbes(PreferencesWindow *pwindow, + PerformancePrefs *perf_prefs, int x, int y) + : BC_GenericButton(x, y, _("Probe Order")) +{ + this->pwindow = pwindow; + this->perf_prefs = perf_prefs; + set_tooltip(_("File Open Probe Ordering")); +} + +int PrefsFileProbes::handle_event() +{ + perf_prefs->start_probe_dialog(); + return 1; +} + + PrefsUseBRender::PrefsUseBRender(PreferencesWindow *pwindow, int x, @@ -559,44 +575,6 @@ int PrefsTrapSigINTR::handle_event() } -PrefsFFMPEGEarlyProbe::PrefsFFMPEGEarlyProbe(PerformancePrefs *perf_prefs, int x, int y) - : BC_CheckBox(x, y, - perf_prefs->pwindow->thread->preferences->ffmpeg_early_probe, - _("On file open, ffmpeg probes early")) -{ - this->perf_prefs = perf_prefs; -} -PrefsFFMPEGEarlyProbe::~PrefsFFMPEGEarlyProbe() -{ -} - -int PrefsFFMPEGEarlyProbe::handle_event() -{ - perf_prefs->pwindow->thread->preferences->ffmpeg_early_probe = get_value(); - return 1; -} - - -PrefsFFMPEGMarkerIndecies::PrefsFFMPEGMarkerIndecies(PerformancePrefs *perf_prefs, int x, int y) - : BC_CheckBox(x, y, - perf_prefs->pwindow->thread->preferences->ffmpeg_marker_indexes, - _("build ffmpeg marker indexes")) -{ - this->perf_prefs = perf_prefs; -} -PrefsFFMPEGMarkerIndecies::~PrefsFFMPEGMarkerIndecies() -{ -} - -int PrefsFFMPEGMarkerIndecies::handle_event() -{ - perf_prefs->pwindow->thread->preferences->ffmpeg_marker_indexes = get_value(); - return 1; -} - - - - PrefsRenderFarmConsolidate::PrefsRenderFarmConsolidate(PreferencesWindow *pwindow, int x, int y) @@ -617,9 +595,6 @@ int PrefsRenderFarmConsolidate::handle_event() } - - - PrefsRenderFarmPort::PrefsRenderFarmPort(PreferencesWindow *pwindow, PerformancePrefs *subwindow, int x, diff --git a/cinelerra-5.1/cinelerra/performanceprefs.h b/cinelerra-5.1/cinelerra/performanceprefs.h index a7923002..22ba6c43 100644 --- a/cinelerra-5.1/cinelerra/performanceprefs.h +++ b/cinelerra-5.1/cinelerra/performanceprefs.h @@ -27,6 +27,7 @@ #include "mwindow.inc" #include "performanceprefs.inc" #include "preferencesthread.h" +#include "probeprefs.inc" class PerformancePrefs : public PreferencesDialog @@ -40,10 +41,12 @@ public: void generate_node_list(); void update_node_list(); void update_rates(); + void start_probe_dialog(); int hot_node; CICacheSize *cache_size; + PrefsFileProbes *file_probes; enum { @@ -60,9 +63,8 @@ public: PrefsRenderFarmNodes *node_list; FormatTools *brender_tools; BC_Title *master_rate; - PrefsFFMPEGEarlyProbe *ffmpeg_early_probe; PrefsYUV420P_DVDlace *yuv420p_dvdlace; - PrefsFFMPEGMarkerIndecies *ffmpeg_marker_indexes; + FileProbeDialog *file_probe_dialog; }; @@ -145,17 +147,6 @@ public: PerformancePrefs *perf_prefs; }; -class PrefsFFMPEGEarlyProbe : public BC_CheckBox -{ -public: - PrefsFFMPEGEarlyProbe(PerformancePrefs *perf_prefs, int x, int y); - ~PrefsFFMPEGEarlyProbe(); - - int handle_event(); - - PerformancePrefs *perf_prefs; -}; - class PrefsFFMPEGMarkerIndecies : public BC_CheckBox { public: @@ -382,4 +373,16 @@ public: PreferencesWindow *pwindow; }; + +class PrefsFileProbes : public BC_GenericButton +{ +public: + PreferencesWindow *pwindow; + PerformancePrefs *perf_prefs; + + int handle_event(); + PrefsFileProbes(PreferencesWindow *pwindow, PerformancePrefs *perf_prefs, int x, int y); +}; + + #endif diff --git a/cinelerra-5.1/cinelerra/performanceprefs.inc b/cinelerra-5.1/cinelerra/performanceprefs.inc index 59e3d8df..af229716 100644 --- a/cinelerra-5.1/cinelerra/performanceprefs.inc +++ b/cinelerra-5.1/cinelerra/performanceprefs.inc @@ -47,5 +47,7 @@ class PrefsRenderFarmSortNodes; class PrefsRenderFarmReset; class PrefsYUV420P_DVDlace; class CICacheSize; +class PrefsFileProbes; + #endif diff --git a/cinelerra-5.1/cinelerra/preferences.C b/cinelerra-5.1/cinelerra/preferences.C index f69ab3e8..5bc21f62 100644 --- a/cinelerra-5.1/cinelerra/preferences.C +++ b/cinelerra-5.1/cinelerra/preferences.C @@ -33,6 +33,7 @@ #include "indexfile.h" #include "mutex.h" #include "preferences.h" +#include "probeprefs.h" #include "shbtnprefs.h" #include "theme.h" #include "videoconfig.h" @@ -77,7 +78,6 @@ Preferences::Preferences() renderfarm_job_count = 20; project_smp = processors = calculate_processors(0); real_processors = calculate_processors(1); - ffmpeg_early_probe = 1; ffmpeg_marker_indexes = 1; warn_indexes = 1; warn_version = 1; @@ -120,6 +120,7 @@ Preferences::~Preferences() { brender_asset->Garbage::remove_user(); shbtn_prefs.remove_all_objects(); + file_probes.remove_all_objects(); renderfarm_nodes.remove_all_objects(); delete preferences_lock; } @@ -180,6 +181,9 @@ void Preferences::copy_from(Preferences *that) this->shbtn_prefs.remove_all_objects(); for( int i=0; ishbtn_prefs.size(); ++i ) this->shbtn_prefs.append(new ShBtnPref(*that->shbtn_prefs[i])); + this->file_probes.remove_all_objects(); + for( int i=0; ifile_probes.size(); ++i ) + this->file_probes.append(new ProbePref(*that->file_probes[i])); cache_size = that->cache_size; project_smp = that->project_smp; force_uniprocessor = that->force_uniprocessor; @@ -187,7 +191,6 @@ void Preferences::copy_from(Preferences *that) trap_sigintr = that->trap_sigintr; processors = that->processors; real_processors = that->real_processors; - ffmpeg_early_probe = that->ffmpeg_early_probe; ffmpeg_marker_indexes = that->ffmpeg_marker_indexes; warn_indexes = that->warn_indexes; warn_version = that->warn_version; @@ -339,7 +342,6 @@ int Preferences::load_defaults(BC_Hash *defaults) project_smp = defaults->get("PROJECT_SMP", project_smp); force_uniprocessor = defaults->get("FORCE_UNIPROCESSOR", force_uniprocessor); - ffmpeg_early_probe = defaults->get("FFMPEG_EARLY_PROBE", ffmpeg_early_probe); ffmpeg_marker_indexes = defaults->get("FFMPEG_MARKER_INDEXES", ffmpeg_marker_indexes); warn_indexes = defaults->get("WARN_INDEXES", warn_indexes); warn_version = defaults->get("WARN_VERSION", warn_version); @@ -406,6 +408,28 @@ int Preferences::load_defaults(BC_Hash *defaults) shbtn_prefs.append(new ShBtnPref(name, commands, warn)); } + file_probes.remove_all_objects(); + int file_probe_total = defaults->get("FILE_PROBE_TOTAL", 0); + for( int i=0; iget(string, name); + sprintf(string, "FILE_PROBE%d_ARMED", i); + int armed = defaults->get(string, 1); + file_probes.append(new ProbePref(name, armed)); + } + // append any missing probes + for( int i=0; i=0 && strcmp(nm, file_probes[k]->name) ); + if( k >= 0 ) continue; + int armed = 1; + if( !strcmp(nm, "FFMPEG_Late") || + !strcmp(nm, "CR2") ) armed = 0; + file_probes.append(new ProbePref(nm, armed)); + } + // Redo with the proper value of force_uniprocessor processors = calculate_processors(0); boundaries(); @@ -445,7 +469,6 @@ int Preferences::save_defaults(BC_Hash *defaults) defaults->update("PROJECT_SMP", project_smp); defaults->update("FORCE_UNIPROCESSOR", force_uniprocessor); - defaults->update("FFMPEG_EARLY_PROBE", ffmpeg_early_probe); defaults->update("FFMPEG_MARKER_INDEXES", ffmpeg_marker_indexes); defaults->update("WARN_INDEXES", warn_indexes); defaults->update("WARN_VERSION", warn_version); @@ -487,6 +510,14 @@ int Preferences::save_defaults(BC_Hash *defaults) sprintf(string, "SHBTN%d_WARN", i); defaults->update(string, pref->warn); } + defaults->update("FILE_PROBE_TOTAL", file_probes.size()); + for( int i=0; iupdate(string, pref->name); + sprintf(string, "FILE_PROBE%d_ARMED", i); + defaults->update(string, pref->armed); + } return 0; } @@ -739,3 +770,19 @@ int Preferences::calculate_processors(int interactive) return BC_WindowBase::get_resources()->machine_cpus; } +int Preferences::get_file_probe_armed(const char *nm) +{ + int k = file_probes.size(); + while( --k>=0 && strcmp(nm, file_probes[k]->name) ); + if( k < 0 ) return -1; + return file_probes[k]->armed; +} + +void Preferences::set_file_probe_armed(const char *nm, int v) +{ + int k = file_probes.size(); + while( --k>=0 && strcmp(nm, file_probes[k]->name) ); + if( k < 0 ) return; + file_probes[k]->armed = v; +} + diff --git a/cinelerra-5.1/cinelerra/preferences.h b/cinelerra-5.1/cinelerra/preferences.h index a54aa466..af401ac0 100644 --- a/cinelerra-5.1/cinelerra/preferences.h +++ b/cinelerra-5.1/cinelerra/preferences.h @@ -29,6 +29,7 @@ #include "maxchannels.h" #include "mutex.inc" #include "preferences.inc" +#include "probeprefs.inc" #include "shbtnprefs.inc" #include "videoconfig.inc" @@ -76,7 +77,9 @@ public: // Determined by /proc/cpuinfo and force_uniprocessor. // interactive forces it to ignore force_uniprocessor int calculate_processors(int interactive = 0); - +// file probe armed + int get_file_probe_armed(const char *nm); + void set_file_probe_armed(const char *nm, int v); // ================================= Performance ================================ // directory to look in for indexes char index_directory[BCTEXTLEN]; @@ -99,8 +102,6 @@ public: int processors; // Number of processors for interactive operations. int real_processors; -// ffmpeg probes early/late during File::open_file read - int ffmpeg_early_probe; // ffmpeg builds marker indexes as it builds idx files int ffmpeg_marker_indexes; // warning @@ -153,6 +154,8 @@ public: char android_pin[BCSTRLEN]; // shell cmd line menu ops ArrayList shbtn_prefs; +// file open probe order + ArrayList file_probes; // ====================================== Plugin Set ============================== char plugin_dir[BCTEXTLEN]; diff --git a/cinelerra-5.1/cinelerra/preferencesthread.C b/cinelerra-5.1/cinelerra/preferencesthread.C index dd8e9c51..4d1a4156 100644 --- a/cinelerra-5.1/cinelerra/preferencesthread.C +++ b/cinelerra-5.1/cinelerra/preferencesthread.C @@ -229,8 +229,9 @@ int PreferencesThread::apply_settings() } mwindow->reset_android_remote(); - mwindow->gui->ffmpeg_toggle->update(mwindow->preferences->ffmpeg_early_probe); - mwindow->gui->ffmpeg_toggle->set_tooltip( mwindow->preferences->ffmpeg_early_probe ? + int ffmpeg_early_probe = mwindow->preferences->get_file_probe_armed("FFPMEG_Early"); + mwindow->gui->ffmpeg_toggle->update(ffmpeg_early_probe); + mwindow->gui->ffmpeg_toggle->set_tooltip(ffmpeg_early_probe ? _("Try FFMpeg first") : _("Try FFMpeg last") ); mwindow->gui->mainshbtns->load(mwindow->preferences); double tc_position = diff --git a/cinelerra-5.1/cinelerra/probeprefs.C b/cinelerra-5.1/cinelerra/probeprefs.C new file mode 100644 index 00000000..dcce262e --- /dev/null +++ b/cinelerra-5.1/cinelerra/probeprefs.C @@ -0,0 +1,270 @@ +#include "bcwindowbase.h" +#include "bcdisplayinfo.h" +#include "bcdialog.h" +#include "language.h" +#include "mainerror.h" +#include "mwindow.h" +#include "probeprefs.h" +#include "preferences.h" +#include "preferencesthread.h" +#include "theme.h" + +#include + +ProbePref::ProbePref(const char *nm, int armed) +{ + strncpy(name, nm, sizeof(name)); + this->armed = armed; +} + +ProbePref::~ProbePref() +{ +} + +FileProbeDialog::FileProbeDialog(PreferencesWindow *pwindow) + : BC_DialogThread() +{ + this->pwindow = pwindow; +} + +FileProbeDialog::~FileProbeDialog() +{ + close_window(); +} + +BC_Window* FileProbeDialog::new_gui() +{ + BC_DisplayInfo display_info; + int x = display_info.get_abs_cursor_x(); + int y = display_info.get_abs_cursor_y(); + + pb_window = new ProbeEditWindow(this, x, y); + pb_window->create_objects(); + return pb_window; +} + +void FileProbeDialog::handle_close_event(int result) +{ + pb_window = 0; +} + + +ProbeEditWindow::ProbeEditWindow(FileProbeDialog *pb_dialog, int x, int y) + : BC_Window(_(PROGRAM_NAME ": Probes"), x, y, 300, 200, 300, 200, 0, 0, 1) +{ + this->pb_dialog = pb_dialog; + probe_list = 0; + probe_up_button = 0; + probe_down_button = 0; + probe_enabled = 0; + pb_enabled = 0; + pb_disabled = 0; +} + +ProbeEditWindow::~ProbeEditWindow() +{ + delete pb_enabled; + delete pb_disabled; +} + +void ProbeEditWindow::create_objects() +{ + pb_enabled = new BC_Pixmap(this, + BC_WindowBase::get_resources()->listbox_up, + PIXMAP_ALPHA); + pb_disabled = new BC_Pixmap(this, + BC_WindowBase::get_resources()->listbox_dn, + PIXMAP_ALPHA); + Preferences *preferences = pb_dialog->pwindow->thread->preferences; + for( int i=0; ifile_probes.size(); ++i ) { + probe_items.append(new ProbePrefItem(this, preferences->file_probes[i])); + } + int x = 10, y = 10; + add_subwindow(probe_list = new ProbePrefList(this, x, y)); + y += probe_list->get_h(); + int x1 = x, y1 = y; + add_subwindow(probe_up_button = new ProbeUpButton(this, x1, y1)); + x1 += probe_up_button->get_w() + 10; + add_subwindow(probe_down_button = new ProbeDownButton(this, x1, y1)); + x1 += probe_down_button->get_w() + 10; + add_subwindow(probe_enabled = new ProbeEnabled(this, x1, y1)); + probe_enabled->disable(); + + add_subwindow(new ProbeEditOK(this)); + add_subwindow(new BC_CancelButton(this)); + + list_update(); + show_window(); +} + +ProbeEditOK::ProbeEditOK(ProbeEditWindow *pb_window) + : BC_OKButton(pb_window) +{ + this->pb_window = pb_window; +} + +ProbeEditOK::~ProbeEditOK() +{ +} + +int ProbeEditOK::handle_event() +{ + Preferences *preferences = pb_window->pb_dialog->pwindow->thread->preferences; + ArrayList &file_probes = preferences->file_probes; + file_probes.remove_all_objects(); + ArrayList &probe_items = pb_window->probe_items; + for( int i=0; iget_text(), item->armed)); + } + return BC_OKButton::handle_event(); +} + +int ProbeEditWindow::list_update() +{ +//for( int i=0; iget_text()); printf("\n"); + probe_list->update((ArrayList *)&probe_items, 0, 0, 1, + probe_list->get_xposition(), probe_list->get_yposition(), + probe_list->get_highlighted_item(), 1, 0); + probe_list->center_selection(); + return 1; +} + +ProbeUpButton::ProbeUpButton(ProbeEditWindow *pb_window, int x, int y) + : BC_GenericButton(x, y, _("Up")) +{ + this->pb_window = pb_window; +} + +ProbeUpButton::~ProbeUpButton() +{ +} + +int ProbeUpButton::handle_event() +{ + ArrayList &probe_items = pb_window->probe_items; + int n = probe_items.size(); + if( n > 1 ) { + ProbePrefItem **pitem = &probe_items[0], *item0 = *pitem; + for( int i=1; iget_selected() ) { + ProbePrefItem *t = item; item = *pitem; *pitem = t; + } + pitem = &item; + } + if( item0->get_selected() ) { + ProbePrefItem *t = *pitem; *pitem = item0; probe_items[0] = t; + } + } + pb_window->list_update(); + return 1; +} + +ProbeDownButton::ProbeDownButton(ProbeEditWindow *pb_window, int x, int y) + : BC_GenericButton(x, y, _("Down")) +{ + this->pb_window = pb_window; +} + +ProbeDownButton::~ProbeDownButton() +{ +} + +ProbeEnabled::ProbeEnabled(ProbeEditWindow *pb_window, int x, int y) + : BC_CheckBox(x, y, 0, _("Enabled")) +{ + this->pb_window = pb_window; +} +ProbeEnabled::~ProbeEnabled() +{ +} + +int ProbeEnabled::handle_event() +{ + ProbePrefItem *item = (ProbePrefItem *)pb_window->probe_list->get_selection(0,0); + if( item ) { + item->set_armed(get_value()); + pb_window->list_update(); + } + return 1; +} + +int ProbeDownButton::handle_event() +{ + ArrayList &probe_items = pb_window->probe_items; + int n = probe_items.size(); + if( n > 1 ) { + ProbePrefItem **pitem = &probe_items[n-1], *item1 = *pitem; + for( int i=n-1; --i>=0; ) { + ProbePrefItem *&item = probe_items[i]; + if( item->get_selected() ) { + ProbePrefItem *t = item; item = *pitem; *pitem = t; + } + pitem = &item; + } + if( item1->get_selected() ) { + ProbePrefItem *t = *pitem; *pitem = item1; probe_items[n-1] = t; + } + } + pb_window->list_update(); + return 1; +} + +ProbePrefItem::ProbePrefItem(ProbeEditWindow *pb_window, ProbePref *pref) + : BC_ListBoxItem(pref->name, pref->armed ? + pb_window->pb_enabled : pb_window->pb_disabled) +{ + this->pb_window = pb_window; + this->armed = pref->armed; +} + +ProbePrefItem::~ProbePrefItem() +{ +} + +void ProbePrefItem::set_armed(int armed) +{ + this->armed = armed; + set_icon(armed ? pb_window->pb_enabled : pb_window->pb_disabled); +} + +ProbePrefList::ProbePrefList(ProbeEditWindow *pb_window, int x, int y) + : BC_ListBox(x, y, pb_window->get_w()-x-10, pb_window->get_h()-y-80, LISTBOX_ICON_LIST, + (ArrayList*) &pb_window->probe_items, 0, 0) +{ + this->pb_window = pb_window; +} + +ProbePrefList::~ProbePrefList() +{ +} + +int ProbePrefList::selection_changed() +{ + ProbePrefItem *item = (ProbePrefItem *)pb_window->probe_list->get_selection(0,0); + if( item ) { + pb_window->probe_enabled->set_value(item->armed); + pb_window->probe_enabled->enable(); + } + else { + pb_window->probe_enabled->set_value(0); + pb_window->probe_enabled->disable(); + } + pb_window->list_update(); + return 1; +} + +int ProbePrefList::handle_event() +{ + if( get_double_click() && get_buttonpress() == 1 ) { + ProbePrefItem *item = (ProbePrefItem *)get_selection(0,0); + int armed = item->armed ? 0 : 1; + pb_window->probe_enabled->enable(); + pb_window->probe_enabled->set_value(armed); + item->set_armed(armed); + pb_window->list_update(); + } + return 1; +} + diff --git a/cinelerra-5.1/cinelerra/probeprefs.h b/cinelerra-5.1/cinelerra/probeprefs.h new file mode 100644 index 00000000..e7fb5bf7 --- /dev/null +++ b/cinelerra-5.1/cinelerra/probeprefs.h @@ -0,0 +1,117 @@ +#ifndef __PROBEPREFS_H__ +#define __PROBEPREFS_H__ + +#include "bcwindowbase.h" +#include "bcbutton.h" +#include "bcdialog.h" +#include "bclistbox.h" +#include "bclistboxitem.h" +#include "bctoggle.h" +#include "preferences.inc" +#include "preferencesthread.inc" +#include "thread.h" +#include "probeprefs.inc" + + +class FileProbeDialog : public BC_DialogThread +{ +public: + PreferencesWindow *pwindow; + + ProbeEditWindow *pb_window; + BC_Window* new_gui(); + void handle_close_event(int result); + + FileProbeDialog(PreferencesWindow *pwindow); + ~FileProbeDialog(); +}; + +class ProbePref +{ +public: + char name[BCSTRLEN]; + int armed; + + ProbePref(const char *nm, int armed); + ~ProbePref(); +}; + +class ProbeUpButton : public BC_GenericButton { +public: + ProbeEditWindow *pb_window; + int handle_event(); + + ProbeUpButton(ProbeEditWindow *pb_window, int x, int y); + ~ProbeUpButton(); +}; + +class ProbeDownButton : public BC_GenericButton { +public: + ProbeEditWindow *pb_window; + int handle_event(); + + ProbeDownButton(ProbeEditWindow *pb_window, int x, int y); + ~ProbeDownButton(); +}; + +class ProbeEnabled : public BC_CheckBox +{ +public: + ProbeEditWindow *pb_window; + int handle_event(); + + ProbeEnabled(ProbeEditWindow *pb_window, int x, int y); + ~ProbeEnabled(); +}; + +class ProbePrefItem : public BC_ListBoxItem { +public: + ProbeEditWindow *pb_window; + int armed; + void set_armed(int armed); + + ProbePrefItem(ProbeEditWindow *pb_window, ProbePref *pref); + ~ProbePrefItem(); +}; + +class ProbePrefList : public BC_ListBox +{ +public: + ProbeEditWindow *pb_window; + int handle_event(); + int selection_changed(); + + ProbePrefList(ProbeEditWindow *pb_window, int x, int y); + ~ProbePrefList(); +}; + +class ProbeEditOK : public BC_OKButton +{ +public: + ProbeEditWindow *pb_window; + int handle_event(); + + ProbeEditOK(ProbeEditWindow *pb_window); + ~ProbeEditOK(); +}; + +class ProbeEditWindow : public BC_Window +{ +public: + ProbeUpButton *probe_up_button; + ProbeDownButton *probe_down_button; + ProbeEnabled *probe_enabled; + ArrayList probe_items; + ProbePrefList *probe_list; + BC_Pixmap *pb_enabled, *pb_disabled; + + void create_objects(); + int list_update(); + + ProbeEditWindow(FileProbeDialog *pb_dialog, int x, int y); + ~ProbeEditWindow(); + + FileProbeDialog *pb_dialog; +}; + +#endif diff --git a/cinelerra-5.1/cinelerra/probeprefs.inc b/cinelerra-5.1/cinelerra/probeprefs.inc new file mode 100644 index 00000000..e20e0b48 --- /dev/null +++ b/cinelerra-5.1/cinelerra/probeprefs.inc @@ -0,0 +1,13 @@ +#ifndef __PROBEPREFS_INC__ +#define __PROBEPREFS_INC__ + +class FileProbeDialog; +class ProbePref; +class ProbeUpButton; +class ProbeDownButton; +class ProbePrefItem; +class ProbePrefList; +class ProbeEditOK; +class ProbeEditWindow; + +#endif diff --git a/cinelerra-5.1/thirdparty/downloads.txt b/cinelerra-5.1/thirdparty/downloads.txt index 30e16771..9e8735ca 100644 --- a/cinelerra-5.1/thirdparty/downloads.txt +++ b/cinelerra-5.1/thirdparty/downloads.txt @@ -1,3 +1,4 @@ +https://www.cybercom.net/~dcoffin/dcraw/dcraw.c http://download-mirror.savannah.gnu.org/releases//openexr/ilmbase-2.2.0.tar.gz http://gnu.mirrors.pair.com/savannah/savannah//openexr/openexr-2.2.0.tar.gz https://sourceforge.net/projects/opencvlibrary/files/latest/download?source=directory = 3.2.0