C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[1]: AVIから映像を1/60フィールドごとにBMP形式で保存


(過去ログ 81 を表示中)

[トピック内 2 記事 (1 - 2 表示)]  << 0 >>

■48346 / inTopicNo.1)  AVIから映像を1/60フィールドごとにBMP形式で保存
  
□投稿者/ ちっぺ (1回)-(2010/04/03(Sat) 10:58:35)

分類:[VB.NET/VB2005 以降] 

こんにちは。
現在、VB.net(2008)でAVIファイルから映像を1/60フィールドごとに
BMP形式で保存するソフトを作成しています。以前、VB6.0で
同様のソフトを作っていましたが、Vista以降、ソフトがうまく
作動しなくなったので、VB.netでの作成を始めました。
いろいろなサイトを検索して、AVIから1/30ごとの映像をBMP形式で
取り出すところまではできましたが、どうしても1/30から1/60に
分割するところがうまくできません(下記VB6.0のソース中の
プロシジャー「SeparateDIB」)。
そこで、みなさまのお知恵をお借りしたいと思い、投稿させて
頂きました。


下記、VB6.0のソースです。

Public Sub AVI_to_BMP(ByVal strAVIFileName As String, ByVal strBMPFileName As String, ByVal lngAVIFrameNo As Long, ByVal intSeparateType As Integer)
    Dim pAVIFile As Long            'AVIファイルのインターフェースアドレス(pPAVIFile)
    Dim pAVIStream As Long          'ビデオストリームのインターフェースアドレス(pPAVIStream)
    Dim pGetFrameObj As Long        'AVIStreamGetFrameで使用するFetFrameオブジェクト
    Dim pDIB As Long                'パックDIB
    Dim bmpIH As BITMAPINFOHEADER   'ビットマップ情報ヘッダー

    'AVIFileライブラリを開く
    AVIFileInit
    'AVIファイルのインターフェースアドレス獲得(pPAVIFile)
    AVIFileOpen pAVIFile, strAVIFileName, OF_READ, 0&
    'ビデオストリームのインターフェースアドレス獲得(pPAVIStream)
    AVIFileGetStream pAVIFile, pAVIStream, streamtypeVIDEO, 0

    'ビットマップ情報ヘッダー
    With bmpIH
        .biSize = 40                
        .biWidth = 0             
        .biHeight = 0              
        .biPlanes = 1             
        .biBitCount = 24           
        .biCompression = 0        
        .biSizeImage = 0           
        .biXPelsPerMeter = 0       
        .biYPelsPerMeter = 0        
        .biClrUsed = 0             
        .biClrImportant = 0        
    End With

    'ビデオストリームからビデオフレームを解凍する準備をする
    '   (AVIStreamGetFrameで使用するGetFrameオブジェクトが返る)
    'bmpIHの戻り値あり->.biWidthと.biHeight
    pGetFrameObj = AVIStreamGetFrameOpen(pAVIStream, bmpIH) '必ず24bit DIBS
    '圧縮解除されたビデオフレームのアドレスを取得する/パックDIBとして返る
    pDIB = AVIStreamGetFrame(pGetFrameObj, lngAVIFrameNo)

    GetPackedDIBPointer pDIB          'パックDIB展開
    SeparateDIB intSeparateType       '1/30->1/60分離
    PutToBMPFile strBMPFileName       'BMPFileName保存

ErrorOut:
    'GetFrameのリソースとインターフェースを開放する
    AVIStreamGetFrameClose pGetFrameObj
    'ビデオストリームを閉じる
    AVIStreamRelease pAVIStream
    'ファイルを閉じる
    AVIFileRelease pAVIFile
    'AVIFileライブラリを閉じる
    AVIFileExit

End Sub



