Skip to content

Commit

Permalink
Add LJpeg predictors 2-7
Browse files Browse the repository at this point in the history
  • Loading branch information
kmilos committed Dec 30, 2021
1 parent a571881 commit 8e0c81d
Showing 1 changed file with 66 additions and 5 deletions.
71 changes: 66 additions & 5 deletions src/librawspeed/decompressors/LJpegDecompressor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ void LJpegDecompressor::decodeScan()
{
assert(frame.cps > 0);

if (predictorMode != 1)
if ((predictorMode < 1) || (predictorMode > 7))
ThrowRDE("Unsupported predictor mode: %u", predictorMode);

for (uint32_t i = 0; i < frame.cps; i++)
Expand Down Expand Up @@ -194,15 +194,47 @@ template <int N_COMP, bool WeirdWidth> void LJpegDecompressor::decodeN() {
copy_n(predNext, N_COMP, pred.data());
// the predictor for the next line is the start of this line
predNext = &img(row, col);
// the predictor mode is always horizontal on the first line
uint32_t predMode = row == 0 ? 1 : predictorMode;

// FIXME: predictor may have value outside of the uint16_t.
// https://github.com/darktable-org/rawspeed/issues/175

// For x, we first process all full pixel blocks within the image buffer ...
for (; col < N_COMP * fullBlocks; col += N_COMP) {
for (int i = 0; i != N_COMP; ++i) {
pred[i] = uint16_t(pred[i] + ht[i]->decodeDifference(bitStream));
img(row, col + i) = pred[i];
img(row, col + i) =
uint16_t(pred[i] + ht[i]->decodeDifference(bitStream));
if (col < N_COMP * (fullBlocks - 1)) {
int predA = img(row, col + i);
int predB = predMode > 1 ? img(row - 1, col + N_COMP + i) : 0;
int predC = predMode > 1 ? img(row - 1, col + i) : 0;
switch (predMode) {
case 1:
pred[i] = uint16_t(predA);
break;
case 2:
pred[i] = uint16_t(predB);
break;
case 3:
pred[i] = uint16_t(predC);
break;
case 4:
pred[i] = uint16_t(predA + predB - predC);
break;
case 5:
pred[i] = uint16_t(predA + ((predB - predC) >> 1));
break;
case 6:
pred[i] = uint16_t(predB + ((predA - predC) >> 1));
break;
case 7:
pred[i] = uint16_t((predA + predB) >> 1);
break;
default:
ThrowRDE("Unsupported predictor mode: %u", predMode);
}
}
}
}

Expand All @@ -217,8 +249,37 @@ template <int N_COMP, bool WeirdWidth> void LJpegDecompressor::decodeN() {
assert(trailingPixels < N_COMP);
unsigned c = 0;
for (; c < trailingPixels; ++c) {
pred[c] = uint16_t(pred[c] + ht[c]->decodeDifference(bitStream));
img(row, col + c) = pred[c];
// Continue predictor update skipped at last full block
int predA = img(row, col - N_COMP + c);
int predB = predMode > 1 ? img(row - 1, col + c) : 0;
int predC = predMode > 1 ? img(row - 1, col - N_COMP + c) : 0;
switch (predMode) {
case 1:
pred[c] = uint16_t(predA);
break;
case 2:
pred[c] = uint16_t(predB);
break;
case 3:
pred[c] = uint16_t(predC);
break;
case 4:
pred[c] = uint16_t(predA + predB - predC);
break;
case 5:
pred[c] = uint16_t(predA + ((predB - predC) >> 1));
break;
case 6:
pred[c] = uint16_t(predB + ((predA - predC) >> 1));
break;
case 7:
pred[c] = uint16_t((predA + predB) >> 1);
break;
default:
ThrowRDE("Unsupported predictor mode: %u", predMode);
}
img(row, col + c) =
uint16_t(pred[c] + ht[c]->decodeDifference(bitStream));
}
// Discard the rest of the block.
assert(c < N_COMP);
Expand Down

0 comments on commit 8e0c81d

Please sign in to comment.