Re: Получить screenshot windows в cv::Mat
От: rs4i  
Дата: 23.04.13 07:29
Оценка:
Пришлось копировать через 2 промежуточных буфера.
И хотя, скорость работы меня уже устраивает,
хотелось бы знать, нет ли более простого способа?

Итого:
std::auto_ptr< cv::Mat > getScreen(){
    // Получить параметры экрана
    HWND hDW = GetDesktopWindow();    
    HDC hDWDC = GetWindowDC( hDW );
    int width = GetSystemMetrics( SM_CXSCREEN );
    int height = GetSystemMetrics( SM_CYSCREEN );

    // Скопировать экран в буфер Windows
    HDC hScreen = CreateCompatibleDC( hDWDC ); // - DeleteDC( hScreen );
    HBITMAP hBM = CreateCompatibleBitmap( hDWDC, width, height ); // - DeleteObject( hBM );
    HGDIOBJ temp = SelectObject( hScreen, hBM ); // - SelectObject( hScreen, temp );
    BitBlt( hScreen, 0, 0, width, height, hDWDC, 0, 0, SRCCOPY );

    // Скопировать в свой буфер
    const int colorSize = 3;
    const int alignment = 4;
    int step = ( width * colorSize / alignment + ( width * colorSize % alignment? 1: 0 ) ) * alignment;
    char* buffer = new char[ step * height ]; // - delete[] buffer;
    BITMAPINFO BMI; // ZeroMemory( &BMI, sizeof BMI );
    BMI.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
    BMI.bmiHeader.biWidth = width;
    BMI.bmiHeader.biHeight = -height;
    BMI.bmiHeader.biPlanes = 1;
    BMI.bmiHeader.biBitCount = 24;
    BMI.bmiHeader.biCompression = BI_RGB;    
    GetDIBits( hScreen, hBM, 0, height, buffer, &BMI, DIB_RGB_COLORS );    

    // Заполнить cv::Mat из буфера
    std::auto_ptr< cv::Mat > screen( new cv::Mat( height, width, CV_8UC3 ) );
    for( int y = 0; y < height; ++y )
        for( int x = 0; x < width; ++x ){
            int pScreen = ( y * screen->cols + x ) * screen->elemSize();
            int pBuffer = y * step + x * colorSize;
            screen->data[ pScreen + 0 ] = buffer[ pBuffer + 0 ]; // B
            screen->data[ pScreen + 1 ] = buffer[ pBuffer + 1 ]; // G
            screen->data[ pScreen + 2 ] = buffer[ pBuffer + 2 ]; // R
        }

    // Удалить не нужные объекты
    SelectObject( hScreen, temp );
    DeleteObject( hBM );
    DeleteDC( hScreen );
    delete[] buffer;

    return screen;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.