In a sudden fit of spontaneousnessness, I decided to create a function to save screenshots in PNG format; basically it's a PNG version of bsave.
savepng.bas
Code: Select all
#include "zlib.bi"
declare function savepng(byref filename as string = "screenshot.png") as integer
declare function bswap(byval n as uinteger) as uinteger
const pngheader as string = chr(&h89) & "PNG" & chr(&hd, &ha, &h1a, &ha)
const ihdrcrc as uinteger = &ha8a1ae0a 'crc32(0, @"IHDR", 4)
const pltecrc as uinteger = &h4ba88955 'crc32(0, @"PLTE", 4)
const idatcrc as uinteger = &h35af061e 'crc32(0, @"IDAT", 4)
const iendcrc as uinteger = &hae426082 'crc32(0, @"IEND", 4)
type struct_ihdr field = 1
width as uinteger
height as uinteger
bitdepth as ubyte
colortype as ubyte
compression as ubyte
filter as ubyte
interlace as ubyte
end type
function bswap(byval n as uinteger) as uinteger
return (n and &h000000ff) shl 24 or _
(n and &h0000ff00) shl 8 or _
(n and &h00ff0000) shr 8 or _
(n and &hff000000) shr 24
end function
function savepng(byref filename as string = "screenshot.png") as integer
dim as uinteger w, h, depth
screeninfo w, h, depth
select case as const depth
case 1 to 8
scope
dim ihdr as struct_ihdr = (bswap(w), bswap(h), 8, 3, 0, 0, 0)
dim as uinteger ihdr_crc32 = crc32(ihdrcrc, cptr(ubyte ptr, @ihdr), sizeof(ihdr))
dim palsize as uinteger = (1 shl depth)
dim pltesize as uinteger = palsize * 3
dim plte(0 to 767) as ubyte
dim plte_crc32 as uinteger
dim as uinteger l = w + 1
dim as uinteger imgsize = l * h
dim as uinteger idatsize = imgsize + 11 + 5 * (imgsize \ 16383)
dim imgdata(0 to imgsize - 1) as ubyte
dim idat(0 to idatsize - 1) as ubyte
dim as uinteger idat_crc32
dim as uinteger x, y, col, r, g, b
for col = 0 to palsize - 1
palette get col, r, g, b
plte(col * 3) = r
plte(col * 3 + 1) = g
plte(col * 3 + 2) = b
next col
plte_crc32 = crc32(pltecrc, @plte(0), pltesize)
screenlock
for y = 0 to h - 1
imgdata(y * l) = 0
for x = 0 to w - 1
col = point(x, y)
imgdata(y * l + x + 1) = col
next w
next y
screenunlock
if compress2(@idat(0), @idatsize, @imgdata(0), imgsize, 9) then return -1
idat_crc32 = crc32(idatcrc, @idat(0), idatsize)
if open (filename for output as #1) then return -1
put #1, , pngheader
put #1, , bswap(13)
put #1, , "IHDR"
put #1, , ihdr
put #1, , bswap(ihdr_crc32)
put #1, , bswap(pltesize)
put #1, , "PLTE"
put #1, , plte(0), 3 * (1 shl depth)
put #1, , bswap(plte_crc32)
put #1, , bswap(idatsize)
put #1, , "IDAT"
put #1, , idat(0), idatsize
put #1, , bswap(idat_crc32)
put #1, , bswap(0)
put #1, , "IEND"
put #1, , bswap(iendcrc)
close #1
end scope
case 9 to 32
scope
dim ihdr as struct_ihdr = (bswap(w), bswap(h), 8, 2, 0, 0, 0)
dim as uinteger ihdr_crc32 = crc32(ihdrcrc, cptr(ubyte ptr, @ihdr), sizeof(ihdr))
dim as uinteger l = (w * 3) + 1
dim as uinteger imgsize = l * h
dim as uinteger idatsize = imgsize + 11 + 5 * (imgsize \ 16383)
dim imgdata(0 to imgsize - 1) as ubyte
dim idat(0 to idatsize - 1) as ubyte
dim as uinteger idat_crc32
dim as uinteger x, y, col, r, g, b
screenlock
for y = 0 to h - 1
imgdata(y * l) = 0
for x = 0 to w - 1
col = point(x, y)
r = col shr 16
g = col shr 8
b = col
imgdata(y * l + x * 3 + 1) = r
imgdata(y * l + x * 3 + 2) = g
imgdata(y * l + x * 3 + 3) = b
next w
next y
screenunlock
if compress2(@idat(0), @idatsize, @imgdata(0), imgsize, 9) then return -1
idat_crc32 = crc32(idatcrc, @idat(0), idatsize)
if open (filename for output as #1) then return -1
put #1, , pngheader
put #1, , bswap(13)
put #1, , "IHDR"
put #1, , ihdr
put #1, , bswap(ihdr_crc32)
put #1, , bswap(idatsize)
put #1, , "IDAT"
put #1, , idat(0), idatsize
put #1, , bswap(idat_crc32)
put #1, , bswap(0)
put #1, , "IEND"
put #1, , bswap(iendcrc)
close #1
end scope
case else
return -1
end select
end function
example.bas
Code: Select all
option explicit
#include "savepng.bas"
dim i as integer
screen 13
randomize timer
for i = 1 to 100
line (int(rnd * 320), int(rnd * 200))-(int(rnd * 320), int(rnd * 200)), int(rnd * 256), bf
next i
sleep
savepng "screenshot.png"
Code: Select all
declare function savepng(byref filename as string = "screenshot.png") as integer
Sorry it's not commented, I only really spent a couple of hours on it, but it should be quite reliable. It should work in paletted and normal SCREEN modes.