2017-01-09 10 views
0

OpenGL ES 2.0のフラグメントシェーダでイメージの輝度、コントラスト、彩度を変更しました。そして...修正した画像を保存するには、私はこの方法を使用しました。glDrawElementsを呼び出した後、FrameBufferからglReadPixelsを使ってレンダリングされたイメージを取得する方法

public static Bitmap saveTexture(int texture, int width, int height) { 
    int[] frame = new int[1]; 
    GLES20.glGenFramebuffers(1, frame, 0); 
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frame[0]); 
    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texture, 0); 

    ByteBuffer buffer = ByteBuffer.allocate(width * height * 4); 
    GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buffer); 
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 
    bitmap.copyPixelsFromBuffer(buffer); 

    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 
    GLES20.glDeleteFramebuffers(1, frame, 0); 

    return bitmap; 
} 

ただし、このメソッドは元の画像を返しますが、変更されません。なにが問題ですか? 解決方法を教えてください。 :/


さらに詳しい情報を追加しました。 このコードは私のGLSurfaceView.Rendererのコードです。

@Override 
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) { 
    mTextureID = OpenGLTools.loadImageTexture(mBitmap, true); 
    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 
    mProgram = OpenGLTools.loadProgram(VERTEX_SHADER, FRAGMENT_SHADER); 
} 

@Override 
public void onSurfaceChanged(GL10 gl10, int width, int height) { 
    GLES20.glViewport(0, 0, width, height); 
} 

@Override 
public void onDrawFrame(GL10 gl10) { 
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 
    draw(); 
} 

public void draw() { 
    if (!GLES20.glIsProgram(mProgram)) OpenGLTools.loadProgram(VERTEX_SHADER, FRAGMENT_SHADER); 
    GLES20.glUseProgram(mProgram); 

    int positionHandle = GLES20.glGetAttribLocation(mProgram, "position"); 
    GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, mVertexBuffer); 
    GLES20.glEnableVertexAttribArray(positionHandle); 

    int textureCoordinateHandle = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate"); 
    GLES20.glVertexAttribPointer(textureCoordinateHandle, 2, GLES20.GL_FLOAT, false, 0, mTexCoordBuffer); 
    GLES20.glEnableVertexAttribArray(textureCoordinateHandle); 

    int brightness = GLES20.glGetUniformLocation(mProgram, "brightness"); 
    GLES20.glUniform1f(brightness, mEditParams.mBrightness/200.0f); 
    int contrast = GLES20.glGetUniformLocation(mProgram, "contrast"); 
    GLES20.glUniform1f(contrast, mEditParams.mContrast/200.0f); 
    int saturation = GLES20.glGetUniformLocation(mProgram, "saturation"); 
    GLES20.glUniform1f(saturation, (mEditParams.mSaturation + 100)/100.0f); 

    GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, mDrawListBuffer); 

    GLES20.glDisableVertexAttribArray(positionHandle); 
    GLES20.glDisableVertexAttribArray(textureCoordinateHandle); 
} 

public Bitmap getBitmap() { 
    return OpenGLTools.saveTexture(mTextureID, mBitmap.getWidth(), mBitmap.getHeight()); 
} 

...これはOpenGLToolsクラスのコードです。

public static int loadImageTexture(final Bitmap bitmap, final boolean recycle) { 
    int[] textureNames = new int[1]; 
    GLES20.glGenTextures(1, textureNames, 0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureNames[0]); 
    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 

    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 

    if (recycle) { 
     bitmap.recycle(); 
    } 

    return textureNames[0]; 
} 

public static int loadProgram(final String vsc, final String fsc) { 
    int[] success = new int[1]; 

    int vshader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); 
    GLES20.glShaderSource(vshader, vsc); 
    GLES20.glCompileShader(vshader); 
    GLES20.glGetShaderiv(vshader, GLES20.GL_COMPILE_STATUS, success, 0); 

    if (success[0] == 0) { 
     Log.e("CheckLog", "Could not compile vertex shader : " + GLES20.glGetShaderInfoLog(vshader)); 
     GLES20.glDeleteShader(vshader); 
     return 0; 
    } 

    int fshader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); 
    GLES20.glShaderSource(fshader, fsc); 
    GLES20.glCompileShader(fshader); 
    GLES20.glGetShaderiv(fshader, GLES20.GL_COMPILE_STATUS, success, 0); 
    if (success[0] == 0) { 
     Log.e("CheckLog", "Could not compile fragment shader : " + GLES20.glGetShaderInfoLog(fshader)); 
     GLES20.glDeleteShader(fshader); 
     return 0; 
    } 

    int program = GLES20.glCreateProgram(); 
    GLES20.glAttachShader(program, vshader); 
    GLES20.glAttachShader(program, fshader); 
    GLES20.glLinkProgram(program); 
    GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, success, 0); 
    if (success[0] <= 0) { 
     Log.e("CheckLog", "Could not link OpenGLES program :" + GLES20.glGetProgramInfoLog(program)); 
     GLES20.glDeleteProgram(program); 
     return 0; 
    } else { 
     Log.i("CheckLog", "Linked OpenGLES program"); 
    } 

    return program; 
} 

public static Bitmap saveTexture(int texture, int width, int height) { 
    int[] frame = new int[1]; 
    GLES20.glGenFramebuffers(1, frame, 0); 
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frame[0]); 
    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texture, 0); 

    ByteBuffer buffer = ByteBuffer.allocate(width * height * 4); 
    GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buffer); 
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 
    bitmap.copyPixelsFromBuffer(buffer); 

    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 
    GLES20.glDeleteFramebuffers(1, frame, 0); 

    return bitmap; 
} 

私は保存ボタンをタッチすると

は、 getBitmap方法はOpenGLESコンテキストで呼ばれています。 Bitmapのパラメータ(明るさ、コントラスト、彩度)を変更することができ、リアルタイムで表示されます。ただし、保存ボタンをタッチすると、変更されたパラメータは保存された画像に適用されません。私は変更されたパラメータで画像を保存したい。

+0

関連するコードを投稿できますか?何かを保存しても上記のコードがうまくいけば間違った入力をしているだけなので、エラーは上のコードにはありません。 – solidpixel

+0

関連コードを追加しました。それを確認してください。 –

答えて

0

オリジナルのテクスチャハンドルをtextureのパラメータ入力としてsaveTexture()に渡すので、それがディスクに保存するデータであることは驚くことではありません。

実際には、アクティブなフレームバッファの内容を保存したいテクスチャを保存する必要はありません。そのため、関数はコードに必要なものではありません。これを試してみてください:

public static Bitmap saveTexture(int width, int height) { 
    ByteBuffer buffer = ByteBuffer.allocate(width * height * 4); 
    GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buffer); 
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 
    bitmap.copyPixelsFromBuffer(buffer);  
    return bitmap; 
} 
+0

コードは正常に動作します。しかし、別の問題があります。アクティブフレームバッファからのイメージは、デフォルトのフレームバッファ(アクティブフレームバッファ)が表示解像度よりも大きくないため、黒いイメージ全体の角に小さな解像度で配置されています。だから、私は、デフォルトのフレームバッファの代わりに大きなフレームバッファに結果イメージをレンダリングする方法を知る必要があると思います。あなたがそれを知っているなら、教えてください。とにかくありがとう。 –

+0

スクリーンよりも大きなものをレンダリングする必要がある場合は、オフスクリーンのフレームバッファーにレンダリングする必要があります。 – solidpixel

関連する問題