当前位置:C++技术网 > 精选软件 > Win32对窗口中的图片进行反色选择处理

Win32对窗口中的图片进行反色选择处理

更新时间:2015-12-16 20:43:33浏览次数:1+次

    在QQ聊天窗口中,我们发送了图片后,然后选择图片后,图片就出现下面这样的效果:

    QQ聊天选择图片后像素翻转,出现这样的反色效果

    下面是QQ聊天文字选择后的效果,原始的颜色是黑色,选择后为白色字:

    QQ聊天文字选择反色

    下面是窗口原始图的效果:

    原始图片

    窗口中反色处理后的效果:

    选择图片后发色处理,窗口反色处理图片

    其实我们最常见的是文字选择后的反色,各种可以打字的地方,选择文字后都反色处理了。只不过,系统默认的反色并不是绝对的反色,而是将选择文字的设置了一个较深的颜色罢了。而对于文字字体上,则由黑色变成了白色。
    那么我们首先来看看什么是反色。不管是文字还是图像,窗口中显示的所有东西都是有像素组成的,而像素又会由三种基色(光的三基色:红绿蓝)合成,在设置颜色是使用的是RGB(红,绿,蓝),其实就是三基色合成一个颜色。对于颜色的基础背景知识,请在C++技术网即本网站搜索“色彩基础知识全面了解”搜到的是作者codeGod原创写作的文章,可以让你对色彩有一个比较深入的了解。
    颜色的三个分量红绿蓝的取值都是从0-255这个范围。每一个像素点都由三个基色组成,从而显示为一个彩色。我们这里讨论的是真彩色,真彩色就是用24位即三个字节表示一个像素的颜色信息。
    那么绝对的反色,就是将三个颜色分量的值在0-255范围内取反,如果当前像素的颜色为RGB(100,200,41),那么绝对反色之后,就是RGB(255-100,255-200,255-41)。如果刚好像素颜色是黑色,即RGB(0,0,0),绝对反色之后,就是RGB(255,255,255)即白色咯。
    要进行反色处理,就要取得每一给像素的颜色信息,就是GetPixel函数获取的,然后使用SetPixel函数来设置颜色。主要的问题就是对要反色的区域进行像素的遍历。客户区就是一个像素矩阵,就是一个二维的像素数组,用行列即可遍历。
    为了实现对图片的反色操作,我加在了一个美女图片,Win32中在窗口上显示图片的实现,已经在文章《Win32实现在窗口贴图,Win32设置窗口背景》详细分析了。
    所以就接着介绍这部分的技术点。我在鼠标左键单击时开始循环遍历对像素反色。代码如下:
case WM_LBUTTONDOWN:
    hdc = GetDC(hwnd);
    for (int i=0;i<pt.x;i++)
    {
        for (int j=0;j<pt.y;j++)
        {
            COLORREF clr = GetPixel(hdc,i,j);
            int red = GetRValue(clr);
            int green = GetGValue(clr);
            int blue = GetBValue(clr);

            SetPixel(hdc,i,j,RGB(255-red,255-green,255-blue));

        }
    }
    ReleaseDC(hwnd,hdc);
    return 0;

    至于GetRValue这三个宏的使用介绍以及COLORREF颜色类型的介绍,请参考《COLOR和COLORREF之间的理解与相互转换》。对于函数SiePixel的介绍,请参考《使用SetPixel在客户区自由绘画的功能实现》。
    我们在鼠标单击时开始反色。因为对客户区所有的像素点进行遍历,你应该会猜测到一个问题,就是效率问题。是的,反色处理的效率极低,非常的慢,而在QQ中选择一个图片,瞬间就反色了。然而这个却带来了一个有趣的效果,即反色过程会慢慢的反色,可以看到动画效果,哈哈哈。也是很不错的感觉哦,可以让你慢慢欣赏反色的过程,很有意思哦,只是不能操作而已。同时,每次单击窗口都会反色。单击一次,得到不正常的图片,再单击一次,恢复正常,然后这样可以不停的反色。

    那么对于反色效率问题,我将在后续的文章来分析,提高效率。

    以下是本程序的完整代码:


#include "windows.h"
#include "resource.h"
#include <tchar.h>
// - 项目是Unicode字符集
HINSTANCE g_hInstance=NULL;
LRESULT CALLBACK WinProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
    HDC hdc,hMem;
    PAINTSTRUCT ps;
    TCHAR Info[100]=_T("美女哦 - 【C++技术网http://www.cjjjs.com】");
    HBITMAP hBitmap;
    static POINT pt;
    switch (message)
    {
     case WM_PAINT:
         hdc = BeginPaint(hwnd,&ps);
         hBitmap = LoadBitmap(g_hInstance,MAKEINTRESOURCE(IDB_BITMAP1));
         hMem = CreateCompatibleDC(hdc);
         SelectObject(hMem,hBitmap);
         TextOut(hMem,0,100,Info,lstrlen(Info));
         BitBlt(hdc,0,0,pt.x,pt.y,hMem,0,0,SRCCOPY);
         EndPaint(hwnd,&ps);
         return 0;
     case WM_LBUTTONDOWN:
         hdc = GetDC(hwnd);
         for (int i=0;i<pt.x;i++)
         {
             for (int j=0;j<pt.y;j++)
             {
                 COLORREF clr = GetPixel(hdc,i,j);
                 int red = GetRValue(clr);
                 int green = GetGValue(clr);
                 int blue = GetBValue(clr);
                 SetPixel(hdc,i,j,RGB(255-red,255-green,255-blue));
             }
         }
         ReleaseDC(hwnd,hdc);
         return 0;
    case WM_SIZE:
        pt.x = LOWORD(lParam);//存储客户区宽度
        pt.y = HIWORD(lParam);//存储客户区高度
        return 0;
     case WM_DESTROY:
         PostQuitMessage(0);
         return 0;
     default:
         return DefWindowProc(hwnd, message, wParam, lParam);
    }
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrev,LPSTR lpCmd,int iShow)
{
    TCHAR ClassName[] = _T("MyClass");
    TCHAR title1[] = _T("C++技术网http://www.cjjjs.com");
    WNDCLASS wndClass;
    wndClass.cbClsExtra=0;
    wndClass.cbWndExtra=0;
    wndClass.hbrBackground= (HBRUSH)GetStockObject(BLACK_BRUSH);
    wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
    wndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
    wndClass.hInstance = hInstance;
    wndClass.lpfnWndProc = WinProc;
    wndClass.lpszClassName = ClassName;
    wndClass.lpszMenuName=NULL;
    wndClass.style=CS_HREDRAW|CS_VREDRAW;

    if(!RegisterClass(&wndClass))
    {
        return 0;
    }

    g_hInstance = hInstance;

    HWND hwnd = CreateWindow(ClassName,title1,WS_OVERLAPPEDWINDOW,0,0,440,440,NULL,NULL,hInstance,NULL);
    ShowWindow(hwnd,SW_SHOWNORMAL);

    MSG msg;
    while (GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}