Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opengl glReadPixels-图像看起来抖动_Opengl_Glreadpixels_Cimg - Fatal编程技术网

Opengl glReadPixels-图像看起来抖动

Opengl glReadPixels-图像看起来抖动,opengl,glreadpixels,cimg,Opengl,Glreadpixels,Cimg,我希望捕获我在openGL中渲染的图像。我使用glReadPixels,然后用CImg保存图像。不幸的是,结果是错误的。见下文。左边的图像是正确的。我用GadWin PrintScreen捕捉到了它。右边的图像不正确。我用glReadPixels和CImg创建了它: 我已经在网上做了很多关于什么可能是错误的研究,但是我已经找不到途径去追求了。在此代码捕获图像: void snapshot() { int width = glutGet(GLUT_WINDOW_WIDTH);

我希望捕获我在openGL中渲染的图像。我使用glReadPixels,然后用CImg保存图像。不幸的是,结果是错误的。见下文。左边的图像是正确的。我用GadWin PrintScreen捕捉到了它。右边的图像不正确。我用glReadPixels和CImg创建了它:

我已经在网上做了很多关于什么可能是错误的研究,但是我已经找不到途径去追求了。在此代码捕获图像:

void snapshot() {
    int width = glutGet(GLUT_WINDOW_WIDTH);
    int height = glutGet(GLUT_WINDOW_HEIGHT);
    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    int bytes = width*height*3; //Color space is RGB
    GLubyte *buffer = (GLubyte *)malloc(bytes);

    glFinish();
    glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
    glFinish();

    CImg<GLubyte> img(buffer,width,height,1,3,false);
    img.save("ScreenShot.ppm");
    exit(0);
}
在一条评论之后,我抓取了位深度并打印到控制台上。结果如下:

redbits=8
greenbits=8
bluebits=8
depthbits=24

很明显,您是从帧缓冲区中获取图像的,但行长度似乎不正确。您将填料对齐设置为良好,但还有更多可设置的参数:

总包包装行长度 GL\u PACK\u SKIP\u像素 总帐\打包\跳过\行
将其设置为0,以确保紧密包装。此外,glReadPixels之后的glFinish也是超级像素。glReadPixels不异步工作–它仅在读取的数据复制到目标缓冲区后返回,或者在写入PBO的情况下,从PBO获取数据将等待操作完成。

您显然是从帧缓冲区获取图像,但行长度似乎不正确。您将填料对齐设置为良好,但还有更多可设置的参数:

总包包装行长度 GL\u PACK\u SKIP\u像素 总帐\打包\跳过\行
将其设置为0,以确保紧密包装。此外,glReadPixels之后的glFinish也是超级像素。glReadPixels不异步工作–它仅在读取数据复制到目标缓冲区后返回,或者在写入PBO的情况下,从PBO获取数据将等待操作完成。

CImg不会交错其颜色。也就是说,3个红色、绿色和蓝色像素将线性存储为:

R1,R2,R3,…,G1,G2,G3,…,B1,B2,B3

但是,OpenGL的glReadPixel和glDrawPixel需要如下交叉颜色组件:

R1、G1、B1、R2、G2、B2

此外,OpenGL将原点0,0放在图像的左下角。CImg在原点位于图像左上角的位置使用更多的方法

下面是我编写的一个例程,它将交错的颜色转换为CImg的面向通道的格式

void convertToNonInterleaved(int w, int h, unsigned char* tangled, unsigned char* untangled) {
    //Take string in format R1 G1 B1 R2 G2 B2... and re-write it 
    //in the format format R1 R2 G1 G2 B1 B2... 
    //Assume 8 bit values for red, green and blue color channels.
    //Assume there are no other channels
    //tangled is a pointer to the input string and untangled 
    //is a pointer to the output string. This method assumes that 
    //memory has already been allocated for the output string.

    int numPixels = w*h;
    int numColors = 3;
    for(int i=0; i<numPixels; ++i) {
        int indexIntoInterleavedTuple = numColors*i;
        //Red
        untangled[i] = tangled[indexIntoInterleavedTuple];
        //Green
        untangled[numPixels+i] = tangled[indexIntoInterleavedTuple+1];
        //Blue
        untangled[2*numPixels+i] = tangled[indexIntoInterleavedTuple+2];
    }
}

CImg不交错其颜色。也就是说,3个红色、绿色和蓝色像素将线性存储为:

R1,R2,R3,…,G1,G2,G3,…,B1,B2,B3

但是,OpenGL的glReadPixel和glDrawPixel需要如下交叉颜色组件:

R1、G1、B1、R2、G2、B2

此外,OpenGL将原点0,0放在图像的左下角。CImg在原点位于图像左上角的位置使用更多的方法

下面是我编写的一个例程,它将交错的颜色转换为CImg的面向通道的格式

void convertToNonInterleaved(int w, int h, unsigned char* tangled, unsigned char* untangled) {
    //Take string in format R1 G1 B1 R2 G2 B2... and re-write it 
    //in the format format R1 R2 G1 G2 B1 B2... 
    //Assume 8 bit values for red, green and blue color channels.
    //Assume there are no other channels
    //tangled is a pointer to the input string and untangled 
    //is a pointer to the output string. This method assumes that 
    //memory has already been allocated for the output string.

    int numPixels = w*h;
    int numColors = 3;
    for(int i=0; i<numPixels; ++i) {
        int indexIntoInterleavedTuple = numColors*i;
        //Red
        untangled[i] = tangled[indexIntoInterleavedTuple];
        //Green
        untangled[numPixels+i] = tangled[indexIntoInterleavedTuple+1];
        //Blue
        untangled[2*numPixels+i] = tangled[indexIntoInterleavedTuple+2];
    }
}

是否确定在绘图代码中使用GL_RGB像素绘图?windoqw是双缓冲的?您应该使用ReadBuffer设置您正在读取的缓冲区。它是双缓冲的,并且我已经在启动例程中将颜色空间初始化为RBG:glutInitDisplayModeGLUT|U double | GLUT|RGB;这看起来很像是一个错误的像素深度类型问题-类似于读取565数据并将其渲染为888。什么是CImg及其参数的含义是什么?您确定在绘图代码中使用GL_RGB像素绘图吗?windoqw是双缓冲的?您应该使用ReadBuffer设置您正在读取的缓冲区。它是双缓冲的,并且我已经在启动例程中将颜色空间初始化为RBG:glutInitDisplayModeGLUT|U double | GLUT|RGB;这看起来很像是一个错误的像素深度类型问题——比如读取565数据并将其渲染为888。什么是CImg及其参数的含义?谢谢DatenWalf。我将包参数设置为0。我还删除了多余的glFinish调用。输出图像也一样。它看起来仍然和问题中的一样。CImg会有错吗?或者你认为glReadPixel调用是问题所在?@ahoffer:是的,CImg可能是罪魁祸首。我并没有首先注意到它,但您正在使用模板实例化它,但您读取的是无符号字节。但是我不知道CImg,所以这可能是原因,也可能不是原因。试着换成CImg。谢谢。我修正了我的代码,但忘了更新StackOverflow。今天我遇到了一位同事,他告诉我不要偷懒,要建立一个良好的调试环境。我将返回并使用glDrawPixels渲染像素缓冲区中的内容,以便实时比较图像。如果这样做有效,那么我知道我使用了错误的CImg参数。我还将继续渲染单个三角形或正方形。@ahoffer:为了调试的目的,最好是在黑色背景上渲染一条1px宽的垂直白线。这样做会告诉你出了什么问题。从技术上讲,这是通过处理链发送一个脉冲,给你一个脉冲响应。你期望一个身份映射,如果冲动没有改变,一切都匹配。然而,如果脉冲
e变化,这些变化告诉你,你面临的是什么样的错误。谢谢datenwolf。我将包参数设置为0。我还删除了多余的glFinish调用。输出图像也一样。它看起来仍然和问题中的一样。CImg会有错吗?或者你认为glReadPixel调用是问题所在?@ahoffer:是的,CImg可能是罪魁祸首。我并没有首先注意到它,但您正在使用模板实例化它,但您读取的是无符号字节。但是我不知道CImg,所以这可能是原因,也可能不是原因。试着换成CImg。谢谢。我修正了我的代码,但忘了更新StackOverflow。今天我遇到了一位同事,他告诉我不要偷懒,要建立一个良好的调试环境。我将返回并使用glDrawPixels渲染像素缓冲区中的内容,以便实时比较图像。如果这样做有效,那么我知道我使用了错误的CImg参数。我还将继续渲染单个三角形或正方形。@ahoffer:为了调试的目的,最好是在黑色背景上渲染一条1px宽的垂直白线。这样做会告诉你出了什么问题。从技术上讲,这是通过处理链发送一个脉冲,给你一个脉冲响应。你期望一个身份映射,如果冲动没有改变,一切都匹配。如果脉搏发生了变化,这些变化会告诉你,你正面临着什么样的错误。
unsigned char* p = (unsigned char *)malloc(bytes);
convertToNonInterleaved(width, height, buffer, p);
CImg<unsigned char> img(p, width, height,1,3);
free(p);
img.mirror('y');
CImgDisplay main_disp(img,"Snapshot");
while (!main_disp.is_closed() ) {
    main_disp.wait();
}
bytes = width*height*3; //Color space is RGB
if(buffer) 
    free(buffer);
buffer = (GLubyte *)malloc(bytes);
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);