Подтвердить что ты не робот

Снимок экрана Android OpenGL

Я пытаюсь сделать снимок экрана Android OpenGL.

Код, который я нашел, выглядит следующим образом:

nt size = width * height;
    ByteBuffer buf = ByteBuffer.allocateDirect(size * 4);
    buf.order(ByteOrder.nativeOrder());
    glContext.glReadPixels(0, 0, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, buf);
    int data[] = new int[size];
    buf.asIntBuffer().get(data);
    buf = null;
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
    bitmap.setPixels(data, size-width, -width, 0, 0, width, height);
    data = null;

    short sdata[] = new short[size];
    ShortBuffer sbuf = ShortBuffer.wrap(sdata);
    bitmap.copyPixelsToBuffer(sbuf);
    for (int i = 0; i < size; ++i) {
        //BGR-565 to RGB-565
        short v = sdata[i];
        sdata[i] = (short) (((v&0x1f) << 11) | (v&0x7e0) | ((v&0xf800) >> 11));
    }
    sbuf.rewind();
    bitmap.copyPixelsFromBuffer(sbuf);

    try {
        FileOutputStream fos = new FileOutputStream("/sdcard/screeshot.png");
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
        fos.flush();
        fos.close();
    } catch (Exception e) {
        // handle
    }

Я попробовал также код с этого сайта текст ссылки

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

4b9b3361

Ответ 1

Извините за поздний ответ...

Чтобы выполнить правильный снимок экрана, вы должны поместить в свой обработчик onDrawFrame (GL10 gl) следующий код:

if(screenshot){                     
                int screenshotSize = width * height;
                ByteBuffer bb = ByteBuffer.allocateDirect(screenshotSize * 4);
                bb.order(ByteOrder.nativeOrder());
                gl.glReadPixels(0, 0, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, bb);
                int pixelsBuffer[] = new int[screenshotSize];
                bb.asIntBuffer().get(pixelsBuffer);
                bb = null;
                Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
                bitmap.setPixels(pixelsBuffer, screenshotSize-width, -width, 0, 0, width, height);
                pixelsBuffer = null;

                short sBuffer[] = new short[screenshotSize];
                ShortBuffer sb = ShortBuffer.wrap(sBuffer);
                bitmap.copyPixelsToBuffer(sb);

                //Making created bitmap (from OpenGL points) compatible with Android bitmap
                for (int i = 0; i < screenshotSize; ++i) {                  
                    short v = sBuffer[i];
                    sBuffer[i] = (short) (((v&0x1f) << 11) | (v&0x7e0) | ((v&0xf800) >> 11));
                }
                sb.rewind();
                bitmap.copyPixelsFromBuffer(sb);
                lastScreenshot = bitmap;

                screenshot = false;
            }

Поле класса "скриншот" имеет значение true, когда пользователь нажимает кнопку, чтобы создать скриншот или при любых других обстоятельствах, которые вы хотите. Внутри тела "если" Вы можете поместить любой скриншот, создающий образец кода. Вы находите в Интернете - самое главное - иметь текущий экземпляр GL10. Например, когда вы просто сохраняете экземпляр GL10 для переменной класса, а затем используете его за пределами события, чтобы создать скриншот. В итоге вы получите совершенно пустое изображение. Вот почему вы должны сделать снимок экрана внутри обработчика события OnDrawFrame, где экземпляр GL10 является текущим. Надеюсь, что это поможет.

С уважением, Гордон.

Ответ 2

Вот как это сделать, если вы хотите сохранить качество (8 бит для каждого цветового канала: красный, зеленый, синий и альфа):

if (this.screenshot) {
    int screenshotSize = this.width * this.height;
    ByteBuffer bb = ByteBuffer.allocateDirect(screenshotSize * 4);
    bb.order(ByteOrder.nativeOrder());
    gl.glReadPixels(0, 0, width, height, GL10.GL_RGBA, GL10.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);
    this.screenshot = false;
}

Ответ 3

Получил это!

Моя ошибка заключалась в том, что я помню GL-контекст в переменной класса. Чтобы сделать снимок экрана, я должен использовать gl-контекст, переданный OnDraw в классе, реализующем интерфейс GLSurfaceView.Renderer. Я просто использую свой код в разделе "if", и все работает так, как ожидалось. Надеюсь, что это замечание поможет кому угодно.

С уважением, Гордон