从帧缓冲区创建的JPEG被旋转180度

JPEG created from frame buffer is rotated 180 degrees

本文关键字:旋转 180度 JPEG 缓冲区 创建      更新时间:2023-10-16

以下代码从帧缓冲区创建jpeg(在readpixels之后,是openGL库的一个函数)。

问题是创建的jpeg(test.jpeg)向左旋转了180度。

你能告诉我错误在哪里吗?

void CTaksiOGL::GetFrameFullSize(CVideoFrame& frame)
{
    // Gets current frame to be stored in video file.
    // select back buffer
    s_glReadBuffer(GL_BACK);
    // read the pixels data
    s_glReadPixels(0, 0, frame.m_Size.cx, frame.m_Size.cy, GL_RGB, GL_UNSIGNED_BYTE, frame.m_pPixels);

    // Adjust pixel encodings: RGB -> BGR
    SwapColorComponents(frame.m_pPixels, frame.m_Size.cx, frame.m_Size.cy);

    FILE* outfile = fopen("C:\testgrab\test.jpeg", "wb");
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
    jpeg_stdio_dest(&cinfo, outfile);

     GLubyte* flip = new GLubyte[sizeof(GLubyte)*frame.m_Size.cx*frame.m_Size.cy*3];

    cinfo.image_width      = frame.m_Size.cx;
    cinfo.image_height     = frame.m_Size.cy;
    cinfo.input_components = 3;
    cinfo.in_color_space   = JCS_RGB;
    int width=frame.m_Size.cx;
    int height=frame.m_Size.cy;
    jpeg_set_defaults(&cinfo);
    /*set the quality [0..100]  */
    jpeg_set_quality (&cinfo, 75, true);
    jpeg_start_compress(&cinfo, true);
    JSAMPROW row_pointer;          /* pointer to a single row */
    // OpenGL writes from bottom to top.
         // libjpeg goes from top to bottom.
         // flip lines.

    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
               flip[(y*height+x)*3] = frame.m_pPixels[((width-1-y)*height+x)*3];
               flip[(y*height+x)*3+1] = frame.m_pPixels[((width-1-y)*height+x)*3+1];
               flip[(y*height+x)*3+2] = frame.m_pPixels[((width-1-y)*height+x)*3+2];
            }
         }

    while (cinfo.next_scanline < cinfo.image_height) {
        row_pointer = (JSAMPROW) &frame.m_pPixels[cinfo.next_scanline*width*3];
        jpeg_write_scanlines(&cinfo, &row_pointer, 1);
    }
    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);
    fclose(outfile);

}

有一个错误:flip[(y*height+x)*3]->对原始2d数组进行索引的规范方法是y*with+x。如果没有这个修复程序,您迟早会遇到缓冲区溢出。单个"y"不是"高度"像素宽,而是"宽度"像素。当然,作业右侧也是如此。

Apart:你确定图像是旋转的吗?然后,如果你不仅镜像y,还镜像x,这个问题将暂时得到解决(当然,在上述修复之后)。

如果这些公式让你感到困惑,可以逐步推导坐标,例如

const int x0 = x,
          x1 = (width-1) - x;
...
target [x0 + y0*width] = source [x1 + y1*width];

听起来坐标系发生了变化:也许当您将字节从flip复制到frame时,您必须反转y坐标顺序。

glReadPixels从帧缓冲区(从左下角位于位置(x,y)的像素开始)向客户端内存(从位置数据开始)返回像素数据。当显示时,大多数框架(我知道Qt是这样做的),以其他方式处理它-(0,0)是左上角。

所以,也许你在显示(或转换)你的图像时没有考虑到这一点。