beatorajaのスキンをカスタマイズしたいときの障壁である拡張子.cim
のファイルについて。
・ソフトウェアを作った
[2021-01-20 追記]
.cim
⇄ .png
の相互変換をするソフトウェアを作った。
ダウンロード、ソースコードはここから → sr8e/cim-ct/releases.
DL時にウイルスチェックに引っかかるらしいが、ウイルスは入ってないので安心して欲しい。心配な人はソースコードからビルドしても良い。
・経緯
先日DAOコンを購入した。ついでにbeatorajaも導入した(なぜかLR2より頻繁に落ちる)。
beatorajaのデフォルトスキンは酷いものだからカスタマイズしようと思ってLR2で使っていたやつの移植とかしていたのだが、プレイ画面以外は特にこだわりもないので流石に面倒臭くなって、beatorajaスキンの中ではほぼ一強状態のLITONEを導入してみた。
さすがは後発スキンが出ないだけのことはあってクオリティは段違いである。しかし細々したところを弄ったり、リソースの流用をしたりしようと思うとやはり多少のカスタマイズには手を付けざるを得ない。ということでスキンのフォルダを開いてみたら...
なんだこれ。
恐らく99.9%の人々は.cim
ってなんやねん、となったと思う。自分もそのうちの1人だし、Twitterで検索してもなんだこれという呟き以外有益な情報はなかった。ググっても土木関係のものしかヒットしない。
・捜索
とりあえずbeatorajaで使われているjavaライブラリの中で画像関係のものはffmpegかLibGDXかJavacvくらいなので適当に検索してみると、すぐに
CIM, a compression format peculiar to Libgdx
との記述を発見。ソースコード(Gdx2DPixmap, PixmapIO)の発掘にも成功。
・フォーマット概要
まず.cim
ファイル自体はdeflate方式で圧縮されている。要するにzipである。
解凍後のファイルがPixmap形式にあたる。ヘッダー(12bytes)とピクセルの生データ(残り全部)のみで構成されているため、ここから画像データを復元するのは容易である。
また12bytesしかないヘッダー自体も、横(4bytes), 縦(4bytes), フォーマット(4bytes)というint型の数値がビッグエンディアンで3つ書き連ねてあるだけの超単純仕様である。単純な分、容量は食うので圧縮が必須なのかも。
フォーマットはGdx2DPixmap
クラス内に1
~6
の定数が定義されている。そのうちよく使いそうなのは3
(24bitRGB)と4
(32bitRGBA)の2つくらいである。
・変換
仕組みがわかってしまえばもう何も怖くない。このくらいならPythonで書くのが楽だろうということで、解凍にzlib
と画像処理にPIL
を使ってみた。
import zlib
from PIL import Image
srcpath = "src.cim"
dstpath = "dst.png"
formats = {
3: "RGB",
4: "RGBA",
}
with open(srcpath, "rb") as fr:
b = zlib.decompress(fr.read())
w = int.from_bytes(b[:4], "big")
h = int.from_bytes(b[4:8], "big")
fmt = int.from_bytes(b[8:12], "big")
im = Image.frombytes(formats[fmt], (w, h,), b[12:])
with open(dstpath, "wb") as fw:
im.save(fw, format="png")
これでcimファイルをpng形式の画像に変換できた。逆変換も同じ要領でピクセルの配列に戻してからヘッダを付けてdeflate圧縮すればよい。
ぶっちゃけpngに戻してしまったらスキン側のsrc定義をpngに置換してしまったほうがカスタマイズは楽だと思う。全部pngに置換するわけでもなければそこまでパフォーマンスに影響を与えない気がするし。
あとbeatorajaのluaスキンについてドキュメントが皆無なので自分なりに読み解いたものをそのうちまとめる予定。いつになるかは知らないけど。