UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
jpeg_writer.c
Go to the documentation of this file.
1
19/*
20 * Copyright (c) 2024 CESNET
21 * Copyright (c) 2011, Silicon Genome, LLC.
22 *
23 * All rights reserved.
24 *
25 * Redistribution and use in source and binary forms, with or without
26 * modification, are permitted provided that the following conditions are met:
27 *
28 * * Redistributions of source code must retain the above copyright
29 * notice, this list of conditions and the following disclaimer.
30 *
31 * * Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
36 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
39 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
40 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
41 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
42 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
43 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
45 * POSSIBILITY OF SUCH DAMAGE.
46 */
47
48#include "jpeg_reader.h"
49
50#include <stdint.h> // for uint8_t
51
52#include "jpeg_writer.h"
53
59
63
68
72
74
76
85
94
111
115
117
118 JPEG_MARKER_ERROR = 0x100
120
121enum {
123};
124
125#define jpeg_writer_emit_byte(buffer, value) *(buffer)++ = (uint8_t) (value);
126#define jpeg_writer_emit_2byte(buffer, value) \
127 { \
128 *(buffer)++ = (uint8_t) (((value) >> 8) & 0xFF); \
129 *(buffer)++ = (uint8_t) ((value) & 0xFF); \
130 }
131
132#define jpeg_writer_emit_marker(buffer, marker) \
133 { \
134 *(buffer)++ = 0xFF; \
135 *(buffer)++ = (uint8_t) (marker); \
136 }
137
138static void
140{
142}
143
144static void
146{
147 // Length of APP0 block (2 bytes)
148 // Block ID (4 bytes - ASCII "JFIF")
149 // Zero byte (1 byte to terminate the ID string)
150 // Version Major, Minor (2 bytes - 0x01, 0x01)
151 // Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 =
152 // cm) Xdpu (2 bytes - dots per unit horizontal) Ydpu
153 // (2 bytes - dots per unit vertical) Thumbnail X size (1 byte)
154 // Thumbnail Y size (1 byte)
156
157 // Length
158 jpeg_writer_emit_2byte(*buffer, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1);
159
160 // Identifier: ASCII "JFIF"
161 jpeg_writer_emit_byte(*buffer, 'J');
162 jpeg_writer_emit_byte(*buffer, 'F');
163 jpeg_writer_emit_byte(*buffer, 'I');
164 jpeg_writer_emit_byte(*buffer, 'F');
165 jpeg_writer_emit_byte(*buffer, 0);
166
167 // We currently emit version code 1.01 since we use no 1.02 features.
168 // This may avoid complaints from some older decoders.
169 // Major version
170 jpeg_writer_emit_byte(*buffer, 1);
171 // Minor version
172 jpeg_writer_emit_byte(*buffer, 1);
173 // Pixel size information
174 jpeg_writer_emit_byte(*buffer, 1);
175 jpeg_writer_emit_2byte(*buffer, 300);
176 jpeg_writer_emit_2byte(*buffer, 300);
177 // No thumbnail image
178 jpeg_writer_emit_byte(*buffer, 0);
179 jpeg_writer_emit_byte(*buffer, 0);
180}
181
182static void
184{
185 enum {
186 MARKER_LEN = 2,
187 LENGTH_LEN = 2,
188 TYPE_LEN = 1,
189 };
190 *buffer += MARKER_LEN;
191 *buffer += LENGTH_LEN;
192 *buffer += TYPE_LEN;
193 *buffer += JPEG_QUANT_SIZE;
194}
195
196static void
197jpeg_writer_write_dqt(char **buffer, int type, const uint8_t *dqt)
198{
200
201 // Length
203
204 // Index: Y component = 0, Cb or Cr component = 1
205 jpeg_writer_emit_byte(*buffer, type);
206
207 // Emit table in zig-zag order
208 for (int i = 0; i < JPEG_QUANT_SIZE; i++) {
209 unsigned char qval = (unsigned char) ((char) (dqt[i]));
210 jpeg_writer_emit_byte(*buffer, qval);
211 }
212}
213
214static void
215jpeg_writer_write_sof0(char **buffer, unsigned width, unsigned height,
216 enum gpujpeg_writer_subsasmpling subsampling)
217{
219
220 // Length
221 jpeg_writer_emit_2byte(*buffer, 8 + 3 * COMP_COUNT);
222
223 // Precision (bit depth)
224 jpeg_writer_emit_byte(*buffer, 8);
225 // Dimensions
226 jpeg_writer_emit_2byte(*buffer, height);
227 jpeg_writer_emit_2byte(*buffer, width);
228
229 // Number of components
231
232 // Components
233 for (int comp_index = 0; comp_index < COMP_COUNT; comp_index++) {
234 // // Get component
235 // struct jpeg_component* component =
236 // &encoder->coder.component[comp_index];
237
238 // Component ID
239 jpeg_writer_emit_byte(*buffer, comp_index + 1);
240
241 // Sampling factors: 422 - [2,1],[1.1],[1,1]; 420 - [2,2][1...
242 int sampling_factor_horizontal = comp_index == 0 ? 2 : 1;
243 int sampling_factor_vertical = 1;
244 if (comp_index == 0 && subsampling == JPEG_WRITER_SUBS_420) {
245 sampling_factor_vertical = 2;
246 }
247 jpeg_writer_emit_byte(*buffer,
248 (sampling_factor_horizontal << 4) +
249 sampling_factor_vertical);
250
251 // Quantization table index
252 if (comp_index == 0) { // Y
253 jpeg_writer_emit_byte(*buffer, 0);
254 } else { // luminance
255 jpeg_writer_emit_byte(*buffer, 1);
256 }
257 }
258}
259
260static void
262{
263 for (int table = 0; table < 4; table++) {
265
266 int length = 0;
267 for (int i = 0; i < 16; i++) {
268 length += default_huffman_tables[table].bits[i];
269 }
270
271 jpeg_writer_emit_2byte(*buffer, length + 2 + 1 + 16);
272
273 int index = 0;
274 switch ((enum huff_type) table) {
275 case LUM_AC:
276 index = 16;
277 break;
278 case LUM_DC:
279 index = 0;
280 break;
281 case CHR_AC:
282 index = 17;
283 break;
284 case CHR_DC:
285 index = 1;
286 break;
287 }
288 jpeg_writer_emit_byte(*buffer, index);
289
290 for (int i = 0; i < 16; i++) {
292 *buffer, default_huffman_tables[table].bits[i]);
293 }
294
295 // Varible-length
296 for (int i = 0; i < length; i++) {
298 *buffer, default_huffman_tables[table].bufval[i]);
299 }
300 }
301}
302
303static void
304jpeg_writer_write_dri(char **buffer, unsigned restart_interval)
305{
307
308 // Length
309 jpeg_writer_emit_2byte(*buffer, 4);
310
311 // Restart interval
312 jpeg_writer_emit_2byte(*buffer, restart_interval);
313}
314
315static void
317{
318 // Begin scan header
320
321 // Length
322 jpeg_writer_emit_2byte(*buffer, 6 + 2 * COMP_COUNT);
323
324 // Component count
326
327 // Components
328 for (int comp_index = 0; comp_index < COMP_COUNT; comp_index++) {
329 // Component ID
330 jpeg_writer_emit_byte(*buffer, comp_index + 1);
331
332 // Component DC and AC entropy coding table indexes
333 if (comp_index == 0) { // luminance
334 jpeg_writer_emit_byte(*buffer, 0); // (0 << 4) | 0
335 } else { // chrominance
336 jpeg_writer_emit_byte(*buffer, 0x11); // (1 << 4) | 1
337 }
338 }
339
340 jpeg_writer_emit_byte(*buffer, 0); // Ss
341 jpeg_writer_emit_byte(*buffer, 0x3F); // Se
342 jpeg_writer_emit_byte(*buffer, 0); // Ah/Al
343}
344
359void
360jpeg_writer_write_headers(char **buffer, struct jpeg_writer_data *info)
361{
362 jpeg_writer_write_soi(buffer);
364 info->dqt_marker_start = *buffer;
365 for (int i = 0; i < 2; i++) {
367 }
368 jpeg_writer_write_sof0(buffer, info->width, info->height,
369 info->subsampling);
370
372
373 if (info->restart_interval > 0) {
374 jpeg_writer_write_dri(buffer, info->restart_interval);
375 }
376
378}
379
383void
384jpeg_writer_fill_dqt(char *buffer, uint8_t quant_table[2][JPEG_QUANT_SIZE])
385{
386 for (int i = 0; i < 2; i++) {
387 jpeg_writer_write_dqt(&buffer, i, quant_table[i]);
388 }
389}
390
391void
393{
395}
const struct huffman_table default_huffman_tables[4]
jpeg_marker_code
huff_type
@ CHR_DC
@ CHR_AC
@ LUM_DC
order of tables in default_huffman_tables
@ LUM_AC
static void jpeg_writer_write_dqt(char **buffer, int type, const uint8_t *dqt)
void jpeg_writer_fill_dqt(char *buffer, uint8_t quant_table[2][JPEG_QUANT_SIZE])
void jpeg_writer_write_eoi(char **buffer)
void jpeg_writer_write_headers(char **buffer, struct jpeg_writer_data *info)
writes JPEG/JFIF headers up to the scan (including SOS header)
@ COMP_COUNT
static void gpujpeg_writer_write_scan_header(char **buffer)
#define jpeg_writer_emit_byte(buffer, value)
static void jpeg_writer_write_dhts(char **buffer)
static void jpeg_writer_write_app0(char **buffer)
static void jpeg_writer_allocate_dqt(char **buffer)
#define jpeg_writer_emit_marker(buffer, marker)
static void jpeg_writer_write_dri(char **buffer, unsigned restart_interval)
@ JPEG_MARKER_COM
@ JPEG_MARKER_SOF14
Definition jpeg_writer.c:70
@ JPEG_MARKER_APP12
@ JPEG_MARKER_APP4
Definition jpeg_writer.c:99
@ JPEG_MARKER_APP0
Definition jpeg_writer.c:95
@ JPEG_MARKER_SOF11
Definition jpeg_writer.c:67
@ JPEG_MARKER_APP1
Definition jpeg_writer.c:96
@ JPEG_MARKER_DNL
Definition jpeg_writer.c:90
@ JPEG_MARKER_RST2
Definition jpeg_writer.c:79
@ JPEG_MARKER_RST0
Definition jpeg_writer.c:77
@ JPEG_MARKER_DHT
Definition jpeg_writer.c:73
@ JPEG_MARKER_SOF15
Definition jpeg_writer.c:71
@ JPEG_MARKER_EOI
Definition jpeg_writer.c:87
@ JPEG_MARKER_SOF7
Definition jpeg_writer.c:62
@ JPEG_MARKER_JPG
Definition jpeg_writer.c:64
@ JPEG_MARKER_APP14
@ JPEG_MARKER_EXP
Definition jpeg_writer.c:93
@ JPEG_MARKER_RST3
Definition jpeg_writer.c:80
@ JPEG_MARKER_SOF13
Definition jpeg_writer.c:69
@ JPEG_MARKER_DRI
Definition jpeg_writer.c:91
@ JPEG_MARKER_JPG0
@ JPEG_MARKER_APP7
@ JPEG_MARKER_APP5
@ JPEG_MARKER_SOF6
Definition jpeg_writer.c:61
@ JPEG_MARKER_RST6
Definition jpeg_writer.c:83
@ JPEG_MARKER_JPG13
@ JPEG_MARKER_APP3
Definition jpeg_writer.c:98
@ JPEG_MARKER_SOF5
Definition jpeg_writer.c:60
@ JPEG_MARKER_RST1
Definition jpeg_writer.c:78
@ JPEG_MARKER_SOF1
Definition jpeg_writer.c:56
@ JPEG_MARKER_DQT
Definition jpeg_writer.c:89
@ JPEG_MARKER_APP15
@ JPEG_MARKER_TEM
@ JPEG_MARKER_RST5
Definition jpeg_writer.c:82
@ JPEG_MARKER_SOF2
Definition jpeg_writer.c:57
@ JPEG_MARKER_APP8
@ JPEG_MARKER_SOF10
Definition jpeg_writer.c:66
@ JPEG_MARKER_APP2
Definition jpeg_writer.c:97
@ JPEG_MARKER_SOF3
Definition jpeg_writer.c:58
@ JPEG_MARKER_RST4
Definition jpeg_writer.c:81
@ JPEG_MARKER_SOF0
Definition jpeg_writer.c:55
@ JPEG_MARKER_DAC
Definition jpeg_writer.c:75
@ JPEG_MARKER_ERROR
@ JPEG_MARKER_APP9
@ JPEG_MARKER_SOS
Definition jpeg_writer.c:88
@ JPEG_MARKER_APP13
@ JPEG_MARKER_RST7
Definition jpeg_writer.c:84
@ JPEG_MARKER_DHP
Definition jpeg_writer.c:92
@ JPEG_MARKER_SOI
Definition jpeg_writer.c:86
@ JPEG_MARKER_APP6
@ JPEG_MARKER_SOF9
Definition jpeg_writer.c:65
@ JPEG_MARKER_APP11
@ JPEG_MARKER_APP10
#define jpeg_writer_emit_2byte(buffer, value)
static void jpeg_writer_write_sof0(char **buffer, unsigned width, unsigned height, enum gpujpeg_writer_subsasmpling subsampling)
static void jpeg_writer_write_soi(char **buffer)
@ JPEG_QUANT_SIZE
items, bytes (for precision=0)
Definition jpeg_writer.h:54
Option::OptType type
Definition settings.cpp:194
const uint8_t * bits
Definition jpeg_reader.h:98
subsampling
Definition types.h:132