123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- #include "PlayerGLWidget.h"
- #include <QOpenGLFunctions> // 添加此行
- #include <QApplication>
- PlayerGLWidget::PlayerGLWidget(QWidget *parent) : QOpenGLWidget(parent)
- {
- QString imagePath = QApplication::applicationDirPath() + "/0.jpg";
- QImage image(imagePath);
- convertQImageToYUV420(image, m_YUV420);
- /* 显示图片 */
- updateFrame(m_YUV420);
- }
- PlayerGLWidget::~PlayerGLWidget()
- {
- }
- /* 刷新一帧 */
- void PlayerGLWidget::updateFrame(Image_YUV420& image)
- {
- yData = image.yData;
- uData = image.uData;
- vData = image.vData;
- imageSize_ = QSize(image.width, image.height);
- update();
- }
- /* 刷新一帧QImage */
- void PlayerGLWidget::updateFrame(Image_QImage& image)
- {
- m_image = image;
- update();
- }
- void PlayerGLWidget::convertQImageToYUV420(const QImage& image, Image_YUV420& yuv420)
- {
- int width = image.width();
- int height = image.height();
- int ySize = width * height;
- int uvSize = ySize / 4;
- yuv420.width = width;
- yuv420.height = height;
- yuv420.yData.resize(ySize);
- yuv420.uData.resize(uvSize);
- yuv420.vData.resize(uvSize);
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; ++x) {
- QColor color = image.pixelColor(x, y);
- int r = color.red();
- int g = color.green();
- int b = color.blue();
- int yIndex = y * width + x;
- yuv420.yData[yIndex] = static_cast<unsigned char>((0.257 * r) + (0.504 * g) + (0.098 * b) + 16);
- if (y % 2 == 0 && x % 2 == 0) {
- int uvIndex = (y / 2) * (width / 2) + (x / 2);
- yuv420.uData[uvIndex] = static_cast<unsigned char>((-0.148 * r) - (0.291 * g) + (0.439 * b) + 128);
- yuv420.vData[uvIndex] = static_cast<unsigned char>((0.439 * r) - (0.368 * g) - (0.071 * b) + 128);
- }
- }
- }
- }
- void PlayerGLWidget::initializeGL()
- {
- initializeOpenGLFunctions(); // 确保初始化 OpenGL 函数
- // 创建并编译顶点着色器
- const char* vertexShaderSource = R"(
- #version 330 core
- layout(location = 0) in vec3 aPos;
- layout(location = 1) in vec2 aTexCoord;
- out vec2 TexCoord;
- void main()
- {
- gl_Position = vec4(aPos, 1.0);
- TexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y); // 翻转纹理坐标
- }
- )";
- GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
- glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
- glCompileShader(vertexShader);
- // 创建并编译片段着色器
- const char* fragmentShaderSource = R"(
- #version 330 core
- out vec4 FragColor;
- in vec2 TexCoord;
- uniform sampler2D textureY;
- uniform sampler2D textureU;
- uniform sampler2D textureV;
- void main()
- {
- float y = texture(textureY, TexCoord).r;
- float u = texture(textureU, TexCoord).r - 0.5;
- float v = texture(textureV, TexCoord).r - 0.5;
- float r = y + 1.402 * v;
- float g = y - 0.344 * u - 0.714 * v;
- float b = y + 1.772 * u;
- FragColor = vec4(r, g, b, 1.0);
- }
- )";
- GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
- glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
- glCompileShader(fragmentShader);
- // 链接着色器程序
- shaderProgram = glCreateProgram();
- glAttachShader(shaderProgram, vertexShader); // 确保传递的是程序对象和着色器对象
- glAttachShader(shaderProgram, fragmentShader); // 确保传递的是程序对象和着色器对象
- glLinkProgram(shaderProgram);
- // 删除着色器对象
- glDeleteShader(vertexShader);
- glDeleteShader(fragmentShader);
- // 创建纹理
- glGenTextures(1, &textureIdY_);
- glGenTextures(1, &textureIdU_);
- glGenTextures(1, &textureIdV_);
- glBindTexture(GL_TEXTURE_2D, textureIdY_);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glBindTexture(GL_TEXTURE_2D, textureIdU_);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glBindTexture(GL_TEXTURE_2D, textureIdV_);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- // 设置顶点数据和缓冲
- float vertices[] = {
- // positions // texture coords
- -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
- 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
- 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
- -1.0f, 1.0f, 0.0f, 0.0f, 1.0f
- };
- unsigned int indices[] = {
- 0, 1, 2,
- 2, 3, 0
- };
- glGenVertexArrays(1, &VAO);
- glGenBuffers(1, &VBO);
- glGenBuffers(1, &EBO);
- glBindVertexArray(VAO);
- glBindBuffer(GL_ARRAY_BUFFER, VBO);
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
- // 位置属性
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
- glEnableVertexAttribArray(0);
- // 纹理坐标属性
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
- glEnableVertexAttribArray(1);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindVertexArray(0);
- }
- void PlayerGLWidget::resizeGL(int w, int h)
- {
- Ortho2DSize_.setWidth(w);
- Ortho2DSize_.setHeight(h);
- glViewport(0, 0, w, h);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0, Ortho2DSize_.width(), Ortho2DSize_.height(), 0, -1, 1);
- glMatrixMode(GL_MODELVIEW);
- }
- void PlayerGLWidget::paintGL()
- {
- glClear(GL_COLOR_BUFFER_BIT);
- if (yData.isEmpty() || uData.isEmpty() || vData.isEmpty()) {
- return;
- }
- // 使用着色器程序
- glUseProgram(shaderProgram);
- // 更新纹理数据
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, textureIdY_);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, imageSize_.width(), imageSize_.height(), 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, yData.data());
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, textureIdU_);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, imageSize_.width() / 2, imageSize_.height() / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, uData.data());
- glActiveTexture(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_2D, textureIdV_);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, imageSize_.width() / 2, imageSize_.height() / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, vData.data());
- // 设置纹理单元
- glUniform1i(glGetUniformLocation(shaderProgram, "textureY"), 0);
- glUniform1i(glGetUniformLocation(shaderProgram, "textureU"), 1);
- glUniform1i(glGetUniformLocation(shaderProgram, "textureV"), 2);
- // 绘制四边形
- glBindVertexArray(VAO);
- glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
- glBindVertexArray(0);
- }
|