Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
21420 lines (20230 sloc) 687 KB
/*
Copyright 2008-2019 LibRaw LLC (info@libraw.org)
LibRaw is free software; you can redistribute it and/or modify
it under the terms of the one of two licenses as you choose:
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
(See file LICENSE.LGPL provided in LibRaw distribution archive for details).
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
(See file LICENSE.CDDL provided in LibRaw distribution archive for details).
This file is generated from Dave Coffin's dcraw.c
dcraw.c -- Dave Coffin's raw photo decoder
Copyright 1997-2010 by Dave Coffin, dcoffin a cybercom o net
Look into dcraw homepage (probably http://cybercom.net/~dcoffin/dcraw/)
for more information
*/
#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"
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}};
if (filters == 1)
return filter[(row + top_margin) & 15][(col + left_margin) & 15];
if (filters == 9)
return xtrans[(row + 6) % 6][(col + 6) % 6];
return FC(row, col);
}
#if !defined(__FreeBSD__)
static size_t local_strnlen(const char *s, size_t n)
{
const char *p = (const char *)memchr(s, 0, n);
return (p ? p - s : n);
}
/* add OS X version check here ?? */
#define strnlen(a, b) local_strnlen(a, b)
#endif
#ifdef LIBRAW_LIBRARY_BUILD
static int Fuji_wb_list1[] = {LIBRAW_WBI_FineWeather, LIBRAW_WBI_Shade, LIBRAW_WBI_FL_D,
LIBRAW_WBI_FL_L, LIBRAW_WBI_FL_W, LIBRAW_WBI_Tungsten};
static int nFuji_wb_list1 = sizeof(Fuji_wb_list1) / sizeof(int);
static int FujiCCT_K[31] = {2500, 2550, 2650, 2700, 2800, 2850, 2950, 3000, 3100, 3200, 3300,
3400, 3600, 3700, 3800, 4000, 4200, 4300, 4500, 4800, 5000, 5300,
5600, 5900, 6300, 6700, 7100, 7700, 8300, 9100, 10000};
static int Fuji_wb_list2[] = {LIBRAW_WBI_Auto, 0, LIBRAW_WBI_Custom, 6, LIBRAW_WBI_FineWeather, 1,
LIBRAW_WBI_Shade, 8, LIBRAW_WBI_FL_D, 10, LIBRAW_WBI_FL_L, 11,
LIBRAW_WBI_FL_W, 12, LIBRAW_WBI_Tungsten, 2, LIBRAW_WBI_Underwater, 35,
LIBRAW_WBI_Ill_A, 82, LIBRAW_WBI_D65, 83};
static int nFuji_wb_list2 = sizeof(Fuji_wb_list2) / sizeof(int);
static int Oly_wb_list1[] = {LIBRAW_WBI_Shade, LIBRAW_WBI_Cloudy, LIBRAW_WBI_FineWeather,
LIBRAW_WBI_Tungsten, LIBRAW_WBI_Sunset, LIBRAW_WBI_FL_D,
LIBRAW_WBI_FL_N, LIBRAW_WBI_FL_W, LIBRAW_WBI_FL_WW};
static int Oly_wb_list2[] = {LIBRAW_WBI_Auto,
0,
LIBRAW_WBI_Tungsten,
3000,
0x100,
3300,
0x100,
3600,
0x100,
3900,
LIBRAW_WBI_FL_W,
4000,
0x100,
4300,
LIBRAW_WBI_FL_D,
4500,
0x100,
4800,
LIBRAW_WBI_FineWeather,
5300,
LIBRAW_WBI_Cloudy,
6000,
LIBRAW_WBI_FL_N,
6600,
LIBRAW_WBI_Shade,
7500,
LIBRAW_WBI_Custom1,
0,
LIBRAW_WBI_Custom2,
0,
LIBRAW_WBI_Custom3,
0,
LIBRAW_WBI_Custom4,
0};
static int Pentax_wb_list1[] = {LIBRAW_WBI_Daylight, LIBRAW_WBI_Shade, LIBRAW_WBI_Cloudy, LIBRAW_WBI_Tungsten,
LIBRAW_WBI_FL_D, LIBRAW_WBI_FL_N, LIBRAW_WBI_FL_W, LIBRAW_WBI_Flash};
static int Pentax_wb_list2[] = {LIBRAW_WBI_Daylight, LIBRAW_WBI_Shade, LIBRAW_WBI_Cloudy,
LIBRAW_WBI_Tungsten, LIBRAW_WBI_FL_D, LIBRAW_WBI_FL_N,
LIBRAW_WBI_FL_W, LIBRAW_WBI_Flash, LIBRAW_WBI_FL_L};
static int nPentax_wb_list2 = sizeof(Pentax_wb_list2) / sizeof(int);
static int stread(char *buf, size_t len, LibRaw_abstract_datastream *fp)
{
if(len>0)
{
int r = fp->read(buf, len, 1);
buf[len - 1] = 0;
return r;
}
else
return 0;
}
#define stmread(buf, maxlen, fp) stread(buf, MIN(maxlen, sizeof(buf)), fp)
#endif
#if !defined(__GLIBC__) && !defined(__FreeBSD__)
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
char *my_strcasestr(char *haystack, const char *needle)
{
char *c;
for (c = haystack; *c; c++)
if (!strncasecmp(c, needle, strlen(needle)))
return c;
return 0;
}
#define strcasestr my_strcasestr
#endif
#define strbuflen(buf) strnlen(buf, sizeof(buf) - 1)
ushort CLASS sget2(uchar *s)
{
if (order == 0x4949) /* "II" means little-endian */
return s[0] | s[1] << 8;
else /* "MM" means big-endian */
return s[0] << 8 | s[1];
}
// DNG was written by:
#define nonDNG 0
#define CameraDNG 1
#define AdobeDNG 2
// Makernote tag type:
#define is_0x927c 0 /* most cameras */
#define is_0xc634 2 /* Adobe DNG, Sony SR2, Pentax */
#ifdef LIBRAW_LIBRARY_BUILD
static int getwords(char *line, char *words[], int maxwords, int maxlen)
{
line[maxlen - 1] = 0;
char *p = line;
int nwords = 0;
while (1)
{
while (isspace(*p))
p++;
if (*p == '\0')
return nwords;
words[nwords++] = p;
while (!isspace(*p) && *p != '\0')
p++;
if (*p == '\0')
return nwords;
*p++ = '\0';
if (nwords >= maxwords)
return nwords;
}
}
static ushort saneSonyCameraInfo(uchar a, uchar b, uchar c, uchar d, uchar e, uchar f)
{
if ((a >> 4) > 9)
return 0;
else if ((a & 0x0f) > 9)
return 0;
else if ((b >> 4) > 9)
return 0;
else if ((b & 0x0f) > 9)
return 0;
else if ((c >> 4) > 9)
return 0;
else if ((c & 0x0f) > 9)
return 0;
else if ((d >> 4) > 9)
return 0;
else if ((d & 0x0f) > 9)
return 0;
else if ((e >> 4) > 9)
return 0;
else if ((e & 0x0f) > 9)
return 0;
else if ((f >> 4) > 9)
return 0;
else if ((f & 0x0f) > 9)
return 0;
return 1;
}
static ushort bcd2dec(uchar data)
{
if ((data >> 4) > 9)
return 0;
else if ((data & 0x0f) > 9)
return 0;
else
return (data >> 4) * 10 + (data & 0x0f);
}
static uchar SonySubstitution[257] =
"\x00\x01\x32\xb1\x0a\x0e\x87\x28\x02\xcc\xca\xad\x1b\xdc\x08\xed\x64\x86\xf0\x4f\x8c\x6c\xb8\xcb\x69\xc4\x2c\x03"
"\x97\xb6\x93\x7c\x14\xf3\xe2\x3e\x30\x8e\xd7\x60\x1c\xa1\xab\x37\xec\x75\xbe\x23\x15\x6a\x59\x3f\xd0\xb9\x96\xb5"
"\x50\x27\x88\xe3\x81\x94\xe0\xc0\x04\x5c\xc6\xe8\x5f\x4b\x70\x38\x9f\x82\x80\x51\x2b\xc5\x45\x49\x9b\x21\x52\x53"
"\x54\x85\x0b\x5d\x61\xda\x7b\x55\x26\x24\x07\x6e\x36\x5b\x47\xb7\xd9\x4a\xa2\xdf\xbf\x12\x25\xbc\x1e\x7f\x56\xea"
"\x10\xe6\xcf\x67\x4d\x3c\x91\x83\xe1\x31\xb3\x6f\xf4\x05\x8a\x46\xc8\x18\x76\x68\xbd\xac\x92\x2a\x13\xe9\x0f\xa3"
"\x7a\xdb\x3d\xd4\xe7\x3a\x1a\x57\xaf\x20\x42\xb2\x9e\xc3\x8b\xf2\xd5\xd3\xa4\x7e\x1f\x98\x9c\xee\x74\xa5\xa6\xa7"
"\xd8\x5e\xb0\xb4\x34\xce\xa8\x79\x77\x5a\xc1\x89\xae\x9a\x11\x33\x9d\xf5\x39\x19\x65\x78\x16\x71\xd2\xa9\x44\x63"
"\x40\x29\xba\xa0\x8f\xe4\xd6\x3b\x84\x0d\xc2\x4e\x58\xdd\x99\x22\x6b\xc9\xbb\x17\x06\xe5\x7d\x66\x43\x62\xf6\xcd"
"\x35\x90\x2e\x41\x8d\x6d\xaa\x09\x73\x95\x0c\xf1\x1d\xde\x4c\x2f\x2d\xf7\xd1\x72\xeb\xef\x48\xc7\xf8\xf9\xfa\xfb"
"\xfc\xfd\xfe\xff";
ushort CLASS sget2Rev(uchar *s) // specific to some Canon Makernotes fields, where they have endian in reverse
{
if (order == 0x4d4d) /* "II" means little-endian, and we reverse to "MM" - big endian */
return s[0] | s[1] << 8;
else /* "MM" means big-endian... */
return s[0] << 8 | s[1];
}
#endif
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, v;
int i, rev;
switch (type)
{
case 3: // ushort "SHORT" (int16u)
return (unsigned short)get2();
case 4: // unsigned "LONG" (int32u)
return (unsigned int)get4();
case 5: // (unsigned, unsigned) "RATIONAL" (rational64u)
u.d = (unsigned int)get4();
v.d = (unsigned int)get4();
return u.d / (v.d ? v.d : 1);
case 8: // short "SSHORT" (int16s)
return (signed short)get2();
case 9: // int "SLONG" (int32s)
return (signed int)get4();
case 10: // (int, int) "SRATIONAL" (rational64s)
u.d = (signed int)get4();
v.d = (signed int)get4();
return u.d / (v.d ? v.d : 1);
case 11: // float "FLOAT" (float)
return int_to_float(get4());
case 12: // double "DOUBLE" (double)
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, unsigned count)
{
if (fread(pixel, 2, count, ifp) < count)
derror();
if ((order == 0x4949) == (ntohs(0x1234) == 0x1234))
swab((char *)pixel, (char *)pixel, count * 2);
}
void CLASS cubic_spline(const int *x_, const int *y_, const int len)
{
float **A, *b, *c, *d, *x, *y;
int i, j;
A = (float **)calloc(((2 * len + 4) * sizeof **A + sizeof *A), 2 * len);
if (!A)
return;
A[0] = (float *)(A + 2 * len);
for (i = 1; i < 2 * len; i++)
A[i] = A[0] + 2 * len * i;
y = len + (x = i + (d = i + (c = i + (b = A[0] + i * i))));
for (i = 0; i < len; i++)
{
x[i] = x_[i] / 65535.0;
y[i] = y_[i] / 65535.0;
}
for (i = len - 1; i > 0; i--)
{
b[i] = (y[i] - y[i - 1]) / (x[i] - x[i - 1]);
d[i - 1] = x[i] - x[i - 1];
}
for (i = 1; i < len - 1; i++)
{
A[i][i] = 2 * (d[i - 1] + d[i]);
if (i > 1)
{
A[i][i - 1] = d[i - 1];
A[i - 1][i] = d[i - 1];
}
A[i][len - 1] = 6 * (b[i + 1] - b[i]);
}
for (i = 1; i < len - 2; i++)
{
float v = A[i + 1][i] / A[i][i];
for (j = 1; j <= len - 1; j++)
A[i + 1][j] -= v * A[i][j];
}
for (i = len - 2; i > 0; i--)
{
float acc = 0;
for (j = i; j <= len - 2; j++)
acc += A[i][j] * c[j];
c[i] = (A[i][len - 1] - acc) / A[i][i];
}
for (i = 0; i < 0x10000; i++)
{
float x_out = (float)(i / 65535.0);
float y_out = 0;
for (j = 0; j < len - 1; j++)
{
if (x[j] <= x_out && x_out <= x[j + 1])
{
float v = x_out - x[j];
y_out = y[j] + ((y[j + 1] - y[j]) / d[j] - (2 * d[j] * c[j] + c[j + 1] * d[j]) / 6) * v + (c[j] * 0.5) * v * v +
((c[j + 1] - c[j]) / (6 * d[j])) * v * v * v;
}
}
curve[i] = y_out < 0.0 ? 0 : (y_out >= 1.0 ? 65535 : (ushort)(y_out * 65535.0 + 0.5));
}
free(A);
}
void CLASS canon_600_fixed_wb(int temp)
{
static const short mul[4][5] = {
{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++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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;
}
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 > 25)
return 0;
if (nbits < 0)
return bitbuf = vbits = reset = 0;
if (nbits == 0 || vbits < 0)
return 0;
while (!reset && vbits < nbits && (c = fgetc(ifp)) != EOF && !(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);
#ifdef LIBRAW_LIBRARY_BUILD
try
{
#endif
for (row = 0; row < raw_height; row += 8)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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);
}
}
#ifdef LIBRAW_LIBRARY_BUILD
}
catch (...)
{
FORC(2) free(huff[c]);
throw;
}
#endif
FORC(2) free(huff[c]);
}
int CLASS ljpeg_start(struct jhead *jh, int info_only)
{
ushort c, tag, len;
int cnt = 0;
uchar data[0x10000];
const uchar *dp;
memset(jh, 0, sizeof *jh);
jh->restart = INT_MAX;
if ((fgetc(ifp), fgetc(ifp)) != 0xd8)
return 0;
do
{
if (feof(ifp))
return 0;
if (cnt++ > 1024)
return 0; // 1024 tags limit
if (!fread(data, 2, 2, ifp))
return 0;
tag = data[0] << 8 | data[1];
len = (data[2] << 8 | data[3]) - 2;
if (tag <= 0xff00)
return 0;
fread(data, 1, len, ifp);
switch (tag)
{
case 0xffc3: // start of frame; lossless, Huffman
jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3;
case 0xffc1:
case 0xffc0:
jh->algo = tag & 0xff;
jh->bits = data[0];
jh->high = data[1] << 8 | data[2];
jh->wide = data[3] << 8 | data[4];
jh->clrs = data[5] + jh->sraw;
if (len == 9 && !dng_version)
getc(ifp);
break;
case 0xffc4: // define Huffman tables
if (info_only)
break;
for (dp = data; dp < data + len && !((c = *dp++) & -20);)
jh->free[c] = jh->huff[c] = make_decoder_ref(&dp);
break;
case 0xffda: // start of scan
jh->psv = data[1 + data[0] * 2];
jh->bits -= data[3 + data[0] * 2] & 15;
break;
case 0xffdb:
FORC(64) jh->quant[c] = data[c * 2 + 1] << 8 | data[c * 2 + 2];
break;
case 0xffdd:
jh->restart = data[0] << 8 | data[1];
}
} while (tag != 0xffda);
if (jh->bits > 16 || jh->clrs > 6 || !jh->bits || !jh->high || !jh->wide || !jh->clrs)
return 0;
if (info_only)
return 1;
if (!jh->huff[0])
return 0;
FORC(19) if (!jh->huff[c + 1]) jh->huff[c + 1] = jh->huff[c];
if (jh->sraw)
{
FORC(4) jh->huff[2 + c] = jh->huff[1];
FORC(jh->sraw) jh->huff[1 + c] = jh->huff[0];
}
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;
if (!huff)
#ifdef LIBRAW_LIBRARY_BUILD
throw LIBRAW_EXCEPTION_IO_CORRUPT;
#else
longjmp(failure, 2);
#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;
}
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, jhigh, jrow, jcol, val, jidx, i, j, row = 0, col = 0;
struct jhead jh;
ushort *rp;
if (!ljpeg_start(&jh, 0))
return;
if (jh.wide < 1 || jh.high < 1 || jh.clrs < 1 || jh.bits < 1)
#ifdef LIBRAW_LIBRARY_BUILD
throw LIBRAW_EXCEPTION_IO_CORRUPT;
#else
longjmp(failure, 2);
#endif
jwide = jh.wide * jh.clrs;
jhigh = jh.high;
if (jh.clrs == 4 && jwide >= raw_width * 2)
jhigh *= 2;
#ifdef LIBRAW_LIBRARY_BUILD
try
{
#endif
for (jrow = 0; jrow < jh.high; jrow++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#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++];
if (cr2_slice[0])
{
jidx = jrow * jwide + jcol;
i = jidx / (cr2_slice[1] * raw_height);
if ((j = i >= cr2_slice[0]))
i = cr2_slice[0];
jidx -= i * (cr2_slice[1] * raw_height);
row = jidx / cr2_slice[1 + j];
col = jidx % cr2_slice[1 + j] + i * cr2_slice[1];
}
if (raw_width == 3984 && (col -= 2) < 0)
col += (row--, raw_width);
if (row > raw_height)
#ifdef LIBRAW_LIBRARY_BUILD
throw LIBRAW_EXCEPTION_IO_CORRUPT;
#else
longjmp(failure, 3);
#endif
if ((unsigned)row < raw_height)
RAW(row, col) = val;
if (++col >= raw_width)
col = (row++, 0);
}
}
#ifdef LIBRAW_LIBRARY_BUILD
}
catch (...)
{
ljpeg_end(&jh);
throw;
}
#endif
ljpeg_end(&jh);
}
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;
#ifdef LIBRAW_LIBRARY_BUILD
int saved_w = width, saved_h = height;
#endif
char *cp;
if (!ljpeg_start(&jh, 0) || jh.clrs < 4)
return;
jwide = (jh.wide >>= 1) * jh.clrs;
#ifdef LIBRAW_LIBRARY_BUILD
if (load_flags & 256)
{
width = raw_width;
height = raw_height;
}
try
{
#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)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
ip = (short(*)[4])image + row * width;
for (col = scol; col < ecol; col += 2, jcol += jh.clrs)
{
if ((jcol %= jwide) == 0)
rp = (short *)ljpeg_row(jrow++, &jh);
if (col >= width)
continue;
#ifdef LIBRAW_LIBRARY_BUILD
if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE)
{
FORC(jh.clrs - 2)
{
ip[col + (c >> 1) * width + (c & 1)][0] = rp[jcol + c];
ip[col + (c >> 1) * width + (c & 1)][1] = ip[col + (c >> 1) * width + (c & 1)][2] = 8192;
}
ip[col][1] = rp[jcol + jh.clrs - 2] - 8192;
ip[col][2] = rp[jcol + jh.clrs - 1] - 8192;
}
else if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SRAW_NO_RGB)
{
FORC(jh.clrs - 2)
ip[col + (c >> 1) * width + (c & 1)][0] = rp[jcol + c];
ip[col][1] = rp[jcol + jh.clrs - 2] - 8192;
ip[col][2] = rp[jcol + jh.clrs - 1] - 8192;
}
else
#endif
{
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;
}
}
}
}
#ifdef LIBRAW_LIBRARY_BUILD
}
catch (...)
{
ljpeg_end(&jh);
throw;
}
#endif
#ifdef LIBRAW_LIBRARY_BUILD
if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE)
{
ljpeg_end(&jh);
maximum = 0x3fff;
height = saved_h;
width = saved_w;
return;
}
#endif
#ifdef LIBRAW_LIBRARY_BUILD
try
{
#endif
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)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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;
}
#ifdef LIBRAW_LIBRARY_BUILD
if (!(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SRAW_NO_RGB))
#endif
for (; rp < ip[0]; rp += 4)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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] = CLIP15(pix[c] * sraw_mul[c] >> 10);
}
#ifdef LIBRAW_LIBRARY_BUILD
}
catch (...)
{
ljpeg_end(&jh);
throw;
}
height = saved_h;
width = saved_w;
#endif
ljpeg_end(&jh);
maximum = 0x3fff;
}
void CLASS adobe_copy_pixel(unsigned row, unsigned col, ushort **rp)
{
int c;
if (tiff_samples == 2 && shot_select)
(*rp)++;
if (raw_image)
{
if (row < raw_height && col < raw_width)
RAW(row, col) = curve[**rp];
*rp += tiff_samples;
}
else
{
#ifdef LIBRAW_LIBRARY_BUILD
if (row < raw_height && col < raw_width)
FORC(tiff_samples)
image[row * raw_width + col][c] = curve[(*rp)[c]];
*rp += tiff_samples;
#else
if (row < height && col < width)
FORC(tiff_samples)
image[row * width + col][c] = curve[(*rp)[c]];
*rp += tiff_samples;
#endif
}
if (tiff_samples == 2 && shot_select)
(*rp)--;
}
void CLASS ljpeg_idct(struct jhead *jh)
{
int c, i, j, len, skip, coef;
float work[3][8][8];
static float cs[106] = {0};
static const uchar zigzag[80] = {0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33,
40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36,
29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54,
47, 55, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63};
if (!cs[0])
FORC(106) cs[c] = cos((c & 31) * M_PI / 16) / 2;
memset(work, 0, sizeof work);
work[0][0][0] = jh->vpred[0] += ljpeg_diff(jh->huff[0]) * jh->quant[0];
for (i = 1; i < 64; i++)
{
len = gethuff(jh->huff[16]);
i += skip = len >> 4;
if (!(len &= 15) && skip < 15)
break;
coef = getbits(len);
if ((coef & (1 << (len - 1))) == 0)
coef -= (1 << len) - 1;
((float *)work)[zigzag[i]] = coef * jh->quant[i];
}
FORC(8) work[0][0][c] *= M_SQRT1_2;
FORC(8) work[0][c][0] *= M_SQRT1_2;
for (i = 0; i < 8; i++)
for (j = 0; j < 8; j++)
FORC(8) work[1][i][j] += work[0][i][c] * cs[(j * 2 + 1) * c];
for (i = 0; i < 8; i++)
for (j = 0; j < 8; j++)
FORC(8) work[2][i][j] += work[1][c][j] * cs[(i * 2 + 1) * c];
FORC(64) jh->idct[c] = CLIP(((float *)work[2])[c] + 0.5);
}
void CLASS lossless_dng_load_raw()
{
unsigned save, trow = 0, tcol = 0, jwide, jrow, jcol, row, col, i, j;
struct jhead jh;
ushort *rp;
while (trow < raw_height)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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 /= MIN(is_raw, tiff_samples);
#ifdef LIBRAW_LIBRARY_BUILD
try
{
#endif
switch (jh.algo)
{
case 0xc1:
jh.vpred[0] = 16384;
getbits(-1);
for (jrow = 0; jrow + 7 < jh.high; jrow += 8)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
for (jcol = 0; jcol + 7 < jh.wide; jcol += 8)
{
ljpeg_idct(&jh);
rp = jh.idct;
row = trow + jcol / tile_width + jrow * 2;
col = tcol + jcol % tile_width;
for (i = 0; i < 16; i += 2)
for (j = 0; j < 8; j++)
adobe_copy_pixel(row + i, col + j, &rp);
}
}
break;
case 0xc3:
for (row = col = jrow = 0; jrow < jh.high; jrow++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
rp = ljpeg_row(jrow, &jh);
if(tiff_samples == 1 && jh.clrs > 1 && jh.clrs*jwide == raw_width)
for (jcol = 0; jcol < jwide*jh.clrs; jcol++)
{
adobe_copy_pixel(trow + row, tcol + col, &rp);
if (++col >= tile_width || col >= raw_width)
row += 1 + (col = 0);
}
else
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);
}
}
}
#ifdef LIBRAW_LIBRARY_BUILD
}
catch (...)
{
ljpeg_end(&jh);
throw;
}
#endif
fseek(ifp, save + 4, SEEK_SET);
if ((tcol += tile_width) >= raw_width)
trow += tile_length + (tcol = 0);
ljpeg_end(&jh);
}
}
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
try
{
#endif
for (row = 0; row < raw_height; row++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
if (tiff_bps == 16)
read_shorts(pixel, raw_width * tiff_samples);
else
{
getbits(-1);
for (col = 0; col < raw_width * tiff_samples; col++)
pixel[col] = getbits(tiff_bps);
}
for (rp = pixel, col = 0; col < raw_width; col++)
adobe_copy_pixel(row, col, &rp);
}
#ifdef LIBRAW_LIBRARY_BUILD
}
catch (...)
{
free(pixel);
throw;
}
#endif
free(pixel);
}
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++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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();
}
}
}
#ifdef LIBRAW_LIBRARY_BUILD
void CLASS nikon_coolscan_load_raw()
{
if(!image)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
int bypp = tiff_bps <= 8 ? 1 : 2;
int bufsize = width * 3 * bypp;
if (tiff_bps <= 8)
gamma_curve(1.0 / imgdata.params.coolscan_nef_gamma, 0., 1, 255);
else
gamma_curve(1.0 / imgdata.params.coolscan_nef_gamma, 0., 1, 65535);
fseek(ifp, data_offset, SEEK_SET);
unsigned char *buf = (unsigned char *)malloc(bufsize);
unsigned short *ubuf = (unsigned short *)buf;
for (int row = 0; row < raw_height; row++) {
int red = fread(buf, 1, bufsize, ifp);
unsigned short(*ip)[4] = (unsigned short(*)[4])image + row * width;
if (is_NikonTransfer == 2) { // it is also (tiff_bps == 8)
for (int col = 0; col < width; col++) {
ip[col][0] = ((float)curve[buf[col * 3] ]) / 255.0f;
ip[col][1] = ((float)curve[buf[col * 3 + 1]]) / 255.0f;
ip[col][2] = ((float)curve[buf[col * 3 + 2]]) / 255.0f;
ip[col][3] = 0;
}
} else if (tiff_bps <= 8) {
for (int col = 0; col < width; col++) {
ip[col][0] = curve[buf[col * 3]];
ip[col][1] = curve[buf[col * 3 + 1]];
ip[col][2] = curve[buf[col * 3 + 2]];
ip[col][3] = 0;
}
} else {
for (int col = 0; col < width; col++) {
ip[col][0] = curve[ubuf[col * 3]];
ip[col][1] = curve[ubuf[col * 3 + 1]];
ip[col][2] = curve[ubuf[col * 3 + 2]];
ip[col][3] = 0;
}
}
}
free(buf);
}
#endif
void CLASS nikon_read_curve()
{
ushort ver0, ver1, vpred[2][2], hpred[2], csize;
int i,step,max;
fseek(ifp, meta_offset, SEEK_SET);
ver0 = fgetc(ifp);
ver1 = fgetc(ifp);
if (ver0 == 0x49 || ver1 == 0x58)
fseek(ifp, 2110, SEEK_CUR);
read_shorts(vpred[0], 4);
max = 1 << tiff_bps & 0x7fff;
if ((csize = get2()) > 1)
step = max / (csize - 1);
if (ver0 == 0x44 && (ver1 == 0x20 || (ver1 == 0x40 && step > 3)) && step > 0)
{
if(ver1 == 0x40) { step /= 4; max /= 4; }
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;
}
else if (ver0 != 0x46 && csize <= 0x4001)
read_shorts(curve, max = csize);
}
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]
#if 0
,csize
#endif
;
int i, min, max,
#if 0
step = 0,
#endif
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 0
if ((csize = get2()) > 1)
step = max / (csize - 1);
if (ver0 == 0x44 && (ver1 == 0x20 || (ver1 == 0x40 && step > 3)) && step > 0)
{
if(ver1 == 0x40) { step /= 4; max /= 4; }
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);
#else
if (ver0 == 0x44 && (ver1 == 0x20 || ver1 == 0x40))
{
if(ver1 == 0x40) max /= 4;
fseek(ifp, meta_offset + 562, SEEK_SET);
split = get2();
}
#endif
while (curve[max - 2] == curve[max - 1])
max--;
huff = make_decoder(nikon_tree[tree]);
fseek(ifp, data_offset, SEEK_SET);
getbits(-1);
#ifdef LIBRAW_LIBRARY_BUILD
try
{
#endif
for (min = row = 0; row < height; row++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
if (split && row == split)
{
free(huff);
huff = make_decoder(nikon_tree[tree + 1]);
max += (min = 16) << 1;
}
for (col = 0; col < raw_width; col++)
{
i = gethuff(huff);
len = i & 15;
shl = i >> 4;
diff = ((getbits(len - shl) << 1) + 1) << shl >> 1;
if ((diff & (1 << (len - 1))) == 0)
diff -= (1 << len) - !shl;
if (col < 2)
hpred[col] = vpred[row & 1][col] += diff;
else
hpred[col & 1] += diff;
if ((ushort)(hpred[col & 1] + min) >= max)
derror();
RAW(row, col) = curve[LIM((short)hpred[col & 1], 0, 0x3fff)];
}
}
#ifdef LIBRAW_LIBRARY_BUILD
}
catch (...)
{
free(huff);
throw;
}
#endif
free(huff);
}
void CLASS nikon_yuv_load_raw()
{
#ifdef LIBRAW_LIBRARY_BUILD
if (!image)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
int row, col, yuv[4], rgb[3], b, c;
UINT64 bitbuf = 0;
float cmul[4];
FORC4 { cmul[c] = cam_mul[c] > 0.001f ? cam_mul[c] : 1.f; }
for (row = 0; row < raw_height; row++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
for (col = 0; col < raw_width; col++)
{
if (!(b = col & 1))
{
bitbuf = 0;
FORC(6) bitbuf |= (UINT64)fgetc(ifp) << c * 8;
FORC(4) yuv[c] = (bitbuf >> c * 12 & 0xfff) - (c >> 1 << 11);
}
rgb[0] = yuv[b] + 1.370705 * yuv[3];
rgb[1] = yuv[b] - 0.337633 * yuv[2] - 0.698001 * yuv[3];
rgb[2] = yuv[b] + 1.732446 * yuv[2];
FORC3 image[row * width + col][c] = curve[LIM(rgb[c], 0, 0xfff)] / cmul[c];
}
}
}
/*
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;
}
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];
#ifdef LIBRAW_LIBRARY_BUILD
if(raw_width > 32767 || raw_height > 32767)
throw LIBRAW_EXCEPTION_IO_BADFILE;
#endif
unsigned maxpixel = raw_width*(raw_height+7);
isix = raw_width * raw_height * 5 / 8;
while (fread(pixel, 1, 10, ifp) == 10)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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)
if(todo[i] < maxpixel)
raw_image[todo[i]] = (todo[i + 1] & 0x3ff);
else
derror();
}
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, high, y, x, c, rend, cend, row, col;
float *mrow, num, mult[4];
read_shorts(head, 8);
if (head[2] * head[3] * head[4] * head[5] == 0)
return;
wide = head[2] / head[4] + (head[2] % head[4] != 0);
high = head[3] / head[5] + (head[3] % head[5] != 0);
mrow = (float *)calloc(nc * wide, sizeof *mrow);
merror(mrow, "phase_one_flat_field()");
for (y = 0; y < high; y++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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 < head[1] + head[3] - head[5]; row++)
{
for (x = 1; x < wide; x++)
{
for (c = 0; c < nc; c += 2)
{
mult[c] = mrow[c * wide + x - 1];
mult[c + 1] = (mrow[c * wide + x] - mult[c]) / head[4];
}
cend = head[0] + x * head[4];
for (col = cend - head[4]; col < raw_width && col < cend && col < head[0] + head[2] - head[4]; col++)
{
c = nc > 2 ? FC(row - top_margin, col - left_margin) : 0;
if (!(c & 1))
{
c = RAW(row, col) * mult[c];
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);
}
int 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] = {NULL, NULL};
ushort *xval[2];
int qmult_applied = 0, qlin_applied = 0;
#ifdef LIBRAW_LIBRARY_BUILD
if (!meta_length)
#else
if (half_size || !meta_length)
#endif
return 0;
#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();
#ifdef LIBRAW_LIBRARY_BUILD
try
{
#endif
while (entries--)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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 || type == 137) /* Bad column */
for (row = 0; row < raw_height; row++)
if (FC(row - top_margin, col - left_margin) == 1)
{
for (sum = i = 0; i < 4; i++)
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;
}
}
else if (tag == 0x41f && !qlin_applied)
{ /* Quadrant linearization */
ushort lc[2][2][16], ref[16];
int qr, qc;
for (qr = 0; qr < 2; qr++)
for (qc = 0; qc < 2; qc++)
for (i = 0; i < 16; i++)
lc[qr][qc][i] = get4();
for (i = 0; i < 16; i++)
{
int v = 0;
for (qr = 0; qr < 2; qr++)
for (qc = 0; qc < 2; qc++)
v += lc[qr][qc][i];
ref[i] = (v + 2) >> 2;
}
for (qr = 0; qr < 2; qr++)
{
for (qc = 0; qc < 2; qc++)
{
int cx[19], cf[19];
for (i = 0; i < 16; i++)
{
cx[1 + i] = lc[qr][qc][i];
cf[1 + i] = ref[i];
}
cx[0] = cf[0] = 0;
cx[17] = cf[17] = ((unsigned int)ref[15] * 65535) / lc[qr][qc][15];
cf[18] = cx[18] = 65535;
cubic_spline(cx, cf, 19);
for (row = (qr ? ph1.split_row : 0); row < (qr ? raw_height : ph1.split_row); row++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
for (col = (qc ? ph1.split_col : 0); col < (qc ? raw_width : ph1.split_col); col++)
RAW(row, col) = curve[RAW(row, col)];
}
}
}
qlin_applied = 1;
}
else if (tag == 0x41e && !qmult_applied)
{ /* Quadrant multipliers */
float qmult[2][2] = {{1, 1}, {1, 1}};
get4();
get4();
get4();
get4();
qmult[0][0] = 1.0 + getreal(11);
get4();
get4();
get4();
get4();
get4();
qmult[0][1] = 1.0 + getreal(11);
get4();
get4();
get4();
qmult[1][0] = 1.0 + getreal(11);
get4();
get4();
get4();
qmult[1][1] = 1.0 + getreal(11);
for (row = 0; row < raw_height; row++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
for (col = 0; col < raw_width; col++)
{
i = qmult[row >= ph1.split_row][col >= ph1.split_col] * RAW(row, col);
RAW(row, col) = LIM(i, 0, 65535);
}
}
qmult_applied = 1;
}
else if (tag == 0x431 && !qmult_applied)
{ /* Quadrant combined */
ushort lc[2][2][7], ref[7];
int qr, qc;
for (i = 0; i < 7; i++)
ref[i] = get4();
for (qr = 0; qr < 2; qr++)
for (qc = 0; qc < 2; qc++)
for (i = 0; i < 7; i++)
lc[qr][qc][i] = get4();
for (qr = 0; qr < 2; qr++)
{
for (qc = 0; qc < 2; qc++)
{
int cx[9], cf[9];
for (i = 0; i < 7; i++)
{
cx[1 + i] = ref[i];
cf[1 + i] = ((unsigned)ref[i] * lc[qr][qc][i]) / 10000;
}
cx[0] = cf[0] = 0;
cx[8] = cf[8] = 65535;
cubic_spline(cx, cf, 9);
for (row = (qr ? ph1.split_row : 0); row < (qr ? raw_height : ph1.split_row); row++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
for (col = (qc ? ph1.split_col : 0); col < (qc ? raw_width : ph1.split_col); col++)
RAW(row, col) = curve[RAW(row, col)];
}
}
}
qmult_applied = 1;
qlin_applied = 1;
}
fseek(ifp, save, SEEK_SET);
}
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++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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]);
}
#ifdef LIBRAW_LIBRARY_BUILD
}
catch (...)
{
if (yval[0])
free(yval[0]);
return LIBRAW_CANCELLED_BY_CALLBACK;
}
#endif
return 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;
#ifdef LIBRAW_LIBRARY_BUILD
if (ph1.black_col || ph1.black_row)
{
imgdata.rawdata.ph1_cblack = (short(*)[2])calloc(raw_height * 2, sizeof(ushort));
merror(imgdata.rawdata.ph1_cblack, "phase_one_load_raw()");
imgdata.rawdata.ph1_rblack = (short(*)[2])calloc(raw_width * 2, sizeof(ushort));
merror(imgdata.rawdata.ph1_rblack, "phase_one_load_raw()");
if (ph1.black_col)
{
fseek(ifp, ph1.black_col, SEEK_SET);
read_shorts((ushort *)imgdata.rawdata.ph1_cblack[0], raw_height * 2);
}
if (ph1.black_row)
{
fseek(ifp, ph1.black_row, SEEK_SET);
read_shorts((ushort *)imgdata.rawdata.ph1_rblack[0], raw_width * 2);
}
}
#endif
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(*c_black)[2], (*r_black)[2];
#ifdef LIBRAW_LIBRARY_BUILD
if (ph1.format == 6)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
pixel = (ushort *)calloc(raw_width * 3 + raw_height * 4, 2);
merror(pixel, "phase_one_load_raw_c()");
offset = (int *)(pixel + raw_width);
fseek(ifp, strip_offset, SEEK_SET);
for (row = 0; row < raw_height; row++)
offset[row] = get4();
c_black = (short(*)[2])(offset + raw_height);
fseek(ifp, ph1.black_col, SEEK_SET);
if (ph1.black_col)
read_shorts((ushort *)c_black[0], raw_height * 2);
r_black = c_black + raw_height;
fseek(ifp, ph1.black_row, SEEK_SET);
if (ph1.black_row)
read_shorts((ushort *)r_black[0], raw_width * 2);
#ifdef LIBRAW_LIBRARY_BUILD
// Copy data to internal copy (ever if not read)
if (ph1.black_col || ph1.black_row)
{
imgdata.rawdata.ph1_cblack = (short(*)[2])calloc(raw_height * 2, sizeof(ushort));
merror(imgdata.rawdata.ph1_cblack, "phase_one_load_raw_c()");
memmove(imgdata.rawdata.ph1_cblack, (ushort *)c_black[0], raw_height * 2 * sizeof(ushort));
imgdata.rawdata.ph1_rblack = (short(*)[2])calloc(raw_width * 2, sizeof(ushort));
merror(imgdata.rawdata.ph1_rblack, "phase_one_load_raw_c()");
memmove(imgdata.rawdata.ph1_rblack, (ushort *)r_black[0], raw_width * 2 * sizeof(ushort));
}
#endif
for (i = 0; i < 256; i++)
curve[i] = i * i / 3.969 + 0.5;
#ifdef LIBRAW_LIBRARY_BUILD
try
{
#endif
for (row = 0; row < raw_height; row++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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]];
}
#ifndef LIBRAW_LIBRARY_BUILD
for (col = 0; col < raw_width; col++)
{
int shift = ph1.format == 8 ? 0 : 2;
i = (pixel[col] << shift) - ph1.t_black + c_black[row][col >= ph1.split_col] +
r_black[col][row >= ph1.split_row];
if (i > 0)
RAW(row, col) = i;
}
#else
if (ph1.format == 8)
memmove(&RAW(row, 0), &pixel[0], raw_width * 2);
else
for (col = 0; col < raw_width; col++)
RAW(row, col) = pixel[col] << 2;
#endif
}
#ifdef LIBRAW_LIBRARY_BUILD
}
catch (...)
{
free(pixel);
throw;
}
#endif
free(pixel);
maximum = 0xfffc - ph1.t_black;
}
void CLASS hasselblad_load_raw()
{
struct jhead jh;
int shot, row, col, *back[5], len[2], diff[12], pred, sh, f, s, c;
unsigned upix, urow, ucol;
ushort *ip;
if (!ljpeg_start(&jh, 0))
return;
order = 0x4949;
ph1_bits(-1);
#ifdef LIBRAW_LIBRARY_BUILD
try
{
#endif
back[4] = (int *)calloc(raw_width, 3 * sizeof **back);
merror(back[4], "hasselblad_load_raw()");
FORC3 back[c] = back[4] + c * raw_width;
cblack[6] >>= sh = tiff_samples > 1;
shot = LIM(shot_select, 1, tiff_samples) - 1;
for (row = 0; row < raw_height; row++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
FORC4 back[(c + 3) & 3] = back[c];
for (col = 0; col < raw_width; col += 2)
{
for (s = 0; s < tiff_samples * 2; s += 2)
{
FORC(2) len[c] = ph1_huff(jh.huff[0]);
FORC(2)
{
diff[s + c] = ph1_bits(len[c]);
if ((diff[s + c] & (1 << (len[c] - 1))) == 0)
diff[s + c] -= (1 << len[c]) - 1;
if (diff[s + c] == 65535)
diff[s + c] = -32768;
}
}
for (s = col; s < col + 2; s++)
{
pred = 0x8000 + load_flags;
if (col)
pred = back[2][s - 2];
if (col && row > 1)
switch (jh.psv)
{
case 11:
pred += back[0][s] / 2 - back[0][s - 2] / 2;
break;
}
f = (row & 1) * 3 ^ ((col + s) & 1);
FORC(tiff_samples)
{
pred += diff[(s & 1) * tiff_samples + c];
upix = pred >> sh & 0xffff;
if (raw_image && c == shot)
RAW(row, s) = upix;
if (image)
{
urow = row - top_margin + (c & 1);
ucol = col - left_margin - ((c >> 1) & 1);
ip = &image[urow * width + ucol][f];
if (urow < height && ucol < width)
*ip = c < 4 ? upix : (*ip + upix) >> 1;
}
}
back[2][s] = pred;
}
}
}
#ifdef LIBRAW_LIBRARY_BUILD
}
catch (...)
{
free(back[4]);
ljpeg_end(&jh);
throw;
}
#endif
free(back[4]);
ljpeg_end(&jh);
if (image)
mix_green = 1;
}
void CLASS leaf_hdr_load_raw()
{
ushort *pixel = 0;
unsigned tile = 0, r, c, row, col;
if (!filters || !raw_image)
{
#ifdef LIBRAW_LIBRARY_BUILD
if(!image)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
pixel = (ushort *)calloc(raw_width, sizeof *pixel);
merror(pixel, "leaf_hdr_load_raw()");
}
#ifdef LIBRAW_LIBRARY_BUILD
try
{
#endif
FORC(tiff_samples)
for (r = 0; r < raw_height; r++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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 && raw_image)
pixel = raw_image + r * raw_width;
read_shorts(pixel, raw_width);
if (!filters && image && (row = r - top_margin) < height)
for (col = 0; col < width; col++)
image[row * width + col][c] = pixel[col + left_margin];
}
#ifdef LIBRAW_LIBRARY_BUILD
}
catch (...)
{
if (!filters)
free(pixel);
throw;
}
#endif
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);
fseek(ifp,-2,SEEK_CUR); // avoid EOF error
if (maximum < 0xffff || load_flags)
for (row = 0; row < raw_height; row++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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 unpacked_load_raw_FujiDBP()
/*
for Fuji DBP for GX680, aka DX-2000
DBP_tile_width = 688;
DBP_tile_height = 3856;
DBP_n_tiles = 8;
*/
{
int scan_line, tile_n;
int nTiles;
nTiles = 8;
tile_width = raw_width / nTiles;
ushort *tile;
tile = (ushort *)calloc(raw_height, tile_width * 2);
for (tile_n = 0; tile_n < nTiles; tile_n++)
{
read_shorts(tile, tile_width * raw_height);
for (scan_line = 0; scan_line < raw_height; scan_line++)
{
memcpy (&raw_image[scan_line * raw_width + tile_n * tile_width], &tile[scan_line * tile_width], tile_width * 2);
}
}
free (tile);
fseek(ifp,-2,SEEK_CUR); // avoid EOF error
}
void CLASS unpacked_load_raw_reversed()
{
int row, col, bits = 0;
while (1 << ++bits < maximum)
;
for (row = raw_height - 1; row >= 0; row--)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
read_shorts(&raw_image[row * raw_width], raw_width);
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 (raw_image)
{
shot = LIM(shot_select, 1, 4) - 1;
fseek(ifp, data_offset + shot * 4, SEEK_SET);
fseek(ifp, get4(), SEEK_SET);
unpacked_load_raw();
return;
}
#ifdef LIBRAW_LIBRARY_BUILD
if (!image)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
pixel = (ushort *)calloc(raw_width, sizeof *pixel);
merror(pixel, "sinar_4shot_load_raw()");
#ifdef LIBRAW_LIBRARY_BUILD
try
{
#endif
for (shot = 0; shot < 4; shot++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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][(row & 1) * 3 ^ (~col & 1)] = pixel[col];
}
}
}
#ifdef LIBRAW_LIBRARY_BUILD
}
catch (...)
{
free(pixel);
throw;
}
#endif
free(pixel);
mix_green = 1;
}
void CLASS imacon_full_load_raw()
{
#ifdef LIBRAW_LIBRARY_BUILD
if (!image)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
int row, col;
#ifdef LIBRAW_LIBRARY_BUILD
unsigned short *buf = (unsigned short *)malloc(width * 3 * sizeof(unsigned short));
merror(buf, "imacon_full_load_raw");
#endif
for (row = 0; row < height; row++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
read_shorts(buf, width * 3);
unsigned short(*rowp)[4] = &image[row * width];
for (col = 0; col < width; col++)
{
rowp[col][0] = buf[col * 3];
rowp[col][1] = buf[col * 3 + 1];
rowp[col][2] = buf[col * 3 + 2];
rowp[col][3] = 0;
}
#else
for (col = 0; col < width; col++)
read_shorts(image[row * width + col], 3);
#endif
}
#ifdef LIBRAW_LIBRARY_BUILD
free(buf);
#endif
}
void CLASS packed_load_raw()
{
int vbits = 0, bwide, rbits, bite, half, irow, row, col, val, i;
UINT64 bitbuf = 0;
bwide = raw_width * tiff_bps / 8;
bwide += bwide & load_flags >> 7;
rbits = bwide * 8 - raw_width * tiff_bps;
if (load_flags & 1)
bwide = bwide * 16 / 15;
bite = 8 + (load_flags & 24);
half = (raw_height + 1) >> 1;
for (irow = 0; irow < raw_height; irow++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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);
}
}
#ifdef LIBRAW_LIBRARY_BUILD
if(feof(ifp)) throw LIBRAW_EXCEPTION_IO_EOF;
#endif
for (col = 0; col < raw_width; col++)
{
for (vbits -= tiff_bps; vbits < 0; vbits += bite)
{
bitbuf <<= bite;
for (i = 0; i < bite; i += 8)
bitbuf |= (unsigned)(fgetc(ifp) << i);
}
val = bitbuf << (64 - tiff_bps - vbits) >> (64 - tiff_bps);
RAW(row, col ^ (load_flags >> 6 & 1)) = val;
if (load_flags & 1 && (col % 10) == 9 && fgetc(ifp) && row < height + top_margin && col < width + left_margin)
derror();
}
vbits -= rbits;
}
}
#ifdef LIBRAW_LIBRARY_BUILD
ushort raw_stride;
void CLASS parse_broadcom()
{
/* This structure is at offset 0xb0 from the 'BRCM' ident. */
struct
{
uint8_t umode[32];
uint16_t uwidth;
uint16_t uheight;
uint16_t padding_right;
uint16_t padding_down;
uint32_t unknown_block[6];
uint16_t transform;
uint16_t format;
uint8_t bayer_order;
uint8_t bayer_format;
} header;
header.bayer_order = 0;
fseek(ifp, 0xb0 - 0x20, SEEK_CUR);
fread(&header, 1, sizeof(header), ifp);
raw_stride = ((((((header.uwidth + header.padding_right) * 5) + 3) >> 2) + 0x1f) & (~0x1f));
raw_width = width = header.uwidth;
raw_height = height = header.uheight;
filters = 0x16161616; /* default Bayer order is 2, BGGR */
switch (header.bayer_order)
{
case 0: /* RGGB */
filters = 0x94949494;
break;
case 1: /* GBRG */
filters = 0x49494949;
break;
case 3: /* GRBG */
filters = 0x61616161;
break;
}
}
void CLASS broadcom_load_raw()
{
uchar *data, *dp;
int rev, row, col, c;
rev = 3 * (order == 0x4949);
data = (uchar *)malloc(raw_stride * 2);
merror(data, "broadcom_load_raw()");
for (row = 0; row < raw_height; row++)
{
if (fread(data + raw_stride, 1, raw_stride, ifp) < raw_stride)
derror();
FORC(raw_stride) data[c] = data[raw_stride + (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);
}
#endif
void CLASS nokia_load_raw()
{
uchar *data, *dp;
int rev, dwide, row, col, c;
double sum[] = {0, 0};
rev = 3 * (order == 0x4949);
dwide = (raw_width * 5 + 1) / 4;
data = (uchar *)malloc(dwide * 2);
merror(data, "nokia_load_raw()");
#ifdef LIBRAW_LIBRARY_BUILD
try
{
#endif
for (row = 0; row < raw_height; row++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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);
}
#ifdef LIBRAW_LIBRARY_BUILD
}
catch (...)
{
free(data);
throw;
}
#endif
free(data);
maximum = 0x3ff;
if (strncmp(make, "OmniVision", 10))
return;
row = raw_height / 2;
FORC(width - 1)
{
sum[c & 1] += SQR(RAW(row, c) - RAW(row + 1, c + 1));
sum[~c & 1] += SQR(RAW(row + 1, c) - RAW(row, c + 1));
}
if (sum[1] > sum[0])
filters = 0x4b4b4b4b;
}
void CLASS android_tight_load_raw()
{
uchar *data, *dp;
int bwide, row, col, c;
bwide = -(-5 * raw_width >> 5) << 3;
data = (uchar *)malloc(bwide);
merror(data, "android_tight_load_raw()");
for (row = 0; row < raw_height; row++)
{
if (fread(data, 1, bwide, ifp) < bwide)
derror();
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);
}
void CLASS android_loose_load_raw()
{
uchar *data, *dp;
int bwide, row, col, c;
UINT64 bitbuf = 0;
bwide = (raw_width + 5) / 6 << 3;
data = (uchar *)malloc(bwide);
merror(data, "android_loose_load_raw()");
for (row = 0; row < raw_height; row++)
{
if (fread(data, 1, bwide, ifp) < bwide)
derror();
for (dp = data, col = 0; col < raw_width; dp += 8, col += 6)
{
FORC(8) bitbuf = (bitbuf << 8) | dp[c ^ 7];
FORC(6) RAW(row, col + c) = (bitbuf >> c * 10) & 0x3ff;
}
}
free(data);
}
void CLASS canon_rmf_load_raw()
{
int row, col, bits, orow, ocol, c;
#ifdef LIBRAW_LIBRARY_BUILD
int *words = (int *)malloc(sizeof(int) * (raw_width / 3 + 1));
merror(words, "canon_rmf_load_raw");
#endif
for (row = 0; row < raw_height; row++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
fread(words, sizeof(int), raw_width / 3, ifp);
for (col = 0; col < raw_width - 2; col += 3)
{
bits = words[col / 3];
FORC3
{
orow = row;
if ((ocol = col + c - 4) < 0)
{
ocol += raw_width;
if ((orow -= 2) < 0)
orow += raw_height;
}
RAW(orow, ocol) = curve[bits >> (10 * c + 2) & 0x3ff];
}
}
#else
for (col = 0; col < raw_width - 2; col += 3)
{
bits = get4();
FORC3
{
orow = row;
if ((ocol = col + c - 4) < 0)
{
ocol += raw_width;
if ((orow -= 2) < 0)
orow += raw_height;
}
RAW(orow, ocol) = curve[bits >> (10 * c + 2) & 0x3ff];
}
}
#endif
}
#ifdef LIBRAW_LIBRARY_BUILD
free(words);
#endif
maximum = curve[0x3ff];
}
unsigned CLASS pana_data(int nb, unsigned *bytes)
{
#ifndef LIBRAW_NOTHREADS
#define vpos tls->pana_data.vpos
#define buf tls->pana_data.buf
#else
static uchar buf[0x4002];
static int vpos;
#endif
int byte;
if (!nb && !bytes)
return vpos = 0;
if (!vpos)
{
fread(buf + load_flags, 1, 0x4000 - load_flags, ifp);
fread(buf, 1, load_flags, ifp);
}
#ifdef LIBRAW_LIBRARY_BUILD /* not part of std. dcraw */
if (pana_encoding == 5)
{
for (byte = 0; byte < 16; byte++)
{
bytes[byte] = buf[vpos++];
vpos &= 0x3FFF;
}
}
else
#endif
{
vpos = (vpos - nb) & 0x1ffff;
byte = vpos >> 3 ^ 0x3ff0;
return (buf[byte] | buf[byte + 1] << 8) >> (vpos & 7) & ~((~0u) << nb);
}
return 0;
#ifndef LIBRAW_NOTHREADS
#undef vpos
#undef buf
#endif
}
void CLASS panasonic_load_raw()
{
int row, col, i, j, sh = 0, pred[2], nonz[2];
unsigned bytes[16];
ushort *raw_block_data;
pana_data(0, 0);
#ifdef LIBRAW_LIBRARY_BUILD
int enc_blck_size = pana_bpp == 12 ? 10 : 9;
if (pana_encoding == 5)
{
for (row = 0; row < raw_height; row++)
{
raw_block_data = raw_image + row * raw_width;
checkCancel();
for (col = 0; col < raw_width; col += enc_blck_size)
{
pana_data(0, bytes);
if (pana_bpp == 12)
{
raw_block_data[col] = ((bytes[1] & 0xF) << 8) + bytes[0];
raw_block_data[col + 1] = 16 * bytes[2] + (bytes[1] >> 4);
raw_block_data[col + 2] = ((bytes[4] & 0xF) << 8) + bytes[3];
raw_block_data[col + 3] = 16 * bytes[5] + (bytes[4] >> 4);
raw_block_data[col + 4] = ((bytes[7] & 0xF) << 8) + bytes[6];
raw_block_data[col + 5] = 16 * bytes[8] + (bytes[7] >> 4);
raw_block_data[col + 6] = ((bytes[10] & 0xF) << 8) + bytes[9];
raw_block_data[col + 7] = 16 * bytes[11] + (bytes[10] >> 4);
raw_block_data[col + 8] = ((bytes[13] & 0xF) << 8) + bytes[12];
raw_block_data[col + 9] = 16 * bytes[14] + (bytes[13] >> 4);
}
else if (pana_bpp == 14)
{
raw_block_data[col] = bytes[0] + ((bytes[1] & 0x3F) << 8);
raw_block_data[col + 1] = (bytes[1] >> 6) + 4 * (bytes[2]) +
((bytes[3] & 0xF) << 10);
raw_block_data[col + 2] = (bytes[3] >> 4) + 16 * (bytes[4]) +
((bytes[5] & 3) << 12);
raw_block_data[col + 3] = ((bytes[5] & 0xFC) >> 2) + (bytes[6] << 6);
raw_block_data[col + 4] = bytes[7] + ((bytes[8] & 0x3F) << 8);
raw_block_data[col + 5] = (bytes[8] >> 6) + 4 * bytes[9] + ((bytes[10] & 0xF) << 10);
raw_block_data[col + 6] = (bytes[10] >> 4) + 16 * bytes[11] + ((bytes[12] & 3) << 12);
raw_block_data[col + 7] = ((bytes[12] & 0xFC) >> 2) + (bytes[13] << 6);
raw_block_data[col + 8] = bytes[14] + ((bytes[15] & 0x3F) << 8);
}
}
}
}
else
#endif
{
for (row = 0; row < raw_height; row++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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_data(2, 0));
if (nonz[i & 1])
{
if ((j = pana_data(8, 0)))
{
if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4)
pred[i & 1] &= ~((~0u) << sh);
pred[i & 1] += j << sh;
}
}
else if ((nonz[i & 1] = pana_data(8, 0)) || i > 11)
pred[i & 1] = nonz[i & 1] << 4 | pana_data(4, 0);
if ((RAW(row, col) = pred[col & 1]) > 4098 && col < width && row < height)
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);
getbits(-1);
for (row = 0; row < height; row++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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++)
;
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);
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();
}
}
}
void CLASS minolta_rd175_load_raw()
{
uchar pixel[768];
unsigned irow, box, row, col;
for (irow = 0; irow < 1481; irow++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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;
#ifdef LIBRAW_LIBRARY_BUILD
if(width>640 || height > 480)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
getbits(-1);
memset(pixel, 0x80, sizeof pixel);
for (row = 2; row < height + 2; row++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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++)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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()
{
#ifdef LIBRAW_LIBRARY_BUILD
// All kodak radc images are 768x512
if (width > 768 || raw_width > 768 || height > 512 || raw_height > 512)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
static const signed 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])
((ushort *)huff)[s++] = src[i] << 8 | (uchar)src[i + 1];
s = kodak_cbpp == 243 ? 2 : 3;
FORC(256) huff[18][c] = (8 - s) << 8 | c >> s << s | 1 << (s - 1);
getbits(-1);
for (i = 0; i < sizeof(buf) / sizeof(short); i++)
((short *)buf)[i] = 2048;
for (row = 0; row < height; row += 4)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
FORC3 mul[c] = getbits(6);
#ifdef LIBRAW_LIBRARY_BUILD
if (!mul[0] || !mul[1] || !mul[2])
throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
FORC3
{
val = ((0x1000000 / last[c] + 0x7ff) >> 12) * mul[c];
s = val > 65564 ? 10 : 12;
x = ~((~0u) << (s - 1));
val <<= 12 - s;
for (i = 0; i < sizeof(buf[0]) / sizeof(short); i++)
((short *)buf[c])[i] = (((short *)buf[c])[i] * val + x) >> s;
last[c] = mul[c];
for (r = 0; r <= !c; r++)
{
buf[c][1][width / 2] = buf[c][2][width / 2] = mul[c] << 7;
for (tree = 1, col = width / 2; col > 0;)
{
if ((tree = radc_token(tree)))
{
col -= 2;
if(col>=0)
{
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;
if(col>=0)
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
#ifndef LIBRAW_LIBRARY_BUILD
METHODDEF(boolean)
fill_input_buffer(j_decompress_ptr cinfo)
{
static uchar jpeg_buffer[4096];
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;
}
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))
{
fprintf(stderr, _("%s: incorrect JPEG dimensions\n"), ifname);
jpeg_destroy_decompress(&cinfo);
longjmp(failure, 3);
}
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;
}
#else
struct jpegErrorManager
{
struct jpeg_error_mgr pub;
};
static void jpegErrorExit(j_common_ptr cinfo)
{
jpegErrorManager *myerr = (jpegErrorManager *)cinfo->err;
throw LIBRAW_EXCEPTION_DECODE_JPEG;
}
// LibRaw's Kodak_jpeg_load_raw
void CLASS kodak_jpeg_load_raw()
{
if (data_size < 1)
throw LIBRAW_EXCEPTION_DECODE_JPEG;
int row, col;
jpegErrorManager jerr;
struct jpeg_decompress_struct cinfo;
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = jpegErrorExit;
unsigned char *jpg_buf = (unsigned char *)malloc(data_size);
merror(jpg_buf, "kodak_jpeg_load_raw");
unsigned char *pixel_buf = (unsigned char *)malloc(width * 3);
jpeg_create_decompress(&cinfo);
merror(pixel_buf, "kodak_jpeg_load_raw");
fread(jpg_buf, data_size, 1, ifp);
swab((char *)jpg_buf, (char *)jpg_buf, data_size);
try
{
jpeg_mem_src(&cinfo, jpg_buf, data_size);
int rc = jpeg_read_header(&cinfo, TRUE);
if (rc != 1)
throw LIBRAW_EXCEPTION_DECODE_JPEG;
jpeg_start_decompress(&cinfo);
if ((cinfo.output_width != width) || (cinfo.output_height * 2 != height) || (cinfo.output_components != 3))
{
throw LIBRAW_EXCEPTION_DECODE_JPEG;
}
unsigned char *buf[1];
buf[0] = pixel_buf;
while (cinfo.output_scanline < cinfo.output_height)
{
checkCancel();
row = cinfo.output_scanline * 2;
jpeg_read_scanlines(&cinfo, buf, 1);
unsigned char(*pixel)[3] = (unsigned char(*)[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];
}
}
}
catch (...)
{
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
free(jpg_buf);
free(pixel_buf);
throw;
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
free(jpg_buf);
free(pixel_buf);
maximum = 0xff << 1;
}
#endif
#ifndef LIBRAW_LIBRARY_BUILD
void CLASS gamma_curve(double pwr, double ts, int mode, int imax);
#endif
void CLASS lossy_dng_load_raw()
{
#ifdef LIBRAW_LIBRARY_BUILD
if (!image)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
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 cur[3][256];
double coeff[9], tot;
if (meta_offset)
{
fseek(ifp, meta_offset, SEEK_SET);
order = 0x4d4d;
ntags = get4();
while (ntags--)
{
opcode = get4();
get4();
get4();
if (opcode != 8)
{
fseek(ifp, get4(), SEEK_CUR);
continue;
}
fseek(ifp, 20, SEEK_CUR);
if ((c = get4()) > 2)
break;
fseek(ifp, 12, SEEK_CUR);
if ((deg = get4()) > 8)
break;
for (i = 0; i <= deg && i < 9; i++)
coeff[i] = getreal(12);
for (i = 0; i < 256; i++)
{
for (tot = j = 0; j <= deg; j++)
tot += coeff[j] * pow(i / 255.0, (int)j);
cur[c][i] = tot * 0xffff;
}
}
order = sorder;
}
else
{
gamma_curve(1 / 2.4, 12.92, 1, 255);
FORC3 memcpy(cur[c], curve, sizeof cur[0]);
}
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);
#ifdef LIBRAW_LIBRARY_BUILD
try
{
#endif
while (cinfo.output_scanline < cinfo.output_height && (row = trow + cinfo.output_scanline) < height)
{
#ifdef LIBRAW_LIBRARY_BUILD
checkCancel();
#endif
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] = cur[c][pixel[col][c]];
}
}
#ifdef LIBRAW_LIBRARY_BUILD
}
catch (...)
{
jpeg_destroy_decompress(&cinfo);
throw;
}
#endif
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<