PPM入出力:
https://www.study.suzulang.com/cppppm-readerwriter
NByteDataを扱うクラス
https://www.study.suzulang.com/2dcg-functions/nbyte-data-type
#include <cstdio> #include <vector> #include <cassert> #include "NByteData.hpp" #include "ppmP3_read.hpp" namespace szl{ inline int calc_position2d(const int x, const int y, const int width) { return x + y * width; }
//canvasの一部に矩形でアクセスできるためのクラス class D2CanvasWindow { public: //! @brief start ~ end の範囲の画素番号一覧 std::vector<size_t> m_imgp; int startx,starty; int endx,endy; int canvaswidth; //!< 元画像の範囲 int canvasheight;//!< 元画像の範囲 inline int width() {return endx - startx + 1;} inline int height() {return endy - starty + 1;} //! @brief 元画像サイズとクリップサイズの設定 //! @param [in] canvaswidth 元画像のサイズ //! @param [in] canvasheight 元画像のサイズ //! @param [in] sx 始点 //! @param [in] sy 始点 //! @param [in] ex 終点 //! @param [in] ey 終点 //! @return なし void set_size(const int canvaswidth, const int canvasheight, const int sx, const int sy, const int ex, const int ey) { startx = sx; starty = sy; endx = ex; endy = ey; const int Width = width(); const int Height = height(); m_imgp.resize(Width * Height); int wx, wy;// クリップする範囲の画素indexの一覧を作成 for (int cx = sx; cx <= ex; cx++) { for (int cy = sy; cy <= ey; cy++) { wx = cx - sx; wy = cy - sy; int ci = calc_position2d(cx, cy, canvaswidth); int wi = calc_position2d(wx, wy, Width); m_imgp[wi] = ci; } } } //! @brief 画像を切り出す //! @param [in] dst 結果画像 //! @param [in] src 元画像 //! @return なし template<typename Canvas> void Clip(Canvas* dst, const Canvas& src) { assert(iwidth(*dst) == width()); assert(iheight(*dst) == height()); for(size_t i =0;i<m_imgp.size();i++){ (*dst)[i] = src[m_imgp[i]]; } } };
} ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// using PixelT = NByteData<3>; //画像データ struct Img2d { std::vector<PixelT> m_img; int width; int height; Img2d(int w, int h) { m_img.resize(w*h); width = w; height = h; } PixelT& operator[](const size_t index) {return m_img[index];} const PixelT& operator[](const size_t index)const {return m_img[index];} }; //! @brief 画像の幅の取得関数 //! @param [in] i 画像 //! @return 画像の幅 int iwidth(const Img2d& i) { return i.width; } //! @brief 画像の高さ取得関数 //! @param [in] i 画像 //! @return 画像の幅 int iheight(const Img2d& i) { return i.height; } ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// //! @brief 画像の書き込み void ppmP3_write( const char* const fname, const int width, const int height, const unsigned char* const p, const int vmax );
int main() { // 画像読み込み PixelT* pimg; int width; int height; int vmax; ppmP3_read( "C:\\test\\p.ppm", &width, &height, &vmax, (unsigned char**)&pimg ); Img2d img(width, height); for (size_t i = 0; i < width*height; i++) { img.m_img[i] = pimg[i]; } delete[]pimg; ///////////////////////////////// ///////////////////////////////// // 画像のクリップ szl::D2CanvasWindow win; win.set_size(img.width,img.height, 2, 3, 8, 10); Img2d clip(win.width(), win.height()); win.Clip(&clip, img); ///////////////////////////////// ///////////////////////////////// ppmP3_write( "C:\\test\\q.ppm", clip.width, clip.height, (unsigned char*)clip.m_img.data(), 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); }