Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
I
ImageConvert
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
zhaozl
ImageConvert
Commits
b54be368
Commit
b54be368
authored
Jan 22, 2025
by
zhaozl
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feature: Save Y Plane.
parent
e76b742e
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
221 additions
and
29 deletions
+221
-29
appInsightsSettings.xml
.idea/appInsightsSettings.xml
+6
-0
FRAGMENT_SHADER_RGB2NV21.glsl
app/src/main/assets/glsl/FRAGMENT_SHADER_RGB2NV21.glsl
+50
-7
FRAGMENT_SHADER_RGB2NV21_backup.glsl
...src/main/assets/glsl/FRAGMENT_SHADER_RGB2NV21_backup.glsl
+136
-0
ImageRenderer.java
app/src/main/java/tv/yunxi/imgfmt/ImageRenderer.java
+29
-22
No files found.
.idea/appInsightsSettings.xml
0 → 100644
View file @
b54be368
<?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
app/src/main/assets/glsl/FRAGMENT_SHADER_RGB2NV21.glsl
View file @
b54be368
...
...
@@ -7,9 +7,13 @@ 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
;
// 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
)
{
...
...
@@ -22,22 +26,50 @@ vec4 cC(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
);
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
)
{
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
)
{
/**
* 根据纹理坐标[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
));
// 根据像素坐标计算出
/**
* 输入: 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
);
...
...
@@ -86,6 +118,7 @@ vec4 calculateVU(float dx, float 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
)
{
...
...
@@ -93,4 +126,14 @@ void main() {
}
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
app/src/main/assets/glsl/FRAGMENT_SHADER_RGB2NV21_backup.glsl
0 → 100644
View file @
b54be368
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
app/src/main/java/tv/yunxi/imgfmt/ImageRenderer.java
View file @
b54be368
...
...
@@ -117,8 +117,8 @@ public class ImageRenderer implements GLSurfaceView.Renderer {
if
(
muMVPMatrixHandle
==
-
1
)
{
throw
new
RuntimeException
(
"Could not get attrib location for uCRatio"
);
}
createTexture
(
);
ByteBuffer
imageBuffer
=
loadBytesFromAssets
(
"image/fish.rgba"
);
mTextureID
=
createTexture
(
imageBuffer
);
createFrameBuffer
();
Log
.
v
(
TAG
,
"mVMatrix 1: "
+
Arrays
.
toString
(
mVMatrix
));
Matrix
.
setLookAtM
(
mVMatrix
,
0
,
...
...
@@ -139,12 +139,14 @@ public class ImageRenderer implements GLSurfaceView.Renderer {
renderTexture
();
mPixelBuffer
.
clear
();
GLES20
.
glReadPixels
(
0
,
0
,
mWidth
,
mHeight
,
GLES20
.
GL_RGBA
,
GLES20
.
GL_UNSIGNED_BYTE
,
mPixelBuffer
);
checkGlError
(
"glReadPixels"
);
mPixelBuffer
.
rewind
();
mPixelBuffer
.
position
(
Y_SIZE
/
2
);
mPixelBuffer
.
get
(
mImageBytes
);
saveImage
(
mImageBytes
,
"
nv21
"
);
saveImage
(
mImageBytes
,
"
gray
"
);
GLES20
.
glBindFramebuffer
(
GLES20
.
GL_FRAMEBUFFER
,
0
);
checkGlError
(
"glBindFramebuffer 0"
);
...
...
@@ -202,20 +204,16 @@ public class ImageRenderer implements GLSurfaceView.Renderer {
checkGlError
(
"glDrawArrays"
);
}
private
void
createTexture
()
{
ByteBuffer
imageBuffer
=
loadBytesFromAssets
(
"image/fish.rgba"
);
private
int
createTexture
(
ByteBuffer
buffer
)
{
// 创建纹理
int
[]
textures
=
new
int
[
1
];
GLES20
.
glGenTextures
(
1
,
textures
,
0
);
mTextureID
=
textures
[
0
];
GLES20
.
glBindTexture
(
GLES20
.
GL_TEXTURE_2D
,
mTextureID
);
checkGlError
(
"glBindTexture
mTextureID
"
);
GLES20
.
glBindTexture
(
GLES20
.
GL_TEXTURE_2D
,
textures
[
0
]
);
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
,
imageBuffer
);
checkGlError
(
"texImage2D mTextureID"
);
GLES20
.
glTexImage2D
(
GLES20
.
GL_TEXTURE_2D
,
0
,
GLES20
.
GL_RGBA
,
mWidth
,
mHeight
,
0
,
GLES20
.
GL_RGBA
,
GLES20
.
GL_UNSIGNED_BYTE
,
buffer
);
checkGlError
(
"texImage2D textures"
);
// Can't do mipmapping with camera source
GLES20
.
glTexParameterf
(
GLES20
.
GL_TEXTURE_2D
,
GLES20
.
GL_TEXTURE_MIN_FILTER
,
...
...
@@ -227,8 +225,12 @@ public class ImageRenderer implements GLSurfaceView.Renderer {
GLES20
.
GL_CLAMP_TO_EDGE
);
GLES20
.
glTexParameteri
(
GLES20
.
GL_TEXTURE_2D
,
GLES20
.
GL_TEXTURE_WRAP_T
,
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
()
{
...
...
@@ -242,16 +244,19 @@ public class ImageRenderer implements GLSurfaceView.Renderer {
checkGlError
(
"glBindFramebuffer mFrameBuffer: "
+
mFrameBuffer
);
// 创建纹理
int
[]
textures
=
new
int
[
1
];
GLES20
.
glGenTextures
(
1
,
textures
,
0
);
mFrameTextureID
=
textures
[
0
];
// int[] textures = new int[1];
// GLES20.glGenTextures(1, 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
);
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
);
checkGlError
(
"glFramebufferTexture2D mFrameTextureID"
);
...
...
@@ -416,7 +421,9 @@ public class ImageRenderer implements GLSurfaceView.Renderer {
private
static
final
int
RGBA_SIZE
=
mWidth
*
mHeight
*
4
;
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"
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment