ぬの部屋(仮)
nu-no-he-ya
  • 1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
     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      
         12
    3456789
    10111213141516
    17181920212223
    2425262728  
           
      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
           
       1234
    567891011
    12131415161718
    19202122232425
    26272829   
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       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     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28      
           
         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     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
    1234567
    891011121314
    15161718192021
    22232425262728
           
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
     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
           
  • 好きな環境変数を設定したコマンドプロンプトを開くバッチファイル作成

    windowsでシステムのプロパティの環境変数のPATHにパスを追加するのが嫌なので、環境変数を適用したコマンドプロンプトを開くバッチファイルを作成する

    toolactivate.bat

    
    cd C:\mybins\command\work
    set PATH_ANC=C:\Users\yamada\anaconda3;C:\Users\yamada\anaconda3\Scripts;C:\Users\yamada\anaconda3\Library\bin
    set PATH_APP=C:\mybins\7za;C:\mybins\command\ffmpeg-2021-11-29-git-86a2123a6e-full_build\bin;C:\mybins\ImageMagick-7.1.0-portable-Q16-x64
    set PATH_CMP=C:\mybins\command\PortableGit\bin;C:\mybins\command\depot_tools
    
    set path=%PATH_ANC%;%PATH_APP%;%PATH_CMP%;%path%;
    
    %windir%\system32\cmd.exe /k
    

    解説

    一行目のcdでカレントディレクトリを設定する。

    二行目以降、setで環境変数を三つ設定。一行でもいいのだが自分が管理しやすいように分割している。

    最後のset path=で三つを結合し%path%と混ぜる。なおanaconda3を%path%より前に書かないとmicrosoft store?的な物が起動してしまう可能性がある。

    最後のcmd.exeでコマンドプロンプトを開く。

    SDL_imageを使う

    SDL2に続いてSDL_imageを使う。

    マニュアルを読むとpngの読込関数なんかが入っているが、別途libpng等を使っているのでただのラッパーだと思われる。

    導入

    URL https://www.libsdl.org/projects/SDL_image/

    ダウンロード SDL2_image-devel-2.0.5-VC.zip (Visual C++ 32/64-bit)

    パス設定

     include : SDL2_image-2.0.5\include

     lib : SDL2_image-2.0.5\lib\x64

    サンプルコード

    // このマクロを定義しないとエントリポイントが SDL_main になる
    #define SDL_MAIN_HANDLED
    #include <SDL.h>
    
    // IMG_Load
    #include <SDL_image.h>
    
    #pragma comment(lib,"SDL2.lib")
    
    #pragma comment(lib,"SDL2_image.lib")
    
    // 必要ファイル:
    // SDL2.dll
    // SDL2_image.dll
    // libpng16-16.dll
    // zlib1.dll
    
    int main(int argc, char* argv[])
    {
      // これがないと IMG_Loadがnullptrを返す
      //SDL_Init(SDL_INIT_VIDEO);
    
      // PNG読むなら必要
      //IMG_Init(IMG_INIT_PNG);
    
      // ↑の筈なんだが無くても動いたりする?
    
    
      //////////////////////////////
      Uint32 rmask, gmask, bmask, amask;
    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
      rmask = 0xff000000;
      gmask = 0x00ff0000;
      bmask = 0x0000ff00;
      amask = 0x000000ff;
    #else 
      rmask = 0x000000ff;
      gmask = 0x0000ff00;
      bmask = 0x00ff0000;
      amask = 0xff000000;
    #endif
    
      //////////////////////////////
      //■ レンダラ作成
      SDL_Surface* surf_out = SDL_CreateRGBSurface(0, 500, 500, 32,
        rmask, gmask, bmask, amask);
      SDL_Renderer* rend_out = SDL_CreateSoftwareRenderer(surf_out);
    
      ////////////////////////////
      // 画像を読み込んでコピー
      SDL_Surface* surf_in = IMG_Load("C:\\test\\data\\a.png");
      SDL_BlitSurface(surf_in, nullptr, surf_out, nullptr);
      SDL_FreeSurface(surf_in);
      ////////////////////////////
    
      // アルファブレンドの設定
      SDL_SetRenderDrawBlendMode(rend_out, SDL_BLENDMODE_BLEND);
    
      //////////////////////////////
      // 赤で直線
      SDL_SetRenderDrawColor(rend_out, 255, 0, 0, 100);
      SDL_RenderDrawLine(rend_out, 50, 20, 500, 200);
    
      // ファイルに保存
      //SDL_SaveBMP(surf_out, "out.bmp");
      IMG_SavePNG(surf_out, "out.png");
      //////////////////////////////
    
      //■ レンダラ破棄
      SDL_DestroyRenderer(rend_out);
    
      SDL_FreeSurface(surf_out);
    
    
      return 0;
    }
    

    結果

    結果のサイズを500x500に設定しているのでクリップされている。

    SDL2で画像を作成して線を一本引いてみる

    諸事情によりSDLライブラリ。

    導入

    URL https://www.libsdl.org/download-2.0.php

    ダウンロード SDL2-devel-2.0.18-VC.zip (Visual C++ 32/64-bit)

    パス設定

    include : SDL2-2.0.18\include

    lib : SDL2-2.0.18\lib\x64

    サンプルコード

    ウィンドウに画像を表示するサンプルばかりだったので、画像を作成してファイルに保存するサンプルにした。

    SDL_CreateRGBSurface と SDL_CreateSoftwareRenderer を使う。

    // このマクロを定義しないとエントリポイントが SDL_main になる
    #define SDL_MAIN_HANDLED
    #include <SDL.h>
    
    #pragma comment(lib,"SDL2.lib")
    
    // 必要ファイル:
    // SDL2.dll
    
    int main(int argc, char* argv[])
    {
      //////////////////////////////
      Uint32 rmask, gmask, bmask, amask;
    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
      rmask = 0xff000000;
      gmask = 0x00ff0000;
      bmask = 0x0000ff00;
      amask = 0x000000ff;
    #else 
      rmask = 0x000000ff;
      gmask = 0x0000ff00;
      bmask = 0x00ff0000;
      amask = 0xff000000;
    #endif
      //////////////////////////////
    
      SDL_Surface* surf = SDL_CreateRGBSurface(
        0,
        256,
        256,
        32, rmask, gmask, bmask, amask);
    
      //■ レンダラ作成
      SDL_Renderer* render = SDL_CreateSoftwareRenderer(surf);
    
      // アルファブレンドの設定
      SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_BLEND);
    
      //////////////////////////////
      // 黒でクリア
      SDL_SetRenderDrawColor(render, 0, 0, 0, 255);
      SDL_RenderClear(render);
      //////////////////////////////
      // 赤で直線
      SDL_SetRenderDrawColor(render, 255, 0, 0, 150);
      SDL_RenderDrawLine(render, 50, 20, 500, 200);
      //////////////////////////////
      // ファイルに保存
      SDL_SaveBMP(surf, "out.bmp");
      //////////////////////////////
    
      //■ レンダラ破棄
      SDL_DestroyRenderer(render);
    
    
      SDL_FreeSurface(surf);
    
    
      return 0;
    }
    

    最大要素数が決まったvectorクラスを作った話

    要素数が「最大N個」の配列が欲しい場合がある。std::vectorではnewでヒープに確保されるので重すぎる。std::arrayはスタックに確保できるがpush_backできない。

    そんなわけで、push_backできるがスタックに置ける配列を考える。

    LimitedVector.hpp

    #include<array>
    
    namespace szl {
    
      //! @brief 最大要素数が決まっている可変長配列
      //! @tparam T arrayに入れるデータ型
      //! @tparam MAX arrayの要素数
      template<typename T, size_t MAX>
      class LimitedVector {
        std::array<T, MAX> _data;
        size_t count; //!< 現在の要素数
      public:
        LimitedVector() :count(0) {}
    
        auto begin() { return _data.begin(); }
        auto end() { return _data.begin() + count; }
        const auto cbegin()const { return _data.cbegin(); }
        const auto cend()const { return _data.cbegin() + count; }
    
        void push_back(const T& v) {
    
          if (count >= MAX)
            throw "count >= MAX";
    
          _data[count++] = v;
        }
        void pop_back() {
    
          if (count == 0)
            throw "count == 0";
    
          count--;
        }
        T& back() {
    
          if (count == 0)
            throw "count == 0";
    
          return _data[count - 1];
        }
        const T& back()const {
          return _data[count - 1];
        }
        const T* data()const { return _data; }
        T* data() { return _data; }
    
        size_t size()const { return count; }
    
        const T& operator[](const size_t index)const {
          return _data[index];
        }
        T& operator[](const size_t index) {
          return _data[index];
        }
    
      };
    
    }
    

    呼び出し例

    #include "LimitedVector.hpp"
    
    int main()
    {
      szl::LimitedVector<int, 3> v;
    
      v.push_back(3);
      v.push_back(4);
      v.push_back(6);
    
      printf("%d\n", v.size());
    
      v[1] = 1;
    
      for (auto vv : v) {
          printf("-- %d\n", vv);
      }
      v.pop_back();
    
      printf("-------\n");
      for (auto vv : v) {
          printf("-- %d\n", vv);
      }
    
    }
    

    実行例

    3
    -- 3
    -- 1
    -- 6
    -------
    -- 3
    -- 1

    ゴミ箱の内容量を取得

    windowsはいつの頃からか、ゴミ箱の中身のファイルサイズ合計が表示されなくなった。

    知りたかったのでC++ + Win32APIでゴミ箱のファイル容量を取得してみる。

    #include <iostream>
    #include <windows.h>
    #include <shellapi.h>   // shell32.lib
    
    
    void GetRecycleBin(const char* drive = nullptr) {
    
      printf("\"%s\"\n", drive);
    
    
      SHQUERYRBINFO   rbInfo = { sizeof(SHQUERYRBINFO) };
      DWORDLONG     i64MB;
    
      // ごみ箱の情報を取得する
      if (SHQueryRecycleBin(drive, &rbInfo) == S_OK) {
    
        i64MB = (rbInfo.i64Size / 1024 / 1024);
        printf("ファイルサイズ合計 :%I64u MiB\n", i64MB);
        printf("ファイル数合計   :%I64u 個\n", rbInfo.i64NumItems);
    
      }
      else {
        printf("ごみ箱の情報を取得できません。\n");
      }
      printf("-----------------------\n");
    }
    
    // メイン関数
    int main(void)
    {
    
      GetRecycleBin("C:\\");
      GetRecycleBin("H:\\");
      GetRecycleBin("");
    
      getchar();
      return 0;
    }
    

     

    "C:\"
    ファイルサイズ合計 :1299 MiB
    ファイル数合計   :114 個
    -----------------------
    "H:\"
    ファイルサイズ合計 :6454 MiB
    ファイル数合計   :739 個
    -----------------------
    ""
    ファイルサイズ合計 :7754 MiB
    ファイル数合計   :853 個
    -----------------------

     

     

    Blender 2.10のアニメーションでフレームが変わったときにTextを変更する

    bpy.app.handlers.frame_change_pre.appendに指定した関数がフレームが変わるたびに走る。

    この例では、テキストオブジェクトに現在のフレーム数を代入している。

    import bpy
    
    
    def frame_change_pre(scene):
    
        bpy.data.objects['Text'].data.body = str(scene.frame_current)
        
    
    bpy.app.handlers.frame_change_pre.append(frame_change_pre)
    

    C++でSobelフィルタを実装

    3x3のソーベルフィルタを実装する。

    SobelFilter.hpp
    #pragma once
    
    
    #include <valarray>
    #include <array>
     
    //! @brief ソーベルフィルタ
    //! @note フィルタを変えれば他の用途にも使える
    class SobelFilter {
    
      // フィルタサイズ 3x3
      static constexpr int FilterSize = 3;
    
      
      std::array < std::array<int, FilterSize>, FilterSize > filterH; //!< 水平方向
      std::array < std::array<int, FilterSize>, FilterSize > filterV; //!< 垂直方向
    
      int m_width;  //!< 入出力画像の幅
      int m_height; //!< 入出力画像の高さ
      const unsigned char* m_pimg; //!< 元画像へのポインタ
    
    
      // -1 →(+1)→ 0 
      //  0 →(+1)→ 1  
      //  1 →(+1)→ 2
    
      //! @brief 水平のフィルタを取得
      int fH(const int x, const int y)const {
        return filterH[x + 1][y + 1];
      }
      //! @brief  垂直のフィルタを取得
      int fV(const int x, const int y)const {
        return filterV[x + 1][y + 1];
      }
    
    public:
      //! @brief 一画素のサイズ。RGBで3バイト
      static constexpr int PixelSize = 3;
    
      using Vector3d = std::valarray<int>;
    
      //! @brief [in] w 画像幅
      //! @brief [in] h 画像幅
      //! @brief [in] pimg 元画像へのポインタ
      SobelFilter(int w, int h, const unsigned char* pimg) {
    
        //ソーベルフィルタ作成
        filterH[0] = { -1, 0, 1 };
        filterH[1] = { -2, 0, 2 };
        filterH[2] = { -1, 0, 1 };
        filterV[0] = { -1,-2,-1 };
        filterV[1] = { 0, 0, 0 };
        filterV[2] = { 1, 2, 1 };
    
        // 画像へアクセスする諸々の設定
        m_width = w;
        m_height = h;
        m_pimg = pimg;
    
      }
    
    
      //! @brief 元画像の(x,y)座標の画素を取得
      Vector3d pixel(const int x, const int y) {
        const unsigned char* p = &m_pimg[(y * m_width + x) * PixelSize];
    
        return Vector3d({ p[0], p[1], p[2] });
      }
    
      // (x,y)座標のフィルタ後の値を取得
      Vector3d get(const int x, const int y) {
        Vector3d tmp({ 0,0,0 });
    
        std::array<Vector3d, FilterSize * 2> px;;
        std::fill(px.begin(), px.end(), Vector3d{ 0,0,0 });
    
        //水平9画素についての合計
        px[0] =
          pixel(x - 1, y - 1) * fH(-1, -1) +
          pixel(x  , y - 1) * fH( 0, -1) +
          pixel(x + 1, y - 1) * fH( 1, -1);
    
        px[1] =
          pixel(x - 1, y) * fH(-1, 0) +
          pixel(x  , y) * fH( 0, 0) +
          pixel(x + 1, y) * fH( 1, 0);
    
        px[2] =
          pixel(x - 1, y + 1) * fH(-1, 1) +
          pixel(x  , y + 1) * fH( 0, 1) +
          pixel(x + 1, y + 1) * fH( 1, 1);
    
        ////////////////////////////////////////////////
        // 垂直9画素についての合計
        px[3] =
          pixel(x - 1, y - 1) * fV(-1, -1) +
          pixel(x, y - 1) * fV(0, -1) +
          pixel(x + 1, y - 1) * fV(1, -1);
    
        px[4] =
          pixel(x - 1, y) * fV(-1, 0) +
          pixel(x, y) * fV(0, 0) +
          pixel(x + 1, y) * fV(1, 0);
    
        px[5] =
          pixel(x - 1, y + 1) * fV(-1, 1) +
          pixel(x, y + 1) * fV(0, 1) +
          pixel(x + 1, y + 1) * fV(1, 1);
    
        for (auto& k : px) {
          for (int i = 0; i < PixelSize; i++) {
            tmp[i] += k[i];
          }
        }
    
        for (int i = 0; i < PixelSize; i++) {
          tmp[i] = (tmp[i] < 0) ? 0 : tmp[i];
          tmp[i] = (tmp[i] > 255) ? 255 : tmp[i];
        }
    
    
        return tmp;
    
      }
    };
    
          
    //! @brief width 画像横画素数
    //! @brief height 画像縦画素数
    //! @param [in] pimg 入力画像
    //! @param [out] dst 出力先
    //! @return なし
    void sobel(
      const int width,
      const int height,
      const unsigned char* pimg,
      unsigned char* dst
    ) {
    
    
      SobelFilter sf(width, height, pimg);
    
      size_t sz = SobelFilter::PixelSize;
    
      for (int x = 1; x < width - 1; x++) {
        for (int y = 1; y < height - 1; y++) {
    
          SobelFilter::Vector3d px = sf.get(x, y);
    
          for (size_t p = 0; p < sz; p++) {
            dst[(y * width + x) * sz + p] = px[p];
          }
        }
    
      }
    }
    

    呼び出し例

    #include <iostream>
    
    #include <vector>
    
    #include "SobelFilter.hpp"
    
    #include "NByteData.hpp" // https://www.study.suzulang.com/2dcg-functions/nbyte-data-type
    
    #include "ppmP3_read.hpp" // https://www.study.suzulang.com/cppppm-readerwriter/ppm-p3-reader-cpp
    
    void ppmP3_write(
      const char* const fname,
      const int width,
      const int height,
      const unsigned char* const p,
      const int vmax
    );
    
    
    
    int main()
    {
      int width;
      int height;
      int vmax;
    
      unsigned char* pimg;
      ppmP3_read("C:\\data\\b.ppm", &width, &height, &vmax, &pimg);
    
      std::vector<unsigned char> ret(width * height * 3);
      sobel(width, height, pimg, ret.data());
    
      ppmP3_write("C:\\data\\sobel.ppm", width, height, ret.data(), 255);
    
    
      std::cout << "Hello World!\n";
    }
    
    //! @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);
    }
    

    Joomla 3 のGantry 5に追加のcssファイルを導入する

    Step 1. custom.scssファイルを用意する

    Gantry 5 にはcssではなくscssを指定する。

    SCSSについての説明は、とりあえず極限まで簡略化すると、SCSSの文法はCSS+書きやすい新たな構文 という感じなので、ひとまず拡張子を.cssから.scssにするだけで良い。

    説明を読むとcssも受け付けるというようなことを書いてあったのだが、試した限りだと上手くいかない。

    そして、ファイル名を「custom.scss」とした上で、内容に以下の一行を記述する。

    @import "dependencies";

    Step 2. 実際に使用したい、スタイルを記述したcssファイルを用意し、ファイル名を変更

    .scssに拡張子を変更する事に加え、ファイル名の先頭に_を加える

    変更前:

    textcolor.css

    変更後:

    _textcolor.scss

    Step 3. custom.scssファイルに、使用したいcssファイルの指定を加える

    最初のステップで作成したcustom.scssファイルの次の行に、_と拡張子.scssを除いたスタイルの記述されたファイル名を指定する。

    ここまでで、custom.scssの内容は以下のようになる。

    @import "dependencies";
    @import "textcolor";

    ここまでのまとめ

    custom.scssに、スタイルを記述したscssファイルを指定する。

    Step 4. 自分が使っているテーマを確認

    テーマを見て、g5_heliumといったテーマ名を確認する。

    Step 5. FTPで上記scssファイルをアップロード

    以下のディレクトリへ、二つのscssファイルをアップロードする。

    ROOT/templates/DEFAULT_TEMPLATE/custom/scss/

    例えば、

    www/mywebsite/templates/g5_helium/custom/scss/

    scss/ディレクトリがない場合は自分で作成する。

    アップロードが終わると、以下の構成になっている

     

    www/mywebsite/templates/g5_helium/custom/scss/custom.scss

    www/mywebsite/templates/g5_helium/custom/scss/_textcolor.scss

     

    Step 6. Gantry 5の設定からscssのコンパイル

    scssファイルはスタイルそのものではなく、「cssに近い文法で書ける、cssを生成するためのメタ言語であり、cssにコンパイルして使用する」。

    なのでGantry 5 の設定画面でコンパイルする。

    適用したいアウトラインを選択

    Clear Cache

    画面右、Extras→Clear Cacheでキャッシュをクリアする

    コンパイル

    Stylesの画面右、Recomple CSSをクリックする。

    結果

    画像の追加について

    以下のディレクトリにテンプレートに使用する画像を入れるらしい。

    www/mywebsite/templates/TEMPLATE_DIR/custom/images/picture.png

    参考

    How to add Custom CSS/SCSS in Gantry 5 Theme

    https://www.rcatheme.com/documentation/gantry5/how-to-add-custom-css-scss-in-gantry5-theme

    Creating Custom File Overrides

    https://docs.gantry.org/gantry5/advanced/file-overrides

    グレイスケール値をサーモグラフィーのように表示

    thermography.h

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

    ppmP3_read.hpp

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

    WordPress 5.8 以降でwebpをアップロードできない時の対応

    環境

    ・さくらのレンタルサーバー

    ・Wordpress 5.9

    現象

    WordPress 5.8 からwebpに正式対応している。にもかかわらずwebpファイルをアップロードできない問題に遭遇した。

    より具体的に言うと、一枚画像は転送できるが、アニメーションwebpは転送できないという状況に遭遇した。

    サーバーが画像を処理できません。このエラーは、サーバーが忙しいか、タスクを完了するために十分なリソースがない場合に発生します。小さな画像をアップロードすれば解決するかもしれません。推奨する最大サイズは2560ピクセルです。

    対応

    WordPressがWebPを使えるためには、サーバー側でImageMagickを有効にしていなければいけない。

    さくらのレンタルサーバーの場合デフォルトでは無効になっているので、以下の手順で有効化する。

    1.コントロールパネルへログイン

    https://secure.sakura.ad.jp/rs/cp/

    extension = imagick.so

    アップロード例

    アニメーションgif版:17.5MB

    webp版:210KB

    参考

    WordPressのWebP対応に関する記述

    In WordPress, the lossless WebP format is only supported when the hosting server uses Imagick (the PHP library) until LibGD adds support.

    https://make.wordpress.org/core/2021/06/07/wordpress-5-8-adds-webp-support/

    さくらのレンタルサーバーでimagickを有効にする手順