位图到char * win32问题

时间:2016-01-23 19:50:54

标签: c++ winapi bitmap winsock

我试图截取屏幕截图,将其转换为char *并通过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写入文件(我不想这样做),我会得到一个有效的屏幕截图。

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

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

任何人都可以帮助我吗?

提前致谢。

1 个答案:

答案 0 :(得分:0)

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

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

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