BMPファイルをサイズを変えることなく回転させるには?


パピー  2006-02-13 01:58:29  No: 130181

bmpファイルを読み込み
180度回転する処理を施し
保存する
というアプリを作成しようとしてますが

picture box に貼り付けて回転させて保存しますと、
元のbmpファイルと大きさ(サイズ)が変わってしまい、困っています。
フォームに作ったpicture boxの大きさに依存するようです。

bmpファイルをサイズなど変えることなく処理をする
方法をご存知の方いましたらご教授ください。

環境はVB6です。


ガッ  2006-02-13 02:49:35  No: 130182

ヒント:
とりあえず「正しく動かない」ソースコードを貼ります
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


ガッ  2006-02-13 02:59:15  No: 130183

まず、ビットマップデータを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ビットビットマップは可能かもしれませんが…


nameless  2006-03-08 00:28:05  No: 130184

bitmapではなく、pictureBoxをまわしたらだめなの。


nameless  2006-03-08 00:30:22  No: 130185

すいません。間違えました。ごめんなさい。
前の発言はなかった事にしてください。


K.J.K.  2006-03-08 18:18:40  No: 130186

変換アルゴリズムを実装したくないのでGDIを使うとして、
元のBMPがRLEなど圧縮されたフォーマットでないとすれば、

1,まず元の画像と同じ形式・大きさのDIBをCreateDIBSection
 などを使って作る。
2,MemDCを作ってSelectObjectする。
3,もし256色以下ならば、SetDIBColorTableなどを用いてパレット
 の色も設定する。
4,BitBltなどの転送命令を使って回転させたデータを転送する。
5,OleCreatePictureIndirectでPictureオブジェクトに変換する。
6,SelectObject、DeleteDCなどで後始末をする。
7,SavePicture関数で保存する。

という手順で行けるでしょう。


自信ないけど  2006-03-25 02:11:14  No: 130187

180度固定ということであれば泥臭いですが

1.PictureBoxを配置しAutoSize=Trueにする
2.画像を読み込み
3.PaintPictureを使ってWidthをマイナスにして左右反転
4.同じくHeightをマイナスにして上下反転

というのはだめでしょうか?


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加