Skip to content

Commit ce27abc

Browse files
committed
Add LJpeg predictors 2-7
1 parent c65fdca commit ce27abc

3 files changed

Lines changed: 77 additions & 12 deletions

File tree

src/librawspeed/decompressors/LJpegDecoder.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ void LJpegDecoder::decode(uint32_t offsetX, uint32_t offsetY, uint32_t width,
9292
void LJpegDecoder::decodeScan() {
9393
invariant(frame.cps > 0);
9494

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

9898
for (uint32_t i = 0; i < frame.cps; i++)
@@ -113,7 +113,8 @@ void LJpegDecoder::decodeScan() {
113113

114114
LJpegDecompressor d(
115115
mRaw, iRectangle2D({(int)offX, (int)offY}, {(int)w, (int)h}),
116-
LJpegDecompressor::Frame{N_COMP, iPoint2D(frame.w, frame.h)}, rec, input);
116+
LJpegDecompressor::Frame{N_COMP, iPoint2D(frame.w, frame.h)}, rec,
117+
predictorMode, input);
117118
d.decode();
118119
}
119120

src/librawspeed/decompressors/LJpegDecompressor.cpp

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ namespace rawspeed {
4040
LJpegDecompressor::LJpegDecompressor(const RawImage& img,
4141
iRectangle2D imgFrame_, Frame frame_,
4242
std::vector<PerComponentRecipe> rec_,
43-
ByteStream bs)
43+
int predictorMode_, ByteStream bs)
4444
: mRaw(img), input(bs), imgFrame(imgFrame_), frame(std::move(frame_)),
45-
rec(std::move(rec_)) {
45+
rec(std::move(rec_)), predictorMode(predictorMode_) {
4646
if (mRaw->getDataType() != RawImageType::UINT16)
4747
ThrowRDE("Unexpected data type (%u)",
4848
static_cast<unsigned>(mRaw->getDataType()));
@@ -157,8 +157,9 @@ template <int N_COMP, bool WeirdWidth> void LJpegDecompressor::decodeN() {
157157
mRaw->getCpp() * imgFrame.dim.x, imgFrame.dim.y);
158158

159159
const auto ht = getPrefixCodeDecoders<N_COMP>();
160-
auto pred = getInitialPreds<N_COMP>();
161-
uint16_t* predNext = pred.data();
160+
auto predInit = getInitialPreds<N_COMP>();
161+
uint16_t* predNext = predInit.data();
162+
std::array<uint16_t, N_COMP> pred;
162163

163164
BitPumpJPEG bitStream(input);
164165

@@ -177,20 +178,53 @@ template <int N_COMP, bool WeirdWidth> void LJpegDecompressor::decodeN() {
177178
for (int row = 0; row < imgFrame.dim.y; ++row) {
178179
int col = 0;
179180

180-
copy_n(predNext, N_COMP, pred.data());
181+
for (int i = 0; i != N_COMP; ++i) {
182+
pred[i] = predNext[i];
183+
}
181184
// the predictor for the next line is the start of this line
182185
predNext = &img(row, col);
186+
// the predictor mode is always horizontal on the first line
187+
int predMode = row == 0 ? 1 : predictorMode;
183188

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

187192
// For x, we first process all full pixel blocks within the image buffer ...
188193
for (; col < N_COMP * fullBlocks; col += N_COMP) {
189194
for (int i = 0; i != N_COMP; ++i) {
190-
pred[i] = uint16_t(
195+
img(row, col + i) = uint16_t(
191196
pred[i] +
192197
((const PrefixCodeDecoder<>&)(ht[i])).decodeDifference(bitStream));
193-
img(row, col + i) = pred[i];
198+
if (col < N_COMP * (fullBlocks - 1)) {
199+
int32_t predA = img(row, col + i);
200+
int32_t predB = predMode > 1 ? img(row - 1, col + N_COMP + i) : 0;
201+
int32_t predC = predMode > 1 ? img(row - 1, col + i) : 0;
202+
switch (predMode) {
203+
case 1:
204+
pred[i] = predA;
205+
break;
206+
case 2:
207+
pred[i] = predB;
208+
break;
209+
case 3:
210+
pred[i] = predC;
211+
break;
212+
case 4:
213+
pred[i] = predA + predB - predC;
214+
break;
215+
case 5:
216+
pred[i] = predA + ((predB - predC) >> 1);
217+
break;
218+
case 6:
219+
pred[i] = predB + ((predA - predC) >> 1);
220+
break;
221+
case 7:
222+
pred[i] = (predA + predB) >> 1;
223+
break;
224+
default:
225+
__builtin_unreachable();
226+
}
227+
}
194228
}
195229
}
196230

@@ -205,10 +239,38 @@ template <int N_COMP, bool WeirdWidth> void LJpegDecompressor::decodeN() {
205239
invariant(trailingPixels < N_COMP);
206240
int c = 0;
207241
for (; c < trailingPixels; ++c) {
208-
pred[c] = uint16_t(
242+
// Continue predictor update skipped at last full block
243+
int32_t predA = img(row, col - N_COMP + c);
244+
int32_t predB = predMode > 1 ? img(row - 1, col + c) : 0;
245+
int32_t predC = predMode > 1 ? img(row - 1, col - N_COMP + c) : 0;
246+
switch (predMode) {
247+
case 1:
248+
pred[c] = predA;
249+
break;
250+
case 2:
251+
pred[c] = predB;
252+
break;
253+
case 3:
254+
pred[c] = predC;
255+
break;
256+
case 4:
257+
pred[c] = predA + predB - predC;
258+
break;
259+
case 5:
260+
pred[c] = predA + ((predB - predC) >> 1);
261+
break;
262+
case 6:
263+
pred[c] = predB + ((predA - predC) >> 1);
264+
break;
265+
case 7:
266+
pred[c] = (predA + predB) >> 1;
267+
break;
268+
default:
269+
__builtin_unreachable();
270+
}
271+
img(row, col + c) = uint16_t(
209272
pred[c] +
210273
((const PrefixCodeDecoder<>&)(ht[c])).decodeDifference(bitStream));
211-
img(row, col + c) = pred[c];
212274
}
213275
// Discard the rest of the block.
214276
invariant(c < N_COMP);

src/librawspeed/decompressors/LJpegDecompressor.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class LJpegDecompressor final {
5656
const Frame frame;
5757
const std::vector<PerComponentRecipe> rec;
5858

59+
int predictorMode;
5960
int fullBlocks = 0;
6061
int trailingPixels = 0;
6162

@@ -76,7 +77,8 @@ class LJpegDecompressor final {
7677

7778
public:
7879
LJpegDecompressor(const RawImage& img, iRectangle2D imgFrame, Frame frame,
79-
std::vector<PerComponentRecipe> rec, ByteStream bs);
80+
std::vector<PerComponentRecipe> rec, int predictorMode,
81+
ByteStream bs);
8082

8183
void decode();
8284
};

0 commit comments

Comments
 (0)