RIFF構造データ(AVI/WAVE+MP3)の再生/画像処理

 AVI/WAVE 等の表示を行うためのプログラム(dgwriff)に画像処理機能を追加し、若干修正等を加えたものです。dgwriff の動作確認を行っていくと、動作環境によってコーデックおよびMP3の再生用のドライバの検索が上手くできなくて再生できない場合も発生するようです。その点の修正等は行っていません。情報等があればご報告おねがいします m(__)m。mp3の再生位置の調整も若干おかしいかも??です。 今回のソースには、Visual Studio(VC 6,7,8) のデバッグ環境も追加しておきます(VC6: dgwriff.dsw, VC7: dgwriff-7.0.vcproj, VC8: dgwriff.vcproj)。自宅のVisual Studio 2005(VC++ 8)でデバッグしていると、sprintf,strcat 等は古いからもう使用するな、というワーニングが大量に出てくるようになっていたのですが、

#pragma warning(disable: 4996)    // Invalid C4996 warning (for VC8)
#pragma warning(disable: 4793)    // Invalid C4793 warning (for VC8)

コーディング部

#pragma warning(pop)

のようにして、ワーニングを抑制しています。gcc 等でコンパイルしている時もあるので、上記のワーニングは意味がないですよね^^。また、VC++ 8でデバッグしていると、_WIN32_IE が宣言されていないみたいな警告も出るようになってしまったので、

#ifndef _MSC_VER
#define _WIN32_IE 0x0300
#endif

も追加するようにしました。下記のプログラムにて確認してください。

cygwin 用の VFW 環境が入っていない方は multilib.zip の内容を、/usr/lib/w32api と /usr/include/w32api にコピーして下さい。最新の VFW のライブラリで動作できるかどうかは未確認です。

 ダウンロード

画像処理用処理関数etc.(ダウンロード用にまとめています。)
(dgwriff.cpp)
/**
 * $Id: dgwriff.cpp,v 1.3 2006/08/29 03:23:51 a-gamyl Exp a-gamyl $
 *  RIFF構造のデータ表示(AVI/WAVE)
 */
