水平エッジ検出・その4(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
// // effect.c // // (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.c // // (c)Copyright Spacesoft corp., 2007 All rights reserved. // Hiro KITAYAMA // #include <windows.h> #include <math.h>
//--------------------------------------------------------------------------- // // エフェクト // // -1 0 1 // // -1 0 1 // // -1 0 1 // void effect( LPBYTE pAligned[], LONG width, LONG height, int alpha ) { LPBYTE lpSrc = pAligned[1] ; LPBYTE lpDst = pAligned[0] ; int x, y, fResult;
for( y = 0 ; y < height-2 ; y++ ) { for( x = 0 ; x < width-2 ; x++ ) { fResult = *(lpSrc+(((width*(y+0))+x)*4)+0) * -1 + *(lpSrc+(((width*(y+1))+x)*4)+0) * -1 + *(lpSrc+(((width*(y+2))+x)*4)+0) * -1 + *(lpSrc+(((width*(y+0))+x)*4)+8) * 1 + *(lpSrc+(((width*(y+1))+x)*4)+8) * 1 + *(lpSrc+(((width*(y+2))+x)*4)+8) * 1;
fResult=abs(fResult); fResult=min(255, fResult);
*(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 0 1 // // -1 0 1 // // -1 0 1 // void effectSimd( LPBYTE pAligned[], LONG width, LONG height, int alpha ) { LPBYTE lpSrc = pAligned[1] ; LPBYTE lpDst = pAligned[0] ; int remainY; float mulMask[] ={1, 0, -1, 0};
_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, [mulMask] ; xmm3 = 0000 0000 0000 FFFF 0000 0000 0000 0001
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] ; 1st line 00M3M3M3 00M2M2M2 00M1M1M1 00M0M0M0 movdqu xmm1, [ebx] ; 2nd line 00M3M3M3 00M2M2M2 00M1M1M1 00M0M0M0 movdqu xmm2, [edx] ; 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
cvtdq2ps xmm0, xmm0 ; 1st line 00000000 000000M2 00000000 000000M0(float) cvtdq2ps xmm1, xmm1 ; 2nd line 00000000 000000M2 00000000 000000M0(float) cvtdq2ps xmm2, xmm2 ; 3rd line 00000000 000000M2 00000000 000000M0(float)
mulps xmm0, xmm7 ; 1st line 000000M3 000000M2 000000M1 000000M0 ; X 0 -1 0 1 mulps xmm1, xmm7 ; 2nd line 000000M3 000000M2 000000M1 000000M0 ; X 0 -1 0 1 mulps xmm2, xmm7 ; 3rd line 000000M3 000000M2 000000M1 000000M0 ; X 0 -1 0 1
addps xmm0, xmm1 ; xmm0 = 1st line + 2nd line(float) addps xmm0, xmm2 ; xmm0 = 1st line + 2nd line + 3rd line(float)
haddps xmm0, xmm0 ; xmm0 = 00000000 000000M2 000000M2 000000M0(float)
haddps xmm0, xmm0 ; xmm0 = 00000000 000000M2 000000M2 00M2+00M0(float)
cvtps2dq xmm0, xmm0 ; xmm0 = -------- -------- -------- 000000XX(DWORD)
; xmm1 = abs( xmm0) movdqa xmm1, xmm0 ; make a copy of x
psrad xmm0, 31 ; replicate sign bit
pxor xmm1, xmm0 ; take 1's complement of just the negative fields psubd xmm1, xmm0 ; add 1 to just the negative fields ; xmm1 = abs( xmm0 ) ; -------- -------- -------- 000000XX(DWORD)
packuswb xmm1, xmm1 ; saturate(0-255)
punpcklbw xmm1, xmm1 ; 0-7を8- 24へコピー, 32-39を40- 63へコピー ; xmm1 = -------- -------- -------- 0000XXXX(DWORD) movdqa xmm3, xmm1 ; xmm3 = -------- -------- -------- 0000XXXX(DWORD) pslldq xmm3, 1 ; xmm3 = -------- -------- -------- 00XXXX00(DWORD) por xmm1, xmm3 ; xmm3 = -------- -------- -------- 00XXXXXX(DWORD)
movd [edi], xmm1 ; write result
lea esi, [esi+4] ; 1st line, next addr lea ebx, [ebx+4] ; 2nd line, next addr lea edx, [edx+4] ; 3rd line, next addr
lea edi, [edi+4] ; destination, next addr
loop loopX
lea esi, [esi+8] ; 1st line, next addr lea ebx, [ebx+8] ; 2nd line, next addr lea edx, [edx+8] ; 3rd line, next addr
lea edi, [edi+8] ; destination, next addr
mov ecx, [remainY] dec ecx jecxz exitY jmp loopY exitY:
} } |
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 |