ソフトフォーカス・その1(GUI)

 

Cbmp.h(クラスのヘッダ)

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

//

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

//                               Hiro KITAYAMA

//

// クラスのヘッダ

//

 

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

#ifndef spCbmpH

#define spCbmpH

 

#define SAFE_DELETE(p)          if(p) { delete(p);         p=NULL ; }

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

#define SAFE_ALIGNED_FREE(p)    if(p) { _aligned_free(p);  p=NULL ; }

 

 

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

class Cbmp

{

private:

    // ----- private method -------------------------------------------------

    BITMAPFILEHEADER    bmFileHdr ;         // ヘッダ

    PBITMAPINFOHEADER   pDib ;              // DIBへのポインタ

    LPBYTE              pBitmap ;           // ビットマップ本体へのポインタ

    char bmpFName[256] ;                    // ビットマップファイル名

    int  wMargine ;                         // ラインの4バイトバウンダリまでの長さ

    int  lenScanline ;                      // ライン長さ(バイト)

 

    bool readHeader( FILE* fp, PBITMAPFILEHEADER bmFileHdr ) ;

    bool readBody( FILE* fp, PBITMAPFILEHEADER bmFileHdr,

                                                PBITMAPINFOHEADER pDib ) ;

 

 

public:

    // ----- Constructor/Destructor -----------------------------------------

    Cbmp( void ) ;                          // コンストラクタ

    ~Cbmp( void ) ;                         // デストラクタ

 

    // ----- public method --------------------------------------------------

    bool getFname( char* inFname ) ;        // ファイル名を取得

    void extFname( char* inFName ) ;        // ファイル名からパスを除く

    bool LoadFromFile( char* bmpFName ) ;   // ビットマップファイルの読み込み

    int  getwMargine( void ) ;              // ラインの4バイト境界までの長さ取得

    unsigned int getWidth( void ) ;         // ビットマップの幅取得

    unsigned int getHeight( void ) ;        // ビットマップの高さ取得

    PBITMAPINFOHEADER getPdib( void ) ;     // ビットマップヘッダのポインタ取得

    LPBYTE getPbitmapBody( void ) ;         // ビットマップ本体のポインタ取得

    LPBYTE getScanline( int lineNo ) ;      // ラインの先頭アドレスを得る

    bool is24bit( void ) ;                  // 24ビット・ビットマップか判断

    bool is32bit( void ) ;                  // 32ビット・ビットマップか判断

 

};

 

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

#endif

 

Cbmp.cpp(クラス)

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

//

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

//                               Hiro KITAYAMA

//

 

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

#include <stdio.h>

#include <windows.h>

 

#include "Cbmp.h"

 

 

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

//

// コンストラクタ

//

Cbmp::Cbmp( void )

{

    try

    {                           // 各初期化

 

        pDib        = NULL ;    // DIBへのポインタ

        pBitmap     = NULL ;    // ビットマップ本体へのポインタ

        bmpFName[0] = '\0' ;    // ビットマップファイル名

        wMargine    =    0 ;    // ラインの4バイトバウンダリまでの長さ

        lenScanline =    0 ;    // ライン長さ(バイト)

 

    }

    catch( ... )

    {

    }

}

 

 

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

//

// デストラクタ

//

Cbmp::~Cbmp( void )

{

    SAFE_FREE( pDib ) ;     // ビットマップオブジェクト削除

}

 

 

////////////////// ↓↓↓ここからprivateメソッド↓↓↓ /////////////////////

//

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

//

bool Cbmp::readHeader( FILE* fp, PBITMAPFILEHEADER bmFileHdr )

{

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

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

    {

        return false ;

    }

 

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

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

    {

        return false ;

    }

    return true ;

}

 

 

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

//

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

//

bool Cbmp::readBody( FILE* fp, PBITMAPFILEHEADER bmFileHdr, PBITMAPINFOHEADER pDib )

{

    int bitmapSize ;

 

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

 

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

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

    {

        return false ;

    }

    return true ;

}

////////////////// ↑↑↑ここまでprivateメソッド↑↑↑ /////////////////////

 

 

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

//

// ファイル名の取得

//

bool Cbmp::getFname( char* inFname )

{

    OPENFILENAME fName ;

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

 

    bmpFName[0] = '\0' ;

 

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

    fName.lStructSize    = sizeof(OPENFILENAME) ;

    fName.lpstrFilter    = filefilter ;

    fName.nFilterIndex   = 1 ;

    fName.lpstrFile      = bmpFName ;

    fName.nMaxFile       = sizeof(bmpFName) ;

    fName.Flags          = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY ;

 

    if( GetOpenFileName( &fName ) == 0 )    // 「ファイルを開く」ダイアログ

        return false ;

 

    strcpy( inFname, bmpFName ) ;

 

    return true ;

}

 

 

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

//

// extract file name

//

void Cbmp::extFname( char* inFName )

{

    char dfName[_MAX_FNAME], dfExt[_MAX_EXT ] ;

 

    // ファイル名の取り出し

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

    strcpy( inFName, dfName ) ;

    strcat( inFName, dfExt ) ;

}

 

 

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

//

// ビットマップのロード

//

// return true :成功

//        false:失敗

//

bool Cbmp::LoadFromFile( char* bmpFName )

{

    FILE* fp ;

    int bitmapSize ;

    bool rVal = true ;

 

    try

    {

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

 

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

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

            return false ;

 

        // ヘッダの読み込み

        if( !readHeader( fp, &bmFileHdr ) )

        {

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

            return false ;

        }

 

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

        bitmapSize = bmFileHdr.bfSize - sizeof(BITMAPFILEHEADER) ;

 

        // メモリ確保

        pDib = (BITMAPINFOHEADER *)malloc( bitmapSize ) ;

 

        // 本体読み込み

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

        {

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

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

            return false ;

        }

 

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

 

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

        pBitmap = (BYTE *)(pDib) + bmFileHdr.bfOffBits

                                    - sizeof(BITMAPFILEHEADER) ;

 

        // バイト数を4の整数倍に切り上げる

        lenScanline = (pDib->biWidth * 3) ;

        wMargine = 0 ;

        if( pDib->biWidth % 4 != 0 )

        {

            wMargine = (4 - (lenScanline % 4) ) ;

            lenScanline += wMargine ;

        }

    }

    catch( ... )

    {

        rVal = false ;

    }

    return rVal ;

}

 

 

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

//

// 4バイトバウンダリまでの長さ

//

int Cbmp::getwMargine( void )

{

    return wMargine ;

}

 

 

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

//

// ビットマップ幅取得

//

unsigned int Cbmp::getWidth( void )

{

    if( pDib == NULL )

        return (unsigned int)0 ;

 

    return (unsigned int)pDib->biWidth ;

}

 

 

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

//

// ビットマップ高さ取得

//

unsigned int Cbmp::getHeight( void )

{

    if( pDib == NULL )

        return (unsigned int)0 ;

 

    return (unsigned int)pDib->biHeight ;

}

 

 

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

//

// ビットマップ全体

//

PBITMAPINFOHEADER Cbmp::getPdib( void )

{

    return pDib ;

}

 

 

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

//

// ビットマップ本体

//

LPBYTE Cbmp::getPbitmapBody( void )

{

    if( pDib == NULL )

        return NULL ;

 

    return pBitmap ;

}

 

 

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

//

// スキャンラインの位置

//

LPBYTE Cbmp::getScanline( int lineNo )

{

    int pos = pDib->biHeight - lineNo - 1 ;

 

    if( pDib == NULL )

        return NULL ;

 

    return ( pBitmap +( pos * lenScanline ) ) ;

}

 

 

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

//

// 24bit ビットマップか

//

bool Cbmp::is24bit( void )

{

    if( pDib->biBitCount == 24 )  // 24 bits bitmap ?

        return true ;

    else

        return false ;

}

 

 

 

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

//

// 32bit ビットマップか

//

bool Cbmp::is32bit( void )

{

    if( pDib->biBitCount == 32 )  // 32 bits bitmap ?

        return true ;

    else

        return false ;

}

 

 

toMono32Bmp.cpp

//

// toMono32Bmp.cpp

//

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

//                               Hiro KITAYAMA

//

#include <windows.h>

 

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

//

// 32 bit RGB to 32 bit monochrome bmp

//

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

{

    int loopCounter = (height*width)/4;

    float monoConst[]={0.114478f,0.586611f,0.298912f,0.000000f};

 

    _asm

    {

        xor         ebx, ebx

        mov         esi, pInSrc         // esi = src

        mov         edi, pInDst         // edi = dst

        mov         ecx, loopCounter    // loop counter

 

 

        pxor        xmm0,xmm0           // fixed zero

        movdqu      xmm7, monoConst

 

 

                                        // xmm0 = zero(integer)

                                        // xmm2 = source

                                        // xmm5 = destination

                                        // xmm7 = mono constant

    loopLbl:

        movdqa      xmm1, [esi+ebx]     // src

        movdqa      xmm2, xmm1          // save src

 

 

 

                                        // p3, p2=================================

        pshufd      xmm1, xmm2, 0eh     // p3, p2を下位へコピー,----1110b

                                        //

                                        // xmm2:   p3   p2   p1  p0

                                        // xmm1:   --   --   p3  p2

                                        //                                       p3           p2

                                        // xmm1:   -- -- -- --  -- -- -- --  aa bb gg rr  aa bb gg rr

        punpcklbw   xmm1, xmm0          // B -> W

                                        //                  p3                   p2

                                        // xmm1:   00aa 00bb 00gg 00rr  00aa 00bb 00gg 00rr

 

        movdqa      xmm3, xmm1          //                                       p3

        punpckhqdq  xmm3, xmm1          // xmm3:   ---- ---- ---- ----  00aa 00bb 00gg 00rr

 

        punpcklwd   xmm1, xmm0          // W -> D

                                        // xmm1:   000000aa  000000bb  000000gg  000000rr, pixcel2

        punpcklwd   xmm3, xmm0          // W -> D

                                        // xmm3:   000000aa  000000bb  000000gg  000000rr, pixcel3

 

                                        // Pixel 2==========

        cvtdq2ps    xmm1, xmm1          // Dword -> Float

        mulps       xmm1, xmm7          // mono= B * 0.114478f

                                        //          + G * 0.586611f

                                        //              + R * 0.298912f);

                                        // xmm1:   00  B2  G2  R2, pixcel2(float)

 

                                        // Pixel 3==========

        cvtdq2ps    xmm3, xmm3          // Dword -> Float

        mulps       xmm3, xmm7          // mono= B * 0.114478f

                                        //          + G * 0.586611f

                                        //              + R * 0.298912f);

                                        // xmm3:   00  B3  G3  R3, pixcel3(float)

 

 

                                        // pixel 3-2の処理

        haddps      xmm1, xmm3          // G + R

                                        // xmm1:   ---B3---  G3+R3   ---B2---  G2+R2  ,  (float)

 

        haddps      xmm1, xmm1          // G + R + B

                                        // xmm1:   B3+G3+R3 B2+G2+R2 B3+G3+R3 B2+G2+R2,  (float)

 

        cvtps2dq    xmm5, xmm1          // float -> Dword

                                        // xmm5:   000000M3 000000M2 000000M3 000000M2,  (DWORD)

 

 

 

        movdqa      xmm1, xmm2          // p1, p0=================================

                                        // xmm1:   p3   p2   p1  p0

                                        //                                       p1           p0

                                        // xmm1:   -- -- -- --  -- -- -- --  aa gg bb rr  aa gg bb rr

        punpcklbw   xmm1, xmm0          // B -> W

                                        //                  p1                   p0

                                        // xmm1:   00aa 00gg 00bb 00rr  00aa 00gg 00bb 00rr

                                        //

                                        //                                       p1

        movdqa      xmm3, xmm1

        punpckhqdq  xmm3, xmm1          // xmm3:   ---- ---- ---- ----  00aa 00gg 00bb 00rr

                                        //

        punpcklwd   xmm1, xmm0          // W -> D

                                        // xmm1:   000000aa  000000gg  000000bb  000000rr, pixcel0

        punpcklwd   xmm3, xmm0          // W -> D

                                        // xmm3:   000000aa  000000gg  000000bb  000000rr, pixcel1

                                       

 

                                        // Pixel 0==========

        cvtdq2ps    xmm1, xmm1          // Dword -> Float

        mulps       xmm1, xmm7          // mono= B * 0.114478f

                                        //          + G * 0.586611f

                                        //              + R * 0.298912f);

                                        // xmm1:   00  B0  G0  R0, pixcel0(float)

 

 

                                        // Pixel 1==========

        cvtdq2ps    xmm3, xmm3          // Dword -> Float

        mulps       xmm3, xmm7          // mono= B * 0.114478f

                                        //          + G * 0.586611f

                                        //              + R * 0.298912f);

                                        // xmm3:   00  B1  G1  R1, pixcel1(float)

 

 

                                        // pixel 1-0の処理

        haddps      xmm1, xmm3          // G + R

                                        // xmm1:   ---B1---  G1+R1   ---B0---  G0+R0  ,  (float)

        haddps      xmm1, xmm1          // G + R + B

                                        // xmm1:   B1+G1+R1 B0+G0+R0 B1+G1+R1 B0+G0+R0,  (float)

 

        cvtps2dq    xmm1, xmm1          // float -> Dword

                                        // xmm5:   000000M1 000000M0 000000M1 000000M0,  (DWORD)

 

 

        movsd       xmm5, xmm1          //  4 pixelを統合

                                        // xmm5:   000000M3 000000M2 000000M1 000000M0,  (DWORD)

 

        movdqa      xmm1, xmm5

        pslldq      xmm1, 1             // xmm1:   0000M300 0000M200 0000M100 0000M000,  (DWORD)

        por         xmm1, xmm5          // xmm1:   0000M3M3 0000M2M2 0000M1M1 0000M0M0,  (DWORD)

 

        movdqa      xmm5, xmm1          // xmm5:   0000M3M3 0000M2M2 0000M1M1 0000M0M0,  (DWORD)

        pslldq      xmm1, 1             // xmm1:   00M3M300 00M2M200 00M1M100 00M0M000,  (DWORD)

        por         xmm5, xmm1          // xmm5:   00M3M3M3 00M2M2M2 00M1M1M1 00M0M0M0,  (DWORD)

 

 

        movdqa  [edi+ebx], xmm5         // write to dest

        lea     ebx,  [ebx+16]          // next address

 

        dec     ecx

        jecxz   exit_x

        jmp     loopLbl

    exit_x:

    }

}

 

