Обычный снимок экрана окна с использованием openGL - PullRequest
0 голосов
/ 18 апреля 2019

Я пытаюсь захватить изображение с рабочего стола.(Все изображения, включая вывод рабочего стола на монитор)

Легко использовать оконный API (BitBlt или CImageClass), и это не так, как я хочу.

Я хочу сделать это с помощью opengl.поэтому я нашел функцию glReadPixel и окно ПРОЗРАЧНОЕ.

Но он просто читает пиксельное собственное окно приложения Windows. (Сохраните как файл bmp и проверьте)

Initialize ()

glfwSetErrorCallback(errorCallback);

if (!glfwInit()) {
    std::cerr << "Error: GLFW " << std::endl;
    exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_DEPTH_BITS, 16);
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_SAMPLES, 4);


const int Monitor_count = GetMonitors();

GLwindow = glfwCreateWindow(
    nWidth, // width
    nHeight, // height
    "OpenGL_Test", // window title
    NULL, NULL);
if (!GLwindow) {
    glfwTerminate();
    exit(EXIT_FAILURE);
}
glfwSwapInterval(1);


if (glfwGetWindowAttrib(GLwindow, GLFW_TRANSPARENT_FRAMEBUFFER))
{
    //...
}
glfwSetWindowOpacity(GLwindow, 0.0f);

auto Mode = glfwGetVideoMode(Monitor[0]);   

glfwMakeContextCurrent(GLwindow);   
glfwSetKeyCallback(GLwindow, keyCallback);

glewExperimental = GL_TRUE;                                         
GLenum errorCode = glewInit();

if (GLEW_OK != errorCode) {

    std::cerr << "Error: GLEW - " << glewGetErrorString(errorCode) << std::endl;
    glfwTerminate();
    exit(EXIT_FAILURE);
}
if (!GLEW_VERSION_3_3) {

    std::cerr << "OpenGL 3.3 API is not available." << std::endl;

    glfwTerminate();
    exit(EXIT_FAILURE);
}

glViewport(0, 0, nWidth, nHeight);

glBindFramebuffer(GL_FRAMEBUFFER, 0);

if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
    std::cerr << "Error: " << std::endl;
}

return true;

Roop

while (!glfwWindowShouldClose(GLwindow)) {

    Sleep(10);

    glClearColor(0.0f, 0.3f, 0.3f, 0.5f);
    glClear(GL_COLOR_BUFFER_BIT);

    unsigned char *image = (unsigned char*)malloc(sizeof(unsigned char)*nWidth*nHeight * 3);

       glReadPixels(0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, image);
    glfwPollEvents();

}

return true;

Q1.Возможен ли захват рабочего стола (вывод Full Image GPU) с помощью OPENGL?

Q2.Если Q1 возможно, я должен использовать FBO и PBO GL_BACK ??

Q3.Как получить доступ к материнскому окну или адаптеру GPU?>> GL, похоже, категорически отвергает это. (Я не хочу никакой визуализации, просто читаю данные пикселей из GPU (изображение на рабочем столе. Не воспроизводится моим приложением.) (Если это возможно ...))

Кто-нибудь показывает мне ссылку или идею?

Ответы [ 2 ]

1 голос
/ 18 апреля 2019

Я пытаюсь захватить изображение с рабочего стола. (Все изображения, включая вывод рабочего стола на монитор)

Легко использовать оконный API (BitBlt или CImageClass), и это не так, как я хочу.

Но так и должно быть.

Я хочу сделать это с помощью opengl. так что я нашел функцию glReadPixel

Вы не можете. OpenGL не «знает» о рабочем столе или других окнах (или вообще о том, что это за окна). Функция glReadPixels будет надежно работать только для изображений, нарисованных с помощью самого OpenGL.

Вы не можете использовать OpenGL для создания снимков экрана! На старых компьютерах это может показаться работающим, но это только из-за более старого управления памятью, когда при создании нового окна его память будет " вырезать из того, что было ниже, и если вы читаете это, это похоже на способ сделать скриншоты. Но это не так.

1 голос
/ 18 апреля 2019

То, что вы просите, является чем-то совершенно не входящим в сферу действия OpenGL. OpenGL разработан, чтобы быть независимым от платформы API для приложений, чтобы говорить о том, как рисовать вещи в фреймбуферы абстрактным способом. OpenGL не имеет представления о Windows *, экранах или рабочем столе. OpenGL не работает на уровне, где существуют такие концепции. Черт, OpenGL даже не знает, что такое GPU. Предполагается, что OpenGL инициализируется через платформо-зависимые механизмы для установления контекста, который присваивает фактическое значение вызовам API OpenGL. Насколько я знаю, нет никакого способа настроить контекст OpenGL с кадровым буфером, содержимое которого каким-то образом соответствует рабочему столу в Windows (или любой другой платформе, о которой я знаю). Насколько я понимаю, на самом деле это не имеет смысла & hellip;

Чтобы делать то, что вы хотите, вы должны полагаться на соответствующие API для конкретной платформы. Вероятно, самый простой способ для Windows - получить HDC для всего рабочего стола и BitBlt оттуда. См., Например, этот вопрос для более подробной информации. Более современным подходом было бы использование DXGI Desktop Duplication API .

(*) да, я знаю, что техническая спецификация OpenGL говорит о «окнах» в нескольких местах; но это действительно так, когда речь идет обо всех вещах, за которые он не отвечает & hellip;

...