ぬの部屋(仮)
nu-no-he-ya
  •      12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    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
           
  • Rustのenumについて学んだ話(3) 混ぜて使う

    enumにはCのunion的な使い方とCのenum的な使い方の両方があるということが分かったが、これを混ぜて使うことも多い。

    // 色を表現する構造体 RGB
    #[derive(Copy,Clone,PartialEq)]
    struct RGB{
      r:i32,g:i32,b:i32
    }
    impl RGB{
      fn New(R:i32,G:i32,B:i32)->RGB{return RGB{r:R,g:G,b:B};}
    }
    
    //////////////////////////////////////////////////
    
    // 色を表現する構造体 HSV
    #[derive(Copy,Clone,PartialEq)]
    struct HSV{
      h:f32,s:f32,v:f32
    }
    impl HSV{
      fn New(H:f32,S:f32,V:f32)->HSV{return HSV{h:H,s:S,v:V};}
    }
    //////////////////////////////////////////////////
    
    
    // 画像のピクセルを入れる型
    // RGBの任意の値、HSVの任意の値 に加え、定数Invalid のどれかを入れることができる
    // Invalid(i32) と書き直すと少し理解がし易いが、入るのはInvalid一つだけなので意味的には違う
    //        (概念的にはInvalidがたまたまi32にキャストできるだけで、i32を入れられるわけではないので)
    #[derive(Copy,Clone,PartialEq)]
    enum PixelInfo{
      ColorRGB(RGB),    // RGBを入れる場合 RGB型の変数ColorRGB
      ColorHSV(HSV),    // HSVを入れる場合 HSV型の変数ColorHSV
      Invalid,          // 定数を定義  RGBが無効のときはこれを入れておく事
    }
    //////////////////////////////////////////////////
    
    fn main() {
    
      let mut pixel:PixelInfo;
    
      // ピクセルを使うかどうかを決める
      let unuse:bool = false;
    
      if unuse {
        // 使わないときはInvalidを入れておく
        pixel = PixelInfo::Invalid;
      }
      else{
        // 色を指定
        pixel = 
          PixelInfo::ColorRGB(
            RGB::New(
              255,
              0,
              0,
            )
          );
    
      }
    
    
    
      if pixel == PixelInfo::Invalid{
        // ピクセルが無効なら対応した処理を行う
        println!("the pixel is invalid");
      }
      else if let PixelInfo::ColorHSV(c) = pixel{
        // ピクセルが有効ならパターンマッチでcを定義して色を取得
        println!("color HSV = ({} {} {})",c.h,c.s,c.v);
      }
      else if let PixelInfo::ColorRGB(c) = pixel{
        // ピクセルが有効ならパターンマッチでcを定義して色を取得
        println!("color RGB = ({} {} {})",c.r,c.g,c.b);
      }
    
    }
    

    C++で似たようなコードを書くと、たぶん以下のようになる。

    #include <iostream>
    
    struct RGB {int r, g, b;};
    struct HSV {float h,s,v; };
    
    union PixelInfo {
      RGB rgb;
      HSV hsv;
    
      // この定数も取れるようにする
      enum {
        INVALID,
      }Invalid;
    };
    
    int main()
    {
      PixelInfo pi;
    
      pi.rgb = { 255, 255, 255 }; // 他の物を入れると無効になる
    
      pi.Invalid = PixelInfo::INVALID;
    
      std::cout << pi.Invalid;
    }
    

    [速報]CLaunchとVisual C++の相性問題が解決したかもしれない話

    ぴょんきち 氏が開発、公開しているCLaunch。

    http://hp.vector.co.jp/authors/VA018351/claunch.html

    どうやら2023/08/11に最新バージョン4.05がリリースされた模様。

    http://hp.vector.co.jp/authors/VA018351/whatsnew.html

    以前、VC++との相性がやたらと悪いという話をした

    のだが、五日間ほどVC++2022,Win32APIの開発時に併用してみたところ、一度も問題が起こらなかったので、解決しているのかもしれない。元々再現性100%ではないので断言できないのだが、間違いないとすればこれは朗報。ありがとうございます。

    Rustのenumについて学んだ話(2) Cのenumとしての使い方

    Rustのenumは高機能なunionという話が前回で、それとは別に、C/C++のenumのような使い方もできる。

    // Rust の enum は、C言語のenumのように特定の値を持つ定数のみを取れる型を定義するように使用できる。
    // ただし、指定できるのは整数のみで、f32やstring等は不可
    enum AsciiCode{
      AsciiA = 65,
      AsciiB = 66,
      AsciiC = 67,
    }
    
    
    fn main() {
    
      // cu を定義。入れられるのはAsciiA,B,Cのいずれかのみ
      let mut cu:AsciiCode = AsciiCode::AsciiA;
    
      cu = AsciiCode::AsciiB;
    
      // この場合もパターンマッチで比較する
      if let AsciiCode::AsciiA=cu{
        println!("AsciiA is used." );
      }
      else{
        println!("Not A." );    
      }
    
      // 数値を取り出すときは as をつける
      println!("cu is {}",cu as i32);
    
    }
    

    なお、変数同士を比較するには、==を使うが、デフォルトでは実装されていないので、PartialEqを指定する。

    // 変数同士を比較するときは、==を使うためにPartialEqを指定
    #[derive(PartialEq)]
    enum AsciiCode{
      AsciiA = 65,
      AsciiB = 66,
      AsciiC = 67,
    }
    
    
    fn main() {
    
      // cu を定義。入れられるのはAsciiA,B,Cのいずれかのみ
      let cu:AsciiCode = AsciiCode::AsciiA;
    
      let rs:AsciiCode=AsciiCode::AsciiB;
    
      // == で比較できる
      if rs == cu{
        println!("same");
      }
      else{
        println!("not same");
      }
    
    }
    

    注意点として、この記法 enum TYPE{ NAME= 65, } で指定できるのは整数のみで、f32などは入れられない。どうもこの表記自体はenumの本来の使い方としてはややずれているようで、Cなどのほかの言語との歩調を合わせるのがこの表記法が可能な主な理由だという(話があった)。

    なお、数値を指定しなくても使える。as i32すれば整数にもなるが、あまりこれを前提としたコードを書くべきとは思えない。

    // 型も値も指定しないバリアントを持てる。
    // ==を使うためにPartialEqを指定
    // as i32をするとmoveされてしまうのでCopyも指定。CopyのためにCloneも指定。
    #[derive(Copy,Clone,PartialEq)]
    enum AsciiCode{
      AsciiA,
      AsciiB,
      AsciiC,
    }
    
    
    fn main() {
    
    
      println!("A as int {}",AsciiCode::AsciiA as i32);
      println!("B as int {}",AsciiCode::AsciiB as i32);
      println!("C as int {}",AsciiCode::AsciiC as i32);
    
      // cu,rs を定義。入れられるのはAsciiA,B,Cのいずれかのみ
      let cu:AsciiCode = AsciiCode::AsciiA;
      let rs:AsciiCode = AsciiCode::AsciiB;
    
      // == で比較した例
      if rs == cu{
        println!("same");
      }
      else{
        println!("not same {} vs {}",cu as i32,rs as i32);
      }
    
    }
    
    A as int 0
    B as int 1
    C as int 2
    not same 0 1

    Rustのenumについて学んだ話(1) unionとしての使い方

    Rustのenumには三つの使い方がある。

    まずはC言語におけるunionに近い使い方。

    以下ではC_Union_Like型を定義しているが、この変数はi32,f32,Stringの「いずれか一つ」を代入することができる。

    // Rust の enum は、C言語のunionに近い使い方ができる。
    // 以下ではivalue,fvalue,svalueの三つのバリアントを定義しているが、
    // 一度に有効なのは一つだけ。
    enum C_Union_Like{
      ivalue(i32),
      fvalue(f32),
      svalue(String),
    }
          
          
    fn main() {
    
      // C_Union_Likeのivalueにi32を入れる。
      let mut cu:C_Union_Like = C_Union_Like::ivalue(33);
    
      // fvalueに入れたので、cuはf32を持つようになった
      cu = C_Union_Like::fvalue(7.5);
    
      // svalueに入れたので、cuはStringを持つようになった
      cu = C_Union_Like::svalue("hello".to_string());
    
    
      // cuは三つのバリアントを持つが、一度に有効なのは一つだけ。
      // cu がどの値を持っているかを知る方法は
      // パターンマッチングでマッチするかで判断する
    
      // cu が ivalue にマッチするなら、iiを定義し、ivalueの値を代入
      if let C_Union_Like::ivalue(ii)=cu {
        println!("int is used. {}",ii);
      }
      else if let C_Union_Like::fvalue(ff)=cu{
        println!("float is used. {}",ff);
      }
      else if let C_Union_Like::svalue(ss)=cu{
        println!("String is used. {}",ss);    
      }
    
    }
    

    このプログラムは、C/C++における以下に近い。

    struct C_Union_Like {
    
        int type;
        union {
            int ivalue;
            float fvalue;
            //std::string svalue; // これはC++ではできないが、Rustならできる
        };
    };
    
    
    int main()
    {
    
        C_Union_Like cu;
    
        cu.type = 0;
        cu.ivalue = 33;
    
        cu.type = 1;
        cu.fvalue = 7.5f;
    
        switch (cu.type) {
        case 0:
            printf("int is used. %d \n", cu.ivalue);
            break;
        case 1:
            printf("float is used. %d \n", cu.fvalue);
            break;
        }
    
    }
    

    Rustのenumは、C/C++のunionと違ってStringなどの複雑な型を取ることができる。さらに型情報も自動で持つので、unionのように自分で管理する必要がない。注意点として、今何が入っているかはパターンマッチングで判断する。上ではif letを使っているが、matchを使ってもよい。

    fn main() {
    
      // C_Union_Likeのivalueにi32を入れる。
      let mut cu:C_Union_Like = C_Union_Like::ivalue(33);
    
      // svalueに入れたので、cuはStringを持つようになった
      cu = C_Union_Like::svalue("hello".to_string());
    
      // fvalueに入れたので、cuはf32を持つようになった
      cu = C_Union_Like::fvalue(7.5);
    
    
    
      // cuは三つのバリアントを持つが、一度に有効なのは一つだけ。
      // cu がどの値を持っているかを知る方法は
      // パターンマッチングでマッチするかで判断する
    
      // cuの取りうるバリアントが多い場合はmatchのほうが読みやすい
      match cu{
        C_Union_Like::ivalue(ii) => {
          println!("int is used. {}",ii);
        },
        C_Union_Like::fvalue(ff) => {
          println!("float is used. {}",ff);
        },
        C_Union_Like::svalue(ss) => {
          println!("String is used. {}",ss);
        },
        _ =>{}
      }
    
    }
    

    Rustのパターンマッチングについて学んだ話 if let

    if let文について。

    端的にいうと、

    • if ... 式が true か false か で分岐を行う
    • if let ... パターンがマッチするか/しないか で分岐を行う

     

    fn main() {
    
      let mytuple=(3,4,5);
    
    
      // (3,4,何でもいい) というタプルと (3,4,5) というタプルはマッチするので
      // if節が実行される
      if let (3,4,_) = mytuple{
        println!("mached ");
      }
    
    
      // (3 ,second, 何でもいい) というタプルと、(3,4,5)はマッチするので
      // secondが定義されて、mytuple.1 が代入される
      if let (3,second,_) = mytuple{
    
        println!("second element is {} ",second);
      }
      
    
      // (4,second,何でもいい) というタプルは、(3,4,5)とマッチしないので、
      // else 節へ行く
      if let (4,second,_) = mytuple{
    
        println!("second element is {}",second);
    
      }
      else {
    
        println!("not matched");
    
      }
    
    
    }
    

    if let はパターンマッチで分岐するので、match文に近い。matchが複数のパターンと比較するが、比較の対象が一つだけの時は書きやすいようにif letが用意されている。

    あと、if letには網羅性がない。matchは網羅性があるので、必要なパターンを陳列し終わったら、「そのほかのケース」として_ を用意し、match文に用意された選択肢のどれか一つに必ずマッチするように書かなければならないが、ifはそうではない。

    fn main() {
    
      let mytuple=(3,4,5);
    
    
    
      // mytuple と (3,second,_)  のマッチ
      match mytuple{
        (3,second,_)=>println!("first = 3, second = {}",second),
        _ => (),
      }
    
      // mytuple と (3,second,_)  のマッチ。
      // 比較対象が一つだけならif letのほうが直観的
      if let (3,second,_) = mytuple{
        println!("first = 3, second = {}",second);
      }
    
    }
    

    Rustのパターンマッチングについて学んだ話

    Rustは構文のレベルでパターンマッチングをする言語で、しかも至る所でそれが出てくるので、パターンマッチングを受け入れないとコードを読めるようにならない。

    例えばmatch文。

    fn main() {
    
        let x:i32=5;
        let y:i32=10;
    
        // 「(5 , 10) というパターン」
        match (x,y){
    
            // (5,10) の内容が 「(5,10)」 に一致する場合
            (5,10)=> println!("Both x and y are 5 and 10, respectively."),
    
            // (5,10) の内容が 「(5,何でもいい)」 に一致する場合
            (5,_)=>  println!("x is 5, and y can be any value."),
    
            // (5,10) の内容が 「上記のパターン以外」 に一致する場合
            _ =>     println!("Neither of the above patterns match x and y."),
        }
    
    
        print!("{} {}",x,y);
    
    }
    

    これはなんとなくわかる。

    ところがRustには「パターンにマッチするか」だけではなく、「マッチして、それが変数だったらそこに値を拘束する」という機能もある。

    つまり以下は、

    ・「パターンマッチ」

    ・「value_of_yの変数宣言」

    ・「value_of_yへのyの代入」

    が同時に行われている。

    fn main() {
    
        let x:i32=5;
        let y:i32=7;
    
        // 「(5 , 10) というパターン」
        match (x,y){
    
            (5,10)=> println!("Both x and y are 5 and 10, respectively."),
    
            // パターンマッチングを行い、マッチした場合は値の拘束(変数の定義と代入)も行う
            (5,value_of_y )=>  println!("x is 5, and y is {}",value_of_y),
    
            _ =>     println!("Neither of the above patterns match x and y."),
        }
    
    }
    

    一事が万事この調子なので、変数を定義する機能だと思っていたletも、実はパターンマッチと、マッチした場合の値の拘束を同時に行う構文だということになる。

    だからlet文で変数定義をするときに_ (ワイルドカード)が使えてしまう。

    fn main() {
    
        // 例1
        // (x,y)というパターンと(3,5)はマッチする
        // マッチするので、
        // x に 3 を拘束
        // y に 5 を拘束
        // この二つを同時に行う。
        let (x,y)=(3,5);
    
    
        // 例2
        // (z,何でもいい) というパターンと (7,9) はマッチする
        // マッチするから 7 が z に 拘束される
        // _ はワイルドカードなので無視される。
        let (z,_)=(7,9);
    
        println!("{} {} {} ",x,y,z);
    
    }
    

    let文の=の右辺と左辺でパターンマッチを行い、拘束可能な部分は拘束する。拘束できないところは無視する。

    こんなもの何に使うんだと思うのだが、ある構造体なりタプルかなりから値を取り出したい、しかし全部取り出す必要はないときに、不要な変数宣言を省略できるという利点がある。

    fn main() {
    
        // 三つの三次元座標を用いて三角形を一枚定義
        let triangle_points = [
             (0,3,9), // 頂点1
             (7,0,6), // 頂点2
             (4,7,2)  // 頂点3
        ];
    
        // この三角形を Z 平面に投影した二次元座標を取得したい
        for p in triangle_points{
    
            // 三要素の p から前二つだけ取り出し、x,yに拘束
            // 三つ目の要素は z に入れるべきだが、不要なので _ を指定して省略。つまり変数 z は定義しない。
            let (x,y,_) = p;
    
            println!("{} {}",x,y);
    
        }
    
    }
    

    Rust的には、「比較するものとされるものがマッチするならコンパイルが通る」わけで、当然構造体でも同じ理屈が通用する。

    構造体の場合、無視の記号は .. を用いる。また構造体はフィールド名で値を選択するので、順番は気にしなくていい。

    struct Point {
        x: i32,
        y: i32,
        z: i32,
    }
    
    fn main() {
    
    
      let point = Point { x: 0, y: 7, z: 9 };
    
      // point からy座標だけ取り出したいので
      // y_coord変数を定義し、 point.y を拘束
      // .. により、ほかのフィールドは無視する
      let Point { y:y_coord, .. } = point;
    
      // point.y が取れているか確認
      println!("y value is {}",y_coord);
    
    
    }
    

    libavifを試す(4) avifファイルを入力

    avifファイルを入力するサンプルコードを書いた。

     

    #pragma comment(lib, "avif.lib")
    
    // 4996無効
    #define _CRT_SECURE_NO_WARNINGS
    
    
    #include <iostream>
    #include <avif/avif.h>
    #include <vector>
    
    void pnmP3_Write(const char* const fname, const int width, const int height, const unsigned char* const p);
    
    
    ///////////////////////////////////////////////////
    ///////////////////////////////////////////////////
    ///////////////////////////////////////////////////
    // libavif で RGBデータをavifデータに変換する
    
    
    
    int main()
    {
        ///////////////////////////////////////////////
        // avifのデコーダ
        avifDecoder* decoder = avifDecoderCreate();
    
        ///////////////////////////////////////////////
        FILE* f = fopen(R"(output.avif)", "rb");
        // avifファイルを全て読み込む
        fseek(f, 0, SEEK_END);
        long fsize = ftell(f);
        fseek(f, 0, SEEK_SET);  //same as rewind(f);
        void* fileBuffer = malloc(fsize);
        long bytesRead = (long)fread(fileBuffer, 1, fsize, f);
    
        ///////////////////////////////////////////////
        avifResult result;
        result = avifDecoderSetIOMemory(decoder, (uint8_t*)fileBuffer, fsize);
        result = avifDecoderParse(decoder);
        ///////////////////////////////////////////////
        // デコード結果を取得する
        printf("Parsed AVIF: %ux%u (%ubpc)\n", decoder->image->width, decoder->image->height, decoder->image->depth);
    
        ///////////////////////////////////////////////
        // avifは複数の画像を持つことができるので、画像一枚ごとにループする
        while (avifDecoderNextImage(decoder) == AVIF_RESULT_OK) {
    
            ///////////////////////////////////////////////
            avifRGBImage rgb;
            memset(&rgb, 0, sizeof(rgb));
            avifRGBImageSetDefaults(&rgb, decoder->image);
            ///////////////////////////////////////////////
            avifRGBImageAllocatePixels(&rgb);
            avifImageYUVToRGB(decoder->image, &rgb);
            ///////////////////////////////////////////////
            if (rgb.depth <= 8) {
                uint8_t* firstPixel = (uint8_t*)rgb.pixels;
    
                // 1画素4byteで格納されているので、 以下で画素を取得
                //r = firstPixel[i*4 + 0]
                //g = firstPixel[i*4 + 1]
                //b = firstPixel[i*4 + 2]
    
                pnmP3_Write("output.ppm", rgb.width, rgb.height, firstPixel);// ファイルに保存
    
            }
        }
    
        return 0;
    }
    
    
    //! @brief PPM(RGB各1byte,カラー,テキスト)を書き込む
    //! @param [in] fname ファイル名
    //! @param [in] width 画像の幅
    //! @param [in] height 画像の高さ
    //! @param [in] p 画像のメモリへのアドレス
    //! @details RGBRGBRGB....のメモリを渡すと、RGBテキストでファイル名fnameで書き込む
    void pnmP3_Write(const char* const fname, const int width, const int height, const unsigned char* const p) { // PPM ASCII
    
        FILE* fp = fopen(fname, "wb");
        fprintf(fp, "P3\n%d %d\n%d\n", width, height, 255);
    
        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 * 4 + 0], p[k * 4 + 1], p[k * 4 + 2]);
                k++;
            }
            fprintf(fp, "\n");
        }
    
        fclose(fp);
    }
    

    libavifを試す(3) avifファイルを出力

    avifを出力するサンプル。

    #pragma comment(lib, "avif.lib")
    
    // 4996無効
    #define _CRT_SECURE_NO_WARNINGS
    
    
    #include <iostream>
    #include <avif/avif.h>
    #include <vector>
    
    
    // RGBの画像データを作成
    std::vector<uint8_t> create_image(int width, int height) {
        std::vector<uint8_t> image(width * height * 3);
    
        for (int y = 0; y < height; ++y) {
            for (int x = 0; x < width; ++x) {
                int index = (y * width + x) * 3;
    
                float t = static_cast<float>(y) / (height - 1);
    
                uint8_t red = static_cast<uint8_t>(255 * (1.0 - t));
                uint8_t green = static_cast<uint8_t>(255 * t);
                uint8_t blue = 0;
    
                image[index] = red;
                image[index + 1] = green;
                image[index + 2] = blue;
            }
        }
    
        return image;
    }
    
    ///////////////////////////////////////////////////
    ///////////////////////////////////////////////////
    ///////////////////////////////////////////////////
    // libavif で RGBデータをavifデータに変換する
    
    
    
    int main()
    {
        std::vector<uint8_t> rgb_src;
        int width = 300;
        int height = 200;
        rgb_src = create_image(width, height);
    
        // RGBデータをエンコードする( YUVデータは入力しないという意味 )
        avifBool encodeYUVDirectly = AVIF_FALSE;
    
    
        // 今回はRGBデータを変換するサンプルとする
    
        if (encodeYUVDirectly == AVIF_FALSE) {
    
            ////////////////////////////////////////////
            // 変換後のデータの設定を行う
            int yuvDepth = 8;
            avifImage* dst_image = avifImageCreate(width, height, yuvDepth, AVIF_PIXEL_FORMAT_YUV444);
    
            ////////////////////////////////////////////
            // 変換前データの設定を行う
            avifRGBImage src_Image;
            avifRGBImageSetDefaults(& src_Image, dst_image);
            src_Image.format = AVIF_RGB_FORMAT_RGB;
            src_Image.pixels = rgb_src.data();
            src_Image.rowBytes = width * 3;
    
            // AVIFはYUV形式で表現するため、まずYUVデータに変換する
            avifResult result = avifImageRGBToYUV(dst_image, &src_Image);
            if (result != AVIF_RESULT_OK) {
                printf("Failed to convert RGB image to YUV: %s\n", avifResultToString(result));
            }
            ////////////////////////////////////////////
            // YUV形式のデータからAVIFのデータを生成
            avifEncoder* encoder = avifEncoderCreate();
            uint32_t quality = 90; // AVIFエンコード品質(0〜100)
            encoder->minQuantizer = AVIF_QUANTIZER_WORST_QUALITY - (uint8_t)(quality * 2.55);
            encoder->maxQuantizer = encoder->minQuantizer;
            ////////////////////////////////////////////
    
            // エンコード
            avifRWData output = AVIF_DATA_EMPTY;
            result = avifEncoderWrite(encoder, dst_image, &output);
            ////////////////////////////////////////////
    
            // 作成した画像をファイルに出力
            FILE* oFile = fopen("output.avif", "wb");
            fwrite(output.data, 1, output.size, oFile);
            fclose(oFile);
            ////////////////////////////////////////////
            // 終了処理
    
            if (dst_image) {
                avifImageDestroy(dst_image);
            }
    
            avifEncoderDestroy(encoder);
            if (output.data) {
                avifRWDataFree(&output);
            }
    
        }
    
        return 0;
    }
    
    
    

    libavifを試す(2)-libavifをビルド

    ダウンロード

    • libavif
      • https://github.com/AOMediaCodec/libavif/releases
      • 上記、Source code (zip) からダウンロード

     

    普通にCMakeする。インストールディレクトリなどを指定する。

    この時、以下のWarningが出る。

    CMake Warning at CMakeLists.txt:426 (message):
    libavif: No decoding library is enabled.

    aomの指定

    Searchにaomを入れるとAVIF_CODEC_AOMの項目を簡単に見つけられるので、ここにチェックを入れてConfigureする。

    するとAOM_INCLUDE_DIRとAOM_LIBRARYを指定できるので、ビルド済みのライブラリとincludeでぃれくとりを指定する。

    あとはConfigure , Generate ,Open Project , ALL_BUILD , INSTALL でインストールまで行く。

    libavifを試す(1)-libavifに必要なaomをビルド

    基本コンセプト

    極力開発環境に変更を加えずにaomをビルドする

    必須

    ダウンロード

    環境変数の設定

    上記したものはパスが通っている必要があるが、環境変数へ直接書き足すと今回のコンセプトに反するので、バッチファイルを作り、上記すべてが使えるコンソールを立ち上げることにする。

    上記すべてをどこかのパスに展開し、例えば以下のようなbatファイルを作り実行すると、パスの通ったコンソールが起動する。

    REM perl
    SET PATH=C:\Software\strawberry-perl-5.32.1.1-64bit-portable;%PATH%
    
    REM Git
    SET PATH=C:\Software\PortableGit\bin;%PATH%
    
    REM CMake-GUI
    SET PATH=C:\Software\cmake-3.25.0-rc2-windows-x86_64\bin;%PATH%
    
    REM nasm
    SET PATH=C:\Software\nasm-2.16.01;%PATH%
    
    REM strawberry-perl environment
    call portableshell.bat
    
    
    start cmd.exe
    

    ビルド

    まず、作業ディレクトリへ移動

    cd D:\myDevelop\aom-build
    D:\myDevelop\aom-build>

    git cloneでソースをダウンロード

    git clone https://aomedia.googlesource.com/aom

    cmakeする。コンソールからでももちろんいいが個人的に使い慣れているcmake-guiを起動。

    cmake-gui D:\myDevelop\aom-build\aom

    Configure → Generate → Open → ALLBUILD → INSTALL

    ビルドにやや時間がかかるが、D:\myDevelop\aom-build\install に各種includeファイルとaom.libが生成される。

    D:\myDevelop\aom-build
    ├─aom                  ... git cloneでダウンロードすると生成
    ├─install              ... INSTALL用に作成
    │  ├─bin
    │  ├─include
    │  │  └─aom
    │  └─lib
    └─solution             ... cmakeした結果格納用に作成