Commit b54be368 authored by zhaozl's avatar zhaozl

feature: Save Y Plane.

parent e76b742e
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AppInsightsSettings">
<option name="selectedTabId" value="Android Vitals" />
</component>
</project>
\ No newline at end of file
...@@ -7,9 +7,13 @@ uniform sampler2D sTexture; ...@@ -7,9 +7,13 @@ uniform sampler2D sTexture;
uniform float uWidth; uniform float uWidth;
uniform float uHeight; uniform float uHeight;
/**
*
*/
float cY(float x, float y) { float cY(float x, float y) {
vec4 c = texture2D(sTexture, vec2(x, y)); vec4 c = texture2D(sTexture, vec2(x, y));
return c.r * 0.257 + c.g * 0.504 + c.b * 0.098 + 0.0625; // return c.r * 0.257 + c.g * 0.504 + c.b * 0.098 + 0.0625;
return 0.299 * c.r + 0.587 * c.g + 0.114 * c.b;
} }
vec4 cC(float x, float y, float dx, float dy) { vec4 cC(float x, float y, float dx, float dy) {
...@@ -22,22 +26,50 @@ vec4 cC(float x, float y, float dx, float dy) { ...@@ -22,22 +26,50 @@ vec4 cC(float x, float y, float dx, float dy) {
float cU(float x, float y, float dx, float dy) { float cU(float x, float y, float dx, float dy) {
vec4 c = cC(x, y, dx, dy); vec4 c = cC(x, y, dx, dy);
return -0.148 * c.r - 0.291 * c.g + 0.439 * c.b + 0.5000; // return -0.148 * c.r - 0.291 * c.g + 0.439 * c.b + 0.5000;
return -0.14713 * c.r - 0.28886 * c.g + 0.436 * c.b;
} }
float cV(float x, float y, float dx, float dy) { float cV(float x, float y, float dx, float dy) {
vec4 c = cC(x, y, dx, dy); vec4 c = cC(x, y, dx, dy);
return 0.439 * c.r - 0.368 * c.g - 0.071 * c.b + 0.5000; // return 0.439 * c.r - 0.368 * c.g - 0.071 * c.b + 0.5000;
return 0.615 * c.r - 0.51499 * c.g - 0.10001 * c.b;
} }
vec2 cPos(float t, float shiftx, float gy) { vec2 cPos(float t, float shiftx, float gy) {
/**
* 根据纹理坐标[x, gy]算出像素坐标pos[x, y]
* 像素坐标取值范围[1920, 1080]
* 输入: x[0, 1] gy[0, 0.25)
* 输出: x[0, 1920] y[0, 270)
*
*/
vec2 pos = vec2(floor(uWidth * vTextureCoord.x), floor(uHeight * gy)); vec2 pos = vec2(floor(uWidth * vTextureCoord.x), floor(uHeight * gy));
// 根据像素坐标计算出
/**
* 输入: x[0, 1920] y[0, 270)
* 输出: x[0, 1920] y[0, 1080)
* [0, 0]=>[0, 0]; [1, 0]=>[4, 0]; [2, 0]=>[8, 0]; ...;[479, 0]=>[1916, 0]; [480, 0]=>[0, 1]??; [481, 0]=>[4, 1];...;
* [1919, 0]=>[1916, 3]; [1920, 0]=>[0, 4]??
*
* [0, 1]=>[0, 4]; [1, 1]=>[4, 4];
*/
return vec2(mod(pos.x * shiftx, uWidth), (pos.y * shiftx + floor(pos.x * shiftx / uWidth)) * t); return vec2(mod(pos.x * shiftx, uWidth), (pos.y * shiftx + floor(pos.x * shiftx / uWidth)) * t);
} }
/**
* x: [0, 1]
* y: [0.625, 0.875)
* 总共计算:x计算1920次,y计算270次,总共1920 * 270次,意味着一次取4个像素计算4个Y
*/
vec4 calculateY() { vec4 calculateY() {
/**
* x: [0, 1]
* y: [0, 0.25)
*/
vec2 pos = cPos(1., 4., vTextureCoord.y - 0.625); vec2 pos = cPos(1., 4., vTextureCoord.y - 0.625);
vec4 oColor = vec4(0); vec4 oColor = vec4(0);
// 将像素坐标转成纹理坐标
float textureYPos = pos.y / uHeight; float textureYPos = pos.y / uHeight;
oColor[0] = cY(pos.x / uWidth, textureYPos); oColor[0] = cY(pos.x / uWidth, textureYPos);
oColor[1] = cY((pos.x + 1.) / uWidth, textureYPos); oColor[1] = cY((pos.x + 1.) / uWidth, textureYPos);
...@@ -86,6 +118,7 @@ vec4 calculateVU(float dx, float dy) { ...@@ -86,6 +118,7 @@ vec4 calculateVU(float dx, float dy) {
return oColor; return oColor;
} }
void main() { void main() {
if (vTextureCoord.x >= 0. && vTextureCoord.x < 1.) {
if (vTextureCoord.y >= 0.625 && vTextureCoord.y < 0.875) { if (vTextureCoord.y >= 0.625 && vTextureCoord.y < 0.875) {
gl_FragColor = calculateY(); gl_FragColor = calculateY();
} else if (vTextureCoord.y >= 0.875) { } else if (vTextureCoord.y >= 0.875) {
...@@ -93,4 +126,14 @@ void main() { ...@@ -93,4 +126,14 @@ void main() {
} else { } else {
gl_FragColor = vec4(0, 0, 0, 0); gl_FragColor = vec4(0, 0, 0, 0);
} }
} else {
gl_FragColor = vec4(0, 0, 0, 0);
}
// if (vTextureCoord.y >= 0.625 && vTextureCoord.y < 0.875) {
// gl_FragColor = calculateY();
// } else if (vTextureCoord.y >= 0.875) {
// gl_FragColor = calculateVU(1. / uWidth, 1. / uHeight);
// } else {
// gl_FragColor = vec4(0, 0, 0, 0);
// }
} }
\ No newline at end of file
precision highp float;
precision highp int;
varying vec2 vTextureCoord;
uniform sampler2D sTexture;
uniform float uWidth;
uniform float uHeight;
/**
*
*/
float cY(float x, float y) {
vec4 c = texture2D(sTexture, vec2(x, y));
return c.r * 0.257 + c.g * 0.504 + c.b * 0.098 + 0.0625;
}
vec4 cC(float x, float y, float dx, float dy) {
vec4 c0 = texture2D(sTexture, vec2(x, y));
vec4 c1 = texture2D(sTexture, vec2(x + dx, y));
vec4 c2 = texture2D(sTexture, vec2(x, y + dy));
vec4 c3 = texture2D(sTexture, vec2(x + dx, y + dy));
return (c0 + c1 + c2 + c3) / 4.;
}
float cU(float x, float y, float dx, float dy) {
vec4 c = cC(x, y, dx, dy);
return -0.148 * c.r - 0.291 * c.g + 0.439 * c.b + 0.5000;
}
float cV(float x, float y, float dx, float dy) {
vec4 c = cC(x, y, dx, dy);
return 0.439 * c.r - 0.368 * c.g - 0.071 * c.b + 0.5000;
}
vec2 cPos(float t, float shiftx, float gy) {
/**
* 根据[x, gy]算出像素坐标pos[x, y]
* pos取值范围[1920, 1080]
* 输入: x[0, 1] gy[0, 0.25)
* 输出: x[0, 1920] y[0, 270)
*
*/
vec2 pos = vec2(floor(uWidth * vTextureCoord.x), floor(uHeight * gy));
// 根据像素坐标计算出
/**
* 输入: x[0, 1920] y[0, 270)
* 输出: x[0, 1920] y[0, 1080)
* [0, 0]=>[0, 0]; [1, 0]=>[4, 0]; [2, 0]=>[8, 0]; ...;[479, 0]=>[1916, 0]; [480, 0]=>[0, 1]??; [481, 0]=>[4, 1];...;
* [1919, 0]=>[1916, 3]; [1920, 0]=>[0, 4]??
*
* [0, 1]=>[0, 4]; [1, 1]=>[4, 4];
*/
return vec2(mod(pos.x * shiftx, uWidth), (pos.y * shiftx + floor(pos.x * shiftx / uWidth)) * t);
}
/**
* x: [0, 1]
* y: [0.625, 0.875)
* 总共计算:x计算1920次,y计算270次,总共1920 * 270次,意味着一次取4个像素计算4个Y
*/
vec4 calculateY() {
/**
* x: [0, 1]
* y: [0, 0.25)
*/
vec2 pos = cPos(1., 4., vTextureCoord.y - 0.625);
vec4 oColor = vec4(0);
// 将像素坐标转成纹理坐标
float textureYPos = pos.y / uHeight;
oColor[0] = cY(pos.x / uWidth, textureYPos);
oColor[1] = cY((pos.x + 1.) / uWidth, textureYPos);
oColor[2] = cY((pos.x + 2.) / uWidth, textureYPos);
oColor[3] = cY((pos.x + 3.) / uWidth, textureYPos);
return oColor;
}
vec4 calculateU(float gy, float dx, float dy) {
vec2 pos = cPos(2., 8., vTextureCoord.y - gy);
vec4 oColor = vec4(0);
float textureYPos = pos.y / uHeight;
oColor[0] = cU(pos.x / uWidth, textureYPos, dx, dy);
oColor[1] = cU((pos.x + 2.) / uWidth, textureYPos, dx, dy);
oColor[2] = cU((pos.x + 4.) / uWidth, textureYPos, dx, dy);
oColor[3] = cU((pos.x + 6.) / uWidth, textureYPos, dx, dy);
return oColor;
}
vec4 calculateV(float gy, float dx, float dy) {
vec2 pos = cPos(2., 8., vTextureCoord.y - gy);
vec4 oColor = vec4(0);
float textureYPos = pos.y / uHeight;
oColor[0] = cV(pos.x / uWidth, textureYPos, dx, dy);
oColor[1] = cV((pos.x + 2.) / uWidth, textureYPos, dx, dy);
oColor[2] = cV((pos.x + 4.) / uWidth, textureYPos, dx, dy);
oColor[3] = cV((pos.x + 6.) / uWidth, textureYPos, dx, dy);
return oColor;
}
vec4 calculateUV(float dx, float dy) {
vec2 pos = cPos(2., 4., vTextureCoord.y - 0.2500);
vec4 oColor = vec4(0);
float textureYPos = pos.y / uHeight;
oColor[0] = cU(pos.x / uWidth, textureYPos, dx, dy);
oColor[1] = cV(pos.x / uWidth, textureYPos, dx, dy);
oColor[2] = cU((pos.x + 2.) / uWidth, textureYPos, dx, dy);
oColor[3] = cV((pos.x + 2.) / uWidth, textureYPos, dx, dy);
return oColor;
}
vec4 calculateVU(float dx, float dy) {
vec2 pos = cPos(2., 4., vTextureCoord.y - 0.875);
vec4 oColor = vec4(0);
float textureYPos = pos.y / uHeight;
oColor[0] = cV(pos.x / uWidth, textureYPos, dx, dy);
oColor[1] = cU(pos.x / uWidth, textureYPos, dx, dy);
oColor[2] = cV((pos.x + 2.) / uWidth, textureYPos, dx, dy);
oColor[3] = cU((pos.x + 2.) / uWidth, textureYPos, dx, dy);
return oColor;
}
void main() {
if (vTextureCoord.x >= 0. && vTextureCoord.x < 1.) {
if (vTextureCoord.y >= 0.625 && vTextureCoord.y < 0.875) {
gl_FragColor = calculateY();
} else if (vTextureCoord.y >= 0.875) {
gl_FragColor = calculateVU(1. / uWidth, 1. / uHeight);
} else {
gl_FragColor = vec4(0, 0, 0, 0);
}
} else {
gl_FragColor = vec4(0, 0, 0, 0);
}
// if (vTextureCoord.y >= 0.625 && vTextureCoord.y < 0.875) {
// gl_FragColor = calculateY();
// } else if (vTextureCoord.y >= 0.875) {
// gl_FragColor = calculateVU(1. / uWidth, 1. / uHeight);
// } else {
// gl_FragColor = vec4(0, 0, 0, 0);
// }
}
\ No newline at end of file
...@@ -117,8 +117,8 @@ public class ImageRenderer implements GLSurfaceView.Renderer { ...@@ -117,8 +117,8 @@ public class ImageRenderer implements GLSurfaceView.Renderer {
if (muMVPMatrixHandle == -1) { if (muMVPMatrixHandle == -1) {
throw new RuntimeException("Could not get attrib location for uCRatio"); throw new RuntimeException("Could not get attrib location for uCRatio");
} }
ByteBuffer imageBuffer = loadBytesFromAssets("image/fish.rgba");
createTexture(); mTextureID = createTexture(imageBuffer);
createFrameBuffer(); createFrameBuffer();
Log.v(TAG, "mVMatrix 1: " + Arrays.toString(mVMatrix)); Log.v(TAG, "mVMatrix 1: " + Arrays.toString(mVMatrix));
Matrix.setLookAtM(mVMatrix, 0, Matrix.setLookAtM(mVMatrix, 0,
...@@ -139,12 +139,14 @@ public class ImageRenderer implements GLSurfaceView.Renderer { ...@@ -139,12 +139,14 @@ public class ImageRenderer implements GLSurfaceView.Renderer {
renderTexture(); renderTexture();
mPixelBuffer.clear();
GLES20.glReadPixels(0, 0, mWidth, mHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mPixelBuffer); GLES20.glReadPixels(0, 0, mWidth, mHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mPixelBuffer);
checkGlError("glReadPixels"); checkGlError("glReadPixels");
mPixelBuffer.rewind(); mPixelBuffer.rewind();
mPixelBuffer.position(Y_SIZE / 2);
mPixelBuffer.get(mImageBytes); mPixelBuffer.get(mImageBytes);
saveImage(mImageBytes, "nv21"); saveImage(mImageBytes, "gray");
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
checkGlError("glBindFramebuffer 0"); checkGlError("glBindFramebuffer 0");
...@@ -202,20 +204,16 @@ public class ImageRenderer implements GLSurfaceView.Renderer { ...@@ -202,20 +204,16 @@ public class ImageRenderer implements GLSurfaceView.Renderer {
checkGlError("glDrawArrays"); checkGlError("glDrawArrays");
} }
private void createTexture() { private int createTexture(ByteBuffer buffer) {
ByteBuffer imageBuffer = loadBytesFromAssets("image/fish.rgba");
// 创建纹理 // 创建纹理
int[] textures = new int[1]; int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0); GLES20.glGenTextures(1, textures, 0);
mTextureID = textures[0];
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
checkGlError("glBindTexture mTextureID"); checkGlError("glBindTexture textures");
// GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap, 0); GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, mWidth, mHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buffer);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, mWidth, mHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, imageBuffer); checkGlError("texImage2D textures");
checkGlError("texImage2D mTextureID");
// Can't do mipmapping with camera source // Can't do mipmapping with camera source
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
...@@ -227,8 +225,12 @@ public class ImageRenderer implements GLSurfaceView.Renderer { ...@@ -227,8 +225,12 @@ public class ImageRenderer implements GLSurfaceView.Renderer {
GLES20.GL_CLAMP_TO_EDGE); GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
GLES20.GL_CLAMP_TO_EDGE); GLES20.GL_CLAMP_TO_EDGE);
checkGlError("glTexParameteri mTextureID: " + mTextureID); checkGlError("glTexParameteri textures: " + textures[0]);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
checkGlError("glBindTexture 0");
return textures[0];
} }
private void createFrameBuffer() { private void createFrameBuffer() {
...@@ -242,16 +244,19 @@ public class ImageRenderer implements GLSurfaceView.Renderer { ...@@ -242,16 +244,19 @@ public class ImageRenderer implements GLSurfaceView.Renderer {
checkGlError("glBindFramebuffer mFrameBuffer: " + mFrameBuffer); checkGlError("glBindFramebuffer mFrameBuffer: " + mFrameBuffer);
// 创建纹理 // 创建纹理
int[] textures = new int[1]; // int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0); // GLES20.glGenTextures(1, textures, 0);
mFrameTextureID = textures[0]; // mFrameTextureID = textures[0];
// GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFrameTextureID);
// checkGlError("glBindTexture mFrameTextureID");
// GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, mWidth, mHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
// checkGlError("glTexImage2D mFrameTextureID");
mFrameTextureID = createTexture(null);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFrameTextureID); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFrameTextureID);
checkGlError("glBindTexture mFrameTextureID"); checkGlError("glBindTexture mFrameTextureID");
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, mWidth, mHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
checkGlError("glTexImage2D mFrameTextureID");
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, mFrameTextureID, 0); GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, mFrameTextureID, 0);
checkGlError("glFramebufferTexture2D mFrameTextureID"); checkGlError("glFramebufferTexture2D mFrameTextureID");
...@@ -416,7 +421,9 @@ public class ImageRenderer implements GLSurfaceView.Renderer { ...@@ -416,7 +421,9 @@ public class ImageRenderer implements GLSurfaceView.Renderer {
private static final int RGBA_SIZE = mWidth * mHeight * 4; private static final int RGBA_SIZE = mWidth * mHeight * 4;
private static final int NV21_SIZE = RGBA_SIZE * 3 / 8; private static final int NV21_SIZE = RGBA_SIZE * 3 / 8;
private byte[] mImageBytes = new byte[NV21_SIZE]; private static final int Y_SIZE = mWidth * mHeight;
private byte[] mImageBytes = new byte[Y_SIZE];
private static final String TAG = "ImageRenderer"; private static final String TAG = "ImageRenderer";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment