| 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 | |