C++ 位图到字符*win32问题

C++ 位图到字符*win32问题,c++,winapi,bitmap,winsock,C++,Winapi,Bitmap,Winsock,我正在尝试截图,将其转换为字符*并通过winsocks发送 我使用位图是因为它似乎是最简单的方法 到目前为止,我得到的是: HDC handle_ScreenDC = GetDC( NULL ); HDC handle_MemoryDC = CreateCompatibleDC( handle_ScreenDC ); BITMAP bitmap; int x = GetDeviceCaps( handle_ScreenDC, HORZRES ); int y = GetDevic

我正在尝试截图,将其转换为字符*并通过winsocks发送

我使用位图是因为它似乎是最简单的方法

到目前为止,我得到的是:

HDC handle_ScreenDC = GetDC( NULL );
    HDC handle_MemoryDC = CreateCompatibleDC( handle_ScreenDC );
    BITMAP bitmap;
int x = GetDeviceCaps( handle_ScreenDC, HORZRES );
int y = GetDeviceCaps( handle_ScreenDC, VERTRES );

HBITMAP handle_Bitmap = CreateCompatibleBitmap( handle_ScreenDC, x, y );
SelectObject( handle_MemoryDC, handle_Bitmap );

BitBlt( handle_MemoryDC, 0, 0, x, y, handle_ScreenDC, 0, 0, SRCCOPY );

GetObject( handle_Bitmap, sizeof( BITMAP ), &bitmap );

BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;

bi.biSize = sizeof( BITMAPINFOHEADER );
bi.biWidth = bitmap.bmWidth;
bi.biHeight = bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;

DWORD dwBmpSize = ( ( bitmap.bmWidth * bi.biBitCount + 5 ) / 32 ) * 4 * bitmap.bmHeight;

HANDLE hDIB = GlobalAlloc( GHND, dwBmpSize );

char* bufptr = ( char * ) GlobalLock( hDIB );

GetDIBits( handle_ScreenDC, handle_Bitmap, 0, ( UINT ) bitmap.bmHeight, bufptr, ( BITMAPINFO * ) &bi, DIB_RGB_COLORS );

return bufptr;
现在,如果我将hBitmap写入一个文件(我不想这样做),我会得到一个有效的屏幕截图

但是,当我尝试将位图转换为char*时,总是会得到以下数据:

\x1\x1\x1ÿ\x1\x1\x1ÿ\x1\x1\x1ÿ\x1\x1\x1ÿ\x1\x1\x1ÿ\x1\x1\x1ÿ\x1\x1\x1ÿ\
有人能帮我吗


提前感谢。

不确定为什么要将其转换为字符串。。您还可以执行当前正在执行的操作,即首先通过位图的标题发送。然后是像素。我认为没有必要将其转换为字符串

下面是一个将位图转换为字符串的非常基本的示例(为了回答这个问题)

