#include <iostream> #include <vector> #include "ppmP3_read.hpp"
class Filter { //画像フィルタ std::vector< std::vector<float> > m_filter; public: //! @brief コンストラクタ //! @param [in] カーネルの一辺のサイズ Filter(const int size) { m_filter.resize(size, std::vector<float>(size, 0)); } //! @brief フィルタの数値を設定する関数 //! @param [in] row 行番号 //! @param [in] 一行分のデータ //! @return なし void set(int row, std::initializer_list<float> values) { int i = 0; for (auto v : values) { m_filter[row][i] = v; i++; } } //! @brief フィルタの全ての要素を割り算する //! @param [in] f 割る数 void operator/=(const float f) { for (auto&& row : m_filter) { for (auto&& c : row) { c /= f; } } } //! @brief フィルタのカーネルの一辺のサイズ int size() const{ return m_filter.size(); } //! @brief フィルタの要素を取得 //! @param [in] x -size()/2 から size()/2 までの整数 //! @param [in] y -size()/2 から size()/2 までの整数 float get(int x, int y)const { int sz = size() / 2; return m_filter[x + sz][y + sz]; } int posmin()const { return -size() / 2; } int posmax()const { return size() / 2; } };
struct image { unsigned char* src; int width; int height; int pixelsize; };
//! @brief 画像にフィルタを適用 //! @param [in] filter 画像フィルタ //! @param [in] x フィルタを適用する画素の座標 //! @param [in] y フィルタを適用する画素の座標 //! @param [in] src 元画像 //! @param [in] ret 結果画像 void apply(const Filter& filter,int x, int y,const image& src, unsigned char* ret) { const int posmin = filter.posmin(); const int posmax = filter.posmax(); const int pixSize = src.pixelsize; unsigned char* retp= &ret[pixSize * (y * src.width + x)]; for (int i = 0; i < pixSize; i++) { retp[i] = 0; } for (int fx = posmin; fx <= posmax; fx++) { for (int fy = posmin; fy <= posmax; fy++) { float g = filter.get(fx, fy); int yy = y + fy; int xx = x + fx; if (yy < 0 || xx < 0) continue; unsigned char* s = &src.src[pixSize * (yy * src.width + xx)]; for (int i = 0; i < pixSize; i++) { retp[i] += s[i]*g; } } } }
int main() { int width; int height; int vmax; // 画像を読み込む unsigned char * img_src = ppmP3_read( "C:\\dev\\c.ppm", &width, &height, &vmax, [](const size_t count) {return new unsigned char[count]; } ); std::vector<unsigned char> img_dst(width * height * 3); #define F1 //フィルタ作成 #ifdef F0 Filter ff(3); ff.set(0, { 1,2,1 }); ff.set(1, { 2,4,2 }); ff.set(2, { 1,2,1 }); ff /= 16.f; #elif defined(F1) Filter ff(5); ff.set(0, { 1, 4, 6, 4,1 }); ff.set(1, { 4,16,24,16,4 }); ff.set(2, { 6,24,36,24,6 }); ff.set(3, { 4,16,24,16,4 }); ff.set(4, { 1, 4, 6, 4,1 }); ff /= 256.f; #elif defined(F2) Filter ff(7); ff.set(0, { 1, 6, 15, 20, 15, 6, 1 }); ff.set(1, { 6, 36, 90,120, 90, 36, 6 }); ff.set(2, { 15, 90,225,300,225, 90, 15 }); ff.set(3, { 20,120,300,400,300,120, 20 }); ff.set(4, { 15, 90,225,300,225, 90, 15 }); ff.set(5, { 6, 36, 90,120, 90, 36, 6 }); ff.set(6, { 1, 6, 15, 20, 15, 6, 1 }); ff /= 4096.f; #endif //全てのピクセルにフィルタを適用 for (size_t x = 0; x < width; x++) { for (size_t y = 0; y < height; y++) { apply(ff,x, y, image{ img_src, width,height,3 }, img_dst.data()); } } //フィルタをかけた画像を保存 pnmP3_Write("C:\\dev\\e.ppm", 255, width, height, img_dst.data()); delete[]img_src; }