@@ -103,6 +103,10 @@ typedef struct _VipsForeignSaveJpeg {
103
103
*/
104
104
int quant_table ;
105
105
106
+ /* Use an MCU restart interval.
107
+ */
108
+ int restart_interval ;
109
+
106
110
} VipsForeignSaveJpeg ;
107
111
108
112
typedef VipsForeignSaveClass VipsForeignSaveJpegClass ;
@@ -231,6 +235,14 @@ vips_foreign_save_jpeg_class_init( VipsForeignSaveJpegClass *class )
231
235
G_STRUCT_OFFSET ( VipsForeignSaveJpeg , subsample_mode ),
232
236
VIPS_TYPE_FOREIGN_SUBSAMPLE ,
233
237
VIPS_FOREIGN_SUBSAMPLE_AUTO );
238
+
239
+ VIPS_ARG_INT ( class , "restart_interval" , 20 ,
240
+ _ ( "Restart interval" ),
241
+ _ ( "Add restart markers every specified number of mcu" ),
242
+ VIPS_ARGUMENT_OPTIONAL_INPUT ,
243
+ G_STRUCT_OFFSET ( VipsForeignSaveJpeg , restart_interval ),
244
+ 0 , INT_MAX , 0 );
245
+
234
246
}
235
247
236
248
static void
@@ -268,7 +280,8 @@ vips_foreign_save_jpeg_target_build( VipsObject *object )
268
280
jpeg -> Q , jpeg -> profile , jpeg -> optimize_coding ,
269
281
jpeg -> interlace , save -> strip , jpeg -> trellis_quant ,
270
282
jpeg -> overshoot_deringing , jpeg -> optimize_scans ,
271
- jpeg -> quant_table , jpeg -> subsample_mode ) )
283
+ jpeg -> quant_table , jpeg -> subsample_mode ,
284
+ jpeg -> restart_interval ) )
272
285
return ( -1 );
273
286
274
287
return ( 0 );
@@ -334,7 +347,8 @@ vips_foreign_save_jpeg_file_build( VipsObject *object )
334
347
jpeg -> Q , jpeg -> profile , jpeg -> optimize_coding ,
335
348
jpeg -> interlace , save -> strip , jpeg -> trellis_quant ,
336
349
jpeg -> overshoot_deringing , jpeg -> optimize_scans ,
337
- jpeg -> quant_table , jpeg -> subsample_mode ) ) {
350
+ jpeg -> quant_table , jpeg -> subsample_mode ,
351
+ jpeg -> restart_interval ) ) {
338
352
VIPS_UNREF ( target );
339
353
return ( -1 );
340
354
}
@@ -404,7 +418,8 @@ vips_foreign_save_jpeg_buffer_build( VipsObject *object )
404
418
jpeg -> Q , jpeg -> profile , jpeg -> optimize_coding ,
405
419
jpeg -> interlace , save -> strip , jpeg -> trellis_quant ,
406
420
jpeg -> overshoot_deringing , jpeg -> optimize_scans ,
407
- jpeg -> quant_table , jpeg -> subsample_mode ) ) {
421
+ jpeg -> quant_table , jpeg -> subsample_mode ,
422
+ jpeg -> restart_interval ) ) {
408
423
VIPS_UNREF ( target );
409
424
return ( -1 );
410
425
}
@@ -477,7 +492,8 @@ vips_foreign_save_jpeg_mime_build( VipsObject *object )
477
492
jpeg -> Q , jpeg -> profile , jpeg -> optimize_coding ,
478
493
jpeg -> interlace , save -> strip , jpeg -> trellis_quant ,
479
494
jpeg -> overshoot_deringing , jpeg -> optimize_scans ,
480
- jpeg -> quant_table , jpeg -> subsample_mode ) ) {
495
+ jpeg -> quant_table , jpeg -> subsample_mode ,
496
+ jpeg -> restart_interval ) ) {
481
497
VIPS_UNREF ( target );
482
498
return ( -1 );
483
499
}
@@ -534,6 +550,7 @@ vips_foreign_save_jpeg_mime_init( VipsForeignSaveJpegMime *mime )
534
550
* * @overshoot_deringing: %gboolean, overshoot samples with extreme values
535
551
* * @optimize_scans: %gboolean, split DCT coefficients into separate scans
536
552
* * @quant_table: %gint, quantization table index
553
+ * * @restart_interval: %gint, restart interval in mcu
537
554
*
538
555
* Write a VIPS image to a file as JPEG.
539
556
*
@@ -604,6 +621,12 @@ vips_foreign_save_jpeg_mime_init( VipsForeignSaveJpegMime *mime )
604
621
* For maximum compression with mozjpeg, a useful set of options is `strip,
605
622
* optimize-coding, interlace, optimize-scans, trellis-quant, quant_table=3`.
606
623
*
624
+ * By default, the output stream won't have restart markers. If a non-zero
625
+ * restart_interval is specified, a restart marker will be added after each
626
+ * specified number of MCU blocks. This makes the stream more recoverable
627
+ * if there are transmission errors, but also allows for some decoders to read
628
+ * part of the JPEG without decoding the whole stream.
629
+ *
607
630
* The image is automatically converted to RGB, Monochrome or CMYK before
608
631
* saving.
609
632
*
@@ -650,6 +673,7 @@ vips_jpegsave( VipsImage *in, const char *filename, ... )
650
673
* * @overshoot_deringing: %gboolean, overshoot samples with extreme values
651
674
* * @optimize_scans: %gboolean, split DCT coefficients into separate scans
652
675
* * @quant_table: %gint, quantization table index
676
+ * * @restart_interval: %gint, restart interval in mcu
653
677
*
654
678
* As vips_jpegsave(), but save to a target.
655
679
*
@@ -689,6 +713,7 @@ vips_jpegsave_target( VipsImage *in, VipsTarget *target, ... )
689
713
* * @overshoot_deringing: %gboolean, overshoot samples with extreme values
690
714
* * @optimize_scans: %gboolean, split DCT coefficients into separate scans
691
715
* * @quant_table: %gint, quantization table index
716
+ * * @restart_interval: %gint, restart interval in mcu
692
717
*
693
718
* As vips_jpegsave(), but save to a memory buffer.
694
719
*
@@ -745,6 +770,7 @@ vips_jpegsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
745
770
* * @overshoot_deringing: %gboolean, overshoot samples with extreme values
746
771
* * @optimize_scans: %gboolean, split DCT coefficients into separate scans
747
772
* * @quant_table: %gint, quantization table index
773
+ * * @restart_interval: %gint, restart interval in mcu
748
774
*
749
775
* As vips_jpegsave(), but save as a mime jpeg on stdout.
750
776
*
0 commit comments