在没有监视器的PC上渲染和捕获屏幕截图

时间:2018-05-08 01:44:08

标签: c++ opengl rendering screenshot sdl-2

根据我的previous question,我使用以下代码截取屏幕截图。但是,我使用的PC连接到没有显示器。然后此方法捕获黑屏。有没有任何方法可以在没有显示器的计算机上强制渲染和捕获图像?

我更喜欢基于代码而不是基于操作系统的解决方案,因为我的一些尝试失败了。

lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.4 LTS
Release:    16.04
Codename:   xenial

代码:

#include "SDL/SDL.h"
#include <iostream>
#include <GL/freeglut.h>
#include <SDL2/SDL.h>

#define SDL_LOCKIFMUST(s) (SDL_MUSTLOCK(s) ? SDL_LockSurface(s) : 0)
#define SDL_UNLOCKIFMUST(s) { if(SDL_MUSTLOCK(s)) SDL_UnlockSurface(s); }

int invert_surface_vertical(SDL_Surface *surface)
{
    Uint8 *t;
    register Uint8 *a, *b;
    Uint8 *last;
    register Uint16 pitch;

    if( SDL_LOCKIFMUST(surface) < 0 )
        return -2;

    /* do nothing unless at least two lines */
    if(surface->h < 2) {
        SDL_UNLOCKIFMUST(surface);
        return 0;
    }

    /* get a place to store a line */
    pitch = surface->pitch;
    t = (Uint8*)malloc(pitch);

    if(t == NULL) {
        SDL_UNLOCKIFMUST(surface);
        return -2;
    }

    /* get first line; it's about to be trampled */
    memcpy(t,surface->pixels,pitch);

    /* now, shuffle the rest so it's almost correct */
    a = (Uint8*)surface->pixels;
    last = a + pitch * (surface->h - 1);
    b = last;

    while(a < b) {
        memcpy(a,b,pitch);
        a += pitch;
        memcpy(b,a,pitch);
        b -= pitch;
    }

    /* in this shuffled state, the bottom slice is too far down */
    memmove( b, b+pitch, last-b );

    /* now we can put back that first row--in the last place */
    memcpy(last,t,pitch);

    /* everything is in the right place; close up. */
    free(t);
    SDL_UNLOCKIFMUST(surface);

    return 0;
}

void screen_shot(std::string filename)
{
    int width = glutGet(GLUT_WINDOW_WIDTH);
    int height = glutGet(GLUT_WINDOW_HEIGHT);

    SDL_Surface * image = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);

    glReadBuffer(GL_FRONT);
    glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, image->pixels);

    invert_surface_vertical(image);
    SDL_SaveBMP(image, filename.c_str());
    SDL_FreeSurface(image);
}

void cback_render()
{
    if(!glutGetWindow())
        return ;
    static float rotations = 0;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);

    glLoadIdentity();
    glRotatef(rotations, 0, 0, 1);

    glBegin(GL_TRIANGLES);
        glVertex3f(0,0,0);
        glVertex3f(1,0,0);
        glVertex3f(0,1,0);
    glEnd();

    glutSwapBuffers();
}

void timer(int )
{
    if(!glutGetWindow())
        return ;
    static bool saved=false;
    if(!saved)
    {
        screen_shot("image.bmp");
        saved=true;
    }
    glutPostRedisplay();
    glutMainLoopEvent();
    glutTimerFunc(30, timer, 1);
}

void init()
{
    int argc=1;
    glutInit(&argc, NULL);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(512, 512);
    glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);

    glutCreateWindow("freegluttest");
    glutDisplayFunc (cback_render);
    glutTimerFunc(30, timer, 1);
}

int main()
{
    init();
    glutMainLoop();

    return 0;
}

P.S。对链接问题的解决方案不感兴趣。

此外,我的ffmpeg无法初始化off-srceen。

即使我完全省略ffmpeg,此代码也会让我Segmentation fault (core dumped)无处可寻(通过-O0 -g3选项编译):

(gdb) bt
#0  0x0000000000000000 in ?? ()
#1  0x0000000000419623 in ?? ()
#2  0x00007f6ec4733510 in ?? ()
#3  0x000000016eccea00 in ?? ()
#4  0x00000000004351d0 in ?? ()
#5  0x68f012126eccea00 in ?? ()
#6  0x000000000063ca60 in ?? ()
#7  0x00000000004125cb in ?? ()
#8  0x000000000063cd60 in ?? ()
#9  0x00007ffd9b2b87c8 in ?? ()
#10 0x0000000000000000 in ?? ()

0 个答案:

没有答案