UWSC|BMP画像の幅と高さを得る自作関数

ポク太郎です。

UWSCでは“画像認識”機能が使えます。以降、画像を扱うことが多くなると思いますので、画像の幅、高さを返す関数を用意しておくことに。

画像のフォーマットは多数ありますが、認識に適する非圧縮のビットマップ(.bmp)を使います。


ビットマップ画像の幅と高さを取得するbmp()関数

画像ファイルにはjpegpngtiffなど形式多数。それぞれ特徴があり目的によって使い分けられています

どんな並び方(フォーマット)で情報が記録されてるかはそれぞれの画像形式で規定。(それぞれの設計者がそれぞれ決めた。)

自分は何モンですよという情報が大抵はファイルの先頭(ヘッダ)に記録→それを読み取ることで幅や高さ、カラー/モノクロの判別が付きます。当てにならない形式もありますが。

ビットマップ画像のフォーマットも仕様として公開→関数内2行目~9行目にメモ。7行目を例にすると“ファイル先頭から数えて18バイト目から4バイト分が幅を記録する部分”という意味。

今回は画像の幅と高さを取得するのが目的ですので、以下がするべき仕事になります。

 幅:ファイル先頭18バイト目から4バイト分読み取り10進数に変換。
 高:ファイル先頭22バイト目から4バイト分読み取り10進数に変換。

FUNCTION bmp(path)//path:ビットマップファイルのパス
//ビットマップ画像のフォーマット
// 0,2:"BM"(ビットマップという意味)
// 2,4:ファイルサイズ
//10,4:画像データへのオフセット(色テーブル分)
//14,4:情報ヘッダーサイズ(Windows用:40,OS/2用:12)
//18,4:幅
//22,4:高さ
//28,2:色数(24bitフルカラー:24)
            DIM get_wh[1]
            bin=CREATEOLEOBJ("ADODB.Stream")
            bin.Open()
            bin.Type=1
            bin.LoadFromFile(path)
            tmp_info=bin.Read(26)
            bin.Close()
      FOR i=18 TO LENGTH(tmp_info)-1
         IF (i<22)
            get_wh[0]=get_wh[0]+tmp_info[i]*POWER(256,i-18)
         ELSEIF (i<26)
            get_wh[1]=get_wh[1]+tmp_info[i]*POWER(256,i-22)
         ENDIF
      NEXT
            RESULT=SLICE(get_wh,0,LENGTH(get_wh)-1)
FEND
関数プログラム説明
1,25行目 1
25
FUNCTION bmp(path)//path:ビットマップファイルのパス
FEND
bmp()関数宣言:BMP画像の幅と高さを得る関数
引数path:BMP画像のパス
2~9行目 2
3
4
5
6
7
8
9
//ビットマップ画像のフォーマット
// 0,2:BM(ビットマップという意味)
// 2,4:ファイルサイズ
//10,4:画像データへのオフセット(色テーブル分)
//14,4:情報ヘッダーサイズ(Windows用:40,OS/2用:12)
//18,4:幅
//22,4:高さ
//28,2:色数(24bitフルカラー:24)
ビットマップ画像のフォーマット(ヘッダ情報)をコメントアウトでメモ。いちいち調べるの面倒なので。
(例)18,4:幅:“18バイト目から4バイト分に幅のデータがある”という意味。
10行目 10             DIM get_wh[1]
取得した幅と高さを代入するための配列変数を宣言しておきます。
11~16行目 11
12
13
14
15
16
            bin=CREATEOLEOBJ(ADODB.Stream)
            bin.Open()
            bin.Type=1
            bin.LoadFromFile(path)
            tmp_info=bin.Read(26)
            bin.Close()
BMP画像のヘッダ情報を読みたいので、バイナリファイルとして読み込みます。ヘッダ情報の内、必要な部分だけを変数に代入します。
12~14行目: バイナリを読み込み
15行目: 配列tmp_infoに27バイト分を代入。(配列に代入される模様)
16行目: バイナリファイルを閉じます。
17~23行目 17
18
19
20
21
22
23
      FOR i=18 TO LENGTH(tmp_info)1
         IF (i<22)
            get_wh[0]=get_wh[0]+tmp_info[i]*POWER(256,i18)
         ELSEIF (i<26)
            get_wh[1]=get_wh[1]+tmp_info[i]*POWER(256,i22)
         ENDIF
      NEXT
配列tmp_infoから目的の幅と高さを10進数で取得する部分です。
i=18からループが始まりますので、
もし22より小さいなら(つまりi=18~21:“幅”なら)19行目を実行せよ
もし26より小さいなら(つまりi=22~25:“高さ”なら)21行目を実行せよ

19行目にPOWER(256,i-18)とあります。
POWER()関数は256の(i-18)乗を返す関数です。
i=18のときは、POWER(256,0)=1
i=19のときは、POWER(256,1)=256
i=20のときは、POWER(256,2)=65536
i=21のときは、POWER(256,3)=1600万

BMP画像は幅と高さを記録するのに4バイト分(16進数の2桁を4つ)確保しています。その4バイト分を10進数に直すには、
1番下の1バイトx1+2番目x256+3番目x65536+4番目x1600万
19、21行目はfor文の中でその計算をしています。

24行目 24             RESULT=SLICE(get_wh,0,LENGTH(get_wh)1)
SLICE(配列、開始要素番号、終了要素番号)
は指定範囲の配列を戻り値として返す関数です。
※関数の戻り値に配列を使う方法はこちら(配列変数と関数【使い方まとめ】)。

ここでは幅と高さだけ取得しましたが、fornext間のif文に条件を付け加え他のヘッダ情報も同様に返すことで取得できるようになります。

画像の幅と高さを得る関数の呼び出しと代入方法

呼び出し側は、

   wh=bmp("C:\poku\ポク太郎アイコン.bmp")
   width=wh[0]//幅が入る
   height=wh[1]//高さが入る
呼び出し側プログラム説明
1~3行目 1
2
3
   wh=bmp(C:\poku\ポク太郎アイコン.bmp)
   width=wh[0]//幅が入る
   height=wh[1]//高さが入る
配列wh[]に「ポク太郎アイコン.bmp」の幅と高さが代入されます。
wh[0]が幅、wh[1]が高さです。

画像検出の話題
BMP画像の幅と高さを得る関数 見つけた指定画像の中心座標を返す関数 高圧縮jpegと劣化なしbmp画像を取得する関数 あいまいな画像認識の前に“できない理由”を調べる
本記事の内容は以下でした。
○ビットマップ画像(.bmp)の幅と高さを取得する関数

コメント

タイトルとURLをコピーしました