zoukankan      html  css  js  c++  java
  • 读取位图文件

    #include<iostream>
    #include<fstream>
    #include <string>
    #include<windows.h>
    using namespace std;
    
    #pragma pack(1)
    struct header
    {
        char header[2];
        int32_t filesize;
        int16_t reser;
        int16_t reser1;
        int32_t dataoffset;
    };
    
    struct infoheader
    {
        int32_t headersize;
        int32_t width;
        int32_t height;
        int16_t plans;
        int16_t bpp;
        int32_t compression;
        int32_t datasize;
        int32_t re;
        int32_t ve;
        int32_t color;
        int32_t importantcolor;
    };
    
    struct  PIxel
    {
        unsigned char G;
        unsigned char B;
        unsigned char R;
    };
    
    int main()
    {
        header h;
        infoheader info;
        PIxel* p;
        ifstream file("timg.bmp", ios::binary);
        if (file.is_open())
        {
            cout << "true" << endl;
            file.read((char*)&h, sizeof(h));
            file.read((char*)&info, sizeof(info));
            cout << info.width << " " << info.height << " " << h.filesize << " " << info.bpp << endl;
            int pa = info.width % 4;
     //       int size1 = (info.width * (info.bpp / 8) + pa) * info.height;
            int size = (((24 * info.width + 31) & ~31) / 8)* info.height;
            char* arr = new char[size];
            file.read(arr, size);
            char* temp = arr;
            int sizep = info.height * info.width;
            p = new PIxel[sizep];
    
            for (int i = info.height - 1; i >= 0; i--)
            {
                for (int j = 0; j < info.width; j++)
                {
                    int index = i * (info.width) + j;
                    p[index].B = *(temp++);
                    p[index].G = *(temp++);
                    p[index].R = *(temp++);
                }
                temp += pa;
            }
    
            HWND consoleWindow = GetConsoleWindow();
            HDC hdc = GetDC(consoleWindow);     
            for (int i = 0; i < info.height; i++)
            {
                for (int j = 0; j < info.width; j++)
                {
                    int index = i * (info.width) + j;
                    PIxel m = p[index];
                    SetPixel(hdc, j, i, RGB(m.R, m.G, m.B));
                }
            }
            ReleaseDC(consoleWindow, hdc);
        }
    }

    拓展:

    将屏幕数据保存为数组:

    使用CreateDIBSection的原因是创建相同尺寸的位图后,使用BitBlt将屏幕位图复制过去,从而可以得到屏幕位图的数据,最终借助Copy函数将位图保存为数组。

    我的一个想法是,借助第一个例子,将这个例子获得位图数组再转换为位图,比如只用RGB数组,使用SetPixel将RGB填入上面的控制台的hdc中,再通过创建DIB文件,使用BitBlt,最终将hdc复制给一个新的memdc,从而得到位图句柄,也就可以得到位图文件了。

    void WINAPI CaptureScreenIntoByteArray(
       BYTE*& screen_bytes,
       DWORD& screen_bytes_size)
    {
       BITMAPFILEHEADER bfHeader;
       BITMAPINFOHEADER biHeader;
       BITMAPINFO bInfo;
       HGDIOBJ hTempBitmap;
       HBITMAP hBitmap;
       BITMAP bAllDesktops;
       HDC hDC, hMemDC;
       LONG lWidth, lHeight;
       BYTE* sb = NULL;
    
       ZeroMemory(&bfHeader, sizeof(BITMAPFILEHEADER));
       ZeroMemory(&biHeader, sizeof(BITMAPFILEHEADER));
       ZeroMemory(&bInfo, sizeof(BITMAPINFO));
       ZeroMemory(&bAllDesktops, sizeof(BITMAP));
    
       hDC = GetDC(NULL);
       hTempBitmap = GetCurrentObject(hDC, OBJ_BITMAP);
       GetObjectW(hTempBitmap, sizeof(BITMAP), &bAllDesktops);
    
       lWidth = bAllDesktops.bmWidth;
       lHeight = bAllDesktops.bmHeight;
    
       DeleteObject(hTempBitmap);
    
       bfHeader.bfType = (WORD)('B' | ('M' << 8));
       bfHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    
       biHeader.biSize = sizeof(BITMAPINFOHEADER);
       biHeader.biBitCount = 24;
       biHeader.biCompression = BI_RGB;
       biHeader.biPlanes = 1;
       biHeader.biWidth = lWidth;
       biHeader.biHeight = lHeight;
    
       bInfo.bmiHeader = biHeader;
    
       screen_bytes_size = (((24 * lWidth + 31) & ~31) / 8) * lHeight;
    
       hMemDC = CreateCompatibleDC(hDC);
       hBitmap = CreateDIBSection(hDC, &bInfo, DIB_RGB_COLORS, (VOID**)&sb, NULL, 0);
       SelectObject(hMemDC, hBitmap);
    
       int x = GetSystemMetrics(SM_XVIRTUALSCREEN);
       int y = GetSystemMetrics(SM_YVIRTUALSCREEN);
       BitBlt(hMemDC, 0, 0, lWidth, lHeight, hDC, x, y, SRCCOPY);
    
       // Need to also copy bfHeader & biHeader bytes somehow...
       screen_bytes = new BYTE[sizeof(BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER) + screen_bytes_size];
       std::copy(&bfHeader, &bfHeader + 1, (BITMAPFILEHEADER*)screen_bytes);
       std::copy(&biHeader, &biHeader + 1, (BITMAPINFOHEADER*)(screen_bytes + sizeof(BITMAPFILEHEADER)));
       std::copy(sb, sb + screen_bytes_size, screen_bytes + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
    
       DeleteDC(hMemDC);
       ReleaseDC(NULL, hDC);
       DeleteObject(hBitmap);
    }

    在C++中,使用GetDIBits读取像素

    #include <Windows.h>
    #include <iostream>
    #include <math.h>
    #include <stdio.h>
    using namespace std;
    
    HBITMAP GetScreenBmp( HDC hdc) {
        // Get screen dimensions
        int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
        int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
    
        // Create compatible DC, create a compatible bitmap and copy the screen using BitBlt()
        HDC hCaptureDC  = CreateCompatibleDC(hdc);
        HBITMAP hBitmap = CreateCompatibleBitmap(hdc, nScreenWidth, nScreenHeight);
        HGDIOBJ hOld = SelectObject(hCaptureDC, hBitmap); 
        BOOL bOK = BitBlt(hCaptureDC,0,0,nScreenWidth, nScreenHeight, hdc,0,0,SRCCOPY|CAPTUREBLT); 
    
        SelectObject(hCaptureDC, hOld); // always select the previously selected object once done
        DeleteDC(hCaptureDC);
        return hBitmap;
    }
    
    int main() {
        HDC hdc = GetDC(0);
    
        HBITMAP hBitmap = GetScreenBmp(hdc);
    
        BITMAPINFO MyBMInfo = {0};
        MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader); 
    
        // Get the BITMAPINFO structure from the bitmap
        if(0 == GetDIBits(hdc, hBitmap, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS)) {
            cout << "error" << endl;
        }
    
        // create the bitmap buffer
        BYTE* lpPixels = new BYTE[MyBMInfo.bmiHeader.biSizeImage];
    
        // Better do this here - the original bitmap might have BI_BITFILEDS, which makes it
        // necessary to read the color table - you might not want this.
        MyBMInfo.bmiHeader.biCompression = BI_RGB;  
    
        // get the actual bitmap buffer
        if(0 == GetDIBits(hdc, hBitmap, 0, MyBMInfo.bmiHeader.biHeight, (LPVOID)lpPixels, &MyBMInfo, DIB_RGB_COLORS)) {
            cout << "error2" << endl;
        }
    
        for(int i = 0; i < 100; i++) {
            cout << (int)lpPixels[i];
        }
    
        DeleteObject(hBitmap);
        ReleaseDC(NULL, hdc);
        delete[] lpPixels;
        return 0;
    }
  • 相关阅读:
    MapiRule例子
    P/invoke in .NET Compact Framework
    MFC C++类型学习
    Windows Mobile上实现可拖动的窗口
    在Wince下使用钩子函数
    VC++动态链接库编程之MFC规则DLL
    VC++动态链接库编程之DLL典型实例
    Using keyboard hooks in WinCE
    Override VK_TTALK & VK_TEND
    Getphonenumber获得电话号码的例子
  • 原文地址:https://www.cnblogs.com/strive-sun/p/12710963.html
Copyright © 2011-2022 走看看