1 // Copyright 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 //  Fast & simple JPEG encoder.
16 //
17 // Author: Skal (pascal.massimino@gmail.com)
18 
19 #ifndef SJPEG_JPEG_H_
20 #define SJPEG_JPEG_H_
21 
22 #include <inttypes.h>
23 #include <memory>
24 #include <string>
25 #include <vector>
26 
27 #define SJPEG_VERSION 0x000100   // 0.1.0
28 
29 #if defined(__cplusplus) || defined(c_plusplus)
30 extern "C" {
31 #endif
32 
33 // Returns the library's version.
34 uint32_t SjpegVersion();
35 
36 // Main function
37 //  This is the simplest possible call. There is only one parameter (quality)
38 //  and most decisions will be made automatically (YUV420/YUV444/etc...).
39 //  Returns the compressed size, and fills *out_data with the bitstream.
40 //  This returned buffer is allocated with 'new[]' operator. It must be
41 //  deallocated by using 'delete[]' or SjpegFreeBuffer() calls.
42 //  Input data 'rgb' are the samples in sRGB format, in R/G/B memory order.
43 //  Picture dimension is width x height.
44 //  Returns 0 in case of error.
45 size_t SjpegCompress(const uint8_t* rgb, int width, int height, float quality,
46                      uint8_t** out_data);
47 
48 // Parameter 'yuv_mode': decides which colorspace to use. Possible values:
49 //   * YUV_AUTO  (0): automated decision between YUV 4:2:0 / sharp / 4:4:4
50 //   * YUV_420   (1): YUV 4:2:0
51 //   * YUV_SHARP (2): YUV 4:2:0 with 'sharp' conversion
52 //   * YUV_444   (3): YUV 4:4:4
53 typedef enum {
54   SJPEG_YUV_AUTO = 0,
55   SJPEG_YUV_420,
56   SJPEG_YUV_SHARP,
57   SJPEG_YUV_444
58 } SjpegYUVMode;
59 
60 // Encodes an RGB picture to JPEG.
61 //
62 //  the dimension of the picture pointed to by 'rgb', is W * H, with stride
63 //  'stride' (must be greater or equal to 3*W). The dimensions must be strictly
64 //  positive.
65 //
66 // The compressed bytes are made available in *out_data, which is a buffer
67 // allocated with new []. This buffer must be disallocated using 'delete []',
68 // or by calling SjpegFreeBuffer().
69 //
70 // Return parameter -if positive- is the size of the JPEG string,
71 // or 0 if an error occurred.
72 //
73 // Parameter 'quality' correspond to the usual quality factor in JPEG:
74 //     0=very bad, 100=very good.
75 // Parameter 'compression_method' refer to the efforts and resources spent
76 //  trying to compress better. Default (fastest) method should be 0. Method 1
77 //  will optimize the size at the expense of using more RAM. Method 2 does
78 //  the same as method #1, but but without any additional RAM (but using twice
79 //  more CPU). Methods 3, 4, 5, and 6 behave like methods 0, 1, and 2, except
80 //  that the quantization matrices are fine-tuned to the source's content using
81 //  histogram. This requires an additional pass, and is hence slower, but can
82 //  give substantial filesize reduction, especially for hi-quality settings.
83 //  Method 5 will try to not use extra RAM to store the Fourier-transformed
84 //  coefficients, at the expense of being ~15% slower, but will still use some
85 //  memory for the Huffman size-optimization. Eventually, method 6 will use
86 //  a minimal amount of RAM, but will be must slower.
87 //  To recap:
88 //     method                     | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
89 //     ---------------------------+---+---+---+---+---+---+---+---+---|
90 //     Huffman size-optimization  |   | x | x |   | x | x | x | x | x |
91 //     Adaptive quantization      |   |   |   | x | x | x | x | x | x |
92 //     Extra RAM for Huffman pass |   | x |   |   | x | x |   | x |   |
93 //     Extra RAM for histogram    |   |   |   | x | x |   |   | x |   |
94 //     Trellis-based quantization |   |   |   |   |   |   |   | x | x |
95 //
96 //  Methods sorted by decreasing speed: 0 > 1 > 2 > 3 > 4 > 5 > 6
97 //  Sorted by increasing efficiency: 0 < [1|2] < 3 < [4|5|6]
98 //
99 //  If you don't have any strict requirements on CPU and memory, you should
100 //  probably use method #4.
101 //
102 size_t SjpegEncode(const uint8_t* rgb,
103                    int width, int height, int stride,
104                    uint8_t** out_data,
105                    float quality,
106                    int compression_method,
107                    SjpegYUVMode yuv_mode);
108 
109 // Deallocate a compressed bitstream that were returned by SjpegEncode(),
110 // SjpegCompress() or sjpeg::Encode(). Useful for non-C++ bindings.
111 void SjpegFreeBuffer(const uint8_t* buffer);
112 
113 ////////////////////////////////////////////////////////////////////////////////
114 // JPEG-parsing tools
115 
116 // Decode the dimensions of a JPEG bitstream, doing as few read operations as
117 // possible. Return false if an error occurred (invalid bitstream, invalid
118 // parameter...).
119 // The pointers 'width', 'height', 'is_yuv420' can be passed NULL.
120 bool SjpegDimensions(const uint8_t* data, size_t size,
121                      int* width, int* height, int* is_yuv420);
122 
123 // Finds the location of the first two quantization matrices within a JPEG
124 // 'data' bitstream. Matrices are 64 coefficients stored as uint8_t.
125 // The matrices are returned in natural order (not zigzag order).
126 // Note that the input can be truncated to include the headers only, but still
127 // must start as a valid JPEG with an 0xffd8 marker.
128 // Returns the number of matrices detected.
129 // Returns 0 in case of bitstream error, or if the DQT chunk is missing.
130 int SjpegFindQuantizer(const uint8_t* data, size_t size,
131                        uint8_t quant[2][64]);
132 
133 // Returns an estimation of the quality factor that would best approximate
134 // the quantization coefficients in matrix[].
135 // Note that matrix[] must be in natural order (not the zigzag order used
136 // in the byte stream). With this restriction, one can then pass the result
137 // of SjpegFindQuantizer() directly to SjpegEstimateQuality().
138 float SjpegEstimateQuality(const uint8_t matrix[64], bool for_chroma);
139 
140 // Generate a default quantization matrix for the given quality factor,
141 // in a libjpeg-6b fashion.
142 void SjpegQuantMatrix(float quality, bool for_chroma, uint8_t matrix[64]);
143 
144 // Returns the favored conversion mode to use (YUV420 / sharp-YUV420 / YUV444)
145 // Return values: SJPEG_YUV_420, SJPEG_YUV_SHARP or SJPEG_YUV_444
146 // If risk is not NULL, the riskiness score (between 0 and 100) is returned.
147 SjpegYUVMode SjpegRiskiness(const uint8_t* rgb, int width, int height,
148                             int stride, float* risk);
149 
150 #if defined(__cplusplus) || defined(c_plusplus)
151 }    // extern "C"
152 #endif
153 
154 ////////////////////////////////////////////////////////////////////////////////
155 // Variant of the function above, but using std::string as interface.
156 
157 bool SjpegCompress(const uint8_t* rgb,
158                    int width, int height, float quality, std::string* output);
159 
160 bool SjpegDimensions(const std::string& jpeg_data,
161                      int* width, int* height, int* is_yuv420);
162 
163 int SjpegFindQuantizer(const std::string& jpeg_data, uint8_t quant[2][64]);
164 
165 
166 ////////////////////////////////////////////////////////////////////////////////
167 // Advanced API, C++ only.
168 //    . Fine control over the encoding parameters using EncoderParam
169 //    . Interfaces to customize the codec
170 ////////////////////////////////////////////////////////////////////////////////
171 
172 namespace sjpeg {
173 
174 // Forward declaration of internal struct:
175 struct Encoder;
176 
177 // interfaces to customize the codec:
178 struct SearchHook;
179 struct ByteSink;
180 struct MemoryManager;
181 
182 // Structure for holding encoding parameter, to be passed to the unique
183 // call to SjpegEncode() below. For a more detailed description of some fields,
184 // see SjpegEncode()'s doc above.
185 struct EncoderParam {
186   EncoderParam();
187   explicit EncoderParam(float quality_factor);
188 
189   // Sets the compression factor. 0 = lowest quality, 100 = best quality.
190   // The call will actually initialize quant[][].
191   void SetQuality(float quality_factor);
192 
193   // Reduce the output size by a factor 'reduction' in [0, 100]:
194   //  reduction ~= 100 -> small size reduction
195   //  reduction ~=   1 -> large size reduction
196   // Note: 'reduction' can be larger than 100.
197   // This function is incompatible with SetQuality()
198   void SetQuantization(const uint8_t m[2][64], float reduction = 100.f);
GetQuantMatrixEncoderParam199   const uint8_t* GetQuantMatrix(int idx) const { return quant_[idx]; }
200 
201   // Limit the quantization by setting up some minimal quantization matrices
202   // based on the current content of quant_[][] matrices.
203   // Hence, this function must be called after SetQuality() or SetQuantMatrix().
204   void SetLimitQuantization(bool limit_quantization = true, int tolerance = 0);
205 
206   // Set the minimal quantization matrices directly, irrespective of the value
207   // of quant_[][].
208   void SetMinQuantization(const uint8_t m[2][64], int min_quant_tolerance = 0);
209 
210   // main compression parameters
211   SjpegYUVMode yuv_mode;        // YUV-420...444 decisions
212   bool Huffman_compress;        // if true, use optimized Huffman tables.
213   bool adaptive_quantization;   // if true, use optimized quantizer matrices.
214   bool adaptive_bias;           // if true, use perceptual bias adaptation
215   bool use_trellis;             // if true, use trellis-based optimization
216 
217   // target size or distortion
218   typedef enum {
219     TARGET_NONE = 0,
220     TARGET_SIZE = 1,
221     TARGET_PSNR = 2,
222   } TargetMode;
223   TargetMode target_mode;
224   float target_value;           // size, psnr or SSIM
225   int passes;                   // max number of passes to try and converge
226   float tolerance;              // percentage of distance-to-target allowed
227   float qmin, qmax;             // Limits for the search quality values.
228                                 // If set, min_quant_[] matrices will take
229                                 // precedence and limit qmax further.
230 
231   // fine-grained control over compression parameters
232   int quantization_bias;    // [0..255] Rounding bias for quantization.
233   int qdelta_max_luma;      // [0..12] How much to hurt luma in adaptive quant
234   int qdelta_max_chroma;    // [0..12] How much to hurt chroma in adaptive quant
235                             // A higher value might be useful for images
236                             // encoded without chroma subsampling.
237 
238   // if null, a default implementation will be used
239   sjpeg::SearchHook* search_hook;
240 
241   // metadata: extra EXIF/XMP/ICCP data that will be embedded in
242   // APP1 or APP2 markers. They should contain only the raw payload and not
243   // the prefixes ("Exif\0", "ICC_PROFILE", etc...). These will be added
244   // automatically during encoding.
245   // Conversely, the content of app_markers is written as is, right after APP0.
246   std::string exif;
247   std::string xmp;
248   std::string iccp;
249   std::string app_markers;
250   void ResetMetadata();      // clears the above
251 
252   // Memory manager used by the codec. If null, default one will be used.
253   sjpeg::MemoryManager* memory;
254 
255  protected:
256   uint8_t quant_[2][64];         // quantization matrices to use
257   uint8_t min_quant_[2][64];     // If limit_quantization is true, these
258                                  // pointers should direct to the minimum
259                                  // quantizer values allowed for luma / chroma.
260   bool use_min_quant_;           // True if min_quant_[][] has been set.
261   int min_quant_tolerance_;      // Tolerance going over min_quant_ ([0..100])
262 
263  protected:
264   void Init(float quality_factor);
265   friend struct sjpeg::Encoder;
266 };
267 
268 // Same as the first version of SjpegEncode(), except encoding parameters are
269 // passed in a EncoderParam. Upon failure (memory allocation or
270 // invalid parameter), the function returns false.
271 bool Encode(const uint8_t* rgb, int width, int height, int stride,
272             const EncoderParam& param, std::string* output);
273 
274 // This version returns data in *out_data. Returns 0 in case of error.
275 size_t Encode(const uint8_t* rgb, int width, int height, int stride,
276               const EncoderParam& param, uint8_t** out_data);
277 
278 // Generic call taking a byte-sink for emitting the compressed data.
279 //   Same as SjpegEncode(), except encoding parameters are passed in a
280 //   EncoderParam. Upon failure (memory allocation or invalid parameter),
281 //   the function returns false.
282 bool Encode(const uint8_t* rgb, int width, int height, int stride,
283             const EncoderParam& param, sjpeg::ByteSink* sink);
284 
285 ////////////////////////////////////////////////////////////////////////////////
286 // Some interfaces for customizing the core codec
287 
288 // Custom search loop
289 struct SearchHook {
290   float q;                // this is the current parameter used
291   float qmin, qmax;       // this is the current bracket for q
292   float target;           // target value (PSNR or size)
293   float tolerance;        // relative tolerance for reaching the 'target' value
294   bool for_size;          // true if we're searching for size
295   float value;            // result for the search after Update() is called
296   int pass;               // pass number (0-based) during search (informative)
297 
298   // Returns false in case of initialization error.
299   // Should always be called by sub-classes.
300   virtual bool Setup(const EncoderParam& param);
301   // Set up the next matrices to try, corresponding to the current q value.
302   // 'idx' is 0 for luma, 1 for chroma
303   virtual void NextMatrix(int idx, uint8_t dst[64]);
304   // return true if the search is finished
305   virtual bool Update(float result);
~SearchHookSearchHook306   virtual ~SearchHook() {}
307 };
308 
309 ////////////////////////////////////////////////////////////////////////////////
310 // Generic byte-sink: custom streaming output of compressed data
311 //
312 // Protocol:
313 //  . Commit(used_size, extra_size, buffer): specify that 'used_size' bytes
314 //       were used since the last call to Commit(). Also reserve 'extra_size'
315 //       bytes for the next cycle and make *data point to the corresponding
316 //       memory. 'extra_size' can be 0, in which case *buffer does not need
317 //       to point to a valid memory area. Most of the time (except during
318 //       header writing), 'extra_size' will be less than 2048.
319 //       Returns false in case of error (both flushing used_size, or allocating
320 //       extra_size).
321 //  . Finalize(): indicates that calls to Commit() are finished until the
322 //       destruction (and the assembled byte-stream can be grabbed).
323 //       Returns false in case of I/O error.
324 //  . Reset(): releases resources (called in case of error or at destruction).
325 
326 struct ByteSink {
327  public:
~ByteSinkByteSink328   virtual ~ByteSink() {}
329   virtual bool Commit(size_t used_size, size_t extra_size, uint8_t** data) = 0;
330   virtual bool Finalize() = 0;
331   virtual void Reset() = 0;
332 };
333 
334 // Some useful factories
335 std::shared_ptr<ByteSink> MakeByteSink(std::string* output);
336 // Vector-based template, specialized for uint8_t
337 template<typename T>
338 std::shared_ptr<ByteSink> MakeByteSink(std::vector<T>* output);
339 template<> std::shared_ptr<ByteSink> MakeByteSink(std::vector<uint8_t>* output);
340 
341 ////////////////////////////////////////////////////////////////////////////////
342 // Memory manager (for internal allocation)
343 
344 struct MemoryManager {
345  public:
~MemoryManagerMemoryManager346   virtual ~MemoryManager() {}
347   virtual void* Alloc(size_t size) = 0;     // same semantic as malloc()
348   virtual void Free(void* const ptr) = 0;   // same semantic as free()
349 };
350 
351 }  // namespace sjpeg
352 
353 #endif    // SJPEG_JPEG_H_
354