effect.cpp

//

// effect.cpp

//

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

//                               Hiro KITAYAMA

//

//なるべくFixedを使用した

//

#include <windows.h>

#include <math.h>

 

 

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

//

// エフェクト

//

//  1    1    1      /

//                  /

//  1    1    1    /     9

//                /

//  1    1    1  /

//

void effect( LPBYTE pAligned[], LONG width, LONG height, int alpha )

{

    LPBYTE  lpSrc = pAligned[1] ;

    LPBYTE  lpDst = pAligned[0] ;

    int     x, y;

    float   fResult;

    float mulMask[3][3] ={ 1,  1,  1,

                           1,  1,  1,

                           1,  1,  1,

    };

 

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

    {

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

        {

            fResult =

                (float)*(lpSrc+((width*(y+0))+(x+0))*4) * mulMask[0][0]

                            + (float)*(lpSrc+((width*(y+0))+(x+1))*4) * mulMask[0][1]

                                + (float)*(lpSrc+((width*(y+0))+(x+2))*4) * mulMask[0][2]

 

                       + (float)*(lpSrc+((width*(y+1))+(x+0))*4) * mulMask[1][0]

                            + (float)*(lpSrc+((width*(y+1))+(x+1))*4) * mulMask[1][1]

                                + (float)*(lpSrc+((width*(y+1))+(x+2))*4) * mulMask[1][2]

 

                       + (float)*(lpSrc+((width*(y+2))+(x+0))*4) * mulMask[2][0]

                            + (float)*(lpSrc+((width*(y+2))+(x+1))*4) * mulMask[2][1]

                                + (float)*(lpSrc+((width*(y+2))+(x+2))*4) * mulMask[2][2];

 

            fResult/=9.0f;

            fResult=min( max( fResult, 0 ), 255 );

 

            *(lpDst+((width*(y+1)+(x+1))*4)+0) = (BYTE)fResult;

            *(lpDst+((width*(y+1)+(x+1))*4)+1) = (BYTE)fResult;

            *(lpDst+((width*(y+1)+(x+1))*4)+2) = (BYTE)fResult;

            *(lpDst+((width*(y+1)+(x+1))*4)+3) = (BYTE)0;

        }

    }

}

 

 

 

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

//

// エフェクト,SIMD

//

//  1    1    1      /

//                  /

//  1    1    1    /     9

//                /

//  1    1    1  /

//

void effectSimd( LPBYTE pAligned[], LONG width, LONG height, int alpha )

