diff --git a/ChangeLog b/ChangeLog index ba178acf..e8646834 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ - add "interlace" option to vips_jpegsave() - remove vips_image_copy_fields() and vips_demand_hint() and add vips_image_pipeline() to do both jobs +- vipsthumbnail allows non-square bounding boxes, thanks seth 18/10/13 started 7.36.3 - fix compiler warnings in ubuntu 13.10 diff --git a/man/vipsthumbnail.1 b/man/vipsthumbnail.1 index 91f997fc..4dfee8bd 100644 --- a/man/vipsthumbnail.1 +++ b/man/vipsthumbnail.1 @@ -40,7 +40,8 @@ Set the output thumbnail size to .B N x .B N -pixels. The image is shrunk so that it just fits within this area, Images +pixels. You can use MxN to specify a rectangular bounding box. +The image is shrunk so that it just fits within this area, images which are smaller than this are expanded. .TP diff --git a/tools/vipsthumbnail.c b/tools/vipsthumbnail.c index 4c618705..9b589558 100644 --- a/tools/vipsthumbnail.c +++ b/tools/vipsthumbnail.c @@ -53,7 +53,9 @@ #include -static int thumbnail_size = 128; +static char *thumbnail_size = "128"; +static int thumbnail_width = 128; +static int thumbnail_height = 128; static char *output_format = "tn_%s.jpg"; static char *interpolator = "bilinear"; static char *export_profile = NULL; @@ -68,8 +70,8 @@ static gboolean nodelete_profile = FALSE; static GOptionEntry options[] = { { "size", 's', 0, - G_OPTION_ARG_INT, &thumbnail_size, - N_( "set thumbnail size to SIZE" ), + G_OPTION_ARG_STRING, &thumbnail_size, + N_( "shrink to SIZE or to WIDTHxHEIGHT" ), N_( "SIZE" ) }, { "output", 'o', 0, G_OPTION_ARG_STRING, &output_format, @@ -115,13 +117,14 @@ static GOptionEntry options[] = { static int calculate_shrink( int width, int height, double *residual ) { - /* We shrink to make the largest dimension equal to size. + /* Calculate the horizontal and vertical shrink we'd need to fit the + * image to the bounding box, and pick the biggest. */ - int dimension = IM_MAX( width, height ); + double horizontal = (double) width / thumbnail_width; + double vertical = (double) height / thumbnail_height; + double factor = VIPS_MAX( horizontal, vertical ); - double factor = dimension / (double) thumbnail_size; - - /* If the shrink factor is <=1.0, we need to zoom rather than shrink. + /* If the shrink factor is <= 1.0, we need to zoom rather than shrink. * Just set the factor to 1 in this case. */ double factor2 = factor < 1.0 ? 1.0 : factor; @@ -130,14 +133,15 @@ calculate_shrink( int width, int height, double *residual ) */ int shrink = floor( factor2 ); - /* Size after int shrink. - */ - int isize = floor( dimension / shrink ); + if( residual ) { + /* Width after int shrink. + */ + int iwidth = width / shrink; - /* Therefore residual scale factor is. - */ - if( residual ) - *residual = thumbnail_size / (double) isize; + /* Therefore residual scale factor is. + */ + *residual = (width / factor) / iwidth; + } return( shrink ); } @@ -555,6 +559,15 @@ main( int argc, char **argv ) g_option_context_free( context ); + if( sscanf( thumbnail_size, "%d x %d", + &thumbnail_width, &thumbnail_height ) != 2 ) { + if( sscanf( thumbnail_size, "%d", &thumbnail_width ) != 1 ) + vips_error_exit( "unable to parse size \"%s\" -- " + "use eg. 128 or 200x300", thumbnail_size ); + + thumbnail_height = thumbnail_width; + } + for( i = 1; i < argc; i++ ) { /* Hang resources for this processing off this. */