スポンサーリンク

| キーワード:

二次元画像をクリップするクラスの作成

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);
}

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: