sjpeg 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/sjpeg/sjpeg.h ADDED
@@ -0,0 +1,353 @@
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);
199
+ 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);
306
+ 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:
328
+ 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:
346
+ 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_