int vips__csv_write( VipsImage *in, const char *filename, const char *separator ) { FILE *fp; VipsImage *memory; if( vips_check_mono( "vips2csv", in ) || vips_check_uncoded( "vips2csv", in ) || !(memory = vips_image_copy_memory( in )) ) return( -1 ); if( !(fp = vips__file_open_write( filename, TRUE )) ) { VIPS_UNREF( memory ); return( -1 ); } if( vips2csv( memory, fp, separator ) ) { fclose( fp ); VIPS_UNREF( memory ); return( -1 ); } fclose( fp ); VIPS_UNREF( memory ); return( 0 ); }
/* Free a single pyramid layer. */ static void layer_free( Layer *layer ) { VIPS_UNREF( layer->strip ); VIPS_UNREF( layer->copy ); VIPS_UNREF( layer->image ); VIPS_FREEF( TIFFClose, layer->tif ); }
static void vips_text_dispose( GObject *gobject ) { VipsText *text = (VipsText *) gobject; VIPS_UNREF( text->layout ); VIPS_UNREF( text->context ); VIPS_FREE( text->bitmap.buffer ); G_OBJECT_CLASS( vips_text_parent_class )->dispose( gobject ); }
static void vips_foreign_load_pdf_dispose( GObject *gobject ) { VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) gobject; VIPS_UNREF( pdf->page ); VIPS_UNREF( pdf->doc ); G_OBJECT_CLASS( vips_foreign_load_pdf_parent_class )-> dispose( gobject ); }
/* Drop any refs vargv may hold. */ static void vips_wrap7_vargv_dispose( im_function *fn, im_object *vargv ) { int i; for( i = 0; i < fn->argc; i++ ) { im_arg_desc *arg = &fn->argv[i]; im_type_desc *type = arg->desc; im_arg_type vt = type->type; switch( vips_wrap7_lookup_type( vt ) ) { case VIPS_WRAP7_NONE: /* IM_TYPE_DISPLAY */ case VIPS_WRAP7_DOUBLE: case VIPS_WRAP7_INT: case VIPS_WRAP7_COMPLEX: case VIPS_WRAP7_DOUBLEVEC: case VIPS_WRAP7_INTVEC: case VIPS_WRAP7_DMASK: case VIPS_WRAP7_IMASK: /* Do nothing. */ break; case VIPS_WRAP7_INTERPOLATE: case VIPS_WRAP7_IMAGE: if( vargv[i] ) VIPS_UNREF( vargv[i] ); break; case VIPS_WRAP7_IMAGEVEC: { im_imagevec_object *iv = vargv[i]; int j; for( j = 0; j < iv->n; j++ ) if( iv->vec[j] ) VIPS_UNREF( iv->vec[j] ); } break; case VIPS_WRAP7_GVALUE: g_value_unset( vargv[i] ); break; default: g_assert( FALSE ); } } }
static void vo_free( Vo *vo ) { heap_unregister_element( vo->rc->heap, &vo->out ); VIPS_UNREF( vo->object ); im_free( vo ); }
static void write_finish( Write *write ) { VIPS_FREEF( fclose, write->fp ); VIPS_UNREF( write->memory ); VIPS_FREE( write->buf ); if( write->pPng ) png_destroy_write_struct( &write->pPng, &write->pInfo ); }
static void vips_quadratic_dispose( GObject *gobject ) { VipsQuadratic *quadratic = (VipsQuadratic *) gobject; VIPS_UNREF( quadratic->mat ); G_OBJECT_CLASS( vips_quadratic_parent_class )->dispose( gobject ); }
static void vips_foreign_load_svg_dispose( GObject *gobject ) { VipsForeignLoadSvg *svg = (VipsForeignLoadSvg *) gobject; VIPS_UNREF( svg->page ); G_OBJECT_CLASS( vips_foreign_load_svg_parent_class )-> dispose( gobject ); }
static int vips_reducev_stop( void *vseq, void *a, void *b ) { Sequence *seq = (Sequence *) vseq; VIPS_UNREF( seq->ir ); VIPS_FREE( seq->t1 ); VIPS_FREE( seq->t2 ); return( 0 ); }
static void vips_foreign_load_nifti_dispose( GObject *gobject ) { VipsForeignLoadNifti *nifti = (VipsForeignLoadNifti *) gobject; VIPS_UNREF( nifti->memory ); VIPS_FREEF( nifti_image_free, nifti->nim ); G_OBJECT_CLASS( vips_foreign_load_nifti_parent_class )-> dispose( gobject ); }
static void write_destroy( Write *write ) { jpeg_destroy_compress( &write->cinfo ); VIPS_FREEF( fclose, write->eman.fp ); VIPS_FREE( write->row_pointer ); VIPS_FREE( write->profile_bytes ); VIPS_UNREF( write->inverted ); g_free( write ); }
static void vips_buildlut_dispose( GObject *gobject ) { VipsBuildlut *lut = (VipsBuildlut *) gobject; VIPS_FREE( lut->data ); VIPS_FREE( lut->buf ); VIPS_UNREF( lut->mat ); G_OBJECT_CLASS( vips_buildlut_parent_class )->dispose( gobject ); }
static void sink_thread_state_dispose( GObject *gobject ) { SinkThreadState *state = (SinkThreadState *) gobject; Sink *sink = (Sink *) ((VipsThreadState *) state)->a; sink_call_stop( sink, state ); VIPS_UNREF( state->reg ); G_OBJECT_CLASS( sink_thread_state_parent_class )->dispose( gobject ); }
/* Free a sequence value. */ static int vips_convi_stop( void *vseq, void *a, void *b ) { VipsConviSequence *seq = (VipsConviSequence *) vseq; VIPS_UNREF( seq->ir ); VIPS_FREE( seq->offsets ); VIPS_FREE( seq->t1 ); VIPS_FREE( seq->t2 ); return( 0 ); }
/* Destroy a sequence value. */ static int vips_maplut_stop( void *vseq, void *a, void *b ) { VipsMaplutSequence *seq = (VipsMaplutSequence *) vseq; VipsMaplut *maplut = (VipsMaplut *) b; /* Add to global stats. */ maplut->overflow += seq->overflow; VIPS_UNREF( seq->ir ); return( 0 ); }
static void tile_destroy( Tile *tile ) { VipsTileCache *cache = tile->cache; cache->tiles = g_slist_remove( cache->tiles, tile ); cache->ntiles -= 1; g_assert( cache->ntiles >= 0 ); tile->cache = NULL; VIPS_UNREF( tile->region ); vips_free( tile ); }
static int vips_foreign_load_pdf_get_page( VipsForeignLoadPdf *pdf, int page_no ) { if( pdf->current_page != page_no ) { VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( pdf ); VIPS_UNREF( pdf->page ); pdf->current_page = -1; #ifdef DEBUG printf( "vips_foreign_load_pdf_get_page: %d\n", page_no ); #endif /*DEBUG*/ if( !(pdf->page = poppler_document_get_page( pdf->doc, page_no )) ) { vips_error( class->nickname, _( "unable to load page %d" ), page_no ); return( -1 ); }
static int vips_resize_build( VipsObject *object ) { VipsResample *resample = VIPS_RESAMPLE( object ); VipsResize *resize = (VipsResize *) object; VipsImage **t = (VipsImage **) vips_object_local_array( object, 7 ); VipsImage *in; int window_size; int int_shrink; int int_shrink_width; double residual; double sigma; if( VIPS_OBJECT_CLASS( vips_resize_parent_class )->build( object ) ) return( -1 ); if( !vips_object_argument_isset( object, "interpolate" ) ) { VipsInterpolate *interpolate; char *nick; if( vips_type_find( "VipsInterpolate", "bicubic" ) ) nick = "bicubic"; else nick = "bilinear"; interpolate = vips_interpolate_new( nick ); g_object_set( object, "interpolate", interpolate, NULL ); VIPS_UNREF( interpolate ); } in = resample->in; window_size = resize->interpolate ? vips_interpolate_get_window_size( resize->interpolate ) : 2; /* If the factor is > 1.0, we need to zoom rather than shrink. * Just set the int part to 1 in this case. */ int_shrink = resize->scale > 1.0 ? 1 : floor( 1.0 / resize->scale ); /* We want to shrink by less for interpolators with larger windows. */ int_shrink = VIPS_MAX( 1, int_shrink / VIPS_MAX( 1, window_size / 2 ) ); /* Size after int shrink. */ int_shrink_width = in->Xsize / int_shrink; /* Therefore residual scale factor is. */ residual = (in->Xsize * resize->scale) / int_shrink_width; /* A copy for enlarge resize. */ if( vips_shrink( in, &t[0], int_shrink, int_shrink, NULL ) ) return( -1 ); in = t[0]; /* We want to make sure we read the image sequentially. * However, the convolution we may be doing later will force us * into SMALLTILE or maybe FATSTRIP mode and that will break * sequentiality. * * So ... read into a cache where tiles are scanlines, and make sure * we keep enough scanlines to be able to serve a line of tiles. * * We use a threaded tilecache to avoid a deadlock: suppose thread1, * evaluating the top block of the output, is delayed, and thread2, * evaluating the second block, gets here first (this can happen on * a heavily-loaded system). * * With an unthreaded tilecache (as we had before), thread2 will get * the cache lock and start evaling the second block of the shrink. * When it reaches the png reader it will stall until the first block * has been used ... but it never will, since thread1 will block on * this cache lock. */ if( int_shrink > 1 ) { int tile_width; int tile_height; int nlines; vips_get_tile_size( in, &tile_width, &tile_height, &nlines ); if( vips_tilecache( in, &t[6], "tile_width", in->Xsize, "tile_height", 10, "max_tiles", 1 + (nlines * 2) / 10, "access", VIPS_ACCESS_SEQUENTIAL, "threaded", TRUE, NULL ) ) return( -1 ); in = t[6]; } /* If the final affine will be doing a large downsample, we can get * nasty aliasing on hard edges. Blur before affine to smooth this out. * * Don't blur for very small shrinks, blur with radius 1 for x1.5 * shrinks, blur radius 2 for x2.5 shrinks and above, etc. */ sigma = ((1.0 / residual) - 0.5) / 1.5; if( residual < 1.0 && sigma > 0.1 ) { if( vips_gaussblur( in, &t[2], sigma, NULL ) ) return( -1 ); in = t[2]; } if( vips_affine( in, &t[3], residual, 0, 0, residual, "interpolate", resize->interpolate, "idx", resize->idx, "idy", resize->idy, NULL ) ) return( -1 ); in = t[3]; /* If we are upsampling, don't sharpen. */ if( int_shrink > 1 ) { t[5] = 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( t[5], "scale", 24 ); if( vips_conv( in, &t[4], t[5], NULL ) ) return( -1 ); in = t[4]; } if( vips_image_write( in, resample->out ) ) return( -1 ); return( 0 ); }
/* Write a VIPS image to PNG. */ static int write_vips( Write *write, int compress, int interlace, const char *profile, VipsForeignPngFilter filter, gboolean strip, gboolean palette, int colours, int Q, double dither ) { VipsImage *in = write->in; int bit_depth; int color_type; int interlace_type; int i, nb_passes; g_assert( in->BandFmt == VIPS_FORMAT_UCHAR || in->BandFmt == VIPS_FORMAT_USHORT ); g_assert( in->Coding == VIPS_CODING_NONE ); g_assert( in->Bands > 0 && in->Bands < 5 ); /* Catch PNG errors. */ if( setjmp( png_jmpbuf( write->pPng ) ) ) return( -1 ); /* Check input image. If we are writing interlaced, we need to make 7 * passes over the image. We advertise ourselves as seq, so to ensure * we only suck once from upstream, switch to WIO. */ if( interlace ) { if( !(write->memory = vips_image_copy_memory( in )) ) return( -1 ); in = write->memory; } else { if( vips_image_pio_input( in ) ) return( -1 ); } if( compress < 0 || compress > 9 ) { vips_error( "vips2png", "%s", _( "compress should be in [0,9]" ) ); return( -1 ); } /* Set compression parameters. */ png_set_compression_level( write->pPng, compress ); /* Set row filter. */ png_set_filter( write->pPng, 0, filter ); bit_depth = in->BandFmt == VIPS_FORMAT_UCHAR ? 8 : 16; switch( in->Bands ) { case 1: color_type = PNG_COLOR_TYPE_GRAY; break; case 2: color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break; case 3: color_type = PNG_COLOR_TYPE_RGB; break; case 4: color_type = PNG_COLOR_TYPE_RGB_ALPHA; break; default: vips_error( "vips2png", _( "can't save %d band image as png" ), in->Bands ); return( -1 ); } #ifdef HAVE_IMAGEQUANT /* Enable image quantisation to paletted 8bpp PNG if colours is set. */ if( palette ) { g_assert( colours >= 2 && colours <= 256 ); bit_depth = 8; color_type = PNG_COLOR_TYPE_PALETTE; } #else if( palette ) g_warning( "%s", _( "ignoring palette (no quantisation support)" ) ); #endif /*HAVE_IMAGEQUANT*/ interlace_type = interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE; png_set_IHDR( write->pPng, write->pInfo, in->Xsize, in->Ysize, bit_depth, color_type, interlace_type, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); /* Set resolution. libpng uses pixels per meter. */ png_set_pHYs( write->pPng, write->pInfo, VIPS_RINT( in->Xres * 1000 ), VIPS_RINT( in->Yres * 1000 ), PNG_RESOLUTION_METER ); /* Set ICC Profile. */ if( profile && !strip ) { if( strcmp( profile, "none" ) != 0 ) { void *data; size_t length; if( !(data = vips__file_read_name( profile, vips__icc_dir(), &length )) ) return( -1 ); #ifdef DEBUG printf( "write_vips: " "attaching %zd bytes of ICC profile\n", length ); #endif /*DEBUG*/ png_set_iCCP( write->pPng, write->pInfo, "icc", PNG_COMPRESSION_TYPE_BASE, data, length ); } } else if( vips_image_get_typeof( in, VIPS_META_ICC_NAME ) && !strip ) { void *data; size_t length; if( vips_image_get_blob( in, VIPS_META_ICC_NAME, &data, &length ) ) return( -1 ); #ifdef DEBUG printf( "write_vips: attaching %zd bytes of ICC profile\n", length ); #endif /*DEBUG*/ png_set_iCCP( write->pPng, write->pInfo, "icc", PNG_COMPRESSION_TYPE_BASE, data, length ); } if( vips_image_get_typeof( in, VIPS_META_XMP_NAME ) ) { const char *str; if( vips_image_get_string( in, VIPS_META_XMP_NAME, &str ) ) return( -1 ); vips__png_set_text( write->pPng, write->pInfo, "XML:com.adobe.xmp", str ); } /* Set any "png-comment-xx-yyy" metadata items. */ if( vips_image_map( in, write_png_comment, write ) ) return( -1 ); #ifdef HAVE_IMAGEQUANT if( palette ) { VipsImage *im_index; VipsImage *im_palette; int palette_count; png_color *png_palette; png_byte *png_trans; int trans_count; if( vips__quantise_image( in, &im_index, &im_palette, colours, Q, dither ) ) return( -1 ); palette_count = im_palette->Xsize; g_assert( palette_count <= PNG_MAX_PALETTE_LENGTH ); png_palette = (png_color *) png_malloc( write->pPng, palette_count * sizeof( png_color ) ); png_trans = (png_byte *) png_malloc( write->pPng, palette_count * sizeof( png_byte ) ); trans_count = 0; for( i = 0; i < palette_count; i++ ) { VipsPel *p = (VipsPel *) VIPS_IMAGE_ADDR( im_palette, i, 0 ); png_color *col = &png_palette[i]; col->red = p[0]; col->green = p[1]; col->blue = p[2]; png_trans[i] = p[3]; if( p[3] != 255 ) trans_count = i + 1; #ifdef DEBUG printf( "write_vips: palette[%d] %d %d %d %d\n", i + 1, p[0], p[1], p[2], p[3] ); #endif /*DEBUG*/ } #ifdef DEBUG printf( "write_vips: attaching %d color palette\n", palette_count ); #endif /*DEBUG*/ png_set_PLTE( write->pPng, write->pInfo, png_palette, palette_count ); if( trans_count ) { #ifdef DEBUG printf( "write_vips: attaching %d alpha values\n", trans_count ); #endif /*DEBUG*/ png_set_tRNS( write->pPng, write->pInfo, png_trans, trans_count, NULL ); } png_free( write->pPng, (void *) png_palette ); png_free( write->pPng, (void *) png_trans ); VIPS_UNREF( im_palette ); VIPS_UNREF( write->memory ); write->memory = im_index; in = write->memory; } #endif /*HAVE_IMAGEQUANT*/ png_write_info( write->pPng, write->pInfo ); /* If we're an intel byte order CPU and this is a 16bit image, we need * to swap bytes. */ if( bit_depth > 8 && !vips_amiMSBfirst() ) png_set_swap( write->pPng ); if( interlace ) nb_passes = png_set_interlace_handling( write->pPng ); else nb_passes = 1; /* Write data. */ for( i = 0; i < nb_passes; i++ ) if( vips_sink_disc( in, write_png_block, write ) ) return( -1 ); /* The setjmp() was held by our background writer: reset it. */ if( setjmp( png_jmpbuf( write->pPng ) ) ) return( -1 ); png_write_end( write->pPng, write->pInfo ); return( 0 ); }