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 for i in nearest bicubic bilinear nohalo lbb; do
test_rotate $image $i test_rotate $image $i
done 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 <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <locale.h> #include <locale.h>
#include <ctype.h>
#include <vips/vips.h> #include <vips/vips.h>
#include <vips/internal.h> #include <vips/internal.h>
@ -271,91 +272,86 @@ thumbnail_process( VipsObject *process, const char *filename )
return( 0 ); 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. /* Parse a geometry string and set thumbnail_width and thumbnail_height.
*/ */
static int static int
thumbnail_parse_geometry( const char *geometry ) thumbnail_parse_geometry( const char *geometry )
{ {
GRegex *regex; /* Geometry strings have a regex like:
GMatchInfo *match_info; *
gboolean handled; * ^(\\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+)? ([<>])?$", /* w or h missing means replace with a huuuge value to prevent
G_REGEX_CASELESS | G_REGEX_EXTENDED, 0, NULL ); * reduction or enlargement in that axis.
g_regex_match( regex, geometry, 0, &match_info ); */
if( g_match_info_matches( match_info ) ) { thumbnail_width = VIPS_MAX_COORD;
const char *w = fetch_match( match_info, 1 ); thumbnail_height = VIPS_MAX_COORD;
const char *x = fetch_match( match_info, 2 );
const char *h = fetch_match( match_info, 3 );
const char *s = fetch_match( match_info, 4 );
/* If --crop is set, both width and height must be specified, p = geometry;
* since we'll need a complete bounding box to fill.
/* 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 && thumbnail_width = thumbnail_height = atoi( p );
x &&
(!w || !h) ) {
vips_error( "thumbnail",
"both width and height must be given if "
"--crop is enabled" );
return( -1 );
}
if( !x ) { /* And skip over it.
/* No "x" means we only allow a single number and it */
* sets both width and height. while( isdigit( *p ) )
*/ p++;
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;
} }
g_match_info_free( match_info ); /* Get the optional 'x'.
g_regex_unref( regex ); */
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", vips_error( "thumbnail",
"unable to parse size \"%s\" -- " "both width and height must be given if "
"use eg. 128 or 200x300>", geometry ); "crop is enabled" );
return( -1 ); return( -1 );
} }