读取位图文件

#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;
}

 

原文链接: https://www.cnblogs.com/strive-sun/p/12710963.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    读取位图文件

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/404933

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月25日 下午4:48
下一篇 2023年4月25日 下午4:48

相关推荐