Feed(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 ; } |
effect.cpp
// // effect.c // // (c)Copyright Spacesoft corp., 2007 All rights reserved. // Hiro KITAYAMA // #include <windows.h>
//--------------------------------------------------------------------------- // // エフェクト // // 0 -1 // 0 1 // void effect( LPBYTE pAligned[], LONG width, LONG height, int alpha ) { LPBYTE lpSrc = pAligned[1] ; LPBYTE lpDst = pAligned[0] ; int x, y ;
lpDst += width*4;
for( y = 1 ; y < height-1 ; y++ ) for( x = 0 ; x < width*4 ; x++ ) *lpDst++ = (BYTE)abs((*lpSrc - *((lpSrc++)+width*4))); }
//--------------------------------------------------------------------------- // // エフェクト,SIMD // // 0 -1 // 0 1 // void effectSimd( LPBYTE pAligned[], LONG width, LONG height, int alpha ) { int loopCounter = ((height-1)*width)/4; int scanLength=width*4; LPBYTE lpSrc = pAligned[1] ; LPBYTE lpDst = pAligned[0] ;
lpDst += width*4;
_asm { xor ebx, ebx mov edx, [scanLength] ; next line mov esi, lpSrc ; esi = src mov edi, lpDst ; edi = dst
mov ecx, loopCounter ; loop counter
loopLbl: movdqa xmm0, [esi+ebx] ; current movdqa xmm1, [esi+edx] ; next movdqa xmm2, xmm0 ; copy source
psubusb xmm0, xmm1 ; compute difference one way
psubusb xmm1, xmm2 ; compute difference the other way
por xmm0, xmm1 ; or them together
movdqa [edi+ebx], xmm0 lea ebx, [ebx+16] lea edx, [edx+16]
loop loopLbl } } |
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 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 // void openFile( void ) { char fName[_MAX_PATH] ;
try { spCbmp[0] = new Cbmp() ; // クラスのインスタンス spCbmp[0] -> getFname( fName ) ; // 引数なし if( !spCbmp[0] -> LoadFromFile( fName ) ) // ファイル読み込み { SAFE_DELETE( spCbmp[0] ) ; // オブジェクト解放 return ; }
spCbmp[1] = new Cbmp() ; // クラスのインスタンス if( !spCbmp[1] -> LoadFromFile( fName ) ) // ファイル読み込み { SAFE_DELETE( spCbmp[0] ) ; // オブジェクト解放 SAFE_DELETE( spCbmp[1] ) ; // オブジェクト解放 return ; } } 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 ;
if( spCbmp[0]->is32bit() == false ) { MessageBox(hWnd, "32ビットBMPでない", "警告", MB_ICONEXCLAMATION); return false; } if( spCbmp[0]->getWidth() % 4 ) { MessageBox(hWnd, "幅が4 バイトの整数倍でない", "警告", MB_ICONEXCLAMATION); 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 WORD 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() ; 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 |