{

    LPBYTE  lpSrc = pAligned[1] ;

    LPBYTE  lpDst = pAligned[0] ;

    int remainY;

    short mulMask0[] ={ 1,0,   1,0,  1,0,  0,0};

    short mulMask1[] ={ 1,0,   1,0,  1,0,  0,0};

    float divConst = 9.0f;

 

    _asm

    {

        mov         eax, [width]        ; eax = width

        shl         eax, 2              ; eax = width*4, = scan length

        mov         esi, [lpSrc]        ; src 1st line

        lea         ebx, [esi+eax]      ; src 2nd line

        lea         edx, [ebx+eax]      ; src 3rd line

 

        mov         edi, [lpDst]        ; edi = dst

        lea         edi, [edi+eax+4]    ; edi = dst

 

        movdqu      xmm7, [mulMask0]    ; xmm7 =   0, -1, -1, -1

        movdqu      xmm6, [mulMask1]    ; xmm7 =   0, -1,  8, -1

        movss       xmm5, [divConst]    ; xmm5 = constant

 

        xor         eax, eax            ; index

 

        mov         ecx, [height]       ; ax = height

        dec         ecx                 ; ax = height - 1

        dec         ecx                 ; ax = height - 2

    loopY:

        mov         [remainY], ecx

 

 

        mov         ecx, [width]        ; ecx = width

        dec         ecx                 ; ecx = width - 1

        dec         ecx                 ; ecx = width - 2

 

    loopX:

        movdqu      xmm0, [esi+eax]     ; 1st line 00M3M3M3 00M2M2M2 00M1M1M1 00M0M0M0

        movdqu      xmm1, [ebx+eax]     ; 2nd line 00M3M3M3 00M2M2M2 00M1M1M1 00M0M0M0

        movdqu      xmm2, [edx+eax]     ; 3rd line 00M3M3M3 00M2M2M2 00M1M1M1 00M0M0M0

 

        psrld       xmm0, 16            ; 1st line 000000M3 000000M2 000000M1 000000M0

        psrld       xmm1, 16            ; 2nd line 000000M3 000000M2 000000M1 000000M0

        psrld       xmm2, 16            ; 3rd line 000000M3 000000M2 000000M1 000000M0

 

 

        pmullw      xmm0, xmm7          ; 1st line 0000 00M3  0000 00M2  0000 00M1  0000 00M0

        pmullw      xmm1, xmm6          ; 2nd line 0000 00M3  0000 00M2  0000 00M1  0000 00M0

        pmullw      xmm2, xmm7          ; 3rd line 0000 00M3  0000 00M2  0000 00M1  0000 00M0

 

        paddsw      xmm0, xmm1          ; xmm0 =   1st line + 2nd line(float)

        paddsw      xmm0, xmm2          ; xmm0 =   1st line + 2nd line + 3rd line(float)

 

        cvtdq2ps    xmm0, xmm0          ; (float)

        haddps      xmm0, xmm0          ; xmm0 =   0   M2   M2   M1+M0(float)

 

        haddps      xmm0, xmm0          ; xmm0 =   0   M2   M2   M2+M1+M0(float)

 

        divss       xmm0, xmm5          ; xmm0 /= 9.0f

 

 

 

        cvtps2dq    xmm1, xmm0          ; xmm1 =   -------- -------- -------- 0000XXXX(DWORD)

 

 

        packuswb    xmm1, xmm1          ; saturate(0-255)

 

 

        punpcklbw   xmm1, xmm1          ; 0-7を8- 24へコピー

                                        ; xmm1 =   -------- -------- -------- 0000XXXX(DWORD)

        movdqa      xmm3, xmm1          ; xmm3 =   -------- -------- -------- 0000XXXX(DWORD)

        pslldq      xmm3, 1             ; xmm3 =   -------- -------- -------- 00XXXX00(DWORD)

        por         xmm1, xmm3          ; xmm3 =   -------- -------- -------- 00XXXXXX(DWORD)

 

 

 

        movd        [edi+eax], xmm1         ; write result

 

        lea         eax, [eax+4]

        loop        loopX

 

 

        lea         eax, [eax+8]

 

        mov         ecx, [remainY]

        loop        loopY

    }

}

 

pgm.cpp

//

// pgm.cpp

//

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

//                               Hiro KITAYAMA

//

#include <stdio.h>

#include <windows.h>

#include "resource.h"

 

#include "Cbmp.h"

Cbmp* spCbmp[2] = { NULL, NULL};

LPBYTE pAligned[2] ={NULL,NULL};    // SIMD用バッファ

 

#define SZCLASSNAME         "SIMD"

#define ID_TIMER            1

#define NUM_OF_LOOP         10

 

void toMono32Bmp( LPBYTE pInSrc, LPBYTE pInDst,

                        LONG width, LONG height );              // to monochrome

 

void effect(     LPBYTE pAligned[], LONG width,

                        LONG height, int alpha );               //C関数

void effectSimd( LPBYTE pAligned[], LONG width,

                        LONG height, int alpha );               //SIMD関数

void (*pFunc)(   LPBYTE pAligned[],

                        LONG width, LONG height, int alpha );   //関数ポインタ

 

 

 

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

//

// ファイル読み込み

//

// spCbmp[0] ... for draw to screen

// spCbmp[1] ... holds original images

// pToMono[0] ... buffer for SIMD

//

void openFile( HWND hWnd )

