The following code creates a jpeg from a framebuffer (after readpixels, a function of openGL libraries).
The problem is that the jpeg created (test.jpeg) is rotated 180 degrees to the left.
Could you tell me where the error is?
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);
开发者_StackOverflow中文版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);
}
There is a bug: flip[(y*height+x)*3]
-> The canonical way of indexing raw 2d arrays is rather y*with+x
. Without this fix, you'll sooner or later run into buffer overflows. A single "y" is not "height" pixels wide, but "width" pixels. Same of course for the right hand side of assignment.
Apart: Are you certain the image is rotated? Then the issue would be fixed for the moment (after aforementioned fixed, of course) if you mirror not only y, but also x.
If those formulas confuse you, derive the coordinates stepwise, e.g.
const int x0 = x,
x1 = (width-1) - x;
...
target [x0 + y0*width] = source [x1 + y1*width];
Sounds like there is a co-ordinate system change: maybe when you copy your bytes from flip
to frame
you have to reverse the y-coordinate order.
glReadPixels returns pixel data from the frame buffer, starting with the pixel whose lower left corner is at location (x, y), into client memory starting at location data. When displaying, most frameworks (I know Qt does this), treats it other way around - (0,0) is top left corner.
So, maybe you didn't take this into account when displaying (or converting) your image.
精彩评论