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 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 ); }
/* 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 ); } }
/* 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 ); }
static int sink_thread_state_build( VipsObject *object ) { SinkThreadState *state = (SinkThreadState *) object; Sink *sink = (Sink *) ((VipsThreadState *) state)->a; if( !(state->reg = vips_region_new( sink->t )) || sink_call_start( sink, state ) ) return( -1 ); return( VIPS_OBJECT_CLASS( sink_thread_state_parent_class )->build( object ) ); }
/* 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 ); }
/* 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 ); }
/* 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 ); }
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 ); }
/* 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 ); } }
/* 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 ); }