{

    char  fName[_MAX_PATH] ;

    LPBYTE pToMono[2] ={NULL,NULL};             // SIMD用バッファ

    int  imgSize ;

 

    try

    {

        spCbmp[0] = new Cbmp() ;                    // クラスのインスタンス

        spCbmp[0] -> getFname( fName ) ;            // 引数なし

        if( !spCbmp[0] -> LoadFromFile( fName ) )   // ファイル読み込み

        {

            SAFE_DELETE( spCbmp[0] ) ;              // オブジェクト解放

            SetWindowText( hWnd, "エラー:読み込み失敗" );

            return ;

        }

        if( spCbmp[0]->is32bit() == false )

        {

            SAFE_DELETE( spCbmp[0] ) ;              // オブジェクト解放

            //MessageBox(hWnd, "32ビットBMPでない",

            //              "警告", MB_ICONEXCLAMATION);

            SetWindowText( hWnd, "エラー:32ビットBMPでない" );

            return;

        }

        if( spCbmp[0]->getWidth() % 4 )

        {

            SAFE_DELETE( spCbmp[0] ) ;              // オブジェクト解放

            //MessageBox(hWnd, "幅が4 バイトの整数倍でない",

            //                     "警告", MB_ICONEXCLAMATION);

            SetWindowText( hWnd, "エラー:幅が4 バイトの整数倍でない" );

            return;

        }

 

        spCbmp[1] = new Cbmp() ;                    // クラスのインスタンス

        if( !spCbmp[1] -> LoadFromFile( fName ) )   // ファイル読み込み

        {

            SAFE_DELETE( spCbmp[0] ) ;              // オブジェクト解放

            SAFE_DELETE( spCbmp[1] ) ;              // オブジェクト解放

            SetWindowText( hWnd, "エラー:読み込み失敗" );

            return ;

        }

 

 

        imgSize=spCbmp[0]->getWidth()*spCbmp[0]->getHeight()*4;

 

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

        pToMono[0] = (LPBYTE)_aligned_malloc(imgSize*2, 16);   // dst

        if( pToMono[0]==NULL)

        {

            pToMono[0]=NULL;

            SAFE_DELETE( spCbmp[0] ) ;              // オブジェクト解放

            SAFE_DELETE( spCbmp[1] ) ;              // オブジェクト解放

            SetWindowText( hWnd, "エラー:メモリ割付失敗" );

            return ;

        }

 

        pToMono[1] = pToMono[0] + imgSize;                          // src

 

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

        memcpy(pToMono[1], spCbmp[1]->getPbitmapBody(), imgSize);   // src

        toMono32Bmp( pToMono[1], pToMono[0],

                spCbmp[0]->getWidth(), spCbmp[0]->getHeight());     // to monochrome

        memcpy(spCbmp[0]->getPbitmapBody(), pToMono[0], imgSize);

        memcpy(spCbmp[1]->getPbitmapBody(), pToMono[0], imgSize);

 

        SAFE_ALIGNED_FREE(pToMono[0]); // メモリ解放

 

        InvalidateRect( hWnd, NULL, FALSE ) ;

    }

    catch( ... )

    {

    }

}

 

 

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

//

// ウィンドウサイズの変更

//

void chgWinSize( HWND hWnd )

{

    RECT rc, rcClient ;

    int  winHeight, winWidth ;

    char fileName[_MAX_PATH] ;

 

    try

    {

        if( spCbmp[0] == NULL )

            return ;

 

        //ファイル名を表示

        spCbmp[0] -> extFname( fileName ) ;

        SetWindowText( hWnd, fileName );

 

        //ウィンドウサイズを調整

        GetWindowRect( hWnd, &rc ) ;

        GetClientRect( hWnd, &rcClient ) ;

        winWidth  = spCbmp[0]->getWidth() ;

        winHeight = spCbmp[0]->getHeight() ;

        winWidth  += (rc.right-rc.left) - (rcClient.right-rcClient.left);

        winHeight += (rc.bottom-rc.top) - (rcClient.bottom-rcClient.top);

        MoveWindow( hWnd, rc.left, rc.top, winWidth, winHeight, TRUE );

    }

    catch( ... )

    {

    }

}

 

 

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

//

// get counter

//

UINT64 getCurCounter(void)

{

    UINT64 counter ;         // 性能表示

 

    _asm

    {

        rdtsc

        mov     dword ptr [counter+0], eax

        mov     dword ptr [counter+4], edx

    }

 

    return counter;

}

 

 

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

//

// 実行準備

//

// pAligned[0] ... pointer to allocated aligned image memory.

// pAligned[0] ... pointer to aligned image memory.

//

bool doPrepareExec( HWND hWnd )

{

    int  imgSize ;

    bool rVal;

 

    if( spCbmp[0]==NULL )

        return false ;

 

    SAFE_ALIGNED_FREE(pAligned[0]); // メモリ解放

 

    imgSize=spCbmp[0]->getWidth() * spCbmp[0]->getHeight() * 4;

 

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

    pAligned[0] = (LPBYTE)_aligned_malloc(imgSize*2, 16);   // dst

    if( pAligned[0]==NULL)

    {

        pAligned[0]=NULL;

 

        rVal=false;

    }

    else

    {

        pAligned[1] = pAligned[0] + imgSize;                    // src

 

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

        memcpy(pAligned[1], spCbmp[1]->getPbitmapBody(), imgSize);  // src

 

        rVal=true;

    }

    return rVal ;

}

 

 

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

