file type

Hello,
Is there a file format, that packs the data exactly the same as the buffer pixels, from glReadPixels() ?
Because I want to make a screenshot and then stream the data to my file, without first compressing and indexing the data.
Thanx Hylke

Well, you could try a bitmap. You only need a header. Google about it. I don’t know if the .raw format would fit your description as well.

They both require an header.
I want one that doesn’t require an header.

Plain non-compressed SGI’s RGB file format is what you might want. Take a look at Mesa’s demo, they generally got one. If not, just tell me so that I can send you the source. But they use some headers.

Otherwise, really simple, there’s the TGA format. They use (very few) headers but they are really simple. Recent posts (about few months) talked about that.

From what I know, there’s no file format that do not have headers. Depending on what you’d like to do, you might simply put on a file what glReadPixels retrieved.

I have this code:

	GLint viewport[4];
	unsigned char *pixels;
	glGetIntegerv(GL_VIEWPORT, viewport);
	pixels = new unsigned char [viewport[2]*viewport[3]*3];
	glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3], GL_RGB, GL_UNSIGNED_BYTE, pixels);
	ofstream screenshot("Screenshot.tga", ios_base::binary | ios_base::out | ios_base::trunc);
	
	//header
	screenshot << 0; //There's no string after the header
	screenshot << 0; //Color Map Type.
	for(int i = 0;i < 5;i++) //this is all for index shit, we don't use an indext image
		screenshot << 0;
	screenshot << 2; // Uncompressed RGB
	screenshot << 0; screenshot << 0; // x origin, pick from the first x pixel
	screenshot << 0; screenshot << 0; //y origin, pick from the first y pixel
	screenshot << (viewport[3]  & 0x00FF); //width
	screenshot << (viewport[3]  & 0x00FF) / 256; //width
	screenshot << (viewport[4]  & 0x00FF); //height
	screenshot << (viewport[4]  & 0x00FF) / 256; //width
	screenshot << 24; //24 bit image, we don't use the alpha value
	screenshot << 0; //this byte is freeform.
	//end of header
	screenshot << *pixels;
	delete [] pixels;
	screenshot.close();

But it doesn’t seem to work.
Could you help me in the right directrion to fix it?
Thanx in advance,
Hylke

try this:

void Screendump(char *tga_file, short W, short H) {
 FILE   *out = fopen(tga_file, "w");
 char   pixel_data[3*W*H];
 short  TGAhead[] = {0, 2, 0, 0, 0, 0, W, H, 24};

 glReadBuffer(GL_FRONT);
 glReadPixels(0, 0, W, H, GL_BGR, GL_UNSIGNED_BYTE, pixel_data);
 fwrite(&TGAhead, sizeof(TGAhead), 1, out);
 fwrite(pixel_data, 3*W*H, 1, out);
 fclose(out); }

that code is giving a segmentation fault.

The code of RigidBody is not responsible of the segmentation fault. Check your code.

For RGB files, here is how I do that:

</font><blockquote><font size=“1” face=“Verdana, Arial”>code:</font><hr /><pre style=“font-size:x-small; font-family: monospace;”>// rgb.h
#include <cstdlib>
#include <cstdio>
#include <string>
#include <GL/gl.h>
#include <GL/glu.h>

using namespace std;

class RgbImage
{
public:
unsigned short imagic;
unsigned short type;
unsigned short dim;
unsigned short sizeX, sizeY, sizeZ;
char name[128];
unsigned char *data;
};

RgbImage* RgbLoad( char *);

// rgb.cc

#include “rgb.h”

#define IMAGIC 0x01da
#define IMAGIC_SWAP 0xda01

