static int read_image( Read *read, VipsImage *out ) { VipsImage **t = (VipsImage **) vips_object_local_array( VIPS_OBJECT( out ), 3 ); webp_decoder decoder; t[0] = vips_image_new_memory(); if( read_header( read, t[0] ) ) return( -1 ); if( vips_image_write_prepare( t[0] ) ) return( -1 ); if( t[0]->Bands == 3 ) decoder = WebPDecodeRGBInto; else decoder = WebPDecodeRGBAInto; if( !decoder( (uint8_t *) read->data, read->length, VIPS_IMAGE_ADDR( t[0], 0, 0 ), VIPS_IMAGE_SIZEOF_IMAGE( t[0] ), VIPS_IMAGE_SIZEOF_LINE( t[0] ) ) ) { vips_error( "webp2vips", "%s", _( "unable to read pixels" ) ); return( -1 ); } if( vips_image_write( t[0], out ) ) return( -1 ); return( 0 ); }
static int read_image( Read *read, VipsImage *out ) { VipsImage **t = (VipsImage **) vips_object_local_array( VIPS_OBJECT( out ), 3 ); t[0] = vips_image_new_memory(); if( read_header( read, t[0] ) ) return( -1 ); if( vips_image_write_prepare( t[0] ) ) return( -1 ); read->config.output.u.RGBA.rgba = VIPS_IMAGE_ADDR( t[0], 0, 0 ); read->config.output.u.RGBA.stride = VIPS_IMAGE_SIZEOF_LINE( t[0] ); read->config.output.u.RGBA.size = VIPS_IMAGE_SIZEOF_IMAGE( t[0] ); read->config.output.is_external_memory = 1; if( WebPDecode( (uint8_t *) read->data, read->length, &read->config) != VP8_STATUS_OK ) { vips_error( "webp2vips", "%s", _( "unable to read pixels" ) ); return( -1 ); } if( vips_image_write( t[0], out ) ) return( -1 ); return( 0 ); }
/* The inverse: take ink to a vec of double. Used in the vips7 compat * wrappers. Result valid while im is valid. */ double * vips__ink_to_vector( const char *domain, VipsImage *im, VipsPel *ink, int *n ) { VipsImage **t = (VipsImage **) vips_object_local_array( VIPS_OBJECT( im ), 6 ); double *result; #ifdef VIPS_DEBUG printf( "vips__ink_to_vector: starting\n" ); #endif /*VIPS_DEBUG*/ /* Wrap a VipsImage around ink. */ t[0] = vips_image_new_from_memory( ink, 1, 1, VIPS_IMAGE_SIZEOF_PEL( im ), VIPS_FORMAT_UCHAR ); if( vips_copy( t[0], &t[1], "bands", im->Bands, "format", im->BandFmt, "coding", im->Coding, "interpretation", im->Type, NULL ) ) return( NULL ); /* The image may be coded .. unpack to double. */ if( vips_image_decode( t[1], &t[2] ) || vips_cast( t[2], &t[3], VIPS_FORMAT_DOUBLE, NULL ) ) return( NULL ); /* To a mem buffer, then copy to out. */ if( !(t[4] = vips_image_new_memory()) || vips_image_write( t[3], t[4] ) ) return( NULL ); if( !(result = VIPS_ARRAY( im, t[4]->Bands, double )) ) return( NULL ); memcpy( result, t[4]->data, VIPS_IMAGE_SIZEOF_PEL( t[4] ) ); *n = t[4]->Bands; #ifdef VIPS_DEBUG { int i; printf( "vips__ink_to_vector:\n" ); printf( "\tink = " ); for( i = 0; i < n; i++ ) printf( "%d ", ink[i] ); printf( "\n" ); printf( "\tvec = " ); for( i = 0; i < *n; i++ ) printf( "%d ", result[i] ); printf( "\n" ); } #endif /*VIPS_DEBUG*/ return( result ); }
static int png2vips_image( Read *read, VipsImage *out ) { int interlace_type = png_get_interlace_type( read->pPng, read->pInfo ); VipsImage **t = (VipsImage **) vips_object_local_array( VIPS_OBJECT( out ), 3 ); if( interlace_type != PNG_INTERLACE_NONE ) { /* Arg awful interlaced image. We have to load to a huge mem * buffer, then copy to out. */ t[0] = vips_image_new_memory(); if( png2vips_header( read, t[0] ) || png2vips_interlace( read, t[0] ) || vips_image_write( t[0], out ) ) return( -1 ); } else { t[0] = vips_image_new(); if( png2vips_header( read, t[0] ) || vips_image_generate( t[0], NULL, png2vips_generate, NULL, read, NULL ) || vips_sequential( t[0], &t[1], "tile_height", 8, "access", read->readbehind ? VIPS_ACCESS_SEQUENTIAL : VIPS_ACCESS_SEQUENTIAL_UNBUFFERED, NULL ) || vips_image_write( t[1], out ) ) return( -1 ); } return( 0 ); }
/* Auto-rotate, if rotate_image is set. */ static VipsImage * read_jpeg_rotate( VipsObject *process, VipsImage *im ) { VipsImage **t = (VipsImage **) vips_object_local_array( process, 2 ); VipsAngle angle = vips_autorot_get_angle( im ); if( angle != VIPS_ANGLE_D0 ) { /* Need to copy to memory or disc, we have to stay seq. */ const guint64 image_size = VIPS_IMAGE_SIZEOF_IMAGE( im ); const guint64 disc_threshold = vips_get_disc_threshold(); if( image_size > disc_threshold ) t[0] = vips_image_new_temp_file( "%s.v" ); else t[0] = vips_image_new_memory(); if( vips_image_write( im, t[0] ) || vips_rot( t[0], &t[1], angle, NULL ) ) return( NULL ); im = t[1]; (void) vips_image_remove( im, ORIENTATION ); } return( im ); }
static int vips_labelregions_build( VipsObject *object ) { VipsMorphology *morphology = VIPS_MORPHOLOGY( object ); VipsImage *in = morphology->in; VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 ); VipsImage *mask; int segments; int *m; int x, y; if( VIPS_OBJECT_CLASS( vips_labelregions_parent_class )-> build( object ) ) return( -1 ); /* Create the zero mask image in memory. */ mask = vips_image_new_memory(); g_object_set( object, "mask", mask, NULL ); if( vips_black( &t[0], in->Xsize, in->Ysize, NULL ) || vips_cast( t[0], &t[1], VIPS_FORMAT_INT, NULL ) || vips_image_write( t[1], mask ) ) return( -1 ); segments = 1; m = (int *) mask->data; for( y = 0; y < mask->Ysize; y++ ) { for( x = 0; x < mask->Xsize; x++ ) { if( !m[x] ) { /* Use a direct path for speed. */ if( vips__draw_flood_direct( mask, in, segments, x, y ) ) return( -1 ); segments += 1; } } m += mask->Xsize; } g_object_set( object, "segments", segments, NULL ); return( 0 ); }
static int vips_freqmult_build( VipsObject *object ) { VipsFreqfilt *freqfilt = VIPS_FREQFILT( object ); VipsFreqmult *freqmult = (VipsFreqmult *) object; VipsImage **t = (VipsImage **) vips_object_local_array( object, 5 ); VipsImage *in; if( VIPS_OBJECT_CLASS( vips_freqmult_parent_class )-> build( object ) ) return( -1 ); in = freqfilt->in; if( vips_band_format_iscomplex( in->BandFmt ) ) { if( vips_multiply( in, freqmult->mask, &t[0], NULL ) || vips_invfft( t[0], &t[1], "real", TRUE, NULL ) ) return( -1 ); in = t[1]; } else { /* Optimisation: output of vips_invfft() is double, we * will usually cast to char, so rather than keeping a * large double buffer and partial to char from that, * cast to a memory buffer and copy to out from that. * * FIXME does this actually work now we're a class? test * perhaps we need a temporary object */ t[4] = vips_image_new_memory(); if( vips_fwfft( in, &t[0], NULL ) || vips_multiply( t[0], freqmult->mask, &t[1], NULL ) || vips_invfft( t[1], &t[2], "real", TRUE, NULL ) || vips_cast( t[2], &t[3], in->BandFmt, NULL ) || vips_image_write( t[3], t[4] ) ) return( -1 ); in = t[4]; } if( vips_image_write( in, freqfilt->out ) ) return( -1 ); return( 0 ); }
/* Auto-rotate, if rotate_image is set. */ static VipsImage * thumbnail_rotate( VipsObject *process, VipsImage *im ) { VipsImage **t = (VipsImage **) vips_object_local_array( process, 2 ); VipsAngle angle = vips_autorot_get_angle( im ); if( rotate_image && angle != VIPS_ANGLE_D0 ) { vips_info( "vipsthumbnail", "rotating by %s", vips_enum_nick( VIPS_TYPE_ANGLE, angle ) ); /* Need to copy to memory, we have to stay seq. */ t[0] = vips_image_new_memory(); if( vips_image_write( im, t[0] ) || vips_rot( t[0], &t[1], angle, NULL ) ) return( NULL ); im = t[1]; vips_autorot_remove_angle( im ); } return( im ); }
/* Calculate a pixel for an image from a vec of double. Valid while im is * valid. imag can be NULL, meaning all zero for the imaginary component. */ VipsPel * vips__vector_to_ink( const char *domain, VipsImage *im, double *real, double *imag, int n ) { /* Run our pipeline relative to this. */ VipsImage *context = vips_image_new(); VipsImage **t = (VipsImage **) vips_object_local_array( VIPS_OBJECT( context ), 6 ); VipsBandFormat format; int bands; double *ones; VipsPel *result; int i; #ifdef VIPS_DEBUG printf( "vips__vector_to_ink: starting\n" ); #endif /*VIPS_DEBUG*/ vips_image_decode_predict( im, &bands, &format ); ones = VIPS_ARRAY( im, n, double ); for( i = 0; i < n; i++ ) ones[i] = 1.0; /* Cast vec to match the decoded image. */ if( vips_black( &t[1], 1, 1, "bands", bands, NULL ) || vips_linear( t[1], &t[2], ones, real, n, NULL ) || vips_cast( t[2], &t[3], format, NULL ) ) { g_object_unref( context ); return( NULL ); } /* And now recode the vec to match the original im. */ if( vips_image_encode( t[3], &t[4], im->Coding ) || !(t[5] = vips_image_new_memory()) || vips_image_write( t[4], t[5] ) ) { g_object_unref( context ); return( NULL ); } if( !(result = VIPS_ARRAY( im, VIPS_IMAGE_SIZEOF_PEL( t[5] ), VipsPel )) ) { g_object_unref( context ); return( NULL ); } g_assert( VIPS_IMAGE_SIZEOF_PEL( t[5] ) == VIPS_IMAGE_SIZEOF_PEL( im ) ); memcpy( result, t[5]->data, VIPS_IMAGE_SIZEOF_PEL( im ) ); g_object_unref( context ); #ifdef VIPS_DEBUG { int i; printf( "vips__vector_to_ink:\n" ); printf( "\t(real, imag) = " ); for( i = 0; i < n; i++ ) printf( "(%g, %g) ", real[i], imag ? imag[i] : 0 ); printf( "\n" ); printf( "\tink = " ); for( i = 0; i < VIPS_IMAGE_SIZEOF_PEL( im ); i++ ) printf( "%d ", result[i] ); printf( "\n" ); } #endif /*VIPS_DEBUG*/ return( result ); }
/* Make a pair of vector constants into a set of formatted pixels. bands can * be 3 while n is 1, meaning expand the constant to the number of bands. * imag can be NULL, meaning all zero for the imaginary component. */ VipsPel * vips__vector_to_pels( const char *domain, int bands, VipsBandFormat format, VipsCoding coding, double *real, double *imag, int n ) { /* Run our pipeline relative to this. */ VipsImage *context = vips_image_new(); VipsImage **t = (VipsImage **) vips_object_local_array( VIPS_OBJECT( context ), 8 ); VipsImage *in; double *ones; VipsPel *result; int i; #ifdef VIPS_DEBUG printf( "vips__vector_to_pels: starting\n" ); #endif /*VIPS_DEBUG*/ ones = VIPS_ARRAY( context, n, double ); for( i = 0; i < n; i++ ) ones[i] = 1.0; /* Make the real and imaginary parts. */ if( vips_black( &t[0], 1, 1, "bands", bands, NULL ) || vips_linear( t[0], &t[1], ones, real, n, NULL ) ) { g_object_unref( context ); return( NULL ); } in = t[1]; if( imag ) { if( vips_black( &t[2], 1, 1, "bands", bands, NULL ) || vips_linear( t[2], &t[3], ones, imag, n, NULL ) || vips_complexform( in, t[3], &t[4], NULL ) ) { g_object_unref( context ); return( NULL ); } in = t[4]; } /* Cast to the output type and coding. */ if( vips_cast( in, &t[5], format, NULL ) || vips_image_encode( t[5], &t[6], coding ) ) { g_object_unref( context ); return( NULL ); } in = t[6]; /* Write to memory, copy to output buffer. */ if( !(t[7] = vips_image_new_memory()) || vips_image_write( in, t[7] ) ) { g_object_unref( context ); return( NULL ); } in = t[7]; if( !(result = VIPS_ARRAY( NULL, VIPS_IMAGE_SIZEOF_PEL( in ), VipsPel )) ) { g_object_unref( context ); return( NULL ); } memcpy( result, in->data, VIPS_IMAGE_SIZEOF_PEL( in ) ); #ifdef VIPS_DEBUG { int i; printf( "vips__vector_to_ink:\n" ); printf( "\t(real, imag) = " ); for( i = 0; i < n; i++ ) printf( "(%g, %g) ", real[i], imag ? imag[i] : 0 ); printf( "\n" ); printf( "\tink = " ); for( i = 0; i < VIPS_IMAGE_SIZEOF_PEL( in ); i++ ) printf( "%d ", result[i] ); printf( "\n" ); } #endif /*VIPS_DEBUG*/ g_object_unref( context ); return( result ); }
#include <vips/vips.h> #include "statistic.h" #include "hough.h" G_DEFINE_ABSTRACT_TYPE( VipsHough, vips_hough, VIPS_TYPE_STATISTIC ); static VipsImage * vips_hough_new_accumulator( VipsHough *hough ) { VipsHoughClass *class = VIPS_HOUGH_GET_CLASS( hough ); VipsStatistic *statistic = VIPS_STATISTIC( hough ); VipsImage *accumulator; accumulator = vips_image_new_memory(); vips_image_pipelinev( accumulator, VIPS_DEMAND_STYLE_ANY, statistic->ready, NULL ); if( class->init_accumulator( hough, accumulator ) || vips_image_write_prepare( accumulator ) ) { g_object_unref( accumulator ); return( NULL ); } /* vips does not guarantee image mem is zeroed. */ memset( VIPS_IMAGE_ADDR( accumulator, 0, 0 ), 0, VIPS_IMAGE_SIZEOF_IMAGE( accumulator ) );