コード例 #1
0
/* Walk the pyramid allocating resources. 
 */
static int
pyramid_fill( Write *write )
{
	Layer *layer;

	for( layer = write->layer; layer; layer = layer->below ) {
		VipsRect strip_size;

		layer->image = vips_image_new();
		if( vips_image_pipelinev( layer->image, 
			VIPS_DEMAND_STYLE_ANY, write->im, NULL ) ) 
			return( -1 );
		layer->image->Xsize = layer->width;
		layer->image->Ysize = layer->height;

		layer->strip = vips_region_new( layer->image );
		layer->copy = vips_region_new( layer->image );

		/* The regions will get used in the bg thread callback, so 
		 * make sure we don't own them.
		 */
		vips__region_no_ownership( layer->strip );
		vips__region_no_ownership( layer->copy );

		/* Build a line of tiles here. 
		 *
		 * Expand the strip if necessary to make sure we have an even 
		 * number of lines. 
		 */
		strip_size.left = 0;
		strip_size.top = 0;
		strip_size.width = layer->image->Xsize;
		strip_size.height = write->tileh;
		if( (strip_size.height & 1) == 1 )
			strip_size.height += 1;
		if( vips_region_buffer( layer->strip, &strip_size ) ) 
			return( -1 );

		if( !(layer->tif = 
			vips__tiff_openout( layer->lname, write->bigtiff )) ||
			write_tiff_header( write, layer ) )  
			return( -1 );
	}

	return( 0 );
}
コード例 #2
0
ファイル: tilecache.c プロジェクト: alon/libvips
static int
tile_move( Tile *tile, int x, int y )
{
	VipsRect area;

	tile->x = x;
	tile->y = y;

	area.left = x;
	area.top = y;
	area.width = tile->cache->tile_width;
	area.height = tile->cache->tile_height;

	if( vips_region_buffer( tile->region, &area ) )
		return( -1 );

	return( 0 );
}
コード例 #3
0
ファイル: tilecache.c プロジェクト: jieah/libvips
static int
vips_tile_move( VipsTile *tile, int x, int y )
{
	/* We are changing x/y and therefore the hash value. We must unlink
	 * from the old hash position and relink at the new place.
	 */
	g_hash_table_steal( tile->cache->tiles, &tile->pos );

	tile->pos.left = x;
	tile->pos.top = y;
	tile->pos.width = tile->cache->tile_width;
	tile->pos.height = tile->cache->tile_height;

	g_hash_table_insert( tile->cache->tiles, &tile->pos, tile );

	if( vips_region_buffer( tile->region, &tile->pos ) )
		return( -1 );

	/* No data yet, but someone must want it.
	 */
	tile->state = VIPS_TILE_STATE_PEND;

	return( 0 );
}
コード例 #4
0
/* A new strip has arrived! The strip has at least enough pixels in to 
 * write a line of tiles or a set of scanlines.  
 *
 * - write a line of tiles / set of scanlines
 * - shrink what we can to the layer below
 * - move our strip down by the tile height
 * - copy the overlap with the previous strip
 */
static int
layer_strip_arrived( Layer *layer )
{
	Write *write = layer->write;

	int result;
	VipsRect new_strip;
	VipsRect overlap;
	VipsRect image_area;

	if( write->tile ) 
		result = layer_write_tile( write, layer, layer->strip );
	else
		result = layer_write_strip( write, layer, layer->strip );
	if( result )
		return( -1 );

	if( layer->below &&
		layer_strip_shrink( layer ) ) 
		return( -1 );

	/* Position our strip down the image.  
	 *
	 * Expand the strip if necessary to make sure we have an even 
	 * number of lines. 
	 */
	layer->y += write->tileh;
	new_strip.left = 0;
	new_strip.top = layer->y;
	new_strip.width = layer->image->Xsize;
	new_strip.height = write->tileh;

	image_area.left = 0;
	image_area.top = 0;
	image_area.width = layer->image->Xsize;
	image_area.height = layer->image->Ysize;
	vips_rect_intersectrect( &new_strip, &image_area, &new_strip ); 

	if( (new_strip.height & 1) == 1 )
		new_strip.height += 1;

	/* What pixels that we will need do we already have? Save them in 
	 * overlap.
	 */
	vips_rect_intersectrect( &new_strip, &layer->strip->valid, &overlap );
	if( !vips_rect_isempty( &overlap ) ) {
		if( vips_region_buffer( layer->copy, &overlap ) )
			return( -1 );
		vips_region_copy( layer->strip, layer->copy, 
			&overlap, overlap.left, overlap.top );
	}

	if( !vips_rect_isempty( &new_strip ) ) {
		if( vips_region_buffer( layer->strip, &new_strip ) ) 
			return( -1 );

		/* And copy back again.
		 */
		if( !vips_rect_isempty( &overlap ) ) 
			vips_region_copy( layer->copy, layer->strip, 
				&overlap, overlap.left, overlap.top );
	}

	return( 0 );
}
コード例 #5
0
ファイル: dzsave.c プロジェクト: eeertekin/libvips
/* Build a pyramid. 
 *
 * width/height is the size of this layer, real_* the subsection of the layer
 * which is real pixels (as opposed to background). 
 */
