24#include "rawspeedconfig.h"
128 :
h(h_),
n(block),
input(input_) {
136 [[nodiscard]]
int RAWSPEED_READONLY
height()
const {
return h.total_lines; }
139 [[nodiscard]]
int RAWSPEED_READONLY
width()
const {
141 if ((
n + 1) !=
h.blocks_in_row)
146 invariant(
h.block_size *
h.blocks_in_row >=
h.raw_width);
158 [[nodiscard]]
int offsetY(
int line = 0)
const {
165 [[nodiscard]]
int offsetX()
const {
return h.block_size *
n; }
169 cur_val -= p.q_point[4];
171 int abs_cur_val = std::abs(cur_val);
176 if (abs_cur_val >= p.q_point[1])
178 if (abs_cur_val >= p.q_point[2])
180 if (abs_cur_val >= p.q_point[3])
210 const int NumGradientTableEntries = 2 * (1 << h.
raw_bits);
211 q_table.resize(NumGradientTableEntries);
212 for (
int i = 0; i != NumGradientTableEntries; ++i) {
221 }
else if (
q_point[4] == 0x3FFF) {
226 }
else if (
q_point[4] == 0xFFF) {
232 ThrowRDE(
"Aha, finally, a 12-bit compressed RAF! Please consider providing "
233 "samples on <https://raw.pixls.us/>, thanks!");
265 template <
typename Tag,
typename T>
272 static int bitDiff(
int value1,
int value2);
275 std::array<int_pair, 41>& grads);
277 std::array<int_pair, 41>& grads);
279 std::array<int_pair, 41>& grads);
283 [[nodiscard]] std::pair<int, int>
285 [[nodiscard]] std::pair<int, int>
327 for (
int j = 0; j < 3; j++) {
328 for (
int i = 0; i < 41; i++) {
337template <
typename Tag,
typename T>
340 std::array<CFAColor, MCU<Tag>.x *
MCU<Tag>.y> CFAData;
341 if constexpr (std::is_same_v<XTransTag, Tag>)
343 else if constexpr (std::is_same_v<BayerTag, Tag>)
346 __builtin_unreachable();
352 for (MCUIdx.
x = 0; MCUIdx.
x != NumMCUs.
x; ++MCUIdx.
x) {
353 for (MCUIdx.
y = 0; MCUIdx.
y != NumMCUs.
y; ++MCUIdx.
y) {
358 for (
int MCURow = 0; MCURow !=
MCU<Tag>.y; ++MCURow) {
359 for (
int MCUCol = 0; MCUCol !=
MCU<Tag>.x; ++MCUCol) {
360 int imgRow = (
MCU<Tag>.y * MCUIdx.
y) + MCURow;
361 int imgCol = (
MCU<Tag>.x * MCUIdx.
x) + MCUCol;
365 switch (CFA(MCURow, MCUCol)) {
368 row =
R2 + (imgRow >> 1);
376 row =
B2 + (imgRow >> 1);
380 __builtin_unreachable();
383 out(MCURow, MCUCol) =
lines(row, 1 + idx(imgCol));
391 int cur_line)
const {
392 auto index = [](
int imgCol) {
393 return (((imgCol * 2 / 3) & 0x7FFFFFFE) | ((imgCol % 3) & 1)) +
401 int cur_line)
const {
402 auto index = [](
int imgCol) {
return imgCol >> 1; };
412 constexpr int batchSize = 32;
413 pump.fill(batchSize);
415 int numZerosInThisBatch = std::countl_zero(batch);
416 count += numZerosInThisBatch;
417 bool allZeroes = numZerosInThisBatch == batchSize;
418 int numBitsToSkip = numZerosInThisBatch;
421 pump.skipBitsNoFill(numBitsToSkip);
436 int lz1 = std::countl_zero(
static_cast<unsigned>(value1));
437 int lz2 = std::countl_zero(
static_cast<unsigned>(value2));
438 int decBits = std::max(lz2 - lz1, 0);
439 if ((value2 << decBits) < value1)
441 return std::min(decBits, 15);
446 std::array<int_pair, 41>& grads) {
447 int gradient = std::abs(grad);
454 codeBits =
bitDiff(grads[gradient].value1, grads[gradient].value2);
455 codeDelta = sampleBits << codeBits;
464 code =
pump->getBitsNoFill(codeBits);
472 code = -1 - code / 2;
477 grads[gradient].value1 += std::abs(code);
480 grads[gradient].value1 >>= 1;
481 grads[gradient].value2 >>= 1;
484 grads[gradient].value2++;
492 if (interp_val < 0) {
507 return (9 * ci.qTableLookup(ci.q_point[4] + v1)) +
514 int Rb =
lines(c - 1, 1 + (2 * (col + 0)) + 0);
515 int Rc =
lines(c - 1, 1 + (2 * (col - 1)) + 1);
516 int Rd =
lines(c - 1, 1 + (2 * (col + 0)) + 1);
517 int Rf =
lines(c - 2, 1 + (2 * (col + 0)) + 0);
519 int diffRcRb = std::abs(Rc - Rb);
520 int diffRfRb = std::abs(Rf - Rb);
521 int diffRdRb = std::abs(Rd - Rb);
526 if (diffRcRb > std::max(diffRfRb, diffRdRb)) {
530 if (diffRdRb > std::max(diffRcRb, diffRfRb)) {
538 int interp_val = Term0 + Term1 + Term2;
542 return {grad, interp_val};
548 int Ra =
lines(c + 0, 1 + (2 * (col + 0)) + 0);
549 int Rb =
lines(c - 1, 1 + (2 * (col + 0)) + 1);
550 int Rc =
lines(c - 1, 1 + (2 * (col + 0)) + 0);
551 int Rd =
lines(c - 1, 1 + (2 * (col + 1)) + 0);
552 int Rg =
lines(c + 0, 1 + (2 * (col + 1)) + 0);
554 int interp_val = (Ra + Rg);
555 if (
auto [min, max] = std::minmax(Rc, Rd); Rb < min || Rb > max) {
556 interp_val += 2 * Rb;
562 return {grad, interp_val};
567 xt_lines c,
int col, std::array<int_pair, 41>& grads) {
574 std::array<int_pair, 41>& grads) {
587 for (
int i = start; i <= end; i++) {
608 [[maybe_unused]]
int cur_line) {
612 auto pass = [
this, &line_width, func_even](std::array<xt_lines, 2> c,
616 struct ColorPos final {
621 std::array<ColorPos, 2> pos;
622 for (
int i = 0; i != line_width + 4; ++i) {
623 if (i < line_width) {
624 for (
int comp = 0; comp != 2; comp++) {
625 int& col = pos[comp].even;
626 int sample = func_even(c[comp], col,
grad_even[grad], row, i, comp);
633 for (
int comp = 0; comp != 2; comp++) {
634 int& col = pos[comp].odd;
643 using Tag = BayerTag;
644 const std::array<CFAColor, MCU<Tag>.x *
MCU<Tag>.
y> CFAData =
648 std::array<int, 3> PerColorCounter;
649 std::fill(PerColorCounter.begin(), PerColorCounter.end(), 0);
650 auto ColorCounter = [&PerColorCounter](
CFAColor c) ->
int& {
656 return PerColorCounter[
static_cast<uint8_t
>(c)];
658 __builtin_unreachable();
662 auto CurLineForColor = [&ColorCounter](
CFAColor c) {
676 __builtin_unreachable();
678 int& off = ColorCounter(c);
679 res =
static_cast<xt_lines>(res + off);
684 for (
int row = 0; row != 6; ++row) {
685 CFAColor c0 = CFA(row % CFA.height(), 0);
686 CFAColor c1 = CFA(row % CFA.height(), 1);
687 pass({CurLineForColor(c0), CurLineForColor(c1)}, row);
700 __builtin_unreachable();
708 [
this](
xt_lines c,
int col, std::array<int_pair, 41>& grads,
int row,
710 if ((comp == 0 && (row == 0 || (row == 2 && i % 2 == 0) ||
711 (row == 4 && i % 2 != 0) || row == 5)) ||
712 (comp == 1 && (row == 1 || row == 2 || (row == 3 && i % 2 != 0) ||
713 (row == 5 && i % 2 == 0))))
715 invariant((comp == 0 && (row == 1 || (row == 2 && i % 2 != 0) ||
716 row == 3 || (row == 4 && i % 2 == 0))) ||
717 (comp == 1 && (row == 0 || (row == 3 && i % 2 == 0) ||
718 row == 4 || (row == 5 && i % 2 != 0))));
726 [
this](
xt_lines c,
int col, std::array<int_pair, 41>& grads,
727 [[maybe_unused]]
int row, [[maybe_unused]]
int i,
728 [[maybe_unused]]
int comp) {
737 struct i_pair final {
742 const std::array<i_pair, 3> colors = {{{
R0, 5}, {
G0, 8}, {
B0, 5}}};
744 for (
int cur_line = 0; cur_line < strip.
height(); cur_line++) {
745 if (
header.raw_type == 16) {
751 if (
header.raw_type == 16) {
757 if (cur_line + 1 == strip.
height())
761 for (
auto i : colors) {
762 memcpy(&
lines(i.a, 0), &
lines(i.a + i.b - 2, 0), 2 * line_size);
765 for (
auto i : colors) {
768 lines.width(), i.b - 2);
810#pragma omp for schedule(static)
812 for (
int block = 0; block <
header.blocks_in_row; ++block) {
820 mRaw->setError(err.what());
823 __builtin_unreachable();
830#pragma omp parallel default(none) \
831 num_threads(rawspeed_get_number_of_processor_cores())
835 std::string firstErr;
836 if (
mRaw->isTooManyErrors(1, &firstErr)) {
837 ThrowRDE(
"Too many errors encountered. Giving up. First Error:\n%s",
848 ThrowRDE(
"Unexpected component count / data type");
854 ThrowRDE(
"compressed RAF header check");
857 ThrowRDE(
"RAF header specifies different dimensions!");
859 if (12 ==
header.raw_bits) {
860 ThrowRDE(
"Aha, finally, a 12-bit compressed RAF! Please consider providing "
861 "samples on <https://raw.pixls.us/>, thanks!");
869 ThrowRDE(
"Unexpected X-Trans phase: {%i,%i}. Please file a bug!", p->x,
876 ThrowRDE(
"Unexpected Bayer phase: %i. Please file a bug!",
877 static_cast<int>(*p));
883 std::vector<uint32_t> block_sizes;
884 block_sizes.resize(
header.blocks_in_row);
885 for (
auto& block_size : block_sizes)
886 block_size =
input.getU32();
891 const int padding = 0x10 - (raw_offset & 0xC);
892 input.skipBytes(padding);
898 for (
const auto& block_size : block_sizes)
899 strips.emplace_back(
input.getStream(block_size).getAsArray1DRef());
903 FujiDecompressorImpl
impl(
920FujiDecompressor::FujiHeader::operator bool()
const {
926 raw_width < 0x300 || raw_width % 24 || raw_rounded_width > 0x3000 ||
assert(dim.area() >=area)
std::vector< Array1DRef< const uint8_t > > strips
FujiDecompressor(RawImage img, ByteStream input)
const Array1DRef< const Array1DRef< const uint8_t > > strips
const fuji_compressed_params common_info
void decompressThread() const noexcept
FujiDecompressorImpl(RawImage mRaw, Array1DRef< const Array1DRef< const uint8_t > > strips, const FujiDecompressor::FujiHeader &h)
const FujiDecompressor::FujiHeader & header
int8_t GetGradient(const fuji_compressed_params &p, int cur_val)
__attribute__((always_inline)) inline int fuji_compressed_block
constexpr uint64_t RAWSPEED_READNONE roundUpDivisionSafe(uint64_t value, uint64_t div)
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
std::array< CFAColor, 4 > getAsCFAColors(BayerPhase p)
Optional< BayerPhase > getAsBayerPhase(const ColorFilterArray &CFA)
Array2DRef(Array1DRef< T > data, int width, int height, int pitch) -> Array2DRef< T >
CroppedArray2DRef(Array2DRef< T > base_, int offsetCols_, int offsetRows_, int croppedWidth_, int croppedHeight_) -> CroppedArray2DRef< typename Array2DRef< T >::value_type >
Optional< XTransPhase > getAsXTransPhase(const ColorFilterArray &CFA)
static void Allocated(const void *addr, size_t size)
int RAWSPEED_READONLY height() const
const Array1DRef< const uint8_t > input
int RAWSPEED_READONLY width() const
iPoint2D numMCUs(iPoint2D MCU) const
int offsetY(int line=0) const
static int RAWSPEED_READONLY lineHeight()
FujiStrip(FujiStrip &&) noexcept=delete
FujiStrip(const FujiStrip &)=delete
const FujiDecompressor::FujiHeader & h
std::array< std::array< int_pair, 41 >, 3 > grad_odd
void fuji_extend_red() const
void fuji_bayer_decode_block(int cur_line)
int fuji_quant_gradient(int v1, int v2) const
void copy_line_to_xtrans(const FujiStrip &strip, int cur_line) const
static int bitDiff(int value1, int value2)
Optional< BitStreamerMSB > pump
const fuji_compressed_params & common_info
int fuji_decode_sample(int grad, int interp_val, std::array< int_pair, 41 > &grads)
std::vector< uint16_t > linealloc
std::pair< int, int > fuji_decode_interpolation_odd_inner(xt_lines c, int col) const
std::pair< int, int > fuji_decode_interpolation_even_inner(xt_lines c, int col) const
void fuji_extend_blue() const
void fuji_extend_green() const
int fuji_decode_sample_even(xt_lines c, int col, std::array< int_pair, 41 > &grads)
void copy_line(const FujiStrip &strip, int cur_line, T idx) const
static int fuji_zerobits(BitStreamerMSB &pump)
const Array2DRef< uint16_t > img
const FujiDecompressor::FujiHeader & header
fuji_compressed_block(Array2DRef< uint16_t > img, const FujiDecompressor::FujiHeader &header, const fuji_compressed_params &common_info)
void fuji_decode_strip(const FujiStrip &strip)
void copy_line_to_bayer(const FujiStrip &strip, int cur_line) const
int fuji_decode_sample_odd(xt_lines c, int col, std::array< int_pair, 41 > &grads)
void xtrans_decode_block(int cur_line)
Array2DRef< uint16_t > lines
int fuji_decode_interpolation_even(xt_lines c, int col) const
std::array< std::array< int_pair, 41 >, 3 > grad_even
void fuji_decode_block(T func_even, int cur_line)
void fuji_extend_generic(int start, int end) const
int8_t qTableLookup(int cur_val) const
fuji_compressed_params(const FujiDecompressor::FujiHeader &h)
std::vector< int8_t > q_table
std::array< int, 5 > q_point