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