BMPファイルから切出し表示

 投稿者:メール  投稿日:2009年10月28日(水)08時20分1秒
  時々、掲示板を見ているのですが最近の内容の広さと深さに驚いています。
そこで、深い理解を持っておられる方々の知恵をお借りしたいのですが

5000×4500のBMPファイルがあるのですが
このファイルからXからX+500,YからY+450の部分を切出してグラフィック画面に表示したいのですがで、きますでしょうか?
これができると必要な部分だけを利用して処理できるようになるので非常に助かるのですが、よろしくお願いします。
 

Re: BMPファイルから切出し表示

 投稿者:山中和義  投稿日:2009年10月28日(水)20時31分50秒
  > No.683[元記事へ]

哲さんへのお返事です。

速度の検証など(改善は期待できない)のプロトタイプとして掲載します。
!BMPファイル(圧縮なし)画像の部分領域(切り出し)を表示する
!参考 http://www.kk.iij4u.or.jp/~kondo/bmp/

OPTION CHARACTER byte


LET CX1=0 !切り出す画像領域の左上座標(ピクセル単位)
LET CY1=0
LET CX2=640 !右下座標
LET CY2=480

SET COLOR mode "NATIVE"
SET bitmap SIZE CX2-CX1,CY2-CY1 !スクリーン座標へ
SET WINDOW 0,CX2-CX1-1,CY2-CY1-1,0 !画面を画像サイズへ
SET POINT STYLE 1 !ドット形式


LET BFile$=REPEAT$(CHR$(0),14) !Dim BFile As BITMAPFILEHEADER
LET BInfo$=REPEAT$(CHR$(0),40) !Dim BInfo As BITMAPINFOHEADER
LET BPalt$=REPEAT$(CHR$(0),4) !Dim BPalt As RGBQUAD


file getname f$,"BMPファイル|*.BMP" !ファイル名を得る
IF f$="" THEN STOP


OPEN #1: NAME f$, ACCESS INPUT
LET cp=0 !読み込み現在位置

!---------- ファイルヘッダ部
LET p=0 !読み込み位置
CALL fseek(p) !Get #1,0,BFile ※VisualBasic
CALL fread(BFile$,p)

IF BFile$(1:2)="MB" THEN !BFile.bfType
   PRINT "BMPファイルではありません。"
   STOP
END IF
LET bfOffBits=CVI(BFile$,10,4) !BFile.bfOffBits
PRINT "bfOffBits=";bfOffBits
PRINT


!---------- 情報ヘッダ部(Windows Bitmap)
CALL fread(BInfo$,p) !Get #1, ,BInfo

LET biWidth=CVI(BInfo$,4,4) !BInfo.biWidth
PRINT "biWidth=";biWidth
LET biHeight=CVI(BInfo$,8,4) !BInfo.biHeight
PRINT "biHeight=";biHeight
LET biBitCount=CVI(BInfo$,14,2) !BInfo.biBitCount
PRINT "biBitCount=";biBitCount
LET biCompression=CVI(BInfo$,16,4) !BInfo.biCompression
PRINT "biCompression=";biCompression
PRINT


!---------- 情報ヘッダ部(パレット部)
DIM PAL(0 TO 255,4)
IF biBitCount<=8 THEN
   FOR k=0 TO 2^biBitCount-1
      CALL fread(BPalt$,p) !Get #1, ,BPalt

      !!PRINT USING "### 番 ": k;
      !!PRINT CVI2(BPalt$,0,1), !BPalt.rgbBlue ※符号なし
      !!PRINT CVI2(BPalt$,1,1), !BPalt.rgbGreen
      !!PRINT CVI2(BPalt$,2,1), !BPalt.rgbRed
      !!PRINT CVI2(BPalt$,3,1) !BPalt.rgbReserved

      LET PAL(k,3)=CVI2(BPalt$,0,1)/255 !BPalt.rgbBlue ※符号なし
      LET PAL(k,2)=CVI2(BPalt$,1,1)/255 !BPalt.rgbGreen
      LET PAL(k,1)=CVI2(BPalt$,2,1)/255 !BPalt.rgbRed
      LET PAL(k,4)=CVI2(BPalt$,3,1)/255 !BPalt.rgbReserved
   NEXT k
