[Hdrflow-svn] SF.net SVN: hdrflow: [286] trunk/lib/extras/src/raw
Status: Pre-Alpha
Brought to you by:
glslang
|
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] |