1 /*
2  * jwrjfif.c
3  *
4  * Copyright (C) 1991, 1992, 1993, Thomas G. Lane.
5  * This file is part of the Independent JPEG Group's software.
6  * For conditions of distribution and use, see the accompanying README file.
7  *
8  * This file contains routines to write standard JPEG file headers/markers.
9  * The file format created is a raw JPEG data stream with (optionally) an
10  * APP0 marker per the JFIF spec.  This will handle baseline and
11  * JFIF-convention JPEG files, although there is currently no provision
12  * for inserting a thumbnail image in the JFIF header.
13  *
14  * These routines may need modification for non-Unix environments or
15  * specialized applications.  As they stand, they assume output to
16  * an ordinary stdio stream.  However, the changes to write to something
17  * else are localized in the macros appearing just below.
18  *
19  * These routines are invoked via the methods write_file_header,
20  * write_scan_header, write_jpeg_data, write_scan_trailer, and
21  * write_file_trailer.
22  */
23 
24 #include "jinclude.h"
25 
26 #ifdef JFIF_SUPPORTED
27 
28 
29 /*
30  * To output to something other than a stdio stream, you'd need to redefine
31  * these macros.
32  */
33 
34 /* Write a single byte */
35 #define emit_byte(cinfo,x)  putc((x), cinfo->output_file)
36 
37 /* Write some bytes from a (char *) buffer */
38 #define WRITE_BYTES(cinfo,dataptr,datacount)  \
39   { if (JFWRITE(cinfo->output_file, dataptr, datacount) \
40 	!= (size_t) (datacount)) \
41       ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?"); }
42 
43 /* Clean up and verify successful output */
44 #define CHECK_OUTPUT(cinfo)  \
45   { fflush(cinfo->output_file); \
46     if (ferror(cinfo->output_file)) \
47       ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?"); }
48 
49 
50 /* End of stdio-specific code. */
51 
52 
53 typedef enum {			/* JPEG marker codes */
54   M_SOF0  = 0xc0,
55   M_SOF1  = 0xc1,
56   M_SOF2  = 0xc2,
57   M_SOF3  = 0xc3,
58 
59   M_SOF5  = 0xc5,
60   M_SOF6  = 0xc6,
61   M_SOF7  = 0xc7,
62 
63   M_JPG   = 0xc8,
64   M_SOF9  = 0xc9,
65   M_SOF10 = 0xca,
66   M_SOF11 = 0xcb,
67 
68   M_SOF13 = 0xcd,
69   M_SOF14 = 0xce,
70   M_SOF15 = 0xcf,
71 
72   M_DHT   = 0xc4,
73 
74   M_DAC   = 0xcc,
75 
76   M_RST0  = 0xd0,
77   M_RST1  = 0xd1,
78   M_RST2  = 0xd2,
79   M_RST3  = 0xd3,
80   M_RST4  = 0xd4,
81   M_RST5  = 0xd5,
82   M_RST6  = 0xd6,
83   M_RST7  = 0xd7,
84 
85   M_SOI   = 0xd8,
86   M_EOI   = 0xd9,
87   M_SOS   = 0xda,
88   M_DQT   = 0xdb,
89   M_DNL   = 0xdc,
90   M_DRI   = 0xdd,
91   M_DHP   = 0xde,
92   M_EXP   = 0xdf,
93 
94   M_APP0  = 0xe0,
95   M_APP15 = 0xef,
96 
97   M_JPG0  = 0xf0,
98   M_JPG13 = 0xfd,
99   M_COM   = 0xfe,
100 
101   M_TEM   = 0x01,
102 
103   M_ERROR = 0x100
104 } JPEG_MARKER;
105 
106 
107 LOCAL void
emit_marker(compress_info_ptr cinfo,JPEG_MARKER mark)108 emit_marker (compress_info_ptr cinfo, JPEG_MARKER mark)
109 /* Emit a marker code */
110 {
111   emit_byte(cinfo, 0xFF);
112   emit_byte(cinfo, mark);
113 }
114 
115 
116 LOCAL void
emit_2bytes(compress_info_ptr cinfo,int value)117 emit_2bytes (compress_info_ptr cinfo, int value)
118 /* Emit a 2-byte integer; these are always MSB first in JPEG files */
119 {
120   emit_byte(cinfo, (value >> 8) & 0xFF);
121   emit_byte(cinfo, value & 0xFF);
122 }
123 
124 
125 LOCAL int
emit_dqt(compress_info_ptr cinfo,int index)126 emit_dqt (compress_info_ptr cinfo, int index)
127 /* Emit a DQT marker */
128 /* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
129 {
130   QUANT_TBL_PTR data = cinfo->quant_tbl_ptrs[index];
131   int prec = 0;
132   int i;
133 
134   for (i = 0; i < DCTSIZE2; i++) {
135     if (data[i] > 255)
136       prec = 1;
137   }
138 
139   emit_marker(cinfo, M_DQT);
140 
141   emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2);
142 
143   emit_byte(cinfo, index + (prec<<4));
144 
145   for (i = 0; i < DCTSIZE2; i++) {
146     if (prec)
147       emit_byte(cinfo, data[i] >> 8);
148     emit_byte(cinfo, data[i] & 0xFF);
149   }
150 
151   return prec;
152 }
153 
154 
155 LOCAL void
emit_dht(compress_info_ptr cinfo,int index,boolean is_ac)156 emit_dht (compress_info_ptr cinfo, int index, boolean is_ac)
157 /* Emit a DHT marker */
158 {
159   HUFF_TBL * htbl;
160   int length, i;
161 
162   if (is_ac) {
163     htbl = cinfo->ac_huff_tbl_ptrs[index];
164     index += 0x10;		/* output index has AC bit set */
165   } else {
166     htbl = cinfo->dc_huff_tbl_ptrs[index];
167   }
168 
169   if (htbl == NULL)
170     ERREXIT1(cinfo->emethods, "Huffman table 0x%02x was not defined", index);
171 
172   if (! htbl->sent_table) {
173     emit_marker(cinfo, M_DHT);
174 
175     length = 0;
176     for (i = 1; i <= 16; i++)
177       length += htbl->bits[i];
178 
179     emit_2bytes(cinfo, length + 2 + 1 + 16);
180     emit_byte(cinfo, index);
181 
182     for (i = 1; i <= 16; i++)
183       emit_byte(cinfo, htbl->bits[i]);
184 
185     for (i = 0; i < length; i++)
186       emit_byte(cinfo, htbl->huffval[i]);
187 
188     htbl->sent_table = TRUE;
189   }
190 }
191 
192 
193 LOCAL void
emit_dac(compress_info_ptr cinfo)194 emit_dac (compress_info_ptr cinfo)
195 /* Emit a DAC marker */
196 /* Since the useful info is so small, we want to emit all the tables in */
197 /* one DAC marker.  Therefore this routine does its own scan of the table. */
198 {
199   char dc_in_use[NUM_ARITH_TBLS];
200   char ac_in_use[NUM_ARITH_TBLS];
201   int length, i;
202 
203   for (i = 0; i < NUM_ARITH_TBLS; i++)
204     dc_in_use[i] = ac_in_use[i] = 0;
205 
206   for (i = 0; i < cinfo->num_components; i++) {
207     dc_in_use[cinfo->comp_info[i].dc_tbl_no] = 1;
208     ac_in_use[cinfo->comp_info[i].ac_tbl_no] = 1;
209   }
210 
211   length = 0;
212   for (i = 0; i < NUM_ARITH_TBLS; i++)
213     length += dc_in_use[i] + ac_in_use[i];
214 
215   emit_marker(cinfo, M_DAC);
216 
217   emit_2bytes(cinfo, length*2 + 2);
218 
219   for (i = 0; i < NUM_ARITH_TBLS; i++) {
220     if (dc_in_use[i]) {
221       emit_byte(cinfo, i);
222       emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4));
223     }
224     if (ac_in_use[i]) {
225       emit_byte(cinfo, i + 0x10);
226       emit_byte(cinfo, cinfo->arith_ac_K[i]);
227     }
228   }
229 }
230 
231 
232 LOCAL void
emit_dri(compress_info_ptr cinfo)233 emit_dri (compress_info_ptr cinfo)
234 /* Emit a DRI marker */
235 {
236   emit_marker(cinfo, M_DRI);
237 
238   emit_2bytes(cinfo, 4);	/* fixed length */
239 
240   emit_2bytes(cinfo, (int) cinfo->restart_interval);
241 }
242 
243 
244 LOCAL void
emit_sof(compress_info_ptr cinfo,JPEG_MARKER code)245 emit_sof (compress_info_ptr cinfo, JPEG_MARKER code)
246 /* Emit a SOF marker */
247 {
248   int i;
249 
250   emit_marker(cinfo, code);
251 
252   emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */
253 
254   if (cinfo->image_height > 65535L || cinfo->image_width > 65535L)
255     ERREXIT(cinfo->emethods, "Maximum image dimension for JFIF is 65535 pixels");
256 
257   emit_byte(cinfo, cinfo->data_precision);
258   emit_2bytes(cinfo, (int) cinfo->image_height);
259   emit_2bytes(cinfo, (int) cinfo->image_width);
260 
261   emit_byte(cinfo, cinfo->num_components);
262 
263   for (i = 0; i < cinfo->num_components; i++) {
264     emit_byte(cinfo, cinfo->comp_info[i].component_id);
265     emit_byte(cinfo, (cinfo->comp_info[i].h_samp_factor << 4)
266 		     + cinfo->comp_info[i].v_samp_factor);
267     emit_byte(cinfo, cinfo->comp_info[i].quant_tbl_no);
268   }
269 }
270 
271 
272 LOCAL void
emit_sos(compress_info_ptr cinfo)273 emit_sos (compress_info_ptr cinfo)
274 /* Emit a SOS marker */
275 {
276   int i;
277 
278   emit_marker(cinfo, M_SOS);
279 
280   emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */
281 
282   emit_byte(cinfo, cinfo->comps_in_scan);
283 
284   for (i = 0; i < cinfo->comps_in_scan; i++) {
285     emit_byte(cinfo, cinfo->cur_comp_info[i]->component_id);
286     emit_byte(cinfo, (cinfo->cur_comp_info[i]->dc_tbl_no << 4)
287 		     + cinfo->cur_comp_info[i]->ac_tbl_no);
288   }
289 
290   emit_byte(cinfo, 0);		/* Spectral selection start */
291   emit_byte(cinfo, DCTSIZE2-1);	/* Spectral selection end */
292   emit_byte(cinfo, 0);		/* Successive approximation */
293 }
294 
295 
296 LOCAL void
emit_jfif_app0(compress_info_ptr cinfo)297 emit_jfif_app0 (compress_info_ptr cinfo)
298 /* Emit a JFIF-compliant APP0 marker */
299 {
300   /*
301    * Length of APP0 block	(2 bytes)
302    * Block ID			(4 bytes - ASCII "JFIF")
303    * Zero byte			(1 byte to terminate the ID string)
304    * Version Major, Minor	(2 bytes - 0x01, 0x01)
305    * Units			(1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm)
306    * Xdpu			(2 bytes - dots per unit horizontal)
307    * Ydpu			(2 bytes - dots per unit vertical)
308    * Thumbnail X size		(1 byte)
309    * Thumbnail Y size		(1 byte)
310    */
311 
312   emit_marker(cinfo, M_APP0);
313 
314   emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */
315 
316   emit_byte(cinfo, 0x4A);	/* Identifier: ASCII "JFIF" */
317   emit_byte(cinfo, 0x46);
318   emit_byte(cinfo, 0x49);
319   emit_byte(cinfo, 0x46);
320   emit_byte(cinfo, 0);
321   emit_byte(cinfo, 1);		/* Major version */
322   emit_byte(cinfo, 1);		/* Minor version */
323   emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */
324   emit_2bytes(cinfo, (int) cinfo->X_density);
325   emit_2bytes(cinfo, (int) cinfo->Y_density);
326   emit_byte(cinfo, 0);		/* No thumbnail image */
327   emit_byte(cinfo, 0);
328 }
329 
330 
331 LOCAL void
emit_com(compress_info_ptr cinfo,char * dataptr,size_t datalen)332 emit_com (compress_info_ptr cinfo, char * dataptr, size_t datalen)
333 /* Emit a COM marker */
334 {
335   if ((unsigned) datalen <= (unsigned) 65533) {	/* safety check */
336     emit_marker(cinfo, M_COM);
337 
338     emit_2bytes(cinfo, (int) (datalen + 2)); /* length */
339 
340     while (datalen--) {
341       emit_byte(cinfo, *dataptr);
342       dataptr++;
343     }
344   }
345 }
346 
347 
348 /*
349  * Write the file header.
350  */
351 
352 
353 METHODDEF void
write_file_header(compress_info_ptr cinfo)354 write_file_header (compress_info_ptr cinfo)
355 {
356   char qt_in_use[NUM_QUANT_TBLS];
357   int i, prec;
358   boolean is_baseline;
359 
360   emit_marker(cinfo, M_SOI);	/* first the SOI */
361 
362   if (cinfo->write_JFIF_header)	/* next an optional JFIF APP0 */
363     emit_jfif_app0(cinfo);
364 
365   if (cinfo->comment_text != NULL) /* and an optional COM block */
366     emit_com(cinfo, cinfo->comment_text,
367 	     (size_t) (strlen(cinfo->comment_text)));
368 
369   /* Emit DQT for each quantization table. */
370   /* Note that doing it here means we can't adjust the QTs on-the-fly. */
371   /* If we did want to do that, we'd have a problem with checking precision */
372   /* for the is_baseline determination. */
373 
374   for (i = 0; i < NUM_QUANT_TBLS; i++)
375     qt_in_use[i] = 0;
376 
377   for (i = 0; i < cinfo->num_components; i++)
378     qt_in_use[cinfo->comp_info[i].quant_tbl_no] = 1;
379 
380   prec = 0;
381   for (i = 0; i < NUM_QUANT_TBLS; i++) {
382     if (qt_in_use[i])
383       prec += emit_dqt(cinfo, i);
384   }
385   /* now prec is nonzero iff there are any 16-bit quant tables. */
386 
387   /* Check for a non-baseline specification. */
388   /* Note we assume that Huffman table numbers won't be changed later. */
389   is_baseline = TRUE;
390   if (cinfo->arith_code || (cinfo->data_precision != 8))
391     is_baseline = FALSE;
392   for (i = 0; i < cinfo->num_components; i++) {
393     if (cinfo->comp_info[i].dc_tbl_no > 1 || cinfo->comp_info[i].ac_tbl_no > 1)
394       is_baseline = FALSE;
395   }
396   if (prec && is_baseline) {
397     is_baseline = FALSE;
398     /* If it's baseline except for quantizer size, warn the user */
399     TRACEMS(cinfo->emethods, 0,
400 	    "Caution: quantization tables are too coarse for baseline JPEG");
401   }
402 
403 
404   /* Emit the proper SOF marker */
405   if (cinfo->arith_code)
406     emit_sof(cinfo, M_SOF9);	/* SOF code for arithmetic coding */
407   else if (is_baseline)
408     emit_sof(cinfo, M_SOF0);	/* SOF code for baseline implementation */
409   else
410     emit_sof(cinfo, M_SOF1);	/* SOF code for non-baseline Huffman file */
411 }
412 
413 
414 /*
415  * Write the start of a scan (everything through the SOS marker).
416  */
417 
418 METHODDEF void
write_scan_header(compress_info_ptr cinfo)419 write_scan_header (compress_info_ptr cinfo)
420 {
421   int i;
422 
423   if (cinfo->arith_code) {
424     /* Emit arith conditioning info.  We will have some duplication
425      * if the file has multiple scans, but it's so small it's hardly
426      * worth worrying about.
427      */
428     emit_dac(cinfo);
429   } else {
430     /* Emit Huffman tables.  Note that emit_dht takes care of
431      * suppressing duplicate tables.
432      */
433     for (i = 0; i < cinfo->comps_in_scan; i++) {
434       emit_dht(cinfo, cinfo->cur_comp_info[i]->dc_tbl_no, FALSE);
435       emit_dht(cinfo, cinfo->cur_comp_info[i]->ac_tbl_no, TRUE);
436     }
437   }
438 
439   /* Emit DRI if required --- note that DRI value could change for each scan.
440    * If it doesn't, a tiny amount of space is wasted in multiple-scan files.
441    * We assume DRI will never be nonzero for one scan and zero for a later one.
442    */
443   if (cinfo->restart_interval)
444     emit_dri(cinfo);
445 
446   emit_sos(cinfo);
447 }
448 
449 
450 /*
451  * Write some bytes of compressed data within a scan.
452  */
453 
454 METHODDEF void
write_jpeg_data(compress_info_ptr cinfo,char * dataptr,int datacount)455 write_jpeg_data (compress_info_ptr cinfo, char *dataptr, int datacount)
456 {
457   WRITE_BYTES(cinfo, dataptr, datacount);
458 }
459 
460 
461 /*
462  * Finish up after a compressed scan (series of write_jpeg_data calls).
463  */
464 
465 METHODDEF void
write_scan_trailer(compress_info_ptr cinfo)466 write_scan_trailer (compress_info_ptr cinfo)
467 {
468   /* no work needed in this format */
469 }
470 
471 
472 /*
473  * Finish up at the end of the file.
474  */
475 
476 METHODDEF void
write_file_trailer(compress_info_ptr cinfo)477 write_file_trailer (compress_info_ptr cinfo)
478 {
479   emit_marker(cinfo, M_EOI);
480   /* Make sure we wrote the output file OK */
481   CHECK_OUTPUT(cinfo);
482 }
483 
484 
485 /*
486  * The method selection routine for standard JPEG header writing.
487  * This should be called from c_ui_method_selection if appropriate.
488  */
489 
490 GLOBAL void
jselwjfif(compress_info_ptr cinfo)491 jselwjfif (compress_info_ptr cinfo)
492 {
493   cinfo->methods->write_file_header = write_file_header;
494   cinfo->methods->write_scan_header = write_scan_header;
495   cinfo->methods->write_jpeg_data = write_jpeg_data;
496   cinfo->methods->write_scan_trailer = write_scan_trailer;
497   cinfo->methods->write_file_trailer = write_file_trailer;
498 }
499 
500 #endif /* JFIF_SUPPORTED */
501