PDA

View Full Version : Write a buffer to a file WITHOUT opening a window?



mrshirts
09-30-2000, 02:36 PM
So, I'm writing a buffer to a file as a bitmap. I want to be able to run this program without ever actually launching the winow, preferrably on a machine that isn't even running X concurrently. Is this possible? I'm using GLUT to do it all, and it seems that no drawing to buffers occurs until glutMainLoop is entered-- and this automatically draws the window. Suggestions?
Cheers,
Michael

rts
10-01-2000, 10:55 AM
Originally posted by mrshirts:
So, I'm writing a buffer to a file as a bitmap. I want to be able to run this program without ever actually launching the winow, preferrably on a machine that isn't even running X concurrently. Is this possible? I'm using GLUT to do it all, and it seems that no drawing to buffers occurs until glutMainLoop is entered-- and this automatically draws the window. Suggestions?
Cheers,
Michael

Just browsing through the Red Book revealed:



Create surfaces that support rendering (both on-screen and off-screen):
...
glXCreatePixmap ...
glXCreatePbuffer ...


Maybe these functions would help?

I'm going to try playing around with them right now...
I'll post my code here if I get anywhere.

Hope this helps

rts
10-01-2000, 12:00 PM
Here's my code... this draws a lit sphere to a
.bmp file.

This will not make a window, but I think it does
require that an X server be running.




CFLAGS = -I/usr/X11R6/include

all: render2bmp

render2bmp: render2bmp.o
cc -o render2bmp render2bmp.o -L/usr/X11R6/lib -lglut -lGLU -lGL -lXext -lX11






#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <GL/glx.h>
#include <GL/glu.h>


void Render(int w, int h)
{
/* Draw a lit sphere */
/* Taken right out of the red book */
GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0};
GLfloat diffuse_material[] = {0.5, 0.5, 0.5, 1.0};

glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_material);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialf(GL_FRONT, GL_SHININESS, 25.0);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

glColorMaterial(GL_FRONT, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);

glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h) {
glOrtho(-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w,
1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
} else {
glOrtho(-1.5*(GLfloat)w/(GLfloat)h,
1.5*(GLfloat)w/(GLfloat)h,
-1.5, 1.5, -10.0, 10.0);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glutSolidSphere(1.0, 20, 16);
glFlush();
}

int MakeBMP(const char *fname, const unsigned char *image, int w, int h)
{
/* See http://www.dcs.ed.ac.uk/home/mxr/gfx/2d/BMP.txt */
struct BMPHeader {
unsigned short type;
unsigned int size;
unsigned short res1;
unsigned short res2;
unsigned int offset;
} __attribute__((packed)) header;
struct BMPInfo {
unsigned int size;
unsigned int width;
unsigned int height;
unsigned short planes;
unsigned short bit_count;
unsigned int comp;
unsigned int sizeImage;
unsigned int x_pels_per_meter;
unsigned int y_pels_per_meter;
unsigned int clr_used;
unsigned int clr_important;
} __attribute__((packed)) info;
FILE *fp;
int ret = 0;

/* Open file */
fp = fopen(fname, "wb");
if (!fp) {
fprintf(stderr,
"Unable to open %s for writing\n",
fname);
ret = -1;
} else {
/* Header */
header.type = 'B' | 'M' << 8;
header.size = sizeof(header) + sizeof(info) + w * h * 3;
header.res1 = header.res2 = 0;
header.offset = sizeof(header) + sizeof(info);
info.size = sizeof(info);
info.width = w;
info.height = h;
info.planes = 1;
info.bit_count = 24;
info.comp = 0;
info.sizeImage = w * h * 3;
info.x_pels_per_meter = info.y_pels_per_meter = 0;
info.clr_used = 0;
info.clr_important = 0;

fwrite(&amp;header, sizeof(header), 1, fp);
fwrite(&amp;info, sizeof(info), 1, fp);

fwrite(image, sizeof(unsigned char), h*w*3, fp);
}

if (fp) {
fclose(fp);
}

return ret;
}

int main(int argc, char **argv)
{
Display *dpy = NULL;
XVisualInfo *vi = NULL;
GLXContext cx = NULL;
Pixmap pmap;
GLXPixmap glxpmap ;
unsigned char *image = NULL;
const int attrib_list[] = {GLX_DOUBLEBUFFER, GLX_RGBA,
GLX_DEPTH_SIZE, 16,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
None};
const int width = 300;
const int height = 300;
int ret = 0;

/* Create a pixmap to render into */
dpy = XOpenDisplay(NULL);
if (dpy == NULL) {
fprintf(stderr, "Could not open display\n");
ret = -1;
goto abort;
}

if (!glXQueryExtension(dpy, NULL, NULL)) {
fprintf(stderr, "X server has no GLX extension\n");
ret = -1;
goto abort;
}

vi = glXChooseVisual(dpy, DefaultScreen(dpy), (int *)attrib_list);
if (vi == NULL) {
fprintf(stderr, "could not create visual\n");
ret = -1;
goto abort;
}

cx = glXCreateContext(dpy, vi, NULL, 0);

if (cx == NULL) {
fprintf(stderr, "could not create rendering context\n");
ret = -1;
goto abort;
}

pmap = XCreatePixmap(dpy, RootWindow(dpy, vi->screen),
width, height, vi->depth);
glxpmap = glXCreateGLXPixmap(dpy, vi, pmap);
glXMakeCurrent(dpy, glxpmap, cx);

/* Now render scene */
Render(width, height);

/* Save the frame buffer to a BMP */
image = (unsigned char *)malloc(sizeof(unsigned char)*width*height*3);
if (!image) {
fprintf(stderr, "Unable to allocate image buffer\n");
ret = -1;
goto abort;
}
glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, image);
MakeBMP("render2bmp.bmp", image, width, height);

/* Clean up */
abort:
if (cx &amp;&amp; dpy) {
glXDestroyContext(dpy, cx);
}
if (dpy) {
/* MesaGL seems to be missing this... doesn't link so well */
/* glXDestroyPixmap(dpy, glxpmap); */
}
if (dpy) {
XFreePixmap(dpy, pmap);
}
if (dpy) {
XCloseDisplay(dpy);
}
if (image) {
free(image);
}

return ret;
}


Hope this helps

flight
10-02-2000, 11:54 AM
If you do not need hardware rendering you could use OSMesa which renders right into a memory buffer.

Judd Tracy