Снимок экрана на Android-приложении OpenGL ES

У меня есть базовое приложение openGL ES 20, работающее с GLSurfaceView, которое было добавлено:

    GLSurfaceView view = new GLSurfaceView(this);
    view.setRenderer(new OpenGLRenderer());
    setContentView(view);

В основном я пытаюсь получить скриншот с помощью следующего метода:

private static Bitmap getScreenshot(View v)
    {
        Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(),
                Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(b);
        v.draw(c);
        return b;
    }

Но кажется, что растровое изображение прозрачно. Мнение, которое я передаю, таково:

View content = m_rootActivity.getWindow().getDecorView().getRootView();

У любого есть решение о том, как сделать скриншот на openGL ES, не прибегая к методу DrawFrame, который я видел в других решениях.

Может быть, перейти в ссылку на рендерер? Любая помощь будет оценена.

Обновление: я изучал рендеринг растрового изображения из onDrawFrame ( отображать черный экран во время захвата скриншота GLSurfaceView)

Однако мне было интересно, есть ли лучшее решение, так как у меня не будет доступа ни к визуализатору, ни к поверхностному виду. Я могу передать их ссылку, но хотел бы найти решение, где мы могли бы просто захватить весь вид, как было упомянуто ранее.

2 ответа

Смотрите этот вопрос.

Вы можете получить скриншот с:

@Override
public void onDrawFrame(GL10 gl) {

    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    // draw ...

    if (takeScreenshot) {

        int screenshotSize = width * height;
        ByteBuffer bb = ByteBuffer.allocateDirect(screenshotSize * 4);
        bb.order(ByteOrder.nativeOrder());
        GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, bb);
        int pixelsBuffer[] = new int[screenshotSize];
        bb.asIntBuffer().get(pixelsBuffer);
        bb = null;

        for (int i = 0; i < screenshotSize; ++i) {
            // The alpha and green channels' positions are preserved while the      red and blue are swapped
            pixelsBuffer[i] = ((pixelsBuffer[i] & 0xff00ff00)) |    ((pixelsBuffer[i] & 0x000000ff) << 16) | ((pixelsBuffer[i] & 0x00ff0000) >> 16);
        }

        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        bitmap.setPixels(pixelsBuffer, screenshotSize-width, -width, 0, 0, width, height);
        // save bitmap...
    }
}

Вы не можете совершенно случайно получить данные буфера в CPU из GPU, не считывая пиксели. Вы должны понимать, что это не тот же конвейер, что и с представлениями, данные в буфере заполняются на GPU и затем отправляются непосредственно на дисплей или в никуда.

Так что, как говорится, ответ - нет. Вы не можете просто получить скриншот, так как концепция скриншота даже не существует в этом вопросе. В буфере графического процессора находятся только необработанные (обычно RGBA) данные. И эти данные должны быть заполнены тем, что вы рисуете, чтобы получить все, что вы нарисовали, если вам нужно было просто прочитать эти данные в любой момент, когда буфер может быть просто очищен, он может быть наполовину нарисован или, если вам повезет, полностью нарисованный.

Вот почему вы делаете эти снимки экрана в конвейере рисования, поскольку вы должны убедиться, что буфер заполнен данными.

Как правило, есть два разумных способа перехватить конвейер рисования, который лучше всего сделать непосредственно перед представлением буфера. Один из них заключается в том, чтобы передать определенный флаг, что снимок экрана должен быть сделан, тогда как сам движок создает снимок экрана, что приятно, так как на лету хранятся все данные буфера. Второе - создать дескриптор обратного вызова, в котором движок будет уведомлять владельца о каждом полностью прорисованном кадре, в этом случае владелец может сделать дополнительное рисование или создать снимок экрана или подсчитать количество кадров в секунду... это опять-таки имеет много бонусов, но вам нужно как минимум передать размеры буфера, чтобы сделать что-нибудь с буфером.

Также обратите внимание, что чтение пикселей происходит очень медленно, и в некоторых случаях изображение, которое вы получите, будет перевернуто.

Другие вопросы по тегам