Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Bitmap Export

Bitmap Export
By: Zeus81


Introduction
Simply a script to save bitmaps in both bmp and png formats.
I know it already exists but I don't share this without reason, my version is "optimized".

Script
https://www.dropbox.com/s/3lqtjvosnrnnet3/Bitmap Export.rb

Instructions
- exporting in bmp format :
bitmap.export('prout.bmp')
or
bitmap.save('prout.bmp')
Exporting in bmp is extremly fast, but not compressed.
Since it's bmp32 it also keeps alpha channel, however not many softwares can deal with it, I just know that RPG Makers and Gimp 2.6 can.

- exporting in png format :
bitmap.export('prout.png')
or
bitmap.save('prout.png')
png is compatible with almost anything and quite well compressed, but it takes a little more time, not that much either unless you're exporting a huge bitmap.

If you don't specify any extension when exporting .png will be added automatically.

- serialize bitmap :
open('prout.rxdata', 'wb') {|file| Marshal.dump(bitmap, file)}
bitmap = open('prout.rxdata', 'rb') {|file| Marshal.load(file)}
or
save_data(bitmap, 'prout.rxdata')
bitmap = load_data('prout.rxdata')
It's quite fast and as compressed as png but only compatible with this script, you can use it if you want to store picture directly into savestates.

- snapshot
Graphics.export('prout.png')
or
Graphics.save('prout.png')
or
Graphics.snapshot('prout.png')
This is a quick way to do a screenshot.
filename is optional, and will be replaced by datetime if omitted.
 
Looks interesting... and like you spend a bit of time on it ;)

For useability (I think you can improve a script in many other aspects than just performance), I'd change the architechture around just a bit. First of all, different parameters seem to be a smart thing, like this:
Code:
def export(filename, extension='png')
That way, you save the hassle of checkin wheather there's a filename in your file... it also circumvents opening and closing a file for nothing.
From here on, after saving a few now-redundant lines, what you got is good. However if you want to keep the check for the filename, split the method up, like this:
Code:
  def export(filename, extension='png')

    case extension

    when 'bmp'

      write_bmp(filename)

    when 'png'

      write_png(filename)

    when ''

      print('Extension missing for' + filename)

    else

      print('Extension ' + extension + ' is not supported.')

    end

  end

 

  def write_bmp(filename)

    file = File.open(filename, 'wb')

    data, size = String.new, width*height*4

    RtlMoveMemory_ip.call(data.__id__*2+8, [size,address].pack('L2'), 8)

    file.write(['BM',size+54,0,54,40,width,height,1,32,0,size,0,0,0,0].pack('a2L6S2L6'))

    file.write(data)

    RtlMoveMemory_ip.call(data.__id__*2+8, "\0"*8, 8)

    file.close

  end

 

  def write_png(filename)

    file = File.open(filename, 'wb')

    def file.write_chunk(chunk)

      write([chunk.size-4].pack('N'))

      write(chunk)

      write([Zlib.crc32(chunk)].pack('N'))

    end

    file.write("\211PNG\r\n\32\n")

    file.write_chunk("IHDR#{[width,height,8,6,0,0,0].pack('N2C5')}")

    RtlMoveMemory_pi.call(data="\0"*(width*height*4), address, data.size)

    (width*height).times {|i| data[i<<=2,3] = data[i,3].reverse!}

    deflate, null_char, w4 = Zlib::Deflate.new(9), "\0", width*4

    (height-1).downto(0) {|i| deflate << null_char << data[i*w4,w4]}

    file.write_chunk("IDAT#{deflate.finish}")

    deflate.close

    file.write_chunk('IEND')

    file.close

  end
That should add a bit more reason, despite the fact of being easier to add upon without creating a massive bulk of cryptic lines.
 
btw blue.. being that the filename provided is likely to not contain the extension, as it is a separate variable, it might be a good idea to tag the extension to it before passing to make_png or make_bmp. Perhaps a little if to see if its already there or something. Or just add it regardless. Eitherway.
 
Hm... assuming you define the filetype by calling the respective method, it doesn't really seem necessary at first glance. There are ocasions this could be useful at, though (such as JPGs, which have .jpg as well as .jpeg as extensions, however use the same algorithm). I don't think it makes sense for BMP or PNG, as while there are different versions of those, they differ in number of channels and not in filetype name (e.g. would require an additional parameter anyway).
I'd include it where needed, but I don't see a reason why it should be added to PNG and BMP (as it's not used either way).
 
However, you must have an extension for windows to know what it is. Otherwise its just a 'file' and it cannot be opened without manually specifying something to open it up.
 
Oh... yeah, of course, but considering you 'pass' the filetype already by calling the filetype-specific write method (you can assume png as the filetype for a file created with write_png), there's no need to pass it as a parameter... that's what I meant.

EDIT: I realize where I caused confusion... I should've changed the write_xxx method's from filetype to filetype + '.xxx' (or well, really just do a filetype += '.xxx' at the beginning of the method).
 
Exactly, I wasnt trying to argue, but I was looking for usability. More often than not, people say filename is not the filename+ext, but just filename. So I would provide it.. and specific the extension in the ext param. However of course as the method goes on, it doesnt append the filename with the ext, so it would be just a 'file' when attempted to be read by windows or any other OS. That is all.
 
New version 15% faster for png export, merely by changing one word. :haha:
+ improved memory usage of bmp export with VXace and merged all in an unique script.
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top