diff options
Diffstat (limited to 'converter/other/cameratopam')
-rw-r--r-- | converter/other/cameratopam/Makefile | 22 | ||||
-rw-r--r-- | converter/other/cameratopam/camera.c | 375 | ||||
-rw-r--r-- | converter/other/cameratopam/camera.h | 95 | ||||
-rw-r--r-- | converter/other/cameratopam/cameratopam.c | 1237 | ||||
-rw-r--r-- | converter/other/cameratopam/cameratopam.h | 6 | ||||
-rw-r--r-- | converter/other/cameratopam/canon.c | 6 | ||||
-rw-r--r-- | converter/other/cameratopam/canon.h | 11 | ||||
-rw-r--r-- | converter/other/cameratopam/dng.c | 151 | ||||
-rw-r--r-- | converter/other/cameratopam/dng.h | 4 | ||||
-rw-r--r-- | converter/other/cameratopam/foveon.c | 37 | ||||
-rw-r--r-- | converter/other/cameratopam/foveon.h | 13 | ||||
-rw-r--r-- | converter/other/cameratopam/global_variables.h | 1 | ||||
-rw-r--r-- | converter/other/cameratopam/identify.c | 2256 | ||||
-rw-r--r-- | converter/other/cameratopam/identify.h | 4 | ||||
-rw-r--r-- | converter/other/cameratopam/ljpeg.c | 238 | ||||
-rw-r--r-- | converter/other/cameratopam/ljpeg.h | 14 |
16 files changed, 2322 insertions, 2148 deletions
diff --git a/converter/other/cameratopam/Makefile b/converter/other/cameratopam/Makefile index 20a95aa2..d6207aea 100644 --- a/converter/other/cameratopam/Makefile +++ b/converter/other/cameratopam/Makefile @@ -9,7 +9,7 @@ EXTERN_INCLUDES = ifneq ($(JPEGLIB),NONE) ifneq ($(JPEGHDR_DIR)x,x) EXTERN_INCLUDES += -I$(JPEGHDR_DIR) - CFLAGS += -DHAVE_JPEG + HAVE_JPEG_DEFINE = -DHAVE_JPEG endif endif @@ -19,20 +19,20 @@ include $(BUILDDIR)/config.mk .PHONY: all all: cameratopam -OBJECTS = util.o identify.o cameratopam.o camera.o foveon.o decode.o \ +ADDL_OBJECTS = util.o identify.o camera.o foveon.o decode.o \ canon.o ljpeg.o dng.o -MERGE_OBJECTS = +OBJECTS = cameratopam.o $(ADDL_OBJECTS) -BINARIES = cameratopam -MERGEBINARIES = +camera.o camera.o2: CFLAGS_TARGET = $(HAVE_JPEG_DEFINE) + +MERGE_OBJECTS = cameratopam.o2 $(ADDL_OBJECTS) + +PORTBINARIES = cameratopam +BINARIES = $(PORTBINARIES) +MERGEBINARIES = cameratopam SCRIPTS = include $(SRCDIR)/common.mk -cameratopam: $(OBJECTS) $(NETPBMLIB) $(LIBOPT) - $(LD) -o $@ \ - $(OBJECTS) $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR)) \ - $(MATHLIB) $(LDFLAGS) $(LDLIBS) \ - $(RPATH) $(LADD) - +cameratopam: $(ADDL_OBJECTS) diff --git a/converter/other/cameratopam/camera.c b/converter/other/cameratopam/camera.c index 98d6d37a..a1adba95 100644 --- a/converter/other/cameratopam/camera.c +++ b/converter/other/cameratopam/camera.c @@ -12,10 +12,13 @@ #include <jpeglib.h> #endif +#include "pm_config.h" #include "pm.h" #include "mallocvar.h" +#include "pm_c_util.h" #include "global_variables.h" +#include "cameratopam.h" #include "util.h" #include "decode.h" #include "bayer.h" @@ -54,67 +57,76 @@ merror (const void *ptr, const char *where) static void -adobe_copy_pixel (int row, int col, unsigned short **rp, bool use_secondary) -{ - unsigned r=row, c=col; - - if (fuji_secondary && use_secondary) (*rp)++; - if (filters) { - if (fuji_width) { - r = row + fuji_width - 1 - (col >> 1); - c = row + ((col+1) >> 1); - } - if (r < height && c < width) - BAYER(r,c) = **rp < 0x1000 ? curve[**rp] : **rp; - *rp += 1 + fuji_secondary; - } else - for (c=0; c < tiff_samples; c++) { - image[row*width+col][c] = **rp < 0x1000 ? curve[**rp] : **rp; - (*rp)++; +adobeCopyPixel(Image const image, + unsigned int const row, + unsigned int const col, + unsigned short ** const rp, + bool const useSecondary) { + + unsigned r=row, c=col; + + if (fuji_secondary && useSecondary) + ++(*rp); + if (filters) { + if (fuji_width) { + r = row + fuji_width - 1 - (col >> 1); + c = row + ((col+1) >> 1); + } + if (r < height && c < width) + BAYER(r,c) = **rp < 0x1000 ? curve[**rp] : **rp; + *rp += 1 + fuji_secondary; + } else { + unsigned int c; + for (c = 0; c < tiff_samples; ++c) { + image[row*width+col][c] = **rp < 0x1000 ? curve[**rp] : **rp; + ++(*rp); + } } - if (fuji_secondary && use_secondary) (*rp)--; + if (fuji_secondary && useSecondary) + --(*rp); } void -adobe_dng_load_raw_lj() -{ - int save, twide, trow=0, tcol=0, jrow, jcol; - struct jhead jh; - unsigned short *rp; +adobe_dng_load_raw_lj(Image const image) { - while (1) { - save = ftell(ifp); - fseek (ifp, get4(ifp), SEEK_SET); - if (!ljpeg_start (ifp, &jh)) break; - if (trow >= raw_height) break; - if (jh.high > raw_height-trow) - jh.high = raw_height-trow; - twide = jh.wide; - if (filters) twide *= jh.clrs; - else colors = jh.clrs; - if (fuji_secondary) twide /= 2; - if (twide > raw_width-tcol) - twide = raw_width-tcol; - - for (jrow=0; jrow < jh.high; jrow++) { - ljpeg_row (&jh); - for (rp=jh.row, jcol=0; jcol < twide; jcol++) - adobe_copy_pixel (trow+jrow, tcol+jcol, &rp, use_secondary); - } - fseek (ifp, save+4, SEEK_SET); - if ((tcol += twide) >= raw_width) { - tcol = 0; - trow += jh.high; + int save, twide, trow=0, tcol=0, jrow, jcol; + struct jhead jh; + unsigned short *rp; + + while (1) { + save = ftell(ifp); + fseek (ifp, get4(ifp), SEEK_SET); + if (!ljpeg_start (ifp, &jh)) break; + if (trow >= raw_height) break; + if (jh.high > raw_height-trow) + jh.high = raw_height-trow; + twide = jh.wide; + if (filters) twide *= jh.clrs; + else colors = jh.clrs; + if (fuji_secondary) twide /= 2; + if (twide > raw_width-tcol) + twide = raw_width-tcol; + + for (jrow=0; jrow < jh.high; jrow++) { + ljpeg_row(ifp, &jh); + for (rp=jh.row, jcol=0; jcol < twide; jcol++) + adobeCopyPixel(image, + trow+jrow, tcol+jcol, &rp, use_secondary); + } + fseek (ifp, save+4, SEEK_SET); + if ((tcol += twide) >= raw_width) { + tcol = 0; + trow += jh.high; + } + free (jh.row); } - free (jh.row); - } } void -adobe_dng_load_raw_nc() -{ +adobe_dng_load_raw_nc(Image const image) { + unsigned short *pixel, *rp; int row, col; @@ -123,7 +135,7 @@ adobe_dng_load_raw_nc() for (row=0; row < raw_height; row++) { read_shorts (ifp, pixel, raw_width * tiff_samples); for (rp=pixel, col=0; col < raw_width; col++) - adobe_copy_pixel (row, col, &rp, use_secondary); + adobeCopyPixel(image, row, col, &rp, use_secondary); } free (pixel); } @@ -133,8 +145,8 @@ adobe_dng_load_raw_nc() static int nikon_curve_offset; void -nikon_compressed_load_raw(void) -{ +nikon_compressed_load_raw(Image const image) { + static const unsigned char nikon_tree[] = { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, 5,4,3,6,2,7,1,0,8,9,11,10,12 @@ -158,7 +170,7 @@ nikon_compressed_load_raw(void) for (row=0; row < height; row++) for (col=0; col < raw_width; col++) { - diff = ljpeg_diff (first_decode); + diff = ljpeg_diff (ifp, first_decode); if (col < 2) { i = 2*(row & 1) + (col & 1); vpred[i] += diff; @@ -175,8 +187,8 @@ nikon_compressed_load_raw(void) } void -nikon_load_raw() -{ +nikon_load_raw(Image const image) { + int irow, row, col, i; getbits(ifp, -1); @@ -293,8 +305,8 @@ minolta_z2() } void -nikon_e2100_load_raw() -{ +nikon_e2100_load_raw(Image const image) { + unsigned char data[3432], *dp; unsigned short pixel[2288], *pix; int row, col; @@ -321,8 +333,8 @@ nikon_e2100_load_raw() } void -nikon_e950_load_raw() -{ +nikon_e950_load_raw(Image const image) { + int irow, row, col; getbits(ifp, -1); @@ -340,8 +352,7 @@ nikon_e950_load_raw() The Fuji Super CCD is just a Bayer grid rotated 45 degrees. */ void -fuji_s2_load_raw() -{ +fuji_s2_load_raw(Image const image) { unsigned short pixel[2944]; int row, col, r, c; @@ -357,8 +368,7 @@ fuji_s2_load_raw() } void -fuji_s3_load_raw() -{ +fuji_s3_load_raw(Image const image) { unsigned short pixel[4352]; int row, col, r, c; @@ -373,42 +383,52 @@ fuji_s3_load_raw() } } -static void fuji_common_load_raw (int ncol, int icol, int nrow) -{ - unsigned short pixel[2048]; - int row, col, r, c; - - for (row=0; row < nrow; row++) { - read_shorts(ifp, pixel, ncol); - for (col=0; col <= icol; col++) { - r = icol - col + (row >> 1); - c = col + ((row+1) >> 1); - BAYER(r,c) = pixel[col]; +static void +fuji_common_load_raw(Image const image, + unsigned int const ncol, + unsigned int const icol, + unsigned int const nrow) { + + unsigned short pixel[2048]; + unsigned int row; + + for (row = 0; row < nrow; ++row) { + unsigned int col; + read_shorts(ifp, pixel, ncol); + for (col = 0; col <= icol; ++col) { + int const r = icol - col + (row >> 1); + int const c = col + ((row+1) >> 1); + BAYER(r,c) = pixel[col]; + } } - } } + + void -fuji_s5000_load_raw() -{ +fuji_s5000_load_raw(Image const image) { + fseek (ifp, (1472*4+24)*2, SEEK_CUR); - fuji_common_load_raw (1472, 1423, 2152); + fuji_common_load_raw(image, 1472, 1423, 2152); } + + void -fuji_s7000_load_raw() -{ - fuji_common_load_raw (2048, 2047, 3080); +fuji_s7000_load_raw(Image const image) { + + fuji_common_load_raw(image, 2048, 2047, 3080); } + + /* The Fuji Super CCD SR has two photodiodes for each pixel. The secondary has about 1/16 the sensitivity of the primary, but this ratio may vary. */ void -fuji_f700_load_raw() -{ +fuji_f700_load_raw(Image const image) { unsigned short pixel[2944]; int row, col, r, c, val; @@ -424,8 +444,7 @@ fuji_f700_load_raw() } void -rollei_load_raw() -{ +rollei_load_raw(Image const image) { unsigned char pixel[10]; unsigned iten=0, isix, i, buffer=0, row, col, todo[16]; @@ -451,8 +470,7 @@ rollei_load_raw() } void -phase_one_load_raw() -{ +phase_one_load_raw(Image const image) { int row, col, a, b; unsigned short *pixel, akey, bkey; @@ -478,8 +496,7 @@ phase_one_load_raw() } void -ixpress_load_raw() -{ +ixpress_load_raw(Image const image) { unsigned short pixel[4090]; int row, col; @@ -493,8 +510,7 @@ ixpress_load_raw() } void -leaf_load_raw() -{ +leaf_load_raw(Image const image) { unsigned short *pixel; int r, c, row, col; @@ -513,8 +529,7 @@ leaf_load_raw() For this function only, raw_width is in bytes, not pixels! */ void -packed_12_load_raw() -{ +packed_12_load_raw(Image const image) { int row, col; getbits(ifp, -1); @@ -527,8 +542,7 @@ packed_12_load_raw() } void -unpacked_load_raw() -{ +unpacked_load_raw(Image const image) { unsigned short *pixel; int row, col; @@ -543,8 +557,7 @@ unpacked_load_raw() } void -olympus_e300_load_raw() -{ +olympus_e300_load_raw(Image const image) { unsigned char *data, *dp; unsigned short *pixel, *pix; int dwide, row, col; @@ -567,8 +580,7 @@ olympus_e300_load_raw() } void -olympus_cseries_load_raw() -{ +olympus_cseries_load_raw(Image const image) { int irow, row, col; for (irow=0; irow < height; irow++) { @@ -583,8 +595,7 @@ olympus_cseries_load_raw() } void -eight_bit_load_raw() -{ +eight_bit_load_raw(Image const image) { unsigned char *pixel; int row, col; @@ -600,8 +611,7 @@ eight_bit_load_raw() } void -casio_qv5700_load_raw() -{ +casio_qv5700_load_raw(Image const image) { unsigned char data[3232], *dp; unsigned short pixel[2576], *pix; int row, col; @@ -621,8 +631,7 @@ casio_qv5700_load_raw() } void -nucore_load_raw() -{ +nucore_load_raw(Image const image) { unsigned short *pixel; int irow, row, col; @@ -684,79 +693,91 @@ static int radc_token (int tree) : (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4) void -kodak_radc_load_raw() -{ - 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]; +kodak_radc_load_raw(Image const image) { + int row, col, tree, nreps, rep, step, c, s, r, x, y, val; + unsigned int i; + short last[3] = { 16,16,16 }, mul[3], buf[3][3][386]; - init_decoder(); - getbits(ifp, -1); - for (i=0; i < sizeof(buf)/sizeof(short); i++) - buf[0][0][i] = 2048; - for (row=0; row < height; row+=4) { - for (i=0; i < 3; i++) - mul[i] = getbits(ifp, 6); - FORC3 { - val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c]; - s = val > 65564 ? 10:12; - x = ~(-1 << (s-1)); - val <<= 12-s; - for (i=0; i < sizeof(buf[0])/sizeof(short); i++) - buf[c][0][i] = (buf[c][0][i] * val + x) >> s; - last[c] = mul[c]; - for (r=0; r <= !c; r++) { - buf[c][1][width/2] = buf[c][2][width/2] = mul[c] << 7; - for (tree=1, col=width/2; col > 0; ) { - if ((tree = radc_token(tree))) { - col -= 2; - if (tree == 8) - FORYX buf[c][y][x] = radc_token(tree+10) * mul[c]; - else - FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR; - } else - do { - nreps = (col > 2) ? radc_token(9) + 1 : 1; - for (rep=0; rep < 8 && rep < nreps && col > 0; rep++) { - col -= 2; - FORYX buf[c][y][x] = PREDICTOR; - if (rep & 1) { - step = radc_token(10) << 4; - FORYX buf[c][y][x] += step; + init_decoder(); + getbits(ifp, -1); + for (i = 0; i < ARRAY_SIZE(buf); ++i) { + unsigned int j; + for (j = 0; j < ARRAY_SIZE(buf[0]); ++j) { + unsigned int k; + for (k = 0; k < ARRAY_SIZE(buf[0][0]); ++k) + buf[i][j][k] = 2048; } - } - } while (nreps == 9); - } - for (y=0; y < 2; y++) - for (x=0; x < width/2; x++) { - val = (buf[c][y+1][x] << 4) / mul[c]; - if (val < 0) val = 0; - if (c) - BAYER(row+y*2+c-1,x*2+2-c) = val; - else - BAYER(row+r*2+y,x*2+y) = val; - } - memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c); - } - } - for (y=row; y < row+4; y++) - for (x=0; x < width; x++) - if ((x+y) & 1) { - val = (BAYER(y,x)-2048)*2 + (BAYER(y,x-1)+BAYER(y,x+1))/2; - if (val < 0) val = 0; - BAYER(y,x) = val; } - } - maximum = 0x1fff; /* wild guess */ + for (row=0; row < height; row+=4) { + unsigned int i; + for (i = 0; i < 3; ++i) + mul[i] = getbits(ifp, 6); + FORC3 { + val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c]; + s = val > 65564 ? 10:12; + x = ~(-1 << (s-1)); + val <<= 12-s; + for (i=0; i < ARRAY_SIZE(buf[c][0]); i++) + buf[c][0][i] = (buf[c][0][i] * val + x) >> s; + last[c] = mul[c]; + for (r=0; r <= !c; r++) { + buf[c][1][width/2] = buf[c][2][width/2] = mul[c] << 7; + for (tree=1, col=width/2; col > 0; ) { + if ((tree = radc_token(tree))) { + col -= 2; + if (tree == 8) + FORYX buf[c][y][x] = + radc_token(tree+10) * mul[c]; + else + FORYX buf[c][y][x] = + radc_token(tree+10) * 16 + PREDICTOR; + } else + do { + nreps = (col > 2) ? radc_token(9) + 1 : 1; + for (rep=0; + rep < 8 && rep < nreps && col > 0; + rep++) { + col -= 2; + FORYX buf[c][y][x] = PREDICTOR; + if (rep & 1) { + step = radc_token(10) << 4; + FORYX buf[c][y][x] += step; + } + } + } while (nreps == 9); + } + for (y=0; y < 2; y++) + for (x=0; x < width/2; x++) { + val = (buf[c][y+1][x] << 4) / mul[c]; + if (val < 0) val = 0; + if (c) + BAYER(row+y*2+c-1,x*2+2-c) = val; + else + BAYER(row+r*2+y,x*2+y) = val; + } + memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c); + } + } + for (y=row; y < row+4; y++) + for (x=0; x < width; x++) + if ((x+y) & 1) { + val = (BAYER(y,x)-2048)*2 + (BAYER(y,x-1)+BAYER(y,x+1))/2; + if (val < 0) val = 0; + BAYER(y,x) = val; + } + } + maximum = 0x1fff; /* wild guess */ } #undef FORYX #undef PREDICTOR #ifndef HAVE_JPEG -void kodak_jpeg_load_raw() {} +void +kodak_jpeg_load_raw(Image const Image) {} #else -static boolean +static bool fill_input_buffer (j_decompress_ptr cinfo) { static char jpeg_buffer[4096]; @@ -770,7 +791,7 @@ fill_input_buffer (j_decompress_ptr cinfo) } void -kodak_jpeg_load_raw() +kodak_jpeg_load_raw(Image const image) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; @@ -811,7 +832,7 @@ kodak_jpeg_load_raw() #endif void -kodak_dc120_load_raw() +kodak_dc120_load_raw(Image const image) { static const int mul[4] = { 162, 192, 187, 92 }; static const int add[4] = { 0, 636, 424, 212 }; @@ -847,7 +868,7 @@ kodak_dc20_coeff (float const juice) } void -kodak_easy_load_raw() +kodak_easy_load_raw(Image const image) { unsigned char *pixel; unsigned row, col, icol; @@ -875,7 +896,7 @@ kodak_easy_load_raw() } void -kodak_compressed_load_raw() +kodak_compressed_load_raw(Image const image) { unsigned char c, blen[256]; unsigned short raw[6]; @@ -939,7 +960,7 @@ kodak_compressed_load_raw() } void -kodak_yuv_load_raw() +kodak_yuv_load_raw(Image const image) { unsigned char c, blen[384]; unsigned row, col, len, bits=0; @@ -1030,7 +1051,7 @@ static void sony_decrypt (unsigned *data, int len, int start, int key) } void -sony_load_raw() +sony_load_raw(Image const image) { unsigned char head[40]; struct pixel { @@ -1298,12 +1319,6 @@ parse_mos(FILE * const ifp, fread (data, 1, 40, ifp); skip = get4(ifp); from = ftell(ifp); -#ifdef USE_LCMS - if (!strcmp(data,"icc_camera_profile")) { - profile_length = skip; - profile_offset = from; - } -#endif if (!strcmp(data,"NeutObj_neutrals")) { for (i=0; i < 4; i++) fscanf (ifp, "%d", neut+i); diff --git a/converter/other/cameratopam/camera.h b/converter/other/cameratopam/camera.h index a1e884cf..02c3f2af 100644 --- a/converter/other/cameratopam/camera.h +++ b/converter/other/cameratopam/camera.h @@ -1,5 +1,10 @@ +#ifndef CAMERA_H_INCLUDED +#define CAMERA_H_INCLUDED + #include <stdio.h> +#include "cameratopam.h" + void parse_ciff(FILE * const ifp, int const offset, @@ -21,20 +26,18 @@ void parse_mos(FILE * const ifp, int const offset); -void -adobe_dng_load_raw_lj(void); +typedef void LoadRawFn(Image const image); -void -adobe_dng_load_raw_nc(void); +LoadRawFn adobe_dng_load_raw_lj; + +LoadRawFn adobe_dng_load_raw_nc; int nikon_is_compressed(void); -void -nikon_compressed_load_raw(void); +LoadRawFn nikon_compressed_load_raw; -void -nikon_e950_load_raw(void); +LoadRawFn nikon_e950_load_raw; void nikon_e950_coeff(void); @@ -45,87 +48,63 @@ nikon_e990(void); int nikon_e2100(void); -void -nikon_e2100_load_raw(void); +LoadRawFn nikon_e2100_load_raw; int minolta_z2(void); -void -fuji_s2_load_raw(void); +LoadRawFn fuji_s2_load_raw; -void -fuji_s3_load_raw(void); +LoadRawFn fuji_s3_load_raw; -void -fuji_s5000_load_raw(void); +LoadRawFn fuji_s5000_load_raw; -void -unpacked_load_raw(void); +LoadRawFn unpacked_load_raw; -void -fuji_s7000_load_raw(void); +LoadRawFn fuji_s7000_load_raw; -void -fuji_f700_load_raw(void); +LoadRawFn fuji_f700_load_raw; -void -packed_12_load_raw(void); +LoadRawFn packed_12_load_raw; -void -eight_bit_load_raw(void); +LoadRawFn eight_bit_load_raw; -void -phase_one_load_raw(void); +LoadRawFn phase_one_load_raw; -void -ixpress_load_raw(void); +LoadRawFn ixpress_load_raw; -void -leaf_load_raw(void); +LoadRawFn leaf_load_raw; -void -olympus_e300_load_raw(void); +LoadRawFn olympus_e300_load_raw; -void -olympus_cseries_load_raw(void); +LoadRawFn olympus_cseries_load_raw; -void -sony_load_raw(void); +LoadRawFn sony_load_raw; -void -kodak_easy_load_raw(void); +LoadRawFn kodak_easy_load_raw; -void -kodak_compressed_load_raw(void); +LoadRawFn kodak_compressed_load_raw; -void -kodak_yuv_load_raw(void); +LoadRawFn kodak_yuv_load_raw; void kodak_dc20_coeff (float const juice); -void -kodak_radc_load_raw(void); +LoadRawFn kodak_radc_load_raw; -void -kodak_jpeg_load_raw(void); +LoadRawFn kodak_jpeg_load_raw; -void -kodak_dc120_load_raw(void); +LoadRawFn kodak_dc120_load_raw; -void -rollei_load_raw(void); +LoadRawFn rollei_load_raw; -void -casio_qv5700_load_raw(void); +LoadRawFn casio_qv5700_load_raw; -void -nucore_load_raw(void); +LoadRawFn nucore_load_raw; -void -nikon_load_raw(void); +LoadRawFn nikon_load_raw; int pentax_optio33(void); +#endif diff --git a/converter/other/cameratopam/cameratopam.c b/converter/other/cameratopam/cameratopam.c index b2d6da9b..ec33dd31 100644 --- a/converter/other/cameratopam/cameratopam.c +++ b/converter/other/cameratopam/cameratopam.c @@ -7,8 +7,11 @@ */ -#define _BSD_SOURCE 1 /* Make sure string.h contains strcasecmp() */ -#define _XOPEN_SOURCE /* Make sure unistd.h contains swab() */ +#define _BSD_SOURCE 1 /* Make sure string.h contains strdup() */ +#define _XOPEN_SOURCE 500 + /* Make sure unistd.h contains swab(), string.h constains strdup() */ + +#include "pm_config.h" #include <ctype.h> #include <unistd.h> @@ -23,10 +26,10 @@ #include <stdlib.h> #include <string.h> -#ifdef __CYGWIN__ +#ifdef HAVE_IO_H #include <io.h> #endif -#if !defined(WIN32) || defined(__CYGWIN__) +#if !MSVCRT #include <unistd.h> #endif @@ -36,6 +39,7 @@ #include "pam.h" #include "global_variables.h" +#include "cameratopam.h" #include "util.h" #include "decode.h" #include "identify.h" @@ -59,22 +63,19 @@ int height, width, fuji_width, colors, tiff_samples; int black, maximum, clip_max; int iheight, iwidth, shrink; int is_dng, is_canon, is_foveon, use_coeff, use_gamma; -int trim, flip, xmag, ymag; +int flip, xmag, ymag; int zero_after_ff; unsigned filters; -unsigned short (*image)[4], white[8][8], curve[0x1000]; +unsigned short white[8][8]; +unsigned short curve[0x1000]; int fuji_secondary; -float cam_mul[4], pre_mul[4], coeff[3][4]; +float cam_mul[4], coeff[3][4]; +float pre_mul[4]; int histogram[3][0x2000]; jmp_buf failure; -bool use_secondary; +int use_secondary; bool verbose; -#ifdef USE_LCMS -#include <lcms.h> -int profile_offset, profile_length; -#endif - #define CLASS #define FORC3 for (c=0; c < 3; c++) @@ -86,7 +87,7 @@ static void CLASS merror (const void *ptr, const char *where) pm_error ("Out of memory in %s", where); } -struct cmdlineInfo { +struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ @@ -110,11 +111,11 @@ struct cmdlineInfo { }; -static struct cmdlineInfo cmdline; +static struct CmdlineInfo cmdline; static void parseCommandLine(int argc, char ** argv, - struct cmdlineInfo *cmdlineP) { + struct CmdlineInfo *cmdlineP) { /*---------------------------------------------------------------------------- Note that many of the strings that this function returns in the *cmdlineP structure are actually in the supplied argv array. And @@ -167,7 +168,7 @@ parseCommandLine(int argc, char ** argv, OPTENT3(0, "linear", OPT_FLAG, NULL, &cmdlineP->linear, 0); - optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0); if (!brightSpec) cmdlineP->bright = 1.0; @@ -189,615 +190,694 @@ parseCommandLine(int argc, char ** argv, } -/* - Seach from the current directory up to the root looking for - a ".badpixels" file, and fix those pixels now. - */ -static void CLASS bad_pixels() -{ - FILE *fp=NULL; - char *fname, *cp, line[128]; - int len, time, row, col, r, c, rad, tot, n, fixed=0; - - if (!filters) return; - for (len=16 ; ; len *= 2) { - fname = malloc (len); - if (!fname) return; - if (getcwd (fname, len-12)) break; - free (fname); - if (errno != ERANGE) return; - } -#ifdef WIN32 - if (fname[1] == ':') - memmove (fname, fname+2, len-2); - for (cp=fname; *cp; cp++) - if (*cp == '\\') *cp = '/'; + +static void CLASS +fixBadPixels(Image const image) { +/*---------------------------------------------------------------------------- + Search from the current directory up to the root looking for + a ".badpixels" file, and fix those pixels now. +-----------------------------------------------------------------------------*/ + if (filters) { + FILE *fp; + char *fname, *cp, line[128]; + int len, time, row, col, rad, tot, n, fixed=0; + + for (len=16 ; ; len *= 2) { + fname = malloc (len); + if (!fname) return; + if (getcwd (fname, len-12)) + break; + free (fname); + if (errno != ERANGE) + return; + } +#if MSVCRT + if (fname[1] == ':') + memmove (fname, fname+2, len-2); + for (cp=fname; *cp; cp++) + if (*cp == '\\') *cp = '/'; #endif - cp = fname + strlen(fname); - if (cp[-1] == '/') cp--; - while (*fname == '/') { - strcpy (cp, "/.badpixels"); - if ((fp = fopen (fname, "r"))) break; - if (cp == fname) break; - while (*--cp != '/'); - } - free (fname); - if (!fp) return; - while (fgets (line, 128, fp)) { - cp = strchr (line, '#'); - if (cp) *cp = 0; - if (sscanf (line, "%d %d %d", &col, &row, &time) != 3) continue; - if ((unsigned) col >= width || (unsigned) row >= height) continue; - if (time > timestamp) continue; - for (tot=n=0, rad=1; rad < 3 && n==0; rad++) - for (r = row-rad; r <= row+rad; r++) - for (c = col-rad; c <= col+rad; c++) - if ((unsigned) r < height && (unsigned) c < width && - (r != row || c != col) && FC(r,c) == FC(row,col)) { - tot += BAYER(r,c); - n++; - } - BAYER(row,col) = tot/n; - if (cmdline.verbose) { - if (!fixed++) - pm_message ("Fixed bad pixels at: %d,%d", col, row); + cp = fname + strlen(fname); + if (cp[-1] == '/') + --cp; + fp = NULL; /* initial value */ + while (*fname == '/') { + strcpy (cp, "/.badpixels"); + fp = fopen (fname, "r"); + if (fp) + break; + if (cp == fname) + break; + while (*--cp != '/'); + } + free (fname); + if (fp) { + while (fgets (line, 128, fp)) { + char * cp; + cp = strchr (line, '#'); + if (cp) *cp = 0; + if (sscanf (line, "%d %d %d", &col, &row, &time) != 3) + continue; + if ((unsigned) col >= width || (unsigned) row >= height) + continue; + if (time > timestamp) continue; + for (tot=n=0, rad=1; rad < 3 && n==0; rad++) { + unsigned int r; + for (r = row-rad; r <= row+rad; ++r) { + unsigned int c; + for (c = col-rad; c <= col+rad; ++c) { + if ((unsigned) r < height && + (unsigned) c < width && + (r != row || c != col) && + FC(r,c) == FC(row,col)) { + tot += BAYER(r,c); + ++n; + } + } + } + } + BAYER(row,col) = tot/n; + if (cmdline.verbose) { + if (!fixed++) + pm_message ("Fixed bad pixels at: %d,%d", col, row); + } + } + fclose (fp); + } } - } - fclose (fp); } -static void CLASS scale_colors() -{ - int row, col, c, val, shift=0; - int min[4], max[4], count[4]; - double sum[4], dmin; - - maximum -= black; - if (cmdline.use_auto_wb || (cmdline.use_camera_wb && camera_red == -1)) { - FORC4 min[c] = INT_MAX; - FORC4 max[c] = count[c] = sum[c] = 0; - for (row=0; row < height; row++) - for (col=0; col < width; col++) - FORC4 { - val = image[row*width+col][c]; - if (!val) continue; - if (min[c] > val) min[c] = val; - if (max[c] < val) max[c] = val; - val -= black; - if (val > maximum-25) continue; - if (val < 0) val = 0; - sum[c] += val; - count[c]++; + + +static void CLASS +scaleColors(Image const image) { + + int row; + int c; + int val; + int shift; + int min[4], max[4], count[4]; + double sum[4], dmin; + int scaleMax; + + scaleMax = maximum - black; /* initial value */ + if (cmdline.use_auto_wb || (cmdline.use_camera_wb && camera_red == -1)) { + unsigned int row; + FORC4 min [c] = INT_MAX; + FORC4 max [c] = 0; + FORC4 count[c] = 0; + FORC4 sum [c] = 0; + for (row = 0; row < height; ++row) { + unsigned int col; + for (col = 0; col < width; ++col) { + FORC4 { + int val; + val = image[row*width+col][c]; + if (val != 0) { + if (min[c] > val) + min[c] = val; + if (max[c] < val) + max[c] = val; + val -= black; + if (val <= scaleMax-25) { + sum [c] += MAX(0, val); + count[c] += 1; + } + } + } + } + } + FORC4 pre_mul[c] = count[c] / sum[c]; } - FORC4 pre_mul[c] = count[c] / sum[c]; - } - if (cmdline.use_camera_wb && camera_red != -1) { - FORC4 count[c] = sum[c] = 0; - for (row=0; row < 8; row++) - for (col=0; col < 8; col++) { - c = FC(row,col); - if ((val = white[row][col] - black) > 0) - sum[c] += val; - count[c]++; - } - val = 1; - FORC4 if (sum[c] == 0) val = 0; - if (val) - FORC4 pre_mul[c] = count[c] / sum[c]; - else if (camera_red && camera_blue) - memcpy (pre_mul, cam_mul, sizeof pre_mul); - else - pm_message ("Cannot use camera white balance."); - } - if (!use_coeff) { - pre_mul[0] *= cmdline.red_scale; - pre_mul[2] *= cmdline.blue_scale; - } - dmin = DBL_MAX; - FORC4 if (dmin > pre_mul[c]) + if (cmdline.use_camera_wb && camera_red != -1) { + unsigned int row; + FORC4 count[c] = sum[c] = 0; + for (row = 0; row < 8; ++row) { + unsigned int col; + for (col = 0; col < 8; ++col) { + c = FC(row,col); + if ((val = white[row][col] - black) > 0) + sum[c] += val; + ++count[c]; + } + } + val = 1; + FORC4 if (sum[c] == 0) val = 0; + if (val) + FORC4 pre_mul[c] = count[c] / sum[c]; + else if (camera_red && camera_blue) + memcpy(pre_mul, cam_mul, sizeof pre_mul); + else + pm_message ("Cannot use camera white balance."); + } + if (!use_coeff) { + pre_mul[0] *= cmdline.red_scale; + pre_mul[2] *= cmdline.blue_scale; + } + dmin = DBL_MAX; + FORC4 if (dmin > pre_mul[c]) dmin = pre_mul[c]; - FORC4 pre_mul[c] /= dmin; - - while (maximum << shift < 0x8000) shift++; - FORC4 pre_mul[c] *= 1 << shift; - maximum <<= shift; - - if (cmdline.linear || cmdline.bright < 1) { - maximum *= cmdline.bright; - if (maximum > 0xffff) - maximum = 0xffff; - FORC4 pre_mul[c] *= cmdline.bright; - } - if (cmdline.verbose) { - fprintf (stderr, "Scaling with black=%d, pre_mul[] =", black); - FORC4 fprintf (stderr, " %f", pre_mul[c]); - fputc ('\n', stderr); - } - clip_max = cmdline.no_clip_color ? 0xffff : maximum; - for (row=0; row < height; row++) - for (col=0; col < width; col++) - FORC4 { - val = image[row*width+col][c]; - if (!val) continue; - val -= black; - val *= pre_mul[c]; - if (val < 0) val = 0; - if (val > clip_max) val = clip_max; - image[row*width+col][c] = val; - } -} - -/* - This algorithm is officially called: + FORC4 pre_mul[c] /= dmin; - "Interpolation using a Threshold-based variable number of gradients" + for (shift = 0; scaleMax << shift < 0x8000; ++shift); - described in http://www-ise.stanford.edu/~tingchen/algodep/vargra.html + FORC4 pre_mul[c] *= 1 << shift; + scaleMax <<= shift; - I've extended the basic idea to work with non-Bayer filter arrays. - Gradients are numbered clockwise from NW=0 to W=7. - */ -static void CLASS vng_interpolate() -{ - static const signed char *cp, terms[] = { - -2,-2,+0,-1,0,(char)0x01, -2,-2,+0,+0,1,(char)0x01, -2,-1,-1,+0,0,(char)0x01, - -2,-1,+0,-1,0,(char)0x02, -2,-1,+0,+0,0,(char)0x03, -2,-1,+0,+1,1,(char)0x01, - -2,+0,+0,-1,0,(char)0x06, -2,+0,+0,+0,1,(char)0x02, -2,+0,+0,+1,0,(char)0x03, - -2,+1,-1,+0,0,(char)0x04, -2,+1,+0,-1,1,(char)0x04, -2,+1,+0,+0,0,(char)0x06, - -2,+1,+0,+1,0,(char)0x02, -2,+2,+0,+0,1,(char)0x04, -2,+2,+0,+1,0,(char)0x04, - -1,-2,-1,+0,0,(char)0x80, -1,-2,+0,-1,0,(char)0x01, -1,-2,+1,-1,0,(char)0x01, - -1,-2,+1,+0,1,(char)0x01, -1,-1,-1,+1,0,(char)0x88, -1,-1,+1,-2,0,(char)0x40, - -1,-1,+1,-1,0,(char)0x22, -1,-1,+1,+0,0,(char)0x33, -1,-1,+1,+1,1,(char)0x11, - -1,+0,-1,+2,0,(char)0x08, -1,+0,+0,-1,0,(char)0x44, -1,+0,+0,+1,0,(char)0x11, - -1,+0,+1,-2,1,(char)0x40, -1,+0,+1,-1,0,(char)0x66, -1,+0,+1,+0,1,(char)0x22, - -1,+0,+1,+1,0,(char)0x33, -1,+0,+1,+2,1,(char)0x10, -1,+1,+1,-1,1,(char)0x44, - -1,+1,+1,+0,0,(char)0x66, -1,+1,+1,+1,0,(char)0x22, -1,+1,+1,+2,0,(char)0x10, - -1,+2,+0,+1,0,(char)0x04, -1,+2,+1,+0,1,(char)0x04, -1,+2,+1,+1,0,(char)0x04, - +0,-2,+0,+0,1,(char)0x80, +0,-1,+0,+1,1,(char)0x88, +0,-1,+1,-2,0,(char)0x40, - +0,-1,+1,+0,0,(char)0x11, +0,-1,+2,-2,0,(char)0x40, +0,-1,+2,-1,0,(char)0x20, - +0,-1,+2,+0,0,(char)0x30, +0,-1,+2,+1,1,(char)0x10, +0,+0,+0,+2,1,(char)0x08, - +0,+0,+2,-2,1,(char)0x40, +0,+0,+2,-1,0,(char)0x60, +0,+0,+2,+0,1,(char)0x20, - +0,+0,+2,+1,0,(char)0x30, +0,+0,+2,+2,1,(char)0x10, +0,+1,+1,+0,0,(char)0x44, - +0,+1,+1,+2,0,(char)0x10, +0,+1,+2,-1,1,(char)0x40, +0,+1,+2,+0,0,(char)0x60, - +0,+1,+2,+1,0,(char)0x20, +0,+1,+2,+2,0,(char)0x10, +1,-2,+1,+0,0,(char)0x80, - +1,-1,+1,+1,0,(char)0x88, +1,+0,+1,+2,0,(char)0x08, +1,+0,+2,-1,0,(char)0x40, - +1,+0,+2,+1,0,(char)0x10 - }, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 }; - unsigned short (*brow[5])[4], *pix; - int code[8][2][320], *ip, gval[8], gmin, gmax, sum[4]; - int row, col, shift, x, y, x1, x2, y1, y2, t, weight, grads, color, diag; - int g, diff, thold, num, c; - - for (row=0; row < 8; row++) { /* Precalculate for bilinear */ - for (col=1; col < 3; col++) { - ip = code[row][col & 1]; - memset (sum, 0, sizeof sum); - for (y=-1; y <= 1; y++) - for (x=-1; x <= 1; x++) { - shift = (y==0) + (x==0); - if (shift == 2) continue; - color = FC(row+y,col+x); - *ip++ = (width*y + x)*4 + color; - *ip++ = shift; - *ip++ = color; - sum[color] += 1 << shift; - } - FORC4 - if (c != FC(row,col)) { - *ip++ = c; - *ip++ = sum[c]; + if (cmdline.linear || cmdline.bright < 1) { + scaleMax = MIN(0xffff, scaleMax * cmdline.bright); + FORC4 pre_mul[c] *= cmdline.bright; } + if (cmdline.verbose) { + fprintf(stderr, "Scaling with black=%d, ", black); + fprintf(stderr, "pre_mul[] = "); + FORC4 fprintf (stderr, " %f", pre_mul[c]); + fprintf(stderr, "\n"); } - } - for (row=1; row < height-1; row++) { /* Do bilinear interpolation */ - for (col=1; col < width-1; col++) { - pix = image[row*width+col]; - ip = code[row & 7][col & 1]; - memset (sum, 0, sizeof sum); - for (g=8; g--; ) { - diff = pix[*ip++]; - diff <<= *ip++; - sum[*ip++] += diff; - } - for (g=colors; --g; ) { - c = *ip++; - pix[c] = sum[c] / *ip++; - } + clip_max = cmdline.no_clip_color ? 0xffff : scaleMax; + for (row = 0; row < height; ++row) { + unsigned int col; + for (col = 0; col < width; ++col) { + unsigned int c; + for (c = 0; c < colors; ++c) { + int val; + val = image[row*width+col][c]; + if (val != 0) { + val -= black; + val *= pre_mul[c]; + image[row*width+col][c] = MAX(0, MIN(clip_max, val)); + } + } + } } - } - if (cmdline.quick_interpolate) - return; - - for (row=0; row < 8; row++) { /* Precalculate for VNG */ - for (col=0; col < 2; col++) { - ip = code[row][col]; - for (cp=terms, t=0; t < 64; t++) { - y1 = *cp++; x1 = *cp++; - y2 = *cp++; x2 = *cp++; - weight = *cp++; - grads = *cp++; - color = FC(row+y1,col+x1); - if (FC(row+y2,col+x2) != color) continue; - diag = (FC(row,col+1) == color && FC(row+1,col) == color) ? 2:1; - if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue; - *ip++ = (y1*width + x1)*4 + color; - *ip++ = (y2*width + x2)*4 + color; - *ip++ = weight; - for (g=0; g < 8; g++) - if (grads & 1<<g) *ip++ = g; - *ip++ = -1; - } - *ip++ = INT_MAX; - for (cp=chood, g=0; g < 8; g++) { - y = *cp++; x = *cp++; - *ip++ = (y*width + x) * 4; - color = FC(row,col); - if (FC(row+y,col+x) != color && FC(row+y*2,col+x*2) == color) - *ip++ = (y*width + x) * 8 + color; - else - *ip++ = 0; - } +} + + + +static void CLASS +vngInterpolate(Image const image) { + + /* + This algorithm is officially called "Interpolation using a + Threshold-based variable number of gradients," described in + http://www-ise.stanford.edu/~tingchen/algodep/vargra.html + + I've extended the basic idea to work with non-Bayer filter arrays. + Gradients are numbered clockwise from NW=0 to W=7. + */ + + static const signed char *cp, terms[] = { + -2,-2,+0,-1,0,(char)0x01, -2,-2,+0,+0,1,(char)0x01, -2,-1,-1,+0,0,(char)0x01, + -2,-1,+0,-1,0,(char)0x02, -2,-1,+0,+0,0,(char)0x03, -2,-1,+0,+1,1,(char)0x01, + -2,+0,+0,-1,0,(char)0x06, -2,+0,+0,+0,1,(char)0x02, -2,+0,+0,+1,0,(char)0x03, + -2,+1,-1,+0,0,(char)0x04, -2,+1,+0,-1,1,(char)0x04, -2,+1,+0,+0,0,(char)0x06, + -2,+1,+0,+1,0,(char)0x02, -2,+2,+0,+0,1,(char)0x04, -2,+2,+0,+1,0,(char)0x04, + -1,-2,-1,+0,0,(char)0x80, -1,-2,+0,-1,0,(char)0x01, -1,-2,+1,-1,0,(char)0x01, + -1,-2,+1,+0,1,(char)0x01, -1,-1,-1,+1,0,(char)0x88, -1,-1,+1,-2,0,(char)0x40, + -1,-1,+1,-1,0,(char)0x22, -1,-1,+1,+0,0,(char)0x33, -1,-1,+1,+1,1,(char)0x11, + -1,+0,-1,+2,0,(char)0x08, -1,+0,+0,-1,0,(char)0x44, -1,+0,+0,+1,0,(char)0x11, + -1,+0,+1,-2,1,(char)0x40, -1,+0,+1,-1,0,(char)0x66, -1,+0,+1,+0,1,(char)0x22, + -1,+0,+1,+1,0,(char)0x33, -1,+0,+1,+2,1,(char)0x10, -1,+1,+1,-1,1,(char)0x44, + -1,+1,+1,+0,0,(char)0x66, -1,+1,+1,+1,0,(char)0x22, -1,+1,+1,+2,0,(char)0x10, + -1,+2,+0,+1,0,(char)0x04, -1,+2,+1,+0,1,(char)0x04, -1,+2,+1,+1,0,(char)0x04, + +0,-2,+0,+0,1,(char)0x80, +0,-1,+0,+1,1,(char)0x88, +0,-1,+1,-2,0,(char)0x40, + +0,-1,+1,+0,0,(char)0x11, +0,-1,+2,-2,0,(char)0x40, +0,-1,+2,-1,0,(char)0x20, + +0,-1,+2,+0,0,(char)0x30, +0,-1,+2,+1,1,(char)0x10, +0,+0,+0,+2,1,(char)0x08, + +0,+0,+2,-2,1,(char)0x40, +0,+0,+2,-1,0,(char)0x60, +0,+0,+2,+0,1,(char)0x20, + +0,+0,+2,+1,0,(char)0x30, +0,+0,+2,+2,1,(char)0x10, +0,+1,+1,+0,0,(char)0x44, + +0,+1,+1,+2,0,(char)0x10, +0,+1,+2,-1,1,(char)0x40, +0,+1,+2,+0,0,(char)0x60, + +0,+1,+2,+1,0,(char)0x20, +0,+1,+2,+2,0,(char)0x10, +1,-2,+1,+0,0,(char)0x80, + +1,-1,+1,+1,0,(char)0x88, +1,+0,+1,+2,0,(char)0x08, +1,+0,+2,-1,0,(char)0x40, + +1,+0,+2,+1,0,(char)0x10 + }, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 }; + unsigned short (*brow[5])[4], *pix; + int code[8][2][320], *ip, gval[8], gmin, gmax, sum[4]; + int row, col, shift, x, y, x1, x2, y1, y2, t, weight, grads, color, diag; + int g, diff, thold, num, c; + + for (row=0; row < 8; row++) { /* Precalculate for bilinear */ + for (col=1; col < 3; col++) { + ip = code[row][col & 1]; + memset (sum, 0, sizeof sum); + for (y=-1; y <= 1; y++) + for (x=-1; x <= 1; x++) { + shift = (y==0) + (x==0); + if (shift == 2) continue; + color = FC(row+y,col+x); + *ip++ = (width*y + x)*4 + color; + *ip++ = shift; + *ip++ = color; + sum[color] += 1 << shift; + } + FORC4 + if (c != FC(row,col)) { + *ip++ = c; + *ip++ = sum[c]; + } + } } - } - brow[4] = calloc (width*3, sizeof **brow); - merror (brow[4], "vng_interpolate()"); - for (row=0; row < 3; row++) - brow[row] = brow[4] + row*width; - for (row=2; row < height-2; row++) { /* Do VNG interpolation */ - for (col=2; col < width-2; col++) { - pix = image[row*width+col]; - ip = code[row & 7][col & 1]; - memset (gval, 0, sizeof gval); - while ((g = ip[0]) != INT_MAX) { /* Calculate gradients */ - num = (diff = pix[g] - pix[ip[1]]) >> 31; - gval[ip[3]] += (diff = ((diff ^ num) - num) << ip[2]); - ip += 5; - if ((g = ip[-1]) == -1) continue; - gval[g] += diff; - while ((g = *ip++) != -1) - gval[g] += diff; - } - ip++; - gmin = gmax = gval[0]; /* Choose a threshold */ - for (g=1; g < 8; g++) { - if (gmin > gval[g]) gmin = gval[g]; - if (gmax < gval[g]) gmax = gval[g]; - } - if (gmax == 0) { - memcpy (brow[2][col], pix, sizeof *image); - continue; - } - thold = gmin + (gmax >> 1); - memset (sum, 0, sizeof sum); - color = FC(row,col); - for (num=g=0; g < 8; g++,ip+=2) { /* Average the neighbors */ - if (gval[g] <= thold) { - FORC4 - if (c == color && ip[1]) - sum[c] += (pix[c] + pix[ip[1]]) >> 1; - else - sum[c] += pix[ip[0] + c]; - num++; + for (row=1; row < height-1; row++) { /* Do bilinear interpolation */ + for (col=1; col < width-1; col++) { + pix = image[row*width+col]; + ip = code[row & 7][col & 1]; + memset (sum, 0, sizeof sum); + for (g=8; g--; ) { + diff = pix[*ip++]; + diff <<= *ip++; + sum[*ip++] += diff; + } + for (g=colors; --g; ) { + c = *ip++; + pix[c] = sum[c] / *ip++; + } + } } - } - FORC4 { /* Save to buffer */ - t = pix[color]; - if (c != color) { - t += (sum[c] - sum[color])/num; - if (t < 0) t = 0; - if (t > clip_max) t = clip_max; + if (cmdline.quick_interpolate) + return; + + for (row=0; row < 8; row++) { /* Precalculate for VNG */ + for (col=0; col < 2; col++) { + ip = code[row][col]; + for (cp=terms, t=0; t < 64; t++) { + y1 = *cp++; x1 = *cp++; + y2 = *cp++; x2 = *cp++; + weight = *cp++; + grads = *cp++; + color = FC(row+y1,col+x1); + if (FC(row+y2,col+x2) != color) continue; + diag = + (FC(row,col+1) == color && FC(row+1,col) == color) ? 2:1; + if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue; + *ip++ = (y1*width + x1)*4 + color; + *ip++ = (y2*width + x2)*4 + color; + *ip++ = weight; + for (g=0; g < 8; g++) + if (grads & 1<<g) *ip++ = g; + *ip++ = -1; + } + *ip++ = INT_MAX; + for (cp=chood, g=0; g < 8; g++) { + y = *cp++; x = *cp++; + *ip++ = (y*width + x) * 4; + color = FC(row,col); + if (FC(row+y,col+x) != color && FC(row+y*2,col+x*2) == color) + *ip++ = (y*width + x) * 8 + color; + else + *ip++ = 0; + } + } } - brow[2][col][c] = t; - } + brow[4] = calloc (width*3, sizeof **brow); + merror (brow[4], "vngInterpolate()"); + for (row=0; row < 3; row++) + brow[row] = brow[4] + row*width; + for (row=2; row < height-2; row++) { /* Do VNG interpolation */ + for (col=2; col < width-2; col++) { + pix = image[row*width+col]; + ip = code[row & 7][col & 1]; + memset (gval, 0, sizeof gval); + while ((g = ip[0]) != INT_MAX) { /* Calculate gradients */ + num = (diff = pix[g] - pix[ip[1]]) >> 31; + gval[ip[3]] += (diff = ((diff ^ num) - num) << ip[2]); + ip += 5; + if ((g = ip[-1]) == -1) continue; + gval[g] += diff; + while ((g = *ip++) != -1) + gval[g] += diff; + } + ip++; + gmin = gmax = gval[0]; /* Choose a threshold */ + for (g=1; g < 8; g++) { + if (gmin > gval[g]) gmin = gval[g]; + if (gmax < gval[g]) gmax = gval[g]; + } + if (gmax == 0) { + memcpy (brow[2][col], pix, sizeof *image); + continue; + } + thold = gmin + (gmax >> 1); + memset (sum, 0, sizeof sum); + color = FC(row,col); + for (num=g=0; g < 8; g++,ip+=2) { /* Average the neighbors */ + if (gval[g] <= thold) { + FORC4 + if (c == color && ip[1]) + sum[c] += (pix[c] + pix[ip[1]]) >> 1; + else + sum[c] += pix[ip[0] + c]; + num++; + } + } + FORC4 { /* Save to buffer */ + t = pix[color]; + if (c != color) { + t += (sum[c] - sum[color])/num; + if (t < 0) t = 0; + if (t > clip_max) t = clip_max; + } + brow[2][col][c] = t; + } + } + if (row > 3) /* Write buffer to image */ + memcpy(image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image); + for (g=0; g < 4; g++) + brow[(g-1) & 3] = brow[g]; } - if (row > 3) /* Write buffer to image */ - memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image); - for (g=0; g < 4; g++) - brow[(g-1) & 3] = brow[g]; - } - memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image); - memcpy (image[(row-1)*width+2], brow[1]+2, (width-4)*sizeof *image); - free (brow[4]); + memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image); + memcpy (image[(row-1)*width+2], brow[1]+2, (width-4)*sizeof *image); + free (brow[4]); } -#ifdef USE_LCMS -static void -apply_profile(FILE * const ifP, - const char * const pfname) -{ - char *prof; - cmsHPROFILE hInProfile=NULL, hOutProfile; - cmsHTRANSFORM hTransform; - - if (pfname) - hInProfile = cmsOpenProfileFromFile (pfname, "r"); - else if (profile_length) { - prof = malloc (profile_length); - merror (prof, "apply_profile()"); - fseek (ifP, profile_offset, SEEK_SET); - fread (prof, 1, profile_length, ifP); - hInProfile = cmsOpenProfileFromMem (prof, profile_length); - free (prof); - } - if (!hInProfile) return; - if (cmdline.verbose) - pm_message( "Applying color profile..."); - maximum = 0xffff; - use_gamma = use_coeff = 0; - - hOutProfile = cmsCreate_sRGBProfile(); - hTransform = cmsCreateTransform (hInProfile, TYPE_RGBA_16, - hOutProfile, TYPE_RGBA_16, INTENT_PERCEPTUAL, 0); - cmsDoTransform (hTransform, image, image, width*height); - - cmsDeleteTransform (hTransform); - cmsCloseProfile (hInProfile); - cmsCloseProfile (hOutProfile); -} -#else -static void -apply_profile(FILE * const ifP, - const char * const pfname) -{ -} -#endif -/* + +static void CLASS +convertToRgb(Image const image, + unsigned int const trim) { +/*---------------------------------------------------------------------------- Convert the entire image to RGB colorspace and build a histogram. - */ -static void CLASS convert_to_rgb() -{ - int row, col, r, g, c=0; - unsigned short *img; - float rgb[3]; - - if (cmdline.document_mode) - colors = 1; - memset (histogram, 0, sizeof histogram); - for (row = trim; row < height-trim; row++) - for (col = trim; col < width-trim; col++) { - img = image[row*width+col]; - if (cmdline.document_mode) - c = FC(row,col); - if (colors == 4 && !use_coeff) /* Recombine the greens */ - img[1] = (img[1] + img[3]) >> 1; - if (colors == 1) /* RGB from grayscale */ - for (r=0; r < 3; r++) - rgb[r] = img[c]; - else if (use_coeff) { /* RGB via coeff[][] */ - for (r=0; r < 3; r++) - for (rgb[r]=g=0; g < colors; g++) - rgb[r] += img[g] * coeff[r][g]; - } else /* RGB from RGB (easy) */ - goto norgb; - for (r=0; r < 3; r++) { - if (rgb[r] < 0) rgb[r] = 0; - if (rgb[r] > clip_max) rgb[r] = clip_max; - img[r] = rgb[r]; - } -norgb: - for (r=0; r < 3; r++) - histogram[r][img[r] >> 3]++; + + We modify 'image' to change it from whatever it is now to RGB. +-----------------------------------------------------------------------------*/ + unsigned int row; + unsigned int c; + float rgb[3]; /* { red, green, blue } */ + + c = 0; /* initial value */ + + if (cmdline.document_mode) + colors = 1; + + memset(histogram, 0, sizeof histogram); + + for (row = 0 + trim; row < height - trim; ++row) { + unsigned int col; + for (col = 0 + trim; col < width - trim; ++col) { + unsigned short * const img = image[row*width+col]; + + if (cmdline.document_mode) + c = FC(row,col); + + if (colors == 4 && !use_coeff) + /* Recombine the greens */ + img[1] = (img[1] + img[3]) / 2; + + if (colors == 1) { + /* RGB from grayscale */ + unsigned int i; + for (i = 0; i < 3; ++i) + rgb[i] = img[c]; + } else if (use_coeff) { + /* RGB via coeff[][] */ + unsigned int i; + for (i = 0; i < 3; ++i) { + unsigned int j; + for (j = 0, rgb[i]= 0; j < colors; ++j) + rgb[i] += img[j] * coeff[i][j]; + } + } else { + /* RGB from RGB (easy) */ + unsigned int i; + for (i = 0; i < 3; ++i) + rgb[i] = img[i]; + } + { + unsigned int i; + for (i = 0; i < 3; ++i) + img[i] = MIN(clip_max, MAX(0, rgb[i])); + } + { + unsigned int i; + for (i = 0; i < 3; ++i) + ++histogram[i][img[i] >> 3]; + } + } } } -static void CLASS fuji_rotate() -{ - int i, wide, high, row, col; - double step; - float r, c, fr, fc; - unsigned ur, uc; - unsigned short (*img)[4], (*pix)[4]; - - if (!fuji_width) return; - if (cmdline.verbose) - pm_message ("Rotating image 45 degrees..."); - fuji_width = (fuji_width + shrink) >> shrink; - step = sqrt(0.5); - wide = fuji_width / step; - high = (height - fuji_width) / step; - img = calloc (wide*high, sizeof *img); - merror (img, "fuji_rotate()"); - - for (row=0; row < high; row++) - for (col=0; col < wide; col++) { - ur = r = fuji_width + (row-col)*step; - uc = c = (row+col)*step; - if (ur > height-2 || uc > width-2) continue; - fr = r - ur; - fc = c - uc; - pix = image + ur*width + uc; - for (i=0; i < colors; i++) - img[row*wide+col][i] = - (pix[ 0][i]*(1-fc) + pix[ 1][i]*fc) * (1-fr) + - (pix[width][i]*(1-fc) + pix[width+1][i]*fc) * fr; + + +static void CLASS +fujiRotate(Image * const imageP) { + + int wide; + int high; + unsigned int row; + double step; + float r, c, fr, fc; + unsigned short (*newImage)[4]; + unsigned short (*pix)[4]; + + if (fuji_width > 0) { + if (cmdline.verbose) + pm_message ("Rotating image 45 degrees..."); + + fuji_width = (fuji_width + shrink) >> shrink; + step = sqrt(0.5); + wide = fuji_width / step; + high = (height - fuji_width) / step; + newImage = calloc (wide*high, sizeof *newImage); + merror (newImage, "fujiRotate()"); + + for (row = 0; row < high; ++row) { + unsigned int col; + for (col = 0; col < wide; ++col) { + unsigned int ur = r = fuji_width + (row-col)*step; + unsigned int uc = c = (row+col)*step; + + unsigned int i; + + if (ur > height-2 || uc > width-2) + continue; + + fr = r - ur; + fc = c - uc; + pix = (*imageP) + ur * width + uc; + + for (i = 0; i < colors; ++i) { + newImage[row*wide+col][i] = + (pix[ 0][i]*(1-fc) + pix[ 1][i]*fc) * (1-fr) + + (pix[width][i]*(1-fc) + pix[width+1][i]*fc) * fr; + } + } + } + free(*imageP); + width = wide; + height = high; + *imageP = newImage; + fuji_width = 0; } - free (image); - width = wide; - height = high; - image = img; - fuji_width = 0; } -static void CLASS flip_image() -{ + + +static void CLASS +flipImage(Image const image) { + unsigned *flag; - int size, base, dest, next, row, col, temp; + int size, base, dest; struct imageCell { unsigned char contents[8]; }; struct imageCell * img; - struct imageCell hold; switch ((flip+3600) % 360) { - case 270: flip = 5; break; - case 180: flip = 3; break; - case 90: flip = 6; + case 270: flip = 0x5; break; + case 180: flip = 0x3; break; + case 90: flip = 0x6; } img = (struct imageCell *) image; size = height * width; flag = calloc ((size+31) >> 5, sizeof *flag); - merror (flag, "flip_image()"); - for (base = 0; base < size; base++) { - if (flag[base >> 5] & (1 << (base & 31))) - continue; - dest = base; - hold = img[base]; - while (1) { - if (flip & 4) { - row = dest % height; - col = dest / height; - } else { - row = dest / width; - col = dest % width; + merror (flag, "flipImage()"); + for (base = 0; base < size; ++base) { + if (flag[base >> 5] & (1 << (base & 31))) { + /* nothing */ + } else { + struct imageCell const hold = img[base]; + dest = base; + while (true) { + unsigned int col; + unsigned int row; + int next; + if (flip & 0x4) { + row = dest % height; + col = dest / height; + } else { + row = dest / width; + col = dest % width; + } + if (flip & 0x2) + row = height - 1 - row; + if (flip & 1) + col = width - 1 - col; + next = row * width + col; + if (next == base) + break; + flag[next >> 5] |= 1 << (next & 31); + img[dest] = img[next]; + dest = next; } - if (flip & 2) - row = height - 1 - row; - if (flip & 1) - col = width - 1 - col; - next = row * width + col; - if (next == base) break; - flag[next >> 5] |= 1 << (next & 31); - img[dest] = img[next]; - dest = next; + img[dest] = hold; } - img[dest] = hold; } free (flag); - if (flip & 4) { - temp = height; + if (flip & 0x4) { + int const oldHeight = height; + int const oldYmag = ymag; + height = width; - width = temp; - temp = ymag; + width = oldHeight; ymag = xmag; - xmag = temp; + xmag = oldYmag; } } -/* - Write the image as an RGB PAM image - */ -static void CLASS write_pam_nonlinear (FILE *ofp) -{ - unsigned char lut[0x10000]; - int perc, c, val, total, i, row, col; - float white=0, r; - struct pam pam; - tuple * tuplerow; - - pam.size = sizeof(pam); - pam.len = PAM_STRUCT_SIZE(tuple_type); - pam.file = ofp; - pam.width = xmag*(width-trim*2); - pam.height = ymag*(height-trim*2); - pam.depth = 3; - pam.format = PAM_FORMAT; - pam.maxval = 255; - strcpy(pam.tuple_type, "RGB"); - - pnm_writepaminit(&pam); - - tuplerow = pnm_allocpamrow(&pam); - - perc = width * height * 0.01; /* 99th percentile white point */ - if (fuji_width) perc /= 2; - FORC3 { - for (val=0x2000, total=0; --val > 32; ) - if ((total += histogram[c][val]) > perc) break; - if (white < val) white = val; - } - white *= 8 / cmdline.bright; - for (i=0; i < 0x10000; i++) { - r = i / white; - val = 256 * ( !use_gamma ? r : - r <= 0.018 ? r*4.5 : pow(r,0.45)*1.099-0.099 ); - if (val > 255) val = 255; - lut[i] = val; - } - for (row=trim; row < height-trim; row++) { - for (col=trim; col < width-trim; col++) { - unsigned int plane; - for (plane=0; plane < pam.depth; ++plane) { - unsigned int copy; - for (copy=0; copy < xmag; ++copy) { - unsigned int const pamcol = xmag*(col-trim)+copy; - tuplerow[pamcol][plane] = lut[image[row*width+col][plane]]; - } - } - } - { - unsigned int copy; - for (copy=0; copy < ymag; ++copy) - pnm_writepamrow(&pam, tuplerow); - } - } - pnm_freepamrow(tuplerow); + + +static void CLASS +writePamLinear(FILE * const ofP, + Image const image, + unsigned int const trim) { +/*---------------------------------------------------------------------------- + Write the image 'image' to a 16-bit PAM file with linear color space +-----------------------------------------------------------------------------*/ + unsigned int row; + + struct pam pam; + tuple * tuplerow; + + pam.size = sizeof(pam); + pam.len = PAM_STRUCT_SIZE(tuple_type); + pam.file = ofP; + pam.width = width - trim - trim; + pam.height = height - trim - trim; + pam.depth = 3; + pam.format = PAM_FORMAT; + pam.maxval = MAX(maximum, 256); + strcpy(pam.tuple_type, "RGB"); + + pnm_writepaminit(&pam); + + tuplerow = pnm_allocpamrow(&pam); + + for (row = 0 + trim; row < height - trim; ++row) { + unsigned int col; + for (col = 0 + trim; col < width - trim; ++col) { + unsigned int const pamCol = col - trim; + unsigned int plane; + for (plane = 0; plane < 3; ++plane) + tuplerow[pamCol][plane] = image[row*width+col][plane]; + } + pnm_writepamrow(&pam, tuplerow); + } + pnm_freepamrow(tuplerow); } -/* - Write the image to a 16-bit PAM file with linear color space - */ -static void CLASS write_pam_linear (FILE *ofp) -{ - int row; - - struct pam pam; - tuple * tuplerow; - - if (maximum < 256) maximum = 256; - - pam.size = sizeof(pam); - pam.len = PAM_STRUCT_SIZE(tuple_type); - pam.file = ofp; - pam.width = width-trim*2; - pam.height = height-trim*2; - pam.depth = 3; - pam.format = PAM_FORMAT; - pam.maxval = MAX(maximum, 256); - strcpy(pam.tuple_type, "RGB"); - - pnm_writepaminit(&pam); - - tuplerow = pnm_allocpamrow(&pam); - - for (row = trim; row < height-trim; row++) { - unsigned int col; - for (col = trim; col < width-trim; col++) { - unsigned int const pamCol = col - trim; - unsigned int plane; - for (plane = 0; plane < 3; ++plane) - tuplerow[pamCol][plane] = image[row*width+col][plane]; - } - pnm_writepamrow(&pam, tuplerow); - } - pnm_freepamrow(tuplerow); + + +static void CLASS +writePamNonlinear(FILE * const ofP, + Image const image, + unsigned int const trim) { +/*---------------------------------------------------------------------------- + Write the image 'image' as an RGB PAM image +-----------------------------------------------------------------------------*/ + unsigned char lut[0x10000]; + int perc; + int c; + int total; + int i; + unsigned int row; + float white; + float r; + struct pam pam; + tuple * tuplerow; + + white = 0; /* initial value */ + + pam.size = sizeof(pam); + pam.len = PAM_STRUCT_SIZE(tuple_type); + pam.file = ofP; + pam.width = xmag*(width-trim*2); + pam.height = ymag*(height-trim*2); + pam.depth = 3; + pam.format = PAM_FORMAT; + pam.maxval = 255; + strcpy(pam.tuple_type, "RGB"); + + pnm_writepaminit(&pam); + + tuplerow = pnm_allocpamrow(&pam); + + perc = width * height * 0.01; /* 99th percentile white point */ + if (fuji_width) perc /= 2; + FORC3 { + int val; + for (val=0x2000, total=0; --val > 32; ) + if ((total += histogram[c][val]) > perc) break; + if (white < val) + white = val; + } + white *= 8 / cmdline.bright; + for (i=0; i < 0x10000; ++i) { + int val; + r = i / white; + val = 256 * ( !use_gamma ? r : + r <= 0.018 ? r*4.5 : pow(r,0.45)*1.099-0.099 ); + lut[i] = MIN(255, val); + } + + for (row = 0 + trim; row < height - trim; ++row) { + unsigned int col; + for (col = 0 + trim; col < width - trim; ++col) { + unsigned int plane; + for (plane = 0; plane < pam.depth; ++plane) { + sample const value = lut[image[row*width+col][plane]]; + unsigned int copy; + for (copy = 0; copy < xmag; ++copy) { + unsigned int const pamcol = xmag*(col-trim)+copy; + tuplerow[pamcol][plane] = value; + } + } + } + { + unsigned int copy; + for (copy = 0; copy < ymag; ++copy) + pnm_writepamrow(&pam, tuplerow); + } + } + pnm_freepamrow(tuplerow); } static void CLASS -writePam(FILE * const ofP, - bool const linear) { +writePam(FILE * const ofP, + Image const image, + bool const linear, + unsigned int const trim) { if (linear) - write_pam_linear(ofP); + writePamLinear(ofP, image, trim); else - write_pam_nonlinear(ofP); + writePamNonlinear(ofP, image, trim); } - static void CLASS -convertIt(FILE * const ifP, - FILE * const ofP, - loadRawFn const load_raw) { +convertIt(FILE * const ifP, + FILE * const ofP, + LoadRawFn * const load_raw) { + + Image image; + unsigned int trim; shrink = cmdline.half_size && filters; iheight = (height + shrink) >> shrink; iwidth = (width + shrink) >> shrink; - image = calloc (iheight*iwidth*sizeof *image + meta_length, 1); + image = calloc (iheight*iwidth*sizeof(*image) + meta_length, 1); merror (image, "main()"); meta_data = (char *) (image + iheight*iwidth); if (cmdline.verbose) @@ -807,43 +887,49 @@ convertIt(FILE * const ifP, ifp = ifP; /* Set global variable for (*load_raw)() */ - load_raw(); - bad_pixels(); + load_raw(image); + fixBadPixels(image); height = iheight; width = iwidth; if (is_foveon) { if (cmdline.verbose) pm_message ("Foveon interpolation..."); - foveon_interpolate(coeff); + foveon_interpolate(image, coeff); } else { - scale_colors(); + scaleColors(image); } - if (shrink) filters = 0; - trim = 0; + if (shrink) + filters = 0; + if (filters && !cmdline.document_mode) { trim = 1; if (cmdline.verbose) pm_message ("%s interpolation...", cmdline.quick_interpolate ? "Bilinear":"VNG"); - vng_interpolate(); - } - fuji_rotate(); - apply_profile(ifP, cmdline.profile); + vngInterpolate(image); + } else + trim = 0; + + fujiRotate(&image); + if (cmdline.verbose) pm_message ("Converting to RGB colorspace..."); - convert_to_rgb(); + convertToRgb(image, trim); if (flip) { if (cmdline.verbose) pm_message ("Flipping image %c:%c:%c...", flip & 1 ? 'H':'0', flip & 2 ? 'V':'0', flip & 4 ? 'T':'0'); - flip_image(); + flipImage(image); } - writePam(ofP, cmdline.linear); + writePam(ofP, image, cmdline.linear, trim); + + free(image); } + int main (int argc, char **argv) { @@ -851,7 +937,7 @@ main (int argc, char **argv) { FILE * ifP; int rc; - loadRawFn load_raw; + LoadRawFn * load_raw; pnm_init(&argc, argv); @@ -861,8 +947,6 @@ main (int argc, char **argv) { ifP = pm_openr(cmdline.inputFileName); - image = NULL; - rc = identify(ifP, cmdline.use_secondary, cmdline.use_camera_rgb, cmdline.red_scale, cmdline.blue_scale, @@ -881,7 +965,6 @@ main (int argc, char **argv) { } pm_close(ifP); pm_close(ofP); - free(image); return 0; } diff --git a/converter/other/cameratopam/cameratopam.h b/converter/other/cameratopam/cameratopam.h new file mode 100644 index 00000000..9ff33cb3 --- /dev/null +++ b/converter/other/cameratopam/cameratopam.h @@ -0,0 +1,6 @@ +#ifndef CAMERATOPAM_H_INCLUDED +#define CAMERATOPAM_H_INCLUDED + +typedef unsigned short (*Image)[4]; + +#endif diff --git a/converter/other/cameratopam/canon.c b/converter/other/cameratopam/canon.c index a34771d0..96a6210b 100644 --- a/converter/other/cameratopam/canon.c +++ b/converter/other/cameratopam/canon.c @@ -9,7 +9,7 @@ void -canon_600_load_raw(void) { +canon_600_load_raw(Image const image) { unsigned char data[1120], *dp; unsigned short pixel[896], *pix; int irow, orow, col; @@ -42,7 +42,7 @@ canon_600_load_raw(void) { void -canon_a5_load_raw(void) { +canon_a5_load_raw(Image const image) { unsigned char data[1940], *dp; unsigned short pixel[1552], *pix; int row, col; @@ -97,7 +97,7 @@ canon_has_lowbits() void -canon_compressed_load_raw(void) { +canon_compressed_load_raw(Image const image) { unsigned short *pixel, *prow; int lowbits, i, row, r, col, save, val; unsigned irow, icol; diff --git a/converter/other/cameratopam/canon.h b/converter/other/cameratopam/canon.h index 041cdc4d..fe6a5a08 100644 --- a/converter/other/cameratopam/canon.h +++ b/converter/other/cameratopam/canon.h @@ -1,13 +1,12 @@ #ifndef CANON_H_INCLUDED #define CANON_H_INCLUDED -void -canon_600_load_raw(void); +#include "camera.h" -void -canon_a5_load_raw(void); +LoadRawFn canon_600_load_raw; -void -canon_compressed_load_raw(void); +LoadRawFn canon_a5_load_raw; + +LoadRawFn canon_compressed_load_raw; #endif diff --git a/converter/other/cameratopam/dng.c b/converter/other/cameratopam/dng.c index 44d45b02..bddfd9f4 100644 --- a/converter/other/cameratopam/dng.c +++ b/converter/other/cameratopam/dng.c @@ -4,70 +4,105 @@ #include "dng.h" void -dng_coeff (double cc[4][4], double cm[4][3], double xyz[3]) -{ - static const double rgb_xyz[3][3] = { /* RGB from XYZ */ - { 3.240479, -1.537150, -0.498535 }, - { -0.969256, 1.875992, 0.041556 }, - { 0.055648, -0.204043, 1.057311 } }; +dng_coeff (double cc[4][4], + double cm[4][3], + double xyz[3]) { + static const double rgb_xyz[3][3] = { /* RGB from XYZ */ + { 3.240479, -1.537150, -0.498535 }, + { -0.969256, 1.875992, 0.041556 }, + { 0.055648, -0.204043, 1.057311 } }; #if 0 - 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 } }; + 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 } }; #endif - double cam_xyz[4][3], xyz_cam[3][4], invert[3][6], num; - int i, j, k; + double cam_xyz[4][3], xyz_cam[3][4], invert[3][6]; + unsigned int i; - memset (cam_xyz, 0, sizeof cam_xyz); - for (i=0; i < colors; i++) - for (j=0; j < 3; j++) - for (k=0; k < colors; k++) - cam_xyz[i][j] += cc[i][k] * cm[k][j] * xyz[j]; + for (i = 0; i < colors; ++i) { + unsigned int j; + for (j = 0; j < 3; ++j) { + unsigned int k; + for (k = 0, cam_xyz[i][j] = 0.0; k < colors; ++k) { + cam_xyz[i][j] += cc[i][k] * cm[k][j] * xyz[j]; + } + } + } + for (i = 0; i < colors; ++i) { + unsigned int j; + double camXyzSum; + + for (j = 0, camXyzSum = 0.0; j < 3; ++j) + camXyzSum += cam_xyz[i][j]; - for (i=0; i < colors; i++) { - for (num=j=0; j < 3; j++) - num += cam_xyz[i][j]; - for (j=0; j < 3; j++) - cam_xyz[i][j] /= num; - pre_mul[i] = 1 / num; - } - for (i=0; i < 3; i++) { - for (j=0; j < 6; j++) - invert[i][j] = j == i+3; - for (j=0; j < 3; j++) - for (k=0; k < colors; k++) - invert[i][j] += cam_xyz[k][i] * cam_xyz[k][j]; - } - for (i=0; i < 3; i++) { - num = invert[i][i]; - for (j=0; j < 6; j++) /* Normalize row i */ - invert[i][j] /= num; - for (k=0; k < 3; k++) { /* Subtract it from other rows */ - if (k==i) continue; - num = invert[k][i]; - for (j=0; j < 6; j++) - invert[k][j] -= invert[i][j] * num; + for (j = 0; j < 3; ++j) + cam_xyz[i][j] /= camXyzSum; + + pre_mul[i] = 1 / camXyzSum; + } + for (i = 0; i < 3; ++i) { + unsigned int j; + for (j = 0; j < 6; ++j) + invert[i][j] = j == i+3; + for (j = 0; j < 3; ++j) { + unsigned int k; + for (k = 0; k < colors; ++k) + invert[i][j] += cam_xyz[k][i] * cam_xyz[k][j]; + } } - } - memset (xyz_cam, 0, sizeof xyz_cam); - for (i=0; i < 3; i++) - for (j=0; j < colors; j++) - for (k=0; k < 3; k++) - xyz_cam[i][j] += invert[i][k+3] * cam_xyz[j][k]; + for (i = 0; i < 3; ++i) { + double const num = invert[i][i]; + unsigned int j; + unsigned int k; + for (j = 0; j < 6; ++j) /* Normalize row i */ + invert[i][j] /= num; + for (k = 0; k < 3; ++k) { /* Subtract it from other rows */ + if (k != i) { + double const num = invert[k][i]; + unsigned int j; + for (j = 0; j < 6; ++j) + invert[k][j] -= invert[i][j] * num; + } + } + } + + memset(xyz_cam, 0, sizeof xyz_cam); - memset (coeff, 0, sizeof coeff); - for (i=0; i < 3; i++) - for (j=0; j < colors; j++) - for (k=0; k < 3; k++) - coeff[i][j] += rgb_xyz[i][k] * xyz_cam[k][j]; + for (i = 0; i < 3; ++i) { + unsigned int j; + for (j = 0; j < colors; ++j) { + unsigned int k; + for (k = 0; k < 3; ++k) + xyz_cam[i][j] += invert[i][k+3] * cam_xyz[j][k]; + } + } + memset (coeff, 0, sizeof coeff); - for (num=j=0; j < colors; j++) - num += coeff[1][j]; - for (i=0; i < 3; i++) { - for (j=0; j < colors; j++) - coeff[i][j] /= num; - } - use_coeff = 1; + for (i = 0; i < 3; ++i) { + unsigned int j; + for (j = 0; j < colors; ++j) { + unsigned int k; + for (k = 0; k < 3; ++k) + coeff[i][j] += rgb_xyz[i][k] * xyz_cam[k][j]; + } + } + { + double greenSum; + unsigned int j; + unsigned int i; + + for (j = 0, greenSum = 0.0; j < colors; ++j) + greenSum += coeff[1][j]; + + for (i = 0; i < 3; ++i) { + unsigned int j; + for (j = 0; j < colors; ++j) + coeff[i][j] /= greenSum; + } + } + use_coeff = 1; } + + diff --git a/converter/other/cameratopam/dng.h b/converter/other/cameratopam/dng.h index 01e7e0a5..56293563 100644 --- a/converter/other/cameratopam/dng.h +++ b/converter/other/cameratopam/dng.h @@ -1,2 +1,4 @@ void -dng_coeff (double cc[4][4], double cm[4][3], double xyz[3]); +dng_coeff(double cc[4][4], + double cm[4][3], + double xyz[3]); diff --git a/converter/other/cameratopam/foveon.c b/converter/other/cameratopam/foveon.c index a8d62bee..a3e5449a 100644 --- a/converter/other/cameratopam/foveon.c +++ b/converter/other/cameratopam/foveon.c @@ -141,8 +141,8 @@ parse_foveon(FILE * const ifp) { void -foveon_coeff(bool * const useCoeffP, - float coeff[3][4]) { +foveon_coeff(int * const useCoeffP, + float coeff[3][4]) { static const float foveon[3][3] = { { 1.4032, -0.2231, -0.1016 }, @@ -211,7 +211,7 @@ foveon_load_camf() { void -foveon_load_raw() { +foveon_load_raw(Image const image) { struct decode *dindex; short diff[1024], pred[3]; @@ -391,7 +391,8 @@ static int foveon_apply_curve (short *curve, int i) } void -foveon_interpolate(float coeff[3][4]) { +foveon_interpolate(Image const image, + float coeff[3][4]) { static const short hood[] = { -1,-1, -1,0, -1,1, 0,-1, 0,1, 1,-1, 1,0, 1,1 }; @@ -472,18 +473,22 @@ foveon_interpolate(float coeff[3][4]) { sgrow = calloc (dim[1], sizeof *sgrow); sgx = (width + dim[1]-2) / (dim[1]-1); - black = calloc (height, sizeof *black); - for (row=0; row < height; row++) { - for (i=0; i < 6; i++) - ddft[0][0][i] = ddft[1][0][i] + - row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]); + black = calloc (height, sizeof(black[0])); + for (row=0; row < height; ++row) { + unsigned int i; + for (i=0; i < 3; ++i) { + unsigned int j; + for (j = 0; j < 2; ++j) + ddft[0][i][j] = ddft[1][i][j] + + row / (height-1.0) * (ddft[2][i][j] - ddft[1][i][j]); + } FORC3 black[row][c] = ( 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]; } - memcpy (black, black+8, sizeof (*black)*8); - memcpy (black+height-11, black+height-22, 11*sizeof *black); + memcpy (black, black+8, 8 * sizeof(black[0])); + memcpy (black+height-11, black+height-22, 11*(sizeof black[0])); memcpy (last, black, sizeof last); for (row=1; row < height-1; row++) { @@ -522,9 +527,13 @@ foveon_interpolate(float coeff[3][4]) { FORC3 black[row][c] += fsum[c]/2 + total[c]/(total[3]*100.0); for (row=0; row < height; row++) { - for (i=0; i < 6; i++) - ddft[0][0][i] = ddft[1][0][i] + - row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]); + unsigned int i; + for (i = 0; i < 3; ++i) { + unsigned int j; + for (j = 0; j < 2; ++j) + ddft[0][i][j] = ddft[1][i][j] + + row / (height-1.0) * (ddft[2][i][j] - ddft[1][i][j]); + } pix = (short*)image[row*width]; memcpy (prev, pix, sizeof prev); frow = row / (height-1.0) * (dim[2]-1); diff --git a/converter/other/cameratopam/foveon.h b/converter/other/cameratopam/foveon.h index 57be2244..c9bf48a8 100644 --- a/converter/other/cameratopam/foveon.h +++ b/converter/other/cameratopam/foveon.h @@ -1,14 +1,17 @@ #include "pm.h" +#include "cameratopam.h" +#include "camera.h" + void parse_foveon(FILE * const ifp); void -foveon_interpolate(float coeff[3][4]); +foveon_interpolate(Image const image, + float coeff[3][4]); -void -foveon_load_raw(void); +LoadRawFn foveon_load_raw; void -foveon_coeff(bool * const useCoeffP, - float coeff[3][4]); +foveon_coeff(int * const useCoeffP, + float coeff[3][4]); diff --git a/converter/other/cameratopam/global_variables.h b/converter/other/cameratopam/global_variables.h index c8732d5a..2bfc08c9 100644 --- a/converter/other/cameratopam/global_variables.h +++ b/converter/other/cameratopam/global_variables.h @@ -23,7 +23,6 @@ extern time_t timestamp; extern int is_foveon; extern int is_dng; extern int is_canon; -extern unsigned short (*image)[4]; extern int maximum; extern int clip_max; extern short order; diff --git a/converter/other/cameratopam/identify.c b/converter/other/cameratopam/identify.c index a101c8ad..394ba0a7 100644 --- a/converter/other/cameratopam/identify.c +++ b/converter/other/cameratopam/identify.c @@ -2,6 +2,8 @@ #include <string.h> #include "pm.h" +#include "pm_c_util.h" +#include "nstring.h" #include "global_variables.h" #include "util.h" @@ -15,235 +17,250 @@ #if HAVE_INT64 - static bool const have64BitArithmetic = true; +static bool const have64BitArithmetic = true; #else - static bool const have64BitArithmetic = false; +static bool const have64BitArithmetic = false; #endif -static loadRawFn load_raw; /* This does the same as the function of the same name in the GNU C library */ static const char *memmem_internal (const char *haystack, size_t haystacklen, - const char *needle, size_t needlelen) + const char *needle, size_t needlelen) { - const char *c; - for (c = haystack; c <= haystack + haystacklen - needlelen; c++) - if (!memcmp (c, needle, needlelen)) - return c; - return NULL; + const char *c; + for (c = haystack; c <= haystack + haystacklen - needlelen; c++) + if (!memcmp (c, needle, needlelen)) + return c; + return NULL; } -/* - Thanks to Adobe for providing these excellent CAM -> XYZ matrices! - */ + + static void -adobe_coeff() -{ - static const struct { - const char *prefix; - short trans[12]; - } table[] = { - { "Canon EOS D2000C", - { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } }, - { "Canon EOS D30", - { 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } }, - { "Canon EOS D60", - { 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } }, - { "Canon EOS 10D", - { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, - { "Canon EOS 20D", - { 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } }, - { "Canon EOS-1Ds Mark II", - { 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } }, - { "Canon EOS-1D Mark II", - { 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 } }, - { "Canon EOS-1DS", - { 4374,3631,-1743,-7520,15212,2472,-2892,3632,8161 } }, - { "Canon EOS-1D", - { 6906,-278,-1017,-6649,15074,1621,-2848,3897,7611 } }, - { "Canon EOS", - { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, - { "Canon PowerShot 600", - { -3822,10019,1311,4085,-157,3386,-5341,10829,4812,-1969,10969,1126 } }, - { "Canon PowerShot A50", - { -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } }, - { "Canon PowerShot A5", - { -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 } }, - { "Canon PowerShot G1", - { -4778,9467,2172,4743,-1141,4344,-5146,9908,6077,-1566,11051,557 } }, - { "Canon PowerShot G2", - { 9087,-2693,-1049,-6715,14382,2537,-2291,2819,7790 } }, - { "Canon PowerShot G3", - { 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } }, - { "Canon PowerShot G5", - { 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } }, - { "Canon PowerShot G6", - { 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } }, - { "Canon PowerShot Pro1", - { 10062,-3522,-999,-7643,15117,2730,-765,817,7323 } }, - { "Canon PowerShot Pro70", - { -4155,9818,1529,3939,-25,4522,-5521,9870,6610,-2238,10873,1342 } }, - { "Canon PowerShot Pro90", - { -4963,9896,2235,4642,-987,4294,-5162,10011,5859,-1770,11230,577 } }, - { "Canon PowerShot S30", - { 10566,-3652,-1129,-6552,14662,2006,-2197,2581,7670 } }, - { "Canon PowerShot S40", - { 8510,-2487,-940,-6869,14231,2900,-2318,2829,9013 } }, - { "Canon PowerShot S45", - { 8163,-2333,-955,-6682,14174,2751,-2077,2597,8041 } }, - { "Canon PowerShot S50", - { 8882,-2571,-863,-6348,14234,2288,-1516,2172,6569 } }, - { "Canon PowerShot S70", - { 9976,-3810,-832,-7115,14463,2906,-901,989,7889 } }, - { "Contax N Digital", - { 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 } }, - { "EPSON R-D1", - { 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } }, - { "FUJIFILM FinePix E550", - { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } }, - { "FUJIFILM FinePix F700", - { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } }, - { "FUJIFILM FinePix S20Pro", - { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } }, - { "FUJIFILM FinePix S2Pro", - { 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 } }, - { "FUJIFILM FinePix S3Pro", - { 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } }, - { "FUJIFILM FinePix S5000", - { 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } }, - { "FUJIFILM FinePix S5100", - { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } }, - { "FUJIFILM FinePix S7000", - { 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } }, - { "Kodak DCS315C", - { 17523,-4827,-2510,756,8546,-137,6113,1649,2250 } }, - { "Kodak DCS330C", - { 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 } }, - { "KODAK DCS420", - { 10868,-1852,-644,-1537,11083,484,2343,628,2216 } }, - { "KODAK DCS460", - { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } }, - { "KODAK EOSDCS1", - { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } }, - { "KODAK EOSDCS3B", - { 9898,-2700,-940,-2478,12219,206,1985,634,1031 } }, - { "Kodak DCS520C", - { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } }, - { "Kodak DCS560C", - { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } }, - { "Kodak DCS620C", - { 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 } }, - { "Kodak DCS620X", - { 13095,-6231,154,12221,-21,-2137,895,4602,2258 } }, - { "Kodak DCS660C", - { 18244,-6351,-2739,-791,11193,-521,3711,-129,2802 } }, - { "Kodak DCS720X", - { 11775,-5884,950,9556,1846,-1286,-1019,6221,2728 } }, - { "Kodak DCS760C", - { 16623,-6309,-1411,-4344,13923,323,2285,274,2926 } }, - { "Kodak DCS Pro SLR", - { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } }, - { "Kodak DCS Pro 14nx", - { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } }, - { "Kodak DCS Pro 14", - { 7791,3128,-776,-8588,16458,2039,-2455,4006,6198 } }, - { "Kodak ProBack645", - { 16414,-6060,-1470,-3555,13037,473,2545,122,4948 } }, - { "Kodak ProBack", - { 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 } }, - { "LEICA DIGILUX 2", - { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } }, - { "Leaf Valeo", - { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } }, - { "Minolta DiMAGE 5", - { 8983,-2942,-963,-6556,14476,2237,-2426,2887,8014 } }, - { "Minolta DiMAGE 7", - { 9144,-2777,-998,-6676,14556,2281,-2470,3019,7744 } }, - { "Minolta DiMAGE A1", - { 9274,-2547,-1167,-8220,16323,1943,-2273,2720,8340 } }, - { "MINOLTA DiMAGE A200", - { 8560,-2487,-986,-8112,15535,2771,-1209,1324,7743 } }, - { "Minolta DiMAGE A2", - { 9097,-2726,-1053,-8073,15506,2762,-966,981,7763 } }, - { "MINOLTA DYNAX 7D", - { 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } }, - { "NIKON D100", - { 5915,-949,-778,-7516,15364,2282,-1228,1337,6404 } }, - { "NIKON D1H", - { 7577,-2166,-926,-7454,15592,1934,-2377,2808,8606 } }, - { "NIKON D1X", - { 7620,-2173,-966,-7604,15843,1805,-2356,2811,8439 } }, - { "NIKON D1", - { 7559,-2130,-965,-7611,15713,1972,-2478,3042,8290 } }, - { "NIKON D2H", - { 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } }, - { "NIKON D70", - { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, - { "NIKON E995", /* copied from E5000 */ - { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, - { "NIKON E2500", - { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, - { "NIKON E4500", - { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, - { "NIKON E5000", - { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, - { "NIKON E5400", - { 9349,-2987,-1001,-7919,15766,2266,-2098,2680,6839 } }, - { "NIKON E5700", - { -5368,11478,2368,5537,-113,3148,-4969,10021,5782,778,9028,211 } }, - { "NIKON E8400", - { 7842,-2320,-992,-8154,15718,2599,-1098,1342,7560 } }, - { "NIKON E8700", - { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } }, - { "NIKON E8800", - { 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } }, - { "OLYMPUS C5050", - { 10508,-3124,-1273,-6079,14294,1901,-1653,2306,6237 } }, - { "OLYMPUS C5060", - { 10445,-3362,-1307,-7662,15690,2058,-1135,1176,7602 } }, - { "OLYMPUS C70", - { 10793,-3791,-1146,-7498,15177,2488,-1390,1577,7321 } }, - { "OLYMPUS C80", - { 8606,-2509,-1014,-8238,15714,2703,-942,979,7760 } }, - { "OLYMPUS E-10", - { 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } }, - { "OLYMPUS E-1", - { 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } }, - { "OLYMPUS E-20", - { 13173,-4732,-1499,-5807,14036,1895,-2045,2452,7142 } }, - { "OLYMPUS E-300", - { 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } }, - { "PENTAX *ist D", - { 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 } }, - { "Panasonic DMC-LC1", - { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } }, - { "SONY DSC-F828", - { 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401,3481 } }, - { "SONY DSC-V3", - { 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } } - }; - double cc[4][4], cm[4][3], xyz[] = { 1,1,1 }; - char name[130]; - int i, j; +adobeCoeff(const char * const make, + const char * const model) { + /* + Thanks to Adobe for providing these excellent CAM -> XYZ matrices! + */ + struct CoeffTableEntry { + const char * prefix; + short trans[12]; + }; + + static struct CoeffTableEntry const table[] = { + { "Canon EOS D2000C", + { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } }, + { "Canon EOS D30", + { 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } }, + { "Canon EOS D60", + { 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } }, + { "Canon EOS 10D", + { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, + { "Canon EOS 20D", + { 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } }, + { "Canon EOS-1Ds Mark II", + { 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } }, + { "Canon EOS-1D Mark II", + { 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 } }, + { "Canon EOS-1DS", + { 4374,3631,-1743,-7520,15212,2472,-2892,3632,8161 } }, + { "Canon EOS-1D", + { 6906,-278,-1017,-6649,15074,1621,-2848,3897,7611 } }, + { "Canon EOS", + { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, + { "Canon PowerShot 600", + { -3822,10019,1311,4085,-157,3386,-5341,10829,4812,-1969,10969, + 1126} }, + { "Canon PowerShot A50", + { -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } }, + { "Canon PowerShot A5", + { -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547} }, + { "Canon PowerShot G1", + { -4778,9467,2172,4743,-1141,4344,-5146,9908,6077,-1566,11051,557} }, + { "Canon PowerShot G2", + { 9087,-2693,-1049,-6715,14382,2537,-2291,2819,7790 } }, + { "Canon PowerShot G3", + { 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } }, + { "Canon PowerShot G5", + { 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } }, + { "Canon PowerShot G6", + { 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } }, + { "Canon PowerShot Pro1", + { 10062,-3522,-999,-7643,15117,2730,-765,817,7323 } }, + { "Canon PowerShot Pro70", + { -4155,9818,1529,3939,-25,4522,-5521,9870,6610,-2238,10873,1342 } }, + { "Canon PowerShot Pro90", + { -4963,9896,2235,4642,-987,4294,-5162,10011,5859,-1770,11230,577} }, + { "Canon PowerShot S30", + { 10566,-3652,-1129,-6552,14662,2006,-2197,2581,7670 } }, + { "Canon PowerShot S40", + { 8510,-2487,-940,-6869,14231,2900,-2318,2829,9013 } }, + { "Canon PowerShot S45", + { 8163,-2333,-955,-6682,14174,2751,-2077,2597,8041 } }, + { "Canon PowerShot S50", + { 8882,-2571,-863,-6348,14234,2288,-1516,2172,6569 } }, + { "Canon PowerShot S70", + { 9976,-3810,-832,-7115,14463,2906,-901,989,7889 } }, + { "Contax N Digital", + { 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 } }, + { "EPSON R-D1", + { 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } }, + { "FUJIFILM FinePix E550", + { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } }, + { "FUJIFILM FinePix F700", + { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } }, + { "FUJIFILM FinePix S20Pro", + { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } }, + { "FUJIFILM FinePix S2Pro", + { 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 } }, + { "FUJIFILM FinePix S3Pro", + { 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } }, + { "FUJIFILM FinePix S5000", + { 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } }, + { "FUJIFILM FinePix S5100", + { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } }, + { "FUJIFILM FinePix S7000", + { 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } }, + { "Kodak DCS315C", + { 17523,-4827,-2510,756,8546,-137,6113,1649,2250 } }, + { "Kodak DCS330C", + { 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 } }, + { "KODAK DCS420", + { 10868,-1852,-644,-1537,11083,484,2343,628,2216 } }, + { "KODAK DCS460", + { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } }, + { "KODAK EOSDCS1", + { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } }, + { "KODAK EOSDCS3B", + { 9898,-2700,-940,-2478,12219,206,1985,634,1031 } }, + { "Kodak DCS520C", + { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } }, + { "Kodak DCS560C", + { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } }, + { "Kodak DCS620C", + { 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 } }, + { "Kodak DCS620X", + { 13095,-6231,154,12221,-21,-2137,895,4602,2258 } }, + { "Kodak DCS660C", + { 18244,-6351,-2739,-791,11193,-521,3711,-129,2802 } }, + { "Kodak DCS720X", + { 11775,-5884,950,9556,1846,-1286,-1019,6221,2728 } }, + { "Kodak DCS760C", + { 16623,-6309,-1411,-4344,13923,323,2285,274,2926 } }, + { "Kodak DCS Pro SLR", + { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } }, + { "Kodak DCS Pro 14nx", + { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } }, + { "Kodak DCS Pro 14", + { 7791,3128,-776,-8588,16458,2039,-2455,4006,6198 } }, + { "Kodak ProBack645", + { 16414,-6060,-1470,-3555,13037,473,2545,122,4948 } }, + { "Kodak ProBack", + { 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 } }, + { "LEICA DIGILUX 2", + { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } }, + { "Leaf Valeo", + { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } }, + { "Minolta DiMAGE 5", + { 8983,-2942,-963,-6556,14476,2237,-2426,2887,8014 } }, + { "Minolta DiMAGE 7", + { 9144,-2777,-998,-6676,14556,2281,-2470,3019,7744 } }, + { "Minolta DiMAGE A1", + { 9274,-2547,-1167,-8220,16323,1943,-2273,2720,8340 } }, + { "MINOLTA DiMAGE A200", + { 8560,-2487,-986,-8112,15535,2771,-1209,1324,7743 } }, + { "Minolta DiMAGE A2", + { 9097,-2726,-1053,-8073,15506,2762,-966,981,7763 } }, + { "MINOLTA DYNAX 7D", + { 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } }, + { "NIKON D100", + { 5915,-949,-778,-7516,15364,2282,-1228,1337,6404 } }, + { "NIKON D1H", + { 7577,-2166,-926,-7454,15592,1934,-2377,2808,8606 } }, + { "NIKON D1X", + { 7620,-2173,-966,-7604,15843,1805,-2356,2811,8439 } }, + { "NIKON D1", + { 7559,-2130,-965,-7611,15713,1972,-2478,3042,8290 } }, + { "NIKON D2H", + { 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } }, + { "NIKON D70", + { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, + { "NIKON E995", /* copied from E5000 */ + { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, + { "NIKON E2500", + { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, + { "NIKON E4500", + { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, + { "NIKON E5000", + { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, + { "NIKON E5400", + { 9349,-2987,-1001,-7919,15766,2266,-2098,2680,6839 } }, + { "NIKON E5700", + { -5368,11478,2368,5537,-113,3148,-4969,10021,5782,778,9028,211 } }, + { "NIKON E8400", + { 7842,-2320,-992,-8154,15718,2599,-1098,1342,7560 } }, + { "NIKON E8700", + { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } }, + { "NIKON E8800", + { 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } }, + { "OLYMPUS C5050", + { 10508,-3124,-1273,-6079,14294,1901,-1653,2306,6237 } }, + { "OLYMPUS C5060", + { 10445,-3362,-1307,-7662,15690,2058,-1135,1176,7602 } }, + { "OLYMPUS C70", + { 10793,-3791,-1146,-7498,15177,2488,-1390,1577,7321 } }, + { "OLYMPUS C80", + { 8606,-2509,-1014,-8238,15714,2703,-942,979,7760 } }, + { "OLYMPUS E-10", + { 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } }, + { "OLYMPUS E-1", + { 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } }, + { "OLYMPUS E-20", + { 13173,-4732,-1499,-5807,14036,1895,-2045,2452,7142 } }, + { "OLYMPUS E-300", + { 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } }, + { "PENTAX *ist D", + { 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 } }, + { "Panasonic DMC-LC1", + { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } }, + { "SONY DSC-F828", + { 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401, + 3481} }, + { "SONY DSC-V3", + { 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } } + }; + double cc[4][4]; + double cm[4][3]; + double xyz[] = { 1,1,1 }; + char name[130]; + unsigned int i; - for (i=0; i < 4; i++) - for (j=0; j < 4; j++) - cc[i][j] = i == j; - sprintf (name, "%s %s", make, model); - for (i=0; i < sizeof table / sizeof *table; i++) - if (!strncmp (name, table[i].prefix, strlen(table[i].prefix))) { - for (j=0; j < 12; j++) - cm[0][j] = table[i].trans[j]; - dng_coeff (cc, cm, xyz); - break; + /* Make an identity matrix (1's on the diagonal) */ + for (i = 0; i < 4; ++i) { + unsigned int j; + for (j = 0; j < 4; ++j) + cc[i][j] = (i == j); + } + sprintf (name, "%s %s", make, model); + + for (i = 0; i < ARRAY_SIZE(table); ++i) { + const struct CoeffTableEntry * const entryP = &table[i]; + + if (strneq(name, entryP->prefix, strlen(entryP->prefix))) { + unsigned int j; + for (j = 0; j < 12; ++j) + cm[j/4][j%4] = entryP->trans[j]; + dng_coeff(cc, cm, xyz); + + break; + } } } -/* - Identify which camera created this file, and set global variables - accordingly. Return nonzero if the file cannot be decoded. - */ + + + int identify(FILE * const ifp, bool const use_secondary, @@ -252,932 +269,937 @@ identify(FILE * const ifp, float const blue_scale, unsigned int const four_color_rgb, const char * const inputFileName, - loadRawFn * const loadRawFnP) -{ - char head[32]; - char * c; - unsigned hlen, fsize, i; - static const struct { - int fsize; - char make[12], model[15], withjpeg; - } table[] = { - { 62464, "Kodak", "DC20" ,0 }, - { 124928, "Kodak", "DC20" ,0 }, - { 311696, "ST Micro", "STV680 VGA" ,0 }, /* SPYz */ - { 787456, "Creative", "PC-CAM 600" ,0 }, - { 2465792, "NIKON", "E950" ,1 }, /* or E800,E700 */ - { 2940928, "NIKON", "E2100" ,1 }, /* or E2500 */ - { 4771840, "NIKON", "E990" ,1 }, /* or E995 */ - { 4775936, "NIKON", "E3700" ,1 }, /* or Optio 33WR */ - { 5869568, "NIKON", "E4300" ,1 }, /* or DiMAGE Z2 */ - { 5865472, "NIKON", "E4500" ,0 }, - { 1976352, "CASIO", "QV-2000UX" ,0 }, - { 3217760, "CASIO", "QV-3*00EX" ,0 }, - { 6218368, "CASIO", "QV-5700" ,0 }, - { 7530816, "CASIO", "QV-R51" ,1 }, - { 7684000, "CASIO", "QV-4000" ,0 }, - { 7753344, "CASIO", "EX-Z55" ,1 }, - { 9313536, "CASIO", "EX-P600" ,1 }, - { 10979200, "CASIO", "EX-P700" ,1 }, - { 3178560, "PENTAX", "Optio S" ,1 }, /* 8-bit */ - { 4841984, "PENTAX", "Optio S" ,1 }, /* 12-bit */ - { 6114240, "PENTAX", "Optio S4" ,1 }, /* or S4i */ - { 12582980, "Sinar", "" ,0 } }; - static const char *corp[] = - { "Canon", "NIKON", "EPSON", "Kodak", "OLYMPUS", "PENTAX", - "MINOLTA", "Minolta", "Konica", "CASIO" }; - float tmp; - - /* What format is this file? Set make[] if we recognize it. */ + LoadRawFn ** const loadRawFnP) { +/*---------------------------------------------------------------------------- + Identify which camera created this file, and set global variables + accordingly. Return nonzero if the file cannot be decoded. +-----------------------------------------------------------------------------*/ + char head[32]; + char * c; + unsigned hlen, fsize, i; + static const struct { + int fsize; + char make[12], model[15], withjpeg; + } table[] = { + { 62464, "Kodak", "DC20" ,0 }, + { 124928, "Kodak", "DC20" ,0 }, + { 311696, "ST Micro", "STV680 VGA" ,0 }, /* SPYz */ + { 787456, "Creative", "PC-CAM 600" ,0 }, + { 2465792, "NIKON", "E950" ,1 }, /* or E800,E700 */ + { 2940928, "NIKON", "E2100" ,1 }, /* or E2500 */ + { 4771840, "NIKON", "E990" ,1 }, /* or E995 */ + { 4775936, "NIKON", "E3700" ,1 }, /* or Optio 33WR */ + { 5869568, "NIKON", "E4300" ,1 }, /* or DiMAGE Z2 */ + { 5865472, "NIKON", "E4500" ,0 }, + { 1976352, "CASIO", "QV-2000UX" ,0 }, + { 3217760, "CASIO", "QV-3*00EX" ,0 }, + { 6218368, "CASIO", "QV-5700" ,0 }, + { 7530816, "CASIO", "QV-R51" ,1 }, + { 7684000, "CASIO", "QV-4000" ,0 }, + { 7753344, "CASIO", "EX-Z55" ,1 }, + { 9313536, "CASIO", "EX-P600" ,1 }, + { 10979200, "CASIO", "EX-P700" ,1 }, + { 3178560, "PENTAX", "Optio S" ,1 }, /* 8-bit */ + { 4841984, "PENTAX", "Optio S" ,1 }, /* 12-bit */ + { 6114240, "PENTAX", "Optio S4" ,1 }, /* or S4i */ + { 12582980, "Sinar", "" ,0 } }; + static const char *corp[] = + { "Canon", "NIKON", "EPSON", "Kodak", "OLYMPUS", "PENTAX", + "MINOLTA", "Minolta", "Konica", "CASIO" }; + float tmp; + LoadRawFn * load_raw; - raw_height = raw_width = fuji_width = flip = 0; - make[0] = model[0] = model2[0] = 0; - memset (white, 0, sizeof white); - timestamp = tiff_samples = 0; - data_offset = meta_length = tiff_data_compression = 0; - zero_after_ff = is_dng = fuji_secondary = filters = 0; - black = is_foveon = use_coeff = 0; - use_gamma = xmag = ymag = 1; - for (i=0; i < 4; i++) { - cam_mul[i] = 1 & i; - pre_mul[i] = 1; - } - colors = 3; - for (i=0; i < 0x1000; i++) curve[i] = i; - maximum = 0xfff; -#ifdef USE_LCMS - profile_length = 0; -#endif + /* What format is this file? Set make[] if we recognize it. */ - order = get2(ifp); - hlen = get4(ifp); - fseek (ifp, 0, SEEK_SET); - fread (head, 1, 32, ifp); - fseek (ifp, 0, SEEK_END); - fsize = ftell(ifp); - if ((c = (char*)memmem_internal(head, 32, "MMMMRawT", 8))) { - strcpy (make, "Phase One"); - data_offset = c - head; - fseek (ifp, data_offset + 8, SEEK_SET); - fseek (ifp, get4(ifp) + 136, SEEK_CUR); - raw_width = get4(ifp); - fseek (ifp, 12, SEEK_CUR); - raw_height = get4(ifp); - } else if (order == 0x4949 || order == 0x4d4d) { - if (!memcmp (head+6, "HEAPCCDR", 8)) { - data_offset = hlen; - parse_ciff(ifp, hlen, fsize - hlen); - } else { - parse_tiff(ifp, 0); - if (!strncmp(make,"NIKON",5) && filters == 0) - make[0] = 0; + raw_height = raw_width = fuji_width = flip = 0; + make[0] = model[0] = model2[0] = 0; + memset (white, 0, sizeof white); + timestamp = tiff_samples = 0; + data_offset = meta_length = tiff_data_compression = 0; + zero_after_ff = is_dng = fuji_secondary = filters = 0; + black = is_foveon = use_coeff = 0; + use_gamma = xmag = ymag = 1; + for (i=0; i < 4; i++) { + cam_mul[i] = 1 & i; + pre_mul[i] = 1; } - } else if (!memcmp (head, "\0MRM", 4)) - parse_minolta(ifp); + colors = 3; + for (i=0; i < 0x1000; i++) curve[i] = i; + maximum = 0xfff; + + order = get2(ifp); + hlen = get4(ifp); + fseek (ifp, 0, SEEK_SET); + fread (head, 1, 32, ifp); + fseek (ifp, 0, SEEK_END); + fsize = ftell(ifp); + if ((c = (char*)memmem_internal(head, 32, "MMMMRawT", 8))) { + strcpy (make, "Phase One"); + data_offset = c - head; + fseek (ifp, data_offset + 8, SEEK_SET); + fseek (ifp, get4(ifp) + 136, SEEK_CUR); + raw_width = get4(ifp); + fseek (ifp, 12, SEEK_CUR); + raw_height = get4(ifp); + } else if (order == 0x4949 || order == 0x4d4d) { + if (!memcmp (head+6, "HEAPCCDR", 8)) { + data_offset = hlen; + parse_ciff(ifp, hlen, fsize - hlen); + } else { + parse_tiff(ifp, 0); + if (!strncmp(make,"NIKON",5) && filters == 0) + make[0] = 0; + } + } else if (!memcmp (head, "\0MRM", 4)) + parse_minolta(ifp); else if (!memcmp (head, "\xff\xd8\xff\xe1", 4) && - !memcmp (head+6, "Exif", 4)) { - fseek (ifp, 4, SEEK_SET); - fseek (ifp, 4 + get2(ifp), SEEK_SET); - if (fgetc(ifp) != 0xff) - parse_tiff(ifp, 12); - } else if (!memcmp (head, "BM", 2)) { - data_offset = 0x1000; - order = 0x4949; - fseek (ifp, 38, SEEK_SET); - if (get4(ifp) == 2834 && get4(ifp) == 2834) { - strcpy (model, "BMQ"); - flip = 3; - goto nucore; - } - } else if (!memcmp (head, "BR", 2)) { - strcpy (model, "RAW"); -nucore: - strcpy (make, "Nucore"); - order = 0x4949; - fseek (ifp, 10, SEEK_SET); - data_offset += get4(ifp); - get4(ifp); - raw_width = get4(ifp); - raw_height = get4(ifp); - if (model[0] == 'B' && raw_width == 2597) { - raw_width++; - data_offset -= 0x1000; - } - } else if (!memcmp (head+25, "ARECOYK", 7)) { - strcpy (make, "Contax"); - strcpy (model,"N Digital"); - fseek (ifp, 60, SEEK_SET); - camera_red = get4(ifp); - camera_red /= get4(ifp); - camera_blue = get4(ifp); - camera_blue = get4(ifp) / camera_blue; - } else if (!memcmp (head, "FUJIFILM", 8)) { - long data_offset_long; - fseek (ifp, 84, SEEK_SET); - parse_tiff(ifp, get4(ifp)+12); - fseek (ifp, 100, SEEK_SET); - pm_readbiglong(ifp, &data_offset_long); - data_offset = data_offset_long; - } else if (!memcmp (head, "DSC-Image", 9)) - parse_rollei(ifp); - else if (!memcmp (head, "FOVb", 4)) - parse_foveon(ifp); - else - for (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) - parse_external_jpeg(inputFileName); - } - parse_mos(ifp, 8); - parse_mos(ifp, 3472); + !memcmp (head+6, "Exif", 4)) { + fseek (ifp, 4, SEEK_SET); + fseek (ifp, 4 + get2(ifp), SEEK_SET); + if (fgetc(ifp) != 0xff) + parse_tiff(ifp, 12); + } else if (!memcmp (head, "BM", 2)) { + data_offset = 0x1000; + order = 0x4949; + fseek (ifp, 38, SEEK_SET); + if (get4(ifp) == 2834 && get4(ifp) == 2834) { + strcpy (model, "BMQ"); + flip = 3; + goto nucore; + } + } else if (!memcmp (head, "BR", 2)) { + strcpy (model, "RAW"); + nucore: + strcpy (make, "Nucore"); + order = 0x4949; + fseek (ifp, 10, SEEK_SET); + data_offset += get4(ifp); + get4(ifp); + raw_width = get4(ifp); + raw_height = get4(ifp); + if (model[0] == 'B' && raw_width == 2597) { + raw_width++; + data_offset -= 0x1000; + } + } else if (!memcmp (head+25, "ARECOYK", 7)) { + strcpy (make, "Contax"); + strcpy (model,"N Digital"); + fseek (ifp, 60, SEEK_SET); + camera_red = get4(ifp); + camera_red /= get4(ifp); + camera_blue = get4(ifp); + camera_blue = get4(ifp) / camera_blue; + } else if (!memcmp (head, "FUJIFILM", 8)) { + long data_offset_long; + fseek (ifp, 84, SEEK_SET); + parse_tiff(ifp, get4(ifp)+12); + fseek (ifp, 100, SEEK_SET); + pm_readbiglong(ifp, &data_offset_long); + data_offset = data_offset_long; + } else if (!memcmp (head, "DSC-Image", 9)) + parse_rollei(ifp); + else if (!memcmp (head, "FOVb", 4)) + parse_foveon(ifp); + else + for (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) + parse_external_jpeg(inputFileName); + } + parse_mos(ifp, 8); + parse_mos(ifp, 3472); + + 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)) + make[16] = model[16] = 0; + c = make + strlen(make); /* Remove trailing spaces */ + while (*--c == ' ') *c = 0; + c = model + strlen(model); + while (*--c == ' ') *c = 0; + i = strlen(make); /* Remove make from model */ + if (!strncmp (model, make, i++)) + memmove (model, model+i, 64-i); + make[63] = model[63] = model2[63] = 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)) - make[16] = model[16] = 0; - c = make + strlen(make); /* Remove trailing spaces */ - while (*--c == ' ') *c = 0; - c = model + strlen(model); - while (*--c == ' ') *c = 0; - i = strlen(make); /* Remove make from model */ - if (!strncmp (model, make, i++)) - memmove (model, model+i, 64-i); - make[63] = model[63] = model2[63] = 0; + if (verbose) + fprintf(stderr, "Make = '%s', Model = '%s'\n", make, model); - if (make[0] == 0) { - pm_message ("unrecognized file format."); - return 1; - } + if (make[0] == 0) { + pm_message ("unrecognized file format."); + return 1; + } /* File format is OK. Do we know this camera? */ /* Start with some useful defaults: */ - top_margin = left_margin = 0; - if ((raw_height | raw_width) < 0) - raw_height = raw_width = 0; - height = raw_height; - width = raw_width; - if (fuji_width) { - width = height + fuji_width; - height = width - 1; - ymag = 1; - } - load_raw = NULL; - if (is_dng) { - strcat (model, " DNG"); - if (!filters) - colors = tiff_samples; - if (tiff_data_compression == 1) - load_raw = adobe_dng_load_raw_nc; - if (tiff_data_compression == 7) - load_raw = adobe_dng_load_raw_lj; - goto dng_skip; - } + top_margin = left_margin = 0; + if ((raw_height | raw_width) < 0) + raw_height = raw_width = 0; + height = raw_height; + width = raw_width; + if (fuji_width) { + width = height + fuji_width; + height = width - 1; + ymag = 1; + } + load_raw = NULL; + if (is_dng) { + strcat (model, " DNG"); + if (!filters) + colors = tiff_samples; + if (tiff_data_compression == 1) + load_raw = adobe_dng_load_raw_nc; + if (tiff_data_compression == 7) + load_raw = adobe_dng_load_raw_lj; + goto dng_skip; + } -/* We'll try to decode anything from Canon or Nikon. */ + /* We'll try to decode anything from Canon or Nikon. */ - if (!filters) filters = 0x94949494; - if ((is_canon = !strcmp(make,"Canon"))) - load_raw = memcmp (head+6,"HEAPCCDR",8) ? - lossless_jpeg_load_raw : canon_compressed_load_raw; - if (!strcmp(make,"NIKON")) - load_raw = nikon_is_compressed() ? - nikon_compressed_load_raw : nikon_load_raw; + if (!filters) filters = 0x94949494; + if ((is_canon = !strcmp(make,"Canon"))) + load_raw = memcmp (head+6,"HEAPCCDR",8) ? + lossless_jpeg_load_raw : canon_compressed_load_raw; + if (!strcmp(make,"NIKON")) + load_raw = nikon_is_compressed() ? + nikon_compressed_load_raw : nikon_load_raw; -/* Set parameters based on camera name (for non-DNG files). */ + /* Set parameters based on camera name (for non-DNG files). */ - if (is_foveon) { - if (!have64BitArithmetic) - pm_error("This program was built without 64 bit arithmetic " - "capability and the Foveon format requires it."); - if (height*2 < width) ymag = 2; - if (width < height) xmag = 2; - filters = 0; - load_raw = foveon_load_raw; - foveon_coeff(&use_coeff, coeff); - } else if (!strcmp(model,"PowerShot 600")) { - height = 613; - width = 854; - colors = 4; - filters = 0xe1e4e1e4; - load_raw = canon_600_load_raw; - } else if (!strcmp(model,"PowerShot A5") || - !strcmp(model,"PowerShot A5 Zoom")) { - height = 773; - width = 960; - raw_width = 992; - colors = 4; - filters = 0x1e4e1e4e; - load_raw = canon_a5_load_raw; - } else if (!strcmp(model,"PowerShot A50")) { - height = 968; - width = 1290; - raw_width = 1320; - colors = 4; - filters = 0x1b4e4b1e; - load_raw = canon_a5_load_raw; - } else if (!strcmp(model,"PowerShot Pro70")) { - height = 1024; - width = 1552; - colors = 4; - filters = 0x1e4b4e1b; - load_raw = canon_a5_load_raw; - black = 34; - } else if (!strcmp(model,"PowerShot Pro90 IS")) { - width = 1896; - 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; - maximum = 0xfa0; - } 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,"EOS D2000C")) { - filters = 0x61616161; - black = curve[200]; - } else if (!strcmp(model,"EOS-1D")) { - raw_height = height = 1662; - raw_width = width = 2496; - data_offset = 288912; - filters = 0x61616161; - } else if (!strcmp(model,"EOS-1DS")) { - raw_height = height = 2718; - raw_width = width = 4082; - data_offset = 289168; - filters = 0x61616161; - } else if (is_canon && raw_width == 3516) { - top_margin = 14; - left_margin = 42; - 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 == 5108) { - top_margin = 13; - left_margin = 98; - maximum = 0xe80; -canon_cr2: - height = raw_height - top_margin; - width = raw_width - left_margin; - } else if (!strcmp(model,"D1")) { - camera_red *= 256/527.0; - camera_blue *= 256/317.0; - } else if (!strcmp(model,"D1X")) { - width = 4024; - ymag = 2; - } else if (!strcmp(model,"D100")) { - if (tiff_data_compression == 34713 && load_raw == nikon_load_raw) - raw_width = (width += 3) + 3; - } else if (!strcmp(model,"D2H")) { - width = 2482; - left_margin = 6; - } else if (!strcmp(model,"D2X")) { - width = 4312; - pre_mul[0] = 1.514; - pre_mul[2] = 1.727; - } else if (fsize == 2465792) { - height = 1203; - width = 1616; - filters = 0x4b4b4b4b; - colors = 4; - load_raw = nikon_e950_load_raw; - nikon_e950_coeff(); - pre_mul[0] = 1.18193; - pre_mul[2] = 1.16452; - pre_mul[3] = 1.17250; - } else if (!strcmp(model,"E990")) { - if (!timestamp && !nikon_e990()) goto cp_e995; - height = 1540; - width = 2064; - colors = 4; - filters = 0xb4b4b4b4; - nikon_e950_coeff(); - pre_mul[0] = 1.196; - pre_mul[1] = 1.246; - pre_mul[2] = 1.018; - } else if (!strcmp(model,"E995")) { -cp_e995: - strcpy (model, "E995"); - height = 1540; - width = 2064; - colors = 4; - filters = 0xe1e1e1e1; - } else if (!strcmp(model,"E2100")) { - if (!timestamp && !nikon_e2100()) goto cp_e2500; - width = 1616; - height = 1206; - load_raw = nikon_e2100_load_raw; - pre_mul[0] = 1.945; - pre_mul[2] = 1.040; - } else if (!strcmp(model,"E2500")) { -cp_e2500: - strcpy (model, "E2500"); - width = 1616; - height = 1204; - colors = 4; - filters = 0x4b4b4b4b; - } else if (!strcmp(model,"E3700")) { - if (!timestamp && pentax_optio33()) goto optio_33wr; - height = 1542; - width = 2064; - load_raw = nikon_e2100_load_raw; - pre_mul[0] = 1.818; - pre_mul[2] = 1.618; - } else if (!strcmp(model,"Optio 33WR")) { -optio_33wr: - strcpy (make, "PENTAX"); - strcpy (model,"Optio 33WR"); - height = 1542; - width = 2064; - load_raw = nikon_e2100_load_raw; - flip = 1; - filters = 0x16161616; - pre_mul[0] = 1.331; - pre_mul[2] = 1.820; - } else if (!strcmp(model,"E4300")) { - if (!timestamp && minolta_z2()) goto dimage_z2; - height = 1710; - width = 2288; - filters = 0x16161616; - pre_mul[0] = 508; - pre_mul[1] = 256; - pre_mul[2] = 322; - } else if (!strcmp(model,"DiMAGE Z2")) { -dimage_z2: - strcpy (make, "MINOLTA"); - strcpy (model,"DiMAGE Z2"); - height = 1710; - width = 2288; - filters = 0x16161616; - load_raw = nikon_e2100_load_raw; - pre_mul[0] = 508; - pre_mul[1] = 256; - pre_mul[2] = 450; - } else if (!strcmp(model,"E4500")) { - height = 1708; - width = 2288; - colors = 4; - filters = 0xb4b4b4b4; - } else if (!strcmp(model,"R-D1")) { - tiff_data_compression = 34713; - load_raw = nikon_load_raw; - } else if (!strcmp(model,"FinePixS2Pro")) { - height = 3584; - width = 3583; - fuji_width = 2144; - filters = 0x61616161; - load_raw = fuji_s2_load_raw; - black = 128; - strcpy (model+7, " S2Pro"); - } else if (!strcmp(model,"FinePix S3Pro")) { - height = 3583; - width = 3584; - fuji_width = 2144; - if (fsize > 18000000 && use_secondary) - data_offset += 4352*2*1444; - filters = 0x49494949; - load_raw = fuji_s3_load_raw; - maximum = 0xffff; - } else if (!strcmp(model,"FinePix S5000")) { - height = 2499; - width = 2500; - fuji_width = 1423; - filters = 0x49494949; - load_raw = fuji_s5000_load_raw; - maximum = 0x3e00; - } else if (!strcmp(model,"FinePix S5100") || - !strcmp(model,"FinePix S5500")) { - height = 1735; - width = 2304; - data_offset += width*10; - filters = 0x49494949; - load_raw = unpacked_load_raw; - maximum = 0xffff; - } else if (!strcmp(model,"FinePix E550") || - !strcmp(model,"FinePix F810") || - !strcmp(model,"FinePix S7000")) { - height = 3587; - width = 3588; - fuji_width = 2047; - filters = 0x49494949; - load_raw = fuji_s7000_load_raw; - maximum = 0x3e00; - } else if (!strcmp(model,"FinePix F700") || - !strcmp(model,"FinePix S20Pro")) { - height = 2523; - width = 2524; - fuji_width = 1440; - filters = 0x49494949; - load_raw = fuji_f700_load_raw; - maximum = 0x3e00; - } else if (!strcmp(model,"Digital Camera KD-400Z")) { - height = 1712; - width = 2312; - raw_width = 2336; - data_offset = 4034; - fseek (ifp, 2032, SEEK_SET); - goto konica_400z; - } else if (!strcmp(model,"Digital Camera KD-510Z")) { - data_offset = 4032; - pre_mul[0] = 1.297; - pre_mul[2] = 1.438; - fseek (ifp, 2032, SEEK_SET); - goto konica_510z; - } else if (!strcasecmp(make,"MINOLTA")) { - load_raw = unpacked_load_raw; - maximum = 0xf7d; - if (!strncmp(model,"DiMAGE A",8)) { - if (!strcmp(model,"DiMAGE A200")) { - filters = 0x49494949; - tmp = camera_red; - camera_red = 1 / camera_blue; - camera_blue = 1 / tmp; - } - load_raw = packed_12_load_raw; - maximum = model[8] == '1' ? 0xf8b : 0xfff; - } else if (!strncmp(model,"ALPHA",5) || - !strncmp(model,"DYNAX",5) || - !strncmp(model,"MAXXUM",6)) { - load_raw = packed_12_load_raw; - maximum = 0xffb; - } else if (!strncmp(model,"DiMAGE G",8)) { - if (model[8] == '4') { - data_offset = 5056; - pre_mul[0] = 1.602; - pre_mul[2] = 1.441; - fseek (ifp, 2078, SEEK_SET); - height = 1716; - width = 2304; - } else if (model[8] == '5') { - data_offset = 4016; - fseek (ifp, 1936, SEEK_SET); -konica_510z: - height = 1956; - width = 2607; - raw_width = 2624; - } else if (model[8] == '6') { - data_offset = 4032; - fseek (ifp, 2030, SEEK_SET); - height = 2136; - width = 2848; - } - filters = 0x61616161; -konica_400z: - load_raw = unpacked_load_raw; - maximum = 0x3df; - order = 0x4d4d; - camera_red = get2(ifp); - camera_blue = get2(ifp); - camera_red /= get2(ifp); - camera_blue /= get2(ifp); - } - if (pre_mul[0] == 1 && pre_mul[2] == 1) { - pre_mul[0] = 1.42; - pre_mul[2] = 1.25; - } - } else if (!strcmp(model,"*ist D")) { - load_raw = unpacked_load_raw; - } else if (!strcmp(model,"*ist DS")) { - height--; - load_raw = packed_12_load_raw; - } else if (!strcmp(model,"Optio S")) { - if (fsize == 3178560) { - height = 1540; - width = 2064; - load_raw = eight_bit_load_raw; - camera_red *= 4; - camera_blue *= 4; - pre_mul[0] = 1.391; - pre_mul[2] = 1.188; - } else { - height = 1544; - width = 2068; - raw_width = 3136; - load_raw = packed_12_load_raw; - maximum = 0xf7c; - pre_mul[0] = 1.137; - pre_mul[2] = 1.453; - } - } else if (!strncmp(model,"Optio S4",8)) { - height = 1737; - width = 2324; - raw_width = 3520; - load_raw = packed_12_load_raw; - maximum = 0xf7a; - pre_mul[0] = 1.980; - pre_mul[2] = 1.570; - } else if (!strcmp(model,"STV680 VGA")) { - height = 484; - width = 644; - load_raw = eight_bit_load_raw; - flip = 2; - filters = 0x16161616; - black = 16; - pre_mul[0] = 1.097; - pre_mul[2] = 1.128; - } else if (!strcmp(make,"Phase One")) { - switch (raw_height) { - case 2060: - strcpy (model, "LightPhase"); - height = 2048; - width = 3080; - top_margin = 5; - left_margin = 22; - pre_mul[0] = 1.331; - pre_mul[2] = 1.154; - break; - case 2682: - strcpy (model, "H10"); - height = 2672; - width = 4012; - top_margin = 5; - left_margin = 26; - break; - case 4128: - strcpy (model, "H20"); - height = 4098; - width = 4098; - top_margin = 20; - left_margin = 26; - pre_mul[0] = 1.963; - pre_mul[2] = 1.430; - break; - case 5488: - strcpy (model, "H25"); - height = 5458; - width = 4098; - top_margin = 20; - left_margin = 26; - pre_mul[0] = 2.80; - pre_mul[2] = 1.20; - } - filters = top_margin & 1 ? 0x94949494 : 0x49494949; - load_raw = phase_one_load_raw; - maximum = 0xffff; - } else if (!strcmp(model,"Ixpress")) { - height = 4084; - width = 4080; - filters = 0x49494949; - load_raw = ixpress_load_raw; - maximum = 0xffff; - pre_mul[0] = 1.963; - pre_mul[2] = 1.430; - } else if (!strcmp(make,"Sinar") && !memcmp(head,"8BPS",4)) { - fseek (ifp, 14, SEEK_SET); - height = get4(ifp); - width = get4(ifp); - filters = 0x61616161; - data_offset = 68; - load_raw = unpacked_load_raw; - maximum = 0xffff; - } else if (!strcmp(make,"Leaf")) { - if (height > width) - filters = 0x16161616; - load_raw = unpacked_load_raw; - maximum = 0x3fff; - strcpy (model, "Valeo"); - if (raw_width == 2060) { - filters = 0; - load_raw = leaf_load_raw; - maximum = 0xffff; - strcpy (model, "Volare"); - } - } else if (!strcmp(model,"DIGILUX 2") || !strcmp(model,"DMC-LC1")) { - height = 1928; - width = 2568; - data_offset = 1024; - load_raw = unpacked_load_raw; - maximum = 0xfff0; - } else if (!strcmp(model,"E-1")) { - filters = 0x61616161; - load_raw = unpacked_load_raw; - maximum = 0xfff0; - black = 1024; - } else if (!strcmp(model,"E-10")) { - load_raw = unpacked_load_raw; - maximum = 0xfff0; - black = 2048; - } else if (!strncmp(model,"E-20",4)) { - load_raw = unpacked_load_raw; - maximum = 0xffc0; - black = 2560; - } else if (!strcmp(model,"E-300")) { - width -= 21; - load_raw = olympus_e300_load_raw; - if (fsize > 15728640) { - load_raw = unpacked_load_raw; - maximum = 0xfc30; - } else - black = 62; - } else if (!strcmp(make,"OLYMPUS")) { - load_raw = olympus_cseries_load_raw; - if (!strcmp(model,"C5050Z") || - !strcmp(model,"C8080WZ")) - filters = 0x16161616; - } else if (!strcmp(model,"N Digital")) { - height = 2047; - width = 3072; - filters = 0x61616161; - data_offset = 0x1a00; - load_raw = packed_12_load_raw; - maximum = 0xf1e; - } else if (!strcmp(model,"DSC-F828")) { - width = 3288; - left_margin = 5; - load_raw = sony_load_raw; - filters = 0x9c9c9c9c; - colors = 4; - black = 491; - } else if (!strcmp(model,"DSC-V3")) { - width = 3109; - left_margin = 59; - load_raw = sony_load_raw; - } else if (!strcasecmp(make,"KODAK")) { - filters = 0x61616161; - if (!strcmp(model,"NC2000F")) { - width -= 4; - left_margin = 1; - for (i=176; i < 0x1000; i++) - curve[i] = curve[i-1]; - pre_mul[0] = 1.509; - pre_mul[2] = 2.686; - } else if (!strcmp(model,"EOSDCS3B")) { - width -= 4; - left_margin = 2; - } else if (!strcmp(model,"EOSDCS1")) { - width -= 4; - left_margin = 2; - } else if (!strcmp(model,"DCS315C")) { - black = 8; - } else if (!strcmp(model,"DCS330C")) { - black = 8; - } else if (!strcmp(model,"DCS420")) { - width -= 4; - left_margin = 2; - } else if (!strcmp(model,"DCS460")) { - width -= 4; - left_margin = 2; - } else if (!strcmp(model,"DCS460A")) { - width -= 4; - left_margin = 2; - colors = 1; - filters = 0; - } else if (!strcmp(model,"DCS520C")) { - black = 180; - } else if (!strcmp(model,"DCS560C")) { - black = 188; - } else if (!strcmp(model,"DCS620C")) { - black = 180; - } else if (!strcmp(model,"DCS620X")) { - black = 185; - } else if (!strcmp(model,"DCS660C")) { - black = 214; - } else if (!strcmp(model,"DCS660M")) { - black = 214; - colors = 1; - filters = 0; - } else if (!strcmp(model,"DCS760M")) { - colors = 1; - filters = 0; - } - switch (tiff_data_compression) { - case 0: /* No compression */ - case 1: - load_raw = kodak_easy_load_raw; - break; - case 7: /* Lossless JPEG */ - load_raw = lossless_jpeg_load_raw; - case 32867: - break; - case 65000: /* Kodak DCR compression */ + if (is_foveon) { if (!have64BitArithmetic) pm_error("This program was built without 64 bit arithmetic " - "capability, and Kodak DCR compression requires it."); - if (kodak_data_compression == 32803) - load_raw = kodak_compressed_load_raw; - else { - load_raw = kodak_yuv_load_raw; - height = (height+1) & -2; - width = (width +1) & -2; + "capability and the Foveon format requires it."); + if (height*2 < width) ymag = 2; + if (width < height) xmag = 2; + filters = 0; + load_raw = foveon_load_raw; + foveon_coeff(&use_coeff, coeff); + } else if (!strcmp(model,"PowerShot 600")) { + height = 613; + width = 854; + colors = 4; + filters = 0xe1e4e1e4; + load_raw = canon_600_load_raw; + } else if (!strcmp(model,"PowerShot A5") || + !strcmp(model,"PowerShot A5 Zoom")) { + height = 773; + width = 960; + raw_width = 992; + colors = 4; + filters = 0x1e4e1e4e; + load_raw = canon_a5_load_raw; + } else if (!strcmp(model,"PowerShot A50")) { + height = 968; + width = 1290; + raw_width = 1320; + colors = 4; + filters = 0x1b4e4b1e; + load_raw = canon_a5_load_raw; + } else if (!strcmp(model,"PowerShot Pro70")) { + height = 1024; + width = 1552; + colors = 4; + filters = 0x1e4b4e1b; + load_raw = canon_a5_load_raw; + black = 34; + } else if (!strcmp(model,"PowerShot Pro90 IS")) { + width = 1896; + 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; + maximum = 0xfa0; + } 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,"EOS D2000C")) { + filters = 0x61616161; + black = curve[200]; + } else if (!strcmp(model,"EOS-1D")) { + raw_height = height = 1662; + raw_width = width = 2496; + data_offset = 288912; + filters = 0x61616161; + } else if (!strcmp(model,"EOS-1DS")) { + raw_height = height = 2718; + raw_width = width = 4082; + data_offset = 289168; + filters = 0x61616161; + } else if (is_canon && raw_width == 3516) { + top_margin = 14; + left_margin = 42; + 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 == 5108) { + top_margin = 13; + left_margin = 98; + maximum = 0xe80; + canon_cr2: + height = raw_height - top_margin; + width = raw_width - left_margin; + } else if (!strcmp(model,"D1")) { + camera_red *= 256/527.0; + camera_blue *= 256/317.0; + } else if (!strcmp(model,"D1X")) { + width = 4024; + ymag = 2; + } else if (!strcmp(model,"D100")) { + if (tiff_data_compression == 34713 && load_raw == nikon_load_raw) + raw_width = (width += 3) + 3; + } else if (!strcmp(model,"D2H")) { + width = 2482; + left_margin = 6; + } else if (!strcmp(model,"D2X")) { + width = 4312; + pre_mul[0] = 1.514; + pre_mul[2] = 1.727; + } else if (fsize == 2465792) { + height = 1203; + width = 1616; + filters = 0x4b4b4b4b; + colors = 4; + load_raw = nikon_e950_load_raw; + nikon_e950_coeff(); + pre_mul[0] = 1.18193; + pre_mul[2] = 1.16452; + pre_mul[3] = 1.17250; + } else if (!strcmp(model,"E990")) { + if (!timestamp && !nikon_e990()) goto cp_e995; + height = 1540; + width = 2064; + colors = 4; + filters = 0xb4b4b4b4; + nikon_e950_coeff(); + pre_mul[0] = 1.196; + pre_mul[1] = 1.246; + pre_mul[2] = 1.018; + } else if (!strcmp(model,"E995")) { + cp_e995: + strcpy (model, "E995"); + height = 1540; + width = 2064; + colors = 4; + filters = 0xe1e1e1e1; + } else if (!strcmp(model,"E2100")) { + if (!timestamp && !nikon_e2100()) goto cp_e2500; + width = 1616; + height = 1206; + load_raw = nikon_e2100_load_raw; + pre_mul[0] = 1.945; + pre_mul[2] = 1.040; + } else if (!strcmp(model,"E2500")) { + cp_e2500: + strcpy (model, "E2500"); + width = 1616; + height = 1204; + colors = 4; + filters = 0x4b4b4b4b; + } else if (!strcmp(model,"E3700")) { + if (!timestamp && pentax_optio33()) goto optio_33wr; + height = 1542; + width = 2064; + load_raw = nikon_e2100_load_raw; + pre_mul[0] = 1.818; + pre_mul[2] = 1.618; + } else if (!strcmp(model,"Optio 33WR")) { + optio_33wr: + strcpy (make, "PENTAX"); + strcpy (model,"Optio 33WR"); + height = 1542; + width = 2064; + load_raw = nikon_e2100_load_raw; + flip = 1; + filters = 0x16161616; + pre_mul[0] = 1.331; + pre_mul[2] = 1.820; + } else if (!strcmp(model,"E4300")) { + if (!timestamp && minolta_z2()) goto dimage_z2; + height = 1710; + width = 2288; + filters = 0x16161616; + pre_mul[0] = 508; + pre_mul[1] = 256; + pre_mul[2] = 322; + } else if (!strcmp(model,"DiMAGE Z2")) { + dimage_z2: + strcpy (make, "MINOLTA"); + strcpy (model,"DiMAGE Z2"); + height = 1710; + width = 2288; + filters = 0x16161616; + load_raw = nikon_e2100_load_raw; + pre_mul[0] = 508; + pre_mul[1] = 256; + pre_mul[2] = 450; + } else if (!strcmp(model,"E4500")) { + height = 1708; + width = 2288; + colors = 4; + filters = 0xb4b4b4b4; + } else if (!strcmp(model,"R-D1")) { + tiff_data_compression = 34713; + load_raw = nikon_load_raw; + } else if (!strcmp(model,"FinePixS2Pro")) { + height = 3584; + width = 3583; + fuji_width = 2144; + filters = 0x61616161; + load_raw = fuji_s2_load_raw; + black = 128; + strcpy (model+7, " S2Pro"); + } else if (!strcmp(model,"FinePix S3Pro")) { + height = 3583; + width = 3584; + fuji_width = 2144; + if (fsize > 18000000 && use_secondary) + data_offset += 4352*2*1444; + filters = 0x49494949; + load_raw = fuji_s3_load_raw; + maximum = 0xffff; + } else if (!strcmp(model,"FinePix S5000")) { + height = 2499; + width = 2500; + fuji_width = 1423; + filters = 0x49494949; + load_raw = fuji_s5000_load_raw; + maximum = 0x3e00; + } else if (!strcmp(model,"FinePix S5100") || + !strcmp(model,"FinePix S5500")) { + height = 1735; + width = 2304; + data_offset += width*10; + filters = 0x49494949; + load_raw = unpacked_load_raw; + maximum = 0xffff; + } else if (!strcmp(model,"FinePix E550") || + !strcmp(model,"FinePix F810") || + !strcmp(model,"FinePix S7000")) { + height = 3587; + width = 3588; + fuji_width = 2047; + filters = 0x49494949; + load_raw = fuji_s7000_load_raw; + maximum = 0x3e00; + } else if (!strcmp(model,"FinePix F700") || + !strcmp(model,"FinePix S20Pro")) { + height = 2523; + width = 2524; + fuji_width = 1440; + filters = 0x49494949; + load_raw = fuji_f700_load_raw; + maximum = 0x3e00; + } else if (!strcmp(model,"Digital Camera KD-400Z")) { + height = 1712; + width = 2312; + raw_width = 2336; + data_offset = 4034; + fseek (ifp, 2032, SEEK_SET); + goto konica_400z; + } else if (!strcmp(model,"Digital Camera KD-510Z")) { + data_offset = 4032; + pre_mul[0] = 1.297; + pre_mul[2] = 1.438; + fseek (ifp, 2032, SEEK_SET); + goto konica_510z; + } else if (!strcasecmp(make,"MINOLTA")) { + load_raw = unpacked_load_raw; + maximum = 0xf7d; + if (!strncmp(model,"DiMAGE A",8)) { + if (!strcmp(model,"DiMAGE A200")) { + filters = 0x49494949; + tmp = camera_red; + camera_red = 1 / camera_blue; + camera_blue = 1 / tmp; + } + load_raw = packed_12_load_raw; + maximum = model[8] == '1' ? 0xf8b : 0xfff; + } else if (!strncmp(model,"ALPHA",5) || + !strncmp(model,"DYNAX",5) || + !strncmp(model,"MAXXUM",6)) { + load_raw = packed_12_load_raw; + maximum = 0xffb; + } else if (!strncmp(model,"DiMAGE G",8)) { + if (model[8] == '4') { + data_offset = 5056; + pre_mul[0] = 1.602; + pre_mul[2] = 1.441; + fseek (ifp, 2078, SEEK_SET); + height = 1716; + width = 2304; + } else if (model[8] == '5') { + data_offset = 4016; + fseek (ifp, 1936, SEEK_SET); + konica_510z: + height = 1956; + width = 2607; + raw_width = 2624; + } else if (model[8] == '6') { + data_offset = 4032; + fseek (ifp, 2030, SEEK_SET); + height = 2136; + width = 2848; + } + filters = 0x61616161; + konica_400z: + load_raw = unpacked_load_raw; + maximum = 0x3df; + order = 0x4d4d; + camera_red = get2(ifp); + camera_blue = get2(ifp); + camera_red /= get2(ifp); + camera_blue /= get2(ifp); + } + if (pre_mul[0] == 1 && pre_mul[2] == 1) { + pre_mul[0] = 1.42; + pre_mul[2] = 1.25; + } + } else if (!strcmp(model,"*ist D")) { + load_raw = unpacked_load_raw; + } else if (!strcmp(model,"*ist DS")) { + height--; + load_raw = packed_12_load_raw; + } else if (!strcmp(model,"Optio S")) { + if (fsize == 3178560) { + height = 1540; + width = 2064; + load_raw = eight_bit_load_raw; + camera_red *= 4; + camera_blue *= 4; + pre_mul[0] = 1.391; + pre_mul[2] = 1.188; + } else { + height = 1544; + width = 2068; + raw_width = 3136; + load_raw = packed_12_load_raw; + maximum = 0xf7c; + pre_mul[0] = 1.137; + pre_mul[2] = 1.453; + } + } else if (!strncmp(model,"Optio S4",8)) { + height = 1737; + width = 2324; + raw_width = 3520; + load_raw = packed_12_load_raw; + maximum = 0xf7a; + pre_mul[0] = 1.980; + pre_mul[2] = 1.570; + } else if (!strcmp(model,"STV680 VGA")) { + height = 484; + width = 644; + load_raw = eight_bit_load_raw; + flip = 2; + filters = 0x16161616; + black = 16; + pre_mul[0] = 1.097; + pre_mul[2] = 1.128; + } else if (!strcmp(make,"Phase One")) { + switch (raw_height) { + case 2060: + strcpy (model, "LightPhase"); + height = 2048; + width = 3080; + top_margin = 5; + left_margin = 22; + pre_mul[0] = 1.331; + pre_mul[2] = 1.154; + break; + case 2682: + strcpy (model, "H10"); + height = 2672; + width = 4012; + top_margin = 5; + left_margin = 26; + break; + case 4128: + strcpy (model, "H20"); + height = 4098; + width = 4098; + top_margin = 20; + left_margin = 26; + pre_mul[0] = 1.963; + pre_mul[2] = 1.430; + break; + case 5488: + strcpy (model, "H25"); + height = 5458; + width = 4098; + top_margin = 20; + left_margin = 26; + pre_mul[0] = 2.80; + pre_mul[2] = 1.20; + } + filters = top_margin & 1 ? 0x94949494 : 0x49494949; + load_raw = phase_one_load_raw; + maximum = 0xffff; + } else if (!strcmp(model,"Ixpress")) { + height = 4084; + width = 4080; + filters = 0x49494949; + load_raw = ixpress_load_raw; + maximum = 0xffff; + pre_mul[0] = 1.963; + pre_mul[2] = 1.430; + } else if (!strcmp(make,"Sinar") && !memcmp(head,"8BPS",4)) { + fseek (ifp, 14, SEEK_SET); + height = get4(ifp); + width = get4(ifp); + filters = 0x61616161; + data_offset = 68; + load_raw = unpacked_load_raw; + maximum = 0xffff; + } else if (!strcmp(make,"Leaf")) { + if (height > width) + filters = 0x16161616; + load_raw = unpacked_load_raw; + maximum = 0x3fff; + strcpy (model, "Valeo"); + if (raw_width == 2060) { filters = 0; + load_raw = leaf_load_raw; + maximum = 0xffff; + strcpy (model, "Volare"); + } + } else if (!strcmp(model,"DIGILUX 2") || !strcmp(model,"DMC-LC1")) { + height = 1928; + width = 2568; + data_offset = 1024; + load_raw = unpacked_load_raw; + maximum = 0xfff0; + } else if (!strcmp(model,"E-1")) { + filters = 0x61616161; + load_raw = unpacked_load_raw; + maximum = 0xfff0; + black = 1024; + } else if (!strcmp(model,"E-10")) { + load_raw = unpacked_load_raw; + maximum = 0xfff0; + black = 2048; + } else if (!strncmp(model,"E-20",4)) { + load_raw = unpacked_load_raw; + maximum = 0xffc0; + black = 2560; + } else if (!strcmp(model,"E-300")) { + width -= 21; + load_raw = olympus_e300_load_raw; + if (fsize > 15728640) { + load_raw = unpacked_load_raw; + maximum = 0xfc30; + } else + black = 62; + } else if (!strcmp(make,"OLYMPUS")) { + load_raw = olympus_cseries_load_raw; + if (!strcmp(model,"C5050Z") || + !strcmp(model,"C8080WZ")) + filters = 0x16161616; + } else if (!strcmp(model,"N Digital")) { + height = 2047; + width = 3072; + filters = 0x61616161; + data_offset = 0x1a00; + load_raw = packed_12_load_raw; + maximum = 0xf1e; + } else if (!strcmp(model,"DSC-F828")) { + width = 3288; + left_margin = 5; + load_raw = sony_load_raw; + filters = 0x9c9c9c9c; + colors = 4; + black = 491; + } else if (!strcmp(model,"DSC-V3")) { + width = 3109; + left_margin = 59; + load_raw = sony_load_raw; + } else if (!strcasecmp(make,"KODAK")) { + filters = 0x61616161; + if (!strcmp(model,"NC2000F")) { + width -= 4; + left_margin = 1; + for (i=176; i < 0x1000; i++) + curve[i] = curve[i-1]; + pre_mul[0] = 1.509; + pre_mul[2] = 2.686; + } else if (!strcmp(model,"EOSDCS3B")) { + width -= 4; + left_margin = 2; + } else if (!strcmp(model,"EOSDCS1")) { + width -= 4; + left_margin = 2; + } else if (!strcmp(model,"DCS315C")) { + black = 8; + } else if (!strcmp(model,"DCS330C")) { + black = 8; + } else if (!strcmp(model,"DCS420")) { + width -= 4; + left_margin = 2; + } else if (!strcmp(model,"DCS460")) { + width -= 4; + left_margin = 2; + } else if (!strcmp(model,"DCS460A")) { + width -= 4; + left_margin = 2; + colors = 1; + filters = 0; + } else if (!strcmp(model,"DCS520C")) { + black = 180; + } else if (!strcmp(model,"DCS560C")) { + black = 188; + } else if (!strcmp(model,"DCS620C")) { + black = 180; + } else if (!strcmp(model,"DCS620X")) { + black = 185; + } else if (!strcmp(model,"DCS660C")) { + black = 214; + } else if (!strcmp(model,"DCS660M")) { + black = 214; + colors = 1; + filters = 0; + } else if (!strcmp(model,"DCS760M")) { + colors = 1; + filters = 0; + } + switch (tiff_data_compression) { + case 0: /* No compression */ + case 1: + load_raw = kodak_easy_load_raw; + break; + case 7: /* Lossless JPEG */ + load_raw = lossless_jpeg_load_raw; + case 32867: + break; + case 65000: /* Kodak DCR compression */ + if (!have64BitArithmetic) + pm_error("This program was built without 64 bit arithmetic " + "capability, and Kodak DCR compression requires it."); + if (kodak_data_compression == 32803) + load_raw = kodak_compressed_load_raw; + else { + load_raw = kodak_yuv_load_raw; + height = (height+1) & -2; + width = (width +1) & -2; + filters = 0; + } + break; + default: + pm_message ("%s %s uses unrecognized compression method %d.", + make, model, tiff_data_compression); + return 1; + } + if (!strcmp(model,"DC20")) { + height = 242; + if (fsize < 100000) { + width = 249; + raw_width = 256; + } else { + width = 501; + raw_width = 512; + } + data_offset = raw_width + 1; + colors = 4; + filters = 0x8d8d8d8d; + kodak_dc20_coeff (1.0); + pre_mul[1] = 1.179; + pre_mul[2] = 1.209; + pre_mul[3] = 1.036; + load_raw = kodak_easy_load_raw; + } else if (strstr(model,"DC25")) { + strcpy (model, "DC25"); + height = 242; + if (fsize < 100000) { + width = 249; + raw_width = 256; + data_offset = 15681; + } else { + width = 501; + raw_width = 512; + data_offset = 15937; + } + colors = 4; + filters = 0xb4b4b4b4; + load_raw = kodak_easy_load_raw; + } else if (!strcmp(model,"Digital Camera 40")) { + strcpy (model, "DC40"); + height = 512; + width = 768; + data_offset = 1152; + load_raw = kodak_radc_load_raw; + } else if (strstr(model,"DC50")) { + strcpy (model, "DC50"); + height = 512; + width = 768; + data_offset = 19712; + load_raw = kodak_radc_load_raw; + } else if (strstr(model,"DC120")) { + strcpy (model, "DC120"); + height = 976; + width = 848; + if (tiff_data_compression == 7) + load_raw = kodak_jpeg_load_raw; + else + load_raw = kodak_dc120_load_raw; + } + } else if (!strcmp(make,"Rollei")) { + switch (raw_width) { + case 1316: + height = 1030; + width = 1300; + top_margin = 1; + left_margin = 6; + break; + case 2568: + height = 1960; + width = 2560; + top_margin = 2; + left_margin = 8; + } + filters = 0x16161616; + load_raw = rollei_load_raw; + pre_mul[0] = 1.8; + pre_mul[2] = 1.3; + } else if (!strcmp(model,"PC-CAM 600")) { + height = 768; + data_offset = width = 1024; + filters = 0x49494949; + load_raw = eight_bit_load_raw; + pre_mul[0] = 1.14; + pre_mul[2] = 2.73; + } else if (!strcmp(model,"QV-2000UX")) { + height = 1208; + width = 1632; + data_offset = width * 2; + load_raw = eight_bit_load_raw; + } else if (!strcmp(model,"QV-3*00EX")) { + height = 1546; + width = 2070; + raw_width = 2080; + load_raw = eight_bit_load_raw; + } else if (!strcmp(model,"QV-4000")) { + height = 1700; + width = 2260; + load_raw = unpacked_load_raw; + maximum = 0xffff; + } else if (!strcmp(model,"QV-5700")) { + height = 1924; + width = 2576; + load_raw = casio_qv5700_load_raw; + } else if (!strcmp(model,"QV-R51")) { + height = 1926; + width = 2576; + raw_width = 3904; + load_raw = packed_12_load_raw; + pre_mul[0] = 1.340; + pre_mul[2] = 1.672; + } else if (!strcmp(model,"EX-Z55")) { + height = 1960; + width = 2570; + raw_width = 3904; + load_raw = packed_12_load_raw; + pre_mul[0] = 1.520; + pre_mul[2] = 1.316; + } else if (!strcmp(model,"EX-P600")) { + height = 2142; + width = 2844; + raw_width = 4288; + load_raw = packed_12_load_raw; + pre_mul[0] = 1.797; + pre_mul[2] = 1.219; + } else if (!strcmp(model,"EX-P700")) { + height = 2318; + width = 3082; + raw_width = 4672; + load_raw = packed_12_load_raw; + pre_mul[0] = 1.758; + pre_mul[2] = 1.504; + } else if (!strcmp(make,"Nucore")) { + filters = 0x61616161; + load_raw = unpacked_load_raw; + if (width == 2598) { + filters = 0x16161616; + load_raw = nucore_load_raw; + flip = 2; } - break; - default: - pm_message ("%s %s uses unrecognized compression method %d.", - make, model, tiff_data_compression); - return 1; - } - if (!strcmp(model,"DC20")) { - height = 242; - if (fsize < 100000) { - width = 249; - raw_width = 256; - } else { - width = 501; - raw_width = 512; - } - data_offset = raw_width + 1; - colors = 4; - filters = 0x8d8d8d8d; - kodak_dc20_coeff (1.0); - pre_mul[1] = 1.179; - pre_mul[2] = 1.209; - pre_mul[3] = 1.036; - load_raw = kodak_easy_load_raw; - } else if (strstr(model,"DC25")) { - strcpy (model, "DC25"); - height = 242; - if (fsize < 100000) { - width = 249; - raw_width = 256; - data_offset = 15681; - } else { - width = 501; - raw_width = 512; - data_offset = 15937; - } - colors = 4; - filters = 0xb4b4b4b4; - load_raw = kodak_easy_load_raw; - } else if (!strcmp(model,"Digital Camera 40")) { - strcpy (model, "DC40"); - height = 512; - width = 768; - data_offset = 1152; - load_raw = kodak_radc_load_raw; - } else if (strstr(model,"DC50")) { - strcpy (model, "DC50"); - height = 512; - width = 768; - data_offset = 19712; - load_raw = kodak_radc_load_raw; - } else if (strstr(model,"DC120")) { - strcpy (model, "DC120"); - height = 976; - width = 848; - if (tiff_data_compression == 7) - load_raw = kodak_jpeg_load_raw; - else - load_raw = kodak_dc120_load_raw; - } - } else if (!strcmp(make,"Rollei")) { - switch (raw_width) { - case 1316: - height = 1030; - width = 1300; - top_margin = 1; - left_margin = 6; - break; - case 2568: - height = 1960; - width = 2560; - top_margin = 2; - left_margin = 8; - } - filters = 0x16161616; - load_raw = rollei_load_raw; - pre_mul[0] = 1.8; - pre_mul[2] = 1.3; - } else if (!strcmp(model,"PC-CAM 600")) { - height = 768; - data_offset = width = 1024; - filters = 0x49494949; - load_raw = eight_bit_load_raw; - pre_mul[0] = 1.14; - pre_mul[2] = 2.73; - } else if (!strcmp(model,"QV-2000UX")) { - height = 1208; - width = 1632; - data_offset = width * 2; - load_raw = eight_bit_load_raw; - } else if (!strcmp(model,"QV-3*00EX")) { - height = 1546; - width = 2070; - raw_width = 2080; - load_raw = eight_bit_load_raw; - } else if (!strcmp(model,"QV-4000")) { - height = 1700; - width = 2260; - load_raw = unpacked_load_raw; - maximum = 0xffff; - } else if (!strcmp(model,"QV-5700")) { - height = 1924; - width = 2576; - load_raw = casio_qv5700_load_raw; - } else if (!strcmp(model,"QV-R51")) { - height = 1926; - width = 2576; - raw_width = 3904; - load_raw = packed_12_load_raw; - pre_mul[0] = 1.340; - pre_mul[2] = 1.672; - } else if (!strcmp(model,"EX-Z55")) { - height = 1960; - width = 2570; - raw_width = 3904; - load_raw = packed_12_load_raw; - pre_mul[0] = 1.520; - pre_mul[2] = 1.316; - } else if (!strcmp(model,"EX-P600")) { - height = 2142; - width = 2844; - raw_width = 4288; - load_raw = packed_12_load_raw; - pre_mul[0] = 1.797; - pre_mul[2] = 1.219; - } else if (!strcmp(model,"EX-P700")) { - height = 2318; - width = 3082; - raw_width = 4672; - load_raw = packed_12_load_raw; - pre_mul[0] = 1.758; - pre_mul[2] = 1.504; - } else if (!strcmp(make,"Nucore")) { - filters = 0x61616161; - load_raw = unpacked_load_raw; - if (width == 2598) { - filters = 0x16161616; - load_raw = nucore_load_raw; - flip = 2; } - } - if (!use_coeff) adobe_coeff(); + if (!use_coeff) + adobeCoeff(make, model); dng_skip: - if (!load_raw || !height) { - pm_message ("This program cannot handle data from %s %s.", - make, model); - return 1; - } + if (!load_raw || !height) { + pm_message ("This program cannot handle data from %s %s.", + make, model); + return 1; + } #ifdef NO_JPEG - if (load_raw == kodak_jpeg_load_raw) { - pm_message ("decoder was not linked with libjpeg."); - return 1; - } -#endif - if (!raw_height) raw_height = height; - if (!raw_width ) raw_width = width; - if (use_camera_rgb && colors == 3) - use_coeff = 0; - if (use_coeff) /* Apply user-selected color balance */ - for (i=0; i < colors; i++) { - coeff[0][i] *= red_scale; - coeff[2][i] *= blue_scale; + if (load_raw == kodak_jpeg_load_raw) { + pm_message ("decoder was not linked with libjpeg."); + return 1; } - if (four_color_rgb && filters && colors == 3) { - for (i=0; i < 32; i+=4) { - if ((filters >> i & 15) == 9) - filters |= 2 << i; - if ((filters >> i & 15) == 6) - filters |= 8 << i; +#endif + if (!raw_height) raw_height = height; + if (!raw_width ) raw_width = width; + if (use_camera_rgb && colors == 3) + use_coeff = 0; + if (use_coeff) /* Apply user-selected color balance */ + for (i=0; i < colors; i++) { + coeff[0][i] *= red_scale; + coeff[2][i] *= blue_scale; + } + if (four_color_rgb && filters && colors == 3) { + for (i=0; i < 32; i+=4) { + if ((filters >> i & 15) == 9) + filters |= 2 << i; + if ((filters >> i & 15) == 6) + filters |= 8 << i; + } + colors++; + pre_mul[3] = pre_mul[1]; + if (use_coeff) + for (i=0; i < 3; i++) + coeff[i][3] = coeff[i][1] /= 2; } - colors++; - pre_mul[3] = pre_mul[1]; - if (use_coeff) - for (i=0; i < 3; i++) - coeff[i][3] = coeff[i][1] /= 2; - } - fseek (ifp, data_offset, SEEK_SET); + fseek (ifp, data_offset, SEEK_SET); - *loadRawFnP = load_raw; + *loadRawFnP = load_raw; - return 0; + return 0; } diff --git a/converter/other/cameratopam/identify.h b/converter/other/cameratopam/identify.h index 012b807c..62c9aae5 100644 --- a/converter/other/cameratopam/identify.h +++ b/converter/other/cameratopam/identify.h @@ -1,4 +1,4 @@ -typedef void (*loadRawFn)(); +#include "camera.h" int identify(FILE * const ifp, @@ -8,4 +8,4 @@ identify(FILE * const ifp, float const blue_scale, unsigned int const four_color_rgb, const char * const inputFileName, - loadRawFn * const loadRawFnP); + LoadRawFn ** const loadRawFnP); diff --git a/converter/other/cameratopam/ljpeg.c b/converter/other/cameratopam/ljpeg.c index 4b092933..07791e25 100644 --- a/converter/other/cameratopam/ljpeg.c +++ b/converter/other/cameratopam/ljpeg.c @@ -20,127 +20,145 @@ */ int -ljpeg_start (FILE * ifp, struct jhead *jh) -{ - int i, tag, len; - unsigned char data[256], *dp; - - init_decoder(); - for (i=0; i < 4; i++) - jh->huff[i] = free_decode; - fread (data, 2, 1, ifp); - if (data[0] != 0xff || data[1] != 0xd8) return 0; - do { - fread (data, 2, 2, ifp); - tag = data[0] << 8 | data[1]; - len = (data[2] << 8 | data[3]); - if (len < 2) - pm_error("Length field is %u; must be at least 2", len); - else { - unsigned int const dataLen = len - 2; - if (tag <= 0xff00 || dataLen > 255) return 0; - fread (data, 1, dataLen, ifp); - switch (tag) { - case 0xffc3: - jh->bits = data[0]; - jh->high = data[1] << 8 | data[2]; - jh->wide = data[3] << 8 | data[4]; - jh->clrs = data[5]; - break; - case 0xffc4: - for (dp = data; dp < data+dataLen && *dp < 4; ) { - jh->huff[*dp] = free_decode; - dp = make_decoder (++dp, 0); +ljpeg_start(FILE * const ifP, + struct jhead * const jhP) { + + int i, tag; + unsigned char data[256], *dp; + + init_decoder(); + for (i=0; i < 4; i++) + jhP->huff[i] = free_decode; + fread (data, 2, 1, ifP); + if (data[0] != 0xff || data[1] != 0xd8) return 0; + do { + unsigned int len; + + fread (data, 2, 2, ifP); + tag = data[0] << 8 | data[1]; + len = data[2] << 8 | data[3]; + + if (len < 2) + pm_error("Length field is %u; must be at least 2", len); + else { + unsigned int const dataLen = len - 2; + + if (tag <= 0xff00 || dataLen > 255) return 0; + fread (data, 1, dataLen, ifP); + switch (tag) { + case 0xffc3: + jhP->bits = data[0]; + jhP->high = data[1] << 8 | data[2]; + jhP->wide = data[3] << 8 | data[4]; + jhP->clrs = data[5]; + break; + case 0xffc4: + for (dp = data; dp < data + dataLen && *dp < 4; ) { + jhP->huff[*dp] = free_decode; + dp = make_decoder (++dp, 0); + } + } } - } - } - } while (tag != 0xffda); - jh->row = calloc (jh->wide*jh->clrs, 2); - if (jh->row == NULL) - pm_error("Out of memory in ljpeg_start()"); - for (i=0; i < 4; i++) - jh->vpred[i] = 1 << (jh->bits-1); - zero_after_ff = 1; - getbits(ifp, -1); - return 1; + } while (tag != 0xffda); + jhP->row = calloc (jhP->wide*jhP->clrs, 2); + if (jhP->row == NULL) + pm_error("Out of memory in ljpeg_start()"); + for (i=0; i < 4; i++) + jhP->vpred[i] = 1 << (jhP->bits-1); + zero_after_ff = 1; + getbits(ifP, -1); + return 1; } + + int -ljpeg_diff (struct decode *dindex) -{ - int len, diff; - - while (dindex->branch[0]) - dindex = dindex->branch[getbits(ifp, 1)]; - diff = getbits(ifp, len = dindex->leaf); - if ((diff & (1 << (len-1))) == 0) - diff -= (1 << len) - 1; - return diff; +ljpeg_diff(FILE * const ifP, + struct decode * const dindexHeadP) { + + int len; + int diff; + struct decode * dindexP; + + for (dindexP = dindexHeadP; dindexP->branch[0]; ) + dindexP = dindexP->branch[getbits(ifP, 1)]; + + diff = getbits(ifP, len = dindexP->leaf); + + if ((diff & (1 << (len-1))) == 0) + diff -= (1 << len) - 1; + + return diff; } + + void -ljpeg_row (struct jhead *jh) -{ - int col, c, diff; - unsigned short *outp=jh->row; - - for (col=0; col < jh->wide; col++) - for (c=0; c < jh->clrs; c++) { - diff = ljpeg_diff (jh->huff[c]); - *outp = col ? outp[-jh->clrs]+diff : (jh->vpred[c] += diff); - outp++; - } +ljpeg_row(FILE * const ifP, + struct jhead * const jhP) { + + int col, c, diff; + unsigned short *outp=jhP->row; + + for (col=0; col < jhP->wide; col++) + for (c=0; c < jhP->clrs; c++) { + diff = ljpeg_diff(ifP, jhP->huff[c]); + *outp = col ? outp[-jhP->clrs]+diff : (jhP->vpred[c] += diff); + outp++; + } } + + void -lossless_jpeg_load_raw(void) -{ - int jwide, jrow, jcol, val, jidx, i, row, col; - struct jhead jh; - int min=INT_MAX; - - if (!ljpeg_start (ifp, &jh)) return; - jwide = jh.wide * jh.clrs; - - for (jrow=0; jrow < jh.high; jrow++) { - ljpeg_row (&jh); - for (jcol=0; jcol < jwide; jcol++) { - val = curve[jh.row[jcol]]; - jidx = jrow*jwide + jcol; - if (raw_width == 5108) { - i = jidx / (1680*jh.high); - if (i < 2) { - row = jidx / 1680 % jh.high; - col = jidx % 1680 + i*1680; - } else { - jidx -= 2*1680*jh.high; - row = jidx / 1748; - col = jidx % 1748 + 2*1680; - } - } else if (raw_width == 3516) { - row = jidx / 1758; - col = jidx % 1758; - if (row >= raw_height) { - row -= raw_height; - col += 1758; - } - } else { - row = jidx / raw_width; - col = jidx % raw_width; - } - if ((unsigned) (row-top_margin) >= height) continue; - if ((unsigned) (col-left_margin) < width) { - BAYER(row-top_margin,col-left_margin) = val; - if (min > val) min = val; - } else - black += val; +lossless_jpeg_load_raw(Image const image) { + + int jwide, jrow, jcol, val, jidx, i, row, col; + struct jhead jh; + int min=INT_MAX; + + if (!ljpeg_start (ifp, &jh)) return; + jwide = jh.wide * jh.clrs; + + for (jrow=0; jrow < jh.high; jrow++) { + ljpeg_row (ifp, &jh); + for (jcol=0; jcol < jwide; jcol++) { + val = curve[jh.row[jcol]]; + jidx = jrow*jwide + jcol; + if (raw_width == 5108) { + i = jidx / (1680*jh.high); + if (i < 2) { + row = jidx / 1680 % jh.high; + col = jidx % 1680 + i*1680; + } else { + jidx -= 2*1680*jh.high; + row = jidx / 1748; + col = jidx % 1748 + 2*1680; + } + } else if (raw_width == 3516) { + row = jidx / 1758; + col = jidx % 1758; + if (row >= raw_height) { + row -= raw_height; + col += 1758; + } + } else { + row = jidx / raw_width; + col = jidx % raw_width; + } + if ((unsigned) (row-top_margin) >= height) continue; + if ((unsigned) (col-left_margin) < width) { + BAYER(row-top_margin,col-left_margin) = val; + if (min > val) min = val; + } else + black += val; + } } - } - free (jh.row); - if (raw_width > width) - black /= (raw_width - width) * height; - if (!strcasecmp(make,"KODAK")) - black = min; + free (jh.row); + if (raw_width > width) + black /= (raw_width - width) * height; + if (!strcasecmp(make,"KODAK")) + black = min; } diff --git a/converter/other/cameratopam/ljpeg.h b/converter/other/cameratopam/ljpeg.h index 60832a3d..9d9d8ee9 100644 --- a/converter/other/cameratopam/ljpeg.h +++ b/converter/other/cameratopam/ljpeg.h @@ -1,17 +1,21 @@ +#include "camera.h" + struct jhead { int bits, high, wide, clrs, vpred[4]; struct decode *huff[4]; unsigned short *row; }; -void -lossless_jpeg_load_raw(void); +LoadRawFn lossless_jpeg_load_raw; int -ljpeg_start (FILE * ifp, struct jhead *jh); +ljpeg_start (FILE * const ifP, + struct jhead * const jhP); int -ljpeg_diff (struct decode *dindex); +ljpeg_diff (FILE * const ifP, + struct decode * const dindexP); void -ljpeg_row (struct jhead *jh); +ljpeg_row(FILE * const ifP, + struct jhead * const jhP); |