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;
@@ -53,7 +68,10 @@ class pana_cs6_page_decoder
{ {
} }
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,18 +101,15 @@ 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) {
@@ -111,10 +126,8 @@ StopWatch Stop1("panasonic_load_raw");
} }
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]) +
((bytes[5] & 3) << 12);
raw_block_data[col + 3] = ((bytes[5] & 0xFC) >> 2) + (bytes[6] << 6); 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 + 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 + 5] = (bytes[8] >> 6) + 4 * bytes[9] + ((bytes[10] & 0xF) << 10);
@@ -129,83 +142,86 @@ 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];
for (int row = 0; row < height; ++row) {
for (int col = 0; col < raw_width; ++col) {
int i;
if ((i = col % 14) == 0) {
pred[0] = pred[1] = nonz[0] = nonz[1] = 0; pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2)); }
if (i % 3 == 2) {
sh = 4 >> (3 - pana_bits(2));
}
if (nonz[i & 1]) { if (nonz[i & 1]) {
int j;
if ((j = pana_bits(8))) { if ((j = pana_bits(8))) {
if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4) if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4) {
pred[i & 1] &= ~(-1 << sh); pred[i & 1] &= ~(-1 << sh);
}
pred[i & 1] += j << sh; pred[i & 1] += j << sh;
} }
} else if ((nonz[i & 1] = pana_bits(8)) || i > 11) } else if ((nonz[i & 1] = pana_bits(8)) || i > 11) {
pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4); pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4);
if ((raw_image[(row)*raw_width+(col)] = pred[col & 1]) > 4098 && col < width) derror(); }
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);
{
int rowstoread = MIN(rowstep, raw_height - row);
fread(iobuf, rowbytes, rowstoread, ifp); 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); pana_cs6_page_decoder page(iobuf, rowbytes * rowstoread);
for (int crow = 0, col = 0; crow < rowstoread; crow++, col = 0) for (int crow = 0, col = 0; crow < rowstoread; ++crow, col = 0) {
{
unsigned short *rowptr = &raw_image[(row + crow) * raw_width]; unsigned short *rowptr = &raw_image[(row + crow) * raw_width];
for (int rblock = 0; rblock < blocksperrow; rblock++) for (int rblock = 0; rblock < blocksperrow; rblock++) {
{
page.read_page(); page.read_page();
unsigned oddeven[2] = {0, 0}, nonzero[2] = {0, 0}; unsigned oddeven[2] = {0, 0}, nonzero[2] = {0, 0};
unsigned pmul = 0, pixel_base = 0; unsigned pmul = 0, pixel_base = 0;
for (int pix = 0; pix < 11; pix++) for (int pix = 0; pix < 11; ++pix) {
{ if (pix % 3 == 2) {
if (pix % 3 == 2)
{
unsigned base = page.nextpixel(); unsigned base = page.nextpixel();
if (base > 3); if (base > 3) {
// throw LIBRAW_EXCEPTION_IO_CORRUPT; // not possible b/c of 2-bit derror();
// field, but.... }
if (base == 3) if (base == 3) {
base = 4; base = 4;
}
pixel_base = 0x200 << base; pixel_base = 0x200 << base;
pmul = 1 << base; pmul = 1 << base;
} }
unsigned epixel = page.nextpixel(); unsigned epixel = page.nextpixel();
if (oddeven[pix % 2]) if (oddeven[pix % 2]) {
{
epixel *= pmul; epixel *= pmul;
if (pixel_base < 0x2000 && nonzero[pix % 2] > pixel_base) if (pixel_base < 0x2000 && nonzero[pix % 2] > pixel_base) {
epixel += 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; nonzero[pix % 2] = epixel;
else } else {
oddeven[pix % 2] = epixel;
if (epixel) {
nonzero[pix % 2] = epixel;
} else {
epixel = nonzero[pix % 2]; epixel = nonzero[pix % 2];
} }
unsigned spix = epixel - 0xf; }
if (spix <= 0xffff) const unsigned spix = epixel - 0xf;
if (spix <= 0xffff) {
rowptr[col++] = spix & 0xffff; rowptr[col++] = spix & 0xffff;
else } else {
{
epixel = (((signed int)(epixel + 0x7ffffff1)) >> 0x1f); epixel = (((signed int)(epixel + 0x7ffffff1)) >> 0x1f);
rowptr[col++] = epixel & 0x3fff; rowptr[col++] = epixel & 0x3fff;
} }