start adding FORCE

start experimental implementation

see https://github.com/jcupitt/libvips/issues/648
This commit is contained in:
John Cupitt 2017-05-01 17:22:03 +01:00
parent 1504fb0249
commit 3900cebdf8
3 changed files with 48 additions and 23 deletions

View File

@ -51,6 +51,7 @@ typedef enum {
VIPS_SIZE_BOTH, VIPS_SIZE_BOTH,
VIPS_SIZE_UP, VIPS_SIZE_UP,
VIPS_SIZE_DOWN, VIPS_SIZE_DOWN,
VIPS_SIZE_FORCE,
VIPS_SIZE_LAST VIPS_SIZE_LAST
} VipsSize; } VipsSize;

View File

@ -87,9 +87,10 @@
* @VIPS_SIZE_BOTH: size both up and down * @VIPS_SIZE_BOTH: size both up and down
* @VIPS_SIZE_UP: only upsize * @VIPS_SIZE_UP: only upsize
* @VIPS_SIZE_DOWN: only downsize * @VIPS_SIZE_DOWN: only downsize
* @VIPS_SIZE_FORCE: force size, that is, break aspect ratio
* *
* Controls whether an operation should upsize, downsize, or both up and * Controls whether an operation should upsize, downsize, both up and
* downsize. * downsize, or force a size.
* *
* See also: vips_thumbnail(). * See also: vips_thumbnail().
*/ */

View File

