add "interlace" option to vips_jpegsave()

see https://github.com/jcupitt/libvips/issues/77
This commit is contained in:
John Cupitt 2013-10-21 12:16:33 +01:00
parent 30e6c27fd5
commit 0bfb23eca8
5 changed files with 39 additions and 10 deletions

View File

@ -2,6 +2,7 @@
- redone im_rotate_*mask45(), im_gauss_*mask*(), im_log_*mask() as classes - redone im_rotate_*mask45(), im_gauss_*mask*(), im_log_*mask() as classes
- vips_init() now does some ABI compat checking, though this change requires - vips_init() now does some ABI compat checking, though this change requires
an ABI break an ABI break
- add "interlace" option to vips_jpegsave()
18/10/13 started 7.36.3 18/10/13 started 7.36.3
- fix compiler warnings in ubuntu 13.10 - fix compiler warnings in ubuntu 13.10

View File

@ -1988,6 +1988,7 @@ vips_jpegload( const char *filename, VipsImage **out, ... )
* @Q: quality factor * @Q: quality factor
* @profile: attach this ICC profile * @profile: attach this ICC profile
* @optimize_coding: compute optimal Huffman coding tables * @optimize_coding: compute optimal Huffman coding tables
* @interlace: write an interlaced (progressive) jpeg
* *
* Write a VIPS image to a file as JPEG. * Write a VIPS image to a file as JPEG.
* *
@ -2012,6 +2013,13 @@ vips_jpegload( const char *filename, VipsImage **out, ... )
* IPCT as @VIPS_META_IPCT_NAME ("ipct-data") and XMP as VIPS_META_XMP_NAME * IPCT as @VIPS_META_IPCT_NAME ("ipct-data") and XMP as VIPS_META_XMP_NAME
* ("xmp-data") are coded and attached. * ("xmp-data") are coded and attached.
* *
* If @optimize_coding is set, the Huffman tables are optimised. This is
* sllightly slower and produces slightly smaller files.
*
* If @interlace is set, the jpeg files will be interlaced (progressive jpeg,
* in jpg parlance). These files may be better for display over a slow network
* conection, but need much more memory to encode and decode.
*
* See also: vips_jpegsave_buffer(), vips_image_write_file(). * See also: vips_jpegsave_buffer(), vips_image_write_file().
* *
* Returns: 0 on success, -1 on error. * Returns: 0 on success, -1 on error.
@ -2041,6 +2049,7 @@ vips_jpegsave( VipsImage *in, const char *filename, ... )
* @Q: JPEG quality factor * @Q: JPEG quality factor
* @profile: attach this ICC profile * @profile: attach this ICC profile
* @optimize_coding: compute optimal Huffman coding tables * @optimize_coding: compute optimal Huffman coding tables
* @interlace: write an interlaced (progressive) jpeg
* *
* As vips_jpegsave(), but save to a memory buffer. * As vips_jpegsave(), but save to a memory buffer.
* *

View File

@ -83,6 +83,10 @@ typedef struct _VipsForeignSaveJpeg {
*/ */
gboolean optimize_coding; gboolean optimize_coding;
/* Generate an interlaced (progressive, in jpg terminology) file.
*/
gboolean interlace;
} VipsForeignSaveJpeg; } VipsForeignSaveJpeg;
typedef VipsForeignSaveClass VipsForeignSaveJpegClass; typedef VipsForeignSaveClass VipsForeignSaveJpegClass;
@ -135,6 +139,13 @@ vips_foreign_save_jpeg_class_init( VipsForeignSaveJpegClass *class )
VIPS_ARGUMENT_OPTIONAL_INPUT, VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveJpeg, optimize_coding ), G_STRUCT_OFFSET( VipsForeignSaveJpeg, optimize_coding ),
FALSE ); FALSE );
VIPS_ARG_BOOL( class, "interlace", 13,
_( "interlace" ),
_( "Generate an interlaced (progressive) jpeg" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveJpeg, interlace ),
FALSE );
} }
static void static void
@ -169,7 +180,8 @@ vips_foreign_save_jpeg_file_build( VipsObject *object )
return( -1 ); return( -1 );
if( vips__jpeg_write_file( save->ready, file->filename, if( vips__jpeg_write_file( save->ready, file->filename,
jpeg->Q, jpeg->profile, jpeg->optimize_coding ) ) jpeg->Q, jpeg->profile, jpeg->optimize_coding,
jpeg->interlace ) )
return( -1 ); return( -1 );
return( 0 ); return( 0 );
@ -234,7 +246,8 @@ vips_foreign_save_jpeg_buffer_build( VipsObject *object )
return( -1 ); return( -1 );
if( vips__jpeg_write_buffer( save->ready, if( vips__jpeg_write_buffer( save->ready,
&obuf, &olen, jpeg->Q, jpeg->profile, jpeg->optimize_coding ) ) &obuf, &olen, jpeg->Q, jpeg->profile, jpeg->optimize_coding,
jpeg->interlace ) )
return( -1 ); return( -1 );
area = vips_area_new_blob( (VipsCallbackFn) vips_free, obuf, olen ); area = vips_area_new_blob( (VipsCallbackFn) vips_free, obuf, olen );
@ -295,7 +308,8 @@ vips_foreign_save_jpeg_mime_build( VipsObject *object )
return( -1 ); return( -1 );
if( vips__jpeg_write_buffer( save->ready, if( vips__jpeg_write_buffer( save->ready,
&obuf, &olen, jpeg->Q, jpeg->profile, jpeg->optimize_coding ) ) &obuf, &olen, jpeg->Q, jpeg->profile, jpeg->optimize_coding,
jpeg->interlace ) )
return( -1 ); return( -1 );
printf( "Content-length: %zd\r\n", olen ); printf( "Content-length: %zd\r\n", olen );

