Merge branch 'add-force-size'
This commit is contained in:
commit
a10787baa3
@ -5,6 +5,7 @@
|
|||||||
- add new_from_image() to Python as well
|
- add new_from_image() to Python as well
|
||||||
- slight change to cpp new_from_image() to match py/C behaviour
|
- slight change to cpp new_from_image() to match py/C behaviour
|
||||||
- vips_conv(), vips_compass(), vips_convsep() default to FLOAT precision
|
- vips_conv(), vips_compass(), vips_convsep() default to FLOAT precision
|
||||||
|
- add FORCE resize mode to break aspect ratio
|
||||||
|
|
||||||
23/4/17 started 8.5.5
|
23/4/17 started 8.5.5
|
||||||
- doc polishing
|
- doc polishing
|
||||||
|
2
TODO
2
TODO
@ -1,6 +1,6 @@
|
|||||||
- vips_compass() needs docs
|
- vips_compass() needs docs
|
||||||
|
|
||||||
- cpp bandjoin should use bandjoin_const() where possibel ... currently
|
- cpp bandjoin should use bandjoin_const() where possible ... currently
|
||||||
uses new_from_image
|
uses new_from_image
|
||||||
|
|
||||||
- not sure about utf8 error messages on win
|
- not sure about utf8 error messages on win
|
||||||
|
@ -102,7 +102,7 @@ example:
|
|||||||
$ vips shrink fred.png jim.png 10 10
|
$ vips shrink fred.png jim.png 10 10
|
||||||
```
|
```
|
||||||
|
|
||||||
meaning shrink `fred.png` by a factor of 10 in both axies and write as
|
meaning shrink `fred.png` by a factor of 10 in both axes and write as
|
||||||
`jim.png`.
|
`jim.png`.
|
||||||
|
|
||||||
You can imagine this operation running without needing `fred.png` to be
|
You can imagine this operation running without needing `fred.png` to be
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -831,6 +831,7 @@ vips_size_get_type( void )
|
|||||||
{VIPS_SIZE_BOTH, "VIPS_SIZE_BOTH", "both"},
|
{VIPS_SIZE_BOTH, "VIPS_SIZE_BOTH", "both"},
|
||||||
{VIPS_SIZE_UP, "VIPS_SIZE_UP", "up"},
|
{VIPS_SIZE_UP, "VIPS_SIZE_UP", "up"},
|
||||||
{VIPS_SIZE_DOWN, "VIPS_SIZE_DOWN", "down"},
|
{VIPS_SIZE_DOWN, "VIPS_SIZE_DOWN", "down"},
|
||||||
|
{VIPS_SIZE_FORCE, "VIPS_SIZE_FORCE", "force"},
|
||||||
{VIPS_SIZE_LAST, "VIPS_SIZE_LAST", "last"},
|
{VIPS_SIZE_LAST, "VIPS_SIZE_LAST", "last"},
|
||||||
{0, NULL, NULL}
|
{0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
@ -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().
|
||||||
*/
|
*/
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
* - from vipsthumbnail.c
|
* - from vipsthumbnail.c
|
||||||
* 6/1/17
|
* 6/1/17
|
||||||
* - add @size parameter
|
* - add @size parameter
|
||||||
|
* 4/5/17
|
||||||
|
* - add FORCE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -135,21 +137,27 @@ 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.
|
||||||
|
*
|
||||||
|
* The hshrink/vshrink are the amount to shrink the input image axes by in
|
||||||
|
* order for the output axes (ie. after rotation) to match the required
|
||||||
|
* thumbnail->width, thumbnail->height and fit mode.
|
||||||
*/
|
*/
|
||||||
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 )
|
||||||
{
|
{
|
||||||
|
/* If we will be rotating, swap the target width and height.
|
||||||
|
*/
|
||||||
gboolean rotate =
|
gboolean rotate =
|
||||||
thumbnail->angle == VIPS_ANGLE_D90 ||
|
(thumbnail->angle == VIPS_ANGLE_D90 ||
|
||||||
thumbnail->angle == VIPS_ANGLE_D270;
|
thumbnail->angle == VIPS_ANGLE_D270) &&
|
||||||
int width = thumbnail->auto_rotate && rotate ?
|
thumbnail->auto_rotate;
|
||||||
input_height : input_width;
|
int target_width = rotate ?
|
||||||
int height = thumbnail->auto_rotate && rotate ?
|
thumbnail->height : thumbnail->width;
|
||||||
input_width : input_height;
|
int target_height = rotate ?
|
||||||
|
thumbnail->width : thumbnail->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.
|
||||||
@ -157,33 +165,53 @@ vips_thumbnail_calculate_shrink( VipsThumbnail *thumbnail,
|
|||||||
* In crop mode, we aim to fill the bounding box, so we must use the
|
* In crop mode, we aim to fill the bounding box, so we must use the
|
||||||
* smaller axis.
|
* smaller axis.
|
||||||
*/
|
*/
|
||||||
double horizontal = (double) width / thumbnail->width;
|
*hshrink = (double) input_width / target_width;
|
||||||
double vertical = (double) height / thumbnail->height;
|
*vshrink = (double) input_height / target_height;
|
||||||
|
|
||||||
if( thumbnail->crop != VIPS_INTERESTING_NONE ) {
|
if( thumbnail->crop != VIPS_INTERESTING_NONE ) {
|
||||||
if( horizontal < vertical )
|
if( *hshrink < *vshrink )
|
||||||
direction = VIPS_DIRECTION_HORIZONTAL;
|
direction = VIPS_DIRECTION_HORIZONTAL;
|
||||||
else
|
else
|
||||||
direction = VIPS_DIRECTION_VERTICAL;
|
direction = VIPS_DIRECTION_VERTICAL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( horizontal < vertical )
|
if( *hshrink < *vshrink )
|
||||||
direction = VIPS_DIRECTION_VERTICAL;
|
direction = VIPS_DIRECTION_VERTICAL;
|
||||||
else
|
else
|
||||||
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 )
|
||||||
|
*vshrink = *hshrink;
|
||||||
|
else
|
||||||
|
*hshrink = *vshrink;
|
||||||
|
}
|
||||||
|
|
||||||
/* Restrict to only upsize, only downsize, or both.
|
if( thumbnail->size == VIPS_SIZE_UP ) {
|
||||||
*/
|
*hshrink = VIPS_MIN( 1, *hshrink );
|
||||||
if( thumbnail->size == VIPS_SIZE_UP )
|
*vshrink = VIPS_MIN( 1, *vshrink );
|
||||||
shrink = VIPS_MIN( 1, shrink );
|
}
|
||||||
if( thumbnail->size == VIPS_SIZE_DOWN )
|
else if( thumbnail->size == VIPS_SIZE_DOWN ) {
|
||||||
shrink = VIPS_MAX( 1, shrink );
|
*hshrink = VIPS_MAX( 1, *hshrink );
|
||||||
|
*vshrink = VIPS_MAX( 1, *vshrink );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return( shrink );
|
/* Just the common part of the shrink: the bit by which both axes must be
|
||||||
|
* shrunk.
|
||||||
|
*/
|
||||||
|
static double
|
||||||
|
vips_thumbnail_calculate_common_shrink( VipsThumbnail *thumbnail,
|
||||||
|
int width, int 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 +219,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.
|
||||||
@ -228,7 +256,7 @@ vips_thumbnail_open( VipsThumbnail *thumbnail )
|
|||||||
VipsThumbnailClass *class = VIPS_THUMBNAIL_GET_CLASS( thumbnail );
|
VipsThumbnailClass *class = VIPS_THUMBNAIL_GET_CLASS( thumbnail );
|
||||||
|
|
||||||
VipsImage *im;
|
VipsImage *im;
|
||||||
int shrink;
|
double shrink;
|
||||||
double scale;
|
double scale;
|
||||||
|
|
||||||
if( class->get_info( thumbnail ) )
|
if( class->get_info( thumbnail ) )
|
||||||
@ -237,24 +265,28 @@ vips_thumbnail_open( VipsThumbnail *thumbnail )
|
|||||||
g_info( "input size is %d x %d",
|
g_info( "input size is %d x %d",
|
||||||
thumbnail->input_width, thumbnail->input_height );
|
thumbnail->input_width, thumbnail->input_height );
|
||||||
|
|
||||||
shrink = 1;
|
shrink = 1.0;
|
||||||
scale = 1.0;
|
scale = 1.0;
|
||||||
|
|
||||||
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,
|
shrink = vips_thumbnail_calculate_common_shrink( thumbnail,
|
||||||
thumbnail->input_width, thumbnail->input_height );
|
thumbnail->input_width, thumbnail->input_height );
|
||||||
|
scale = 1.0 / shrink;
|
||||||
|
|
||||||
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 );
|
thumbnail->input_width, thumbnail->input_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 +304,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.
|
||||||
@ -373,12 +406,13 @@ vips_thumbnail_build( VipsObject *object )
|
|||||||
in = t[3];
|
in = t[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
shrink = vips_thumbnail_calculate_shrink( thumbnail,
|
vips_thumbnail_calculate_shrink( thumbnail,
|
||||||
in->Xsize, in->Ysize );
|
in->Xsize, in->Ysize, &hshrink, &vshrink );
|
||||||
|
|
||||||
/* Use centre convention to better match imagemagick.
|
/* Use centre convention to better match imagemagick.
|
||||||
*/
|
*/
|
||||||
if( vips_resize( in, &t[4], 1.0 / shrink,
|
if( vips_resize( in, &t[4], 1.0 / hshrink,
|
||||||
|
"vscale", 1.0 / vshrink,
|
||||||
"centre", TRUE,
|
"centre", TRUE,
|
||||||
NULL ) )
|
NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
@ -639,8 +673,6 @@ vips_thumbnail_file_open( VipsThumbnail *thumbnail, int shrink, double scale )
|
|||||||
{
|
{
|
||||||
VipsThumbnailFile *file = (VipsThumbnailFile *) thumbnail;
|
VipsThumbnailFile *file = (VipsThumbnailFile *) thumbnail;
|
||||||
|
|
||||||
/* We can't use UNBUFERRED safely on very-many-core systems.
|
|
||||||
*/
|
|
||||||
if( shrink != 1 )
|
if( shrink != 1 )
|
||||||
return( vips_image_new_from_file( file->filename,
|
return( vips_image_new_from_file( file->filename,
|
||||||
"access", VIPS_ACCESS_SEQUENTIAL,
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
@ -697,7 +729,7 @@ vips_thumbnail_file_init( VipsThumbnailFile *file )
|
|||||||
* Optional arguments:
|
* Optional arguments:
|
||||||
*
|
*
|
||||||
* * @height: %gint, target height in pixels
|
* * @height: %gint, target height in pixels
|
||||||
* * @size: #VipsSize, upsize, downsize or both
|
* * @size: #VipsSize, upsize, downsize, both or force
|
||||||
* * @auto_rotate: %gboolean, rotate upright using orientation tag
|
* * @auto_rotate: %gboolean, rotate upright using orientation tag
|
||||||
* * @crop: #VipsInteresting, shrink and crop to fill target
|
* * @crop: #VipsInteresting, shrink and crop to fill target
|
||||||
* * @linear: %gboolean, perform shrink in linear light
|
* * @linear: %gboolean, perform shrink in linear light
|
||||||
@ -719,19 +751,22 @@ 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,
|
||||||
* these tags will not be interpreted.
|
* these tags will not be interpreted.
|
||||||
*
|
*
|
||||||
* Shrinking is normally done in sRGB colourspace. Set @linear to shrink in
|
* Shrinking is normally done in sRGB colourspace. Set @linear to shrink in
|
||||||
* linear light colourspace instead --- this can give better results, but can
|
* linear light colourspace instead. This can give better results, but can
|
||||||
* also be far slower, since tricks like JPEG shrink-on-load cannot be used in
|
* also be far slower, since tricks like JPEG shrink-on-load cannot be used in
|
||||||
* linear space.
|
* linear space.
|
||||||
*
|
*
|
||||||
@ -866,7 +901,7 @@ vips_thumbnail_buffer_init( VipsThumbnailBuffer *buffer )
|
|||||||
* Optional arguments:
|
* Optional arguments:
|
||||||
*
|
*
|
||||||
* * @height: %gint, target height in pixels
|
* * @height: %gint, target height in pixels
|
||||||
* * @size: #VipsSize, upsize, downsize or both
|
* * @size: #VipsSize, upsize, downsize, both or force
|
||||||
* * @auto_rotate: %gboolean, rotate upright using orientation tag
|
* * @auto_rotate: %gboolean, rotate upright using orientation tag
|
||||||
* * @crop: #VipsInteresting, shrink and crop to fill target
|
* * @crop: #VipsInteresting, shrink and crop to fill target
|
||||||
* * @linear: %gboolean, perform shrink in linear light
|
* * @linear: %gboolean, perform shrink in linear light
|
||||||
|
@ -94,7 +94,7 @@ option.
|
|||||||
.TP
|
.TP
|
||||||
.B -c, --crop
|
.B -c, --crop
|
||||||
Crop the output image down. The image is shrunk so as to completely fill the
|
Crop the output image down. The image is shrunk so as to completely fill the
|
||||||
bounding box in both axies, then any excess is cropped off.
|
bounding box in both axes, then any excess is cropped off.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B -d, --delete
|
.B -d, --delete
|
||||||
|
BIN
test/images/Landscape_6.jpg
Normal file
BIN
test/images/Landscape_6.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 127 KiB |
@ -107,6 +107,7 @@ class TestResample(unittest.TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.jpeg_file = "images/йцук.jpg"
|
self.jpeg_file = "images/йцук.jpg"
|
||||||
|
self.rotated_jpeg_file = "images/Landscape_6.jpg"
|
||||||
|
|
||||||
def test_affine(self):
|
def test_affine(self):
|
||||||
im = Vips.Image.new_from_file(self.jpeg_file)
|
im = Vips.Image.new_from_file(self.jpeg_file)
|
||||||
@ -216,12 +217,38 @@ class TestResample(unittest.TestCase):
|
|||||||
self.assertNotEqual(im.width, 300)
|
self.assertNotEqual(im.width, 300)
|
||||||
self.assertEqual(im.height, 100)
|
self.assertEqual(im.height, 100)
|
||||||
|
|
||||||
# with @crop, should fit both width and height
|
# force should fit width and height ... although this jpg has an
|
||||||
im = Vips.Image.thumbnail(self.jpeg_file, 100,
|
# orientation tag, we ignore it unless autorot is on
|
||||||
height = 300, crop = True)
|
im = Vips.Image.thumbnail(self.rotated_jpeg_file, 100, height = 300,
|
||||||
|
size = "force")
|
||||||
self.assertEqual(im.width, 100)
|
self.assertEqual(im.width, 100)
|
||||||
self.assertEqual(im.height, 300)
|
self.assertEqual(im.height, 300)
|
||||||
|
|
||||||
|
# with force + autorot, we spin the image, but the output size should
|
||||||
|
# not change
|
||||||
|
im = Vips.Image.thumbnail(self.rotated_jpeg_file, 100, height = 300,
|
||||||
|
size = "force", auto_rotate = True)
|
||||||
|
self.assertEqual(im.width, 100)
|
||||||
|
self.assertEqual(im.height, 300)
|
||||||
|
|
||||||
|
# with @crop, should fit both width and height
|
||||||
|
im = Vips.Image.thumbnail(self.jpeg_file, 100,
|
||||||
|
height = 300, crop = "centre")
|
||||||
|
self.assertEqual(im.width, 100)
|
||||||
|
self.assertEqual(im.height, 300)
|
||||||
|
|
||||||
|
# with size up, should not downsize
|
||||||
|
im = Vips.Image.thumbnail(self.jpeg_file, 100, size = "up")
|
||||||
|
self.assertEqual(im.width, im_orig.width)
|
||||||
|
im = Vips.Image.thumbnail(self.jpeg_file, 10000, size = "up")
|
||||||
|
self.assertEqual(im.width, 10000)
|
||||||
|
|
||||||
|
# with size down, should not upsize
|
||||||
|
im = Vips.Image.thumbnail(self.jpeg_file, 100, size = "down")
|
||||||
|
self.assertEqual(im.width, 100)
|
||||||
|
im = Vips.Image.thumbnail(self.jpeg_file, 10000, size = "down")
|
||||||
|
self.assertEqual(im.width, im_orig.width)
|
||||||
|
|
||||||
im1 = Vips.Image.thumbnail(self.jpeg_file, 100)
|
im1 = Vips.Image.thumbnail(self.jpeg_file, 100)
|
||||||
with open(self.jpeg_file, 'rb') as f:
|
with open(self.jpeg_file, 'rb') as f:
|
||||||
buf = f.read()
|
buf = f.read()
|
||||||
|
@ -90,6 +90,8 @@
|
|||||||
* 6/1/17
|
* 6/1/17
|
||||||
* - fancy geometry strings
|
* - fancy geometry strings
|
||||||
* - support VipSize restrictions
|
* - support VipSize restrictions
|
||||||
|
* 4/5/17
|
||||||
|
* - add ! geo modifier
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -333,7 +335,7 @@ thumbnail_parse_geometry( const char *geometry )
|
|||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the final < or >.
|
/* Get the final <>!
|
||||||
*/
|
*/
|
||||||
while( isspace( *p ) )
|
while( isspace( *p ) )
|
||||||
p++;
|
p++;
|
||||||
@ -341,6 +343,8 @@ thumbnail_parse_geometry( const char *geometry )
|
|||||||
size_restriction = VIPS_SIZE_UP;
|
size_restriction = VIPS_SIZE_UP;
|
||||||
else if( *p == '>' )
|
else if( *p == '>' )
|
||||||
size_restriction = VIPS_SIZE_DOWN;
|
size_restriction = VIPS_SIZE_DOWN;
|
||||||
|
else if( *p == '!' )
|
||||||
|
size_restriction = VIPS_SIZE_FORCE;
|
||||||
else if( *p != '\0' ||
|
else if( *p != '\0' ||
|
||||||
(thumbnail_width == VIPS_MAX_COORD &&
|
(thumbnail_width == VIPS_MAX_COORD &&
|
||||||
thumbnail_height == VIPS_MAX_COORD) ) {
|
thumbnail_height == VIPS_MAX_COORD) ) {
|
||||||
@ -348,18 +352,30 @@ thumbnail_parse_geometry( const char *geometry )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If --crop is set, both width and height must be specified,
|
/* If force is set and one of width or height isn't set, copy from the
|
||||||
* since we'll need a complete bounding box to fill.
|
* one that is.
|
||||||
*/
|
*/
|
||||||
if( (crop_image || smartcrop_image) &&
|
if( size_restriction == VIPS_SIZE_FORCE ) {
|
||||||
(thumbnail_width == VIPS_MAX_COORD ||
|
if( thumbnail_width == VIPS_MAX_COORD )
|
||||||
thumbnail_height == VIPS_MAX_COORD) ) {
|
thumbnail_width = thumbnail_height;
|
||||||
vips_error( "thumbnail",
|
if( thumbnail_height == VIPS_MAX_COORD )
|
||||||
"both width and height must be given if "
|
thumbnail_height = thumbnail_width;
|
||||||
"crop is enabled" );
|
|
||||||
return( -1 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If --crop is set or force is set, both width and height must be
|
||||||
|
* specified, since we'll need a complete bounding box to fill.
|
||||||
|
*/
|
||||||
|
if( crop_image ||
|
||||||
|
smartcrop_image ||
|
||||||
|
size_restriction == VIPS_SIZE_FORCE )
|
||||||
|
if( thumbnail_width == VIPS_MAX_COORD ||
|
||||||
|
thumbnail_height == VIPS_MAX_COORD ) {
|
||||||
|
vips_error( "thumbnail",
|
||||||
|
"both width and height must be given if "
|
||||||
|
"crop is enabled" );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user