无法使用 xlib 将屏幕截图位图保存到文件

Can not save screen shot bitmap to file using xlib

我正在尝试将屏幕复制到位图文件,我发现了这个 write XImage to .bmp file in C 线程。我尝试了自己提供的代码,但无法使代码正常工作。它可以保存 img 文件,但无法打开它。我在这里做错什么了吗?

#include <iostream>
#include <X11/Xlib.h>

#include <cstring>
#include<stdio.h>

typedef unsigned short  WORD; // 2bytes
typedef unsigned long  DWORD; //4bytes
typedef long LONG;

using namespace std;

void saveXImageToBitmap(XImage *pImage);

int main()
{
        Display *display;
        int screen;
        Window root;
        display = XOpenDisplay(0);
        screen = DefaultScreen(display);
        root = RootWindow(display, screen);
        XImage *img = XGetImage(display,root,0,0,400,400,XAllPlanes(),ZPixmap);

        if (img != NULL)
        {
saveXImageToBitmap(img);
           //save image here
        }
        return 0;
}
#pragma pack(push, 1) 
typedef struct BITMAPFILEHEADER {
WORD    bfType;
DWORD   bfSize;
WORD    bfReserved1;
WORD    bfReserved2;
DWORD   bfOffBits;
};
#pragma pack(pop)
#pragma pack (push,1)
typedef struct BITMAPINFOHEADER{
DWORD  biSize;
LONG   biWidth;
LONG   biHeight;
WORD   biPlanes;
WORD   biBitCount;
DWORD  biCompression;
DWORD  biSizeImage;
LONG   biXPelsPerMeter;
LONG   biYPelsPerMeter;
DWORD  biClrUsed;
DWORD  biClrImportant;
};
#pragma pack(pop)
void saveXImageToBitmap(XImage *pImage)
{
BITMAPFILEHEADER bmpFileHeader;
BITMAPINFOHEADER bmpInfoHeader;
FILE *fp;
static int cnt = 0;
int dummy;
char filePath[255];
memset(&bmpFileHeader, 0, sizeof(BITMAPFILEHEADER));
memset(&bmpInfoHeader, 0, sizeof(BITMAPINFOHEADER));
bmpFileHeader.bfType = 0x4D42;
bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +  pImage->width*pImage->height*4;
bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmpFileHeader.bfReserved1 = 0;
bmpFileHeader.bfReserved2 = 0;

bmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfoHeader.biWidth = pImage->width;
bmpInfoHeader.biHeight = pImage->height;
bmpInfoHeader.biPlanes = 1;
bmpInfoHeader.biBitCount = 32;
dummy = (pImage->width * 3) % 4;
if((4-dummy)==4)
    dummy=0;
else
    dummy=4-dummy;

bmpInfoHeader.biSizeImage = ((pImage->width*3)+dummy)*pImage->height;
bmpInfoHeader.biCompression = 0;
bmpInfoHeader.biXPelsPerMeter = 0;
bmpInfoHeader.biYPelsPerMeter = 0;
bmpInfoHeader.biClrUsed = 0;
bmpInfoHeader.biClrImportant = 0;

sprintf(filePath, "bitmap%d.bmp", cnt++);
fp = fopen(filePath,"wb");

if(fp == NULL)
    return;

fwrite(&bmpFileHeader, sizeof(bmpFileHeader), 1, fp);
fwrite(&bmpInfoHeader, sizeof(bmpInfoHeader), 1, fp);
fwrite(pImage->data, 4*pImage->width*pImage->height, 1, fp);
fclose(fp);
}

我想通了,根据位图文件格式,结构 BITMAPFILEHEADER 的大小应该是 14,我使用的类型是错误的。请检查修改后的代码以获得答案

#include <iostream>
#include <X11/Xlib.h>

#include <cstring>
#include<stdio.h>

using namespace std;

void saveXImageToBitmap(XImage *pImage);

int main()
{
        Display *display;
        int screen;
        Window root;
        display = XOpenDisplay(0);
        screen = DefaultScreen(display);
        root = RootWindow(display, screen);
    XWindowAttributes gwa;

   XGetWindowAttributes(display, root, &gwa);
   int width = gwa.width;
   int height = gwa.height;
        XImage *img = XGetImage(display,root,0,0,width,height,XAllPlanes(),ZPixmap);

        if (img != NULL)
        {
saveXImageToBitmap(img);
           //save image here
        }
        return 0;
}

#pragma pack (1)
typedef struct BITMAPFILEHEADER 
{
short    bfType;
int    bfSize;
short    bfReserved1;
short    bfReserved2;
int   bfOffBits;
};

typedef struct BITMAPINFOHEADER
{
int  biSize;
int   biWidth;
int   biHeight;
short   biPlanes;
short   biBitCount;
int  biCompression;
int  biSizeImage;
int   biXPelsPerMeter;
int   biYPelsPerMeter;
int  biClrUsed;
int  biClrImportant;
};

void saveXImageToBitmap(XImage *pImage)
{
BITMAPFILEHEADER bmpFileHeader;
BITMAPINFOHEADER bmpInfoHeader;
FILE *fp;
static int cnt = 0;
int dummy;
char filePath[255];
memset(&bmpFileHeader, 0, sizeof(BITMAPFILEHEADER));
memset(&bmpInfoHeader, 0, sizeof(BITMAPINFOHEADER));
bmpFileHeader.bfType = 0x4D42;
bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmpFileHeader.bfReserved1 = 0;
bmpFileHeader.bfReserved2 = 0;
int biBitCount =32;
int dwBmpSize = ((pImage->width * biBitCount + 31) / 32) * 4 * pImage->height;
printf("size of short:%d\r\n",(int)sizeof(short));
printf("size of int:%d\r\n",(int)sizeof(int));
printf("size of long:%d\r\n",(int)sizeof(long));
printf("dwBmpSize:%d\r\n",(int)dwBmpSize);
printf("BITMAPFILEHEADER:%d\r\n",(int)sizeof(BITMAPFILEHEADER));
printf("BITMAPINFOHEADER:%d\r\n",(int)sizeof(BITMAPINFOHEADER));
bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +  dwBmpSize;

bmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfoHeader.biWidth = pImage->width;
bmpInfoHeader.biHeight = pImage->height;
bmpInfoHeader.biPlanes = 1;
bmpInfoHeader.biBitCount = biBitCount;
bmpInfoHeader.biSizeImage = 0;
bmpInfoHeader.biCompression = 0;
bmpInfoHeader.biXPelsPerMeter = 0;
bmpInfoHeader.biYPelsPerMeter = 0;
bmpInfoHeader.biClrUsed = 0;
bmpInfoHeader.biClrImportant = 0;

sprintf(filePath, "bitmap%d.bmp", cnt++);
fp = fopen(filePath,"wb");

if(fp == NULL)
    return;

fwrite(&bmpFileHeader, sizeof(bmpFileHeader), 1, fp);
fwrite(&bmpInfoHeader, sizeof(bmpInfoHeader), 1, fp);
fwrite(pImage->data, dwBmpSize, 1, fp);
fclose(fp);
}