Page 1 of 3 123 LastLast
Results 1 to 10 of 24

Thread: This is easiest way to make screenshoots of your game.

  1. #1

    This is easiest way to make screenshoots of your game.

    Need some fast code to dump whole screenshoot of your opengl program to TGA image?

    No problem!

    with some small changes it would save to bmp as well, if you like png or jpg you'll have to extend that yourself

    Code:
    // this saves the viewport to a TGA file format
    Procedure ScreenShoot(filen: string);
    
    type
    TTGAHeader = packed record
      Length:            Byte;
      ColorMapType:      Byte;
      ImageType:         Byte;
      FirstEntryIndex:   Word;
      ColorMapLength:    Word; // Palette Length - should be alaways 256
      ColorMapEntrySize: Byte; // Palette BPP
      XOriginImage:      Word;
      YOriginImage:      Word;
      ImageWidth:        Word;
      ImageHeight:       Word;
      PixelDepth:        Byte;
      ImageDescriptor:   Byte; // AlphaBits (for example - 8 bits for 32 bit tga)
    end; // 18
    
    var
      vport: array[0..3] of integer;
      buffer: pchar;
      bufflen: integer;
      f: Tmemorystream;
      TGAHeader: TTGAHeader;
    begin
      glGetIntegerv(GL_VIEWPORT, @vPort);
    
      bufflen:= (vport[2] * vport[3]) * 3;  // rgb
      getmem(buffer, bufflen);
    
      glPixelStorei(GL_PACK_ALIGNMENT, 1);
    
      glReadPixels(0, 0, vport[2], vport[3], GL_BGR_EXT, GL_UNSIGNED_BYTE, buffer);
    
      fillchar(TGAHeader, sizeof(TGAHeader), 0);
      TGAHeader.ImageType:= 2;
      TGAHeader.ImageWidth:= vport[2];
      TGAHeader.ImageHeight:= vport[3];
      TGAHeader.PixelDepth:= 24;
    
      f:= Tmemorystream.Create;
      f.Write(TGAHeader, sizeof(TGAHeader));
      f.Write(buffer^, bufflen);
      f.SaveToFile(filen);
      f.free;
    
      freemem(buffer);
    
    end;
    This is my game project - Top Down City:
    http://www.pascalgamedevelopment.com...y-Topic-Reboot

    My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
    http://www.pascalgamedevelopment.com...source+manager

  2. #2
    Legendary Member cairnswm's Avatar
    Join Date
    Nov 2002
    Location
    Randburg, South Africa
    Posts
    1,537

    This is easiest way to make screenshoots of your game.

    Very Cool

    I had a few problems through:

    [pascal] f: Tfile;
    TGAHeader: Tmemorystream; [/pascal]

    changes to
    [pascal] f: Tmemorystream;
    TGAHeader: TTGAHeader;[/pascal]

    And then it worked right first time.

    Thanks for this. (Already added to S2DL - will upload new S2DL later tonight)
    William Cairns
    My Games: http://www.cairnsgames.co.za (Currently very inactive)
    MyOnline Games: http://TheGameDeveloper.co.za (Currently very inactive)

  3. #3

    This is easiest way to make screenshoots of your game.

    Well, TGA has the enormous advantage of an origin at the bottom left - just like OpenGL. BMP and JPG do not have this advantage.

    I wrote something to make it work for SDL and BMP:

    [pascal]
    type
    TRGB=record
    R, G, B: Byte;
    end;
    PRGB=^TRGB;
    var
    viewport: array[0..3] of Integer;
    buffer: Pointer;
    size: Integer;
    Surface: PSDL_Surface;
    I, J: Integer;
    begin
    glGetIntegerv(GL_VIEWPORT, @viewport);
    size:=viewport[2]*viewport[3]*3;
    GetMem(buffer, size);
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
    GL_RGB, GL_UNSIGNED_BYTE, buffer);
    Surface:=SDL_CreateRGBSurface(0, viewport[2], viewport[3],
    24, $FF, $FF00, $FF0000, $00);
    for I:=0 to viewport[3]-1 do
    for J:=0 to viewport[2]-1 do
    PRGB(Integer(Surface.pixels)+I*viewport[2]*3+J*3)^:=
    PRGB(Integer(buffer)+(viewport[3]-I-1)*viewport[2]*3+J*3)^;
    SDL_SaveBMP(Surface, PChar(AFilename));
    SDL_FreeSurface(Surface);
    end;
    [/pascal]

  4. #4

    This is easiest way to make screenshoots of your game.

    Quote Originally Posted by cairnswm
    Very Cool

    I had a few problems through:

    [pascal] f: Tfile;
    TGAHeader: Tmemorystream; [/pascal]

    changes to
    [pascal] f: Tmemorystream;
    TGAHeader: TTGAHeader;[/pascal]
    yeah, sorry, i use Tfile class, which is compatible with Tmemorystream, so i just wanted to rename the variable types and seems i made an error, i'll edit my post to correct this.

    3_of_8: BMP has also a top-left origin, and also doesn't need any encoding.

    raw formats such as tga and bmp has advantage over jpeg and png, because they don't need encoding, that makes them simplier to implement.
    This is my game project - Top Down City:
    http://www.pascalgamedevelopment.com...y-Topic-Reboot

    My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
    http://www.pascalgamedevelopment.com...source+manager

  5. #5

    This is easiest way to make screenshoots of your game.

    TGA is not necessarily raw. It can also have RLE.

    And yes, BMP has the origin at the TOP left, but OpenGL at the BOTTOM left. Therefore, with your method, a BMP screenshot is upside down and you do need to encode it. Believe me, I've tried it out not two hours ago.

  6. #6

    This is easiest way to make screenshoots of your game.

    Quote Originally Posted by 3_of_8
    TGA is not necessarily raw. It can also have RLE.

    And yes, BMP has the origin at the TOP left, but OpenGL at the BOTTOM left. Therefore, with your method, a BMP screenshot is upside down and you do need to encode it. Believe me, I've tried it out not two hours ago.
    BMP has a bottom left origin, i have no idea what you did, but bmp raw data IS upside down in the file.

    edit: see:
    http://www.fortunecity.com/skyscrape.../bmpffrmt.html
    This is my game project - Top Down City:
    http://www.pascalgamedevelopment.com...y-Topic-Reboot

    My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
    http://www.pascalgamedevelopment.com...source+manager

  7. #7

    This is easiest way to make screenshoots of your game.

    Here's a working BMP saving variant:

    Code:
    Procedure ScreenShoot(filen: string);
    
    // 54 bytes bmp header
    TBMPheader = packed record
    magic               : word;     // BM (word: 19778)
    headersize          : longword; // 54
    reserved            : longword; // 0
    dataofs             : longword; // 54
    
    Size                : longword;
    Width               : longword;
    Height              : longword;
    Planes              : word;     // 1
    BitCount            : word;     // 24
    Compression         : longword; // 0
    SizeImage           : longword; // w * h * 3
    XPelsPerMeter       : longword; // 36100
    YPelsPerMeter       : longword; // 36100
    ClrUsed             : longword; // 0
    ClrImportant        : longword; // 0
    end;
    
    var
      vport: array[0..3] of integer;
      buffer: pchar;
      bufflen: integer;
      f: Tmemorystream;
      TGAHeader: TTGAHeader;
      BMPheader: TBMPheader;
    begin
      glGetIntegerv(GL_VIEWPORT, @vPort);
    
      bufflen:= (vport[2] * vport[3]) * 3;  // rgb
      getmem(buffer, bufflen);
    
      glPixelStorei(GL_PACK_ALIGNMENT, 1);
    
      glReadPixels(0, 0, vport[2], vport[3], GL_BGR_EXT, GL_UNSIGNED_BYTE, buffer);
    
      fillchar(BMPheader, sizeof(BMPheader), 0);
    
      BMPheader.magic               := 19778;
      BMPheader.headersize          := 54;
      BMPheader.reserved            := 0;
      BMPheader.dataofs             := 54;
      BMPheader.Size                := 40;
      BMPheader.Width               := vport[2];
      BMPheader.Height              := vport[3];
      BMPheader.Planes              := 1;
      BMPheader.BitCount            := 24;
      BMPheader.SizeImage           := bufflen;
      BMPheader.XPelsPerMeter       := 36100;
      BMPheader.YPelsPerMeter       := 36100;
      BMPheader.ClrUsed             := 0;
      BMPheader.ClrImportant        := 0;
    
      f:= Tmemorystream.Create;
      f.Write(BMPheader, sizeof(BMPheader));
      f.Write(buffer^, bufflen);
      f.SaveToFile(filen);
      f.free;
    
      freemem(buffer);
    
    end;
    This is my game project - Top Down City:
    http://www.pascalgamedevelopment.com...y-Topic-Reboot

    My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
    http://www.pascalgamedevelopment.com...source+manager

  8. #8
    Legendary Member cairnswm's Avatar
    Join Date
    Nov 2002
    Location
    Randburg, South Africa
    Posts
    1,537

    This is easiest way to make screenshoots of your game.

    How do you get the info from a stream into a TBitmap object?

    If we could do this then you can use the more standard Delphi calls to save JPEG and PNG.
    William Cairns
    My Games: http://www.cairnsgames.co.za (Currently very inactive)
    MyOnline Games: http://TheGameDeveloper.co.za (Currently very inactive)

  9. #9

    This is easiest way to make screenshoots of your game.

    I did never say anything else. BMP origin is on the top left but OpenGL origin is on the bottom left.

    I used SDL_SaveBMP and it was indeed upside down. So, for anyone who wants to use SDL, my solution is necessary.

  10. #10

    This is easiest way to make screenshoots of your game.

    BMP has a bottom left origin ...
    BMP has the origin at the TOP left ...
    Bitmap can have TOP-left origin as well as BOTTOM-left origin. Width and Height fields in the BMP header should be signed integers not unsigned. Then if Height is positive BMP is bottom-up and when Height is negative then BMP is considered top-down.

    Quote Originally Posted by MSDN
    biHeight -
    Specifies the height of the bitmap, in pixels. If biHeight is positive, the bitmap is a bottom-up DIB and its origin is the lower-left corner. If biHeight is negative, the bitmap is a top-down DIB and its origin is the upper-left corner.
    If biHeight is negative, indicating a top-down DIB, biCompression must be either BI_RGB or BI_BITFIELDS. Top-down DIBs cannot be compressed.
    Vampyre Imaging Library
    Earth Under Fire (PGD Big Boss 3rd place)
    Domains Of Chaos (PGD Multiplexity 5th place)

Page 1 of 3 123 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •