Chaos Project

RPG Maker => RPG Maker Scripts => Script Troubleshooting => Topic started by: Valdred on August 17, 2010, 05:23:57 am

Title: Saving Bitmap as a file.
Post by: Valdred on August 17, 2010, 05:23:57 am
How can I save a bitmap or sprite object as a png or bitmap file?
Title: Re: Saving Bitmap as a file.
Post by: Blizzard on August 17, 2010, 07:16:03 am
You need an exporter script.
Title: Re: Saving Bitmap as a file.
Post by: Zeriab on August 17, 2010, 07:53:21 am
I think there was a method in MACL which could save bitmaps as .png files.
I know that there was a script somewhere on 66RPG's website (http://bbs.66rpg.com/forum-rmxp-1.html). Good luck finding it ^_^
Title: Re: Saving Bitmap as a file.
Post by: G_G on August 17, 2010, 08:05:52 am
Here. Use bitmap.make_png("file name", "directory")
=begin
==============================================================================
                        Bitmap to PNG By 轮回者
==============================================================================

对Bitmap对象直接使用

bitmap_obj.make_png(name[, path])

name:保存文件名
path:保存路径

感谢66、夏娜、金圭子的提醒和帮助!
   
==============================================================================
=end

module Zlib
  class Png_File < GzipWriter
    #--------------------------------------------------------------------------
    # ● 主处理
    #--------------------------------------------------------------------------
    def make_png(bitmap_Fx,mode)
      @mode = mode
      @bitmap_Fx = bitmap_Fx
      self.write(make_header)
      self.write(make_ihdr)
      self.write(make_idat)
      self.write(make_iend)
    end
    #--------------------------------------------------------------------------
    # ● PNG文件头数据块
    #--------------------------------------------------------------------------
    def make_header
      return [0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a].pack("C*")
    end
    #--------------------------------------------------------------------------
    # ● PNG文件情报头数据块(IHDR)
    #--------------------------------------------------------------------------
    def make_ihdr
      ih_size = [13].pack("N")
      ih_sign = "IHDR"
      ih_width = [@bitmap_Fx.width].pack("N")
      ih_height = [@bitmap_Fx.height].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
    #--------------------------------------------------------------------------
    # ● 生成图像数据(IDAT)
    #--------------------------------------------------------------------------
    def make_idat
      header = "\x49\x44\x41\x54"
      case @mode # 请54~
      when 1
        data = make_bitmap_data#1
      else
        data = make_bitmap_data
      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
    #--------------------------------------------------------------------------
    # ● 从Bitmap对象中生成图像数据 mode 1(请54~)
    #--------------------------------------------------------------------------
    def make_bitmap_data1
      w = @bitmap_Fx.width
      h = @bitmap_Fx.height
      data = []
      for y in 0...h
        data.push(0)
        for x in 0...w
          color = @bitmap_Fx.get_pixel(x, y)
          red = color.red
          green = color.green
          blue = color.blue
          alpha = color.alpha
          data.push(red)
          data.push(green)
          data.push(blue)
          data.push(alpha)
        end
      end
      return data.pack("C*")
    end
    #--------------------------------------------------------------------------
    # ● 从Bitmap对象中生成图像数据 mode 0
    #--------------------------------------------------------------------------
    def make_bitmap_data
      gz = Zlib::GzipWriter.open('hoge.gz')
      t_Fx = 0
      w = @bitmap_Fx.width
      h = @bitmap_Fx.height
      data = []
      for y in 0...h
        data.push(0)
        for x in 0...w
          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)
          red = color.red
          green = color.green
          blue = color.blue
          alpha = color.alpha
          data.push(red)
          data.push(green)
          data.push(blue)
          data.push(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
    #--------------------------------------------------------------------------
    # ● PNG文件尾数据块(IEND)
    #--------------------------------------------------------------------------
    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
#------------------------------------------------------------------------------
#  关联到Bitmap。
#==============================================================================
class Bitmap
  #--------------------------------------------------------------------------
  # ● 关联
  #--------------------------------------------------------------------------
  def make_png(name="like", path="",mode=0)
    make_dir(path) if path != ""
    Zlib::Png_File.open("temp.gz") {|gz|
      gz.make_png(self,mode)
    }
    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
  #--------------------------------------------------------------------------
  # ● 生成保存路径
  #--------------------------------------------------------------------------
  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
Title: Re: Saving Bitmap as a file.
Post by: Valdred on August 17, 2010, 09:15:36 am
Thank you :D
Title: Re: Saving Bitmap as a file.
Post by: Blizzard on August 17, 2010, 10:23:06 am
Just great. If I knew this script existed, I didn't have to write my own TGA exporter that I used to create prerendered damage text image files about a year ago. ._.

Spoiler: ShowHide
#==============================================================================
# module CP
#==============================================================================

module CP
 
 module Cache
   
   WIDTH = 576
   FONT_HEIGHT = 64
   
   def self.generate_damage
     allcolors = [[ColorHP, ColorHP2], [ColorMP, ColorMP2], [ColorCritical,
         ColorCritical2], [ColorMissed, ColorMissed2], [ColorDamage,
         ColorDamage2]]
     colors = []
     allcolors.each {|c| colors.push(c[0])}
     characters = ('0'..'9').to_a + ('A'..'Z').to_a + ('a'..'z').to_a + ['-', '+', '%', ',', '!']
     $sprite = Sprite.new
     $sprite.x, $sprite.y = 160, 224
     $sprite.bitmap = Bitmap.new(320, 32)
     $sprite.bitmap.clear
     $sprite.bitmap.draw_text(0, 0, 320, 32, '-> Start', 1)
     damages = self.create_damage(allcolors, characters)
     Graphics.update
     rects = self.generate_positions(damages[colors[0]], characters)
     Graphics.update
     height = rects.delete(0)
 ### rect save
     data = []
     characters.each {|c| data.push("'#{c}' => Rect.new(#{rects[c].x/2}, #{rects[c].y/2}, #{rects[c].width/2}, #{rects[c].height/2})")}
     file = File.open('dmg.txt', 'w')
     file.write("{\n" + data.join(",\n") + "\n}\n")
     file.close
 ### bitmap save into tga
     w1 = WIDTH % 256
     w2 = WIDTH / 256
     h1 = height % 256
     h2 = height / 256
     header = "\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00" + w1.chr + w2.chr + h1.chr + h2.chr + "\x20\x08"
     trail = "\x00\x00\x00\x00\x00\x00\x00\x00TRUEVISION-XFILE\x00"
     colors.each {|c|
         Graphics.update
         bitmap = self.create_bitmap(damages[c], characters, rects, height)
         Graphics.update
         stream = self.create_stream(bitmap)
         Graphics.update
         filename = sprintf("%d-%d-%d.tga", c.red.to_i, c.green.to_i, c.blue.to_i)
         file = File.open(filename, 'wb')
         file.write(header + stream + trail)
         file.close}
     $sprite.dispose
   end
   
   def self.create_bitmap(damages, characters, rects, height)
     bitmap = Bitmap.new(WIDTH, height)
     characters.each {|c|
         r = Rect.new(0, 0, rects[c].width, rects[c].height)
         bitmap.blt(rects[c].x, rects[c].y, damages[c], r)}
     return bitmap
   end
   
   def self.create_stream(bitmap)
     stream = []
     (0...bitmap.height).to_a.reverse.each {|y|
 if y % 40 == 0
           $sprite.bitmap.clear
           $sprite.bitmap.draw_text(0, 0, 320, 32, 'Stream ' + ((bitmap.height - y) * 100 / bitmap.height).to_s + '%', 1)
           Graphics.update
 end
 line = []
         (0...bitmap.width).each {|x|
             c = bitmap.get_pixel(x, y)
             line.push(c.blue.to_i.chr + c.green.to_i.chr + c.red.to_i.chr + c.alpha.to_i.chr)}
 stream.push(line.join(''))}
     return stream.join('')
   end
   
   def self.generate_positions(sprites, characters)
     x = y = 0
     rects = {}
     characters.each {|c|
         if x + sprites[c].width >= WIDTH
           y += sprites[c].height
           x = 0
         end
         rects[c] = Rect.new(x, y, sprites[c].width, sprites[c].height)
         x += sprites[c].width}
     rects[0] = y + rects[characters[0]].height
     return rects
   end
   
   def self.create_damage(colors, characters)
     damages = {}
     b1 = Bitmap.new(FONT_HEIGHT, FONT_HEIGHT)
     b1.font.name = 'Georgia'
     b1.font.size = FONT_HEIGHT
     b1.font.bold = false#true
     b1.font.italic = true
     b2 = b1.clone
     colors.each {|ary|
         color1, color2 = ary
         damages[color1] = {}
         characters.each {|c|
             self.draw_text_on(b1, c, color1)
             self.draw_text_on(b2, c, color2)
             rect = self.get_text_size(b1)
             damages[color1][c] = self.transfer_text(b1, b2, rect)}
         $sprite.bitmap.clear
         $sprite.bitmap.draw_text(0, 0, 320, 32, sprintf("%d, %d, %d", color1.red.to_i, color1.green.to_i, color1.blue.to_i), 1)
 Graphics.update}
     return damages
   end
   
   def self.draw_text_on(bitmap, text, color)
     bitmap.clear
     bitmap.font.color = Color.new(0, 0, 0)
     bitmap.draw_text(-5, -5, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-5, -3, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-3, -5, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-3, -3, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     #bitmap.font.color = Color.new(0, 0, 0, 192)
     bitmap.draw_text(-6, -6, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-6, -5, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-6, -4, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-6, -3, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-6, -2, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-5, -2, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-4, -2, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-3, -2, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-2, -2, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-2, -3, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-2, -4, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-2, -5, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-2, -6, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-3, -6, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-4, -6, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-5, -6, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     #bitmap.font.color = Color.new(0, 0, 0, 128)
     bitmap.draw_text(-5, -1, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-4, -1, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-3, -1, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-2, -1, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-1, -5, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-1, -4, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-1, -3, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-1, -2, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-1, -1, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-4, 0, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-3, 0, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-2, 0, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(-1, 0, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(0, -4, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(0, -3, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(0, -2, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.draw_text(0, -1, FONT_HEIGHT, FONT_HEIGHT, text, 1)
     bitmap.font.color = color
     bitmap.draw_text(-4, -4, FONT_HEIGHT, FONT_HEIGHT, text, 1)
   end
   
   def self.get_text_size(bitmap)
     minx, maxx, miny, maxy = bitmap.width - 1, 0, bitmap.height - 1, 0
     (0...bitmap.height).each {|y| (0...bitmap.width).each {|x|
         color = bitmap.get_pixel(x, y)
         if color.alpha > 0
           minx = x if minx > x
           maxx = x if maxx < x
           miny = y if miny > y
           maxy = y if maxy < y
         end}}
     return Rect.new(minx - 1, miny, maxx - minx + 3, maxy - miny + 1)
   end
   
   def self.transfer_text(b1, b2, rect)
     h, o = rect.height, rect.height / 4
     bitmap = Bitmap.new(rect.width, b1.height)
     (0...h).each {|y| (0...rect.width).each {|x|
         c1 = b1.get_pixel(x + rect.x, y + rect.y)
         if c1.alpha > 0
           c2 = b2.get_pixel(x + rect.x, y + rect.y)
           if y >= (h - o) / 2 && y < (h + o) / 2
             i = (h - o) / 2
           else
             i = ((y < h / 2) ? y : h - y - 1)
           end
           r = c2.red + (c1.red - c2.red) * i / ((h - o) / 2)
           g = c2.green + (c1.green - c2.green) * i / ((h - o) / 2)
           b = c2.blue + (c1.blue - c2.blue) * i / ((h - o) / 2)
           bitmap.set_pixel(x, y + rect.y, Color.new(r, g, b, c1.alpha))
         end}}
     return bitmap
   end
 
 end
 
end