Panasonic DC-GH5S raw support. Thanks to @agriggio for the patch, fixes #4675

This commit is contained in:
heckflosse
2019-02-14 15:46:19 +01:00
parent 9e1fcb31ef
commit 6292b4e994
2 changed files with 94 additions and 23 deletions

View File

@@ -2672,43 +2672,92 @@ void CLASS canon_rmf_load_raw()
maximum = curve[0x3ff];
}
unsigned CLASS pana_bits_t::operator() (int nbits)
unsigned CLASS pana_bits_t::operator() (int nbits, unsigned *bytes)
{
/*RT static uchar buf[0x4000]; */
/*RT static int vbits;*/
int byte;
if (!nbits) return vbits=0;
if (!nbits && !bytes) return vbits=0;
if (!vbits) {
fread (buf+load_flags, 1, 0x4000-load_flags, ifp);
fread (buf, 1, load_flags, ifp);
}
vbits = (vbits - nbits) & 0x1ffff;
byte = vbits >> 3 ^ 0x3ff0;
return (buf[byte] | buf[byte+1] << 8) >> (vbits & 7) & ~(-1 << nbits);
if (encoding == 5) {
for (byte = 0; byte < 16; byte++)
{
bytes[byte] = buf[vbits++];
vbits &= 0x3FFF;
}
return 0;
} else {
vbits = (vbits - nbits) & 0x1ffff;
byte = vbits >> 3 ^ 0x3ff0;
return (buf[byte] | buf[byte+1] << 8) >> (vbits & 7) & ~(-1 << nbits);
}
}
void CLASS panasonic_load_raw()
{
pana_bits_t pana_bits(ifp,load_flags);
pana_bits_t pana_bits(ifp,load_flags, RT_pana_info.encoding);
int row, col, i, j, sh=0, pred[2], nonz[2];
unsigned bytes[16] = {};
ushort *raw_block_data;
pana_bits(0);
for (row=0; row < height; row++)
for (col=0; col < raw_width; col++) {
if ((i = col % 14) == 0)
pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2));
if (nonz[i & 1]) {
if ((j = pana_bits(8))) {
if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4)
pred[i & 1] &= ~(-1 << sh);
pred[i & 1] += j << sh;
}
} else if ((nonz[i & 1] = pana_bits(8)) || i > 11)
pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4);
if ((RAW(row,col) = pred[col & 1]) > 4098 && col < width) derror();
pana_bits(0, 0);
int enc_blck_size = RT_pana_info.bpp == 12 ? 10 : 9;
if (RT_pana_info.encoding == 5) {
for (row = 0; row < raw_height; row++)
{
raw_block_data = raw_image + row * raw_width;
for (col = 0; col < raw_width; col += enc_blck_size) {
pana_bits(0, bytes);
if (RT_pana_info.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 (RT_pana_info.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 < height; row++)
for (col=0; col < raw_width; col++) {
if ((i = col % 14) == 0)
pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2));
if (nonz[i & 1]) {
if ((j = pana_bits(8))) {
if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4)
pred[i & 1] &= ~(-1 << sh);
pred[i & 1] += j << sh;
}
} else if ((nonz[i & 1] = pana_bits(8)) || i > 11)
pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4);
if ((RAW(row,col) = pred[col & 1]) > 4098 && col < width) derror();
}
}
}
void CLASS olympus_load_raw()
@@ -6081,6 +6130,7 @@ int CLASS parse_tiff_ifd (int base)
unsigned *buf, sony_offset=0, sony_length=0, sony_key=0;
struct jhead jh;
/*RT*/ IMFILE *sfp;
/*RT*/ int pana_raw = 0;
if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0])
return 1;
@@ -6096,10 +6146,16 @@ int CLASS parse_tiff_ifd (int base)
while (entries--) {
tiff_get (base, &tag, &type, &len, &save);
switch (tag) {
case 1: if (len == 4) pana_raw = get4(); break;
case 5: width = get2(); break;
case 6: height = get2(); break;
case 7: width += get2(); break;
case 9: if ((i = get2())) filters = i; break;
case 10:
if (pana_raw && len == 1 && type == 3) {
RT_pana_info.bpp = get2();
}
break;
case 17: case 18:
if (type == 3 && len == 1)
cam_mul[(tag-17)*2] = get2() / 256.0;
@@ -6119,6 +6175,12 @@ int CLASS parse_tiff_ifd (int base)
fseek (ifp, 12, SEEK_CUR);
FORC3 cam_mul[c] = get2();
break;
case 45:
if (pana_raw && len == 1 && type == 3)
{
RT_pana_info.encoding = get2();
}
break;
case 46:
if (type != 7 || fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) break;
thumb_offset = ftell(ifp) - 2;

View File

@@ -159,6 +159,13 @@ protected:
std::string RT_software;
double RT_baseline_exposure;
struct PanasonicRW2Info {
ushort bpp;
ushort encoding;
PanasonicRW2Info(): bpp(0), encoding(0) {}
};
PanasonicRW2Info RT_pana_info;
float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4];
int histogram[4][0x2000];
@@ -395,13 +402,15 @@ void nokia_load_raw();
class pana_bits_t{
public:
pana_bits_t(IMFILE *i, unsigned &u): ifp(i), load_flags(u), vbits(0) {}
unsigned operator()(int nbits);
pana_bits_t(IMFILE *i, unsigned &u, unsigned enc):
ifp(i), load_flags(u), vbits(0), encoding(enc) {}
unsigned operator()(int nbits, unsigned *bytes=nullptr);
private:
IMFILE *ifp;
unsigned &load_flags;
uchar buf[0x4000];
int vbits;
unsigned encoding;
};
void canon_rmf_load_raw();