早速ですが
フォームにline関数などで描画したものを白黒ビットマップで保存するには
どうすればいいでしょうか
フツーにSavePictureを使えは24ビットのものになってしまいます
またフォームですから実行した環境の解像度のファイルになってしまいます
どうすればいいでしょうか
よろしくお願いします
忘れていましたが
WinXPでVB6です
どうぞよろしくお願いします
とりあえずピクチャの全ての点で色を調べて白か黒に
置き換えれば2色に変換はできるよね?その後の保存
ファイルの形式を指定できるのか?…はそれらしい
情報に行き着きませんでした。SavePicture ステー
トメントでビットマップを扱った場合は元のファイルと
同じ形式で保管されるとヘルプに書いてあります。
API を使ってビットマップの加工を…したりするの
かなぁ?その辺りを調べてみて下さい。
うーーーーーーん
やっぱりAPIですか・・・
確かにAPIを使えば出来そうなきもするんですが・・・
どうなんでしょう
別に直接API関数を使う必要は無いでしょう。
2色化できていれば、ビットマップのフォーマットを調べて、
それをバイナリーとしてファイルに書き込むだけですよね。
http://kone.vis.ne.jp/program/
ここにそれっぽいサンプルがありますが、どうでしょう?
2色化されてない場合はCreateBitmapで2色にできますよ。
CreateCompatibleBitmapじゃないので間違えないように
後は
BITMAPFILEHEADER
BITMAPINFO(BITMAPINFOHEADER、RGBQUAD)
を正しく設定して
GetDIBitsでピクセルデータを取得し
BITMAPFILEHEADER
BITMAPINFO(BITMAPINFOHEADER、RGBQUAD)
ピクセルデータの順でバイナリで書き込めば完成です。
モノクロはパレット(RGBQUAD)って必要??失念しました。
CreateBitmapはいらないかもしれませんね。
ちょいと実験がてらサンプルでも作ってみます。
サンプル作成途中でVBが落ちたので作成するのやめました。
CreateBitmapはいらないですね。
モノクロもパレットは必要でした。
RGBQUAD(1)ですね。
皆さん回答ありがとうございます
話がずれてしまいますが
独自の形式で保存する
(といっても0なら白1なら黒というようにならんでいるファイルです)
なら
for X=0 to ピクチャーの横
DoEvents
for Y=0 to ピクチャーの横
DoEvents
if(point(x,y)=白の数)then
alldata=alldata & 0
else
alldata=alldata & 1
end if
next Y
next X
ALLDATAと書き出す
とすると
膨大な時間(処理に)がかかりますね
それならどうするべきでしょうか??
当初の質問とは違ってきましたが
よろしくお願いします
すいません訂正します
ALLDATAと書き出す
は
ALLDATAを書き出す
の間違いです
すいません
最近ビットマップ触ってないけど、
1 GetDIBits()で2値のビットマップデータを受け取り、
2 そのビットマップを減色して、
3 BITMAPFILEHEADERを作り、
4 BITMAPFILEHEADERとBITMAPINFOとBITMAPINFOHEADERをファイルに書きこむ
だけ…のはず。
> 通り巣鴨さん
> RGBQUAD(1)ですね。
そうですね、RGBQUAD(1 to 2)としたほうが分かりやすい&安全かもしれません。
> ぼう人間さん
時間がかかるのは、ピクチャーの横:W、とピクチャーの縦:Hを捜査している間に
(W+2)*(H+1)回(?)DoEventsを挟み、
VB標準のメソッドPoint()を使っていて、
ALLDATAに文字列としてInteger型を強引に連結しているせいだと思います。
高速化したいならDIB(Device Independent Bitmap)について勉強してください。
ファイルにALLDATAを書くのは早いのでは?
たしか256色のビットマップが1ピクセル1バイトです。
パレットの0に白1に黒を割り当ててビットマップ作れば
多分、できます
文字列の足し算は1000文字を超えると急激に遅くなります。
For Y = 0 To ピクチャーの横
If(point(x,y)=白の数)then
s = s & 0
Else
s = s & 1
End If
i = i + 1
If i = 1000 Then
alldata = alldata + s
s = ""
i = 0
End if
Next n
こんなことをすれば速くなります。
あ!
Nextの後に alldata = alldata + s を入れて下さい。
サイズが決定されている文字列操作ならやっぱりMID$()ステートメントが一番かと。
それかByte()→Stringを使うことかな…
-VB6-
dim s as string
s="1234"
mid$(s,1,2)="ab"
過去に書いた0なら白1なら黒というようにならんでいる形式
で保存すると何故か24Bitになってしまいました
せっかく
ガッ様 ねろ様・・・ すいませんが
元の話に戻らせていただきます(勝手ながら)
通ってみた様の教えていただいたものですと
(コードです長々とすいません)'色取得用
Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long) As Long
'BMPファイルのヘッダー−ファイル情報
Private Type BITMAPFILEHEADER
bfType As Integer
bfSize As Long
bfReserved1 As Integer
bfReserved2 As Integer
bfOffBits As Long
End Type
'BMPファイルのヘッダー−ビットマップの情報
Private Type BITMAPINFOHEADER
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
'パレット用
Private Type RGBQUAD
rgbBlue As Byte
rgbGreen As Byte
rgbRed As Byte
rgbReserved As Byte
End Type
Sub SaveMonoImage(FN As String, picBox As PictureBox)
Dim BFH As BITMAPFILEHEADER 'ヘッダーその1
Dim BIH As BITMAPINFOHEADER 'ヘッダーその2
Dim Pal(1) As RGBQUAD 'パレット2色分
Dim BMByte() As Byte '実際のバイト
Dim BMX As Integer, BMY As Integer '縦横のサイズ
Dim BMXByte As Integer '1ラインあたりのバイト数
Dim Temp As Integer, Temp2 As Integer, Temp3 As Long, Temp4 As Long '作業用変数
Dim Tcol As Byte '作業用変数
Dim srcDC As Long 'デバイスコンテキスト
'高速化のためにPoint関数でなくGetPixelを使っています。
'そのためAutoRedrawプロパティがTrueでないとうまく動作しません。
'ビットマップファイルの各ラインのバイト数計算
BMX = picBox.ScaleWidth
BMY = picBox.ScaleHeight
BMXByte = (BMX - 1) \ 8 + 1 'バイト数計算
Temp = ((BMXByte - 1) \ 4 + 1) * 4 - 1 'バイト境界を4バイトにそろえている
ReDim BMByte(Temp, BMY - 1)
'ヘッダー初期化
With BFH
.bfType = &H4D42 '保存時に「BM」となる
.bfOffBits = 62 'BFHが14バイト、BIFが40バイト、パレットが8バイト
.bfSize = 62 + (Temp + 1) * BMY
End With
With BIH
.biSize = 40 'BIFは40バイト
.biWidth = BMX '幅
.biHeight = BMY '高さ
.biPlanes = 1 '常に1
.biBitCount = 1 '2色なので1ビット
.biSizeImage = BFH.bfSize - 62
End With
With Pal(0)
.rgbBlue = 255: .rgbRed = 255: .rgbGreen = 255 'rgbReservedは0なのでそのまま
'Pal(1)は黒だが、すべて0でいいのでそのまま
End With
srcDC = picBox.hdc
For Temp = BMY - 1 To 0 Step -1 '1ラインずつ下から作成
For Temp2 = 0 To BMXByte - 1 '1バイトずつ作成
Tcol = 0
For Temp3 = 0 To 7 '1バイトは8ビット
Temp4 = GetPixel(srcDC, Temp2 * 8 + Temp3, Temp)
If Temp4 = 0 Then Tcol = Tcol + 2 ^ (7 - Temp3) '黒の場合
Next
BMByte(Temp2, BMY - 1 - Temp) = Tcol
Next
Next
Open FN For Binary As 1
Put 1, , BFH
Put 1, , BIH
Put 1, , Pal()
Put 1, , BMByte()
Close
なんですが・・・
Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
'BMPファイルのヘッダー−ファイル情報
Private Type BITMAPFILEHEADER
bfType As Integer
bfSize As Long
bfReserved1 As Integer
bfReserved2 As Integer
bfOffBits As Long
End Type
'BMPファイルのヘッダー−ビットマップの情報
Private Type BITMAPINFOHEADER
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
'パレット用
Private Type RGBQUAD
rgbBlue As Byte
rgbGreen As Byte
rgbRed As Byte
rgbReserved As Byte
End Type
Private Type BITMAPINFO
bmiHeader As BITMAPINFOHEADER
bmiColors(1) As RGBQUAD
End Type
Sub SaveMonoImage(FN As String, picBox As PictureBox)
Dim BFH As BITMAPFILEHEADER 'ヘッダーその1
Dim BInf As BITMAPINFO 'ヘッダーその2
Dim BMByte() As Byte '実際のバイト
Dim BMX As Integer, BMY As Integer '縦横のサイズ
Dim srcDC As Long 'デバイスコンテキスト
Dim Fno As Long
'高速化のためにPoint関数でなくGetPixelを使っています。
'そのためAutoRedrawプロパティがTrueでないとうまく動作しません。
'ビットマップファイルの各ラインのバイト数計算
BMX = picBox.ScaleWidth
BMY = picBox.ScaleHeight
ReDim BMByte((BMX * BMY \ 8) - 1)'イメージのサイズ
'ヘッダー初期化
With BFH
.bfType = &H4D42 '保存時に「BM」となる
.bfOffBits = 62 'BFHが14バイト、BIFが40バイト、パレットが8バイト
.bfSize = Len(BFH) + Len(BInf) + (BMX * BMY \ 8)
End With
With BInf.bmiHeader
.biSize = Len(BInf.bmiHeader) 'BIFは40バイト
.biWidth = BMX '幅
.biHeight = BMY '高さ
.biPlanes = 1 '常に1
.biBitCount = 1 '2色なので1ビット
.biSizeImage = BFH.bfSize - Len(BInf)
End With
With BInf.bmiColors(1)
.rgbBlue = 255: .rgbRed = 255: .rgbGreen = 255 'rgbReservedは0なのでそのまま
'Pal(1)は黒だが、すべて0でいいのでそのまま
End With
GetDIBits picBox.hDC, picBox.Image, 0&, BInf.bmiHeader.biHeight,BMByte(0), BInf, 0&
Fno = FreeFile
Open FN For Binary As #Fno
Put #Fno, , BFH
Put #Fno, , BInf
Put #Fno, , BMByte()
Close #Fno
End Sub
適当に変えてみました。
あとは手直ししてくださいね。
ツイート | ![]() |