Decode standard Panasonic DC-S1 and DC-S1R files (pixelshift files are not supported yet), #5204

This commit is contained in:
Ingo Weyrich 2019-11-06 14:40:05 +01:00
parent a2d5ef356c
commit e12b58cfcf
3 changed files with 191 additions and 0 deletions

View File

@ -2142,6 +2142,11 @@ Camera constants:
}
},
{ // Quality B, per ISO info missing
"make_model": [ "Panasonic DC-S1", "Panasonic DC-S1R" ],
"ranges": { "white": 16383 }
},
{ // Quality B, per ISO info missing
"make_model": "PENTAX K-x",
"dcraw_matrix": [ 8843,-2837,-625,-5025,12644,2668,-411,1234,7410 ], // adobe dcp d65

View File

@ -2757,6 +2757,10 @@ void CLASS panasonic_load_raw()
}
}
}
} else if (RT_pana_info.encoding == 6) {
panasonicC6_load_raw();
} else if (RT_pana_info.encoding == 7) {
panasonicC7_load_raw();
} else {
for (row=0; row < height; row++)
for (col=0; col < raw_width; col++) {
@ -10759,6 +10763,173 @@ void CLASS nikon_14bit_load_raw()
free(buf);
}
// Code adapted from libraw
/* -*- C++ -*-
* Copyright 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).
*/
void CLASS pana_cs6_page_decoder::read_page()
{
if (!buffer || (maxoffset - lastoffset < 16))
;
#define wbuffer(i) ((unsigned short)buffer[lastoffset + 15 - i])
pixelbuffer[0] = (wbuffer(0) << 6) | (wbuffer(1) >> 2); // 14 bit
pixelbuffer[1] =
(((wbuffer(1) & 0x3) << 12) | (wbuffer(2) << 4) | (wbuffer(3) >> 4)) &
0x3fff;
pixelbuffer[2] = (wbuffer(3) >> 2) & 0x3;
pixelbuffer[3] = ((wbuffer(3) & 0x3) << 8) | wbuffer(4);
pixelbuffer[4] = (wbuffer(5) << 2) | (wbuffer(6) >> 6);
pixelbuffer[5] = ((wbuffer(6) & 0x3f) << 4) | (wbuffer(7) >> 4);
pixelbuffer[6] = (wbuffer(7) >> 2) & 0x3;
pixelbuffer[7] = ((wbuffer(7) & 0x3) << 8) | wbuffer(8);
pixelbuffer[8] = ((wbuffer(9) << 2) & 0x3fc) | (wbuffer(10) >> 6);
pixelbuffer[9] = ((wbuffer(10) << 4) | (wbuffer(11) >> 4)) & 0x3ff;
pixelbuffer[10] = (wbuffer(11) >> 2) & 0x3;
pixelbuffer[11] = ((wbuffer(11) & 0x3) << 8) | wbuffer(12);
pixelbuffer[12] = (((wbuffer(13) << 2) & 0x3fc) | wbuffer(14) >> 6) & 0x3ff;
pixelbuffer[13] = ((wbuffer(14) << 4) | (wbuffer(15) >> 4)) & 0x3ff;
#undef wbuffer
current = 0;
lastoffset += 16;
}
void CLASS panasonicC6_load_raw()
{
const int rowstep = 16;
const int blocksperrow = raw_width / 11;
const int rowbytes = blocksperrow * 16;
unsigned char *iobuf = (unsigned char *)malloc(rowbytes * rowstep);
merror(iobuf, "panasonicC6_load_raw()");
for (int row = 0; row < raw_height - rowstep + 1;
row += rowstep)
{
int rowstoread = MIN(rowstep, raw_height - row);
fread (iobuf, rowbytes, rowstoread, ifp);
// if (libraw_internal_data.internal_data.input->read(
// iobuf, rowbytes, rowstoread) != rowstoread)
// throw LIBRAW_EXCEPTION_IO_EOF;
pana_cs6_page_decoder page(iobuf, rowbytes * rowstoread);
for (int crow = 0, col = 0; crow < rowstoread; crow++, col = 0)
{
unsigned short *rowptr = &raw_image[(row + crow) * raw_width];
for (int rblock = 0; rblock < blocksperrow; rblock++)
{
page.read_page();
unsigned oddeven[2] = {0, 0}, nonzero[2] = {0, 0};
unsigned pmul = 0, pixel_base = 0;
for (int pix = 0; pix < 11; pix++)
{
if (pix % 3 == 2)
{
unsigned base = page.nextpixel();
if (base > 3);
// throw LIBRAW_EXCEPTION_IO_CORRUPT; // not possible b/c of 2-bit
// field, but....
if (base == 3)
base = 4;
pixel_base = 0x200 << base;
pmul = 1 << base;
}
unsigned epixel = page.nextpixel();
if (oddeven[pix % 2])
{
epixel *= pmul;
if (pixel_base < 0x2000 && nonzero[pix % 2] > pixel_base)
epixel += nonzero[pix % 2] - pixel_base;
nonzero[pix % 2] = epixel;
}
else
{
oddeven[pix % 2] = epixel;
if (epixel)
nonzero[pix % 2] = epixel;
else
epixel = nonzero[pix % 2];
}
unsigned spix = epixel - 0xf;
if (spix <= 0xffff)
rowptr[col++] = spix & 0xffff;
else
{
epixel = (((signed int)(epixel + 0x7ffffff1)) >> 0x1f);
rowptr[col++] = epixel & 0x3fff;
}
}
}
}
}
free(iobuf);
tiff_bps = RT_pana_info.bpp;
}
void CLASS panasonicC7_load_raw()
{
const int rowstep = 16;
int pixperblock = RT_pana_info.bpp == 14 ? 9 : 10;
int rowbytes = raw_width / pixperblock * 16;
unsigned char *iobuf = (unsigned char *)malloc(rowbytes * rowstep);
merror(iobuf, "panasonicC7_load_raw()");
for (int row = 0; row < raw_height - rowstep + 1;
row += rowstep)
{
int rowstoread = MIN(rowstep, raw_height - row);
fread (iobuf, rowbytes, rowstoread, ifp);
unsigned char *bytes = iobuf;
for (int crow = 0; crow < rowstoread; crow++)
{
unsigned short *rowptr = &raw_image[(row + crow)];
for (int col = 0; col < raw_width - pixperblock + 1;
col += pixperblock, bytes += 16)
{
if (RT_pana_info.bpp == 14)
{
rowptr[col] = bytes[0] + ((bytes[1] & 0x3F) << 8);
rowptr[col + 1] =
(bytes[1] >> 6) + 4 * (bytes[2]) + ((bytes[3] & 0xF) << 10);
rowptr[col + 2] =
(bytes[3] >> 4) + 16 * (bytes[4]) + ((bytes[5] & 3) << 12);
rowptr[col + 3] = ((bytes[5] & 0xFC) >> 2) + (bytes[6] << 6);
rowptr[col + 4] = bytes[7] + ((bytes[8] & 0x3F) << 8);
rowptr[col + 5] =
(bytes[8] >> 6) + 4 * bytes[9] + ((bytes[10] & 0xF) << 10);
rowptr[col + 6] =
(bytes[10] >> 4) + 16 * bytes[11] + ((bytes[12] & 3) << 12);
rowptr[col + 7] = ((bytes[12] & 0xFC) >> 2) + (bytes[13] << 6);
rowptr[col + 8] = bytes[14] + ((bytes[15] & 0x3F) << 8);
}
else if (RT_pana_info.bpp ==
12) // have not seen in the wild yet
{
rowptr[col] = ((bytes[1] & 0xF) << 8) + bytes[0];
rowptr[col + 1] = 16 * bytes[2] + (bytes[1] >> 4);
rowptr[col + 2] = ((bytes[4] & 0xF) << 8) + bytes[3];
rowptr[col + 3] = 16 * bytes[5] + (bytes[4] >> 4);
rowptr[col + 4] = ((bytes[7] & 0xF) << 8) + bytes[6];
rowptr[col + 5] = 16 * bytes[8] + (bytes[7] >> 4);
rowptr[col + 6] = ((bytes[10] & 0xF) << 8) + bytes[9];
rowptr[col + 7] = 16 * bytes[11] + (bytes[10] >> 4);
rowptr[col + 8] = ((bytes[13] & 0xF) << 8) + bytes[12];
rowptr[col + 9] = 16 * bytes[14] + (bytes[13] >> 4);
}
}
}
}
free(iobuf);
tiff_bps = RT_pana_info.bpp;
}
//-----------------------------------------------------------------------------
/* RT: Delete from here */

View File

@ -411,6 +411,21 @@ private:
unsigned encoding;
};
class pana_cs6_page_decoder
{
unsigned int pixelbuffer[14], lastoffset, maxoffset;
unsigned char current, *buffer;
public:
pana_cs6_page_decoder(unsigned char *_buffer, unsigned int bsize)
: lastoffset(0), maxoffset(bsize), current(0), buffer(_buffer)
{
}
void read_page(); // will throw IO error if not enough space in buffer
unsigned int nextpixel() { return current < 14 ? pixelbuffer[current++] : 0; }
};
void panasonicC6_load_raw();
void panasonicC7_load_raw();
void canon_rmf_load_raw();
void panasonic_load_raw();
void olympus_load_raw();