Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
PHPBinaryTips
Search
yoya
November 10, 2015
Programming
670
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
PHPBinaryTips
PHPでバイナリ処理Tips
yoya
November 10, 2015
More Decks by yoya
See All by yoya
resize_nitpick
yoya
1
190
ImageFluxBinary
yoya
2
3.1k
HEIF-kaisetsu
yoya
4
3.6k
go-thumber-imagick
yoya
1
210
chokaizomae
yoya
2
620
wildimagebinary
yoya
1
230
goimagicksyokai
yoya
2
1.2k
GoImagickThumbnail
yoya
0
1.7k
sushigazou
yoya
0
12k
Other Decks in Programming
See All in Programming
ジョジョの世界をXRで再現する
mofurune
0
140
なぜCTOを降りてFDEを選んだのか?〜なぜプロダクト企業がFDEで顧客の現場に踏み込むのか〜
gonta
1
170
mrbgem 三角測量 開発
ogom
0
220
phperだってパンチカードでコーディングしたい
o0h
PRO
0
250
速習iPhone Duo対応
yuukiw00w
2
970
複雑なUIコンポーネントとの ⻑い付き合い⽅:波及するバグからテスト戦略を経て、安全な再設計へ
mixplace
0
280
IBM Bob でAI駆動開発『QC-Playbook』
ichirokano2
0
100
setup-vp GitLab対応の裏側
naokihaba
0
160
Vue Fes Japan の “作る側”に関わってみて
naokihaba
0
140
機械に任せるテスト、人が見るテスト ⽣成AIで引き直した、運⽤保守フェーズの線引き
dske104
0
170
カツオ、ご期待ください
suneo3476
0
160
Domain-Driven Transformation
hschwentner
2
2.3k
Featured
See All Featured
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
520
My Coaching Mixtape
mlcsv
0
340
Deep Space Network (abreviated)
tonyrice
0
360
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
580
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
710
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
540
Bootstrapping a Software Product
garrettdimon
PRO
306
120k
Fantastic passwords and where to find them - at NoRuKo
philnash
53
4k
A Soul's Torment
seathinner
8
3.7k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Code Reviewing Like a Champion
maltzj
529
40k
Transcript
PHP でバイナリ処理Tips 2015/11/10
[email protected]
自己紹介 • 2年前、六本木のSNS系会社で働いてました • バイナリ変換が趣味です 1
1 0 1 0 0 1 0
公開ライブラリ • h8ps://github.com/yoya/IO_Bit – バイナリ編集ライブラリ – h8ps://github.com/yoya/IO_MIDI •
音楽の MIDI ファイル編集 – h8ps://github.com/yoya/IO_PNG • 画像ファイルのPNG編集 – h8ps://github.com/yoya/IO_ICC • ICCプロファイル編集
本発表について • この発表の焼き直しです – PHPでバイナリ変換プログラミング – h8p://www.slideshare.net/yoyayoya1/ php-‐10133775 •
PHP でバイナリ変換するのは楽という話 – 小さなバイナリを処理するには良い感じ – (メモリを沢山使うので、大きなバイナリを扱うの はキツい)
バイナリって何? • バイナリって何? – 本来は、コンピュータが処理し易い 0,1 の2進値 データ – 世間的には、テキスト以外のデータ
(狭義のバイ ナリ) GIFファイル (php.gif)
バイナリとテキスト • 1バイトで0~255の値を表現できるけど、US-‐ ASCII テキストはその一部しか使わない。(日 本語は複雑なので棚にあげる) • バイナリの方がより多くの情報を詰められる
0〜0x19 0x20~0xf9 0x80~0xff ! ” # … A B C … 0 1 2 … a b c … この辺りの 値が化けて 表示される
バイナリの例 • バイナリの種類 – 実行ファイル (exe, a.out, jar) •
セキュリティ界隈だと主にコレ – マルチメディア系ファイル (JPEG, PNG, MPEG, …) – ネットワーク通信パケット (TCP, ISDN, …) – 圧縮されたデータ (zip, gzip) – 暗号化されたデータ (SSL) いろいろある!
何故バイナリ処理するのか • Webサービスでもテキスト以外の、画像や動 画、または生の通信プロトコルを扱う事があ る • そのデータを PHP で改変する事で
– より多くの種類の端末にサービスを提供できたり – 通信データ量を減らせたり • エディタで開いて化けるだけで編集を諦める のは、勿体無い。
ビット(Bit)とバイト(Byte) • コンピュータ内部で処理(入出力、編集)する 単位 • バイナリ処理は、これらの単位でプログラミン グする 43 57
53 06 00 48 2c 00 78 9c b9 6b バイト列 00100011 01010111 ビット列 バイナリ バイナリ
ビット(Bit)について • 0 と 1 を用いて2通りの状態を示す • ビットを並べ4通り8通りと表現の幅を広げる 1
0 2通り (0〜1) 1 0 4通り (0〜3) 1 0 1 0 256通り (0〜255) 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 8通り (0〜7) 1 0 1 0 00, 01, 10,11 0, 1 000, 001, 010, 011, 100, 101, 110, 111 00000000, 00000001, 00000010, 00000011, … …, 11111101, 11111110, 11111111 1 0 0 0 0 1 1 1
バイト(Byte)について • (欧米の)1文字を表すビットの集まり – 一般的にはビットを8つまとめた単位 – 16進数で表示する事が多い (バイナリダンプ等) 1 0
4Bit で 16進1文字 1 0 1 0 1 0 1 0 1 0 1 0 1 0 F F 0 0 8Bit で 16進2文字 8bitまとめて 1byte 実例 (JPEG の頭) FF D8 FF E0
バイナリエディタ諸々 • Macintosh なら 0xED, Windows なら S_rling, Bz
Editor • 手で編集するのが面倒になった時、PHP の出番
閑話休題 • ここまでがバイナリの基本 • ここから PHP でバイナリ処理の話
PHP でバイナリ大丈夫? • PHP の String 型はバイナリとして使える – h8p://www.php.net/manual/ja/
language.types.string.php#language.types.string.details • 文字列としての処理を勝手にしない – 8bit スルー、¥0 終端無視! PHP における文字列型は、バイトの配列と整数値 ( バッファ長) で実装されています。 バイト列を文字列 に変換する方法については何の情報も持っておらず、 完全にプログラマ任せとなっています。
String 型でバイト単位の処理 • (バイナリ)ファイル入出力 • 連結と分解 file_get_contents file_put_contents
ファイル ファイル input output 連結 $c = $a . $b $b = substr($a, $x, $y) 分解 $a $b $c $a $b $x $y
String 型とInteger型変換 • ord と chr で相互変換する $b = ord($a)
$a = chr($b) バイナリ $a 整数値 $b $a = ‘Yoya’; $b = ord($a[0]); echo $b; $b = 89; $c = 111; $a = chr($b).chr($c); echo $a; 実行結果 ⇒ 89 = (0x59) 実行例 (分かりやすいようにテ キストで) Y o 実行結果 ⇒ Yo Y (string) (integer or float)
Endian に応じた処理 • 2byte以上のバイナリと整数値の相互変換 – Bit Endian (MSB First)
– Li8le Endian (LSB First) バイナリ 0x12 0x34 整数値 x y (x*256)+y 0x1234 = 4660 バイナリ 0x12 0x34 整数値 x y x+(256*y) 0x3412 = 13330 =0x100
BigEndian で unpack • バイナリと整数値の相互変換 (BigEndian) • pack で逆変換
$b = unpack(‘n’, $a) バイナリ $a $b = unpack(‘N’, $a) $b[1] $b[1] 整数値 整数値 バイナリ $a w x y z (((((w*256)+x)*256)+y)*256)+z x y (x*256)+y
Li8leEndian で unpack • バイナリと整数値の相互変換 (Li8leEndian) • pack で逆変換
$b = unpack(‘v’, $a) バイナリ $a $b = unpack(‘V’, $a) $b[1] $b[1] 整数値 整数値 バイナリ $a w x y z w+(256*(x+(256*(y+(256*z))))) x y x+(256*y)
String 型のバイト処理 その他 • strrev で前後リバース (逆順にする) • substr_replace
で一部入れ替え • strcmp でバイナリ比較 (一致するか否か) • str_pad, str_repeat で同じバイトの繰り返し str 系で色々なバイナリ操作が可能!
バイト処理の注意点 • $a[0] • 文字列を配列のように参照すると、($a の 0 番目の数値でなく)、0番 目の文字を切り出したものが取得できる。
• $a[0] は substr($a, 0, 1) と同じ (C言語出身者は多分ココで躓く) • unpack(‘N’, … と ‘V’の PHP bug – N, V は unsigned long (32ビット値)のはずだが、実際は signed long(符号付き)の値が出てくる – 負の値が出てきたら 4294967296 を足して補正 • 足すと (integer の範囲を超えて)型が float になる。要注意。 • 64bit環境ではこの問題がなくなりました。 • でも、今度は 64ビット非負整数 (Q, P)で同様の問題あり – pack は正でも負でも受理してくれる
バイト処理の実例 JPEG分解 • JPEGの画像サイズを抜き出す – h8p://www.w3.org/Graphics/JPEG/ ← 仕様 •
JPEG チャンクの並び JPEG SOI DQT DHT RST APP1 SOS SOF0 EOI ここにサイズが 入っている width height
JPEG データ形式 • JPEG チャンクのデータ形式 SOF0 Marker =0xffc0 Length
2 bytes 2 bytes Data P height 1 byte width 2 byte 2 byte SOI,EOI Marker APP,DQT, SOF0 Marker Length SOS,RSTx Marker 2 bytes 2 bytes 2 bytes 2 bytes 次のchunkまでscan Data Data Length Marker FF?? & ! FF00
JPEG サイズ抽出サンプル <?php $data = file_get_contents($argv[1]); // JPEGfile input for
($i = 1 ; $i < strlen($data) ; $i++) { switch(ord($data[$i++])) { // chunk marker case 0xD8: case 0xD9: // SOI (or EOI) break; // skip default: $len = unpack('n', substr($data, $i, 2)); $i += $len[1]; break; // skip case 0xC0: // SOF0 $sof0 = unpack('CP/nH/nW', substr($data, $i + 2, 5)); echo "width:{$sof0['W']} heigth:{$sof0['H']}\n"; exit (0); // OK } }
ちなみに • ge_magesize で画像サイズは取れます。。 <?php $imagesize = getimagesize($argv[1]); //
JPEGfile input var_dump($imagesize);
IO_Bit • やっぱり str 系関数使うの面倒ですよね – バイナリなのに str 使うの気持ち悪い
• そんな人(自分含む)の為に • h8ps://github.com/yoya/IO_Bit – バイナリ編集ライブラリ
IO_Bit ライブラリ • ビットやバイトを頭から切り出す • Endian 処理も簡単 <?php
require_once ‘IO/Bit.php’; $data = file_get_contents($argv[1]); $iobit = new IO_Bit(); $iobit->input($data); var_dump($iobit->getData(4)); // 2byte のBigEndian整数を取得 var_dump($iobit->getUI16BE());
IO_Bit の使い方 • バイナリを解釈して PHP の配列に入れる • PHP の配列を操作して、またバイナリに戻す
[[Event:9, Note:43, Velocity:100], …⋯] PHP配列 バイナリ バイナリ Input & parse build & output
IO_MIDI • h8ps://github.com/yoya/IO_MIDI – MIDI編集ライブラリ IO_Bit IO_MIDI ユーザ プログラム
parse input 入力 output build バイナリ 出力 ここで 編集
IO_MIDI 使い方 • h8ps://github.com/yoya/IO_MIDI – MIDI編集ライブラリ (IO_Bit でバイナリ分解) <?php
require_once 'IO/MIDI.php'; $data = file_get_contents($argv[1]); $midi = new IO_MIDI(); $midi->parse($data); var_dump($midi);
var_dump($midi) 出力
IO_MIDI 構造 IO_MIDI header tracks header Format(1) NumberOfTracks (9)
Division (480) 0 track DeltaTime EventType NoteNumber Velocity 1 8 : : これを 書き換えて みる (音程) (音の強さ)
音程を変える • 1オクターブ上げる (半音で12個上) <?php require_once 'IO/MIDI.php'; $data = file_get_contents($argv[1]);
$midi = new IO_MIDI(); $midi->parse($data); foreach ($midi->tracks as &$track) { foreach ($track['track'] as &$event) { if (isset($event['NoteNumber'])) { $event['NoteNumber'] += 12; // octave up! } } } echo $midi->build();
結果 • 元 h8p://diary.awm.jp/~yoya/data/2015/11/10/akatomb.mid • 変換後)
1オクターブup h8p://diary.awm.jp/~yoya/data/2015/11/10/ akatomb-‐12up.mid
1オクターブ上がると ピンとこない人用 • 元) h8p://diary.awm.jp/~yoya/data/2015/11/10/akatomb.mid
• 変換後) 半オクターブup h8p://diary.awm.jp/~yoya/data/2015/11/10/ akatomb-‐6up.mid // $event['NoteNumber'] += 12; // octave up! $event['NoteNumber'] += 6; // half octave up!
という感じで • バイナリと PHP配列構造との、相互変換 (parse と build) を作ってしまえば、編集し放題 です
• 以上です