我发现了非常神秘的问题,我注释掉了程序中的调试行和程序“段错误(核心转储)”。
我缩小了程序范围,来到了这个。这是重现问题的整个代码:
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <highgui.h>
#include <GL/glut.h>
#include <iostream>
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_ALPHA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(500, 281);
(void) glutCreateWindow("Alpha Test");
cv::Mat image = cv::imread("alphatest.png");
int texWidth = image.cols;
int texHeight = image.rows;
GLuint texId;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
//std::cout << "hi" << std::endl;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, image.ptr());
}
Run Code Online (Sandbox Code Playgroud)
该程序崩溃并glTexImage2D显示错误消息:
zsh: segmentation fault (core dumped) ./mystery
Run Code Online (Sandbox Code Playgroud)
(该节目已被命名为神秘)
通过取消注释该cout行,程序运行良好,没有错误以及消息“hi”。我想知道为什么我必须保留调试线?
很可能您的图像行对齐方式不符合 OpenGL 读取图像的默认设置(4 字节行对齐方式)。这可能会导致 OpenGL 从未映射的页面读取,从而导致段错误。在执行可能创建页面分配的 iostream 输出时,与图像缓冲区相邻,以便此问题保持“隐藏”。
测试这个:
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); /* tightly packed*/
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); /* tightly packed*/
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); /* tightly packed*/
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* tightly aligned*/
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, image.ptr());
Run Code Online (Sandbox Code Playgroud)
此外,如果您的图像是灰度的,那么读取 GL_BGRA 格式将需要比 imread 传递的更多数据。您不应该对这些参数进行硬编码,而是在 imread 返回时从图像文件中确定它们。