ICUライブラリでのutf16の扱い方を調べていてマクロがあることを知ったのでいくつか列挙しておきたい。
ICU 71.1:utf16.h File Reference
https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/utf16_8h.html
utf16文字からコードポイントを得る
#pragma warning(disable:4996) #include <iostream> #include <unicode/utf16.h> int main() { const char16_t* u16c = u"あいう"; char32_t u32c; FILE* fp = fopen("test.txt", "w"); U16_GET_UNSAFE(u16c, 0, u32c); fwrite(&u32c, 4, 1, fp); U16_GET_UNSAFE(u16c, 2, u32c); fwrite(&u32c, 4, 1, fp); fclose(fp); }
与えられたコードポイントが、utf16で何要素になるかを返す。返却値は 1 または 2。
std::u32string cc; // U16_LENGTH 与えられたu32がu16で何要素になるか int len; cc = U"a"; len = U16_LENGTH(cc[0]); printf("--- %d\n", len); // 1 utf16一文字 cc = U"あ"; len = U16_LENGTH(cc[0]); printf("--- %d\n", len); // 1 utf16一文字 cc = U"👨👩👧👦"; len = U16_LENGTH(cc[0]); printf("--- %d\n", len); // 2 結合文字の最初の一文字 cc = U"𠀋"; len = U16_LENGTH(cc[0]); printf("--- %d\n", len); // 2 サロゲートペア cc = U"𠀋𡚴"; len = U16_LENGTH(cc[0]); printf("--- %d\n", len); // 2 最初の一文字がサロゲートペア
U16_IS_SINGLE(c) utf16文字cが、サロゲートペアでなければtrue。
U16_IS_SURROGATE(c) utf16文字cが、サロゲートペアであればtrue。
U16_IS_SURROGATE_LEAD(c) utf16文字cが、上位サロゲートであればtrue。ただし、cがサロゲートペアであることが分かっている必要がある。
U16_IS_SURROGATE_TRAIL(c) utf16文字cが、下位サロゲートであればtrue。ただし、cがサロゲートペアであることが分かっている必要がある。
U16_IS_SINGLE | U16_IS_SURROGATE | U16_IS_SURROGATE_LEAD | U16_IS_SURROGATE_TRAIL | |
u”a”[0] | true | false | true | false |
u”あ”[0] | true | false | true | false |
u”👨👩👧👦”[0] | false | true | true | false |
u”𠀋”[0] | false | true | true | false |
u”a”[1] | true | false | true | false |
u”あ”[1] | true | false | true | false |
u”👨👩👧👦”[1] | false | true | false | true |
u”𠀋”[1] | false | true | false | true |
コードポイントから上位サロゲート(lead)、下位サロゲート(trail)を算出する
#pragma warning(disable:4996) #include <iostream> #include <unicode/utf16.h> int main() { // UTF32 //char32_t u32c = U'あ'; char32_t u32c = U'𠀋'; // char32->char16に変換したとき何文字になるかをチェック if (U16_LENGTH(u32c) == 2){
// utf16に変換したときサロゲートペアになる場合は上下サロゲートを算出 char16_t aa[2]; aa[0] = U16_LEAD(u32c); // 上位サロゲート aa[1] = U16_TRAIL(u32c); // 下位サロゲート // ファイル出力 FILE* fp = fopen("test.txt", "w"); fwrite(aa, 2, 2, fp); fclose(fp);
} else {
//サロゲートペアに変換する必要がなければコードユニット値がutf16文字
char16_t u16 = char16_t(u32c); // ファイル出力 FILE* fp = fopen("test.txt", "w"); fwrite(&u16, 2, 1, fp); fclose(fp);
} }
まず私は動画編集は全く詳しくない。あと今回は半分雑談。
アマレココ
http://www.amarectv.com/download_amarecco4.htm
AMV4
http://www.amarectv.com/buy.htm
アマレココはH.264やUtVideoコーデックで録画もできるが、AMV4(有料)をインストールしておかないとロゴが入る。だからAMV4の購入は必須。
ただしAMV4は「入れてさえおけば」いいのでH.264などが使ったほうが動画編集ソフトで読み込めて勝手が良い。AMV4に対応している編集ソフトは多くない(知らない)。
だから私はずっと「アマレココ」 + 「AMV4」 + 「x264VFW」でデスクトップをキャプチャしていたのだが、PCを初期化したので環境を整えなおして録画してみたところうまく動作しなくなった。
なお動画サイズを640×480などのサイズにするとうまくいくので多分走査線的なものがずれている。
H.264を使わずにAMV4で録画する。
AMV4で録画してからH.264に変換するためにAviUtlを使うが、x264guiExを導入しなければいけない。
AviUtl
http://spring-fragrance.mints.ne.jp/aviutl/
x264guiEx
https://github.com/rigaya/x264guiEx/releases
x264guiExを導入すればH.264に変換できる。
glmの、ある点に最も近い線分上の点を求める関数。
公式マニュアル:
https://glm.g-truc.net/0.9.9/api/a00310.html
static float z = 3.f; { z -= 0.1; glm::vec3 p(1, z, 0); //どこか頂点 glm::vec3 a(0, -2, 0);//線分の始点 glm::vec3 b(0, 2, 0); //線分の終点 // 点に最も近い直線上の点を求めるのに必要 // #include <glm/gtx/closest_point.hpp> glm::vec3 kk = glm::closestPointOnLine(p, a, b); glLineWidth(3);//線分 glBegin(GL_LINES); glVertex3fv(glm::value_ptr(a)); glVertex3fv(glm::value_ptr(b)); glEnd(); glPointSize(7);//どこか頂点 glColor3d(1, 0, 0); glBegin(GL_POINTS); glVertex3fv(glm::value_ptr(p)); glEnd(); glPointSize(7);//線分上の点 glColor3d(0, 1, 0); glBegin(GL_POINTS); glVertex3fv(glm::value_ptr(kk)); glEnd(); }
import bpy # マテリアルにワイヤフレームを追加する def set_wireframe(mat): nodetree = mat.node_tree nodes = nodetree.nodes MaterialOutput = nodes['Material Output'] # MaterialOutputにつながっているノードを取得。 # backup -- (wireframe) -- MaterialOutput と挟み込む backup = MaterialOutput.inputs[0].links[0].from_node # ワイヤフレームに必要なノードを追加 wireframe = nodes.new('ShaderNodeWireframe') diffuse = nodes.new('ShaderNodeBsdfDiffuse') mixnode = nodes.new('ShaderNodeMixShader') # ワイヤフレームの色を黒に設定 diffuse.inputs["Color"].default_value[0] =0 diffuse.inputs["Color"].default_value[1] =0 diffuse.inputs["Color"].default_value[2] =0 # mix , diffuse , wireframe の三つをつなげる nodetree.links.new(wireframe.outputs[0],mixnode.inputs[0]) nodetree.links.new(diffuse.outputs[0],mixnode.inputs[2]) # mixにこれまで指定されていたノードをつなぐ nodetree.links.new(backup.outputs[0],mixnode.inputs[1]) # mixをMaterialOutputへ繋げる nodetree.links.new(mixnode.outputs[0],MaterialOutput.inputs[0]) # 位置調整 # MaterialOutputを少し右へずらし、その位置にmixを入れ、同じ位置にdiffuseとwireframeを入れる MaterialOutput.location.x = MaterialOutput.location.x + 200 mixnode.location.x = MaterialOutput.location.x - 200 wireframe.location.x = mixnode.location.x diffuse.location.x = mixnode.location.x # mix,wireframe,diffuseの高さを変えてそれぞれ配置する mixnode.location.y = MaterialOutput.location.y wireframe.location.y = mixnode.location.y + 200 diffuse.location.y = mixnode.location.y - 200 # ワイヤフレームの線の太さを設定 wireframe.inputs["Size"].default_value = 0.05 set_wireframe( bpy.context.active_object.material_slots["Material"].material)