ぬの部屋(仮)
nu-no-he-ya
  •     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
           
  • ICUライブラリ+win32apiでutf16を一文字ずつ表示

    ICUライブラリで文字を一文字ずつ切り出したい。しかし切り出した結果をコンソール出力するのはもろもろの事情で難しく、ファイル出力は確認がめんどくさいのでウィンドウに描画する。

    #include <windows.h>
    
    #include <unicode/ucnv.h>
    #include <unicode/brkiter.h>
    
    // 要リンク
    #pragma comment(lib, "icuuc.lib")
    
    // 以下のdllを要求される
    // icudt69.dll
    // icuuc69.dll
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    WCHAR szClassName[] = L"MY_ICU_TEST";  //ウィンドウクラス
    
    LPCWSTR fontname = L"MS P ゴシック";
    
    HFONT hFont1;
    
    void WinPaint(HWND hWnd) {
    
      // 元の文字列の定義
      std::u16string u16s = u"aあغ山👨‍👧經经";
    
      /////////////////////////////
      // ICUの設定
    
      icu::UnicodeString usr(u16s.c_str());
    
      UErrorCode err;
      icu::BreakIterator* bi = icu::BreakIterator::createCharacterInstance(
        icu::Locale::getDefault(),err);
      bi->setText(usr);
    
      ////////////////////////////
      //フォトの設定
      HDC hdc;
      PAINTSTRUCT ps;
      hdc = BeginPaint(hWnd, &ps);
      SetTextColor(hdc, RGB(0, 0, 0));  //文字の色を設定
      SetBkColor(hdc, RGB(230, 230, 230));  //文字の背景色を設定
      HFONT backup = (HFONT)SelectObject(hdc, hFont1);  //フォントを適応
      TEXTMETRIC tm;
      GetTextMetrics(hdc, &tm);
      int TH = 10;
    
    //////////////////////////// //文字を一文字(書記素)ずつ表示
    int32_t current = bi->first(); while (current != icu::BreakIterator::DONE) { // 文字の長さを知る必要があるので、 // 「現在の文字の位置」と「前の文字の位置」が必要 int32_t prev = current; current = bi->next(); if (current == UBRK_DONE) { break; } int32_t count = current - prev;//文字の長さ //win32api のWCHARはutf16なのでただキャストするだけで変換できる TextOutW(hdc, 10, TH, (WCHAR*)(&u16s.data()[prev]), count);//文字を書く // こっちでもいい substr(現在位置,切り取る長さ) // std::u16string sub = u16s.substr(prev, count); // TextOutW(hdc, 10, TH, (WCHAR*)sub.data(), count);//文字を書く //改行 TH += tm.tmHeight+5; } SelectObject(hdc, backup); EndPaint(hWnd, &ps); }
    ////////////////////////////////////
    ////////////////////////////////////
    // 表示用
    ////////////////////////////////////
    ////////////////////////////////////
    
    
    int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) {
      MSG msg;
      BOOL bRet;
      WNDCLASSEX wc;
      HWND hWnd;
      ATOM atom;
    
      wc.cbSize = sizeof(WNDCLASSEX);
      wc.style = CS_HREDRAW | CS_VREDRAW;
      wc.lpfnWndProc = WndProc;
      wc.cbClsExtra = 0;
      wc.cbWndExtra = 0;
      wc.hInstance = hCurInst;
      wc.hIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
      wc.hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
      wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
      wc.lpszMenuName = NULL;
      wc.lpszClassName = (LPCWSTR)szClassName;
      wc.hIconSm = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
    
      if ((atom = RegisterClassEx(&wc)) == 0)return FALSE;
    
      hWnd = CreateWindow(
        MAKEINTATOM(atom), 
        L"icu test", 
        WS_OVERLAPPEDWINDOW, 
        CW_USEDEFAULT, CW_USEDEFAULT, 
        200, 500, // ウィンドウのサイズ
        NULL, NULL, hCurInst, NULL);
    
      if (!hWnd)return FALSE;
    
      ShowWindow(hWnd, nCmdShow);
      UpdateWindow(hWnd);
      while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
        if (bRet == -1) {
          break;
        }
        else {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
        }
      }
      return (int)msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
      switch (msg) {
      case WM_CREATE:
        //Step1  フォント作成
        hFont1 = CreateFont(
          50, 0, //高さ, 幅
          0, 0, FW_BOLD,
          FALSE, FALSE, FALSE,
          SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS,
          CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
          VARIABLE_PITCH | FF_ROMAN, fontname);
        break;
      case WM_PAINT:
        WinPaint(hWnd);
        break;
      case WM_DESTROY:
        DeleteObject(hFont1);   //Step4. HFONTオブジェクトを破棄
        PostQuitMessage(0);
        break;
      default:
        return (DefWindowProc(hWnd, msg, wp, lp));
      }
      return 0;
    }
    

    ICUライブラリのicu::UnicodeString::extractに指定するコードページにはどんなものがあるか

    ICUライブラリを使って文字コードの変換を行うとき、例えば日本固有の文字コードに変換したいなら「Shift_JIS」や「EUC-JP」、中国固有の文字コードなら「GBK」「EUC-CN」など、変換先の文字コードを指定しなければならない。この文字コード名を「コードページ」というらしいが、Shift_JISやEUC-JPの他にどんな物があるか。

    void test() {
    
      icu::UnicodeString us(u"いろはにほへと");
    
      const char* code_page = "Shift_JIS"; // コードページ。他にどんな物があるか。
    
      char dst_data[100];
      int32_t len = us.extract(0, us.length(), dst_data, code_page);
    
      printf("%s (%d) \n",dst_data,len);
    
    }
    

    コンバータ名一覧を取得する関数

    マニュアルを読むと、どうやらConverter Namesという呼称でコードページを与えるらしい。そして使える名前一覧を取得する関数がいくつか用意されているらしい。

    https://unicode-org.github.io/icu/userguide/conversion/converters.html#converter-names

    ucnv_openAllNames

    例えば、ucnv_openAllNames は

    Get a list of all known converter names.

    と、「全ての知られているコンバータ名を取得する」と書かれている。使い方はこんな感じ。

      auto name_enum = ucnv_openAllNames(&err);
    
      int32_t len;
      const char* name;
    
      while (name = uenum_next(name_enum, &len, &err)) {
        printf("%s\n", name);
      }
      uenum_close(name_enum);
    

    ucnv_openAllNamesでイテレータを取得して、uenum_nextでイテレータを前に進めるような使い方をする。

    ただこれで得られる内容は膨大すぎてよくわからない。

    ucnv_countAvailable

    次に、ucnv_countAvailable は

    Get a list of available converter names that can be opened.

    と、「使えるコンバータのリストを取得する」と書かれている。使い方はこんな感じ。

      int32_t convcount = ucnv_countAvailable();
      for (int32_t i = 0; i < convcount; i++) {
        printf("[%03d] %s\n",i, ucnv_getAvailableName(i));
      }
    

    これでも200個以上出てくる上に、Shift_JISなどわかりやすい物がない。

    ucnv_getAliases コードページの別名一覧を取得

    そもそも同じコードページにも複数の表記法があるらしい。例えばShift_JIS,CP932,Windows-31J,MS932は(ほぼ)同じ意味になる。 ucnv_getAliases はそんな、あるコードページの仲間のコードページを探す。

    int main()
    {
      UErrorCode err;
    
      const char* ALIAS = "Shift_JIS";   // 日本語のコードページ
    
    
      // ALIAS で表されるコードページの別名一覧を表示
      uint16_t acount = ucnv_countAliases(ALIAS, &err);
      for (auto i = 0; i < acount; i++) {
        const char* code_page_arias = ucnv_getAlias(ALIAS, i, &err);
    
        printf("-- %s\n", code_page_arias);
    
      }
      
      getchar();
    }
    

    出力:

    -- ibm-943_P15A-2003
    -- ibm-943
    -- Shift_JIS
    -- MS_Kanji
    -- csShiftJIS
    -- windows-31j
    -- csWindows31J
    -- x-sjis
    -- x-ms-cp932
    -- cp932
    -- windows-932
    -- cp943c
    -- IBM-943C
    -- ms932
    -- pck
    -- sjis
    -- ibm-943_VSUB_VPUA
    -- x-MS932_0213
    -- x-JISAutoDetect

    CP932 vs Shift_JIS

    Shift_JIS を ucnv_getAliases にかけるとエイリアスが大量に出てくるのだが違いがあるのかよくわからない。拡張文字の有無など微細な違いがあるらしいCP932とShift_JISにそれぞれ変換してみた。

    #include <fstream>
    #include <iostream>
    
    #include <unicode/ucnv.h>
    #include <unicode/unistr.h>
    #pragma comment(lib, "icuuc.lib")
    
    // 以下のdllを要求される
    // icudt69.dll
    // icuuc69.dll
    
    
    void Converter(const icu::UnicodeString& us,const char* dstCode) {
    
    
      //内部形式の文字コードを目的の文字コードへ変換
      char dst_data[100];
      int32_t len = us.extract(0, us.length(), dst_data, dstCode);
    
      printf("length: %d\n", len);
    
      std::string textname = "C:\\dev\\icu-test\\converted-";
      textname += dstCode;
      textname += ".txt";
      ///////////////////////////////
    // 文字コード変換した内容をファイル出力 std::fstream w( textname, std::ios::out | std::ios::binary | std::ios::trunc); w << dst_data; }
    int main()
    {
      UErrorCode err;
    
      const char* ALIAS = "Shift_JIS";   // 日本語のコードページ
    
      //std::u16string src_data = u"いろはにほへと";       // 日本語
    
      // NEC拡張文字
      // ①②㌍
      // IBM拡張文字
      // 髙ⅱⅲ㈱
      std::u16string jps = u"①②㌍髙ⅱⅲ㈱";
    
      // ICUの内部表現へ変更
      icu::UnicodeString ustr(jps.c_str());
    
      Converter(ustr, "Shift_JIS");// コードページを指定して変換
      Converter(ustr, "CP932");
    
    
      
      getchar();
    }
    

    実行結果。特に変換できない文字は出てこなかった。

    指定できそうなコードページを調べる

    https://www.ibm.com/docs/ja/integration-bus/10.0?topic=ssmkhh-10-0-0-com-ibm-etools-mft-doc-ac00408--htm

    ICUライブラリのページではないようだがIBMのページなので、ここの一覧から選ぶことができそうである。いくつか拾い上げて ucnv_getAliases に与えると表のとおりの結果が返ってきている。

    おまけ

    中国語やギリシャ語への変換例。確認方法が面倒。Converterは前述のものを使用。

    ギリシャ語はWordでフォントをTimes New Romanにすると確認できる。

    int main()
    {
      UErrorCode err;
    
      const char* ALIAS = "EUC-CN";      // 中国語のコードページ
      std::u16string src_data = u"什么";  // 中国語
    
      icu::UnicodeString ustr(src_data.c_str());
    
      Converter(ustr, ALIAS);
      
      getchar();
    }
    
    int main()
    {
      UErrorCode err;
    
      const char* ALIAS = "ibm737";     // ギリシャ語のコードページ
      std::u16string src_data = u"πανσέληνος"; // ギリシャ語
    
      icu::UnicodeString ustr(src_data.c_str());
    
      Converter(ustr, ALIAS);
    
      getchar();
    }
    

    参考:

     

     

    本当は怖くないCP932
    https://qiita.com/kasei-san/items/cfb993786153231e5413

    ICUライブラリ(再)

    以前やったのが2014年とかだったので更新する。

    古い記事:

    1.ダウンロード

    https://icu.unicode.org/download

    公式サイトからICU4C系をクリックする。

    ICU4CはC++。

    ICU4JはJava。

    その先のページの一番下のDownloadにある、Source and binary downloads are available on the git/GitHub tag pageのリンクへ飛ぶ。

    一覧の中から、対応開発環境のものを選ぶ

    2.サンプルコード

    リンクにicuuc.libが必要。また実行時にicudt69.dll , icuuc69.dllが必要。

    #include <fstream>
    
    
    #include <unicode/ucnv.h>
    
    // icu::UnicodeString に必要
    #include <unicode/unistr.h>
    
    // 要リンク
    #pragma comment(lib, "icuuc.lib")
    
    // 以下のdllを要求される
    // icudt69.dll
    // icuuc69.dll
    
    void Converter() {
    
      std::fstream r("C:\\dev\\icu-test\\shiftjis.txt");
      std::string src_data;
      r >> src_data;
      //エラーを受け取る変数
      UErrorCode err = U_ZERO_ERROR;
    
      //入力・出力の各文字コード
      char srcCode[] = "shift-jis";
      char dstCode[] = "euc-jp";
    
      //UnicodeStringに渡す文字列の文字コードを指定する
      UConverter* srccnv = ucnv_open(srcCode, &err);
    
      //入力された文字の文字コードを内部形式に変換
      icu::UnicodeString srcstr(src_data.c_str(), src_data.length(), srccnv, err);
    
      //内部形式の文字コードを目的の文字コードへ変換
      char* dst_data = new char[100];
      srcstr.extract(0, srcstr.length(), dst_data, dstCode);
      using namespace std;
      std::fstream w("C:\\dev\\icu-test\\euc-jp.txt", ios::out | ios::binary | ios::trunc);
      w << dst_data;
    }
    
    int main()
    {
      Converter();
    }
    

    Gimp Script-fuですべてのレイヤーをマージした画像をpngにエクスポート

    file-png-save-defaults関数を使うのだが、画像番号と一緒にdrawableを指定しなければならず、したがってそのdrawableのレイヤーしか保存できない。

    全てのレイヤーをマージするにはgimp-image-merge-visible-layers関数を使えばいいが、エクスポートしたいだけでマージするわけにいかないので、gimp-image-duplicateで現在の画像をコピーし、それに対してマージを行い、保存した後でgimp-image-deleteで削除する

    ; 画像を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") 
      )
    )
    
          
    ; 全てのレイヤーを統合してpngにエクスポート
    ; Image 画像番号 (gimp-image-list) で取得可能
    ; outpath 出力先のパス。C:\\test\\
    (define (my-save-png-as-single-image Image outpath )
      (begin
      
        ; 現在の画像をコピーする
        (define dummydup   '())
        (set! dummydup   (car (gimp-image-duplicate Image ) ) )
        
        ; コピーした画像の全レイヤーをマージして一つの画像にする
        (gimp-image-merge-visible-layers dummydup CLIP-TO-IMAGE )
        
        ; 保存に必要な、dummydupのdrawableを取得する
        (define activedrawable   '())
        (set! activedrawable (car (gimp-image-get-active-drawable dummydup ) ) )
        
        (my-save-to-png
          dummydup
          activedrawable
          outpath
          (car (gimp-image-get-name Image) ); 画像の名前を取得してファイル名に指定
        )
        
        (gimp-image-delete dummydup)
        
      )
    )
    ;; usage :
    ;; (gimp-image-list)
    ;; > (1 #(5))
    ;; (my-save-png-as-single-image 5 "C:\\test\\")
    ;; > (#t)
    

    Gimp側

    出力

    BlenderでPythonから画像を読み込み、アスペクト比を調整する

    Import Images as Planeを使えばする必要すらないが、Pythonコードからplaneにテクスチャを設定する場合。

    import bpy
    
    # @brief Planeオブジェクトのサイズをテクスチャ画像に合わせて調整
    # @param [in,out] plane Planeオブジェクト
    # @param [in] Image Textureノード
    # @param [in] ratio 何倍のサイズにするか
    # @return なし
    def TextureFixSize(plane,imgnode,ratio):
        
        maxsize = max( imgnode.image.size[0] , imgnode.image.size[1] )
        plane.scale[0] = imgnode.image.size[0] / maxsize * ratio
        plane.scale[1] = imgnode.image.size[1] / maxsize * ratio 
        
    
    # @brief テクスチャをplaneに設定する
    # @param [in,out] plane Planeオブジェクト
    # @param [in] filepath 画像データへのパス
    # @note マテリアルが設定され、Image Textureノードが存在している必要がある
    # @return なし
    def TextureFromFile(plane,filepath):
        ####################
        ## 画像ファイルを読み込み
        pngdata = bpy.data.images.load(filepath = filepath)
    
        ####################
        ## planeオブジェクトのImage Textureノードを取得
        nodetree = plane.material_slots["Material.001"].material.node_tree
        imgnode = nodetree.nodes["Image Texture"]
    
        ####################
        ## Image Textureノードへ画像を設定
        imgnode.image = pngdata
    
        ####################
        ## 張り付けたPlaneオブジェクトのサイズを画像サイズと同じ縦横比に合わせる
        TextureFixSize(plane,imgnode,1)
        
    
    act = bpy.context.active_object
    TextureFromFile(act,'C:/test/lake-6627781_640.jpg')
    

    実行例

    実行前

    実行後

    解説

    画像読み込み、設定

    まず画像ファイルを読み込む

    pngdata = bpy.data.images.load(filepath = filepath)

    次にマテリアルからImage Textureノードを取得する

    nodetree = plane.material_slots["Material.001"].material.node_tree
    imgnode = nodetree.nodes["Image Texture"]

    ノードに画像を設定

    imgnode.image = pngdata

    画像サイズの取得

    Image TextureノードのImageオブジェクトにsizeがある。

    https://docs.blender.org/api/current/bpy.types.ShaderNodeTexImage.html

    Blenderでループするparticleのアニメーションを作成

    1.アニメーションの長さを決める

    例えばアニメーションの長さを 500フレーム とする。この時、

    F == 500
    H == 250 (...500/2)

    と定義する。

    2.Particleを一つ作り、必要な設定をする

    Particleの発生時間を、以下のように設定

    start -(H-1)
    stop H

    3.Particleをコピーし設定

    次に、そのParticleをコピーし、、発生時間を以下のように設定
    start H+1
    stop F+H

    4.フレームとparticleの発生範囲の関係

    500 frameのアニメーションであれば以下のようになる

    まずアニメーションを500フレームに設定

    次にparticleの発生時間を設定し、それをコピーした二つ目のparticleの設定も行う

    particle1 : -249 …. 250
    particle2 : 251 …. 750

    結果

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