polishing

This commit is contained in:
John Cupitt 2016-11-08 14:42:54 +00:00
parent b56b888bf0
commit d5934d606a
7 changed files with 74 additions and 52 deletions

13
TODO
View File

@ -1,18 +1,5 @@
- test with libwebp 0.3, the earliest that supports libwebpmux - test with libwebp 0.3, the earliest that supports libwebpmux
test with ubuntu ... seems to have libwebpmux2
test webp metadata read and write
webpsave should support strip
update docs
need to check for >4gb overflow ... use guint64 for all size calculations
webpsave needs hooking up to exif.c
- not sure about utf8 error messages on win - not sure about utf8 error messages on win

View File

@ -220,11 +220,13 @@ int vips__webp_read_buffer( const void *buf, size_t len,
int vips__webp_write_file( VipsImage *out, const char *filename, int vips__webp_write_file( VipsImage *out, const char *filename,
int Q, gboolean lossless, VipsForeignWebpPreset preset, int Q, gboolean lossless, VipsForeignWebpPreset preset,
gboolean smart_subsample, gboolean near_lossless, gboolean smart_subsample, gboolean near_lossless,
int alpha_q ); int alpha_q,
gboolean strip );
int vips__webp_write_buffer( VipsImage *out, void **buf, size_t *len, int vips__webp_write_buffer( VipsImage *out, void **buf, size_t *len,
int Q, gboolean lossless, VipsForeignWebpPreset preset, int Q, gboolean lossless, VipsForeignWebpPreset preset,
gboolean smart_subsample, gboolean near_lossless, gboolean smart_subsample, gboolean near_lossless,
int alpha_q ); int alpha_q,
gboolean strip );
int vips__openslide_isslide( const char *filename ); int vips__openslide_isslide( const char *filename );
int vips__openslide_read_header( const char *filename, VipsImage *out, int vips__openslide_read_header( const char *filename, VipsImage *out,

View File

@ -89,8 +89,12 @@ get_preset( VipsForeignWebpPreset preset )
typedef struct { typedef struct {
uint8_t *mem; uint8_t *mem;
size_t size;
size_t max_size; /* We want to be able to detect >4gb even on machines that have size_t
* as uint32.
*/
guint64 size;
guint64 max_size;
} VipsWebPWriter; } VipsWebPWriter;
static void static void
@ -103,21 +107,33 @@ vips_webp_writer_init( VipsWebPWriter *writer )
static int static int
vips_webp_writer_append( VipsWebPWriter *writer, vips_webp_writer_append( VipsWebPWriter *writer,
const uint8_t *data, size_t data_size ) const uint8_t *data, guint64 data_size )
{ {
size_t next_size; guint64 next_size;
next_size = writer->size + data_size; next_size = writer->size + data_size;
if( next_size > writer->max_size ) { if( next_size > writer->max_size ) {
uint8_t *new_mem; uint8_t *new_mem;
const size_t next_max_size = const guint64 next_max_size =
VIPS_MAX( 8192, VIPS_MAX( next_size, VIPS_MAX( 8192, VIPS_MAX( next_size,
writer->max_size * 2 ) ); writer->max_size * 2 ) );
if( !(new_mem = (uint8_t *) /* We should let it creep up to 4gb rather than just
g_try_realloc( writer->mem, next_max_size )) ) * blocking when max goes over, but no one will make a >2gb
* webp image.
*/
if( next_max_size > UINT_MAX ) {
vips_error( "webp",
"%s", _( "output webp image too large" ) );
return( 0 ); return( 0 );
}
if( !(new_mem = (uint8_t *)
g_try_realloc( writer->mem, next_max_size )) ) {
vips_error( "webp", "%s", _( "out of memory" ) );
return( 0 );
}
writer->mem = new_mem; writer->mem = new_mem;
writer->max_size = next_max_size; writer->max_size = next_max_size;
@ -167,7 +183,7 @@ vips_webp_writer_appendcc( VipsWebPWriter *writer, const char buf[4] )
static gboolean static gboolean
vips_webp_writer_appendc( VipsWebPWriter *writer, vips_webp_writer_appendc( VipsWebPWriter *writer,
const char fourcc[4], const uint8_t *data, size_t data_size ) const char fourcc[4], const uint8_t *data, guint64 data_size )
{ {
const int zero = 0; const int zero = 0;
gboolean need_padding = (data_size & 1) != 0; gboolean need_padding = (data_size & 1) != 0;
@ -284,7 +300,7 @@ static int
vips_webp_add_chunk( VipsWebPWriter *writer, VipsImage *image, vips_webp_add_chunk( VipsWebPWriter *writer, VipsImage *image,
const char *vips, const char webp[4] ) const char *vips, const char webp[4] )
{ {
if( vips_image_get_typeof( image, vips) ) { if( vips_image_get_typeof( image, vips ) ) {
void *data; void *data;
size_t length; size_t length;
@ -345,6 +361,11 @@ vips_webp_add_metadata( VipsWebPWriter *writer, VipsImage *image )
guint64 new_size; guint64 new_size;
VipsWebPWriter new; VipsWebPWriter new;
/* Rebuild the EXIF block, if any, ready for writing.
*/
if( vips__exif_update( image ) )
return( -1 );
/* We have to find the size of the block we will write before we can /* We have to find the size of the block we will write before we can
* start to write it. * start to write it.
*/ */
@ -474,7 +495,7 @@ int
vips__webp_write_file( VipsImage *in, const char *filename, vips__webp_write_file( VipsImage *in, const char *filename,
int Q, gboolean lossless, VipsForeignWebpPreset preset, int Q, gboolean lossless, VipsForeignWebpPreset preset,
gboolean smart_subsample, gboolean near_lossless, gboolean smart_subsample, gboolean near_lossless,
int alpha_q ) int alpha_q, gboolean strip )
{ {
WebPPicture pic; WebPPicture pic;
VipsWebPWriter writer; VipsWebPWriter writer;
@ -499,7 +520,8 @@ vips__webp_write_file( VipsImage *in, const char *filename,
WebPPictureFree( &pic ); WebPPictureFree( &pic );
if( vips_webp_add_metadata( &writer, in ) ) { if( !strip &&
vips_webp_add_metadata( &writer, in ) ) {
vips_webp_writer_unset( &writer ); vips_webp_writer_unset( &writer );
return( -1 ); return( -1 );
} }
@ -525,7 +547,7 @@ int
vips__webp_write_buffer( VipsImage *in, void **obuf, size_t *olen, vips__webp_write_buffer( VipsImage *in, void **obuf, size_t *olen,
int Q, gboolean lossless, VipsForeignWebpPreset preset, int Q, gboolean lossless, VipsForeignWebpPreset preset,
gboolean smart_subsample, gboolean near_lossless, gboolean smart_subsample, gboolean near_lossless,
int alpha_q ) int alpha_q, gboolean strip )
{ {
WebPPicture pic; WebPPicture pic;
VipsWebPWriter writer; VipsWebPWriter writer;
@ -549,7 +571,8 @@ vips__webp_write_buffer( VipsImage *in, void **obuf, size_t *olen,
WebPPictureFree( &pic ); WebPPictureFree( &pic );
if( vips_webp_add_metadata( &writer, in ) ) { if( !strip &&
vips_webp_add_metadata( &writer, in ) ) {
vips_webp_writer_unset( &writer ); vips_webp_writer_unset( &writer );
return( -1 ); return( -1 );
} }

View File

@ -236,7 +236,7 @@ read_header( Read *read, VipsImage *out )
WebPMux *mux; WebPMux *mux;
int i; int i;
/* We have to parse the whole file again to get the ICC profile out. /* We have to parse the whole file again to get the metadata out.
*/ */
bitstream.bytes = read->data; bitstream.bytes = read->data;
bitstream.size = read->length; bitstream.size = read->length;
@ -245,7 +245,7 @@ read_header( Read *read, VipsImage *out )
return( -1 ); return( -1 );
} }
for( i = 0; i < VIPS_NUMBER( vips__webp_names ); i++ ) { for( i = 0; i < vips__n_webp_names; i++ ) {
const char *vips = vips__webp_names[i].vips; const char *vips = vips__webp_names[i].vips;
const char *webp = vips__webp_names[i].webp; const char *webp = vips__webp_names[i].webp;

View File

@ -293,6 +293,9 @@ vips_foreign_load_webp_buffer_init( VipsForeignLoadWebpBuffer *buffer )
* *
* Use @shrink to specify a shrink-on-load factor. * Use @shrink to specify a shrink-on-load factor.
* *
* If libwebpmux is available, image metadata is also read. The loader supports
* ICC, EXIF and XMP metadata.
*
* 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.

View File

@ -191,7 +191,7 @@ vips_foreign_save_webp_file_build( VipsObject *object )
if( vips__webp_write_file( save->ready, file->filename, if( vips__webp_write_file( save->ready, file->filename,
webp->Q, webp->lossless, webp->preset, webp->Q, webp->lossless, webp->preset,
webp->smart_subsample, webp->near_lossless, webp->smart_subsample, webp->near_lossless,
webp->alpha_q ) ) webp->alpha_q, save->strip ) )
return( -1 ); return( -1 );
return( 0 ); return( 0 );
@ -255,7 +255,7 @@ vips_foreign_save_webp_buffer_build( VipsObject *object )
if( vips__webp_write_buffer( save->ready, &obuf, &olen, if( vips__webp_write_buffer( save->ready, &obuf, &olen,
webp->Q, webp->lossless, webp->preset, webp->Q, webp->lossless, webp->preset,
webp->smart_subsample, webp->near_lossless, webp->smart_subsample, webp->near_lossless,
webp->alpha_q ) ) webp->alpha_q, save->strip ) )
return( -1 ); return( -1 );
/* obuf is a g_free() buffer, not vips_free(). /* obuf is a g_free() buffer, not vips_free().
@ -320,7 +320,7 @@ vips_foreign_save_webp_mime_build( VipsObject *object )
if( vips__webp_write_buffer( save->ready, &obuf, &olen, if( vips__webp_write_buffer( save->ready, &obuf, &olen,
webp->Q, webp->lossless, webp->preset, webp->Q, webp->lossless, webp->preset,
webp->smart_subsample, webp->near_lossless, webp->smart_subsample, webp->near_lossless,
webp->alpha_q ) ) webp->alpha_q, save->strip ) )
return( -1 ); return( -1 );
printf( "Content-length: %zu\r\n", olen ); printf( "Content-length: %zu\r\n", olen );
@ -363,12 +363,13 @@ vips_foreign_save_webp_mime_init( VipsForeignSaveWebpMime *mime )
* *
* Optional arguments: * Optional arguments:
* *
* * @Q: %gint quality factor * * @Q: %gint, quality factor
* * @lossless: %gboolean enables lossless compression * * @lossless: %gboolean, enables lossless compression
* * @preset: #VipsForeignWebpPreset choose lossy compression preset * * @preset: #VipsForeignWebpPreset, choose lossy compression preset
* * @smart_subsample: %gboolean enables high quality chroma subsampling * * @smart_subsample: %gboolean, enables high quality chroma subsampling
* * @near_lossless: %gboolean preprocess in lossless mode (controlled by Q) * * @near_lossless: %gboolean, preprocess in lossless mode (controlled by Q)
* * @alpha_q: %gint set alpha quality in lossless mode * * @alpha_q: %gint, set alpha quality in lossless mode
* * @strip: %gboolean, remove all metadata from image
* *
* Write an image to a file in WebP format. * Write an image to a file in WebP format.
* *
@ -386,6 +387,9 @@ vips_foreign_save_webp_mime_init( VipsForeignSaveWebpMime *mime )
* with @Q 80, 60, 40 or 20 to apply increasing amounts of preprocessing * with @Q 80, 60, 40 or 20 to apply increasing amounts of preprocessing
* which improves the near-lossless compression ratio by up to 50%. * which improves the near-lossless compression ratio by up to 50%.
* *
* The writer will attach ICC, EXIF and XMP metadata, unless @strip is set to
* %TRUE.
*
* See also: vips_webpload(), vips_image_write_to_file(). * See also: vips_webpload(), vips_image_write_to_file().
* *
* Returns: 0 on success, -1 on error. * Returns: 0 on success, -1 on error.
@ -412,12 +416,13 @@ vips_webpsave( VipsImage *in, const char *filename, ... )
* *
* Optional arguments: * Optional arguments:
* *
* * @Q: %gint quality factor * * @Q: %gint, quality factor
* * @lossless: %gboolean enables lossless compression * * @lossless: %gboolean, enables lossless compression
* * @preset: #VipsForeignWebpPreset choose lossy compression preset * * @preset: #VipsForeignWebpPreset, choose lossy compression preset
* * @smart_subsample: %gboolean enables high quality chroma subsampling * * @smart_subsample: %gboolean, enables high quality chroma subsampling
* * @near_lossless: %gboolean preprocess in lossless mode (controlled by Q) * * @near_lossless: %gboolean, preprocess in lossless mode (controlled by Q)
* * @alpha_q: %gint set alpha quality in lossless mode * * @alpha_q: %gint, set alpha quality in lossless mode
* * @strip: %gboolean, remove all metadata from image
* *
* As vips_webpsave(), but save to a memory buffer. * As vips_webpsave(), but save to a memory buffer.
* *
@ -464,12 +469,13 @@ vips_webpsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
* *
* Optional arguments: * Optional arguments:
* *
* * @Q: %gint quality factor * * @Q: %gint, quality factor
* * @lossless: %gboolean enables lossless compression * * @lossless: %gboolean, enables lossless compression
* * @preset: #VipsForeignWebpPreset choose lossy compression preset * * @preset: #VipsForeignWebpPreset, choose lossy compression preset
* * @smart_subsample: %gboolean enables high quality chroma subsampling * * @smart_subsample: %gboolean, enables high quality chroma subsampling
* * @near_lossless: %gboolean preprocess in lossless mode (controlled by Q) * * @near_lossless: %gboolean, preprocess in lossless mode (controlled by Q)
* * @alpha_q: %gint set alpha quality in lossless mode * * @alpha_q: %gint, set alpha quality in lossless mode
* * @strip: %gboolean, remove all metadata from image
* *
* As vips_webpsave(), but save as a mime webp on stdout. * As vips_webpsave(), but save as a mime webp on stdout.
* *

View File

@ -49,7 +49,8 @@ save_load() {
fi fi
if ! $vips copy $tmp/t1.$format $tmp/back.v ; then if ! $vips copy $tmp/t1.$format $tmp/back.v ; then
echo "read from $out failed" echo "read from $tmp/t1.format failed"
echo " (was written by $vips copy $in $tmp/t1.$format$mode)"
exit 1 exit 1
fi fi
} }