1 /*
2     RawSpeed - RAW file decoder.
3 
4     Copyright (C) 2009-2014 Klaus Post
5     Copyright (C) 2017 Axel Waggershauser
6 
7     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Lesser General Public
9     License as published by the Free Software Foundation; either
10     version 2 of the License, or (at your option) any later version.
11 
12     This library is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15     Lesser General Public License for more details.
16 
17     You should have received a copy of the GNU Lesser General Public
18     License along with this library; if not, write to the Free Software
19     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21 
22 #pragma once
23 
24 #include "common/RawImage.h"                    // for RawImage
25 #include "decoders/RawDecoderException.h"       // for ThrowRDE
26 #include "decompressors/AbstractDecompressor.h" // for AbstractDecompressor
27 #include "decompressors/HuffmanTable.h"         // for HuffmanTable
28 #include "io/ByteStream.h"                      // for ByteStream
29 #include <array>                                // for array
30 #include <cstdint>                              // for uint32_t, uint16_t
31 #include <memory>                               // for unique_ptr
32 #include <vector>                               // for vector
33 
34 /*
35  * The following enum and two structs are stolen from the IJG JPEG library
36  * Comments added by tm. See also Copyright in HuffmanTable.h.
37  */
38 
39 namespace rawspeed {
40 
41 enum class JpegMarker { /* JPEG marker codes			*/
42                         STUFF = 0x00,
43                         SOF0 = 0xc0, /* baseline DCT */
44                         SOF1 = 0xc1, /* extended sequential DCT		*/
45                         SOF2 = 0xc2, /* progressive DCT			*/
46                         SOF3 = 0xc3, /* lossless (sequential)		*/
47 
48                         SOF5 = 0xc5, /* differential sequential DCT
49                                       */
50                         SOF6 = 0xc6, /* differential progressive DCT
51                                       */
52                         SOF7 = 0xc7, /* differential lossless		*/
53 
54                         JPG = 0xc8,   /* JPEG extensions			*/
55                         SOF9 = 0xc9,  /* extended sequential DCT		*/
56                         SOF10 = 0xca, /* progressive DCT */
57                         SOF11 = 0xcb, /* lossless (sequential)		*/
58 
59                         SOF13 = 0xcd, /* differential sequential DCT
60                                        */
61                         SOF14 = 0xce, /* differential progressive DCT
62                                        */
63                         SOF15 = 0xcf, /* differential lossless		*/
64 
65                         DHT = 0xc4, /* define Huffman tables		*/
66 
67                         DAC = 0xcc, /* define arithmetic conditioning table
68                                      */
69 
70                         RST0 = 0xd0, /* restart				*/
71                         RST1 = 0xd1, /* restart				*/
72                         RST2 = 0xd2, /* restart				*/
73                         RST3 = 0xd3, /* restart				*/
74                         RST4 = 0xd4, /* restart				*/
75                         RST5 = 0xd5, /* restart				*/
76                         RST6 = 0xd6, /* restart				*/
77                         RST7 = 0xd7, /* restart				*/
78 
79                         SOI = 0xd8, /* start of image			*/
80                         EOI = 0xd9, /* end of image */
81                         SOS = 0xda, /* start of scan			*/
82                         DQT =
83                             0xdb,   /* define quantization tables		*/
84                         DNL = 0xdc, /* define number of lines		*/
85                         DRI = 0xdd, /* define restart interval		*/
86                         DHP = 0xde, /* define hierarchical progression	*/
87                         EXP =
88                             0xdf, /* expand reference image(s)		*/
89 
90                         APP0 =
91                             0xe0,     /* application marker, used for JFIF	*/
92                         APP1 = 0xe1,  /* application marker  */
93                         APP2 = 0xe2,  /* application marker  */
94                         APP3 = 0xe3,  /* application marker  */
95                         APP4 = 0xe4,  /* application marker  */
96                         APP5 = 0xe5,  /* application marker  */
97                         APP6 = 0xe6,  /* application marker  */
98                         APP7 = 0xe7,  /* application marker  */
99                         APP8 = 0xe8,  /* application marker  */
100                         APP9 = 0xe9,  /* application marker  */
101                         APP10 = 0xea, /* application marker */
102                         APP11 = 0xeb, /* application marker */
103                         APP12 = 0xec, /* application marker */
104                         APP13 = 0xed, /* application marker */
105                         APP14 =
106                             0xee,     /* application marker, used by Adobe	*/
107                         APP15 = 0xef, /* application marker */
108 
109                         JPG0 = 0xf0,  /* reserved for JPEG extensions
110                                        */
111                         JPG13 = 0xfd, /* reserved for JPEG extensions
112                                        */
113                         COM = 0xfe,   /* comment				*/
114 
115                         TEM = 0x01, /* temporary use			*/
116                         FILL = 0xFF
117 
118 };
119 
120 /*
121 * The following structure stores basic information about one component.
122 */
123 struct JpegComponentInfo {
124   /*
125   * These values are fixed over the whole image.
126   * They are read from the SOF marker.
127   */
128   uint32_t componentId = ~0U; /* identifier for this component (0..255) */
129 
130   /*
131   * Huffman table selector (0..3). The value may vary
132   * between scans. It is read from the SOS marker.
133   */
134   uint32_t dcTblNo = ~0U;
135   uint32_t superH = ~0U; // Horizontal Supersampling
136   uint32_t superV = ~0U; // Vertical Supersampling
137 };
138 
139 class SOFInfo {
140 public:
141   std::array<JpegComponentInfo, 4> compInfo;
142   uint32_t w = 0;    // Width
143   uint32_t h = 0;    // Height
144   uint32_t cps = 0;  // Components
145   uint32_t prec = 0; // Precision
146   bool initialized = false;
147 };
148 
149 class AbstractLJpegDecompressor : public AbstractDecompressor {
150   // std::vector of unique HTs, to not recreate HT, but cache them
151   std::vector<std::unique_ptr<HuffmanTable>> huffmanTableStore;
152   HuffmanTable ht_;      // temporary table, used
153 
154   uint32_t Pt = 0;
155   std::array<HuffmanTable*, 4> huff{{}}; // 4 pointers into the store
156 
157 public:
158   AbstractLJpegDecompressor(ByteStream bs, const RawImage& img);
159 
160   virtual ~AbstractLJpegDecompressor() = default;
161 
162 protected:
163   bool fixDng16Bug = false;  // DNG v1.0.x compatibility
164   bool fullDecodeHT = true;  // FullDecode Huffman
165 
166   void decode();
167   void parseSOF(ByteStream data, SOFInfo* i);
168   void parseSOS(ByteStream data);
169   void parseDHT(ByteStream data);
170   JpegMarker getNextMarker(bool allowskip);
171 
172   template <int N_COMP>
173   [[nodiscard]] [[nodiscard]] [[nodiscard]] std::array<HuffmanTable*, N_COMP>
getHuffmanTables()174   getHuffmanTables() const {
175     std::array<HuffmanTable*, N_COMP> ht;
176     for (int i = 0; i < N_COMP; ++i) {
177       const unsigned dcTblNo = frame.compInfo[i].dcTblNo;
178       if (const unsigned dcTbls = huff.size(); dcTblNo >= dcTbls) {
179         ThrowRDE("Decoding table %u for comp %i does not exist (tables = %u)",
180                  dcTblNo, i, dcTbls);
181       }
182       ht[i] = huff[dcTblNo];
183     }
184 
185     return ht;
186   }
187 
188   template <int N_COMP>
189   [[nodiscard]] [[nodiscard]] [[nodiscard]] __attribute__((pure))
190   std::array<uint16_t, N_COMP>
getInitialPredictors()191   getInitialPredictors() const {
192     std::array<uint16_t, N_COMP> pred;
193     if (frame.prec < (Pt + 1)) {
194       ThrowRDE("Invalid precision (%u) and point transform (%u) combination!",
195                frame.prec, Pt);
196     }
197     pred.fill(1 << (frame.prec - Pt - 1));
198     return pred;
199   }
200 
201   virtual void decodeScan() = 0;
202 
203   ByteStream input;
204   RawImage mRaw;
205 
206   SOFInfo frame;
207   uint32_t predictorMode = 0;
208 };
209 
210 } // namespace rawspeed
211