X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-core%2Ftrunk%2Fsrc%2Fsynfig%2Flayer_bitmap.cpp;h=cda5d09897d0fd8defef6108bc3500636bf2c819;hb=9459638ad6797b8139f1e9f0715c96076dbf0890;hp=27d39112071ca749e0b95b865ee38ba295e24c0f;hpb=e8a065f2385c219c511b57dac52786120bfa097d;p=synfig.git diff --git a/synfig-core/trunk/src/synfig/layer_bitmap.cpp b/synfig-core/trunk/src/synfig/layer_bitmap.cpp index 27d3911..cda5d09 100644 --- a/synfig-core/trunk/src/synfig/layer_bitmap.cpp +++ b/synfig-core/trunk/src/synfig/layer_bitmap.cpp @@ -2,7 +2,7 @@ /*! \file layer_bitmap.cpp ** \brief Template Header ** -** $Id: layer_bitmap.cpp,v 1.2 2005/01/24 03:08:18 darco Exp $ +** $Id$ ** ** \legal ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley @@ -68,10 +68,11 @@ synfig::Layer_Bitmap::Layer_Bitmap(): br (0.5,-0.5), c (1), surface (128,128), + trimmed (false), gamma_adjust (1.0) { } - + bool synfig::Layer_Bitmap::set_param(const String & param, ValueBase value) { @@ -84,7 +85,7 @@ synfig::Layer_Bitmap::set_param(const String & param, ValueBase value) //gamma_adjust.set_gamma(1.0/value.get(Real())); return true; } - + return Layer_Composite::set_param(param,value); } @@ -99,13 +100,15 @@ synfig::Layer_Bitmap::get_param(const String & param)const if(param=="_width") { + if (trimmed) return int(width); return surface.get_w(); } if(param=="_height") { + if (trimmed) return int(height); return surface.get_h(); } - + return Layer_Composite::get_param(param); } @@ -113,7 +116,7 @@ Layer::Vocab Layer_Bitmap::get_param_vocab()const { Layer::Vocab ret(Layer_Composite::get_param_vocab()); - + ret.push_back(ParamDesc("tl") .set_local_name(_("Top-Left")) .set_description(_("Upper left-hand Corner of image")) @@ -146,7 +149,7 @@ Layer_Bitmap::hit_check(synfig::Context context, const synfig::Point &pos)const { Point surface_pos; surface_pos=pos-tl; - + surface_pos[0]/=br[0]-tl[0]; if(surface_pos[0]<=1.0 && surface_pos[0]>=0.0) { @@ -156,22 +159,20 @@ Layer_Bitmap::hit_check(synfig::Context context, const synfig::Point &pos)const return const_cast(this); } } - + return context.hit_check(pos); } inline const Color& -synfig::Layer_Bitmap::filter(const Color& c)const +synfig::Layer_Bitmap::filter(Color& x)const { - if(gamma_adjust==1.0) - return c; - static Color x; - x=c; - - x.set_r(powf((float)x.get_r(),gamma_adjust)); - x.set_g(powf((float)x.get_g(),gamma_adjust)); - x.set_b(powf((float)x.get_b(),gamma_adjust)); + if(gamma_adjust!=1.0) + { + x.set_r(powf((float)x.get_r(),gamma_adjust)); + x.set_g(powf((float)x.get_g(),gamma_adjust)); + x.set_b(powf((float)x.get_b(),gamma_adjust)); + } return x; } @@ -182,18 +183,32 @@ synfig::Layer_Bitmap::get_color(Context context, const Point &pos)const if(!get_amount()) return context.get_color(pos); - + surface_pos=pos-tl; - + surface_pos[0]/=br[0]-tl[0]; if(surface_pos[0]<=1.0 && surface_pos[0]>=0.0) { surface_pos[1]/=br[1]-tl[1]; if(surface_pos[1]<=1.0 && surface_pos[1]>=0.0) { - surface_pos[0]*=surface.get_w(); - surface_pos[1]*=surface.get_h(); - + if (trimmed) + { + surface_pos[0]*=width; + surface_pos[1]*=height; + + if (surface_pos[0] > left+surface.get_w() || surface_pos[0] < left || surface_pos[1] > top+surface.get_h() || surface_pos[1] < top) + return context.get_color(pos); + + surface_pos[0] -= left; + surface_pos[1] -= top; + } + else + { + surface_pos[0]*=surface.get_w(); + surface_pos[1]*=surface.get_h(); + } + Color ret(Color::alpha()); switch(c) @@ -220,16 +235,16 @@ synfig::Layer_Bitmap::get_color(Context context, const Point &pos)const } break; } - + ret=filter(ret); - + if(get_amount()==1 && get_blend_method()==Color::BLEND_STRAIGHT) return ret; else return Color::blend(ret,context.get_color(pos),get_amount(),get_blend_method()); } } - + return context.get_color(pos); } @@ -245,18 +260,19 @@ Layer_Bitmap::accelerated_render(Context context,Surface *out_surface,int qualit // We can only handle NN and Linear at the moment //if(interp>1) // return Layer_Composite::accelerated_render(context,out_surface,quality,renddesc,cb); - + //if we don't actually have a valid surface just skip us if(!surface.is_valid()) { // Render what is behind us return context.accelerated_render(out_surface,quality,renddesc,cb); } - + SuperCallback subcb(cb,1,10000,10001+renddesc.get_h()); if( get_amount()==1 && get_blend_method()==Color::BLEND_STRAIGHT && + !trimmed && renddesc.get_tl()==tl && renddesc.get_br()==br) { @@ -276,92 +292,109 @@ Layer_Bitmap::accelerated_render(Context context,Surface *out_surface,int qualit if(!context.accelerated_render(out_surface,quality,renddesc,&subcb)) return false; } - + if(cb && !cb->amount_complete(10000,10001+renddesc.get_h())) return false; Point obr = renddesc.get_br(), otl = renddesc.get_tl(); - + //Vector::value_type pw=renddesc.get_w()/(renddesc.get_br()[0]-renddesc.get_tl()[0]); //Vector::value_type ph=renddesc.get_h()/(renddesc.get_br()[1]-renddesc.get_tl()[1]); - + //A = representation of input (just tl,br) //just a scaling right now //B = representation of output (just tl,br) //just a scaling right now //sa = scaling for input (0,1) -> (0,w/h) //sb = scaling for output (0,1) -> (0,w/h) - - float inwf = br[0] - tl[0]; - float inhf = br[1] - tl[1]; - + float outwf = obr[0] - otl[0]; float outhf = obr[1] - otl[1]; - + int inw = surface.get_w(); int inh = surface.get_h(); - + int outw = renddesc.get_w(); int outh = renddesc.get_h(); - + + float inwf, inhf; + Point itl, ibr; + + if (trimmed) + { + inwf = (br[0] - tl[0])*surface.get_w()/width; + inhf = (br[1] - tl[1])*surface.get_h()/height; + itl = Point(tl[0] + (br[0]-tl[0])*left/width, + tl[1] + (br[1]-tl[1])*top/height); + ibr = Point(tl[0] + (br[0]-tl[0])*(left+inw)/width, + tl[1] + (br[1]-tl[1])*(top+inh)/height); + } + else + { + inwf = br[0] - tl[0]; + inhf = br[1] - tl[1]; + itl = tl; + ibr = br; + } + //need to get the input coords in output space, so we can clip - + //get the desired corners of the bitmap (in increasing order) in integers //floating point corners - float x1f = (tl[0] - otl[0])*outw/outwf; - float x2f = (br[0] - otl[0])*outw/outwf; - float y1f = (tl[1] - otl[1])*outh/outhf; - float y2f = (br[1] - otl[1])*outh/outhf; - + float x1f = (itl[0] - otl[0])*outw/outwf; + float x2f = (ibr[0] - otl[0])*outw/outwf; + float y1f = (itl[1] - otl[1])*outh/outhf; + float y2f = (ibr[1] - otl[1])*outh/outhf; + if(x1f > x2f) swap(x1f,x2f); if(y1f > y2f) swap(y1f,y2f); - + int x_start = max(0,(int)floor(x1f)); //probably floor int x_end = min(outw,(int)ceil(x2f)); //probably ceil int y_start = max(0,(int)floor(y1f)); //probably floor int y_end = min(outh,(int)ceil(y2f)); //probably ceil - + //need to get the x,y,dx,dy values from output space to input, so we can do fast interpolation - + //get the starting position in input space... for interpolating - + // in int -> out float: // Sb(B^-1)A(Sa^-1) x - float inx_start = (((x_start/*+0.5f*/)*outwf/outw + otl[0]) - tl[0])*inw/inwf; //may want to bias this (center of pixel)??? - float iny_start = (((y_start/*+0.5f*/)*outhf/outh + otl[1]) - tl[1])*inh/inhf; //may want to bias this (center of pixel)??? - + float inx_start = (((x_start/*+0.5f*/)*outwf/outw + otl[0]) - itl[0])*inw/inwf; //may want to bias this (center of pixel)??? + float iny_start = (((y_start/*+0.5f*/)*outhf/outh + otl[1]) - itl[1])*inh/inhf; //may want to bias this (center of pixel)??? + //calculate the delta values in input space for one pixel movement in output space //same matrix but with a vector instead of a point... float indx = outwf*(inw)/((outw)*inwf); //translations died float indy = outhf*(inh)/((outh)*inhf); //translations died - - //perhaps use a DDA algorithm... if faster... + + //perhaps use a DDA algorithm... if faster... // will still want pixel fractions to be floating point since colors are //synfig::info("xstart:%d ystart:%d xend:%d yend:%d",x_start,y_start,x_end,y_end); - + //start drawing at the start of the bitmap (either origin or corner of input...) //and get other info Surface::alpha_pen pen(out_surface->get_pen(x_start,y_start)); pen.set_alpha(get_amount()); pen.set_blend_method(get_blend_method()); - + //check if we should use the downscale filtering if(quality <= 7) { - //the stride of the value should be inverted because we want to downsample + //the stride of the value should be inverted because we want to downsample //when the stride is small, not big //int multw = (int)ceil(indx); //int multh = (int)ceil(indy); - + if(indx > 1.7 || indy > 1.7) { - /*synfig::info("Decided to downsample? ratios - (%f,%f) -> (%d,%d)", - indx, indy, multw, multh); */ - + /*synfig::info("Decided to downsample? ratios - (%f,%f) -> (%d,%d)", + indx, indy, multw, multh); */ + //use sample rect here... - + float iny, inx; int x,y; - + //Point sample - truncate iny = iny_start;//+0.5f; for(y = y_start; y < y_end; ++y, pen.inc_y(), iny += indy) @@ -374,21 +407,21 @@ Layer_Bitmap::accelerated_render(Context context,Surface *out_surface,int qualit } pen.dec_x(x_end-x_start); } - + //Color c = (*out_surface)[0][0]; //synfig::info("ValueBase of first pixel = (%f,%f,%f,%f)",c.get_r(),c.get_g(),c.get_b(),c.get_a()); - + return true; } } - + //perform normal interpolation if(interp==0) - { + { //synfig::info("Decided to do nearest neighbor"); float iny, inx; int x,y; - + //Point sample - truncate iny = iny_start;//+0.5f; for(y = y_start; y < y_end; y++, pen.inc_y(), iny += indy) @@ -408,14 +441,14 @@ Layer_Bitmap::accelerated_render(Context context,Surface *out_surface,int qualit if(interp==1) { //bilinear filtering - + //float xmf,xpf,ymf,ypf; //int xm,xp,ym,yp; float inx,iny; int x,y; - + //can probably buffer for x values... - + //loop and based on inx,iny sample input image iny = iny_start; for(y = y_start; y < y_end; y++, pen.inc_y(), iny += indy) @@ -423,24 +456,25 @@ Layer_Bitmap::accelerated_render(Context context,Surface *out_surface,int qualit inx = inx_start; for(x = x_start; x < x_end; x++, pen.inc_x(), inx += indx) { - pen.put_value(filter(surface.linear_sample(inx,iny))); + Color col(surface.linear_sample(inx,iny)); + pen.put_value(filter(col)); } pen.dec_x(x_end-x_start); - + } - } + } else if(interp==2) { //cosine filtering - + //float xmf,xpf,ymf,ypf; //int xm,xp,ym,yp; float inx,iny; int x,y; - + //can probably buffer for x values... - + //loop and based on inx,iny sample input image iny = iny_start; for(y = y_start; y < y_end; y++, pen.inc_y(), iny += indy) @@ -448,23 +482,24 @@ Layer_Bitmap::accelerated_render(Context context,Surface *out_surface,int qualit inx = inx_start; for(x = x_start; x < x_end; x++, pen.inc_x(), inx += indx) { - pen.put_value(filter(surface.cosine_sample(inx,iny))); + Color col(surface.cosine_sample(inx,iny)); + pen.put_value(filter(col)); } pen.dec_x(x_end-x_start); - + } - } + } else { //cubic filtering - + //float xmf,xpf,ymf,ypf; //int xm,xp,ym,yp; float inx,iny; int x,y; - + //can probably buffer for x values... - + //loop and based on inx,iny sample input image iny = iny_start; for(y = y_start; y < y_end; y++, pen.inc_y(), iny += indy) @@ -472,12 +507,13 @@ Layer_Bitmap::accelerated_render(Context context,Surface *out_surface,int qualit inx = inx_start; for(x = x_start; x < x_end; x++, pen.inc_x(), inx += indx) { - pen.put_value(filter(surface.cubic_sample(inx,iny))); + Color col(surface.cubic_sample(inx,iny)); + pen.put_value(filter(col)); } pen.dec_x(x_end-x_start); - + } - } + } return true; }