/* RawSpeed - RAW file decoder. Copyright (C) 2009-2014 Klaus Post Copyright (C) 2017 Axel Waggershauser This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include "common/Common.h" // for uint32, ushort16 #include "common/RawImage.h" // for RawImage #include "decoders/RawDecoderException.h" // for ThrowRDE #include "decompressors/AbstractDecompressor.h" // for AbstractDecompressor #include "decompressors/HuffmanTable.h" // for HuffmanTable #include "io/ByteStream.h" // for ByteStream #include // for array #include // for unique_ptr #include // for vector /* * The following enum and two structs are stolen from the IJG JPEG library * Comments added by tm. See also Copyright in HuffmanTable.h. */ namespace rawspeed { enum JpegMarker { /* JPEG marker codes */ M_STUFF = 0x00, M_SOF0 = 0xc0, /* baseline DCT */ M_SOF1 = 0xc1, /* extended sequential DCT */ M_SOF2 = 0xc2, /* progressive DCT */ M_SOF3 = 0xc3, /* lossless (sequential) */ M_SOF5 = 0xc5, /* differential sequential DCT */ M_SOF6 = 0xc6, /* differential progressive DCT */ M_SOF7 = 0xc7, /* differential lossless */ M_JPG = 0xc8, /* JPEG extensions */ M_SOF9 = 0xc9, /* extended sequential DCT */ M_SOF10 = 0xca, /* progressive DCT */ M_SOF11 = 0xcb, /* lossless (sequential) */ M_SOF13 = 0xcd, /* differential sequential DCT */ M_SOF14 = 0xce, /* differential progressive DCT */ M_SOF15 = 0xcf, /* differential lossless */ M_DHT = 0xc4, /* define Huffman tables */ M_DAC = 0xcc, /* define arithmetic conditioning table */ M_RST0 = 0xd0, /* restart */ M_RST1 = 0xd1, /* restart */ M_RST2 = 0xd2, /* restart */ M_RST3 = 0xd3, /* restart */ M_RST4 = 0xd4, /* restart */ M_RST5 = 0xd5, /* restart */ M_RST6 = 0xd6, /* restart */ M_RST7 = 0xd7, /* restart */ M_SOI = 0xd8, /* start of image */ M_EOI = 0xd9, /* end of image */ M_SOS = 0xda, /* start of scan */ M_DQT = 0xdb, /* define quantization tables */ M_DNL = 0xdc, /* define number of lines */ M_DRI = 0xdd, /* define restart interval */ M_DHP = 0xde, /* define hierarchical progression */ M_EXP = 0xdf, /* expand reference image(s) */ M_APP0 = 0xe0, /* application marker, used for JFIF */ M_APP1 = 0xe1, /* application marker */ M_APP2 = 0xe2, /* application marker */ M_APP3 = 0xe3, /* application marker */ M_APP4 = 0xe4, /* application marker */ M_APP5 = 0xe5, /* application marker */ M_APP6 = 0xe6, /* application marker */ M_APP7 = 0xe7, /* application marker */ M_APP8 = 0xe8, /* application marker */ M_APP9 = 0xe9, /* application marker */ M_APP10 = 0xea, /* application marker */ M_APP11 = 0xeb, /* application marker */ M_APP12 = 0xec, /* application marker */ M_APP13 = 0xed, /* application marker */ M_APP14 = 0xee, /* application marker, used by Adobe */ M_APP15 = 0xef, /* application marker */ M_JPG0 = 0xf0, /* reserved for JPEG extensions */ M_JPG13 = 0xfd, /* reserved for JPEG extensions */ M_COM = 0xfe, /* comment */ M_TEM = 0x01, /* temporary use */ M_FILL = 0xFF }; /* * The following structure stores basic information about one component. */ struct JpegComponentInfo { /* * These values are fixed over the whole image. * They are read from the SOF marker. */ uint32 componentId = ~0U; /* identifier for this component (0..255) */ /* * Huffman table selector (0..3). The value may vary * between scans. It is read from the SOS marker. */ uint32 dcTblNo = ~0U; uint32 superH = ~0U; // Horizontal Supersampling uint32 superV = ~0U; // Vertical Supersampling }; class SOFInfo { public: std::array compInfo; uint32 w = 0; // Width uint32 h = 0; // Height uint32 cps = 0; // Components uint32 prec = 0; // Precision bool initialized = false; }; class AbstractLJpegDecompressor : public AbstractDecompressor { // std::vector of unique HTs, to not recreate HT, but cache them std::vector> huffmanTableStore; HuffmanTable ht_; // temporary table, used uint32 Pt = 0; std::array huff{{}}; // 4 pointers into the store public: AbstractLJpegDecompressor(ByteStream bs, const RawImage& img); virtual ~AbstractLJpegDecompressor() = default; protected: bool fixDng16Bug = false; // DNG v1.0.x compatibility bool fullDecodeHT = true; // FullDecode Huffman void decode(); void parseSOF(ByteStream data, SOFInfo* i); void parseSOS(ByteStream data); void parseDHT(ByteStream data); JpegMarker getNextMarker(bool allowskip); template std::array getHuffmanTables() const { std::array ht; for (int i = 0; i < N_COMP; ++i) { const unsigned dcTblNo = frame.compInfo[i].dcTblNo; const unsigned dcTbls = huff.size(); if (dcTblNo >= dcTbls) { ThrowRDE("Decoding table %u for comp %i does not exist (tables = %u)", dcTblNo, i, dcTbls); } ht[i] = huff[dcTblNo]; } return ht; } template __attribute__((pure)) std::array getInitialPredictors() const { std::array pred; if (frame.prec < (Pt + 1)) { ThrowRDE("Invalid precision (%u) and point transform (%u) combination!", frame.prec, Pt); } pred.fill(1 << (frame.prec - Pt - 1)); return pred; } virtual void decodeScan() = 0; ByteStream input; RawImage mRaw; SOFInfo frame; uint32 predictorMode = 0; }; } // namespace rawspeed