OpenGL screenshot

rogue
Unregistered
 
Post: #1
Hi all, I'd like to add the possibility to take screenshots to my little OpenGL app, but I can't figure out how to do that. Generally I have no Idea whatsoever when it comes to save things to files... really I must have been creating completely useless software so far Rolleyes
Quote this message in a reply
Member
Posts: 204
Joined: 2002.09
Post: #2
Greetings,

Use glReadPixels() to capture the rendered buffer, then reformat the data and save it to a file in the image format you're most comfortable with (I use targa's, mostly because I use them for input as well, check out NEHE's tutorials for information on the format of targa files).

Cheers,
Rocco
Quote this message in a reply
Member
Posts: 509
Joined: 2002.05
Post: #3
Hit command shift 3, sometimes it doesn't work with GL games or DivX movies, so make sure the scene is static
Quote this message in a reply
Member
Posts: 148
Joined: 2003.03
Post: #4
The follow group of functions allow you to write the pixels of the current OpenGL context to a TIFF image. It may have to be tweaked to suit your code.

Code:
-(void)saveSnapshotToFile:(NSString*)filePath
{
        NSBitmapImageRep *    bitmap;
        GLint        viewport[4];
        long        bytewidth;
        GLint        width, height;
        long        bytes;
    
        glReadBuffer(GL_FRONT);
        glGetIntegerv(GL_VIEWPORT, viewport);
        
        width = viewport[2];
        height = viewport[3];
            
        bytewidth = width * 4;
        bytewidth = (bytewidth + 3) & ~3;
        bytes = bytewidth * height;

        bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
                    pixelsWide:width
                    pixelsHigh:height
                    bitsPerSample:8
                    samplesPerPixel:3
                    hasAlpha:NO
                    isPlanar:NO
                    colorSpaceName:NSDeviceRGBColorSpace
                    bytesPerRow:bytewidth
                    bitsPerPixel:8 * 4];
                    
        glFinish();
        glPixelStorei(GL_PACK_ALIGNMENT, 4);
        glPixelStorei(GL_PACK_ROW_LENGTH, 0);
        glPixelStorei(GL_PACK_SKIP_ROWS, 0);
        glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
    

        glReadPixels(0, 0, width, height,
                    GL_BGRA,
                    GL_UNSIGNED_INT_8_8_8_8_REV,
                [bitmap bitmapData]);
                
        swizzleBitmap(bitmap);
        
    NSData * tiff;

    if (bitmap == NULL)
        return;

    tiff = [bitmap TIFFRepresentation];
    [tiff writeToFile:filePath atomically:YES];
}

static inline void swapcopy32(void * src, void * dst, int bytecount )
{
    uint32_t *srcP;
    uint32_t *dstP;
    uint32_t p0, p1, p2, p3;
    uint32_t u0, u1, u2, u3;
    
    srcP = src;
    dstP = dst;
   #define SWAB_PIXEL(p) (((p) << 8) | ((p) >> 24))

    while ( bytecount >= 16 )
    {
        p3 = srcP[3];
        p2 = srcP[2];
        p1 = srcP[1];
        p0 = srcP[0];
        
        u3 = SWAB_PIXEL(p3);
        u2 = SWAB_PIXEL(p2);
        u1 = SWAB_PIXEL(p1);
        u0 = SWAB_PIXEL(p0);
        srcP += 4;

        dstP[3] = u3;
        dstP[2] = u2;
        dstP[1] = u1;
        dstP[0] = u0;
        bytecount -= 16;
        dstP += 4;
    }
    while ( bytecount >= 4 )
    {
        p0 = *srcP++;
        bytecount -= 4;
        *dstP++ = SWAB_PIXEL(p0);
    }
}

static void swizzleBitmap(NSBitmapImageRep * bitmap)
{
    int top, bottom;
    void * buffer;
    void * topP;
    void * bottomP;
    void * base;
    int rowBytes;

    rowBytes = [bitmap bytesPerRow];
    top = 0;
    bottom = [bitmap pixelsHigh] - 1;
    base = [bitmap bitmapData];
    buffer = malloc(rowBytes);
    
    while ( top < bottom )
    {
        topP = (top * rowBytes) + base;
        bottomP = (bottom * rowBytes) + base;
        
        swapcopy32( topP, buffer, rowBytes );
        swapcopy32( bottomP, topP, rowBytes );
        bcopy( buffer, bottomP, rowBytes );
        
        ++top;
        --bottom;
    }
    free( buffer );
}
Quote this message in a reply
Mars_999
Unregistered
 
Post: #5
Be aware glReadPixels() is slow.
Quote this message in a reply
Member
Posts: 164
Joined: 2002.04
Post: #6
But faster than the alternative, i.e. pausing the game and painting everything you see on a piece of canvas
Quote this message in a reply
rogue
Unregistered
 
Post: #7
to be honest, I haven't yet found my way around cocoa or obj-c. my whole code is basically the cocoa-app template, but without the nib or main.m files. GLUT handles all the windowing stuff, and all my drawing and interaction functions. its all written in plain C. I don't think I can use all these fancy cocoa NSBitmap things without major overhaul of the whole thing, which is not what I really want to do.

I think a library which makes such tasks like saving a frame to a picture would be the most straightforward way, or am I wrong?
Quote this message in a reply
Member
Posts: 370
Joined: 2002.04
Post: #8
You don't even have to deal with NSBitmap, all you have to do is call saveSnapshotToBuffer, with an NSString.

Did you ever wonder why we had to run for shelter when the promise of a brave new world unfurled beneath the clear blue sky?
Quote this message in a reply
Member
Posts: 148
Joined: 2003.03
Post: #9
Yes, calling that function for each and every frame will drastically hamper your frame rate. It's meant as a snapshot function, not a recording function. If you want to record, then you'd probably do what Steven suggested: save all the data to a buffer, then dump the buffer into images/movie whenever the animation is done (or when memory is full).
Quote this message in a reply
Sta7ic
Unregistered
 
Post: #10
If you're running GLUT, just select File/Save As...
Kudos to Smashspeak for finding that oddity out.

-"Sta7ic" Matt
Quote this message in a reply
rogue
Unregistered
 
Post: #11
thats cool... GLUT, eh?! Wink
Quote this message in a reply
Member
Posts: 148
Joined: 2003.03
Post: #12
Wow, that really is odd. I never expected it to be able to do that.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Screenshot of OpenGL context aarku 6 7,077 Jul 23, 2004 07:05 PM
Last Post: aarku
  Normal Problem - Screenshot available designdb 8 3,842 May 17, 2003 11:31 AM
Last Post: designdb