Ich hatte dazu mal ein Script geschrieben:
	Code: 
	class PngWriter
  PNGException = Class.new(RuntimeError)
  # Color types
  INDEXED = 3
  RGB = 2
  RGBA = 6
  # Filter methods
  NONE = 0
  
  attr_accessor :header, :bitmap
  attr_reader :chunks, :mode, :alpha_color, :palette, :palette_offset, :filter_method, :bit_depth
  
  # @param [Bitmap] pixeldata
  def initialize bitmap
    @bitmap = bitmap
    @header = Header.new self
    @chunks = []
    @mode = RGBA
    @bit_depth = 8
    @palette = {}
    @palette_offset = 0
    @palette_size = 0
    @filter_method = NONE # currently not implemented
  end
  
  # @param [INDEXED, RGB, RGBA, NONE] mode color type constant
  def set_mode mode
    @mode = mode    
  end
  
  # set PngWriter to rgba mode. In this mode PngWriter stores each pixel as 32 bit bytestring
  def use_rgba
    set_mode RGBA
  end
  
  # set PngWriter to rgb mode. In this mode PngWriter stores each pixel as 24 bit bytestring
  # if you choose rgb mode, all transparency information will be lost
  def use_rgb
    set_mode RGB
  end
  
  # set PngWriter to indexing mode. In this mode PngWriter stores each used color
  # into a 24 bit table. The pixel values in the images are stored as <=8 bit table index.
  def use_indexing
    set_mode INDEXED
  end
  
  # writes the image to the given file
  # @param [String] filename path to the file
  def write_to_file filename
    File.open(filename, "wb") {|io| write io }
  end
  
  # writes the image to the given buffer
  # @param [String, IO] io Object which responds to #<<(String)
  def write io
    write_header io
    @header.write io
    if @mode == INDEXED
      compute_palette
      Palette.new(self).write io
      Transparency.new(self).write io if @palette_offset >= 0
    end
    Image.new(self).write io
    @chunks.each {|chunk| chunk.write io}
    Eof.new(self).write io
    io
  end
  
  
  private
  
  def write_header buffer
    buffer << [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A].pack("C8")
  end
  
  def compute_palette
    @palette.clear
    index = 0
    alpha_index = 1
    (0...bitmap.height).each do |y|
      (0...bitmap.width).each do |x|
        color = bitmap.get_pixel(x,y)
        if !@palette.has_key?(color) then
          if color.alpha == 255 then
            @palette[bitmap.get_pixel(x,y)] = (index+=1) 
          else
            @palette[bitmap.get_pixel(x,y)] = (alpha_index-=1)
          end
        end
      end
    end
    @palette_offset = -alpha_index
    max = (1<<@bit_depth)
    raise PNGException.new("Indexed palette has more than #{max} entries") if @palette.size > max
  end
  
  class Chunk
    def data
      ""
    end
    
    def initialize png
       @png = png
    end
    
    def write buffer
      chunk_data = data
      fields = chunk_name << chunk_data
      crc = [Zlib.crc32(fields)].pack("N")
      buffer << [chunk_data.length].pack("N") << fields << crc
    end
    
  end  
  
  class Header < Chunk    
        
    def chunk_name
      "IHDR"
    end
    
    def data
      bitmap = @png.bitmap
      color_type = @png.mode
      bit_depth = @png.bit_depth
      interlace_method = 0
      [bitmap.width, bitmap.height, bit_depth, color_type, 0, 0, interlace_method].pack("N2C5")
    end
    
  end
  
  class Palette < Chunk
    
    def chunk_name
      "PLTE"
    end
    
    def data
      palette = @png.palette
      offset = @png.palette_offset
      buffer = "\00" * (palette.size * 3)
      palette.each do |key, value|
        i = (value+offset)*3
        buffer[i] = Integer(key.red).chr
        buffer[i+1] = Integer(key.green).chr
        buffer[i+2] = Integer(key.blue).chr
      end
      buffer
    end
    
  end
  
  class Transparency < Chunk
    
    def chunk_name
      "tRNS"
    end
    
    def data
      buffer = "\00" * (@png.palette_offset+1)
      @png.palette.each do |color, value|
        buffer[-value] = Integer(color.alpha).chr if value <= 0 
      end
      buffer
    end
    
  end
  
  class Image < Chunk
    
    def chunk_name
      "IDAT"
    end
    
    def data
      compress(@png.mode == INDEXED ? scanlines_indexed : scanlines_rgba)
    end
    
    def scanlines_indexed
      bitmap = @png.bitmap
      palette = @png.palette
      offset = @png.palette_offset
      buffer = "\00" * ((bitmap.width+1) * bitmap.height)
      filter = NONE
      i = -1
      (0...bitmap.height).each do |y|
        buffer[i+=1] = filter
        (0...bitmap.width).each do |x|
          buffer[i+=1] = palette[bitmap.get_pixel(x, y)] + offset
        end
      end
      buffer
    end
    
    def scanlines_rgba
      bitmap = @png.bitmap
      alpha = @png.mode == RGBA
      buffer = "\00" * (bitmap.width * bitmap.height * (alpha ? 4 : 3) +  bitmap.height)
      filter = @png.filter_method
      i = -1
      (0...bitmap.height).each do |y|
        buffer[i+=1] = filter
        (0...bitmap.width).each do |x|
          color = bitmap.get_pixel(x, y)
          buffer[i+=1] = Integer(color.red).chr
          buffer[i+=1] = Integer(color.green).chr
          buffer[i+=1] = Integer(color.blue).chr
          buffer[i+=1] = Integer(color.alpha).chr if alpha
        end
      end
      buffer
    end
    
    def compress buffer
      Zlib::Deflate.deflate(buffer)
    end
    
  end
  
  class Eof < Chunk
    def chunk_name
      "IEND"
    end
  end
  
  module Filters
    
  end
  
end
class Color
  # returns a hash value for color objects
  # @return [Fixnum]
  def hash
    (Integer(red) << 22) ^ (Integer(green) << 14) ^ (Integer(blue) << 6) ^ Integer(alpha)
  end
end 
 Einfach in Scripteditor kopieren. Verwendung funktioniert folgendermaßen:
	Code: 
	# laden eines beliebigen Bildes
bitmap = RPG::Cache.picture("mein_picture")
png = PngWriter.new(bitmap)
png.write_to_file("mein_bild.png") 
 Du kannst Grafiken in drei verschiedenen Modi abspeichern: RGB, RGBA und INDEXED. RGB braucht 24 bit pro Pixel, hat dafür aber keine Transparenz. RGBA braucht 32 bit pro Pixel. INDEXED braucht nur 8 bit pro Pixel, dafür sind aber nur 256 Farben pro Bild erlaubt. Außerdem ist INDEXED etwas langsamer beim Speichern der Datei als die anderen beiden Verfahren. Die Grafiken in der RTP sind üblicherweise im INDEXED Modus gespeichert. Der Speicherplatzunterschied zwischen RGB, RGBA und INDEXED ist allerdings nicht soo extrem hoch (da die Bilddaten hinterher eh komprimiert werden), von daher ist es egal was du verwendest. Generell gilt: Alle drei Verfahren sind recht langsam (brauchen ~200 ms für mittel große Bilder). Daher nicht jeden Frame aufrufen ^^°
	Code: 
	png = PngWriter.new(bitmap)
# je nachdem welchen Modus du willst
png.use_rgba # STANDARD
png.use_rgb
png.use_indexing