gpt4 book ai didi

android - 通过 fragment 着色器将 YUV 转换为 RGB

转载 作者:塔克拉玛干 更新时间:2023-11-02 09:05:34 25 4
gpt4 key购买 nike

我在将 Android 中的相机预览从 YUV 格式转换为 RGB 时遇到了问题。转换的目的是应用一些效果。我尝试通过 fragment 着色器进行转换,因为通过 native 代码进行的转换速度很慢(大约 14fps)。我使用的引用是 http://jyrom.tistory.com/m/post/view/id/187 .我尝试将此代码移植到 Android 平台,但结果是黑绿色矩形。但是,我可以通过我得到的输出来观察某种形式。你能帮我解决这个问题吗?我相信这是一个普遍的问题:将效果应用于相机预览。我还提供了我的测试项目的链接:https://dl.dropbox.com/u/12829395/application/FilterGL/FilterGL.zip .谢谢你。
更新:
这是我的 onPreviewFrame 方法:

public void onPreviewFrame(byte[] data, Camera camera) {
yBuffer.put(data);
yBuffer.position(0);

System.arraycopy(data, U_INDEX, uData, 0, LENGTH_4 * 2);
uBuffer.put(uData);
uBuffer.position(0);

System.arraycopy(data, V_INDEX, vData, 0, LENGTH_4);
vBuffer.put(vData);
vBuffer.position(0);
}

这就是我在 onDrawFrame 方法中将字节数组绑定(bind)到 OpenGL 纹理的方式:

    GLES20.glUniform1i(yTexture, 1);
GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE,
320, 240, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, yBuffer);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);

GLES20.glUniform1i(uTexture, 2);
GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE,
160, 120, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, uBuffer);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);

GLES20.glUniform1i(vTexture, 3);
GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE,
160, 120, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, vBuffer);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);

这是我的 fragment 着色器代码:

#ifdef GL_ES
precision highp float;
#endif

varying vec2 v_texCoord;
uniform sampler2D y_texture;
uniform sampler2D u_texture;
uniform sampler2D v_texture;

void main()
{
float nx,ny,r,g,b,y,u,v;
nx=v_texCoord.x;
ny=v_texCoord.y;
y=texture2D(y_texture,v_texCoord).r;
u=texture2D(u_texture,v_texCoord).r;
v=texture2D(v_texture,v_texCoord).r;

y=1.1643*(y-0.0625);
u=u-0.5;
v=v-0.5;

r=y+1.5958*v;
g=y-0.39173*u-0.81290*v;
b=y+2.017*u;

gl_FragColor = vec4(r,g,b,1.0);
}

最佳答案

不知道你的问题解决了吗

我用了你的代码,我在这种模式下解决了。

public class MyRenderer implements Renderer{
public static final int recWidth = Costanti.recWidth;
public static final int recHeight = Costanti.recHeight;

private static final int U_INDEX = recWidth*recHeight;
private static final int V_INDEX = recWidth*recHeight*5/4;
private static final int LENGTH = recWidth*recHeight;
private static final int LENGTH_4 = recWidth*recHeight/4;

private int previewFrameWidth = 256;
private int previewFrameHeight = 256;

private int[] yTextureNames;
private int[] uTextureNames;
private int[] vTextureNames;

private MainActivity activity;

private FloatBuffer mVertices;
private ShortBuffer mIndices;

private int mProgramObject;
private int mPositionLoc;
private int mTexCoordLoc;

private int yTexture;
private int uTexture;
private int vTexture;

private final float[] mVerticesData = { -1.f, 1.f, 0.0f, // Position 0
0.0f, 0.0f, // TexCoord 0
-1.f, -1.f, 0.0f, // Position 1
0.0f, 1.0f, // TexCoord 1
1.f, -1.f, 0.0f, // Position 2
1.0f, 1.0f, // TexCoord 2
1.f, 1.f, 0.0f, // Position 3
1.0f, 0.0f // TexCoord 3
};
private final short[] mIndicesData = { 0, 1, 2, 0, 2, 3 };

private ByteBuffer yBuffer;
private ByteBuffer uBuffer;
private ByteBuffer vBuffer;

private IntBuffer frameBuffer;
private IntBuffer renderBuffer;
private IntBuffer parameterBufferWidth;
private IntBuffer parameterBufferHeigth;

byte[] ydata = new byte[LENGTH];
byte[] uData = new byte[LENGTH_4];
byte[] vData = new byte[LENGTH_4];

public MyRenderer(MainActivity activity) {
this.activity = activity;

mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mVertices.put(mVerticesData).position(0);

mIndices = ByteBuffer.allocateDirect(mIndicesData.length * 2)
.order(ByteOrder.nativeOrder()).asShortBuffer();
mIndices.put(mIndicesData).position(0);

yBuffer = MyGraphUtils.makeByteBuffer(LENGTH);
uBuffer = MyGraphUtils.makeByteBuffer(LENGTH_4/* * 2*/);
vBuffer = MyGraphUtils.makeByteBuffer(LENGTH_4);
}

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

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Log.d("debug", "on surface created");
// Define a simple shader program for our point.
final String vShaderStr = readTextFileFromRawResource(activity, R.raw.v_simple);
final String fShaderStr = readTextFileFromRawResource(activity, R.raw.f_convert);
frameBuffer = IntBuffer.allocate(1);
renderBuffer= IntBuffer.allocate(1);

GLES20.glEnable(GLES20.GL_TEXTURE_2D);

GLES20.glGenFramebuffers(1, frameBuffer);
GLES20.glGenRenderbuffers(1, renderBuffer);
GLES20.glActiveTexture(GLES20.GL_ACTIVE_TEXTURE);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuffer.get(0));
GLES20.glClear(0);
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, renderBuffer.get(0));

GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16,
320, 240);

parameterBufferHeigth = IntBuffer.allocate(1);
parameterBufferWidth = IntBuffer.allocate(1);
GLES20.glGetRenderbufferParameteriv(GLES20.GL_RENDERBUFFER, GLES20.GL_RENDERBUFFER_WIDTH, parameterBufferWidth);
GLES20.glGetRenderbufferParameteriv(GLES20.GL_RENDERBUFFER, GLES20.GL_RENDERBUFFER_HEIGHT, parameterBufferHeigth);
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_RENDERBUFFER, renderBuffer.get(0));
if (GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER)!=GLES20.GL_FRAMEBUFFER_COMPLETE){
Log.d("debug", "gl frame buffer status != frame buffer complete");
}
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GLES20.glClear(0);

mProgramObject = loadProgram(vShaderStr, fShaderStr);

// Get the attribute locations
mPositionLoc = GLES20.glGetAttribLocation(mProgramObject, "a_position");
mTexCoordLoc = GLES20.glGetAttribLocation(mProgramObject, "a_texCoord");

GLES20.glEnable(GLES20.GL_TEXTURE_2D);
yTexture = GLES20.glGetUniformLocation(mProgramObject, "y_texture");
yTextureNames = new int[1];
GLES20.glGenTextures(1, yTextureNames, 0);
int yTextureName = yTextureNames[0];

GLES20.glEnable(GLES20.GL_TEXTURE_2D);
uTexture = GLES20.glGetUniformLocation(mProgramObject, "u_texture");
uTextureNames = new int[1];
GLES20.glGenTextures(1, uTextureNames, 0);
int uTextureName = uTextureNames[0];

GLES20.glEnable(GLES20.GL_TEXTURE_2D);
vTexture = GLES20.glGetUniformLocation(mProgramObject, "v_texture");
vTextureNames = new int[1];
GLES20.glGenTextures(1, vTextureNames, 0);
int vTextureName = vTextureNames[0];

GLES20.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
}

