blob: dd7287b1dbd6bc739e7a324d088683411bd2c561 [file]
/* -*- C++ -*-
* Copyright 2019-2025 LibRaw LLC (info@libraw.org)
*
LibRaw uses code from dcraw.c -- Dave Coffin's raw photo decoder,
dcraw.c is copyright 1997-2018 by Dave Coffin, dcoffin a cybercom o net.
LibRaw do not use RESTRICTED code from dcraw.c
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).
*/
#include "third_party/libraw/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()
{
// All kodak radc images are 768x512
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,0);
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] = ushort((float)(c - pt[i - 2]) / (pt[i] - pt[i - 2]) *
(pt[i + 1] - pt[i - 1]) +
pt[i - 1] + 0.5f);
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] =
short((MIN(0x7FFFFFFF, (((short *)buf[c])[i] * static_cast<long long>(val) + x)) >> s) & 0xffff);
last[c] = mul[c];
for (r = 0; r <= int(!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;
}
// LibRaw's Kodak_jpeg_load_raw
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;
if (INT64(data_size) >
INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024))
throw LIBRAW_EXCEPTION_TOOBIG;
unsigned char *jpg_buf = (unsigned char *)calloc(data_size,1);
std::vector<uchar> pixel_buf(width * 3, 0);
jpeg_create_decompress(&cinfo);
fread(jpg_buf, data_size, 1, ifp);
libraw_swab(jpg_buf, int(data_size));
try
{
jpeg_mem_src(&cinfo, jpg_buf, (unsigned long)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.data();
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);
throw;
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
free(jpg_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;
int row, col, y, cb, cr, rgb[3], c;
std::vector<uchar> pixel(raw_width*2 + 4);
for (row = 0; row < height; row++)
{
checkCancel();
if (fread(pixel.data(), 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)];
}
}
maximum = curve[0xff];
}
void LibRaw::kodak_c603_load_raw()
{
if (!image)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
int row, col, y, cb, cr, rgb[3], c;
std::vector<uchar> pixel(raw_width * 3);
for (row = 0; row < height; row++)
{
checkCancel();
if (~row & 1)
if (fread(pixel.data(), 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)];
}
}
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];
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;
std::vector<uchar> pixel(raw_width * 32 + ns * 4);
strip = (int *)(pixel.data() + 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 (...)
{
FORC(2) free(huff[c]);
throw;
}
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 bits = 0, i, j, len, diff;
INT64 save;
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]; /* 264 looks enough */
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;
const int pixels = int(width)*int(height);
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();
int indx = (row + j) * width + col + i + k;
if(indx>=0 && indx < pixels)
{
ip = image[indx];
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;
}