![](/img/trans.png)
[英]Image Bitmap gets rotated when loaded from camera/gallery [Android 9]
[英]Android: How to change OpenGLES texture data / bitmap from gallery / camera
我嘗試重用Android 媒體效果示例,並希望能夠使用來自相機或圖庫選擇的新位圖更改紋理數據。 目前沒有解決辦法
這是示例的初始加載紋理: https : //github.com/googlesamples/android-MediaEffects/blob/master/Application/src/main/java/com/example/android/mediaeffects/MediaEffectsFragment.java
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();
}
這是我的麻煩功能:
public void changeBackground(Uri bitmapUri) {
Log.d(TAG, "changeBackground : " + bitmapUri.getPath());
Bitmap bitmap = BitmapFactory.decodeFile(bitmapUri.getPath());
mImageWidth = bitmap.getWidth();
mImageHeight = bitmap.getHeight();
mTexRenderer.updateTextureSize(mImageWidth, mImageHeight);
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, bitmap);
theBackground.requestRender(); //my GLSurfaceView
bitmap.recycle();
}
我嘗試了幾種方法:
僅使用 texSubImage2D -> 紋理未更新
刪除並使用新位圖重新創建紋理 -> 黑色紋理
注意:位圖尺寸是固定的,為 1080 x 1080
如何使用新位圖更改/修改/替換紋理數據?
更新:
我認為這個問題與這個問題更相關: 使用照片庫中的圖像在 3D 對象上設置紋理。 我從畫廊意圖抓取圖像后調用 changeBackground() 然后裁剪它(另一個意圖)。
現在,如何使用畫廊意圖中的位圖有效地更改紋理數據? 有人有線索嗎?
解決了
我通過將紋理加載過程推遲到 onSurfaceChange() 函數解決了這個問題。 只需使用一個標志來指示要加載的文件,然后 onSurfaceChange 再次檢查該標志。
private Uri mFileToLoad = null; public void changeBackground(Uri bitmapUri) { Log.d(TAG, "changeBackground : " + bitmapUri.getPath()); mFileToLoad = bitmapUri; theBackground.requestRender(); }
和我的 onSurfaceChange()
public void onSurfaceChanged(GL10 gl, int width, int height) { Log.d(TAG, "onSurfaceChanged w:" + width + " h:" + height); if (mFileToLoad!=null) { GLES20.glDeleteTextures(mTextures.length, mTextures, 0); GLES20.glGenTextures(mTextures.length, mTextures, 0); Bitmap bitmap = BitmapFactory.decodeFile(mFileToLoad.getPath()); 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(); mFileToLoad = null; bitmap.recycle(); } if (mTexRenderer != null) { mTexRenderer.updateViewSize(width, height); } }
到目前為止它有效。
看起來您的changeBackground()
方法可能是從 UI 線程調用的,或者至少是從渲染線程以外的線程調用的。
GLSurfaceView
創建一個單獨的渲染線程,當你的渲染方法被調用時,它有一個當前的 OpenGL 上下文。 因此,它已為您的 OpenGL 調用做好了准備。 對於所有其他線程,情況並非如此。 當前的 OpenGL 上下文是每個線程的。 因此,除非您對此采取一些措施(這是可能的,但會增加顯着的復雜性),否則您無法從其他線程進行 OpenGL 調用。
有幾個選項可以解決這個問題。 最簡單的一個可能是使用queueEvent()
的方法GLSurfaceView
,它允許你在一個通過Runnable
,將在渲染線程中執行。
我不確定代碼中的mTexRenderer.updateTextureSize()
方法是做什么的。 但通常,如果紋理大小發生變化,則必須使用GLUtils.texImage2D()
而不是GLUtils.texSubImage2D()
來更新紋理。
代碼可能如下所示(未經測試,因此可能無法完全按照輸入的方式工作):
final Bitmap bitmap = BitmapFactory.decodeFile(bitmapUri.getPath());
theBackground.queueEvent(new Runnable() {
@Override
void run() {
mImageWidth = bitmap.getWidth();
mImageHeight = bitmap.getHeight();
mTexRenderer.updateTextureSize(mImageWidth, mImageHeight);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
});
theBackground.requestRender();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.