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);
posted @ 2012-08-30 15:54  likebeta  阅读(1731)  评论(0编辑  收藏  举报