-
Notifications
You must be signed in to change notification settings - Fork 0
/
jpge.cuh
226 lines (186 loc) · 7.17 KB
/
jpge.cuh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/**
* © 2013, 2015 Kornel Lesiński. All rights reserved.
* Based on code by Rich Geldreich.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JPEG_ENCODER_H
#define JPEG_ENCODER_H
namespace jpge {
typedef unsigned char uint8;
typedef signed short int16;
typedef signed int int32;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned int uint;
struct rgb {
uint8 r,g,b;
};
struct rgba {
uint8 r,g,b,a;
};
typedef double dct_t;
typedef int16 dctq_t; // quantized
// JPEG chroma subsampling factors. Y_ONLY (grayscale images) and H2V2 (color images) are the most common.
enum subsampling_t { Y_ONLY = 0, H1V1 = 1, H2V1 = 2, H2V2 = 3 };
// JPEG compression parameters structure.
struct params {
inline params() : m_quality(85), m_subsampling(H2V2), m_no_chroma_discrim_flag(false) { }
inline bool check() const
{
if ((m_quality < 1) || (m_quality > 100)) {
return false;
}
if ((uint)m_subsampling > (uint)H2V2) {
return false;
}
return true;
}
// Quality: 1-100, higher is better. Typical values are around 50-95.
float m_quality;
// m_subsampling:
// 0 = Y (grayscale) only
// 1 = YCbCr, no subsampling (H1V1, YCbCr 1x1x1, 3 blocks per MCU)
// 2 = YCbCr, H2V1 subsampling (YCbCr 2x1x1, 4 blocks per MCU)
// 3 = YCbCr, H2V2 subsampling (YCbCr 4x1x1, 6 blocks per MCU-- very common)
subsampling_t m_subsampling;
// Disables CbCr discrimination - only intended for testing.
// If true, the Y quantization table is also used for the CbCr channels.
bool m_no_chroma_discrim_flag;
};
// Writes JPEG image to a file.
// num_channels must be 1 (Y) or 3 (RGB), image pitch must be width*num_channels.
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());
// Writes JPEG image to memory buffer.
// On entry, buf_size is the size of the output buffer pointed at by pBuf, which should be at least ~1024 bytes.
// If return value is true, buf_size will be set to the size of the compressed data.
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());
// Output stream abstract class - used by the jpeg_encoder class to write to the output stream.
// put_buf() is generally called with len==JPGE_OUT_BUF_SIZE bytes, but for headers it'll be called with smaller amounts.
class output_stream {
public:
virtual ~output_stream() { };
virtual bool put_buf(const void *Pbuf, int len) = 0;
template<class T> inline bool put_obj(const T &obj) {
return put_buf(&obj, sizeof(T));
}
};
bool compress_image_to_stream(output_stream &dst_stream, int width, int height, int num_channels, const uint8 *pImage_data, const params &comp_params);
class huffman_table {
public:
uint m_codes[256];
uint8 m_code_sizes[256];
uint8 m_bits[17];
uint8 m_val[256];
uint32 m_count[256];
void optimize(int table_len);
void compute();
};
class component {
public:
uint8 m_h_samp, m_v_samp;
int m_last_dc_val;
};
struct huffman_dcac {
int32 m_quantization_table[64];
huffman_table dc,ac;
};
class image {
public:
void init();
void deinit();
int m_x, m_y;
float *m_pixels;
float get_px(int x, int y);
void set_px(float px, int x, int y);
void load_block(dct_t *, int x, int y);
dctq_t *get_dctq(int x, int y);
void subsample(image &luma, int v_samp);
private:
dctq_t *m_dctqs; // quantized dcts
dct_t blend_dual(int x, int y, image &);
dct_t blend_quad(int x, int y, image &);
};
// Lower level jpeg_encoder class - useful if more control is needed than the above helper functions.
class jpeg_encoder {
public:
jpeg_encoder();
~jpeg_encoder();
// Initializes the compressor.
// pStream: The stream object to use for writing compressed data.
// params - Compression parameters structure, defined above.
// width, height - Image dimensions.
// Returns false on out of memory or if a stream write fails.
bool init(output_stream *pStream, int width, int height, const params &comp_params = params());
const params &get_params() const {
return m_params;
}
// Deinitializes the compressor, freeing any allocated memory. May be called at any time.
void deinit();
// Call this method with each source scanline.
// width * src_channels bytes per scanline is expected (RGB or Y format).
// channels - May be 1, or 3. 1 indicates grayscale, 3 indicates RGB source data.
// Returns false on out of memory or if a stream write fails.
bool read_image(const uint8 *data, int width, int height, int bpp);
bool process_scanline2(const uint8 *pScanline, int y);
// You must call after all scanlines are processed to finish compression.
bool compress_image();
void load_mcu_Y(const uint8 *pSrc, int width, int bpp, int y);
void load_mcu_YCC(const uint8 *pSrc, int width, int bpp, int y, int height);
private:
jpeg_encoder(const jpeg_encoder &);
jpeg_encoder &operator =(const jpeg_encoder &);
output_stream *m_pStream;
params m_params;
uint8 m_num_components;
component m_comp[3];
struct huffman_dcac m_huff[2];
enum { JPGE_OUT_BUF_SIZE = 2048 };
uint8 m_out_buf[JPGE_OUT_BUF_SIZE];
uint8 *m_pOut_buf;
uint m_out_buf_left;
uint32 m_bit_buffer;
uint m_bits_in;
bool m_all_stream_writes_succeeded;
int m_mcu_w, m_mcu_h;
int m_x, m_y;
image m_image[3];
void rewrite_luma(const uint8 *image_data, int width, int height, int bpp);
void emit_byte(uint8 i);
void emit_word(uint i);
void emit_marker(int marker);
void emit_jfif_app0();
void emit_dqt();
void emit_sof();
void emit_dht(uint8 *bits, uint8 *val, int index, bool ac_flag);
void emit_dhts();
void emit_sos();
void emit_start_markers();
bool emit_end_markers();
void compute_quant_table(int32 *dst, int16 *src);
void adjust_quant_table(int32 *dst, int32 *src);
void reset_last_dc();
void compute_huffman_tables();
bool jpg_open(int p_x_res, int p_y_res);
void quantize_pixels(dct_t *pSrc, int16 *pDst, const int32 *q);
void flush_output_buffer();
void put_bits(uint bits, uint len);
void put_signed_int_bits(int num, uint len);
void code_block(dctq_t *coefficients, huffman_dcac *huff, component *comp, bool putbits);
void code_mcu_row(int y, bool write);
void clear();
void init();
};
} // namespace jpge
#endif // JPEG_ENCODER