PDA

View Full Version : file type



Hylke Donker
08-07-2005, 05:21 AM
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

dvm
08-07-2005, 05:55 AM
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.

Hylke Donker
08-07-2005, 06:31 AM
They both require an header.
I want one that doesn't require an header.

jide
08-07-2005, 08:17 AM
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.

Hylke Donker
08-08-2005, 11:24 PM
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

RigidBody
08-09-2005, 12:28 AM
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(&amp;TGAhead, sizeof(TGAhead), 1, out);
fwrite(pixel_data, 3*W*H, 1, out);
fclose(out); }

Hylke Donker
08-09-2005, 02:38 AM
that code is giving a segmentation fault.

jide
08-09-2005, 04:13 AM
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!\n");
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->sizeX*256);
if (image->tmp[i] == NULL )
{
fprintf(stderr, "Out of memory!\n");
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

jide
08-09-2005, 04:16 AM
Sorry, seems to have many problems on the network. I'll put the all code later.

RigidBody
08-09-2005, 11:46 AM
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\n"); to see where exactly
the problem is. maybe you are not allowed to
create a file, so you should check if (out==NULL).

Hylke Donker
08-10-2005, 12:22 AM
I found out that if I give the parameters W and H an higher value than 900 and 700 it crashes.

jide
08-10-2005, 01:12 AM
Maybe short on your system are only 8 bits ?

jide
08-10-2005, 01:17 AM
I post the rgb.cc a second time, hoping all will be available :)

</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!\n");
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->sizeX*256);
if (image->tmp[i] == NULL )
{
fprintf(stderr, "Out of memory!\n");
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

jide
08-10-2005, 01:20 AM
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

jide
08-10-2005, 02:36 AM
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.

:)

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

Hylke Donker
08-10-2005, 02:36 AM
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?

Hylke Donker
08-10-2005, 02:40 AM
If you could help me find out how to write the bytes properly to a file, I have a proper tga writer.

jide
08-10-2005, 05:33 AM
Can you post all the relevant code (image loading/saving, texture loading/creation and use) ?

Hylke Donker
08-11-2005, 04:19 AM
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(&amp;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.

Shukun no Haifun
08-11-2005, 04:55 AM
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.

Hylke Donker
08-11-2005, 08:38 AM
I want to use as less libraries as possible.

jide
08-11-2005, 11:29 AM
I don't see bad stuffs in your code, it should work.
Try to use char instead of unsigned char to store the values (and cast into char if necessary).
Also, ensure your rendering context is still available when you do that.
I really don't see what's wrong, sorry.

dvm
08-11-2005, 07:04 PM
You're not using libraries (apart from C/C++) if you write your own image handling code. The header has nothing to do with the library.

Hylke Donker
08-12-2005, 09:15 AM
Originally posted by jide:
I don't see bad stuffs in your code, it should work.
Try to use char instead of unsigned char to store the values (and cast into char if necessary).
Also, ensure your rendering context is still available when you do that.
I really don't see what's wrong, sorry.Ok.


You're not using libraries (apart from C/C++) if you write your own image handling code. The header has nothing to do with the library.What I meant was, I don't want to use libpng, because I want to use as less libraries as possible, so that's why I choose for creating my own headers.