Пришлось копировать через 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;
}