/** * im_benchmarkn: * @in: input image * @out: output image * @n: iterations * * This operation runs a complicated set of other operations on image @in, * producing image @out. Use @n to set the number of iterations to run: a * larger number will make the operation more CPU-bound, a smaller number will * make the operation more IO-bound. * * See http://www.vips.ecs.soton.ac.uk/index.php?title=Benchmarks for a * detailed discussion of the benchmark and some sample results. * * See also: im_benchmark2(). * * Returns: 0 on success, -1 on error */ int im_benchmarkn( IMAGE *in, IMAGE *out, int n ) { IMAGE *t[2]; if( n == 0 ) /* To sRGB. */ return( im_LabQ2disp( in, out, im_col_displays( 7 ) ) ); else return( im_open_local_array( out, t, 2, "benchmarkn", "p" ) || benchmark( in, t[0] ) || /* Expand back to the original size again ... * benchmark does a 200 pixel crop plus a 10% shrink, * so if we chain many of them together the image gets * too small. */ im_affinei_all( t[0], t[1], vips_interpolate_bilinear_static(), (double) in->Xsize / t[0]->Xsize, 0, 0, (double) in->Ysize / t[0]->Ysize, 0, 0 ) || im_benchmarkn( t[1], out, n - 1 ) ); }
int im_similarity( IMAGE *in, IMAGE *out, double a, double b, double dx, double dy ) { return( im_affinei_all( in, out, vips_interpolate_bilinear_static(), a, -b, b, a, dx, dy ) ); }
/* Call im_affinei_all via arg vector. */ static int affinei_all_vec( im_object *argv ) { VipsInterpolate *interpolate = VIPS_INTERPOLATE( argv[2] ); double a = *((double *) argv[3]); double b = *((double *) argv[4]); double c = *((double *) argv[5]); double d = *((double *) argv[6]); double dx = *((double *) argv[7]); double dy = *((double *) argv[8]); return( im_affinei_all( argv[0], argv[1], interpolate, a, b, c, d, dx, dy ) ); }
/* The main part of the benchmark ... transform labq to labq. Chain several of * these together to get a CPU-bound operation. */ static int benchmark( IMAGE *in, IMAGE *out ) { IMAGE *t[18]; double one[3] = { 1.0, 1.0, 1.0 }; double zero[3] = { 0.0, 0.0, 0.0 }; double darken[3] = { 1.0 / 1.18, 1.0, 1.0 }; double whitepoint[3] = { 1.06, 1.0, 1.01 }; double shadow[3] = { -2, 0, 0 }; double white[3] = { 100, 0, 0 }; DOUBLEMASK *d652d50 = im_create_dmaskv( "d652d50", 3, 3, 1.13529, -0.0604663, -0.0606321, 0.0975399, 0.935024, -0.0256156, -0.0336428, 0.0414702, 0.994135 ); im_add_close_callback( out, (im_callback_fn) im_free_dmask, d652d50, NULL ); return( /* Set of descriptors for this operation. */ im_open_local_array( out, t, 18, "im_benchmark", "p" ) || /* Unpack to float. */ im_LabQ2Lab( in, t[0] ) || /* Crop 100 pixels off all edges. */ im_extract_area( t[0], t[1], 100, 100, t[0]->Xsize - 200, t[0]->Ysize - 200 ) || /* Shrink by 10%, bilinear interp. */ im_affinei_all( t[1], t[2], vips_interpolate_bilinear_static(), 0.9, 0, 0, 0.9, 0, 0 ) || /* Find L ~= 100 areas (white surround). */ im_extract_band( t[2], t[3], 0 ) || im_moreconst( t[3], t[4], 99 ) || /* Adjust white point and shadows. */ im_lintra_vec( 3, darken, t[2], zero, t[5] ) || im_Lab2XYZ( t[5], t[6] ) || im_recomb( t[6], t[7], d652d50 ) || im_lintra_vec( 3, whitepoint, t[7], zero, t[8] ) || im_lintra( 1.5, t[8], 0.0, t[9] ) || im_XYZ2Lab( t[9], t[10] ) || im_lintra_vec( 3, one, t[10], shadow, t[11] ) || /* Make a solid white image. */ im_black( t[12], t[4]->Xsize, t[4]->Ysize, 3 ) || im_lintra_vec( 3, zero, t[12], white, t[13] ) || /* Reattach border. */ im_ifthenelse( t[4], t[13], t[11], t[14] ) || /* Sharpen. */ im_Lab2LabQ( t[14], t[15] ) || im_sharpen( t[15], out, 11, 2.5, 40, 20, 0.5, 1.5 ) ); }
static int shrink_factor( IMAGE *in, IMAGE *out, int shrink, double residual, VipsInterpolate *interp ) { IMAGE *t[9]; VipsImage **s = (VipsImage **) vips_object_local_array( VIPS_OBJECT( out ), 1 ); IMAGE *x; int tile_width; int tile_height; int nlines; if( im_open_local_array( out, t, 9, "thumbnail", "p" ) ) return( -1 ); x = in; /* Unpack the two coded formats we support to float for processing. */ if( x->Coding == IM_CODING_LABQ ) { if( verbose ) printf( "unpacking LAB to RGB\n" ); if( im_LabQ2disp( x, t[1], im_col_displays( 7 ) ) ) return( -1 ); x = t[1]; } else if( x->Coding == IM_CODING_RAD ) { if( verbose ) printf( "unpacking Rad to float\n" ); if( im_rad2float( x, t[1] ) ) return( -1 ); x = t[1]; } if( im_shrink( x, t[2], shrink, shrink ) ) return( -1 ); /* We want to make sure we read the image sequentially. * However, the convolution we may be doing later will force us * into SMALLTILE or maybe FATSTRIP mode and that will break * sequentiality. * * So ... read into a cache where tiles are scanlines, and make sure * we keep enough scanlines to be able to serve a line of tiles. */ vips_get_tile_size( t[2], &tile_width, &tile_height, &nlines ); if( vips_tilecache( t[2], &s[0], "tile_width", t[2]->Xsize, "tile_height", 10, "max_tiles", (nlines * 2) / 10, "strategy", VIPS_CACHE_SEQUENTIAL, NULL ) || im_affinei_all( s[0], t[4], interp, residual, 0, 0, residual, 0, 0 ) ) return( -1 ); x = t[4]; /* If we are upsampling, don't sharpen, since nearest looks dumb * sharpened. */ if( shrink > 1 && residual <= 1.0 && !nosharpen ) { if( verbose ) printf( "sharpening thumbnail\n" ); if( im_conv( x, t[5], sharpen_filter() ) ) return( -1 ); x = t[5]; } /* Colour management: we can transform the image if we have an output * profile and an input profile. The input profile can be in the * image, or if there is no profile there, supplied by the user. */ if( export_profile && (im_header_get_typeof( x, IM_META_ICC_NAME ) || import_profile) ) { if( im_header_get_typeof( x, IM_META_ICC_NAME ) ) { if( verbose ) printf( "importing with embedded profile\n" ); if( im_icc_import_embedded( x, t[6], IM_INTENT_RELATIVE_COLORIMETRIC ) ) return( -1 ); } else { if( verbose ) printf( "importing with profile %s\n", import_profile ); if( im_icc_import( x, t[6], import_profile, IM_INTENT_RELATIVE_COLORIMETRIC ) ) return( -1 ); } if( verbose ) printf( "exporting with profile %s\n", export_profile ); if( im_icc_export_depth( t[6], t[7], 8, export_profile, IM_INTENT_RELATIVE_COLORIMETRIC ) ) return( -1 ); x = t[7]; } if( delete_profile ) { if( verbose ) printf( "deleting profile from output image\n" ); if( im_meta_get_typeof( x, IM_META_ICC_NAME ) && !im_meta_remove( x, IM_META_ICC_NAME ) ) return( -1 ); } if( im_copy( x, out ) ) return( -1 ); return( 0 ); }