ぬの部屋(仮)
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
           
  • Blender pythonで全て三角形と考えてmeshの三角形を取得する

    blender のメッシュはNgonが可能なので、三角形だけカウントすると四角形以降がカウントされなかったりする。

    mesh.calc_loop_triangles()関数を使えば、全て三角形として頂点を取り出すことができる。

    注意点としてこれを呼び出したからと言ってモデルが三角形メッシュになるわけではないらしい。また三角形メッシュに変換した結果とこの結果が異なったりする。

    import bpy
    
    
    # @brief メッシュを構成する三角形を三頂点の組み合わせのリストで取得
    # @param [in] obj オブジェクト
    def get_triangles(obj):
        ret = []
        mesh = obj.data
        mesh.calc_loop_triangles()
        for tri in mesh.loop_triangles:
            ret.append([tri.vertices[0],tri.vertices[1],tri.vertices[2] ])
            
        # [index0,index1,index2]のリスト
        return ret
    
    
    # @brief 与えられたオブジェクトの重心を求める
    # @param [in] obj オブジェクト
    # @param [in] vid0 obj.data.verticesのindex
    # @param [in] vid1 obj.data.verticesのindex
    # @param [in] vid2 obj.data.verticesのindex
    # @return 三次元座標 <Vector ( x , y , z )>
    def calc_triangle_center(obj,vid0,vid1,vid2):
        mesh = obj.data
        
        tri_center = (mesh.vertices[vid0].co) +\
                     (mesh.vertices[vid1].co) +\
                     (mesh.vertices[vid2].co)
        tri_center /= 3.0
        
        return tri_center
    
    
    # @brief オブジェクトの全ての三角形の重心にsphereを配置する
    # @param [in] オブジェクト
    def disp_triangle_centers(obj):
        
        # 三角形をindex listで取得
        PIDs = get_triangles(obj)
        
        for pid in PIDs:
            # 三角形の重心を算出
            c = calc_triangle_center(obj, pid[0],pid[1],pid[2])
            
            # 座標 c にsphereを配置
            bpy.ops.mesh.primitive_uv_sphere_add(
                radius=0.05,
                segments=8,
                ring_count=8,
                enter_editmode=False, 
                location=c
                )
            
    
    # 使用例
    myobj = bpy.context.active_object
    disp_triangle_centers(myobj)
    

    Gimp Script-fuのスクリプトをGUIに登録して使えるようにする

    スクリプトの保存先を確認

    スクリプト本体

    まずコードを用意して、上記フォルダへ適当な名前で保存する

    例 script-test.scm

    ; 画像をPNG保存する自作関数。この関数を呼び出したい
    ; Image 画像番号
    ; Drawable レイヤー番号
    ; outpath 保存先(ファイル名を含まない)
    ; filename ファイル名(.pngを含まない)
    (define (my-save-to-png Image Drawable outpath filename)
      ; 保存処理
      (file-png-save-defaults
        RUN-NONINTERACTIVE
        Image
        Drawable
        (string-append outpath filename ".png")
        (string-append filename ".png") 
      )
    )
          
          
    ; GUIダイアログの項目を設定
    ;; 参考 http://sampodo.la.coocan.jp/graphics/gimp2/gimp2_1.html
    (script-fu-register
    
      ;
      ; 呼び出す関数
      ; メニュー上の情報
      ; ダイアログの項目設定
      ;
    
      "my-save-to-png"                ;呼び出す関数
      
      "PNGで保存"                     ;メニューに表示する項目
      "テスト用スクリプト\
       の説明文"                      ;説明文章
      "空鳥夜鳥"                      ;制作者
      "copyright 2021, szl"           ;著作編表示
      "2021/11/08"                    ;制作日時
      "*"                             ;スクリプト関数が扱う画像のタイプ
      
      ; 以降、引数を指定するGUIパーツの作成、個数は任意。
      ;
      ; 呼び出す関数が my-save-to-png であるので、
      ; my-save-to-png の引数の順番と同じでなければいけない
      ; 
      ; 指定方法 : 
      ; GUIアイテムの種類   "表示用ラベル"   デフォルト値
      
      SF-IMAGE         "Image"        0
    SF-DRAWABLE "Drawable" 0 SF-STRING "パス\\" "C:\\test\\" ; テキストボックスになる SF-STRING "ファイル名" "default-name" )
          
          
    ; メニューに登録する
    (script-fu-menu-register
    
      ; 呼び出す関数名
      "my-save-to-png"
      
      ; メニューのどの位置に項目を挿入するか
      "<Image>/File/オリジナル項目"
    )
    

    スクリプトを再読み込み

    結果

    gimp script-fuでレイヤーごとにファイルに保存するスクリプト

    save-layers関数を作成。

    ;; レイヤー一覧取得
    ;; image (car (gimp-image-list)) で取得
    (define (get-layer-list image)
      (vector->list 
        (car 
          (cdr 
            (gimp-image-get-layers image)
          )
        )
      )
    )
    
          
    ;; outpath 出力先のディレクトリ
    ;; filename ファイル名 拡張子なし
    ;; image 画像番号
    ;; drawablelayer レイヤー番号
    (define (save-to-image outpath filename image drawablelayer)
      (begin
        ; 保存情報を表示
        (display "saving:")
        (display (string-append outpath filename ".png") )
        (newline)
      
        ; 保存処理
        (file-png-save-defaults
          RUN-NONINTERACTIVE
          image
          drawablelayer
          (string-append outpath filename ".png")
          (string-append filename ".png") 
        )
      )
    )
    
          
    ;; outpath 出力先のパス
    ;; image 画像番号
    ;; layerlist 残りのレイヤー一覧 
    (define (save-more-layers outpath image layerlist)
    
      ; 画像一覧が空リストでないなら保存
      (if (not (null? layerlist) )
        (begin
              
          ; リストの先頭要素をPNGで保存
          (save-to-image 
            outpath                                     ; 出力先パス
            (car (gimp-layer-get-name (car layerlist))) ; ファイル名としてレイヤー名を取得
            image                                       ; 画像番号
            (car layerlist) )                           ; レイヤー番号リストの一番左
    
          ; 残りのリストを保存(再帰)
          (save-more-layers
             outpath           ; 出力先パス
             image             ; 画像番号
             (cdr layerlist) ) ; 残りのリスト
          ;
        )
      )
    )
    
          
    ;; レイヤーをPNGファイルに保存する関数
    ;; outpath ファイルパス 例 C:\\test\\
    ;; image 画像番号 (car (gimp-image-list))で取得可
    (define (save-laysers outpath image)
      (save-more-layers 
         outpath 
         image
         (get-layer-list image) ) )
        
    

    Gimp Script-fuで画像ファイルを読み込んでxcf保存

    パスの文字列を加工したりとかいろいろ複合的に使ってみたやつ。

    ;----------------------------------
    ;----------------------------------
    ; フォルダから画像を読み込む
    
    ; ファイルパスからファイル名を取得する
    (define (my-extract-file-name text)
      (car (reverse (strbreakup text "\\") ) )
    )
    
    
    ; 画像を読み込んだ後、タブを表示する
    (define (my-tab-update image)
      (begin
        (gimp-display-new image)
        (gimp-displays-flush)
        image
      )
    )
    
    ; リストで与えられた画像ファイルを全て読み込む
    (define (my-open-all-images flist)
      (if (null? flist)
        '()
        (cons
          (my-tab-update (car (gimp-file-load 0 (car flist) (my-extract-file-name (car flist) ) ) ) )
          (my-open-all-images (cdr flist) )
        )
      )
    )
    
    ; パスで指定したディレクトリから画像を読み込む。
    ; パスの最後は\\*で終わっている必要がある 
    ; 例 (my-open-images "C:\\dev\\*")
    (define (my-open-images pathnamelist)
      ( my-open-all-images (car (cdr (file-glob pathnamelist 0))) )
    )
    
    ;----------------------------------
    ;----------------------------------
    ; 画像をxcf形式で保存する
    
    ; 画像を一枚xcf形式で保存する。
    ; ファイル名は元の名前+xcf
    (define (my-save-as-xcf-single image outdir basename)
      (gimp-xcf-save
        0
        image
        (car (gimp-image-get-active-drawable image) )
        (string-append outdir basename ".xcf")
        (string-append basename ".xcf")
      )
    )
    
    ; outdirへ画像群を保存。outdirは"\\"で終わっている必要がある
    (define (my-save-images outdir images)
      (if (null? images)
        '()
        (begin
          (my-save-as-xcf-single
            (car images)
            outdir
            (my-extract-file-name (car (gimp-image-get-filename (car images) ) ) ) ;画像番号からファイルパスを取得しファイル名を切り出す
          )
          (my-save-images outdir (cdr images) )
        )
      )
    )
    
    
    ;(my-save-as-xcf-images "H:\\input\\*" "H:\\output\\")
    (define (my-save-as-xcf-images indir outdir)
      (my-save-images
        outdir 
        (my-open-images indir)
      )
    )
    

    Gimp Script-Fuでxcf保存(gimp-xcf-save)

    保存にはgimp-xcf-saveを使う。

    ; 画像番号は (gimp-image-list) で取得できる数字。今回は「1」
    (gimp-xcf-save 
      0                                        ; ダミーパラメータ
      1                                        ; 画像番号
      (car (gimp-image-get-active-drawable 1)) ; 有効にしたいレイヤー(現在選択中のレイヤー)
      "c:/data/test.xcf"                       ; 保存ファイル名 URI形式
      "test.xcf"                               ; 保存ファイルのベース名
    )
    

    第一引数はダミーパラメータ。0でも入れておけばいい

    第二引数は保存したい画像。一度に複数の画像を開いていたり、開いた画像のいくつかを閉じたりすると「1」の画像がなくなる可能性がある。ので、「gimp-image-list」で確認するといい

    第三引数はアクティブにしたいレイヤー。(gimp-image-get-active-drawable image)で取得するのが無難。

    第四引数は保存するファイル名。URI形式で指定。

    第五引数はベースファイル名(ファイル名+拡張子)だが色々指定したが無視されているようにしか思えない。

    画素番号と画像幅からx,y座標を求める…のをScript-Fuでやる

    式自体は何のことはない。問題はGimpのScript-Fuでやりたいので結構手間取った。

    さすがにGimpのScript-Fuコンソールから実験するのは環境が悪すぎたので、RacketをインストールしてScheme環境を作った。

    https://racket-lang.org/

    Scheme版

    remainderは剰余。

    ;; 画素番号と画像幅からx座標を計算
    (define (getx pos width)
      (remainder pos width)
    )
    
    ;; x座標と画素番号と画像幅からy座標を計算し、x,yで返す
    (define (getxy x pos width)
      (list
        x
        (/ (- pos x) width)
      )
    )
    
    ;; 画素番号と画像幅からx,y座標を計算する
    (define (2dcoord pos width)
        (getxy (getx pos width) pos width)
    )
    

    Gimp Script-Fu上で実行

    width=50の画像の1162番のx,y座標は(12,23)。

    C++版

    // x,yから画素番号を算出
    inline int calcpos(int x, int y,int width) {
      return
        y * width + x;
    }
    
    // 画素番号と画像幅からx座標を計算
    int getx(int pos, int width) {
      return pos % width;
    }
    
    // 画素番号とx座標と画像幅からy座標を計算
    int gety(int x, int pos, int width) {
      return (pos - x) / width;
    }
    
    
    int main()
    {
      int width = 50;
      int height = 25;
    
      int x = 12;
      int y = 23;
    
      int pos = calcpos(x, y, width); //1162
    
      printf("pos %d\n", pos);
    
      int xx = getx(pos, width);
      int yy = gety(xx, pos, width);
    
      printf("xx %d\n", xx);
      printf("yy %d\n", yy);
    
    }
    

    Gimp Script-Fu 画像レイヤー,テキストレイヤー , パスをそれぞれ取得

    パス一覧

    パス一覧は (gimp-image-get-vectors 画像番号) で取得できる

    > (gimp-image-get-vectors 1)
    (2 #(10 9))
    > (gimp-layer-get-name 10)
    ("パス(曲線)")
    > (gimp-layer-get-name 9)
    ("パス(写真1)")

    レイヤー一覧

    gimp-image-get-layersで取得できるのだが、vectorではなくlistでほしいのでラップする。

    ; レイヤー一覧
    (define (get-layer-list image)
      (vector->list 
        (car 
          (cdr 
            (gimp-image-get-layers image)
          )
        )
      )
    )
    
    > (get-layer-list 1)
    (8 7 2 22)

    レイヤー一覧から、テキストレイヤーの一覧を取得する

    レイヤーに対して、gimp-drawable-is-text-layerでテキストレイヤーかどうかを判定できる。

    ; imagelistの中からテキストレイヤーだけを抽出する
    (define (get-text-layers imagelist)
      (if ( null? imagelist )
        '()
         (if (= 1 (car (gimp-drawable-is-text-layer (car imagelist) ) ) )
           (cons
             (car imagelist)
             (get-text-layers (cdr imagelist) )
           )
           (get-text-layers (cdr imagelist) )
         )
      )
    )
    
    > ( get-text-layers (get-layer-list 1) )
    (8 7)
    > (gimp-layer-get-name 8)
    ("青")
    > (gimp-layer-get-name 7)
    ("写真1")

    GimpのScript-Fuで画素を書き換える

    Script-Fuは フィルター → Script-Fu → Script-Fu コンソール からコンソールのウィンドウを開き一行ずつ入力できる。

    初めてのGimpのスクリプト。

    スクリプト

    ;; 画像一覧
    (define Images (vector->list (car (cdr (gimp-image-list)))))
    (define ImageIndex (car Images) )
    
    ;; ImageIndex内のレイヤー一覧
    (define Layers (vector->list (car (cdr (gimp-image-get-layers ImageIndex)))))
    (define LayerIndex (car Layers) )
    
    ;; 編集対象は以後Drawable
    (define Drawable LayerIndex)
    
    ;; 画像サイズ確認
    (gimp-drawable-width Drawable)
    (gimp-drawable-height Drawable)
    
    ;; 座標
    (define x 10)
    (define y 10)
    
    ;; ピクセルの更新
    (gimp-drawable-set-pixel Drawable x x 3 #(255 0 0) )
    (gimp-displays-flush)
    (gimp-drawable-update Drawable x y 1 1)
    

    実行結果

    参考

    https://developer.gimp.org/api/2.0/libgimp/libgimp-gimpdrawable.html

    std::variant

    C++でバリアント型を使う。C++17以降。

    基本的な使い方

    #include <cstdio>
    #include <string>
    #include <variant>
    
    enum VARIANT_TYPES {
      V_INT = 0,
      V_STR = 1,
      V_DBL = 2
    };
    
    int main()
    {
    
      std::variant<int, std::string, double> val;
    
      val = 2;
      //val = 5.5;
      //val = "abc";
    
      if (val.index() == V_INT) {
        int& x = std::get<V_INT>(val);
        printf("--- %d\n", x);
      }
    
    else if(val.index()==V_STR){ std::string& s = std::get<V_STR>(val); printf("--- %s\n", s.c_str()); }
    else if (val.index() == V_DBL) { double& d = std::get<V_DBL>(val); printf("--- %lf\n", d); } int k = getchar(); }

    std::visit

    std::variant型を引数で取る関数を作ってもいいが、std::visit関数でoperator()を定義したクラスのインスタンスを渡して呼び出す方が美しいらしい。

    #include <cstdio>
    #include <string>
    
    #include <variant>
    
    
    
    struct Print {
    
      // int が代入されたときに呼び出される
      void operator()(const int& data) {
        printf("--- %d\n", data);
      }
    
      // std::string が代入されたときに呼び出される
      void operator()(const std::string& data) {
        printf("--- %s\n", data.c_str());
      }
    
      // double が代入されたときに呼び出される
      void operator()(const double& data) {
        printf("--- %lf\n", data);
      }
    
    };
    int main()
    {
    
      std::variant<int, std::string, double> val;
    
      val = 2;
      std::visit(Print(), val);
    
      val = 5.5;
      std::visit(Print(), val);
    
      val = "abc";
      std::visit(Print(), val);
    
      int k = getchar();
    }
    

    std::visitは第一引数に関数、第二引数以降はstd::variant型でなければならない(らしい)。

    std::visit( 関数() , variant1 , variant2 , variant3 , … )

    なので、std::visitの引数で渡す場合、std::variantで渡さなければいけない。

    #include <cstdio>
    #include <string>
    
    #include <variant>
    
    
    struct Print {
    
      // int が代入されたときに呼び出される
      void operator()(const int& data) {
        printf("--- %d\n", data);
      }
    
      // std::string が代入されたときに呼び出される
      void operator()(const std::string& data) {
        printf("--- %s\n", data.c_str());
      }
    
      // double が代入されたときに呼び出される
      void operator()(const double& data) {
        printf("--- %lf\n", data);
      }
    
    };
    
    
    struct Add {
    
      // int が代入されたときに呼び出される
      void operator()(int& data, const int val) {
        data += val;
      }
    
      // std::string が代入されたときに呼び出される
      void operator()(std::string& data, const int val) {
        data += std::to_string(val);
      }
    
      // double が代入されたときに呼び出される
      void operator()(double& data, const int val) {
        data += val;
      }
    
    };
    int main()
    {
    
      std::variant<int, std::string, double> val;
    
    
      val = 2;
      std::visit( Add(), val,std::variant<int>(4) );
      std::visit(Print(),val);
    
      val = 5.5;
      std::visit( Add(), val, std::variant<int>(4));
      std::visit(Print(), val);
    
      val = "abc";
      std::visit( Add(), val, std::variant<int>(4));
      std::visit(Print(), val);
    
      int k = getchar();
    }
    

    引数を渡すならコンストラクタに渡した方がスマートだと思う。

    #include <cstdio>
    #include <string>
    
    #include <variant>
    
    
    
    struct Print {
    
      std::string _sign;
    public:
      Print(const std::string& sign):_sign(sign) {}
    
      // int が代入されたときに呼び出される
      void operator()(const int& data) {
        printf("%s %d\n",_sign.c_str(), data);
      }
    
      // std::string が代入されたときに呼び出される
      void operator()(const std::string& data) {
        printf("%s %s\n", _sign.c_str(), data.c_str());
      }
    
      // double が代入されたときに呼び出される
      void operator()(const double& data) {
        printf("%s %lf\n", _sign.c_str(), data);
      }
    
    };
    int main()
    {
    
      std::variant<int, std::string, double> val;
    
    
      val = 2;
      std::visit(Print(">>"),val);
    
      val = 5.5;
      std::visit(Print(">>"), val);
    
      val = "abc";
      std::visit(Print(">>"), val);
    
      int k = getchar();
    }
    

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

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