- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试从 WebRTC Android 应用程序保存帧。在 SurfaceViewRenderer.java它使用 GLES 着色器绘制 YUV 帧。为了保存绘制的框架,我从 grafika 添加了 saveFrame()到 SurfaceViewRenderer.java 但当我调用 saveFrame() 它不起作用(位图为空)。我以为 glReadPixels() 从当前颜色缓冲区读取像素,但它似乎没有在当前 EGLcontext 中调用?如何调用glReadPixels()保存当前帧?
我写的代码是这样的:
在 MainActivity 中我添加了这样的按钮。
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bitmap = localSurfaceViewRender.saveFrame();
if (bitmap != null) {
Toast.makeText(getApplicationContext(), "Saved!!", Toast.LENGTH_SHORT).show();
imageView.setImageBitmap(bitmap);
}
}
});
在 SurfaceViewRenderer.java 我添加了一些方法来从当前绑定(bind)的 egl 中获取值
public int getSurfaceHeight() {
if (mHeight < 0) {
return eglBase.surfaceHeight();
} else {
return mHeight;
}
}
public int getSurfaceWidth() {
if (mWidth < 0) {
return eglBase.surfaceWidth();
} else {
return mWidth;
}
}
public Bitmap saveFrame() {
int width = eglBase.surfaceWidth();
int height = eglBase.surfaceHeight();
ByteBuffer buf = ByteBuffer.allocateDirect(width * height * 4);
buf.order(ByteOrder.LITTLE_ENDIAN);
GLES20.glFinish();
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, buf);
GlUtil.checkNoGLES2Error("glReadPixels");
buf.rewind();
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bmp.copyPixelsFromBuffer(buf);
return bmp;
}
编辑:这段代码是saveFrame的完整代码
// save as a file
public void saveFrame(final File file) {
runOnRenderThread(new Runnable() {
@Override
public void run() {
int width = eglBase.surfaceWidth();
int height = eglBase.surfaceHeight();
ByteBuffer buf = ByteBuffer.allocateDirect(width * height * 4);
buf.order(ByteOrder.LITTLE_ENDIAN);
GLES20.glFinish();
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf);
GlUtil.checkNoGLES2Error("glReadPixels");
buf.rewind();
// fliping by vertical
byte[] tmp = new byte[width * 4];
for (int i = 0; i < height / 2; i++) {
buf.get(tmp);
System.arraycopy(buf.array(), buf.limit() - buf.position(),
buf.array(), buf.position() - width * 4, width * 4);
System.arraycopy(tmp, 0, buf.array(), buf.limit() - buf.position(), width * 4);
}
buf.rewind();
String filename = file.toString();
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(new FileOutputStream(filename));
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bmp.copyPixelsFromBuffer(buf);
bmp.compress(Bitmap.CompressFormat.JPEG, 100, bos);
bmp.recycle();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (bos != null) try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Log.d(TAG, "Saved " + width + "x" + height + " frame as '" + filename + "'");
}
});
}
最佳答案
glReadPixels()
函数从当前上下文中读取帧缓冲区的内容。一旦 eglSwapBuffers()
被调用,内容就消失了。
换句话说,应用无法从 SurfaceView 中读取任何内容。因此,您必须在将缓冲区提交给合成器之前读出像素。
(我实际上不确定如果您在交换缓冲区后立即调用 glReadPixels()
会发生什么......您可能会从回收缓冲区读取先前发送的帧,但您不能总是依赖它。)
您似乎是从主 UI 线程调用 glReadPixels()
。如果 SurfaceView 渲染发生在不同的线程上,您将需要从同一个线程访问帧缓冲区,因为这是 EGL 上下文当前所在的位置。给定的上下文不能同时在多个线程中处于当前状态。
关于android - glReadPixels 在 WebRTC Android SurfaceViewRenderer 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35764190/
我有一个具有两个线程的 Android OpenGL-ES 应用程序。将线程 1 称为“显示线程”,它将其当前纹理与来自线程 2 的纹理“混合”,也就是“工作线程”。线程 2 执行屏幕外渲染(渲染到纹
我正在使用 pyopengl 获取深度图。 我可以使用 glReadPixels() 获得标准化的深度图。如何将归一化值恢复为世界坐标中的实际深度? 我试过使用 glDepthRange(),但它总是
比如在片段着色器中 FragColor = vec4(TexCoords, MicrifiedCurrentPixelLevel, 0.5); notes:A'value is 0.5. 我想获得Fr
当我绘制一个点时,glReadPixels 不会立即更新。 glColor3f(1.0f, 0.0f, 0.0f); glBegin(GL_POINTS); glVertex2f(x,
我想使用 JOGL 保存我正在用 openGL 显示的视频。为此,我按如下方式将我的帧写入图片,然后,一旦我保存了所有帧,我将使用 ffmpeg。我知道这不是最好的方法,但我仍然不太清楚如何使用 te
我正在尝试使用 glReadPixels 从像素中获取数据。它工作了一段时间。但现在它停止工作了,我不知道为什么。 我需要制作Flood fill算法。 glBegin(GL_POINTS);
我正在使用代码渲染圆形渐变并通过触摸在渐变上创建十字准线( subview )。我现在想读取触摸位置的像素并让它返回 RGB 值,但它总是给我相同的值.. 编辑:添加了呈现渐变的代码 全新代码: vi
我尝试获取渲染像素的颜色。 gl.glColor3f(1f, 0, 0); //draw gl.glReadPixels(lastX - pw / 2, MyCanvas.this.getHeight
我就开门见山了:) 从上面的 480 x 320 图中,我想我可以像蠕虫游戏一样检测像素级别的碰撞。 我想知道的是如何对不同图层上的像素进行采样。正如您在图中看到的,当蠕虫下落时,我只想使用 glRe
经过一个多小时的寻找答案(尝试 Munshi 的“OpenGL ES 2.0 编程指南”中的内容、搜索 Apple 的文档、搜索 StackOverflow),我仍然对如何让 glReadPixels
当我将我的场景渲染到屏幕上时,场景使用了 _MultiSampling Anti-Aliasing 8x; 没问题。 但我想通过 glReadPixels() 读取像素缓冲区,我有一个带有别名线的别名
我正在尝试读取屏幕上绘制的矩形的颜色,但是当我尝试从坐标读取时,它似乎是从一个偏移量读取的,但这个偏移量并不一致。 (我正在使用 SDL2 库以防有帮助)我发现它正在反转坐标,例如如果 y 为 0,则
我使用 JOGL 来处理 OpenGL,但无法获取像素颜色。方法 glReadPixels() 始终返回一个全零的数组。 这就是我的使用方式: private static GL2 gl; stati
我正在尝试通过使用带有 C++ 代码的 glReadPixels 选择两个点(对角)来读取一个像素矩形。选择 Y 轴值时出现问题。 目前,我设法让 glReadPixels 工作直到缩放。当您放大(放
我遇到了 glReadPixels 无法读取颜色附件的问题。 我正在尝试做的事情: 读取非默认帧缓冲区的第三种颜色附件(下面的代码) glFlush(); glFinish(); //binds my
我有一个可以在显示器上渲染的 3d 场景。但是,除了渲染它以显示之外,我还希望能够将渲染的场景导出为图像(比如每 100 帧一次)(比如 JPG 或 PNG 图像),也许将其保存为文件保存在我的某个地
目前我的视口(viewport)上是: 这是我导出图片的方法。 void exportImage() { int width = 200; int height = 100; GLubyt
下面的代码工作正常 const char *title = "glReadOutput"; Mat out1, out2; out1.create(screenHeight,screenWidth,
我是 OpenGL 和 C++ 的新手,最近一直在尝试从我渲染的窗口中提取深度值。我注意到了一些有趣的事情,但我似乎无法弄清楚为什么会这样。 如果我使用与我的窗口大小匹配的“宽度”和“高度”值调用 g
我正在使用 glReadPixels 在 GLSurfaceView.Renderer 的 drawFrame 方法中定期拍摄快照。我需要定期拍摄此快照,以根据我的应用程序要求继续保存我的数据。 但是
我是一名优秀的程序员,十分优秀!