/* Combine two transformations. out can be one of the ins. */ int im__transform_add( const Transformation *in1, const Transformation *in2, Transformation *out ) { out->a = in1->a * in2->a + in1->c * in2->b; out->b = in1->b * in2->a + in1->d * in2->b; out->c = in1->a * in2->c + in1->c * in2->d; out->d = in1->b * in2->c + in1->d * in2->d; out->dx = in1->dx * in2->a + in1->dy * in2->b + in2->dx; out->dy = in1->dx * in2->c + in1->dy * in2->d + in2->dy; if( im__transform_calc_inverse( out ) ) return( -1 ); return( 0 ); }
/* Init a Transform. */ void im__transform_init( Transformation *trn ) { trn->oarea.left = 0; trn->oarea.top = 0; trn->oarea.width = -1; trn->oarea.height = -1; trn->iarea.left = 0; trn->iarea.top = 0; trn->iarea.width = -1; trn->iarea.height = -1; trn->a = 1.0; /* Identity transform */ trn->b = 0.0; trn->c = 0.0; trn->d = 1.0; trn->dx = 0.0; trn->dy = 0.0; (void) im__transform_calc_inverse( trn ); }
/* Like im_similarity(), but return the transform we generated. */ static int apply_similarity( Transformation *trn, IMAGE *in, IMAGE *out, double a, double b, double dx, double dy ) { trn->iarea.left = 0; trn->iarea.top = 0; trn->iarea.width = in->Xsize; trn->iarea.height = in->Ysize; trn->a = a; trn->b = -b; trn->c = b; trn->d = a; trn->dx = dx; trn->dy = dy; im__transform_set_area( trn ); if( im__transform_calc_inverse( trn ) ) return( -1 ); if( im__affine( in, out, trn ) ) return( -1 ); return( 0 ); }
static int affinei( IMAGE *in, IMAGE *out, VipsInterpolate *interpolate, Transformation *trn ) { Affine *affine; double edge; /* Make output image. */ if( im_piocheck( in, out ) ) return( -1 ); if( im_cp_desc( out, in ) ) return( -1 ); /* Need a copy of the params for the lifetime of out. */ if( !(affine = IM_NEW( out, Affine )) ) return( -1 ); affine->interpolate = NULL; if( im_add_close_callback( out, (im_callback_fn) affine_free, affine, NULL ) ) return( -1 ); affine->in = in; affine->out = out; affine->interpolate = interpolate; g_object_ref( interpolate ); affine->trn = *trn; if( im__transform_calc_inverse( &affine->trn ) ) return( -1 ); out->Xsize = affine->trn.oarea.width; out->Ysize = affine->trn.oarea.height; /* Normally SMALLTILE ... except if this is a size up/down affine. */ if( affine->trn.b == 0.0 && affine->trn.c == 0.0 ) { if( im_demand_hint( out, IM_FATSTRIP, in, NULL ) ) return( -1 ); } else { if( im_demand_hint( out, IM_SMALLTILE, in, NULL ) ) return( -1 ); } /* Check for coordinate overflow ... we want to be able to hold the * output space inside INT_MAX / TRANSFORM_SCALE. */ edge = INT_MAX / VIPS_TRANSFORM_SCALE; if( affine->trn.oarea.left < -edge || affine->trn.oarea.top < -edge || IM_RECT_RIGHT( &affine->trn.oarea ) > edge || IM_RECT_BOTTOM( &affine->trn.oarea ) > edge ) { im_error( "im_affinei", "%s", _( "output coordinates out of range" ) ); return( -1 ); } /* Generate! */ if( im_generate( out, im_start_one, affinei_gen, im_stop_one, in, affine ) ) return( -1 ); return( 0 ); }