【发布时间】:2015-08-31 13:06:34
【问题描述】:
因此,我正在实现一个屏幕,以将效果(颗粒、负片等)应用于用户从相机拍摄的图像或从他们的画廊拍摄的图像。我能够拍摄他们选择或拍摄的图像,并通过使用 OpenGL 以全分辨率显示给他们(或根据他们设备的最大纹理尺寸和图像的大小按比例缩小以保持纵横比)。此外,选择效果并应用于纹理完全可以正常工作。就像拍摄图像并制作一堆小预览缩略图一样,该缩略图以 60x60 大小应用于它的特定效果。我这样做的方法是使用 FrameBuffer 渲染图像并使用 glReadPixels 立即将其保存到位图。
我遇到的问题是: 我想保存应用了所选过滤器的图像,其尺寸与正在显示的尺寸相同。所以我使用与保存缩略图相同的算法,但使用完整的图像大小而不是 60x60。但是当我这样做时,保存的位图只是图像的左下角,其余的只是黑屏。但是,当我将尺寸从 3072x4096 更改为 1080x1920 时,会正确绘制并保存位图。我相信这与防止 glReadPixels 读取完整尺寸的设备屏幕尺寸有关,因为它比设备屏幕大。
有没有人知道如何准确解决这个问题?或者可以向我解释为什么程序会以这种方式运行。
感谢您的帮助。
int[] mTextures = new int[2];
//... I set the Effect I want, this all works fine so I've ommited it for clarity...///
GLES20.glBindFrameBuffer(GLES20.GL_FRAMEBUFFER, 0) // Bind Default Frame buffer
/// setup up program and everything works
GLES20.glViewPort(0,0,mTexWdith, mTexHeight) // should be something along 3160x4096, which is mImageHeight and mImageWdith
// COntinue with normal rendering///
GLES20.ActiveTextture(GLES20.GL_TEXTURE0)
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[1];
这一步之后是我使用glesReadPixels的地方 这个方法看起来像这样:
GLES20.glBindFrameBuffer(GLES20.GL_FRAMEBUFFER, 0) // is this the correct binding?
//allocate byte buffer here. Works fine
GLES20.glReadPixels(0,0,mImageWidth, mImageHeight, GLES20.GL_RGBA,GLES.INSIGNED, byteBuffer)
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GLToolBox.checkGlError("store Pixels");
pixelBuffer.rewind();
//set bitmap and use matrix to account for the image being vertically flipped
Bitmap bm = Bitmap.createBitmap(mImageWidth, mImageHeight, Bitmap.Config.ARGB_8888);
bm.copyPixelsFromBuffer(pixelBuffer);
Matrix m = new Matrix();
m.setScale(-1, 1);
m.preRotate(180);
bm = Bitmap.createBitmap(bm,0,0,mImageWidth, mImageHeight, m, false);
那我继续把这里的图片存成一个文件///
【问题讨论】:
-
如果您想以高于窗口或屏幕提供的分辨率进行渲染和检索,则必须渲染到屏幕外表面,例如 FBO。
-
是的,我正在使用 FBO 以 60x60 的大小呈现我的图像的缩略图版本。然而,当我尝试渲染接近最大纹理大小的图像时,奇怪的事情开始发生。就像只绘制图像的左下角,其余部分将显示为黑色。考虑到 60x60 的图像完美地工作,这很奇怪。
-
很难说发生了什么。您可能会达到一些硬件限制,例如最大视口大小。但它也可能只是代码中的一个错误。如果没有任何进一步的细节,我真的无能为力。
-
我在原帖中添加了一些 sudo 代码。我省略了我知道工作正常的事情。但我想演示我如何绑定帧缓冲区和纹理,因为这是我不确定的部分。就像它说的那样,它适用于生成 60x60 的图像,但不适用于较大的图像
-
您明确使用 FB 0,这是窗口(或您的上下文附加到的任何可绘制对象)提供的默认帧缓冲区。您没有在此代码中使用任何 FBO,您将无法以这种方式渲染比屏幕更大的图像。