diff options
Diffstat (limited to 'source/blender/freestyle/intern/image')
-rwxr-xr-x | source/blender/freestyle/intern/image/GaussianFilter.cpp | 96 | ||||
-rwxr-xr-x | source/blender/freestyle/intern/image/GaussianFilter.h | 144 | ||||
-rwxr-xr-x | source/blender/freestyle/intern/image/Image.h | 389 | ||||
-rwxr-xr-x | source/blender/freestyle/intern/image/ImagePyramid.cpp | 166 | ||||
-rwxr-xr-x | source/blender/freestyle/intern/image/ImagePyramid.h | 92 | ||||
-rwxr-xr-x | source/blender/freestyle/intern/image/image.pro | 66 | ||||
-rwxr-xr-x | source/blender/freestyle/intern/image/src.pri | 13 |
7 files changed, 966 insertions, 0 deletions
diff --git a/source/blender/freestyle/intern/image/GaussianFilter.cpp b/source/blender/freestyle/intern/image/GaussianFilter.cpp new file mode 100755 index 00000000000..97c2aedc62e --- /dev/null +++ b/source/blender/freestyle/intern/image/GaussianFilter.cpp @@ -0,0 +1,96 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// This program 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 program 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "GaussianFilter.h" +#include <stdlib.h> + +GaussianFilter::GaussianFilter(float iSigma ) +{ + _sigma = iSigma; + _mask = 0; + computeMask(); +} + +GaussianFilter::GaussianFilter(const GaussianFilter& iBrother) +{ + _sigma = iBrother._sigma; + _maskSize = iBrother._maskSize; + _bound = iBrother._bound; + _storedMaskSize = iBrother._storedMaskSize; + _mask = new float[_maskSize*_maskSize]; + memcpy(_mask, iBrother._mask, _maskSize*_maskSize*sizeof(float)); +} + + +GaussianFilter& GaussianFilter::operator= (const GaussianFilter& iBrother) +{ + _sigma = iBrother._sigma; + _maskSize = iBrother._maskSize; + _bound = iBrother._bound; + _storedMaskSize = iBrother._storedMaskSize; + _mask = new float[_storedMaskSize*_storedMaskSize]; + memcpy(_mask, iBrother._mask, _storedMaskSize*_storedMaskSize*sizeof(float)); + return *this; +} + + +GaussianFilter::~GaussianFilter() +{ + if(0!=_mask) + { + delete [] _mask; + } +} + +int GaussianFilter::computeMaskSize(float sigma) +{ + int maskSize = (int)floor(4*sigma)+1; + if(0 == maskSize%2) + ++maskSize; + + return maskSize; +} + +void GaussianFilter::SetSigma(float sigma) +{ + _sigma = sigma; + computeMask(); +} + +void GaussianFilter::computeMask() +{ + if(0 != _mask){ + delete [] _mask; + } + + _maskSize = computeMaskSize(_sigma); + _storedMaskSize = (_maskSize+1)>>1; + _bound = _storedMaskSize-1; + + float norm = _sigma*_sigma*2.f*M_PI; + float invNorm = 1.0/norm; + _mask = new float[_storedMaskSize*_storedMaskSize*sizeof(float)]; + for(int i=0; i<_storedMaskSize; ++i) + for(int j=0; j<_storedMaskSize; ++j) + _mask[i*_storedMaskSize+j] = invNorm*exp(-(i*i + j*j)/(2.0*_sigma*_sigma)); + //_mask[i*_storedMaskSize+j] = exp(-(i*i + j*j)/(2.0*_sigma*_sigma)); +} + diff --git a/source/blender/freestyle/intern/image/GaussianFilter.h b/source/blender/freestyle/intern/image/GaussianFilter.h new file mode 100755 index 00000000000..c75177541d3 --- /dev/null +++ b/source/blender/freestyle/intern/image/GaussianFilter.h @@ -0,0 +1,144 @@ +// +// Filename : Image.h +// Author(s) : Stephane Grabli +// Purpose : Class to perform gaussian filtering operations on an image +// Date of creation : 20/05/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// This program 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 program 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GAUSSIANFILTER_H +# define GAUSSIANFILTER_H + +#include "../system/FreestyleConfig.h" + +class LIB_IMAGE_EXPORT GaussianFilter{ +protected: + /* the mask is a symetrical 2d array (with respect + to the middle point). + Thus, M(i,j) = M(-i,j) = M(i,-j) = M(-i,-j). + For this reason, to represent a NxN array (N odd), we only store + a ((N+1)/2)x((N+1)/2) array. + */ + float _sigma; + float *_mask; + int _bound; + int _maskSize; // the real mask size (must be odd)(the size of the mask we store is ((_maskSize+1)/2)*((_maskSize+1)/2)) + int _storedMaskSize; //(_maskSize+1)/2) + +public: + GaussianFilter(float iSigma = 1.f) ; + GaussianFilter(const GaussianFilter&) ; + GaussianFilter& operator= (const GaussianFilter&) ; + virtual ~GaussianFilter() ; + + /*! Returns the value for pixel x,y of image "map" after a gaussian blur, + * made using the sigma value. + * The sigma value determines the mask size (~ 2 x sigma). + * \param map + * The image we wish to work on. The Map template must implement the + * foloowing methods: + * - float pixel(unsigned int x,unsigned int y) const; + * - unsigned width() const; + * - unsigned height() const; + * \param x + * The abscissa of the pixel where we want to evaluate the gaussian blur. + * \param y + * The ordinate of the pixel where we want to evaluate the gaussian blur. + * \param sigma + * The sigma value of the gaussian function. + */ + template<class Map> + float getSmoothedPixel(Map * map, int x, int y) ; + + /*! Compute the mask size and returns the REAL mask size ((2*_maskSize)-1) + * This method is provided for convenience. + */ + static int computeMaskSize(float sigma) ; + + /*! accessors */ + inline float sigma() const {return _sigma;} + inline int maskSize() const {return _maskSize;} + inline int getBound() {return _bound;} + + /*! modifiers */ + void SetSigma(float sigma) ; + // void SetMaskSize(int size) {_maskSize = size;_storedMaskSize=(_maskSize+1)>>1;} + + +protected: + void computeMask(); +}; + +/* + + ############################################# + ############################################# + ############################################# + ###### ###### + ###### I M P L E M E N T A T I O N ###### + ###### ###### + ############################################# + ############################################# + ############################################# + +*/ + + +#include <math.h> + +#ifdef __MACH__ +#define sqrtf(x) (sqrt(x)) +#endif + +template<class Map> +float GaussianFilter::getSmoothedPixel(Map * map, int x, int y) +{ + float sum = 0.f; + float L=0.f; + unsigned w=map->width(); + unsigned h=map->height(); + + // Current pixel is x,y + // Sum surrounding pixels L value: + for(int i=-_bound; i<=_bound; ++i) + { + if((y+i < 0) || (y+i >= h)) + continue; + for(int j=-_bound; j<=_bound; ++j) + { + if((x+j < 0) || (x+j >= w)) + continue; + + float tmpL = map->pixel(x+j,y+i); + float m = _mask[abs(i)*_storedMaskSize+abs(j)]; + L += m*tmpL; + sum += m; + } + } + //L /= sum; + return L; +} + + +#endif // GAUSSIANFILTER diff --git a/source/blender/freestyle/intern/image/Image.h b/source/blender/freestyle/intern/image/Image.h new file mode 100755 index 00000000000..83d6785e32f --- /dev/null +++ b/source/blender/freestyle/intern/image/Image.h @@ -0,0 +1,389 @@ +// +// Filename : Image.h +// Author(s) : Stephane Grabli +// Purpose : Class to encapsulate an array of RGB or Gray level values +// Date of creation : 20/05/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// This program 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 program 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef IMAGE_H +# define IMAGE_H + +# include <string> // for memcpy + +// +// Image base class, for all types of images +// +/////////////////////////////////////////////////////////////////////////////// + +/*! This class allows the storing of part of an image, + * while allowing a normal access to its pixel values. + * You can for example only a rectangle of sw*sh, whose + * lower-left corner is at (ox, oy), of an image of + * size w*h, and access these pixels using x,y coordinates + * specified in the whole image coordinate system. + */ +class Image +{ + public: + + /*! Default constructor */ + Image() { + _storedWidth = 0; + _storedHeight = 0; + _width = 0; + _height = 0; + _Ox = 0; + _Oy = 0; + } + + /*! Copy constructor */ + Image(const Image& brother) { + _storedWidth = brother._storedWidth; + _storedHeight = brother._storedHeight; + _width = brother._width; + _height = brother._height; + _Ox = brother._Ox; + _Oy = brother._Oy; + } + + /*! Builds an image from its width and height. + * The memory is allocated consequently. + */ + Image(unsigned w, unsigned h) { + _width = w; + _height = h; + _storedWidth = w; + _storedHeight = h; + _Ox = 0; + _Oy = 0; + } + + /*! Builds a partial-storing image. + * \param w + * The width of the complete image + * \param h + * The height of the complete image + * \param sw + * The width of the rectangle that will actually + * be stored. + * \param sh + * The height of the rectangle that will actually + * be stored. + * \param ox + * The x-abscissa of the origin of the rectangle that will actually + * be stored. + * \param oy + * The x-abscissa of the origin of the rectangle that will actually + * be stored. + */ + Image(unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy) { + _width = w; + _height = h; + _storedWidth = sw; + _storedHeight = sh; + _Ox = ox; + _Oy = oy; + } + + /*! Operator= */ + Image& operator=(const Image& brother) { + _width = brother._width; + _height = brother._height; + _storedWidth = brother._storedWidth; + _storedHeight = brother._storedHeight; + _Ox = brother._Ox; + _Oy = brother._Oy; + return* this; + } + + /*! Destructor */ + virtual ~Image() {} + + /*! Returns the width of the complete image */ + inline unsigned width() const { + return _width; + } + /*! Returns the height of the complete image */ + inline unsigned height() const { + return _height; + } + + /*! Returns the grey value for pixel x,y */ + virtual float pixel(unsigned x, unsigned y) const = 0; + + /*! Sets the array. + * \param array + * The array containing the values we wish to store. + * Its size is sw*sh. + * \param width + * The width of the complete image + * \param height + * The height of the complete image + * \param sw + * The width of the rectangle that will actually + * be stored. + * \param sh + * The height of the rectangle that will actually + * be stored. + * \param ox + * The x-abscissa of the origin of the rectangle that will actually + * be stored. + * \param oy + * The x-abscissa of the origin of the rectangle that will actually + * be stored. + * \param copy + * If true, the array is copied, otherwise the pointer is + * copied + */ + virtual void setArray(float* array, unsigned width, unsigned height, unsigned sw, unsigned sh, unsigned x, unsigned y, bool copy = true) = 0; + + /*! Returns the array containing the pixels values. + * Its size is sw*sh, i.e. potentially a smaller + * rectangular part of the complete image. + */ + virtual float * getArray() = 0; + + protected: + + unsigned _width; + unsigned _height; + unsigned _storedWidth; + unsigned _storedHeight; + unsigned _Ox; // origin of the stored part + unsigned _Oy; // origin of the stored part +}; + + +// +// RGBImage +// +/////////////////////////////////////////////////////////////////////////////// + +class RGBImage : public Image +{ + public: + + RGBImage() : Image() { + _rgb = 0; + } + + RGBImage(const RGBImage& brother) : Image(brother) { + _rgb = new float[3 * _storedWidth * _storedHeight]; + memcpy(_rgb, brother._rgb, 3 * _storedWidth * _storedHeight * sizeof(float)); + } + + RGBImage(unsigned w, unsigned h) : Image(w, h) { + _rgb = new float[3 * _width * _height]; + } + + RGBImage(float* rgb, unsigned w, unsigned h) : Image(w, h) { + _rgb = new float[3 * _width * _height]; + memcpy(_rgb, rgb, 3 * _width * _height * sizeof(float)); + } + + /*! Builds an RGB partial image from the useful part buffer. + * \param rgb + * The array of size 3*sw*sh containing the RGB values + * of the sw*sh pixels we need to stored. + * These sw*sh pixels constitute a rectangular part of + * a bigger RGB image containing w*h pixels. + * \param w + * The width of the complete image + * \param h + * The height of the complete image + * \param sw + * The width of the part of the image we want to store and work on + * \param sh + * The height of the part of the image we want to store and work on + */ + RGBImage(float* rgb, unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy) : Image(w, h, sw, sh, ox, oy) { + _rgb = new float[3 * _storedWidth * _storedHeight]; + memcpy(_rgb, rgb, 3 * _storedWidth * _storedHeight * sizeof(float)); + } + + RGBImage& operator=(const RGBImage& brother) { + dynamic_cast<Image&>(*this) = brother; + _rgb = new float[3 * _storedWidth * _storedHeight]; + memcpy(_rgb, brother._rgb, 3 * _storedWidth * _storedHeight * sizeof(float)); + return* this; + } + + virtual ~RGBImage() { + if(_rgb) + delete[] _rgb; + } + + inline float getR(unsigned x, unsigned y) const { + return _rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3]; + } + + inline float getG(unsigned x, unsigned y) const { + return _rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3 + 1]; + } + + inline float getB(unsigned x, unsigned y) const { + return _rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3 + 2]; + } + + virtual void setPixel(unsigned x, unsigned y, float r, float g, float b){ + float * tmp = &(_rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3]); + *tmp = r;++tmp; + *tmp = g;++tmp; + *tmp = b; + } + + virtual float pixel(unsigned x, unsigned y) const { + float res = 0; + float* tmp = &(_rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3]); + res += 11 * (*tmp++); + res += 16 * (*tmp++); + res += 5 * (*tmp); + return res / 32; + } + + /*! Sets the RGB array. + * copy + * If true, the array is copied, otherwise the pointer is + * copied + */ + virtual void setArray(float* rgb, unsigned width, unsigned height, unsigned sw, unsigned sh, unsigned x, unsigned y, bool copy = true) { + _width = width; + _height = height; + _storedWidth = sw; + _storedHeight = sh; + _Ox = x; + _Oy = y; + if(!copy) { + _rgb = rgb; + return; + } + + memcpy(_rgb, rgb, 3 * _storedWidth * _storedHeight* sizeof(float)); + } + + virtual float * getArray() {return _rgb;} + + protected: + + float* _rgb; +}; + + +// +// GrayImage +// +/////////////////////////////////////////////////////////////////////////////// + +class GrayImage : public Image +{ + public: + + GrayImage() : Image() { + _lvl = 0; + } + + GrayImage(const GrayImage& brother) : Image(brother) { + _lvl = new float[_storedWidth*_storedHeight]; + memcpy(_lvl, brother._lvl, _storedWidth*_storedHeight*sizeof(*_lvl)); + } + + /*! Builds an empty gray image */ + GrayImage(unsigned w, unsigned h) : Image(w, h) { + _lvl = new float[_width*_height]; + } + + GrayImage(float* lvl, unsigned w, unsigned h) : Image(w, h) { + _lvl = new float[_width*_height]; + memcpy(_lvl, lvl, _width*_height*sizeof(*_lvl)); + } + + /*! Builds a partial image from the useful part buffer. + * \param lvl + * The array of size sw*sh containing the gray values + * of the sw*sh pixels we need to stored. + * These sw*sh pixels constitute a rectangular part of + * a bigger gray image containing w*h pixels. + * \param w + * The width of the complete image + * \param h + * The height of the complete image + * \param sw + * The width of the part of the image we want to store and work on + * \param sh + * The height of the part of the image we want to store and work on + */ + GrayImage(float* lvl, unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy) : Image(w, h, sw, sh, ox, oy) { + _lvl = new float[_storedWidth*_storedHeight]; + memcpy(_lvl, lvl, _storedWidth*_storedHeight*sizeof(float)); + } + + GrayImage& operator=(const GrayImage& brother) { + dynamic_cast<Image&>(*this) = brother; + _lvl = new float[_storedWidth * _storedHeight]; + memcpy(_lvl, brother._lvl, _storedWidth * _storedHeight * sizeof(float)); + return *this; + } + + virtual ~GrayImage() { + if(_lvl) + delete[] _lvl; + } + + inline void setPixel(unsigned x, unsigned y, float v){ + _lvl[(y-_Oy) * _storedWidth+ (x-_Ox)] = v; + } + + inline float pixel(unsigned x, unsigned y) const { + return _lvl[(y-_Oy) * _storedWidth+ (x-_Ox)]; + } + + /*! Sets the array. + * copy + * If true, the array is copie, otherwise the pounsigneder is + * copied + */ + void setArray(float *lvl, unsigned width, unsigned height, unsigned sw, unsigned sh, unsigned x, unsigned y, bool copy = true) { + _width = width; + _height = height; + _storedWidth = sw; + _storedHeight = sh; + _Ox = x; + _Oy = y; + if(!copy) { + _lvl = lvl; + return; + } + + memcpy(_lvl, lvl, _storedWidth * _storedHeight * sizeof(float)); + } + /*! Returns the array containing the gray values. */ + virtual float * getArray() {return _lvl;} + + protected: + + float *_lvl; +}; + +#endif // IMAGE_H diff --git a/source/blender/freestyle/intern/image/ImagePyramid.cpp b/source/blender/freestyle/intern/image/ImagePyramid.cpp new file mode 100755 index 00000000000..45c02004d1c --- /dev/null +++ b/source/blender/freestyle/intern/image/ImagePyramid.cpp @@ -0,0 +1,166 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// This program 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 program 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// +#include "ImagePyramid.h" +#include "Image.h" +#include "GaussianFilter.h" +#include <iostream> + +using namespace std; + +//ImagePyramid::ImagePyramid(const GrayImage& level0, unsigned nbLevels){ +// //BuildPyramid(level0,nbLevels); +//} + +ImagePyramid::ImagePyramid(const ImagePyramid& iBrother){ + if(!_levels.empty()){ + for(vector<GrayImage*>::iterator im=_levels.begin(), imend=_levels.end(); + im!=imend; + ++im){ + _levels.push_back(new GrayImage(**im)); + } + } +} +ImagePyramid::~ImagePyramid(){ + if(!_levels.empty()){ + for(vector<GrayImage*>::iterator im=_levels.begin(), imend=_levels.end(); + im!=imend; + ++im){ + delete (*im); + } + _levels.clear(); + } +} + +GrayImage * ImagePyramid::getLevel(int l){ + return _levels[l]; +} + +float ImagePyramid::pixel(int x, int y, int level){ + GrayImage *img = _levels[level]; + if(0 == level){ + return img->pixel(x,y); + } + int i = 1<<level; + int sx = x>>level; + int sy = y>>level; + if(sx >= img->width()) + sx = img->width()-1; + if(sy >= img->height()) + sy = img->height()-1; + + // bilinear interpolation + float A = i*(sx+1)-x; + float B = x-i*sx; + float C = i*(sy+1)-y; + float D = y-i*sy; + + float P1(0), P2(0); + P1 = A*img->pixel(sx,sy); + if(sx < img->width()-1){ + if(x%i != 0) + P1 += B*img->pixel(sx+1,sy); + }else{ + P1 += B*img->pixel(sx,sy); + } + if(sy<img->height()-1){ + if(y%i != 0){ + P2 = A*img->pixel(sx,sy+1); + if(sx < img->width()-1){ + if(x%i != 0) + P2 += B*img->pixel(sx+1,sy+1); + }else{ + P2 += B*img->pixel(sx,sy+1); + } + } + }else{ + P2 = P1; + } + return (1.f/(float)(1<<2*level))*(C*P1 + D*P2); +} + +int ImagePyramid::width(int level){ + return _levels[level]->width(); +} + +int ImagePyramid::height(int level){ + return _levels[level]->height(); +} + +GaussianPyramid::GaussianPyramid(const GrayImage& level0, unsigned nbLevels, float iSigma) + : ImagePyramid() +{ + _sigma = iSigma; + BuildPyramid(level0,nbLevels); +} +GaussianPyramid::GaussianPyramid(GrayImage* level0, unsigned nbLevels, float iSigma) + : ImagePyramid() +{ + _sigma = iSigma; + BuildPyramid(level0,nbLevels); +} + +GaussianPyramid::GaussianPyramid(const GaussianPyramid& iBrother) +: ImagePyramid(iBrother){ + _sigma = iBrother._sigma; +} +void GaussianPyramid::BuildPyramid(const GrayImage& level0, unsigned nbLevels){ + GrayImage *pLevel = new GrayImage(level0); + BuildPyramid(pLevel, nbLevels); +} + +void GaussianPyramid::BuildPyramid(GrayImage* level0, unsigned nbLevels){ + GrayImage *pLevel = level0; + _levels.push_back(pLevel); + GaussianFilter gf(_sigma); + // build the nbLevels: + unsigned w = pLevel->width(); + unsigned h = pLevel->height(); + if(nbLevels!=0) + { + for(unsigned i=0; i<nbLevels; ++i){ + w = pLevel->width()>>1; + h = pLevel->height()>>1; + GrayImage *img = new GrayImage(w,h); + for(unsigned y=0; y<h; ++y){ + for(unsigned x=0; x<w; ++x){ + float v = gf.getSmoothedPixel<GrayImage>(pLevel, 2*x,2*y); + img->setPixel(x,y,v); + } + } + _levels.push_back(img); + pLevel = img; + } + }else{ + while((w>1) && (h>1)){ + w = pLevel->width()>>1; + h = pLevel->height()>>1; + GrayImage *img = new GrayImage(w,h); + for(unsigned y=0; y<h; ++y){ + for(unsigned x=0; x<w; ++x){ + float v = gf.getSmoothedPixel<GrayImage>(pLevel, 2*x,2*y); + img->setPixel(x,y,v); + } + } + _levels.push_back(img); + pLevel = img; + } + } +} diff --git a/source/blender/freestyle/intern/image/ImagePyramid.h b/source/blender/freestyle/intern/image/ImagePyramid.h new file mode 100755 index 00000000000..9e326757f02 --- /dev/null +++ b/source/blender/freestyle/intern/image/ImagePyramid.h @@ -0,0 +1,92 @@ +// +// Filename : ImagePyramid.h +// Author(s) : Stephane Grabli +// Purpose : Class to represent a pyramid of images +// Date of creation : 25/12/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// This program 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 program 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef IMAGEPYRAMID_H +# define IMAGEPYRAMID_H + +#include "../system/FreestyleConfig.h" +#include <vector> + +class GrayImage; +class LIB_IMAGE_EXPORT ImagePyramid{ +protected: + std::vector<GrayImage*> _levels; + +public: + ImagePyramid(){} + ImagePyramid(const ImagePyramid& iBrother); + //ImagePyramid(const GrayImage& level0, unsigned nbLevels); + virtual ~ImagePyramid(); + + /*! Builds the pyramid. + * must be overloaded by inherited classes. + * if nbLevels==0, the complete pyramid is built + */ + virtual void BuildPyramid(const GrayImage& level0, unsigned nbLevels) = 0; + + /*! Builds a pyramid without copying the base level */ + virtual void BuildPyramid(GrayImage* level0, unsigned nbLevels) = 0; + + virtual GrayImage * getLevel(int l); + /*! Returns the pixel x,y using bilinear interpolation. + * \param x + * the abscissa specified in the finest level coordinate system + * \param y + * the ordinate specified in the finest level coordinate system + * \param level + * the level from which we want the pixel to be evaluated + */ + virtual float pixel(int x, int y, int level=0); + /*! Returns the width of the level-th level image */ + virtual int width(int level=0); + /*! Returns the height of the level-th level image */ + virtual int height(int level=0); + /*! Returns the number of levels in the pyramid */ + inline int getNumberOfLevels() const { return _levels.size();} +}; + +class LIB_IMAGE_EXPORT GaussianPyramid : public ImagePyramid +{ +protected: + float _sigma; +public: + GaussianPyramid(float iSigma=1.f) : ImagePyramid() {_sigma=iSigma;} + GaussianPyramid(const GrayImage& level0, unsigned nbLevels, float iSigma=1.f); + GaussianPyramid(GrayImage* level0, unsigned nbLevels, float iSigma=1.f); + GaussianPyramid(const GaussianPyramid& iBrother); + virtual ~GaussianPyramid(){} + + virtual void BuildPyramid(const GrayImage& level0, unsigned nbLevels); + virtual void BuildPyramid(GrayImage* level0, unsigned nbLevels); + /* accessors */ + inline float getSigma() const {return _sigma;} + /* modifiers */ + +}; +#endif // IMAGEPYRAMID_H diff --git a/source/blender/freestyle/intern/image/image.pro b/source/blender/freestyle/intern/image/image.pro new file mode 100755 index 00000000000..133b6cf4f35 --- /dev/null +++ b/source/blender/freestyle/intern/image/image.pro @@ -0,0 +1,66 @@ +# This file should be viewed as a -*- mode: Makefile -*- + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# W A R N I N G ! ! ! # +# a u t h o r i z e d p e r s o n a l o n l y # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +include(../Config.pri) + +TEMPLATE = lib + +TARGET = $${LIB_IMAGE} +VERSION = $${APPVERSION} +TARGET_VERSION_EXT = $${APPVERSION_MAJ}.$${APPVERSION_MID} + +# +# CONFIG +# +####################################### + +CONFIG *= dll + +# +# DEFINES +# +####################################### + +win32:DEFINES *= MAKE_LIB_IMAGE_DLL + +# +# INCLUDE PATH +# +####################################### + +#INCLUDEPATH *= ../system + +# +# BUILD DIRECTORIES +# +####################################### + +BUILD_DIR = ../../build + +OBJECTS_DIR = $${BUILD_DIR}/$${REL_OBJECTS_DIR} +!win32:DESTDIR = $${BUILD_DIR}/$${REL_DESTDIR}/lib +win32:DESTDIR = $${BUILD_DIR}/$${REL_DESTDIR} + +# +# INSTALL +# +####################################### + +LIB_DIR = ../../lib +# install library +target.path = $$LIB_DIR +# "make install" configuration options +INSTALLS += target + +# +# SOURCES & HEADERS +# +####################################### + +!static { + include(src.pri) +} diff --git a/source/blender/freestyle/intern/image/src.pri b/source/blender/freestyle/intern/image/src.pri new file mode 100755 index 00000000000..c047929b49f --- /dev/null +++ b/source/blender/freestyle/intern/image/src.pri @@ -0,0 +1,13 @@ +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# W A R N I N G ! ! ! # +# a u t h o r i z e d p e r s o n a l o n l y # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +IMAGE_DIR = ../image + +SOURCES *= $${IMAGE_DIR}/GaussianFilter.cpp \ + $${IMAGE_DIR}/ImagePyramid.cpp + +HEADERS *= $${IMAGE_DIR}/Image.h \ + $${IMAGE_DIR}/GaussianFilter.h \ + $${IMAGE_DIR}/ImagePyramid.h |