Я использую текущую поточную библиотеку под названием Cine.io, чтобы сохранить кадр из потока на внешнее хранилище Android.Как преобразовать изображение при использовании Open GL Framebuffer в Android
В самой библиотеке используется ресурс Google Grafika.
Когда я просто настроил ByteBufferand и прочитал его с помощью GLReadPixel, изображение будет сохранено правильно, но оно будет инвертировано, так как изображения GL имеют обратные координаты координат BMP.
Для решения этой проблемы я считаю, что наиболее эффективным решением является использование открытого фреймбуфера GL для рендеринга входящего кадра, переворачивание его с помощью орто-матрицы, а затем чтение его с помощью GLReadPixel, чтобы сохранить его на диске ,
Это код, который я считаю, будет достичь этой цели:
int width = getWidth();
int height = getHeight();
ByteBuffer buf = ByteBuffer.allocateDirect(width * height * 4);
buf.order(ByteOrder.LITTLE_ENDIAN);
int[] fboId = new int[1];
int[] rendId = new int[1];
float[] projMatrix = new float[16];
GLES20.glGenFramebuffers(1, fboId, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboId[0]);
GLES20.glGenRenderbuffers(1, rendId, 0);
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, rendId[0]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER,GLES20.GL_RGBA4, width, height);
switch(GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER)){
case GLES20.GL_FRAMEBUFFER_COMPLETE:
Log.i(TAG, "Is Complete");
break;
case GLES20.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
Log.i(TAG, "Incomplete Attachment");
break;
case GLES20.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
Log.i(TAG, "Missing Attachment");
break;
default: Log.i(TAG, "Something else is going on");
}
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_RENDERBUFFER,rendId[0]);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboId[0]);
GLES20.glViewport(0,0,width, height);
android.opengl.Matrix.orthoM(projMatrix, 0, 0, width, height, 0, -1, 1);
GLES20.glReadPixels(0, 0, width, height,
GLES20.GL_RGBA4, GLES20.GL_UNSIGNED_BYTE, buf);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GlUtil.checkGlError("glReadPixels");
buf.rewind();
Однако код просто создает пустой файл изображения, который является пустым (размер 3.6kb). Кроме того, переменный блок «buff» состоит только из 0 после вызова метода GLreadpixels.
Наконец, если я установил BindFramebuffer равным 0 (привязка по умолчанию) и поместил его перед вызовом GLReadPixels, изображение будет отображаться, но все же инвертировано - это похоже на то, что команды Framebuffer никогда не взаимодействовали с ним.
Как я могу это решить?
PS: многие люди пытаются ответить на предыдущую, более запутанную версию вопроса ниже - но суть этого по-прежнему сохраняется.
Определенно прошел через песню и танец фреймбуфера, чтобы я мог достичь варианта № 2. Моя проблема при определении методов сопоставления в Android. Я буду. – Laurent
Я думаю, что код, который вы предоставили для опции № 2, для GL v1.0. Поскольку я использую GL 2.0 в Android, у меня возникли проблемы с поиском соответствующего кода для привязки преобразования к фреймбуферу. – Laurent
О, право. К сожалению, я все еще довольно новичок в openGL, но думаю, что я все еще могу помочь. Итак, я немного смущен, вы читаете пиксели из буфера кадров по умолчанию (0) и сохраняете их на диск? Зачем вам нужен буфер кадров, который вы создали над ним? Разве вы не должны быть привязаны к идентификатору буфера фрейма, который вы создали выше? Что бы я сделал, это привязка к буферу фрейма, который вы создали выше, при рендеринге, чтобы он отображался в буфер кадра (он не будет отображаться на экране). Когда вы применяете матричное преобразование, вы можете считывать пиксели из этого фреймового буфера. – QualityPixels