Ergebnis 1 bis 3 von 3

Thema: Sprite to File

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1

    Doktor von Stein Gast

    Sprite to File

    Wie kann man einen Sprite, der im Spiel gezeichnet wurde, in ein neues Bild im Spieleordner "konvertieren"? Meine Kentnisse mit dem File-Objekt reichen dazu nicht aus.

  2. #2
    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 ^^°

    Die Modi setzt du folgenderweise:
    Code:
    png = PngWriter.new(bitmap)
    # je nachdem welchen Modus du willst
    png.use_rgba # STANDARD
    png.use_rgb
    png.use_indexing

    Geändert von -KD- (27.10.2011 um 16:46 Uhr)

  3. #3

    Doktor von Stein Gast
    Danke.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •