PlayerGLWidget.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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 frameSize = width * height;
  49. int chromaSize = frameSize / 4;
  50. uint8_t* yuv = new uint8_t[frameSize + chromaSize * 2];
  51. uint8_t* yPlane = yuv;
  52. uint8_t* uPlane = yuv + frameSize;
  53. uint8_t* vPlane = yuv + frameSize + chromaSize;
  54. auto rgb = image.bits();
  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. for (int j = 0; j < height; j++) {
  71. for (int i = 0; i < width; i++) {
  72. int r = rgb[(j * width + i) * 3];
  73. int g = rgb[(j * width + i) * 3 + 1];
  74. int b = rgb[(j * width + i) * 3 + 2];
  75. // int y = (0.257 * r) + (0.504 * g) + (0.098 * b) + 16;
  76. // int u = -(0.148 * r) - (0.291 * g) + (0.439 * b) + 128;
  77. // int v = (0.439 * r) - (0.368 * g) - (0.071 * b) + 128;
  78. int y = (0.299 * r) + (0.587 * g) + (0.114 * b);
  79. int u = (-0.169 * r) - (0.331 * g) + (0.5 * b) + 128;
  80. int v = (0.5 * r) - (0.419 * g) - (0.081 * b) + 128;
  81. yPlane[j * width + i] = std::clamp(y, 0, 255);
  82. if (j % 2 == 0 && i % 2 == 0) {
  83. uPlane[(j / 2) * (width / 2) + (i / 2)] = std::clamp(u, 0, 255);
  84. vPlane[(j / 2) * (width / 2) + (i / 2)] = std::clamp(v, 0, 255);
  85. }
  86. }
  87. }
  88. yuv420.width = width;
  89. yuv420.height = height;
  90. yuv420.yData.resize(frameSize);
  91. yuv420.uData.resize(chromaSize);
  92. yuv420.vData.resize(chromaSize);
  93. yuv420.yData.append(reinterpret_cast<char*>(yPlane), frameSize);
  94. yuv420.uData.append(reinterpret_cast<char*>(uPlane), chromaSize);
  95. yuv420.vData.append(reinterpret_cast<char*>(vPlane), chromaSize);
  96. }
  97. void PlayerGLWidget::initializeGL()
  98. {
  99. initializeOpenGLFunctions(); // 确保初始化 OpenGL 函数
  100. // 创建并编译顶点着色器
  101. const char* vertexShaderSource = R"(
  102. #version 330 core
  103. layout(location = 0) in vec3 aPos;
  104. layout(location = 1) in vec2 aTexCoord;
  105. out vec2 TexCoord;
  106. void main()
  107. {
  108. gl_Position = vec4(aPos, 1.0);
  109. TexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y); // 翻转纹理坐标
  110. }
  111. )";
  112. GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
  113. glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
  114. glCompileShader(vertexShader);
  115. // 创建并编译片段着色器
  116. const char* fragmentShaderSource = R"(
  117. #version 330 core
  118. out vec4 FragColor;
  119. in vec2 TexCoord;
  120. uniform sampler2D textureY;
  121. uniform sampler2D textureU;
  122. uniform sampler2D textureV;
  123. void main()
  124. {
  125. float y = texture(textureY, TexCoord).r;
  126. float u = texture(textureU, TexCoord).r - 0.5;
  127. float v = texture(textureV, TexCoord).r - 0.5;
  128. float r = y + 1.402 * v;
  129. float g = y - 0.344 * u - 0.714 * v;
  130. float b = y + 1.772 * u;
  131. FragColor = vec4(r, g, b, 1.0);
  132. }
  133. )";
  134. GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
  135. glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
  136. glCompileShader(fragmentShader);
  137. // 链接着色器程序
  138. shaderProgram = glCreateProgram();
  139. glAttachShader(shaderProgram, vertexShader); // 确保传递的是程序对象和着色器对象
  140. glAttachShader(shaderProgram, fragmentShader); // 确保传递的是程序对象和着色器对象
  141. glLinkProgram(shaderProgram);
  142. // 删除着色器对象
  143. glDeleteShader(vertexShader);
  144. glDeleteShader(fragmentShader);
  145. // 创建纹理
  146. glGenTextures(1, &textureIdY_);
  147. glGenTextures(1, &textureIdU_);
  148. glGenTextures(1, &textureIdV_);
  149. glBindTexture(GL_TEXTURE_2D, textureIdY_);
  150. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  151. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  152. glBindTexture(GL_TEXTURE_2D, textureIdU_);
  153. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  154. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  155. glBindTexture(GL_TEXTURE_2D, textureIdV_);
  156. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  157. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  158. // 设置顶点数据和缓冲
  159. float vertices[] = {
  160. // positions // texture coords
  161. -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
  162. 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
  163. 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
  164. -1.0f, 1.0f, 0.0f, 0.0f, 1.0f
  165. };
  166. unsigned int indices[] = {
  167. 0, 1, 2,
  168. 2, 3, 0
  169. };
  170. glGenVertexArrays(1, &VAO);
  171. glGenBuffers(1, &VBO);
  172. glGenBuffers(1, &EBO);
  173. glBindVertexArray(VAO);
  174. glBindBuffer(GL_ARRAY_BUFFER, VBO);
  175. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  176. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
  177. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
  178. // 位置属性
  179. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
  180. glEnableVertexAttribArray(0);
  181. // 纹理坐标属性
  182. glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
  183. glEnableVertexAttribArray(1);
  184. glBindBuffer(GL_ARRAY_BUFFER, 0);
  185. glBindVertexArray(0);
  186. }
  187. void PlayerGLWidget::resizeGL(int w, int h)
  188. {
  189. Ortho2DSize_.setWidth(w);
  190. Ortho2DSize_.setHeight(h);
  191. glViewport(0, 0, w, h);
  192. glMatrixMode(GL_PROJECTION);
  193. glLoadIdentity();
  194. glOrtho(0, Ortho2DSize_.width(), Ortho2DSize_.height(), 0, -1, 1);
  195. glMatrixMode(GL_MODELVIEW);
  196. }
  197. void PlayerGLWidget::paintGL()
  198. {
  199. glClear(GL_COLOR_BUFFER_BIT);
  200. if (m_yData.isEmpty() || m_uData.isEmpty() || m_vData.isEmpty()) {
  201. return;
  202. }
  203. int uvWidth = m_imageSize.width() / 2;
  204. int uvHeight = m_imageSize.height() / 2;
  205. // 使用着色器程序
  206. glUseProgram(shaderProgram);
  207. // 更新纹理数据
  208. glActiveTexture(GL_TEXTURE0);
  209. glBindTexture(GL_TEXTURE_2D, textureIdY_);
  210. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_imageSize.width(), m_imageSize.height(), 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_yData.data());
  211. glActiveTexture(GL_TEXTURE1);
  212. glBindTexture(GL_TEXTURE_2D, textureIdU_);
  213. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, uvWidth, uvHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_uData.data());
  214. glActiveTexture(GL_TEXTURE2);
  215. glBindTexture(GL_TEXTURE_2D, textureIdV_);
  216. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, uvWidth, uvHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_vData.data());
  217. // 设置纹理单元
  218. glUniform1i(glGetUniformLocation(shaderProgram, "textureY"), 0);
  219. glUniform1i(glGetUniformLocation(shaderProgram, "textureU"), 1);
  220. glUniform1i(glGetUniformLocation(shaderProgram, "textureV"), 2);
  221. // 绘制四边形
  222. glBindVertexArray(VAO);
  223. glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
  224. glBindVertexArray(0);
  225. }