bmpファイルを読み込み
180度回転する処理を施し
保存する
というアプリを作成しようとしてますが
picture box に貼り付けて回転させて保存しますと、
元のbmpファイルと大きさ(サイズ)が変わってしまい、困っています。
フォームに作ったpicture boxの大きさに依存するようです。
bmpファイルをサイズなど変えることなく処理をする
方法をご存知の方いましたらご教授ください。
環境はVB6です。
ヒント:
とりあえず「正しく動かない」ソースコードを貼ります
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, Source As Any, ByVal Length As Long)
Sub rot180(ByVal srcfile As String, ByVal dstfile As String)
'正しく動きません
Const btimapfileheader_len = 14
Const bitmapinfoheader_len = 40
Dim i As Long
Dim j As Long
Dim srcff As Integer
Dim dstff As Integer
Dim wlen As Long
Dim wlenb As Long
Dim hlen As Long
Dim bitc As Long
Dim buf() As Byte
Dim buf2() As Byte
srcff = FreeFile: Open srcfile For Binary Lock Read Write As srcff
dstff = FreeFile: Open dstfile For Binary Lock Write As dstff
'1 ヘッダ部分をコピー
ReDim buf(1 To btimapfileheader_len + bitmapinfoheader_len)
Get #srcff, , buf
Put #dstff, , buf
bitc = getInt(buf, 28)
wlen = getLng(buf, 18) * bitc / 8: wlenb = ((wlen - 1) \ 4 + 1) * 4
hlen = getLng(buf, 22)
'2 パレットを必要に応じてコピー
If bitc <= 8 Then
ReDim buf(1 To 2 ^ bitc)
Get #srcff, , buf
Put #dstff, , buf
End If
'3 イメージを反転してコピー
ReDim buf(1 To wlenb * hlen)
ReDim buf2(1 To wlenb * hlen)
Get #srcff, , buf
For i = 0 To hlen - 1
For j = 1 To wlen
buf2((hlen - i - 1) * wlenb + (wlen - j + 1)) = buf(i * wlenb + j)
Next
Next
Put #dstff, , buf2
Close srcff, dstff
End Sub
Function getInt(ByRef b() As Byte, ByVal ofs As Long) As Integer
CopyMemory getInt, b(LBound(b) + ofs), 2
End Function
Function getLng(ByRef b() As Byte, ByVal ofs As Long) As Integer
CopyMemory getLng, b(LBound(b) + ofs), 4
End Function
まず、ビットマップデータを180°回転させることはどういうことかというと
・dstBitmap.pixel(x,y)=srcBitmap.pixel(width-x+1,height-y+1)
(1<=x<=width, 1<=y<=height)
という操作を全ピクセルに対して行うということです。
ここで重要なのは、1ピクセルのビット数(色深度)が1,4,8,16,24,32ビットの種類があるということと、
8ビット以下のビットマップの場合はインデックスカラーを使っていることと、
8ビット未満のビットマップのビットにアクセスする場合はビット列を操作しなくてはいけないことです。
つまり、ピクセル≠Byteなので、冒頭に書いたような表現(.pixel()という夢のメソッドを使った表現)になるわけです。
…とまぁ多分、専用のライブラリを探すか、1ピクセルにアクセスできるようなライブラリを作るとかしないと面倒だと思います。
ちなみに、前回の私のレスのプログラムはその辺を全く考慮していません。
もしかしたら8ビットビットマップは可能かもしれませんが…
bitmapではなく、pictureBoxをまわしたらだめなの。
すいません。間違えました。ごめんなさい。
前の発言はなかった事にしてください。
変換アルゴリズムを実装したくないのでGDIを使うとして、
元のBMPがRLEなど圧縮されたフォーマットでないとすれば、
1,まず元の画像と同じ形式・大きさのDIBをCreateDIBSection
などを使って作る。
2,MemDCを作ってSelectObjectする。
3,もし256色以下ならば、SetDIBColorTableなどを用いてパレット
の色も設定する。
4,BitBltなどの転送命令を使って回転させたデータを転送する。
5,OleCreatePictureIndirectでPictureオブジェクトに変換する。
6,SelectObject、DeleteDCなどで後始末をする。
7,SavePicture関数で保存する。
という手順で行けるでしょう。
180度固定ということであれば泥臭いですが
1.PictureBoxを配置しAutoSize=Trueにする
2.画像を読み込み
3.PaintPictureを使ってWidthをマイナスにして左右反転
4.同じくHeightをマイナスにして上下反転
というのはだめでしょうか?
ツイート | ![]() |