AVIFが読めないアプリケーションがたまにあるので、AVIF(AV1 Image File Format)画像をJPEGなど他の形式に変換する方法をメモしておきます。AVIFが変換できるなら別に何でも良いのですが、今回はImageMagickを使用します。
AVIFとは何かですが、まずMPEG系のHEICファイル形式があります。HEIF(High Efficiency Image File Format)コンテナにHEVC(High Efficiency Video Coding, ISO/IEC 23008-2 HEVC, ITU-T H.265)で圧縮した画像を格納したファイル形式です。AVIFはHEIFコンテナを流用して、HEVCの代わりにAV1(Alliance for Open Media Video 1)で圧縮した画像を格納したファイル形式です。まとめるとこんな感じです。
ファイル形式 | コンテナ | 画像圧縮方式 |
---|---|---|
HEIC | HEIF | HEVC/H.265 |
AVIF | HEIF | AV1 |
WebP | WebM(Matroskaサブセット) | On2/Google VP8, Google VP9(当時、AV1対応が遅れていたらしい) |
AOMedia(Alliance for Open Mediaを略したもの)を含む、非MPEG系の陣営はWebMというMatroskaベースのコンテナを使うことが多いです。でもAVIFはHEIFを使うんですよね。動画系コーデックは大抵MPEG系のMP4(ISO/IEC 14496-12, 14 MP4ファイルフォーマット)コンテナに対応していますし、MPEG系コンテナを使うこと自体は変ではないですが……。WebPの策定が遅れたらしく、AVIFが先に流行っちゃったのは面白いなと思います。
ビルド前の準備です。AVIFはHEIFコンテナを使っていますので、HEIFを扱うためのライブラリをインストールしておきます。
# apt-get install libheif-dev
ImageMagickのソースコードはGitHubにあるので、cloneしてきてビルドします。
$ git clone https://github.com/ImageMagick/ImageMagick $ cd ImageMagick $ mkdir build $ cd build $ ../configure $ make
AVIFを扱えるかどうかはconfigureログのHEICの行に表示されます。
Delegate library configuration: BZLIB --with-bzlib=yes yes Autotrace --with-autotrace=no no DJVU --with-djvu=yes no DPS --with-dps=no no FFTW --with-fftw=no no FLIF --with-flif=no no FlashPIX --with-fpx=no no FontConfig --with-fontconfig=yes yes FreeType --with-freetype=yes yes Ghostscript lib --with-gslib=no no Graphviz --with-gvc=yes no HEIC --with-heic=yes yes ★yesになっていればOK JBIG --with-jbig=yes yes JPEG v1 --with-jpeg=yes yes JPEG XL --with-jxl=yes no ...
下記のように実行します。
./magick.sh ./utilities/magick hato.avif hato.jpg
ビルドに失敗していると、no decode delegate for this imageエラーが出て怒られます。
magick: no decode delegate for this image format `AVIF' @ error/constitute.c/ReadImage/746.
このメッセージが出るときは先ほど紹介したconfigureのログを確認してみてください。
いきなり仕事部屋のシーリングライトが消えました。蛍光管の寿命にしては去年(2022年10月19日の日記参照)替えたばかりですし、もしかして本体が壊れた……?
リビングのシーリングライト(同機種)と蛍光管を入れ替えると点くので、蛍光管は生きていて本体(Panasonic HHFZ4290)が壊れたようです。去年の蛍光管交換時に「2回目交換する前にシーリングライト本体が壊れそう(本体の寿命<蛍光管2回分の寿命)」と予想していましたが、その通りになりました。悲しいね。
昨今は蛍光灯が悪者扱い(わずかに水銀を使う)で製造禁止に向かっているようです(一般照明用の蛍光ランプの製造・輸出入は2027年までに廃止されます - 環境省)。店頭にはほぼLEDのシーリングライトしか売っていません。
広範囲を照らせると触れ込みのPanasonic HH-CG1034Aを買いました。明かりの色を白くしたり黄色くしたり好きに変えられるのは、LEDならではですね。あとリモコンがでっかいです。邪魔くさい。
目次: Linux
VSCodeのPlantUML Extensionをインストールすると、MarkdownにPlantUMLの図を混ぜることができます。
何も設定しない状態だと、
このようにプレビュー画面に「No PlantUML server, specify one with "plantuml.server".」エラーが出ます。
VSCodeのSettingsの検索ボックスにplantuml.serverと入力するとPlantuml: Server項目が出るはずなので、そこにサーバーのURLを設定します。ヘルプメッセージにもあるように、自分で書いたPlantUMLのソースコードをインターネットに送ってよければhttps://www.plantuml.com/plantumlを指定するのが最も簡単です。
設定し終わったら、このようなMarkdownの文書で動作確認します。
# Title 1
This is body.
## Title 2
- aaa
- aaa is AAA
- bbb is BBB
```plantuml
node "PC" as pc {
node "CPU" as cpu
node "OS" as os
}
cpu -> os: boot
```
プレビュー画面にこのような画像が出るはずです。
www.plantuml.comサーバーを使用したときの表示例
表示されました、簡単ですね。しかし外部にソースコードを送りたくない場合もあります。
インターネットに自分で書いたPlantUMLのソースコードを送信されると困る場合は、PlantUMLのサーバーをローカルで起動すると良いです。PlantUMLのサイト(PlantUML Downloads and Source Code)から、PlantUMLのJARファイルをダウンロードします。今回はバージョン1.2024.4を使用しました。
起動方法は公式サイト(PlantUML PicoWeb Server)にある通りにやりましょう。
$ java -jar ./plantuml-mit-1.2024.4.jar -picoweb:5000:0.0.0.0
オプション-picowebにてサーバーが待ち受けに使うポートとアドレスを指定します。
VSCodeのPlantuml: Serverには、PlantUMLのローカルサーバーを動作させているマシンのIPアドレスと、PlantUMLを起動するときに指定したポートを指定します(例えば、http://192.168.1.2:5000など)。設定し終わったら先ほどと同じMarkdownの文書を用いて動作確認します。一度プレビュー画面を閉じてもう一度開いてください。
Insecure contentを表示させない設定になっているときの表示
VSCodeはhttpつまり暗号化されていないサーバーとの通信を拒否する設定になっています(改ざんが可能なので)。しかしローカルLANで実験する場合はこの制限は不要ですので、プレビュー画面に「Some content has been disabled in this document」と書かれた横長のボタンが表示され、画像が表示されないときは、
ボタンを押し、リストに表示される「Allow insecure content Enable loading content over http」を選択します。
プレビュー画像が表示されました。生成される画像は似ていますが、私の環境だと文字の表示が変になってしまいます。なぜだろう……?それは今度調べるとして、インターネット上のサーバーに比較してレスポンスが早いです。良いですね。
これはテスト用の簡易サーバー機能なので、本格的に運用する際はアプリケーションサーバーに登録したほうが良いと思います、その設定はまた今度。
目次: Zephyr
Zephyr SDKのhosttoolsを移動したらハマったので、メモしておきます。
Zephyr SDKは自前のhosttools(dtcやopenocd、qemuなど)のバイナリを持っていてシステム側のバイナリのバージョンによる不具合などを避けて必要なツールを使うことができます。が、インストールしたパスに強く依存していてディレクトリを移動させると動かなくなります。
今回は動かないバイナリを観察してなぜ動かないのか調べます。
ダイナミックリンカーのパスは実行バイナリに含まれています。
$ readelf -S ./sysroots/x86_64-pokysdk-linux/usr/bin/dtc There are 29 section headers, starting at offset 0x1e7b8: Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .interp PROGBITS 00000000000002a8 000002a8 ★これ★ 0000000000001000 0000000000000000 A 0 0 1 [ 2] .note.gnu.bu[...] NOTE 00000000000012a8 000012a8 0000000000000024 0000000000000000 A 0 0 4 $ hexdump -C ./sysroots/x86_64-pokysdk-linux/usr/bin/dtc ...略... 00000290 10 09 00 00 00 00 00 00 10 09 00 00 00 00 00 00 |................| 000002a0 01 00 00 00 00 00 00 00 2f 68 6f 6d 65 2f 6b 61 |......../home/ka| ★.interpセクションヘッダ★ 000002b0 74 73 75 68 69 72 6f 2f 74 65 73 74 2f 7a 65 70 |tsuhiro/test/zep| ★環境依存のパスがある★ 000002c0 68 79 72 2d 73 64 6b 2d 30 2e 31 36 2e 35 2d 31 |hyr-sdk-0.16.5-1| 000002d0 2f 73 79 73 72 6f 6f 74 73 2f 78 38 36 5f 36 34 |/sysroots/x86_64| 000002e0 2d 70 6f 6b 79 73 64 6b 2d 6c 69 6e 75 78 2f 6c |-pokysdk-linux/l| 000002f0 69 62 2f 6c 64 2d 6c 69 6e 75 78 2d 78 38 36 2d |ib/ld-linux-x86-| 00000300 36 34 2e 73 6f 2e 32 00 00 00 00 00 00 00 00 00 |64.so.2.........| 00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
Zephyrの公式サイトで配布しているバイナリに、私のホームディレクトリを含むパスが入っている訳がありません。おそらくインストール時に書き換えているのでしょう。
解析のためhosttoolsのインストーラを改造し、バイナリを書き換える前(292行目辺り)に入力待ちで止まるコマンド(catとか)を入れて実行を止めます。インストーラ改造の際の注意点として、インストーラ末尾にあるバイナリを壊さないように編集してください(例えばVimのバイナリモードvim -bなどを使う)。
## zephyr-sdk-x86_64-hosttools-standalone-0.9.sh: 290行目付近
...
executable_files=$($SUDO_EXEC find $native_sysroot -type f \
\( -perm -0100 -o -perm -0010 -o -perm -0001 \) -printf "'%h/%f' ")
if [ "x$executable_files" = "x" ]; then
echo "SDK relocate failed, could not get executalbe files"
exit 1
fi
cat ★この後で書き換えているようなので、ここで止める★
tdir=`mktemp -d`
if [ x$tdir = x ] ; then
echo "SDK relocate failed, could not create a temporary directory"
exit 1
fi
...
$ ./zephyr-sdk-x86_64-hosttools-standalone-0.9.sh -y -d ~/test/aaa Zephyr Yocto Toolchain SDK installer version 0.9 ================================================ You are about to install the SDK to "/home/katsuhiro/test/aaa". Proceed [Y/n]? Y Extracting SDK..................done Setting it up...^Z [1]+ 停止 ./zephyr-sdk-x86_64-hosttools-standalone-0.9.sh -y -d ~/test/aaa
バイナリの書き換えが起こる前に止めました。この状態でダイナミックリンカーのパスを見ます。
$ ldd ./sysroots/x86_64-pokysdk-linux/usr/bin/dtc linux-vdso.so.1 (0x00007ffd5d74f000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa4d5e8e000) /opt/zephyr-sdk/0.9/sysroots/x86_64-pokysdk-linux/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fa4d60b5000)
書き換える前のパスは/opt/zephyr-sdk/0.9で、インストーラのデフォルトインストール先と同じパスです。
ダイナミックリンカーのパスを書き換えるのは誰か?ディレクトリにあるrelocate_sdk.pyスクリプトです。このスクリプトはhosttoolsインストール終了後に消されるので、インストーラを改造して途中で止めないと中身を拝むことができません。
$ ls environment-setup-x86_64-pokysdk-linux relocate_sdk.py ★このスクリプト★ sysroots version-x86_64-pokysdk-linux zephyr-sdk-x86_64-hosttools-standalone-0.9.sh
詳しく追っていませんが、change_interpreter()関数が書き換える本体のようです。
def change_interpreter(elf_file_name):
if arch == 32:
ph_fmt = "<IIIIIIII"
else:
ph_fmt = "<IIQQQQQQ"
""" look for PT_INTERP section """
for i in range(0,e_phnum):
f.seek(e_phoff + i * e_phentsize)
ph_hdr = f.read(e_phentsize)
if arch == 32:
# 32bit
p_type, p_offset, p_vaddr, p_paddr, p_filesz,\
p_memsz, p_flags, p_align = struct.unpack(ph_fmt, ph_hdr)
else:
# 64bit
p_type, p_flags, p_offset, p_vaddr, p_paddr, \
p_filesz, p_memsz, p_align = struct.unpack(ph_fmt, ph_hdr)
""" change interpreter """
if p_type == 3:
# PT_INTERP section
f.seek(p_offset)
# External SDKs with mixed pre-compiled binaries should not get
# relocated so look for some variant of /lib
fname = f.read(11)
if fname.startswith(b("/lib/")) or fname.startswith(b("/lib64/")) or \
fname.startswith(b("/lib32/")) or fname.startswith(b("/usr/lib32/")) or \
fname.startswith(b("/usr/lib32/")) or fname.startswith(b("/usr/lib64/")):
break
if p_filesz == 0:
break
if (len(new_dl_path) >= p_filesz):
print("ERROR: could not relocate %s, interp size = %i and %i is needed." \
% (elf_file_name, p_memsz, len(new_dl_path) + 1))
break
dl_path = new_dl_path + b("\0") * (p_filesz - len(new_dl_path))
f.seek(p_offset)
f.write(dl_path) #★新たなパスに書き換え★
break
プログラムヘッダのPT_INTERPセクションを探して、/libや/usr/libから始まるパス以外であれば書き換える仕組みです。バイナリにデフォルトで含まれているパスは/optから始まっていましたから、書き換え対象になるわけです。
Zephyr SDKのhosttoolsインストール時にこんなことしてたんですね……知らんかった。
目次: Zephyr
Zephyr SDKのhosttoolsを移動したらハマったので、メモしておきます。
Zephyr SDKは自前のhosttools(dtcやopenocd、qemuなど)のバイナリを持っていてシステム側のバイナリのバージョンによる不具合などを避けて必要なツールを使うことができます。直接呼び出すことはなくても、westを使っている人は間接的に使っているはずです。
そんな便利なhosttoolsなんですけど、インストールしたパスに強く依存していてディレクトリを移動させると動かなくなります。何が起きるか順に見ましょう。初めにhosttoolsのみをインストールし、dtcを実行します。
$ mkdir test $ cd ~/test $ wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.5-1/zephyr-sdk-0.16.5-1_linux-x86_64_minimal.tar.xz $ tar xf zephyr-sdk-0.16.5-1_linux-x86_64_minimal.tar.xz $ cd ~/test/zephyr-sdk-0.16.5-1 $ ./zephyr-sdk-x86_64-hosttools-standalone-0.9.sh -y -d ~/test/zephyr-sdk-0.16.5-1 $ ./sysroots/x86_64-pokysdk-linux/usr/bin/dtc --version Version: DTC 1.6.0-dirty
正常動作しました。次にディレクトリを移動して、もう一度dtcを実行します。
$ cd ~/test $ mv zephyr-sdk-0.16.5-1 aaa $ cd ~/test/aaa $ ./sysroots/x86_64-pokysdk-linux/usr/bin/dtc --version bash: ./sysroots/x86_64-pokysdk-linux/usr/bin/dtc: 実行できません: 必要なファイルがありません
バイナリは一切変更していないのに動かなくなってしまいました……。バイナリは同一ですから設定もしくはダイナミックリンク周りが怪しそうです。まずはlddでライブラリ参照パスを見ます。
$ ldd ./sysroots/x86_64-pokysdk-linux/usr/bin/dtc linux-vdso.so.1 (0x00007ffd3e302000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbd136b2000) /home/katsuhiro/test/zephyr-sdk-0.16.5-1/sysroots/x86_64-pokysdk-linux/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fbd138d9000)
ダイナミックリンカー(ld-linux.so)のパスにhosttoolsをインストールしたパスが含まれています。先ほどhosttoolsのディレクトリごと移動してしまったので、リンカーが見当たらないと怒っているようです。
続きはまた今度にします。
ささやかではありますが台湾東部沖地震に寄付しました。日本の赤十字社→台湾の赤十字(正式名称は中華民国紅十字会)の経路で支援されるようです。
今回調べて初めて知ったのですが、台湾の赤十字社は中国との関係で微妙な位置に立たされているようです。
とまあ中国と台湾間の政治問題によるものみたいです。まあ政治問題はさておいて、私は台湾赤十字の支援活動が誠実に行われていると信じて寄付するのみです。
< | 2024 | > | ||||
<< | < | 04 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | - | - | - | - |
合計:
本日: