PlayerGLWidget.cpp 7.2 KB

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