緑の抜き出し(C)

 

effect.c

//

// effect.c

//

// (c)Copyright Spacesoft corp., 2007 All rights reserved.

//                               Hiro KITAYAMA

//

#include <windows.h>

 

 

//---------------------------------------------------------------------------

//

// エフェクト

//

void effect( LPBYTE pInSrc, LPBYTE pInDst, LONG width, LONG height )

{

    int x, y ;

    LPBYTE pSrc=pInSrc ;

    LPBYTE pDst=pInDst ;

 

    for( y = 0 ; y < height ; y++ )

        for( x = 0 ; x < width ; x++ )

        {

            *pDst++ = 0 ;           // G

            *pDst++ = *pSrc++ ;     // B

            *pDst++ = 0 ;           // R

            pDst++ ;

            pSrc +=3;

        }

}

 

pgm.c

//

// pgm.c

//

// (c)Copyright Spacesoft corp., 2007 All rights reserved.

//                               Hiro KITAYAMA

//

#include <stdio.h>

#include <conio.h>                  // kbhit(), getch()

#include <stdlib.h>                 // _splitpath()

#include <windows.h>

 

#define SAFE_FREE( p )      if( p ) { free( p ) ; p=NULL ; }

#define SZCLASSNAME         "TEST"

 

// グローバル変数

PBITMAPINFOHEADER   pDib ;      // tolal

LPBYTE              pBitmap ;   // data

 

void effect( LPBYTE pSrc, LPBYTE pDst, LONG width, LONG height );

 

 

//---------------------------------------------------------------------------

//

// ファイル名の取得

//

BOOL getFname( char* inFname )

{

    OPENFILENAME fName ;

    char fileName[256] ;

    const char filefilter[] = "BMPファイル(*.bmp)\0*.bmp\0\0" ;

 

    fileName[0] = '\0' ;

 

    memset( &fName, 0, sizeof(OPENFILENAME) ) ;

    fName.lStructSize    = sizeof(OPENFILENAME) ;

    fName.lpstrFilter    = filefilter ;

    fName.nFilterIndex   = 1 ;

    fName.lpstrFile      = fileName ;

    fName.nMaxFile       = sizeof(fileName) ;

    fName.Flags          = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY ;

 

    // 「ファイルを開く」ダイアログ

    if( GetOpenFileName( &fName ) == 0 )

        return FALSE ;

 

    strcpy( inFname, fileName ) ;

 

    return TRUE ;

}

 

 

//---------------------------------------------------------------------------

//

// ビットッマプヘッダの読み込み

//

BOOL readHeader( FILE* fp, PBITMAPFILEHEADER bmHdr )

{

    // ビットッマプヘッダの読み込み

    if( fread( bmHdr, sizeof(BITMAPFILEHEADER), 1, fp ) !=  1 )

    {

        fprintf( stderr, "エラー:ファイル読み込み.\n" ) ;

        return FALSE ;

    }

 

    // ビットッマプファイルかチェック

    if ( bmHdr -> bfType != 'M'*256+'B' )

    {

        fprintf( stderr, "エラー:BMPフォーマットでは無い.\n" );

        return FALSE ;

    }

    return TRUE ;

}

 

 

//---------------------------------------------------------------------------

//

// ビットッマプ本体の読み込み

//

BOOL readBody( FILE* fp, PBITMAPFILEHEADER bmHdr, PBITMAPINFOHEADER pDib )

{

    int bitmapSize ;

 

    bitmapSize = bmHdr -> bfSize - sizeof(BITMAPFILEHEADER) ;   // 画像の大きさ

 

    // ビットッマプ本体の読み込み

    if( fread( pDib , bitmapSize, 1, fp ) !=  1 )

    {

        fprintf( stderr, "エラー:ファイル読み込み.\n" ) ;

        return FALSE ;

    }

    if( pDib -> biBitCount != 32 )

    {

        fprintf( stderr, "エラー:32ビット ビットッマプではない.\n");

        return FALSE ;

    }

    return TRUE ;

}

 

 

//---------------------------------------------------------------------------

//

// window procedure

//

LRESULT CALLBACK WindProc( HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam )

{

    PAINTSTRUCT ps ;

 

    switch( uMessage )

    {

        case WM_PAINT:

            BeginPaint( hWnd, &ps ) ;

            SetDIBitsToDevice( ps.hdc, 0, 0,        // copy BMP

                                pDib -> biWidth, pDib -> biHeight,

                                    0, 0, 0, pDib -> biHeight, pBitmap,

                                        (BITMAPINFO*)pDib, DIB_RGB_COLORS ) ;

            EndPaint( hWnd, &ps ) ;

            break ;

 

        case WM_DESTROY:

            PostQuitMessage( 0 ) ;

            break ;

 

        default:

            return DefWindowProc( hWnd, uMessage, wParam, lParam ) ;

    }

    return 0 ;

}

 

 

//---------------------------------------------------------------------------

//

// create window

//

HWND createWindow( PBITMAPINFOHEADER pDib )

