3

I have applied some effects to camera preview by OpenGL ES 2.0 shaders. Next, I want to save these effect pictures (grayscale, negative ...)

I call glReadPixels() in onDrawFrame(), create a bitmap based on the pixels I read from opengl frame buffer and then save it to device storage.

However, in this way, I only "snapshot" the camera effect preview. In other words, the saved image resolution (ex: 800*480) is not the same as the image taken by Camera.PictureCallback (ex: 1920 * 1080).

I know the preview size can be changed by setPreviewSize(), but it can't equal to picture size finally.

So, is it possible to use glsl shader to post process directly the image get by Camera.PictureCallback ? Or there is another way to achieve the same goal?

Any suggestion will be greatly appreciated. Thanks.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
Justin
  • 115
  • 3
  • 9
  • I believe 800×480 is not the camera preview size, but the screen buffer size – Alex Cohn Aug 29 '13 at 19:23
  • @fen: I have already applied OpenGL effects to camera preview. My question is how to save it. – Justin Aug 30 '13 at 01:32
  • @AlexCohn: oh? I got the 800x480 from getSupportedPreviewSizes(). – Justin Aug 30 '13 at 01:32
  • Are you using setPreviewTexture()? – Alex Cohn Aug 30 '13 at 12:15
  • I think what you want to do is render the preview to a texture or RenderBuffer (resized, with your effect applied), then read the RenderBuffer with glReadPixels(). See: http://processors.wiki.ti.com/index.php/Render_to_Texture_with_OpenGL_ES – ClayMontgomery Aug 31 '13 at 16:14
  • @AlexCohn: As far as I knew, setPreviewTexture() only route camera preview frames to OpenGL ES texture .Could you explain more detail? Thanks. – Justin Sep 01 '13 at 10:15
  • @ClayMontgomery: I am a newbie to OpenGL, need some time to study the info you provided. BTW, do you have any examples or code snippet for me reference to shorten learning curve? Thanks. – Justin Sep 01 '13 at 10:25
  • That article I posted the link to at ti.com does include some example code that I wrote. It is not for Android specifically, but could be adapted for Android easily, either Java or native. – ClayMontgomery Sep 01 '13 at 16:49
  • @ClayMontgomery: After going through the page, I have no idea how to resize the RenderBuffer.... and, is it possible to scale preview texture more than 100%? (ex: 800x480 -> 1920x1080 , picture size is often bigger than preview size). I really can't get it.. Thanks for your patience. – Justin Sep 02 '13 at 05:55
  • Use another glViewport() call to set the RenderBuffer dimensions. Yes, these dimensions can be larger than the texture size. – ClayMontgomery Sep 02 '13 at 16:30
  • @ClayMontgomery: Thanks for your explanation. I set render target to FBO and use glReadPixels() to save it. It works, but not perfectly. I encounter another 2 problems. 1. glCheckFramebufferStatus() returns GL_FRAMEBUFFER_UNSUPPORTED when texture size is huge.(ex: 4160x3120) 2. glReadPixels() takes too much time for reading huge texture. (ex: 3648x2736) Any suggestions? – Justin Sep 04 '13 at 08:31
  • Using such large textures is GPU type dependent as some support larger textures than others. It's best to avoid using glReadPixels() altogether. If you render to an EGL Surface backed by a SurfaceTexture, you can display that directly and avoid glReadPixels(). – ClayMontgomery Sep 04 '13 at 21:24
  • @ClayMontgomery: It sounds large textures (larger than 4096x4096) is a device limitation (GPU dependent). However, as my question title in the beginning, I want to **SAVE these large image to device**. If I can't create large textures and can't use glReadPixels(), how can I do this? Could you please point me out the right direction? Many thanks. – Justin Sep 05 '13 at 10:21
  • I saw camera [Live Filters](http://www.samsung.com/us/article/11-camera-tips-for-your-galaxy-s-4) on Samsung Galaxy S4. It is pretty like what I want to do. How to know if this feature is implemented by OpenGL ES or hardware? If the answer is OpenGL ES, it saves large image really fast.... – Justin Sep 08 '13 at 13:04
  • @Justin have you found a solution? – defhlt Apr 20 '15 at 22:29

1 Answers1

0

Justin, this was my question about setPreviewTexture(), not a suggestion. If you send the pixel data as received from onPreviewFrame() callback, it will naturally be limited by supported preview sizes.

You can use the same logic to push the pixels from onPictureTaken() to a texture, but you should decode them into RGB from JPEG format.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307