static ReadJpeg * readjpeg_new( VipsImage *out, int shrink, gboolean fail, gboolean readbehind, gboolean autorotate ) { ReadJpeg *jpeg; if( !(jpeg = VIPS_NEW( out, ReadJpeg )) ) return( NULL ); jpeg->out = out; jpeg->shrink = shrink; jpeg->fail = fail; jpeg->readbehind = readbehind; jpeg->filename = NULL; jpeg->cinfo.err = jpeg_std_error( &jpeg->eman.pub ); jpeg->eman.pub.error_exit = vips__new_error_exit; jpeg->eman.pub.output_message = vips__new_output_message; jpeg->eman.fp = NULL; jpeg->y_pos = 0; jpeg->autorotate = autorotate; /* jpeg_create_decompress() can fail on some sanity checks. Don't * readjpeg_free() since we don't want to jpeg_destroy_decompress(). */ if( setjmp( jpeg->eman.jmp ) ) return( NULL ); jpeg_create_decompress( &jpeg->cinfo ); g_signal_connect( out, "close", G_CALLBACK( readjpeg_close ), jpeg ); return( jpeg ); }
static VipsFits * vips_fits_new_read( const char *filename, VipsImage *out, int band_select ) { VipsFits *fits; int status; if( !(fits = VIPS_NEW( out, VipsFits )) ) return( NULL ); fits->filename = vips_strdup( NULL, filename ); fits->image = out; fits->fptr = NULL; fits->lock = NULL; fits->band_select = band_select; fits->buffer = NULL; g_signal_connect( out, "close", G_CALLBACK( vips_fits_close_cb ), fits ); status = 0; if( fits_open_file( &fits->fptr, filename, READONLY, &status ) ) { vips_error( "fits", _( "unable to open \"%s\"" ), filename ); vips_fits_error( status ); return( NULL ); } fits->lock = vips_g_mutex_new(); return( fits ); }
/* Convolution start function. */ static void * vips_convi_start( VipsImage *out, void *a, void *b ) { VipsImage *in = (VipsImage *) a; VipsConvi *convi = (VipsConvi *) b; VipsConviSequence *seq; if( !(seq = VIPS_NEW( out, VipsConviSequence )) ) return( NULL ); seq->convi = convi; seq->ir = NULL; seq->offsets = NULL; seq->pts = NULL; seq->last_bpl = -1; seq->t1 = NULL; seq->t2 = NULL; seq->ir = vips_region_new( in ); /* C mode. */ if( convi->nnz ) { seq->offsets = VIPS_ARRAY( NULL, convi->nnz, int ); seq->pts = VIPS_ARRAY( NULL, convi->nnz, VipsPel * ); if( !seq->offsets || !seq->pts ) { vips_convi_stop( seq, in, convi ); return( NULL ); } }
static Tile * tile_new( VipsTileCache *cache ) { Tile *tile; if( !(tile = VIPS_NEW( NULL, Tile )) ) return( NULL ); tile->cache = cache; tile->region = NULL; tile->time = cache->time; tile->x = -1; tile->y = -1; cache->tiles = g_slist_prepend( cache->tiles, tile ); g_assert( cache->ntiles >= 0 ); cache->ntiles += 1; if( !(tile->region = vips_region_new( cache->in )) ) { tile_destroy( tile ); return( NULL ); } vips__region_no_ownership( tile->region ); return( tile ); }
/* Make a new window. */ static VipsWindow * vips_window_new( IMAGE *im, int top, int height ) { VipsWindow *window; if( !(window = VIPS_NEW( NULL, VipsWindow )) ) return( NULL ); window->ref_count = 0; window->im = im; window->top = 0; window->height = 0; window->data = NULL; window->baseaddr = NULL; window->length = 0; if( vips_window_set( window, top, height ) ) { vips_window_free( window ); return( NULL ); } im->windows = g_slist_prepend( im->windows, window ); window->ref_count += 1; #ifdef DEBUG printf( "** vips_window_new: window top = %d, height = %d (%p)\n", window->top, window->height, window ); #endif /*DEBUG*/ return( window ); }
static VipsTile * vips_tile_new( VipsBlockCache *cache, int x, int y ) { VipsTile *tile; if( !(tile = VIPS_NEW( NULL, VipsTile )) ) return( NULL ); tile->cache = cache; tile->state = VIPS_TILE_STATE_PEND; tile->ref_count = 0; tile->region = NULL; tile->time = cache->time; tile->pos.left = x; tile->pos.top = y; tile->pos.width = cache->tile_width; tile->pos.height = cache->tile_height; g_hash_table_insert( cache->tiles, &tile->pos, tile ); g_assert( cache->ntiles >= 0 ); cache->ntiles += 1; if( !(tile->region = vips_region_new( cache->in )) ) { g_hash_table_remove( cache->tiles, &tile->pos ); return( NULL ); } vips__region_no_ownership( tile->region ); if( vips_tile_move( tile, x, y ) ) { g_hash_table_remove( cache->tiles, &tile->pos ); return( NULL ); } return( tile ); }
static void * vips_reducev_start( VipsImage *out, void *a, void *b ) { VipsImage *in = (VipsImage *) a; VipsReducev *reducev = (VipsReducev *) b; int sz = VIPS_IMAGE_N_ELEMENTS( in ); Sequence *seq; if( !(seq = VIPS_NEW( out, Sequence )) ) return( NULL ); /* Init! */ seq->reducev = reducev; seq->ir = NULL; seq->t1 = NULL; seq->t2 = NULL; /* Attach region and arrays. */ seq->ir = vips_region_new( in ); seq->t1 = VIPS_ARRAY( NULL, sz, signed short ); seq->t2 = VIPS_ARRAY( NULL, sz, signed short ); if( !seq->ir || !seq->t1 || !seq->t2 ) { vips_reducev_stop( seq, NULL, NULL ); return( NULL ); } return( seq ); }
static Write * write_new( VipsImage *in ) { Write *write; if( !(write = VIPS_NEW( in, Write )) ) return( NULL ); memset( write, 0, sizeof( Write ) ); write->in = in; g_signal_connect( in, "close", G_CALLBACK( write_destroy ), write ); if( !(write->row_pointer = VIPS_ARRAY( in, in->Ysize, png_bytep )) ) return( NULL ); if( !(write->pPng = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, user_error_function, user_warning_function )) ) return( NULL ); /* Catch PNG errors from png_create_info_struct(). */ if( setjmp( png_jmpbuf( write->pPng ) ) ) return( NULL ); if( !(write->pInfo = png_create_info_struct( write->pPng )) ) return( NULL ); return( write ); }
static Layer * pyramid_new( Write *write, Layer *above, int width, int height ) { Layer *layer; layer = VIPS_NEW( write->im, Layer ); layer->write = write; layer->width = width; layer->height = height; if( !above ) /* Top of pyramid. */ layer->sub = 1; else layer->sub = above->sub * 2; layer->lname = NULL; layer->tif = NULL; layer->image = NULL; layer->write_y = 0; layer->y = 0; layer->strip = NULL; layer->copy = NULL; layer->below = NULL; layer->above = above; if( write->pyramid ) if( layer->width > write->tilew || layer->height > write->tileh ) layer->below = pyramid_new( write, layer, width / 2, height / 2 ); /* The name for the top layer is the output filename. * * We need lname to be freed automatically: it has to stay * alive until after write_gather(). */ if( !above ) layer->lname = vips_strdup( VIPS_OBJECT( write->im ), write->filename ); else { char *lname; lname = vips__temp_name( "%s.tif" ); layer->lname = vips_strdup( VIPS_OBJECT( write->im ), lname ); g_free( lname ); } return( layer ); }
static WriteBuf * write_buf_new( void ) { WriteBuf *wbuf; if( !(wbuf = VIPS_NEW( NULL, WriteBuf )) ) return( NULL ); wbuf->buf = NULL; wbuf->len = 0; wbuf->alloc = 0; return( wbuf ); }
int im_add_callback1( VipsImage *im, const char *name, im_callback_fn fn, void *a, void *b ) { Callback *callback; callback = VIPS_NEW( VIPS_OBJECT( im ), Callback ); callback->fn = fn; callback->a = a; callback->b = b; g_signal_connect( im, name, G_CALLBACK( im_add_callback_cb1 ), callback ); return( 0 ); }
static Read * read_new( const char *filename, VipsImage *out ) { Read *read; int64_t w, h; read = VIPS_NEW( out, Read ); memset( read, 0, sizeof( *read ) ); g_signal_connect( out, "close", G_CALLBACK( read_destroy_cb ), read ); GDALAllRegister(); read->hDataset = GDALOpen( filename, GA_ReadOnly ); if( read->hDataset == NULL ) { vips_error( "gdal2vips", "%s", _( "unsupported gdal format" ) ); return( NULL ); } vips_image_pipelinev( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL ); w = GDALGetRasterXSize (read->hDataset); h = GDALGetRasterYSize (read->hDataset); GDALRasterBandH hBand; hBand = GDALGetRasterBand( read->hDataset, 1 ); if( hBand == NULL ) { vips_error( "gdal2vips", "%s", _( "can not open raster band" ) ); return( NULL ); } GDALGetBlockSize( hBand, &read->tile_width, &read->tile_height ); read->data_type = GDALGetRasterDataType( hBand ); // int vipsFormat = VIPS_FORMAT_UCHAR; // switch( dataType ) { // case GDT_Byte: vipsFormat = VIPS_FORMAT_UCHAR; break; // case GDT_UInt16: vipsFormat = VIPS_FORMAT_USHORT; break; // } vips_image_init_fields( out, w, h, 3, VIPS_FORMAT_UCHAR, VIPS_CODING_NONE, VIPS_INTERPRETATION_RGB, 1.0, 1.0 ); return( read ); }
static void * vips_worley_start( VipsImage *out, void *a, void *b ) { VipsWorley *worley = (VipsWorley *) b; Sequence *seq; if( !(seq = VIPS_NEW( NULL, Sequence )) ) return( NULL ); seq->worley = worley; seq->cell_x = -1; seq->cell_y = -1; return( seq ); }
VipsVector * vips_vector_new( const char *name, int dsize ) { static int vector_number = 0; VipsVector *vector; int i; if( !(vector = VIPS_NEW( NULL, VipsVector )) ) return( NULL ); vector->name = name; vector->unique_name = g_strdup_printf( "p[%d]", vector_number++ ); vector->n_temp = 0; vector->n_scanline = 0; vector->n_source = 0; vector->n_destination = 0; vector->n_constant = 0; vector->n_parameter = 0; vector->n_instruction = 0; for( i = 0; i < VIPS_VECTOR_SOURCE_MAX; i++ ) { vector->s[i] = -1; vector->sl[i] = -1; } vector->d1 = -1; vector->compiled = FALSE; #ifdef HAVE_ORC vector->program = orc_program_new(); #ifdef DEBUG_TRACE printf( "%s = orc_program_new();\n", vector->unique_name ); #endif /*DEBUG_TRACE*/ #endif /*HAVE_ORC*/ /* We always make d1, our callers make either a single point source, or * for area ops, a set of scanlines. * * Don't check error return. orc uses 0 to mean error, but the first * var you create will have id 0 :-( The first var is unlikely to fail * anyway. */ vector->d1 = vips_vector_destination( vector, "d1", dsize ); return( vector ); }
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 ); }
static Read * read_new( VipsImage *out, gboolean readbehind ) { Read *read; if( !(read = VIPS_NEW( out, Read )) ) return( NULL ); read->name = NULL; read->readbehind = readbehind; read->out = out; read->y_pos = 0; read->pPng = NULL; read->pInfo = NULL; read->row_pointer = NULL; read->fp = NULL; read->buffer = NULL; read->length = 0; read->read_pos = 0; g_signal_connect( out, "close", G_CALLBACK( read_close_cb ), read ); if( !(read->pPng = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, user_error_function, user_warning_function )) ) return( NULL ); #ifdef PNG_SKIP_sRGB_CHECK_PROFILE /* Prevent libpng (>=1.6.11) verifying sRGB profiles. */ png_set_option( read->pPng, PNG_SKIP_sRGB_CHECK_PROFILE, PNG_OPTION_ON ); #endif /*PNG_SKIP_sRGB_CHECK_PROFILE*/ /* Catch PNG errors from png_create_info_struct(). */ if( setjmp( png_jmpbuf( read->pPng ) ) ) return( NULL ); if( !(read->pInfo = png_create_info_struct( read->pPng )) ) return( NULL ); return( read ); }
static VipsFits * vips_fits_new_write( VipsImage *in, const char *filename ) { VipsFits *fits; int status; status = 0; if( !(fits = VIPS_NEW( in, VipsFits )) ) return( NULL ); fits->filename = vips_strdup( VIPS_OBJECT( in ), 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 = vips_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, VipsPel )) ) 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 ) ) { vips_error( "fits", _( "unable to write to \"%s\"" ), filename ); vips_fits_error( status ); return( NULL ); } fits->lock = vips_g_mutex_new(); return( fits ); }
/* Make a sequence value. */ static void * vips_shrink2_start( VipsImage *out, void *a, void *b ) { VipsImage *in = (VipsImage *) a; VipsShrink2 *shrink = (VipsShrink2 *) b; VipsShrink2Sequence *seq; if( !(seq = VIPS_NEW( out, VipsShrink2Sequence )) ) return( NULL ); seq->ir = vips_region_new( in ); if( !(seq->sum = (VipsPel *) VIPS_ARRAY( out, in->Bands, double )) ) { vips_shrink2_stop( seq, in, shrink ); return( NULL ); } return( (void *) seq ); }
static Read * read_new( const char *filename, void *data, size_t length ) { Read *read; if( !(read = VIPS_NEW( NULL, Read )) ) return( NULL ); read->filename = g_strdup( filename ); read->data = data; read->length = length; read->fd = 0; read->idec = NULL; if( read->filename ) { /* libwebp makes streaming from a file source very hard. We * have to read to a full memory buffer, then copy to out. * * mmap the input file, it's slightly quicker. */ if( (read->fd = vips__open_image_read( read->filename )) < 0 || (read->length = vips_file_length( read->fd )) < 0 || !(read->data = vips__mmap( read->fd, FALSE, read->length, 0 )) ) { read_free( read ); return( NULL ); } } WebPInitDecoderConfig( &read->config ); if( WebPGetFeatures( read->data, MINIMAL_HEADER, &read->config.input ) != VP8_STATUS_OK ) { read_free( read ); return( NULL ); } if( read->config.input.has_alpha ) read->config.output.colorspace = MODE_RGBA; else read->config.output.colorspace = MODE_RGB; read->config.options.use_threads = TRUE; return( read ); }
/* Make a sequence value. */ static void * vips_shrinkh_start( VipsImage *out, void *a, void *b ) { VipsImage *in = (VipsImage *) a; VipsShrinkhSequence *seq; if( !(seq = VIPS_NEW( out, VipsShrinkhSequence )) ) return( NULL ); seq->ir = vips_region_new( in ); /* Big enough for the largest intermediate. */ seq->sum = VIPS_ARRAY( out, in->Bands * vips_format_sizeof( VIPS_FORMAT_DPCOMPLEX ), VipsPel ); return( (void *) seq ); }
/* Our start function. */ static void * vips_maplut_start( VipsImage *out, void *a, void *b ) { VipsImage *in = (VipsImage *) a; VipsMaplutSequence *seq; if( !(seq = VIPS_NEW( out, VipsMaplutSequence )) ) return( NULL ); /* Init! */ seq->ir = NULL; seq->overflow = 0; if( !(seq->ir = vips_region_new( in )) ) return( NULL ); return( seq ); }
static Write * write_new( VipsImage *in, const char *name ) { Write *write; if( !(write = VIPS_NEW( NULL, Write )) ) return( NULL ); write->in = in; write->name = vips_strdup( NULL, name ); write->fp = vips__file_open_write( name, FALSE ); if( !write->name || !write->fp ) { write_destroy( write ); return( NULL ); } return( write ); }
static Write * write_new( VipsImage *in ) { Write *write; if( !(write = VIPS_NEW( in, Write )) ) return( NULL ); memset( write, 0, sizeof( Write ) ); write->in = in; write->memory = NULL; write->fp = NULL; write->buf = NULL; write->len = 0; write->alloc = 0; g_signal_connect( in, "close", G_CALLBACK( write_destroy ), write ); if( !(write->row_pointer = VIPS_ARRAY( in, in->Ysize, png_bytep )) ) return( NULL ); if( !(write->pPng = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, user_error_function, user_warning_function )) ) return( NULL ); #ifdef PNG_SKIP_sRGB_CHECK_PROFILE /* Prevent libpng (>=1.6.11) verifying sRGB profiles. */ png_set_option( write->pPng, PNG_SKIP_sRGB_CHECK_PROFILE, PNG_OPTION_ON ); #endif /*PNG_SKIP_sRGB_CHECK_PROFILE*/ /* Catch PNG errors from png_create_info_struct(). */ if( setjmp( png_jmpbuf( write->pPng ) ) ) return( NULL ); if( !(write->pInfo = png_create_info_struct( write->pPng )) ) return( NULL ); return( write ); }
static void * vips_rank_start( IMAGE *out, void *a, void *b ) { VipsImage *in = (VipsImage *) a; VipsRank *rank = (VipsRank *) b; VipsRankSequence *seq; if( !(seq = VIPS_NEW( out, VipsRankSequence )) ) return( NULL ); seq->ir = NULL; seq->sort = NULL; seq->ir = vips_region_new( in ); if( !(seq->sort = VIPS_ARRAY( out, VIPS_IMAGE_SIZEOF_ELEMENT( in ) * rank->n, VipsPel )) ) { vips_rank_stop( seq, in, rank ); return( NULL ); } return( (void *) seq ); }
static Read * read_new( const char *filename, VipsImage *im ) { Read *read; static int inited = 0; if( !inited ) { #ifdef HAVE_MAGICKCOREGENESIS MagickCoreGenesis( vips_get_argv0(), MagickFalse ); #else /*!HAVE_MAGICKCOREGENESIS*/ InitializeMagick( "" ); #endif /*HAVE_MAGICKCOREGENESIS*/ inited = 1; } if( !(read = VIPS_NEW( im, Read )) ) return( NULL ); read->filename = g_strdup( 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(); g_signal_connect( im, "close", G_CALLBACK( read_destroy ), read ); if( !read->image_info ) return( NULL ); vips_strncpy( read->image_info->filename, filename, MaxTextExtent ); #ifdef DEBUG printf( "magick2vips: read_new: %s\n", read->filename ); #endif /*DEBUG*/ return( read ); }
/* Convolution start function. */ static void * vips_convi_start( VipsImage *out, void *a, void *b ) { VipsImage *in = (VipsImage *) a; VipsConvi *convi = (VipsConvi *) b; VipsConviSequence *seq; if( !(seq = VIPS_NEW( out, VipsConviSequence )) ) return( NULL ); seq->convi = convi; seq->ir = NULL; seq->offsets = NULL; seq->last_bpl = -1; seq->t1 = NULL; seq->t2 = NULL; seq->ir = vips_region_new( in ); /* C mode. */ if( convi->nnz ) { if( !(seq->offsets = VIPS_ARRAY( NULL, convi->nnz, int )) ) { vips_convi_stop( seq, in, convi ); return( NULL ); } } /* Vector mode. */ if( convi->n_pass ) { seq->t1 = VIPS_ARRAY( NULL, VIPS_IMAGE_N_ELEMENTS( in ), short ); seq->t2 = VIPS_ARRAY( NULL, VIPS_IMAGE_N_ELEMENTS( in ), short ); if( !seq->t1 || !seq->t2 ) { vips_convi_stop( seq, in, convi ); return( NULL ); } }
VipsVector * vips_vector_new( const char *name, int dsize ) { VipsVector *vector; int i; if( !(vector = VIPS_NEW( NULL, VipsVector )) ) return( NULL ); vector->name = name; vector->n_temp = 0; vector->n_scanline = 0; vector->n_source = 0; vector->n_destination = 0; vector->n_constant = 0; vector->n_parameter = 0; vector->n_instruction = 0; for( i = 0; i < VIPS_VECTOR_SOURCE_MAX; i++ ) { vector->s[i] = -1; vector->sl[i] = -1; } vector->d1 = -1; vector->compiled = FALSE; #ifdef HAVE_ORC vector->program = orc_program_new(); /* We always make d1, our callers make either a single point source, or * for area ops, a set of scanlines. */ vector->d1 = orc_program_add_destination( vector->program, dsize, "d1" ); vector->n_destination += 1; #endif /*HAVE_ORC*/ return( vector ); }
static Read * read_new( const char *filename, void *buf, size_t len ) { Read *read; unsigned char header[MINIMAL_HEADER]; if( !(read = VIPS_NEW( NULL, Read )) ) return( NULL ); read->filename = g_strdup( filename ); read->buf = buf; read->len = len; read->idec = NULL; WebPInitDecoderConfig( &read->config ); if( filename ) { if( vips__get_bytes( filename, header, MINIMAL_HEADER ) && WebPGetFeatures( header, MINIMAL_HEADER, &read->config.input ) != VP8_STATUS_OK ) { read_free( read ); return( NULL ); } } else { if( WebPGetFeatures( read->buf, read->len, &read->config.input ) != VP8_STATUS_OK ) { read_free( read ); return( NULL ); } } if( read->config.input.has_alpha ) read->config.output.colorspace = MODE_RGBA; else read->config.output.colorspace = MODE_RGB; read->config.options.use_threads = TRUE; return( read ); }
static Read * read_new( VipsImage *out, gboolean readbehind ) { Read *read; if( !(read = VIPS_NEW( out, Read )) ) return( NULL ); read->name = NULL; read->readbehind = readbehind; read->out = out; read->y_pos = 0; read->pPng = NULL; read->pInfo = NULL; read->row_pointer = NULL; read->fp = NULL; read->buffer = NULL; read->length = 0; read->read_pos = 0; g_signal_connect( out, "close", G_CALLBACK( read_destroy ), read ); if( !(read->pPng = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, user_error_function, user_warning_function )) ) return( NULL ); /* Catch PNG errors from png_create_info_struct(). */ if( setjmp( png_jmpbuf( read->pPng ) ) ) return( NULL ); if( !(read->pInfo = png_create_info_struct( read->pPng )) ) return( NULL ); return( read ); }
static ReadJpeg * readjpeg_new( VipsImage *out, int shrink, gboolean fail ) { ReadJpeg *jpeg; if( !(jpeg = VIPS_NEW( out, ReadJpeg )) ) return( NULL ); jpeg->out = out; jpeg->shrink = shrink; jpeg->fail = fail; jpeg->filename = NULL; jpeg->decompressing = FALSE; jpeg->cinfo.err = jpeg_std_error( &jpeg->eman.pub ); jpeg->eman.pub.error_exit = vips__new_error_exit; jpeg->eman.pub.output_message = vips__new_output_message; jpeg->eman.fp = NULL; jpeg_create_decompress( &jpeg->cinfo ); g_signal_connect( out, "close", G_CALLBACK( readjpeg_close ), jpeg ); return( jpeg ); }