how to capture full bitmap from after applied effect not draw to GLSurfaceView.
monxarat opened this issue · comments
How to capture full bitmap after applied effect not draw on GLSurfaceView.
My code
public void getBitmapWithFilter(final Bitmap bitmap, final File outFile, final OnBitmapReceiveListener onBitmapReceiveListener){
if (!mIsSaving) {
mIsSaving = true;
mGLSurfaceView.queueEvent(new Runnable() {
@Override
public void run() {
int width = 1024;//bitmap.getWidth();
int height = 910;//bitmap.getHeight();
if(mFilter != null) {
mFilter.onInputSizeChanged(width, height);
mFilter.onDisplaySizeChanged(width, height);
}
// init buffer for texture
int[] mFrameBuffers = new int[1];
int[] mFrameBufferTextures = new int[1];
// load texture
OpenGlUtils.loadTextureBufferFiltering(mFrameBuffers, mFrameBufferTextures, width, height);
GLES20.glViewport(0, 0, width, height);
int textureId = OpenGlUtils.loadTexture(bitmap, OpenGlUtils.NO_TEXTURE, true);
// draw frame to texture
if(mFilter != null){
mFilter.onDrawFrame(mFrameBufferTextures[0], gLCubeBuffer, gLTextureBuffer);
} else {
imageInput.onDrawFrame(textureId, gLCubeBuffer, gLTextureBuffer);
}
// copy pixel buffer from the current texture
Bitmap result = BitmapProcessor.createBitmap(width, height);
// delete texture
OpenGlUtils.deleteTextureBufferFiltering(textureId, mFrameBuffers, mFrameBufferTextures);
// rest getBitmapWithFilter display
if(mFilter != null) {
mFilter.onDisplaySizeChanged(mSurfaceWidth, mSurfaceHeight);
mFilter.onInputSizeChanged(mImageWidth, mImageHeight);
}
if (outFile != null) {
// save bitmap to disk
BitmapProcessor.saveBitmapToImage(result, outFile);
}
mIsSaving = false;
// reset viewport of the current texture.
GLES20.glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
// notice to activity
if (onBitmapReceiveListener != null) {
onBitmapReceiveListener.onBitmapReceive(result);
}
}
});
}
}
public static void loadTextureBufferFiltering(int[] mFrameBuffers, int[] mFrameBufferTextures, int width, int height) {
GLES20.glGenFramebuffers(1, mFrameBuffers, 0);
GLES20.glGenTextures(1, mFrameBufferTextures, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFrameBufferTextures[0]);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffers[0]);
//Bind the texture to your FBO
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, mFrameBufferTextures[0], 0);
}
```
public static Bitmap createBitmap(int width, int height) {
IntBuffer ib = IntBuffer.allocate(width * height);
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, ib);
Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
result.copyPixelsFromBuffer(ib);
return result;
}
And where this function is placed in project?
this function I put in the class Renderer.
Sorry, but i dont know where getBitmapWithFilter and createBitmap should be use! Could you show me that? Thank you very much!
Thank you for a reply.
Below code, I have implemented.
public abstract class EffectBaseViewRenderer implements GLSurfaceView.Renderer{
public void getBitmapWithFilter(final Bitmap bitmap, final File outFile, final OnBitmapReceiveListener onBitmapReceiveListener) {
......
}
}
public abstract class EffectBase extends GLSurfaceBaseView {
private EffectViewRenderer mEffectViewRenderer;
....
public void getBitmapWithFilter(final Bitmap bitmap, final File outFile, final OnBitmapReceiveListener onBitmapReceiveListener) {
mEffectViewRenderer.getBitmapWithFilter(bitmap, outFile, receiveListener);
....
}
}
public class PlayerView extends EffectBase {
.....
}
public class ExportImage extends AsyncTask<Void, Integer, Boolean> implements EffectBaseViewRenderer.OnBitmapReceiveListener {
private EffectBase mEffectBase;
...
@Override
protected Boolean doInBackground(Void... voids) {
while (index < count) {
if (!isRunning) {
isRunning = true;
Bitmap bitmap = effectBase.getBitmap(index);
final File outFile = new File(mFolderContaining, String.format(Locale.ENGLISH, Config.IN_FRAME_FORMAT, index));
mEffectBase.getBitmapWithFilter(bitmap, outFile, this);
}
}
return null;
}
...
}
public class EditorViewBaseActivity extends BaseActivity {
private PlayerView mPlayerView;
@Override
public void onClick(final View v) {
if (v == btnExport) {
ExportImage exportImage = new ExportImage(EditorViewBaseActivity.this, mPlayerView);
exportImage.setCount(mImageFolder.getCount());
exportImage.execute();
}
}
}
// draw frame to texture
if(mFilter != null){
mFilter.onDrawFrame(mFrameBufferTextures[0], gLCubeBuffer, gLTextureBuffer);
} else {
imageInput.onDrawFrame(textureId, gLCubeBuffer, gLTextureBuffer);
}
Can two filters be superimposed?
for example
__
if(filter == null){
beautyFilter.onDrawFrame(textureId, gLCubeBuffer, gLTextureBuffer);
}else{
beautyFilter.onDrawFrame(textureId);
filter.onDrawFrame(mFrameBufferTextures[0], gLCubeBuffer, gLTextureBuffer);
}
Thank you so much! brs, Nam.