diff options
Diffstat (limited to 'source/blender/freestyle/intern/stroke/Canvas.cpp')
-rw-r--r-- | source/blender/freestyle/intern/stroke/Canvas.cpp | 718 |
1 files changed, 367 insertions, 351 deletions
diff --git a/source/blender/freestyle/intern/stroke/Canvas.cpp b/source/blender/freestyle/intern/stroke/Canvas.cpp index f2cfe6a855f..a51c138f64e 100644 --- a/source/blender/freestyle/intern/stroke/Canvas.cpp +++ b/source/blender/freestyle/intern/stroke/Canvas.cpp @@ -1,455 +1,471 @@ - -// -// 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 "StrokeRenderer.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/stroke/Canvas.cpp + * \ingroup freestyle + * \brief Class to define a canvas designed to draw style modules + * \author Stephane Grabli + * \date 20/10/2002 + */ + +#include <sstream> #include <vector> -#include "../system/FreestyleConfig.h" -#include "../system/TimeStamp.h" -#include "../system/PseudoNoise.h" + #include "Canvas.h" +#include "StrokeRenderer.h" +#include "StyleModule.h" + #include "../image/Image.h" #include "../image/GaussianFilter.h" #include "../image/ImagePyramid.h" + +#include "../system/FreestyleConfig.h" +#include "../system/TimeStamp.h" +#include "../system/PseudoNoise.h" + #include "../view_map/SteerableViewMap.h" -#include "StyleModule.h" //soc #include <qimage.h> //soc #include <QString> -#include <sstream> extern "C" { -#include "IMB_imbuf.h" -#include "IMB_imbuf_types.h" +# include "IMB_imbuf.h" +# include "IMB_imbuf_types.h" } using namespace std; LIB_STROKE_EXPORT -Canvas * Canvas::_pInstance = 0; +Canvas *Canvas::_pInstance = 0; LIB_STROKE_EXPORT -const char * Canvas::_MapsPath = 0; - -using namespace std; +const char *Canvas::_MapsPath = 0; Canvas::Canvas() { - _SelectedFEdge = 0; - _pInstance = this; - PseudoNoise::init(42); - _Renderer = 0; - _current_sm = NULL; - _steerableViewMap = new SteerableViewMap(NB_STEERABLE_VIEWMAP-1); - _basic = false; + _SelectedFEdge = 0; + _pInstance = this; + PseudoNoise::init(42); + _Renderer = 0; + _current_sm = NULL; + _steerableViewMap = new SteerableViewMap(NB_STEERABLE_VIEWMAP - 1); + _basic = false; } Canvas::Canvas(const Canvas& iBrother) { - _SelectedFEdge = iBrother._SelectedFEdge; - _pInstance = this; - PseudoNoise::init(42); - _Renderer = iBrother._Renderer; - _current_sm = iBrother._current_sm; - _steerableViewMap = new SteerableViewMap(*(iBrother._steerableViewMap)); - _basic = iBrother._basic; + _SelectedFEdge = iBrother._SelectedFEdge; + _pInstance = this; + PseudoNoise::init(42); + _Renderer = iBrother._Renderer; + _current_sm = iBrother._current_sm; + _steerableViewMap = new SteerableViewMap(*(iBrother._steerableViewMap)); + _basic = iBrother._basic; } Canvas::~Canvas() { - _pInstance = 0; - - Clear(); - if(_Renderer) - { - delete _Renderer; - _Renderer = 0; - } - // FIXME: think about an easy control - // for the maps memory management... - if(!_maps.empty()){ - for(mapsMap::iterator m=_maps.begin(), mend=_maps.end(); - m!=mend; - ++m){ - delete ((*m).second); - } - _maps.clear(); - } - if(_steerableViewMap) - delete _steerableViewMap; + _pInstance = 0; + + Clear(); + if (_Renderer) { + delete _Renderer; + _Renderer = 0; + } + // FIXME: think about an easy control for the maps memory management... + if (!_maps.empty()) { + for (mapsMap::iterator m = _maps.begin(), mend = _maps.end(); m != mend; ++m) { + delete ((*m).second); + } + _maps.clear(); + } + if (_steerableViewMap) + delete _steerableViewMap; } void Canvas::preDraw() {} void Canvas::Draw() { - if(_StyleModules.empty()) - return; - preDraw(); - TimeStamp *timestamp = TimeStamp::instance(); + if (_StyleModules.empty()) + return; + preDraw(); + TimeStamp *timestamp = TimeStamp::instance(); - for(unsigned i = 0; i < _StyleModules.size(); i++) { - _current_sm = _StyleModules[i]; + for (unsigned int i = 0; i < _StyleModules.size(); ++i) { + _current_sm = _StyleModules[i]; - if (i < _Layers.size() && _Layers[i]) - delete _Layers[i]; + if (i < _Layers.size() && _Layers[i]) + delete _Layers[i]; - _Layers[i] = _StyleModules[i]->execute(); - if (!_Layers[i]) - continue; + _Layers[i] = _StyleModules[i]->execute(); + if (!_Layers[i]) + continue; - stroke_count += _Layers[i]->strokes_size(); + stroke_count += _Layers[i]->strokes_size(); - timestamp->increment(); - } - postDraw(); + timestamp->increment(); + } + postDraw(); } void Canvas::postDraw() { - update(); + update(); } void Canvas::Clear() { - if(!_Layers.empty()) { - for (deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end(); - sl != slend; - ++sl) - if (*sl) - delete (*sl); - _Layers.clear(); - } - - if(!_StyleModules.empty()) { - for (deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end(); - s != send; - ++s) - if (*s) - delete (*s); - _StyleModules.clear(); - } - if(_steerableViewMap) - _steerableViewMap->Reset(); + if (!_Layers.empty()) { + for (deque<StrokeLayer*>::iterator sl = _Layers.begin(), slend = _Layers.end(); sl != slend; ++sl) { + if (*sl) + delete (*sl); + } + _Layers.clear(); + } + + if (!_StyleModules.empty()) { + for (deque<StyleModule*>::iterator s = _StyleModules.begin(), send = _StyleModules.end(); s != send; ++s) { + if (*s) + delete (*s); + } + _StyleModules.clear(); + } + if (_steerableViewMap) + _steerableViewMap->Reset(); stroke_count = 0; } void Canvas::Erase() { - if(!_Layers.empty()) - { - for (deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end(); - sl != slend; - ++sl) - if (*sl) - (*sl)->clear(); - } - if(_steerableViewMap) - _steerableViewMap->Reset(); - update(); - -stroke_count = 0; + if (!_Layers.empty()) { + for (deque<StrokeLayer*>::iterator sl = _Layers.begin(), slend = _Layers.end(); sl != slend; ++sl) { + if (*sl) + (*sl)->clear(); + } + } + if (_steerableViewMap) + _steerableViewMap->Reset(); + update(); + + stroke_count = 0; } -void Canvas::PushBackStyleModule(StyleModule *iStyleModule) { - StrokeLayer* layer = new StrokeLayer(); - _StyleModules.push_back(iStyleModule); - _Layers.push_back(layer); +void Canvas::PushBackStyleModule(StyleModule *iStyleModule) +{ + StrokeLayer* layer = new StrokeLayer(); + _StyleModules.push_back(iStyleModule); + _Layers.push_back(layer); } -void Canvas::InsertStyleModule(unsigned index, StyleModule *iStyleModule) { - unsigned size = _StyleModules.size(); - StrokeLayer* layer = new StrokeLayer(); - if((_StyleModules.empty()) || (index == size)) { - _StyleModules.push_back(iStyleModule); - _Layers.push_back(layer); - return; - } +void Canvas::InsertStyleModule(unsigned index, StyleModule *iStyleModule) +{ + unsigned size = _StyleModules.size(); + StrokeLayer *layer = new StrokeLayer(); + if ((_StyleModules.empty()) || (index == size)) { + _StyleModules.push_back(iStyleModule); + _Layers.push_back(layer); + return; + } _StyleModules.insert(_StyleModules.begin() + index, iStyleModule); - _Layers.insert(_Layers.begin()+index, layer); + _Layers.insert(_Layers.begin() + index, layer); } void Canvas::RemoveStyleModule(unsigned index) { - unsigned i=0; - if (!_StyleModules.empty()) - { - for(deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end(); - s!=send; - ++s) - { - if(i == index) - { - // remove shader - if (*s) - delete *s; - _StyleModules.erase(s); - break; - } - ++i; + unsigned int i = 0; + if (!_StyleModules.empty()) { + for (deque<StyleModule*>::iterator s = _StyleModules.begin(), send = _StyleModules.end(); + s != send; + ++s, ++i) + { + if (i == index) { + // remove shader + if (*s) + delete *s; + _StyleModules.erase(s); + break; + } + } + } + + if (!_Layers.empty()) { + i = 0; + for (deque<StrokeLayer*>::iterator sl = _Layers.begin(), slend = _Layers.end(); + sl != slend; + ++sl, ++i) + { + if (i == index) { + // remove layer + if (*sl) + delete *sl; + _Layers.erase(sl); + break; + } + } } - } - i=0; - if(!_Layers.empty()) - { - for(deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end(); - sl!=slend; - ++sl) - { - if(i == index) - { - // remove layer - if (*sl) - delete *sl; - _Layers.erase(sl); - break; - } - ++i; - } - } } void Canvas::SwapStyleModules(unsigned i1, unsigned i2) { - StyleModule* tmp; - tmp = _StyleModules[i1]; - _StyleModules[i1] = _StyleModules[i2]; - _StyleModules[i2] = tmp; - - StrokeLayer* tmp2; - tmp2 = _Layers[i1]; - _Layers[i1] = _Layers[i2]; - _Layers[i2] = tmp2; + StyleModule *tmp; + tmp = _StyleModules[i1]; + _StyleModules[i1] = _StyleModules[i2]; + _StyleModules[i2] = tmp; + + StrokeLayer *tmp2; + tmp2 = _Layers[i1]; + _Layers[i1] = _Layers[i2]; + _Layers[i2] = tmp2; } void Canvas::ReplaceStyleModule(unsigned index, StyleModule *iStyleModule) { - unsigned i=0; - for(deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end(); - s != send; - ++s) - { - if(i == index) - { - if (*s) - delete *s; - *s = iStyleModule; - break; + unsigned i = 0; + for (deque<StyleModule*>::iterator s = _StyleModules.begin(), send = _StyleModules.end(); s != send; ++s, ++i) { + if (i == index) { + if (*s) + delete *s; + *s = iStyleModule; + break; + } } - ++i; - } } -void Canvas::setVisible(unsigned index, bool iVisible) { - _StyleModules[index]->setDisplayed(iVisible); +void Canvas::setVisible(unsigned index, bool iVisible) +{ + _StyleModules[index]->setDisplayed(iVisible); } - + void Canvas::setModified(unsigned index, bool iMod) { - _StyleModules[index]->setModified(iMod); + _StyleModules[index]->setModified(iMod); } -void Canvas::resetModified(bool iMod/* =false */) +void Canvas::resetModified(bool iMod/* = false */) { - unsigned size = _StyleModules.size(); - for(unsigned i = 0; i < size; ++i) - setModified(i,iMod); + unsigned int size = _StyleModules.size(); + for (unsigned int i = 0; i < size; ++i) + setModified(i, iMod); } -void Canvas::causalStyleModules(vector<unsigned>& vec, unsigned index) { - unsigned size = _StyleModules.size(); +void Canvas::causalStyleModules(vector<unsigned>& vec, unsigned index) +{ + unsigned int size = _StyleModules.size(); - for(unsigned i = index; i < size; ++i) - if (_StyleModules[i]->getCausal()) - vec.push_back(i); + for (unsigned int i = index; i < size; ++i) { + if (_StyleModules[i]->getCausal()) + vec.push_back(i); + } } void Canvas::Render(const StrokeRenderer *iRenderer) { - for (unsigned i = 0; i < _StyleModules.size(); i++) { - if(!_StyleModules[i]->getDisplayed() || !_Layers[i]) - continue; - _Layers[i]->Render(iRenderer); - } + for (unsigned int i = 0; i < _StyleModules.size(); ++i) { + if (!_StyleModules[i]->getDisplayed() || !_Layers[i]) + continue; + _Layers[i]->Render(iRenderer); + } } void Canvas::RenderBasic(const StrokeRenderer *iRenderer) - { - for (unsigned i = 0; i < _StyleModules.size(); i++) { - if(!_StyleModules[i]->getDisplayed() || !_Layers[i]) - continue; - _Layers[i]->RenderBasic(iRenderer); - } + for (unsigned int i = 0; i < _StyleModules.size(); ++i) { + if (!_StyleModules[i]->getDisplayed() || !_Layers[i]) + continue; + _Layers[i]->RenderBasic(iRenderer); + } } -void Canvas::loadMap(const char *iFileName, const char *iMapName, unsigned int iNbLevels, float iSigma){ - // check whether this map was already loaded: - if(!_maps.empty()){ - mapsMap::iterator m = _maps.find(iMapName); - if(m!=_maps.end()){ - // lazy check for size changes - ImagePyramid * pyramid = (*m).second; - if((pyramid->width() != width()) || (pyramid->height() != height())){ - delete pyramid; - }else{ - return; - } - } - } - string filePath; - if(_MapsPath){ - filePath = _MapsPath; - filePath += iFileName; - }else{ - filePath = iFileName; - } - - //soc - // QImage *qimg; - // QImage newMap(filePath.c_str()); - // if(newMap.isNull()){ - // cout << "Could not load image file " << filePath << endl; - // return; - // } - // qimg = &newMap; +void Canvas::loadMap(const char *iFileName, const char *iMapName, unsigned int iNbLevels, float iSigma) +{ + // check whether this map was already loaded: + if (!_maps.empty()) { + mapsMap::iterator m = _maps.find(iMapName); + if (m != _maps.end()) { + // lazy check for size changes + ImagePyramid * pyramid = (*m).second; + if ((pyramid->width() != width()) || (pyramid->height() != height())) { + delete pyramid; + } + else { + return; + } + } + } + + string filePath; + if (_MapsPath) { + filePath = _MapsPath; + filePath += iFileName; + } + else { + filePath = iFileName; + } + +#if 0 //soc + QImage *qimg; + QImage newMap(filePath.c_str()); + if (newMap.isNull()) { + cout << "Could not load image file " << filePath << endl; + return; + } + qimg = &newMap; +#endif /* OCIO_TODO: support different input color space */ - ImBuf *qimg = IMB_loadiffname(filePath.c_str(), 0, NULL); - if( qimg == 0 ){ + ImBuf *qimg = IMB_loadiffname(filePath.c_str(), 0, NULL); + if (qimg == 0) { cout << "Could not load image file " << filePath << endl; - return; + return; } - // soc - //resize - // QImage scaledImg; - // if((newMap.width()!=width()) || (newMap.height()!=height())){ - // scaledImg = newMap.scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - // qimg = &scaledImg; - // } +#if 0 // soc + // resize + QImage scaledImg; + if ((newMap.width() != width()) || (newMap.height() != height())) { + scaledImg = newMap.scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + qimg = &scaledImg; + } +#endif ImBuf *scaledImg; - if( ( qimg->x != width() ) || ( qimg->y != height() ) ){ - scaledImg = IMB_dupImBuf(qimg); - IMB_scaleImBuf(scaledImg, width(), height()); - } - - - // deal with color image - // if(newMap->depth() != 8){ - // int w = newMap->width(); - // int h = newMap->height(); - // QImage *tmp = new QImage(w, h, 8); - // for(unsigned y=0;y<h;++y){ - // for(unsigned x=0;x<w;++x){ - // int c = qGray(newMap->pixel(x,y)); - // tmp->setPixel(x,y,c); - // } - // } - // delete newMap; - // newMap = tmp; - // } - - int x,y; - int w = qimg->x; - int h = qimg->y; -int rowbytes = w*4; - GrayImage tmp(w,h); - char *pix; - - for(y=0; y<h;++y){ - for(x=0;x<w;++x){ - pix = (char*)qimg->rect + y*rowbytes + x*4; - float c = (pix[0]*11 + pix[1]*16 + pix[2]*5)/32; - tmp.setPixel(x,y,c); - } - } - - // GrayImage blur(w,h); - // GaussianFilter gf(4.f); - // //int bound = gf.getBound(); - // for(y=0; y<h;++y){ - // for(x=0;x<w;++x){ - // int c = gf.getSmoothedPixel<GrayImage>(&tmp, x,y); - // blur.setPixel(x,y,c); - // } - // } - - GaussianPyramid *pyramid = new GaussianPyramid(tmp, iNbLevels, iSigma); - int ow = pyramid->width(0); - int oh = pyramid->height(0); - string base(iMapName); //soc - for(int i=0; i<pyramid->getNumberOfLevels(); ++i){ - // save each image: - // w = pyramid.width(i); - // h = pyramid.height(i); - - //soc QImage qtmp(ow, oh, QImage::Format_RGB32); - ImBuf *qtmp = IMB_allocImBuf(ow, oh, 32, IB_rect); - -//int k = (1<<i); - for(y=0;y<oh;++y){ - for(x=0;x<ow;++x){ - int c = pyramid->pixel(x,y,i);//255*pyramid->pixel(x,y,i); - //soc qtmp.setPixel(x,y,qRgb(c,c,c)); - pix = (char*)qtmp->rect + y*rowbytes + x*4; - pix[0] = pix [1] = pix[2] = c; - } - } - //soc qtmp.save(base+QString::number(i)+".bmp", "BMP"); - stringstream filename; - filename << base; - filename << i << ".bmp"; - qtmp->ftype= BMP; - IMB_saveiff(qtmp, const_cast<char *>(filename.str().c_str()), 0); - - } - // QImage *qtmp = new QImage(w, h, 32); - // for(y=0;y<h;++y){ - // for(x=0;x<w;++x){ - // int c = (int)blur.pixel(x,y); - // qtmp->setPixel(x,y,qRgb(c,c,c)); - // } - // } - // delete newMap; - // newMap = qtmp; - // - _maps[iMapName] = pyramid; - // newMap->save("toto.bmp", "BMP"); + if ((qimg->x != width()) || (qimg->y != height())) { + scaledImg = IMB_dupImBuf(qimg); + IMB_scaleImBuf(scaledImg, width(), height()); + } + + + // deal with color image +#if 0 + if (newMap->depth() != 8) { + int w = newMap->width(); + int h = newMap->height(); + QImage *tmp = new QImage(w, h, 8); + for (unsigned int y = 0; y < h; ++y) { + for (unsigned int x = 0; x < w; ++x) { + int c = qGray(newMap->pixel(x, y)); + tmp->setPixel(x, y, c); + } + } + delete newMap; + newMap = tmp; + } +#endif + + int x, y; + int w = qimg->x; + int h = qimg->y; + int rowbytes = w * 4; + GrayImage tmp(w, h); + char *pix; + + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { + pix = (char*)qimg->rect + y * rowbytes + x * 4; + float c = (pix[0] * 11 + pix[1] * 16 + pix[2] * 5) / 32; + tmp.setPixel(x, y, c); + } + } + +#if 0 + GrayImage blur(w, h); + GaussianFilter gf(4.0f); + //int bound = gf.getBound(); + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { + int c = gf.getSmoothedPixel<GrayImage>(&tmp, x, y); + blur.setPixel(x, y, c); + } + } +#endif + + GaussianPyramid *pyramid = new GaussianPyramid(tmp, iNbLevels, iSigma); + int ow = pyramid->width(0); + int oh = pyramid->height(0); + string base(iMapName); //soc + for (int i = 0; i < pyramid->getNumberOfLevels(); ++i) { + // save each image: +#if 0 + w = pyramid.width(i); + h = pyramid.height(i); +#endif + + //soc QImage qtmp(ow, oh, QImage::Format_RGB32); + ImBuf *qtmp = IMB_allocImBuf(ow, oh, 32, IB_rect); + + //int k = (1 << i); + for (y = 0; y < oh; ++y) { + for (x = 0; x < ow; ++x) { + int c = pyramid->pixel(x, y, i); // 255 * pyramid->pixel(x, y, i); + //soc qtmp.setPixel(x, y, qRgb(c, c, c)); + pix = (char*)qtmp->rect + y * rowbytes + x * 4; + pix[0] = pix [1] = pix[2] = c; + } + } + //soc qtmp.save(base + QString::number(i) + ".bmp", "BMP"); + stringstream filename; + filename << base; + filename << i << ".bmp"; + qtmp->ftype = BMP; + IMB_saveiff(qtmp, const_cast<char *>(filename.str().c_str()), 0); + } + +#if 0 + QImage *qtmp = new QImage(w, h, 32); + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { + int c = (int)blur.pixel(x, y); + qtmp->setPixel(x, y, qRgb(c, c, c)); + } + } + delete newMap; + newMap = qtmp; +#endif + + _maps[iMapName] = pyramid; + //newMap->save("toto.bmp", "BMP"); } -float Canvas::readMapPixel(const char *iMapName, int level, int x, int y){ - if(_maps.empty()){ - cout << "readMapPixel warning: no map was loaded "<< endl; - return -1; - } - mapsMap::iterator m = _maps.find(iMapName); - if(m==_maps.end()){ - cout << "readMapPixel warning: no map was loaded with the name " << iMapName << endl; - return -1; - } - ImagePyramid *pyramid = (*m).second; - if((x<0) || (x>=pyramid->width()) || (y<0) || (y>=pyramid->height())) - return 0; - - return pyramid->pixel(x,height()-1-y,level); +float Canvas::readMapPixel(const char *iMapName, int level, int x, int y) +{ + if (_maps.empty()) { + cout << "readMapPixel warning: no map was loaded "<< endl; + return -1; + } + mapsMap::iterator m = _maps.find(iMapName); + if (m == _maps.end()) { + cout << "readMapPixel warning: no map was loaded with the name " << iMapName << endl; + return -1; + } + ImagePyramid *pyramid = (*m).second; + if ((x < 0) || (x >= pyramid->width()) || (y < 0) || (y >= pyramid->height())) + return 0; + + return pyramid->pixel(x, height() - 1 - y, level); } |