2017年3月5日日曜日

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

初心者のプログラミング導入のため、UWSCという開発ソフトを使って作り上げる作業を実際にやって見せるカテゴリ。準備した自作関数や使い方、トラブルを記事にしていきます。得るものがあれば幸いです。
UWSCは“画像認識”ができるということでビットマップ画像の幅と高さを取得する関数を作りました。

記事の内容

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

UWSCでは“画像認識”という機能が使えます。

以降、画像を扱うことが多くなると思いますので、ここで画像の幅、高さを返してくれる関数を用意しておくことにしました。画像のフォーマットは色々ありますが、認識に使うのに適している非圧縮のビットマップ(.bmp)を使います。


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

画像ファイルと呼ばれるものの中には.jpg、png、tiffなど多数あります。それぞれ特徴があり目的によって使い分けられています。ファイルの中にどういった並び方で情報が書かれているか(フォーマット)は、それぞれの画像形式で規定されています。(それぞれの画像形式を作った人がそれぞれ決めた。)

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

ビットマップ画像に関しても当然フォーマットが規定されており仕様として公開されています。その仕様が関数内の2行目~9行目のコメントアウトでメモってあります。例えば7行目を例にすると、“ファイルの先頭から数えて18バイト目から4バイト分が幅を言い表している部分”という意味です。今回は、画像の幅と高さをゲットするのが目的ですので、
18バイト目から4バイト分を読み取って10進数にする(幅)
22バイト目から4バイト分を読み取って10進数にする(高さ)
のがするべき仕事になります。
bmp()関数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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,i-18)
         ELSEIF (i<26)
            get_wh[1]=get_wh[1]+tmp_info[i]*POWER(256,i-22)
         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行目はその計算をしています。この部分がよく分からない場合は、こことかこことかここを参照してみてください。
24行目24            RESULT=SLICE(get_wh,0,LENGTH(get_wh)-1)
SLICE(配列、開始要素番号、終了要素番号)
は指定範囲の配列を戻り値として返す関数です。

呼び出し側は、
呼び出し側
1
2
3
   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]が高さです。

ここでは幅と高さを取得しましたが、カラーの画像かモノクロの画像かを判定したい場合には、fornext間のif文に条件を付け加えて同じように取得することができます。



記事の内容

記事の内容は伝わりましたでしょうか。
○ビットマップ画像(.bmp)の幅と高さを取得する関数


関数群のダウンロードはこちら
func_poku.uwsのコメント欄に呼び出し方が書いてあります。


【関連記事】[UWSC]iniファイルを扱う関数
[UWSC]画像が表示された中心座標を返す関数
[UWSC]指定画像が表示された座標を返す関数
[UWSC]配列変数と関数[使い方まとめ]


スポンサーリンク



ブログ村へ blogramのブログランキング

ポク太郎の「俺の説明聞いてくれ」 コンテンツ
ポク太郎の「俺の説明聞いてくれ」最キラー記事 コンピュータ(ハード/ソフト)
映画・ドラマ・芸能
変人のつぶやきとトラブル
ホームへ戻る


0 件のコメント:

コメントを投稿