END IF
PRINT


IF biCompression<>0 THEN
   PRINT "圧縮形式は未サポートです。"
   STOP
END IF


!---------- 画像データ部
!SET DRAW mode hidden !ちらつき防止の開始

LET p=bfOffBits !ファイル内の画像データの先頭位置
CALL fseek(p)

LET L1=biWidth*biBitCount/8
LET L1b=(INT((L1-1)/4)+1)*4 !4バイト境界

FOR y=1 TO biHeight
   LET BData$=REPEAT$(CHR$(0),L1b) !1行分の画像データ
   CALL fread(BData$,p) !Get #1, ,BData

   IF y>=biHeight-CY2 AND y<=biHeight-CY1 THEN !切り出し領域内なら ※下から格納されている

      SELECT CASE biBitCount
      CASE 1 !2色

         FOR x=MAX(INT((CX1-1)/8),0) TO L1b-1 !1行分の画像データ(切り出し領域内左端から)

         !!PRINT "(";8/biBitCount*x+1;",";y;")",
            LET b=CVI2(BData$,x,1)
            !!!PRINT right$("0000000"&BSTR$(b,2),8)

            LET t$=right$("0000000"&BSTR$(b,2),8)
            LET bb=1
            DO UNTIL bb>8
               LET xx=x*8+bb-1
               IF xx>CX2 THEN EXIT FOR !切り出し領域内右端なら
               IF xx>=CX1 THEN
                  IF xx<=biWidth THEN
                     LET t=VAL(t$(bb:bb))
                     SET POINT COLOR colorindex(PAL(t,1),PAL(t,2),PAL(t,3))
                     PLOT POINTS: xx - CX1, biHeight-y - CY1 !※下から格納されている
                  END IF
               END IF
               LET bb=bb+1
            LOOP

         NEXT x

      CASE 4 !16色

         FOR x=MAX(INT((CX1-1)/2),0) TO L1b-1 !1行分の画像データ(切り出し領域内左端から)

         !!PRINT "(";8/biBitCount*x+1;",";y;")",
            LET b=CVI2(BData$,x,1)
            !!PRINT INT(b/16); !上4bit
            !!PRINT MOD(b,16) !下4bit

            LET xx=8/biBitCount*x+1

            IF xx>CX2 THEN EXIT FOR !切り出し領域内右端なら
            IF xx>=CX1 THEN
               IF xx<=biWidth THEN
                  LET t=INT(b/16) !上4bit
                  SET POINT COLOR colorindex(PAL(t,1),PAL(t,2),PAL(t,3))
                  PLOT POINTS: xx - CX1, biHeight-y - CY1 !※下から格納されている
               END IF
            END IF
            IF xx+1>CX2 THEN EXIT FOR !切り出し領域内なら
            IF xx+1>=CX1 THEN
               IF xx<=biWidth THEN
                  LET t=MOD(b,16) !下4bit
                  SET POINT COLOR colorindex(PAL(t,1),PAL(t,2),PAL(t,3))
                  PLOT POINTS: xx+1 - CX1, biHeight-y - CY1 !※下から格納されている
               END IF
            END IF

         NEXT x

      CASE ELSE !256色、24ビット色、32ビット色

         FOR x=MAX(CX1,1) TO MIN(CX2,biWidth) !切り出し領域内

            LET t=(x-1)*biBitCount/8

            !!PRINT "(";x;",";y;")",
            !!FOR k=0 TO biBitCount/8-1
            !!   PRINT CVI2(BData$,t+k,1); !BData ※符号なし
            !!NEXT k
            !!PRINT

            IF biBitCount=8 THEN !256色なら
               LET tt=CVI2(BData$,t+0,1)
               SET POINT COLOR colorindex(PAL(tt,1),PAL(tt,2),PAL(tt,3))
            ELSE
               LET bb=CVI2(BData$,t+0,1) !BData ※符号なし
               LET gg=CVI2(BData$,t+1,1)
               LET rr=CVI2(BData$,t+2,1)
               SET POINT COLOR colorindex(rr/255,gg/255,bb/255)
            END IF
            PLOT POINTS: x - CX1, biHeight-y - CY1 !※下から格納されている

         NEXT x

      END SELECT

   END IF

