代码之家  ›  专栏  ›  技术社区  ›  Marzi Heidari

如何从GLSurfaceView获取输出位图?

  •  -1
  • Marzi Heidari  · 技术社区  · 8 年前

    我面前有android Hello Effect示例。我可以看到它如何在 android.opengl.GLSurfaceView 。全部成功完成。我想知道如何从 GLSurfaceView ? 这是代码:

       private GLSurfaceView glSurfaceView;
        private int[] mTextures = new int[2];
        private EffectContext mEffectContext;
        private Effect mEffect;
        private TextureRenderer mTexRenderer = new TextureRenderer();
        private int mImageWidth;
        private int mImageHeight;
        private boolean mInitialized = false;
        int mCurrentEffect;
    
        public void setCurrentEffect(int effect) {
            mCurrentEffect = effect;
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            /**
             * Initialize the renderer and tell it to only render when
             * explicity requested with the RENDERMODE_WHEN_DIRTY option
             */
            glSurfaceView = (GLSurfaceView) findViewById(R.id.effectsview);
            glSurfaceView.setEGLContextClientVersion(2);
            glSurfaceView.setRenderer(this);
            glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
            mCurrentEffect = R.id.none;
    
        }
    
    
    
        private void loadTextures() {
            // Generate textures
            GLES20.glGenTextures(2, mTextures, 0);
    
            // Load input bitmap
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
                    R.drawable.puppy);
            mImageWidth = bitmap.getWidth();
            mImageHeight = bitmap.getHeight();
            mTexRenderer.updateTextureSize(mImageWidth, mImageHeight);
    
            // Upload to texture
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
            // Set texture parameters
            GLToolbox.initTexParams();
        }
    
        private void initEffect() {
            EffectFactory effectFactory = mEffectContext.getFactory();
            if (mEffect != null) {
                mEffect.release();
            }
            /**
             * Initialize the correct effect based on the selected menu/action item
             */
            switch (mCurrentEffect) {
    
                case R.id.none:
                    break;
    
                case R.id.autofix:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_AUTOFIX);
                    mEffect.setParameter("scale", 0.5f);
                    break;
    
                case R.id.bw:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_BLACKWHITE);
                    mEffect.setParameter("black", .1f);
                    mEffect.setParameter("white", .7f);
                    break;
    
                case R.id.brightness:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_BRIGHTNESS);
                    mEffect.setParameter("brightness", 2.0f);
                    break;
    
                case R.id.contrast:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_CONTRAST);
                    mEffect.setParameter("contrast", 1.4f);
                    break;
    
                case R.id.crossprocess:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_CROSSPROCESS);
                    break;
    
                case R.id.documentary:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_DOCUMENTARY);
                    break;
    
                case R.id.duotone:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_DUOTONE);
                    mEffect.setParameter("first_color", Color.YELLOW);
                    mEffect.setParameter("second_color", Color.DKGRAY);
                    break;
    
                case R.id.filllight:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_FILLLIGHT);
                    mEffect.setParameter("strength", .8f);
                    break;
    
                case R.id.fisheye:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_FISHEYE);
                    mEffect.setParameter("scale", .5f);
                    break;
    
                case R.id.flipvert:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_FLIP);
                    mEffect.setParameter("vertical", true);
                    break;
    
                case R.id.fliphor:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_FLIP);
                    mEffect.setParameter("horizontal", true);
                    break;
    
                case R.id.grain:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_GRAIN);
                    mEffect.setParameter("strength", 1.0f);
                    break;
    
                case R.id.grayscale:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_GRAYSCALE);
                    break;
    
                case R.id.lomoish:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_LOMOISH);
                    break;
    
                case R.id.negative:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_NEGATIVE);
                    break;
    
                case R.id.posterize:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_POSTERIZE);
                    break;
    
                case R.id.rotate:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_ROTATE);
                    mEffect.setParameter("angle", 180);
                    break;
    
                case R.id.saturate:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_SATURATE);
                    mEffect.setParameter("scale", .5f);
                    break;
    
                case R.id.sepia:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_SEPIA);
                    break;
    
                case R.id.sharpen:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_SHARPEN);
                    break;
    
                case R.id.temperature:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_TEMPERATURE);
                    mEffect.setParameter("scale", .9f);
                    break;
    
                case R.id.tint:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_TINT);
                    mEffect.setParameter("tint", Color.MAGENTA);
                    break;
    
                case R.id.vignette:
                    mEffect = effectFactory.createEffect(
                            EffectFactory.EFFECT_VIGNETTE);
                    mEffect.setParameter("scale", .5f);
                    break;
    
                default:
                    break;
    
            }
    
        }
    
        private void applyEffect() {
            mEffect.apply(mTextures[0], mImageWidth, mImageHeight, mTextures[1]);
        }
    
        private void renderResult() {
            if (mCurrentEffect != R.id.none) {
                // if no effect is chosen, just render the original bitmap
                mTexRenderer.renderTexture(mTextures[1]);
            } else {
                // render the result of applyEffect()
                mTexRenderer.renderTexture(mTextures[0]);
            }
        }
    
        @Override
        public void onDrawFrame(GL10 gl) {
            if (!mInitialized) {
                //Only need to do this once
                mEffectContext = EffectContext.createWithCurrentGlContext();
                mTexRenderer.init();
                loadTextures();
                mInitialized = true;
            }
            if (mCurrentEffect != R.id.none) {
                //if an effect is chosen initialize it and apply it to the texture
                initEffect();
                applyEffect();
            }
            renderResult();
        }
    
        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            if (mTexRenderer != null) {
                mTexRenderer.updateViewSize(width, height);
    
            }
        }
    
        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.menu_main, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            setCurrentEffect(item.getItemId());
            glSurfaceView.requestRender();
            return true;
        }
    }
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Nikunj Paradva    5 年前

    你可以用 glReadPixels() 在完成渲染之后,但在之前 eglSwapBuffers() 被调用。您使用的是GLSurfaceView,当 onDrawFrame() 返回,所以您需要在 打开绘图框() .

    您可以在中找到一个将当前GLES帧缓冲区保存到PNG的示例 Grafika 。请参见 EglSurfaceBase#saveFrame() 方法(您可以忽略顶部的mEglCore测试)。

        2
  •  0
  •   Ismail Osunlana    3 年前

    要从glSurfaceView获取输出位图,需要使用glReadPixes()。使用glReadPixels()时,请确保从渲染器线程调用它。如果你从主线程调用,它将不起作用。下面是获取输出位图的代码。

       public Bitmap createBitmapFromGLSurface(int w, int h) {
        w = screenWidth;
        h = screenHeight;
    
    
        int bitmapBuffer[] = new int[w * h];
        int bitmapSource[] = new int[w * h];
        IntBuffer intBuffer = IntBuffer.wrap(bitmapBuffer);
        intBuffer.position(0);
        try {
    
    
            GLES20.glReadPixels(x, y, w, h, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, intBuffer);
            int offset1, offset2;
            for (int i = 0; i < h; i++) {
                offset1 = i * w;
                offset2 = (h - i - 1) * w;
                for (int j = 0; j < w; j++) {
                    int texturePixel = bitmapBuffer[offset1 + j];
                    int blue = (texturePixel >> 16) & 0xff;
                    int red = (texturePixel << 16) & 0x00ff0000;
                    int pixel = (texturePixel & 0xff00ff00) | red | blue;
                    bitmapSource[offset2 + j] = pixel;
                }
            }
        } catch (GLException e) {
            e.printStackTrace();
            return null;
        }
        return Bitmap.createBitmap(bitmapSource, w, h, Bitmap.Config.ARGB_8888);
        }