23#include "rawspeedconfig.h"
60inline TileSequenceStatus
129 const int tileHeight = std::min(outRowsRemaining, tileRowsRemaining);
130 tile.
dim.
y = tileHeight;
160 [[nodiscard]] std::pair<iRectangle2D, int>
coalesce()
const {
169 const TileSequenceStatus
s = evaluateConsecutiveTiles(rect, nextRect);
170 invariant(
s != TileSequenceStatus::Invalid &&
"Bad tiling.");
171 if (
s == TileSequenceStatus::BeginsNewColumn)
173 invariant(
s == TileSequenceStatus::ContinuesColumn);
202 "Comparing unrelated iterators.");
207template <
typename PrefixCodeDecoder>
208iterator_range<Cr2SliceIterator>
214template <
typename PrefixCodeDecoder>
222template <
typename PrefixCodeDecoder>
226 auto first = allOutputTiles.begin();
227 auto end = allOutputTiles.end();
230 while (std::next(last) != end && (*last).getBottomRight() !=
dim)
232 assert((*last).getBottomRight() ==
dim &&
"Bad tiling");
233 return {first, ++last};
236template <
typename PrefixCodeDecoder>
241 std::end(outputTiles)),
243 std::end(outputTiles))};
269 std::tuple<int /*N_COMP*/, int /*X_S_F*/, int /*Y_S_F*/> format)
270 :
N_COMP(std::get<0>(format)),
X_S_F(std::get<1>(format)),
279template <
typename PrefixCodeDecoder>
282 std::tuple<int /*N_COMP*/, int /*X_S_F*/, int /*Y_S_F*/> format_,
293 if (!((std::make_tuple(3, 2, 2) ==
format) ||
294 (std::make_tuple(3, 2, 1) ==
format) ||
295 (std::make_tuple(2, 1, 1) ==
format) ||
296 (std::make_tuple(4, 1, 1) ==
format)))
303 if (!
dim.hasPositiveArea() ||
dim.x % dsc.groupSize != 0)
304 ThrowRDE(
"Unexpected image dimension multiplicity");
305 dim.x /= dsc.groupSize;
307 if (!
frame.hasPositiveArea() ||
frame.x % dsc.X_S_F != 0 ||
308 frame.y % dsc.Y_S_F != 0)
309 ThrowRDE(
"Unexpected LJpeg frame dimension multiplicity");
310 frame.x /= dsc.X_S_F;
311 frame.y /= dsc.Y_S_F;
313 if (
mRaw->dim.x > 19440 ||
mRaw->dim.y > 5920) {
314 ThrowRDE(
"Unexpected image dimensions found: (%d; %d)",
mRaw->dim.x,
318 for (
auto sliceId = 0; sliceId <
slicing.numSlices; sliceId++) {
319 const auto sliceWidth =
slicing.widthOfSlice(sliceId);
321 ThrowRDE(
"Bad slice width: %i", sliceWidth);
324 if (dsc.subSampled ==
mRaw->isCFA)
325 ThrowRDE(
"Cannot decode subsampled image to CFA data or vice versa");
327 if (
static_cast<int>(
rec.size()) != dsc.N_COMP)
328 ThrowRDE(
"HT/Initial predictor count does not match component count");
330 for (
const auto& recip :
rec) {
331 if (!recip.ht.isFullDecode())
332 ThrowRDE(
"Huffman table is not of a full decoding variety");
335 for (
auto* width : {&
slicing.sliceWidth, &
slicing.lastSliceWidth}) {
336 if (*width % dsc.sliceColStep != 0) {
337 ThrowRDE(
"Slice width (%d) should be multiple of pixel group size (%d)",
338 *width, dsc.sliceColStep);
340 *width /= dsc.sliceColStep;
344 ThrowRDE(
"Frame area smaller than the image area");
348 if (lastTile && evaluateConsecutiveTiles(*lastTile, output) ==
349 TileSequenceStatus::Invalid)
350 ThrowRDE(
"Invalid tiling - slice width change mid-output row?");
351 if (output.getBottomRight() <=
dim) {
355 if (output.getTopLeft() <
dim)
356 ThrowRDE(
"Output tile partially outside of image");
361 if (lastTile->getBottomRight() !=
dim)
362 ThrowRDE(
"Tiles do not cover the entire image area.");
365template <
typename PrefixCodeDecoder>
366template <
int N_COMP,
size_t... I>
367std::array<std::reference_wrapper<const PrefixCodeDecoder>, N_COMP>
369 std::index_sequence<I...> )
const {
370 return std::array<std::reference_wrapper<const PrefixCodeDecoder>, N_COMP>{
371 std::cref(
rec[I].ht)...};
374template <
typename PrefixCodeDecoder>
376std::array<std::reference_wrapper<const PrefixCodeDecoder>, N_COMP>
381template <
typename PrefixCodeDecoder>
383std::array<uint16_t, N_COMP>
385 std::array<uint16_t, N_COMP> preds;
387 rec.begin(),
rec.end(), preds.begin(),
396template <
typename PrefixCodeDecoder>
397template <
int N_COMP,
int X_S_F,
int Y_S_F>
405 constexpr Dsc dsc({N_COMP, X_S_F, Y_S_F});
413 auto ht = getPrefixCodeDecoders<N_COMP>();
414 auto pred = getInitialPreds<N_COMP>();
415 auto predNext = out[0]
416 .getCrop(0, dsc.groupSize)
421 int globalFrameCol = 0;
422 int globalFrameRow = 0;
423 (void)globalFrameRow;
425 auto frameColsRemaining = [&]() {
426 int r = frame.x - globalFrameCol;
432 for (
int row = output.getTop(), rowEnd = output.getBottom(); row != rowEnd;
434 for (
int col = output.getLeft(), colEnd = output.getRight();
437 if (frameColsRemaining() == 0) {
442 for (
int c = 0; c < N_COMP; ++c)
443 pred[c] = predNext(c == 0 ? c : dsc.groupSize - (N_COMP - c));
445 .getBlock(dsc.groupSize,
450 invariant(globalFrameRow < frame.y &&
"Run out of frame");
455 for (
int colFrameEnd = std::min(colEnd, col + frameColsRemaining());
456 col != colFrameEnd; ++col, ++globalFrameCol) {
457 for (
int p = 0;
p < dsc.groupSize; ++
p) {
458 int c =
p < dsc.pixelsPerGroup ? 0 :
p - dsc.pixelsPerGroup + 1;
459 out(row, (dsc.groupSize * col) + p) = pred[c] +=
461 .decodeDifference(bs);
467 return bs.getStreamPosition();
470template <
typename PrefixCodeDecoder>
472 if (std::make_tuple(3, 2, 2) ==
format) {
473 return decompressN_X_Y<3, 2, 2>();
475 if (std::make_tuple(3, 2, 1) ==
format) {
476 return decompressN_X_Y<3, 2, 1>();
478 if (std::make_tuple(2, 1, 1) ==
format) {
479 return decompressN_X_Y<2, 1, 1>();
481 if (std::make_tuple(4, 1, 1) ==
format) {
482 return decompressN_X_Y<4, 1, 1>();
484 __builtin_unreachable();
assert(dim.area() >=area)
const std::tuple< int, int, int > format
iterator_range< Cr2VerticalOutputStripIterator > getVerticalOutputStrips() const
std::array< std::reference_wrapper< const PrefixCodeDecoder >, N_COMP > getPrefixCodeDecoders() const
ByteStream::size_type decompress() const
const std::vector< PerComponentRecipe > rec
const Array1DRef< const uint8_t > input
Cr2Decompressor(RawImage mRaw, std::tuple< int, int, int > format, iPoint2D frame, Cr2SliceWidths slicing, std::vector< PerComponentRecipe > rec, Array1DRef< const uint8_t > input)
std::array< uint16_t, N_COMP > getInitialPreds() const
iterator_range< Cr2OutputTileIterator > getOutputTiles() const
std::array< std::reference_wrapper< const PrefixCodeDecoder >, N_COMP > getPrefixCodeDecodersImpl(std::index_sequence< I... >) const
iterator_range< Cr2OutputTileIterator > getAllOutputTiles() const
__attribute__((noinline)) ByteStream iterator_range< Cr2SliceIterator > getSlices() const
Cr2OutputTileIterator outputTileIterator
std::ptrdiff_t difference_type
Cr2VerticalOutputStripIterator & operator++()
const value_type & reference
Cr2OutputTileIterator outputTileIterator_end
std::input_iterator_tag iterator_category
friend bool operator==(const Cr2VerticalOutputStripIterator &a, const Cr2VerticalOutputStripIterator &b)
const value_type * pointer
Cr2VerticalOutputStripIterator(const Cr2OutputTileIterator &outputTileIterator_, const Cr2OutputTileIterator &outputTileIterator_end_)
std::pair< iRectangle2D, int > coalesce() const
value_type operator*() const
constexpr int getTop() const
constexpr iPoint2D getTopRight() const
constexpr int getHeight() const
constexpr int getRight() const
constexpr iPoint2D getBottomLeft() const
constexpr iPoint2D getTopLeft() const
constexpr int getWidth() const
constexpr int getLeft() const
constexpr iPoint2D getBottomRight() const
TileSequenceStatus evaluateConsecutiveTiles(const iRectangle2D &rect, const iRectangle2D &nextRect)
PrefixCodeLUTDecoder< CodeTag, PrefixCodeLookupDecoder< CodeTag > > PrefixCodeDecoder
Cr2OutputTileIterator(const Cr2SliceIterator &sliceIter_, const iPoint2D &imgDim_)
std::input_iterator_tag iterator_category
value_type operator*() const
const value_type * pointer
Cr2OutputTileIterator & operator++()
friend bool RAWSPEED_READONLY operator==(const Cr2OutputTileIterator &a, const Cr2OutputTileIterator &b)
const value_type & reference
std::ptrdiff_t difference_type
Cr2SliceIterator sliceIter
const value_type * pointer
std::ptrdiff_t difference_type
Cr2SliceIterator(const Cr2SliceWidthIterator &sliceWidthIter_, const iPoint2D &frame)
const value_type & reference
friend bool operator==(const Cr2SliceIterator &a, const Cr2SliceIterator &b)
value_type RAWSPEED_READONLY operator*() const
Cr2SliceWidthIterator widthIter
Cr2SliceIterator & operator++()
std::input_iterator_tag iterator_category
constexpr Dsc(std::tuple< int, int, int > format)