@@ -40,9 +40,9 @@ namespace rawspeed {
4040LJpegDecompressor::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);
0 commit comments