Private Sub GetPackedDIBPointer(ByRef pDIB As Long)
    'BMP情報ヘッダー獲得    VarPtr(value)|バリアブルポインター|変数のアドレスを長整数型(long)で返す
    Call CopyMemory(ByVal VarPtr(m_BmpIH.biSize), ByVal pDIB, Len(m_BmpIH))

    'BMPサイズイメージを再定義<<< 720*480や640*480の画像へ変更したときに有効
    ReDim m_memBits(0 To m_BmpIH.biSizeImage - 1)

    'BMP変数へ一気にコピー
    Call CopyMemory(m_memBits(0), ByVal pDIB + 40, m_BmpIH.biSizeImage)

    'ファイルヘッダー部
    With m_BmpFH
        .bftype = "BM"
        .bfSize = 55 + m_BmpIH.biSizeImage          
        .bfReserved1 = 0&
        .bfReserved2 = 0&
        .bfOffBits = 54                             
    End With
End Sub



Private Sub SeparateDIB(ByVal intSeparateType As Integer)
    Dim j As Long
Dim k As Long
Dim l As Long

    ' フィールドの分離
    Select Case intSeparateType
    Case 0
        '後の1/60は偶数行:偶数行を次の奇数行にコピー
        For j = 0 To m_BmpIH.biHeight - 2 Step 2
            k = j * m_BmpIH.biWidth * 3         'Org
            l = (j + 1) * m_BmpIH.biWidth * 3   'Dest
            Call CopyMemory(m_memBits(l), m_memBits(k), Len(m_memBits(k)) * m_BmpIH.biWidth * 3)
        Next
    Case 1
        '先の1/60は奇数行:奇数行を次の偶数行にコピー
        For j = 1 To m_BmpIH.biHeight - 2 Step 2
            k = j * m_BmpIH.biWidth * 3         'Org
            l = (j + 1) * m_BmpIH.biWidth * 3   'Dest
            Call CopyMemory(m_memBits(l), m_memBits(k), Len(m_memBits(k)) * m_BmpIH.biWidth * 3)
        Next
    End Select
End Sub



Private Sub PutToBMPFile(ByVal strFileName As String)
    Dim intFileNumber As Integer

    intFileNumber = FreeFile()
    Open strFileName For Binary As intFileNumber
    Put intFileNumber, 1, m_BmpFH
    Put intFileNumber, Len(m_BmpFH) + 1, m_BmpIH
    Put intFileNumber, , m_memBits
    Close intFileNumber
End Sub


現在は、一旦1/30のBMPで落として、その後、System.Drawing.Bitmap.Clone、
System.Drawing.Graphics.FromImageを使って、走査線の
偶数行(もしくは奇数行)を次の奇数行(もしくは偶数行)
にコピーして、1/60の映像を抽出してますが、処理速度が
遅すぎて、実用的ではありません。
ソフトの使用方法としては、BMP形式で保存したファイルをフォーム上の
picture boxに表示させようとしているですが、わざわざBMP
で落とさず(処理速度を高めるために)、直接メモリから表示
できる方法があれば、合わせてお教え頂ければ幸いです。

どうかよろしくお願い致します。


引用返信 編集キー/
■48350 / inTopicNo.2)  Re[1]: AVIから映像を1/60フィールドごとにBMP形式で保存
□投稿者/ やじゅ (1580回)-(2010/04/03(Sat) 11:56:24)
やじゅ さんの Web サイト
2010/04/03(Sat) 12:13:59 編集(投稿者)
2010/04/03(Sat) 12:08:02 編集(投稿者)

No48346 (ちっぺ さん) に返信
> picture boxに表示させようとしているですが、わざわざBMP
> で落とさず(処理速度を高めるために)、直接メモリから表示
> できる方法があれば、合わせてお教え頂ければ幸いです。

参考になりそうなサイトとして、
画像ファイルフォーマットをMemoryStreamに書き込んで、それを自力で解釈する方法です

System.Drawing.Bitmap画像を使った高速な画像処理プログラミングについて
http://blogs.yahoo.co.jp/mocchi_2003/40367106.html

[C#]AVIファイルからBMPを作成する
http://d.hatena.ne.jp/akiramei/20071224/1198500056

ついで…
■Excelで「ひぐらしのなく頃に解」のOP(オープニング)を再現してみた
http://clicksclicks.blog105.fc2.com/blog-entry-241.html
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -