#include "../../internal/dcraw_defs.h"
#include "../../internal/libraw_cameraids.h"
unsigned LibRaw::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)) != (unsigned)EOF &&
!(reset = zero_after_ff && c == 0xff && fgetc(ifp)))
{
bitbuf = (bitbuf << 8) + (uchar)c;
vbits += 8;
}
c = vbits == 0 ? 0 : 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
}
ushort *LibRaw::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 *LibRaw::make_decoder(const uchar *source)
{
return make_decoder_ref(&source);
}
void LibRaw::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]);
}
int LibRaw::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 < int(sizeof test - 1); i++)
if (test[i] == 0xff)
{
if (test[i + 1])
return 1;
ret = 0;
}
return ret;
}
void LibRaw::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);
try
{
for (row = 0; row < raw_height; row += 8)
{
checkCancel();
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);
}
}
}
catch (...)
{
FORC(2) free(huff[c]);
throw;
}
FORC(2) free(huff[c]);
}
int LibRaw::ljpeg_start(struct jhead *jh, int info_only)
{
ushort c, tag, len;
int cnt = 0;
std::vector<uchar> data_buffer(0x10000);
uchar* data = &data_buffer[0];
const uchar *dp;
memset(jh, 0, sizeof *jh);
jh->restart = INT_MAX;
if (fread(data, 2, 1, ifp) != 1 || data[1] != 0xd8)
return 0;
do
{
if (feof(ifp))
return 0;
if (cnt++ > 1024)
return 0; if (fread(data, 2, 2, ifp) != 2)
return 0;
tag = data[0] << 8 | data[1];
len = (data[2] << 8 | data[3]) - 2;
if (tag <= 0xff00)
return 0;
if (fread(data, 1, len, ifp) != len)
return 0;
switch (tag)
{
case 0xffc3: 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: 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: 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, 16);
merror(jh->row, "ljpeg_start()");
return zero_after_ff = 1;
}
void LibRaw::ljpeg_end(struct jhead *jh)
{
int c;
FORC4 if (jh->free[c]) free(jh->free[c]);
free(jh->row);
}
int LibRaw::ljpeg_diff(ushort *huff)
{
int len, diff;
if (!huff)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
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 *LibRaw::ljpeg_row(int jrow, struct jhead *jh)
{
int col, c, diff, pred, spred = 0;
ushort mark = 0, *row[3];
if (!jh->sraw)
return ljpeg_row_unrolled(jrow, jh);
if (jh->restart != 0 && 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)
if(!(load_flags & 512))
derror();
if (c <= jh->sraw)
spred = **row;
row[0]++;
row[1]++;
}
return row[2];
}
ushort *LibRaw::ljpeg_row_unrolled(int jrow, struct jhead *jh)
{
int col, c, diff, pred;
ushort mark = 0, *row[3];
if (jh->restart != 0 && 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);
FORC(jh->clrs)
{
diff = ljpeg_diff(jh->huff[c]);
pred = (jh->vpred[c] += diff) - diff;
if ((**row = pred + diff) >> jh->bits)
derror();
row[0]++;
row[1]++;
}
if (!jrow)
{
for (col = 1; col < jh->wide; col++)
FORC(jh->clrs)
{
diff = ljpeg_diff(jh->huff[c]);
pred = row[0][-jh->clrs];
if ((**row = pred + diff) >> jh->bits)
derror();
row[0]++;
row[1]++;
}
}
else if (jh->psv == 1)
{
for (col = 1; col < jh->wide; col++)
FORC(jh->clrs)
{
diff = ljpeg_diff(jh->huff[c]);
pred = row[0][-jh->clrs];
if ((**row = pred + diff) >> jh->bits)
derror();
row[0]++;
}
}
else
{
for (col = 1; col < jh->wide; col++)
FORC(jh->clrs)
{
diff = ljpeg_diff(jh->huff[c]);
pred = row[0][-jh->clrs];
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();
row[0]++;
row[1]++;
}
}
return row[2];
}
void LibRaw::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)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
jwide = jh.wide * jh.clrs;
jhigh = jh.high;
if (jh.clrs == 4 && jwide >= raw_width * 2)
jhigh *= 2;
try
{
for (jrow = 0; jrow < jh.high; jrow++)
{
checkCancel();
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)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
if ((unsigned)row < raw_height)
RAW(row, col) = val;
if (++col >= raw_width)
col = (row++, 0);
}
}
}
catch (...)
{
ljpeg_end(&jh);
throw;
}
ljpeg_end(&jh);
}
void LibRaw::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;
int saved_w = width, saved_h = height;
char *cp;
if (!ljpeg_start(&jh, 0) || jh.clrs < 4)
return;
jwide = (jh.wide >>= 1) * jh.clrs;
if (load_flags & 256)
{
width = raw_width;
height = raw_height;
}
try
{
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)
{
checkCancel();
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;
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
{
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;
}
}
}
}
}
catch (...)
{
ljpeg_end(&jh);
throw;
}
if (imgdata.params.raw_processing_options &
LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE)
{
ljpeg_end(&jh);
maximum = 0x3fff;
height = saved_h;
width = saved_w;
return;
}
try
{
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 >= 0x80000281ULL ||
(unique_id == 0x80000218ULL && ver > 1000006))
hue = jh.sraw << 1;
ip = (short(*)[4])image;
rp = ip[0];
for (row = 0; row < height; row++, ip += width)
{
checkCancel();
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;
}
if (!(imgdata.params.raw_processing_options &
LIBRAW_PROCESSING_SRAW_NO_RGB))
for (; rp < ip[0]; rp += 4)
{
checkCancel();
if ((unique_id == CanonID_EOS_5D_Mark_II) ||
(unique_id == CanonID_EOS_7D) ||
(unique_id == CanonID_EOS_50D) ||
(unique_id == CanonID_EOS_1D_Mark_IV) ||
(unique_id == CanonID_EOS_60D))
{
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 < CanonID_EOS_5D_Mark_II)
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);
}
}
catch (...)
{
ljpeg_end(&jh);
throw;
}
height = saved_h;
width = saved_w;
ljpeg_end(&jh);
maximum = 0x3fff;
}
void LibRaw::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 LibRaw::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++)
{
checkCancel();
for (col = 0; col < raw_width; col++)
{
diff = ljpeg_diff(huff);
if (col < 2)
hpred[col] = vpred[row & 1][col] += diff;
else
hpred[col & 1] += diff;
RAW(row, col) = hpred[col & 1];
if (hpred[col & 1] >> tiff_bps)
derror();
}
}
}
void LibRaw::nikon_read_curve()
{
ushort ver0, ver1, vpred[2][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 LibRaw::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,
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,
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,
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,
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,
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,
7, 6, 8, 5, 9, 4, 10, 3, 11, 12, 2, 0, 1, 13, 14}};
ushort *huff, ver0, ver1, vpred[2][2], hpred[2];
int i, min, max, 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 (ver0 == 0x44 && (ver1 == 0x20 || ver1 == 0x40))
{
if (ver1 == 0x40)
max /= 4;
fseek(ifp, meta_offset + 562, SEEK_SET);
split = get2();
}
while (max > 2 && (curve[max - 2] == curve[max - 1]))
max--;
huff = make_decoder(nikon_tree[tree]);
fseek(ifp, data_offset, SEEK_SET);
getbits(-1);
try
{
for (min = row = 0; row < height; row++)
{
checkCancel();
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 (len > 0 && (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)];
}
}
}
catch (...)
{
free(huff);
throw;
}
free(huff);
}
void LibRaw::nikon_yuv_load_raw()
{
if (!image)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
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++)
{
checkCancel();
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];
}
}
}
void LibRaw::rollei_load_raw()
{
uchar pixel[10];
unsigned iten = 0, isix, i, buffer = 0, todo[16];
if (raw_width > 32767 || raw_height > 32767)
throw LIBRAW_EXCEPTION_IO_BADFILE;
unsigned maxpixel = raw_width * (raw_height + 7);
isix = raw_width * raw_height * 5 / 8;
while (fread(pixel, 1, 10, ifp) == 10)
{
checkCancel();
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;
}
void LibRaw::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;
#ifdef USE_6BY9RPI
if (raw_stride)
dwide = raw_stride;
#endif
data = (uchar *)malloc(dwide * 2);
merror(data, "nokia_load_raw()");
try
{
for (row = 0; row < raw_height; row++)
{
checkCancel();
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);
}
}
catch (...)
{
free(data);
throw;
}
free(data);
maximum = 0x3ff;
#ifdef USE_6BY9RPI
if (!strcmp(make, "OmniVision") ||
!strcmp(make, "Sony") ||
!strcmp(make, "RaspberryPi")) return;
#else
if (strncmp(make, "OmniVision", 10))
return;
#endif
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 LibRaw::canon_rmf_load_raw()
{
int row, col, bits, orow, ocol, c;
int *words = (int *)malloc(sizeof(int) * (raw_width / 3 + 1));
merror(words, "canon_rmf_load_raw");
for (row = 0; row < raw_height; row++)
{
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];
}
}
}
free(words);
maximum = curve[0x3ff];
}
unsigned LibRaw::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);
}
if (pana_encoding == 5)
{
for (byte = 0; byte < 16; byte++)
{
bytes[byte] = buf[vpos++];
vpos &= 0x3FFF;
}
}
else
{
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 LibRaw::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);
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
{
for (row = 0; row < raw_height; row++)
{
checkCancel();
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 LibRaw::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++)
{
checkCancel();
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 LibRaw::minolta_rd175_load_raw()
{
uchar pixel[768];
unsigned irow, box, row, col;
for (irow = 0; irow < 1481; irow++)
{
checkCancel();
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 LibRaw::quicktake_100_load_raw()
{
std::vector<uchar> pixel_buffer(484 * 644, 0x80);
uchar* pixel = &pixel_buffer[0];
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;
if (width > 640 || height > 480)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
getbits(-1);
for (row = 2; row < height + 2; row++)
{
checkCancel();
for (col = 2 + (row & 1); col < width + 2; col += 2)
{
val = ((pixel[(row - 1) * 644 + col - 1] + 2 * pixel[(row - 1) * 644 + col + 1] + pixel[row * 644 + col - 2]) >> 2) + gstep[getbits(4)];
pixel[row * 644 + col] = val = LIM(val, 0, 255);
if (col < 4)
pixel[row * 644 + col - 2] = pixel[(row + 1) * 644 + (~row & 1)] = val;
if (row == 2)
pixel[(row - 1) * 644 + col + 1] = pixel[(row - 1) * 644 + col + 3] = val;
}
pixel[row * 644 + col] = val;
}
for (rb = 0; rb < 2; rb++)
for (row = 2 + rb; row < height + 2; row += 2)
{
checkCancel();
for (col = 3 - (row & 1); col < width + 2; col += 2)
{
if (row < 4 || col < 4)
sharp = 2;
else
{
val = ABS(pixel[(row - 2) * 644 + col] - pixel[row * 644 + col - 2]) + ABS(pixel[(row - 2) * 644 + col] - pixel[(row - 2) * 644 + col - 2]) +
ABS(pixel[row * 644 + col - 2] - pixel[(row - 2) * 644 + col - 2]);
sharp = val < 4
? 0
: val < 8
? 1
: val < 16 ? 2 : val < 32 ? 3 : val < 48 ? 4 : 5;
}
val = ((pixel[(row - 2) * 644 + col] + pixel[row * 644 + col - 2]) >> 1) + rstep[sharp][getbits(2)];
pixel[row * 644 + col] = val = LIM(val, 0, 255);
if (row < 4)
pixel[(row - 2) * 644 + col + 2] = val;
if (col < 4)
pixel[(row + 2) * 644 + col - 2] = val;
}
}
for (row = 2; row < height + 2; row++)
{
checkCancel();
for (col = 3 - (row & 1); col < width + 2; col += 2)
{
val = ((pixel[row * 644 + col - 1] + (pixel[row * 644 + col] << 2) + pixel[row * 644 + col + 1]) >> 1) - 0x100;
pixel[row * 644 + col] = LIM(val, 0, 255);
}
}
for (row = 0; row < height; row++)
{
checkCancel();
for (col = 0; col < width; col++)
RAW(row, col) = t_curve[pixel[(row + 2) * 644 + col + 2]];
}
maximum = 0x3ff;
}
void LibRaw::sony_load_raw()
{
uchar head[40];
ushort *pixel;
unsigned i, key, row, col;
fseek(ifp, 200896, SEEK_SET);
fseek(ifp, (unsigned)fgetc(ifp) * 4 - 1, SEEK_CUR);
order = 0x4d4d;
key = get4();
fseek(ifp, 164600, SEEK_SET);
fread(head, 1, 40, ifp);
sony_decrypt((unsigned *)head, 10, 1, key);
for (i = 26; i-- > 22;)
key = key << 8 | head[i];
fseek(ifp, data_offset, SEEK_SET);
for (row = 0; row < raw_height; row++)
{
checkCancel();
pixel = raw_image + row * raw_width;
if (fread(pixel, 2, raw_width, ifp) < raw_width)
derror();
sony_decrypt((unsigned *)pixel, raw_width / 2, !row, key);
for (col = 0; col < raw_width; col++)
if ((pixel[col] = ntohs(pixel[col])) >> 14)
derror();
}
maximum = 0x3ff0;
}
void LibRaw::sony_arw_load_raw()
{
std::vector<ushort> huff_buffer(32770);
ushort* huff = &huff_buffer[0];
static const ushort tab[18] = {0xf11, 0xf10, 0xe0f, 0xd0e, 0xc0d, 0xb0c,
0xa0b, 0x90a, 0x809, 0x708, 0x607, 0x506,
0x405, 0x304, 0x303, 0x300, 0x202, 0x201};
int i, c, n, col, row, sum = 0;
huff[0] = 15;
for (n = i = 0; i < 18; i++)
FORC(32768 >> (tab[i] >> 8)) huff[++n] = tab[i];
getbits(-1);
for (col = raw_width; col--;)
{
checkCancel();
for (row = 0; row < raw_height + 1; row += 2)
{
if (row == raw_height)
row = 1;
if ((sum += ljpeg_diff(huff)) >> 12)
derror();
if (row < height)
RAW(row, col) = sum;
}
}
}
void LibRaw::sony_arw2_load_raw()
{
uchar *data, *dp;
ushort pix[16];
int row, col, val, max, min, imax, imin, sh, bit, i;
data = (uchar *)malloc(raw_width + 1);
merror(data, "sony_arw2_load_raw()");
try
{
for (row = 0; row < height; row++)
{
checkCancel();
fread(data, 1, raw_width, ifp);
for (dp = data, col = 0; col < raw_width - 30; dp += 16)
{
max = 0x7ff & (val = sget4(dp));
min = 0x7ff & val >> 11;
imax = 0x0f & val >> 22;
imin = 0x0f & val >> 26;
for (sh = 0; sh < 4 && 0x80 << sh <= max - min; sh++)
;
if (!(imgdata.params.raw_processing_options &
LIBRAW_PROCESSING_SONYARW2_ALLFLAGS) || (imgdata.params.raw_processing_options &
LIBRAW_PROCESSING_SONYARW2_DELTATOVALUE))
{
for (bit = 30, i = 0; i < 16; i++)
if (i == imax)
pix[i] = max;
else if (i == imin)
pix[i] = min;
else
{
pix[i] =
((sget2(dp + (bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min;
if (pix[i] > 0x7ff)
pix[i] = 0x7ff;
bit += 7;
}
}
else if (imgdata.params.raw_processing_options &
LIBRAW_PROCESSING_SONYARW2_BASEONLY)
{
for (bit = 30, i = 0; i < 16; i++)
if (i == imax)
pix[i] = max;
else if (i == imin)
pix[i] = min;
else
pix[i] = 0;
}
else if (imgdata.params.raw_processing_options &
LIBRAW_PROCESSING_SONYARW2_DELTAONLY)
{
for (bit = 30, i = 0; i < 16; i++)
if (i == imax)
pix[i] = 0;
else if (i == imin)
pix[i] = 0;
else
{
pix[i] =
((sget2(dp + (bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min;
if (pix[i] > 0x7ff)
pix[i] = 0x7ff;
bit += 7;
}
}
else if (imgdata.params.raw_processing_options &
LIBRAW_PROCESSING_SONYARW2_DELTAZEROBASE)
{
for (bit = 30, i = 0; i < 16; i++)
if (i == imax)
pix[i] = 0;
else if (i == imin)
pix[i] = 0;
else
{
pix[i] = ((sget2(dp + (bit >> 3)) >> (bit & 7) & 0x7f) << sh);
if (pix[i] > 0x7ff)
pix[i] = 0x7ff;
bit += 7;
}
}
if (imgdata.params.raw_processing_options &
LIBRAW_PROCESSING_SONYARW2_DELTATOVALUE)
{
for (i = 0; i < 16; i++, col += 2)
{
unsigned slope =
pix[i] < 1001 ? 2
: curve[pix[i] << 1] - curve[(pix[i] << 1) - 2];
unsigned step = 1 << sh;
RAW(row, col) =
curve[pix[i] << 1] >
black + imgdata.params.sony_arw2_posterization_thr
? LIM(((slope * step * 1000) /
(curve[pix[i] << 1] - black)),
0, 10000)
: 0;
}
}
else
for (i = 0; i < 16; i++, col += 2)
RAW(row, col) = curve[pix[i] << 1];
col -= col & 1 ? 1 : 31;
}
}
}
catch (...)
{
free(data);
throw;
}
if (imgdata.params.raw_processing_options &
LIBRAW_PROCESSING_SONYARW2_DELTATOVALUE)
maximum = 10000;
free(data);
}
void LibRaw::samsung_load_raw()
{
int row, col, c, i, dir, op[4], len[4];
if (raw_width > 32768 ||
raw_height > 32768) throw LIBRAW_EXCEPTION_IO_BADFILE;
unsigned maxpixels = raw_width * (raw_height + 7);
order = 0x4949;
for (row = 0; row < raw_height; row++)
{
checkCancel();
fseek(ifp, strip_offset + row * 4, SEEK_SET);
fseek(ifp, data_offset + get4(), SEEK_SET);
ph1_bits(-1);
FORC4 len[c] = row < 2 ? 7 : 4;
for (col = 0; col < raw_width; col += 16)
{
dir = ph1_bits(1);
FORC4 op[c] = ph1_bits(2);
FORC4 switch (op[c])
{
case 3:
len[c] = ph1_bits(4);
break;
case 2:
len[c]--;
break;
case 1:
len[c]++;
}
for (c = 0; c < 16; c += 2)
{
i = len[((c & 1) << 1) | (c >> 3)];
unsigned idest = RAWINDEX(row, col + c);
unsigned isrc = (dir ? RAWINDEX(row + (~c | -2), col + c)
: col ? RAWINDEX(row, col + (c | -2)) : 0);
if (idest < maxpixels &&
isrc <
maxpixels) RAW(row, col + c) = (i > 0 ? ((signed)ph1_bits(i) << (32 - i) >> (32 - i)) : 0) +
(dir ? RAW(row + (~c | -2), col + c) : col ? RAW(row, col + (c | -2)) : 128);
else
derror();
if (c == 14)
c = -1;
}
}
}
for (row = 0; row < raw_height - 1; row += 2)
for (col = 0; col < raw_width - 1; col += 2)
SWAP(RAW(row, col + 1), RAW(row + 1, col));
}
void LibRaw::samsung2_load_raw()
{
static const ushort tab[14] = {0x304, 0x307, 0x206, 0x205, 0x403,
0x600, 0x709, 0x80a, 0x90b, 0xa0c,
0xa0d, 0x501, 0x408, 0x402};
ushort huff[1026], vpred[2][2] = {{0, 0}, {0, 0}}, hpred[2];
int i, c, n, row, col, diff;
huff[0] = 10;
for (n = i = 0; i < 14; i++)
FORC(1024 >> (tab[i] >> 8)) huff[++n] = tab[i];
getbits(-1);
for (row = 0; row < raw_height; row++)
{
checkCancel();
for (col = 0; col < raw_width; col++)
{
diff = ljpeg_diff(huff);
if (col < 2)
hpred[col] = vpred[row & 1][col] += diff;
else
hpred[col & 1] += diff;
RAW(row, col) = hpred[col & 1];
if (hpred[col & 1] >> tiff_bps)
derror();
}
}
}
void LibRaw::samsung3_load_raw()
{
int opt, init, mag, pmode, row, tab, col, pred, diff, i, c;
ushort lent[3][2], len[4], *prow[2];
order = 0x4949;
fseek(ifp, 9, SEEK_CUR);
opt = fgetc(ifp);
init = (get2(), get2());
for (row = 0; row < raw_height; row++)
{
checkCancel();
fseek(ifp, (data_offset - ftell(ifp)) & 15, SEEK_CUR);
ph1_bits(-1);
mag = 0;
pmode = 7;
FORC(6)((ushort *)lent)[c] = row < 2 ? 7 : 4;
prow[row & 1] = &RAW(row - 1, 1 - ((row & 1) << 1)); prow[~row & 1] = &RAW(row - 2, 0); for (tab = 0; tab + 15 < raw_width; tab += 16)
{
if (~opt & 4 && !(tab & 63))
{
i = ph1_bits(2);
mag = i < 3 ? mag - '2' + "204"[i] : ph1_bits(12);
}
if (opt & 2)
pmode = 7 - 4 * ph1_bits(1);
else if (!ph1_bits(1))
pmode = ph1_bits(3);
if (opt & 1 || !ph1_bits(1))
{
FORC4 len[c] = ph1_bits(2);
FORC4
{
i = ((row & 1) << 1 | (c & 1)) % 3;
if (i < 0)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
len[c] = len[c] < 3 ? lent[i][0] - '1' + "120"[len[c]] : ph1_bits(4);
lent[i][0] = lent[i][1];
lent[i][1] = len[c];
}
}
FORC(16)
{
col = tab + (((c & 7) << 1) ^ (c >> 3) ^ (row & 1));
if (col < 0)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
if (pmode < 0)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
if (pmode != 7 && row >= 2 && (col - '4' + "0224468"[pmode]) < 0)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
pred = (pmode == 7 || row < 2)
? (tab ? RAW(row, tab - 2 + (col & 1)) : init)
: (prow[col & 1][col - '4' + "0224468"[pmode]] +
prow[col & 1][col - '4' + "0244668"[pmode]] + 1) >>
1;
diff = ph1_bits(i = len[c >> 2]);
if (i > 0 && diff >> (i - 1))
diff -= 1 << i;
diff = diff * (mag * 2 + 1) + mag;
RAW(row, col) = pred + diff;
}
}
}
}
void LibRaw::redcine_load_raw()
{
#ifndef NO_JASPER
int c, row, col;
jas_stream_t *in;
jas_image_t *jimg;
jas_matrix_t *jmat;
jas_seqent_t *data;
ushort *img, *pix;
jas_init();
in = (jas_stream_t *)ifp->make_jas_stream();
if (!in)
throw LIBRAW_EXCEPTION_DECODE_JPEG2000;
jas_stream_seek(in, data_offset + 20, SEEK_SET);
jimg = jas_image_decode(in, -1, 0);
if (!jimg)
{
jas_stream_close(in);
throw LIBRAW_EXCEPTION_DECODE_JPEG2000;
}
jmat = jas_matrix_create(height / 2, width / 2);
merror(jmat, "redcine_load_raw()");
img = (ushort *)calloc((height + 2), (width + 2) * 2);
merror(img, "redcine_load_raw()");
bool fastexitflag = false;
try
{
FORC4
{
checkCancel();
jas_image_readcmpt(jimg, c, 0, 0, width / 2, height / 2, jmat);
data = jas_matrix_getref(jmat, 0, 0);
for (row = c >> 1; row < height; row += 2)
for (col = c & 1; col < width; col += 2)
img[(row + 1) * (width + 2) + col + 1] =
data[(row / 2) * (width / 2) + col / 2];
}
for (col = 1; col <= width; col++)
{
img[col] = img[2 * (width + 2) + col];
img[(height + 1) * (width + 2) + col] =
img[(height - 1) * (width + 2) + col];
}
for (row = 0; row < height + 2; row++)
{
img[row * (width + 2)] = img[row * (width + 2) + 2];
img[(row + 1) * (width + 2) - 1] = img[(row + 1) * (width + 2) - 3];
}
for (row = 1; row <= height; row++)
{
checkCancel();
pix = img + row * (width + 2) + (col = 1 + (FC(row, 1) & 1));
for (; col <= width; col += 2, pix += 2)
{
c = (((pix[0] - 0x800) << 3) + pix[-(width + 2)] + pix[width + 2] +
pix[-1] + pix[1]) >>
2;
pix[0] = LIM(c, 0, 4095);
}
}
for (row = 0; row < height; row++)
{
checkCancel();
for (col = 0; col < width; col++)
RAW(row, col) = curve[img[(row + 1) * (width + 2) + col + 1]];
}
}
catch (...)
{
fastexitflag = true;
}
free(img);
jas_matrix_destroy(jmat);
jas_image_destroy(jimg);
jas_stream_close(in);
if (fastexitflag)
throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK;
#endif
}