PlayerGLWidget.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. #include "PlayerGLWidget.h"
  2. #include <QOpenGLFunctions> // 添加此行
  3. #include <QApplication>
  4. PlayerGLWidget::PlayerGLWidget(QWidget *parent) : QOpenGLWidget(parent)
  5. {
  6. QString imagePath = QApplication::applicationDirPath() + "/0.jpg";
  7. QImage image(imagePath);
  8. convertQImageToYUV420(image, m_YUV420);
  9. /* 显示图片 */
  10. updateFrame(m_YUV420);
  11. }
  12. PlayerGLWidget::~PlayerGLWidget()
  13. {
  14. }
  15. /* 刷新一帧 */
  16. void PlayerGLWidget::updateFrame(Image_YUV420& image)
  17. {
  18. yData = image.yData;
  19. uData = image.uData;
  20. vData = image.vData;
  21. imageSize_ = QSize(image.width, image.height);
  22. update();
  23. }
  24. /* 刷新一帧QImage */
  25. void PlayerGLWidget::updateFrame(Image_QImage& image)
  26. {
  27. m_image = image;
  28. update();
  29. }
  30. void PlayerGLWidget::convertQImageToYUV420(const QImage& image, Image_YUV420& yuv420)
  31. {
  32. int width = image.width();
  33. int height = image.height();
  34. int ySize = width * height;
  35. int uvSize = ySize / 4;
  36. yuv420.width = width;
  37. yuv420.height = height;
  38. yuv420.yData.resize(ySize);
  39. yuv420.uData.resize(uvSize);
  40. yuv420.vData.resize(uvSize);
  41. for (int y = 0; y < height; ++y) {
  42. for (int x = 0; x < width; ++x) {
  43. QColor color = image.pixelColor(x, y);
  44. int r = color.red();
  45. int g = color.green();
  46. int b = color.blue();
  47. int yIndex = y * width + x;
  48. yuv420.yData[yIndex] = static_cast<unsigned char>((0.257 * r) + (0.504 * g) + (0.098 * b) + 16);
  49. if (y % 2 == 0 && x % 2 == 0) {
  50. int uvIndex = (y / 2) * (width / 2) + (x / 2);
  51. yuv420.uData[uvIndex] = static_cast<unsigned char>((-0.148 * r) - (0.291 * g) + (0.439 * b) + 128);
  52. yuv420.vData[uvIndex] = static_cast<unsigned char>((0.439 * r) - (0.368 * g) - (0.071 * b) + 128);
  53. }
  54. }
  55. }
  56. }
  57. void PlayerGLWidget::initializeGL()
  58. {
  59. initializeOpenGLFunctions(); // 确保初始化 OpenGL 函数
  60. // 创建并编译顶点着色器
  61. const char* vertexShaderSource = R"(
  62. #version 330 core
  63. layout(location = 0) in vec3 aPos;
  64. layout(location = 1) in vec2 aTexCoord;
  65. out vec2 TexCoord;
  66. void main()
  67. {
  68. gl_Position = vec4(aPos, 1.0);
  69. TexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y); // 翻转纹理坐标
  70. }
  71. )";
  72. GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
  73. glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
  74. glCompileShader(vertexShader);
  75. // 创建并编译片段着色器
  76. const char* fragmentShaderSource = R"(
  77. #version 330 core
  78. out vec4 FragColor;
  79. in vec2 TexCoord;
  80. uniform sampler2D textureY;
  81. uniform sampler2D textureU;
  82. uniform sampler2D textureV;
  83. void main()
  84. {
  85. float y = texture(textureY, TexCoord).r;
  86. float u = texture(textureU, TexCoord).r - 0.5;
  87. float v = texture(textureV, TexCoord).r - 0.5;
  88. float r = y + 1.402 * v;
  89. float g = y - 0.344 * u - 0.714 * v;
  90. float b = y + 1.772 * u;
  91. FragColor = vec4(r, g, b, 1.0);
  92. }
  93. )";
  94. GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
  95. glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
  96. glCompileShader(fragmentShader);
  97. // 链接着色器程序
  98. shaderProgram = glCreateProgram();
  99. glAttachShader(shaderProgram, vertexShader); // 确保传递的是程序对象和着色器对象
  100. glAttachShader(shaderProgram, fragmentShader); // 确保传递的是程序对象和着色器对象
  101. glLinkProgram(shaderProgram);
  102. // 删除着色器对象
  103. glDeleteShader(vertexShader);
  104. glDeleteShader(fragmentShader);
  105. // 创建纹理
  106. glGenTextures(1, &textureIdY_);
  107. glGenTextures(1, &textureIdU_);
  108. glGenTextures(1, &textureIdV_);
  109. glBindTexture(GL_TEXTURE_2D, textureIdY_);
  110. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  111. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  112. glBindTexture(GL_TEXTURE_2D, textureIdU_);
  113. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  114. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  115. glBindTexture(GL_TEXTURE_2D, textureIdV_);
  116. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  117. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  118. // 设置顶点数据和缓冲
  119. float vertices[] = {
  120. // positions // texture coords
  121. -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
  122. 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
  123. 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
  124. -1.0f, 1.0f, 0.0f, 0.0f, 1.0f
  125. };
  126. unsigned int indices[] = {
  127. 0, 1, 2,
  128. 2, 3, 0
  129. };
  130. glGenVertexArrays(1, &VAO);
  131. glGenBuffers(1, &VBO);
  132. glGenBuffers(1, &EBO);
  133. glBindVertexArray(VAO);
  134. glBindBuffer(GL_ARRAY_BUFFER, VBO);
  135. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  136. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
  137. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
  138. // 位置属性
  139. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
  140. glEnableVertexAttribArray(0);
  141. // 纹理坐标属性
  142. glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
  143. glEnableVertexAttribArray(1);
  144. glBindBuffer(GL_ARRAY_BUFFER, 0);
  145. glBindVertexArray(0);
  146. }
  147. void PlayerGLWidget::resizeGL(int w, int h)
  148. {
  149. Ortho2DSize_.setWidth(w);
  150. Ortho2DSize_.setHeight(h);
  151. glViewport(0, 0, w, h);
  152. glMatrixMode(GL_PROJECTION);
  153. glLoadIdentity();
  154. glOrtho(0, Ortho2DSize_.width(), Ortho2DSize_.height(), 0, -1, 1);
  155. glMatrixMode(GL_MODELVIEW);
  156. }
  157. void PlayerGLWidget::paintGL()
  158. {
  159. glClear(GL_COLOR_BUFFER_BIT);
  160. if (yData.isEmpty() || uData.isEmpty() || vData.isEmpty()) {
  161. return;
  162. }
  163. // 使用着色器程序
  164. glUseProgram(shaderProgram);
  165. // 更新纹理数据
  166. glActiveTexture(GL_TEXTURE0);
  167. glBindTexture(GL_TEXTURE_2D, textureIdY_);
  168. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, imageSize_.width(), imageSize_.height(), 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, yData.data());
  169. glActiveTexture(GL_TEXTURE1);
  170. glBindTexture(GL_TEXTURE_2D, textureIdU_);
  171. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, imageSize_.width() / 2, imageSize_.height() / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, uData.data());
  172. glActiveTexture(GL_TEXTURE2);
  173. glBindTexture(GL_TEXTURE_2D, textureIdV_);
  174. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, imageSize_.width() / 2, imageSize_.height() / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, vData.data());
  175. // 设置纹理单元
  176. glUniform1i(glGetUniformLocation(shaderProgram, "textureY"), 0);
  177. glUniform1i(glGetUniformLocation(shaderProgram, "textureU"), 1);
  178. glUniform1i(glGetUniformLocation(shaderProgram, "textureV"), 2);
  179. // 绘制四边形
  180. glBindVertexArray(VAO);
  181. glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
  182. glBindVertexArray(0);
  183. }