As a starting note, the original Module can be found here:
http://www.66rpg.com/htm/news624.htmAnd yes, I claim no rights to the original work, I've just edited it for versatility and less processing time.
If this has already been done, then I apologize, as I do not keep up with the RM community as much as I used to.
So, here we go
PNG Ouput Module Update
Original Author:
.
Editor: Jaffer
Date: December 23, 2009
What it does:
I've modified the original module for two reasons:
1.) Less processing time is needed. A cut of about .85 seconds to snap a standard resolution screenshot.
2.) Specific image dimensions. Now this module will allow you to take a screenshot of specific parts of the screen, of any width or height. If no values are specified, it will default to the original size of the bitmap being passed.
Uses:
You could use this as an in-game screen-shot feature (instead of having to printscreen, paste in paint, etc), or my personal use, use it to take snapshots of the current game screen for save menus. With the module update, the processing takes a lot less time if you specify the size you want, instead of relying on the clear_rect() function. Can also be used as an in-game camera, if you wanted a mini-game like that.
Code:
#============================================================================
# ?????www.66rpg.com???????
#============================================================================
#=begin
#============================================================================
# Bitmap to PNG By ???
#============================================================================
#
#?Bitmap??????
#
#bitmap_obj.make_png(name[, path])
#
#name:?????
#path:????
#
# ??66??????????????
#
#==============================================================================
#=end
# Modifications done by Jaffer to optimize processing speed and to increase
# versatility of the code.
module Zlib
class Png_File < GzipWriter
#--------------------------------------------------------------------------
# Process the file
#--------------------------------------------------------------------------
def make_png(bitmap_Fx,mode, ini_x, ini_y, fin_x, fin_y)
@mode = mode
@bitmap_Fx = bitmap_Fx
self.write(make_header)
self.write(make_ihdr(ini_x, ini_y, fin_x, fin_y))
self.write(make_idat(ini_x, ini_y, fin_x, fin_y))
self.write(make_iend)
end
#--------------------------------------------------------------------------
# Define the header
#--------------------------------------------------------------------------
def make_header
return [0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a].pack("C*")
end
#--------------------------------------------------------------------------
# Set .png file specifications
#--------------------------------------------------------------------------
def make_ihdr(ini_x, ini_y, fin_x, fin_y)
ih_size = [13].pack("N")
ih_sign = "IHDR"
ih_width = [fin_x - ini_x].pack("N")
ih_height = [fin_y - ini_y].pack("N")
ih_bit_depth = [8].pack("C")
ih_color_type = [6].pack("C")
ih_compression_method = [0].pack("C")
ih_filter_method = [0].pack("C")
ih_interlace_method = [0].pack("C")
string = ih_sign + ih_width + ih_height + ih_bit_depth + ih_color_type +
ih_compression_method + ih_filter_method + ih_interlace_method
ih_crc = [Zlib.crc32(string)].pack("N")
return ih_size + string + ih_crc
end
#--------------------------------------------------------------------------
# Determine data type
#--------------------------------------------------------------------------
def make_idat(ini_x, ini_y, fin_x, fin_y)
header = "\x49\x44\x41\x54"
case @mode # ?54~
when 1
data = make_bitmap_data(ini_x, ini_y, fin_x, fin_y)#1
else
data = make_bitmap_data(ini_x, ini_y, fin_x, fin_y)
end
data = Zlib::Deflate.deflate(data, 8)
crc = [Zlib.crc32(header + data)].pack("N")
size = [data.length].pack("N")
return size + header + data + crc
end
#--------------------------------------------------------------------------
# Pull the pixel values and write them to the output
#--------------------------------------------------------------------------
def make_bitmap_data1(ini_x, ini_y, fin_x, fin_y)
data = []
for y in ini_y...fin_y
data.push(0)
for x in ini_y...fin_x
color = @bitmap_Fx.get_pixel(x, y)
data.push(color.red)
data.push(color.green)
data.push(color.blue)
data.push(color.alpha)
end
end
return data.pack("C*")
end
#--------------------------------------------------------------------------
# Write the data for the Bitmap class
#--------------------------------------------------------------------------
def make_bitmap_data(ini_x, ini_y, fin_x, fin_y)
gz = Zlib::GzipWriter.open('hoge.gz')
t_Fx = 0
data = []
for y in ini_y...fin_y
data.push(0)
for x in ini_x...fin_x
t_Fx += 1
if t_Fx % 10000 == 0
Graphics.update
end
if t_Fx % 100000 == 0
s = data.pack("C*")
gz.write(s)
data.clear
#GC.start
end
color = @bitmap_Fx.get_pixel(x, y)
data.push(color.red)
data.push(color.green)
data.push(color.blue)
data.push(color.alpha)
end
end
s = data.pack("C*")
gz.write(s)
gz.close
data.clear
gz = Zlib::GzipReader.open('hoge.gz')
data = gz.read
gz.close
File.delete('hoge.gz')
return data
end
#--------------------------------------------------------------------------
# Finish packing the .png file
#--------------------------------------------------------------------------
def make_iend
ie_size = [0].pack("N")
ie_sign = "IEND"
ie_crc = [Zlib.crc32(ie_sign)].pack("N")
return ie_size + ie_sign + ie_crc
end
end
end
#==============================================================================
# Bitmap
#------------------------------------------------------------------------------
# Addition to the Bitmap class to support .png and image writing
#==============================================================================
class Bitmap
#--------------------------------------------------------------------------
# Add .png write support
#--------------------------------------------------------------------------
def make_png(name, path="", mode=0, ini_x=0, ini_y=0, fin_x=self.width, fin_y=self.height)
make_dir(path) if path != ""
Zlib::Png_File.open("temp.gz") {|gz|
gz.make_png(self,mode, ini_x, ini_y, fin_x, fin_y)
}
Zlib::GzipReader.open("temp.gz") {|gz|
$read = gz.read
}
f = File.open(path + name + ".png","wb")
f.write($read)
f.close
File.delete('temp.gz')
end
#--------------------------------------------------------------------------
# Make the directory if it is necessary
#--------------------------------------------------------------------------
def make_dir(path)
dir = path.split("/")
for i in 0...dir.size
unless dir == "."
add_dir = dir[0..i].join("/")
begin
Dir.mkdir(add_dir)
rescue
end
end
end
end
end
Implementation:
This is a module, and thus goes below the other modules.
How to call:
It's simple, all you do is use the .make_png class operation on any bitmap image. For example:
save_img = Bitmap.new(544, 416)
save_img = Graphics.snap_to_bitmap
save_img.make_png("Saved_File_Name", "Path_Directory", "Mode", "Initial_X", "Initial_Y", "Final_X", "Final_Y")
Basic format: .make_png(name, path, mode, initial x, initial y, final x, final y)
Now of course, you don't have to call every single value. In fact, the only required value is the File Name, the rest of the stuff will default as follows:
path: Defaults to the main folder of your RMVX game.
Initial X: Defaults to 0
Initial Y: Defaults to 0
Final X: Defaults to the width of the bitmap
Final Y: Defaults to the height of the bitmap
Mode: Defaults to 0 (If you don't know what this does, you can move the "mode=0" in the make_png definition to the last spot so that you don't have to constantly set it to 0. I left it here so that it has complete compatability over the previous module.)
I personally like to output the files to Graphics/Pictures, but however you use it is up to you. This
should be fine to paste over the previous Module, as I have not changed much.
Credits:
To the original author,
.
And to myself I suppose, Jaffer.