4,915 views
この記事は最終更新から 1784日 が経過しています。
octaveで fopen, freadを使ってバイナリファイルをロードしてみる。
「正しく読めたか?」の確認には、画像データを表示させてみるとわかりやすい。
以下のような BMPファイル bird.bmp を用意し、これを octaveで読み込んで表示してみる。
この写真↑は、私が上野動物園で撮影したハシビロコウです ^^)
octave:1> ls bird.bmp
まずはバイナリファイルを fopenでオープンする。
octave:4> fid=fopen('bird.bmp','r','b')
fid = 3
BMPファイルの先頭には、BITMAPFILE HEADER と BITMAPINFO HEADER が格納されている。
画像データの縦横サイズなどの情報が格納されている。
まずは BITMAPFILE HEADERを読み込んでみる。
octave:5> BfType=fread(fid,1,'uint16'); octave:6> BfSize=fread(fid,1,'uint32'); octave:7> BfReserved1=fread(fid,1,'uint16'); octave:8> BfReserved2=fread(fid,1,'uint16'); octave:9> BfOffBits=fread(fid,1,'uint32');
次に BITMAPINFO HEADERを読み込んでみる。
octave:10> BiSize=fread(fid,1,'uint32'); octave:11> BiWidth=fread(fid,1,'uint32'); octave:12> BiHeight=fread(fid,1,'uint32'); octave:13> BiPlanes=fread(fid,1,'uint16'); octave:14> BiBitCount=fread(fid,1,'uint16'); octave:15> BiCompression=fread(fid,1,'uint32'); octave:16> BiSizeImage=fread(fid,1,'uint32'); octave:17> BiXPelsPerMeter=fread(fid,1,'uint32'); octave:18> BiYPelsPerMeter=fread(fid,1,'uint32'); octave:19> BiClrUsed=fread(fid,1,'uint32'); octave:20> BiClrImportant=fread(fid,1,'uint32');
BITMAPINFO HEADERから読み込んだ BMP画像の縦横サイズを表示してみる。
横幅は BiWidth, 高さは BiHeightに取得してある。
octave:21> BiWidth BiWidth = 3.5568e+09 octave:22> BiHeight BiHeight = 2.6172e+09
何かおかしい…
縦横サイズがめちゃくちゃ大きくなっている。
読み込んだデータを16進数で表示してみると Little endian で表示されている。
octave:29> printf('%x , %x\n', BiWidth, BiHeight); d4000000 , 9c000000
swapbytes で Big endian に変換した後に10進数で表示してみると、正しく縦横サイズが表示された。
octave:30> swapbytes(uint32(BiWidth)) ans = 212 octave:31> swapbytes(uint32(BiHeight)) ans = 156 octave:32>
BITMAPFILE HEADER, BITMAPINFO HEADERに続いて格納されているのがいよいよ画像データだ。
「青・緑・赤」の3バイトで1画素の値が作られており、これが横×縦サイズ分だけ格納されている。
このため、octave的には [ 3 212 156 ] の3次元配列で取得すればよい。
octave:32> img=fread(fid,[3 212* 156],'uint8'); octave:33> size(img) ans = 3 33072 octave:34> img=reshape(img,3,212,156); octave:35> size(img) ans = 3 212 156
imshow で画像を表示する場合、入力する画像データ配列を [y][x][color] の順に作る必要がある。
そこで上記の img配列の次元を permute で入れ替え、imshow で表示してみる。
octave:38> img=permute(img,[3 2 1]); octave:39> imshow(uint8(img));
上下が反対だ…
flipdim で行方向に反転する。
octave:40> img=flipdim(img,1); octave:41> imshow(uint8(img));
色合いがおかしい…
imshowで指定する画像データの3次元目は、RGB(赤・緑・青)の順にデータを格納する必要がある。
BMPファイルにはBGR(青・緑・赤)の順にデータが格納されているため、赤と青がひっくり返って表示されている。
こちらも flipdimで画像データ配列の3次元目を反転させて赤と青のデータを入れ替える。
octave:42> img=flipdim(img,3); octave:43> imshow(uint8(img));
正しく表示できた!
fread を使ってバイナリファイルの中身を読み込む方法がわかった!
最後は fclose でファイルをクローズして終わりです。
octave:44> fclose(fid)
ans = 0
octave:45>