1 | // jpge.h - C++ class for JPEG compression. |
2 | // Public Domain or Apache 2.0, Richard Geldreich <richgel99@gmail.com> |
3 | // Alex Evans: Added RGBA support, linear memory allocator. |
4 | #ifndef JPEG_ENCODER_H |
5 | #define JPEG_ENCODER_H |
6 | |
7 | namespace jpge |
8 | { |
9 | typedef unsigned char uint8; |
10 | typedef signed short int16; |
11 | typedef signed int int32; |
12 | typedef unsigned short uint16; |
13 | typedef unsigned int uint32; |
14 | typedef unsigned int uint; |
15 | |
16 | // JPEG chroma subsampling factors. Y_ONLY (grayscale images) and H2V2 (color images) are the most common. |
17 | enum subsampling_t { Y_ONLY = 0, H1V1 = 1, H2V1 = 2, H2V2 = 3 }; |
18 | |
19 | // JPEG compression parameters structure. |
20 | struct params |
21 | { |
22 | inline params() : m_quality(85), m_subsampling(H2V2), m_no_chroma_discrim_flag(false), m_two_pass_flag(false), m_use_std_tables(false) { } |
23 | |
24 | inline bool check() const |
25 | { |
26 | if ((m_quality < 1) || (m_quality > 100)) return false; |
27 | if ((uint)m_subsampling > (uint)H2V2) return false; |
28 | return true; |
29 | } |
30 | |
31 | // Quality: 1-100, higher is better. Typical values are around 50-95. |
32 | int m_quality; |
33 | |
34 | // m_subsampling: |
35 | // 0 = Y (grayscale) only |
36 | // 1 = YCbCr, no subsampling (H1V1, YCbCr 1x1x1, 3 blocks per MCU) |
37 | // 2 = YCbCr, H2V1 subsampling (YCbCr 2x1x1, 4 blocks per MCU) |
38 | // 3 = YCbCr, H2V2 subsampling (YCbCr 4x1x1, 6 blocks per MCU-- very common) |
39 | subsampling_t m_subsampling; |
40 | |
41 | // Disables CbCr discrimination - only intended for testing. |
42 | // If true, the Y quantization table is also used for the CbCr channels. |
43 | bool m_no_chroma_discrim_flag; |
44 | |
45 | bool m_two_pass_flag; |
46 | |
47 | // By default we use the same quantization tables as mozjpeg's default. |
48 | // Set to true to use the traditional tables from JPEG Annex K. |
49 | bool m_use_std_tables; |
50 | }; |
51 | |
52 | // Writes JPEG image to a file. |
53 | // num_channels must be 1 (Y) or 3 (RGB), image pitch must be width*num_channels. |
54 | bool compress_image_to_jpeg_file(const char* pFilename, int width, int height, int num_channels, const uint8* pImage_data, const params& comp_params = params()); |
55 | |
56 | // Writes JPEG image to memory buffer. |
57 | // On entry, buf_size is the size of the output buffer pointed at by pBuf, which should be at least ~1024 bytes. |
58 | // If return value is true, buf_size will be set to the size of the compressed data. |
59 | bool compress_image_to_jpeg_file_in_memory(void* pBuf, int& buf_size, int width, int height, int num_channels, const uint8* pImage_data, const params& comp_params = params()); |
60 | |
61 | // Output stream abstract class - used by the jpeg_encoder class to write to the output stream. |
62 | // put_buf() is generally called with len==JPGE_OUT_BUF_SIZE bytes, but for headers it'll be called with smaller amounts. |
63 | class output_stream |
64 | { |
65 | public: |
66 | virtual ~output_stream() { }; |
67 | virtual bool put_buf(const void* Pbuf, int len) = 0; |
68 | template<class T> inline bool put_obj(const T& obj) { return put_buf(&obj, sizeof(T)); } |
69 | }; |
70 | |
71 | // Lower level jpeg_encoder class - useful if more control is needed than the above helper functions. |
72 | class jpeg_encoder |
73 | { |
74 | public: |
75 | jpeg_encoder(); |
76 | ~jpeg_encoder(); |
77 | |
78 | // Initializes the compressor. |
79 | // pStream: The stream object to use for writing compressed data. |
80 | // params - Compression parameters structure, defined above. |
81 | // width, height - Image dimensions. |
82 | // channels - May be 1, or 3. 1 indicates grayscale, 3 indicates RGB source data. |
83 | // Returns false on out of memory or if a stream write fails. |
84 | bool init(output_stream* pStream, int width, int height, int src_channels, const params& comp_params = params()); |
85 | |
86 | const params& get_params() const { return m_params; } |
87 | |
88 | // Deinitializes the compressor, freeing any allocated memory. May be called at any time. |
89 | void deinit(); |
90 | |
91 | uint get_total_passes() const { return m_params.m_two_pass_flag ? 2 : 1; } |
92 | inline uint get_cur_pass() { return m_pass_num; } |
93 | |
94 | // Call this method with each source scanline. |
95 | // width * src_channels bytes per scanline is expected (RGB or Y format). |
96 | // You must call with NULL after all scanlines are processed to finish compression. |
97 | // Returns false on out of memory or if a stream write fails. |
98 | bool process_scanline(const void* pScanline); |
99 | |
100 | private: |
101 | jpeg_encoder(const jpeg_encoder&); |
102 | jpeg_encoder& operator =(const jpeg_encoder&); |
103 | |
104 | typedef int32 sample_array_t; |
105 | |
106 | output_stream* m_pStream; |
107 | params m_params; |
108 | uint8 m_num_components; |
109 | uint8 m_comp_h_samp[3], m_comp_v_samp[3]; |
110 | int m_image_x, m_image_y, m_image_bpp, m_image_bpl; |
111 | int m_image_x_mcu, m_image_y_mcu; |
112 | int m_image_bpl_xlt, m_image_bpl_mcu; |
113 | int m_mcus_per_row; |
114 | int m_mcu_x, m_mcu_y; |
115 | uint8* m_mcu_lines[16]; |
116 | uint8 m_mcu_y_ofs; |
117 | sample_array_t m_sample_array[64]; |
118 | int16 m_coefficient_array[64]; |
119 | int32 m_quantization_tables[2][64]; |
120 | uint m_huff_codes[4][256]; |
121 | uint8 m_huff_code_sizes[4][256]; |
122 | uint8 m_huff_bits[4][17]; |
123 | uint8 m_huff_val[4][256]; |
124 | uint32 m_huff_count[4][256]; |
125 | int m_last_dc_val[3]; |
126 | enum { JPGE_OUT_BUF_SIZE = 2048 }; |
127 | uint8 m_out_buf[JPGE_OUT_BUF_SIZE]; |
128 | uint8* m_pOut_buf; |
129 | uint m_out_buf_left; |
130 | uint32 m_bit_buffer; |
131 | uint m_bits_in; |
132 | uint8 m_pass_num; |
133 | bool m_all_stream_writes_succeeded; |
134 | |
135 | void optimize_huffman_table(int table_num, int table_len); |
136 | void emit_byte(uint8 i); |
137 | void emit_word(uint i); |
138 | void emit_marker(int marker); |
139 | void emit_jfif_app0(); |
140 | void emit_dqt(); |
141 | void emit_sof(); |
142 | void emit_dht(uint8* bits, uint8* val, int index, bool ac_flag); |
143 | void emit_dhts(); |
144 | void emit_sos(); |
145 | void emit_markers(); |
146 | void compute_huffman_table(uint* codes, uint8* code_sizes, uint8* bits, uint8* val); |
147 | void compute_quant_table(int32* dst, int16* src); |
148 | void adjust_quant_table(int32* dst, int32* src); |
149 | void first_pass_init(); |
150 | bool second_pass_init(); |
151 | bool jpg_open(int p_x_res, int p_y_res, int src_channels); |
152 | void load_block_8_8_grey(int x); |
153 | void load_block_8_8(int x, int y, int c); |
154 | void load_block_16_8(int x, int c); |
155 | void load_block_16_8_8(int x, int c); |
156 | void load_quantized_coefficients(int component_num); |
157 | void flush_output_buffer(); |
158 | void put_bits(uint bits, uint len); |
159 | void code_coefficients_pass_one(int component_num); |
160 | void code_coefficients_pass_two(int component_num); |
161 | void code_block(int component_num); |
162 | void process_mcu_row(); |
163 | bool terminate_pass_one(); |
164 | bool terminate_pass_two(); |
165 | bool process_end_of_image(); |
166 | void load_mcu(const void* src); |
167 | void clear(); |
168 | void init(); |
169 | }; |
170 | |
171 | } // namespace jpge |
172 | |
173 | #endif // JPEG_ENCODER |
174 | |
175 | |