/* Out is a huge "t" buffer we decompress to. */ static int png2vips_interlace( Read *read, VipsImage *out ) { int y; #ifdef DEBUG printf( "png2vips_interlace: reading whole image\n" ); #endif /*DEBUG*/ if( vips_image_write_prepare( out ) ) return( -1 ); if( setjmp( png_jmpbuf( read->pPng ) ) ) return( -1 ); if( !(read->row_pointer = VIPS_ARRAY( NULL, out->Ysize, png_bytep )) ) return( -1 ); for( y = 0; y < out->Ysize; y++ ) read->row_pointer[y] = VIPS_IMAGE_ADDR( out, 0, y ); /* Some libpng warn you to call png_set_interlace_handling(); here, but * that can actually break interlace. We have to live with the warning, * unfortunately. */ png_read_image( read->pPng, read->row_pointer ); png_read_end( read->pPng, NULL ); read_destroy( read ); return( 0 ); }
/* Out is a huge "t" buffer we decompress to. */ static int png2vips_interlace( Read *read, VipsImage *out ) { int y; #ifdef DEBUG printf( "png2vips_interlace: reading whole image\n" ); #endif /*DEBUG*/ if( vips_image_write_prepare( out ) ) return( -1 ); if( setjmp( png_jmpbuf( read->pPng ) ) ) return( -1 ); if( !(read->row_pointer = VIPS_ARRAY( NULL, out->Ysize, png_bytep )) ) return( -1 ); for( y = 0; y < out->Ysize; y++ ) read->row_pointer[y] = VIPS_IMAGE_ADDR( out, 0, y ); png_read_image( read->pPng, read->row_pointer ); png_read_end( read->pPng, NULL ); read_destroy( read ); return( 0 ); }
static Read * read_new( IMAGE *in, IMAGE *out, int tile_width, int tile_height, int max_tiles ) { Read *read; if( !(read = IM_NEW( NULL, Read )) ) return( NULL ); read->in = in; read->out = out; read->tile_width = tile_width; read->tile_height = tile_height; read->max_tiles = max_tiles; read->time = 0; read->ntiles = 0; read->lock = g_mutex_new(); read->cache = NULL; if( im_add_close_callback( out, (im_callback_fn) read_destroy, read, NULL ) ) { read_destroy( read ); return( NULL ); } return( read ); }
static Read * read_new( const char *filename, VipsImage *out ) { Read *read; if( !(read = VIPS_NEW( NULL, Read )) ) return( NULL ); read->filename = vips_strdup( NULL, filename ); read->out = out; read->mat = NULL; read->var = NULL; if( !(read->mat = Mat_Open( filename, MAT_ACC_RDONLY )) ) { vips_error( "mat2vips", _( "unable to open \"%s\"" ), filename ); read_destroy( read ); return( NULL ); } for(;;) { if( !(read->var = Mat_VarReadNextInfo( read->mat )) ) { vips_error( "mat2vips", _( "no matrix variables in \"%s\"" ), filename ); read_destroy( read ); return( NULL ); } #ifdef DEBUG printf( "mat2vips: seen:\n" ); printf( "var->name == %s\n", read->var->name ); printf( "var->class_type == %d\n", read->var->class_type ); printf( "var->rank == %d\n", read->var->rank ); #endif /*DEBUG*/ /* Vector to colour image is OK for us. */ if( read->var->rank >= 1 && read->var->rank <= 3 ) break; VIPS_FREEF( Mat_VarFree, read->var ); } return( read ); }
/* Read a PNG file header into a VIPS header. */ static int png2vips_header( const char *name, IMAGE *out ) { Read *read; if( !(read = read_new( name, out )) ) return( -1 ); if( png2vips( read, 1 ) ) { read_destroy( read ); return( -1 ); } read_destroy( read ); return( 0 ); }
int vips__mat_header( const char *filename, VipsImage *out ) { Read *read; #ifdef DEBUG printf( "mat2vips_header: reading \"%s\"\n", filename ); #endif /*DEBUG*/ if( !(read = read_new( filename, out )) ) return( -1 ); if( mat2vips_get_header( read->var, read->out ) ) { read_destroy( read ); return( -1 ); } read_destroy( read ); return( 0 ); }
static Read * read_new( const char *name, IMAGE *out ) { Read *read; if( !(read = IM_NEW( NULL, Read )) ) return( NULL ); read->name = im_strdup( NULL, name ); read->out = out; read->fp = NULL; read->pPng = NULL; read->pInfo = NULL; read->row_pointer = NULL; read->data = NULL; if( !(read->fp = im__file_open_read( name, NULL )) ) { read_destroy( read ); return( NULL ); } if( !(read->pPng = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, user_error_function, user_warning_function )) ) { read_destroy( read ); return( NULL ); } /* Catch PNG errors from png_create_info_struct(). */ if( setjmp( read->pPng->jmpbuf ) ) { read_destroy( read ); return( NULL ); } if( !(read->pInfo = png_create_info_struct( read->pPng )) ) { read_destroy( read ); return( NULL ); } return( read ); }
/** * im_mat2vips: * @filename: file to load * @out: image to write to * * Read a Matlab save file into a VIPS image. * * This operation searches the save * file for the first array variable with between 1 and 3 dimensions and loads * it as an image. It will not handle complex images. It does not handle * sparse matrices. * * See also: #VipsFormat. * * Returns: 0 on success, -1 on error. */ int im_mat2vips( const char *filename, IMAGE *out ) { Read *read; #ifdef DEBUG printf( "mat2vips: reading \"%s\"\n", filename ); #endif /*DEBUG*/ if( !(read = read_new( filename, out )) ) return( -1 ); if( mat2vips_get_header( read->var, read->out ) || mat2vips_get_data( read->mat, read->var, read->out ) ) { read_destroy( read ); return( -1 ); } read_destroy( read ); return( 0 ); }
/** * im_png2vips: * @filename: file to load * @out: image to write to * * Read a PNG file into a VIPS image. It can read all png images, including 8- * and 16-bit images, 1 and 3 channel, with and without an alpha channel. * * There is no support for embedded ICC profiles. * * See also: #VipsFormat, im_vips2png(). * * Returns: 0 on success, -1 on error. */ int im_png2vips( const char *name, IMAGE *out ) { Read *read; #ifdef DEBUG printf( "im_png2vips: reading \"%s\"\n", name ); #endif /*DEBUG*/ if( !(read = read_new( name, out )) ) return( -1 ); if( png2vips( read, 0 ) ) { read_destroy( read ); return( -1 ); } read_destroy( read ); return( 0 ); }
/* Read a PNG file header into a VIPS header. */ int vips__png_header( const char *name, VipsImage *out ) { Read *read; if( !(read = read_new_filename( out, name, FALSE )) || png2vips_header( read, out ) ) return( -1 ); /* Just a header read: we can free the read early and save an fd. */ read_destroy( read ); return( 0 ); }
static Read * read_new( const char *filename, IMAGE *im ) { Read *read; static int inited = 0; if( !inited ) { #ifdef HAVE_MAGICKCOREGENESIS MagickCoreGenesis( im_get_argv0(), MagickFalse ); #else /*!HAVE_MAGICKCOREGENESIS*/ InitializeMagick( "" ); #endif /*HAVE_MAGICKCOREGENESIS*/ inited = 1; } if( !(read = IM_NEW( NULL, Read )) ) return( NULL ); read->filename = im_strdup( NULL, filename ); read->im = im; read->image = NULL; read->image_info = CloneImageInfo( NULL ); GetExceptionInfo( &read->exception ); read->n_frames = 0; read->frames = NULL; read->frame_height = 0; read->lock = g_mutex_new(); if( im_add_close_callback( im, (im_callback_fn) read_destroy, read, NULL ) ) { read_destroy( read ); return( NULL ); } if( !read->filename || !read->image_info ) return( NULL ); im_strncpy( read->image_info->filename, filename, MaxTextExtent ); #ifdef DEBUG printf( "im_magick2vips: read_new: %s\n", read->filename ); #endif /*DEBUG*/ return( read ); }
static int png2vips_generate( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsRect *r = &or->valid; Read *read = (Read *) a; int y; #ifdef DEBUG printf( "png2vips_generate: line %d, %d rows\n", r->top, r->height ); printf( "png2vips_generate: y_top = %d\n", read->y_pos ); #endif /*DEBUG*/ /* We're inside a tilecache where tiles are the full image width, so * this should always be true. */ g_assert( r->left == 0 ); g_assert( r->width == or->im->Xsize ); g_assert( VIPS_RECT_BOTTOM( r ) <= or->im->Ysize ); /* Tiles should always be a strip in height, unless it's the final * strip. */ g_assert( r->height == VIPS_MIN( 8, or->im->Ysize - r->top ) ); /* And check that y_pos is correct. It should be, since we are inside * a vips_sequential(). */ if( r->top != read->y_pos ) { vips_error( "vipspng", _( "out of order read at line %d" ), read->y_pos ); return( -1 ); } for( y = 0; y < r->height; y++ ) { png_bytep q = (png_bytep) VIPS_REGION_ADDR( or, 0, r->top + y ); /* We need to catch and ignore errors from read_row(). */ if( !setjmp( png_jmpbuf( read->pPng ) ) ) png_read_row( read->pPng, q, NULL ); else { #ifdef DEBUG printf( "png2vips_generate: png_read_row() failed, " "line %d\n", r->top + y ); printf( "png2vips_generate: file %s\n", read->name ); printf( "png2vips_generate: thread %p\n", g_thread_self() ); #endif /*DEBUG*/ } read->y_pos += 1; } /* Turn errors back on. png_read_end() can trigger them too. */ if( setjmp( png_jmpbuf( read->pPng ) ) ) return( -1 ); /* We need to shut down the reader immediately at the end of read or * we won't detach ready for the next image. */ if( read->y_pos >= read->out->Ysize ) { png_read_end( read->pPng, NULL ); read_destroy( read ); } return( 0 ); }
static void read_close_cb( VipsImage *out, Read *read ) { read_destroy( read ); }
static int png2vips_generate( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsRect *r = &or->valid; Read *read = (Read *) a; int y; #ifdef DEBUG printf( "png2vips_generate: line %d, %d rows\n", r->top, r->height ); printf( "png2vips_generate: y_top = %d\n", read->y_pos ); #endif /*DEBUG*/ /* We're inside a tilecache where tiles are the full image width, so * this should always be true. */ g_assert( r->left == 0 ); g_assert( r->width == or->im->Xsize ); g_assert( VIPS_RECT_BOTTOM( r ) <= or->im->Ysize ); /* Tiles should always be a strip in height, unless it's the final * strip. */ g_assert( r->height == VIPS_MIN( 8, or->im->Ysize - r->top ) ); /* And check that y_pos is correct. It should be, since we are inside * a vips_sequential(). */ if( r->top != read->y_pos ) { vips_error( "vipspng", _( "out of order read at line %d" ), read->y_pos ); return( -1 ); } for( y = 0; y < r->height; y++ ) { png_bytep q = (png_bytep) VIPS_REGION_ADDR( or, 0, r->top + y ); /* We need to catch errors from read_row(). */ if( !setjmp( png_jmpbuf( read->pPng ) ) ) png_read_row( read->pPng, q, NULL ); else { /* We've failed to read some pixels. Knock this * operation out of cache. */ vips_foreign_load_invalidate( read->out ); #ifdef DEBUG printf( "png2vips_generate: png_read_row() failed, " "line %d\n", r->top + y ); printf( "png2vips_generate: file %s\n", read->name ); printf( "png2vips_generate: thread %p\n", g_thread_self() ); #endif /*DEBUG*/ /* And bail if fail is on. We have to add an error * message, since the handler we install just does * g_warning(). */ if( read->fail ) { vips_error( "vipspng", "%s", _( "libpng read error" ) ); return( -1 ); } } read->y_pos += 1; } /* Catch errors from png_read_end(). This can fail on a truncated * file. */ if( setjmp( png_jmpbuf( read->pPng ) ) ) { if( read->fail ) { vips_error( "vipspng", "%s", _( "libpng read error" ) ); return( -1 ); } return( 0 ); } /* We need to shut down the reader immediately at the end of read or * we won't detach ready for the next image. */ if( read->y_pos >= read->out->Ysize ) { png_read_end( read->pPng, NULL ); read_destroy( read ); } return( 0 ); }