/******************************************************************** ** Image Component Library (ICL) ** ** ** ** Copyright (C) 2006-2013 CITEC, University of Bielefeld ** ** Neuroinformatics Group ** ** Website: www.iclcv.org and ** ** http://opensource.cit-ec.de/projects/icl ** ** ** ** File : ICLFilter/src/ICLFilter/DitheringOp.cpp ** ** Module : ICLFilter ** ** Authors: Christof Elbrechter ** ** ** ** ** ** GNU LESSER GENERAL PUBLIC LICENSE ** ** This file may be used under the terms of the GNU Lesser General ** ** Public License version 3.0 as published by the ** ** ** ** Free Software Foundation and appearing in the file LICENSE.LGPL ** ** included in the packaging of this file. Please review the ** ** following information to ensure the license requirements will ** ** be met: http://www.gnu.org/licenses/lgpl-3.0.txt ** ** ** ** The development of this software was supported by the ** ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** ** Forschungsgemeinschaft (DFG) in the context of the German ** ** Excellence Initiative. ** ** ** ********************************************************************/ #include <ICLFilter/DitheringOp.h> #include <ICLCore/Img.h> namespace icl{ using namespace utils; using namespace core; namespace filter{ DitheringOp::DitheringOp (Algorithm a, int l){ setAlgorithm(a); setLevels(l); } inline void clipped_add(icl8u &v, int x){ int s = (int)v + x; v = s < 0 ? 0 : s > 255 ? 255 : s; } void DitheringOp::apply (const core::ImgBase *poSrc, core::ImgBase **ppoDst){ if(!prepare(ppoDst, depth8u, poSrc->getSize(), poSrc->getFormat(), poSrc->getChannels(), poSrc->getROI(), poSrc->getTime())){ throw ICLException("DitheringOp::apply: prepare failed"); } Rect roi; if(getClipToROI()){ poSrc->convertROI(*ppoDst); roi = (*ppoDst)->getImageRect(); }else{ poSrc->convert(*ppoDst); roi = (*ppoDst)->getROI(); } icl8u lut[256] = {0}; int dl = 256/m_levels, dval=255/(m_levels-1); for(int i=0;i<m_levels;++i){ std::fill(lut+i*dl, lut+(i+1)*dl, i*dval); } const int maxx = roi.x + roi.width; const int maxy = roi.y + roi.height; for(int c=0;c<poSrc->getChannels();++c){ Channel8u img = (*(*ppoDst)->as8u())[c]; for (int y=roi.y; y<maxy; y++) { for (int x=roi.x; x<maxx; x++) { icl8u o = img(x,y); icl8u n = 0; if(o <= 0) n = 0; else if(o >= 255) n = 255; else n = lut[o]; img(x,y) = n; int e = o - n; // img(x+1,y) += e * 7./16.; // img(x-1,y+1) += e * 3./16.; // img(x,y+1) += e * 3./16.; // img(x+1,y+1) += e * 1./16.; bool xin = x+1<maxx, yin = y+1<maxy; if(xin){ clipped_add(img(x+1,y),(e*7)/16); } if(yin){ clipped_add(img(x-1,y+1),(e*3)/16); clipped_add(img(x,y+1),(e*3)/16); if(xin){ clipped_add(img(x+1,y+1),e/16); } } } } } } } // namespace filter }