#define SWAP_SHORT_BYTES(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
#define SWAP_LONG_BYTES(x) (((((x) & 0xff) << 24) | (((x) & 0xff00) << 8)) |
((((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24)))

class _RgbImage
{
public:
unsigned short imagic;
unsigned short type;
unsigned short dim;
unsigned short sizeX, sizeY, sizeZ;
unsigned long min, max;
unsigned long wasteBytes;
char name[80];
unsigned long colorMap;
FILE *file;
unsigned char *tmp[5];
unsigned long rleEnd;
unsigned long *rowStart;
unsigned long *rowSize;
};

static _RgbImage *ImageOpen(char *fileName)
{
_RgbImage *image;
unsigned long *rowStart, *rowSize, ulTmp;
int x, i;

image = (_RgbImage )malloc(sizeof(_RgbImage));
if (image == NULL)
{
fprintf(stderr, "Out of memory!
");
exit(-1);
}
if ((image->file = fopen(fileName, “rb”)) == NULL)
{
perror(fileName);
exit(-1);
}
/

  • Read the image header
    /
    fread(image, 1, 12, image->file);
    /
  • Check byte order
    */
    if (image->imagic == IMAGIC_SWAP)
    {
    image->type = SWAP_SHORT_BYTES(image->type);
    image->dim = SWAP_SHORT_BYTES(image->dim);
    image->sizeX = SWAP_SHORT_BYTES(image->sizeX);
    image->sizeY = SWAP_SHORT_BYTES(image->sizeY);
    image->sizeZ = SWAP_SHORT_BYTES(image->sizeZ);
    }

for ( i = 0 ; i <= image->sizeZ ; i++ )
{
image->tmp[i] = (unsigned char )malloc(image->sizeX256);
if (image->tmp[i] == NULL )
{
fprintf(stderr, "Out of memory!
");
exit(-1);
}
}

if ((image->type & 0xFF00) == 0x0100) /* RLE image */
{
x = image->sizeY * image->sizeZ * sizeof(long);
image->rowStart = (unsigned long *)malloc(x);
image->rowSize = (unsigned long *)malloc(x);
if (image->rowStart == NULL

Sorry, seems to have many problems on the network. I’ll put the all code later.

well, i never had a segv with this, but there’s
a first time for everything.

the question is: where does the segmentation fault
occur? you should expand the code i posted with
some printf("ok so far
"); to see where exactly
the problem is. maybe you are not allowed to
create a file, so you should check if (out==NULL).

I found out that if I give the parameters W and H an higher value than 900 and 700 it crashes.

Maybe short on your system are only 8 bits ?

I post the rgb.cc a second time, hoping all will be available :slight_smile:

</font><blockquote><font size=“1” face=“Verdana, Arial”>code:</font><hr /><pre style=“font-size:x-small; font-family: monospace;”>#include “rgb.h”

#define IMAGIC 0x01da
#define IMAGIC_SWAP 0xda01

#define SWAP_SHORT_BYTES(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
#define SWAP_LONG_BYTES(x) (((((x) & 0xff) << 24) | (((x) & 0xff00) << 8)) |
((((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24)))

class _RgbImage
{
public:
unsigned short imagic;
unsigned short type;
unsigned short dim;
unsigned short sizeX, sizeY, sizeZ;
unsigned long min, max;
unsigned long wasteBytes;
char name[80];
unsigned long colorMap;
FILE *file;
unsigned char *tmp[5];
unsigned long rleEnd;
unsigned long *rowStart;
unsigned long *rowSize;
};

static _RgbImage *ImageOpen(char *fileName)
{
_RgbImage *image;
unsigned long *rowStart, *rowSize, ulTmp;
int x, i;

image = (_RgbImage )malloc(sizeof(_RgbImage));
if (image == NULL)
{
fprintf(stderr, "Out of memory!
");
exit(-1);
}
if ((image->file = fopen(fileName, “rb”)) == NULL)
{
perror(fileName);
exit(-1);
}
/

  • Read the image header
    /
    fread(image, 1, 12, image->file);
    /
  • Check byte order
    */
    if (image->imagic == IMAGIC_SWAP)
    {
    image->type = SWAP_SHORT_BYTES(image->type);
    image->dim = SWAP_SHORT_BYTES(image->dim);
    image->sizeX = SWAP_SHORT_BYTES(image->sizeX);
    image->sizeY = SWAP_SHORT_BYTES(image->sizeY);
    image->sizeZ = SWAP_SHORT_BYTES(image->sizeZ);
    }

for ( i = 0 ; i <= image->sizeZ ; i++ )
{
image->tmp[i] = (unsigned char )malloc(image->sizeX256);
if (image->tmp[i] == NULL )
{
fprintf(stderr, "Out of memory!
");
exit(-1);
}
}

if ((image->type & 0xFF00) == 0x0100) /* RLE image */
{
x = image->sizeY * image->sizeZ * sizeof(long);
image->rowStart = (unsigned long *)malloc(x);
image->rowSize = (unsigned long *)malloc(x);
if (image->rowStart == NULL

And the following.

</font><blockquote><font size=“1” face=“Verdana, Arial”>code:</font><hr /><pre style=“font-size:x-small; font-family: monospace;”> if (image->rowStart == NULL

Still not the whole code.
But I’ve fixed that problem with the segmentation fault by allocating memory using the new operator.
One final question.
Why does give fwrite the right result and stream.write not?

	screenshot.write((const char*)TGAhead, sizeof(TGAhead));
	screenshot.write(pixel_data, sizeof(pixel_data));

It generates a .tga file, but the pixels are not from my screenshot.
Could be that stream.write uses const char* str instead of const void * buffer?

I am really sorry to ‘polute’ this post.

If you want I’ll send you the full code by mail (threw the message system of this website). Just tell me.

:slight_smile:

EDIT: You should use unsigned char (GLubyte). Use some casts if necessary.

If you could help me find out how to write the bytes properly to a file, I have a proper tga writer.

Can you post all the relevant code (image loading/saving, texture loading/creation and use) ?

void KeyboardEvent::CreateScreenshot()
{
	GLint viewport[4];
	glGetIntegerv(GL_VIEWPORT, viewport);
	ofstream screenshot("Screenie.tga");
	unsigned char   *pixel_data = new unsigned char [3*viewport[2]*viewport[3]];
	short  TGAhead[] = {0, 2, 0, 0, 0, 0, viewport[2], viewport[3], 24};

	glReadBuffer(GL_FRONT);
	glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3], GL_BGR, GL_UNSIGNED_BYTE, pixel_data);
 //fwrite(&TGAhead, sizeof(TGAhead), 1, out);
// fwrite(pixel_data, 3*W*H, 1, out);
	screenshot.write((const char*)TGAhead, sizeof(TGAhead));
	screenshot.write((const char*)pixel_data, sizeof(pixel_data));
	delete [] pixel_data;
// fclose(out);
	screenshot.close();
	//Screendump("test.tga", 900, 768);
}

CreateScreenshot() is triggerd when the escape button is pressed.

You could also just bust out libpng and use that – the interface is pretty sane. EVERY common image file format uses some sort of header; it’s just a Good Idea to announce to programs the particulars of your images. Stuff like the width, the bit depth, and so forth.