cgifsave: add support for interlaced GIF write (#2984)
* cgifsave: add support for interlaced GIF write note: cgif >= v0.3.0 is required * switch to warning instead of error * add test * fix test
This commit is contained in:
parent
0029b3c416
commit
0b70145d99
@ -83,6 +83,7 @@ typedef struct _VipsForeignSaveCgif {
|
|||||||
int bitdepth;
|
int bitdepth;
|
||||||
double interframe_maxerror;
|
double interframe_maxerror;
|
||||||
gboolean reoptimise;
|
gboolean reoptimise;
|
||||||
|
gboolean interlace;
|
||||||
double interpalette_maxerror;
|
double interpalette_maxerror;
|
||||||
VipsTarget *target;
|
VipsTarget *target;
|
||||||
|
|
||||||
@ -601,6 +602,16 @@ vips_foreign_save_cgif_write_frame( VipsForeignSaveCgif *cgif )
|
|||||||
frame_config.numLocalPaletteEntries = n_colours;
|
frame_config.numLocalPaletteEntries = n_colours;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Write an interlaced GIF, if requested.
|
||||||
|
*/
|
||||||
|
if( cgif->interlace ) {
|
||||||
|
#ifdef HAVE_CGIF_FRAME_ATTR_INTERLACED
|
||||||
|
frame_config.attrFlags |= CGIF_FRAME_ATTR_INTERLACED;
|
||||||
|
#else /*!HAVE_CGIF_FRAME_ATTR_INTERLACED*/
|
||||||
|
g_warning( "%s: cgif >= v0.3.0 required for interlaced GIF write", class->nickname );
|
||||||
|
#endif /*HAVE_CGIF_FRAME_ATTR_INTERLACED*/
|
||||||
|
}
|
||||||
|
|
||||||
/* Write frame to cgif.
|
/* Write frame to cgif.
|
||||||
*/
|
*/
|
||||||
frame_config.pImageData = cgif->index;
|
frame_config.pImageData = cgif->index;
|
||||||
@ -893,6 +904,14 @@ vips_foreign_save_cgif_class_init( VipsForeignSaveCgifClass *class )
|
|||||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
G_STRUCT_OFFSET( VipsForeignSaveCgif, interpalette_maxerror ),
|
G_STRUCT_OFFSET( VipsForeignSaveCgif, interpalette_maxerror ),
|
||||||
0, 256, 3.0 );
|
0, 256, 3.0 );
|
||||||
|
|
||||||
|
VIPS_ARG_BOOL( class, "interlace", 16,
|
||||||
|
_( "Interlaced" ),
|
||||||
|
_( "Generate an interlaced (progressive) GIF" ),
|
||||||
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignSaveCgif, interlace ),
|
||||||
|
FALSE );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -903,6 +922,7 @@ vips_foreign_save_cgif_init( VipsForeignSaveCgif *gif )
|
|||||||
gif->bitdepth = 8;
|
gif->bitdepth = 8;
|
||||||
gif->interframe_maxerror = 0.0;
|
gif->interframe_maxerror = 0.0;
|
||||||
gif->reoptimise = FALSE;
|
gif->reoptimise = FALSE;
|
||||||
|
gif->interlace = FALSE;
|
||||||
gif->interpalette_maxerror = 3.0;
|
gif->interpalette_maxerror = 3.0;
|
||||||
gif->mode = VIPS_FOREIGN_SAVE_CGIF_MODE_GLOBAL;
|
gif->mode = VIPS_FOREIGN_SAVE_CGIF_MODE_GLOBAL;
|
||||||
}
|
}
|
||||||
@ -1087,6 +1107,7 @@ vips_foreign_save_cgif_buffer_init( VipsForeignSaveCgifBuffer *buffer )
|
|||||||
* * @bitdepth: %gint, number of bits per pixel
|
* * @bitdepth: %gint, number of bits per pixel
|
||||||
* * @interframe_maxerror: %gdouble, maximum inter-frame error for transparency
|
* * @interframe_maxerror: %gdouble, maximum inter-frame error for transparency
|
||||||
* * @reoptimise: %gboolean, reoptimise colour palettes
|
* * @reoptimise: %gboolean, reoptimise colour palettes
|
||||||
|
* * @interlace: %gboolean, write an interlaced (progressive) GIF
|
||||||
* * @interpalette_maxerror: %gdouble, maximum inter-palette error for palette
|
* * @interpalette_maxerror: %gdouble, maximum inter-palette error for palette
|
||||||
* reusage
|
* reusage
|
||||||
*
|
*
|
||||||
@ -1110,6 +1131,10 @@ vips_foreign_save_cgif_buffer_init( VipsForeignSaveCgifBuffer *buffer )
|
|||||||
* @interpalette_maxerror to set the threshold below which one of the previously
|
* @interpalette_maxerror to set the threshold below which one of the previously
|
||||||
* generated palettes will be reused.
|
* generated palettes will be reused.
|
||||||
*
|
*
|
||||||
|
* If @interlace is TRUE, the GIF file will be interlaced (progressive GIF).
|
||||||
|
* These files may be better for display over a slow network
|
||||||
|
* conection, but need more memory to encode.
|
||||||
|
*
|
||||||
* See also: vips_image_new_from_file().
|
* See also: vips_image_new_from_file().
|
||||||
*
|
*
|
||||||
* Returns: 0 on success, -1 on error.
|
* Returns: 0 on success, -1 on error.
|
||||||
@ -1141,6 +1166,7 @@ vips_gifsave( VipsImage *in, const char *filename, ... )
|
|||||||
* * @bitdepth: %gint, number of bits per pixel
|
* * @bitdepth: %gint, number of bits per pixel
|
||||||
* * @interframe_maxerror: %gdouble, maximum inter-frame error for transparency
|
* * @interframe_maxerror: %gdouble, maximum inter-frame error for transparency
|
||||||
* * @reoptimise: %gboolean, reoptimise colour palettes
|
* * @reoptimise: %gboolean, reoptimise colour palettes
|
||||||
|
* * @interlace: %gboolean, write an interlaced (progressive) GIF
|
||||||
* * @interpalette_maxerror: %gdouble, maximum inter-palette error for palette
|
* * @interpalette_maxerror: %gdouble, maximum inter-palette error for palette
|
||||||
* reusage
|
* reusage
|
||||||
*
|
*
|
||||||
@ -1195,6 +1221,7 @@ vips_gifsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
|
|||||||
* * @bitdepth: %gint, number of bits per pixel
|
* * @bitdepth: %gint, number of bits per pixel
|
||||||
* * @interframe_maxerror: %gdouble, maximum inter-frame error for transparency
|
* * @interframe_maxerror: %gdouble, maximum inter-frame error for transparency
|
||||||
* * @reoptimise: %gboolean, reoptimise colour palettes
|
* * @reoptimise: %gboolean, reoptimise colour palettes
|
||||||
|
* * @interlace: %gboolean, write an interlaced (progressive) GIF
|
||||||
* * @interpalette_maxerror: %gdouble, maximum inter-palette error for palette
|
* * @interpalette_maxerror: %gdouble, maximum inter-palette error for palette
|
||||||
* reusage
|
* reusage
|
||||||
*
|
*
|
||||||
|
@ -259,6 +259,9 @@ if quantisation_package.found()
|
|||||||
if cc.compiles('#include <cgif.h>\nint i = CGIF_ATTR_NO_LOOP;', name: 'Has CGIF_ATTR_NO_LOOP', dependencies: cgif_dep)
|
if cc.compiles('#include <cgif.h>\nint i = CGIF_ATTR_NO_LOOP;', name: 'Has CGIF_ATTR_NO_LOOP', dependencies: cgif_dep)
|
||||||
cfg_var.set('HAVE_CGIF_ATTR_NO_LOOP', '1')
|
cfg_var.set('HAVE_CGIF_ATTR_NO_LOOP', '1')
|
||||||
endif
|
endif
|
||||||
|
if cc.compiles('#include <cgif.h>\nint i = CGIF_FRAME_ATTR_INTERLACED;', name: 'Has CGIF_FRAME_ATTR_INTERLACED', dependencies: cgif_dep)
|
||||||
|
cfg_var.set('HAVE_CGIF_FRAME_ATTR_INTERLACED', '1')
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -1478,6 +1478,16 @@ class TestForeign:
|
|||||||
# FIXME ... this requires cgif0.3 or later for fixed loop support
|
# FIXME ... this requires cgif0.3 or later for fixed loop support
|
||||||
# assert x1.get("loop") == x2.get("loop")
|
# assert x1.get("loop") == x2.get("loop")
|
||||||
|
|
||||||
|
# Interlaced write
|
||||||
|
x1 = pyvips.Image.new_from_file(GIF_FILE, n=-1)
|
||||||
|
b1 = x1.gifsave_buffer(interlace=False)
|
||||||
|
b2 = x1.gifsave_buffer(interlace=True)
|
||||||
|
# Interlaced GIFs are usually larger in file size
|
||||||
|
# FIXME ... cgif v0.3 or later required for interlaced write.
|
||||||
|
# If interlaced write is not supported b2 and b1 are expected to be
|
||||||
|
# of the same file size.
|
||||||
|
assert len(b2) >= len(b1)
|
||||||
|
|
||||||
# Reducing dither will typically reduce file size (and quality)
|
# Reducing dither will typically reduce file size (and quality)
|
||||||
little_dither = self.colour.gifsave_buffer(dither=0.1, effort=1)
|
little_dither = self.colour.gifsave_buffer(dither=0.1, effort=1)
|
||||||
large_dither = self.colour.gifsave_buffer(dither=0.9, effort=1)
|
large_dither = self.colour.gifsave_buffer(dither=0.9, effort=1)
|
||||||
|
Loading…
Reference in New Issue
Block a user