panasonic decoders: cleanup

This commit is contained in:
Ingo Weyrich
2019-11-07 19:35:02 +01:00
parent ffa461d3de
commit 9ac34eb33c

View File

@@ -1,7 +1,23 @@
/*
* This file is part of RawTherapee.
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RawTherapee is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
*/
#include "StopWatch.h"
#include <iostream> #include <iostream>
#include "dcraw.h" #include "dcraw.h"
// Code adapted from libraw // Code adapted from libraw
/* -*- C++ -*- /* -*- C++ -*-
* Copyright 2019 LibRaw LLC (info@libraw.org) * Copyright 2019 LibRaw LLC (info@libraw.org)
@@ -17,7 +33,6 @@
*/ */
unsigned DCraw::pana_bits_t::operator() (int nbits, unsigned *bytes) unsigned DCraw::pana_bits_t::operator() (int nbits, unsigned *bytes)
{ {
int byte; int byte;
@@ -45,15 +60,18 @@ unsigned DCraw::pana_bits_t::operator() (int nbits, unsigned *bytes)
class pana_cs6_page_decoder class pana_cs6_page_decoder
{ {
unsigned int pixelbuffer[14], lastoffset, maxoffset; unsigned int pixelbuffer[14], lastoffset, maxoffset;
unsigned char current, *buffer; unsigned char current, *buffer;
public: public:
pana_cs6_page_decoder(unsigned char *_buffer, unsigned int bsize) pana_cs6_page_decoder(unsigned char *_buffer, unsigned int bsize)
: lastoffset(0), maxoffset(bsize), current(0), buffer(_buffer) : lastoffset(0), maxoffset(bsize), current(0), buffer(_buffer)
{ {
} }
void read_page(); // will throw IO error if not enough space in buffer void read_page(); // will throw IO error if not enough space in buffer
unsigned int nextpixel() { return current < 14 ? pixelbuffer[current++] : 0; } unsigned int nextpixel()
{
return current < 14 ? pixelbuffer[current++] : 0;
}
}; };
#define wbuffer(i) ((unsigned short)buffer[lastoffset + 15 - i]) #define wbuffer(i) ((unsigned short)buffer[lastoffset + 15 - i])
@@ -83,44 +101,39 @@ void pana_cs6_page_decoder::read_page()
void DCraw::panasonic_load_raw() void DCraw::panasonic_load_raw()
{ {
StopWatch Stop1("panasonic_load_raw");
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] = {};
pana_bits(0, 0);
int enc_blck_size = RT_pana_info.bpp == 12 ? 10 : 9; int enc_blck_size = RT_pana_info.bpp == 12 ? 10 : 9;
if (RT_pana_info.encoding == 5) { if (RT_pana_info.encoding == 5) {
for (row = 0; row < raw_height; row++) { pana_bits_t pana_bits(ifp, load_flags, RT_pana_info.encoding);
pana_bits(0, 0);
unsigned bytes[16] = {};
for (int row = 0; row < raw_height; ++row) {
ushort* raw_block_data = raw_image + row * raw_width; ushort* raw_block_data = raw_image + row * raw_width;
for (col = 0; col < raw_width; col += enc_blck_size) { for (int col = 0; col < raw_width; col += enc_blck_size) {
pana_bits(0, bytes); pana_bits(0, bytes);
if (RT_pana_info.bpp == 12) { if (RT_pana_info.bpp == 12) {
raw_block_data[col] = ((bytes[1] & 0xF) << 8) + bytes[0]; 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 + 1] = 16 * bytes[2] + (bytes[1] >> 4);
raw_block_data[col + 2] = ((bytes[4] & 0xF) << 8) + bytes[3]; 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 + 3] = 16 * bytes[5] + (bytes[4] >> 4);
raw_block_data[col + 4] = ((bytes[7] & 0xF) << 8) + bytes[6]; 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 + 5] = 16 * bytes[8] + (bytes[7] >> 4);
raw_block_data[col + 6] = ((bytes[10] & 0xF) << 8) + bytes[9]; 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 + 7] = 16 * bytes[11] + (bytes[10] >> 4);
raw_block_data[col + 8] = ((bytes[13] & 0xF) << 8) + bytes[12]; raw_block_data[col + 8] = ((bytes[13] & 0xF) << 8) + bytes[12];
raw_block_data[col + 9] = 16 * bytes[14] + (bytes[13] >> 4); raw_block_data[col + 9] = 16 * bytes[14] + (bytes[13] >> 4);
} }
else if (RT_pana_info.bpp == 14) { else if (RT_pana_info.bpp == 14) {
raw_block_data[col] = bytes[0] + ((bytes[1] & 0x3F) << 8); raw_block_data[col] = bytes[0] + ((bytes[1] & 0x3F) << 8);
raw_block_data[col + 1] = (bytes[1] >> 6) + 4 * (bytes[2]) + raw_block_data[col + 1] = (bytes[1] >> 6) + 4 * (bytes[2]) + ((bytes[3] & 0xF) << 10);
((bytes[3] & 0xF) << 10); raw_block_data[col + 2] = (bytes[3] >> 4) + 16 * (bytes[4]) + ((bytes[5] & 3) << 12);
raw_block_data[col + 2] = (bytes[3] >> 4) + 16 * (bytes[4]) + raw_block_data[col + 3] = ((bytes[5] & 0xFC) >> 2) + (bytes[6] << 6);
((bytes[5] & 3) << 12); raw_block_data[col + 4] = bytes[7] + ((bytes[8] & 0x3F) << 8);
raw_block_data[col + 3] = ((bytes[5] & 0xFC) >> 2) + (bytes[6] << 6); raw_block_data[col + 5] = (bytes[8] >> 6) + 4 * bytes[9] + ((bytes[10] & 0xF) << 10);
raw_block_data[col + 4] = bytes[7] + ((bytes[8] & 0x3F) << 8); raw_block_data[col + 6] = (bytes[10] >> 4) + 16 * bytes[11] + ((bytes[12] & 3) << 12);
raw_block_data[col + 5] = (bytes[8] >> 6) + 4 * bytes[9] + ((bytes[10] & 0xF) << 10); raw_block_data[col + 7] = ((bytes[12] & 0xFC) >> 2) + (bytes[13] << 6);
raw_block_data[col + 6] = (bytes[10] >> 4) + 16 * bytes[11] + ((bytes[12] & 3) << 12); raw_block_data[col + 8] = bytes[14] + ((bytes[15] & 0x3F) << 8);
raw_block_data[col + 7] = ((bytes[12] & 0xFC) >> 2) + (bytes[13] << 6);
raw_block_data[col + 8] = bytes[14] + ((bytes[15] & 0x3F) << 8);
} }
} }
} }
@@ -129,92 +142,95 @@ StopWatch Stop1("panasonic_load_raw");
} else if (RT_pana_info.encoding == 7) { } else if (RT_pana_info.encoding == 7) {
panasonicC7_load_raw(); panasonicC7_load_raw();
} else { } else {
for (row=0; row < height; row++) pana_bits_t pana_bits(ifp, load_flags, RT_pana_info.encoding);
for (col=0; col < raw_width; col++) { pana_bits(0, 0);
if ((i = col % 14) == 0) int sh = 0, pred[2], nonz[2];
pred[0] = pred[1] = nonz[0] = nonz[1] = 0; for (int row = 0; row < height; ++row) {
if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2)); for (int col = 0; col < raw_width; ++col) {
if (nonz[i & 1]) { int i;
if ((j = pana_bits(8))) { if ((i = col % 14) == 0) {
if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4) pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
pred[i & 1] &= ~(-1 << sh); }
pred[i & 1] += j << sh; if (i % 3 == 2) {
} sh = 4 >> (3 - pana_bits(2));
} else if ((nonz[i & 1] = pana_bits(8)) || i > 11) }
pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4); if (nonz[i & 1]) {
if ((raw_image[(row)*raw_width+(col)] = pred[col & 1]) > 4098 && col < width) derror(); int j;
} 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_image[(row)*raw_width+(col)] = pred[col & 1]) > 4098 && col < width) {
derror();
}
}
}
} }
} }
void DCraw::panasonicC6_load_raw() void DCraw::panasonicC6_load_raw()
{ {
const int rowstep = 16; constexpr int rowstep = 16;
const int blocksperrow = raw_width / 11; const int blocksperrow = raw_width / 11;
const int rowbytes = blocksperrow * 16; const int rowbytes = blocksperrow * 16;
unsigned char *iobuf = (unsigned char *)malloc(rowbytes * rowstep); unsigned char *iobuf = (unsigned char *)malloc(rowbytes * rowstep);
merror(iobuf, "panasonicC6_load_raw()"); merror(iobuf, "panasonicC6_load_raw()");
for (int row = 0; row < raw_height - rowstep + 1; for (int row = 0; row < raw_height - rowstep + 1; row += rowstep) {
row += rowstep) const int rowstoread = MIN(rowstep, raw_height - row);
{ fread(iobuf, rowbytes, rowstoread, ifp);
int rowstoread = MIN(rowstep, raw_height - row); pana_cs6_page_decoder page(iobuf, rowbytes * rowstoread);
fread (iobuf, rowbytes, rowstoread, ifp); for (int crow = 0, col = 0; crow < rowstoread; ++crow, col = 0) {
// if (libraw_internal_data.internal_data.input->read( unsigned short *rowptr = &raw_image[(row + crow) * raw_width];
// iobuf, rowbytes, rowstoread) != rowstoread) for (int rblock = 0; rblock < blocksperrow; rblock++) {
// throw LIBRAW_EXCEPTION_IO_EOF; page.read_page();
pana_cs6_page_decoder page(iobuf, rowbytes * rowstoread); unsigned oddeven[2] = {0, 0}, nonzero[2] = {0, 0};
for (int crow = 0, col = 0; crow < rowstoread; crow++, col = 0) unsigned pmul = 0, pixel_base = 0;
{ for (int pix = 0; pix < 11; ++pix) {
unsigned short *rowptr = &raw_image[(row + crow) * raw_width]; if (pix % 3 == 2) {
for (int rblock = 0; rblock < blocksperrow; rblock++) unsigned base = page.nextpixel();
{ if (base > 3) {
page.read_page(); derror();
unsigned oddeven[2] = {0, 0}, nonzero[2] = {0, 0}; }
unsigned pmul = 0, pixel_base = 0; if (base == 3) {
for (int pix = 0; pix < 11; pix++) base = 4;
{ }
if (pix % 3 == 2) pixel_base = 0x200 << base;
{ pmul = 1 << base;
unsigned base = page.nextpixel(); }
if (base > 3); unsigned epixel = page.nextpixel();
// throw LIBRAW_EXCEPTION_IO_CORRUPT; // not possible b/c of 2-bit if (oddeven[pix % 2]) {
// field, but.... epixel *= pmul;
if (base == 3) if (pixel_base < 0x2000 && nonzero[pix % 2] > pixel_base) {
base = 4; epixel += nonzero[pix % 2] - pixel_base;
pixel_base = 0x200 << base; }
pmul = 1 << base; nonzero[pix % 2] = epixel;
} } else {
unsigned epixel = page.nextpixel(); oddeven[pix % 2] = epixel;
if (oddeven[pix % 2]) if (epixel) {
{ nonzero[pix % 2] = epixel;
epixel *= pmul; } else {
if (pixel_base < 0x2000 && nonzero[pix % 2] > pixel_base) epixel = nonzero[pix % 2];
epixel += nonzero[pix % 2] - pixel_base; }
nonzero[pix % 2] = epixel; }
} const unsigned spix = epixel - 0xf;
else if (spix <= 0xffff) {
{ rowptr[col++] = spix & 0xffff;
oddeven[pix % 2] = epixel; } else {
if (epixel) epixel = (((signed int)(epixel + 0x7ffffff1)) >> 0x1f);
nonzero[pix % 2] = epixel; rowptr[col++] = epixel & 0x3fff;
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);
free(iobuf); tiff_bps = RT_pana_info.bpp;
tiff_bps = RT_pana_info.bpp;
} }
void DCraw::panasonicC7_load_raw() void DCraw::panasonicC7_load_raw()