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 namespace rawspeed {
35 
36 class ByteStream;
37 
Cr2Decompressor(const ByteStream & bs,const RawImage & img)38 Cr2Decompressor::Cr2Decompressor(const ByteStream& bs, const RawImage& img)
39     : AbstractLJpegDecompressor(bs, img) {
40   if (mRaw->getDataType() != TYPE_USHORT16)
41     ThrowRDE("Unexpected data type");
42 
43   if (!((mRaw->getCpp() == 1 && mRaw->getBpp() == sizeof(uint16_t))))
44     ThrowRDE("Unexpected cpp: %u", mRaw->getCpp());
45 
46   if (!mRaw->dim.x || !mRaw->dim.y || mRaw->dim.x > 19440 ||
47       mRaw->dim.y > 5920) {
48     ThrowRDE("Unexpected image dimensions found: (%u; %u)", mRaw->dim.x,
49              mRaw->dim.y);
50   }
51 }
52 
decodeScan()53 void Cr2Decompressor::decodeScan()
54 {
55   if (predictorMode != 1)
56     ThrowRDE("Unsupported predictor mode.");
57 
58   if (slicing.empty()) {
59     const int slicesWidth = frame.w * frame.cps;
60     if (slicesWidth > mRaw->dim.x)
61       ThrowRDE("Don't know slicing pattern, and failed to guess it.");
62 
63     slicing = Cr2Slicing(/*numSlices=*/1, /*sliceWidth=don't care*/ 0,
64                          /*lastSliceWidth=*/slicesWidth);
65   }
66 
67   bool isSubSampled = false;
68   for (uint32_t i = 0; i < frame.cps; i++)
69     isSubSampled = isSubSampled || frame.compInfo[i].superH != 1 ||
70                    frame.compInfo[i].superV != 1;
71 
72   if (isSubSampled) {
73     if (mRaw->isCFA)
74       ThrowRDE("Cannot decode subsampled image to CFA data");
75 
76     if (frame.cps != 3)
77       ThrowRDE("Unsupported number of subsampled components: %u", frame.cps);
78 
79     // see http://lclevy.free.fr/cr2/#sraw for overview table
80     bool isSupported = frame.compInfo[0].superH == 2;
81 
82     isSupported = isSupported && (frame.compInfo[0].superV == 1 ||
83                                   frame.compInfo[0].superV == 2);
84 
85     for (uint32_t i = 1; i < frame.cps; i++)
86       isSupported = isSupported && frame.compInfo[i].superH == 1 &&
87                     frame.compInfo[i].superV == 1;
88 
89     if (!isSupported) {
90       ThrowRDE("Unsupported subsampling ([[%u, %u], [%u, %u], [%u, %u]])",
91                frame.compInfo[0].superH, frame.compInfo[0].superV,
92                frame.compInfo[1].superH, frame.compInfo[1].superV,
93                frame.compInfo[2].superH, frame.compInfo[2].superV);
94     }
95 
96     if (frame.compInfo[0].superV == 2)
97       decodeN_X_Y<3, 2, 2>(); // Cr2 sRaw1/mRaw
98     else {
99       assert(frame.compInfo[0].superV == 1);
100       decodeN_X_Y<3, 2, 1>(); // Cr2 sRaw2/sRaw
101     }
102   } else {
103     switch (frame.cps) {
104     case 2:
105       decodeN_X_Y<2, 1, 1>();
106       break;
107     case 4:
108       decodeN_X_Y<4, 1, 1>();
109       break;
110     default:
111       ThrowRDE("Unsupported number of components: %u", frame.cps);
112     }
113   }
114 }
115 
decode(const Cr2Slicing & slicing_)116 void Cr2Decompressor::decode(const Cr2Slicing& slicing_) {
117   slicing = slicing_;
118   for (auto sliceId = 0; sliceId < slicing.numSlices; sliceId++) {
119     const auto sliceWidth = slicing.widthOfSlice(sliceId);
120     if (sliceWidth <= 0)
121       ThrowRDE("Bad slice width: %i", sliceWidth);
122   }
123 
124   AbstractLJpegDecompressor::decode();
125 }
126 
127 // N_COMP == number of components (2, 3 or 4)
128 // X_S_F  == x/horizontal sampling factor (1 or 2)
129 // Y_S_F  == y/vertical   sampling factor (1 or 2)
130 
131 template <int N_COMP, int X_S_F, int Y_S_F>
decodeN_X_Y()132 void Cr2Decompressor::decodeN_X_Y()
133 {
134   const Array2DRef<uint16_t> out(mRaw->getU16DataAsUncroppedArray2DRef());
135 
136   // To understand the CR2 slice handling and sampling factor behavior, see
137   // https://github.com/lclevy/libcraw2/blob/master/docs/cr2_lossless.pdf?raw=true
138 
139   constexpr bool subSampled = X_S_F != 1 || Y_S_F != 1;
140 
141   // inner loop decodes one group of pixels at a time
142   //  * for <N,1,1>: N  = N*1*1 (full raw)
143   //  * for <3,2,1>: 6  = 3*2*1
144   //  * for <3,2,2>: 12 = 3*2*2
145   // and advances x by N_COMP*X_S_F and y by Y_S_F
146   constexpr int sliceColStep = N_COMP * X_S_F;
147   constexpr int frameRowStep = Y_S_F;
148   constexpr int pixelsPerGroup = X_S_F * Y_S_F;
149   constexpr int groupSize = !subSampled ? N_COMP : 2 + pixelsPerGroup;
150   const int cpp = !subSampled ? 1 : 3;
151   const int colsPerGroup = !subSampled ? cpp : groupSize;
152 
153   iPoint2D realDim = mRaw->dim;
154   if (subSampled) {
155     assert(realDim.x % groupSize == 0);
156     realDim.x /= groupSize;
157   }
158   realDim.x *= X_S_F;
159   realDim.y *= Y_S_F;
160 
161   auto ht = getHuffmanTables<N_COMP>();
162   auto pred = getInitialPredictors<N_COMP>();
163   auto* predNext = &out(0, 0);
164 
165   BitPumpJPEG bs(input);
166 
167   if (frame.cps != 3 && frame.w * frame.cps > 2 * frame.h) {
168     // Fix Canon double height issue where Canon doubled the width and halfed
169     // the height (e.g. with 5Ds), ask Canon. frame.w needs to stay as is here
170     // because the number of pixels after which the predictor gets updated is
171     // still the doubled width.
172     // see: FIX_CANON_HALF_HEIGHT_DOUBLE_WIDTH
173     frame.h *= 2;
174   }
175 
176   if (X_S_F == 2 && Y_S_F == 1)
177   {
178     // fix the inconsistent slice width in sRaw mode, ask Canon.
179     for (auto* width : {&slicing.sliceWidth, &slicing.lastSliceWidth})
180       *width = (*width) * 3 / 2;
181   }
182 
183   for (const auto& width : {slicing.sliceWidth, slicing.lastSliceWidth}) {
184     if (width > realDim.x)
185       ThrowRDE("Slice is longer than image's height, which is unsupported.");
186     if (width % sliceColStep != 0) {
187       ThrowRDE("Slice width (%u) should be multiple of pixel group size (%u)",
188                width, sliceColStep);
189     }
190     if (width % cpp != 0) {
191       ThrowRDE("Slice width (%u) should be multiple of image cpp (%u)", width,
192                cpp);
193     }
194   }
195 
196   if (iPoint2D::area_type(frame.h) * slicing.totalWidth() <
197       cpp * realDim.area())
198     ThrowRDE("Incorrrect slice height / slice widths! Less than image size.");
199 
200   unsigned globalFrameCol = 0;
201   unsigned globalFrameRow = 0;
202   for (auto sliceId = 0; sliceId < slicing.numSlices; sliceId++) {
203     const unsigned sliceWidth = slicing.widthOfSlice(sliceId);
204 
205     assert(frame.h % frameRowStep == 0);
206     for (unsigned sliceFrameRow = 0; sliceFrameRow < frame.h;
207          sliceFrameRow += frameRowStep, globalFrameRow += frameRowStep) {
208       unsigned row = globalFrameRow % realDim.y;
209       unsigned col = globalFrameRow / realDim.y * slicing.widthOfSlice(0) / cpp;
210       if (col >= static_cast<unsigned>(realDim.x))
211         break;
212 
213       assert(sliceWidth % cpp == 0);
214       unsigned pixelsPerSliceRow = sliceWidth / cpp;
215       if (col + pixelsPerSliceRow > static_cast<unsigned>(realDim.x))
216         ThrowRDE("Bad slice width / frame size / image size combination.");
217       if (((sliceId + 1) == slicing.numSlices) &&
218           (col + pixelsPerSliceRow != static_cast<unsigned>(realDim.x)))
219         ThrowRDE("Insufficient slices - do not fill the entire image");
220 
221       row /= Y_S_F;
222 
223       assert(col % X_S_F == 0);
224       col /= X_S_F;
225       col *= colsPerGroup;
226       assert(sliceWidth % sliceColStep == 0);
227       for (unsigned sliceCol = 0; sliceCol < sliceWidth;) {
228         // check if we processed one full raw row worth of pixels
229         if (globalFrameCol == frame.w) {
230           // if yes -> update predictor by going back exactly one row,
231           // no matter where we are right now.
232           // makes no sense from an image compression point of view, ask Canon.
233           for (int c = 0; c < N_COMP; ++c)
234             pred[c] = predNext[c == 0 ? c : groupSize - (N_COMP - c)];
235           predNext = &out(row, col);
236           globalFrameCol = 0;
237         }
238 
239         // How many pixel can we decode until we finish the row of either
240         // the frame (i.e. predictor change time), or of the current slice?
241         assert(frame.w % X_S_F == 0);
242         unsigned sliceColsRemainingInThisFrameRow =
243             sliceColStep * ((frame.w - globalFrameCol) / X_S_F);
244         unsigned sliceColsRemainingInThisSliceRow = sliceWidth - sliceCol;
245         unsigned sliceColsRemaining = std::min(
246             sliceColsRemainingInThisSliceRow, sliceColsRemainingInThisFrameRow);
247         assert(sliceColsRemaining >= sliceColStep &&
248                (sliceColsRemaining % sliceColStep) == 0);
249         for (unsigned sliceColEnd = sliceCol + sliceColsRemaining;
250              sliceCol < sliceColEnd; sliceCol += sliceColStep,
251                       globalFrameCol += X_S_F, col += groupSize) {
252           for (int p = 0; p < groupSize; ++p) {
253             int c = p < pixelsPerGroup ? 0 : p - pixelsPerGroup + 1;
254             out(row, col + p) = pred[c] += ht[c]->decodeDifference(bs);
255           }
256         }
257       }
258     }
259   }
260 }
261 
262 } // namespace rawspeed
263