You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在OpenGL(GLUT)项目中将绘制的图形保存为图像文件

PPM保存功能整合步骤
  • 补充缺失头文件:savePPM函数用到了std::vector存储像素数据,需要在代码头部新增#include <vector>引用
  • 前置函数定义:将savePPM函数的完整实现放在display函数之前,或者提前做函数声明,避免编译阶段报未定义错误
  • 选择正确的调用时机:必须在所有绘制指令提交完成、glFlush()执行完毕后再调用保存函数,此时帧缓冲内才是完整的渲染结果,glReadPixels才能读到正确的像素数据
  • 匹配参数:你创建的窗口尺寸为920*920,读取区域从窗口左下角(0,0)坐标开始覆盖整个窗口即可,savePPM内部已经做了OpenGL坐标和PPM格式坐标的上下翻转适配,不需要额外处理坐标问题
  • 可选优化:如果不需要每次窗口重绘都保存文件,可以加一个键盘回调,比如按下s键时才触发savePPM调用,避免不必要的文件写入开销。

整合完成的可运行代码如下:

#include <GL/glut.h>
#include <stdio.h>
#include <vector>

void savePPM(int start_x,int start_y,int w,int h,char *fname)
{
        FILE *f=fopen(fname,"wb");
        if (!f) return;
        std::vector<unsigned char> out(3*w*h);
        glPixelStorei(GL_PACK_ALIGNMENT,1); /* 按字节对齐读取像素 */
        glReadPixels(start_x,start_y,w,h, GL_RGB,GL_UNSIGNED_BYTE,&out[0]);
        fprintf(f,"P6\n%d %d\n255\n",w,h);
        for (int y=0;y<h;y++) { /* 输出时翻转图像上下方向,匹配常规图像坐标习惯 */
                fwrite(&out[3*(h-1-y)*w],1,3*w,f);
        }
        fclose(f);
}

void display(void) {

  glClear(GL_COLOR_BUFFER_BIT);

  glColor3f(1.0f, 0.0f, 0.0f);
  glBegin(GL_TRIANGLES);

  glVertex2f(0.1, 0.1);
  glVertex2f(0.3, 0.1);

  glVertex2f(0.2, 0.3);

  glEnd();

  glBegin(GL_POLYGON);

  glColor3f(0.0, 1.0, 0.0);

  glVertex2f(0.3, -0.1);
  glVertex2f(0.3, 0.1);
  glVertex2f(0.1, 0.1);
  glVertex2f(0.1, -0.1);

  glEnd();

  glFlush();
  // 渲染完成后保存整个窗口内容为PPM文件
  savePPM(0, 0, 920, 920, (char*)"render_result.ppm");
}
int main(int argc, char *argv[]) {

  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
  glutInitWindowPosition(10, 10);
  glutInitWindowSize(920, 920);
  glutCreateWindow("First Raster Shape");
  glutDisplayFunc(display);
  glutMainLoop();

  return 0;
}
其他渲染结果保存方案
  • 轻量单头文件方案:使用stb_image_write这类无依赖的单头文件库,只需要将头文件加入项目,通过宏开启实现后,即可直接读取帧缓冲像素保存为PNG、JPG、BMP等通用格式,不需要额外编译链接第三方库,文件通用性远强于PPM格式。
  • 全功能图像库方案:使用FreeImage等成熟的图像处理库,支持几乎所有主流图像格式的读写,内置像素格式转换、图像翻转、压缩参数调整等接口,适合需要多格式输出、后续要做图像后处理的场景,缺点是需要提前编译链接对应库文件。
  • 离屏渲染方案:如果不需要弹出窗口实时显示渲染内容,可以创建自定义帧缓冲对象(FBO)作为渲染输出目标,渲染完成后直接从FBO读取像素保存,不需要依赖窗口系统的默认帧缓冲,适合批量渲染出图、自动化生成渲染结果的场景。
  • 注意事项:如果后续切换为双缓冲渲染模式(GLUT_DOUBLE),需要在glutSwapBuffers交换缓冲之前调用glReadPixels,否则会读取到已交换的后台缓冲残留数据,导致保存的图像空白或内容错误。

内容的提问来源于stack exchange,提问作者Stoicism

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 21:21:25