类图像
{
私人:
std::矢量像素;
标准:uint32_t宽度、高度;
标准:uint16_t比特像素;
公众:
显式图像(HDC DC、int X、int Y、int Width、int Height);
std::uint32_t get_width(){return width;}
std::uint32_t get_height(){return height;}
std::uint32\u t获取每像素的位(){return BitsPerPixel;}
std::string to_string();
};
图像::图像(HDC DC,int X,int Y,int Width,int Height):像素(),宽度(Width),高度(Height),比特像素(32)
{
位图Bmp={0};
HBITMAP hBmp=reinterpret_cast(GetCurrentObject(DC,OBJ_位图));
if(GetObject(hBmp,sizeof(位图),&Bmp)==0)
抛出std::runtime_错误(“未找到位图DC”);
矩形区域={X,Y,X+宽度,Y+高度};
HWND Window=WindowFromDC(DC);
GetClientRect(窗口和区域);
HDC MemDC=GetDC(nullptr);
HDC SDC=CreateCompatibleDC(MemDC);
HBITMAP hSBmp=CreateCompatibleBitmap(MemDC、宽度、高度);
DeleteObject(SelectObject(SDC、hSBmp));
BitBlt(SDC,0,0,宽度,高度,DC,X,Y,SRCCOPY);
无符号整数数据大小=((宽度*比特像素+31)/32)*4*高度;
这->像素。调整大小(数据大小);
BITMAPINFO信息={sizeof(BITMAPINFO头),静态强制转换(宽度),静态强制转换(高度),1,BitsPerPixel,BI_RGB,数据大小,0,0,0};
GetDIBits(SDC、hSBmp、0、高度和像素[0]、&Info、DIB_RGB_颜色);
DeleteDC(SDC);
删除对象(hSBmp);
ReleaseDC(nullptr,MemDC);
}
std::string Image::to_string()
{
auto base64encode=[](标准::向量和输入,标准::字符串和输出)->void{
int i,j;
char*ptr;
uint32_t c[4];
静态字符索引[]={0,2,1};
静态常量char*Base64Chars=“abcdefghijklmnopqrstuvxyzabcdefghijklmnopqrstuvxyz012456789+/”;
out.resize(4*((in.size()+2)/3));
ptr=&out[0];
对于(i=0,j=0;i>2*6)和0x3F];
ptr[j++]=Base64Chars[(c[3]>>1*6)和0x3F];
ptr[j++]=Base64Chars[(c[3]>>0*6)和0x3F];
}
对于(i=0;i
如何尝试“转换”图像?并通过套接字将其作为实际的
BMP
发送,它需要标头(两种标头结构)还有数据。你的图像包含什么样的像素数据?你正在显示的字符串不是完全不可定位的-很明显,这取决于实际图片的外观,我尝试用以下行来转换它:GetDIBits(handle_ScreenDC,handle_Bitmap,0,(UINT)Bitmap.bmHeight,bufptr,(BITMAPINFO*)&bi,DIB_RGB_COLORS);图像只是我主屏幕的一个屏幕截图,每次截图时都不一样。你知道从
GetDIBits
获取的数据是原始二进制数据吗?换句话说,它不是可以作为字符串检查的数据。
class Image
{
private:
    std::vector<std::uint8_t> Pixels;
    std::uint32_t width, height;
    std::uint16_t BitsPerPixel;

public:
    explicit Image(HDC DC, int X, int Y, int Width, int Height);

    std::uint32_t get_width() {return width;}
    std::uint32_t get_height() {return height;}
    std::uint32_t get_bits_per_pixel() {return BitsPerPixel;}
    std::string to_string();
};

Image::Image(HDC DC, int X, int Y, int Width, int Height) : Pixels(), width(Width), height(Height), BitsPerPixel(32)
{
    BITMAP Bmp = {0};
    HBITMAP hBmp = reinterpret_cast<HBITMAP>(GetCurrentObject(DC, OBJ_BITMAP));

    if (GetObject(hBmp, sizeof(BITMAP), &Bmp) == 0)
        throw std::runtime_error("BITMAP DC NOT FOUND.");

    RECT area = {X, Y, X + Width, Y + Height};
    HWND Window = WindowFromDC(DC);
    GetClientRect(Window, &area);

    HDC MemDC = GetDC(nullptr);
    HDC SDC = CreateCompatibleDC(MemDC);
    HBITMAP hSBmp = CreateCompatibleBitmap(MemDC, width, height);
    DeleteObject(SelectObject(SDC, hSBmp));

    BitBlt(SDC, 0, 0, width, height, DC, X, Y, SRCCOPY);
    unsigned int data_size = ((width * BitsPerPixel + 31) / 32) * 4 * height;
    this->Pixels.resize(data_size);

    BITMAPINFO Info = {sizeof(BITMAPINFOHEADER), static_cast<long>(width), static_cast<long>(height), 1, BitsPerPixel, BI_RGB, data_size, 0, 0, 0, 0};

    GetDIBits(SDC, hSBmp, 0, height, &Pixels[0], &Info, DIB_RGB_COLORS);

    DeleteDC(SDC);
    DeleteObject(hSBmp);
    ReleaseDC(nullptr, MemDC);
}

std::string Image::to_string()
{
    auto base64encode = [](std::vector<uint8_t> &in, std::string &out) -> void {
        int i, j;
        char *ptr;
        uint32_t c[4];
        static char indexes[] = {0, 2, 1};
        static const char *Base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

        out.resize(4 * ((in.size() + 2) / 3));
        ptr = &out[0];

        for (i = 0, j = 0; i < in.size();)
        {
            c[0] = i < in.size() ? in[i++] : 0;
            c[1] = i < in.size() ? in[i++] : 0;
            c[2] = i < in.size() ? in[i++] : 0;

            c[3] = (c[0] << 0x10) + (c[1] << 0x08) + c[2];

            ptr[j++] = Base64Chars[(c[3] >> 3 * 6) & 0x3F];
            ptr[j++] = Base64Chars[(c[3] >> 2 * 6) & 0x3F];
            ptr[j++] = Base64Chars[(c[3] >> 1 * 6) & 0x3F];
            ptr[j++] = Base64Chars[(c[3] >> 0 * 6) & 0x3F];
        }

        for (i = 0; i < indexes[in.size() % 3]; ++i)
            ptr[out.size() - 1 - i] = '=';
    };

    std::string result;
    base64encode(Pixels, result);
    return result;
}

int main()
{
    //..
    Image img(screen_dc, 0, 0, screen_width, screen_height);
    std::string res = img.to_string();
    std::size_t size = res.size();

    //..
    socket.write(&screen_width, sizeof(screen_width));
    socket.write(&screen_height, sizeof(screen_height);
    socket.write(&size, sizeof(size));
    socket.write(&res[0], res.size());
}