Thread: [Hdrflow-svn] SF.net SVN: hdrflow: [285] trunk/lib/extras/src/raw
Status: Pre-Alpha
Brought to you by:
glslang
From: <gl...@us...> - 2007-08-30 22:34:19
|
Revision: 285 http://hdrflow.svn.sourceforge.net/hdrflow/?rev=285&view=rev Author: glslang Date: 2007-08-30 15:34:13 -0700 (Thu, 30 Aug 2007) Log Message: ----------- + *nix build fixes Modified Paths: -------------- trunk/lib/extras/src/raw/Makefile.am Added Paths: ----------- trunk/lib/extras/src/raw/dcraw.cpp Removed Paths: ------------- trunk/lib/extras/src/raw/dcraw.c Modified: trunk/lib/extras/src/raw/Makefile.am =================================================================== --- trunk/lib/extras/src/raw/Makefile.am 2007-08-30 22:21:09 UTC (rev 284) +++ trunk/lib/extras/src/raw/Makefile.am 2007-08-30 22:34:13 UTC (rev 285) @@ -7,15 +7,14 @@ lib_LTLIBRARIES = libhdrflow_extras_raw.la -bin_PROGRAMS = dcraw - libhdrflow_extras_raw_la_SOURCES = \ raw.cpp \ - dcraw.c + dcraw.cpp libhdrflow_extras_raw_la_CXXFLAGS = \ $(BOOST_INCLUDE_PATH) \ -I$(top_builddir)/../openlibraries/src \ - $(OFX_INCLUDE_PATH) \ - -DNO_JPEG \ + $(OFX_INCLUDE_PATH) \ + -DNO_JPEG \ -DNO_LCMS + Deleted: trunk/lib/extras/src/raw/dcraw.c =================================================================== --- trunk/lib/extras/src/raw/dcraw.c 2007-08-30 22:21:09 UTC (rev 284) +++ trunk/lib/extras/src/raw/dcraw.c 2007-08-30 22:34:13 UTC (rev 285) @@ -1,7726 +0,0 @@ -/* - dcraw.c -- Dave Coffin's raw photo decoder - Copyright 1997-2007 by Dave Coffin, dcoffin a cybercom o net - - This is a command-line ANSI C program to convert raw photos from - any digital camera on any computer running any operating system. - - No license is required to download and use dcraw.c. However, - to lawfully redistribute this code, you must either (a) include - full source code* for all executable files containing RESTRICTED - functions, (b) remove all RESTRICTED functions, re-implement them, - or copy them from an earlier, unrestricted Revision of dcraw.c, - or (c) purchase a license from the author. - - The functions that process Foveon images have been RESTRICTED - since Revision 1.237. All other code remains free for all uses. - - *If you have not modified dcraw.c in any way, a link to my - homepage qualifies as "full source code". - - $Revision: 1.379 $ - $Date: 2007/05/03 06:15:16 $ - */ - -#define VERSION "8.71" - -#define _GNU_SOURCE -#define _USE_MATH_DEFINES -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <float.h> -#include <limits.h> -#include <math.h> -#include <setjmp.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -/* - NO_JPEG disables decoding of compressed Kodak DC120 files. - NO_LCMS disables the "-p" option. - */ -#ifndef NO_JPEG -#include <jpeglib.h> -#endif -#ifndef NO_LCMS -#include <lcms.h> -#endif -#ifdef LOCALEDIR -#include <libintl.h> -#define _(String) gettext(String) -#else -#define _(String) (String) -#endif -#ifndef DJGPP -#define fgetc getc_unlocked -#endif -#ifdef __CYGWIN__ -#include <io.h> -#endif -#ifdef WIN32 -#include <sys/utime.h> -#include <winsock2.h> -#pragma comment(lib, "ws2_32.lib") -#define strcasecmp _stricmp -#define strncasecmp _strnicmp -#define getc_unlocked getc -typedef __int64 INT64; -typedef unsigned __int64 UINT64; -#pragma warning( disable:4018 4244 4305 4389 4706 ) -#else -#include <unistd.h> -#include <utime.h> -#include <netinet/in.h> -typedef long long INT64; -typedef unsigned long long UINT64; -#endif - -#ifdef LJPEG_DECODE -#error Please compile dcraw.c by itself. -#error Do not link it with ljpeg_decode. -#endif - -#ifndef LONG_BIT -#define LONG_BIT (8 * sizeof (long)) -#endif - -#define ushort UshORt -typedef unsigned char uchar; -typedef unsigned short ushort; - -/* - All global variables are defined here, and all functions that - access them are prefixed with "CLASS". Note that a thread-safe - C++ class cannot have non-const static local variables. - */ -FILE *ifp; -short order; -char *ifname, make[64], model[64], model2[64], *meta_data, cdesc[5]; -float flash_used, canon_ev, iso_speed, shutter, aperture, focal_len; -time_t timestamp; -unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id; -unsigned profile_offset, profile_length, *oprof; -unsigned thumb_offset, thumb_length, thumb_misc; -unsigned data_offset, strip_offset, curve_offset, meta_offset, meta_length; -unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress, tile_length; -unsigned black, maximum, mix_green, raw_color, use_gamma, zero_is_bad; -unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error; -ushort raw_height, raw_width, height, width, top_margin, left_margin; -ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height; -int flip, tiff_flip, colors; -double pixel_aspect; -ushort (*image)[4], white[8][8], curve[0x1000], cr2_slice[3]; -float bright=1, user_mul[4]={0,0,0,0}, threshold=0; -int half_size=0, four_color_rgb=0, document_mode=0, highlight=0; -int verbose=0, use_auto_wb=0, use_camera_wb=0; -int output_color=1, output_bps=8, output_tiff=0; -int fuji_layout, fuji_secondary, shot_select=0; -unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX }; -float cam_mul[4], pre_mul[4], rgb_cam[3][4]; /* RGB from camera color */ -const double xyz_rgb[3][3] = { /* XYZ from RGB */ - { 0.412453, 0.357580, 0.180423 }, - { 0.212671, 0.715160, 0.072169 }, - { 0.019334, 0.119193, 0.950227 } }; -const float d65_white[3] = { 0.950456, 1, 1.088754 }; -int histogram[4][0x2000]; -void (*write_thumb)(FILE *), (*write_fun)(FILE *); -void (*load_raw)(), (*thumb_load_raw)(); -jmp_buf failure; - -struct decode { - struct decode *branch[2]; - int leaf; -} first_decode[2048], *second_decode, *free_decode; - -struct { - int width, height, bps, comp, phint, offset, flip, samples, bytes; -} tiff_ifd[10]; - -struct { - int format, key_off, black, black_off, split_col, tag_21a; - float tag_210; -} ph1; - -#define CLASS - -#define FORC3 for (c=0; c < 3; c++) -#define FORC4 for (c=0; c < 4; c++) -#define FORCC for (c=0; c < colors; c++) - -#define SQR(x) ((x)*(x)) -#define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31)) -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#define LIM(x,min,max) MAX(min,MIN(x,max)) -#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y)) -#define CLIP(x) LIM(x,0,65535) -#define SWAP(a,b) { a ^= b; a ^= (b ^= a); } - -/* - In order to inline this calculation, I make the risky - assumption that all filter patterns can be described - by a repeating pattern of eight rows and two columns - - Do not use the FC or BAYER macros with the Leaf CatchLight, - because its pattern is 16x16, not 2x8. - - Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2/3 = R/G1/B/G2 - - PowerShot 600 PowerShot A50 PowerShot Pro70 Pro90 & G1 - 0xe1e4e1e4: 0x1b4e4b1e: 0x1e4b4e1b: 0xb4b4b4b4: - - 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 - 0 G M G M G M 0 C Y C Y C Y 0 Y C Y C Y C 0 G M G M G M - 1 C Y C Y C Y 1 M G M G M G 1 M G M G M G 1 Y C Y C Y C - 2 M G M G M G 2 Y C Y C Y C 2 C Y C Y C Y - 3 C Y C Y C Y 3 G M G M G M 3 G M G M G M - 4 C Y C Y C Y 4 Y C Y C Y C - PowerShot A5 5 G M G M G M 5 G M G M G M - 0x1e4e1e4e: 6 Y C Y C Y C 6 C Y C Y C Y - 7 M G M G M G 7 M G M G M G - 0 1 2 3 4 5 - 0 C Y C Y C Y - 1 G M G M G M - 2 C Y C Y C Y - 3 M G M G M G - - All RGB cameras use one of these Bayer grids: - - 0x16161616: 0x61616161: 0x49494949: 0x94949494: - - 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 - 0 B G B G B G 0 G R G R G R 0 G B G B G B 0 R G R G R G - 1 G R G R G R 1 B G B G B G 1 R G R G R G 1 G B G B G B - 2 B G B G B G 2 G R G R G R 2 G B G B G B 2 R G R G R G - 3 G R G R G R 3 B G B G B G 3 R G R G R G 3 G B G B G B - */ - -#define FC(row,col) \ - (filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) - -#define BAYER(row,col) \ - image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)] - -#define BAYER2(row,col) \ - image[((row) >> shrink)*iwidth + ((col) >> shrink)][fc(row,col)] - -int CLASS fc (int row, int col) -{ - static const char filter[16][16] = - { { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 }, - { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 }, - { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 }, - { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 }, - { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 }, - { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 }, - { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 }, - { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 }, - { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 }, - { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 }, - { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 }, - { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 }, - { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 }, - { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 }, - { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 }, - { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } }; - - if (filters != 1) return FC(row,col); - return filter[(row+top_margin) & 15][(col+left_margin) & 15]; -} - -#ifndef __GLIBC__ -char *my_memmem (char *haystack, size_t haystacklen, - char *needle, size_t needlelen) -{ - char *c; - for (c = haystack; c <= haystack + haystacklen - needlelen; c++) - if (!memcmp (c, needle, needlelen)) - return c; - return 0; -} -#define memmem my_memmem -#endif - -void CLASS merror (void *ptr, char *where) -{ - if (ptr) return; - fprintf (stderr,_("%s: Out of memory in %s\n"), ifname, where); - longjmp (failure, 1); -} - -void CLASS derror() -{ - if (!data_error) { - fprintf (stderr, "%s: ", ifname); - if (feof(ifp)) - fprintf (stderr,_("Unexpected end of file\n")); - else - fprintf (stderr,_("Corrupt data near 0x%lx\n"), ftell(ifp)); - } - data_error = 1; -} - -ushort CLASS sget2 (uchar *s) -{ - if (order == 0x4949) /* "II" means little-endian */ - return s[0] | s[1] << 8; - else /* "MM" means big-endian */ - return s[0] << 8 | s[1]; -} - -ushort CLASS get2() -{ - uchar str[2] = { 0xff,0xff }; - fread (str, 1, 2, ifp); - return sget2(str); -} - -unsigned CLASS sget4 (uchar *s) -{ - if (order == 0x4949) - return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; - else - return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]; -} -#define sget4(s) sget4((uchar *)s) - -unsigned CLASS get4() -{ - uchar str[4] = { 0xff,0xff,0xff,0xff }; - fread (str, 1, 4, ifp); - return sget4(str); -} - -unsigned CLASS getint (int type) -{ - return type == 3 ? get2() : get4(); -} - -float CLASS int_to_float (int i) -{ - union { int i; float f; } u; - u.i = i; - return u.f; -} - -double CLASS getreal (int type) -{ - union { char c[8]; double d; } u; - int i, rev; - - switch (type) { - case 3: return (unsigned short) get2(); - case 4: return (unsigned int) get4(); - case 5: u.d = (unsigned int) get4(); - return u.d / (unsigned int) get4(); - case 8: return (signed short) get2(); - case 9: return (signed int) get4(); - case 10: u.d = (signed int) get4(); - return u.d / (signed int) get4(); - case 11: return int_to_float (get4()); - case 12: - rev = 7 * ((order == 0x4949) == (ntohs(0x1234) == 0x1234)); - for (i=0; i < 8; i++) - u.c[i ^ rev] = fgetc(ifp); - return u.d; - default: return fgetc(ifp); - } -} -#define getrat() getreal(10) - -void CLASS read_shorts (ushort *pixel, int count) -{ - if (fread (pixel, 2, count, ifp) < count) derror(); - if ((order == 0x4949) == (ntohs(0x1234) == 0x1234)) - swab (pixel, pixel, count*2); -} - -void CLASS canon_600_fixed_wb (int temp) -{ - static const short mul[4][5] = { - { 667, 358,397,565,452 }, - { 731, 390,367,499,517 }, - { 1119, 396,348,448,537 }, - { 1399, 485,431,508,688 } }; - int lo, hi, i; - float frac=0; - - for (lo=4; --lo; ) - if (*mul[lo] <= temp) break; - for (hi=0; hi < 3; hi++) - if (*mul[hi] >= temp) break; - if (lo != hi) - frac = (float) (temp - *mul[lo]) / (*mul[hi] - *mul[lo]); - for (i=1; i < 5; i++) - pre_mul[i-1] = 1 / (frac * mul[hi][i] + (1-frac) * mul[lo][i]); -} - -/* Return values: 0 = white 1 = near white 2 = not white */ -int CLASS canon_600_color (int ratio[2], int mar) -{ - int clipped=0, target, miss; - - if (flash_used) { - if (ratio[1] < -104) - { ratio[1] = -104; clipped = 1; } - if (ratio[1] > 12) - { ratio[1] = 12; clipped = 1; } - } else { - if (ratio[1] < -264 || ratio[1] > 461) return 2; - if (ratio[1] < -50) - { ratio[1] = -50; clipped = 1; } - if (ratio[1] > 307) - { ratio[1] = 307; clipped = 1; } - } - target = flash_used || ratio[1] < 197 - ? -38 - (398 * ratio[1] >> 10) - : -123 + (48 * ratio[1] >> 10); - if (target - mar <= ratio[0] && - target + 20 >= ratio[0] && !clipped) return 0; - miss = target - ratio[0]; - if (abs(miss) >= mar*4) return 2; - if (miss < -20) miss = -20; - if (miss > mar) miss = mar; - ratio[0] = target - miss; - return 1; -} - -void CLASS canon_600_auto_wb() -{ - int mar, row, col, i, j, st, count[] = { 0,0 }; - int test[8], total[2][8], ratio[2][2], stat[2]; - - memset (&total, 0, sizeof total); - i = canon_ev + 0.5; - if (i < 10) mar = 150; - else if (i > 12) mar = 20; - else mar = 280 - 20 * i; - if (flash_used) mar = 80; - for (row=14; row < height-14; row+=4) - for (col=10; col < width; col+=2) { - for (i=0; i < 8; i++) - test[(i & 4) + FC(row+(i >> 1),col+(i & 1))] = - BAYER(row+(i >> 1),col+(i & 1)); - for (i=0; i < 8; i++) - if (test[i] < 150 || test[i] > 1500) goto next; - for (i=0; i < 4; i++) - if (abs(test[i] - test[i+4]) > 50) goto next; - for (i=0; i < 2; i++) { - for (j=0; j < 4; j+=2) - ratio[i][j >> 1] = ((test[i*4+j+1]-test[i*4+j]) << 10) / test[i*4+j]; - stat[i] = canon_600_color (ratio[i], mar); - } - if ((st = stat[0] | stat[1]) > 1) goto next; - for (i=0; i < 2; i++) - if (stat[i]) - for (j=0; j < 2; j++) - test[i*4+j*2+1] = test[i*4+j*2] * (0x400 + ratio[i][j]) >> 10; - for (i=0; i < 8; i++) - total[st][i] += test[i]; - count[st]++; -next: continue; - } - if (count[0] | count[1]) { - st = count[0]*200 < count[1]; - for (i=0; i < 4; i++) - pre_mul[i] = 1.0 / (total[st][i] + total[st][i+4]); - } -} - -void CLASS canon_600_coeff() -{ - static const short table[6][12] = { - { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 }, - { -1203,1715,-1136,1648, 1388,-876,267,245, -1641,2153,3921,-3409 }, - { -615,1127,-1563,2075, 1437,-925,509,3, -756,1268,2519,-2007 }, - { -190,702,-1886,2398, 2153,-1641,763,-251, -452,964,3040,-2528 }, - { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 }, - { -807,1319,-1785,2297, 1388,-876,769,-257, -230,742,2067,-1555 } }; - int t=0, i, c; - float mc, yc; - - mc = pre_mul[1] / pre_mul[2]; - yc = pre_mul[3] / pre_mul[2]; - if (mc > 1 && mc <= 1.28 && yc < 0.8789) t=1; - if (mc > 1.28 && mc <= 2) { - if (yc < 0.8789) t=3; - else if (yc <= 2) t=4; - } - if (flash_used) t=5; - for (raw_color = i=0; i < 3; i++) - FORCC rgb_cam[i][c] = table[t][i*4 + c] / 1024.0; -} - -void CLASS canon_600_load_raw() -{ - uchar data[1120], *dp; - ushort pixel[896], *pix; - int irow, row, col, val; - static const short mul[4][2] = - { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } }; - - for (irow=row=0; irow < height; irow++) { - if (fread (data, 1, raw_width*5/4, ifp) < raw_width*5/4) derror(); - for (dp=data, pix=pixel; dp < data+1120; dp+=10, pix+=8) { - pix[0] = (dp[0] << 2) + (dp[1] >> 6 ); - pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3); - pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3); - pix[3] = (dp[4] << 2) + (dp[1] & 3); - pix[4] = (dp[5] << 2) + (dp[9] & 3); - pix[5] = (dp[6] << 2) + (dp[9] >> 2 & 3); - pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3); - pix[7] = (dp[8] << 2) + (dp[9] >> 6 ); - } - for (col=0; col < width; col++) - BAYER(row,col) = pixel[col]; - for (col=width; col < raw_width; col++) - black += pixel[col]; - if ((row+=2) > height) row = 1; - } - if (raw_width > width) - black = black / ((raw_width - width) * height) - 4; - for (row=0; row < height; row++) - for (col=0; col < width; col++) { - val = (BAYER(row,col) - black) * mul[row & 3][col & 1] >> 9; - if (val < 0) val = 0; - BAYER(row,col) = val; - } - canon_600_fixed_wb(1311); - canon_600_auto_wb(); - canon_600_coeff(); - maximum = (0x3ff - black) * 1109 >> 9; - black = 0; -} - -void CLASS remove_zeroes() -{ - unsigned row, col, tot, n, r, c; - - for (row=0; row < height; row++) - for (col=0; col < width; col++) - if (BAYER(row,col) == 0) { - tot = n = 0; - for (r = row-2; r <= row+2; r++) - for (c = col-2; c <= col+2; c++) - if (r < height && c < width && - FC(r,c) == FC(row,col) && BAYER(r,c)) - tot += (n++,BAYER(r,c)); - if (n) BAYER(row,col) = tot/n; - } -} - -int CLASS canon_s2is() -{ - unsigned row; - - for (row=0; row < 100; row++) { - fseek (ifp, row*3340 + 3284, SEEK_SET); - if (getc(ifp) > 15) return 1; - } - return 0; -} - -void CLASS canon_a5_load_raw() -{ - ushort data[2335], *dp, pixel; - int vbits=0, buf=0, row, col, bc=0; - - order = 0x4949; - for (row=-top_margin; row < raw_height-top_margin; row++) { - read_shorts (dp=data, raw_width * 10 / 16); - for (col=-left_margin; col < raw_width-left_margin; col++) { - if (vbits < 10) - buf = (vbits += 16, (buf << 16) + *dp++); - pixel = buf >> (vbits -= 10) & 0x3ff; - if ((unsigned) row < height && (unsigned) col < width) - BAYER(row,col) = pixel; - else if (col > 1-left_margin && col != width) - black += (bc++,pixel); - } - } - if (bc) black /= bc; - maximum = 0x3ff; - if (raw_width > 1600) remove_zeroes(); -} - -/* - getbits(-1) initializes the buffer - getbits(n) where 0 <= n <= 25 returns an n-bit integer - */ -unsigned CLASS getbits (int nbits) -{ - static unsigned bitbuf=0; - static int vbits=0, reset=0; - unsigned c; - - if (nbits == -1) - return bitbuf = vbits = reset = 0; - if (nbits == 0 || reset) return 0; - while (vbits < nbits) { - if ((c = fgetc(ifp)) == EOF) derror(); - if ((reset = zero_after_ff && c == 0xff && fgetc(ifp))) return 0; - bitbuf = (bitbuf << 8) + (uchar) c; - vbits += 8; - } - vbits -= nbits; - return bitbuf << (32-nbits-vbits) >> (32-nbits); -} - -void CLASS init_decoder() -{ - memset (first_decode, 0, sizeof first_decode); - free_decode = first_decode; -} - -/* - Construct a decode tree according the specification in *source. - The first 16 bytes specify how many codes should be 1-bit, 2-bit - 3-bit, etc. Bytes after that are the leaf values. - - For example, if the source is - - { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, - 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff }, - - then the code is - - 00 0x04 - 010 0x03 - 011 0x05 - 100 0x06 - 101 0x02 - 1100 0x07 - 1101 0x01 - 11100 0x08 - 11101 0x09 - 11110 0x00 - 111110 0x0a - 1111110 0x0b - 1111111 0xff - */ -uchar * CLASS make_decoder (const uchar *source, int level) -{ - struct decode *cur; - static int leaf; - int i, next; - - if (level==0) leaf=0; - cur = free_decode++; - if (free_decode > first_decode+2048) { - fprintf (stderr,_("%s: decoder table overflow\n"), ifname); - longjmp (failure, 2); - } - for (i=next=0; i <= leaf && next < 16; ) - i += source[next++]; - if (i > leaf) { - if (level < next) { - cur->branch[0] = free_decode; - make_decoder (source, level+1); - cur->branch[1] = free_decode; - make_decoder (source, level+1); - } else - cur->leaf = source[16 + leaf++]; - } - return (uchar *) source + 16 + leaf; -} - -void CLASS crw_init_tables (unsigned table) -{ - static const uchar first_tree[3][29] = { - { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, - 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff }, - { 0,2,2,3,1,1,1,1,2,0,0,0,0,0,0,0, - 0x03,0x02,0x04,0x01,0x05,0x00,0x06,0x07,0x09,0x08,0x0a,0x0b,0xff }, - { 0,0,6,3,1,1,2,0,0,0,0,0,0,0,0,0, - 0x06,0x05,0x07,0x04,0x08,0x03,0x09,0x02,0x00,0x0a,0x01,0x0b,0xff }, - }; - static const uchar second_tree[3][180] = { - { 0,2,2,2,1,4,2,1,2,5,1,1,0,0,0,139, - 0x03,0x04,0x02,0x05,0x01,0x06,0x07,0x08, - 0x12,0x13,0x11,0x14,0x09,0x15,0x22,0x00,0x21,0x16,0x0a,0xf0, - 0x23,0x17,0x24,0x31,0x32,0x18,0x19,0x33,0x25,0x41,0x34,0x42, - 0x35,0x51,0x36,0x37,0x38,0x29,0x79,0x26,0x1a,0x39,0x56,0x57, - 0x28,0x27,0x52,0x55,0x58,0x43,0x76,0x59,0x77,0x54,0x61,0xf9, - 0x71,0x78,0x75,0x96,0x97,0x49,0xb7,0x53,0xd7,0x74,0xb6,0x98, - 0x47,0x48,0x95,0x69,0x99,0x91,0xfa,0xb8,0x68,0xb5,0xb9,0xd6, - 0xf7,0xd8,0x67,0x46,0x45,0x94,0x89,0xf8,0x81,0xd5,0xf6,0xb4, - 0x88,0xb1,0x2a,0x44,0x72,0xd9,0x87,0x66,0xd4,0xf5,0x3a,0xa7, - 0x73,0xa9,0xa8,0x86,0x62,0xc7,0x65,0xc8,0xc9,0xa1,0xf4,0xd1, - 0xe9,0x5a,0x92,0x85,0xa6,0xe7,0x93,0xe8,0xc1,0xc6,0x7a,0x64, - 0xe1,0x4a,0x6a,0xe6,0xb3,0xf1,0xd3,0xa5,0x8a,0xb2,0x9a,0xba, - 0x84,0xa4,0x63,0xe5,0xc5,0xf3,0xd2,0xc4,0x82,0xaa,0xda,0xe4, - 0xf2,0xca,0x83,0xa3,0xa2,0xc3,0xea,0xc2,0xe2,0xe3,0xff,0xff }, - { 0,2,2,1,4,1,4,1,3,3,1,0,0,0,0,140, - 0x02,0x03,0x01,0x04,0x05,0x12,0x11,0x06, - 0x13,0x07,0x08,0x14,0x22,0x09,0x21,0x00,0x23,0x15,0x31,0x32, - 0x0a,0x16,0xf0,0x24,0x33,0x41,0x42,0x19,0x17,0x25,0x18,0x51, - 0x34,0x43,0x52,0x29,0x35,0x61,0x39,0x71,0x62,0x36,0x53,0x26, - 0x38,0x1a,0x37,0x81,0x27,0x91,0x79,0x55,0x45,0x28,0x72,0x59, - 0xa1,0xb1,0x44,0x69,0x54,0x58,0xd1,0xfa,0x57,0xe1,0xf1,0xb9, - 0x49,0x47,0x63,0x6a,0xf9,0x56,0x46,0xa8,0x2a,0x4a,0x78,0x99, - 0x3a,0x75,0x74,0x86,0x65,0xc1,0x76,0xb6,0x96,0xd6,0x89,0x85, - 0xc9,0xf5,0x95,0xb4,0xc7,0xf7,0x8a,0x97,0xb8,0x73,0xb7,0xd8, - 0xd9,0x87,0xa7,0x7a,0x48,0x82,0x84,0xea,0xf4,0xa6,0xc5,0x5a, - 0x94,0xa4,0xc6,0x92,0xc3,0x68,0xb5,0xc8,0xe4,0xe5,0xe6,0xe9, - 0xa2,0xa3,0xe3,0xc2,0x66,0x67,0x93,0xaa,0xd4,0xd5,0xe7,0xf8, - 0x88,0x9a,0xd7,0x77,0xc4,0x64,0xe2,0x98,0xa5,0xca,0xda,0xe8, - 0xf3,0xf6,0xa9,0xb2,0xb3,0xf2,0xd2,0x83,0xba,0xd3,0xff,0xff }, - { 0,0,6,2,1,3,3,2,5,1,2,2,8,10,0,117, - 0x04,0x05,0x03,0x06,0x02,0x07,0x01,0x08, - 0x09,0x12,0x13,0x14,0x11,0x15,0x0a,0x16,0x17,0xf0,0x00,0x22, - 0x21,0x18,0x23,0x19,0x24,0x32,0x31,0x25,0x33,0x38,0x37,0x34, - 0x35,0x36,0x39,0x79,0x57,0x58,0x59,0x28,0x56,0x78,0x27,0x41, - 0x29,0x77,0x26,0x42,0x76,0x99,0x1a,0x55,0x98,0x97,0xf9,0x48, - 0x54,0x96,0x89,0x47,0xb7,0x49,0xfa,0x75,0x68,0xb6,0x67,0x69, - 0xb9,0xb8,0xd8,0x52,0xd7,0x88,0xb5,0x74,0x51,0x46,0xd9,0xf8, - 0x3a,0xd6,0x87,0x45,0x7a,0x95,0xd5,0xf6,0x86,0xb4,0xa9,0x94, - 0x53,0x2a,0xa8,0x43,0xf5,0xf7,0xd4,0x66,0xa7,0x5a,0x44,0x8a, - 0xc9,0xe8,0xc8,0xe7,0x9a,0x6a,0x73,0x4a,0x61,0xc7,0xf4,0xc6, - 0x65,0xe9,0x72,0xe6,0x71,0x91,0x93,0xa6,0xda,0x92,0x85,0x62, - 0xf3,0xc5,0xb2,0xa4,0x84,0xba,0x64,0xa5,0xb3,0xd2,0x81,0xe5, - 0xd3,0xaa,0xc4,0xca,0xf2,0xb1,0xe4,0xd1,0x83,0x63,0xea,0xc3, - 0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff } - }; - if (table > 2) table = 2; - init_decoder(); - make_decoder ( first_tree[table], 0); - second_decode = free_decode; - make_decoder (second_tree[table], 0); -} - -/* - Return 0 if the image starts with compressed data, - 1 if it starts with uncompressed low-order bits. - - In Canon compressed data, 0xff is always followed by 0x00. - */ -int CLASS canon_has_lowbits() -{ - uchar test[0x4000]; - int ret=1, i; - - fseek (ifp, 0, SEEK_SET); - fread (test, 1, sizeof test, ifp); - for (i=540; i < sizeof test - 1; i++) - if (test[i] == 0xff) { - if (test[i+1]) return 1; - ret=0; - } - return ret; -} - -void CLASS canon_compressed_load_raw() -{ - ushort *pixel, *prow; - int nblocks, lowbits, i, row, r, col, save, val; - unsigned irow, icol; - struct decode *decode, *dindex; - int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2]; - uchar c; - - crw_init_tables (tiff_compress); - pixel = (ushort *) calloc (raw_width*8, sizeof *pixel); - merror (pixel, "canon_compressed_load_raw()"); - lowbits = canon_has_lowbits(); - if (!lowbits) maximum = 0x3ff; - fseek (ifp, 540 + lowbits*raw_height*raw_width/4, SEEK_SET); - zero_after_ff = 1; - getbits(-1); - for (row=0; row < raw_height; row+=8) { - nblocks = MIN (8, raw_height-row) * raw_width >> 6; - for (block=0; block < nblocks; block++) { - memset (diffbuf, 0, sizeof diffbuf); - decode = first_decode; - for (i=0; i < 64; i++ ) { - for (dindex=decode; dindex->branch[0]; ) - dindex = dindex->branch[getbits(1)]; - leaf = dindex->leaf; - decode = second_decode; - if (leaf == 0 && i) break; - if (leaf == 0xff) continue; - i += leaf >> 4; - len = leaf & 15; - if (len == 0) continue; - diff = getbits(len); - if ((diff & (1 << (len-1))) == 0) - diff -= (1 << len) - 1; - if (i < 64) diffbuf[i] = diff; - } - diffbuf[0] += carry; - carry = diffbuf[0]; - for (i=0; i < 64; i++ ) { - if (pnum++ % raw_width == 0) - base[0] = base[1] = 512; - if ((pixel[(block << 6) + i] = base[i & 1] += diffbuf[i]) >> 10) - derror(); - } - } - if (lowbits) { - save = ftell(ifp); - fseek (ifp, 26 + row*raw_width/4, SEEK_SET); - for (prow=pixel, i=0; i < raw_width*2; i++) { - c = fgetc(ifp); - for (r=0; r < 8; r+=2, prow++) { - val = (*prow << 2) + ((c >> r) & 3); - if (raw_width == 2672 && val < 512) val += 2; - *prow = val; - } - } - fseek (ifp, save, SEEK_SET); - } - for (r=0; r < 8; r++) { - irow = row - top_margin + r; - if (irow >= height) continue; - for (col=0; col < raw_width; col++) { - icol = col - left_margin; - if (icol < width) - BAYER(irow,icol) = pixel[r*raw_width+col]; - else - black += pixel[r*raw_width+col]; - } - } - } - free (pixel); - if (raw_width > width) - black /= (raw_width - width) * height; -} - -/* - Not a full implementation of Lossless JPEG, just - enough to decode Canon, Kodak and Adobe DNG images. - */ -struct jhead { - int bits, high, wide, clrs, restart, vpred[4]; - struct decode *huff[4]; - ushort *row; -}; - -int CLASS ljpeg_start (struct jhead *jh, int info_only) -{ - int i, tag, len; - uchar data[0x10000], *dp; - - init_decoder(); - memset (jh, 0, sizeof *jh); - for (i=0; i < 4; i++) - jh->huff[i] = free_decode; - jh->restart = INT_MAX; - fread (data, 2, 1, ifp); - if (data[1] != 0xd8) return 0; - do { - fread (data, 2, 2, ifp); - tag = data[0] << 8 | data[1]; - len = (data[2] << 8 | data[3]) - 2; - if (tag <= 0xff00) return 0; - fread (data, 1, len, ifp); - switch (tag) { - case 0xffc0: - 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: - if (info_only) break; - for (dp = data; dp < data+len && *dp < 4; ) { - jh->huff[*dp] = free_decode; - dp = make_decoder (++dp, 0); - } - break; - case 0xffdd: - jh->restart = data[0] << 8 | data[1]; - } - } while (tag != 0xffda); - if (info_only) return 1; - jh->row = (ushort *) calloc (jh->wide*jh->clrs, 2); - merror (jh->row, " jpeg_start()"); - return zero_after_ff = 1; -} - -int CLASS ljpeg_diff (struct decode *dindex) -{ - int len, diff; - - while (dindex->branch[0]) - dindex = dindex->branch[getbits(1)]; - len = dindex->leaf; - if (len == 16 && (!dng_version || dng_version >= 0x1010000)) - return -32768; - diff = getbits(len); - if ((diff & (1 << (len-1))) == 0) - diff -= (1 << len) - 1; - return diff; -} - -void CLASS ljpeg_row (int jrow, struct jhead *jh) -{ - int col, c, diff; - ushort mark=0, *outp=jh->row; - - if (jrow * jh->wide % jh->restart == 0) { - FORC4 jh->vpred[c] = 1 << (jh->bits-1); - if (jrow) - do mark = (mark << 8) + (c = fgetc(ifp)); - while (c != EOF && mark >> 4 != 0xffd); - getbits(-1); - } - for (col=0; col < jh->wide; col++) - for (c=0; c < jh->clrs; c++) { - diff = ljpeg_diff (jh->huff[c]); - *outp = diff = col ? outp[-jh->clrs]+diff : (jh->vpred[c] += diff); - if (diff >> jh->bits) derror(); - outp++; - } -} - -void CLASS lossless_jpeg_load_raw() -{ - int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0; - struct jhead jh; - int min=INT_MAX; - - if (!ljpeg_start (&jh, 0)) return; - jwide = jh.wide * jh.clrs; - - for (jrow=0; jrow < jh.high; jrow++) { - ljpeg_row (jrow, &jh); - for (jcol=0; jcol < jwide; jcol++) { - val = jh.row[jcol]; - if (jh.bits <= 12) - val = curve[val]; - if (cr2_slice[0]) { - jidx = jrow*jwide + jcol; - i = jidx / (cr2_slice[1]*jh.high); - if ((j = i >= cr2_slice[0])) - i = cr2_slice[0]; - jidx -= i * (cr2_slice[1]*jh.high); - row = jidx / cr2_slice[1+j]; - col = jidx % cr2_slice[1+j] + i*cr2_slice[1]; - } - if (raw_width == 3984 && (col -= 2) < 0) - col += (row--,raw_width); - if ((unsigned) (row-top_margin) < height) { - if ((unsigned) (col-left_margin) < width) { - BAYER(row-top_margin,col-left_margin) = val; - if (min > val) min = val; - } else black += val; - } - if (++col >= raw_width) - col = (row++,0); - } - } - free (jh.row); - if (raw_width > width) - black /= (raw_width - width) * height; - if (!strcasecmp(make,"KODAK")) - black = min; -} - -void CLASS adobe_copy_pixel (int row, int col, ushort **rp) -{ - unsigned r, c; - - r = row -= top_margin; - c = col -= left_margin; - if (fuji_secondary && shot_select) (*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 { - if (r < height && c < width) - for (c=0; c < tiff_samples; c++) - image[row*width+col][c] = (*rp)[c] < 0x1000 ? curve[(*rp)[c]]:(*rp)[c]; - *rp += tiff_samples; - } - if (fuji_secondary && shot_select) (*rp)--; -} - -void CLASS adobe_dng_load_raw_lj() -{ - int save, twide, trow=0, tcol=0, jrow, jcol; - struct jhead jh; - ushort *rp; - - while (1) { - save = ftell(ifp); - if (tile_length < INT_MAX) - fseek (ifp, get4(), SEEK_SET); - if (!ljpeg_start (&jh, 0)) 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 (jrow, &jh); - for (rp=jh.row, jcol=0; jcol < twide; jcol++) - adobe_copy_pixel (trow+jrow, tcol+jcol, &rp); - } - fseek (ifp, save+4, SEEK_SET); - if ((tcol += twide) >= raw_width) { - tcol = 0; - trow += jh.high; - } - free (jh.row); - } -} - -void CLASS adobe_dng_load_raw_nc() -{ - ushort *pixel, *rp; - int row, col; - - pixel = (ushort *) calloc (raw_width * tiff_samples, sizeof *pixel); - merror (pixel, "adobe_dng_load_raw_nc()"); - for (row=0; row < raw_height; row++) { - if (tiff_bps == 16) - read_shorts (pixel, raw_width * tiff_samples); - else { - getbits(-1); - for (col=0; col < raw_width * tiff_samples; col++) - pixel[col] = getbits(tiff_bps); - } - for (rp=pixel, col=0; col < raw_width; col++) - adobe_copy_pixel (row, col, &rp); - } - free (pixel); -} - -void CLASS pentax_k10_load_raw() -{ - static const uchar pentax_tree[] = - { 0,2,3,1,1,1,1,1,1,2,0,0,0,0,0,0, - 3,4,2,5,1,6,0,7,8,9,10,11,12 }; - int row, col, diff; - ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2]; - - init_decoder(); - make_decoder (pentax_tree, 0); - getbits(-1); - for (row=0; row < height; row++) - for (col=0; col < raw_width; col++) { - diff = ljpeg_diff (first_decode); - if (col < 2) - hpred[col] = vpred[row & 1][col] += diff; - else - hpred[col & 1] += diff; - if (col < width) - BAYER(row,col) = hpred[col & 1]; - if (hpred[col & 1] >> 12) derror(); - } -} - -void CLASS nikon_compressed_load_raw() -{ - static const uchar nikon_tree[] = - { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, - 5,4,3,6,2,7,1,0,8,9,11,10,12 }; - int csize, row, col, diff; - ushort vpred[2][2], hpred[2], *curve; - - init_decoder(); - make_decoder (nikon_tree, 0); - - fseek (ifp, curve_offset, SEEK_SET); - read_shorts (vpred[0], 4); - csize = get2(); - curve = (ushort *) calloc (csize, sizeof *curve); - merror (curve, "nikon_compressed_load_raw()"); - read_shorts (curve, csize); - - fseek (ifp, data_offset, SEEK_SET); - getbits(-1); - for (row=0; row < height; row++) - for (col=0; col < raw_width; col++) { - diff = ljpeg_diff (first_decode); - if (col < 2) - hpred[col] = vpred[row & 1][col] += diff; - else - hpred[col & 1] += diff; - if ((unsigned) (col-left_margin) >= width) continue; - if (hpred[col & 1] >= csize) derror(); - else BAYER(row,col-left_margin) = curve[hpred[col & 1]]; - } - free (curve); -} - -void CLASS nikon_load_raw() -{ - int irow, row, col, i; - - getbits(-1); - for (irow=0; irow < height; irow++) { - row = irow; - if (make[0] == 'O' || model[0] == 'E') { - row = irow * 2 % height + irow / (height/2); - if (row == 1 && data_offset == 0) { - fseek (ifp, 0, SEEK_END); - fseek (ifp, ftell(ifp)/2, SEEK_SET); - getbits(-1); - } - } - for (col=0; col < raw_width; col++) { - i = getbits(12); - if ((unsigned) (col-left_margin) < width) - BAYER(row,col-left_margin) = i; - if (tiff_compress == 34713 && (col % 10) == 9) - if (getbits(8)) derror(); - } - } -} - -/* - Figure out if a NEF file is compressed. These fancy heuristics - are only needed for the D100, thanks to a bug in some cameras - that tags all images as "compressed". - */ -int CLASS nikon_is_compressed() -{ - uchar test[256]; - int i; - - if (tiff_compress != 34713) - return 0; - if (strcmp(model,"D100")) - return 1; - fseek (ifp, data_offset, SEEK_SET); - fread (test, 1, 256, ifp); - for (i=15; i < 256; i+=16) - if (test[i]) return 1; - return 0; -} - -/* - Returns 1 for a Coolpix 995, 0 for anything else. - */ -int CLASS nikon_e995() -{ - int i, histo[256]; - const uchar often[] = { 0x00, 0x55, 0xaa, 0xff }; - - memset (histo, 0, sizeof histo); - fseek (ifp, -2000, SEEK_END); - for (i=0; i < 2000; i++) - histo[fgetc(ifp)]++; - for (i=0; i < 4; i++) - if (histo[often[i]] < 200) - return 0; - return 1; -} - -/* - Returns 1 for a Coolpix 2100, 0 for anything else. - */ -int CLASS nikon_e2100() -{ - uchar t[12]; - int i; - - fseek (ifp, 0, SEEK_SET); - for (i=0; i < 1024; i++) { - fread (t, 1, 12, ifp); - if (((t[2] & t[4] & t[7] & t[9]) >> 4 - & t[1] & t[6] & t[8] & t[11] & 3) != 3) - return 0; - } - return 1; -} - -void CLASS nikon_3700() -{ - int bits, i; - uchar dp[24]; - static const struct { - int bits; - char make[12], model[15]; - } table[] = { - { 0x00, "PENTAX", "Optio 33WR" }, - { 0x03, "NIKON", "E3200" }, - { 0x32, "NIKON", "E3700" }, - { 0x33, "OLYMPUS", "C740UZ" } }; - - fseek (ifp, 3072, SEEK_SET); - fread (dp, 1, 24, ifp); - bits = (dp[8] & 3) << 4 | (dp[20] & 3); - for (i=0; i < sizeof table / sizeof *table; i++) - if (bits == table[i].bits) { - strcpy (make, table[i].make ); - strcpy (model, table[i].model); - } -} - -/* - Separates a Minolta DiMAGE Z2 from a Nikon E4300. - */ -int CLASS minolta_z2() -{ - int i; - char tail[424]; - - fseek (ifp, -sizeof tail, SEEK_END); - fread (tail, 1, sizeof tail, ifp); - for (i=0; i < sizeof tail; i++) - if (tail[i]) return 1; - return 0; -} - -/* Here raw_width is in bytes, not pixels. */ -void CLASS nikon_e900_load_raw() -{ - int offset=0, irow, row, col; - - for (irow=0; irow < height; irow++) { - row = irow * 2 % height; - if (row == 1) - offset = - (-offset & -4096); - fseek (ifp, offset, SEEK_SET); - offset += raw_width; - getbits(-1); - for (col=0; col < width; col++) - BAYER(row,col) = getbits(10); - } -} - -void CLASS nikon_e2100_load_raw() -{ - uchar data[4608], *dp; - ushort pixel[3072], *pix; - int row, col; - - for (row=0; row <= height; row+=2) { - if (row == height) { - fseek (ifp, 0, SEEK_END); - fseek (ifp, ftell(ifp)/2, SEEK_SET); - row = 1; - } - fread (data, 1, width*3/2, ifp); - for (dp=data, pix=pixel; pix < pixel+width; dp+=12, pix+=8) { - pix[0] = (dp[2] >> 4) + (dp[ 3] << 4); - pix[1] = (dp[2] << 8) + dp[ 1]; - pix[2] = (dp[7] >> 4) + (dp[ 0] << 4); - pix[3] = (dp[7] << 8) + dp[ 6]; - pix[4] = (dp[4] >> 4) + (dp[ 5] << 4); - pix[5] = (dp[4] << 8) + dp[11]; - pix[6] = (dp[9] >> 4) + (dp[10] << 4); - pix[7] = (dp[9] << 8) + dp[ 8]; - } - for (col=0; col < width; col++) - BAYER(row,col) = (pixel[col] & 0xfff); - } -} - -/* - The Fuji Super CCD is just a Bayer grid rotated 45 degrees. - */ -void CLASS fuji_load_raw() -{ - ushort *pixel; - int wide, row, col, r, c; - - fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR); - wide = fuji_width << !fuji_layout; - pixel = (ushort *) calloc (wide, sizeof *pixel); - merror (pixel, "fuji_load_raw()"); - for (row=0; row < raw_height; row++) { - read_shorts (pixel, wide); - fseek (ifp, 2*(raw_width - wide), SEEK_CUR); - for (col=0; col < wide; col++) { - if (fuji_layout) { - r = fuji_width - 1 - col + (row >> 1); - c = col + ((row+1) >> 1); - } else { - r = fuji_width - 1 + row - (col >> 1); - c = row + ((col+1) >> 1); - } - BAYER(r,c) = pixel[col]; - } - } - free (pixel); -} - -void CLASS jpeg_thumb (FILE *tfp); - -void CLASS ppm_thumb (FILE *tfp) -{ - char *thumb; - thumb_length = thumb_width*thumb_height*3; - thumb = (char *) malloc (thumb_length); - merror (thumb, "ppm_thumb()"); - fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height); - fread (thumb, 1, thumb_length, ifp); - fwrite (thumb, 1, thumb_length, tfp); - free (thumb); -} - -void CLASS layer_thumb (FILE *tfp) -{ - int i, c; - char *thumb, map[][4] = { "012","102" }; - - colors = thumb_misc >> 5 & 7; - thumb_length = thumb_width*thumb_height; - thumb = (char *) calloc (colors, thumb_length); - merror (thumb, "layer_thumb()"); - fprintf (tfp, "P%d\n%d %d\n255\n", - 5 + (colors >> 1), thumb_width, thumb_height); - fread (thumb, thumb_length, colors, ifp); - for (i=0; i < thumb_length; i++) - FORCC putc (thumb[i+thumb_length*(map[thumb_misc >> 8][c]-'0')], tfp); - free (thumb); -} - -void CLASS rollei_thumb (FILE *tfp) -{ - unsigned i; - ushort *thumb; - - thumb_length = thumb_width * thumb_height; - thumb = (ushort *) calloc (thumb_length, 2); - merror (thumb, "rollei_thumb()"); - fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height); - read_shorts (thumb, thumb_length); - for (i=0; i < thumb_length; i++) { - putc (thumb[i] << 3, tfp); - putc (thumb[i] >> 5 << 2, tfp); - putc (thumb[i] >> 11 << 3, tfp); - } - free (thumb); -} - -void CLASS rollei_load_raw() -{ - uchar pixel[10]; - unsigned iten=0, isix, i, buffer=0, row, col, todo[16]; - - isix = raw_width * raw_height * 5 / 8; - while (fread (pixel, 1, 10, ifp) == 10) { - for (i=0; i < 10; i+=2) { - todo[i] = iten++; - todo[i+1] = pixel[i] << 8 | pixel[i+1]; - buffer = pixel[i] >> 2 | buffer << 6; - } - for ( ; i < 16; i+=2) { - todo[i] = isix++; - todo[i+1] = buffer >> (14-i)*5; - } - for (i=0; i < 16; i+=2) { - row = todo[i] / raw_width - top_margin; - col = todo[i] % raw_width - left_margin; - if (row < height && col < width) - BAYER(row,col) = (todo[i+1] & 0x3ff); - } - } - maximum = 0x3ff; -} - -int CLASS bayer (unsigned row, unsigned col) -{ - return (row < height && col < width) ? BAYER(row,col) : 0; -} - -void CLASS phase_one_flat_field (int is_float, int nc) -{ - ushort head[8]; - unsigned wide, y, x, c, rend, cend, row, col; - float *mrow, num, mult[4]; - - read_shorts (head, 8); - wide = head[2] / head[4]; - mrow = (float *) calloc (nc*wide, sizeof *mrow); - merror (mrow, "phase_one_flat_field()"); - for (y=0; y < head[3] / head[5]; y++) { - for (x=0; x < wide; x++) - for (c=0; c < nc; c+=2) { - num = is_float ? getreal(11) : get2()/32768.0; - if (y==0) mrow[c*wide+x] = num; - else mrow[(c+1)*wide+x] = (num - mrow[c*wide+x]) / head[5]; - } - if (y==0) continue; - rend = head[1]-top_margin + y*head[5]; - for (row = rend-head[5]; row < height && row < rend; row++) { - for (x=1; x < wide; x++) { - for (c=0; c < nc; c+=2) { - mult[c] = mrow[c*wide+x-1]; - mult[c+1] = (mrow[c*wide+x] - mult[c]) / head[4]; - } - cend = head[0]-left_margin + x*head[4]; - for (col = cend-head[4]; col < width && col < cend; col++) { - c = nc > 2 ? FC(row,col) : 0; - if (!(c & 1)) { - c = BAYER(row,col) * mult[c]; - BAYER(row,col) = LIM(c,0,65535); - } - for (c=0; c < nc; c+=2) - mult[c] += mult[c+1]; - } - } - for (x=0; x < wide; x++) - for (c=0; c < nc; c+=2) - mrow[c*wide+x] += mrow[(c+1)*wide+x]; - } - } - free (mrow); -} - -void CLASS phase_one_correct() -{ - unsigned entries, tag, data, save, col, row, type; - int len, i, j, k, cip, val[4], dev[4], sum, max; - int head[9], diff, mindiff=INT_MAX, off_412=0; - static const signed char dir[12][2] = - { {-1,-1}, {-1,1}, {1,-1}, {1,1}, {-2,0}, {0,-2}, {0,2}, {2,0}, - {-2,-2}, {-2,2}, {2,-2}, {2,2} }; - float poly[8], num, cfrac, frac, mult[2], *yval[2]; - ushort curve[0x10000], *xval[2]; - - if (half_size || !meta_length) return; - if (verbose) fprintf (stderr,_("Phase One correction...\n")); - fseek (ifp, meta_offset, SEEK_SET); - order = get2(); - fseek (ifp, 6, SEEK_CUR); - fseek (ifp, meta_offset+get4(), SEEK_SET); - entries = get4(); get4(); - while (entries--) { - tag = get4(); - len = get4(); - data = get4(); - save = ftell(ifp); - fseek (ifp, meta_offset+data, SEEK_SET); - if (tag == 0x419) { /* Polynomial curve */ - for (get4(), i=0; i < 8; i++) - poly[i] = getreal(11); - poly[3] += (ph1.tag_210 - poly[7]) * poly[6] + 1; - for (i=0; i < 0x10000; i++) { - num = (poly[5]*i + poly[3])*i + poly[1]; - curve[i] = LIM(num,0,65535); - } goto apply; /* apply to right half */ - } else if (tag == 0x41a) { /* Polynomial curve */ - for (i=0; i < 4; i++) - poly[i] = getreal(11); - for (i=0; i < 0x10000; i++) { - for (num=0, j=4; j--; ) - num = num * i + poly[j]; - curve[i] = LIM(num+i,0,65535); - } apply: /* apply to whole image */ - for (row=0; row < height; row++) - for (col = (tag & 1)*ph1.split_col; col < width; col++) - BAYER(row,col) = curve[BAYER(row,col)]; - } else if (tag == 0x400) { /* Sensor defects */ - while ((len -= 8) >= 0) { - col = get2() - left_margin; - row = get2() - top_margin; - type = get2(); get2(); - if (col >= width) continue; - if (type == 131) /* Bad column */ - for (row=0; row < height; row++) - if (FC(row,col) == 1) { - for (sum=i=0; i < 4; i++) - sum += val[i] = bayer (row+dir[i][0], col+dir[i][1]); - for (max=i=0; i < 4; i++) { - dev[i] = abs((val[i] << 2) - sum); - if (dev[max] < dev[i]) max = i; - } - BAYER(row,col) = (sum - val[max])/3.0 + 0.5; - } else { - for (sum=0, i=8; i < 12; i++) - sum += bayer (row+dir[i][0], col+dir[i][1]); - BAYER(row,col) = 0.5 + sum * 0.0732233 + - (bayer(row,col-2) + bayer(row,col+2)) * 0.3535534; - } - else if (type == 129) { /* Bad pixel */ - if (row >= height) continue; - j = (FC(row,col) != 1) * 4; - for (sum=0, i=j; i < j+8; i++) - sum += bayer (row+dir[i][0], col+dir[i][1]); - BAYER(row,col) = (sum + 4) >> 3; - } - } - } else if (tag == 0x401) { /* All-color flat fields */ - phase_one_flat_field (1, 2); - } else if (tag == 0x416 || tag == 0x410) { - phase_one_flat_field (0, 2); - } else if (tag == 0x40b) { /* Red+blue flat field */ - phase_one_flat_field (0, 4); - } else if (tag == 0x412) { - fseek (ifp, 36, SEEK_CUR); - diff = abs (get2() - ph1.tag_21a); - if (mindiff > diff) { - mindiff = diff; - off_412 = ftell(ifp) - 38; - } - } - fseek (ifp, save, SEEK_SET); - } - if (off_412) { - fseek (ifp, off_412, SEEK_SET); - for (i=0; i < 9; i++) head[i] = get4() & 0x7fff; - yval[0] = (float *) calloc (head[1]*head[3] + head[2]*head[4], 6); - merror (yval[0], "phase_one_correct()"); - yval[1] = (float *) (yval[0] + head[1]*head[3]); - xval[0] = (ushort *) (yval[1] + head[2]*head[4]); - xval[1] = (ushort *) (xval[0] + head[1]*head[3]); - get2(); - for (i=0; i < 2; i++) - for (j=0; j < head[i+1]*head[i+3]; j++) - yval[i][j] = getreal(11); - for (i=0; i < 2; i++) - for (j=0; j < head[i+1]*head[i+3]; j++) - xval[i][j] = get2(); - for (row=0; row < height; row++) - for (col=0; col < width; col++) { - cfrac = (float) col * head[3] / raw_width; - cfrac -= cip = cfrac; - num = BAYER(row,col) * 0.5; - for (i=cip; i < cip+2; i++) { - for (k=j=0; j < head[1]; j++) - if (num < xval[0][k = head[1]*i+j]) break; - frac = (j == 0 || j == head[1]) ? 0 : - (xval[0][k] - num) / (xval[0][k] - xval[0][k-1]); - mult[i-cip] = yval[0][k-1] * frac + yval[0][k] * (1-frac); - } - i = ((mult[0] * (1-cfrac) + mult[1] * cfrac) - * (row + top_margin) + num) * 2; - BAYER(row,col) = LIM(i,0,65535); - } - free (yval[0]); - } -} - -void CLASS phase_one_load_raw() -{ - int row, col, a, b; - ushort *pixel, akey, bkey, mask; - - fseek (ifp, ph1.key_off, SEEK_SET); - akey = get2(); - bkey = get2(); - mask = ph1.format == 1 ? 0x5555:0x1354; - fseek (ifp, data_offset + top_margin*raw_width*2, SEEK_SET); - pixel = (ushort *) calloc (raw_width, sizeof *pixel); - merror (pixel, "phase_one_load_raw()"); - for (row=0; row < height; row++) { - read_shorts (pixel, raw_width); - for (col=0; col < raw_width; col+=2) { - a = pixel[col+0] ^ akey; - b = pixel[col+1] ^ bkey; - pixel[col+0] = (a & mask) | (b & ~mask); - pixel[col+1] = (b & mask) | (a & ~mask); - } - for (col=0; col < width; col++) - BAYER(row,col) = pixel[col+left_margin]; - } - free (pixel); - phase_one_correct(); -} - -unsigned CLASS ph1_bits (int nbits) -{ - static UINT64 bitbuf=0; - static int vbits=0; - - if (nbits == 0) - return bitbuf = vbits = 0; - if (vbits < nbits) { - bitbuf = bitbuf << 32 | get4(); - vbits += 32; - } - vbits -= nbits; - return bitbuf << (64 - nbits - vbits) >> (64 - nbits); -} - -void CLASS phase_one_load_raw_c() -{ - static const int length[] = { 8,7,6,9,11,10,5,12,14,13 }; - int *offset, len[2], pred[2], row, col, i, j; - ushort *pixel; - short (*black)[2]; - - pixel = (ushort *) calloc (raw_width + raw_height*4, 2); - merror (pixel, "phase_one_load_raw_c()"); - offset = (int *) (pixel + raw_width); - fseek (ifp, strip_offset, SEEK_SET); - for (row=0; row < raw_height; row++) - offset[row] = get4(); - black = (short (*)[2]) offset + raw_height; - fseek (ifp, ph1.black_off, SEEK_SET); - if (ph1.black_off) - read_shorts ((ushort *) black[0], raw_height*2); - for (i=0; i < 256; i++) - curve[i] = i*i / 3.969 + 0.5; - for (row=0; row < raw_height; row++) { - fseek (ifp, data_offset + offset[row], SEEK_SET); - ph1_bits(0); - pred[0] = pred[1] = 0; - for (col=0; col < raw_width; col++) { - if (col >= (raw_width & -8)) - len[0] = len[1] = 14; - else if ((col & 7) == 0) - for (i=0; i < 2; i++) { - for (j=0; j < 5 && !ph1_bits(1); j++); - if (j--) len[i] = length[j*2 + ph1_bits(1)]; - } - if ((i = len[col & 1]) == 14) - pixel[col] = pred[col & 1] = ph1_bits(16); - else - pixel[col] = pred[col & 1] += ph1_bits(i) + 1 - (1 << (i - 1)); - if (pred[col & 1] >> 16) derror(); - if (ph1.format == 5 && pixel[col] < 256) - pixel[col] = curve[pixel[col]]; - } - if ((unsigned) (row-top_margin) < height) - for (col=0; col < width; col++) { - i = (pixel[col+left_margin] << 2) - - ph1.black + black[row][col >= ph1.split_col]; - if (i > 0) BAYER(row-top_margin,col) = i; - } - } - free (pixel); - phase_one_correct(); - maximum = 0xfffc - ph1.black; -} - -void CLASS leaf_hdr_load_raw() -{ - ushort *pixel; - unsigned tile=0, r, c, row, col; - - pixel = (ushort *) calloc (raw_width, sizeof *pixel); - merror (pixel, "leaf_hdr_load_raw()"); - for (c=0; c < tiff_samples; c++) { - for (r=0; r < raw_height; r++) { - if (r % tile_length == 0) { - fseek (ifp, data_offset + 4*tile++, SEEK_SET); - fseek (ifp, get4() + 2*left_margin, SEEK_SET); - } - if (filters && c != shot_select) continue; - read_shorts (pixel, raw_width); - if ((row = r - top_margin) >= height) continue; - for (col=0; col < width; col++) - if (filters) BAYER(row,col) = pixel[col]; - else image[row*width+col][c] = pixel[col]; - } - } - free (pixel); - if (!filters) { - maximum = 0xffff; - raw_color = 1; - } -} - -void CLASS unpacked_load_raw(); - -void CLASS sinar_4shot_load_raw() -{ - ushort *pixel; - unsigned shot, row, col, r, c; - - if ((shot = shot_select) || half_size) { - if (shot) shot--; - if (shot > 3) shot = 3; - fseek (ifp, data_offset + shot*4, SEEK_SET); - fseek (ifp, get4(), SEEK_SET); - unpacked_load_raw(); - return; - } - free (image); - image = (ushort (*)[4]) - calloc ((iheight=height)*(iwidth=width), sizeof *image); - merror (image, "sinar_4shot_load_raw()"); - pixel = (ushort *) calloc (raw_width, sizeof *pixel); - merror (pixel, "sinar_4shot_load_raw()"); - for (shot=0; shot < 4; shot++) { - fseek (ifp, data_offset + shot*4, SEEK_SET); - fseek (ifp, get4(), SEEK_SET); - for (row=0; row < raw_height; row++) { - read_shorts (pixel, raw_width); - if ((r = row-top_margin - (shot >> 1 & 1)) >= height) continue; - for (col=0; col < raw_width; col++) { - if ((c = col-left_margin - (shot & 1)) >= width) continue; - image[r*width+c][FC(row,col)] = pixel[col]; - } - } - } - free (pixel); - shrink = filters = 0; -} - -void CLASS imacon_full_load_raw() -{ - int row, col; - - for (row=0; row < height; row++) - for (col=0; col < width; col++) - read_shorts (image[row*width+col], 3); -} - -void CLASS packed_12_load_raw() -{ - int row, col; - - if (raw_width * 2 < width * 3) - raw_width = raw_width * 3 / 2; /* Convert raw_width to bytes */ - getbits(-1); - for (row=0; row < height; row++) { - for (col=0; col < left_margin; col++) - getbits(12); - for (col=0; col < width; col++) - BAYER(row,col) = getbits(12); - for (col = (width+left_margin)*3/2; col < raw_width; col++) - if (getbits(8) && raw_width-col < 35 && width != 3896) derror(); - } -} - -void CLASS unpacked_load_raw() -{ - ushort *pixel; - int row, col, bits=0; - - while (1 << ++bits < maximum); - fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR); - pixel = (ushort *) calloc (width, sizeof *pixel); - merror (pixel, "unpacked_load_raw()"); - for (row=0; row < height; row++) { - read_shorts (pixel, width); - fseek (ifp, 2*(raw_width - width), SEEK_CUR); - for (col=0; col < width; col++) - if ((BAYER2(row,col) = pixel[col]) >> bits) derror(); - } - free (pixel); -} - -void CLASS olympus_e300_load_raw() -{ - uchar *data, *dp; - ushort *pixel, *pix; - int dwide, row, col; - - dwide = raw_width * 16 / 10; - fseek (ifp, dwide*top_margin, SEEK_CUR); - data = (uchar *) malloc (dwide + raw_width*2); - merror (data, "olympus_e300_load_raw()"); - pixel = (ushort *) (data + dwide); - for (row=0; row < height; row++) { - if (fread (data, 1, dwide, ifp) < dwide) derror(); - for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=3, pix+=2) { - if (((dp-data) & 15) == 15) - if (*dp++ && pix < pixel+width+left_margin) derror(); - pix[0] = dp[1] << 8 | dp[0]; - pix[1] = dp[2] << 4 | dp[1] >> 4; - } - for (col=0; col < width; col++) - BAYER(row,col) = (pixel[col+left_margin] & 0xfff); - } - free (data); - if (!strcmp(make,"OLYMPUS")) { - maximum = 0xfff; - black >>= 4; - } -} - -void CLASS olympus_e410_load_raw() -{ - int row, col, nbits, sign, low, high, i, w, n, nw; - int acarry[2][3], *carry, pred, diff; - - fseek (ifp, 7, SEEK_CUR); - getbits(-1); - for (row=0; row < height; row++) { - memset (acarry, 0, sizeof acarry); - for (col=0; col < width; col++) { - carry = acarry[col & 1]; - i = 2 * (carry[2] < 3); - for (nbits=2+i; (ushort) carry[0] >> (nbits+i); nbits++); - sign = getbits(1) * -1; - low = getbits(2); - for (high=0; high < 12; high++) - if (getbits(1)) break; - if (high == 12) - high = getbits(16-nbits) >> 1; - carry[0] = (high << nbits) | getbits(nbits); - diff = (carry[0] ^ sign) + carry[1]; - carry[1] = (diff*3 + carry[1]) >> 5; - carry[2] = carry[0] > 16 ? 0 : carry[2]+1; - if (row < 2 && col < 2) pred = 0; - else if (row < 2) pred = BAYER(row,col-2); - else if (col < 2) pred = BAYER(row-2,col); - else { - w = BAYER(row,col-2); - n = BAYER(row-2,col); - nw = BAYER(row-2,col-2); - if ((w < nw && nw < n) || (n < nw && nw < w)) { - if (ABS(w-nw) > 32 || ABS(n-nw) > 32) - pred = w + n - nw; - else pred = (w + n) >> 1; - } else pred = ABS(w-nw) > ABS(n-nw) ? w : n; - } - if ((BAYER(row,col) = pred + ((diff << 2) | low)) >> 12) derror(); - } - } -} - -void CLASS olympus_cseries_load_raw() -{ - int irow, row, col; - - for (irow=0; irow < height; irow++) { - row = irow * 2 % height + irow / (height/2); - if (row < 2) { - fseek (ifp, data_offset - row*(-width*height*3/4 & -2048), SEEK_SET); - getbits(-1); - } - for (col=0; col < width; col++) - BAYER(row,col) = getbits(12); - } - black >>= 4; -} - -void CLASS minolta_rd175_load_raw() -{ - uchar pixel[768]; - unsigned irow, box, row, col; - - for (irow=0; irow < 1481; irow++) { - if (fread (pixel, 1, 768, ifp) < 768) derror(); - box = irow / 82; - row = irow % 82 * 12 + ((box < 12) ? box | 1 : (box-12)*2); - switch (irow) { - case 1477: case 1479: continue; - case 1476: row = 984; break; - case 1480: row = 985; break; - case 1478: row = 985; box = 1; - } - if ((box < 12) && (box & 1)) { - for (col=0; col < 1533; col++, row ^= 1) - if (col != 1) BAYER(row,col) = (col+1) & 2 ? - pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1; - BAYER(row,1) = pixel[1] << 1; - BAYER(row,1533) = pixel[765] << 1; - } else - for (col=row & 1; col < 1534; col+=2) - BAYER(row,col) = pixel[col/2] << 1; - } - maximum = 0xff << 1; -} - -void CLASS eight_bit_load_raw() -{ - uchar *pixel; - int row, col; - - pixel = (uchar *) calloc (raw_width, sizeof *pixel); - merror (pixel, "eight_bit_load_raw()"); - for (row=0; row < height; row++) { - if (fread (pixel, 1, raw_width, ifp) < raw_width) derror(); - for (col=0; col < width; col++) - BAYER(row,col) = pixel[col]; - } - free (pixel); - maximum = 0xff; -} - -void CLASS casio_qv5700_load_raw() -{ - uchar data[3232], *dp; - ushort pixel[2576], *pix; - int row, col; - - for (row=0; row < height; row++) { - fread (data, 1, 3232, ifp); - for (dp=data, pix=pixel; dp < data+3220; dp+=5, pix+=4) { - pix[0] = (dp[0] << 2) + (dp[1] >> 6); - pix[1] = (dp[1] << 4) + (dp[2] >> 4); - pix[2] = (dp[2] << 6) + (dp[3] >> 2); - pix[3] = (dp[3] << 8) + (dp[4] ); - } - for (col=0; col < width; col++) - BAYER(row,col) = (pixel[col] & 0x3ff); - } - maximum = 0x3fc; -} - -void CLASS quicktake_100_load_raw() -{ - uchar pixel[484][644]; - static const short gstep[16] = - { -89,-60,-44,-32,-22,-15,-8,-2,2,8,15,22,32,44,60,89 }; - static const short rstep[6][4] = - { { -3,-1,1,3 }, { -5,-1,1,5 }, { -8,-2,2,8 }, - { -13,-3,3,13 }, { -19,-4,4,19 }, { -28,-6,6,28 } }; - static const short curve[256] = - { 0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27, - 28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,53, - 54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78, - 79,80,81,82,83,84,86,88,90,92,94,97,99,101,103,105,107,110,112,114,116, - 118,120,123,125,127,129,131,134,136,138,140,142,144,147,149,151,153,155, - 158,160,162,164,166,168,171,173,175,177,179,181,184,186,188,190,192,195, - 197,199,201,203,205,208,210,212,214,216,218,221,223,226,230,235,239,244, - 248,252,257,261,265,270,274,278,283,287,291,296,300,305,309,313,318,322, - 326,331,335,339,344,348,352,357,361,365,370,374,379,383,387,392,396,400, - 405,409,413,418,422,426,431,435,440,444,448,453,457,461,466,470,474,479, - 483,487,492,496,500,508,519,531,542,553,564,575,587,598,609,620,631,643, - 654,665,676,687,698,710,721,732,743,754,766,777,788,799,810,822,833,844, - 855,866,878,889,900,911,922,933,945,956,967,978,989,1001,1012,1023 }; - int rb, row, col, sharp, val=0; - - getbits(-1); - memset (pixel, 0x80, sizeof pixel); - for (row=2; row < height+2; row++) { - for (col=2+(row & 1); col < width+2; col+=2) { - val = ((pixel[row-1][col-1] + 2*pixel[row-1][col+1] + - pixel[row][col-2]) >> 2) + gstep[getbits(4)]; - pixel[row][col] = val = LIM(val,0,255); - if (col < 4) - pixel[row][col-2] = pixel[row+1][~row & 1] = val; - if (row == 2) - pixel[row-1][col+1] = pixel[row-1][col+3] = val; - } - pixel[row][col] = val; - } - for (rb=0; rb < 2; rb++) - for (row=2+rb; row < height+2; row+=2) - for (col=3-(row & 1); col < width+2; col+=2) { - if (row < 4 || col < 4) sharp = 2; - else { - val = ABS(pixel[row-2][col] - pixel[row][col-2]) - + ABS(pixel[row-2][col] - pixel[row-2][col-2]) - + ABS(pixel[row][col-2] - pixel[row-2][col-2]); - sharp = val < 4 ? 0 : val < 8 ? 1 : val < 16 ? 2 : - val < 32 ? 3 : val < 48 ? 4 : 5; - } - val = ((pixel[row-2][col] + pixel[row][col-2]) >> 1) - + rstep[sharp][getbits(2)]; - pixel[row][col] = val = LIM(val,0,255); - if (row < 4) pixel[row-2][col+2] = val; - if (col < 4) pixel[row+2][col-2] = val; - } - for (row=2; row < height+2; row++) - for (col=3-(row & 1); col < width+2; col+=2) { - val = ((pixel[row][col-1] + (pixel[row][col] << 2) + - pixel[row][col+1]) >> 1) - 0x100; - pixel[row][col] = LIM(val,0,255); - } - for (row=0; row < height; row++) - for (col=0; col < width; col++) - BAYER(row,col) = curve[pixel[row+2][col+2]]; - maximum = 0x3ff; -} - -const int * CLASS make_decoder_int (const int *source, int level) -{ - struct decode *cur; - - cur = free_decode++; - if (level < source[0]) { - cur->branch[0] = free_decode; - source = make_decoder_int (source, level+1); - cur->branch[1] = free_decode; - source = make_decoder_int (source, level+1); - } else { - cur->leaf = source[1]; - source += 2; - } - return source; -} - -int CLASS radc_token (int tree) -{ - int t; - static struct decode *dstart[18], *dindex; - static const int *s, source[] = { - 1,1, 2,3, 3,4, 4,2, 5,7, 6,5, 7,6, 7,8, - 1,0, 2,1, 3,3, 4,4, 5,2, 6,7, 7,6, 8,5, 8,8, - 2,1, 2,3, 3,0, 3,2, 3,4, 4,6, 5,5, 6,7, 6,8, - 2,0, 2,1, 2,3, 3,2, 4,4, 5,6, 6,7, 7,5, 7,8, - 2,1, 2,4, 3,0, 3,2, 3,3, 4,7, 5,5, 6,6, 6,8, - 2,3, 3,1, 3,2, 3,4, 3,5, 3,6, 4,7, 5,0, 5,8, - 2,3, 2,6, 3,0, 3,1, 4,4, 4,5, 4,7, 5,2, 5,8, - 2,4, 2,7, 3,3, 3,6, 4,1, 4,2, 4,5, 5,0, 5,8, - 2,6, 3,1, 3,3, 3,5, 3,7, 3,8, 4,0, 5,2, 5,4, - 2,0, 2,1, 3,2, 3,3, 4,4, 4,5, 5,6, 5,7, 4,8, - 1,0, 2,2, 2,-2, - 1,-3, 1,3, - 2,-17, 2,-5, 2,5, 2,17, - 2,-7, 2,2, 2,9, 2,18, - 2,-18, 2,-9, 2,-2, 2,7, - 2,-28, 2,28, 3,-49, 3,-9, 3,9, 4,49, 5,-79, 5,79, - 2,-1, 2,13, 2,26, 3,39, 4,-16, 5,55, 6,-37, 6,76, - 2,-26, 2,-13, 2,1, 3,-39, 4,16, 5,-55, 6,-76, 6,37 - }; - - if (free_decode == first_decode) - for (s=source, t=0; t < 18; t++) { - dstart[t] = free_decode; - s = make_decoder_int (s, 0); - } - if (tree == 18) { - if (kodak_cbpp == 243) - return (getbits(6) << 2) + 2; /* most DC50 photos */ - else - return (getbits(5) << 3) + 4; /* DC40, Fotoman Pixtura */ - } - for (dindex = dstart[tree]; dindex->branch[0]; ) - dindex = dindex->branch[getbits(1)]; - return dindex->leaf; -} - -#define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; ... [truncated message content] |
From: <gl...@us...> - 2007-08-30 22:38:37
|
Revision: 286 http://hdrflow.svn.sourceforge.net/hdrflow/?rev=286&view=rev Author: glslang Date: 2007-08-30 15:38:33 -0700 (Thu, 30 Aug 2007) Log Message: ----------- + portability fixes Modified Paths: -------------- trunk/lib/extras/src/raw/Makefile.am Added Paths: ----------- trunk/lib/extras/src/raw/dcraw.c Removed Paths: ------------- trunk/lib/extras/src/raw/dcraw.cpp Modified: trunk/lib/extras/src/raw/Makefile.am =================================================================== --- trunk/lib/extras/src/raw/Makefile.am 2007-08-30 22:34:13 UTC (rev 285) +++ trunk/lib/extras/src/raw/Makefile.am 2007-08-30 22:38:33 UTC (rev 286) @@ -9,12 +9,14 @@ libhdrflow_extras_raw_la_SOURCES = \ raw.cpp \ - dcraw.cpp + dcraw.c libhdrflow_extras_raw_la_CXXFLAGS = \ $(BOOST_INCLUDE_PATH) \ -I$(top_builddir)/../openlibraries/src \ - $(OFX_INCLUDE_PATH) \ - -DNO_JPEG \ + $(OFX_INCLUDE_PATH) + +libhdrflow_extras_raw_la_CFLAGS = \ + -DNO_JPEG \ -DNO_LCMS Copied: trunk/lib/extras/src/raw/dcraw.c (from rev 285, trunk/lib/extras/src/raw/dcraw.cpp) =================================================================== --- trunk/lib/extras/src/raw/dcraw.c (rev 0) +++ trunk/lib/extras/src/raw/dcraw.c 2007-08-30 22:38:33 UTC (rev 286) @@ -0,0 +1,7726 @@ +/* + dcraw.c -- Dave Coffin's raw photo decoder + Copyright 1997-2007 by Dave Coffin, dcoffin a cybercom o net + + This is a command-line ANSI C program to convert raw photos from + any digital camera on any computer running any operating system. + + No license is required to download and use dcraw.c. However, + to lawfully redistribute this code, you must either (a) include + full source code* for all executable files containing RESTRICTED + functions, (b) remove all RESTRICTED functions, re-implement them, + or copy them from an earlier, unrestricted Revision of dcraw.c, + or (c) purchase a license from the author. + + The functions that process Foveon images have been RESTRICTED + since Revision 1.237. All other code remains free for all uses. + + *If you have not modified dcraw.c in any way, a link to my + homepage qualifies as "full source code". + + $Revision: 1.379 $ + $Date: 2007/05/03 06:15:16 $ + */ + +#define VERSION "8.71" + +#define _GNU_SOURCE +#define _USE_MATH_DEFINES +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <float.h> +#include <limits.h> +#include <math.h> +#include <setjmp.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +/* + NO_JPEG disables decoding of compressed Kodak DC120 files. + NO_LCMS disables the "-p" option. + */ +#ifndef NO_JPEG +#include <jpeglib.h> +#endif +#ifndef NO_LCMS +#include <lcms.h> +#endif +#ifdef LOCALEDIR +#include <libintl.h> +#define _(String) gettext(String) +#else +#define _(String) (String) +#endif +#ifndef DJGPP +#define fgetc getc_unlocked +#endif +#ifdef __CYGWIN__ +#include <io.h> +#endif +#ifdef WIN32 +#include <sys/utime.h> +#include <winsock2.h> +#pragma comment(lib, "ws2_32.lib") +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#define getc_unlocked getc +typedef __int64 INT64; +typedef unsigned __int64 UINT64; +#pragma warning( disable:4018 4244 4305 4389 4706 ) +#else +#include <unistd.h> +#include <utime.h> +#include <netinet/in.h> +typedef long long INT64; +typedef unsigned long long UINT64; +#endif + +#ifdef LJPEG_DECODE +#error Please compile dcraw.c by itself. +#error Do not link it with ljpeg_decode. +#endif + +#ifndef LONG_BIT +#define LONG_BIT (8 * sizeof (long)) +#endif + +#define ushort UshORt +typedef unsigned char uchar; +typedef unsigned short ushort; + +/* + All global variables are defined here, and all functions that + access them are prefixed with "CLASS". Note that a thread-safe + C++ class cannot have non-const static local variables. + */ +FILE *ifp; +short order; +char *ifname, make[64], model[64], model2[64], *meta_data, cdesc[5]; +float flash_used, canon_ev, iso_speed, shutter, aperture, focal_len; +time_t timestamp; +unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id; +unsigned profile_offset, profile_length, *oprof; +unsigned thumb_offset, thumb_length, thumb_misc; +unsigned data_offset, strip_offset, curve_offset, meta_offset, meta_length; +unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress, tile_length; +unsigned black, maximum, mix_green, raw_color, use_gamma, zero_is_bad; +unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error; +ushort raw_height, raw_width, height, width, top_margin, left_margin; +ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height; +int flip, tiff_flip, colors; +double pixel_aspect; +ushort (*image)[4], white[8][8], curve[0x1000], cr2_slice[3]; +float bright=1, user_mul[4]={0,0,0,0}, threshold=0; +int half_size=0, four_color_rgb=0, document_mode=0, highlight=0; +int verbose=0, use_auto_wb=0, use_camera_wb=0; +int output_color=1, output_bps=8, output_tiff=0; +int fuji_layout, fuji_secondary, shot_select=0; +unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX }; +float cam_mul[4], pre_mul[4], rgb_cam[3][4]; /* RGB from camera color */ +const double xyz_rgb[3][3] = { /* XYZ from RGB */ + { 0.412453, 0.357580, 0.180423 }, + { 0.212671, 0.715160, 0.072169 }, + { 0.019334, 0.119193, 0.950227 } }; +const float d65_white[3] = { 0.950456, 1, 1.088754 }; +int histogram[4][0x2000]; +void (*write_thumb)(FILE *), (*write_fun)(FILE *); +void (*load_raw)(), (*thumb_load_raw)(); +jmp_buf failure; + +struct decode { + struct decode *branch[2]; + int leaf; +} first_decode[2048], *second_decode, *free_decode; + +struct { + int width, height, bps, comp, phint, offset, flip, samples, bytes; +} tiff_ifd[10]; + +struct { + int format, key_off, black, black_off, split_col, tag_21a; + float tag_210; +} ph1; + +#define CLASS + +#define FORC3 for (c=0; c < 3; c++) +#define FORC4 for (c=0; c < 4; c++) +#define FORCC for (c=0; c < colors; c++) + +#define SQR(x) ((x)*(x)) +#define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define LIM(x,min,max) MAX(min,MIN(x,max)) +#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y)) +#define CLIP(x) LIM(x,0,65535) +#define SWAP(a,b) { a ^= b; a ^= (b ^= a); } + +/* + In order to inline this calculation, I make the risky + assumption that all filter patterns can be described + by a repeating pattern of eight rows and two columns + + Do not use the FC or BAYER macros with the Leaf CatchLight, + because its pattern is 16x16, not 2x8. + + Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2/3 = R/G1/B/G2 + + PowerShot 600 PowerShot A50 PowerShot Pro70 Pro90 & G1 + 0xe1e4e1e4: 0x1b4e4b1e: 0x1e4b4e1b: 0xb4b4b4b4: + + 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 + 0 G M G M G M 0 C Y C Y C Y 0 Y C Y C Y C 0 G M G M G M + 1 C Y C Y C Y 1 M G M G M G 1 M G M G M G 1 Y C Y C Y C + 2 M G M G M G 2 Y C Y C Y C 2 C Y C Y C Y + 3 C Y C Y C Y 3 G M G M G M 3 G M G M G M + 4 C Y C Y C Y 4 Y C Y C Y C + PowerShot A5 5 G M G M G M 5 G M G M G M + 0x1e4e1e4e: 6 Y C Y C Y C 6 C Y C Y C Y + 7 M G M G M G 7 M G M G M G + 0 1 2 3 4 5 + 0 C Y C Y C Y + 1 G M G M G M + 2 C Y C Y C Y + 3 M G M G M G + + All RGB cameras use one of these Bayer grids: + + 0x16161616: 0x61616161: 0x49494949: 0x94949494: + + 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 + 0 B G B G B G 0 G R G R G R 0 G B G B G B 0 R G R G R G + 1 G R G R G R 1 B G B G B G 1 R G R G R G 1 G B G B G B + 2 B G B G B G 2 G R G R G R 2 G B G B G B 2 R G R G R G + 3 G R G R G R 3 B G B G B G 3 R G R G R G 3 G B G B G B + */ + +#define FC(row,col) \ + (filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) + +#define BAYER(row,col) \ + image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)] + +#define BAYER2(row,col) \ + image[((row) >> shrink)*iwidth + ((col) >> shrink)][fc(row,col)] + +int CLASS fc (int row, int col) +{ + static const char filter[16][16] = + { { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 }, + { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 }, + { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 }, + { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 }, + { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 }, + { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 }, + { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 }, + { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 }, + { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 }, + { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 }, + { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 }, + { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 }, + { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 }, + { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 }, + { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 }, + { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } }; + + if (filters != 1) return FC(row,col); + return filter[(row+top_margin) & 15][(col+left_margin) & 15]; +} + +#ifndef __GLIBC__ +char *my_memmem (char *haystack, size_t haystacklen, + char *needle, size_t needlelen) +{ + char *c; + for (c = haystack; c <= haystack + haystacklen - needlelen; c++) + if (!memcmp (c, needle, needlelen)) + return c; + return 0; +} +#define memmem my_memmem +#endif + +void CLASS merror (void *ptr, char *where) +{ + if (ptr) return; + fprintf (stderr,_("%s: Out of memory in %s\n"), ifname, where); + longjmp (failure, 1); +} + +void CLASS derror() +{ + if (!data_error) { + fprintf (stderr, "%s: ", ifname); + if (feof(ifp)) + fprintf (stderr,_("Unexpected end of file\n")); + else + fprintf (stderr,_("Corrupt data near 0x%lx\n"), ftell(ifp)); + } + data_error = 1; +} + +ushort CLASS sget2 (uchar *s) +{ + if (order == 0x4949) /* "II" means little-endian */ + return s[0] | s[1] << 8; + else /* "MM" means big-endian */ + return s[0] << 8 | s[1]; +} + +ushort CLASS get2() +{ + uchar str[2] = { 0xff,0xff }; + fread (str, 1, 2, ifp); + return sget2(str); +} + +unsigned CLASS sget4 (uchar *s) +{ + if (order == 0x4949) + return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; + else + return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]; +} +#define sget4(s) sget4((uchar *)s) + +unsigned CLASS get4() +{ + uchar str[4] = { 0xff,0xff,0xff,0xff }; + fread (str, 1, 4, ifp); + return sget4(str); +} + +unsigned CLASS getint (int type) +{ + return type == 3 ? get2() : get4(); +} + +float CLASS int_to_float (int i) +{ + union { int i; float f; } u; + u.i = i; + return u.f; +} + +double CLASS getreal (int type) +{ + union { char c[8]; double d; } u; + int i, rev; + + switch (type) { + case 3: return (unsigned short) get2(); + case 4: return (unsigned int) get4(); + case 5: u.d = (unsigned int) get4(); + return u.d / (unsigned int) get4(); + case 8: return (signed short) get2(); + case 9: return (signed int) get4(); + case 10: u.d = (signed int) get4(); + return u.d / (signed int) get4(); + case 11: return int_to_float (get4()); + case 12: + rev = 7 * ((order == 0x4949) == (ntohs(0x1234) == 0x1234)); + for (i=0; i < 8; i++) + u.c[i ^ rev] = fgetc(ifp); + return u.d; + default: return fgetc(ifp); + } +} +#define getrat() getreal(10) + +void CLASS read_shorts (ushort *pixel, int count) +{ + if (fread (pixel, 2, count, ifp) < count) derror(); + if ((order == 0x4949) == (ntohs(0x1234) == 0x1234)) + swab (pixel, pixel, count*2); +} + +void CLASS canon_600_fixed_wb (int temp) +{ + static const short mul[4][5] = { + { 667, 358,397,565,452 }, + { 731, 390,367,499,517 }, + { 1119, 396,348,448,537 }, + { 1399, 485,431,508,688 } }; + int lo, hi, i; + float frac=0; + + for (lo=4; --lo; ) + if (*mul[lo] <= temp) break; + for (hi=0; hi < 3; hi++) + if (*mul[hi] >= temp) break; + if (lo != hi) + frac = (float) (temp - *mul[lo]) / (*mul[hi] - *mul[lo]); + for (i=1; i < 5; i++) + pre_mul[i-1] = 1 / (frac * mul[hi][i] + (1-frac) * mul[lo][i]); +} + +/* Return values: 0 = white 1 = near white 2 = not white */ +int CLASS canon_600_color (int ratio[2], int mar) +{ + int clipped=0, target, miss; + + if (flash_used) { + if (ratio[1] < -104) + { ratio[1] = -104; clipped = 1; } + if (ratio[1] > 12) + { ratio[1] = 12; clipped = 1; } + } else { + if (ratio[1] < -264 || ratio[1] > 461) return 2; + if (ratio[1] < -50) + { ratio[1] = -50; clipped = 1; } + if (ratio[1] > 307) + { ratio[1] = 307; clipped = 1; } + } + target = flash_used || ratio[1] < 197 + ? -38 - (398 * ratio[1] >> 10) + : -123 + (48 * ratio[1] >> 10); + if (target - mar <= ratio[0] && + target + 20 >= ratio[0] && !clipped) return 0; + miss = target - ratio[0]; + if (abs(miss) >= mar*4) return 2; + if (miss < -20) miss = -20; + if (miss > mar) miss = mar; + ratio[0] = target - miss; + return 1; +} + +void CLASS canon_600_auto_wb() +{ + int mar, row, col, i, j, st, count[] = { 0,0 }; + int test[8], total[2][8], ratio[2][2], stat[2]; + + memset (&total, 0, sizeof total); + i = canon_ev + 0.5; + if (i < 10) mar = 150; + else if (i > 12) mar = 20; + else mar = 280 - 20 * i; + if (flash_used) mar = 80; + for (row=14; row < height-14; row+=4) + for (col=10; col < width; col+=2) { + for (i=0; i < 8; i++) + test[(i & 4) + FC(row+(i >> 1),col+(i & 1))] = + BAYER(row+(i >> 1),col+(i & 1)); + for (i=0; i < 8; i++) + if (test[i] < 150 || test[i] > 1500) goto next; + for (i=0; i < 4; i++) + if (abs(test[i] - test[i+4]) > 50) goto next; + for (i=0; i < 2; i++) { + for (j=0; j < 4; j+=2) + ratio[i][j >> 1] = ((test[i*4+j+1]-test[i*4+j]) << 10) / test[i*4+j]; + stat[i] = canon_600_color (ratio[i], mar); + } + if ((st = stat[0] | stat[1]) > 1) goto next; + for (i=0; i < 2; i++) + if (stat[i]) + for (j=0; j < 2; j++) + test[i*4+j*2+1] = test[i*4+j*2] * (0x400 + ratio[i][j]) >> 10; + for (i=0; i < 8; i++) + total[st][i] += test[i]; + count[st]++; +next: continue; + } + if (count[0] | count[1]) { + st = count[0]*200 < count[1]; + for (i=0; i < 4; i++) + pre_mul[i] = 1.0 / (total[st][i] + total[st][i+4]); + } +} + +void CLASS canon_600_coeff() +{ + static const short table[6][12] = { + { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 }, + { -1203,1715,-1136,1648, 1388,-876,267,245, -1641,2153,3921,-3409 }, + { -615,1127,-1563,2075, 1437,-925,509,3, -756,1268,2519,-2007 }, + { -190,702,-1886,2398, 2153,-1641,763,-251, -452,964,3040,-2528 }, + { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 }, + { -807,1319,-1785,2297, 1388,-876,769,-257, -230,742,2067,-1555 } }; + int t=0, i, c; + float mc, yc; + + mc = pre_mul[1] / pre_mul[2]; + yc = pre_mul[3] / pre_mul[2]; + if (mc > 1 && mc <= 1.28 && yc < 0.8789) t=1; + if (mc > 1.28 && mc <= 2) { + if (yc < 0.8789) t=3; + else if (yc <= 2) t=4; + } + if (flash_used) t=5; + for (raw_color = i=0; i < 3; i++) + FORCC rgb_cam[i][c] = table[t][i*4 + c] / 1024.0; +} + +void CLASS canon_600_load_raw() +{ + uchar data[1120], *dp; + ushort pixel[896], *pix; + int irow, row, col, val; + static const short mul[4][2] = + { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } }; + + for (irow=row=0; irow < height; irow++) { + if (fread (data, 1, raw_width*5/4, ifp) < raw_width*5/4) derror(); + for (dp=data, pix=pixel; dp < data+1120; dp+=10, pix+=8) { + pix[0] = (dp[0] << 2) + (dp[1] >> 6 ); + pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3); + pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3); + pix[3] = (dp[4] << 2) + (dp[1] & 3); + pix[4] = (dp[5] << 2) + (dp[9] & 3); + pix[5] = (dp[6] << 2) + (dp[9] >> 2 & 3); + pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3); + pix[7] = (dp[8] << 2) + (dp[9] >> 6 ); + } + for (col=0; col < width; col++) + BAYER(row,col) = pixel[col]; + for (col=width; col < raw_width; col++) + black += pixel[col]; + if ((row+=2) > height) row = 1; + } + if (raw_width > width) + black = black / ((raw_width - width) * height) - 4; + for (row=0; row < height; row++) + for (col=0; col < width; col++) { + val = (BAYER(row,col) - black) * mul[row & 3][col & 1] >> 9; + if (val < 0) val = 0; + BAYER(row,col) = val; + } + canon_600_fixed_wb(1311); + canon_600_auto_wb(); + canon_600_coeff(); + maximum = (0x3ff - black) * 1109 >> 9; + black = 0; +} + +void CLASS remove_zeroes() +{ + unsigned row, col, tot, n, r, c; + + for (row=0; row < height; row++) + for (col=0; col < width; col++) + if (BAYER(row,col) == 0) { + tot = n = 0; + for (r = row-2; r <= row+2; r++) + for (c = col-2; c <= col+2; c++) + if (r < height && c < width && + FC(r,c) == FC(row,col) && BAYER(r,c)) + tot += (n++,BAYER(r,c)); + if (n) BAYER(row,col) = tot/n; + } +} + +int CLASS canon_s2is() +{ + unsigned row; + + for (row=0; row < 100; row++) { + fseek (ifp, row*3340 + 3284, SEEK_SET); + if (getc(ifp) > 15) return 1; + } + return 0; +} + +void CLASS canon_a5_load_raw() +{ + ushort data[2335], *dp, pixel; + int vbits=0, buf=0, row, col, bc=0; + + order = 0x4949; + for (row=-top_margin; row < raw_height-top_margin; row++) { + read_shorts (dp=data, raw_width * 10 / 16); + for (col=-left_margin; col < raw_width-left_margin; col++) { + if (vbits < 10) + buf = (vbits += 16, (buf << 16) + *dp++); + pixel = buf >> (vbits -= 10) & 0x3ff; + if ((unsigned) row < height && (unsigned) col < width) + BAYER(row,col) = pixel; + else if (col > 1-left_margin && col != width) + black += (bc++,pixel); + } + } + if (bc) black /= bc; + maximum = 0x3ff; + if (raw_width > 1600) remove_zeroes(); +} + +/* + getbits(-1) initializes the buffer + getbits(n) where 0 <= n <= 25 returns an n-bit integer + */ +unsigned CLASS getbits (int nbits) +{ + static unsigned bitbuf=0; + static int vbits=0, reset=0; + unsigned c; + + if (nbits == -1) + return bitbuf = vbits = reset = 0; + if (nbits == 0 || reset) return 0; + while (vbits < nbits) { + if ((c = fgetc(ifp)) == EOF) derror(); + if ((reset = zero_after_ff && c == 0xff && fgetc(ifp))) return 0; + bitbuf = (bitbuf << 8) + (uchar) c; + vbits += 8; + } + vbits -= nbits; + return bitbuf << (32-nbits-vbits) >> (32-nbits); +} + +void CLASS init_decoder() +{ + memset (first_decode, 0, sizeof first_decode); + free_decode = first_decode; +} + +/* + Construct a decode tree according the specification in *source. + The first 16 bytes specify how many codes should be 1-bit, 2-bit + 3-bit, etc. Bytes after that are the leaf values. + + For example, if the source is + + { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, + 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff }, + + then the code is + + 00 0x04 + 010 0x03 + 011 0x05 + 100 0x06 + 101 0x02 + 1100 0x07 + 1101 0x01 + 11100 0x08 + 11101 0x09 + 11110 0x00 + 111110 0x0a + 1111110 0x0b + 1111111 0xff + */ +uchar * CLASS make_decoder (const uchar *source, int level) +{ + struct decode *cur; + static int leaf; + int i, next; + + if (level==0) leaf=0; + cur = free_decode++; + if (free_decode > first_decode+2048) { + fprintf (stderr,_("%s: decoder table overflow\n"), ifname); + longjmp (failure, 2); + } + for (i=next=0; i <= leaf && next < 16; ) + i += source[next++]; + if (i > leaf) { + if (level < next) { + cur->branch[0] = free_decode; + make_decoder (source, level+1); + cur->branch[1] = free_decode; + make_decoder (source, level+1); + } else + cur->leaf = source[16 + leaf++]; + } + return (uchar *) source + 16 + leaf; +} + +void CLASS crw_init_tables (unsigned table) +{ + static const uchar first_tree[3][29] = { + { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, + 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff }, + { 0,2,2,3,1,1,1,1,2,0,0,0,0,0,0,0, + 0x03,0x02,0x04,0x01,0x05,0x00,0x06,0x07,0x09,0x08,0x0a,0x0b,0xff }, + { 0,0,6,3,1,1,2,0,0,0,0,0,0,0,0,0, + 0x06,0x05,0x07,0x04,0x08,0x03,0x09,0x02,0x00,0x0a,0x01,0x0b,0xff }, + }; + static const uchar second_tree[3][180] = { + { 0,2,2,2,1,4,2,1,2,5,1,1,0,0,0,139, + 0x03,0x04,0x02,0x05,0x01,0x06,0x07,0x08, + 0x12,0x13,0x11,0x14,0x09,0x15,0x22,0x00,0x21,0x16,0x0a,0xf0, + 0x23,0x17,0x24,0x31,0x32,0x18,0x19,0x33,0x25,0x41,0x34,0x42, + 0x35,0x51,0x36,0x37,0x38,0x29,0x79,0x26,0x1a,0x39,0x56,0x57, + 0x28,0x27,0x52,0x55,0x58,0x43,0x76,0x59,0x77,0x54,0x61,0xf9, + 0x71,0x78,0x75,0x96,0x97,0x49,0xb7,0x53,0xd7,0x74,0xb6,0x98, + 0x47,0x48,0x95,0x69,0x99,0x91,0xfa,0xb8,0x68,0xb5,0xb9,0xd6, + 0xf7,0xd8,0x67,0x46,0x45,0x94,0x89,0xf8,0x81,0xd5,0xf6,0xb4, + 0x88,0xb1,0x2a,0x44,0x72,0xd9,0x87,0x66,0xd4,0xf5,0x3a,0xa7, + 0x73,0xa9,0xa8,0x86,0x62,0xc7,0x65,0xc8,0xc9,0xa1,0xf4,0xd1, + 0xe9,0x5a,0x92,0x85,0xa6,0xe7,0x93,0xe8,0xc1,0xc6,0x7a,0x64, + 0xe1,0x4a,0x6a,0xe6,0xb3,0xf1,0xd3,0xa5,0x8a,0xb2,0x9a,0xba, + 0x84,0xa4,0x63,0xe5,0xc5,0xf3,0xd2,0xc4,0x82,0xaa,0xda,0xe4, + 0xf2,0xca,0x83,0xa3,0xa2,0xc3,0xea,0xc2,0xe2,0xe3,0xff,0xff }, + { 0,2,2,1,4,1,4,1,3,3,1,0,0,0,0,140, + 0x02,0x03,0x01,0x04,0x05,0x12,0x11,0x06, + 0x13,0x07,0x08,0x14,0x22,0x09,0x21,0x00,0x23,0x15,0x31,0x32, + 0x0a,0x16,0xf0,0x24,0x33,0x41,0x42,0x19,0x17,0x25,0x18,0x51, + 0x34,0x43,0x52,0x29,0x35,0x61,0x39,0x71,0x62,0x36,0x53,0x26, + 0x38,0x1a,0x37,0x81,0x27,0x91,0x79,0x55,0x45,0x28,0x72,0x59, + 0xa1,0xb1,0x44,0x69,0x54,0x58,0xd1,0xfa,0x57,0xe1,0xf1,0xb9, + 0x49,0x47,0x63,0x6a,0xf9,0x56,0x46,0xa8,0x2a,0x4a,0x78,0x99, + 0x3a,0x75,0x74,0x86,0x65,0xc1,0x76,0xb6,0x96,0xd6,0x89,0x85, + 0xc9,0xf5,0x95,0xb4,0xc7,0xf7,0x8a,0x97,0xb8,0x73,0xb7,0xd8, + 0xd9,0x87,0xa7,0x7a,0x48,0x82,0x84,0xea,0xf4,0xa6,0xc5,0x5a, + 0x94,0xa4,0xc6,0x92,0xc3,0x68,0xb5,0xc8,0xe4,0xe5,0xe6,0xe9, + 0xa2,0xa3,0xe3,0xc2,0x66,0x67,0x93,0xaa,0xd4,0xd5,0xe7,0xf8, + 0x88,0x9a,0xd7,0x77,0xc4,0x64,0xe2,0x98,0xa5,0xca,0xda,0xe8, + 0xf3,0xf6,0xa9,0xb2,0xb3,0xf2,0xd2,0x83,0xba,0xd3,0xff,0xff }, + { 0,0,6,2,1,3,3,2,5,1,2,2,8,10,0,117, + 0x04,0x05,0x03,0x06,0x02,0x07,0x01,0x08, + 0x09,0x12,0x13,0x14,0x11,0x15,0x0a,0x16,0x17,0xf0,0x00,0x22, + 0x21,0x18,0x23,0x19,0x24,0x32,0x31,0x25,0x33,0x38,0x37,0x34, + 0x35,0x36,0x39,0x79,0x57,0x58,0x59,0x28,0x56,0x78,0x27,0x41, + 0x29,0x77,0x26,0x42,0x76,0x99,0x1a,0x55,0x98,0x97,0xf9,0x48, + 0x54,0x96,0x89,0x47,0xb7,0x49,0xfa,0x75,0x68,0xb6,0x67,0x69, + 0xb9,0xb8,0xd8,0x52,0xd7,0x88,0xb5,0x74,0x51,0x46,0xd9,0xf8, + 0x3a,0xd6,0x87,0x45,0x7a,0x95,0xd5,0xf6,0x86,0xb4,0xa9,0x94, + 0x53,0x2a,0xa8,0x43,0xf5,0xf7,0xd4,0x66,0xa7,0x5a,0x44,0x8a, + 0xc9,0xe8,0xc8,0xe7,0x9a,0x6a,0x73,0x4a,0x61,0xc7,0xf4,0xc6, + 0x65,0xe9,0x72,0xe6,0x71,0x91,0x93,0xa6,0xda,0x92,0x85,0x62, + 0xf3,0xc5,0xb2,0xa4,0x84,0xba,0x64,0xa5,0xb3,0xd2,0x81,0xe5, + 0xd3,0xaa,0xc4,0xca,0xf2,0xb1,0xe4,0xd1,0x83,0x63,0xea,0xc3, + 0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff } + }; + if (table > 2) table = 2; + init_decoder(); + make_decoder ( first_tree[table], 0); + second_decode = free_decode; + make_decoder (second_tree[table], 0); +} + +/* + Return 0 if the image starts with compressed data, + 1 if it starts with uncompressed low-order bits. + + In Canon compressed data, 0xff is always followed by 0x00. + */ +int CLASS canon_has_lowbits() +{ + uchar test[0x4000]; + int ret=1, i; + + fseek (ifp, 0, SEEK_SET); + fread (test, 1, sizeof test, ifp); + for (i=540; i < sizeof test - 1; i++) + if (test[i] == 0xff) { + if (test[i+1]) return 1; + ret=0; + } + return ret; +} + +void CLASS canon_compressed_load_raw() +{ + ushort *pixel, *prow; + int nblocks, lowbits, i, row, r, col, save, val; + unsigned irow, icol; + struct decode *decode, *dindex; + int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2]; + uchar c; + + crw_init_tables (tiff_compress); + pixel = (ushort *) calloc (raw_width*8, sizeof *pixel); + merror (pixel, "canon_compressed_load_raw()"); + lowbits = canon_has_lowbits(); + if (!lowbits) maximum = 0x3ff; + fseek (ifp, 540 + lowbits*raw_height*raw_width/4, SEEK_SET); + zero_after_ff = 1; + getbits(-1); + for (row=0; row < raw_height; row+=8) { + nblocks = MIN (8, raw_height-row) * raw_width >> 6; + for (block=0; block < nblocks; block++) { + memset (diffbuf, 0, sizeof diffbuf); + decode = first_decode; + for (i=0; i < 64; i++ ) { + for (dindex=decode; dindex->branch[0]; ) + dindex = dindex->branch[getbits(1)]; + leaf = dindex->leaf; + decode = second_decode; + if (leaf == 0 && i) break; + if (leaf == 0xff) continue; + i += leaf >> 4; + len = leaf & 15; + if (len == 0) continue; + diff = getbits(len); + if ((diff & (1 << (len-1))) == 0) + diff -= (1 << len) - 1; + if (i < 64) diffbuf[i] = diff; + } + diffbuf[0] += carry; + carry = diffbuf[0]; + for (i=0; i < 64; i++ ) { + if (pnum++ % raw_width == 0) + base[0] = base[1] = 512; + if ((pixel[(block << 6) + i] = base[i & 1] += diffbuf[i]) >> 10) + derror(); + } + } + if (lowbits) { + save = ftell(ifp); + fseek (ifp, 26 + row*raw_width/4, SEEK_SET); + for (prow=pixel, i=0; i < raw_width*2; i++) { + c = fgetc(ifp); + for (r=0; r < 8; r+=2, prow++) { + val = (*prow << 2) + ((c >> r) & 3); + if (raw_width == 2672 && val < 512) val += 2; + *prow = val; + } + } + fseek (ifp, save, SEEK_SET); + } + for (r=0; r < 8; r++) { + irow = row - top_margin + r; + if (irow >= height) continue; + for (col=0; col < raw_width; col++) { + icol = col - left_margin; + if (icol < width) + BAYER(irow,icol) = pixel[r*raw_width+col]; + else + black += pixel[r*raw_width+col]; + } + } + } + free (pixel); + if (raw_width > width) + black /= (raw_width - width) * height; +} + +/* + Not a full implementation of Lossless JPEG, just + enough to decode Canon, Kodak and Adobe DNG images. + */ +struct jhead { + int bits, high, wide, clrs, restart, vpred[4]; + struct decode *huff[4]; + ushort *row; +}; + +int CLASS ljpeg_start (struct jhead *jh, int info_only) +{ + int i, tag, len; + uchar data[0x10000], *dp; + + init_decoder(); + memset (jh, 0, sizeof *jh); + for (i=0; i < 4; i++) + jh->huff[i] = free_decode; + jh->restart = INT_MAX; + fread (data, 2, 1, ifp); + if (data[1] != 0xd8) return 0; + do { + fread (data, 2, 2, ifp); + tag = data[0] << 8 | data[1]; + len = (data[2] << 8 | data[3]) - 2; + if (tag <= 0xff00) return 0; + fread (data, 1, len, ifp); + switch (tag) { + case 0xffc0: + 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: + if (info_only) break; + for (dp = data; dp < data+len && *dp < 4; ) { + jh->huff[*dp] = free_decode; + dp = make_decoder (++dp, 0); + } + break; + case 0xffdd: + jh->restart = data[0] << 8 | data[1]; + } + } while (tag != 0xffda); + if (info_only) return 1; + jh->row = (ushort *) calloc (jh->wide*jh->clrs, 2); + merror (jh->row, " jpeg_start()"); + return zero_after_ff = 1; +} + +int CLASS ljpeg_diff (struct decode *dindex) +{ + int len, diff; + + while (dindex->branch[0]) + dindex = dindex->branch[getbits(1)]; + len = dindex->leaf; + if (len == 16 && (!dng_version || dng_version >= 0x1010000)) + return -32768; + diff = getbits(len); + if ((diff & (1 << (len-1))) == 0) + diff -= (1 << len) - 1; + return diff; +} + +void CLASS ljpeg_row (int jrow, struct jhead *jh) +{ + int col, c, diff; + ushort mark=0, *outp=jh->row; + + if (jrow * jh->wide % jh->restart == 0) { + FORC4 jh->vpred[c] = 1 << (jh->bits-1); + if (jrow) + do mark = (mark << 8) + (c = fgetc(ifp)); + while (c != EOF && mark >> 4 != 0xffd); + getbits(-1); + } + for (col=0; col < jh->wide; col++) + for (c=0; c < jh->clrs; c++) { + diff = ljpeg_diff (jh->huff[c]); + *outp = diff = col ? outp[-jh->clrs]+diff : (jh->vpred[c] += diff); + if (diff >> jh->bits) derror(); + outp++; + } +} + +void CLASS lossless_jpeg_load_raw() +{ + int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0; + struct jhead jh; + int min=INT_MAX; + + if (!ljpeg_start (&jh, 0)) return; + jwide = jh.wide * jh.clrs; + + for (jrow=0; jrow < jh.high; jrow++) { + ljpeg_row (jrow, &jh); + for (jcol=0; jcol < jwide; jcol++) { + val = jh.row[jcol]; + if (jh.bits <= 12) + val = curve[val]; + if (cr2_slice[0]) { + jidx = jrow*jwide + jcol; + i = jidx / (cr2_slice[1]*jh.high); + if ((j = i >= cr2_slice[0])) + i = cr2_slice[0]; + jidx -= i * (cr2_slice[1]*jh.high); + row = jidx / cr2_slice[1+j]; + col = jidx % cr2_slice[1+j] + i*cr2_slice[1]; + } + if (raw_width == 3984 && (col -= 2) < 0) + col += (row--,raw_width); + if ((unsigned) (row-top_margin) < height) { + if ((unsigned) (col-left_margin) < width) { + BAYER(row-top_margin,col-left_margin) = val; + if (min > val) min = val; + } else black += val; + } + if (++col >= raw_width) + col = (row++,0); + } + } + free (jh.row); + if (raw_width > width) + black /= (raw_width - width) * height; + if (!strcasecmp(make,"KODAK")) + black = min; +} + +void CLASS adobe_copy_pixel (int row, int col, ushort **rp) +{ + unsigned r, c; + + r = row -= top_margin; + c = col -= left_margin; + if (fuji_secondary && shot_select) (*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 { + if (r < height && c < width) + for (c=0; c < tiff_samples; c++) + image[row*width+col][c] = (*rp)[c] < 0x1000 ? curve[(*rp)[c]]:(*rp)[c]; + *rp += tiff_samples; + } + if (fuji_secondary && shot_select) (*rp)--; +} + +void CLASS adobe_dng_load_raw_lj() +{ + int save, twide, trow=0, tcol=0, jrow, jcol; + struct jhead jh; + ushort *rp; + + while (1) { + save = ftell(ifp); + if (tile_length < INT_MAX) + fseek (ifp, get4(), SEEK_SET); + if (!ljpeg_start (&jh, 0)) 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 (jrow, &jh); + for (rp=jh.row, jcol=0; jcol < twide; jcol++) + adobe_copy_pixel (trow+jrow, tcol+jcol, &rp); + } + fseek (ifp, save+4, SEEK_SET); + if ((tcol += twide) >= raw_width) { + tcol = 0; + trow += jh.high; + } + free (jh.row); + } +} + +void CLASS adobe_dng_load_raw_nc() +{ + ushort *pixel, *rp; + int row, col; + + pixel = (ushort *) calloc (raw_width * tiff_samples, sizeof *pixel); + merror (pixel, "adobe_dng_load_raw_nc()"); + for (row=0; row < raw_height; row++) { + if (tiff_bps == 16) + read_shorts (pixel, raw_width * tiff_samples); + else { + getbits(-1); + for (col=0; col < raw_width * tiff_samples; col++) + pixel[col] = getbits(tiff_bps); + } + for (rp=pixel, col=0; col < raw_width; col++) + adobe_copy_pixel (row, col, &rp); + } + free (pixel); +} + +void CLASS pentax_k10_load_raw() +{ + static const uchar pentax_tree[] = + { 0,2,3,1,1,1,1,1,1,2,0,0,0,0,0,0, + 3,4,2,5,1,6,0,7,8,9,10,11,12 }; + int row, col, diff; + ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2]; + + init_decoder(); + make_decoder (pentax_tree, 0); + getbits(-1); + for (row=0; row < height; row++) + for (col=0; col < raw_width; col++) { + diff = ljpeg_diff (first_decode); + if (col < 2) + hpred[col] = vpred[row & 1][col] += diff; + else + hpred[col & 1] += diff; + if (col < width) + BAYER(row,col) = hpred[col & 1]; + if (hpred[col & 1] >> 12) derror(); + } +} + +void CLASS nikon_compressed_load_raw() +{ + static const uchar nikon_tree[] = + { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, + 5,4,3,6,2,7,1,0,8,9,11,10,12 }; + int csize, row, col, diff; + ushort vpred[2][2], hpred[2], *curve; + + init_decoder(); + make_decoder (nikon_tree, 0); + + fseek (ifp, curve_offset, SEEK_SET); + read_shorts (vpred[0], 4); + csize = get2(); + curve = (ushort *) calloc (csize, sizeof *curve); + merror (curve, "nikon_compressed_load_raw()"); + read_shorts (curve, csize); + + fseek (ifp, data_offset, SEEK_SET); + getbits(-1); + for (row=0; row < height; row++) + for (col=0; col < raw_width; col++) { + diff = ljpeg_diff (first_decode); + if (col < 2) + hpred[col] = vpred[row & 1][col] += diff; + else + hpred[col & 1] += diff; + if ((unsigned) (col-left_margin) >= width) continue; + if (hpred[col & 1] >= csize) derror(); + else BAYER(row,col-left_margin) = curve[hpred[col & 1]]; + } + free (curve); +} + +void CLASS nikon_load_raw() +{ + int irow, row, col, i; + + getbits(-1); + for (irow=0; irow < height; irow++) { + row = irow; + if (make[0] == 'O' || model[0] == 'E') { + row = irow * 2 % height + irow / (height/2); + if (row == 1 && data_offset == 0) { + fseek (ifp, 0, SEEK_END); + fseek (ifp, ftell(ifp)/2, SEEK_SET); + getbits(-1); + } + } + for (col=0; col < raw_width; col++) { + i = getbits(12); + if ((unsigned) (col-left_margin) < width) + BAYER(row,col-left_margin) = i; + if (tiff_compress == 34713 && (col % 10) == 9) + if (getbits(8)) derror(); + } + } +} + +/* + Figure out if a NEF file is compressed. These fancy heuristics + are only needed for the D100, thanks to a bug in some cameras + that tags all images as "compressed". + */ +int CLASS nikon_is_compressed() +{ + uchar test[256]; + int i; + + if (tiff_compress != 34713) + return 0; + if (strcmp(model,"D100")) + return 1; + fseek (ifp, data_offset, SEEK_SET); + fread (test, 1, 256, ifp); + for (i=15; i < 256; i+=16) + if (test[i]) return 1; + return 0; +} + +/* + Returns 1 for a Coolpix 995, 0 for anything else. + */ +int CLASS nikon_e995() +{ + int i, histo[256]; + const uchar often[] = { 0x00, 0x55, 0xaa, 0xff }; + + memset (histo, 0, sizeof histo); + fseek (ifp, -2000, SEEK_END); + for (i=0; i < 2000; i++) + histo[fgetc(ifp)]++; + for (i=0; i < 4; i++) + if (histo[often[i]] < 200) + return 0; + return 1; +} + +/* + Returns 1 for a Coolpix 2100, 0 for anything else. + */ +int CLASS nikon_e2100() +{ + uchar t[12]; + int i; + + fseek (ifp, 0, SEEK_SET); + for (i=0; i < 1024; i++) { + fread (t, 1, 12, ifp); + if (((t[2] & t[4] & t[7] & t[9]) >> 4 + & t[1] & t[6] & t[8] & t[11] & 3) != 3) + return 0; + } + return 1; +} + +void CLASS nikon_3700() +{ + int bits, i; + uchar dp[24]; + static const struct { + int bits; + char make[12], model[15]; + } table[] = { + { 0x00, "PENTAX", "Optio 33WR" }, + { 0x03, "NIKON", "E3200" }, + { 0x32, "NIKON", "E3700" }, + { 0x33, "OLYMPUS", "C740UZ" } }; + + fseek (ifp, 3072, SEEK_SET); + fread (dp, 1, 24, ifp); + bits = (dp[8] & 3) << 4 | (dp[20] & 3); + for (i=0; i < sizeof table / sizeof *table; i++) + if (bits == table[i].bits) { + strcpy (make, table[i].make ); + strcpy (model, table[i].model); + } +} + +/* + Separates a Minolta DiMAGE Z2 from a Nikon E4300. + */ +int CLASS minolta_z2() +{ + int i; + char tail[424]; + + fseek (ifp, -sizeof tail, SEEK_END); + fread (tail, 1, sizeof tail, ifp); + for (i=0; i < sizeof tail; i++) + if (tail[i]) return 1; + return 0; +} + +/* Here raw_width is in bytes, not pixels. */ +void CLASS nikon_e900_load_raw() +{ + int offset=0, irow, row, col; + + for (irow=0; irow < height; irow++) { + row = irow * 2 % height; + if (row == 1) + offset = - (-offset & -4096); + fseek (ifp, offset, SEEK_SET); + offset += raw_width; + getbits(-1); + for (col=0; col < width; col++) + BAYER(row,col) = getbits(10); + } +} + +void CLASS nikon_e2100_load_raw() +{ + uchar data[4608], *dp; + ushort pixel[3072], *pix; + int row, col; + + for (row=0; row <= height; row+=2) { + if (row == height) { + fseek (ifp, 0, SEEK_END); + fseek (ifp, ftell(ifp)/2, SEEK_SET); + row = 1; + } + fread (data, 1, width*3/2, ifp); + for (dp=data, pix=pixel; pix < pixel+width; dp+=12, pix+=8) { + pix[0] = (dp[2] >> 4) + (dp[ 3] << 4); + pix[1] = (dp[2] << 8) + dp[ 1]; + pix[2] = (dp[7] >> 4) + (dp[ 0] << 4); + pix[3] = (dp[7] << 8) + dp[ 6]; + pix[4] = (dp[4] >> 4) + (dp[ 5] << 4); + pix[5] = (dp[4] << 8) + dp[11]; + pix[6] = (dp[9] >> 4) + (dp[10] << 4); + pix[7] = (dp[9] << 8) + dp[ 8]; + } + for (col=0; col < width; col++) + BAYER(row,col) = (pixel[col] & 0xfff); + } +} + +/* + The Fuji Super CCD is just a Bayer grid rotated 45 degrees. + */ +void CLASS fuji_load_raw() +{ + ushort *pixel; + int wide, row, col, r, c; + + fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR); + wide = fuji_width << !fuji_layout; + pixel = (ushort *) calloc (wide, sizeof *pixel); + merror (pixel, "fuji_load_raw()"); + for (row=0; row < raw_height; row++) { + read_shorts (pixel, wide); + fseek (ifp, 2*(raw_width - wide), SEEK_CUR); + for (col=0; col < wide; col++) { + if (fuji_layout) { + r = fuji_width - 1 - col + (row >> 1); + c = col + ((row+1) >> 1); + } else { + r = fuji_width - 1 + row - (col >> 1); + c = row + ((col+1) >> 1); + } + BAYER(r,c) = pixel[col]; + } + } + free (pixel); +} + +void CLASS jpeg_thumb (FILE *tfp); + +void CLASS ppm_thumb (FILE *tfp) +{ + char *thumb; + thumb_length = thumb_width*thumb_height*3; + thumb = (char *) malloc (thumb_length); + merror (thumb, "ppm_thumb()"); + fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height); + fread (thumb, 1, thumb_length, ifp); + fwrite (thumb, 1, thumb_length, tfp); + free (thumb); +} + +void CLASS layer_thumb (FILE *tfp) +{ + int i, c; + char *thumb, map[][4] = { "012","102" }; + + colors = thumb_misc >> 5 & 7; + thumb_length = thumb_width*thumb_height; + thumb = (char *) calloc (colors, thumb_length); + merror (thumb, "layer_thumb()"); + fprintf (tfp, "P%d\n%d %d\n255\n", + 5 + (colors >> 1), thumb_width, thumb_height); + fread (thumb, thumb_length, colors, ifp); + for (i=0; i < thumb_length; i++) + FORCC putc (thumb[i+thumb_length*(map[thumb_misc >> 8][c]-'0')], tfp); + free (thumb); +} + +void CLASS rollei_thumb (FILE *tfp) +{ + unsigned i; + ushort *thumb; + + thumb_length = thumb_width * thumb_height; + thumb = (ushort *) calloc (thumb_length, 2); + merror (thumb, "rollei_thumb()"); + fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height); + read_shorts (thumb, thumb_length); + for (i=0; i < thumb_length; i++) { + putc (thumb[i] << 3, tfp); + putc (thumb[i] >> 5 << 2, tfp); + putc (thumb[i] >> 11 << 3, tfp); + } + free (thumb); +} + +void CLASS rollei_load_raw() +{ + uchar pixel[10]; + unsigned iten=0, isix, i, buffer=0, row, col, todo[16]; + + isix = raw_width * raw_height * 5 / 8; + while (fread (pixel, 1, 10, ifp) == 10) { + for (i=0; i < 10; i+=2) { + todo[i] = iten++; + todo[i+1] = pixel[i] << 8 | pixel[i+1]; + buffer = pixel[i] >> 2 | buffer << 6; + } + for ( ; i < 16; i+=2) { + todo[i] = isix++; + todo[i+1] = buffer >> (14-i)*5; + } + for (i=0; i < 16; i+=2) { + row = todo[i] / raw_width - top_margin; + col = todo[i] % raw_width - left_margin; + if (row < height && col < width) + BAYER(row,col) = (todo[i+1] & 0x3ff); + } + } + maximum = 0x3ff; +} + +int CLASS bayer (unsigned row, unsigned col) +{ + return (row < height && col < width) ? BAYER(row,col) : 0; +} + +void CLASS phase_one_flat_field (int is_float, int nc) +{ + ushort head[8]; + unsigned wide, y, x, c, rend, cend, row, col; + float *mrow, num, mult[4]; + + read_shorts (head, 8); + wide = head[2] / head[4]; + mrow = (float *) calloc (nc*wide, sizeof *mrow); + merror (mrow, "phase_one_flat_field()"); + for (y=0; y < head[3] / head[5]; y++) { + for (x=0; x < wide; x++) + for (c=0; c < nc; c+=2) { + num = is_float ? getreal(11) : get2()/32768.0; + if (y==0) mrow[c*wide+x] = num; + else mrow[(c+1)*wide+x] = (num - mrow[c*wide+x]) / head[5]; + } + if (y==0) continue; + rend = head[1]-top_margin + y*head[5]; + for (row = rend-head[5]; row < height && row < rend; row++) { + for (x=1; x < wide; x++) { + for (c=0; c < nc; c+=2) { + mult[c] = mrow[c*wide+x-1]; + mult[c+1] = (mrow[c*wide+x] - mult[c]) / head[4]; + } + cend = head[0]-left_margin + x*head[4]; + for (col = cend-head[4]; col < width && col < cend; col++) { + c = nc > 2 ? FC(row,col) : 0; + if (!(c & 1)) { + c = BAYER(row,col) * mult[c]; + BAYER(row,col) = LIM(c,0,65535); + } + for (c=0; c < nc; c+=2) + mult[c] += mult[c+1]; + } + } + for (x=0; x < wide; x++) + for (c=0; c < nc; c+=2) + mrow[c*wide+x] += mrow[(c+1)*wide+x]; + } + } + free (mrow); +} + +void CLASS phase_one_correct() +{ + unsigned entries, tag, data, save, col, row, type; + int len, i, j, k, cip, val[4], dev[4], sum, max; + int head[9], diff, mindiff=INT_MAX, off_412=0; + static const signed char dir[12][2] = + { {-1,-1}, {-1,1}, {1,-1}, {1,1}, {-2,0}, {0,-2}, {0,2}, {2,0}, + {-2,-2}, {-2,2}, {2,-2}, {2,2} }; + float poly[8], num, cfrac, frac, mult[2], *yval[2]; + ushort curve[0x10000], *xval[2]; + + if (half_size || !meta_length) return; + if (verbose) fprintf (stderr,_("Phase One correction...\n")); + fseek (ifp, meta_offset, SEEK_SET); + order = get2(); + fseek (ifp, 6, SEEK_CUR); + fseek (ifp, meta_offset+get4(), SEEK_SET); + entries = get4(); get4(); + while (entries--) { + tag = get4(); + len = get4(); + data = get4(); + save = ftell(ifp); + fseek (ifp, meta_offset+data, SEEK_SET); + if (tag == 0x419) { /* Polynomial curve */ + for (get4(), i=0; i < 8; i++) + poly[i] = getreal(11); + poly[3] += (ph1.tag_210 - poly[7]) * poly[6] + 1; + for (i=0; i < 0x10000; i++) { + num = (poly[5]*i + poly[3])*i + poly[1]; + curve[i] = LIM(num,0,65535); + } goto apply; /* apply to right half */ + } else if (tag == 0x41a) { /* Polynomial curve */ + for (i=0; i < 4; i++) + poly[i] = getreal(11); + for (i=0; i < 0x10000; i++) { + for (num=0, j=4; j--; ) + num = num * i + poly[j]; + curve[i] = LIM(num+i,0,65535); + } apply: /* apply to whole image */ + for (row=0; row < height; row++) + for (col = (tag & 1)*ph1.split_col; col < width; col++) + BAYER(row,col) = curve[BAYER(row,col)]; + } else if (tag == 0x400) { /* Sensor defects */ + while ((len -= 8) >= 0) { + col = get2() - left_margin; + row = get2() - top_margin; + type = get2(); get2(); + if (col >= width) continue; + if (type == 131) /* Bad column */ + for (row=0; row < height; row++) + if (FC(row,col) == 1) { + for (sum=i=0; i < 4; i++) + sum += val[i] = bayer (row+dir[i][0], col+dir[i][1]); + for (max=i=0; i < 4; i++) { + dev[i] = abs((val[i] << 2) - sum); + if (dev[max] < dev[i]) max = i; + } + BAYER(row,col) = (sum - val[max])/3.0 + 0.5; + } else { + for (sum=0, i=8; i < 12; i++) + sum += bayer (row+dir[i][0], col+dir[i][1]); + BAYER(row,col) = 0.5 + sum * 0.0732233 + + (bayer(row,col-2) + bayer(row,col+2)) * 0.3535534; + } + else if (type == 129) { /* Bad pixel */ + if (row >= height) continue; + j = (FC(row,col) != 1) * 4; + for (sum=0, i=j; i < j+8; i++) + sum += bayer (row+dir[i][0], col+dir[i][1]); + BAYER(row,col) = (sum + 4) >> 3; + } + } + } else if (tag == 0x401) { /* All-color flat fields */ + phase_one_flat_field (1, 2); + } else if (tag == 0x416 || tag == 0x410) { + phase_one_flat_field (0, 2); + } else if (tag == 0x40b) { /* Red+blue flat field */ + phase_one_flat_field (0, 4); + } else if (tag == 0x412) { + fseek (ifp, 36, SEEK_CUR); + diff = abs (get2() - ph1.tag_21a); + if (mindiff > diff) { + mindiff = diff; + off_412 = ftell(ifp) - 38; + } + } + fseek (ifp, save, SEEK_SET); + } + if (off_412) { + fseek (ifp, off_412, SEEK_SET); + for (i=0; i < 9; i++) head[i] = get4() & 0x7fff; + yval[0] = (float *) calloc (head[1]*head[3] + head[2]*head[4], 6); + merror (yval[0], "phase_one_correct()"); + yval[1] = (float *) (yval[0] + head[1]*head[3]); + xval[0] = (ushort *) (yval[1] + head[2]*head[4]); + xval[1] = (ushort *) (xval[0] + head[1]*head[3]); + get2(); + for (i=0; i < 2; i++) + for (j=0; j < head[i+1]*head[i+3]; j++) + yval[i][j] = getreal(11); + for (i=0; i < 2; i++) + for (j=0; j < head[i+1]*head[i+3]; j++) + xval[i][j] = get2(); + for (row=0; row < height; row++) + for (col=0; col < width; col++) { + cfrac = (float) col * head[3] / raw_width; + cfrac -= cip = cfrac; + num = BAYER(row,col) * 0.5; + for (i=cip; i < cip+2; i++) { + for (k=j=0; j < head[1]; j++) + if (num < xval[0][k = head[1]*i+j]) break; + frac = (j == 0 || j == head[1]) ? 0 : + (xval[0][k] - num) / (xval[0][k] - xval[0][k-1]); + mult[i-cip] = yval[0][k-1] * frac + yval[0][k] * (1-frac); + } + i = ((mult[0] * (1-cfrac) + mult[1] * cfrac) + * (row + top_margin) + num) * 2; + BAYER(row,col) = LIM(i,0,65535); + } + free (yval[0]); + } +} + +void CLASS phase_one_load_raw() +{ + int row, col, a, b; + ushort *pixel, akey, bkey, mask; + + fseek (ifp, ph1.key_off, SEEK_SET); + akey = get2(); + bkey = get2(); + mask = ph1.format == 1 ? 0x5555:0x1354; + fseek (ifp, data_offset + top_margin*raw_width*2, SEEK_SET); + pixel = (ushort *) calloc (raw_width, sizeof *pixel); + merror (pixel, "phase_one_load_raw()"); + for (row=0; row < height; row++) { + read_shorts (pixel, raw_width); + for (col=0; col < raw_width; col+=2) { + a = pixel[col+0] ^ akey; + b = pixel[col+1] ^ bkey; + pixel[col+0] = (a & mask) | (b & ~mask); + pixel[col+1] = (b & mask) | (a & ~mask); + } + for (col=0; col < width; col++) + BAYER(row,col) = pixel[col+left_margin]; + } + free (pixel); + phase_one_correct(); +} + +unsigned CLASS ph1_bits (int nbits) +{ + static UINT64 bitbuf=0; + static int vbits=0; + + if (nbits == 0) + return bitbuf = vbits = 0; + if (vbits < nbits) { + bitbuf = bitbuf << 32 | get4(); + vbits += 32; + } + vbits -= nbits; + return bitbuf << (64 - nbits - vbits) >> (64 - nbits); +} + +void CLASS phase_one_load_raw_c() +{ + static const int length[] = { 8,7,6,9,11,10,5,12,14,13 }; + int *offset, len[2], pred[2], row, col, i, j; + ushort *pixel; + short (*black)[2]; + + pixel = (ushort *) calloc (raw_width + raw_height*4, 2); + merror (pixel, "phase_one_load_raw_c()"); + offset = (int *) (pixel + raw_width); + fseek (ifp, strip_offset, SEEK_SET); + for (row=0; row < raw_height; row++) + offset[row] = get4(); + black = (short (*)[2]) offset + raw_height; + fseek (ifp, ph1.black_off, SEEK_SET); + if (ph1.black_off) + read_shorts ((ushort *) black[0], raw_height*2); + for (i=0; i < 256; i++) + curve[i] = i*i / 3.969 + 0.5; + for (row=0; row < raw_height; row++) { + fseek (ifp, data_offset + offset[row], SEEK_SET); + ph1_bits(0); + pred[0] = pred[1] = 0; + for (col=0; col < raw_width; col++) { + if (col >= (raw_width & -8)) + len[0] = len[1] = 14; + else if ((col & 7) == 0) + for (i=0; i < 2; i++) { + for (j=0; j < 5 && !ph1_bits(1); j++); + if (j--) len[i] = length[j*2 + ph1_bits(1)]; + } + if ((i = len[col & 1]) == 14) + pixel[col] = pred[col & 1] = ph1_bits(16); + else + pixel[col] = pred[col & 1] += ph1_bits(i) + 1 - (1 << (i - 1)); + if (pred[col & 1] >> 16) derror(); + if (ph1.format == 5 && pixel[col] < 256) + pixel[col] = curve[pixel[col]]; + } + if ((unsigned) (row-top_margin) < height) + for (col=0; col < width; col++) { + i = (pixel[col+left_margin] << 2) + - ph1.black + black[row][col >= ph1.split_col]; + if (i > 0) BAYER(row-top_margin,col) = i; + } + } + free (pixel); + phase_one_correct(); + maximum = 0xfffc - ph1.black; +} + +void CLASS leaf_hdr_load_raw() +{ + ushort *pixel; + unsigned tile=0, r, c, row, col; + + pixel = (ushort *) calloc (raw_width, sizeof *pixel); + merror (pixel, "leaf_hdr_load_raw()"); + for (c=0; c < tiff_samples; c++) { + for (r=0; r < raw_height; r++) { + if (r % tile_length == 0) { + fseek (ifp, data_offset + 4*tile++, SEEK_SET); + fseek (ifp, get4() + 2*left_margin, SEEK_SET); + } + if (filters && c != shot_select) continue; + read_shorts (pixel, raw_width); + if ((row = r - top_margin) >= height) continue; + for (col=0; col < width; col++) + if (filters) BAYER(row,col) = pixel[col]; + else image[row*width+col][c] = pixel[col]; + } + } + free (pixel); + if (!filters) { + maximum = 0xffff; + raw_color = 1; + } +} + +void CLASS unpacked_load_raw(); + +void CLASS sinar_4shot_load_raw() +{ + ushort *pixel; + unsigned shot, row, col, r, c; + + if ((shot = shot_select) || half_size) { + if (shot) shot--; + if (shot > 3) shot = 3; + fseek (ifp, data_offset + shot*4, SEEK_SET); + fseek (ifp, get4(), SEEK_SET); + unpacked_load_raw(); + return; + } + free (image); + image = (ushort (*)[4]) + calloc ((iheight=height)*(iwidth=width), sizeof *image); + merror (image, "sinar_4shot_load_raw()"); + pixel = (ushort *) calloc (raw_width, sizeof *pixel); + merror (pixel, "sinar_4shot_load_raw()"); + for (shot=0; shot < 4; shot++) { + fseek (ifp, data_offset + shot*4, SEEK_SET); + fseek (ifp, get4(), SEEK_SET); + for (row=0; row < raw_height; row++) { + read_shorts (pixel, raw_width); + if ((r = row-top_margin - (shot >> 1 & 1)) >= height) continue; + for (col=0; col < raw_width; col++) { + if ((c = col-left_margin - (shot & 1)) >= width) continue; + image[r*width+c][FC(row,col)] = pixel[col]; + } + } + } + free (pixel); + shrink = filters = 0; +} + +void CLASS imacon_full_load_raw() +{ + int row, col; + + for (row=0; row < height; row++) + for (col=0; col < width; col++) + read_shorts (image[row*width+col], 3); +} + +void CLASS packed_12_load_raw() +{ + int row, col; + + if (raw_width * 2 < width * 3) + raw_width = raw_width * 3 / 2; /* Convert raw_width to bytes */ + getbits(-1); + for (row=0; row < height; row++) { + for (col=0; col < left_margin; col++) + getbits(12); + for (col=0; col < width; col++) + BAYER(row,col) = getbits(12); + for (col = (width+left_margin)*3/2; col < raw_width; col++) + if (getbits(8) && raw_width-col < 35 && width != 3896) derror(); + } +} + +void CLASS unpacked_load_raw() +{ + ushort *pixel; + int row, col, bits=0; + + while (1 << ++bits < maximum); + fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR); + pixel = (ushort *) calloc (width, sizeof *pixel); + merror (pixel, "unpacked_load_raw()"); + for (row=0; row < height; row++) { + read_shorts (pixel, width); + fseek (ifp, 2*(raw_width - width), SEEK_CUR); + for (col=0; col < width; col++) + if ((BAYER2(row,col) = pixel[col]) >> bits) derror(); + } + free (pixel); +} + +void CLASS olympus_e300_load_raw() +{ + uchar *data, *dp; + ushort *pixel, *pix; + int dwide, row, col; + + dwide = raw_width * 16 / 10; + fseek (ifp, dwide*top_margin, SEEK_CUR); + data = (uchar *) malloc (dwide + raw_width*2); + merror (data, "olympus_e300_load_raw()"); + pixel = (ushort *) (data + dwide); + for (row=0; row < height; row++) { + if (fread (data, 1, dwide, ifp) < dwide) derror(); + for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=3, pix+=2) { + if (((dp-data) & 15) == 15) + if (*dp++ && pix < pixel+width+left_margin) derror(); + pix[0] = dp[1] << 8 | dp[0]; + pix[1] = dp[2] << 4 | dp[1] >> 4; + } + for (col=0; col < width; col++) + BAYER(row,col) = (pixel[col+left_margin] & 0xfff); + } + free (data); + if (!strcmp(make,"OLYMPUS")) { + maximum = 0xfff; + black >>= 4; + } +} + +void CLASS olympus_e410_load_raw() +{ + int row, col, nbits, sign, low, high, i, w, n, nw; + int acarry[2][3], *carry, pred, diff; + + fseek (ifp, 7, SEEK_CUR); + getbits(-1); + for (row=0; row < height; row++) { + memset (acarry, 0, sizeof acarry); + for (col=0; col < width; col++) { + carry = acarry[col & 1]; + i = 2 * (carry[2] < 3); + for (nbits=2+i; (ushort) carry[0] >> (nbits+i); nbits++); + sign = getbits(1) * -1; + low = getbits(2); + for (high=0; high < 12; high++) + if (getbits(1)) break; + if (high == 12) + high = getbits(16-nbits) >> 1; + carry[0] = (high << nbits) | getbits(nbits); + diff = (carry[0] ^ sign) + carry[1]; + carry[1] = (diff*3 + carry[1]) >> 5; + carry[2] = carry[0] > 16 ? 0 : carry[2]+1; + if (row < 2 && col < 2) pred = 0; + else if (row < 2) pred = BAYER(row,col-2); + else if (col < 2) pred = BAYER(row-2,col); + else { + w = BAYER(row,col-2); + n = BAYER(row-2,col); + nw = BAYER(row-2,col-2); + if ((w < nw && nw < n) || (n < nw && nw < w)) { + if (ABS(w-nw) > 32 || ABS(n-nw) > 32) + pred = w + n - nw; + else pred = (w + n) >> 1; + } else pred = ABS(w-nw) > ABS(n-nw) ? w : n; + } + if ((BAYER(row,col) = pred + ((diff << 2) | low)) >> 12) derror(); + } + } +} + +void CLASS olympus_cseries_load_raw() +{ + int irow, row, col; + + for (irow=0; irow < height; irow++) { + row = irow * 2 % height + irow / (height/2); + if (row < 2) { + fseek (ifp, data_offset - row*(-width*height*3/4 & -2048), SEEK_SET); + getbits(-1); + } + for (col=0; col < width; col++) + BAYER(row,col) = getbits(12); + } + black >>= 4; +} + +void CLASS minolta_rd175_load_raw() +{ + uchar pixel[768]; + unsigned irow, box, row, col; + + for (irow=0; irow < 1481; irow++) { + if (fread (pixel, 1, 768, ifp) < 768) derror(); + box = irow / 82; + row = irow % 82 * 12 + ((box < 12) ? box | 1 : (box-12)*2); + switch (irow) { + case 1477: case 1479: continue; + case 1476: row = 984; break; + case 1480: row = 985; break; + case 1478: row = 985; box = 1; + } + if ((box < 12) && (box & 1)) { + for (col=0; col < 1533; col++, row ^= 1) + if (col != 1) BAYER(row,col) = (col+1) & 2 ? + pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1; + BAYER(row,1) = pixel[1] << 1; + BAYER(row,1533) = pixel[765] << 1; + } else + for (col=row & 1; col < 1534; col+=2) + BAYER(row,col) = pixel[col/2] << 1; + } + maximum = 0xff << 1; +} + +void CLASS eight_bit_load_raw() +{ + uchar *pixel; + int row, col; + + pixel = (uchar *) calloc (raw_width, sizeof *pixel); + merror (pixel, "eight_bit_load_raw()"); + for (row=0; row < height; row++) { + if (fread (pixel, 1, raw_width, ifp) < raw_width) derror(); + for (col=0; col < width; col++) + BAYER(row,col) = pixel[col]; + } + free (pixel); + maximum = 0xff; +} + +void CLASS casio_qv5700_load_raw() +{ + uchar data[3232], *dp; + ushort pixel[2576], *pix; + int row, col; + + for (row=0; row < height; row++) { + fread (data, 1, 3232, ifp); + for (dp=data, pix=pixel; dp < data+3220; dp+=5, pix+=4) { + pix[0] = (dp[0] << 2) + (dp[1] >> 6); + pix[1] = (dp[1] << 4) + (dp[2] >> 4); + pix[2] = (dp[2] << 6) + (dp[3] >> 2); + pix[3] = (dp[3] << 8) + (dp[4] ); + } + for (col=0; col < width; col++) + BAYER(row,col) = (pixel[col] & 0x3ff); + } + maximum = 0x3fc; +} + +void CLASS quicktake_100_load_raw() +{ + uchar pixel[484][644]; + static const short gstep[16] = + { -89,-60,-44,-32,-22,-15,-8,-2,2,8,15,22,32,44,60,89 }; + static const short rstep[6][4] = + { { -3,-1,1,3 }, { -5,-1,1,5 }, { -8,-2,2,8 }, + { -13,-3,3,13 }, { -19,-4,4,19 }, { -28,-6,6,28 } }; + static const short curve[256] = + { 0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27, + 28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,53, + 54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78, + 79,80,81,82,83,84,86,88,90,92,94,97,99,101,103,105,107,110,112,114,116, + 118,120,123,125,127,129,131,134,136,138,140,142,144,147,149,151,153,155, + 158,160,162,164,166,168,171,173,175,177,179,181,184,186,188,190,192,195, + 197,199,201,203,205,208,210,212,214,216,218,221,223,226,230,235,239,244, + 248,252,257,261,265,270,274,278,283,287,291,296,300,305,309,313,318,322, + 326,331,335,339,344,348,352,357,361,365,370,374,379,383,387,392,396,400, + 405,409,413,418,422,426,431,435,440,444,448,453,457,461,466,470,474,479, + 483,487,492,496,500,508,519,531,542,553,564,575,587,598,609,620,631,643, + 654,665,676,687,698,710,721,732,743,754,766,777,788,799,810,822,833,844, + 855,866,878,889,900,911,922,933,945,956,967,978,989,1001,1012,1023 }; + int rb, row, col, sharp, val=0; + + getbits(-1); + memset (pixel, 0x80, sizeof pixel); + for (row=2; row < height+2; row++) { + for (col=2+(row & 1); col < width+2; col+=2) { + val = ((pixel[row-1][col-1] + 2*pixel[row-1][col+1] + + pixel[row][col-2]) >> 2) + gstep[getbits(4)]; + pixel[row][col] = val = LIM(val,0,255); + if (col < 4) + pixel[row][col-2] = pixel[row+1][~row & 1] = val; + if (row == 2) + pixel[row-1][col+1] = pixel[row-1][col+3] = val; + } + pixel[row][col] = val; + } + for (rb=0; rb < 2; rb++) + for (row=2+rb; row < height+2; row+=2) + for (col=3-(row & 1); col < width+2; col+=2) { + if (row < 4 || col < 4) sharp = 2; + else { + val = ABS(pixel[row-2][col] - pixel[row][col-2]) + + ABS(pixel[row-2][col] - pixel[row-2][col-2]) + + ABS(pixel[row][col-2] - pixel[row-2][col-2]); + sharp = val < 4 ? 0 : val < 8 ? 1 : val < 16 ? 2 : + val < 32 ? 3 : val < 48 ? 4 : 5; + } + val = ((pixel[row-2][col] + pixel[row][col-2]) >> 1) + + rstep[sharp][getbits(2)]; + pixel[row][col] = val = LIM(val,0,255); + if (row < 4) pixel[row-2][col+2] = val; + if (col < 4) pixel[row+2][col-2] = val; + } + for (row=2; row < height+2; row++) + for (col=3-(row & 1); col < width+2; col+=2) { + val = ((pixel[row][col-1] + (pixel[row][col] << 2) + + pixel[row][col+1]) >> 1) - 0x100; + pixel[row][col] = LIM(val,0,255); + } + for (row=0; row < height; row++) + for (col=0; col < width; col++) + BAYER(row,col) = curve[pixel[row+2][col+2]]; + maximum = 0x3ff; +} + +const int * CLASS make_decoder_int (const int *source, int level) +{ + struct decode *cur; + + cur = free_decode++; + if (level < source[0]) { + cur->branch[0] = free_decode; + source = make_decoder_int (source, level+1); + cur->branch[1] = free_decode; + source = make_decoder_int (source, level+1); + } else { + cur->leaf = source[1]; + source += 2; + } + return source; +} + +int CLASS radc_token (int tree) +{ + int t; + static struct decode *dstart[18], *dindex; + static const int *s, source[] = { + 1,1, 2,3, 3,4, 4,2, 5,7, 6,5, 7,6, 7,8, + 1,0, 2,1, 3,3, 4,4, 5,2, 6,7, 7,6, 8,5, 8,8, + 2,1, 2,3, 3,0, 3,2, 3,4, 4,6, 5,5, 6,7, 6,8, + 2,0, 2,1, 2,3, 3,2, 4,4, 5,6, 6,7, 7,5, 7,8, + 2,1, 2,4, 3,0, 3,2, 3,3, 4,7, 5,5, 6,6, 6,8, + 2,3, 3,1, 3,2, 3,4, 3,5, 3,6, 4,7, 5,0, 5,8, + 2,3, 2,6, 3,0, 3,1, 4,4, 4,5, 4,7, 5,2, 5,8, + 2,4, 2,7, 3,3, 3,6, 4,1, 4,2, 4,5, 5,0, 5,8, + 2,6, 3,1, 3,3, 3,5, 3,7, 3,8, 4,0, 5,2, 5,4, + 2,0, 2,1, 3,2, 3,3, 4,4, 4,5, 5,6, 5,7, 4,8, + 1,0, 2,2, 2,-2, + 1,-3, 1,3, + 2,-17, 2,-5, 2,5, 2,17, + 2,-7, 2,2, 2,9, 2,18, + 2,-18, 2,-9, 2,-2, 2,7, + 2,-28, 2,28, 3,-49, 3,-9, 3,9, 4,49, 5,-79, 5,79, + 2,-1, 2,13, 2,26, 3,39, 4,-16, 5,55, 6,-37, 6,76, + 2,-26, 2,-13, 2,1, 3,-39, 4,16, 5,-55, 6,-76, 6,37 + }; + + if (free_decode == first_decode) + for (s=source, t=0; t < 18; t++) { + dstart[t] = free_decode; + s = make_decoder_int (s, 0); + } + if (tree == 18) { + if (kodak_cbpp == 243) + return (getbits(6) << 2) + 2; /* most DC50 photos */ + else + return (getbits(5) << 3) + 4; /* DC40, Fotoman Pixtura */ + } + for (dindex = dstart[tree]; dindex->branch[0]; ) + dindex = dindex->branch[getbits(1)]; + return dindex->leaf; +} + +#define FORYX for (y=1; y < 3; y++) for (x=co... [truncated message content] |
From: <gl...@us...> - 2007-09-01 14:36:19
|
Revision: 287 http://hdrflow.svn.sourceforge.net/hdrflow/?rev=287&view=rev Author: glslang Date: 2007-09-01 07:36:14 -0700 (Sat, 01 Sep 2007) Log Message: ----------- + raw importer plugin functional Modified Paths: -------------- trunk/lib/extras/src/raw/Makefile.am trunk/lib/extras/src/raw/dcraw.c trunk/lib/extras/src/raw/raw.cpp trunk/lib/extras/src/raw/raw_vc8.vcproj Added Paths: ----------- trunk/lib/extras/src/raw/raw_plugin.opl Modified: trunk/lib/extras/src/raw/Makefile.am =================================================================== --- trunk/lib/extras/src/raw/Makefile.am 2007-08-30 22:38:33 UTC (rev 286) +++ trunk/lib/extras/src/raw/Makefile.am 2007-09-01 14:36:14 UTC (rev 287) @@ -13,10 +13,17 @@ libhdrflow_extras_raw_la_CXXFLAGS = \ $(BOOST_INCLUDE_PATH) \ - -I$(top_builddir)/../openlibraries/src \ - $(OFX_INCLUDE_PATH) + -I$(top_builddir)/../openlibraries/src libhdrflow_extras_raw_la_CFLAGS = \ -DNO_JPEG \ -DNO_LCMS +libhdrflow_extras_raw_la_LIBADD = \ + $(top_builddir)/../openlibraries/src/openpluginlib/pl/libopenpluginlib_pl.la \ + $(top_builddir)/../openlibraries/src/openimagelib/il/libopenimagelib_il.la + +libhdrflow_extras_raw_ladir = $(EXTRAS_PLUGINPATH) +libhdrflow_extras_raw_la_DATA = raw_plugin.opl + +nobase_dist_libhdrflow_extras_raw_la_DATA = raw_plugin.opl Modified: trunk/lib/extras/src/raw/dcraw.c =================================================================== --- trunk/lib/extras/src/raw/dcraw.c 2007-08-30 22:38:33 UTC (rev 286) +++ trunk/lib/extras/src/raw/dcraw.c 2007-09-01 14:36:14 UTC (rev 287) @@ -7395,7 +7395,7 @@ free (ppm); } -int CLASS main_ (int argc, char **argv) +int CLASS dcraw_ (int argc, char **argv) { int arg, status=0, user_flip=-1, user_black=-1, user_qual=-1; int timestamp_only=0, thumbnail_only=0, identify_only=0; Modified: trunk/lib/extras/src/raw/raw.cpp =================================================================== --- trunk/lib/extras/src/raw/raw.cpp 2007-08-30 22:38:33 UTC (rev 286) +++ trunk/lib/extras/src/raw/raw.cpp 2007-09-01 14:36:14 UTC (rev 287) @@ -11,7 +11,9 @@ #include <windows.h> #endif +#include <openpluginlib/pl/utf8_utils.hpp> #include <openpluginlib/pl/pcos/property_container.hpp> + #include <openimagelib/il/openimagelib_plugin.hpp> namespace pl = olib::openpluginlib; @@ -20,13 +22,61 @@ namespace hdrflow { namespace extras { namespace raw { -extern "C" int main_( int argc, char** argv ); +extern "C" int dcraw_( int argc, char** argv ); namespace { - bool dcraw( pcos::property_container properties ) + struct query_traits { - return true; + query_traits( const pl::wstring& filename ) + : filename_( filename ) + { } + + pl::wstring libname( ) const + { return L"openimagelib"; } + + pl::wstring to_match( ) const + { return filename_; } + + pl::wstring type( ) const + { return L""; } + + int merit( ) const + { return 0; } + + pl::wstring filename_; + }; + + il::image_type_ptr dcraw( pcos::property_container properties ) // TODO: change to ptr when pcos moves to proper copy semantics + { + pl::string tiff = properties.get_property_with_key( pcos::key::from_string( "tiff_output" ) ).value<pl::string>( ); + pl::string path = properties.get_property_with_key( pcos::key::from_string( "path" ) ).value<pl::string>( ); + + std::vector<const char*> args; + args.push_back( "dcraw" ); + args.push_back( tiff.c_str( ) ); + args.push_back( path.c_str( ) ); + + if( dcraw_( static_cast<int>( args.size( ) ), const_cast<char**>( &args[ 0 ] ) ) ) + return il::image_type_ptr( ); + + pl::string pathname( path.begin( ), path.find_last_of( "." ) ); + pathname += ".tiff"; + + typedef pl::discovery<query_traits> discovery; + + discovery plugins( query_traits( pl::to_wstring( pathname ) ) ); + if( plugins.empty( ) ) + return il::image_type_ptr( ); + + for( discovery::const_iterator i = plugins.begin( ); i != plugins.end( ); ++i ) + { + il::openimagelib_plugin_ptr plug = boost::shared_dynamic_cast<il::openimagelib_plugin>( i->create_plugin( "" ) ); + if( plug ) + return plug->load( pl::make_stream( pathname, std::ios::in ) ); + } + + return il::image_type_ptr( ); } } @@ -54,15 +104,48 @@ , which_raw_( pcos::key::from_string( "which_raw" ) ) , sRGB_output_( pcos::key::from_string( "sRGB_output" ) ) , tiff_output_( pcos::key::from_string( "tiff_output" ) ) - { } + , path_( pcos::key::from_string( "path" ) ) + { + set_raw_properties( ); + } - virtual il::image_type_ptr load( pl::stream_ptr ) - { return il::image_type_ptr( ); } + virtual il::image_type_ptr load( pl::stream_ptr stream ) + { + raw_props_.get_property_with_key( pcos::key::from_string( "path" ) ) = stream->path( ); + return dcraw( raw_props_ ); + } virtual bool store( pl::stream_ptr, il::image_type_ptr ) { return false; } private: + void set_raw_properties( ) + { + raw_props_.append( verbose_ ); + raw_props_.append( thumbnail_ ); + raw_props_.append( camera_white_balance_ ); + raw_props_.append( average_white_balance_ ); + raw_props_.append( average_grey_box_white_balance_ ); + raw_props_.append( user_white_balance_ ); + raw_props_.append( brightness_ ); + raw_props_.append( wavelet_denoising_threshold_ ); + raw_props_.append( black_point_ ); + raw_props_.append( highlight_mode_ ); + raw_props_.append( flip_image_ ); + raw_props_.append( output_colorspace_ ); + raw_props_.append( document_mode_ ); + raw_props_.append( stretch_rotate_ ); + raw_props_.append( interpolation_quality_ ); + raw_props_.append( half_size_ ); + raw_props_.append( four_colour_interpolation_ ); + raw_props_.append( which_raw_ ); + raw_props_.append( sRGB_output_ ); + raw_props_.append( tiff_output_ = pl::string( "-T" ) ); + raw_props_.append( path_ = pl::string( "" ) ); + } + +private: + pcos::property_container raw_props_; pcos::property verbose_; pcos::property thumbnail_; pcos::property camera_white_balance_; @@ -83,29 +166,36 @@ pcos::property which_raw_; pcos::property sRGB_output_; pcos::property tiff_output_; + pcos::property path_; }; } } } +#ifdef WIN32 +# define RAW_DECLSPEC __declspec( dllexport ) +#else +# define RAW_DECLSPEC __attribute__( ( visibility( "default" ) ) ) +#endif + extern "C" { - bool openplugin_init( void ) + RAW_DECLSPEC bool openplugin_init( void ) { return true; } - bool openplugin_uninit( void ) + RAW_DECLSPEC bool openplugin_uninit( void ) { return true; } - bool openplugin_create_plugin( const char*, pl::openplugin** plug ) + RAW_DECLSPEC bool openplugin_create_plugin( const char*, pl::openplugin** plug ) { *plug = new hdrflow::extras::raw::raw_plugin; return true; } - void openplugin_destroy_plugin( pl::openplugin* plug ) + RAW_DECLSPEC void openplugin_destroy_plugin( pl::openplugin* plug ) { delete static_cast<hdrflow::extras::raw::raw_plugin*>( plug ); } Added: trunk/lib/extras/src/raw/raw_plugin.opl =================================================================== --- trunk/lib/extras/src/raw/raw_plugin.opl (rev 0) +++ trunk/lib/extras/src/raw/raw_plugin.opl 2007-09-01 14:36:14 UTC (rev 287) @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<openlibraries version="1.0"> + <!-- plugins go here --> + <openimagelib name="oil" version="0.2.0"> + <plugin name="HDRFlow Raw plugin" type="input" in_filter="*.raw *.cr2" extension='".*\.raw", ".*\.cr2"' merit="0" filename='"libhdrflow_raw.so", "libhdrflow_raw.dylib", "hdrflow_raw-vc80-d-0_1_0.dll", "hdrflow_raw-vc80-r-0_1_0.dll"'/> + </openimagelib> +</openlibraries> Property changes on: trunk/lib/extras/src/raw/raw_plugin.opl ___________________________________________________________________ Name: svn:eol-style + native Modified: trunk/lib/extras/src/raw/raw_vc8.vcproj =================================================================== --- trunk/lib/extras/src/raw/raw_vc8.vcproj 2007-08-30 22:38:33 UTC (rev 286) +++ trunk/lib/extras/src/raw/raw_vc8.vcproj 2007-09-01 14:36:14 UTC (rev 287) @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=""$(SolutionDir)\..\openlibraries\src";"C:\Boost\include\boost-1_34"" - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;RAW_EXPORTS;HAVE_FLEX_STRING;NO_JPEG;NO_LCMS" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;RAW_EXPORTS;HAVE_FLEX_STRING;_CRT_SECURE_NO_WARNINGS;NO_JPEG;NO_LCMS" MinimalRebuild="true" ExceptionHandling="2" BasicRuntimeChecks="3" @@ -51,6 +51,7 @@ WarningLevel="4" Detect64BitPortabilityProblems="true" DebugInformationFormat="4" + DisableSpecificWarnings="4503" /> <Tool Name="VCManagedResourceCompilerTool" @@ -124,7 +125,7 @@ <Tool Name="VCCLCompilerTool" AdditionalIncludeDirectories=""$(SolutionDir)\..\openlibraries\src";"C:\Boost\include\boost-1_34"" - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;RAW_EXPORTS;HAVE_FLEX_STRING;NO_JPEG;NO_LCMS" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;RAW_EXPORTS;HAVE_FLEX_STRING;_CRT_SECURE_NO_WARNINGS;NO_JPEG;NO_LCMS" ExceptionHandling="2" RuntimeLibrary="2" BufferSecurityCheck="false" @@ -134,6 +135,7 @@ WarningLevel="4" Detect64BitPortabilityProblems="true" DebugInformationFormat="3" + DisableSpecificWarnings="4503" /> <Tool Name="VCManagedResourceCompilerTool" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <gl...@us...> - 2007-09-05 22:20:18
|
Revision: 296 http://hdrflow.svn.sourceforge.net/hdrflow/?rev=296&view=rev Author: glslang Date: 2007-09-05 15:20:13 -0700 (Wed, 05 Sep 2007) Log Message: ----------- + output to temp directory (untested) Modified Paths: -------------- trunk/lib/extras/src/raw/dcraw.c trunk/lib/extras/src/raw/raw.cpp Modified: trunk/lib/extras/src/raw/dcraw.c =================================================================== --- trunk/lib/extras/src/raw/dcraw.c 2007-09-02 22:35:27 UTC (rev 295) +++ trunk/lib/extras/src/raw/dcraw.c 2007-09-05 22:20:13 UTC (rev 296) @@ -7407,6 +7407,8 @@ #ifndef NO_LCMS char *cam_profile=0, *out_profile=0; #endif + char tempdir[ BUFSIZ ]; + DWORD dw; #ifndef LOCALTIME putenv ("TZ=UTC"); @@ -7694,12 +7696,20 @@ write_ext = ".tiff"; else write_ext = ".pgm\0.ppm\0.ppm\0.pam" + colors*5-5; - ofname = (char *) malloc (strlen(ifname) + 16); +#ifdef WIN32 + dw = GetTempPath(BUFSIZ, tempdir); + if( dw > BUFSIZ || dw == 0 ) + return 2; +#else + tempdir = "/var/tmp"; +#endif + ofname = (char *) malloc (strlen(ifname) + strlen(tempdir)+ 16); merror (ofname, "main()"); if (write_to_stdout) strcpy (ofname,_("standard output")); else { - strcpy (ofname, ifname); + strcpy (ofname, tempdir); + strcat (ofname, ifname); if ((cp = strrchr (ofname, '.'))) *cp = 0; if (thumbnail_only) strcat (ofname, ".thumb"); Modified: trunk/lib/extras/src/raw/raw.cpp =================================================================== --- trunk/lib/extras/src/raw/raw.cpp 2007-09-02 22:35:27 UTC (rev 295) +++ trunk/lib/extras/src/raw/raw.cpp 2007-09-05 22:20:13 UTC (rev 296) @@ -61,9 +61,20 @@ if( dcraw_( static_cast<int>( args.size( ) ), const_cast<char**>( &args[ 0 ] ) ) ) return il::image_type_ptr( ); - + + pl::string tempdir; +#ifdef WIN32 + TCHAR wtempdir[ BUFSIZ ]; + DWORD dw = GetTempPath(BUFSIZ, wtempdir); + if( dw > BUFSIZ || dw == 0 ) + return il::image_type_ptr( ); + tempdir = pl::to_string( wtempdir ); +#else + tempdir = "/var/tmp"; +#endif + pl::string pathname( path.begin( ), path.begin( ) + path.find_last_of( "." ) ); - pathname += ".tiff"; + pathname = pl::string( tempdir ) + pathname + ".tiff"; typedef pl::discovery<query_traits> discovery; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <gl...@us...> - 2007-09-06 22:34:33
|
Revision: 297 http://hdrflow.svn.sourceforge.net/hdrflow/?rev=297&view=rev Author: glslang Date: 2007-09-06 15:34:31 -0700 (Thu, 06 Sep 2007) Log Message: ----------- + writes output to temp Modified Paths: -------------- trunk/lib/extras/src/raw/dcraw.c trunk/lib/extras/src/raw/raw.cpp Modified: trunk/lib/extras/src/raw/dcraw.c =================================================================== --- trunk/lib/extras/src/raw/dcraw.c 2007-09-05 22:20:13 UTC (rev 296) +++ trunk/lib/extras/src/raw/dcraw.c 2007-09-06 22:34:31 UTC (rev 297) @@ -7407,9 +7407,7 @@ #ifndef NO_LCMS char *cam_profile=0, *out_profile=0; #endif - char tempdir[ BUFSIZ ]; - DWORD dw; - + #ifndef LOCALTIME putenv ("TZ=UTC"); #endif @@ -7457,7 +7455,7 @@ puts(""); return 1; } - argv[argc] = ""; + //argv[argc] = ""; for (arg=1; argv[arg][0] == '-'; ) { opt = argv[arg++][1]; if ((cp = strchr (sp="nbrktqsHA", opt))) @@ -7503,6 +7501,7 @@ case 'm': output_color = 0; break; case 'T': output_tiff = 1; break; case '4': output_bps = 16; break; + case 'Z': ofname = argv[arg++]; break; default: fprintf (stderr,_("Unknown option \"-%c\".\n"), opt); return 1; @@ -7528,7 +7527,7 @@ status = 1; image = 0; oprof = 0; - meta_data = ofname = 0; + meta_data = 0; if (setjmp (failure)) { if (fileno(ifp) > 2) fclose(ifp); if (fileno(ofp) > 2) fclose(ofp); @@ -7696,24 +7695,15 @@ write_ext = ".tiff"; else write_ext = ".pgm\0.ppm\0.ppm\0.pam" + colors*5-5; -#ifdef WIN32 - dw = GetTempPath(BUFSIZ, tempdir); - if( dw > BUFSIZ || dw == 0 ) - return 2; -#else - tempdir = "/var/tmp"; -#endif - ofname = (char *) malloc (strlen(ifname) + strlen(tempdir)+ 16); - merror (ofname, "main()"); if (write_to_stdout) strcpy (ofname,_("standard output")); else { - strcpy (ofname, tempdir); - strcat (ofname, ifname); - if ((cp = strrchr (ofname, '.'))) *cp = 0; - if (thumbnail_only) - strcat (ofname, ".thumb"); - strcat (ofname, write_ext); +// strcpy (ofname, tempdir); +// strcat (ofname, ifname); +// if ((cp = strrchr (ofname, '.'))) *cp = 0; +// if (thumbnail_only) +// strcat (ofname, ".thumb"); +// strcat (ofname, write_ext); ofp = fopen (ofname, "wb"); if (!ofp) { status = 1; @@ -7728,7 +7718,7 @@ if (ofp != stdout) fclose(ofp); cleanup: if (meta_data) free (meta_data); - if (ofname) free (ofname); + //if (ofname) free (ofname); if (oprof) free (oprof); if (image) free (image); } Modified: trunk/lib/extras/src/raw/raw.cpp =================================================================== --- trunk/lib/extras/src/raw/raw.cpp 2007-09-05 22:20:13 UTC (rev 296) +++ trunk/lib/extras/src/raw/raw.cpp 2007-09-06 22:34:31 UTC (rev 297) @@ -52,33 +52,22 @@ pl::string linear_output = properties.get_property_with_key( pcos::key::from_string( "linear_output" ) ).value<pl::string>( ); pl::string tiff = properties.get_property_with_key( pcos::key::from_string( "tiff_output" ) ).value<pl::string>( ); pl::string path = properties.get_property_with_key( pcos::key::from_string( "path" ) ).value<pl::string>( ); + pl::string output_path = properties.get_property_with_key( pcos::key::from_string( "output_path" ) ).value<pl::string>( ); std::vector<const char*> args; args.push_back( "dcraw" ); args.push_back( linear_output.c_str( ) ); args.push_back( tiff.c_str( ) ); + args.push_back( "-Z" ); + args.push_back( output_path.c_str( ) ); args.push_back( path.c_str( ) ); if( dcraw_( static_cast<int>( args.size( ) ), const_cast<char**>( &args[ 0 ] ) ) ) return il::image_type_ptr( ); - pl::string tempdir; -#ifdef WIN32 - TCHAR wtempdir[ BUFSIZ ]; - DWORD dw = GetTempPath(BUFSIZ, wtempdir); - if( dw > BUFSIZ || dw == 0 ) - return il::image_type_ptr( ); - tempdir = pl::to_string( wtempdir ); -#else - tempdir = "/var/tmp"; -#endif - - pl::string pathname( path.begin( ), path.begin( ) + path.find_last_of( "." ) ); - pathname = pl::string( tempdir ) + pathname + ".tiff"; + typedef pl::discovery<query_traits> discovery; - typedef pl::discovery<query_traits> discovery; - - discovery plugins( query_traits( pl::to_wstring( pathname ) ) ); + discovery plugins( query_traits( pl::to_wstring( output_path ) ) ); if( plugins.empty( ) ) return il::image_type_ptr( ); @@ -86,7 +75,7 @@ { il::openimagelib_plugin_ptr plug = boost::shared_dynamic_cast<il::openimagelib_plugin>( i->create_plugin( "" ) ); if( plug ) - return plug->load( pl::make_stream( pathname, std::ios::in ) ); + return plug->load( pl::make_stream( output_path, std::ios::in ) ); } return il::image_type_ptr( ); @@ -118,6 +107,7 @@ , linear_output_( pcos::key::from_string( "linear_output" ) ) , tiff_output_( pcos::key::from_string( "tiff_output" ) ) , path_( pcos::key::from_string( "path" ) ) + , output_path_( pcos::key::from_string( "output_path" ) ) { set_raw_properties( ); } @@ -155,6 +145,18 @@ raw_props_.append( linear_output_ = pl::string( "-4" ) ); raw_props_.append( tiff_output_ = pl::string( "-T" ) ); raw_props_.append( path_ = pl::string( "" ) ); + + pl::string tempdir; +#ifdef WIN32 + TCHAR wtempdir[ BUFSIZ ]; + DWORD dw = GetTempPath(BUFSIZ, wtempdir); + if( !( dw > BUFSIZ || dw == 0 ) ) + tempdir = pl::to_string( wtempdir ); +#else + tempdir = "/var/tmp/"; +#endif + + raw_props_.append( output_path_ = tempdir + pl::string( "hdrflow_extras_raw_.tiff" ) ); } private: @@ -180,6 +182,7 @@ pcos::property linear_output_; pcos::property tiff_output_; pcos::property path_; + pcos::property output_path_; }; } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <gl...@us...> - 2008-03-29 18:40:44
|
Revision: 431 http://hdrflow.svn.sourceforge.net/hdrflow/?rev=431&view=rev Author: glslang Date: 2008-03-29 11:40:39 -0700 (Sat, 29 Mar 2008) Log Message: ----------- + update dcraw Modified Paths: -------------- trunk/lib/extras/src/raw/dcraw.c trunk/lib/extras/src/raw/raw.cpp trunk/lib/extras/src/raw/raw_vc8.vcproj Modified: trunk/lib/extras/src/raw/dcraw.c =================================================================== --- trunk/lib/extras/src/raw/dcraw.c 2008-03-08 19:53:37 UTC (rev 430) +++ trunk/lib/extras/src/raw/dcraw.c 2008-03-29 18:40:39 UTC (rev 431) @@ -1,16 +1,17 @@ /* dcraw.c -- Dave Coffin's raw photo decoder - Copyright 1997-2007 by Dave Coffin, dcoffin a cybercom o net + Copyright 1997-2008 by Dave Coffin, dcoffin a cybercom o net This is a command-line ANSI C program to convert raw photos from any digital camera on any computer running any operating system. No license is required to download and use dcraw.c. However, - to lawfully redistribute this code, you must either (a) include - full source code* for all executable files containing RESTRICTED - functions, (b) remove all RESTRICTED functions, re-implement them, - or copy them from an earlier, unrestricted Revision of dcraw.c, - or (c) purchase a license from the author. + to lawfully redistribute dcraw, you must either (a) offer, at + no extra charge, full source code* for all executable files + containing RESTRICTED functions, (b) distribute this code under + the GPL Version 2 or later, (c) remove all RESTRICTED functions, + re-implement them, or copy them from an earlier, unrestricted + Revision of dcraw.c, or (d) purchase a license from the author. The functions that process Foveon images have been RESTRICTED since Revision 1.237. All other code remains free for all uses. @@ -18,11 +19,11 @@ *If you have not modified dcraw.c in any way, a link to my homepage qualifies as "full source code". - $Revision: 1.379 $ - $Date: 2007/05/03 06:15:16 $ + $Revision: 1.399 $ + $Date: 2008/03/05 01:29:34 $ */ -#define VERSION "8.71" +#define VERSION "8.83" #define _GNU_SOURCE #define _USE_MATH_DEFINES @@ -37,6 +38,7 @@ #include <stdlib.h> #include <string.h> #include <time.h> +#include <sys/types.h> /* NO_JPEG disables decoding of compressed Kodak DC120 files. NO_LCMS disables the "-p" option. @@ -53,7 +55,10 @@ #else #define _(String) (String) #endif -#ifndef DJGPP +#ifdef DJGPP +#define fseeko fseek +#define ftello ftell +#else #define fgetc getc_unlocked #endif #ifdef __CYGWIN__ @@ -63,12 +68,11 @@ #include <sys/utime.h> #include <winsock2.h> #pragma comment(lib, "ws2_32.lib") -#define strcasecmp _stricmp -#define strncasecmp _strnicmp -#define getc_unlocked getc +#define snprintf _snprintf +#define strcasecmp stricmp +#define strncasecmp strnicmp typedef __int64 INT64; typedef unsigned __int64 UINT64; -#pragma warning( disable:4018 4244 4305 4389 4706 ) #else #include <unistd.h> #include <utime.h> @@ -97,28 +101,31 @@ */ FILE *ifp; short order; -char *ifname, make[64], model[64], model2[64], *meta_data, cdesc[5]; +char *ifname, *meta_data; +char cdesc[5], desc[512], make[64], model[64], model2[64], artist[64]; float flash_used, canon_ev, iso_speed, shutter, aperture, focal_len; time_t timestamp; unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id; -unsigned profile_offset, profile_length, *oprof; -unsigned thumb_offset, thumb_length, thumb_misc; -unsigned data_offset, strip_offset, curve_offset, meta_offset, meta_length; -unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress, tile_length; +off_t strip_offset, data_offset; +off_t thumb_offset, meta_offset, profile_offset; +unsigned thumb_length, meta_length, profile_length; +unsigned thumb_misc, *oprof, fuji_layout, shot_select=0, multi_out=0; +unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress; unsigned black, maximum, mix_green, raw_color, use_gamma, zero_is_bad; unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error; +unsigned tile_width, tile_length, gpsdata[32]; ushort raw_height, raw_width, height, width, top_margin, left_margin; ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height; int flip, tiff_flip, colors; -double pixel_aspect; -ushort (*image)[4], white[8][8], curve[0x1000], cr2_slice[3]; +double pixel_aspect, aber[4]={1,1,1,1}; +ushort (*image)[4], white[8][8], curve[0x4001], cr2_slice[3], sraw_mul[4]; float bright=1, user_mul[4]={0,0,0,0}, threshold=0; int half_size=0, four_color_rgb=0, document_mode=0, highlight=0; -int verbose=0, use_auto_wb=0, use_camera_wb=0; -int output_color=1, output_bps=8, output_tiff=0; -int fuji_layout, fuji_secondary, shot_select=0; +int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=-1; +int output_color=1, output_bps=8, output_tiff=0, med_passes=0; +int no_auto_bright=0; unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX }; -float cam_mul[4], pre_mul[4], rgb_cam[3][4]; /* RGB from camera color */ +float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4]; const double xyz_rgb[3][3] = { /* XYZ from RGB */ { 0.412453, 0.357580, 0.180423 }, { 0.212671, 0.715160, 0.072169 }, @@ -145,9 +152,10 @@ #define CLASS -#define FORC3 for (c=0; c < 3; c++) -#define FORC4 for (c=0; c < 4; c++) -#define FORCC for (c=0; c < colors; c++) +#define FORC(cnt) for (c=0; c < cnt; c++) +#define FORC3 FORC(3) +#define FORC4 FORC(4) +#define FORCC FORC(colors) #define SQR(x) ((x)*(x)) #define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31)) @@ -257,7 +265,7 @@ if (feof(ifp)) fprintf (stderr,_("Unexpected end of file\n")); else - fprintf (stderr,_("Corrupt data near 0x%lx\n"), ftell(ifp)); + fprintf (stderr,_("Corrupt data near 0x%llx\n"), (INT64) ftello(ifp)); } data_error = 1; } @@ -328,7 +336,6 @@ default: return fgetc(ifp); } } -#define getrat() getreal(10) void CLASS read_shorts (ushort *pixel, int count) { @@ -420,7 +427,7 @@ for (i=0; i < 8; i++) total[st][i] += test[i]; count[st]++; -next: continue; +next: ; } if (count[0] | count[1]) { st = count[0]*200 < count[1]; @@ -483,8 +490,8 @@ black = black / ((raw_width - width) * height) - 4; for (row=0; row < height; row++) for (col=0; col < width; col++) { - val = (BAYER(row,col) - black) * mul[row & 3][col & 1] >> 9; - if (val < 0) val = 0; + if ((val = BAYER(row,col) - black) < 0) val = 0; + val = val * mul[row & 3][col & 1] >> 9; BAYER(row,col) = val; } canon_600_fixed_wb(1311); @@ -524,7 +531,7 @@ void CLASS canon_a5_load_raw() { - ushort data[2335], *dp, pixel; + ushort data[2565], *dp, pixel; int vbits=0, buf=0, row, col, bc=0; order = 0x4949; @@ -792,8 +799,8 @@ enough to decode Canon, Kodak and Adobe DNG images. */ struct jhead { - int bits, high, wide, clrs, restart, vpred[4]; - struct decode *huff[4]; + int bits, high, wide, clrs, psv, restart, vpred[4]; + struct CLASS decode *huff[4]; ushort *row; }; @@ -816,12 +823,13 @@ if (tag <= 0xff00) return 0; fread (data, 1, len, ifp); switch (tag) { - case 0xffc0: + case 0xffc0: data[7] = 0; case 0xffc3: jh->bits = data[0]; jh->high = data[1] << 8 | data[2]; jh->wide = data[3] << 8 | data[4]; - jh->clrs = data[5]; + jh->clrs = data[5] + (data[7] == 0x21); + if (len == 9 && !dng_version) getc(ifp); break; case 0xffc4: if (info_only) break; @@ -830,13 +838,20 @@ dp = make_decoder (++dp, 0); } break; + case 0xffda: + jh->psv = data[1+data[0]*2]; + break; case 0xffdd: jh->restart = data[0] << 8 | data[1]; } } while (tag != 0xffda); if (info_only) return 1; - jh->row = (ushort *) calloc (jh->wide*jh->clrs, 2); - merror (jh->row, " jpeg_start()"); + if (jh->clrs == 4) { + jh->huff[3] = jh->huff[2] = jh->huff[1]; + jh->huff[1] = jh->huff[0]; + } + jh->row = (ushort *) calloc (jh->wide*jh->clrs, 4); + merror (jh->row, "ljpeg_start()"); return zero_after_ff = 1; } @@ -855,10 +870,10 @@ return diff; } -void CLASS ljpeg_row (int jrow, struct jhead *jh) +ushort * CLASS ljpeg_row (int jrow, struct jhead *jh) { - int col, c, diff; - ushort mark=0, *outp=jh->row; + int col, c, diff, pred; + ushort mark=0, *row[3]; if (jrow * jh->wide % jh->restart == 0) { FORC4 jh->vpred[c] = 1 << (jh->bits-1); @@ -867,13 +882,28 @@ while (c != EOF && mark >> 4 != 0xffd); getbits(-1); } + FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1); for (col=0; col < jh->wide; col++) - for (c=0; c < jh->clrs; c++) { + FORC(jh->clrs) { diff = ljpeg_diff (jh->huff[c]); - *outp = diff = col ? outp[-jh->clrs]+diff : (jh->vpred[c] += diff); - if (diff >> jh->bits) derror(); - outp++; + if (jh->clrs == 4 && c < 2 && (col | c)) + pred = row[0][(c << 1)-3]; + else if (col) pred = row[0][-jh->clrs]; + else pred = (jh->vpred[c] += diff) - diff; + if (jrow && col) switch (jh->psv) { + case 1: break; + case 2: pred = row[1][0]; break; + case 3: pred = row[1][-jh->clrs]; break; + case 4: pred = pred + row[1][0] - row[1][-jh->clrs]; break; + case 5: pred = pred + ((row[1][0] - row[1][-jh->clrs]) >> 1); break; + case 6: pred = row[1][0] + ((pred - row[1][-jh->clrs]) >> 1); break; + case 7: pred = (pred + row[1][0]) >> 1; break; + default: pred = 0; + } + if ((**row = pred + diff) >> jh->bits) derror(); + row[0]++; row[1]++; } + return row[2]; } void CLASS lossless_jpeg_load_raw() @@ -881,14 +911,15 @@ int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0; struct jhead jh; int min=INT_MAX; + ushort *rp; if (!ljpeg_start (&jh, 0)) return; jwide = jh.wide * jh.clrs; for (jrow=0; jrow < jh.high; jrow++) { - ljpeg_row (jrow, &jh); + rp = ljpeg_row (jrow, &jh); for (jcol=0; jcol < jwide; jcol++) { - val = jh.row[jcol]; + val = *rp++; if (jh.bits <= 12) val = curve[val]; if (cr2_slice[0]) { @@ -919,13 +950,57 @@ black = min; } +void CLASS canon_sraw_load_raw() +{ + struct jhead jh; + short *rp=0, *ip; + int jwide, slice, scol, ecol, row, col, jrow=0, jcol=0, pix[3], c; + + if (!ljpeg_start (&jh, 0)) return; + jwide = (jh.wide >>= 1) * 4; + + for (ecol=slice=0; slice <= cr2_slice[0]; slice++) { + scol = ecol; + ecol += cr2_slice[1] >> 1; + if (!cr2_slice[0] || ecol > width-1) ecol = width & -2; + for (row=0; row < height; row++) { + ip = (short *) image[row*width+scol]; + for (col=scol; col < ecol; col+=2, jcol+=4, ip+=8) { + if ((jcol %= jwide) == 0) + rp = (short *) ljpeg_row (jrow++, &jh); + ip[0] = rp[jcol]; + ip[4] = rp[jcol+1]; + ip[1] = (short) (rp[jcol+2] << 2) >> 2; + ip[2] = (short) (rp[jcol+3] << 2) >> 2; + } + } + } + for (row=0; row < height; row++) { + ip = (short *) image[row*width+1]; + for (col=1; col < width-1; col+=2, ip+=8) { + ip[1] = (ip[-3] + ip[5] + 1) >> 1; + ip[2] = (ip[-2] + ip[6] + 1) >> 1; + } + if (col < width) { ip[1] = ip[-3]; ip[2] = ip[-2]; } + ip = (short *) image[row*width]; + for (col=0; col < width; col++, ip+=4) { + pix[0] = ip[2] + ip[0]; + pix[2] = ip[1] + ip[0]; + pix[1] = ((ip[0] << 12) - ip[1]*778 - (ip[2] << 11)) >> 12; + FORC3 ip[c] = CLIP((pix[c] - 512) * sraw_mul[c] >> 10); + } + } + free (jh.row); + maximum = 0x3fff; +} + void CLASS adobe_copy_pixel (int row, int col, ushort **rp) { unsigned r, c; r = row -= top_margin; c = col -= left_margin; - if (fuji_secondary && shot_select) (*rp)++; + if (is_raw == 2 && shot_select) (*rp)++; if (filters) { if (fuji_width) { r = row + fuji_width - 1 - (col >> 1); @@ -933,47 +1008,41 @@ } if (r < height && c < width) BAYER(r,c) = **rp < 0x1000 ? curve[**rp] : **rp; - *rp += 1 + fuji_secondary; + *rp += is_raw; } else { if (r < height && c < width) - for (c=0; c < tiff_samples; c++) + FORC(tiff_samples) image[row*width+col][c] = (*rp)[c] < 0x1000 ? curve[(*rp)[c]]:(*rp)[c]; *rp += tiff_samples; } - if (fuji_secondary && shot_select) (*rp)--; + if (is_raw == 2 && shot_select) (*rp)--; } void CLASS adobe_dng_load_raw_lj() { - int save, twide, trow=0, tcol=0, jrow, jcol; + unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col; struct jhead jh; ushort *rp; - while (1) { + while (trow < raw_height) { save = ftell(ifp); if (tile_length < INT_MAX) fseek (ifp, get4(), SEEK_SET); if (!ljpeg_start (&jh, 0)) 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 (jrow, &jh); - for (rp=jh.row, jcol=0; jcol < twide; jcol++) - adobe_copy_pixel (trow+jrow, tcol+jcol, &rp); + jwide = jh.wide; + if (filters) jwide *= jh.clrs; + jwide /= is_raw; + for (row=col=jrow=0; jrow < jh.high; jrow++) { + rp = ljpeg_row (jrow, &jh); + for (jcol=0; jcol < jwide; jcol++) { + adobe_copy_pixel (trow+row, tcol+col, &rp); + if (++col >= tile_width || col >= raw_width) + row += 1 + (col = 0); + } } fseek (ifp, save+4, SEEK_SET); - if ((tcol += twide) >= raw_width) { - tcol = 0; - trow += jh.high; - } + if ((tcol += tile_width) >= raw_width) + trow += tile_length + (tcol = 0); free (jh.row); } } @@ -1013,10 +1082,8 @@ for (row=0; row < height; row++) for (col=0; col < raw_width; col++) { diff = ljpeg_diff (first_decode); - if (col < 2) - hpred[col] = vpred[row & 1][col] += diff; - else - hpred[col & 1] += diff; + if (col < 2) hpred[col] = vpred[row & 1][col] += diff; + else hpred[col & 1] += diff; if (col < width) BAYER(row,col) = hpred[col & 1]; if (hpred[col & 1] >> 12) derror(); @@ -1025,36 +1092,68 @@ void CLASS nikon_compressed_load_raw() { - static const uchar nikon_tree[] = - { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, - 5,4,3,6,2,7,1,0,8,9,11,10,12 }; - int csize, row, col, diff; - ushort vpred[2][2], hpred[2], *curve; + static const uchar nikon_tree[][32] = { + { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy */ + 5,4,3,6,2,7,1,0,8,9,11,10,12 }, + { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy after split */ + 0x39,0x5a,0x38,0x27,0x16,5,4,3,2,1,0,11,12,12 }, + { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, /* 12-bit lossless */ + 5,4,6,3,7,2,8,1,9,0,10,11,12 }, + { 0,1,4,3,1,1,1,1,1,2,0,0,0,0,0,0, /* 14-bit lossy */ + 5,6,4,7,8,3,9,2,1,0,10,11,12,13,14 }, + { 0,1,5,1,1,1,1,1,1,1,2,0,0,0,0,0, /* 14-bit lossy after split */ + 8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 }, + { 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0, /* 14-bit lossless */ + 7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } }; + struct decode *dindex; + ushort ver0, ver1, vpred[2][2], hpred[2], csize; + int i, max, step=0, huff=0, split=0, row, col, len, shl, diff; + fseek (ifp, meta_offset, SEEK_SET); + ver0 = fgetc(ifp); + ver1 = fgetc(ifp); + if (ver0 == 0x49 || ver1 == 0x58) + fseek (ifp, 2110, SEEK_CUR); + if (ver0 == 0x46) huff = 2; + if (tiff_bps == 14) huff += 3; + read_shorts (vpred[0], 4); + max = 1 << tiff_bps & 0x7fff; + if ((csize = get2()) > 1) + step = max / (csize-1); + if (ver0 == 0x44 && ver1 == 0x20 && step > 0) { + for (i=0; i < csize; i++) + curve[i*step] = get2(); + for (i=0; i < max; i++) + curve[i] = ( curve[i-i%step]*(step-i%step) + + curve[i-i%step+step]*(i%step) ) / step; + fseek (ifp, meta_offset+562, SEEK_SET); + split = get2(); + } else if (ver0 != 0x46 && csize <= 0x4001) + read_shorts (curve, max=csize); init_decoder(); - make_decoder (nikon_tree, 0); - - fseek (ifp, curve_offset, SEEK_SET); - read_shorts (vpred[0], 4); - csize = get2(); - curve = (ushort *) calloc (csize, sizeof *curve); - merror (curve, "nikon_compressed_load_raw()"); - read_shorts (curve, csize); - + make_decoder (nikon_tree[huff], 0); fseek (ifp, data_offset, SEEK_SET); getbits(-1); - for (row=0; row < height; row++) + for (row=0; row < height; row++) { + if (split && row == split) { + init_decoder(); + make_decoder (nikon_tree[huff+1], 0); + } for (col=0; col < raw_width; col++) { - diff = ljpeg_diff (first_decode); - if (col < 2) - hpred[col] = vpred[row & 1][col] += diff; - else - hpred[col & 1] += diff; - if ((unsigned) (col-left_margin) >= width) continue; - if (hpred[col & 1] >= csize) derror(); - else BAYER(row,col-left_margin) = curve[hpred[col & 1]]; + for (dindex=first_decode; dindex->branch[0]; ) + dindex = dindex->branch[getbits(1)]; + len = dindex->leaf & 15; + shl = dindex->leaf >> 4; + diff = ((getbits(len-shl) << 1) + 1) << shl >> 1; + if ((diff & (1 << (len-1))) == 0) + diff -= (1 << len) - !shl; + if (col < 2) hpred[col] = vpred[row & 1][col] += diff; + else hpred[col & 1] += diff; + if (hpred[col & 1] >= max) derror(); + if ((unsigned) (col-left_margin) < width) + BAYER(row,col-left_margin) = curve[hpred[col & 1] & 0x3fff]; } - free (curve); + } } void CLASS nikon_load_raw() @@ -1076,7 +1175,7 @@ i = getbits(12); if ((unsigned) (col-left_margin) < width) BAYER(row,col-left_margin) = i; - if (tiff_compress == 34713 && (col % 10) == 9) + if (tiff_compress > 32768 && (col % 10) == 9) if (getbits(8)) derror(); } } @@ -1092,10 +1191,6 @@ uchar test[256]; int i; - if (tiff_compress != 34713) - return 0; - if (strcmp(model,"D100")) - return 1; fseek (ifp, data_offset, SEEK_SET); fread (test, 1, 256, ifp); for (i=15; i < 256; i+=16) @@ -1531,14 +1626,15 @@ static UINT64 bitbuf=0; static int vbits=0; - if (nbits == 0) + if (nbits == -1) return bitbuf = vbits = 0; + if (nbits == 0) return 0; if (vbits < nbits) { bitbuf = bitbuf << 32 | get4(); vbits += 32; } vbits -= nbits; - return bitbuf << (64 - nbits - vbits) >> (64 - nbits); + return bitbuf << (64-nbits-vbits) >> (64-nbits); } void CLASS phase_one_load_raw_c() @@ -1562,7 +1658,7 @@ curve[i] = i*i / 3.969 + 0.5; for (row=0; row < raw_height; row++) { fseek (ifp, data_offset + offset[row], SEEK_SET); - ph1_bits(0); + ph1_bits(-1); pred[0] = pred[1] = 0; for (col=0; col < raw_width; col++) { if (col >= (raw_width & -8)) @@ -1592,6 +1688,36 @@ maximum = 0xfffc - ph1.black; } +void CLASS hasselblad_load_raw() +{ + struct jhead jh; + struct decode *dindex; + int row, col, pred[2], len[2], diff, i; + + if (!ljpeg_start (&jh, 0)) return; + free (jh.row); + ph1_bits(-1); + for (row=-top_margin; row < height; row++) { + pred[0] = pred[1] = 0x8000; + for (col=-left_margin; col < raw_width-left_margin; col+=2) { + for (i=0; i < 2; i++) { + for (dindex=jh.huff[0]; dindex->branch[0]; ) + dindex = dindex->branch[ph1_bits(1)]; + len[i] = dindex->leaf; + } + for (i=0; i < 2; i++) { + diff = ph1_bits(len[i]); + if ((diff & (1 << (len[i]-1))) == 0) + diff -= (1 << len[i]) - 1; + pred[i] += diff; + if (row >= 0 && (unsigned)(col+i) < width) + BAYER(row,col+i) = pred[i]; + } + } + } + maximum = 0xffff; +} + void CLASS leaf_hdr_load_raw() { ushort *pixel; @@ -1599,7 +1725,7 @@ pixel = (ushort *) calloc (raw_width, sizeof *pixel); merror (pixel, "leaf_hdr_load_raw()"); - for (c=0; c < tiff_samples; c++) { + FORC(tiff_samples) for (r=0; r < raw_height; r++) { if (r % tile_length == 0) { fseek (ifp, data_offset + 4*tile++, SEEK_SET); @@ -1612,7 +1738,6 @@ if (filters) BAYER(row,col) = pixel[col]; else image[row*width+col][c] = pixel[col]; } - } free (pixel); if (!filters) { maximum = 0xffff; @@ -1701,6 +1826,65 @@ free (pixel); } +void CLASS nokia_load_raw() +{ + uchar *data, *dp; + ushort *pixel, *pix; + int dwide, row, c; + + dwide = raw_width * 5 / 4; + data = (uchar *) malloc (dwide + raw_width*2); + merror (data, "nokia_load_raw()"); + pixel = (ushort *) (data + dwide); + for (row=0; row < raw_height; row++) { + if (fread (data, 1, dwide, ifp) < dwide) derror(); + for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=5, pix+=4) + FORC4 pix[c] = (dp[c] << 2) | (dp[4] >> (c << 1) & 3); + if (row < top_margin) + FORC(width) black += pixel[c]; + else + FORC(width) BAYER(row-top_margin,c) = pixel[c]; + } + free (data); + if (top_margin) black /= top_margin * width; + maximum = 0x3ff; +} + +unsigned CLASS pana_bits (int nbits) +{ + static uchar buf[16], vbits=0; + + if (!vbits && fread (buf, 1, 16, ifp) < 16) derror(); + vbits = (vbits - nbits) & 127; + return (buf[(vbits >> 3)+1] << 8 | buf[vbits >> 3]) + >> (vbits & 7) & ~(-1 << nbits); +} + +void CLASS panasonic_load_raw() +{ + int row, col, i, j, sh=0, pred[2], nonz[2]; + + raw_width = (raw_width+13)/14*14; + for (row=0; row < height; row++) + for (col=0; col < raw_width; col++) { + if ((i = col % 14) < 2) + nonz[i] = pred[i] = pana_bits(12); + else { + if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2)); + if ((j = pana_bits(8))) { + if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4) + pred[i & 1] &= ~(-1 << sh); + pred[i & 1] += nonz[i & 1] ? j << sh : j; + nonz[i & 1] = 1; + } + } + if (col < width) + if ((BAYER(row,col) = pred[col & 1]) >> 12) derror(); + } + maximum = 0xf96; + black = 15; +} + void CLASS olympus_e300_load_raw() { uchar *data, *dp; @@ -1724,10 +1908,8 @@ BAYER(row,col) = (pixel[col+left_margin] & 0xfff); } free (data); - if (!strcmp(make,"OLYMPUS")) { - maximum = 0xfff; - black >>= 4; - } + maximum >>= 4; + black >>= 4; } void CLASS olympus_e410_load_raw() @@ -1815,22 +1997,6 @@ maximum = 0xff << 1; } -void CLASS eight_bit_load_raw() -{ - uchar *pixel; - int row, col; - - pixel = (uchar *) calloc (raw_width, sizeof *pixel); - merror (pixel, "eight_bit_load_raw()"); - for (row=0; row < height; row++) { - if (fread (pixel, 1, raw_width, ifp) < raw_width) derror(); - for (col=0; col < width; col++) - BAYER(row,col) = pixel[col]; - } - free (pixel); - maximum = 0xff; -} - void CLASS casio_qv5700_load_raw() { uchar data[3232], *dp; @@ -2123,27 +2289,26 @@ maximum = 0xff; } -void CLASS kodak_easy_load_raw() +void CLASS eight_bit_load_raw() { uchar *pixel; - unsigned row, col, val; + unsigned row, col, val, lblack=0; - if (raw_width > width) - black = 0; pixel = (uchar *) calloc (raw_width, sizeof *pixel); - merror (pixel, "kodak_easy_load_raw()"); + merror (pixel, "eight_bit_load_raw()"); + fseek (ifp, top_margin*raw_width, SEEK_CUR); for (row=0; row < height; row++) { if (fread (pixel, 1, raw_width, ifp) < raw_width) derror(); for (col=0; col < raw_width; col++) { val = curve[pixel[col]]; if ((unsigned) (col-left_margin) < width) BAYER(row,col-left_margin) = val; - else black += val; + else lblack += val; } } free (pixel); - if (raw_width > width) - black /= (raw_width - width) * height; + if (raw_width > width+1) + black = lblack / ((raw_width - width) * height); if (!strncmp(model,"DC2",3)) black = 0; maximum = curve[0xff]; @@ -2383,6 +2548,45 @@ } } +void CLASS sony_arw2_load_raw() +{ + uchar *data, *dp; + ushort pix[16]; + int row, col, val, max, min, imax, imin, sh, bit, i; + + data = (uchar *) malloc (raw_width*tiff_bps >> 3); + merror (data, "sony_arw2_load_raw()"); + for (row=0; row < height; row++) { + fread (data, 1, raw_width*tiff_bps >> 3, ifp); + if (tiff_bps == 8) { + for (dp=data, col=0; col < width-30; dp+=16) { + max = 0x7ff & (val = sget4(dp)); + min = 0x7ff & val >> 11; + imax = 0x0f & val >> 22; + imin = 0x0f & val >> 26; + for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++); + for (bit=30, i=0; i < 16; i++) + if (i == imax) pix[i] = max; + else if (i == imin) pix[i] = min; + else { + pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min; + if (pix[i] > 0x7ff) pix[i] = 0x7ff; + bit += 7; + } + for (i=0; i < 16; i++, col+=2) + BAYER(row,col) = curve[pix[i] << 1] >> 1; + col -= col & 1 ? 1:31; + } + } else if (tiff_bps == 12) + for (dp=data, col=0; col < width; dp+=3, col+=2) { + BAYER(row,col) = ((dp[1] << 8 | dp[0]) & 0xfff) << 1; + BAYER(row,col+1) = (dp[2] << 4 | dp[1] >> 4) << 1; + } + } + free (data); + maximum = 0x1fff; +} + #define HOLE(row) ((holes >> (((row) - raw_height) & 7)) & 1) /* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */ @@ -2623,7 +2827,7 @@ for (row=0; row < height; row++) { memset (pred, 0, sizeof pred); - if (!bit && !fixed && width < 2688) get4(); + if (!bit && !fixed && atoi(model+2) < 14) get4(); for (col=bit=0; col < width; col++) { if (fixed) { bitbuf = get4(); @@ -3171,35 +3375,39 @@ Seach from the current directory up to the root looking for a ".badpixels" file, and fix those pixels now. */ -void CLASS bad_pixels() +void CLASS bad_pixels (char *fname) { FILE *fp=0; - char *fname, *cp, line[128]; + char *cp, line[128]; int len, time, row, col, r, c, rad, tot, n, fixed=0; if (!filters) return; - for (len=32 ; ; len *= 2) { - fname = (char *) malloc (len); - if (!fname) return; - if (getcwd (fname, len-16)) break; - free (fname); - if (errno != ERANGE) return; - } + if (fname) + fp = fopen (fname, "r"); + else { + for (len=32 ; ; len *= 2) { + fname = (char *) malloc (len); + if (!fname) return; + if (getcwd (fname, len-16)) break; + free (fname); + if (errno != ERANGE) return; + } #if defined(WIN32) || defined(DJGPP) - if (fname[1] == ':') - memmove (fname, fname+2, len-2); - for (cp=fname; *cp; cp++) - if (*cp == '\\') *cp = '/'; + 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 != '/'); + 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); } - free (fname); if (!fp) return; while (fgets (line, 128, fp)) { cp = strchr (line, '#'); @@ -3218,7 +3426,7 @@ BAYER2(row,col) = tot/n; if (verbose) { if (!fixed++) - fprintf (stderr,_("Fixed bad pixels at:")); + fprintf (stderr,_("Fixed dead pixels at:")); fprintf (stderr, " %d,%d", col, row); } } @@ -3441,7 +3649,7 @@ merror (fimg, "wavelet_denoise()"); temp = fimg + size*3; if ((nc = colors) == 3 && filters) nc++; - for (c=0; c < nc; c++) { /* denoise R,G1,B,G3 individually */ + FORC(nc) { /* denoise R,G1,B,G3 individually */ for (i=0; i < size; i++) fimg[i] = sqrt((unsigned) (image[i][c] << (scale+16))); for (hpass=lev=0; lev < 5; lev++) { @@ -3500,10 +3708,11 @@ void CLASS scale_colors() { - unsigned bottom, right, row, col, x, y, c, sum[8]; - int val, dblack; + unsigned bottom, right, size, row, col, ur, uc, i, x, y, c, sum[8]; + int val, dark, sat; double dsum[8], dmin, dmax; - float scale_mul[4]; + float scale_mul[4], fr, fc; + ushort *img=0, *pix; if (user_mul[0]) memcpy (pre_mul, user_mul, sizeof pre_mul); @@ -3528,9 +3737,8 @@ sum[c+4]++; if (filters) break; } - for (c=0; c < 8; c++) dsum[c] += sum[c]; -skip_block: - continue; + FORC(8) dsum[c] += sum[c]; +skip_block: ; } FORC4 if (dsum[c]) pre_mul[c] = dsum[c+4] / dsum[c]; } @@ -3551,7 +3759,8 @@ fprintf (stderr,_("%s: Cannot use camera white balance.\n"), ifname); } if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1; - dblack = black; + dark = black; + sat = maximum; if (threshold) wavelet_denoise(); maximum -= black; for (dmin=DBL_MAX, dmax=c=0; c < 4; c++) { @@ -3563,19 +3772,45 @@ if (!highlight) dmax = dmin; FORC4 scale_mul[c] = (pre_mul[c] /= dmax) * 65535.0 / maximum; if (verbose) { - fprintf (stderr,_("Scaling with black %d, multipliers"), dblack); + fprintf (stderr, + _("Scaling with darkness %d, saturation %d, and\nmultipliers"), dark, sat); FORC4 fprintf (stderr, " %f", pre_mul[c]); fputc ('\n', stderr); } - for (row=0; row < iheight; row++) - for (col=0; col < iwidth; col++) - FORC4 { - val = image[row*iwidth+col][c]; - if (!val) continue; - val -= black; - val *= scale_mul[c]; - image[row*iwidth+col][c] = CLIP(val); + size = iheight*iwidth; + for (i=0; i < size*4; i++) { + val = image[0][i]; + if (!val) continue; + val -= black; + val *= scale_mul[i & 3]; + image[0][i] = CLIP(val); + } + if ((aber[0] != 1 || aber[2] != 1) && colors == 3) { + if (verbose) + fprintf (stderr,_("Correcting chromatic aberration...\n")); + for (c=0; c < 4; c+=2) { + if (aber[c] == 1) continue; + img = (ushort *) malloc (size * sizeof *img); + merror (img, "scale_colors()"); + for (i=0; i < size; i++) + img[i] = image[i][c]; + for (row=0; row < iheight; row++) { + ur = fr = (row - iheight*0.5) * aber[c] + iheight*0.5; + if (ur > iheight-2) continue; + fr -= ur; + for (col=0; col < iwidth; col++) { + uc = fc = (col - iwidth*0.5) * aber[c] + iwidth*0.5; + if (uc > iwidth-2) continue; + fc -= uc; + pix = img + ur*iwidth + uc; + image[row*iwidth+col][c] = + (pix[ 0]*(1-fc) + pix[ 1]*fc) * (1-fr) + + (pix[iwidth]*(1-fc) + pix[iwidth+1]*fc) * fr; + } } + free(img); + } + } } void CLASS pre_interpolate() @@ -3587,7 +3822,6 @@ if (half_size) { height = iheight; width = iwidth; - filters = 0; } else { img = (ushort (*)[4]) calloc (height*width, sizeof *img); merror (img, "unshrink()"); @@ -3610,6 +3844,7 @@ filters &= ~((filters & 0x55555555) << 1); } } + if (half_size) filters = 0; } void CLASS border_interpolate (int border) @@ -3660,7 +3895,7 @@ FORCC if (c != fc(row,col)) { *ip++ = c; - *ip++ = sum[c]; + *ip++ = 256 / sum[c]; } } for (row=1; row < height-1; row++) @@ -3671,7 +3906,7 @@ for (i=8; i--; ip+=3) sum[ip[2]] += pix[ip[0]] << ip[1]; for (i=colors; --i; ip+=2) - pix[ip[0]] = sum[ip[0]] / ip[1]; + pix[ip[0]] = sum[ip[0]] * ip[1] >> 8; } } @@ -3812,6 +4047,76 @@ } /* + Patterned Pixel Grouping Interpolation by Alain Desbiolles +*/ +void CLASS ppg_interpolate() +{ + int gr[4], dir[5] = { 1, width, -1, -width, 1 }; + int row, col, avg, diff[2], guess[2], c, d, i; + static const short sort[] = { 0,2,1,3,0,1,2,3 }; + ushort (*pix)[4]; + + border_interpolate(3); + if (verbose) fprintf (stderr,_("PPG interpolation...\n")); + +/* Fill in the green layer with gradients and pattern recognition: */ + for (row=3; row < height-3; row++) + for (col=3+(FC(row,3) & 1), c=FC(row,col); col < width-3; col+=2) { + pix = image + row*width+col; + for (avg=i=0; i < 4; i++) + avg += gr[i] = pix[dir[i]][1] << 2; + avg >>= 2; + for (i=0; i < 8; i+=2) + if (gr[sort[i]] > gr[sort[i+1]]) + SWAP(gr[sort[i]],gr[sort[i+1]]) + for (d=0; d < 4; d++) { + for (i=-2; i < 2; i++) + if (pix[i*dir[d] + (i+1)*dir[d+1]][1] <= avg) break; + if (i == 2) { + pix[0][1] = (gr[1]+gr[2]) >> 3; + goto next_pixel; + } + } + for (i=0; (d=dir[i]) > 0; i++) { + guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2 + - pix[-2*d][c] - pix[2*d][c]; + diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) + + ABS(pix[ 2*d][c] - pix[ 0][c]) + + ABS(pix[ -d][1] - pix[ d][1]) ) * 3 + + ( ABS(pix[ 3*d][1] - pix[ d][1]) + + ABS(pix[-3*d][1] - pix[-d][1]) ) * 2; + } + d = dir[i = diff[0] > diff[1]]; + pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]); +next_pixel: ; + } +/* Calculate red and blue for each green pixel: */ + for (row=1; row < height-1; row++) + for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) { + pix = image + row*width+col; + for (i=0; (d=dir[i]) > 0; c=2-c, i++) + pix[0][c] = CLIP((pix[-d][c] + pix[d][c] + 2*pix[0][1] + - pix[-d][1] - pix[d][1]) >> 1); + } +/* Calculate blue for red pixels and vice versa: */ + for (row=1; row < height-1; row++) + for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < width-1; col+=2) { + pix = image + row*width+col; + for (i=0; (d=dir[i]+dir[i+1]) > 0; i++) { + diff[i] = ABS(pix[-d][c] - pix[d][c]) + + ABS(pix[-d][1] - pix[0][1]) + + ABS(pix[ d][1] - pix[0][1]); + guess[i] = pix[-d][c] + pix[d][c] + 2*pix[0][1] + - pix[-d][1] - pix[d][1]; + } + if (diff[0] != diff[1]) + pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 1); + else + pix[0][c] = CLIP((guess[0]+guess[1]) >> 2); + } +} + +/* Adaptive Homogeneity-Directed interpolation is based on the work of Keigo Hirakawa, Thomas Parks, and Paul Lee. */ @@ -3942,6 +4247,34 @@ } #undef TS +void CLASS median_filter () +{ + ushort (*pix)[4]; + int pass, c, i, j, k, med[9]; + static const uchar opt[] = /* Optimal 9-element median search */ + { 1,2, 4,5, 7,8, 0,1, 3,4, 6,7, 1,2, 4,5, 7,8, + 0,3, 5,8, 4,7, 3,6, 1,4, 2,5, 4,7, 4,2, 6,4, 4,2 }; + + for (pass=1; pass <= med_passes; pass++) { + if (verbose) + fprintf (stderr,_("Median filter pass %d...\n"), pass); + for (c=0; c < 3; c+=2) { + for (pix = image; pix < image+width*height; pix++) + pix[0][3] = pix[0][c]; + for (pix = image+width; pix < image+width*(height-1); pix++) { + if ((pix-image+1) % width < 2) continue; + for (k=0, i = -width; i <= width; i += width) + for (j = i-1; j <= i+1; j++) + med[k++] = pix[j][3] - pix[j][1]; + for (i=0; i < sizeof opt; i+=2) + if (med[opt[i]] > med[opt[i+1]]) + SWAP (med[opt[i]] , med[opt[i+1]]); + pix[0][c] = CLIP(med[4] + pix[0][1]); + } + } + } +} + void CLASS blend_highlights() { int clip=INT_MAX, row, col, c, i, j; @@ -4119,15 +4452,14 @@ 0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb, 0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f } }; unsigned offset=0, entries, tag, type, len, save, c; - unsigned ver97=0, serial=0, i, wb[4]={0,0,0,0}; + unsigned ver97=0, serial=0, i, wbi=0, wb[4]={0,0,0,0}; uchar buf97[324], ci, cj, ck; - short sorder; + short sorder=order; char buf[10]; /* The MakerNote might have its own TIFF header (possibly with its own byte-order!), or it might just be a table. */ - sorder = order; fread (buf, 1, 10, ifp); if (!strncmp (buf,"KDK" ,3) || /* these aren't TIFF tables */ !strncmp (buf,"VER" ,3) || @@ -4183,17 +4515,20 @@ aperture = pow (2, i/64.0); if ((i=get2()) != 0xffff) shutter = pow (2, (short) i/-32.0); - shot_order = (get4(),get2(),get2()); + wbi = (get2(),get2()); + shot_order = (get2(),get2()); } if (tag == 8 && type == 4) shot_order = get4(); + if (tag == 9 && !strcmp(make,"Canon")) + fread (artist, 64, 1, ifp); if (tag == 0xc && len == 4) { - cam_mul[0] = getrat(); - cam_mul[2] = getrat(); + cam_mul[0] = getreal(type); + cam_mul[2] = getreal(type); } if (tag == 0x10 && type == 4) unique_id = get4(); - if (tag == 0x11 && is_raw) { + if (tag == 0x11 && is_raw && !strncmp(make,"NIKON",5)) { fseek (ifp, get4()+base, SEEK_SET); parse_tiff_ifd (base); } @@ -4201,6 +4536,8 @@ fseek (ifp, 1248, SEEK_CUR); goto get2_256; } + if (tag == 0x15 && type == 2 && is_raw) + fread (model, 64, 1, ifp); if (strstr(make,"PENTAX")) { if (tag == 0x1b) tag = 0x1018; if (tag == 0x1c) tag = 0x1017; @@ -4215,6 +4552,11 @@ raw_width = get2(); filters = 0x61616161; } + if (tag == 0x29 && type == 1) { + c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0; + fseek (ifp, 8 + c*32, SEEK_CUR); + FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get4(); + } if ((tag == 0x81 && type == 7) || (tag == 0x100 && type == 7) || (tag == 0x280 && type == 1)) { @@ -4225,10 +4567,8 @@ thumb_offset += base; if (tag == 0x89 && type == 4) thumb_length = get4(); - if (tag == 0x8c) - curve_offset = ftell(ifp) + 2112; - if (tag == 0x96) - curve_offset = ftell(ifp) + 2; + if (tag == 0x8c || tag == 0x96) + meta_offset = ftell(ifp); if (tag == 0x97) { for (i=0; i < 4; i++) ver97 = (ver97 << 4) + fgetc(ifp)-'0'; @@ -4249,6 +4589,10 @@ fread (buf97, 324, 1, ifp); } } + if (tag == 0xa4 && type == 3) { + fseek (ifp, wbi*48, SEEK_CUR); + FORC3 cam_mul[c] = get2(); + } if (tag == 0xa7 && ver97 >> 8 == 2) { ci = xlat[0][serial & 0xff]; cj = xlat[1][fgetc(ifp)^fgetc(ifp)^fgetc(ifp)^fgetc(ifp)]; @@ -4257,6 +4601,9 @@ buf97[i] ^= (cj += ci * ck++); FORC4 cam_mul[c ^ (c >> 1)] = sget2 (buf97 + (ver97 == 0x205 ? 14:6) + c*2); + if (ver97 == 0x209) + FORC4 cam_mul[c ^ (c >> 1) ^ 1] = + sget2 (buf97 + 10 + c*2); } if (tag == 0x200 && len == 3) shot_order = (get4(),get4()); @@ -4293,11 +4640,9 @@ else goto next; goto get2_256; } - if (((tag == 0x1011 && len == 9) || tag == 0x20400200) && use_camera_wb) { + if ((tag == 0x1011 && len == 9) || tag == 0x20400200) for (i=0; i < 3; i++) - FORC3 rgb_cam[i][c] = ((short) get2()) / 256.0; - raw_color = rgb_cam[0][0] < 1; - } + FORC3 cmatrix[i][c] = ((short) get2()) / 256.0; if ((tag == 0x1012 || tag == 0x20400600) && len == 4) for (black = i=0; i < 4; i++) black += get2() << 2; @@ -4324,6 +4669,8 @@ fseek (ifp, i, SEEK_CUR); get2_rggb: FORC4 cam_mul[c ^ (c >> 1)] = get2(); + fseek (ifp, 22, SEEK_CUR); + FORC4 sraw_mul[c ^ (c >> 1)] = get2(); } next: fseek (ifp, save, SEEK_SET); @@ -4342,7 +4689,6 @@ char str[20]; int i; - if (timestamp) return; str[19] = 0; if (reversed) for (i=19; i--; ) str[i] = fgetc(ifp); @@ -4368,15 +4714,15 @@ while (entries--) { tiff_get (base, &tag, &type, &len, &save); switch (tag) { - case 33434: shutter = getrat(); break; - case 33437: aperture = getrat(); break; + case 33434: shutter = getreal(type); break; + case 33437: aperture = getreal(type); break; case 34855: iso_speed = get2(); break; case 36867: case 36868: get_timestamp(0); break; - case 37377: if ((expo = -getrat()) < 128) + case 37377: if ((expo = -getreal(type)) < 128) shutter = pow (2, expo); break; - case 37378: aperture = pow (2, getrat()/2); break; - case 37386: focal_len = getrat(); break; + case 37378: aperture = pow (2, getreal(type)/2); break; + case 37386: focal_len = getreal(type); break; case 37500: parse_makernote (base, 0); break; case 40962: if (kodak) raw_width = get4(); break; case 40963: if (kodak) raw_height = get4(); break; @@ -4389,6 +4735,27 @@ } } +void CLASS parse_gps (int base) +{ + unsigned entries, tag, type, len, save, c; + + entries = get2(); + while (entries--) { + tiff_get (base, &tag, &type, &len, &save); + switch (tag) { + case 1: case 3: case 5: + gpsdata[29+tag/2] = getc(ifp); break; + case 2: case 4: case 7: + FORC(6) gpsdata[tag/3*6+c] = get4(); break; + case 6: + FORC(2) gpsdata[18+c] = get4(); break; + case 18: case 29: + fgets ((char *) (gpsdata+14+tag/3), MIN(len,12), ifp); + } + fseek (ifp, save, SEEK_SET); + } +} + void CLASS romm_coeff (float romm_cam[3][3]) { static const float rgb_romm[3][3] = /* ROMM == Kodak ProPhoto */ @@ -4397,10 +4764,10 @@ { -0.008565, -0.153273, 1.161839 } }; int i, j, k; - for (raw_color = i=0; i < 3; i++) + for (i=0; i < 3; i++) for (j=0; j < 3; j++) - for (rgb_cam[i][j] = k=0; k < 3; k++) - rgb_cam[i][j] += rgb_romm[i][k] * romm_cam[k][j]; + for (cmatrix[i][j] = k=0; k < 3; k++) + cmatrix[i][j] += rgb_romm[i][k] * romm_cam[k][j]; } void CLASS parse_mos (int offset) @@ -4433,8 +4800,13 @@ if ((unsigned) i < sizeof mod / sizeof (*mod)) strcpy (model, mod[i]); } - if (!strcmp(data,"CaptProf_color_matrix") && use_camera_wb) { + if (!strcmp(data,"icc_camera_to_tone_matrix")) { for (i=0; i < 9; i++) + romm_cam[0][i] = int_to_float(get4()); + romm_coeff (romm_cam); + } + if (!strcmp(data,"CaptProf_color_matrix")) { + for (i=0; i < 9; i++) fscanf (ifp, "%f", &romm_cam[0][i]); romm_coeff (romm_cam); } @@ -4514,6 +4886,7 @@ uchar cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256]; double dblack, cc[4][4], cm[4][3], cam_xyz[4][3], num; double ab[]={ 1,1,1,1 }, asn[] = { 0,0,0,0 }, xyz[] = { 1,1,1 }; + unsigned sony_curve[] = { 0,0,0,0,0,4095 }; unsigned *buf, sony_offset=0, sony_length=0, sony_key=0; struct jhead jh; FILE *sfp; @@ -4544,6 +4917,11 @@ fseek (ifp, 12, SEEK_CUR); FORC3 cam_mul[c] = get2(); break; + case 46: + if (type != 7 || fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) break; + thumb_offset = ftell(ifp) - 2; + thumb_length = len; + break; case 2: case 256: /* ImageWidth */ tiff_ifd[ifd].width = getint(type); break; @@ -4560,6 +4938,9 @@ case 262: /* PhotometricInterpretation */ tiff_ifd[ifd].phint = get2(); break; + case 270: /* ImageDescription */ + fread (desc, 512, 1, ifp); + break; case 271: /* Make */ fgets (make, 64, ifp); break; @@ -4602,12 +4983,21 @@ case 306: /* DateTime */ get_timestamp(0); break; + case 315: /* Artist */ + fread (artist, 64, 1, ifp); + break; + case 322: /* TileWidth */ + tile_width = getint(type); + break; case 323: /* TileLength */ tile_length = getint(type); break; case 324: /* TileOffsets */ tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4(); - if (len == 4) load_raw = &CLASS sinar_4shot_load_raw; + if (len == 4) { + load_raw = &CLASS sinar_4shot_load_raw; + is_raw = 5; + } break; case 330: /* SubIFDs */ if (!strcmp(model,"DSLR-A100") && tiff_ifd[ifd].width == 3872) { @@ -4625,9 +5015,19 @@ strcpy (make, "Sarnoff"); maximum = 0xfff; break; + case 28688: + FORC4 sony_curve[c+1] = get2() >> 2 & 0xfff; + for (i=0; i < 5; i++) + for (j = sony_curve[i]+1; j <= sony_curve[i+1]; j++) + curve[j] = curve[j-1] + (1 << i); + break; case 29184: sony_offset = get4(); break; case 29185: sony_length = get4(); break; case 29217: sony_key = get4(); break; + case 29264: + parse_minolta (ftell(ifp)); + raw_width = 0; + break; case 29443: FORC4 cam_mul[c ^ (c < 2)] = get2(); break; @@ -4650,10 +5050,10 @@ parse_kodak_ifd (base); break; case 33434: /* ExposureTime */ - shutter = getrat(); + shutter = getreal(type); break; case 33437: /* FNumber */ - aperture = getrat(); + aperture = getreal(type); break; case 34306: /* Leaf white balance */ FORC4 cam_mul[c ^ 1] = 4096.0 / get2(); @@ -4679,6 +5079,10 @@ fseek (ifp, get4()+base, SEEK_SET); parse_exif (base); break; + case 34853: /* GPSInfo tag */ + fseek (ifp, get4()+base, SEEK_SET); + parse_gps (base); + break; case 34675: /* InterColorProfile */ case 50831: /* AsShotICCProfile */ profile_offset = ftell(ifp); @@ -4688,15 +5092,15 @@ kodak_cbpp = get4(); break; case 37386: /* FocalLength */ - focal_len = getrat(); + focal_len = getreal(type); break; case 37393: /* ImageNumber */ shot_order = getint(type); break; case 37400: /* old Kodak KDC tag */ for (raw_color = i=0; i < 3; i++) { - getrat(); - FORC3 rgb_cam[i][c] = getrat(); + getreal(type); + FORC3 rgb_cam[i][c] = getreal(type); } break; case 46275: /* Imacon tags */ @@ -4712,6 +5116,11 @@ width = raw_width - left_margin - (get4() & 7); top_margin = get4() & 7; height = raw_height - top_margin - (get4() & 7); + if (raw_width == 7262) { + height = 5444; + width = 7244; + left_margin = 7; + } fseek (ifp, 52, SEEK_CUR); FORC3 cam_mul[c] = getreal(11); fseek (ifp, 114, SEEK_CUR); @@ -4720,6 +5129,13 @@ if (flip % 180 == 90) SWAP(width,height); filters = flip = 0; } + sprintf (model, "Ixpress %d-Mp", height*width/1000000); + load_raw = &CLASS imacon_full_load_raw; + if (filters) { + if (left_margin & 1) filters = 0x61616161; + load_raw = &CLASS unpacked_load_raw; + } + maximum = 0xffff; break; case 50454: /* Sinar tag */ case 50455: @@ -4730,6 +5146,17 @@ sscanf (cp+8, "%f %f %f", cam_mul, cam_mul+1, cam_mul+2); free (cbuf); break; + case 50459: /* Hasselblad tag */ + i = order; + j = ftell(ifp); + c = tiff_nifds; + order = get2(); + fseek (ifp, j+(get2(),get4()), SEEK_SET); + parse_tiff_ifd (j); + maximum = 0xffff; + tiff_nifds = c; + order = i; + break; case 50706: /* DNGVersion */ FORC4 dng_version = (dng_version << 8) + fgetc(ifp); break; @@ -4764,36 +5191,34 @@ maximum = getint(type); break; case 50718: /* DefaultScale */ - pixel_aspect = getrat(); - pixel_aspect /= getrat(); + pixel_aspect = getreal(type); + pixel_aspect /= getreal(type); break; case 50721: /* ColorMatrix1 */ case 50722: /* ColorMatrix2 */ FORCC for (j=0; j < 3; j++) - cm[c][j] = getrat(); + cm[c][j] = getreal(type); use_cm = 1; break; case 50723: /* CameraCalibration1 */ case 50724: /* CameraCalibration2 */ for (i=0; i < colors; i++) - FORCC cc[i][c] = getrat(); + FORCC cc[i][c] = getreal(type); case 50727: /* AnalogBalance */ - FORCC ab[c] = getrat(); + FORCC ab[c] = getreal(type); break; case 50728: /* AsShotNeutral */ FORCC asn[c] = getreal(type); break; case 50729: /* AsShotWhiteXY */ - xyz[0] = getrat(); - xyz[1] = getrat(); + xyz[0] = getreal(type); + xyz[1] = getreal(type); xyz[2] = 1 - xyz[0] - xyz[1]; FORC3 xyz[c] /= d65_white[c]; break; case 50740: /* DNGPrivateData */ if (dng_version) break; - i = order; parse_minolta (j = get4()+base); - order = i; fseek (ifp, j, SEEK_SET); parse_tiff_ifd (base); break; @@ -4873,6 +5298,7 @@ for (i=0; i < tiff_nifds; i++) { if (max_samp < tiff_ifd[i].samples) max_samp = tiff_ifd[i].samples; + if (max_samp > 3) max_samp = 3; if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) && tiff_ifd[i].width*tiff_ifd[i].height > raw_width*raw_height) { raw_width = tiff_ifd[i].width; @@ -4882,7 +5308,6 @@ data_offset = tiff_ifd[i].offset; tiff_flip = tiff_ifd[i].flip; tiff_samples = tiff_ifd[i].samples; - fuji_secondary = tiff_samples == 2; raw = i; } } @@ -4894,6 +5319,8 @@ switch (tiff_bps) { case 8: load_raw = &CLASS eight_bit_load_raw; break; case 12: load_raw = &CLASS packed_12_load_raw; + if (!strncmp(make,"NIKON",5)) + load_raw = &CLASS nikon_load_raw; if (strncmp(make,"PENTAX",6)) break; case 14: case 16: load_raw = &CLASS unpacked_load_raw; break; @@ -4907,8 +5334,14 @@ load_raw = &CLASS lossless_jpeg_load_raw; break; case 262: load_raw = &CLASS kodak_262_load_raw; break; + case 32767: + load_raw = &CLASS sony_arw2_load_raw; break; + case 32769: + load_raw = &CLASS nikon_load_raw; break; case 32773: load_raw = &CLASS packed_12_load_raw; break; + case 34713: + load_raw = &CLASS nikon_compressed_load_raw; break; case 65535: load_raw = &CLASS pentax_k10_load_raw; break; case 65000: @@ -4917,10 +5350,14 @@ case 6: load_raw = &CLASS kodak_ycbcr_load_raw; filters = 0; break; case 32803: load_raw = &CLASS kodak_65000_load_raw; } + case 32867: break; + default: is_raw = 0; } if (!dng_version && tiff_samples == 3) if (tiff_ifd[raw].bytes && tiff_bps != 14 && tiff_bps != 2048) is_raw = 0; + if (!dng_version && tiff_bps == 8 && tiff_compress == 1 && + tiff_ifd[raw].phint == 1) is_raw = 0; for (i=0; i < tiff_nifds; i++) if (i != raw && tiff_ifd[i].samples == max_samp && tiff_ifd[i].width * tiff_ifd[i].height / SQR(tiff_ifd[i].bps+1) > @@ -4954,6 +5391,7 @@ void CLASS parse_minolta (int base) { int save, tag, len, offset, high=0, wide=0, i, c; + short sorder=order; fseek (ifp, base, SEEK_SET); if (fgetc(ifp) || fgetc(ifp)-'M' || fgetc(ifp)-'R') return; @@ -4982,6 +5420,7 @@ } raw_height = high; raw_width = wide; + order = sorder; } /* @@ -5079,6 +5518,8 @@ if ((((type >> 8) + 8) | 8) == 0x38) parse_ciff (ftell(ifp), len); /* Parse a sub-table */ + if (type == 0x0810) + fread (artist, 64, 1, ifp); if (type == 0x080a) { fread (make, 64, 1, ifp); fseek (ifp, strlen(make) - 63, SEEK_CUR); @@ -5261,7 +5702,7 @@ romm_coeff (romm_cam); break; case 0x107: - FORC3 cam_mul[c] = pre_mul[c] = getreal(11); + FORC3 cam_mul[c] = getreal(11); break; case 0x108: raw_width = data; break; case 0x109: raw_height = data; break; @@ -5404,6 +5845,55 @@ if (ver == 9) load_raw = &CLASS smal_v9_load_raw; } +void CLASS parse_cine() +{ + unsigned off_head, off_setup, off_image, i; + + order = 0x4949; + fseek (ifp, 4, SEEK_SET); + is_raw = get2() == 2; + fseek (ifp, 14, SEEK_CUR); + is_raw *= get4(); + off_head = get4(); + off_setup = get4(); + off_image = get4(); + timestamp = get4(); + if ((i = get4())) timestamp = i; + fseek (ifp, off_head+4, SEEK_SET); + raw_width = get4(); + raw_height = get4(); + switch (get2(),get2()) { + case 8: load_raw = &CLASS eight_bit_load_raw; break; + case 16: load_raw = &CLASS unpacked_load_raw; + } + fseek (ifp, off_setup+792, SEEK_SET); + strcpy (make, "CINE"); + sprintf (model, "%d", get4()); + fseek (ifp, 12, SEEK_CUR); + switch ((i=get4()) & 0xffffff) { + case 3: filters = 0x94949494; break; + case 4: filters = 0x49494949; break; + default: is_raw = 0; + } + fseek (ifp, 72, SEEK_CUR); + switch ((get4()+3600) % 360) { + case 270: flip = 4; break; + case 180: flip = 1; break; + case 90: flip = 7; break; + case 0: flip = 2; + } + cam_mul[0] = getreal(11); + cam_mul[2] = getreal(11); + maximum = ~(-1 << get4()); + fseek (ifp, 668, SEEK_CUR); + shutter = get4()/1000000000.0; + fseek (ifp, off_image, SEEK_SET); + if (shot_select < is_raw) + fseek (ifp, shot_select*8, SEEK_CUR); + data_offset = (INT64) get4() + 8; + data_offset += (INT64) get4() << 32; +} + char * CLASS foveon_gets (int offset, char *str, int len) { int i; @@ -5508,6 +5998,8 @@ const char *prefix; short black, trans[12]; } table[] = { + { "Apple QuickTake", 0, /* DJC */ + { 17576,-3191,-3318,5210,6733,-1942,9031,1280,-124 } }, { "Canon EOS D2000", 0, { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } }, { "Canon EOS D6000", 0, @@ -5524,14 +6016,20 @@ { 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } }, { "Canon EOS 30D", 0, { 6257,-303,-1000,-7880,15621,2396,-1714,1904,7046 } }, + { "Canon EOS 40D", 0, + { 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 } }, { "Canon EOS 350D", 0, { 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } }, { "Canon EOS 400D", 0, { 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } }, + { "Canon EOS-1Ds Mark III", 0, + { 5859,-211,-930,-8255,16017,2353,-1732,1887,7448 } }, { "Canon EOS-1Ds Mark II", 0, { 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } }, { "Canon EOS-1D Mark II N", 0, { 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } }, + { "Canon EOS-1D Mark III", 0, + { 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } }, { "Canon EOS-1D Mark II", 0, { 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 } }, { "Canon EOS-1DS", 0, @@ -5554,6 +6052,8 @@ { 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } }, { "Canon PowerShot G6", 0, { 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } }, + { "Canon PowerShot G9", 0, + { 7368,-2141,-598,-5621,13254,2625,-1418,1696,5743 } }, { "Canon PowerShot Pro1", 0, { 10062,-3522,-999,-7643,15117,2730,-765,817,7323 } }, { "Canon PowerShot Pro70", 34, @@ -5576,8 +6076,18 @@ { 15591,-6402,-1592,-5365,13198,2168,-1300,1824,5075 } }, { "Canon PowerShot A620", 0, /* DJC */ { 15265,-6193,-1558,-4125,12116,2010,-888,1639,5220 } }, + { "Canon PowerShot A640", 0, /* DJC */ + { 13124,-5329,-1390,-3602,11658,1944,-1612,2863,4885 } }, + { "Canon PowerShot A650", 0, /* DJC */ + { 9427,-3036,-959,-2581,10671,1911,-1039,1982,4430 } }, { "Canon PowerShot S3 IS", 0, /* DJC */ { 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } }, + { "CINE 650", 0, + { 3390,480,-500,-800,3610,340,-550,2336,1192 } }, + { "CINE 660", 0, + { 3390,480,-500,-800,3610,340,-550,2336,1192 } }, + { "CINE", 0, + { 20183,-4295,-423,-3940,15330,3985,-280,4870,9800 } }, { "Contax N Digital", 0, { 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 } }, { "EPSON R-D1", 0, @@ -5597,7 +6107,7 @@ { "FUJIFILM FinePix S3Pro", 0, { 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } }, { "FUJIFILM FinePix S5Pro", 0, - { 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } }, + { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } }, { "FUJIFILM FinePix S5000", 0, { 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } }, { "FUJIFILM FinePix S5100", 0, @@ -5620,10 +6130,12 @@ { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } }, { "FUJIFILM FinePix S9600", 0, { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } }, + { "FUJIFILM IS-1", 0, + { 21461,-10807,-1441,-2332,10599,1999,289,875,7703 } }, { "Imacon Ixpress", 0, /* DJC */ { 7025,-1415,-704,-5188,13765,1424,-1248,2742,6038 } }, - { "KODAK NC2000", 0, /* DJC */ - { 16475,-6903,-1218,-851,10375,477,2505,-7,1020 } }, + { "KODAK NC2000", 0, + { 13891,-6055,-803,-465,9919,642,2121,82,1291 } }, { "Kodak DCS315C", 8, { 17523,-4827,-2510,756,8546,-137,6113,1649,2250 } }, { "Kodak DCS330C", 8, @@ -5670,6 +6182,8 @@ { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } }, { "Leaf Valeo 6", 0, { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } }, + { "Leaf Aptus 54S", 0, + { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } }, { "Leaf Aptus 65", 0, { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } }, { "Leaf Aptus 75", 0, @@ -5710,6 +6224,8 @@ { 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } }, { "NIKON D2X", 0, { 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 } }, + { "NIKON D40X", 0, + { 8819,-2543,-911,-9025,16928,2151,-1329,1213,8449 } }, { "NIKON D40", 0, { 6992,-1668,-806,-8138,15748,2543,-874,850,7897 } }, { "NIKON D50", 0, @@ -5720,10 +6236,16 @@ { 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 } }, { "NIKON D200", 0, { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } }, + { "NIKON D300", 0, + { 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } }, + { "NIKON D3", 0, + { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } }, { "NIKON E950", 0, /* DJC */ { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } }, { "NIKON E995", 0, /* copied from E5000 */ { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, + { "NIKON E2100", 0, /* copied from Z2, new white balance */ + { 13142,-4152,-1596,-4655,12374,2282,-1769,2696,6711} }, { "NIKON E2500", 0, { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } }, { "NIKON E4300", 0, /* copied from Minolta DiMAGE Z2 */ @@ -5762,10 +6284,16 @@ { 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } }, { "OLYMPUS E-330", 0, { 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } }, + { "OLYMPUS E-3", 0, + { 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } }, { "OLYMPUS E-400", 0, { 6169,-1483,-21,-7107,14761,2536,-2904,3580,8568 } }, + { "OLYMPUS E-410", 0, + { 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } }, { "OLYMPUS E-500", 0, { 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 } }, + { "OLYMPUS E-510", 0, + { 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } }, { "OLYMPUS SP350", 0, { 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 } }, { "OLYMPUS SP3", 0, @@ -5774,6 +6302,10 @@ { 9493,-3415,-666,-5211,12334,3260,-1548,2262,6482 } }, { "OLYMPUS SP510UZ", 0, { 10593,-3607,-1010,-5881,13127,3084,-1200,1805,6721 } }, + { "OLYMPUS SP550UZ", 0, + { 11597,-4006,-1049,-5432,12799,2957,-1029,1750,6516 } }, + { "OLYMPUS SP560UZ", 0, + { 10915,-3677,-982,-5587,12986,2911,-1168,1968,6223 } }, { "PENTAX *ist DL2", 0, { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } }, { "PENTAX *ist DL", 0, @@ -5790,10 +6322,14 @@ { 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 } }, { "Panasonic DMC-FZ8", 0, { 8986,-2755,-802,-6341,13575,3077,-1476,2144,6379 } }, + { "Panasonic DMC-FZ18", 0, + { 9932,-3060,-935,-5809,13331,2753,-1267,2155,5575 } }, { "Panasonic DMC-FZ30", 0, { 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } }, { "Panasonic DMC-FZ50", 0, /* aka "LEICA V-LUX1" */ { 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } }, + { "Panasonic DMC-L10", 0, + { 8025,-1942,-1050,-7920,15904,2100,-2456,3005,7039 } }, { "Panasonic DMC-L1", 0, /* aka "LEICA DIGILUX 3" */ { 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } }, { "Panasonic DMC-LC1", 0, /* aka "LEICA DIGILUX 2" */ @@ -5802,6 +6338,14 @@ { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } }, { "Panasonic DMC-LX2", 0, /* aka "LEICA D-LUX3" */ { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } }, + { "Phase One H 20", 0, /* DJC */ + { 1313,1855,-109,-6715,15908,808,-327,1840,6020 } }, + { "Phase One P 2", 0, + { 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } }, + { "Phase One P 30", 0, + { 4516,-245,-37,-7020,14976,2173,-3206,4671,7087 } }, + { "Phase One P 45", 0, + { 5053,-24,-117,-5684,14076,1702,-2619,4492,5849 } }, { "SAMSUNG GX-1", 0, { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } }, { "Sinar", 0, /* DJC */ @@ -5813,7 +6357,13 @@ { "SONY DSC-V3", 0, { 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } }, { "SONY DSLR-A100", 0, - { 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } } + { 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } }, + { "SONY DSLR-A200", 0, + { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } }, + { "SONY DSLR-A350", 0, /* copied from above */ + { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } }, + { "SONY DSLR-A700", 254, + { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } } }; double cam_xyz[4][3]; char name[130]; @@ -5886,11 +6436,14 @@ { 62464, "Kodak", "DC20" ,0 }, { 124928, "Kodak", "DC20" ,0 }, { 1652736, "Kodak", "DCS200" ,0 }, + { 4159302, "Kodak", "C330" ,0 }, + { 4162462, "Kodak", "C330" ,0 }, { 311696, "ST Micro", "STV680 VGA" ,0 }, /* SPYz */ { 614400, "Kodak", "KAI-0340" ,0 }, { 787456, "Creative", "PC-CAM 600" ,0 }, { 1138688, "Minolta", "RD175" ,0 }, { 3840000, "Foculus", "531C" ,0 }, + { 786432, "AVT", "F-080C" ,0 }, { 1447680, "AVT", "F-145C" ,0 }, { 1920000, "AVT", "F-201C" ,0 }, { 5067304, "AVT", "F-510C" ,0 }, @@ -5902,10 +6455,14 @@ { 6624000, "Pixelink", "A782" ,0 }, { 13248000, "Pixelink", "A782" ,0 }, { 6291456, "RoverShot","3320AF" ,0 }, + { 6553440, "Canon", "PowerShot A460",0 }, + { 6653280, "Canon", "PowerShot A530",0 }, { 657312... [truncated message content] |