Beispiel #1
0
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 );
}
Beispiel #2
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 );
}
Beispiel #3
0
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 );
}
Beispiel #4
0
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 );
}
Beispiel #5
0
/* 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 );
		}
	}
}
Beispiel #6
0
static void
vo_free( Vo *vo )
{
	heap_unregister_element( vo->rc->heap, &vo->out );
	VIPS_UNREF( vo->object );

	im_free( vo );
}
Beispiel #7
0
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 );
}
Beispiel #8
0
static void
vips_quadratic_dispose( GObject *gobject )
{
	VipsQuadratic *quadratic = (VipsQuadratic *) gobject;

	VIPS_UNREF( quadratic->mat ); 

	G_OBJECT_CLASS( vips_quadratic_parent_class )->dispose( gobject );
}
Beispiel #9
0
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 );
}
Beispiel #10
0
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 );
}
Beispiel #11
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 );
}
Beispiel #12
0
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 );
}
Beispiel #13
0
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 );
}
Beispiel #14
0
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 );
}
Beispiel #15
0
/* 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 );
}
Beispiel #16
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 );
}
Beispiel #17
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 );
}
Beispiel #18
0
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 ); 
		}
Beispiel #19
0
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 );
}
Beispiel #20
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 );
}