@Override
public final void onDrawFrame(GL10 gl) {
Log.d("debug", "on Draw frame");
// Clear the color buffer
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

// Use the program object
GLES20.glUseProgram(mProgramObject);

// Load the vertex position
mVertices.position(0);
GLES20.glVertexAttribPointer(mPositionLoc, 3, GLES20.GL_FLOAT, false, 5*4, mVertices);
// Load the texture coordinate
mVertices.position(3);
GLES20.glVertexAttribPointer(mTexCoordLoc, 2, GLES20.GL_FLOAT, false, 5*4, mVertices);

GLES20.glEnableVertexAttribArray(mPositionLoc);
GLES20.glEnableVertexAttribArray(mTexCoordLoc);

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, yTextureNames[0]);
GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE,
320, 240, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, yBuffer);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_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.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, yTextureNames[0]);
GLES20.glUniform1i(yTexture, 0);

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, uTextureNames[0]);
GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE,
160, 120, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, uBuffer);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_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.glActiveTexture(GLES20.GL_TEXTURE1+2);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, uTextureNames[0]);
GLES20.glUniform1i(uTexture, 2);

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, vTextureNames[0]);
GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE,
160, 120, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, vBuffer);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_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.glActiveTexture(GLES20.GL_TEXTURE1+1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, vTextureNames[0]);
GLES20.glUniform1i(vTexture, 1);

GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, mIndices);
}



public void setPreviewFrameSize(int realWidth, int realHeight) {
previewFrameHeight = realHeight;
previewFrameWidth = realWidth;
}

public static String readTextFileFromRawResource(final Context context, final int resourceId) {
final InputStream inputStream = context.getResources().openRawResource(resourceId);
final InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
final BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

String nextLine;
final StringBuilder body = new StringBuilder();

try {
while ((nextLine = bufferedReader.readLine()) != null) {
body.append(nextLine);
body.append('\n');
}
} catch (IOException e) {
return null;
}

return body.toString();
}

public static int loadShader(int type, String shaderSrc) {
int shader;
int[] compiled = new int[1];

// Create the shader object
shader = GLES20.glCreateShader(type);
if (shader == 0) {
return 0;
}
// Load the shader source
GLES20.glShaderSource(shader, shaderSrc);
// Compile the shader
GLES20.glCompileShader(shader);
// Check the compile status
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);

if (compiled[0] == 0) {
Log.e("ESShader", GLES20.glGetShaderInfoLog(shader));
GLES20.glDeleteShader(shader);
return 0;
}
return shader;
}

public static int loadProgram(String vertShaderSrc, String fragShaderSrc) {
int vertexShader;
int fragmentShader;
int programObject;
int[] linked = new int[1];

// Load the vertex/fragment shaders
vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertShaderSrc);
if (vertexShader == 0) {
return 0;
}

fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragShaderSrc);
if (fragmentShader == 0) {
GLES20.glDeleteShader(vertexShader);
return 0;
}

// Create the program object
programObject = GLES20.glCreateProgram();

if (programObject == 0) {
return 0;
}

GLES20.glAttachShader(programObject, vertexShader);
GLES20.glAttachShader(programObject, fragmentShader);

// Link the program
GLES20.glLinkProgram(programObject);

// Check the link status
GLES20.glGetProgramiv(programObject, GLES20.GL_LINK_STATUS, linked, 0);

if (linked[0] == 0) {
Log.e("ESShader", "Error linking program:");
Log.e("ESShader", GLES20.glGetProgramInfoLog(programObject));
GLES20.glDeleteProgram(programObject);
return 0;
}

// Free up no longer needed shader resources
GLES20.glDeleteShader(vertexShader);
GLES20.glDeleteShader(fragmentShader);

return programObject;
}

@Override
public void onPreviewFrame(byte[] data, Camera camera) {

System.arraycopy(data, 0, ydata, 0, LENGTH);
yBuffer.put(ydata);
yBuffer.position(0);

System.arraycopy(data, U_INDEX, uData, 0, LENGTH_4);
uBuffer.put(uData);
uBuffer.position(0);

System.arraycopy(data, V_INDEX, vData, 0, LENGTH_4);
vBuffer.put(vData);
vBuffer.position(0);
}

关于android - 通过 fragment 着色器将 YUV 转换为 RGB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12130790/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com