glTexImage2D的android位图像素格式
我正在尝试从Java和Bitmap类加载要与NDK OpenGL一起使用的纹理。它可以工作,但我的像素格式有问题 首先,在Java中,我从assets文件夹加载位图,如下所示:glTexImage2D的android位图像素格式,android,opengl-es,bitmap,java-native-interface,textures,Android,Opengl Es,Bitmap,Java Native Interface,Textures,我正在尝试从Java和Bitmap类加载要与NDK OpenGL一起使用的纹理。它可以工作,但我的像素格式有问题 首先,在Java中,我从assets文件夹加载位图,如下所示: Bitmap bitmap = BitmapFactory.decodeStream(amgr.open(path)); return bitmap.copy(Bitmap.Config.ARGB_8888, false); 位图配置没有RGBA通道顺序选项 [JNI在这里发生的事情] 然后使用GLES 1缓冲纹理,如
Bitmap bitmap = BitmapFactory.decodeStream(amgr.open(path));
return bitmap.copy(Bitmap.Config.ARGB_8888, false);
位图配置没有RGBA通道顺序选项
[JNI在这里发生的事情]
然后使用GLES 1缓冲纹理,如下所示:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// `pixels` is the pixel buffer I produced earlier.
如您所见,像素格式存在问题glTexImage2D
没有ARGB选项,但是Java位图类没有在RGBA中创建缓冲区的选项。所以我的颜色通道被弄乱了。顺便说一下,我需要阿尔法通道
问题是:如何最有效地从Java位图类生成RGBA888格式的像素缓冲区,或者如何加载argb888格式的GL纹理
除了手动逐像素交换字节之外,肯定还有其他方法吗
我目前正在这样做:
void pxl::swap_channels_ARGB_to_RGBA(void *pixBuf, const int len)
{
jint *pixels = (jint *)pixBuf;
for(int i = 0; i < len; i++)
{
jint pixel = pixels[i];
jint a = (pixel >> 24) & 0xFF;
jint r = (pixel >> 16) & 0xFF;
jint g = (pixel >> 8) & 0xFF;
jint b = (pixel >> 0) & 0xFF;
pixels[i] = (jint)(a | (r << 24 ) | (g << 16) | (b << 8));
}
}
void pxl::将信道ARGB交换到RGBA(void*pixBuf,const int len)
{
jint*像素=(jint*)pixBuf;
对于(int i=0;i>24)&0xFF;
jint r=(像素>>16)&0xFF;
jint g=(像素>>8)&0xFF;
jint b=(像素>>0)&0xFF;
像素[i]=(jint)(a |)(r我认为没有办法做到这一点,但你可以用这个优化你的算法
void pxl::swap_channels_ARGB_to_RGBA(void *pixBuf, const int len) {
jint *pixels = (jint *)pixBuf;
for(int i = 0; i < len; i++) {
unsigned int aux = (int)pixels[i];
pixels[i] = (aux << 8) | (aux >> 24);
}
}
void pxl::将信道ARGB交换到RGBA(void*pixBuf,const int len){
jint*像素=(jint*)pixBuf;
对于(int i=0;i24);
}
}
此问题无法在OpenGL ES 1.1中解决,但可以在OpenGL ES 3.0中或通过OpenGL扩展解决:
自OpenGL ES 3.0以来,您可以使用纹理swizzle参数交换颜色通道。请参阅:
GL\u纹理\u SWIZZLE\R
设置在返回着色器之前将应用于纹理的r分量的旋转。参数的有效值为GL_RED
,GL_GREEN
,GL_BLUE
,GL_ALPHA
,GL_ZERO
和GL_ONE
。如果GL_TEXTURE_旋转
为GL_RED
,则r wi的值如果GL\u TEXTURE\u SWIZZLE\u R
为GL\u GREEN
,则R的值将从提取纹理的第二个通道中获取
这意味着,当您将以下纹理参数设置到纹理对象时,在查找纹理时,颜色通道将被交换:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_GREEN);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_ALPHA);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
有关本规范的相关部分,请访问
要检查OpenGL扩展是否有效,可以使用,它将返回以空格分隔的受支持扩展列表
另一种完全不同的解决方案是使用A进行转换。在画布上绘制,然后使用画布上保留的目标位图。
我在GitHub上找到了此解决方案:
你需要在JNI侧上进行GLTEXIGE2D调用吗?或者你可以使用GLUTILL。TXGIVEGE2D在java端上传它,然后把纹理ID作为一个int通过JNI。谢谢,但是我想把C++中的所有GL东西都保留下来。它对我来说是手动交换的,我只是好奇如果有一个更优雅的解决方案。我很好奇。o、 因为不做任何交换,但它可以工作。它通过将位图对象作为jobject传递给JNI并调用getPixels()。检查util_texImage2D函数。能否显示在传递给JNI之前如何从位图提取数据?是否使用getPixels()或copyPixelsToBuffer()?
public static Bitmap convert(Bitmap bitmap, Bitmap.Config config) {
Bitmap convertedBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), config);
Canvas canvas = new Canvas(convertedBitmap);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
canvas.drawBitmap(bitmap, 0, 0, paint);
return convertedBitmap;
}