スポンサーリンク
#pragma once #include <vector> #include<cassert> class Thermography { using InputColor = std::array<int, 3>; using CalcColor = std::array<double, 3>; using OutputColor = std::array<unsigned char, 3>; std::vector< InputColor > m_ctable; double m_dmin; double m_dmax; private: template<typename Return> Return clamp(Return _min, Return _max, double value) const { if (value < _min) return _min; if (value > _max) return _max; return value; } //! @brief 0.0~1.0 の範囲のRGBを取得 CalcColor calc(const int from, const double ratio)const { constexpr int R = 0, G = 1, B = 2; const int to = from + 1; double r = (m_ctable[from][R] + (m_ctable[to][R] - m_ctable[from][R]) * ratio) / 255.0; double g = (m_ctable[from][G] + (m_ctable[to][G] - m_ctable[from][G]) * ratio) / 255.0; double b = (m_ctable[from][B] + (m_ctable[to][B] - m_ctable[from][B]) * ratio) / 255.0; return CalcColor{r,g,b}; } //! @brief 0~255の範囲のRGBを取得 OutputColor toOutput(const CalcColor& cc)const { return OutputColor{ clamp<unsigned char>(0 ,255 ,cc[0] * 255), clamp<unsigned char>(0 ,255 ,cc[1] * 255), clamp<unsigned char>(0 ,255 ,cc[2] * 255) }; } public: // @brief カラーテーブルを設定する template<class It> void setColorTable(It first, It last) { for (auto c = first;c!= last;c++) m_ctable.push_back(*c); } // @brief カラーテーブルを設定する void setColorTable( std::initializer_list< InputColor > colors ) { setColorTable(colors.begin(), colors.end()); } // @brief 着色する値の範囲を設定 void setArea(double _min, double _max) { m_dmin = _min; m_dmax = _max; } //! @brief 値をRGB色へ変換 OutputColor thermography(const double value)const { constexpr int R = 0, G = 1, B = 2; int N = m_ctable.size(); // 値の正規化 double nvalue; double vwidth = m_dmax - m_dmin; nvalue = (value - m_dmin) / vwidth; int from, to; double ratio; ////////////////////////////// // 範囲外 if (nvalue <= 0.0) { from = 0; ratio = 0.0; } else if (nvalue >= 1.0) { from = m_ctable.size() - 2; ratio = 1.0; } ////////////////////////////// // 範囲内なら from ~ to の間で正規化してratioにする else { from = nvalue * (N - 1); to = from + 1; double NnFrom = from / double(N - 1); double NnTo = to / double(N - 1); ratio = (nvalue - NnFrom) / (NnTo - NnFrom); } CalcColor rgb = calc(from, ratio); return toOutput(rgb); } };
#include <iostream> // https://www.study.suzulang.com/2dcg-functions/nbyte-data-type #include "NByteData.hpp" #include "ppmP3_read.hpp" #include "thermography.h" #include <vector> #include <array> void ppmP3_write( const char* const fname, const int width, const int height, const unsigned char* const p, const int vmax ); int main() { using PixelT = NByteData<3>; std::vector<PixelT> mem; // 画像読み込み int width; int height; int vmax; ppmP3_read( "C:\\test\\ppp.ppm", &width, &height, &vmax, [&mem](const size_t pixelcount) { mem.resize(pixelcount); return (unsigned char*)&mem[0]; } );
////////////////////////////////////////////// ////////////////////////////////////////////// std::vector< std::array<int, 3>> ColorTable{ std::array<int, 3>{ 0 , 0, 0 }, // 黒 std::array<int, 3>{ 0 , 0, 255}, // 青 std::array<int, 3>{ 0 ,200,200}, // 水色 std::array<int, 3>{ 0 ,255, 0 }, // 緑 std::array<int, 3>{200,200, 0 }, // 橙 std::array<int, 3>{255, 0 , 0 }, // 赤 std::array<int, 3>{255,255,255} // 白 }; Thermography c; c.setArea(0, 255);//この範囲外の値は0,255として扱われる c.setColorTable(ColorTable.begin(), ColorTable.end());
// 色を反転 for (auto& p : mem) { std::array<unsigned char,3> rgb = c.thermography(p.data()[0]); p.data()[0] = rgb[0]; p.data()[1] = rgb[1]; p.data()[2] = rgb[2]; p.data()[0] = (p.data()[0] > 255) ? 255 : p.data()[0]; p.data()[1] = (p.data()[1] > 255) ? 255 : p.data()[1]; p.data()[2] = (p.data()[2] > 255) ? 255 : p.data()[2]; } ///////////////////////////////// ///////////////////////////////// ppmP3_write( "C:\\test\\qqq.ppm", width, height, (unsigned char*)&mem[0], 255); } //! @brief PPM(RGB各1byte,カラー,テキスト)を書き込む //! @param [in] fname ファイル名 //! @param [in] width 画像の幅 //! @param [in] height 画像の高さ //! @param [in] p 画像のメモリへのアドレス //! @param [in] vmax 全てのRGBの中の最大値。普通の画像なら255 //! @details RGBRGBRGB....のメモリを渡すと、RGBテキストでファイル名fnameで書き込む void ppmP3_write( const char* const fname, const int width, const int height, const unsigned char* const p, const int vmax ) { FILE* fp = fopen(fname, "wb"); fprintf(fp, "P3\n%d %d\n%d\n", width, height, vmax); size_t k = 0; for (size_t i = 0; i < (size_t)height; i++) { for (size_t j = 0; j < (size_t)width; j++) { fprintf(fp, "%d %d %d ", p[k * 3 + 0], p[k * 3 + 1], p[k * 3 + 2] ); k++; } fprintf(fp, "\n"); } fclose(fp); }
#include <iostream> // https://www.study.suzulang.com/2dcg-functions/nbyte-data-type #include "NByteData.hpp"
// https://suzulang.com/ppmp3_read-memalloc-ver/ #include "ppmP3_read.hpp" #include "thermography.h" #include <vector> #include <array> void ppmP3_write( const char* const fname, const int width, const int height, const unsigned char* const p, const int vmax ); int main() { using PixelT = NByteData<3>; std::vector<PixelT> mem; // 画像読み込み int width; int height; int vmax; ppmP3_read( "C:\\test\\ppp.ppm", &width, &height, &vmax, [&mem](const size_t pixelcount) { mem.resize(pixelcount); return (unsigned char*)&mem[0]; } );
////////////////////////////////////////////// ////////////////////////////////////////////// std::vector< std::array<int, 3>> ColorTable{ std::array<int, 3>{ 0 , 0, 0 }, // 黒 std::array<int, 3>{ 0 , 0, 255}, // 青 std::array<int, 3>{ 0 ,200,200}, // 水色 std::array<int, 3>{ 0 ,255, 0 }, // 緑 std::array<int, 3>{200,200, 0 }, // 橙 std::array<int, 3>{255, 0 , 0 }, // 赤 std::array<int, 3>{255,255,255} // 白 }; Thermography c; c.setArea(0, 255);//この範囲外の値は0,255として扱われる c.setColorTable(ColorTable.begin(), ColorTable.end());
// 色を反転 for (auto& p : mem) { std::array<unsigned char,3> rgb = c.thermography(p.data()[0]); p.data()[0] = rgb[0]; p.data()[1] = rgb[1]; p.data()[2] = rgb[2]; p.data()[0] = (p.data()[0] > 255) ? 255 : p.data()[0]; p.data()[1] = (p.data()[1] > 255) ? 255 : p.data()[1]; p.data()[2] = (p.data()[2] > 255) ? 255 : p.data()[2]; } ///////////////////////////////// ///////////////////////////////// ppmP3_write( "C:\\test\\qqq.ppm", width, height, (unsigned char*)&mem[0], 255); } //! @brief PPM(RGB各1byte,カラー,テキスト)を書き込む //! @param [in] fname ファイル名 //! @param [in] width 画像の幅 //! @param [in] height 画像の高さ //! @param [in] p 画像のメモリへのアドレス //! @param [in] vmax 全てのRGBの中の最大値。普通の画像なら255 //! @details RGBRGBRGB....のメモリを渡すと、RGBテキストでファイル名fnameで書き込む void ppmP3_write( const char* const fname, const int width, const int height, const unsigned char* const p, const int vmax ) { FILE* fp = fopen(fname, "wb"); fprintf(fp, "P3\n%d %d\n%d\n", width, height, vmax); size_t k = 0; for (size_t i = 0; i < (size_t)height; i++) { for (size_t j = 0; j < (size_t)width; j++) { fprintf(fp, "%d %d %d ", p[k * 3 + 0], p[k * 3 + 1], p[k * 3 + 2] ); k++; } fprintf(fp, "\n"); } fclose(fp); }