add basic auto-rotate support to vipsthumbnail

This commit is contained in:
John Cupitt 2014-03-06 19:39:18 +00:00
parent 7ed644789c
commit ffed43dffe
4 changed files with 55 additions and 19 deletions

View File

@ -9,6 +9,7 @@
- better rounding in vips_flatten() - better rounding in vips_flatten()
- VipsStatistic operations are sequential - VipsStatistic operations are sequential
- vipsthumbnail attaches main image metadata to embedded thumbnails - vipsthumbnail attaches main image metadata to embedded thumbnails
- vipsthumbnail has --rotate auto-rotate option
6/3/14 started 7.38.6 6/3/14 started 7.38.6
- grey ramp minimum was wrong - grey ramp minimum was wrong

1
TODO
View File

@ -1,3 +1,4 @@
- vipsthumbnail needs an auto-rotate flag
- think of a better way to support skipahead - think of a better way to support skipahead

View File

@ -1,18 +1,6 @@
/* make a test pattern to show the point's frequency response /* base class for point-wise creators
* *
* Copyright: 1990, 1991, N.Dessipris.
*
* Author N. Dessipris
* Written on 30/05/1990
* Updated on: 27/01/1991, 07/03/1991,
* 22/7/93 JC
* - im_outcheck() added
* 30/8/95 JC
* - modernized
* 1/2/11
* - gtk-doc
* 13/6/13 * 13/6/13
* - redo as a class
*/ */
/* /*

View File

@ -59,6 +59,8 @@
#include <vips/vips.h> #include <vips/vips.h>
#define ORIENTATION ("exif-ifd0-Orientation")
static char *thumbnail_size = "128"; static char *thumbnail_size = "128";
static int thumbnail_width = 128; static int thumbnail_width = 128;
static int thumbnail_height = 128; static int thumbnail_height = 128;
@ -70,6 +72,7 @@ static char *convolution_mask = "mild";
static gboolean delete_profile = FALSE; static gboolean delete_profile = FALSE;
static gboolean linear_processing = FALSE; static gboolean linear_processing = FALSE;
static gboolean crop_image = FALSE; static gboolean crop_image = FALSE;
static gboolean rotate_image = FALSE;
/* Deprecated and unused. /* Deprecated and unused.
*/ */
@ -108,6 +111,9 @@ static GOptionEntry options[] = {
{ "crop", 'c', 0, { "crop", 'c', 0,
G_OPTION_ARG_NONE, &crop_image, G_OPTION_ARG_NONE, &crop_image,
N_( "crop exactly to SIZE" ), NULL }, N_( "crop exactly to SIZE" ), NULL },
{ "rotate", 't', 0,
G_OPTION_ARG_NONE, &rotate_image,
N_( "auto-rotate" ), NULL },
{ "delete", 'd', 0, { "delete", 'd', 0,
G_OPTION_ARG_NONE, &delete_profile, G_OPTION_ARG_NONE, &delete_profile,
N_( "delete profile from exported image" ), NULL }, N_( "delete profile from exported image" ), NULL },
@ -123,6 +129,23 @@ static GOptionEntry options[] = {
{ NULL } { NULL }
}; };
static VipsAngle
get_angle( VipsImage *im )
{
VipsAngle angle;
const char *orientation;
angle = VIPS_ANGLE_0;
if( vips_image_get_typeof( im, ORIENTATION ) &&
vips_image_get_string( im, ORIENTATION, &orientation ) ) {
if( vips_isprefix( "6", orientation ) )
angle = VIPS_ANGLE_90;
}
return( angle );
}
/* Calculate the shrink factors. /* Calculate the shrink factors.
* *
* We shrink in two stages: first, a shrink with a block average. This can * We shrink in two stages: first, a shrink with a block average. This can
@ -130,8 +153,13 @@ static GOptionEntry options[] = {
* a supplied interpolator to get the exact size we want. * a supplied interpolator to get the exact size we want.
*/ */
static int static int
calculate_shrink( int width, int height, double *residual ) calculate_shrink( VipsImage *im, double *residual )
{ {
VipsAngle angle = get_angle( im );
gboolean rotate = angle == VIPS_ANGLE_90 || angle == VIPS_ANGLE_270;
int width = rotate_image && rotate ? im->Ysize : im->Xsize;
int height = rotate_image && rotate ? im->Xsize : im->Ysize;
/* 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.
* *
@ -171,7 +199,7 @@ calculate_shrink( int width, int height, double *residual )
static int static int
thumbnail_find_jpegshrink( VipsImage *im ) thumbnail_find_jpegshrink( VipsImage *im )
{ {
int shrink = calculate_shrink( im->Xsize, im->Ysize, NULL ); int shrink = calculate_shrink( im, NULL );
/* 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.
@ -224,7 +252,7 @@ thumbnail_get_thumbnail( VipsImage *im )
return( NULL ); return( NULL );
} }
calculate_shrink( thumb->Xsize, thumb->Ysize, &residual ); calculate_shrink( thumb, &residual );
if( residual > 1.0 ) { if( residual > 1.0 ) {
vips_info( "vipsthumbnail", "jpeg thumbnail too small" ); vips_info( "vipsthumbnail", "jpeg thumbnail too small" );
g_object_unref( thumb ); g_object_unref( thumb );
@ -340,7 +368,7 @@ thumbnail_interpolator( VipsObject *process, VipsImage *in )
double residual; double residual;
VipsInterpolate *interp; VipsInterpolate *interp;
calculate_shrink( in->Xsize, in->Ysize, &residual ); calculate_shrink( in, &residual );
/* For images smaller than the thumbnail, we upscale with nearest /* For images smaller than the thumbnail, we upscale with nearest
* neighbor. Otherwise we makes thumbnails that look fuzzy and awful. * neighbor. Otherwise we makes thumbnails that look fuzzy and awful.
@ -446,7 +474,7 @@ thumbnail_shrink( VipsObject *process, VipsImage *in,
return( NULL ); return( NULL );
in = t[2]; in = t[2];
shrink = calculate_shrink( in->Xsize, in->Ysize, &residual ); shrink = calculate_shrink( in, &residual );
vips_info( "vipsthumbnail", "integer shrink by %d", shrink ); vips_info( "vipsthumbnail", "integer shrink by %d", shrink );
@ -581,6 +609,22 @@ thumbnail_crop( VipsObject *process, VipsImage *im )
return( im ); return( im );
} }
/* Auto-rotate, if rotate_image is set.
*/
static VipsImage *
thumbnail_rotate( VipsObject *process, VipsImage *im )
{
VipsImage **t = (VipsImage **) vips_object_local_array( process, 2 );
if( rotate_image ) {
if( vips_rot( im, &t[0], get_angle( im ), NULL ) )
return( NULL );
im = t[0];
}
return( im );
}
/* Given (eg.) "/poop/somefile.png", write @im to the thumbnail name, /* Given (eg.) "/poop/somefile.png", write @im to the thumbnail name,
* (eg.) "/poop/tn_somefile.jpg". * (eg.) "/poop/tn_somefile.jpg".
*/ */
@ -636,13 +680,15 @@ thumbnail_process( VipsObject *process, const char *filename )
VipsInterpolate *interp; VipsInterpolate *interp;
VipsImage *thumbnail; VipsImage *thumbnail;
VipsImage *crop; VipsImage *crop;
VipsImage *rotate;
if( !(in = thumbnail_open( process, filename )) || if( !(in = thumbnail_open( process, filename )) ||
!(interp = thumbnail_interpolator( process, in )) || !(interp = thumbnail_interpolator( process, in )) ||
!(thumbnail = !(thumbnail =
thumbnail_shrink( process, in, interp, sharpen )) || thumbnail_shrink( process, in, interp, sharpen )) ||
!(crop = thumbnail_crop( process, thumbnail )) || !(crop = thumbnail_crop( process, thumbnail )) ||
thumbnail_write( crop, filename ) ) !(rotate = thumbnail_rotate( process, crop )) ||
thumbnail_write( rotate, filename ) )
return( -1 ); return( -1 );
return( 0 ); return( 0 );