egami
C++ Image Processing program
|
00001 #ifndef PROCESSES_CONVOLUTION_HPP_INCLUDED 00002 #define PROCESSES_CONVOLUTION_HPP_INCLUDED 00003 00004 #include <cmath> 00005 #include <array> 00006 00007 #include "../progress.hpp" 00008 #include "../display_unit.hpp" 00009 00010 template<int N> 00011 class Advancement{ 00012 public: 00013 Advancement(){} 00014 void advance(double d){ p.advance(d); } 00015 private: 00016 Progress p; 00017 }; 00018 00019 template<> 00020 class Advancement<1>{ 00021 public: 00022 void advance(double){} 00023 }; 00024 00025 template<int N> 00026 Image_unit* apply(const Image_unit *in, const std::array<std::array<double, 2*N+1>, 2*N+1> &kernel, double divisor){ 00027 Advancement<N> adv; 00028 Image_unit *out=new Image_unit(*in); 00029 00030 for(unsigned y=0; y<out->height(); ++y){ 00031 adv.advance(static_cast<double>(y)/out->height()); 00032 for(unsigned x=0; x<out->width(); ++x){ 00033 double vr=0, vg=0, vb=0; 00034 for(int dy=-N; dy<=N; ++dy) 00035 for(int dx=-N; dx<=N; ++dx){ 00036 // @todo error if the kernel is bigger than the image 00037 vr+=in->m_red(y+dy, x+dx)*kernel[dy+N][dx+N]; 00038 vg+=in->m_green(y+dy, x+dx)*kernel[dy+N][dx+N]; 00039 vb+=in->m_blue(y+dy, x+dx)*kernel[dy+N][dx+N]; 00040 } 00041 vr/=divisor; 00042 vg/=divisor; 00043 vb/=divisor; 00044 vr=vr<0?0:vr>255?255:vr; 00045 vg=vg<0?0:vg>255?255:vg; 00046 vb=vb<0?0:vb>255?255:vb; 00047 out->red(y, x, vr); 00048 out->green(y, x, vg); 00049 out->blue(y, x, vb); 00050 } 00051 } 00052 return out; 00053 } 00054 00055 /* Iterator version : 00056 00057 for(Image::const_iterator it=in->begin(); it!=in->end(); ++it){ 00058 double vr=0, vg=0, vb=0; 00059 for(int dy=-N; dy<=N; ++dy) 00060 for(int dx=-N; dx<=N; ++dx){ 00061 Image::const_iterator ti(it+dy*in->width()+dx); 00062 if(ti.valid()){ 00063 vr+=ti->r*kernel[dy+N][dx+N]; 00064 vg+=ti->g*kernel[dy+N][dx+N];; 00065 vb+=ti->b*kernel[dy+N][dx+N];; 00066 } 00067 } 00068 00069 Image::iterator to=(out->begin()+(it-in->begin())); 00070 to->r=static_cast<unsigned char>(std::abs(vr/divisor)); 00071 to->g=static_cast<unsigned char>(std::abs(vg/divisor)); 00072 to->b=static_cast<unsigned char>(std::abs(vb/divisor)); 00073 } 00074 */ 00075 00076 #endif