1 /*
2     RawSpeed - RAW file decoder.
3 
4     Copyright (C) 2009-2014 Klaus Post
5     Copyright (C) 2017 Axel Waggershauser
6     Copyright (C) 2017-2018 Roman Lebedev
7 
8     This library is free software; you can redistribute it and/or
9     modify it under the terms of the GNU Lesser General Public
10     License as published by the Free Software Foundation; either
11     version 2 of the License, or (at your option) any later version.
12 
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16     Lesser General Public License for more details.
17 
18     You should have received a copy of the GNU Lesser General Public
19     License along with this library; if not, write to the Free Software
20     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22 
23 #include "decompressors/Cr2Decompressor.h"
24 #include "common/Array2DRef.h"            // for Array2DRef
25 #include "common/Point.h"                 // for iPoint2D, iPoint2D::area_type
26 #include "common/RawImage.h"              // for RawImage, RawImageData
27 #include "decoders/RawDecoderException.h" // for ThrowRDE
28 #include "io/BitPumpJPEG.h"               // for BitPumpJPEG, BitStream<>::...
29 #include <algorithm>                      // for copy_n, min
30 #include <array>                          // for array
31 #include <cassert>                        // for assert
32 #include <initializer_list>               // for initializer_list
33 
34 using std::copy_n;
35 
36 namespace rawspeed {
37 
38 class ByteStream;
39 
Cr2Decompressor(const ByteStream & bs,const RawImage & img)40 Cr2Decompressor::Cr2Decompressor(const ByteStream& bs, const RawImage& img)
41     : AbstractLJpegDecompressor(bs, img) {
42   if (mRaw->getDataType() != TYPE_USHORT16)
43     ThrowRDE("Unexpected data type");
44 
45   if (!((mRaw->getCpp() == 1 && mRaw->getBpp() == sizeof(uint16_t)) ||
46         (mRaw->getCpp() == 3 && mRaw->getBpp() == 3 * sizeof(uint16_t))))
47     ThrowRDE("Unexpected cpp: %u", mRaw->getCpp());
48 
49   if (!mRaw->dim.x || !mRaw->dim.y || mRaw->dim.x > 8896 ||
50       mRaw->dim.y > 5920) {
51     ThrowRDE("Unexpected image dimensions found: (%u; %u)", mRaw->dim.x,
52              mRaw->dim.y);
53   }
54 }
55 
decodeScan()56 void Cr2Decompressor::decodeScan()
57 {
58   if (predictorMode != 1)
59     ThrowRDE("Unsupported predictor mode.");
60 
61   if (slicing.empty()) {
62     const int slicesWidth = frame.w * frame.cps;
63     if (slicesWidth > mRaw->dim.x)
64       ThrowRDE("Don't know slicing pattern, and failed to guess it.");
65 
66     slicing = Cr2Slicing(/*numSlices=*/1, /*sliceWidth=don't care*/ 0,
67                          /*lastSliceWidth=*/slicesWidth);
68   }
69 
70   bool isSubSampled = false;
71   for (uint32_t i = 0; i < frame.cps; i++)
72     isSubSampled = isSubSampled || frame.compInfo[i].superH != 1 ||
73                    frame.compInfo[i].superV != 1;
74 
75   if (isSubSampled) {
76     if (mRaw->isCFA)
77       ThrowRDE("Cannot decode subsampled image to CFA data");
78 
79     if (mRaw->getCpp() != frame.cps)
80       ThrowRDE("Subsampled component count does not match image.");
81 
82     if (frame.cps != 3)
83       ThrowRDE("Unsupported number of subsampled components: %u", frame.cps);
84 
85     // see http://lclevy.free.fr/cr2/#sraw for overview table
86     bool isSupported = frame.compInfo[0].superH == 2;
87 
88     isSupported = isSupported && (frame.compInfo[0].superV == 1 ||
89                                   frame.compInfo[0].superV == 2);
90 
91     for (uint32_t i = 1; i < frame.cps; i++)
92       isSupported = isSupported && frame.compInfo[i].superH == 1 &&
93                     frame.compInfo[i].superV == 1;
94 
95     if (!isSupported) {
96       ThrowRDE("Unsupported subsampling ([[%u, %u], [%u, %u], [%u, %u]])",
97                frame.compInfo[0].superH, frame.compInfo[0].superV,
98                frame.compInfo[1].superH, frame.compInfo[1].superV,
99                frame.compInfo[2].superH, frame.compInfo[2].superV);
100     }
101 
102     if (frame.compInfo[0].superV == 2)
103       decodeN_X_Y<3, 2, 2>(); // Cr2 sRaw1/mRaw
104     else {
105       assert(frame.compInfo[0].superV == 1);
106       decodeN_X_Y<3, 2, 1>(); // Cr2 sRaw2/sRaw
107     }
108   } else {
109     switch (frame.cps) {
110     case 2:
111       decodeN_X_Y<2, 1, 1>();
112       break;
113     case 4:
114       decodeN_X_Y<4, 1, 1>();
115       break;
116     default:
117       ThrowRDE("Unsupported number of components: %u", frame.cps);
118     }
119   }
120 }
121 
decode(const Cr2Slicing & slicing_)122 void Cr2Decompressor::decode(const Cr2Slicing& slicing_) {
123   slicing = slicing_;
124   for (auto sliceId = 0; sliceId < slicing.numSlices; sliceId++) {
125     const auto sliceWidth = slicing.widthOfSlice(sliceId);
126     if (sliceWidth <= 0)
127       ThrowRDE("Bad slice width: %i", sliceWidth);
128   }
129 
130   AbstractLJpegDecompressor::decode();
131 }
132 
133 // N_COMP == number of components (2, 3 or 4)
134 // X_S_F  == x/horizontal sampling factor (1 or 2)
135 // Y_S_F  == y/vertical   sampling factor (1 or 2)
136 
137 template <int N_COMP, int X_S_F, int Y_S_F>
decodeN_X_Y()138 void Cr2Decompressor::decodeN_X_Y()
139 {
140   // To understand the CR2 slice handling and sampling factor behavior, see
141   // https://github.com/lclevy/libcraw2/blob/master/docs/cr2_lossless.pdf?raw=true
142 
143   // inner loop decodes one group of pixels at a time
144   //  * for <N,1,1>: N  = N*1*1 (full raw)
145   //  * for <3,2,1>: 6  = 3*2*1
146   //  * for <3,2,2>: 12 = 3*2*2
147   // and advances x by N_COMP*X_S_F and y by Y_S_F
148   constexpr int sliceColStep = N_COMP * X_S_F;
149   constexpr int frameRowStep = Y_S_F;
150 
151   auto ht = getHuffmanTables<N_COMP>();
152   auto pred = getInitialPredictors<N_COMP>();
153   auto* predNext = reinterpret_cast<uint16_t*>(mRaw->getDataUncropped(0, 0));
154 
155   BitPumpJPEG bs(input);
156 
157   if (frame.cps != 3 && frame.w * frame.cps > 2 * frame.h) {
158     // Fix Canon double height issue where Canon doubled the width and halfed
159     // the height (e.g. with 5Ds), ask Canon. frame.w needs to stay as is here
160     // because the number of pixels after which the predictor gets updated is
161     // still the doubled width.
162     // see: FIX_CANON_HALF_HEIGHT_DOUBLE_WIDTH
163     frame.h *= 2;
164   }
165 
166   if (X_S_F == 2 && Y_S_F == 1)
167   {
168     // fix the inconsistent slice width in sRaw mode, ask Canon.
169     for (auto* width : {&slicing.sliceWidth, &slicing.lastSliceWidth})
170       *width = (*width) * 3 / 2;
171   }
172 
173   for (const auto& width : {slicing.sliceWidth, slicing.lastSliceWidth}) {
174     if (width > mRaw->dim.x)
175       ThrowRDE("Slice is longer than image's height, which is unsupported.");
176     if (width % sliceColStep != 0) {
177       ThrowRDE("Slice width (%u) should be multiple of pixel group size (%u)",
178                width, sliceColStep);
179     }
180     if (width % mRaw->getCpp() != 0) {
181       ThrowRDE("Slice width (%u) should be multiple of image cpp (%u)", width,
182                mRaw->getCpp());
183     }
184   }
185 
186   if (iPoint2D::area_type(frame.h) * slicing.totalWidth() <
187       mRaw->getCpp() * mRaw->dim.area())
188     ThrowRDE("Incorrrect slice height / slice widths! Less than image size.");
189 
190   const Array2DRef<uint16_t> out(mRaw->getU16DataAsUncroppedArray2DRef());
191   unsigned globalFrameCol = 0;
192   unsigned globalFrameRow = 0;
193   for (auto sliceId = 0; sliceId < slicing.numSlices; sliceId++) {
194     const unsigned sliceWidth = slicing.widthOfSlice(sliceId);
195 
196     assert(frame.h % frameRowStep == 0);
197     for (unsigned sliceFrameRow = 0; sliceFrameRow < frame.h;
198          sliceFrameRow += frameRowStep, globalFrameRow += frameRowStep) {
199       unsigned row = globalFrameRow % mRaw->dim.y;
200       unsigned col = globalFrameRow / mRaw->dim.y * slicing.widthOfSlice(0) /
201                      mRaw->getCpp();
202       if (col >= static_cast<unsigned>(mRaw->dim.x))
203         break;
204 
205       assert(sliceWidth % mRaw->getCpp() == 0);
206       unsigned pixelsPerSliceRow = sliceWidth / mRaw->getCpp();
207       if (col + pixelsPerSliceRow > static_cast<unsigned>(mRaw->dim.x))
208         ThrowRDE("Bad slice width / frame size / image size combination.");
209       if (((sliceId + 1) == slicing.numSlices) &&
210           (col + pixelsPerSliceRow != static_cast<unsigned>(mRaw->dim.x)))
211         ThrowRDE("Insufficient slices - do not fill the entire image");
212 
213       col *= mRaw->getCpp();
214       assert(sliceWidth % sliceColStep == 0);
215       for (unsigned sliceCol = 0; sliceCol < sliceWidth;) {
216         // check if we processed one full raw row worth of pixels
217         if (globalFrameCol == frame.w) {
218           // if yes -> update predictor by going back exactly one row,
219           // no matter where we are right now.
220           // makes no sense from an image compression point of view, ask Canon.
221           copy_n(predNext, N_COMP, pred.data());
222           predNext = &out(row, col);
223           globalFrameCol = 0;
224         }
225 
226         // How many pixel can we decode until we finish the row of either
227         // the frame (i.e. predictor change time), or of the current slice?
228         assert(frame.w % X_S_F == 0);
229         unsigned sliceColsRemainingInThisFrameRow =
230             sliceColStep * ((frame.w - globalFrameCol) / X_S_F);
231         unsigned sliceColsRemainingInThisSliceRow = sliceWidth - sliceCol;
232         unsigned sliceColsRemaining = std::min(
233             sliceColsRemainingInThisSliceRow, sliceColsRemainingInThisFrameRow);
234         assert(sliceColsRemaining >= sliceColStep &&
235                (sliceColsRemaining % sliceColStep) == 0);
236         for (unsigned sliceColEnd = sliceCol + sliceColsRemaining;
237              sliceCol < sliceColEnd; sliceCol += sliceColStep,
238                       globalFrameCol += X_S_F, col += sliceColStep) {
239           if (X_S_F == 1) { // will be optimized out
240             for (int c = 0; c < sliceColStep; ++c)
241               out(row, col + c) = pred[c] += ht[c]->decodeDifference(bs);
242           } else {
243             for (int dstRow = 0; dstRow < Y_S_F; ++dstRow) {
244               for (int c : {0, 3})
245                 out(row + dstRow, col + c) = pred[0] +=
246                     ht[0]->decodeDifference(bs);
247             }
248 
249             for (int c : {1, 2})
250               out(row, col + c) = pred[c] += ht[c]->decodeDifference(bs);
251           }
252         }
253       }
254     }
255   }
256 }
257 
258 } // namespace rawspeed
259