]> git.cworth.org Git - vogl/blob - src/voglcore/vogl_jpge.h
Initial vogl checkin
[vogl] / src / voglcore / vogl_jpge.h
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27 // jpge.h - C++ class for JPEG compression.
28 // Public domain, Rich Geldreich <richgel99@gmail.com>
29 // Alex Evans: Added RGBA support, linear memory allocator.
30 #ifndef JPEG_ENCODER_H
31 #define JPEG_ENCODER_H
32
33 #include "vogl_core.h"
34
35 namespace jpge
36 {
37     typedef unsigned char uint8;
38     typedef signed short int16;
39     typedef signed int int32;
40     typedef unsigned short uint16;
41     typedef unsigned int uint32;
42     typedef unsigned int uint;
43
44     // JPEG chroma subsampling factors. Y_ONLY (grayscale images) and H2V2 (color images) are the most common.
45     enum subsampling_t
46     {
47         Y_ONLY = 0,
48         H1V1 = 1,
49         H2V1 = 2,
50         H2V2 = 3
51     };
52
53     // JPEG compression parameters structure.
54     struct params
55     {
56         inline params()
57             : m_quality(85), m_subsampling(H2V2), m_no_chroma_discrim_flag(false), m_two_pass_flag(false)
58         {
59         }
60
61         inline bool check() const
62         {
63             if ((m_quality < 1) || (m_quality > 100))
64                 return false;
65             if ((uint)m_subsampling > (uint)H2V2)
66                 return false;
67             return true;
68         }
69
70         // Quality: 1-100, higher is better. Typical values are around 50-95.
71         int m_quality;
72
73         // m_subsampling:
74         // 0 = Y (grayscale) only
75         // 1 = YCbCr, no subsampling (H1V1, YCbCr 1x1x1, 3 blocks per MCU)
76         // 2 = YCbCr, H2V1 subsampling (YCbCr 2x1x1, 4 blocks per MCU)
77         // 3 = YCbCr, H2V2 subsampling (YCbCr 4x1x1, 6 blocks per MCU-- very common)
78         subsampling_t m_subsampling;
79
80         // Disables CbCr discrimination - only intended for testing.
81         // If true, the Y quantization table is also used for the CbCr channels.
82         bool m_no_chroma_discrim_flag;
83
84         bool m_two_pass_flag;
85     };
86
87     // Writes JPEG image to a file.
88     // num_channels must be 1 (Y) or 3 (RGB), image pitch must be width*num_channels.
89     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());
90
91     // Writes JPEG image to memory buffer.
92     // On entry, buf_size is the size of the output buffer pointed at by pBuf, which should be at least ~1024 bytes.
93     // If return value is true, buf_size will be set to the size of the compressed data.
94     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());
95
96     // Output stream abstract class - used by the jpeg_encoder class to write to the output stream.
97     // put_buf() is generally called with len==JPGE_OUT_BUF_SIZE bytes, but for headers it'll be called with smaller amounts.
98     class output_stream
99     {
100     public:
101         virtual ~output_stream() {};
102         virtual bool put_buf(const void *Pbuf, int len) = 0;
103         template <class T>
104         inline bool put_obj(const T &obj)
105         {
106             return put_buf(&obj, sizeof(T));
107         }
108     };
109
110     // Lower level jpeg_encoder class - useful if more control is needed than the above helper functions.
111     class jpeg_encoder
112     {
113     public:
114         jpeg_encoder();
115         ~jpeg_encoder();
116
117         // Initializes the compressor.
118         // pStream: The stream object to use for writing compressed data.
119         // params - Compression parameters structure, defined above.
120         // width, height  - Image dimensions.
121         // channels - May be 1, or 3. 1 indicates grayscale, 3 indicates RGB source data.
122         // Returns false on out of memory or if a stream write fails.
123         bool init(output_stream *pStream, int width, int height, int src_channels, const params &comp_params = params());
124
125         const params &get_params() const
126         {
127             return m_params;
128         }
129
130         // Deinitializes the compressor, freeing any allocated memory. May be called at any time.
131         void deinit();
132
133         uint get_total_passes() const
134         {
135             return m_params.m_two_pass_flag ? 2 : 1;
136         }
137         inline uint get_cur_pass()
138         {
139             return m_pass_num;
140         }
141
142         // Call this method with each source scanline.
143         // width * src_channels bytes per scanline is expected (RGB or Y format).
144         // You must call with NULL after all scanlines are processed to finish compression.
145         // Returns false on out of memory or if a stream write fails.
146         bool process_scanline(const void *pScanline);
147
148     private:
149         jpeg_encoder(const jpeg_encoder &);
150         jpeg_encoder &operator=(const jpeg_encoder &);
151
152         typedef int32 sample_array_t;
153
154         output_stream *m_pStream;
155         params m_params;
156         uint8 m_num_components;
157         uint8 m_comp_h_samp[3], m_comp_v_samp[3];
158         int m_image_x, m_image_y, m_image_bpp, m_image_bpl;
159         int m_image_x_mcu, m_image_y_mcu;
160         int m_image_bpl_xlt, m_image_bpl_mcu;
161         int m_mcus_per_row;
162         int m_mcu_x, m_mcu_y;
163         uint8 *m_mcu_lines[16];
164         uint8 m_mcu_y_ofs;
165         sample_array_t m_sample_array[64];
166         int16 m_coefficient_array[64];
167         int32 m_quantization_tables[2][64];
168         uint m_huff_codes[4][256];
169         uint8 m_huff_code_sizes[4][256];
170         uint8 m_huff_bits[4][17];
171         uint8 m_huff_val[4][256];
172         uint32 m_huff_count[4][256];
173         int m_last_dc_val[3];
174         enum
175         {
176             JPGE_OUT_BUF_SIZE = 2048
177         };
178         uint8 m_out_buf[JPGE_OUT_BUF_SIZE];
179         uint8 *m_pOut_buf;
180         uint m_out_buf_left;
181         uint32 m_bit_buffer;
182         uint m_bits_in;
183         uint8 m_pass_num;
184         bool m_all_stream_writes_succeeded;
185
186         void optimize_huffman_table(int table_num, int table_len);
187         void emit_byte(uint8 i);
188         void emit_word(uint i);
189         void emit_marker(int marker);
190         void emit_jfif_app0();
191         void emit_dqt();
192         void emit_sof();
193         void emit_dht(uint8 *bits, uint8 *val, int index, bool ac_flag);
194         void emit_dhts();
195         void emit_sos();
196         void emit_markers();
197         void compute_huffman_table(uint *codes, uint8 *code_sizes, uint8 *bits, uint8 *val);
198         void compute_quant_table(int32 *dst, int16 *src);
199         void adjust_quant_table(int32 *dst, int32 *src);
200         void first_pass_init();
201         bool second_pass_init();
202         bool jpg_open(int p_x_res, int p_y_res, int src_channels);
203         void load_block_8_8_grey(int x);
204         void load_block_8_8(int x, int y, int c);
205         void load_block_16_8(int x, int c);
206         void load_block_16_8_8(int x, int c);
207         void load_quantized_coefficients(int component_num);
208         void flush_output_buffer();
209         void put_bits(uint bits, uint len);
210         void code_coefficients_pass_one(int component_num);
211         void code_coefficients_pass_two(int component_num);
212         void code_block(int component_num);
213         void process_mcu_row();
214         bool terminate_pass_one();
215         bool terminate_pass_two();
216         bool process_end_of_image();
217         void load_mcu(const void *src);
218         void clear();
219         void init();
220     };
221
222 } // namespace jpge
223
224 #endif // JPEG_ENCODER