X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=ETL%2Ftags%2FETL_0_04_10%2FETL%2F_surface.h;fp=ETL%2Ftags%2FETL_0_04_10%2FETL%2F_surface.h;h=0000000000000000000000000000000000000000;hb=3a6643238c67c043fc3592837a05d6d2861967f1;hp=eae2df095ad65480d75262a2c9189b866bd939d3;hpb=47fce282611fbba1044921d22ca887f9b53ad91a;p=synfig.git diff --git a/ETL/tags/ETL_0_04_10/ETL/_surface.h b/ETL/tags/ETL_0_04_10/ETL/_surface.h deleted file mode 100644 index eae2df0..0000000 --- a/ETL/tags/ETL_0_04_10/ETL/_surface.h +++ /dev/null @@ -1,647 +0,0 @@ -/*! ======================================================================== -** Extended Template and Library -** Surface Class Implementation -** $Id$ -** -** Copyright (c) 2002 Robert B. Quattlebaum Jr. -** -** This package is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License as -** published by the Free Software Foundation; either version 2 of -** the License, or (at your option) any later version. -** -** This package is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** General Public License for more details. -** -** === N O T E S =========================================================== -** -** This is an internal header file, included by other ETL headers. -** You should not attempt to use it directly. -** -** ========================================================================= */ - -/* === S T A R T =========================================================== */ - -#ifndef __ETL__SURFACE_H -#define __ETL__SURFACE_H - -/* === H E A D E R S ======================================================= */ - -#include "_pen.h" -#include "_misc.h" -#include - -/* === M A C R O S ========================================================= */ - -/* === C L A S S E S & S T R U C T S ======================================= */ - -_ETL_BEGIN_NAMESPACE - -template -class value_prep -{ -public: - typedef T value_type; - typedef AT accumulator_type; - - accumulator_type cook(const value_type& x)const { return (accumulator_type)x; } - value_type uncook(const accumulator_type& x)const { return (value_type)x; } -}; - -template > -class surface -{ -public: - typedef T value_type; - typedef AT accumulator_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef generic_pen pen; - typedef generic_pen const_pen; - typedef VP value_prep_type; - - typedef alpha_pen const_alpha_pen; - typedef alpha_pen alpha_pen; - - typedef typename pen::difference_type size_type; - typedef typename pen::difference_type difference_type; - - typedef typename pen::iterator_x iterator_x; - typedef typename pen::iterator_y iterator_y; - typedef typename pen::const_iterator_x const_iterator_x; - typedef typename pen::const_iterator_y const_iterator_y; - -private: - value_type *data_; - value_type *zero_pos_; - typename difference_type::value_type pitch_; - int w_, h_; - bool deletable_; - - value_prep_type cooker_; - - void swap(const surface &x) - { - std::swap(data_,x.data_); - std::swap(zero_pos_,x.zero_pos_); - std::swap(pitch_,x.pitch_); - std::swap(w_,x.w_); - std::swap(h_,x.h_); - std::swap(deletable_,x.deletable_); - } - -public: - surface(): - data_(0), - zero_pos_(data_), - pitch_(0), - w_(0),h_(0), - deletable_(false) { } - - surface(value_type* data, int w, int h, bool deletable=false): - data_(data), - zero_pos_(data), - pitch_(sizeof(value_type)*w), - w_(w),h_(h), - deletable_(deletable) { } - - surface(const typename size_type::value_type &w, const typename size_type::value_type &h): - data_(new value_type[w*h]), - zero_pos_(data_), - pitch_(sizeof(value_type)*w), - w_(w),h_(h), - deletable_(true) { } - - surface(const size_type &s): - data_(new value_type[s.x*s.y]), - zero_pos_(data_), - pitch_(sizeof(value_type)*s.x), - w_(s.x),h_(s.y), - deletable_(true) { } - - template - surface(const _pen &_begin, const _pen &_end) - { - typename _pen::difference_type size=_end-_begin; - - data_=new value_type[size.x*size.y]; - w_=size.x; - h_=size.y; - zero_pos_=data_; - pitch_=sizeof(value_type)*w_; - deletable_=true; - - int x,y; - - for(y=0;y void - fill(value_type v, _pen& PEN, int w, int h) - { - assert(data_); - if(w<=0 || h<=0)return; - int y; - PEN.set_value(v); - for(y=0;y void blit_to(_pen &pen) - { return blit_to(pen,0,0, get_w(),get_h()); } - - template void - blit_to(_pen &DEST_PEN, - int x, int y, int w, int h) //src param - { - if(x>=w_ || y>=h_) - return; - - //clip source origin - if(x<0) - { - w+=x; //decrease - x=0; - } - - if(y<0) - { - h+=y; //decrease - y=0; - } - - //clip width against dest width - w = std::min((long)w,(long)(DEST_PEN.end_x()-DEST_PEN.x())); - h = std::min((long)h,(long)(DEST_PEN.end_y()-DEST_PEN.y())); - - //clip width against src width - w = std::min(w,w_-x); - h = std::min(h,h_-y); - - if(w<=0 || h<=0) - return; - - pen SOURCE_PEN(get_pen(x,y)); - - for(; h>0; h--,DEST_PEN.inc_y(),SOURCE_PEN.inc_y()) - { - int i; - for(i=0; i0 - && h_>0 - && pitch_!=0 - ; - } - - operator bool()const { return is_valid(); } - - pen begin() { assert(data_); return pen(data_,w_,h_,pitch_); } - pen get_pen(int x, int y) { assert(data_); return begin().move(x,y); } - pen end() { assert(data_); return get_pen(w_,h_); } - - const_pen begin()const { assert(data_); return const_pen(data_,w_,h_,pitch_); } - const_pen get_pen(int x, int y)const { assert(data_); return begin().move(x,y); } - const_pen end()const { assert(data_); return get_pen(w_,h_); } - - //! Linear sample - value_type linear_sample(const float x, const float y)const - { - int u(floor_to_int(x)), v(floor_to_int(y)); - float a, b; - static const float epsilon(1.0e-6); - - if(x<0.0f)u=0,a=0.0f; - else if(x>w_-1)u=w_-1,a=0.0f; - else a=x-u; - - if(y<0.0f)v=0,b=0.0f; - else if(y>h_-1)v=h_-1,b=0.0f; - else b=y-v; - - const float - c(1.0f-a), d(1.0f-b), - e(a*d),f(c*b),g(a*b); - - accumulator_type ret(cooker_.cook((*this)[v][u])*(c*d)); - if(e>=epsilon)ret+=cooker_.cook((*this)[v][u+1])*e; - if(f>=epsilon)ret+=cooker_.cook((*this)[v+1][u])*f; - if(g>=epsilon)ret+=cooker_.cook((*this)[v+1][u+1])*g; - return cooker_.uncook(ret); - } - - //! Cosine sample - value_type cosine_sample(const float x, const float y)const - { - int u(floor_to_int(x)), v(floor_to_int(y)); - float a, b; - static const float epsilon(1.0e-6); - - if(x<0.0f)u=0,a=0.0f; - else if(x>w_-1)u=w_-1,a=0.0f; - else a=x-u; - - if(y<0.0f)v=0,b=0.0f; - else if(y>h_-1)v=h_-1,b=0.0f; - else b=y-v; - - a=(1.0f-cos(a*3.1415927f))*0.5f; - b=(1.0f-cos(b*3.1415927f))*0.5f; - - const float - c(1.0f-a), d(1.0f-b), - e(a*d),f(c*b),g(a*b); - - accumulator_type ret(cooker_.cook((*this)[v][u])*(c*d)); - if(e>=epsilon)ret+=cooker_.cook((*this)[v][u+1])*e; - if(f>=epsilon)ret+=cooker_.cook((*this)[v+1][u])*f; - if(g>=epsilon)ret+=cooker_.cook((*this)[v+1][u+1])*g; - - return cooker_.uncook(ret); - } - - //! Cubic sample - value_type cubic_sample(float x, float y)const - { - #if 0 - #define P(x) (((x)>=0)?((x)*(x)*(x)):0.0f) - #define R(x) ( P(x+2) - 4.0f*P(x+1) + 6.0f*P(x) - 4.0f*P(x-1) )*(1.0f/6.0f) - #define F(i,j) (cooker_.cook((*this)[max(min(j+v,h_-1),0)][max(min(i+u,w_-1),0)])*(R((i)-a)*R(b-(j)))) - #define Z(i,j) ret+=F(i,j) - #define X(i,j) // placeholder... To make box more symmetric - - int u(floor_to_int(x)), v(floor_to_int(y)); - float a, b; - - // Clamp X - if(x<0.0f)u=0,a=0.0f; - else if(u>w_-1)u=w_-1,a=0.0f; - else a=x-u; - - // Clamp Y - if(y<0.0f)v=0,b=0.0f; - else if(v>h_-1)v=h_-1,b=0.0f; - else b=y-v; - - // Interpolate - accumulator_type ret(F(0,0)); - Z(-1,-1); Z(-1, 0); Z(-1, 1); Z(-1, 2); - Z( 0,-1); X( 0, 0); Z( 0, 1); Z( 0, 2); - Z( 1,-1); Z( 1, 0); Z( 1, 1); Z( 1, 2); - Z( 2,-1); Z( 2, 0); Z( 2, 1); Z( 2, 2); - - return cooker_.uncook(ret); - - #undef X - #undef Z - #undef F - #undef P - #undef R - #else - - #define f(j,i) (cooker_.cook((*this)[j][i])) - //Using catmull rom interpolation because it doesn't blur at all - //bezier curve with intermediate ctrl pts: 0.5/3(p(i+1) - p(i-1)) and similar - accumulator_type xfa [4]; - - //precalculate indices (all clamped) and offset - const int xi = x > 0 ? (x < w_ ? (int)floor(x) : w_-1) : 0; - const int xa[] = {std::max(0,xi-1),xi,std::min(w_-1,xi+1),std::min(w_-1,xi+2)}; - - const int yi = y > 0 ? (y < h_ ? (int)floor(y) : h_-1) : 0; - const int ya[] = {std::max(0,yi-1),yi,std::min(h_-1,yi+1),std::min(h_-1,yi+2)}; - - const float xf = x-xi; - const float yf = y-yi; - - //figure polynomials for each point - const float txf[] = - { - 0.5*xf*(xf*(xf*(-1) + 2) - 1), //-t + 2t^2 -t^3 - 0.5*(xf*(xf*(3*xf - 5)) + 2), //2 - 5t^2 + 3t^3 - 0.5*xf*(xf*(-3*xf + 4) + 1), //t + 4t^2 - 3t^3 - 0.5*xf*xf*(xf-1) //-t^2 + t^3 - }; - - const float tyf[] = - { - 0.5*yf*(yf*(yf*(-1) + 2) - 1), //-t + 2t^2 -t^3 - 0.5*(yf*(yf*(3*yf - 5)) + 2), //2 - 5t^2 + 3t^3 - 0.5*yf*(yf*(-3*yf + 4) + 1), //t + 4t^2 - 3t^3 - 0.5*yf*yf*(yf-1) //-t^2 + t^3 - }; - - //evaluate polynomial for each row - for(int i = 0; i < 4; ++i) - { - xfa[i] = f(ya[i],xa[0])*txf[0] + f(ya[i],xa[1])*txf[1] + f(ya[i],xa[2])*txf[2] + f(ya[i],xa[3])*txf[3]; - } - - //return the cumulative column evaluation - return cooker_.uncook(xfa[0]*tyf[0] + xfa[1]*tyf[1] + xfa[2]*tyf[2] + xfa[3]*tyf[3]); -#undef f -#endif - } - - value_type sample_rect(float x0,float y0,float x1,float y1) const - { - const surface &s = *this; - - //assumes it's clamped to the boundary of the image - //force min max relationship for x0,x1 and y0,y1 - if(x0 > x1) std::swap(x0,x1); - if(y0 > y1) std::swap(y0,y1); - - //local variable madness - //all things that want to inter-operate should provide a default value constructor for = 0 - accumulator_type acum = 0; - int xi=0,yi=0; - - int xib=(int)floor(x0), - xie=(int)floor(x1); - - int yib=(int)floor(y0), - yie=(int)floor(y1); - - //the weight for the pixel should remain the same... - float weight = (y1-y0)*(x1-x0); - assert(weight != 0); - - float ylast = y0, xlastb = x0; - const_pen pen_ = s.get_pen(xib,yib); - - for(yi = yib; yi < yie; ylast = ++yi, pen_.inc_y()) - { - const float yweight = yi+1 - ylast; - - float xlast = xlastb; - for(xi = xib; xi < xie; xlast = ++xi, pen_.inc_x()) - { - const float w = yweight*(xi+1 - xlast); - acum += cooker_.cook(pen_.get_value())*w; - } - - //post... with next being fractional... - const float w = yweight*(x1 - xlast); - acum += cooker_.cook(pen_.get_value())*w; - - pen_.dec_x(xie-xib); - } - - //post in y direction... must have all x... - { - const float yweight = y1 - ylast; - - float xlast = xlastb; - for(xi = xib; xi < xie; xlast = ++xi) - { - const float w = yweight*(xi+1 - xlast); - - acum += cooker_.cook(pen_.get_value())*w; - } - - //post... with next being fractional... - const float w = yweight*(x1 - xlast); - acum += cooker_.cook(pen_.get_value())*w; - } - - acum *= 1/weight; - return cooker_.uncook(acum); - } - - value_type sample_rect_clip(float x0,float y0,float x1,float y1) const - { - const surface &s = *this; - - //assumes it's clamped to the boundary of the image - //force min max relationship for x0,x1 and y0,y1 - if(x0 > x1) std::swap(x0,x1); - if(y0 > y1) std::swap(y0,y1); - - //local variable madness - //all things that want to inter-operate should provide a default value constructor for = 0 - accumulator_type acum = 0; - int xi=0,yi=0; - - int xib=(int)floor(x0), - xie=(int)floor(x1); - - int yib=(int)floor(y0), - yie=(int)floor(y1); - - //the weight for the pixel should remain the same... - float weight = (y1-y0)*(x1-x0); - - assert(weight != 0); - - //clip to the input region - if(x0 >= s.get_w() || x1 <= 0) return acum; - if(y0 >= s.get_h() || y1 <= 0) return acum; - - if(x0 < 0) { x0 = 0; xib = 0; } - if(x1 >= s.get_w()) - { - x1 = s.get_w(); //want to be just below the last pixel... - xie = s.get_w()-1; - } - - if(y0 < 0) { y0 = 0; yib = 0; } - if(y1 >= s.get_h()) - { - y1 = s.get_h(); //want to be just below the last pixel... - yie = s.get_h()-1; - } - - float ylast = y0, xlastb = x0; - const_pen pen = s.get_pen(xib,yib); - - for(yi = yib; yi < yie; ylast = ++yi, pen.inc_y()) - { - const float yweight = yi+1 - ylast; - - float xlast = xlastb; - for(xi = xib; xi < xie; xlast = ++xi, pen.inc_x()) - { - const float w = yweight*(xi+1 - xlast); - acum += cooker_.cook(pen.get_value())*w; - } - - //post... with next being fractional... - const float w = yweight*(x1 - xlast); - acum += cooker_.cook(pen.get_value())*w; - - pen.dec_x(xie-xib); - } - - //post in y direction... must have all x... - { - const float yweight = y1 - ylast; - - float xlast = xlastb; - for(xi = xib; xi < xie; xlast = ++xi) - { - const float w = yweight*(xi+1 - xlast); - - acum += cooker_.cook(pen.get_value())*w; - } - - //post... with next being fractional... - const float w = yweight*(x1 - xlast); - acum += cooker_.cook(pen.get_value())*w; - } - - acum *= 1/weight; - return cooker_.uncook(acum); - } -}; - -_ETL_END_NAMESPACE - -/* === T Y P E D E F S ===================================================== */ - - -/* === E N D =============================================================== */ - -#endif