xxdコマンドで画像データを16進数変換してiOSライブラリ内に画像データを内包する
iOSでstaticライブラリを開発していると画像等を同梱したい場合がある。
通常だとaファイルの他にbundleを作成する必要があるが、
これをaファイルの中に同梱する方法を調べた。
やり方としては、画像などのバイナリデータを一旦16進数情報に変換、
ライブラリのソース内にchar配列として保持し、
それを実行時にNSDataで読み込みUIImageに変換する感じになる。
バイナリデータを16進数に変換する
xxdコマンドでバイナリデータを16進数に変換できる。
例えばあるpngファイルをxxdコマンドにかけると以下のような出力になる。
$ xxd original.png
00000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452 .PNG........IHDR
00000010: 0000 02ee 0000 0536 0802 0000 0045 b5a4 .......6.....E..
00000020: 5100 0000 0173 5247 4200 aece 1ce9 0000 Q....sRGB.......
00000030: 4000 4944 4154 7801 ecbd 0794 1dc7 79ef @.IDATx.......y.
00000040: 79f3 e4c1 2067 2232 8101 cc20 0966 5282 y... g"2... .fR.
00000050: a8b0 b244 59d2 932c 796d e959 b2fd deca ...DY..,ym.Y....
00000060: a215 8eed b59f c33b 4eeb f5f3 8ab6 f73c .......;N......<
00000070: 9f77 1cf6 59b6 ec5d db92 455a 6612 730e .w..Y..]..EZf.s.
00000080: 2041 82c8 3963 1027 cfdc b4bf 3b05 140b A..9c.'....;...
00000090: dd7d efdc 7bfb cef4 0cf0 ef83 33a8 aeae .}..{.......3...
さらに、pオプションをつけるとプレーンな16進数出力になる。
$ xxd -p original.png
89504e470d0a1a0a0000000d49484452000002ee00000536080200000045
b5a451000000017352474200aece1ce900004000494441547801ecbd0794
1dc779ef79f3e4c1206722328101cc2009665282a8b0b24459d2932c796d
e959b2fddecaa2158eedb59fc33b4eebf5f38ab6f73c9f771cf659b6ec5d
db92455a6612730e204182c839631027cfdcb4bf3b05140bdd7defdc7bfb
cef40cf0ef8333a8aeaefaaaead7b7bbfefd557575fc81071e88c7e3b132
5bb15834474863c3c4d8b027be8c9980e80a8506a46e5c94ad79e34cca92
08888008888008348c4054fd63c31a50bb218f9630bb2e8742a19048245c
c36e6f9e62c7ee938ed46e660e99ddd1542559e31e65d7e6750ba81cf658
a89cb8e147a32dbde1cd914111100111100111983c042aab82725db02797
逆に、16進数出力結果をバイナリ形式に変換することもできる。
その場合はrオプションをつける。
xxd original.png > original.hex
xxd -r original.hex > revert.png
オプション無しの出力結果の他に、-pの出力結果もrevertできる。
その場合はpオプションを付与する。
xxd -r -p original.hex > revert.png
画像データをCのchar配列形式で出力
ここからが本題で、xxdコマンドにiオプションを付与すると以下のように画像データをCのchar配列形式で出力できる。
$ xxd -i original.png
unsigned char original_png[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x02, 0xee, 0x00, 0x00, 0x05, 0x36,
// 中略
0x80, 0x10, 0x10, 0x02, 0x42, 0x20, 0x4f, 0x08, 0xfc, 0xff, 0x2c, 0x24,
0xa4, 0xb5, 0x8f, 0x74, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45,
0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
unsigned int original_png_len = 954870;
これをNSDataに食わせて、それをUIImageとして扱うことでソースから画像を生成することができる。
+ (UIImage *)revertHexImage
{
unsigned char original_png[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
// 中略
0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
unsigned int original_png_len = 954870;
// 画像データからNSDataを生成し、それを元にUIImageを生成する
NSData *data = [NSData dataWithBytes:original_png
length:original_png_len];
return [UIImage imageWithData:data];
}
今回は説明簡単にするためにメソッドの中にベタ書きしたけど、
実際には別ファイルに書き出してincludeするとかしたほうが良さそう。