NEXT y

!SET DRAW mode explicit !ちらつき防止の終了


CLOSE #1


!ファイル関連
SUB fseek(p) !読み込み位置を設定する
   IF p<cp THEN !前へ
      SET #1: POINTER BEGIN
      LET cp=0
   END IF
   FOR i=1 TO p-cp !skip it
      CHARACTER INPUT #1: tmp$
   NEXT i
   LET cp=p !現在位置の更新
END SUB
SUB fread(r$,p) !レコードを読み込む
   FOR i=1 TO LEN(r$) !read it
      CHARACTER INPUT #1: r$(i:i)
   NEXT i
   LET p=p+LEN(r$) !現在位置の更新
   LET cp=p
END SUB

END


EXTERNAL FUNCTION CVI(s$,p,m) !文字列に埋め込まれたm*8ビット符号付き整数を取り出す
OPTION CHARACTER byte
LET n=0
FOR i=1 TO m
   LET n=n+256^(i-1)*ORD(s$(p+i:p+i))
NEXT i
IF n<2^(m*8-1) THEN LET CVI=n ELSE LET CVI=n-2^(m*8)
END FUNCTION
EXTERNAL FUNCTION CVI2(s$,p,m) !文字列に埋め込まれたm*8ビット符号なし整数を取り出す
OPTION CHARACTER byte
LET n=0
FOR i=1 TO m
   LET n=n+256^(i-1)*ORD(s$(p+i:p+i))
NEXT i
LET CVI2=n
END FUNCTION
 

Re: BMPファイルから切出し表示

 投稿者:SECOND  投稿日:2009年10月29日(木)03時05分54秒
  > No.683[元記事へ]

哲さんへ

!十進BASIC のグラフ機能だけでの処理ですが、5000 x 4500 は、どんなでしょう。

OPTION ARITHMETIC NATIVE
SET COLOR mode "NATIVE"
OPTION BASE 0
DIM D(1000,1000)
ASK directory currentD$
!
SET directory "C:\WINDOWS\デスクトップ" !最初に開くdirectory(削除:マイドキュメント)
FILE GETNAME file$, "BMP"
IF file$="" THEN
   PRINT "入力ファイル名無しで、中止。"
   STOP
END IF
PRINT "入力ファイル:"& file$
!
!---原画をロード、グラフ座標を、左上から右下方向へ画素単位に設定
gload file$
ASK PIXEL SIZE xw,yw
SET WINDOW 0,xw,yw,0
PRINT xw+1;"*";yw+1;"画素の原画"
!
!---原画から、切出したい画素の範囲を書く
LET X0=10   !左
LET Y0=20   !上
LET X1=200  !右
LET Y1=200  !下
!
!---切り出し
MAT D=ZER(X1-X0,Y1-Y0)
ASK PIXEL ARRAY (X0,Y0) D
!
!---切り出し画像の表示
SET bitmap SIZE X1-X0+1,Y1-Y0+1
MAT PLOT CELLS,IN 0,1;1,0 :D
PRINT "(";X0;",";Y0;")から、";"(";X1;",";Y1;")までの切り出し画像"
!
!---切り出し画像の保存と、再表示
SET directory currentD$
gsave "sample.bmp"
gload "sample.bmp"
SET bitmap SIZE 501,501

END
 

Re: BMPファイルから切出し表示

 投稿者:  投稿日:2009年10月29日(木)08時23分15秒
  > No.686[元記事へ]

山中さんへ
見事な調査と解析をしてくださってありがとうございます。
残念ながら処理時間が掛かり過ぎるようなので使うことができませんでした。

SECONDへ
正にこれです!!!
見事に指定範囲が表示できました。
切出し方法がわからず悩んでいたのですがこんな使い方があったとは知りませんでした。
色々、調べていたのですがAPIでBMPの指定範囲を呼び出すことができそうだったのですが使用例が見つからず扱いきれませんでした。

これで短時間で処理が可能となって非常に助かりました。
本当にありがとうございました。
 

戻る