diff --git a/.gitignore b/.gitignore index 91154068..af3b5d66 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ a.out +*.log +*.trs +tmp +test/variables.sh scan compile po/*.pot diff --git a/Makefile.am b/Makefile.am index a173ba1e..b361cae6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -42,6 +42,7 @@ SUBDIRS = \ po \ man \ doc \ + test \ $(C_COMPILE_DIR) \ $(P_COMPILE_DIR) \ $(P8_COMPILE_DIR) \ diff --git a/TODO b/TODO index 8c44765f..c0ddb796 100644 --- a/TODO +++ b/TODO @@ -1,21 +1,14 @@ -- use vips_gaussblur() in vips_resize(), and vipsthumbnail.c +- getting an error in test_formats.sh + $ ./test_formats.sh + testing IMG_4618.jpg v ... ok + testing IMG_4618.jpg tif ... ok + testing IMG_4618.jpg tif[compression=jpeg] ... ok + testing IMG_4618.jpg tif[compression=deflate] ... ok + testing IMG_4618.jpg tif[compression=packbits] ... ok + testing IMG_4618.jpg tif[compression=jpeg,tile] ... vips warning: linecache: + error reading tile 0x128: VipsJpeg: out of order read at line 384 -- test building without cpp - - need to add introspection.m4 to m4/ dir? - - configure.ac has - - GOBJECT_INTROSPECTION_CHECK([1.30.0]) - - libvips/Makefile.am has - - if HAVE_INTROSPECTION - - what defines that? is it a left-over? - -- test building without python - use vips_resize() in vipsthumbnail? @@ -39,8 +32,6 @@ output imagevec output blob -- use vips_autorot() in jpegload and vipsthumbnail - - fix up aconv - more python tests diff --git a/configure.ac b/configure.ac index 049ad5bd..e51c7467 100644 --- a/configure.ac +++ b/configure.ac @@ -791,6 +791,11 @@ AC_SUBST(VIPS_LIBS) AC_SUBST(VIPS_CXX_LIBS) AC_SUBST(PACKAGES_USED) +# needed by test/variables.sh.in +# :( what's a better way to do this, argh +TOP_SRCDIR=$ac_pwd +AC_SUBST(TOP_SRCDIR) + AC_OUTPUT([ vips.pc vipsCC.pc @@ -828,6 +833,8 @@ AC_OUTPUT([ tools/light_correct tools/shrink_width python/Makefile + test/Makefile + test/variables.sh swig/Makefile swig/vipsCC/Makefile man/Makefile diff --git a/libvips/conversion/autorot.c b/libvips/conversion/autorot.c index 90b3ab1e..db9c032c 100644 --- a/libvips/conversion/autorot.c +++ b/libvips/conversion/autorot.c @@ -55,6 +55,17 @@ G_DEFINE_TYPE( VipsAutorot, vips_autorot, VIPS_TYPE_CONVERSION ); #define ORIENTATION ("exif-ifd0-Orientation") +/** + * vips_autorot_get_angle: + * @im: image to fetch orientation from + * + * Examine the metadata on @im and return the #VipsAngle to rotate by to turn + * the image upright. + * + * See also: vips_autorot(). + * + * Returns: the #VipsAngle to rotate by to make the image upright. + */ VipsAngle vips_autorot_get_angle( VipsImage *im ) { diff --git a/python/test/test_all.py b/python/test/test_all.py deleted file mode 100755 index ffc0b69c..00000000 --- a/python/test/test_all.py +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/python - -import unittest - -from test_arithmetic import TestArithmetic -from test_colour import TestColour -from test_conversion import TestConversion - -if __name__ == '__main__': - unittest.main() diff --git a/test/Makefile.am b/test/Makefile.am new file mode 100644 index 00000000..fea31bc6 --- /dev/null +++ b/test/Makefile.am @@ -0,0 +1,14 @@ + +EXTRA_DIST = \ + images \ + variables.sh.in + +TESTS = \ + test_cli.sh \ + test_formats.sh \ + test_seq.sh \ + test_threading.sh \ + test_arithmetic.py \ + test_colour.py \ + test_conversion.py + diff --git a/python/test/images/IMG_4618.jpg b/test/images/IMG_4618.jpg similarity index 100% rename from python/test/images/IMG_4618.jpg rename to test/images/IMG_4618.jpg diff --git a/python/test/images/sRGB.icm b/test/images/sRGB.icm similarity index 100% rename from python/test/images/sRGB.icm rename to test/images/sRGB.icm diff --git a/test/images/sample.mat b/test/images/sample.mat new file mode 100644 index 00000000..b809dee6 Binary files /dev/null and b/test/images/sample.mat differ diff --git a/test/images/sample.png b/test/images/sample.png new file mode 100644 index 00000000..ede09131 Binary files /dev/null and b/test/images/sample.png differ diff --git a/test/images/t00740_tr1_segm.hdr b/test/images/t00740_tr1_segm.hdr new file mode 100644 index 00000000..6ea6141b Binary files /dev/null and b/test/images/t00740_tr1_segm.hdr differ diff --git a/test/images/t00740_tr1_segm.img b/test/images/t00740_tr1_segm.img new file mode 100644 index 00000000..1101323b Binary files /dev/null and b/test/images/t00740_tr1_segm.img differ diff --git a/python/test/test_arithmetic.py b/test/test_arithmetic.py similarity index 100% rename from python/test/test_arithmetic.py rename to test/test_arithmetic.py diff --git a/test/test_cli.sh b/test/test_cli.sh new file mode 100755 index 00000000..0eed7c75 --- /dev/null +++ b/test/test_cli.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +#set -x + +. ./variables.sh + +# is a difference beyond a threshold? return 0 (meaning all ok) or 1 (meaning +# error, or outside threshold) +# +# use bc since bash does not support fp math +break_threshold() { + diff=$1 + threshold=$2 + return $(echo "$diff <= $threshold" | bc -l) +} + +# subtract, look for max difference less than a threshold +test_difference() { + before=$1 + after=$2 + threshold=$3 + + vips subtract $before $after $tmp/difference.v + vips abs $tmp/difference.v $tmp/abs.v + dif=$(vips max $tmp/abs.v) + + if break_threshold $dif $threshold; then + echo "difference is $dif" + exit 1 + fi +} + +test_rotate() { + im=$1 + inter=$2 + + echo -n "testing $inter ... " + + # 90 degree clockwise rotate + trn="0 1 1 0" + + vips affine $im $tmp/t1.v "$trn" --interpolate $inter + vips affine $tmp/t1.v $tmp/t2.v "$trn" --interpolate $inter + vips affine $tmp/t2.v $tmp/t1.v "$trn" --interpolate $inter + vips affine $tmp/t1.v $tmp/t2.v "$trn" --interpolate $inter + + test_difference $im $tmp/t2.v 1 + + echo "ok" +} + +# vsqbs is non-interpolatory, don't test this way + +echo "testing with $(basename $image)" +for i in nearest bicubic bilinear nohalo lbb; do + test_rotate $image $i +done diff --git a/python/test/test_colour.py b/test/test_colour.py similarity index 100% rename from python/test/test_colour.py rename to test/test_colour.py diff --git a/python/test/test_conversion.py b/test/test_conversion.py similarity index 100% rename from python/test/test_conversion.py rename to test/test_conversion.py diff --git a/python/test/test_convolution.py b/test/test_convolution.py similarity index 100% rename from python/test/test_convolution.py rename to test/test_convolution.py diff --git a/test/test_formats.sh b/test/test_formats.sh new file mode 100755 index 00000000..3d384db9 --- /dev/null +++ b/test/test_formats.sh @@ -0,0 +1,170 @@ +#!/bin/sh + +# set -x + +. ./variables.sh + +# the matlab image and reference image +matlab=$test_images/sample.mat +matlab_ref=$test_images/sample.png + +# make a mono image +vips extract_band $image $tmp/mono.v 1 +mono=$tmp/mono.v + +# make a radiance image +vips float2rad $image $tmp/rad.v +rad=$tmp/rad.v + +# make a cmyk image +vips bandjoin "$image $tmp/mono.v" $tmp/t1.v +vips copy $tmp/t1.v $tmp/cmyk.v --interpretation cmyk +cmyk=$tmp/cmyk.v + +# save to t1.format, load as back.v +save_load() { + in=$1 + format=$2 + mode=$3 + + if ! vips copy $in $tmp/t1.$format$mode ; then + echo "write to $out failed" + exit 1 + fi + + if ! vips copy $tmp/t1.$format $tmp/back.v ; then + echo "read from $out failed" + exit 1 + fi +} + +# is a difference beyond a threshold? return 0 (meaning all ok) or 1 (meaning +# error, or outside threshold) +# +# use bc since bash does not support fp math +break_threshold() { + diff=$1 + threshold=$2 + return $(echo "$diff <= $threshold" | bc -l) +} + +# subtract, look for max difference less than a threshold +test_difference() { + before=$1 + after=$2 + threshold=$3 + + vips subtract $before $after $tmp/difference.v + vips abs $tmp/difference.v $tmp/abs.v + dif=`vips max $tmp/abs.v` + + if break_threshold $dif $threshold; then + echo "save / load difference is $dif" + exit 1 + fi +} + +# save to the named file in tmp, convert back to vips again, subtract, look +# for max difference less than a threshold +test_format() { + in=$1 + format=$2 + threshold=$3 + mode=$4 + + echo -n "testing $(basename $in) $format$mode ... " + + save_load $in $format $mode + test_difference $in $tmp/back.v $threshold + + echo "ok" +} + +# as above, but hdr format +# this is a coded format, so we need to rad2float before we can test for +# differences +test_rad() { + in=$1 + + echo -n "testing $(basename $in) hdr ... " + + save_load $in hdr + + vips rad2float $in $tmp/before.v + vips rad2float $tmp/back.v $tmp/after.v + + test_difference $tmp/before.v $tmp/after.v 0 + + echo "ok" +} + +# as above, but raw format +# we can't use suffix stuff to pick the load/save +test_raw() { + in=$1 + + echo -n "testing $(basename $in) raw ... " + + vips copy $in $tmp/before.v + width=`vipsheader -f Xsize $tmp/before.v` + height=`vipsheader -f Ysize $tmp/before.v` + bands=`vipsheader -f Bands $tmp/before.v` + + vips rawsave $tmp/before.v $tmp/raw + vips rawload $tmp/raw $tmp/after.v $width $height $bands + + test_difference $tmp/before.v $tmp/after.v 0 + + echo "ok" +} + +# a format for which we only have a load (eg. matlab) +# pass in a reference file as well and compare to that +test_loader() { + ref=$1 + in=$2 + format=$3 + + echo -n "testing $(basename $in) $format ... " + + vips copy $ref $tmp/before.v + vips copy $in $tmp/after.v + + test_difference $tmp/before.v $tmp/after.v 0 + + echo "ok" +} + +test_format $image v 0 +test_format $image tif 0 +test_format $image tif 70 [compression=jpeg] +test_format $image tif 0 [compression=deflate] +test_format $image tif 0 [compression=packbits] +test_format $image tif 70 [compression=jpeg,tile] +test_format $image tif 70 [compression=jpeg,tile,pyramid] +test_format $image png 0 +test_format $image png 0 [compression=9,interlace=1] +test_format $image jpg 15 +test_format $image ppm 0 +test_format $image pfm 0 +test_format $image fits 0 + +# csv can only do mono +test_format $mono csv 0 + +# cmyk jpg is a special path +test_format $cmyk jpg 15 +test_format $cmyk tif 0 +test_format $cmyk tif 15 [compression=jpeg] +test_format $cmyk tif 15 [compression=jpeg,tile] +test_format $cmyk tif 15 [compression=jpeg,tile,pyramid] + +test_rad $rad + +test_raw $mono +test_raw $image + +test_loader $matlab_ref $matlab matlab + +# we have loaders but not savers for other formats, add tests here + diff --git a/test/test_seq.sh b/test/test_seq.sh new file mode 100755 index 00000000..3023685d --- /dev/null +++ b/test/test_seq.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +# set -x + +. ./variables.sh + +# make a large PNG, roughly the size of Chicago.png +echo -n "building huge test PNG image ... " +vips replicate $image $tmp/huge.png 30 5 +echo "ok" + +huge=$tmp/huge.png + +echo -n "testing vipsthumbnail ... " +rm -f $tmp/x.png +vipsthumbnail $huge -o $tmp/x.png +if ! vipsheader $tmp/x.png > /dev/null 2>&1 ; then + echo "vipsthumbnail failed in basic mode" + exit 1 +fi +echo "ok" + +if [ ! -d $tmp/readonly ] ; then + mkdir $tmp/readonly + chmod ugo-wx $tmp/readonly +fi +export TMPDIR=$tmp/readonly + +echo -n "testing vipsthumbnail does not make temps ... " +rm -f $tmp/x.png +vipsthumbnail $huge -o $tmp/x.png +if ! vipsheader $tmp/x.png > /dev/null 2>&1 ; then + echo "vipsthumbnail made a temp" + exit 1 +fi +echo "ok" + +echo -n "testing shrink does not make temps ... " +rm -f $tmp/x.png +vips shrink $huge $tmp/x.png 230 230 +if ! vipsheader $tmp/x.png > /dev/null 2>&1 ; then + echo "shrink made a temp" + exit 1 +fi +echo "ok" diff --git a/test/test_threading.sh b/test/test_threading.sh new file mode 100755 index 00000000..75a83f5b --- /dev/null +++ b/test/test_threading.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +# set -x + +source variables.sh + +chain=1 + +# im_benchmark needs a labq +vips im_sRGB2XYZ $image $tmp/t1.v +vips im_XYZ2Lab $tmp/t1.v $tmp/t2.v +vips im_Lab2LabQ $tmp/t2.v $tmp/t3.v + +for tile in 10 64 128 512; do + # benchmark includes a dither which will vary with tile size + vips --vips-concurrency=1 \ + --vips-tile-width=$tile --vips-tile-height=$tile \ + im_benchmarkn $tmp/t3.v $tmp/t5.v $chain + + for cpus in 2 3 4 5 6 7 8 99 1024; do + echo trying cpus = $cpus, tile = $tile ... + vips --vips-concurrency=$cpus \ + --vips-tile-width=$tile --vips-tile-height=$tile \ + im_benchmarkn $tmp/t3.v $tmp/t7.v $chain + vips im_subtract $tmp/t5.v $tmp/t7.v $tmp/t8.v + vips im_abs $tmp/t8.v $tmp/t9.v + max=`vips im_max $tmp/t9.v` + if [ $max -gt 0 ]; then + break + fi + done + if [ $max -gt 0 ]; then + break + fi +done + +if [ $max -gt 0 ]; then + echo error, max == $max + exit 1 +else + echo all threading tests passed +fi + diff --git a/test/variables.sh.in b/test/variables.sh.in new file mode 100644 index 00000000..148b838e --- /dev/null +++ b/test/variables.sh.in @@ -0,0 +1,4 @@ +top_srcdir=@TOP_SRCDIR@ +tmp=$top_srcdir/test/tmp +test_images=$top_srcdir/test/images +image=$test_images/IMG_4618.jpg diff --git a/tools/vipsthumbnail.c b/tools/vipsthumbnail.c index 08e5741c..aff2dd7d 100644 --- a/tools/vipsthumbnail.c +++ b/tools/vipsthumbnail.c @@ -151,35 +151,6 @@ static GOptionEntry options[] = { { NULL } }; -static VipsAngle -get_angle( VipsImage *im ) -{ - VipsAngle angle; - const char *orientation; - - angle = VIPS_ANGLE_D0; - - if( vips_image_get_typeof( im, ORIENTATION ) && - !vips_image_get_string( im, ORIENTATION, &orientation ) ) { - if( vips_isprefix( "6", orientation ) ) - angle = VIPS_ANGLE_D90; - else if( vips_isprefix( "8", orientation ) ) - angle = VIPS_ANGLE_D270; - else if( vips_isprefix( "3", orientation ) ) - angle = VIPS_ANGLE_D180; - - /* Other values do rotate + mirror, don't bother handling them - * though, how common can mirroring be. - * - * See: - * - * http://www.80sidea.com/archives/2316 - */ - } - - return( angle ); -} - /* Calculate the shrink factors. * * We shrink in two stages: first, a shrink with a block average. This can @@ -193,7 +164,7 @@ static int calculate_shrink( VipsImage *im, double *residual, VipsInterpolate *interp ) { - VipsAngle angle = get_angle( im ); + VipsAngle angle = vips_autorot_get_angle( im ); gboolean rotate = angle == VIPS_ANGLE_D90 || angle == VIPS_ANGLE_D270; int width = rotate_image && rotate ? im->Ysize : im->Xsize; int height = rotate_image && rotate ? im->Xsize : im->Ysize; @@ -518,18 +489,10 @@ thumbnail_shrink( VipsObject *process, VipsImage *in, sigma = ((1.0 / residual) - 0.5) / 1.5; if( residual < 1.0 && sigma > 0.1 ) { - if( vips_gaussmat( &t[9], sigma, 0.2, - "separable", TRUE, - "integer", TRUE, - NULL ) || - vips_convsep( in, &t[5], t[9], NULL ) ) + if( vips_gaussblur( in, &t[5], sigma, NULL ) ) return( NULL ); vips_info( "vipsthumbnail", "anti-alias, sigma %g", sigma ); -#ifdef DEBUG - printf( "anti-alias blur matrix is:\n" ); - vips_matrixprint( t[9], NULL ); -#endif /*DEBUG*/ in = t[5]; } @@ -664,7 +627,7 @@ static VipsImage * thumbnail_rotate( VipsObject *process, VipsImage *im ) { VipsImage **t = (VipsImage **) vips_object_local_array( process, 2 ); - VipsAngle angle = get_angle( im ); + VipsAngle angle = vips_autorot_get_angle( im ); if( rotate_image && angle != VIPS_ANGLE_D0 ) {