//-----------------------------------------------------------------
// for gcc
//-----------------------------------------------------------------
#ifndef _MSC_VER
#define _WIN32_IE 0x0300
#endif
//-----------------------------------------------------------------
#include <windows.h>
#include "resource.h"
#include "driff.h"
//-----------------------------------------------------------------
#pragma warning(push)
#pragma warning(disable: 4996)    // Invalid C4996 warning (for VC8)
#pragma warning(disable: 4793)    // Invalid C4793 warning (for VC8)
//-----------------------------------------------------------------
#pragma comment(linker,"/subsystem:windows")    // for VC++
//-----------------------------------------------------------------
// global strings
//-----------------------------------------------------------------
HINSTANCE hAppInst;                        // instance of application
TCHAR szTitle[256];                        // title string
TCHAR szWindowClass[256];                // class name
TCHAR ArgFname[256];                    // argument
BOOL  ArgLoad = FALSE;
//-----------------------------------------------------------------
// declaration of functions
//-----------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
ATOM MyRegisterClass(HINSTANCE hInst);
BOOL InitInstance(HINSTANCE hInst,int nCmdSw);
void GetWinRect(HWND hWnd,int* x,int* y);
HWND MakeMyRebar(HWND hWnd);
//-----------------------------------------------------------------
int APIENTRY WinMain(HINSTANCE hInst,HINSTANCE hpInst,LPSTR lpArgv,int nCmdSw)
{
    MSG msg; HACCEL hAccelTable;
    // load strings
    LoadString(hInst,IDS_APP_TITLE,szTitle,256);
    LoadString(hInst,IDC_DG,szWindowClass,256);
    MyRegisterClass(hInst);
    // get argument
    if(strcmp(lpArgv,"")) {
        ArgLoad = TRUE; strcat(ArgFname,lpArgv);
    }
    // initialize application
    if(!InitInstance(hInst,nCmdSw)) { return FALSE; }
    // message loop
    hAccelTable = LoadAccelerators(hInst,(LPCTSTR)IDC_DG);
    while(GetMessage(&msg,NULL,0,0)) {
        if(!TranslateAccelerator (msg.hwnd,hAccelTable,&msg)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return (int)msg.wParam;
}
//-----------------------------------------------------------------
// MyRegisterClass(HINSTANCE hInst)
//-----------------------------------------------------------------
ATOM MyRegisterClass(HINSTANCE hInst)
{
    WNDCLASSEX wcex;
    wcex.cbSize         = sizeof(WNDCLASSEX); 
    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = (WNDPROC)WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInst;
    wcex.hIcon            = NULL;
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = (LPCSTR)IDC_DG;
    wcex.lpszClassName    = szWindowClass;
    wcex.hIconSm        = NULL;
    return RegisterClassEx(&wcex);
}
//-----------------------------------------------------------------
// InitInstance(HANDLE, int)
//-----------------------------------------------------------------
BOOL InitInstance(HINSTANCE hInst,int nCmdSw)
{
    hAppInst = hInst;
    HWND hWnd = CreateWindow(szWindowClass,szTitle,WS_OVERLAPPEDWINDOW,
                             CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInst,NULL);
    if(!hWnd) return FALSE;
    DragAcceptFiles(hWnd,TRUE);    // accept drag and drop
    ShowWindow(hWnd,nCmdSw);
    UpdateWindow(hWnd);
    return TRUE;
}
//-----------------------------------------------------------------
// WndProc(HWND, unsigned, WORD, LONG)
//-----------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
    static int no=0,scrPos=0;
    static INITCOMMONCONTROLSEX ic;
    static REBARBANDINFO rbBand;
    static SCROLLINFO scr;
    static HWND hEdit,hCanvas;
    static HWND hRebar,hBut,hScroll,hCombo;
    static HMENU hMenu;
    static HDROP hDrop;
    static HFONT hFont;
    static int wx,wy,wex,wey;
    static char szFn[256];
    char szData[16];
    RECT rc;
    // ip functions
    static int n_ipfunc = 14;
    static int IPFUNC[] = {
        IDM_IP_DEFAULT,IDM_IP_GRAYSCALE,IDM_IP_MEDIAN,IDM_IP_BINALIZE,
        IDM_IP_SELBINALIZE,IDM_IP_STEPCOLOR,IDM_IP_BWEROSION,IDM_IP_BWDILATATION,
        IDM_IP_BWTHINNING,IDM_IP_HGTLINE1,IDM_IP_HGTLINE2,IDM_IP_HGTCIRCLE,
        IDM_IP_HGTCIRCLE_1,IDM_IP_HGTCIRCLE_2};
    
    switch(msg) {
    case WM_CREATE: {
        InitCommonControls();
        hAppWnd = hWnd;
        hCanvas = hWnd;
        GetWinRect(hWnd,&wx,&wy);
        // Font
        hFont = CreateFont(11,0,0,0,FW_NORMAL,0,0,0,SHIFTJIS_CHARSET,
                           OUT_STROKE_PRECIS,CLIP_STROKE_PRECIS,DRAFT_QUALITY,
                           VARIABLE_PITCH | FF_SWISS,"MS ゴシック");
        // ToolBar
        ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
        ic.dwICC = ICC_COOL_CLASSES;
        InitCommonControlsEx(&ic);
        
        hRebar = MakeMyRebar(hWnd);
        ZeroMemory(&rbBand,sizeof(REBARBANDINFO));
        rbBand.cbSize = sizeof(REBARBANDINFO);
        rbBand.fMask  = RBBIM_TEXT | RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE;
        rbBand.fStyle = RBBS_CHILDEDGE;
        rbBand.cxMinChild = 0;
        rbBand.cyMinChild = 25;
        // Button
        hBut = CreateWindow("BUTTON","開始",
                            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                            0, 0, 0, 0, hRebar, (HMENU)ID_BUT1, hAppInst ,NULL);
        SendMessage(hBut,WM_SETFONT,(WPARAM)hFont,MAKELONG(TRUE,0));
        //rbBand.lpText = "開始";
        rbBand.hwndChild = hBut;
        rbBand.cx = 100;
        SendMessage(hRebar,RB_INSERTBAND,(WPARAM)-1,(LPARAM)&rbBand);

        // Canvas
        GetWindowRect(hRebar, &rc);
        hCanvas = CreateWindow("STATIC", NULL, WS_CHILD | WS_VISIBLE | SS_SUNKEN,
                               0,30+5,wx,wy-30+5,
                               hWnd,(HMENU)ID_CANVAS,hAppInst,NULL);
        // Edit
        hEdit = CreateWindow("EDIT", NULL, WS_CHILD | WS_THICKFRAME | WS_VISIBLE | WS_VSCROLL |
                             ES_MULTILINE | ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
                             wx-200,-3,200+3,wy-50+6,
                             hCanvas,(HMENU)ID_EDIT,hAppInst,NULL);
        SendMessage(hEdit,EM_SETLIMITTEXT,(WPARAM)1024*64,0);
        SendMessage(hEdit,WM_SETFONT,(WPARAM)hFont,MAKELONG(TRUE,0));
        GetWinRect(hEdit,&wex,&wey);
        
        // Scroll
        hScroll = CreateWindow("SCROLLBAR", NULL, WS_CHILD | WS_VISIBLE | SB_CTL,
                               0,wy-20,wx,20,
                               hWnd,(HMENU)ID_SCROLL,hAppInst,NULL);
        scr.cbSize = sizeof(SCROLLINFO);
        scr.fMask = SIF_PAGE | SIF_RANGE;
        scr.nMin  = 0; scr.nMax = 0;
        scr.nPage = 0;
        SetScrollInfo(hScroll,SB_CTL,&scr,TRUE);
        scr.fMask = SIF_POS;

        hMenu = GetMenu(hWnd);
        EnableMenuItem(hMenu,IDM_DWG1,MF_GRAYED);
        EnableMenuItem(hMenu,IDM_DWG2,MF_ENABLED);

        EnableMenuItem(hMenu,IDM_IP_DEFAULT,MF_GRAYED);
        
        // set image processing function
        dr.setImageFilter(IDM_IP_DEFAULT);
        // initialize DIB
        dggd.DDib = DrawDibOpen();
        // load argument
        if(ArgLoad) dr.FileOpen(ArgFname);
        
        dr.setWindow(hCanvas,hEdit,hBut,hScroll);
        break;
    }
    case WM_COMMAND: {
        /** image processing functions **/
        if(LOWORD(wParam) >= IDM_IP_DEFAULT && LOWORD(wParam) <= IPFUNC[n_ipfunc-1]){
            for(int i=0;i<n_ipfunc;i++){
                if(IPFUNC[i] == LOWORD(wParam)) EnableMenuItem(hMenu,IPFUNC[i],MF_GRAYED);
                else EnableMenuItem(hMenu,IPFUNC[i],MF_ENABLED);
            }
            dr.setImageFilter(LOWORD(wParam));
            break;
        }
        /** select menu **/
        switch(LOWORD(wParam)) {
        case IDM_EXIT:  DestroyWindow(hWnd);    break;
        case IDM_OPEN:  dr.FileOpen(); SetWindowText(hBut,"開始");    break;
        case IDM_OMIC:  dr.setWaveInput();        break;
        case IDM_CLOSE: dr.DrawClose(); SetWindowText(hBut,"開始");    break;
        case IDM_SIMG:  dr.FrameSave();            break;
        case IDM_DWG1:
            hMenu = GetMenu(hWnd);
            dr.setWaveDraw(DGW_NORMAL);
            EnableMenuItem(hMenu,IDM_DWG1,MF_GRAYED);
            EnableMenuItem(hMenu,IDM_DWG2,MF_ENABLED);
            break;
        case IDM_DWG2:
            hMenu = GetMenu(hWnd);
            dr.setWaveDraw(DGW_FFT);
            EnableMenuItem(hMenu,IDM_DWG2,MF_GRAYED);
            EnableMenuItem(hMenu,IDM_DWG1,MF_ENABLED);
            break;
        /** volume control **/
        case IDM_VOLUP:   dr.volumeUp();   break;
        case IDM_VOLDOWN: dr.volumeDown(); break;
        /** command buttons **/
        case ID_BUT1: {
            GetWindowText(hBut,szData,10);
            if(!strcmp(szData,"開始")){
                dr.DrawStart(); SetWindowText(hBut,"停止");
            } else {
                dr.DrawStop();  SetWindowText(hBut,"開始");
            }
            return FALSE;
            break;
        }
        InvalidateRect(hWnd,NULL,TRUE);
        break;
        }
    }
    // scroll position
    case WM_HSCROLL: {
        scrPos = GetScrollPos(hScroll,SB_CTL);
        switch(LOWORD(wParam)) {
        case SB_LINELEFT:   scrPos--;        break;
        case SB_LINERIGHT:  scrPos++;        break;
        case SB_PAGELEFT:   scrPos -= 10;    break;
        case SB_PAGERIGHT:  scrPos += 10;    break;
        case SB_THUMBTRACK: scrPos =(int)(HIWORD(wParam)); break;
        }
        dr.setScroll(scrPos);
        break;
    }
    // sound play done
    case MM_WOM_DONE: {
        dr.WavePlayDone();    break;
    }
    // record input sound done
    case MM_WIM_DATA: {
        dr.DrawWaveInput();    break;
    }
    case WM_PAINT: {
        InvalidateRect(hBut,NULL,FALSE);
        dr.DrawGraphic(1);
        break;
    }
    case WM_SIZE: {
        GetWinRect(hWnd,&wx,&wy);
        MoveWindow(hRebar,0,0,wx,30,TRUE);
        GetWindowRect(hRebar,&rc);
        GetWinRect(hEdit,&wex,&wey);
        if(wex>wx) wex=wx; if(wex<100) wex=100;
        MoveWindow(hCanvas,0,28,wx,wy-28-20,TRUE);
        MoveWindow(hEdit,wx-wex,-3,wex+3,wy-50+7,TRUE);
        MoveWindow(hScroll,0,wy-20,wx,20,TRUE);
        InvalidateRect(hCanvas,NULL,TRUE);
        SendMessage(hCanvas,WM_PAINT,0,0);
        break;
    }
    // file drop
    case WM_DROPFILES: {
        hDrop = (HDROP)wParam;
        DragQueryFile(hDrop,0,szFn,MAX_PATH);
        DragFinish(hDrop);
        dr.FileOpen(szFn);
        break;
    }
    case WM_DESTROY: {
        dr.DrawClose();
        DrawDibClose(dggd.DDib);
        PostQuitMessage(0);
        break;
    }
    }
    return DefWindowProc(hWnd,msg,wParam,lParam);
}

void GetWinRect(HWND hWnd,int* x,int* y)
{
    RECT rc;
    GetClientRect(hWnd,&rc);
    *x = rc.right - rc.left;
    *y = rc.bottom - rc.top;
    return;
}

HWND MakeMyRebar(HWND hWnd)
{
    int wx,wy;
    HWND hRebar;
    REBARINFO rbi;
    GetWinRect(hWnd,&wx,&wy);
    hRebar = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL,
                            WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | RBS_BANDBORDERS |
                            WS_CLIPCHILDREN | CCS_NODIVIDER,
                            0,0,wx,30,
                            hWnd, NULL, hAppInst, NULL);
    ZeroMemory(&rbi, sizeof(REBARINFO));
    rbi.cbSize = sizeof(REBARINFO);
    SendMessage(hRebar, RB_SETBARINFO, 0, (LPARAM)&rbi);
    return hRebar;
}

#pragma warning(pop)
inserted by FC2 system