more centos5 fixes

can't use GRegexp if we need to support centos5 ... vipsthumbnail was
using it to parse geometry strings

new geo parser, plus some tests

see https://github.com/jcupitt/libvips/issues/622
This commit is contained in:
John Cupitt 2017-03-15 12:08:52 +00:00
parent bd4fad332e
commit e6bbfe4672
2 changed files with 96 additions and 71 deletions

View File

@ -58,3 +58,32 @@ echo "testing with $(basename $image)"
for i in nearest bicubic bilinear nohalo lbb; do
test_rotate $image $i
done
test_thumbnail() {
geo=$1
correct_width=$2
correct_height=$3
printf "testing thumbnail -s $geo ... "
$vipsthumbnail $image -s "$geo" -o $tmp/t1.jpg
width=$(vipsheader -f width $tmp/t1.jpg)
height=$(vipsheader -f height $tmp/t1.jpg)
if [ $width -ne $correct_width ]; then
echo width is $width, not $correct_width
exit 1
fi
if [ $height -ne $correct_height ]; then
echo width is $height, not $correct_height
exit 1
fi
echo "ok"
}
test_thumbnail 100 100 75
test_thumbnail 100x100 100 75
test_thumbnail x100 133 100
test_thumbnail "100x100<" 1024 768
test_thumbnail "2000<" 2000 1500
test_thumbnail "100x100>" 100 75
test_thumbnail "2000>" 1024 768

View File

@ -102,6 +102,7 @@
#include <string.h>
#include <stdlib.h>
#include <locale.h>
#include <ctype.h>
#include <vips/vips.h>
#include <vips/internal.h>
@ -271,91 +272,86 @@ thumbnail_process( VipsObject *process, const char *filename )
return( 0 );
}
/* Fetch a match_info string, NULL for "".
*/
static const char *
fetch_match( GMatchInfo *match_info, int n )
{
const char *str = g_match_info_fetch( match_info, n );
return( str && strcmp( str, "" ) == 0 ? NULL : str );
}
/* Parse a geometry string and set thumbnail_width and thumbnail_height.
*/
static int
thumbnail_parse_geometry( const char *geometry )
{
GRegex *regex;
GMatchInfo *match_info;
gboolean handled;
/* Geometry strings have a regex like:
*
* ^(\\d+)? (x)? (\\d+)? ([<>])?$
*
* Sadly GRegex is 2.14 and later, and we need to work with 2.6.
*/
handled = FALSE;
const char *p;
regex = g_regex_new( "^(\\d+)? (x)? (\\d+)? ([<>])?$",
G_REGEX_CASELESS | G_REGEX_EXTENDED, 0, NULL );
g_regex_match( regex, geometry, 0, &match_info );
if( g_match_info_matches( match_info ) ) {
const char *w = fetch_match( match_info, 1 );
const char *x = fetch_match( match_info, 2 );
const char *h = fetch_match( match_info, 3 );
const char *s = fetch_match( match_info, 4 );
/* w or h missing means replace with a huuuge value to prevent
* reduction or enlargement in that axis.
*/
thumbnail_width = VIPS_MAX_COORD;
thumbnail_height = VIPS_MAX_COORD;
/* If --crop is set, both width and height must be specified,
* since we'll need a complete bounding box to fill.
p = geometry;
/* Get the width.
*/
while( isspace( *p ) )
p++;
if( isdigit ( *p ) ) {
/* We have a number! vipsthumbnail history means that "-s 200"
* means "200x200", not "200xhuge"
*/
if( crop_image &&
x &&
(!w || !h) ) {
vips_error( "thumbnail",
"both width and height must be given if "
"--crop is enabled" );
return( -1 );
}
thumbnail_width = thumbnail_height = atoi( p );
if( !x ) {
/* No "x" means we only allow a single number and it
* sets both width and height.
*/
if( w && !h ) {
thumbnail_width = thumbnail_height = atoi( w );
handled = TRUE;
}
if( !w && h ) {
thumbnail_width = thumbnail_height = atoi( h );
handled = TRUE;
}
}
else {
/* w or h missing means replace with a huuuge value
* to prevent reduction or enlargement in that axis.
*/
thumbnail_width = VIPS_MAX_COORD;
thumbnail_height = VIPS_MAX_COORD;
if( w ) {
thumbnail_width = atoi( w );
handled = TRUE;
}
if( h ) {
thumbnail_height = atoi( h );
handled = TRUE;
}
}
if( s && strcmp( s, ">" ) == 0 )
size_restriction = VIPS_SIZE_DOWN;
if( s && strcmp( s, "<" ) == 0 )
size_restriction = VIPS_SIZE_UP;
/* And skip over it.
*/
while( isdigit( *p ) )
p++;
}
g_match_info_free( match_info );
g_regex_unref( regex );
/* Get the optional 'x'.
*/
while( isspace( *p ) )
p++;
if( *p == 'x' )
p += 1;
while( isspace( *p ) )
p++;
if( !handled ) {
/* Get the height.
*/
if( isdigit( *p ) ) {
thumbnail_height = atoi( p );
while( isdigit( *p ) )
p++;
}
/* Get the final < or >.
*/
while( isspace( *p ) )
p++;
if( *p == '<' )
size_restriction = VIPS_SIZE_UP;
else if( *p == '>' )
size_restriction = VIPS_SIZE_DOWN;
else if( *p != '\0' ||
(thumbnail_width == VIPS_MAX_COORD &&
thumbnail_height == VIPS_MAX_COORD) ) {
vips_error( "thumbnail", "%s", _( "bad geometry spec" ) );
return( -1 );
}
/* If --crop is set, both width and height must be specified,
* since we'll need a complete bounding box to fill.
*/
if( (crop_image || smartcrop_image) &&
(thumbnail_width == VIPS_MAX_COORD ||
thumbnail_height == VIPS_MAX_COORD) ) {
vips_error( "thumbnail",
"unable to parse size \"%s\" -- "
"use eg. 128 or 200x300>", geometry );
"both width and height must be given if "
"crop is enabled" );
return( -1 );
}