static Layer *
pyramid_build( VipsForeignSaveDz *dz, Layer *above, 
	int width, int height, VipsRect *real_pixels )
{
	VipsForeignSave *save = VIPS_FOREIGN_SAVE( dz );
	Layer *layer = VIPS_NEW( dz, Layer );

	VipsRect strip;
	int limit; 

	layer->dz = dz;
	layer->width = width;
	layer->height = height;

	layer->tiles_across = ROUND_UP( width, dz->tile_size ) / dz->tile_size;
	layer->tiles_down = ROUND_UP( height, dz->tile_size ) / dz->tile_size;

	layer->real_pixels = *real_pixels; 

	layer->image = NULL;
	layer->strip = NULL;
	layer->copy = NULL;

	if( !above )
		/* Top of pyramid.
		 */
		layer->sub = 1;	
	else
		layer->sub = above->sub * 2;

	layer->below = NULL;
	layer->above = above;

	/* We round the image size up to an even number to make x2 shrink
	 * easy.
	 */
	layer->image = vips_image_new();
	if( vips_image_pipelinev( layer->image, 
		VIPS_DEMAND_STYLE_ANY, save->ready, NULL ) ) {
		layer_free( layer );
		return( NULL );
	}
	layer->image->Xsize = width + (width & 1);
	layer->image->Ysize = height + (height & 1);

	layer->strip = vips_region_new( layer->image );
	layer->copy = vips_region_new( layer->image );

	/* The regions will get used in the bg thread callback, so make sure
	 * we don't own them.
	 */
	vips__region_no_ownership( layer->strip );
	vips__region_no_ownership( layer->copy );

	/* Build a line of tiles here. Normally strips are height + 2 *
	 * overlap, but the first row is missing the top edge.
	 *
	 * Expand the strip if necessary to make sure we have an even 
	 * number of lines. 
	 */
	layer->y = 0;
	layer->write_y = 0;
	strip.left = 0;
	strip.top = 0;
	strip.width = layer->image->Xsize;
	strip.height = dz->tile_size + dz->overlap;
	if( (strip.height & 1) == 1 )
		strip.height += 1;
	if( vips_region_buffer( layer->strip, &strip ) ) {
		layer_free( layer );
		return( NULL );
	}

	switch( dz->depth ) {
	case VIPS_FOREIGN_DZ_DEPTH_ONEPIXEL:
		limit = 1;
		break;

	case VIPS_FOREIGN_DZ_DEPTH_ONETILE:
		limit = dz->tile_size;
		break;

	case VIPS_FOREIGN_DZ_DEPTH_ONE:
		limit = VIPS_MAX( width, height );
		break;

	default:
		g_assert( 0 );
		limit = dz->tile_size;
		break;
	}

	if( width > limit || 
		height > limit ) {
		/* Round up, so eg. a 5 pixel wide image becomes 3 a layer
		 * down.
		 *
		 * For the rect, round left/top down, round bottom/right up,
		 * so we get all possible pixels. 
		 */
		VipsRect halfrect;

		halfrect.left = real_pixels->left / 2;
		halfrect.top = real_pixels->top / 2;
		halfrect.width = (VIPS_RECT_RIGHT( real_pixels ) + 1) / 2 - 
			halfrect.left;
		halfrect.height = (VIPS_RECT_BOTTOM( real_pixels ) + 1) / 2 - 
			halfrect.top;

		if( !(layer->below = pyramid_build( dz, layer, 
			(width + 1) / 2, (height + 1) / 2,
			&halfrect )) ) { 
			layer_free( layer );
			return( NULL );
		}
		layer->n = layer->below->n + 1;
	}
	else
		layer->n = 0;

#ifdef DEBUG
	printf( "pyramid_build:\n" );
	printf( "\tn = %d\n", layer->n );
	printf( "\twidth = %d, height = %d\n", width, height );
	printf( "\tXsize = %d, Ysize = %d\n", 
		layer->image->Xsize, layer->image->Ysize );
	printf( "\treal_pixels.left = %d, real_pixels.top = %d\n", 
		real_pixels->left, real_pixels->top ); 
	printf( "\treal_pixels.width = %d, real_pixels.height = %d\n", 
		real_pixels->width, real_pixels->height ); 
#endif

	return( layer );
}