ぬの部屋(仮)
nu-no-he-ya
  •  123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
         12
    3456789
    10111213141516
    17181920212223
    242526272829 
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
        123
    45678910
    11121314151617
    18192021222324
    25262728   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    15161718192021
    293031    
           
         12
    3456789
    10111213141516
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
          1
    2345678
    9101112131415
    16171819202122
    232425262728 
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
  • PNM Reader(改)

    プログラム本体(pnm_reader.hpp)

    #pragma once
    
    #include <fstream>
    #include <sstream>
    #include <string>
    #include <vector>
    
    #pragma warning(disable:4996)
    
    
    
    //! @class CGetGrayBits
    //! @brief 配列上のx番目の画素値を取得するクラス
    //! @sa https://suzulang.com/bit-depth-1-2-4-getpixelvalue/
    class CGetGrayBits {
      unsigned char* m_p;        //!< 画素へのポインタ
      const int m_depth = 1;     //!< ビット深度
    
      unsigned char m_mask = 1;  //!< depth8未満の時のビットマスク
    public:
    
      //! @brief コンストラクタ
      //! @param [in] p 画素配列へのポインタ
      CGetGrayBits(
        const void* const p) :
        m_p(static_cast<unsigned char*>(const_cast<void*>(p))) {
      }
    
      //! @brief 指定した番号の画素を取得
      //! @param [in] x 画素番号
      //! @return 画素値
      int operator[](const std::size_t x) {
        // x ドットが何バイト目かを算出 (0開始)
        std::size_t byte = x / (8 / m_depth);
    
        unsigned char c = m_p[byte];
    
        std::size_t pos = x % (8 / m_depth);
    
        int shift = 8 - m_depth - pos * m_depth;
    
        unsigned char mask1 = m_mask << shift;
        unsigned int val = (c & mask1) >> shift;
    
        return val;
      }
    
    };
    //! @brief PNMファイルの種類
    enum class PNM_TYPE {
      P1 = 1,  //Portable bitmap   ASCII
      P2 = 2,  //Portable graymap  ASCII
      P3 = 3,  //Portable pixmap   ASCII
      P4 = 4,  //Portable bitmap   Binary
      P5 = 5,  //Portable graymap  Binary
      P6 = 6,  //Portable pixmap   Binary
      PError = 7,
      PBitmap = 8,
      PGraymap = 9,
      PPixmap = 10
    };
    //! @brief ストリームから入力 bitmap ASCII
    //! @param [out] img 画像の格納先
    //! @param [out] s 入力ストリーム
    void read_P1(std::vector<unsigned char>& img, std::ifstream& s) {
      while (s.eof() == false) {
    
        char c;
        s.read(&c, 1);
        if (isdigit(c) != false) {
          img.push_back(c - '0');
        }
    
      }
    
    }
    //! @brief ストリームから入力 graymap,pixmap ASCII
    //! @param [out] img 画像の格納先
    //! @param [out] s 入力ストリーム
    void read_P23(std::vector<unsigned char> & img, std::ifstream & s) {
      while (s.eof() == false) {
    
        std::string val;
    
        s >> val;
    
        int value;
        try {
          value = std::stoi(val);
        }
        catch (std::invalid_argument) {
          continue;
        }
    
        img.push_back(value);
    
      }
    
    }
    //! @brief ストリームから入力 bitmap Binary
    //! @param [out] img 画像の格納先
    //! @param [out] s 入力ストリーム
    //! @return なし
    //! @details P4は1ビット=1画素なので全部読み込んでから1ビットずつとりだしている
    void read_P4(std::vector<unsigned char> & img, std::ifstream & s, int count) {
      std::vector<unsigned char> tmp;
    
      unsigned char tc;
      while (!s.eof()) {
        s.read((char*)& tc, sizeof(char));
        tmp.push_back(tc);
      }
    
      CGetGrayBits bits(&tmp[0]);
    
      for (size_t i = 0; i < count; i++) {
        img.push_back(bits[i]);
      }
    
    }
    //! @brief ストリームから入力 graymap,pixmap Binary
    //! @param [out] img 画像の格納先
    //! @param [out] s 入力ストリーム
    //! @return なし
    void read_P56(std::vector<unsigned char> & img, std::ifstream & s) {
      while (s.eof() == false) {
    
        unsigned char c;
        s.read((char*)& c, 1);
        img.push_back(c);
    
      }
    }
    //! @brief pnmファイルを読み込む
    //! @param [in] fpathname pnmファイルへのパス
    //! @param [out] img 画像の格納先
    //! @param [out] width 横方向の画素数
    //! @param [out] height 縦方向の画素数
    //! @param [out] maxvalue 画素の最大値
    //! @param [out] datatype 形式を識別する定数
    //! @retval true 読込成功
    //! @retval false 読込失敗
    bool read_pnm(const char* fpathname, std::vector<unsigned char> * img, int* width, int* height, int* maxvalue, PNM_TYPE * datatype) {
      std::ifstream ifs(fpathname, std::ios::in | std::ios::binary);
    
      if (!ifs)
        return false;
    
      std::string text;
    
      *width = -1;
      *height = -1;
      *maxvalue = -1;
    
      //タイプの読み取り
      PNM_TYPE type;
      {
        int _type = (int)PNM_TYPE::PError;
        while (std::getline(ifs, text).eof() == false) {
          if (text[0] == 'P') {
            _type = ((int)text[1] - (int)'0');
            break;
          }
        }
        switch (_type) {
        case (int)PNM_TYPE::P1:*datatype = PNM_TYPE::PBitmap; break;
        case (int)PNM_TYPE::P2:*datatype = PNM_TYPE::PGraymap; break;
        case (int)PNM_TYPE::P3:*datatype = PNM_TYPE::PPixmap; break;
        case (int)PNM_TYPE::P4:*datatype = PNM_TYPE::PBitmap; break;
        case (int)PNM_TYPE::P5:*datatype = PNM_TYPE::PGraymap; break;
        case (int)PNM_TYPE::P6:*datatype = PNM_TYPE::PPixmap; break;
        default:
          *datatype = PNM_TYPE::PError;
          return false;
        }
        type = (PNM_TYPE)_type;
      }
    
      while (std::getline(ifs, text).eof() == false) {
    
        //コメントスキップ
        if (text[0] == '#')
          continue;
    
        //コメントでないなら各種値の入力
        std::stringstream ss(text);
    
        //幅入力
        if (*width < 0) {
          ss >> *width;
          if (*width < 0)
            continue;
        }
    
        //高さ入力
        if (*height < 0) {
          ss >> *height;
          if (*height < 0)
            continue;
        }
    
        //最大値入力
        if (*datatype != PNM_TYPE::PBitmap) {
          if (*maxvalue < 0) {
            ss >> *maxvalue;
            if (*maxvalue < 0)
              continue;
          }
        }
    
        break;
      }
    
      int count = *width * *height;
    
      switch (type) {
      case PNM_TYPE::P1:
        img->reserve(count);
        read_P1(*img, ifs);
        break;
      case PNM_TYPE::P2:
        img->reserve(count);
        read_P23(*img, ifs);
        break;
      case PNM_TYPE::P3:
        img->reserve(count * 3);
        read_P23(*img, ifs);
        break;
      case PNM_TYPE::P4:
        read_P4(*img, ifs, count);
        break;
      case PNM_TYPE::P5:
        read_P56(*img, ifs);
        break;
      case PNM_TYPE::P6:
        read_P56(*img, ifs);
        break;
      }
    
    }
    

    テスト用コード

    #include <iostream>
    
    #include "pnm_reader.hpp"
    
    
    //! @brief pnmの各型式のデータをppm形式の格納方法に変更する
    //! @param [out] dst 結果画像データ
    //! @param [in] src 元画像データ
    //! @param [in] pixelcount 画素数
    //! @param [in] type P1~P6のいずれか
    //! @return なし
    void pnm_to_ppm(
      std::vector<unsigned char>& dst,
      unsigned char* src,
      int pixelcount,
      PNM_TYPE type
      ) {
    
      switch (type)
      {
      case PNM_TYPE::P1:
      case PNM_TYPE::P4:
      case PNM_TYPE::PBitmap:
        for (size_t i = 0; i < pixelcount; i++) {
          dst.push_back(src[i] ? 0 : 255);
          dst.push_back(src[i] ? 0 : 255);
          dst.push_back(src[i] ? 0 : 255);
        }
        break;
      case PNM_TYPE::P2:
      case PNM_TYPE::P5:
      case PNM_TYPE::PGraymap:
        for (size_t i = 0; i < pixelcount; i++) {
          dst.push_back(src[i]);
          dst.push_back(src[i]);
          dst.push_back(src[i]);
        }
        break;
      case PNM_TYPE::P3:
      case PNM_TYPE::P6:
      case PNM_TYPE::PPixmap:
        for (size_t i = 0; i < pixelcount; i++) {
          dst.push_back(src[i * 3 + 0]);
          dst.push_back(src[i * 3 + 1]);
          dst.push_back(src[i * 3 + 2]);
        }
        break;
      }
    }
    //! @brief PPM(RGB各1byte,カラー,テキスト)を書き込む
    //! @param [in] fname ファイル名
    //! @param [in] vmax 全てのRGBの中の最大値
    //! @param [in] width 画像の幅
    //! @param [in] height 画像の高さ
    //! @param [in] p 画像のメモリへのアドレス
    //! @details RGBRGBRGB....のメモリを渡すと、RGBテキストでファイル名fnameで書き込む
    void pnmP3_Write(
      const char* const fname, 
      const int vmax, 
      const int width, 
      const int height, 
      const unsigned char* const p) {
    
      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);
    }
    int main()
    {
      const char* fpathname = "C:\\test\\butterfly-5546907_640-binary.ppm";
    
    
      std::vector<unsigned char> img;
      int width, height, maxvalue;
      PNM_TYPE type;
      read_pnm(
        fpathname,
        &img,
        &width,
        &height,
        &maxvalue,
        &type
      );
    
      std::vector<unsigned char> tmp;
      pnm_to_ppm(tmp, &img[0], width * height,type);
      //////////////////////////////
      const char* fname = "C:\\test\\out.ppm";
      pnmP3_Write(fname, 255, width, height, &tmp[0]);
    
    
    }