I'd love to be able to make all my screenshots in PNG format (which would mean writing to PNG) I've gone as far as to
Here is my incomplete implimentation of a PNG screenshot generator: (taken from Garland's Quest)
Code:
type
TPNGStart = packed Array[0 .. 8] of Byte;
TPNG_IHDR = packed record
Width : DWord;
Height : DWord;
BitDepth : Byte;
ColorType : Byte;
CompressionMethod : Byte;
FilterMethod : Byte;
InterlaceMethod : Byte;
end;
TPNG_Chunk = packed record
Length : DWord;
ChunkType : Array[0 .. 3] of Byte;
ChunkCRC : DWord;
end;
procedure ScreenShot_PNG(Filename: String);
var
i: Integer;
pngStartBytes: TPNGStart;
pngIHDR: TPNG_IHDR;
pngChunk: TPNG_Chunk;
vport: array[0 .. 3] of Integer;
Buffer: PChar;
BufferLength: Integer;
f: TMemoryStream;
crc: Cardinal;
begin
// First 8 bytes //
pngStartBytes[0] := 137;
pngStartBytes[1] := 80;
pngStartBytes[2] := 78;
pngStartBytes[3] := 71;
pngStartBytes[4] := 13;
pngStartBytes[5] := 10;
pngStartBytes[6] := 26;
pngStartBytes[7] := 10;
// Get OpenGL ViewPort Data
glGetIntegerv(GL_VIEWPORT, @vport);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
// Chunk Information //
FillChar(pngChunk, SizeOf(pngChunk), 0);
pngChunk.Length := SizeOf(pngIHDR);
pngChunk.ChunkType[0] := ord('I');
pngChunk.ChunkType[1] := ord('H');
pngChunk.ChunkType[2] := ord('D');
pngChunk.ChunkType[3] := ord('R');
// IHDR Chunk Data //
FillChar(pngIHDR, SizeOf(pngIHDR), 0);
pngIHDR.Width := vport[2];
pngIHDR.Height := vport[3];
pngIHDR.BitDepth := 8;
pngIHDR.ColorType := 2; // 2 = Each pixel is an R,G,B triple. 6 = Each pixel is an R,G,B triple, followed by an alpha sample.
pngIHDR.CompressionMethod := 0; // deflate/inflate compression with a sliding window of at most 32768 bytes
pngIHDR.FilterMethod := 0; // adaptive filtering with five basic filter types
pngIHDR.InterlaceMethod := 0; // 0 (no interlace) or 1 (Adam7 interlace)
// Temp Store Chunk Type & Data into Buffer for processing
BufferLength := (4 + SizeOf(pngIHDR)); // ChunkType + ChunkData
GetMem(Buffer, BufferLength);
for i := 0 to 3 do // Chunk Type to Buffer
Write(Buffer^, pngChunk.ChunkType[i]);
// Write(Buffer^, pngIHDR); // Chunk Data to Buffer
// CRC for Chunk Data //
crc := crc32(0, nil, 0);
// pngChunk.ChunkCRC := crc32(crc, Buffer, BufferLength);
// Start Writing PNG File
f := TMemoryStream.Create;
for i := 0 to 7 do
f.Write(pngStartBytes[0], 1); // First 8 bytes
f.Write(pngChunk.Length, SizeOf(pngChunk.Length)); // IHDR Chunk Length
f.Write(buffer, BufferLength); // IHDR Chunk Type & Data
f.Write(pngChunk.ChunkCRC, SizeOf(pngChunk.ChunkCRC)); // IHDR Chunk CRC
FreeMem(Buffer);
// --- IDAT Chunk --- //
// Chunk Information //
FillChar(pngChunk, SizeOf(pngChunk), 0);
pngChunk.Length := SizeOf(pngIHDR);
pngChunk.ChunkType[0] := ord('I');
pngChunk.ChunkType[1] := ord('H');
pngChunk.ChunkType[2] := ord('D');
pngChunk.ChunkType[3] := ord('R');
// Temp Store Chunk Type & Data into Buffer for processing
BufferLength := (4 + (pngIHDR.Width * pngIHDR.Height * 3)); // rgb
GetMem(Buffer, BufferLength);
glReadPixels(0, 0, vport[2], vport[3], GL_RGB8, GL_UNSIGNED_BYTE, Buffer);
FreeMem(Buffer);
// crc32(crc : cardinal; buf : Pbyte; len : cardinal)
// f.Write(Buffer^, BufferLength);
// IEND Chunk
f.SaveToFile(Filename);
f.Free;
end;
it should work if you can modify it to generate the proper LZH compression for whatever pixel format you will be using. Oh and it is OpenGL dependent.
Bookmarks