View File

@ -841,7 +841,7 @@ write_jpeg_block( REGION *region, Rect *area, void *a )
*/ */
static int static int
write_vips( Write *write, int qfac, const char *profile, write_vips( Write *write, int qfac, const char *profile,
gboolean optimize_coding ) gboolean optimize_coding, gboolean progressive )
{ {
VipsImage *in; VipsImage *in;
J_COLOR_SPACE space; J_COLOR_SPACE space;
@ -898,6 +898,11 @@ write_vips( Write *write, int qfac, const char *profile,
*/ */
write->cinfo.optimize_coding = optimize_coding; write->cinfo.optimize_coding = optimize_coding;
/* Enable progressive write.
*/
if( progressive )
jpeg_simple_progression( &write->cinfo );
/* Build compress tables. /* Build compress tables.
*/ */
jpeg_start_compress( &write->cinfo, TRUE ); jpeg_start_compress( &write->cinfo, TRUE );
@ -941,7 +946,7 @@ write_vips( Write *write, int qfac, const char *profile,
int int
vips__jpeg_write_file( VipsImage *in, vips__jpeg_write_file( VipsImage *in,
const char *filename, int Q, const char *profile, const char *filename, int Q, const char *profile,
gboolean optimize_coding ) gboolean optimize_coding, gboolean progressive )
{ {
Write *write; Write *write;
@ -971,7 +976,7 @@ vips__jpeg_write_file( VipsImage *in,
/* Convert! /* Convert!
*/ */
if( write_vips( write, Q, profile, optimize_coding ) ) { if( write_vips( write, Q, profile, optimize_coding, progressive ) ) {
write_destroy( write ); write_destroy( write );
return( -1 ); return( -1 );
} }
@ -1218,7 +1223,7 @@ buf_dest( j_compress_ptr cinfo, void **obuf, size_t *olen )
int int
vips__jpeg_write_buffer( VipsImage *in, vips__jpeg_write_buffer( VipsImage *in,
void **obuf, size_t *olen, int Q, const char *profile, void **obuf, size_t *olen, int Q, const char *profile,
gboolean optimize_coding ) gboolean optimize_coding, gboolean progressive )
{ {
Write *write; Write *write;
@ -1247,7 +1252,7 @@ vips__jpeg_write_buffer( VipsImage *in,
/* Convert! /* Convert!
*/ */
if( write_vips( write, Q, profile, optimize_coding ) ) { if( write_vips( write, Q, profile, optimize_coding, progressive ) ) {
write_destroy( write ); write_destroy( write );
return( -1 ); return( -1 );

View File

@ -39,10 +39,10 @@ extern const char *vips__jpeg_suffs[];
int vips__jpeg_write_file( VipsImage *in, int vips__jpeg_write_file( VipsImage *in,
const char *filename, int Q, const char *profile, const char *filename, int Q, const char *profile,
gboolean optimize_coding ); gboolean optimize_coding, gboolean progressive );
int vips__jpeg_write_buffer( VipsImage *in, int vips__jpeg_write_buffer( VipsImage *in,
void **obuf, size_t *olen, int Q, const char *profile, void **obuf, size_t *olen, int Q, const char *profile,
gboolean optimize_coding ); gboolean optimize_coding, gboolean progressive );
int vips__isjpeg( const char *filename ); int vips__isjpeg( const char *filename );
int vips__jpeg_read_file( const char *name, VipsImage *out, int vips__jpeg_read_file( const char *name, VipsImage *out,