Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

11138 lines (10652 sloc) 342.961 kb
#ifndef IGNOREALL
/*
dcraw.c -- Dave Coffin's raw photo decoder
Copyright 1997-2012 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 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.
*If you have not modified dcraw.c in any way, a link to my
homepage qualifies as "full source code".
$Revision: 1.454 $
$Date: 2012/12/23 19:25:36 $
*/
/*@out DEFINES
#ifndef USE_JPEG
#define NO_JPEG
#endif
#ifndef USE_JASPER
#define NO_JASPER
#endif
@end DEFINES */
#define NO_LCMS
#define DCRAW_VERBOSE
//@out DEFINES
#define DCRAW_VERSION "9.17"
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#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>
#include <sys/types.h>
#ifdef NODEPS
#define NO_JASPER
#define NO_JPEG
#define NO_LCMS
#endif
#ifndef NO_JASPER
#include <jasper/jasper.h> /* Decode RED camera movies */
#endif
#ifndef NO_JPEG
#include <jpeglib.h> /* Decode compressed Kodak DC120 photos */
#endif /* and Adobe Lossy DNGs */
//@end DEFINES
#ifndef NO_LCMS
#include <lcms.h> /* Support color profiles */
#endif
//@out DEFINES
#ifdef LOCALEDIR
#include <libintl.h>
#define _(String) gettext(String)
#else
#define _(String) (String)
#endif
//@end DEFINES
#if defined(DJGPP) || defined(__MINGW32__)
#define fseeko fseek
#define ftello ftell
#else
#define fgetc getc_unlocked
#endif
//@out DEFINES
#ifdef __CYGWIN__
#include <io.h>
#endif
#ifdef WIN32
#include <sys/utime.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define snprintf _snprintf
#define strcasecmp stricmp
#define strncasecmp strnicmp
//@end DEFINES
typedef __int64 INT64;
typedef unsigned __int64 UINT64;
//@out DEFINES
#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
//@end DEFINES
#if !defined(uchar)
#define uchar unsigned char
#endif
#if !defined(ushort)
#define ushort unsigned short
#endif
/*
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, *ofp;
short order;
const char *ifname;
char *meta_data;
char cdesc[5], desc[512], make[64], model[64], model2[64], artist[64];
float flash_used, canon_ev, iso_speed, shutter, aperture, focal_len;
time_t timestamp;
unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id;
off_t strip_offset, data_offset;
off_t thumb_offset, meta_offset, profile_offset;
unsigned thumb_length, meta_length, profile_length;
unsigned thumb_misc, *oprof, fuji_layout, shot_select=0, multi_out=0;
unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress;
unsigned black, cblack[4], maximum, mix_green, raw_color, zero_is_bad;
unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error;
unsigned tile_width, tile_length, gpsdata[32], load_flags;
ushort raw_height, raw_width, height, width, top_margin, left_margin;
ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height;
ushort *raw_image, (*image)[4];
ushort white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4];
int mask[8][4], flip, tiff_flip, colors;
double pixel_aspect, aber[4]={1,1,1,1}, gamm[6]={ 0.45,4.5,0,0,0,0 };
float bright=1, user_mul[4]={0,0,0,0}, threshold=0;
int half_size=0, four_color_rgb=0, document_mode=0, highlight=0;
int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=-1;
int output_color=1, output_bps=8, output_tiff=0, med_passes=0;
int no_auto_bright=0;
unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX };
float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4];
const double xyz_rgb[3][3] = { /* XYZ from RGB */
{ 0.412453, 0.357580, 0.180423 },
{ 0.212671, 0.715160, 0.072169 },
{ 0.019334, 0.119193, 0.950227 } };
const float d65_white[3] = { 0.950456, 1, 1.088754 };
int histogram[4][0x2000];
void (*write_thumb)(), (*write_fun)();
void (*load_raw)(), (*thumb_load_raw)();
jmp_buf failure;
struct decode {
struct decode *branch[2];
int leaf;
} first_decode[2048], *second_decode, *free_decode;
struct tiff_ifd {
int t_width, t_height, bps, comp, phint, offset, t_flip, samples, bytes;
int t_tile_width, t_tile_length;
} tiff_ifd[10];
struct ph1 {
int format, key_off, t_black, black_off, split_col, tag_21a;
float tag_210;
} ph1;
#define CLASS
//@out DEFINES
#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))
#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=a+b; b=a-b; a=a-b; }
/*
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 RAW(row,col) \
raw_image[(row)*raw_width+(col)]
//@end DEFINES
#define FC(row,col) \
(filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)
//@out DEFINES
#define BAYER(row,col) \
image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)]
#define BAYER2(row,col) \
image[((row) >> shrink)*iwidth + ((col) >> shrink)][fcol(row,col)]
//@end DEFINES
/* @out COMMON
#include <math.h>
#define CLASS LibRaw::
#include "libraw/libraw_types.h"
#define LIBRAW_LIBRARY_BUILD
#define LIBRAW_IO_REDEFINED
#include "libraw/libraw.h"
#include "internal/defines.h"
#include "internal/var_defines.h"
#include "internal/libraw_bytebuffer.h"
@end COMMON */
//@out COMMON
int CLASS fcol (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 } };
static const char filter2[6][6] =
{ { 1,1,0,1,1,2 },
{ 1,1,2,1,1,0 },
{ 2,0,1,0,2,1 },
{ 1,1,2,1,1,0 },
{ 1,1,0,1,1,2 },
{ 0,2,1,2,0,1 } };
if (filters == 1) return filter[(row+top_margin)&15][(col+left_margin)&15];
if (filters == 2) return filter2[(row+6) % 6][(col+6) % 6];
return FC(row,col);
}
#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
//@end COMMON
void CLASS merror (void *ptr, const 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%llx\n"), (INT64) ftello(ifp));
}
data_error++;
}
//@out COMMON
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);
}
}
void CLASS read_shorts (ushort *pixel, int count)
{
if (fread (pixel, 2, count, ifp) < count) derror();
if ((order == 0x4949) == (ntohs(0x1234) == 0x1234))
swab ((char*)pixel, (char*)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: ;
}
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 *pix;
int irow, row;
for (irow=row=0; irow < height; irow++) {
if (fread (data, 1, 1120, ifp) < 1120) derror();
pix = raw_image + row*raw_width;
for (dp=data; 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 );
}
if ((row+=2) > height) row = 1;
}
}
void CLASS canon_600_correct()
{
int row, col, val;
static const short mul[4][2] =
{ { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } };
for (row=0; row < height; row++)
for (col=0; col < width; col++) {
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);
canon_600_auto_wb();
canon_600_coeff();
maximum = (0x3ff - black) * 1109 >> 9;
black = 0;
}
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;
}
/*
getbits(-1) initializes the buffer
getbits(n) where 0 <= n <= 25 returns an n-bit integer
*/
unsigned CLASS getbithuff (int nbits, ushort *huff)
{
#ifdef LIBRAW_NOTHREADS
static unsigned bitbuf=0;
static int vbits=0, reset=0;
#else
#define bitbuf tls->getbits.bitbuf
#define vbits tls->getbits.vbits
#define reset tls->getbits.reset
#endif
unsigned c;
if (nbits == -1)
return bitbuf = vbits = reset = 0;
if (nbits == 0 || vbits < 0) return 0;
while (!reset && vbits < nbits && (c = fgetc(ifp)) != EOF &&
!(reset = zero_after_ff && c == 0xff && fgetc(ifp))) {
bitbuf = (bitbuf << 8) + (uchar) c;
vbits += 8;
}
c = bitbuf << (32-vbits) >> (32-nbits);
if (huff) {
vbits -= huff[c] >> 8;
c = (uchar) huff[c];
} else
vbits -= nbits;
if (vbits < 0) derror();
return c;
#ifndef LIBRAW_NOTHREADS
#undef bitbuf
#undef vbits
#undef reset
#endif
}
#define getbits(n) getbithuff(n,0)
#define gethuff(h) getbithuff(*h,h+1)
/*
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
*/
ushort * CLASS make_decoder_ref (const uchar **source)
{
int max, len, h, i, j;
const uchar *count;
ushort *huff;
count = (*source += 16) - 17;
for (max=16; max && !count[max]; max--);
huff = (ushort *) calloc (1 + (1 << max), sizeof *huff);
merror (huff, "make_decoder()");
huff[0] = max;
for (h=len=1; len <= max; len++)
for (i=0; i < count[len]; i++, ++*source)
for (j=0; j < 1 << (max-len); j++)
if (h <= 1 << max)
huff[h++] = len << 8 | **source;
return huff;
}
ushort * CLASS make_decoder (const uchar *source)
{
return make_decoder_ref (&source);
}
void CLASS crw_init_tables (unsigned table, ushort *huff[2])
{
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;
huff[0] = make_decoder ( first_tree[table]);
huff[1] = make_decoder (second_tree[table]);
}
/*
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_load_raw()
{
ushort *pixel, *prow, *huff[2];
int nblocks, lowbits, i, c, row, r, save, val;
int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2];
crw_init_tables (tiff_compress, huff);
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) {
pixel = raw_image + row*raw_width;
nblocks = MIN (8, raw_height-row) * raw_width >> 6;
for (block=0; block < nblocks; block++) {
memset (diffbuf, 0, sizeof diffbuf);
for (i=0; i < 64; i++ ) {
leaf = gethuff(huff[i > 0]);
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);
}
}
FORC(2) free (huff[c]);
}
//@end COMMON
/*
Not a full implementation of Lossless JPEG, just
enough to decode Canon, Kodak and Adobe DNG images.
*/
struct jhead {
int bits, high, wide, clrs, sraw, psv, restart, vpred[6];
ushort *huff[6], *free[4], *row;
};
//@out COMMON
int CLASS ljpeg_start (struct jhead *jh, int info_only)
{
int c, tag, len;
uchar data[0x10000];
const uchar *dp;
memset (jh, 0, sizeof *jh);
jh->restart = INT_MAX;
fread (data, 2, 1, ifp);
if (data[1] != 0xd8) return 0;
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 0xffc3:
jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3;
case 0xffc0:
jh->bits = data[0];
jh->high = data[1] << 8 | data[2];
jh->wide = data[3] << 8 | data[4];
jh->clrs = data[5] + jh->sraw;
if (len == 9 && !dng_version) getc(ifp);
break;
case 0xffc4:
if (info_only) break;
for (dp = data; dp < data+len && (c = *dp++) < 4; )
jh->free[c] = jh->huff[c] = make_decoder_ref (&dp);
break;
case 0xffda:
jh->psv = data[1+data[0]*2];
jh->bits -= data[3+data[0]*2] & 15;
break;
case 0xffdd:
jh->restart = data[0] << 8 | data[1];
}
} while (tag != 0xffda);
if (info_only) return 1;
FORC(5) if (!jh->huff[c+1]) jh->huff[c+1] = jh->huff[c];
if (jh->sraw) {
FORC(4) jh->huff[2+c] = jh->huff[1];
FORC(jh->sraw) jh->huff[1+c] = jh->huff[0];
}
jh->row = (ushort *) calloc (jh->wide*jh->clrs, 4);
merror (jh->row, "ljpeg_start()");
return zero_after_ff = 1;
}
void CLASS ljpeg_end (struct jhead *jh)
{
int c;
FORC4 if (jh->free[c]) free (jh->free[c]);
free (jh->row);
}
int CLASS ljpeg_diff (ushort *huff)
{
int len, diff;
#ifdef LIBRAW_LIBRARY_BUILD
if(!huff)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
len = gethuff(huff);
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;
}
#ifdef LIBRAW_LIBRARY_BUILD
int CLASS ljpeg_diff_new (LibRaw_bit_buffer& bits, LibRaw_byte_buffer* buf,ushort *huff)
{
int len, diff;
if(!huff || !buf)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
len = bits._gethuff_lj(buf,*huff,huff+1);
if (len == 16 && (!dng_version || dng_version >= 0x1010000))
return -32768;
diff = bits._getbits_lj(buf,len);
if ((diff & (1 << (len-1))) == 0)
diff -= (1 << len) - 1;
return diff;
}
ushort * CLASS ljpeg_row_new (int jrow, struct jhead *jh, LibRaw_bit_buffer& bits,LibRaw_byte_buffer* bytes)
{
int col, c, diff, pred, spred=0;
ushort mark=0, *row[3];
if (jrow * jh->wide % jh->restart == 0) {
FORC(6) jh->vpred[c] = 1 << (jh->bits-1);
if (jrow) {
bytes->unseek2();
do mark = (mark << 8) + (c = bytes->get_byte());
while (c != EOF && mark >> 4 != 0xffd);
}
bits.reset();
}
FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1);
for (col=0; col < jh->wide; col++)
FORC(jh->clrs) {
diff = ljpeg_diff_new (bits,bytes,jh->huff[c]);
if (jh->sraw && c <= jh->sraw && (col | c))
pred = spred;
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();
if (c <= jh->sraw) spred = **row;
row[0]++; row[1]++;
}
return row[2];
}
#endif
ushort * CLASS ljpeg_row (int jrow, struct jhead *jh)
{
int col, c, diff, pred, spred=0;
ushort mark=0, *row[3];
if (jrow * jh->wide % jh->restart == 0) {
FORC(6) jh->vpred[c] = 1 << (jh->bits-1);
if (jrow) {
fseek (ifp, -2, SEEK_CUR);
do mark = (mark << 8) + (c = fgetc(ifp));
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++)
FORC(jh->clrs) {
diff = ljpeg_diff (jh->huff[c]);
if (jh->sraw && c <= jh->sraw && (col | c))
pred = spred;
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();
if (c <= jh->sraw) spred = **row;
row[0]++; row[1]++;
}
return row[2];
}
void CLASS lossless_jpeg_load_raw()
{
int jwide, jrow, jcol, val, i, row=0, col=0;
#ifndef LIBRAW_LIBRARY_BUILD
int jidx,j;
#endif
struct jhead jh;
ushort *rp;
#ifdef LIBRAW_LIBRARY_BUILD
int save_min = 0;
unsigned slicesW[16],slicesWcnt=0,slices;
unsigned *offset;
unsigned t_y=0,t_x=0,t_s=0,slice=0,pixelsInSlice,pixno;
if (!strcasecmp(make,"KODAK"))
save_min = 1;
#endif
#ifdef LIBRAW_LIBRARY_BUILD
if (cr2_slice[0]>15)
throw LIBRAW_EXCEPTION_IO_EOF; // change many slices
#else
if (cr2_slice[0]>15)
{
fprintf(stderr,"Too many CR2 slices: %d\n",cr2_slice[0]+1);
return;
}
#endif
if (!ljpeg_start (&jh, 0)) return;
#ifdef LIBRAW_LIBRARY_BUILD
if(jh.wide<1 || jh.high<1 || jh.clrs<1 || jh.bits <1)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
jwide = jh.wide * jh.clrs;
#ifdef LIBRAW_LIBRARY_BUILD
if(cr2_slice[0])
{
for(i=0;i<cr2_slice[0];i++)
slicesW[slicesWcnt++] = cr2_slice[1];
slicesW[slicesWcnt++] = cr2_slice[2];
}
else
{
// not sliced
slicesW[slicesWcnt++] = raw_width; // safe fallback
}
slices = slicesWcnt * jh.high;
if(!slices)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
offset = (unsigned*)calloc(slices+1,sizeof(offset[0]));
for(slice=0;slice<slices;slice++)
{
offset[slice] = (t_x + t_y * raw_width)| (t_s<<28);
if((offset[slice] & 0x0fffffff) >= raw_width * raw_height)
{
free(offset);
throw LIBRAW_EXCEPTION_IO_BADFILE;
}
t_y++;
if(t_y == jh.high)
{
t_y = 0;
t_x += slicesW[t_s++];
}
}
offset[slices] = offset[slices-1];
slice = 1; // next slice
pixno = offset[0];
pixelsInSlice = slicesW[0];
#endif
#ifdef LIBRAW_LIBRARY_BUILD
LibRaw_byte_buffer *buf=NULL;
if(data_size)
buf = ifp->make_byte_buffer(data_size);
LibRaw_bit_buffer bits;
#endif
for (jrow=0; jrow < jh.high; jrow++) {
#ifdef LIBRAW_LIBRARY_BUILD
if (buf)
rp = ljpeg_row_new (jrow, &jh,bits,buf);
else
#endif
rp = ljpeg_row (jrow, &jh);
if (load_flags & 1)
row = jrow & 1 ? height-1-jrow/2 : jrow/2;
for (jcol=0; jcol < jwide; jcol++) {
val = curve[*rp++];
#ifndef LIBRAW_LIBRARY_BUILD
// slow dcraw way to calculate row/col
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];
}
#else
// new fast one, but for data_size defined only (i.e. new CR2 format, not 1D/1Ds)
if(buf)
{
if(!(load_flags & 1))
row = pixno/raw_width;
col = pixno % raw_width;
pixno++;
if (0 == --pixelsInSlice)
{
if(slice > slices)
{
free(offset);
throw LIBRAW_EXCEPTION_IO_CORRUPT;
}
unsigned o = offset[slice++];
pixno = o & 0x0fffffff;
pixelsInSlice = slicesW[o>>28];
}
}
#endif
if(row>raw_height)
#ifdef LIBRAW_LIBRARY_BUILD
{
free(offset);
throw LIBRAW_EXCEPTION_IO_CORRUPT;
}
#else
longjmp (failure, 3);
#endif
if (raw_width == 3984 && (col -= 2) < 0)
col += (row--,raw_width);
if (row >= 0) RAW(row,col) = val;
#ifndef LIBRAW_LIBRARY_BUILD
if (++col >= raw_width)
col = (row++,0);
#else
if(!buf) // 1D or 1Ds case
if (++col >= raw_width)
col = (row++,0);
#endif
}
}
ljpeg_end (&jh);
#ifdef LIBRAW_LIBRARY_BUILD
if(buf)
delete buf;
free(offset);
#endif
}
void CLASS canon_sraw_load_raw()
{
struct jhead jh;
short *rp=0, (*ip)[4];
int jwide, slice, scol, ecol, row, col, jrow=0, jcol=0, pix[3], c;
int v[3]={0,0,0}, ver, hue;
char *cp;
if (!ljpeg_start (&jh, 0)) return;
jwide = (jh.wide >>= 1) * jh.clrs;
#ifdef LIBRAW_LIBRARY_BUILD
if(!data_size)
throw LIBRAW_EXCEPTION_IO_BADFILE;
LibRaw_byte_buffer *buf = ifp->make_byte_buffer(data_size);
LibRaw_bit_buffer bits;
#endif
for (ecol=slice=0; slice <= cr2_slice[0]; slice++) {
scol = ecol;
ecol += cr2_slice[1] * 2 / jh.clrs;
if (!cr2_slice[0] || ecol > raw_width-1) ecol = raw_width & -2;
for (row=0; row < height; row += (jh.clrs >> 1) - 1) {
ip = (short (*)[4]) image + row*width;
for (col=scol; col < ecol; col+=2, jcol+=jh.clrs) {
if ((jcol %= jwide) == 0)
#ifdef LIBRAW_LIBRARY_BUILD
rp = (short*) ljpeg_row_new (jrow++, &jh,bits,buf);
#else
rp = (short *) ljpeg_row (jrow++, &jh);
#endif
if (col >= width) continue;
FORC (jh.clrs-2)
ip[col + (c >> 1)*width + (c & 1)][0] = rp[jcol+c];
ip[col][1] = rp[jcol+jh.clrs-2] - 16384;
ip[col][2] = rp[jcol+jh.clrs-1] - 16384;
}
}
}
for (cp=model2; *cp && !isdigit(*cp); cp++);
sscanf (cp, "%d.%d.%d", v, v+1, v+2);
ver = (v[0]*1000 + v[1])*1000 + v[2];
hue = (jh.sraw+1) << 2;
if (unique_id >= 0x80000281 || (unique_id == 0x80000218 && ver > 1000006))
hue = jh.sraw << 1;
ip = (short (*)[4]) image;
rp = ip[0];
for (row=0; row < height; row++, ip+=width) {
if (row & (jh.sraw >> 1))
for (col=0; col < width; col+=2)
for (c=1; c < 3; c++)
if (row == height-1)
ip[col][c] = ip[col-width][c];
else ip[col][c] = (ip[col-width][c] + ip[col+width][c] + 1) >> 1;
for (col=1; col < width; col+=2)
for (c=1; c < 3; c++)
if (col == width-1)
ip[col][c] = ip[col-1][c];
else ip[col][c] = (ip[col-1][c] + ip[col+1][c] + 1) >> 1;
}
for ( ; rp < ip[0]; rp+=4) {
if (unique_id == 0x80000218 ||
unique_id == 0x80000250 ||
unique_id == 0x80000261 ||
unique_id == 0x80000281 ||
unique_id == 0x80000287) {
rp[1] = (rp[1] << 2) + hue;
rp[2] = (rp[2] << 2) + hue;
pix[0] = rp[0] + (( 50*rp[1] + 22929*rp[2]) >> 14);
pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 14);
pix[2] = rp[0] + ((29040*rp[1] - 101*rp[2]) >> 14);
} else {
if (unique_id < 0x80000218) rp[0] -= 512;
pix[0] = rp[0] + rp[2];
pix[2] = rp[0] + rp[1];
pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12);
}
FORC3 rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10);
}
#ifdef LIBRAW_LIBRARY_BUILD
delete buf;
#endif
ljpeg_end (&jh);
maximum = 0x3fff;
}
#ifndef LIBRAW_LIBRARY_BUILD
void CLASS adobe_copy_pixel (unsigned row, unsigned col, ushort **rp)
{
int c;
if (is_raw == 2 && shot_select) (*rp)++;
if (raw_image) {
if (row < raw_height && col < raw_width)
RAW(row,col) = curve[**rp];
*rp += is_raw;
} else {
if (row < height && col < width)
FORC(tiff_samples)
image[row*width+col][c] = curve[(*rp)[c]];
*rp += tiff_samples;
}
if (is_raw == 2 && shot_select) (*rp)--;
}
#else
void CLASS adobe_copy_pixel_raw (unsigned row, unsigned col, ushort **rp)
{
if (is_raw == 2 && shot_select) (*rp)++;
if (row < raw_height && col < raw_width)
RAW(row,col) = curve[**rp];
*rp += is_raw;
if (is_raw == 2 && shot_select) (*rp)--;
}
void CLASS adobe_copy_pixel_color (unsigned row, unsigned col, ushort **rp)
{
int c;
if (is_raw == 2 && shot_select) (*rp)++;
if (row < height && col < width)
FORC(tiff_samples)
image[row*width+col][c] = curve[(*rp)[c]];
*rp += tiff_samples;
if (is_raw == 2 && shot_select) (*rp)--;
}
#endif
void CLASS lossless_dng_load_raw()
{
unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col;
struct jhead jh;
ushort *rp;
while (trow < raw_height) {
save = ftell(ifp);
if (tile_length < INT_MAX)
fseek (ifp, get4(), SEEK_SET);
if (!ljpeg_start (&jh, 0)) break;
jwide = jh.wide;
if (filters) jwide *= jh.clrs;
jwide /= is_raw;
#ifdef LIBRAW_LIBRARY_BUILD
if(!data_size)
throw LIBRAW_EXCEPTION_IO_BADFILE;
LibRaw_byte_buffer *buf = ifp->make_byte_buffer(data_size);
LibRaw_bit_buffer bits;
#endif
#ifndef LIBRAW_LIBRARY_BUILD
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);
}
}
#else
if(raw_image)
{
for (row=col=jrow=0; jrow < jh.high; jrow++) {
#ifdef LIBRAW_LIBRARY_BUILD
rp = ljpeg_row_new (jrow, &jh,bits,buf);
#else
rp = ljpeg_row (jrow, &jh);
#endif
for (jcol=0; jcol < jwide; jcol++) {
adobe_copy_pixel_raw (trow+row, tcol+col, &rp);
if (++col >= tile_width || col >= raw_width)
row += 1 + (col = 0);
}
}
}
else
{
for (row=col=jrow=0; jrow < jh.high; jrow++) {
#ifdef LIBRAW_LIBRARY_BUILD
rp = ljpeg_row_new (jrow, &jh,bits,buf);
#else
rp = ljpeg_row (jrow, &jh);
#endif
for (jcol=0; jcol < jwide; jcol++) {
adobe_copy_pixel_color (trow+row, tcol+col, &rp);
if (++col >= tile_width || col >= raw_width)
row += 1 + (col = 0);
}
}
}
#endif
fseek (ifp, save+4, SEEK_SET);
if ((tcol += tile_width) >= raw_width)
trow += tile_length + (tcol = 0);
ljpeg_end (&jh);
#ifdef LIBRAW_LIBRARY_BUILD
delete buf;
#endif
}
}
void CLASS packed_dng_load_raw()
{
ushort *pixel, *rp;
int row, col;
pixel = (ushort *) calloc (raw_width * tiff_samples, sizeof *pixel);
merror (pixel, "packed_dng_load_raw()");
#ifdef LIBRAW_LIBRARY_BUILD
int dsz= raw_height*raw_width * tiff_samples * tiff_bps/8;
LibRaw_byte_buffer *buf = NULL;
if (tiff_bps != 16)
{
buf = ifp->make_byte_buffer(dsz);
}
LibRaw_bit_buffer bits;
#endif
for (row=0; row < raw_height; row++) {
if (tiff_bps == 16)
read_shorts (pixel, raw_width * tiff_samples);
else {
#ifdef LIBRAW_LIBRARY_BUILD
bits.reset();
for (col=0; col < raw_width * tiff_samples; col++)
pixel[col] = bits._getbits(buf,tiff_bps,zero_after_ff);
#else
getbits(-1);
for (col=0; col < raw_width * tiff_samples; col++)
pixel[col] = getbits(tiff_bps);
#endif
}
#ifndef LIBRAW_LIBRARY_BUILD
for (rp=pixel, col=0; col < raw_width; col++)
adobe_copy_pixel (row, col, &rp);
#else
if(raw_image)
for (rp=pixel, col=0; col < raw_width; col++)
adobe_copy_pixel_raw (row, col, &rp);
else
for (rp=pixel, col=0; col < raw_width; col++)
adobe_copy_pixel_color (row, col, &rp);
#endif
}
free (pixel);
#ifdef LIBRAW_LIBRARY_BUILD
if(buf)
delete buf;
#endif
}
void CLASS pentax_load_raw()
{
ushort bit[2][15], huff[4097];
int dep, row, col, diff, c, i;
ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2];
fseek (ifp, meta_offset, SEEK_SET);
dep = (get2() + 12) & 15;
fseek (ifp, 12, SEEK_CUR);
FORC(dep) bit[0][c] = get2();
FORC(dep) bit[1][c] = fgetc(ifp);
FORC(dep)
for (i=bit[0][c]; i <= ((bit[0][c]+(4096 >> bit[1][c])-1) & 4095); )
huff[++i] = bit[1][c] << 8 | c;
huff[0] = 12;
fseek (ifp, data_offset, SEEK_SET);
getbits(-1);
for (row=0; row < raw_height; row++)
for (col=0; col < raw_width; col++) {
diff = ljpeg_diff (huff);
if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
else hpred[col & 1] += diff;
RAW(row,col) = hpred[col & 1];
if (hpred[col & 1] >> tiff_bps) derror();
}
}
void CLASS nikon_load_raw()
{
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 } };
ushort *huff, ver0, ver1, vpred[2][2], hpred[2], csize;
int i, min, max, step=0, tree=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) tree = 2;
if (tiff_bps == 14) tree += 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);
while (curve[max-2] == curve[max-1]) max--;
huff = make_decoder (nikon_tree[tree]);
fseek (ifp, data_offset, SEEK_SET);
#ifdef LIBRAW_LIBRARY_BUILD
if(!data_size)
throw LIBRAW_EXCEPTION_IO_BADFILE;
LibRaw_byte_buffer *buf = ifp->make_byte_buffer(data_size);
LibRaw_bit_buffer bits;
bits.reset();
#else
getbits(-1);
#endif
for (min=row=0; row < height; row++) {
if (split && row == split) {
free (huff);
huff = make_decoder (nikon_tree[tree+1]);
max += (min = 16) << 1;
}
for (col=0; col < raw_width; col++) {
#ifdef LIBRAW_LIBRARY_BUILD
i = bits._gethuff(buf,*huff,huff+1,zero_after_ff);
#else
i = gethuff(huff);
#endif
len = i & 15;
shl = i >> 4;
#ifdef LIBRAW_LIBRARY_BUILD
diff = ((bits._getbits(buf,len-shl,zero_after_ff) << 1) + 1) << shl >> 1;
#else
diff = ((getbits(len-shl) << 1) + 1) << shl >> 1;
#endif
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 ((ushort)(hpred[col & 1] + min) >= max) derror();
RAW(row,col) = curve[LIM((short)hpred[col & 1],0,0x3fff)];
}
}
#ifdef LIBRAW_LIBRARY_BUILD
delete buf;
#endif
free (huff);
}
/*
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 t_make[12], t_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].t_make );
strcpy (model, table[i].t_model);
}
}
/*
Separates a Minolta DiMAGE Z2 from a Nikon E4300.
*/
int CLASS minolta_z2()
{
int i, nz;
char tail[424];
fseek (ifp, -sizeof tail, SEEK_END);
fread (tail, 1, sizeof tail, ifp);
for (nz=i=0; i < sizeof tail; i++)
if (tail[i]) nz++;
return nz > 20;
}
//@end COMMON
void CLASS jpeg_thumb();
//@out COMMON
void CLASS ppm_thumb()
{
char *thumb;
thumb_length = thumb_width*thumb_height*3;
thumb = (char *) malloc (thumb_length);
merror (thumb, "ppm_thumb()");
fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
fread (thumb, 1, thumb_length, ifp);
fwrite (thumb, 1, thumb_length, ofp);
free (thumb);
}
void CLASS ppm16_thumb()
{
int i;
char *thumb;
thumb_length = thumb_width*thumb_height*3;
thumb = (char *) calloc (thumb_length,2);
merror (thumb, "ppm16_thumb()");
read_shorts ((ushort *) thumb, thumb_length);
for (i=0; i < thumb_length; i++)
thumb[i] = ((ushort *) thumb)[i] >> 8;
fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
fwrite (thumb, 1, thumb_length, ofp);
free (thumb);
}
void CLASS layer_thumb()
{
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 (ofp, "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')], ofp);
free (thumb);
}
void CLASS rollei_thumb()
{
unsigned i;
ushort *thumb;
thumb_length = thumb_width * thumb_height;
thumb = (ushort *) calloc (thumb_length, 2);
merror (thumb, "rollei_thumb()");
fprintf (ofp, "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, ofp);
putc (thumb[i] >> 5 << 2, ofp);
putc (thumb[i] >> 11 << 3, ofp);
}
free (thumb);
}
void CLASS rollei_load_raw()
{
uchar pixel[10];
unsigned iten=0, isix, i, buffer=0, 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)
raw_image[todo[i]] = (todo[i+1] & 0x3ff);
}
maximum = 0x3ff;
}
int CLASS raw (unsigned row, unsigned col)
{
return (row < raw_height && col < raw_width) ? RAW(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] + y*head[5];
for (row = rend-head[5]; row < raw_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] + x*head[4];
for (col = cend-head[4]; col < raw_width && col < cend; col++) {
c = nc > 2 ? FC(row-top_margin,col-left_margin) : 0;
if (!(c & 1)) {
c = RAW(row,col) * mult[c];
RAW(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 *xval[2];
if (half_size || !meta_length) return;
#ifdef DCRAW_VERBOSE
if (verbose) fprintf (stderr,_("Phase One correction...\n"));
#endif
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 < raw_height; row++)
for (col = (tag & 1)*ph1.split_col; col < raw_width; col++)
RAW(row,col) = curve[RAW(row,col)];
} else if (tag == 0x400) { /* Sensor defects */
while ((len -= 8) >= 0) {
col = get2();
row = get2();
type = get2(); get2();
if (col >= raw_width) continue;
if (type == 131) /* Bad column */
for (row=0; row < raw_height; row++)
if (FC(row-top_margin,col-left_margin) == 1) {
for (sum=i=0; i < 4; i++)
sum += val[i] = raw (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;
}
RAW(row,col) = (sum - val[max])/3.0 + 0.5;
} else {
for (sum=0, i=8; i < 12; i++)
sum += raw (row+dir[i][0], col+dir[i][1]);
RAW(row,col) = 0.5 + sum * 0.0732233 +
(raw(row,col-2) + raw(row,col+2)) * 0.3535534;
}
else if (type == 129) { /* Bad pixel */
if (row >= raw_height) continue;
j = (FC(row-top_margin,col-left_margin) != 1) * 4;
for (sum=0, i=j; i < j+8; i++)
sum += raw (row+dir[i][0], col+dir[i][1]);
RAW(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 < raw_height; row++)
for (col=0; col < raw_width; col++) {
cfrac = (float) col * head[3] / raw_width;
cfrac -= cip = cfrac;
num = RAW(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 + num) * 2;
RAW(row,col) = LIM(i,0,65535);
}
free (yval[0]);
}
}
void CLASS phase_one_load_raw()
{
int a, b, i;
ushort akey, bkey, t_mask;
fseek (ifp, ph1.key_off, SEEK_SET);
akey = get2();
bkey = get2();
t_mask = ph1.format == 1 ? 0x5555:0x1354;
fseek (ifp, data_offset, SEEK_SET);
read_shorts (raw_image, raw_width*raw_height);
if (ph1.format)
for (i=0; i < raw_width*raw_height; i+=2) {
a = raw_image[i+0] ^ akey;
b = raw_image[i+1] ^ bkey;
raw_image[i+0] = (a & t_mask) | (b & ~t_mask);
raw_image[i+1] = (b & t_mask) | (a & ~t_mask);
}
}
unsigned CLASS ph1_bithuff (int nbits, ushort *huff)
{
#ifndef LIBRAW_NOTHREADS
#define bitbuf tls->ph1_bits.bitbuf
#define vbits tls->ph1_bits.vbits
#else
static UINT64 bitbuf=0;
static int vbits=0;
#endif
unsigned c;
if (nbits == -1)
return bitbuf = vbits = 0;
if (nbits == 0) return 0;
if (vbits < nbits) {
bitbuf = bitbuf << 32 | get4();
vbits += 32;
}
c = bitbuf << (64-vbits) >> (64-nbits);
if (huff) {
vbits -= huff[c] >> 8;
return (uchar) huff[c];
}
vbits -= nbits;
return c;
#ifndef LIBRAW_NOTHREADS
#undef bitbuf
#undef vbits
#endif
}
#define ph1_bits(n) ph1_bithuff(n,0)
#define ph1_huff(h) ph1_bithuff(*h,h+1)
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 (*t_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();
t_black = (short (*)[2]) offset + raw_height;
fseek (ifp, ph1.black_off, SEEK_SET);
if (ph1.black_off)
{
read_shorts ((ushort *) t_black[0], raw_height*2);
#ifdef LIBRAW_LIBRARY_BUILD
imgdata.rawdata.ph1_black = (short (*)[2])calloc(raw_height*2,sizeof(short));
merror (imgdata.rawdata.ph1_black, "phase_one_load_raw_c()");
memmove(imgdata.rawdata.ph1_black,(short *) t_black[0],raw_height*2*sizeof(short));
#endif
}
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(-1);
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]];
}
for (col=0; col < raw_width; col++) {
#ifndef LIBRAW_LIBRARY_BUILD
i = (pixel[col] << 2) - ph1.t_black + t_black[row][col >= ph1.split_col];
if (i > 0) RAW(row,col) = i;
#else
RAW(row,col) = pixel[col] << 2;
#endif
}
}
free (pixel);
maximum = 0xfffc - ph1.t_black;
}
void CLASS hasselblad_load_raw()
{
struct jhead jh;
int row, col, pred[2], len[2], diff, c;
if (!ljpeg_start (&jh, 0)) return;
order = 0x4949;
ph1_bits(-1);
for (row=0; row < raw_height; row++) {
pred[0] = pred[1] = 0x8000 + load_flags;
for (col=0; col < raw_width; col+=2) {
FORC(2) len[c] = ph1_huff(jh.huff[0]);
FORC(2) {
diff = ph1_bits(len[c]);
if ((diff & (1 << (len[c]-1))) == 0)
diff -= (1 << len[c]) - 1;
if (diff == 65535) diff = -32768;
RAW(row,col+c) = pred[c] += diff;
}
}
}
ljpeg_end (&jh);
maximum = 0xffff;
}
void CLASS leaf_hdr_load_raw()
{
ushort *pixel=0;
unsigned tile=0, r, c, row, col;
if (!filters) {
pixel = (ushort *) calloc (raw_width, sizeof *pixel);
merror (pixel, "leaf_hdr_load_raw()");
}
FORC(tiff_samples)
for (r=0; r < raw_height; r++) {
if (r % tile_length == 0) {
fseek (ifp, data_offset + 4*tile++, SEEK_SET);
fseek (ifp, get4(), SEEK_SET);
}
if (filters && c != shot_select) continue;
if (filters) pixel = raw_image + r*raw_width;
read_shorts (pixel, raw_width);
if (!filters && (row = r - top_margin) < height)
for (col=0; col < width; col++)
image[row*width+col][c] = pixel[col+left_margin];
}
if (!filters) {
maximum = 0xffff;
raw_color = 1;
free (pixel);
}
}
void CLASS unpacked_load_raw()
{
int row, col, bits=0;
while (1 << ++bits < maximum);
read_shorts (raw_image, raw_width*raw_height);
for (row=0; row < raw_height; row++)
for (col=0; col < raw_width; col++)
if ((RAW(row,col) >>= load_flags) >> bits
&& (unsigned) (row-top_margin) < height
&& (unsigned) (col-left_margin) < width) derror();
}
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;
}
#ifndef LIBRAW_LIBRARY_BUILD
free (raw_image);
raw_image = 0;
free (image);
image = (ushort (*)[4])
calloc ((iheight=height)*(iwidth=width), sizeof *image);
merror (image, "sinar_4shot_load_raw()");
#endif
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_load_raw()
{
int vbits=0, bwide, pwide, rbits, bite, half, irow, row, col, val, i;
UINT64 bitbuf=0;
if (raw_width * 8 >= width * tiff_bps) /* Is raw_width in bytes? */
pwide = (bwide = raw_width) * 8 / tiff_bps;
else bwide = (pwide = raw_width) * tiff_bps / 8;
rbits = bwide * 8 - pwide * tiff_bps;
if (load_flags & 1) bwide = bwide * 16 / 15;
bite = 8 + (load_flags & 24);
half = (raw_height+1) >> 1;
for (irow=0; irow < raw_height; irow++) {
row = irow;
if (load_flags & 2 &&
(row = irow % half * 2 + irow / half) == 1 &&
load_flags & 4) {
if (vbits=0, tiff_compress)
fseek (ifp, data_offset - (-half*bwide & -2048), SEEK_SET);
else {
fseek (ifp, 0, SEEK_END);
fseek (ifp, ftell(ifp) >> 3 << 2, SEEK_SET);
}
}
for (col=0; col < pwide; col++) {
for (vbits -= tiff_bps; vbits < 0; vbits += bite) {
bitbuf <<= bite;
for (i=0; i < bite; i+=8)
bitbuf |= (unsigned) (fgetc(ifp) << i);
}
val = bitbuf << (64-tiff_bps-vbits) >> (64-tiff_bps);
RAW(row,col ^ (load_flags >> 6)) = val;
if (load_flags & 1 && (col % 10) == 9 &&
fgetc(ifp) && col < width+left_margin) derror();
}
vbits -= rbits;
}
}
void CLASS nokia_load_raw()
{
uchar *data, *dp;
int rev, dwide, row, col, c;
rev = 3 * (order == 0x4949);
dwide = (raw_width * 5 +1) / 4;
data = (uchar *) malloc (dwide*2);
merror (data, "nokia_load_raw()");
for (row=0; row < raw_height; row++) {
if (fread (data+dwide, 1, dwide, ifp) < dwide) derror();
FORC(dwide) data[c] = data[dwide+(c ^ rev)];
for (dp=data, col=0; col < raw_width; dp+=5, col+=4)
FORC4 RAW(row,col+c) = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
}
free (data);
maximum = 0x3ff;
}
unsigned CLASS pana_bits (int nbits)
{
#ifndef LIBRAW_NOTHREADS
#define buf tls->pana_bits.buf
#define vbits tls->pana_bits.vbits
#else
static uchar buf[0x4000];
static int vbits;
#endif
int byte;
if (!nbits) return vbits=0;
if (!vbits) {
fread (buf+load_flags, 1, 0x4000-load_flags, ifp);
fread (buf, 1, load_flags, ifp);
}
vbits = (vbits - nbits) & 0x1ffff;
byte = vbits >> 3 ^ 0x3ff0;
return (buf[byte] | buf[byte+1] << 8) >> (vbits & 7) & ~(-1 << nbits);
#ifndef LIBRAW_NOTHREADS
#undef buf
#undef vbits
#endif
}
void CLASS panasonic_load_raw()
{
int row, col, i, j, sh=0, pred[2], nonz[2];
pana_bits(0);
for (row=0; row < height; row++)
for (col=0; col < raw_width; col++) {
if ((i = col % 14) == 0)
pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2));
if (nonz[i & 1]) {
if ((j = pana_bits(8))) {
if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4)
pred[i & 1] &= ~(-1 << sh);
pred[i & 1] += j << sh;
}
} else if ((nonz[i & 1] = pana_bits(8)) || i > 11)
pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4);
if ((RAW(row,col) = pred[col & 1]) > 4098 && col < width) derror();
}
}
void CLASS olympus_load_raw()
{
ushort huff[4096];
int row, col, nbits, sign, low, high, i, c, w, n, nw;
int acarry[2][3], *carry, pred, diff;
huff[n=0] = 0xc0c;
for (i=12; i--; )
FORC(2048 >> i) huff[++n] = (i+1) << 8 | i;
fseek (ifp, 7, SEEK_CUR);
#ifdef LIBRAW_LIBRARY_BUILD
if(!data_size)
throw LIBRAW_EXCEPTION_IO_BADFILE;
LibRaw_byte_buffer *buf = ifp->make_byte_buffer(data_size);
LibRaw_bit_buffer bits;
bits.reset();
#else
getbits(-1);
#endif
for (row=0; row < height; row++) {
memset (acarry, 0, sizeof acarry);
for (col=0; col < raw_width; col++) {
carry = acarry[col & 1];
i = 2 * (carry[2] < 3);
for (nbits=2+i; (ushort) carry[0] >> (nbits+i); nbits++);
#ifdef LIBRAW_LIBRARY_BUILD
low = (sign = bits._getbits(buf,3,zero_after_ff)) & 3;
sign = sign << 29 >> 31;
if ((high = bits._gethuff(buf,12,huff,zero_after_ff)) == 12)
high = bits._getbits(buf,16-nbits,zero_after_ff) >> 1;
carry[0] = (high << nbits) | bits._getbits(buf,nbits,zero_after_ff);
#else
low = (sign = getbits(3)) & 3;
sign = sign << 29 >> 31;
if ((high = getbithuff(12,huff)) == 12)
high = getbits(16-nbits) >> 1;
carry[0] = (high << nbits) | getbits(nbits);
#endif
diff = (carry[0] ^ sign) + carry[1];
carry[1] = (diff*3 + carry[1]) >> 5;
carry[2] = carry[0] > 16 ? 0 : carry[2]+1;
if (col >= width) continue;
if (row < 2 && col < 2) pred = 0;
else if (row < 2) pred = RAW(row,col-2);
else if (col < 2) pred = RAW(row-2,col);
else {
w = RAW(row,col-2);
n = RAW(row-2,col);
nw = RAW(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 ((RAW(row,col) = pred + ((diff << 2) | low)) >> 12) derror();
}
}
#ifdef LIBRAW_LIBRARY_BUILD
delete buf;
#endif
}
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) RAW(row,col) = (col+1) & 2 ?
pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1;
RAW(row,1) = pixel[1] << 1;
RAW(row,1533) = pixel[765] << 1;
} else
for (col=row & 1; col < 1534; col+=2)
RAW(row,col) = pixel[col/2] << 1;
}
maximum = 0xff << 1;
}
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 t_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++)
RAW(row,col) = t_curve[pixel[row+2][col+2]];
maximum = 0x3ff;
}
#define radc_token(tree) ((signed char) getbithuff(8,huff[tree]))
#define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--)
#define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \
: (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4)
#ifdef __GNUC__
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
# pragma GCC optimize("no-aggressive-loop-optimizations")
# endif
#endif
void CLASS kodak_radc_load_raw()
{
static const char src[] = {
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
};
ushort huff[19][256];
int row, col, tree, nreps, rep, step, i, c, s, r, x, y, val;
short last[3] = { 16,16,16 }, mul[3], buf[3][3][386];
static const ushort pt[] =
{ 0,0, 1280,1344, 2320,3616, 3328,8000, 4095,16383, 65535,16383 };
for (i=2; i < 12; i+=2)
for (c=pt[i-2]; c <= pt[i]; c++)
curve[c] = (float)
(c-pt[i-2]) / (pt[i]-pt[i-2]) * (pt[i+1]-pt[i-1]) + pt[i-1] + 0.5;
for (s=i=0; i < sizeof src; i+=2)
FORC(256 >> src[i])
huff[0][s++] = src[i] << 8 | (uchar) src[i+1];
s = kodak_cbpp == 243 ? 2 : 3;
FORC(256) huff[18][c] = (8-s) << 8 | c >> s << s | 1 << (s-1);
getbits(-1);
for (i=0; i < sizeof(buf)/sizeof(short); i++)
buf[0][0][i] = 2048;
for (row=0; row < height; row+=4) {
FORC3 mul[c] = getbits(6);
FORC3 {
val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c];
s = val > 65564 ? 10:12;
x = ~(-1 << (s-1));
val <<= 12-s;
for (i=0; i < sizeof(buf[0])/sizeof(short); i++)
buf[c][0][i] = (buf[c][0][i] * val + x) >> s;
last[c] = mul[c];
for (r=0; r <= !c; r++) {
buf[c][1][width/2] = buf[c][2][width/2] = mul[c] << 7;
for (tree=1, col=width/2; col > 0; ) {
if ((tree = radc_token(tree))) {
col -= 2;
if (tree == 8)
FORYX buf[c][y][x] = (uchar) radc_token(18) * mul[c];
else
FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR;
} else
do {
nreps = (col > 2) ? radc_token(9) + 1 : 1;
for (rep=0; rep < 8 && rep < nreps && col > 0; rep++) {
col -= 2;
FORYX buf[c][y][x] = PREDICTOR;
if (rep & 1) {
step = radc_token(10) << 4;
FORYX buf[c][y][x] += step;
}
}
} while (nreps == 9);
}
for (y=0; y < 2; y++)
for (x=0; x < width/2; x++) {
val = (buf[c][y+1][x] << 4) / mul[c];
if (val < 0) val = 0;
if (c) RAW(row+y*2+c-1,x*2+2-c) = val;
else RAW(row+r*2+y,x*2+y) = val;
}
memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c);
}
}
for (y=row; y < row+4; y++)
for (x=0; x < width; x++)
if ((x+y) & 1) {
r = x ? x-1 : x+1;
s = x+1 < width ? x+1 : x-1;
val = (RAW(y,x)-2048)*2 + (RAW(y,r)+RAW(y,s))/2;
if (val < 0) val = 0;
RAW(y,x) = val;
}
}
for (i=0; i < height*width; i++)
raw_image[i] = curve[raw_image[i]];
maximum = 0x3fff;
}
#undef FORYX
#undef PREDICTOR
#ifdef NO_JPEG
void CLASS kodak_jpeg_load_raw() {}
void CLASS lossy_dng_load_raw() {}
#else
#ifdef LIBRAW_LIBRARY_BUILD
void CLASS kodak_jpeg_load_raw() {}
#else
METHODDEF(boolean)
fill_input_buffer (j_decompress_ptr cinfo)
{
#ifndef LIBRAW_NOTHREADS
#define jpeg_buffer tls->jpeg_buffer
#else
static uchar jpeg_buffer[4096];
#endif
size_t nbytes;
nbytes = fread (jpeg_buffer, 1, 4096, ifp);
swab (jpeg_buffer, jpeg_buffer, nbytes);
cinfo->src->next_input_byte = jpeg_buffer;
cinfo->src->bytes_in_buffer = nbytes;
return TRUE;
#ifndef LIBRAW_NOTHREADS
#undef jpeg_buffer
#endif
}
void CLASS kodak_jpeg_load_raw()
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPARRAY buf;
JSAMPLE (*pixel)[3];
int row, col;
cinfo.err = jpeg_std_error (&jerr);
jpeg_create_decompress (&cinfo);
jpeg_stdio_src (&cinfo, ifp);
cinfo.src->fill_input_buffer = fill_input_buffer;
jpeg_read_header (&cinfo, TRUE);
jpeg_start_decompress (&cinfo);
if ((cinfo.output_width != width ) ||
(cinfo.output_height*2 != height ) ||
(cinfo.output_components != 3 )) {
#ifdef DCRAW_VERBOSE
fprintf (stderr,_("%s: incorrect JPEG dimensions\n"), ifname);
#endif
jpeg_destroy_decompress (&cinfo);
#ifdef LIBRAW_LIBRARY_BUILD
throw LIBRAW_EXCEPTION_DECODE_JPEG;
#else
longjmp (failure, 3);
#endif
}
buf = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, width*3, 1);
while (cinfo.output_scanline < cinfo.output_height) {
row = cinfo.output_scanline * 2;
jpeg_read_scanlines (&cinfo, buf, 1);
pixel = (JSAMPLE (*)[3]) buf[0];
for (col=0; col < width; col+=2) {
RAW(row+0,col+0) = pixel[col+0][1] << 1;
RAW(row+1,col+1) = pixel[col+1][1] << 1;
RAW(row+0,col+1) = pixel[col][0] + pixel[col+1][0];
RAW(row+1,col+0) = pixel[col][2] + pixel[col+1][2];
}
}
jpeg_finish_decompress (&cinfo);
jpeg_destroy_decompress (&cinfo);
maximum = 0xff << 1;
}
#endif
void CLASS lossy_dng_load_raw()
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPARRAY buf;
JSAMPLE (*pixel)[3];
unsigned sorder=order, ntags, opcode, deg, i, j, c;
unsigned save=data_offset-4, trow=0, tcol=0, row, col;
ushort t_curve[3][256];
double coeff[9], tot;
fseek (ifp, meta_offset, SEEK_SET);
order = 0x4d4d;
ntags = get4();
while (ntags--) {
opcode = get4(); get4(); get4();
if (opcode != 8)
{ fseek (ifp, get4(), SEEK_CUR); continue; }
fseek (ifp, 20, SEEK_CUR);
if ((c = get4()) > 2) break;
fseek (ifp, 12, SEEK_CUR);
if ((deg = get4()) > 8) break;
for (i=0; i <= deg && i < 9; i++)
coeff[i] = getreal(12);
for (i=0; i < 256; i++) {
for (tot=j=0; j <= deg; j++)
tot += coeff[j] * pow(i/255.0, (int)j);
t_curve[c][i] = tot*0xffff;
}
}
order = sorder;
cinfo.err = jpeg_std_error (&jerr);
jpeg_create_decompress (&cinfo);
while (trow < raw_height) {
fseek (ifp, save+=4, SEEK_SET);
if (tile_length < INT_MAX)
fseek (ifp, get4(), SEEK_SET);
#ifdef LIBRAW_LIBRARY_BUILD
if(libraw_internal_data.internal_data.input->jpeg_src(&cinfo) == -1)
{
jpeg_destroy_decompress(&cinfo);
throw LIBRAW_EXCEPTION_DECODE_JPEG;
}
#else
jpeg_stdio_src (&cinfo, ifp);
#endif
jpeg_read_header (&cinfo, TRUE);
jpeg_start_decompress (&cinfo);
buf = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, cinfo.output_width*3, 1);
while (cinfo.output_scanline < cinfo.output_height &&
(row = trow + cinfo.output_scanline) < height) {
jpeg_read_scanlines (&cinfo, buf, 1);
pixel = (JSAMPLE (*)[3]) buf[0];
for (col=0; col < cinfo.output_width && tcol+col < width; col++) {
FORC3 image[row*width+tcol+col][c] = t_curve[c][pixel[col][c]];
}
}
jpeg_abort_decompress (&cinfo);
if ((tcol += tile_width) >= raw_width)
trow += tile_length + (tcol = 0);
}
jpeg_destroy_decompress (&cinfo);
maximum = 0xffff;
}
#endif
void CLASS kodak_dc120_load_raw()
{
static const int mul[4] = { 162, 192, 187, 92 };
static const int add[4] = { 0, 636, 424, 212 };
uchar pixel[848];
int row, shift, col;
for (row=0; row < height; row++) {
if (fread (pixel, 1, 848, ifp) < 848) derror();
shift = row * mul[row & 3] + add[row & 3];
for (col=0; col < width; col++)
RAW(row,col) = (ushort) pixel[(col + shift) % 848];
}
maximum = 0xff;
}
void CLASS eight_bit_load_raw()
{
uchar *pixel;
unsigned row, col;
pixel = (uchar *) calloc (raw_width, sizeof *pixel);
merror (pixel, "eight_bit_load_raw()");
for (row=0; row < raw_height; row++) {
if (fread (pixel, 1, raw_width, ifp) < raw_width) derror();
for (col=0; col < raw_width; col++)
RAW(row,col) = curve[pixel[col]];
}
free (pixel);
maximum = curve[0xff];
}
void CLASS kodak_yrgb_load_raw()
{
uchar *pixel;
int row, col, y, cb, cr, rgb[3], c;
pixel = (uchar *) calloc (raw_width, 3*sizeof *pixel);
merror (pixel, "kodak_yrgb_load_raw()");
for (row=0; row < height; row++) {
if (~row & 1)
if (fread (pixel, raw_width, 3, ifp) < 3) derror();
for (col=0; col < raw_width; col++) {
y = pixel[width*2*(row & 1) + col];
cb = pixel[width + (col & -2)] - 128;
cr = pixel[width + (col & -2)+1] - 128;
rgb[1] = y-((cb + cr + 2) >> 2);
rgb[2] = rgb[1] + cb;
rgb[0] = rgb[1] + cr;
FORC3 image[row*width+col][c] = curve[LIM(rgb[c],0,255)];
}
}
free (pixel);
maximum = curve[0xff];
}
void CLASS kodak_262_load_raw()
{
static const uchar kodak_tree[2][26] =
{ { 0,1,5,1,1,2,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 },
{ 0,3,1,1,1,1,1,2,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 } };
ushort *huff[2];
uchar *pixel;
int *strip, ns, c, row, col, chess, pi=0, pi1, pi2, pred, val;
FORC(2) huff[c] = make_decoder (kodak_tree[c]);
ns = (raw_height+63) >> 5;
pixel = (uchar *) malloc (raw_width*32 + ns*4);
merror (pixel, "kodak_262_load_raw()");
strip = (int *) (pixel + raw_width*32);
order = 0x4d4d;
FORC(ns) strip[c] = get4();
for (row=0; row < raw_height; row++) {
if ((row & 31) == 0) {
fseek (ifp, strip[row >> 5], SEEK_SET);
getbits(-1);
pi = 0;
}
for (col=0; col < raw_width; col++) {
chess = (row + col) & 1;
pi1 = chess ? pi-2 : pi-raw_width-1;
pi2 = chess ? pi-2*raw_width : pi-raw_width+1;
if (col <= chess) pi1 = -1;
if (pi1 < 0) pi1 = pi2;
if (pi2 < 0) pi2 = pi1;
if (pi1 < 0 && col > 1) pi1 = pi2 = pi-2;
pred = (pi1 < 0) ? 0 : (pixel[pi1] + pixel[pi2]) >> 1;
pixel[pi] = val = pred + ljpeg_diff (huff[chess]);
if (val >> 8) derror();
val = curve[pixel[pi++]];
RAW(row,col) = val;
}
}
free (pixel);
FORC(2) free (huff[c]);
}
int CLASS kodak_65000_decode (short *out, int bsize)
{
uchar c, blen[768];
ushort raw[6];
INT64 bitbuf=0;
int save, bits=0, i, j, len, diff;
save = ftell(ifp);
bsize = (bsize + 3) & -4;
for (i=0; i < bsize; i+=2) {
c = fgetc(ifp);
if ((blen[i ] = c & 15) > 12 ||
(blen[i+1] = c >> 4) > 12 ) {
fseek (ifp, save, SEEK_SET);
for (i=0; i < bsize; i+=8) {
read_shorts (raw, 6);
out[i ] = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12;
out[i+1] = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12;
for (j=0; j < 6; j++)
out[i+2+j] = raw[j] & 0xfff;
}
return 1;
}
}
if ((bsize & 7) == 4) {
bitbuf = fgetc(ifp) << 8;
bitbuf += fgetc(ifp);
bits = 16;
}
for (i=0; i < bsize; i++) {
len = blen[i];
if (bits < len) {
for (j=0; j < 32; j+=8)
bitbuf += (INT64) fgetc(ifp) << (bits+(j^8));
bits += 32;
}
diff = bitbuf & (0xffff >> (16-len));
bitbuf >>= len;
bits -= len;
if ((diff & (1 << (len-1))) == 0)
diff -= (1 << len) - 1;
out[i] = diff;
}
return 0;
}
void CLASS kodak_65000_load_raw()
{
short buf[256];
int row, col, len, pred[2], ret, i;
for (row=0; row < height; row++)
for (col=0; col < width; col+=256) {
pred[0] = pred[1] = 0;
len = MIN (256, width-col);
ret = kodak_65000_decode (buf, len);
for (i=0; i < len; i++)
if ((RAW(row,col+i) = curve[ret ? buf[i] :
(pred[i & 1] += buf[i])]) >> 12) derror();
}
}
void CLASS kodak_ycbcr_load_raw()
{
short buf[384], *bp;
int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3];
ushort *ip;
for (row=0; row < height; row+=2)
for (col=0; col < width; col+=128) {
len = MIN (128, width-col);
kodak_65000_decode (buf, len*3);
y[0][1] = y[1][1] = cb = cr = 0;
for (bp=buf, i=0; i < len; i+=2, bp+=2) {
cb += bp[4];
cr += bp[5];
rgb[1] = -((cb + cr + 2) >> 2);
rgb[2] = rgb[1] + cb;
rgb[0] = rgb[1] + cr;
for (j=0; j < 2; j++)
for (k=0; k < 2; k++) {
if ((y[j][k] = y[j][k^1] + *bp++) >> 10) derror();
ip = image[(row+j)*width + col+i+k];
FORC3 ip[c] = curve[LIM(y[j][k]+rgb[c], 0, 0xfff)];
}
}
}
}
void CLASS kodak_rgb_load_raw()
{
short buf[768], *bp;
int row, col, len, c, i, rgb[3];
ushort *ip=image[0];
#ifndef LIBRAW_LIBRARY_BUILD
if (raw_image) free (raw_image);
raw_image = 0;
#endif
for (row=0; row < height; row++)
for (col=0; col < width; col+=256) {
len = MIN (256, width-col);
kodak_65000_decode (buf, len*3);
memset (rgb, 0, sizeof rgb);
for (bp=buf, i=0; i < len; i++, ip+=4)
FORC3 if ((ip[c] = rgb[c] += *bp++) >> 12) derror();
}
}
void CLASS kodak_thumb_load_raw()
{
int row, col;
colors = thumb_misc >> 5;
for (row=0; row < height; row++)
for (col=0; col < width; col++)
read_shorts (image[row*width+col], colors);
maximum = (1 << (thumb_misc & 31)) - 1;
}
void CLASS sony_decrypt (unsigned *data, int len, int start, int key)
{
#ifndef LIBRAW_NOTHREADS
#define pad tls->sony_decrypt.pad
#define p tls->sony_decrypt.p
#else
static unsigned pad[128], p;
#endif
if (start) {
for (p=0; p < 4; p++)
pad[p] = key = key * 48828125 + 1;
pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
for (p=4; p < 127; p++)
pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;
for (p=0; p < 127; p++)
pad[p] = htonl(pad[p]);
}
#if 1 // Avoid gcc 4.8 bug
while (len--)
{
*data++ ^= pad[p & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127];
p++;
}
#else
while (len--)
*data++ ^= pad[p++ & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127];
#endif
#ifndef LIBRAW_NOTHREADS
#undef pad
#undef p
#endif
}
void CLASS sony_load_raw()
{
uchar head[40];
ushort *pixel;
unsigned i, key, row, col;
fseek (ifp, 200896, SEEK_SET);
fseek (ifp, (unsigned) fgetc(ifp)*4 - 1, SEEK_CUR);
order = 0x4d4d;
key = get4();
fseek (ifp, 164600, SEEK_SET);
fread (head, 1, 40, ifp);
sony_decrypt ((unsigned int *) head, 10, 1, key);
for (i=26; i-- > 22; )
key = key << 8 | head[i];
fseek (ifp, data_offset, SEEK_SET);
for (row=0; row < raw_height; row++) {
pixel = raw_image + row*raw_width;
if (fread (pixel, 2, raw_width, ifp) < raw_width) derror();
sony_decrypt ((unsigned int *) pixel, raw_width/2, !row, key);
for (col=0; col < raw_width; col++)
if ((pixel[col] = ntohs(pixel[col])) >> 14) derror();
}
maximum = 0x3ff0;
}
void CLASS sony_arw_load_raw()
{
ushort huff[32768];
static const ushort tab[18] =
{ 0xf11,0xf10,0xe0f,0xd0e,0xc0d,0xb0c,0xa0b,0x90a,0x809,
0x708,0x607,0x506,0x405,0x304,0x303,0x300,0x202,0x201 };
int i, c, n, col, row, len, diff, sum=0;
for (n=i=0; i < 18; i++)
FORC(32768 >> (tab[i] >> 8)) huff[n++] = tab[i];
#ifdef LIBRAW_LIBRARY_BUILD
LibRaw_byte_buffer *buf=NULL;
if(data_size)
buf = ifp->make_byte_buffer(data_size);
else
getbits(-1);
LibRaw_bit_buffer bits;
bits.reset();
#else
getbits(-1);
#endif
for (col = raw_width; col--; )
for (row=0; row < raw_height+1; row+=2) {
if (row == raw_height) row = 1;
#ifdef LIBRAW_LIBRARY_BUILD
if(data_size)
{
len = bits._gethuff(buf,15,huff,zero_after_ff);
diff = bits._getbits(buf,len,zero_after_ff);
}
else
{
len = getbithuff(15,huff);
diff = getbits(len);
}
#else
len = getbithuff(15,huff);
diff = getbits(len);
#endif
if ((diff & (1 << (len-1))) == 0)
diff -= (1 << len) - 1;
if ((sum += diff) >> 12) derror();
if (row < height) RAW(row,col) = sum;
}
#ifdef LIBRAW_LIBRARY_BUILD
if(buf) delete buf;
#endif
}
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);
merror (data, "sony_arw2_load_raw()");
for (row=0; row < height; row++) {
fread (data, 1, raw_width, ifp);
for (dp=data, col=0; col < raw_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;
}
#ifdef LIBRAW_LIBRARY_BUILD
if(imgdata.params.sony_arw2_hack)
{
for (i=0; i < 16; i++, col+=2)
RAW(row,col) = curve[pix[i] << 1];
}
else
{
for (i=0; i < 16; i++, col+=2)
RAW(row,col) = curve[pix[i] << 1] >> 2;
}
#else
for (i=0; i < 16; i++, col+=2)
RAW(row,col) = curve[pix[i] << 1] >> 2;
#endif
col -= col & 1 ? 1:31;
}
}
free (data);
#ifdef LIBRAW_LIBRARY_BUILD
if(imgdata.params.sony_arw2_hack)
{
black <<= 2;
maximum <<=2;
}
#endif
}
#define HOLE(row) ((holes >> (((row) - raw_height) & 7)) & 1)
/* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */
void CLASS smal_decode_segment (unsigned seg[2][2], int holes)
{
uchar hist[3][13] = {
{ 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
{ 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
{ 3, 3, 0, 0, 63, 47, 31, 15, 0 } };
int low, high=0xff, carry=0, nbits=8;
int pix, s, count, bin, next, i, sym[3];
uchar diff, pred[]={0,0};
ushort data=0, range=0;
fseek (ifp, seg[0][1]+1, SEEK_SET);
getbits(-1);
for (pix=seg[0][0]; pix < seg[1][0]; pix++) {
for (s=0; s < 3; s++) {
data = data << nbits | getbits(nbits);
if (carry < 0)
carry = (nbits += carry+1) < 1 ? nbits-1 : 0;
while (--nbits >= 0)
if ((data >> nbits & 0xff) == 0xff) break;
if (nbits > 0)
data = ((data & ((1 << (nbits-1)) - 1)) << 1) |
((data + (((data & (1 << (nbits-1)))) << 1)) & (-1 << nbits));
if (nbits >= 0) {
data += getbits(1);
carry = nbits - 8;
}
count = ((((data-range+1) & 0xffff) << 2) - 1) / (high >> 4);
for (bin=0; hist[s][bin+5] > count; bin++);
low = hist[s][bin+5] * (high >> 4) >> 2;
if (bin) high = hist[s][bin+4] * (high >> 4) >> 2;
high -= low;
for (nbits=0; high << nbits < 128; nbits++);
range = (range+low) << nbits;
high <<= nbits;
next = hist[s][1];
if (++hist[s][2] > hist[s][3]) {
next = (next+1) & hist[s][0];
hist[s][3] = (hist[s][next+4] - hist[s][next+5]) >> 2;
hist[s][2] = 1;
}
if (hist[s][hist[s][1]+4] - hist[s][hist[s][1]+5] > 1) {
if (bin < hist[s][1])
for (i=bin; i < hist[s][1]; i++) hist[s][i+5]--;
else if (next <= bin)
for (i=hist[s][1]; i < bin; i++) hist[s][i+5]++;
}
hist[s][1] = next;
sym[s] = bin;
}
diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3);
if (sym[0] & 4)
diff = diff ? -diff : 0x80;
if (ftell(ifp) + 12 >= seg[1][1])
diff = 0;
raw_image[pix] = pred[pix & 1] += diff;
if (!(pix & 1) && HOLE(pix / raw_width)) pix += 2;
}
maximum = 0xff;
}
void CLASS smal_v6_load_raw()
{
unsigned seg[2][2];
fseek (ifp, 16, SEEK_SET);
seg[0][0] = 0;
seg[0][1] = get2();
seg[1][0] = raw_width * raw_height;
seg[1][1] = INT_MAX;
smal_decode_segment (seg, 0);
}
int CLASS median4 (int *p)
{
int min, max, sum, i;
min = max = sum = p[0];
for (i=1; i < 4; i++) {
sum += p[i];
if (min > p[i]) min = p[i];
if (max < p[i]) max = p[i];
}
return (sum - min - max) >> 1;
}
void CLASS fill_holes (int holes)
{
int row, col, val[4];
for (row=2; row < height-2; row++) {
if (!HOLE(row)) continue;
for (col=1; col < width-1; col+=4) {
val[0] = RAW(row-1,col-1);
val[1] = RAW(row-1,col+1);
val[2] = RAW(row+1,col-1);
val[3] = RAW(row+1,col+1);
RAW(row,col) = median4(val);
}
for (col=2; col < width-2; col+=4)
if (HOLE(row-2) || HOLE(row+2))
RAW(row,col) = (RAW(row,col-2) + RAW(row,col+2)) >> 1;
else {
val[0] = RAW(row,col-2);
val[1] = RAW(row,col+2);
val[2] = RAW(row-2,col);
val[3] = RAW(row+2,col);
RAW(row,col) = median4(val);
}
}
}
void CLASS smal_v9_load_raw()
{
unsigned seg[256][2], offset, nseg, holes, i;
fseek (ifp, 67, SEEK_SET);
offset = get4();
nseg = fgetc(ifp);
fseek (ifp, offset, SEEK_SET);
for (i=0; i < nseg*2; i++)
seg[0][i] = get4() + data_offset*(i & 1);
fseek (ifp, 78, SEEK_SET);
holes = fgetc(ifp);
fseek (ifp, 88, SEEK_SET);
seg[nseg][0] = raw_height * raw_width;
seg[nseg][1] = get4() + data_offset;
for (i=0; i < nseg; i++)
smal_decode_segment (seg+i, holes);
if (holes) fill_holes (holes);
}
void CLASS redcine_load_raw()
{
#ifndef NO_JASPER
int c, row, col;
jas_stream_t *in;
jas_image_t *jimg;
jas_matrix_t *jmat;
jas_seqent_t *data;
ushort *img, *pix;
jas_init();
#ifndef LIBRAW_LIBRARY_BUILD
in = jas_stream_fopen (ifname, "rb");
#else
in = (jas_stream_t*)ifp->make_jas_stream();
if(!in)
throw LIBRAW_EXCEPTION_DECODE_JPEG2000;
#endif
jas_stream_seek (in, data_offset+20, SEEK_SET);
jimg = jas_image_decode (in, -1, 0);
#ifndef LIBRAW_LIBRARY_BUILD
if (!jimg) longjmp (failure, 3);
#else
if(!jimg)
{
jas_stream_close (in);
throw LIBRAW_EXCEPTION_DECODE_JPEG2000;
}
#endif
jmat = jas_matrix_create (height/2, width/2);
merror (jmat, "redcine_load_raw()");
img = (ushort *) calloc ((height+2)*(width+2), 2);
merror (img, "redcine_load_raw()");
FORC4 {
jas_image_readcmpt (jimg, c, 0, 0, width/2, height/2, jmat);
data = jas_matrix_getref (jmat, 0, 0);
for (row = c >> 1; row < height; row+=2)
for (col = c & 1; col < width; col+=2)
img[(row+1)*(width+2)+col+1] = data[(row/2)*(width/2)+col/2];
}
for (col=1; col <= width; col++) {
img[col] = img[2*(width+2)+col];
img[(height+1)*(width+2)+col] = img[(height-1)*(width+2)+col];
}
for (row=0; row < height+2; row++) {
img[row*(width+2)] = img[row*(width+2)+2];
img[(row+1)*(width+2)-1] = img[(row+1)*(width+2)-3];
}
for (row=1; row <= height; row++) {
pix = img + row*(width+2) + (col = 1 + (FC(row,1) & 1));
for ( ; col <= width; col+=2, pix+=2) {
c = (((pix[0] - 0x800) << 3) +
pix[-(width+2)] + pix[width+2] + pix[-1] + pix[1]) >> 2;
pix[0] = LIM(c,0,4095);
}
}
for (row=0; row < height; row++)
for (col=0; col < width; col++)
RAW(row,col) = curve[img[(row+1)*(width+2)+col+1]];
free (img);
jas_matrix_destroy (jmat);
jas_image_destroy (jimg);
jas_stream_close (in);
#endif
}
//@end COMMON
/* RESTRICTED code starts here */
void CLASS foveon_decoder (unsigned size, unsigned code)
{
static unsigned huff[1024];
struct decode *cur;
int i, len;
if (!code) {
for (i=0; i < size; i++)
huff[i] = get4();
memset (first_decode, 0, sizeof first_decode);
free_decode = first_decode;
}
cur = free_decode++;
if (free_decode > first_decode+2048) {
fprintf (stderr,_("%s: decoder table overflow\n"), ifname);
longjmp (failure, 2);
}
if (code)
for (i=0; i < size; i++)
if (huff[i] == code) {
cur->leaf = i;
return;
}
if ((len = code >> 27) > 26) return;
code = (len+1) << 27 | (code & 0x3ffffff) << 1;
cur->branch[0] = free_decode;
foveon_decoder (size, code);
cur->branch[1] = free_decode;
foveon_decoder (size, code+1);
}
void CLASS foveon_thumb()
{
unsigned bwide, row, col, bitbuf=0, bit=1, c, i;
char *buf;
struct decode *dindex;
short pred[3];
bwide = get4();
fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
if (bwide > 0) {
if (bwide < thumb_width*3) return;
buf = (char *) malloc (bwide);
merror (buf, "foveon_thumb()");
for (row=0; row < thumb_height; row++) {
fread (buf, 1, bwide, ifp);
fwrite (buf, 3, thumb_width, ofp);
}
free (buf);
return;
}
foveon_decoder (256, 0);
for (row=0; row < thumb_height; row++) {
memset (pred, 0, sizeof pred);
if (!bit) get4();
for (bit=col=0; col < thumb_width; col++)
FORC3 {
for (dindex=first_decode; dindex->branch[0]; ) {
if ((bit = (bit-1) & 31) == 31)
for (i=0; i < 4; i++)
bitbuf = (bitbuf << 8) + fgetc(ifp);
dindex = dindex->branch[bitbuf >> bit & 1];
}
pred[c] += dindex->leaf;
fputc (pred[c], ofp);
}
}
}
void CLASS foveon_sd_load_raw()
{
struct decode *dindex;
short diff[1024];
unsigned bitbuf=0;
int pred[3], row, col, bit=-1, c, i;
read_shorts ((ushort *) diff, 1024);
if (!load_flags) foveon_decoder (1024, 0);
for (row=0; row < height; row++) {
memset (pred, 0, sizeof pred);
if (!bit && !load_flags && atoi(model+2) < 14) get4();
for (col=bit=0; col < width; col++) {
if (load_flags) {
bitbuf = get4();
FORC3 pred[2-c] += diff[bitbuf >> c*10 & 0x3ff];
}
else FORC3 {
for (dindex=first_decode; dindex->branch[0]; ) {
if ((bit = (bit-1) & 31) == 31)
for (i=0; i < 4; i++)
bitbuf = (bitbuf << 8) + fgetc(ifp);
dindex = dindex->branch[bitbuf >> bit & 1];
}
pred[c] += diff[dindex->leaf];
if (pred[c] >> 16 && ~pred[c] >> 16) derror();
}
FORC3 image[row*width+col][c] = pred[c];
}
}
}
void CLASS foveon_huff (ushort *huff)
{
int i, j, clen, code;
huff[0] = 8;
for (i=0; i < 13; i++) {
clen = getc(ifp);
code = getc(ifp);
for (j=0; j < 256 >> clen; )
huff[code+ ++j] = clen << 8 | i;
}
get2();
}
void CLASS foveon_dp_load_raw()
{
unsigned c, roff[4], row, col, diff;
ushort huff[258], vpred[2][2], hpred[2];
fseek (ifp, 8, SEEK_CUR);
foveon_huff (huff);
roff[0] = 48;
FORC3 roff[c+1] = -(-(roff[c] + get4()) & -16);
FORC3 {
fseek (ifp, data_offset+roff[c], SEEK_SET);
getbits(-1);
vpred[0][0] = vpred[0][1] = vpred[1][0] = vpred[1][1] = 512;
for (row=0; row < height; row++) {
for (col=0; col < width; col++) {
diff = ljpeg_diff(huff);
if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
else hpred[col & 1] += diff;
image[row*width+col][c] = hpred[col & 1];
}
}
}
}
void CLASS foveon_load_camf()
{
unsigned type, wide, high, i, j, row, col, diff;
ushort huff[258], vpred[2][2] = {{512,512},{512,512}}, hpred[2];
fseek (ifp, meta_offset, SEEK_SET);
type = get4(); get4(); get4();
wide = get4();
high = get4();
if (type == 2) {
fread (meta_data, 1, meta_length, ifp);
for (i=0; i < meta_length; i++) {
high = (high * 1597 + 51749) % 244944;
wide = high * (INT64) 301593171 >> 24;
meta_data[i] ^= ((((high << 8) - wide) >> 1) + wide) >> 17;
}
} else if (type == 4) {
free (meta_data);
meta_data = (char *) malloc (meta_length = wide*high*3/2);
merror (meta_data, "foveon_load_camf()");
foveon_huff (huff);
get4();
getbits(-1);
for (j=row=0; row < high; row++) {
for (col=0; col < wide; col++) {
diff = ljpeg_diff(huff);
if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
else hpred[col & 1] += diff;
if (col & 1) {
meta_data[j++] = hpred[0] >> 4;
meta_data[j++] = hpred[0] << 4 | hpred[1] >> 8;
meta_data[j++] = hpred[1];
}
}
}
} else
fprintf (stderr,_("%s has unknown CAMF type %d.\n"), ifname, type);
}
const char * CLASS foveon_camf_param (const char *block, const char *param)
{
unsigned idx, num;
char *pos, *cp, *dp;
for (idx=0; idx < meta_length; idx += sget4(pos+8)) {
pos = meta_data + idx;
if (strncmp (pos, "CMb", 3)) break;
if (pos[3] != 'P') continue;
if (strcmp (block, pos+sget4(pos+12))) continue;
cp = pos + sget4(pos+16);
num = sget4(cp);
dp = pos + sget4(cp+4);
while (num--) {
cp += 8;
if (!strcmp (param, dp+sget4(cp)))
return dp+sget4(cp+4);
}
}
return 0;
}
void * CLASS foveon_camf_matrix (unsigned dim[3], const char *name)
{
unsigned i, idx, type, ndim, size, *mat;
char *pos, *cp, *dp;
double dsize;
for (idx=0; idx < meta_length; idx += sget4(pos+8)) {
pos = meta_data + idx;
if (strncmp (pos, "CMb", 3)) break;
if (pos[3] != 'M') continue;
if (strcmp (name, pos+sget4(pos+12))) continue;
dim[0] = dim[1] = dim[2] = 1;
cp = pos + sget4(pos+16);
type = sget4(cp);
if ((ndim = sget4(cp+4)) > 3) break;
dp = pos + sget4(cp+8);
for (i=ndim; i--; ) {
cp += 12;
dim[i] = sget4(cp);
}
if ((dsize = (double) dim[0]*dim[1]*dim[2]) > meta_length/4) break;
mat = (unsigned *) malloc ((size = dsize) * 4);
merror (mat, "foveon_camf_matrix()");
for (i=0; i < size; i++)
if (type && type != 6)
mat[i] = sget4(dp + i*4);
else
mat[i] = sget4(dp + i*2) & 0xffff;
return mat;
}
fprintf (stderr,_("%s: \"%s\" matrix not found!\n"), ifname, name);
return 0;
}
int CLASS foveon_fixed (void *ptr, int size, const char *name)
{
void *dp;
unsigned dim[3];
if (!name) return 0;
dp = foveon_camf_matrix (dim, name);
if (!dp) return 0;
memcpy (ptr, dp, size*4);
free (dp);
return 1;
}
float CLASS foveon_avg (short *pix, int range[2], float cfilt)
{
int i;
float val, min=FLT_MAX, max=-FLT_MAX, sum=0;
for (i=range[0]; i <= range[1]; i++) {
sum += val = pix[i*4] + (pix[i*4]-pix[(i-1)*4]) * cfilt;
if (min > val) min = val;
if (max < val) max = val;
}
if (range[1] - range[0] == 1) return sum/2;
return (sum - min - max) / (range[1] - range[0] - 1);
}
short * CLASS foveon_make_curve (double max, double mul, double filt)
{
short *curve;
unsigned i, size;
double x;
if (!filt) filt = 0.8;
size = 4*M_PI*max / filt;
if (size == UINT_MAX) size--;
curve = (short *) calloc (size+1, sizeof *curve);
merror (curve, "foveon_make_curve()");
curve[0] = size;
for (i=0; i < size; i++) {
x = i*filt/max/4;
curve[i+1] = (cos(x)+1)/2 * tanh(i*filt/mul) * mul + 0.5;
}
return curve;
}
void CLASS foveon_make_curves
(short **curvep, float dq[3], float div[3], float filt)
{
double mul[3], max=0;
int c;
FORC3 mul[c] = dq[c]/div[c];
FORC3 if (max < mul[c]) max = mul[c];
FORC3 curvep[c] = foveon_make_curve (max, mul[c], filt);
}
int CLASS foveon_apply_curve (short *curve, int i)
{
if (abs(i) >= curve[0]) return 0;
return i < 0 ? -curve[1-i] : curve[1+i];
}
#define image ((short (*)[4]) image)
void CLASS foveon_interpolate()
{
static const short hood[] = { -1,-1, -1,0, -1,1, 0,-1, 0,1, 1,-1, 1,0, 1,1 };
short *pix, prev[3], *curve[8], (*shrink)[3];
float cfilt=0, ddft[3][3][2], ppm[3][3][3];
float cam_xyz[3][3], correct[3][3], last[3][3], trans[3][3];
float chroma_dq[3], color_dq[3], diag[3][3], div[3];
float (*black)[3], (*sgain)[3], (*sgrow)[3];
float fsum[3], val, frow, num;
int row, col, c, i, j, diff, sgx, irow, sum, min, max, limit;
int dscr[2][2], dstb[4], (*smrow[7])[3], total[4], ipix[3];
int work[3][3], smlast, smred, smred_p=0, dev[3];
int satlev[3], keep[4], active[4];
unsigned dim[3], *badpix;
double dsum=0, trsum[3];
char str[128];
const char* cp;
if (verbose)
fprintf (stderr,_("Foveon interpolation...\n"));
foveon_load_camf();
foveon_fixed (dscr, 4, "DarkShieldColRange");
foveon_fixed (ppm[0][0], 27, "PostPolyMatrix");
foveon_fixed (satlev, 3, "SaturationLevel");
foveon_fixed (keep, 4, "KeepImageArea");
foveon_fixed (active, 4, "ActiveImageArea");
foveon_fixed (chroma_dq, 3, "ChromaDQ");
foveon_fixed (color_dq, 3,
foveon_camf_param ("IncludeBlocks", "ColorDQ") ?
"ColorDQ" : "ColorDQCamRGB");
if (foveon_camf_param ("IncludeBlocks", "ColumnFilter"))
foveon_fixed (&cfilt, 1, "ColumnFilter");
memset (ddft, 0, sizeof ddft);
if (!foveon_camf_param ("IncludeBlocks", "DarkDrift")
|| !foveon_fixed (ddft[1][0], 12, "DarkDrift"))
for (i=0; i < 2; i++) {
foveon_fixed (dstb, 4, i ? "DarkShieldBottom":"DarkShieldTop");
for (row = dstb[1]; row <= dstb[3]; row++)
for (col = dstb[0]; col <= dstb[2]; col++)
FORC3 ddft[i+1][c][1] += (short) image[row*width+col][c];
FORC3 ddft[i+1][c][1] /= (dstb[3]-dstb[1]+1) * (dstb[2]-dstb[0]+1);
}
if (!(cp = foveon_camf_param ("WhiteBalanceIlluminants", model2)))
{ fprintf (stderr,_("%s: Invalid white balance \"%s\"\n"), ifname, model2);
return; }
foveon_fixed (cam_xyz, 9, cp);
foveon_fixed (correct, 9,
foveon_camf_param ("WhiteBalanceCorrections", model2));
memset (last, 0, sizeof last);
for (i=0; i < 3; i++)
for (j=0; j < 3; j++)
FORC3 last[i][j] += correct[i][c] * cam_xyz[c][j];
#define LAST(x,y) last[(i+x)%3][(c+y)%3]
for (i=0; i < 3; i++)
FORC3 diag[c][i] = LAST(1,1)*LAST(2,2) - LAST(1,2)*LAST(2,1);
#undef LAST
FORC3 div[c] = diag[c][0]*0.3127 + diag[c][1]*0.329 + diag[c][2]*0.3583;
sprintf (str, "%sRGBNeutral", model2);
if (foveon_camf_param ("IncludeBlocks", str))
foveon_fixed (div, 3, str);
num = 0;
FORC3 if (num < div[c]) num = div[c];
FORC3 div[c] /= num;
memset (trans, 0, sizeof trans);
for (i=0; i < 3; i++)
for (j=0; j < 3; j++)
FORC3 trans[i][j] += rgb_cam[i][c] * last[c][j] * div[j];
FORC3 trsum[c] = trans[c][0] + trans[c][1] + trans[c][2];
dsum = (6*trsum[0] + 11*trsum[1] + 3*trsum[2]) / 20;
for (i=0; i < 3; i++)
FORC3 last[i][c] = trans[i][c] * dsum / trsum[i];
memset (trans, 0, sizeof trans);
for (i=0; i < 3; i++)
for (j=0; j < 3; j++)
FORC3 trans[i][j] += (i==c ? 32 : -1) * last[c][j] / 30;
foveon_make_curves (curve, color_dq, div, cfilt);
FORC3 chroma_dq[c] /= 3;
foveon_make_curves (curve+3, chroma_dq, div, cfilt);
FORC3 dsum += chroma_dq[c] / div[c];
curve[6] = foveon_make_curve (dsum, dsum, cfilt);
curve[7] = foveon_make_curve (dsum*2, dsum*2, cfilt);
sgain = (float (*)[3]) foveon_camf_matrix (dim, "SpatialGain");
if (!sgain) return;
sgrow = (float (*)[3]) calloc (dim[1], sizeof *sgrow);
sgx = (width + dim[1]-2) / (dim[1]-1);
black = (float (*)[3]) calloc (height, sizeof *black);
for (row=0; row < height; row++) {
for (i=0; i < 6; i++)
ddft[0][0][i] = ddft[1][0][i] +
row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]);
FORC3 black[row][c] =
( foveon_avg (image[row*width]+c, dscr[0], cfilt) +
foveon_avg (image[row*width]+c, dscr[1], cfilt) * 3
- ddft[0][c][0] ) / 4 - ddft[0][c][1];
}
memcpy (black, black+8, sizeof *black*8);
memcpy (black+height-11, black+height-22, 11*sizeof *black);
memcpy (last, black, sizeof last);
for (row=1; row < height-1; row++) {
FORC3 if (last[1][c] > last[0][c]) {
if (last[1][c] > last[2][c])
black[row][c] = (last[0][c] > last[2][c]) ? last[0][c]:last[2][c];
} else
if (last[1][c] < last[2][c])
black[row][c] = (last[0][c] < last[2][c]) ? last[0][c]:last[2][c];
memmove (last, last+1, 2*sizeof last[0]);
memcpy (last[2], black[row+1], sizeof last[2]);
}
FORC3 black[row][c] = (last[0][c] + last[1][c])/2;
FORC3 black[0][c] = (black[1][c] + black[3][c])/2;
val = 1 - exp(-1/24.0);
memcpy (fsum, black, sizeof fsum);
for (row=1; row < height; row++)
FORC3 fsum[c] += black[row][c] =
(black[row][c] - black[row-1][c])*val + black[row-1][c];
memcpy (last[0], black[height-1], sizeof last[0]);
FORC3 fsum[c] /= height;
for (row = height; row--; )
FORC3 last[0][c] = black[row][c] =
(black[row][c] - fsum[c] - last[0][c])*val + last[0][c];
memset (total, 0, sizeof total);
for (row=2; row < height; row+=4)
for (col=2; col < width; col+=4) {
FORC3 total[c] += (short) image[row*width+col][c];
total[3]++;
}
for (row=0; row < height; row++)
FORC3 black[row][c] += fsum[c]/2 + total[c]/(total[3]*100.0);
for (row=0; row < height; row++) {
for (i=0; i < 6; i++)
ddft[0][0][i] = ddft[1][0][i] +
row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]);
pix = image[row*width];
memcpy (prev, pix, sizeof prev);
frow = row / (height-1.0) * (dim[2]-1);
if ((irow = frow) == dim[2]-1) irow--;
frow -= irow;
for (i=0; i < dim[1]; i++)
FORC3 sgrow[i][c] = sgain[ irow *dim[1]+i][c] * (1-frow) +
sgain[(irow+1)*dim[1]+i][c] * frow;
for (col=0; col < width; col++) {
FORC3 {
diff = pix[c] - prev[c];
prev[c] = pix[c];
ipix[c] = pix[c] + floor ((diff + (diff*diff >> 14)) * cfilt
- ddft[0][c][1] - ddft[0][c][0] * ((float) col/width - 0.5)
- black[row][c] );
}
FORC3 {
work[0][c] = ipix[c] * ipix[c] >> 14;
work[2][c] = ipix[c] * work[0][c] >> 14;
work[1][2-c] = ipix[(c+1) % 3] * ipix[(c+2) % 3] >> 14;
}
FORC3 {
for (val=i=0; i < 3; i++)
for ( j=0; j < 3; j++)
val += ppm[c][i][j] * work[i][j];
ipix[c] = floor ((ipix[c] + floor(val)) *
( sgrow[col/sgx ][c] * (sgx - col%sgx) +
sgrow[col/sgx+1][c] * (col%sgx) ) / sgx / div[c]);
if (ipix[c] > 32000) ipix[c] = 32000;
pix[c] = ipix[c];
}
pix += 4;
}
}
free (black);
free (sgrow);
free (sgain);
if ((badpix = (unsigned int *) foveon_camf_matrix (dim, "BadPixels"))) {
for (i=0; i < dim[0]; i++) {
col = (badpix[i] >> 8 & 0xfff) - keep[0];
row = (badpix[i] >> 20 ) - keep[1];
if ((unsigned)(row-1) > height-3 || (unsigned)(col-1) > width-3)
continue;
memset (fsum, 0, sizeof fsum);
for (sum=j=0; j < 8; j++)
if (badpix[i] & (1 << j)) {
FORC3 fsum[c] += (short)
image[(row+hood[j*2])*width+col+hood[j*2+1]][c];
sum++;
}
if (sum) FORC3 image[row*width+col][c] = fsum[c]/sum;
}
free (badpix);
}
/* Array for 5x5 Gaussian averaging of red values */
smrow[6] = (int (*)[3]) calloc (width*5, sizeof **smrow);
merror (smrow[6], "foveon_interpolate()");
for (i=0; i < 5; i++)
smrow[i] = smrow[6] + i*width;
/* Sharpen the reds against these Gaussian averages */
for (smlast=-1, row=2; row < height-2; row++) {
while (smlast < row+2) {
for (i=0; i < 6; i++)
smrow[(i+5) % 6] = smrow[i];
pix = image[++smlast*width+2];
for (col=2; col < width-2; col++) {
smrow[4][col][0] =
(pix[0]*6 + (pix[-4]+pix[4])*4 + pix[-8]+pix[8] + 8) >> 4;
pix += 4;
}
}
pix = image[row*width+2];
for (col=2; col < width-2; col++) {
smred = ( 6 * smrow[2][col][0]