//

// ウィンドウ・プロシージャ

//

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    static UINT_PTR wTimer;

    static int loop ;

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

 

    PAINTSTRUCT ps ;

    char   szBuffer[256];

    int    imgSize ;

 

    switch( message )

    {

        case WM_COMMAND:

            switch( LOWORD( wParam ) )

            {

                case IDM_OPEN:              // 「開く」メニュー

                    openFile(hWnd) ;

                    chgWinSize( hWnd ) ;

                    InvalidateRect( hWnd, NULL, FALSE ) ;

                    break ;

 

                case IDM_REDRAW:            // 「原画の再表示」メニュー

                    if(NULL==spCbmp[0] || NULL==spCbmp[1])

                        break;

 

                    imgSize=spCbmp[0]->getWidth() * spCbmp[0]->getHeight() * 4;

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

                    memcpy(spCbmp[0]->getPbitmapBody(),

                                        spCbmp[1]->getPbitmapBody(), imgSize);

 

                    InvalidateRect( hWnd, NULL, FALSE ) ;

                    break ;

 

                case IDM_EXEC:              // 「C 実行」メニュー

                    totalElapsed=0;

                    loop=0;

                    pFunc=effect;

                    if(true==doPrepareExec(hWnd))

                        wTimer = SetTimer( hWnd, ID_TIMER, 50, NULL ) ;

                    break ;

 

                case IDM_EXEC_SIMD:         // 「SIMD 実行」メニュー

                    totalElapsed=0;

                    loop=0;

                    pFunc=effectSimd;

                    if(true==doPrepareExec(hWnd))

                        wTimer = SetTimer( hWnd, ID_TIMER, 50, NULL ) ;

                    break ;

 

                case IDM_CLOSE:             // 「閉じる」メニュー

                    DestroyWindow( hWnd ) ;

                    break ;

 

                default:

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

            }

            break ;

 

        case WM_TIMER:

            if(++loop > NUM_OF_LOOP )

            {

                if( wTimer )

                {

                    KillTimer( hWnd, ID_TIMER ) ;

                    wTimer=0;

                }

                break ;

            }

            begin = getCurCounter();

 

            //画像処理

            pFunc( pAligned, spCbmp[0]->getWidth(), spCbmp[0]->getHeight(),loop ) ;

 

            finish = getCurCounter();

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

            totalElapsed+=elapsed;

            wsprintf( szBuffer, "loop=%d, elapsed=%I64u\n",loop,totalElapsed ) ;

            SetWindowText( hWnd, szBuffer );

 

            imgSize=spCbmp[0]->getWidth() * spCbmp[0]->getHeight() * 4;

 

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

            memcpy(spCbmp[0]->getPbitmapBody(), pAligned[0], imgSize);

 

            InvalidateRect( hWnd, NULL, FALSE ) ;

            break ;

 

        case WM_PAINT:

            if( spCbmp[0] == NULL )

                break ;

            BeginPaint( hWnd, &ps ) ;

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

                spCbmp[0] -> getWidth(),

                    spCbmp[0] -> getHeight(),

                        0, 0, 0,

                            spCbmp[0] -> getHeight(),

                                spCbmp[0] -> getPbitmapBody(),

                                    (PBITMAPINFO)(spCbmp[0]->getPdib()),

                                        DIB_RGB_COLORS ) ;

            EndPaint( hWnd, &ps ) ;

            break ;

 

        case WM_DESTROY:                    // メッセージループを終了へ

            if( wTimer ) KillTimer( hWnd, ID_TIMER ) ;

            SAFE_DELETE( spCbmp[0] ) ;      // オブジェクト解放

            SAFE_DELETE( spCbmp[1] ) ;      // オブジェクト解放

            SAFE_ALIGNED_FREE(pAligned[0]); // メモリ解放

            PostQuitMessage( 0 ) ;

            break;

 

        default:

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

    }

    return 0 ;

}

 

 

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

//

// ウィンドウの生成

//

HWND createWindow( HINSTANCE hInstance )

{

    WNDCLASSEX  wcx ;

    HWND hWnd ;

    LPCSTR szTitle = SZCLASSNAME ;

    LPCSTR szWindowClass = SZCLASSNAME ;

 

    // ウィンドウクラスの登録

    ZeroMemory( &wcx, sizeof( wcx ) ) ;

    wcx.cbSize          = sizeof( WNDCLASSEX ) ;

    wcx.style           = CS_HREDRAW | CS_VREDRAW ;

    wcx.lpfnWndProc     = (WNDPROC)WndProc ;

    wcx.cbClsExtra      = 0 ;

    wcx.cbWndExtra      = 0 ;

    wcx.hInstance       = hInstance ;

    wcx.hIcon           = LoadIcon( hInstance, "ICON" ) ;

    wcx.hIconSm         = LoadIcon( hInstance, "SICON" ) ;

    wcx.hCursor         = LoadCursor( NULL, IDC_ARROW ) ;

    wcx.hbrBackground   = (HBRUSH)GetStockObject( BLACK_BRUSH ) ;

    wcx.lpszMenuName    = "MENU" ;      // メニューあり

    wcx.lpszClassName   = szWindowClass ;

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

        return 0 ;                      // エラー

 

    // ウィンドウの生成

    hWnd = CreateWindow( szWindowClass, szTitle,

                WS_OVERLAPPEDWINDOW | WS_VISIBLE,

                    CW_USEDEFAULT, CW_USEDEFAULT,

                        CW_USEDEFAULT, CW_USEDEFAULT,

                            HWND_DESKTOP, NULL,

                                hInstance, NULL ) ;

 

    return hWnd ;

}

 

 

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

//

// WinMainプロシージャ

//

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,

                                           LPSTR lpCmdLine, int nCmdShow )

{

    HWND hWnd ;

    MSG msg;

 

    hWnd=createWindow(hInstance);

    if( !hWnd )

        return 0 ;      // エラー

 

    // メッセージ・ループ

    while( GetMessage( &msg, NULL, 0, 0 ) != 0 )

    {

        TranslateMessage( &msg ) ;

        DispatchMessage( &msg ) ;

    }

    return (int)msg.wParam ;

}

 

pgm.rc

// Microsoft Visual C++ generated resource script.

//

#include "resource."

 

#define APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 2 resource.

//

#include "afxres.h"

 

/////////////////////////////////////////////////////////////////////////////

#undef APSTUDIO_READONLY_SYMBOLS

 

/////////////////////////////////////////////////////////////////////////////

// 日本語 resources

 

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)

#ifdef _WIN32

LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT

#pragma code_page(932)

#endif //_WIN32

 

/////////////////////////////////////////////////////////////////////////////

//

// Menu

//

 

MENU MENU

BEGIN

    POPUP "画像処理(&I)"

    BEGIN

        MENUITEM "開く(&O)",                      IDM_OPEN

        MENUITEM "Cで実行(&E)",                    IDM_EXEC

        MENUITEM "SIMDで実行(&S)",                 IDM_EXEC_SIMD

        MENUITEM "原画再表示(&R)",                   IDM_REDRAW

        MENUITEM "閉じる(&C)",                     IDM_CLOSE

    END

END

 

 

/////////////////////////////////////////////////////////////////////////////

//

// Icon

//

 

// Icon with lowest ID value placed first to ensure application icon

// remains consistent on all systems.

ICON                    ICON                    "icon.ico"

SICON                   ICON                    "sicon.ico"

 

#ifdef APSTUDIO_INVOKED

/////////////////////////////////////////////////////////////////////////////

//

// TEXTINCLUDE

//

 

1 TEXTINCLUDE

BEGIN

    "resource.\0"

END

 

3 TEXTINCLUDE

BEGIN

    "\r\0"

END

 

2 TEXTINCLUDE

BEGIN

    "#include ""afxres.h""\r\0"

END

 

#endif    // APSTUDIO_INVOKED

 

#endif    // 日本語 resources

/////////////////////////////////////////////////////////////////////////////

 

 

 

#ifndef APSTUDIO_INVOKED

/////////////////////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 3 resource.

//

 

 

/////////////////////////////////////////////////////////////////////////////

#endif    // not APSTUDIO_INVOKED

 

 

resource.h

//{{NO_DEPENDENCIES}}

// Microsoft Visual C++ generated include file.

// Used by pgm.rc

//

#define IDM_OPEN                        40001

#define IDM_EXEC                        40002

#define IDM_EXEC_SIMD                   40003

#define IDM_CLOSE                       40004

#define ID_40005                        40005

#define IDM_REDRAW                      40006

 

// Next default values for new objects

//

#ifdef APSTUDIO_INVOKED

#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NEXT_RESOURCE_VALUE        101

#define _APS_NEXT_COMMAND_VALUE         40007

#define _APS_NEXT_CONTROL_VALUE         1000

#define _APS_NEXT_SYMED_VALUE           101

#endif

#endif