{

    HINSTANCE hInstanse ;

    WNDCLASSEX  wcx ;

    HWND hWnd = NULL ;

    int  ttlHeight, frameWidth, frameHeight ;

    int  windowWidth, windowHeight ;

 

    hInstanse = (HINSTANCE)GetWindowLong( NULL, GWL_HINSTANCE ) ;

 

    memset( &wcx, 0, sizeof(WNDCLASSEX) ) ;

    wcx.cbSize        = sizeof(WNDCLASSEX) ;

    wcx.lpfnWndProc   = WindProc ;                      // ウィンドウプロシージャ

    wcx.hInstance     = hInstanse ;

    wcx.hCursor       = LoadCursor( NULL, IDC_ARROW ) ;

    wcx.lpszClassName = SZCLASSNAME ;                   // ウィンドウクラス名

    if( !RegisterClassEx( &wcx ) )                      // ウィンドウクラスの登録

        return NULL ;                                   // 失敗

 

    ttlHeight   = GetSystemMetrics( SM_CYCAPTION ) ;    // ウィンドウタイトルの高さ

    frameWidth  = GetSystemMetrics( SM_CXFIXEDFRAME ) ; // ウィンドウフレームの幅

    frameHeight = GetSystemMetrics( SM_CYFIXEDFRAME ) ; // ウィンドウフレームの高さ

 

    windowWidth = pDib -> biWidth  + (frameWidth * 2),  // ウィンドウの幅

    windowHeight= pDib -> biHeight

                    + ttlHeight + (frameHeight * 2) ;   // ウィンドウの高さ

 

    hWnd = CreateWindow( SZCLASSNAME,                   // ウィンドウクラス名

                "表示ウィンドウ",                       // ウィンドウタイトル

                WS_OVERLAPPED | WS_SYSMENU | WS_VISIBLE,// ウィンドウスタイル

                CW_USEDEFAULT, CW_USEDEFAULT,           // ウィンドウ位置

                windowWidth,windowHeight,               // ウィンドウサイズ

                HWND_DESKTOP, NULL, hInstanse, NULL ) ;

 

    return hWnd ;

}

 

 

//---------------------------------------------------------------------------

//

// main

//

int main( int argc, char* argv[] )

{

    char  fName[_MAX_PATH], dfFile[_MAX_PATH], dfName[_MAX_FNAME], dfExt[_MAX_EXT ] ;

    BITMAPFILEHEADER bmHdr ;

    FILE*  fp ;

    HWND   hWnd ;

    MSG    msg ;

    int    bitmapSize, loop, imgSize ;

    LPBYTE pSrc, pDst ;                     // SIMD用バッファ

    UINT64 begin, finish, elapsed ;         // 性能表示

 

    if( argc < 2 )

        getFname( fName ) ;                 // 引数なし

    else

        strcpy( fName, argv[1] ) ;          // 引数あり

 

 

    // ビットマップファイルのオープン

    if( (fp = fopen( fName, "rb" )) == NULL )

    {

        fprintf( stderr, "エラー:ファイルのオープンに失敗.\n" ) ;

        return -1;

    }

 

    // ファイル名の表示

    _splitpath( fName, NULL, NULL, dfName, dfExt ) ;

    strcpy( dfFile, dfName ) ;

    strcat( dfFile, dfExt ) ;

    fprintf( stdout, "ファイル名 = [%s]\n", dfFile ) ;

 

    // ヘッダの読み込み

    if( !readHeader( fp, &bmHdr ) )

    {

        fclose( fp ) ;      // ファイルクローズ

        return -1;

    }

 

 

    // ビットマップ本体のサイズ

    bitmapSize = bmHdr.bfSize - sizeof(BITMAPFILEHEADER) ;

 

    // メモリ確保

    pDib = (BITMAPINFOHEADER *)malloc( bitmapSize ) ;

 

    // 本体読み込み

    if( !readBody( fp, &bmHdr, pDib ) )

    {

        SAFE_FREE( pDib ) ;     // メモリ解放

        fclose( fp ) ;          // ファイルクローズ

        return -1;

    }

 

    fclose( fp ) ;              // ファイルクローズ

 

 

    // 画像サイズの表示

    fprintf( stdout, "ビットマップサイズ= %d x %d\n",

                                pDib -> biWidth, pDib -> biHeight ) ;

 

    // ポインタをビットマップ本体位置へ移動

    pBitmap = (BYTE *)(pDib) + bmHdr.bfOffBits - sizeof(BITMAPFILEHEADER) ;

 

    imgSize=pDib->biWidth * pDib->biHeight * 4;

 

    // alignされたメモリを確保

    pSrc = (LPBYTE)_aligned_malloc(imgSize, 16);

    pDst = (LPBYTE)_aligned_malloc(imgSize, 16);

 

    // alignされたエリアにコピー

    memcpy(pSrc, pBitmap, imgSize);

 

    _asm

    {

        rdtsc

        mov     dword ptr [begin], eax

        mov     dword ptr [begin+4], edx

    }

 

    //画像処理

    for(loop=0;loop<100;loop++) //キャッシュなどの影響を排除するため100回実行

        effect( pSrc, pDst, pDib -> biWidth, pDib -> biHeight ) ;

 

    _asm

    {

        rdtsc

        mov     dword ptr [finish], eax

        mov     dword ptr [finish+4], edx

    }

    elapsed = finish > begin ? finish - begin : begin - finish ;

    printf( "counter= %I64u\n", elapsed ) ;

 

 

    // alignされたエリアからbitmapへコピー

    memcpy(pBitmap, pDst, imgSize);

 

    hWnd = createWindow( pDib ) ;           // ウィンドウ表示

 

    fprintf( stdout, "Enterキーを押せば終わります..." ) ;

 

    // メッセージループ

    msg.message = WM_CREATE ;               // dummy for while

    while( msg.message != WM_QUIT )

    {

        if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )

        {

            TranslateMessage( &msg ) ;

            DispatchMessage( &msg ) ;

        }

 

        // Enterキーを押されたらQuit

        if( kbhit() )

        {

            PostMessage( hWnd, (UINT)WM_DESTROY, (UINT)0, (LONG)0 ) ;

            getch() ;

        }

    }

 

    SAFE_FREE( pDib ) ;         // メモリ解放

    _aligned_free(pSrc);        // メモリ解放

    _aligned_free(pDst);        // メモリ解放

 

    return 0;

}