Пример #1
0
static int
read_image( Read *read, VipsImage *out )
{
	VipsImage **t = (VipsImage **) 
		vips_object_local_array( VIPS_OBJECT( out ), 3 );

	t[0] = vips_image_new_memory();
	if( read_header( read, t[0] ) )
		return( -1 );
	if( vips_image_write_prepare( t[0] ) ) 
		return( -1 );

	read->config.output.u.RGBA.rgba = VIPS_IMAGE_ADDR( t[0], 0, 0 );
	read->config.output.u.RGBA.stride = VIPS_IMAGE_SIZEOF_LINE( t[0] );
	read->config.output.u.RGBA.size = VIPS_IMAGE_SIZEOF_IMAGE( t[0] );
	read->config.output.is_external_memory = 1;

	if( WebPDecode( (uint8_t *) read->data, read->length, 
		&read->config) != VP8_STATUS_OK ) {
		vips_error( "webp2vips", "%s", _( "unable to read pixels" ) ); 
		return( -1 );
	}

	if( vips_image_write( t[0], out ) )
		return( -1 );

	return( 0 );
}
Пример #2
0
/* Smaller circles have fewer pixels and therefore fewer votes. Scale bands by
 * the ratio of circumference, so all radii get equal weight.
 */
static void
vips_hough_circle_normalise( VipsHoughCircle *hough_circle )
{
	VipsHough *hough = (VipsHough *) hough_circle;

	int max_radius = hough_circle->max_radius;
	int min_radius = hough_circle->min_radius;
	int scale = hough_circle->scale;
	int bands = hough_circle->bands;
	int width = hough_circle->width;
	int height = hough_circle->height;

	double max_circumference = 2 * VIPS_PI * max_radius;

	int b;

	for( b = 0; b < bands; b++ ) {
		int radius = b * scale + min_radius;
		double circumference = 2 * VIPS_PI * radius;
		double ratio = max_circumference / circumference;
		size_t n_pels = (size_t) width * height * bands; 

		size_t i;
		guint *q; 

		q = b + (guint *) VIPS_IMAGE_ADDR( hough->out, 0, 0 );
		for( i = 0; i < n_pels; i += bands )
			q[i] *= ratio;
	}
}
Пример #3
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 );
}
Пример #4
0
static int
read_image( Read *read, VipsImage *out )
{
	VipsImage **t = (VipsImage **) 
		vips_object_local_array( VIPS_OBJECT( out ), 3 );
	webp_decoder decoder;

	t[0] = vips_image_new_memory();
	if( read_header( read, t[0] ) )
		return( -1 );
	if( vips_image_write_prepare( t[0] ) ) 
		return( -1 );

	if( t[0]->Bands == 3 )
		decoder = WebPDecodeRGBInto;
	else
		decoder = WebPDecodeRGBAInto;

	if( !decoder( (uint8_t *) read->data, read->length, 
		VIPS_IMAGE_ADDR( t[0], 0, 0 ), 
		VIPS_IMAGE_SIZEOF_IMAGE( t[0] ),
		VIPS_IMAGE_SIZEOF_LINE( t[0] ) ) ) { 
		vips_error( "webp2vips", "%s", _( "unable to read pixels" ) ); 
		return( -1 );
	}

	if( vips_image_write( t[0], out ) )
		return( -1 );

	return( 0 );
}
Пример #5
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 );
}
Пример #6
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 );

	/* 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 );
}
Пример #7
0
static int
read_image( Read *read, VipsImage *out )
{
	VipsImage **t = (VipsImage **) 
		vips_object_local_array( VIPS_OBJECT( out ), 3 );
	guint64 length;
	void *data; 
	int fd;
	webp_decoder decoder;

	/* libwebp makes streaming very hard. We have to read to a full memory
	 * buffer, then copy to out.
	 *
	 * mmap the input file, it's slightly quicker.
	 */
	t[0] = vips_image_new_buffer();
	if( read_header( read, t[0] ) )
		return( -1 );
	if( vips_image_write_prepare( t[0] ) ) 
		return( -1 );

	if( !(fd = vips__open_image_read( read->filename )) )
		return( -1 );
	if( (length = vips_file_length( fd )) < 0 ) {
		vips_tracked_close( fd ); 
		return( -1 );
	}
	if( !(data = vips__mmap( fd, FALSE, length, 0 )) ) {
		vips_tracked_close( fd ); 
		return( -1 );
	}

	if( t[0]->Bands == 3 )
		decoder = WebPDecodeRGBInto;
	else
		decoder = WebPDecodeRGBAInto;

	if( !decoder( (uint8_t *) data, length, 
		VIPS_IMAGE_ADDR( t[0], 0, 0 ), 
		VIPS_IMAGE_SIZEOF_IMAGE( t[0] ),
		VIPS_IMAGE_SIZEOF_LINE( t[0] ) ) ) { 
		vips__munmap( data, length ); 
		vips_tracked_close( fd ); 
		vips_error( "webp2vips", "%s", _( "unable to read pixels" ) ); 
		return( -1 );
	}

	vips__munmap( data, length ); 
	vips_tracked_close( fd ); 

	if( vips_image_write( t[0], out ) )
		return( -1 );

	return( 0 );
}
Пример #8
0
static int
vips_recomb_build( VipsObject *object )
{
	VipsConversion *conversion = (VipsConversion *) object;
	VipsRecomb *recomb = (VipsRecomb *) object;
	VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 );

	if( VIPS_OBJECT_CLASS( vips_recomb_parent_class )->build( object ) )
		return( -1 );

	if( vips_image_pio_input( recomb->in ) || 
		vips_check_uncoded( "VipsRecomb", recomb->in ) ||
		vips_check_noncomplex( "VipsRecomb", recomb->in ) )
		return( -1 );
	if( vips_image_pio_input( recomb->m ) || 
		vips_check_uncoded( "VipsRecomb", recomb->m ) ||
		vips_check_noncomplex( "VipsRecomb", recomb->m ) ||
		vips_check_mono( "VipsRecomb", recomb->m ) )
		return( -1 );
	if( recomb->in->Bands != recomb->m->Xsize ) {
		vips_error( "VipsRecomb", 
			"%s", _( "bands in must equal matrix width" ) );
		return( -1 );
	}

	if( vips_cast( recomb->m, &t[0], VIPS_FORMAT_DOUBLE, NULL ) ||
		vips_image_wio_input( t[0] ) )
		return( -1 );
	recomb->coeff = (double *) VIPS_IMAGE_ADDR( t[0], 0, 0 );

	if( vips_image_copy_fields( conversion->out, recomb->in ) )
		return( -1 );
        vips_demand_hint( conversion->out, 
		VIPS_DEMAND_STYLE_THINSTRIP, recomb->in, NULL );

	conversion->out->Bands = recomb->m->Ysize;
	if( vips_bandfmt_isint( recomb->in->BandFmt ) ) 
		conversion->out->BandFmt = VIPS_FORMAT_FLOAT;

	if( vips_image_generate( conversion->out,
		vips_start_one, vips_recomb_gen, vips_stop_one, 
		recomb->in, recomb ) )
		return( -1 );

	return( 0 );
}
Пример #9
0
int
vips__webp_write_buffer( VipsImage *in, void **obuf, size_t *olen,
                         int Q, gboolean lossless )
{
    webp_encoder encoder;

    if( vips_image_wio_input( in ) )
        return( -1 );

    if( in->Bands == 4 )
        encoder = WebPEncodeRGBA;
    else
        encoder = WebPEncodeRGB;

    if( !(*olen = encoder( VIPS_IMAGE_ADDR( in, 0, 0 ),
                           in->Xsize, in->Ysize,
                           VIPS_IMAGE_SIZEOF_LINE( in ),
                           Q, (uint8_t **) obuf )) ) {
        vips_error( "vips2webp", "%s", _( "unable to encode" ) );
        return( -1 );
    }

    return( 0 );
}
Пример #10
0
int
vips__webp_write_file( VipsImage *in, const char *filename,
                       int Q, gboolean lossless )
{
    size_t len;
    uint8_t *buffer;
    FILE *fp;

    if( vips_image_wio_input( in ) )
        return( -1 );

    if( lossless ) {
        webp_encoder_lossless encoder;

        if( in->Bands == 4 )
            encoder = WebPEncodeLosslessRGBA;
        else
            encoder = WebPEncodeLosslessRGB;

        if( !(len = encoder( VIPS_IMAGE_ADDR( in, 0, 0 ),
                             in->Xsize, in->Ysize,
                             VIPS_IMAGE_SIZEOF_LINE( in ),
                             &buffer )) ) {
            vips_error( "vips2webp",
                        "%s", _( "unable to encode" ) );
            return( -1 );
        }
    }
    else {
        webp_encoder encoder;

        if( in->Bands == 4 )
            encoder = WebPEncodeRGBA;
        else
            encoder = WebPEncodeRGB;

        if( !(len = encoder( VIPS_IMAGE_ADDR( in, 0, 0 ),
                             in->Xsize, in->Ysize,
                             VIPS_IMAGE_SIZEOF_LINE( in ),
                             Q, &buffer )) ) {
            vips_error( "vips2webp",
                        "%s", _( "unable to encode" ) );
            return( -1 );
        }
    }

    if( !(fp = vips__file_open_write( filename, FALSE )) ) {
        free( buffer );
        return( -1 );
    }

    if( vips__file_write( buffer, len, 1, fp ) ) {
        fclose( fp );
        free( buffer );
        return( -1 );
    }

    fclose( fp );
    free( buffer );

    return( 0 );
}
Пример #11
0
static int
vips_quadratic_gen( VipsRegion *or, void *vseq, 
	void *a, void *b, gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) vseq;
	VipsQuadratic *quadratic = (VipsQuadratic *) b;
	VipsResample *resample = VIPS_RESAMPLE( quadratic );
	VipsInterpolateMethod interpolate_fn = 
		vips_interpolate_get_method( quadratic->interpolate );

	/* @in is the enlarged image (borders on, after vips_embed()). Use
	 * @resample->in for the original, not-expanded image. 
	 */
	const VipsImage *in = (VipsImage *) a;

	const int ps = VIPS_IMAGE_SIZEOF_PEL( in );

	double *vec = (double *) VIPS_IMAGE_ADDR( quadratic->mat, 0, 0 );

	int clip_width = resample->in->Xsize;
	int clip_height = resample->in->Ysize;

	int xlow = or->valid.left;
	int ylow = or->valid.top;
	int xhigh = VIPS_RECT_RIGHT( &or->valid );
	int yhigh = VIPS_RECT_BOTTOM( &or->valid );

	VipsPel *q;

	int xo, yo;		/* output coordinates, dstimage */
	int z;
	double fxi, fyi; 	/* input coordinates */
	double dx, dy;        	/* xo derivative of input coord. */
	double ddx, ddy;      	/* 2nd xo derivative of input coord. */

	VipsRect image;

	image.left = 0;
	image.top = 0;
	image.width = in->Xsize;
	image.height = in->Ysize;
	if( vips_region_image( ir, &image ) )
		return( -1 );

	for( yo = ylow; yo < yhigh; yo++ ) {
		fxi = xlow + vec[0];                /* order 0 */
		fyi = yo + vec[1];    
		dx = 1.0;
		dy = 0.0;

		switch( quadratic->order ) {
		case 3: 
			fxi += vec[10] * yo * yo + vec[8] * xlow * xlow;
			fyi += vec[11] * yo * yo + vec[9] * xlow * xlow;
			dx += vec[8];
			ddx = vec[8] * 2.0;
			dy += vec[9];
			ddy = vec[9] * 2.0;

		case 2: 
			fxi += vec[6] * xlow * yo;
			fyi += vec[7] * xlow * yo;
			dx += vec[6] * yo;
			dy += vec[7] * yo;

		case 1: 
			fxi += vec[4] * yo + vec[2] * xlow;
			fyi += vec[5] * yo + vec[3] * xlow;
			dx += vec[2];
			dy += vec[3];

		case 0: 
			/* See above for order 0.
			 */
			break;

		default:
		    	g_assert( 0 );
		    	return(-7);
		}

		q = VIPS_REGION_ADDR( or, xlow, yo );

		for( xo = xlow; xo < xhigh; xo++ ) {
			int xi, yi; 	

			xi = fxi;
			yi = fyi;

			/* Clipping! 
			 */
			if( xi < 0 || 
				yi < 0 || 
				xi >= clip_width || 
				yi >= clip_height ) {
				for( z = 0; z < ps; z++ ) 
					q[z] = 0;
			}
			else 
				interpolate_fn( quadratic->interpolate, 
					q, ir, fxi, fyi );

			q += ps;

			fxi += dx;
			fyi += dy;

			if( quadratic->order > 2 ) {
				dx += ddx;
				dy += ddy;
			}
		}
	}

	return( 0 );
}
Пример #12
0
static int
vips_draw_rect_build( VipsObject *object )
{
	VipsDraw *draw = VIPS_DRAW( object );
	VipsDrawink *drawink = VIPS_DRAWINK( object );
	VipsArea *ink = VIPS_AREA( drawink->ink );
	VipsDrawRect *draw_rect = (VipsDrawRect *) object;
	int left = draw_rect->left;
	int top = draw_rect->top;
	int width = draw_rect->width;
	int height = draw_rect->height;

	VipsRect image;
	VipsRect rect; 
	VipsRect clip;

	if( VIPS_OBJECT_CLASS( vips_draw_rect_parent_class )->build( object ) )
		return( -1 );

	/* Also use a solid fill for very narrow unfilled rects.
	 */
	if( !draw_rect->fill &&
		width > 2 &&
		height > 2 ) 
		return( vips_draw_rect( draw->image, 
				ink->data, ink->n, 
				left, top, width, 1, NULL ) ||
			vips_draw_rect( draw->image, 
				ink->data, ink->n, 
				left + width - 1, top, 1, height, NULL ) ||
			vips_draw_rect( draw->image, 
				ink->data, ink->n, 
				left, top + height - 1, width, 1, NULL ) ||
			vips_draw_rect( draw->image, 
				ink->data, ink->n, 
				left, top, 1, height, NULL ) );

	image.left = 0;
	image.top = 0;
	image.width = draw->image->Xsize;
	image.height = draw->image->Ysize;
	rect.left = left;
	rect.top = top;
	rect.width = width;
	rect.height = height;
	vips_rect_intersectrect( &rect, &image, &clip );

	if( !vips_rect_isempty( &clip ) ) {
		VipsPel *to = 
			VIPS_IMAGE_ADDR( draw->image, clip.left, clip.top );

		VipsPel *q;
		int x, y;

		/* We plot the first line pointwise, then memcpy() it for the
		 * subsequent lines.
		 */

		q = to;
		for( x = 0; x < clip.width; x++ ) {
			vips__drawink_pel( drawink, q );
			q += draw->psize;
		}

		q = to + draw->lsize;
		for( y = 1; y < clip.height; y++ ) {
			memcpy( q, to, clip.width * draw->psize );
			q += draw->lsize;
		}
	}

	return( 0 );
}
Пример #13
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 );
}
Пример #14
0
static int
vips_histogram_build( VipsObject *object )
{
	VipsHistogram *histogram = VIPS_HISTOGRAM( object );
	VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
	VipsHistogramClass *hclass = VIPS_HISTOGRAM_GET_CLASS( histogram );

	VipsImage **decode;
	VipsImage **format;
	VipsImage **band;
	VipsImage **size;
	VipsImage **memory;

	VipsPel *outbuf;		
	VipsPel **inbuf;		
	int i;

#ifdef DEBUG
	printf( "vips_histogram_build: " );
	vips_object_print_name( object );
	printf( "\n" );
#endif /*DEBUG*/

	if( VIPS_OBJECT_CLASS( vips_histogram_parent_class )->build( object ) )
		return( -1 );

	g_assert( histogram->n > 0 ); 

	/* Must be NULL-terminated.
	 */
	g_assert( !histogram->in[histogram->n] ); 

	decode = (VipsImage **) vips_object_local_array( object, histogram->n );
	format = (VipsImage **) vips_object_local_array( object, histogram->n );
	band = (VipsImage **) vips_object_local_array( object, histogram->n );
	size = (VipsImage **) vips_object_local_array( object, histogram->n );
	memory = (VipsImage **) vips_object_local_array( object, histogram->n );

	g_object_set( histogram, "out", vips_image_new(), NULL ); 

	for( i = 0; i < histogram->n; i++ ) 
		if( vips_image_decode( histogram->in[i], &decode[i] ) ||
			vips_check_hist( class->nickname, decode[i] ) )
			return( -1 ); 

	/* Cast our input images up to a common format, bands and size. If
	 * input_format is set, cast to a fixed input type.
	 */
	if( hclass->input_format != VIPS_FORMAT_NOTSET ) {
		for( i = 0; i < histogram->n; i++ ) 
			if( vips_cast( decode[i], &format[i],
				hclass->input_format, NULL ) )
				return( -1 ); 
	}
	else {
		if( vips__formatalike_vec( decode, format, histogram->n ) )
			return( -1 );
	}
		
	if( vips__bandalike_vec( class->nickname, 
		format, band, histogram->n, 1 ) ||
		vips__hist_sizealike_vec( band, size, histogram->n ) ) 
		return( -1 );

	if( vips_image_pipeline_array( histogram->out, 
		VIPS_DEMAND_STYLE_THINSTRIP, size ) ) 
		return( -1 );

	/* Need a copy of the inputs in memory.
	 */
	if( !(inbuf = VIPS_ARRAY( object, histogram->n + 1, VipsPel * )) )
                return( -1 );
	for( i = 0; i < histogram->n; i++ ) {
		if( !(memory[i] = vips_image_copy_memory( size[i] )) )
			return( -1 ); 
		inbuf[i] = VIPS_IMAGE_ADDR( memory[i], 0, 0 );
	}
	inbuf[i] = NULL; 

	/* Keep a copy of the memory images here for subclasses.
	 */
	histogram->ready = memory;

	histogram->out->Xsize = VIPS_IMAGE_N_PELS( histogram->ready[0] );
	histogram->out->Ysize = 1;
	if( hclass->format_table ) 
		histogram->out->BandFmt = 
			hclass->format_table[histogram->ready[0]->BandFmt];
	histogram->out->Type = VIPS_INTERPRETATION_HISTOGRAM;

	if( !(outbuf = vips_malloc( object, 
		VIPS_IMAGE_SIZEOF_LINE( histogram->out ))) )
                return( -1 );

	hclass->process( histogram, outbuf, inbuf, histogram->ready[0]->Xsize );

	if( vips_image_write_line( histogram->out, 0, outbuf ) )
		return( -1 ); 

	return( 0 );
}