@ -136,9 +136,9 @@ vips_thumbnail_finalize( GObject *gobject )
/* Calculate the shrink factor, taking into account auto-rotate, the fit mode, /* Calculate the shrink factor, taking into account auto-rotate, the fit mode,
* and so on. * and so on.
*/ */
static double static void
vips_thumbnail_calculate_shrink( VipsThumbnail *thumbnail, vips_thumbnail_calculate_shrink( VipsThumbnail *thumbnail,
int input_width, int input_height ) int input_width, int input_height, double *hshrink, double *vshrink )
{ {
gboolean rotate = gboolean rotate =
thumbnail->angle == VIPS_ANGLE_D90 || thumbnail->angle == VIPS_ANGLE_D90 ||
@ -149,7 +149,6 @@ vips_thumbnail_calculate_shrink( VipsThumbnail *thumbnail,
input_width : input_height; input_width : input_height;
VipsDirection direction; VipsDirection direction;
double shrink;
/* Calculate the horizontal and vertical shrink we'd need to fit the /* Calculate the horizontal and vertical shrink we'd need to fit the
* image to the bounding box, and pick the biggest. * image to the bounding box, and pick the biggest.
@ -173,17 +172,34 @@ vips_thumbnail_calculate_shrink( VipsThumbnail *thumbnail,
direction = VIPS_DIRECTION_HORIZONTAL; direction = VIPS_DIRECTION_HORIZONTAL;
} }
shrink = direction == VIPS_DIRECTION_HORIZONTAL ? if( thumbnail->size != VIPS_SIZE_FORCE ) {
horizontal : vertical; if( direction == VIPS_DIRECTION_HORIZONTAL )
vertical = horizontal;
/* Restrict to only upsize, only downsize, or both. else
*/ horizontal = vertical;
if( thumbnail->size == VIPS_SIZE_UP ) }
else if( thumbnail->size == VIPS_SIZE_UP )
shrink = VIPS_MIN( 1, shrink ); shrink = VIPS_MIN( 1, shrink );
if( thumbnail->size == VIPS_SIZE_DOWN ) else if( thumbnail->size == VIPS_SIZE_DOWN )
shrink = VIPS_MAX( 1, shrink ); shrink = VIPS_MAX( 1, shrink );
return( shrink );
}
/* Just the common part of the shrink: the bit by which both axies must be
* shrunk.
*/
static double
vips_thumbnail_calculate_common_shrink( VipsThumbnail *thumbnail,
int input_width, int input_height )
{
double hshrink;
double vshrink;
vips_thumbnail_calculate_shrink( thumbnail, width, height,
&hshrink, &vshrink );
return( VIPS_MIN( hshrink, vshrink ) );
} }
/* Find the best jpeg preload shrink. /* Find the best jpeg preload shrink.
@ -191,8 +207,8 @@ vips_thumbnail_calculate_shrink( VipsThumbnail *thumbnail,
static int static int
vips_thumbnail_find_jpegshrink( VipsThumbnail *thumbnail, int width, int height ) vips_thumbnail_find_jpegshrink( VipsThumbnail *thumbnail, int width, int height )
{ {
double shrink = double shrink = vips_thumbnail_calculate_common_shrink( thumbnail,
vips_thumbnail_calculate_shrink( thumbnail, width, height ); width, height );
/* We can't use pre-shrunk images in linear mode. libjpeg shrinks in Y /* We can't use pre-shrunk images in linear mode. libjpeg shrinks in Y
* (of YCbCR), not linear space. * (of YCbCR), not linear space.
@ -243,18 +259,21 @@ vips_thumbnail_open( VipsThumbnail *thumbnail )
if( vips_isprefix( "VipsForeignLoadJpeg", thumbnail->loader ) ) { if( vips_isprefix( "VipsForeignLoadJpeg", thumbnail->loader ) ) {
shrink = vips_thumbnail_find_jpegshrink( thumbnail, shrink = vips_thumbnail_find_jpegshrink( thumbnail,
thumbnail->input_width, thumbnail->input_height ); thumbnail->input_width, thumbnail->input_height );
g_info( "loading jpeg with factor %d pre-shrink", shrink ); g_info( "loading jpeg with factor %g pre-shrink", shrink );
} }
else if( vips_isprefix( "VipsForeignLoadPdf", thumbnail->loader ) || else if( vips_isprefix( "VipsForeignLoadPdf", thumbnail->loader ) ||
vips_isprefix( "VipsForeignLoadSvg", thumbnail->loader ) ) { vips_isprefix( "VipsForeignLoadSvg", thumbnail->loader ) ) {
scale = 1.0 / vips_thumbnail_calculate_shrink( thumbnail, scale = 1.0 /
thumbnail->input_width, thumbnail->input_height ); vips_thumbnail_calculate_common_shrink( thumbnail,
width, height );
g_info( "loading PDF/SVG with factor %g pre-scale", scale ); g_info( "loading PDF/SVG with factor %g pre-scale", scale );
} }
else if( vips_isprefix( "VipsForeignLoadWebp", thumbnail->loader ) ) { else if( vips_isprefix( "VipsForeignLoadWebp", thumbnail->loader ) ) {
shrink = vips_thumbnail_calculate_shrink( thumbnail, shrink = vips_thumbnail_calculate_common_shrink( thumbnail,
thumbnail->input_width, thumbnail->input_height ); width, height );
g_info( "loading webp with factor %d pre-shrink", shrink );
g_info( "loading webp with factor %g pre-shrink", shrink );
} }
if( !(im = class->open( thumbnail, shrink, scale )) ) if( !(im = class->open( thumbnail, shrink, scale )) )
@ -272,7 +291,8 @@ vips_thumbnail_build( VipsObject *object )
VIPS_INTERPRETATION_scRGB : VIPS_INTERPRETATION_sRGB; VIPS_INTERPRETATION_scRGB : VIPS_INTERPRETATION_sRGB;
VipsImage *in; VipsImage *in;
double shrink; double hshrink;
double vshrink;
/* TRUE if we've done the import of an ICC transform and still need to /* TRUE if we've done the import of an ICC transform and still need to
* export. * export.
@ -719,12 +739,15 @@ vips_thumbnail_file_init( VipsThumbnailFile *file )
* @height rectangle, with any excess cropped away. See vips_smartcrop() for * @height rectangle, with any excess cropped away. See vips_smartcrop() for
* details on the cropping strategy. * details on the cropping strategy.
* *
* Normally the operation will upsize or downsize as required. If @size is set * Normally the operation will upsize or downsize as required to fit the image
* inside or outside the target size. If @size is set
* to #VIPS_SIZE_UP, the operation will only upsize and will just * to #VIPS_SIZE_UP, the operation will only upsize and will just
* copy if asked to downsize. * copy if asked to downsize.
* If @size is set * If @size is set
* to #VIPS_SIZE_DOWN, the operation will only downsize and will just * to #VIPS_SIZE_DOWN, the operation will only downsize and will just
* copy if asked to upsize. * copy if asked to upsize.
* If @size is #VIPS_SIZE_FORCE, the image aspect ratio will be broken and the
* image will be forced to fit the target.
* *
* Normally any orientation tags on the input image (such as EXIF tags) are * Normally any orientation tags on the input image (such as EXIF tags) are
* interpreted to rotate the image upright. If you set @auto_rotate to %FALSE, * interpreted to rotate the image upright. If you set @auto_rotate to %FALSE,