简体   繁体   English

位图为char * win32问题

[英]Bitmap to char * win32 problems

Im trying to take a screenshot, converting it to a char * and sending it via winsocks. 我试图拍摄屏幕截图,将其转换为char *并通过winsocks发送。

I use bitmaps because it appears to be the easiest way. 我使用位图,因为它似乎是最简单的方法。

Heres what I got so far: 到目前为止,这是我得到的:

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;

Now, I get a valid screenshot if I write hBitmap to a file ( which I do not want to do ). 现在,如果我将hBitmap写入文件(我不想这样做),则会得到一个有效的屏幕截图。

However, when I try to convert the Bitmap to a char *, I always get the following data: 但是,当我尝试将位图转换为char *时,总是得到以下数据:

\x1\x1\x1ÿ\x1\x1\x1ÿ\x1\x1\x1ÿ\x1\x1\x1ÿ\x1\x1\x1ÿ\x1\x1\x1ÿ\x1\x1\x1ÿ\

Can anyone help me out? 谁能帮我吗?

Thanks in advance. 提前致谢。

Not sure why you want to convert it to a string.. You could also do what you're currently doing which is to send over the header of the bitmap first. 不知道为什么要将它转换为字符串。您还可以执行当前正在做的事情,即先发送位图的标头。 Followed by the pixels. 其次是像素。 I don't see the need to convert it to a string. 我认为没有必要将其转换为字符串。

Here is a very basic example of converting the bitmap to a string (for the sake of answering the question). 这是将位图转换为字符串的一个非常基本的示例(为了回答问题)。

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());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM