diff --git a/rtengine/panasonic_decoders.cc b/rtengine/panasonic_decoders.cc index 5630ae3f2..37f586a6b 100644 --- a/rtengine/panasonic_decoders.cc +++ b/rtengine/panasonic_decoders.cc @@ -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 . +*/ -#include "StopWatch.h" #include #include "dcraw.h" + // Code adapted from libraw /* -*- C++ -*- * Copyright 2019 LibRaw LLC (info@libraw.org) @@ -17,7 +33,6 @@ */ - unsigned DCraw::pana_bits_t::operator() (int nbits, unsigned *bytes) { int byte; @@ -45,15 +60,18 @@ unsigned DCraw::pana_bits_t::operator() (int nbits, unsigned *bytes) 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) + 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 read_page(); // will throw IO error if not enough space in buffer + unsigned int nextpixel() + { + return current < 14 ? pixelbuffer[current++] : 0; + } }; #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() { -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; 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; - 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); 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); + 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); + 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); } } } @@ -129,92 +142,95 @@ StopWatch Stop1("panasonic_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++) { - 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_image[(row)*raw_width+(col)] = pred[col & 1]) > 4098 && col < width) derror(); - } + pana_bits_t pana_bits(ifp, load_flags, RT_pana_info.encoding); + pana_bits(0, 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; + } + if (i % 3 == 2) { + sh = 4 >> (3 - pana_bits(2)); + } + if (nonz[i & 1]) { + 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() { - 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()"); + constexpr 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; - } + for (int row = 0; row < raw_height - rowstep + 1; row += rowstep) { + const int rowstoread = MIN(rowstep, raw_height - row); + fread(iobuf, rowbytes, rowstoread, ifp); + 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) { + derror(); + } + 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]; + } + } + const 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; + free(iobuf); + tiff_bps = RT_pana_info.bpp; } void DCraw::panasonicC7_load_raw()