#include "../../internal/dcraw_defs.h"
#define radc_token(tree) ((signed char)getbithuff(8, huff + (tree) * 256))
#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 LibRaw::kodak_radc_load_raw()
{
if (width > 768 || raw_width > 768 || height > 512 || raw_height > 512)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
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};
std::vector<ushort> huff_buffer(19 * 256);
ushort* huff = &huff_buffer[0];
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 < int(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 * 256 + c] = (8 - s) << 8 | c >> s << s | 1 << (s - 1);
getbits(-1);
for (i = 0; i < int(sizeof(buf) / sizeof(short)); i++)
((short *)buf)[i] = 2048;
for (row = 0; row < height; row += 4)
{
checkCancel();
FORC3 mul[c] = getbits(6);
if (!mul[0] || !mul[1] || !mul[2])
throw LIBRAW_EXCEPTION_IO_CORRUPT;
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 < int(sizeof(buf[0]) / sizeof(short)); i++)
((short *)buf[c])[i] = MIN(0x7FFFFFFF, (((short *)buf[c])[i] * static_cast<long long>(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 LibRaw::kodak_jpeg_load_raw() {}
#else
static void jpegErrorExit_k(j_common_ptr cinfo)
{
throw LIBRAW_EXCEPTION_DECODE_JPEG;
}
void LibRaw::kodak_jpeg_load_raw()
{
if (data_size < 1)
throw LIBRAW_EXCEPTION_DECODE_JPEG;
int row, col;
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr pub;
cinfo.err = jpeg_std_error(&pub);
pub.error_exit = jpegErrorExit_k;
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
void LibRaw::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++)
{
checkCancel();
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 LibRaw::kodak_c330_load_raw()
{
if (!image)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
uchar *pixel;
int row, col, y, cb, cr, rgb[3], c;
pixel = (uchar *)calloc(raw_width, 2 * sizeof *pixel);
merror(pixel, "kodak_c330_load_raw()");
try
{
for (row = 0; row < height; row++)
{
checkCancel();
if (fread(pixel, raw_width, 2, ifp) < 2)
derror();
if (load_flags && (row & 31) == 31)
fseek(ifp, raw_width * 32, SEEK_CUR);
for (col = 0; col < width; col++)
{
y = pixel[col * 2];
cb = pixel[(col * 2 & -4) | 1] - 128;
cr = pixel[(col * 2 & -4) | 3] - 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)];
}
}
}
catch (...)
{
free(pixel);
throw;
}
free(pixel);
maximum = curve[0xff];
}
void LibRaw::kodak_c603_load_raw()
{
if (!image)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
uchar *pixel;
int row, col, y, cb, cr, rgb[3], c;
pixel = (uchar *)calloc(raw_width, 3 * sizeof *pixel);
merror(pixel, "kodak_c603_load_raw()");
try
{
for (row = 0; row < height; row++)
{
checkCancel();
if (~row & 1)
if (fread(pixel, raw_width, 3, ifp) < 3)
derror();
for (col = 0; col < 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)];
}
}
}
catch (...)
{
free(pixel);
throw;
}
free(pixel);
maximum = curve[0xff];
}
void LibRaw::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();
try
{
for (row = 0; row < raw_height; row++)
{
checkCancel();
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;
}
}
}
catch (...)
{
free(pixel);
throw;
}
free(pixel);
FORC(2) free(huff[c]);
}
int LibRaw::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 (len > 0 && (diff & (1 << (len - 1))) == 0)
diff -= (1 << len) - 1;
out[i] = diff;
}
return 0;
}
void LibRaw::kodak_65000_load_raw()
{
short buf[272];
int row, col, len, pred[2], ret, i;
for (row = 0; row < height; row++)
{
checkCancel();
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++)
{
int idx = ret ? buf[i] : (pred[i & 1] += buf[i]);
if (idx >= 0 && idx < 0xffff)
{
if ((RAW(row, col + i) = curve[idx]) >> 12)
derror();
}
else
derror();
}
}
}
}
void LibRaw::kodak_ycbcr_load_raw()
{
if (!image)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
short buf[384], *bp;
int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3];
ushort *ip;
unsigned int bits =
(load_flags && load_flags > 9 && load_flags < 17) ? load_flags : 10;
for (row = 0; row < height; row += 2)
{
checkCancel();
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++) >> bits)
derror();
ip = image[(row + j) * width + col + i + k];
FORC3 ip[c] = curve[LIM(y[j][k] + rgb[c], 0, 0xfff)];
}
}
}
}
}
void LibRaw::kodak_rgb_load_raw()
{
if (!image)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
short buf[768], *bp;
int row, col, len, c, i, rgb[3], ret;
ushort *ip = image[0];
for (row = 0; row < height; row++)
{
checkCancel();
for (col = 0; col < width; col += 256)
{
len = MIN(256, width - col);
ret = kodak_65000_decode(buf, len * 3);
memset(rgb, 0, sizeof rgb);
for (bp = buf, i = 0; i < len; i++, ip += 4)
if (load_flags == 12)
FORC3 ip[c] = ret ? (*bp++) : (rgb[c] += *bp++);
else
FORC3 if ((ip[c] = ret ? (*bp++) : (rgb[c] += *bp++)) >> 12) derror();
}
}
}
void LibRaw::kodak_thumb_load_raw()
{
if (!image)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
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;
}