PlayerGLWidget.cpp 7.6 KB

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