多媒体指令(图像二值化)
主要用来学习多媒体指令的,要不我也不会这么麻烦的用win32 sdk编程。
果然要只学习图像算法,还是推荐matlab。
这里主要用了pcmpgtb指令
格式 pcmpgtb mm0,mm1;
解释:当 mm0 中对应字节大于 mm1对应字节时,mm0相应位置置0xff,否则置0x00。
当然,相关还有pcmpgtw等。
//本程序算是一个简单的框架了,可以用来处理图像 //主要是用来学习多媒体指令mmx/sse相关的。 #include <windows.h> #include <gdiplus.h> #pragma comment(lib, "gdiplus.lib") using namespace Gdiplus; typedef union { ARGB Color; struct { BYTE Blue; BYTE Green; BYTE Red; BYTE Alpha; }; }Pix; VOID asmGray2BW(BitmapData *data) { UINT Height=data->Height; UINT Width=data->Width; Pix* p=(Pix*)data->Scan0; UINT n=Height*Width/2; //非常奇怪,我明明定义的无符号字节,本应该用0x80的,可这里只能用0作为阈值,才相当于cpp版的128 //取0x80808080,无符号单字节是128,可这里显然是有符号的-128,着实奇怪。 //也只能认为mmx寄存器默认为有符号的了。 Pix cp[]={0x00000000,0x00000000}; __asm { push esi; mov ecx,n; mov esi,[p]; movq mm2,[cp]; lp: movq mm1,mm2; movq mm0,[esi]; pcmpgtb mm1,mm0; movq [esi],mm1; add esi,8; dec ecx; jnz lp; pop esi; emms; } } VOID cppGray2BW(BitmapData *data) { Pix* p=(Pix*)data->Scan0; for(UINT h = 0; h < data->Height; ++h) { for(UINT w = 0; w < data->Width; ++w) { if (p->Red>128) { p->Red=0xff; p->Blue=0xff; p->Green=0xff; } else { p->Red=0; p->Blue=0; p->Green=0; } ++p; } } } VOID OnPaint(HDC hdc) { Graphics graphics(hdc); Bitmap srcbitmap(L"lena.jpg",0); Bitmap *dstbitmap=srcbitmap.Clone(0,0,srcbitmap.GetWidth(),srcbitmap.GetHeight(),srcbitmap.GetPixelFormat()); BitmapData data; Rect rect(0,0,dstbitmap->GetWidth(),dstbitmap->GetHeight()); dstbitmap->LockBits(&rect,ImageLockModeRead | ImageLockModeWrite,PixelFormat32bppARGB,&data); asmGray2BW(&data); // cppGray2BW(&data); dstbitmap->UnlockBits(&data); graphics.DrawImage(&srcbitmap,0,0); graphics.DrawImage(dstbitmap,300,0); delete dstbitmap; } LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow) { HWND hWnd; MSG msg; WNDCLASS wndClass; GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; // Initialize GDI+. GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hInstance; wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndClass.lpszMenuName = NULL; wndClass.lpszClassName = TEXT("DIP"); RegisterClass(&wndClass); hWnd = CreateWindow( TEXT("DIP"), // window class name TEXT("DIP"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position 600, // initial x size 400, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters /* HWND button=CreateWindow("button", "处理", WS_CHILD, 200, 300, 100, 30, hWnd, NULL, hInstance, 0); */ ShowWindow(hWnd, iCmdShow); // ShowWindow(button,iCmdShow); UpdateWindow(hWnd); while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } GdiplusShutdown(gdiplusToken); return msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; switch(message) { // case WM_COMMAND: case WM_PAINT: hdc = BeginPaint(hWnd, &ps); OnPaint(hdc); EndPaint(hWnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; default: return DefWindowProc(hWnd, message, wParam, lParam); } }
效果: