static void * vips_fits_write_meta( VipsImage *image, const char *field, GValue *value, void *a ) { VipsFits *fits = (VipsFits *) a; int status; const char *value_str; status = 0; /* We want fields which start "fits-". */ if( !vips_isprefix( "fits-", field ) ) return( NULL ); /* The value should be a refstring, since we wrote it in fits2vips * above ^^. */ value_str = vips_value_get_ref_string( value, NULL ); VIPS_DEBUG_MSG( "vips_fits_write_meta: setting meta on fits image:\n" ); VIPS_DEBUG_MSG( " value == \"%s\"\n", value_str ); if( fits_write_record( fits->fptr, value_str, &status ) ) { vips_fits_error( status ); return( a ); } return( NULL ); }
static void vips_exif_set_int( ExifData *ed, ExifEntry *entry, unsigned long component, void *data ) { int value = *((int *) data); ExifByteOrder bo; size_t sizeof_component; size_t offset = component; if( entry->components <= component ) { VIPS_DEBUG_MSG( "vips_exif_set_int: too few components\n" ); return; } /* Wait until after the component check to make sure we cant get /0. */ bo = exif_data_get_byte_order( ed ); sizeof_component = entry->size / entry->components; offset = component * sizeof_component; VIPS_DEBUG_MSG( "vips_exif_set_int: %s = %d\n", vips_exif_entry_get_name( entry ), value ); if( entry->format == EXIF_FORMAT_SHORT ) exif_set_short( entry->data + offset, bo, value ); else if( entry->format == EXIF_FORMAT_SSHORT ) exif_set_sshort( entry->data + offset, bo, value ); else if( entry->format == EXIF_FORMAT_LONG ) exif_set_long( entry->data + offset, bo, value ); else if( entry->format == EXIF_FORMAT_SLONG ) exif_set_slong( entry->data + offset, bo, value ); }
/* Renumber after clustering. We will have removed a lot of hlines ... shuffle * the rest down, adjust all the vline references. */ static void boxes_renumber( Boxes *boxes ) { int i, j; VIPS_DEBUG_MSG( "boxes_renumber: renumbering ...\n" ); /* Loop for all zero-weight hlines. */ for( i = 0; i < boxes->n_hline; ) { if( boxes->hline[i].weight > 0 ) { i++; continue; } /* We move hlines i + 1 down, so we need to adjust all * band[] refs to match. */ for( j = 0; j < boxes->n_velement; j++ ) if( boxes->velement[j].band > i ) boxes->velement[j].band -= 1; memmove( boxes->hline + i, boxes->hline + i + 1, sizeof( HLine ) * (boxes->n_hline - i - 1) ); boxes->n_hline -= 1; } VIPS_DEBUG_MSG( "boxes_renumber: ... %d hlines remain\n", boxes->n_hline ); }
/* Does both signed and unsigned rationals from a double*. * * Don't change the exit entry if the value currently there is a good * approximation of the double we are trying to set. */ static void vips_exif_set_double( ExifData *ed, ExifEntry *entry, unsigned long component, void *data ) { double value = *((double *) data); ExifByteOrder bo; size_t sizeof_component; size_t offset; double old_value; if( entry->components <= component ) { VIPS_DEBUG_MSG( "vips_exif_set_double: " "too few components\n" ); return; } /* Wait until after the component check to make sure we cant get /0. */ bo = exif_data_get_byte_order( ed ); sizeof_component = entry->size / entry->components; offset = component * sizeof_component; VIPS_DEBUG_MSG( "vips_exif_set_double: %s = %g\n", vips_exif_entry_get_name( entry ), value ); if( entry->format == EXIF_FORMAT_RATIONAL ) { ExifRational rv; rv = exif_get_rational( entry->data + offset, bo ); old_value = (double) rv.numerator / rv.denominator; if( VIPS_FABS( old_value - value ) > 0.0001 ) { vips_exif_double_to_rational( value, &rv ); VIPS_DEBUG_MSG( "vips_exif_set_double: %u / %u\n", rv.numerator, rv.denominator ); exif_set_rational( entry->data + offset, bo, rv ); } } else if( entry->format == EXIF_FORMAT_SRATIONAL ) { ExifSRational srv; srv = exif_get_srational( entry->data + offset, bo ); old_value = (double) srv.numerator / srv.denominator; if( VIPS_FABS( old_value - value ) > 0.0001 ) { vips_exif_double_to_srational( value, &srv ); VIPS_DEBUG_MSG( "vips_exif_set_double: %d / %d\n", srv.numerator, srv.denominator ); exif_set_srational( entry->data + offset, bo, srv ); } } }
/* Find existing tile, make a new tile, or if we have a full set of tiles, * reuse one. */ static VipsTile * vips_tile_find( VipsBlockCache *cache, int x, int y ) { VipsTile *tile; VipsTileSearch search; /* In cache already? */ if( (tile = vips_tile_search( cache, x, y )) ) { VIPS_DEBUG_MSG( "vips_tile_find: tile %d x %d in cache\n", x, y ); return( tile ); } /* VipsBlockCache not full? */ if( cache->max_tiles == -1 || cache->ntiles < cache->max_tiles ) { VIPS_DEBUG_MSG( "vips_tile_find: making new tile at %d x %d\n", x, y ); if( !(tile = vips_tile_new( cache, x, y )) ) return( NULL ); return( tile ); } /* Reuse an old one. */ search.oldest = cache->time; search.topmost = cache->in->Ysize; search.tile = NULL; g_hash_table_foreach( cache->tiles, vips_tile_search_recycle, &search ); tile = search.tile; if( !tile ) { /* There are no tiles we can reuse -- we have to make another * for now. They will get culled down again next time around. */ if( !(tile = vips_tile_new( cache, x, y )) ) return( NULL ); return( tile ); } VIPS_DEBUG_MSG( "tilecache: reusing tile %d x %d\n", tile->pos.left, tile->pos.top ); if( vips_tile_move( tile, x, y ) ) return( NULL ); return( tile ); }
int vips__openslide_isslide( const char *filename ) { #ifdef HAVE_OPENSLIDE_3_4 const char *vendor; int ok; vendor = openslide_detect_vendor( filename ); /* Generic tiled tiff images can be opened by openslide as well. * Only offer to load this file if it's not a generic tiff since * we want vips_tiffload() to handle these. */ ok = ( vendor && strcmp( vendor, "generic-tiff" ) != 0 ); VIPS_DEBUG_MSG( "vips__openslide_isslide: %s - %d\n", filename, ok ); return( ok ); #else openslide_t *osr; int ok; ok = 0; osr = openslide_open( filename ); if( osr ) { const char *vendor; /* Generic tiled tiff images can be opened by openslide as * well. Only offer to load this file if it's not a generic * tiff since we want vips_tiffload() to handle these. */ vendor = openslide_get_property_value( osr, OPENSLIDE_PROPERTY_NAME_VENDOR ); /* vendor will be NULL if osr is in error state. */ if( vendor && strcmp( vendor, "generic-tiff" ) != 0 ) ok = 1; openslide_close( osr ); } VIPS_DEBUG_MSG( "vips__openslide_isslide: %s - %d\n", filename, ok ); return( ok ); #endif }
static int vips_statistic_scan( VipsRegion *region, void *seq, void *a, void *b, gboolean *stop ) { VipsStatistic *statistic = VIPS_STATISTIC( a ); VipsStatisticClass *class = VIPS_STATISTIC_GET_CLASS( statistic ); VipsRect *r = ®ion->valid; int lsk = IM_REGION_LSKIP( region ); int y; PEL *p; VIPS_DEBUG_MSG( "vips_statistic_scan: %d x %d @ %d x %d\n", r->width, r->height, r->left, r->top ); p = (PEL *) IM_REGION_ADDR( region, r->left, r->top ); for( y = 0; y < r->height; y++ ) { if( class->scan( statistic, seq, r->left, r->top + y, p, r->width ) ) return( -1 ); p += lsk; } /* If we've requested stop, pass the message on. */ if( statistic->stop ) *stop = TRUE; return( 0 ); }
static int vips_sequential_build( VipsObject *object ) { VipsConversion *conversion = VIPS_CONVERSION( object ); VipsSequential *sequential = (VipsSequential *) object; VIPS_DEBUG_MSG( "vips_sequential_build\n" ); if( VIPS_OBJECT_CLASS( vips_sequential_parent_class )->build( object ) ) return( -1 ); if( vips_image_pio_input( sequential->in ) ) return( -1 ); if( vips_image_copy_fields( conversion->out, sequential->in ) ) return( -1 ); vips_demand_hint( conversion->out, VIPS_DEMAND_STYLE_FATSTRIP, sequential->in, NULL ); if( vips_image_generate( conversion->out, vips_start_one, vips_sequential_generate, vips_stop_one, sequential->in, sequential ) ) return( -1 ); return( 0 ); }
static void vips_operation_finalize( GObject *gobject ) { VIPS_DEBUG_MSG( "vips_operation_finalize: %p\n", gobject ); G_OBJECT_CLASS( vips_operation_parent_class )->finalize( gobject ); }
int vips__openslide_isslide( const char *filename ) { openslide_t *osr; const char *vendor; int ok; ok = 0; if( (osr = openslide_open( filename )) ) { /* Generic tiled tiff images can be opened by openslide as * well. Only offer to load this file if it's not a generic * tiff since we want vips_tiffload() to handle these. */ vendor = openslide_get_property_value( osr, OPENSLIDE_PROPERTY_NAME_VENDOR ); if( vendor && strcmp( vendor, "generic-tiff" ) != 0 ) ok = 1; openslide_close( osr ); } VIPS_DEBUG_MSG( "vips__openslide_isslide: %s - %d\n", filename, ok ); return( ok ); }
int vips__openslide_read_associated( const char *filename, VipsImage *out, const char *associated ) { ReadSlide *rslide; VipsImage *raw; const char *error; VIPS_DEBUG_MSG( "vips__openslide_read_associated: %s %s\n", filename, associated ); /* Memory buffer. Get associated directly to this, then copy to out. */ raw = vips_image_new_buffer(); vips_object_local( out, raw ); if( !(rslide = readslide_new( filename, raw, 0, associated )) || vips_image_write_prepare( raw ) ) return( -1 ); openslide_read_associated_image( rslide->osr, rslide->associated, (uint32_t *) VIPS_IMAGE_ADDR( raw, 0, 0 ) ); error = openslide_get_error( rslide->osr ); if( error ) { vips_error( "openslide2vips", _( "reading associated image: %s" ), error ); return( -1 ); } if( vips_image_write( raw, out ) ) return( -1 ); return( 0 ); }
static int vips_tile_cache_build( VipsObject *object ) { VipsConversion *conversion = VIPS_CONVERSION( object ); VipsTileCache *cache = (VipsTileCache *) object; VIPS_DEBUG_MSG( "vips_tile_cache_build\n" ); if( VIPS_OBJECT_CLASS( vips_tile_cache_parent_class )->build( object ) ) return( -1 ); if( vips_image_pio_input( cache->in ) ) return( -1 ); if( vips_image_copy_fields( conversion->out, cache->in ) ) return( -1 ); vips_demand_hint( conversion->out, VIPS_DEMAND_STYLE_SMALLTILE, cache->in, NULL ); if( vips_image_generate( conversion->out, vips_start_one, vips_tile_cache_gen, vips_stop_one, cache->in, cache ) ) return( -1 ); return( 0 ); }
static void vips_thread_profile_save( VipsThreadProfile *profile ) { g_mutex_lock( vips__global_lock ); VIPS_DEBUG_MSG( "vips_thread_profile_save: %s\n", profile->name ); if( !vips__thread_fp ) { vips__thread_fp = vips__file_open_write( "vips-profile.txt", TRUE ); if( !vips__thread_fp ) { g_mutex_unlock( vips__global_lock ); g_warning( "unable to create profile log" ); return; } printf( "recording profile in vips-profile.txt\n" ); } fprintf( vips__thread_fp, "thread: %s (%p)\n", profile->name, profile ); g_hash_table_foreach( profile->gates, vips_thread_profile_save_cb, vips__thread_fp ); vips_thread_profile_save_gate( profile->memory, vips__thread_fp ); g_mutex_unlock( vips__global_lock ); }
static int vips_sequential_build( VipsObject *object ) { VipsConversion *conversion = VIPS_CONVERSION( object ); VipsSequential *sequential = (VipsSequential *) object; VipsImage *t; VIPS_DEBUG_MSG( "vips_sequential_build\n" ); if( VIPS_OBJECT_CLASS( vips_sequential_parent_class )->build( object ) ) return( -1 ); if( vips_image_pio_input( sequential->in ) ) return( -1 ); if( vips_linecache( sequential->in, &t, "tile_height", sequential->tile_height, "access", sequential->access, NULL ) ) return( -1 ); vips_object_local( object, t ); if( vips_image_pipelinev( conversion->out, VIPS_DEMAND_STYLE_THINSTRIP, t, NULL ) ) return( -1 ); if( vips_image_generate( conversion->out, vips_start_one, vips_sequential_generate, vips_stop_one, t, sequential ) ) return( -1 ); return( 0 ); }
static void vips_exif_update( ExifData *ed, VipsImage *image ) { VipsExifRemove ve; VIPS_DEBUG_MSG( "vips_exif_update: \n" ); /* If this exif came from the image (rather than being an exif block we * have made afresh), then any fields which are in the block but not on * the image must have been deliberately removed. Remove them from the * block as well. * * If there are any string-valued fields (eg. comment etc.) which * exist as libvips metadata tags, we must also remove those from the * exif block. * * libexif does not allow you to change string lengths, you must make * new tags, so we have to remove ready to re-add. */ if( vips_image_get_typeof( image, VIPS_META_EXIF_NAME ) ) { ve.image = image; ve.ed = ed; exif_data_foreach_content( ed, (ExifDataForeachContentFunc) vips_exif_exif_content, &ve ); } /* Walk the image and add any exif- that's set in image metadata. */ vips_image_map( image, vips_exif_image_field, ed ); }
static int vips_region_build( VipsObject *object ) { VipsRegion *region = VIPS_REGION( object ); VipsImage *image = region->im; VIPS_DEBUG_MSG( "vips_region_build: %p\n", region ); if( VIPS_OBJECT_CLASS( vips_region_parent_class )->build( object ) ) return( -1 ); vips__region_take_ownership( region ); /* We're usually inside the ss lock anyway. But be safe ... */ VIPS_GATE_START( "vips_region_build: wait" ); g_mutex_lock( image->sslock ); VIPS_GATE_STOP( "vips_region_build: wait" ); image->regions = g_slist_prepend( image->regions, region ); g_mutex_unlock( image->sslock ); return( 0 ); }
/* Does both signed and unsigned rationals from a char *. */ static void vips_exif_set_rational( ExifData *ed, ExifEntry *entry, unsigned long component, void *data ) { char *value = (char *) data; ExifByteOrder bo; size_t sizeof_component; size_t offset; if( entry->components <= component ) { VIPS_DEBUG_MSG( "vips_exif_set_rational: " "too few components\n" ); return; } /* Wait until after the component check to make sure we cant get /0. */ bo = exif_data_get_byte_order( ed ); sizeof_component = entry->size / entry->components; offset = component * sizeof_component; VIPS_DEBUG_MSG( "vips_exif_set_rational: %s = \"%s\"\n", vips_exif_entry_get_name( entry ), value ); if( entry->format == EXIF_FORMAT_RATIONAL ) { ExifRational rv; vips_exif_parse_rational( value, &rv ); VIPS_DEBUG_MSG( "vips_exif_set_rational: %u / %u\n", rv.numerator, rv.denominator ); exif_set_rational( entry->data + offset, bo, rv ); } else if( entry->format == EXIF_FORMAT_SRATIONAL ) { ExifSRational srv; vips_exif_parse_srational( value, &srv ); VIPS_DEBUG_MSG( "vips_exif_set_rational: %d / %d\n", srv.numerator, srv.denominator ); exif_set_srational( entry->data + offset, bo, srv ); } }
/** * im_fits2vips: * @filename: file to load * @out: image to write to * * Read a FITS image file into a VIPS image. * * See also: im_vips2fits(), #VipsFormat. * * Returns: 0 on success, -1 on error. */ int im_fits2vips( const char *filename, VipsImage *out ) { VipsImage *t; int n_bands; VIPS_DEBUG_MSG( "im_fits2vips: reading \"%s\"\n", filename ); /* fits is naturally a band-separated format. For single-band images, * we can just read out. For many bands, we read each band out * separately then join them. */ if( !(t = vips_image_new()) || vips_object_local( out, t ) || fits2vips_header( filename, t ) ) return( -1 ); n_bands = t->Bands; if( n_bands == 1 ) { if( !(t = vips_image_new()) || vips_object_local( out, t ) || fits2vips( filename, t, 0 ) ) return( -1 ); } else { VipsImage *acc; int i; acc = NULL; for( i = 0; i < n_bands; i++ ) { if( !(t = vips_image_new()) || vips_object_local( out, t ) || fits2vips( filename, t, i ) ) return( -1 ); if( !acc ) acc = t; else { VipsImage *t2; if( !(t2 = vips_image_new()) || vips_object_local( out, t2 ) || im_bandjoin( acc, t, t2 ) ) return( -1 ); acc = t2; } } t = acc; } /* fits has inverted y. */ if( im_flipver( t, out ) ) return( -1 ); return( 0 ); }
static void vips_region_finalize( GObject *gobject ) { #ifdef VIPS_DEBUG VIPS_DEBUG_MSG( "vips_region_finalize: " ); vips_object_print_name( VIPS_OBJECT( gobject ) ); VIPS_DEBUG_MSG( "\n" ); #endif /*VIPS_DEBUG*/ #ifdef VIPS_DEBUG g_mutex_lock( vips__global_lock ); vips__regions_all = g_slist_remove( vips__regions_all, gobject ); g_mutex_unlock( vips__global_lock ); #endif /*VIPS_DEBUG*/ G_OBJECT_CLASS( vips_region_parent_class )->finalize( gobject ); }
static int vips_fits_write( VipsRegion *region, VipsRect *area, void *a ) { VipsFits *fits = (VipsFits *) a; VipsImage *image = fits->image; int es = VIPS_IMAGE_SIZEOF_ELEMENT( image ); int ps = VIPS_IMAGE_SIZEOF_PEL( image ); int status; int y, b, x, k; status = 0; VIPS_DEBUG_MSG( "vips_fits_write: " "writing left = %d, top = %d, width = %d, height = %d\n", area->left, area->top, area->width, area->height ); /* We need to write a band at a time. We can't bandsplit in vips, * since vips_sink_disc() can't loop over many images at once, sadly. */ for( y = 0; y < area->height; y++ ) { VipsPel *p = VIPS_REGION_ADDR( region, area->left, area->top + y ); for( b = 0; b < image->Bands; b++ ) { VipsPel *p1, *q; long fpixel[3]; p1 = p + b * es; q = fits->buffer; for( x = 0; x < area->width; x++ ) { for( k = 0; k < es; k++ ) q[k] = p1[k]; q += es; p1 += ps; } fpixel[0] = area->left + 1; fpixel[1] = area->top + y + 1; fpixel[2] = b + 1; /* No need to lock, write functions are single-threaded. */ if( fits_write_pix( fits->fptr, fits->datatype, fpixel, area->width, fits->buffer, &status ) ) { vips_fits_error( status ); return( -1 ); } } } return( 0 ); }
static void vips_thread_profile_free( VipsThreadProfile *profile ) { VIPS_DEBUG_MSG( "vips_thread_profile_free: %s\n", profile->name ); VIPS_FREEF( g_hash_table_destroy, profile->gates ); VIPS_FREEF( vips_thread_gate_free, profile->memory ); VIPS_FREE( profile ); }
static int vips_fits_set_header( VipsFits *fits, VipsImage *in ) { int status; int bitpix; int i; status = 0; fits->naxis = 3; fits->naxes[0] = in->Xsize; fits->naxes[1] = in->Ysize; fits->naxes[2] = in->Bands; for( i = 0; i < VIPS_NUMBER( fits2vips_formats ); i++ ) if( fits2vips_formats[i][1] == in->BandFmt ) break; if( i == VIPS_NUMBER( fits2vips_formats ) ) { vips_error( "fits", _( "unsupported BandFmt %d\n" ), in->BandFmt ); return( -1 ); } bitpix = fits2vips_formats[i][0]; fits->datatype = fits2vips_formats[i][2]; #ifdef VIPS_DEBUG VIPS_DEBUG_MSG( "naxis = %d\n", fits->naxis ); for( i = 0; i < fits->naxis; i++ ) VIPS_DEBUG_MSG( "%d) %lld\n", i, fits->naxes[i] ); VIPS_DEBUG_MSG( "bitpix = %d\n", bitpix ); #endif /*VIPS_DEBUG*/ if( fits_create_imgll( fits->fptr, bitpix, fits->naxis, fits->naxes, &status ) ) { vips_fits_error( status ); return( -1 ); } if( vips_image_map( in, (VipsImageMapFn) vips_fits_write_meta, fits ) ) return( -1 ); return( 0 ); }
/* Set the EXIF resolution from the vips xres/yres tags. */ static int vips_exif_resolution_from_image( ExifData *ed, VipsImage *image ) { double xres, yres; const char *p; int unit; VIPS_DEBUG_MSG( "vips_exif_resolution_from_image: vips res of %g, %g\n", image->Xres, image->Yres ); /* Default to inches, more progs support it. */ unit = 2; if( vips_image_get_typeof( image, VIPS_META_RESOLUTION_UNIT ) && !vips_image_get_string( image, VIPS_META_RESOLUTION_UNIT, &p ) ) { if( vips_isprefix( "cm", p ) ) unit = 3; else if( vips_isprefix( "none", p ) ) unit = 1; } switch( unit ) { case 1: xres = image->Xres; yres = image->Yres; break; case 2: xres = image->Xres * 25.4; yres = image->Yres * 25.4; break; case 3: xres = image->Xres * 10.0; yres = image->Yres * 10.0; break; default: g_warning( "%s", _( "unknown EXIF resolution unit" ) ); return( 0 ); } /* Main image xres/yres/unit are in ifd0. ifd1 has the thumbnail * xres/yres/unit. */ vips_exif_set_tag( ed, 0, EXIF_TAG_X_RESOLUTION, vips_exif_set_double, (void *) &xres ); vips_exif_set_tag( ed, 0, EXIF_TAG_Y_RESOLUTION, vips_exif_set_double, (void *) &yres ); vips_exif_set_tag( ed, 0, EXIF_TAG_RESOLUTION_UNIT, vips_exif_set_int, (void *) &unit ); return( 0 ); }
void VImage::call_option_string( const char *operation_name, const char *option_string, VOption *options ) throw( VError ) { VipsOperation *operation; VIPS_DEBUG_MSG( "vips_call_by_name: starting for %s ...\n", operation_name ); if( !(operation = vips_operation_new( operation_name )) ) { if( options ) delete options; throw( VError() ); } /* Set str options before vargs options, so the user can't * override things we set deliberately. */ if( option_string && vips_object_set_from_string( VIPS_OBJECT( operation ), option_string ) ) { vips_object_unref_outputs( VIPS_OBJECT( operation ) ); g_object_unref( operation ); delete options; throw( VError() ); } if( options ) options->set_operation( operation ); /* Build from cache. */ if( vips_cache_operation_buildp( &operation ) ) { vips_object_unref_outputs( VIPS_OBJECT( operation ) ); delete options; throw( VError() ); } /* Walk args again, writing output. */ if( options ) options->get_operation( operation ); /* We're done with options! */ delete options; /* The operation we have built should now have been reffed by * one of its arguments or have finished its work. Either * way, we can unref. */ g_object_unref( operation ); }
/** * vips_verror: * @domain: the source of the error * @fmt: printf()-style format string for the error * @ap: arguments to the format string * * Append a message to the error buffer. * * See also: vips_error(). */ void vips_verror( const char *domain, const char *fmt, va_list ap ) { g_mutex_lock( vips__global_lock ); vips_buf_appendf( &vips_error_buf, "%s: ", domain ); vips_buf_vappendf( &vips_error_buf, fmt, ap ); vips_buf_appends( &vips_error_buf, "\n" ); g_mutex_unlock( vips__global_lock ); VIPS_DEBUG_MSG( "vips_verror: %s\n", fmt ); }
static void vips_region_dispose( GObject *gobject ) { VipsRegion *region = VIPS_REGION( gobject ); VipsImage *image = region->im; #ifdef VIPS_DEBUG VIPS_DEBUG_MSG( "vips_region_dispose: " ); vips_object_print_name( VIPS_OBJECT( gobject ) ); VIPS_DEBUG_MSG( "\n" ); #endif /*VIPS_DEBUG*/ vips_object_preclose( VIPS_OBJECT( gobject ) ); /* Stop this sequence. */ vips__region_stop( region ); /* Free any attached memory. */ VIPS_FREEF( vips_window_unref, region->window ); VIPS_FREEF( vips_buffer_unref, region->buffer ); /* Detach from image. */ VIPS_GATE_START( "vips_region_dispose: wait" ); g_mutex_lock( image->sslock ); VIPS_GATE_STOP( "vips_region_dispose: wait" ); image->regions = g_slist_remove( image->regions, region ); g_mutex_unlock( image->sslock ); region->im = NULL; g_object_unref( image ); G_OBJECT_CLASS( vips_region_parent_class )->dispose( gobject ); }
/* Generate func. */ static int vips_tile_cache_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsRegion *in = (VipsRegion *) seq; VipsTileCache *cache = (VipsTileCache *) b; const int tw = cache->tile_width; const int th = cache->tile_height; VipsRect *r = &or->valid; /* Find top left of tiles we need. */ int xs = (r->left / tw) * tw; int ys = (r->top / th) * th; int x, y; g_mutex_lock( cache->lock ); VIPS_DEBUG_MSG( "vips_tile_cache_gen: " "left = %d, top = %d, width = %d, height = %d\n", r->left, r->top, r->width, r->height ); for( y = ys; y < VIPS_RECT_BOTTOM( r ); y += th ) for( x = xs; x < VIPS_RECT_RIGHT( r ); x += tw ) { Tile *tile; VipsRect tarea; VipsRect hit; if( !(tile = tile_find( cache, in, x, y )) ) { g_mutex_unlock( cache->lock ); return( -1 ); } /* The area of the tile. */ tarea.left = x; tarea.top = y; tarea.width = tw; tarea.height = th; /* The part of the tile that we need. */ vips_rect_intersectrect( &tarea, r, &hit ); copy_region( tile->region, or, &hit ); } g_mutex_unlock( cache->lock ); return( 0 ); }
int vips__fits_read( const char *filename, VipsImage *out ) { VipsImage *t; int n_bands; VIPS_DEBUG_MSG( "fits2vips: reading \"%s\"\n", filename ); /* fits is naturally a band-separated format. For single-band images * we can just read out. For many bands we read each band out * separately then join them. */ t = vips_image_new(); if( vips__fits_read_header( filename, t ) ) { g_object_unref( t ); return( -1 ); } n_bands = t->Bands; g_object_unref( t ); if( n_bands == 1 ) { if( fits2vips( filename, out, 0 ) ) return( -1 ); } else { VipsImage **x; int i; t = vips_image_new(); x = (VipsImage **) vips_object_local_array( VIPS_OBJECT( t ), n_bands + 1 ); for( i = 0; i < n_bands; i++ ) { x[i] = vips_image_new(); if( fits2vips( filename, x[i], i ) ) { g_object_unref( t ); return( -1 ); } } if( vips_bandjoin( x, &x[n_bands], n_bands, NULL ) || vips_image_write( x[n_bands], out ) ) { g_object_unref( t ); return( -1 ); } g_object_unref( t ); } return( 0 ); }
int vips__fits_isfits( const char *filename ) { fitsfile *fptr; int status; VIPS_DEBUG_MSG( "isfits: testing \"%s\"\n", filename ); status = 0; if( fits_open_image( &fptr, filename, READONLY, &status ) ) { VIPS_DEBUG_MSG( "isfits: error reading \"%s\"\n", filename ); #ifdef VIPS_DEBUG vips_fits_error( status ); #endif /*VIPS_DEBUG*/ return( 0 ); } fits_close_file( fptr, &status ); return( 1 ); }
/* Exif also tracks image dimensions. */ static int vips_exif_set_dimensions( ExifData *ed, VipsImage *im ) { VIPS_DEBUG_MSG( "vips_exif_set_dimensions: vips size of %d, %d\n", im->Xsize, im->Ysize ); vips_exif_set_tag( ed, 2, EXIF_TAG_PIXEL_X_DIMENSION, vips_exif_set_int, (void *) &im->Xsize ); vips_exif_set_tag( ed, 2, EXIF_TAG_PIXEL_Y_DIMENSION, vips_exif_set_int, (void *) &im->Ysize ); return( 0 ); }