/** * 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 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 ); }
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 ); }
/* Just for compatibility. New code should use vips_object_local() directly. */ VipsImage * im_open_local( VipsImage *parent, const char *filename, const char *mode ) { VipsImage *image; if( !(image = im_open( filename, mode )) ) return( NULL ); vips_object_local( parent, image ); return( image ); }
/* Open an image, returning the best version of that image for thumbnailing. * * libjpeg supports fast shrink-on-read, so if we have a JPEG, we can ask * VIPS to load a lower resolution version. */ static VipsImage * thumbnail_open( VipsObject *process, const char *filename ) { const char *loader; VipsImage *im; vips_info( "vipsthumbnail", "thumbnailing %s", filename ); if( linear_processing ) vips_info( "vipsthumbnail", "linear mode" ); if( !(loader = vips_foreign_find_load( filename )) ) return( NULL ); vips_info( "vipsthumbnail", "selected loader is %s", loader ); if( strcmp( loader, "VipsForeignLoadJpegFile" ) == 0 ) { int jpegshrink; /* This will just read in the header and is quick. */ if( !(im = vips_image_new_from_file( filename, NULL )) ) return( NULL ); jpegshrink = thumbnail_find_jpegshrink( im ); g_object_unref( im ); vips_info( "vipsthumbnail", "loading jpeg with factor %d pre-shrink", jpegshrink ); if( !(im = vips_image_new_from_file( filename, "access", VIPS_ACCESS_SEQUENTIAL, "shrink", jpegshrink, NULL )) ) return( NULL ); } else { /* All other formats. */ if( !(im = vips_image_new_from_file( filename, "access", VIPS_ACCESS_SEQUENTIAL, NULL )) ) return( NULL ); } vips_object_local( process, im ); return( im ); }
static VipsInterpolate * thumbnail_interpolator( VipsObject *process, VipsImage *in ) { double residual; VipsInterpolate *interp; calculate_shrink( in, &residual ); /* For images smaller than the thumbnail, we upscale with nearest * neighbor. Otherwise we makes thumbnails that look fuzzy and awful. */ if( !(interp = VIPS_INTERPOLATE( vips_object_new_from_string( g_type_class_ref( VIPS_TYPE_INTERPOLATE ), residual > 1.0 ? "nearest" : interpolator ) )) ) return( NULL ); vips_object_local( process, interp ); return( interp ); }
int vips__openslide_read( const char *filename, VipsImage *out, int layer ) { ReadSlide *rslide; VipsImage *raw; VipsImage *t; VIPS_DEBUG_MSG( "vips__openslide_read: %s %d\n", filename, layer ); /* Tile cache: keep enough for two complete rows of tiles. OpenSlide * has its own tile cache, but it's not large enough for a complete * scan line. */ raw = vips_image_new(); vips_object_local( out, raw ); if( !(rslide = readslide_new( filename, raw, layer, NULL )) ) return( -1 ); if( vips_image_generate( raw, NULL, vips__openslide_generate, NULL, rslide, NULL ) ) return( -1 ); /* Copy to out, adding a cache. Enough tiles for a complete row, plus * 50%. */ if( vips_tilecache( raw, &t, "tile_width", TILE_WIDTH, "tile_height", TILE_WIDTH, "max_tiles", (int) (1.5 * (1 + raw->Xsize / TILE_WIDTH)), NULL ) ) return( -1 ); if( vips_image_write( t, out ) ) { g_object_unref( t ); return( -1 ); } g_object_unref( t ); return( 0 ); }
/** * vips_check_matrix: * @domain: the originating domain for the error message * @im: image to check * @out: put image as in-memory doubles here * * Matrix images must have width and height less than 1000 and have 1 band. * * Return 0 if the image will pass as a matrix, or -1 and set an error * message otherwise. * * @out is set to be @im cast to double and stored in memory. Use * VIPS_IMAGE_ADDR() to address values in @out. @out is unreffed for you * when @im is unreffed. * * See also: vips_error(). * * Returns: 0 if OK, -1 otherwise. */ int vips_check_matrix( const char *domain, VipsImage *im, VipsImage **out ) { if( im->Xsize > 1000 || im->Ysize > 1000 ) { vips_error( domain, "%s", _( "matrix image too large" ) ); return( -1 ); } if( im->Bands != 1 ) { vips_error( domain, "%s", _( "matrix image must have one band" ) ); return( -1 ); } if( vips_cast( im, out, VIPS_FORMAT_DOUBLE, NULL ) ) return( -1 ); vips_object_local( im, *out ); if( vips_image_wio_input( *out ) ) return( -1 ); return( 0 ); }
int vips__gdal_read( const char *filename, VipsImage *out ) { Read *read; VipsImage *raw; VipsImage *t; VIPS_DEBUG_MSG( "vips__gdal_read: %s\n", filename ); raw = vips_image_new(); vips_object_local( out, raw ); if( !(read = read_new( filename, raw )) ) return( -1 ); if( vips_image_generate( raw, NULL, vips__gdal_generate, NULL, read, NULL ) ) return( -1 ); /* Copy to out, adding a cache. Enough tiles for a complete row, plus * 50%. */ if( vips_tilecache( raw, &t, "tile_width", read->tile_width, "tile_height", read->tile_height, "max_tiles", (int) (1.5 * (1 + raw->Xsize / read->tile_width)), "threaded", FALSE, NULL ) ) return( -1 ); if( vips_image_write( t, out ) ) { g_object_unref( t ); return( -1 ); } g_object_unref( t ); return( 0 ); }
/* Some interpolators look a little soft, so we have an optional sharpening * stage. */ static VipsImage * thumbnail_sharpen( VipsObject *process ) { VipsImage *mask; if( strcmp( convolution_mask, "none" ) == 0 ) mask = NULL; else if( strcmp( convolution_mask, "mild" ) == 0 ) { mask = vips_image_new_matrixv( 3, 3, -1.0, -1.0, -1.0, -1.0, 32.0, -1.0, -1.0, -1.0, -1.0 ); vips_image_set_double( mask, "scale", 24 ); } else if( !(mask = vips_image_new_from_file( convolution_mask, NULL )) ) vips_error_exit( "unable to load sharpen mask" ); if( mask ) vips_object_local( process, mask ); return( mask ); }
/* Open an image, returning the best version of that image for thumbnailing. * * libjpeg supports fast shrink-on-read, so if we have a JPEG, we can ask * VIPS to load a lower resolution version. */ static VipsImage * thumbnail_open( VipsObject *process, const char *filename ) { const char *loader; VipsImage *im; vips_info( "vipsthumbnail", "thumbnailing %s", filename ); if( linear_processing ) vips_info( "vipsthumbnail", "linear mode" ); if( !(loader = vips_foreign_find_load( filename )) ) return( NULL ); vips_info( "vipsthumbnail", "selected loader is %s", loader ); if( strcmp( loader, "VipsForeignLoadJpegFile" ) == 0 ) { int jpegshrink; /* This will just read in the header and is quick. */ if( !(im = vips_image_new_from_file( filename, NULL )) ) return( NULL ); jpegshrink = thumbnail_find_jpegshrink( im ); g_object_unref( im ); vips_info( "vipsthumbnail", "loading jpeg with factor %d pre-shrink", jpegshrink ); /* We can't use UNBUFERRED safely on very-many-core systems. */ if( !(im = vips_image_new_from_file( filename, "access", VIPS_ACCESS_SEQUENTIAL, "shrink", jpegshrink, NULL )) ) return( NULL ); } else if( strcmp( loader, "VipsForeignLoadPdfFile" ) == 0 || strcmp( loader, "VipsForeignLoadSvgFile" ) == 0 ) { double shrink; /* This will just read in the header and is quick. */ if( !(im = vips_image_new_from_file( filename, NULL )) ) return( NULL ); shrink = calculate_shrink( im ); g_object_unref( im ); vips_info( "vipsthumbnail", "loading PDF/SVG with factor %g pre-shrink", shrink ); /* We can't use UNBUFERRED safely on very-many-core systems. */ if( !(im = vips_image_new_from_file( filename, "access", VIPS_ACCESS_SEQUENTIAL, "scale", 1.0 / shrink, NULL )) ) return( NULL ); } else if( strcmp( loader, "VipsForeignLoadWebpFile" ) == 0 ) { double shrink; /* This will just read in the header and is quick. */ if( !(im = vips_image_new_from_file( filename, NULL )) ) return( NULL ); shrink = calculate_shrink( im ); g_object_unref( im ); vips_info( "vipsthumbnail", "loading webp with factor %g pre-shrink", shrink ); /* We can't use UNBUFERRED safely on very-many-core systems. */ if( !(im = vips_image_new_from_file( filename, "access", VIPS_ACCESS_SEQUENTIAL, "shrink", (int) shrink, NULL )) ) return( NULL ); } else { /* All other formats. We can't use UNBUFERRED safely on * very-many-core systems. */ if( !(im = vips_image_new_from_file( filename, "access", VIPS_ACCESS_SEQUENTIAL, NULL )) ) return( NULL ); } vips_object_local( process, im ); return( im ); }
/* Open an image, returning the best version of that image for thumbnailing. * * jpegs can have embedded thumbnails ... use that if it's large enough. * * libjpeg supports fast shrink-on-read, so if we have a JPEG, we can ask * VIPS to load a lower resolution version. */ static VipsImage * thumbnail_open( VipsObject *process, const char *filename ) { const char *loader; VipsImage *im; vips_info( "vipsthumbnail", "thumbnailing %s", filename ); if( linear_processing ) vips_info( "vipsthumbnail", "linear mode" ); if( !(loader = vips_foreign_find_load( filename )) ) return( NULL ); vips_info( "vipsthumbnail", "selected loader is %s", loader ); if( strcmp( loader, "VipsForeignLoadJpegFile" ) == 0 ) { VipsImage *thumb; /* This will just read in the header and is quick. */ if( !(im = vips_image_new_from_file( filename )) ) return( NULL ); /* Try to read an embedded thumbnail. If we find one, use that * instead. */ if( (thumb = thumbnail_get_thumbnail( im )) ) { /* @thumb has not been fully decoded yet ... * we must not close @im * until we're done with @thumb. */ vips_object_local( VIPS_OBJECT( thumb ), im ); im = thumb; } else { int jpegshrink; vips_info( "vipsthumbnail", "processing main jpeg image" ); jpegshrink = thumbnail_find_jpegshrink( im ); g_object_unref( im ); vips_info( "vipsthumbnail", "loading jpeg with factor %d pre-shrink", jpegshrink ); if( vips_foreign_load( filename, &im, "access", VIPS_ACCESS_SEQUENTIAL, "shrink", jpegshrink, NULL ) ) return( NULL ); } } else { /* All other formats. */ if( vips_foreign_load( filename, &im, "access", VIPS_ACCESS_SEQUENTIAL, NULL ) ) return( NULL ); } vips_object_local( process, im ); return( im ); }
static VipsFits * vips_fits_new_write( VipsImage *in, const char *filename ) { VipsImage *flip; VipsImage *type; VipsFits *fits; int status; status = 0; if( im_check_noncomplex( "im_vips2fits", in ) || im_check_uncoded( "im_vips2fits", in ) ) return( NULL ); /* Cast to a supported format. */ if( !(type = vips_image_new()) || vips_object_local( in, type ) || im_clip2fmt( in, type, vips_fits_bandfmt[in->BandFmt] ) ) return( NULL ); in = type; /* FITS has (0,0) in the bottom left, we need to flip. */ if( !(flip = vips_image_new()) || vips_object_local( in, flip ) || im_flipver( in, flip ) ) return( NULL ); in = flip; if( !(fits = VIPS_NEW( in, VipsFits )) ) return( NULL ); fits->filename = im_strdup( NULL, filename ); fits->image = in; fits->fptr = NULL; fits->lock = NULL; fits->band_select = -1; fits->buffer = NULL; g_signal_connect( in, "close", G_CALLBACK( vips_fits_close_cb ), fits ); if( !(fits->filename = im_strdup( NULL, filename )) ) return( NULL ); /* We need to be able to hold one scanline of one band. */ if( !(fits->buffer = VIPS_ARRAY( NULL, VIPS_IMAGE_SIZEOF_ELEMENT( in ) * in->Xsize, PEL )) ) return( NULL ); /* fits_create_file() will fail if there's a file of thet name, unless * we put a "!" in front ofthe filename. This breaks conventions with * the rest of vips, so just unlink explicitly. */ g_unlink( filename ); if( fits_create_file( &fits->fptr, filename, &status ) ) { im_error( "fits", _( "unable to write to \"%s\"" ), filename ); vips_fits_error( status ); return( NULL ); } fits->lock = g_mutex_new(); return( fits ); }