zoukankan      html  css  js  c++  java
  • 第14章 位图和位块传输_14.1-14.3 位图基础

    14.1 位图基础

    (1)位图和图元文件的区别:位图是点阵图形;图元文件是矢量图形

    (2)位图的缺点:

      ①受设备相关的影响(如色彩、分辨率、纵横比例)

      ②需要很大的存储空间:如640×480像素,16种颜色(4位),需要640*480*4/8/1024(即150KB);1024×768像素,24位图形需要1024*768*24/8/1024/1024(即2.25MB)。位图的存储空间是由图像大小和它所包含颜色的数目决定。而图元文件的存储空间是由图像的复杂度和它所包含的GDI命令的个数来决定的。

    (3)位图的优点:速度快,将位图复制到视频显示器,通常比绘制一个图元文件要快得多。

    14.2 位图尺寸

    14.2.1 颜色和位图

     (1)颜色深度(Color Depth):每个像素需要的位的数目。也称位数(bit-count)或每像素位数(bits per pixel,bpp)。

    (2)单色位图:每个像素只有1位,也称为“二级(bitlevel)”或“二色”位图。

    (3)位数(n)和所能表示的颜色数目(m): m =2^n

    14.2.2 现实世界的设备

    (1)CGA和HGC显卡:单色(1位)

    (2)EGA:16种颜色(4位)。EGA提供64种颜色的调色板,但应用程序只能选16种)。

         ①16色位图的色彩编码IRGB(强度—红—绿—蓝)

         ②EGA把内存分为4个“颜色平面”,分别是强度、红、绿、蓝。而每个像素颜色的定义是分别从这4个平面中取1位出来组合得一个IRGB值,然后将此值做为索引从下列表格中取出相应的RGB颜色。

         ③IRGB值与RGB颜色值的对应关系

    IRGB

    RGB颜色

    颜色名称

    IRGB

    RGB颜色

    颜色名称

    0000

    00-00-00

    1000

    80-80-80

    深灰

    0001

    00-00-80

    深蓝

    1001

    00-00-FF

    0010

    00-80-00

    深绿

    1010

    00-FF-00

    绿

    0011

    00-80-80

    深青

    1011

    00-FF-FF

    0100

    80-00-00

    深红

    1100

    FF-00-00

    0101

    80-00-80

    深洋红

    1101

    FF-00-FF

    洋红

    0110

    80-80-00

    深黄

    1110

    FF-FF-00

    0111

    C0-C0-C0

    浅灰

    1111

    FF-FF-FF

    (3)VGA或SVGA显卡:256种颜色(每个像素用8位,不一定对应具体的颜色),显卡采用的是“调色板查找表”的方式。其中20种是保留颜色,其作236种可以自定义。

    (4)全真彩显卡:16位或24位。现在一般用24位。即每个像素用3个字节表示。

    14.3 位块传输

    14.3.1 几个位块传输函数

    (1)BitBlt函数:BitBlt(hdcDst,xDst,yDst,cx,cy,hdcSrc,xSrc,ySrc,dwROP);

      ①从“源”设备环境传输到“目标”设备环境(注意是从DC到DC的传输,源是来自DC而不是资源文件)。

      ②源和目标设备可以相同

      ③最重要限制是两个设备一定要“兼容”,如无法从屏幕的东西blt到打印机DC中。

      ④坐标单位和尺寸是基于逻辑单位的。而图像的尺寸cx和cy是源和目标设备共用的参数。如果当源和设备的逻辑单位不同(即映射模式不同)时,图像会被缩放,相当于StretchBlt函数,但其灵活性不如StretchBlt。

    【BitBlt程序】注意由于Win7的Aero特性,标题栏等非客户区会出现毛玻璃效果,从而使该程序不能正常运行!
    效果图

    /*------------------------------------------------------------
    BITBLT.C -- BitBlt Demonstration
    (c) Charles Petzold, 1998
    ------------------------------------------------------------*/
    #include <windows.h>
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("BitBlt");
        HWND         hwnd;
        MSG          msg;
        WNDCLASSEX     wndclass;
        wndclass.style = CS_HREDRAW | CS_VREDRAW;
        wndclass.cbSize = sizeof(WNDCLASSEX);
        wndclass.lpfnWndProc = WndProc;
        wndclass.cbClsExtra = 0;
        wndclass.cbWndExtra = 0;
        wndclass.hInstance = hInstance;
        wndclass.hIcon = LoadIcon(NULL, IDI_INFORMATION);
        wndclass.hIconSm = LoadIcon(NULL, IDI_INFORMATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;
        if (!RegisterClassEx(&wndclass))
        {
            MessageBox(NULL, TEXT("This program requires Windows NT!"),
                       szAppName, MB_ICONERROR);
            return 0;
        }
    
        hwnd = CreateWindow(szAppName,                  // window class name
                            TEXT("BitBlt Demo"), // window caption
                            WS_OVERLAPPEDWINDOW,        // window style
                            CW_USEDEFAULT,              // initial x position
                            CW_USEDEFAULT,              // initial y position
                            CW_USEDEFAULT,              // initial x size
                            CW_USEDEFAULT,              // initial y size
                            NULL,                       // parent window handle
                            NULL,                       // window menu handle
                            hInstance,                  // program instance handle
                            NULL);                     // creation parameters
    
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
    
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return msg.wParam;
    }
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        static int cxClient, cyClient, cxSource, cySource;
        HDC         hdcClient, hdcWindow;
        PAINTSTRUCT ps;
        switch (message)
        {
        case WM_CREATE:
            //cxSource=边框+标题栏中图标按钮的宽度
            cxSource = GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXSIZE);
            //cySource=边框+标题栏高度
            cySource = GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION);
            return 0;
        case WM_SIZE:
            cxClient = LOWORD(lParam);
            cyClient = HIWORD(lParam);
            return 0;
        case WM_PAINT:
            hdcClient = BeginPaint(hwnd, &ps);
            hdcWindow = GetWindowDC(hwnd); //整个窗口含非客户区的dc
    
            for (int y = 0; y < cyClient; y += cySource)
                for (int x = 0; x < cxClient; x += cxSource)
                {
                    BitBlt(hdcClient, x, y, cxSource, cySource,
                           hdcWindow, 0, 0, SRCCOPY);
                }
    
            ReleaseDC(hwnd, hdcWindow);
            EndPaint(hwnd, &ps);
            return 0;
    
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

    (2)StretchBlt函数:——拉伸位图

      StretchBlt(hdcDst,xDst,yDst,cxDst,cyDst,hdcSrc,xSrc,ySrc,cxSrc,cySrc, dwPOP);

      ①除拉伸外,还可以镜像图像或翻转图像。如将cxSrc或cxDst符号

      ②拉伸模式:SetStreatchBltMode(hdc,iMode)——拉伸或缩小时,像素的复制或合并

       模式

    说明

    BLACKONWHITE

    STRETCH_ANDSCANS(默认)

    如果两个或多个像素必须结合与一个像素,则进行逻辑与操作。像素都是白是,结果才是白。也就是合并的结果一般给出黑色,只有都是白色是才为白。这对白底黑色图案的单色位图来说比较好。

    WHITEONBLACK

    STRETCH_ORSCANS

    逻辑或运算。当像素都是黑时,才是黑色。也就是合并的结果一般给出白色,只有像素都是黑色是才是黑的。这对黑底白色图像的单色位置比较好。

    COLORONCOLOR

    STRETCH_DELETESCANS

    简单地去掉像素行或列。这对彩色位图常是最佳的方法。

    HALFTONE

    STRETCH_HALFTONE

    结合源的颜色,计算平均目标颜色。一般和半色调色板一起使用(见第16章)

    【StretchBlt程序】——注意在Win7下会出现与BitBlt程序一样的问题
    效果图

    /*------------------------------------------------------------
    STRETCH.C -- StretchBlt Demonstration
    (c) Charles Petzold, 1998
    ------------------------------------------------------------*/
    #include <windows.h>
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("StretchBlt");
        HWND         hwnd;
        MSG          msg;
        WNDCLASSEX     wndclass;
        wndclass.style = CS_HREDRAW | CS_VREDRAW;
        wndclass.cbSize = sizeof(WNDCLASSEX);
        wndclass.lpfnWndProc = WndProc;
        wndclass.cbClsExtra = 0;
        wndclass.cbWndExtra = 0;
        wndclass.hInstance = hInstance;
        wndclass.hIcon = LoadIcon(NULL, IDI_INFORMATION);
        wndclass.hIconSm = LoadIcon(NULL, IDI_INFORMATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;
        if (!RegisterClassEx(&wndclass))
        {
            MessageBox(NULL, TEXT("This program requires Windows NT!"),
                       szAppName, MB_ICONERROR);
            return 0;
        }
    
        hwnd = CreateWindow(szAppName,                  // window class name
                            TEXT("StretchBlt Demo"), // window caption
                            WS_OVERLAPPEDWINDOW,        // window style
                            CW_USEDEFAULT,              // initial x position
                            CW_USEDEFAULT,              // initial y position
                            CW_USEDEFAULT,              // initial x size
                            CW_USEDEFAULT,              // initial y size
                            NULL,                       // parent window handle
                            NULL,                       // window menu handle
                            hInstance,                  // program instance handle
                            NULL);                     // creation parameters
    
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
    
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return msg.wParam;
    }
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        static int cxClient, cyClient, cxSource, cySource;
        HDC         hdcClient, hdcWindow;
        PAINTSTRUCT ps;
        switch (message)
        {
        case WM_CREATE:
            //cxSource=边框+标题栏中图标按钮的宽度
            cxSource = GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXSIZE);
            //cySource=边框+标题栏高度
            cySource = GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION);
            return 0;
        case WM_SIZE:
            cxClient = LOWORD(lParam);
            cyClient = HIWORD(lParam);
            return 0;
        case WM_PAINT:
            hdcClient = BeginPaint(hwnd, &ps);
            hdcWindow = GetWindowDC(hwnd); //整个窗口含非客户区的dc
    
            StretchBlt(hdcClient, 0, 0, cxClient, cyClient,
                       hdcWindow, 0, 0, cxSource, cySource, SRCCOPY);
    
            ReleaseDC(hwnd, hdcWindow);
            EndPaint(hwnd, &ps);
            return 0;
    
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

    (3)PatBlt——图案块传输:PatBlt(hdc,x,y,cx,cy,dwROP);

      ①单位都是基于逻辑单位的

      ②该函数没有源句柄,因为源为hdc中的画刷句柄。

      ③PatBlt和FillRect函数比较

    应用举例

    函数调用的差别

    绘制黑色矩形

    PatBlt(hdc,x,y,cx,cy,BLCKNESS);

    FillRect(hdc,&rect,hBrush); //hBrush为黑色画刷,内部也是通过PatBlt的。

    反转矩形颜色

    PatBlt(hdc,x,y,cx,cy,DSTINVERT);

    InvertRect(hdc,&rect);//内部调用PatBlt

    14.3.2 光栅操作ROP

    (1)位块传输时要涉及三个图像像素位的操作

        ①源:将源位图拉伸或压缩成目标矩形同样的大小

      ②目标:函数调用前的目标矩形

      ③图案:即目标设备上的画刷,要在横向和纵向上不断重复,直到与目标区域一样大。

    (2)支持BitBlt、StretchBlt与PatBlt的光栅操作不同(见MSDN相应的函数说明)

    14.3.3 单顶点和逻辑矩形问题——以PatBlt(hdc,x,y,cx,cy,dwROP)为例

    (1)GDI绘图函数中,只有BitBlt、PatBlt、StretchBlt是以单个顶点加边长来规定逻辑矩形坐标的。其他的函数都要求左上角和右下角坐标。

    (2)不同映射模式下顶点坐标和逻辑矩形的设置

  • 相关阅读:
    Oracle Convert DateTime to String
    Javascript Regular Expression 日期
    AIX disk usage command
    Truncate a number to a certain number of decimal places
    Start Oracle Sqlplus with Login Information Script
    10)drf 过滤器(条件查询 排序 ) 分页器
    10.windows权限维持
    11.msf和cs补充
    12.linux提权
    4.内网信息收集(补充)
  • 原文地址:https://www.cnblogs.com/5iedu/p/4695503.html
Copyright © 2011-2022 走看看