@@ -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+ ByteStream bs, bool interleaveRows_ )
4444 : mRaw (img), input(bs), imgFrame(imgFrame_), frame(std::move(frame_)),
45- rec (std::move(rec_)) {
45+ rec (std::move(rec_)), interleaveRows{interleaveRows_} {
4646 if (mRaw ->getDataType () != RawImageType::UINT16)
4747 ThrowRDE (" Unexpected data type (%u)" ,
4848 static_cast <unsigned >(mRaw ->getDataType ()));
@@ -100,16 +100,19 @@ LJpegDecompressor::LJpegDecompressor(const RawImage& img,
100100 ThrowRDE (" Got less pixels than the components per sample" );
101101
102102 // How many output pixels are we expected to produce, as per DNG tiling?
103- const int tileRequiredWidth = (int )mRaw ->getCpp () * imgFrame.dim .x ;
103+ const auto interleaveFactor = interleaveRows ? 2 : 1 ;
104+ const int tileRequiredWidth =
105+ (int )mRaw ->getCpp () * imgFrame.dim .x * interleaveFactor;
106+ // How many of these rows do we need?
107+ const auto numRows = imgFrame.dim .y / interleaveFactor;
104108
105109 // How many full pixel blocks do we need to consume for that?
106110 if (const int blocksToConsume = roundUpDivision (tileRequiredWidth, frame.cps );
107- frame.dim .x < blocksToConsume || frame.dim .y < imgFrame. dim . y ||
111+ frame.dim .x < blocksToConsume || frame.dim .y < numRows ||
108112 (int64_t )frame.cps * frame.dim .x <
109113 (int64_t )mRaw ->getCpp () * imgFrame.dim .x ) {
110114 ThrowRDE (" LJpeg frame (%u, %u) is smaller than expected (%u, %u)" ,
111- frame.cps * frame.dim .x , frame.dim .y , tileRequiredWidth,
112- imgFrame.dim .y );
115+ frame.cps * frame.dim .x , frame.dim .y , tileRequiredWidth, numRows);
113116 }
114117
115118 // How many full pixel blocks will we produce?
@@ -148,17 +151,20 @@ template <int N_COMP, bool WeirdWidth> void LJpegDecompressor::decodeN() {
148151 invariant (N_COMP > 0 );
149152 invariant (N_COMP >= mRaw ->getCpp ());
150153 invariant ((N_COMP / mRaw ->getCpp ()) > 0 );
154+ invariant (((N_COMP & 1 ) == 0 ) | !interleaveRows);
151155
152156 invariant (mRaw ->dim .x >= N_COMP);
153157 invariant ((mRaw ->getCpp () * (mRaw ->dim .x - imgFrame.pos .x )) >= N_COMP);
154158
159+ auto interleaveHeight = (interleaveRows ? 2 : 1 );
160+ auto interleaveWidth = N_COMP / interleaveHeight;
161+
155162 const CroppedArray2DRef img (mRaw ->getU16DataAsUncroppedArray2DRef (),
156163 mRaw ->getCpp () * imgFrame.pos .x , imgFrame.pos .y ,
157164 mRaw ->getCpp () * imgFrame.dim .x , imgFrame.dim .y );
158165
159166 const auto ht = getPrefixCodeDecoders<N_COMP>();
160167 auto pred = getInitialPreds<N_COMP>();
161- uint16_t * predNext = pred.data ();
162168
163169 BitPumpJPEG bitStream (input);
164170
@@ -173,13 +179,17 @@ template <int N_COMP, bool WeirdWidth> void LJpegDecompressor::decodeN() {
173179 invariant (imgFrame.pos .y + imgFrame.dim .y <= mRaw ->dim .y );
174180 invariant (imgFrame.pos .x + imgFrame.dim .x <= mRaw ->dim .x );
175181
182+ const auto numRows = imgFrame.dim .y / interleaveHeight;
183+
176184 // For y, we can simply stop decoding when we reached the border.
177- for (int row = 0 ; row < imgFrame. dim . y ; ++row) {
185+ for (int row = 0 ; row < numRows ; ++row) {
178186 int col = 0 ;
179187
188+ /*
180189 copy_n(predNext, N_COMP, pred.data());
181190 // the predictor for the next line is the start of this line
182191 predNext = &img(row, col);
192+ */
183193
184194 // FIXME: predictor may have value outside of the uint16_t.
185195 // https://github.com/darktable-org/rawspeed/issues/175
@@ -190,7 +200,12 @@ template <int N_COMP, bool WeirdWidth> void LJpegDecompressor::decodeN() {
190200 pred[i] = uint16_t (
191201 pred[i] +
192202 ((const PrefixCodeDecoder<>&)(ht[i])).decodeDifference (bitStream));
193- img (row, col + i) = pred[i];
203+ if (interleaveRows) {
204+ img ((row * interleaveHeight) + (i / interleaveHeight),
205+ (col / interleaveWidth) + (i % interleaveWidth)) = pred[i];
206+ } else {
207+ img (row, col + i) = pred[i];
208+ }
194209 }
195210 }
196211
@@ -223,6 +238,16 @@ template <int N_COMP, bool WeirdWidth> void LJpegDecompressor::decodeN() {
223238 for (int i = 0 ; i != N_COMP; ++i)
224239 ((const PrefixCodeDecoder<>&)(ht[i])).decodeDifference (bitStream);
225240 }
241+
242+ // The first sample of the next row is calculated based on the first sample
243+ // of this row, so copy it for the next iteration
244+ if (interleaveRows) {
245+ copy_n (&img (row * interleaveHeight, 0 ), interleaveWidth, pred.data ());
246+ copy_n (&img (row * interleaveHeight + 1 , 0 ), interleaveWidth,
247+ pred.data () + interleaveWidth);
248+ } else {
249+ copy_n (&img (row, 0 ), N_COMP, pred.data ());
250+ }
226251 }
227252}
228253
0 commit comments