c++提取两张相同背景的bitmap的不同部分
原始位图, 由于不能传bmp文件, 都转换成了jpg:
处理后效果图:
直接代码:
// test1.cpp : Defines the entry point for the application. // #include "stdafx.h" #include "test1.h" #include <WindowsX.h> #define MAX_LOADSTRING 100 // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name // Forward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: Place code here. MSG msg; HACCEL hAccelTable; // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_TEST1, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TEST1)); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TEST1)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL;//MAKEINTRESOURCE(IDC_TEST1); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); RECT rcClient; GetClientRect(hWnd,&rcClient); // TODO: Add any drawing code here... HDC hdcBk = CreateCompatibleDC(hdc); HBITMAP hBmpBk = LoadBitmap(hInst,MAKEINTRESOURCE(IDB_BITMAP2));//bk.bmp SelectBitmap(hdcBk,hBmpBk); HDC hdcPic = CreateCompatibleDC(hdc); HBITMAP hBmpPic = LoadBitmap(hInst,MAKEINTRESOURCE(IDB_BITMAP1));//pic.bmp SelectBitmap(hdcPic,hBmpPic); HDC hdcBkg = CreateCompatibleDC(hdc); HBITMAP hBmpBkg = LoadBitmap(hInst,MAKEINTRESOURCE(IDB_BITMAP3));//bkg.bmp SelectBitmap(hdcBkg,hBmpBkg); HDC hdcMem = CreateCompatibleDC(hdc); HBITMAP hBmpMem = CreateCompatibleBitmap(hdc,rcClient.right,rcClient.bottom); SelectBitmap(hdcMem,hBmpMem); BITMAPINFO MyBMInfo = {0}; MyBMInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); // Get the BITMAPINFO structure from the bitmap int nRet = GetDIBits(hdcBk, hBmpBk, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS); // create the bitmap buffer BYTE* lpPixelsBk = new BYTE[MyBMInfo.bmiHeader.biSizeImage]; BYTE* lpPixelsPic = new BYTE[MyBMInfo.bmiHeader.biSizeImage]; // set up the structure of the buffer to receive by setting up the BITMAPINFOHEADER structure MyBMInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); MyBMInfo.bmiHeader.biBitCount = 32; // no stride necessary, although you won't use the alpha value provided MyBMInfo.bmiHeader.biCompression = BI_RGB; // no compression -> easier to parse MyBMInfo.bmiHeader.biHeight = (MyBMInfo.bmiHeader.biHeight < 0) ? (-MyBMInfo.bmiHeader.biHeight) : (MyBMInfo.bmiHeader.biHeight); // correct the bottom-up ordering of lines // get the actual bitmap buffer if(0 == GetDIBits(hdcBk, hBmpBk, 0, MyBMInfo.bmiHeader.biHeight, (LPVOID)lpPixelsBk, &MyBMInfo, DIB_RGB_COLORS)) { // error handling } if (0 == GetDIBits(hdcPic, hBmpPic, 0, MyBMInfo.bmiHeader.biHeight, (LPVOID)lpPixelsPic, &MyBMInfo, DIB_RGB_COLORS)) { //error handling } for (DWORD i=0;i < MyBMInfo.bmiHeader.biSizeImage;i=i+4) { if (lpPixelsBk[i] == lpPixelsPic[i]&&lpPixelsBk[i+1] == lpPixelsPic[i+1]&&lpPixelsBk[i+2] == lpPixelsPic[i+2]/*&&lpPixelsBk[i+3] == lpPixelsPic[i+3]*/) { // lpPixelsPic[i]<<8; // ~(lpPixelsBk[i]<<8); lpPixelsPic[i]=0; lpPixelsPic[i+1]=0; lpPixelsPic[i+2]=0; //lpPixelsPic[i+3]=255; lpPixelsBk[i]=255; lpPixelsBk[i+1]=255; lpPixelsBk[i+2]=255; //lpPixelsBk[i+3]=255; } else { // lpPixelsBk[i]<<8; lpPixelsBk[i]=0; lpPixelsBk[i+1]=0; lpPixelsBk[i+2]=0; //lpPixelsBk[i+3]=255; } } SetStretchBltMode(hdc,HALFTONE); StretchBlt(hdcMem,0,0,rcClient.right,rcClient.bottom,hdcBkg,0,0,646,368,SRCCOPY); StretchDIBits(hdcMem,0,0,646,368,0,0,646,368,lpPixelsBk,&MyBMInfo,DIB_RGB_COLORS,SRCAND); StretchDIBits(hdcMem,0,0,646,368,0,0,646,368,lpPixelsPic,&MyBMInfo,DIB_RGB_COLORS,SRCPAINT); BitBlt(hdc,0,0,rcClient.right,rcClient.bottom,hdcMem,0,0,SRCCOPY); delete []lpPixelsBk; delete []lpPixelsPic; DeleteBitmap(hBmpBk); DeleteBitmap(hBmpPic); DeleteBitmap(hBmpBkg); DeleteBitmap(hBmpMem); DeleteDC(hdcBk); DeleteDC(hdcPic); DeleteDC(hdcBkg); DeleteDC(hdcMem); EndPaint(hWnd, &ps); }break; case WM_ERASEBKGND:break; case WM_DESTROY: { PostQuitMessage(0); } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
追加:
又发现了一个方法,使用AlphaBlend,需要
#include <Wingdi.h>
#pragma comment(lib,"Msimg32")
核心代码如下:
SetStretchBltMode(hdc,HALFTONE); StretchBlt(hdcMem,0,0,rcClient.right,rcClient.bottom,hdcBkg,0,0,646,368,SRCCOPY); //StretchDIBits(hdcMem,0,0,646,368,0,0,646,368,lpPixelsBk,&MyBMInfo,DIB_RGB_COLORS,SRCAND); StretchDIBits(hdcPic,0,0,646,368,0,0,646,368,lpPixelsPic,&MyBMInfo,DIB_RGB_COLORS,SRCCOPY); BLENDFUNCTION ftn = { 0 }; ftn.BlendOp = AC_SRC_OVER; // 目前只能设置这个值 ftn.AlphaFormat = AC_SRC_ALPHA; // 也只能设置这个值 ftn.BlendFlags = 0; // 必须为0 ftn.SourceConstantAlpha = 255; // 指定源图片的alpha // 调用这个函数来进行Alpha混合 AlphaBlend(hdcMem, 0,0,646,368, hdcPic,0,0,646,368, ftn); BitBlt(hdc,0,0,rcClient.right,rcClient.bottom,hdcMem,0,0,SRCCOPY);