Ir para conteúdo

Xspriter


colex

Posts Recomendados

XSpriterv0.1
Extractor de Sprites em Lua



O que é o XSpriter?
O XSpriter foi desenvolvido com um intuito de aprendizagem. Este script mostra como ler ficheiros binários e, no caso de conter imagens, como extrair-las. Através deste script você poderá também adiquirir mais conhecimentos sobre a estrutura do Tibia.spr.

Este script só foi testado na versão 8.50 e 8.53, porém deverá funcionar em outras versões.

O projeto XSpriter é constituído por dois scripts (de minha autoria):
  • BinaryStream - permite criar, ler e editar ficheiros binários
  • XSpriter - o próprio extractor transforma o binário em imagens

(Para criar as imagens utilizo a biblioteca GD)

Como funciona?

Para extrair as imagens do Tibia.spr basta colocar o ficheiro na pasta do script e executar-lo. Será, então, criada uma nova pasta com o nome de Sprites, com as sprites dentro.

Scripts:
  • BinaryStream.lua


--[[
    Binary Stream
Allows you to read, edit and create new binary files
Developed by Colex (Alexandre Santos)
]]--

require("bit")

_BINARY_STREAM = {
    Position = 0
}

BinaryStream = function(filename)
    local obj = {}
    local file = io.open(filename, "rb")

    if not (file) then
        return nil
    end

    setmetatable(obj, _BINARY_STREAM)
    _BINARY_STREAM.__index = _BINARY_STREAM

    obj["Buffer"] = file:read("*all")
    obj["Length"] = obj.Buffer:len()
    obj["FileName"] = filename
    file:close()
    return obj
end

CreateBinary = function(filename)
    local obj = {}

    setmetatable(obj, _BINARY_STREAM)
    _BINARY_STREAM.__index = _BINARY_STREAM

    obj["Buffer"] = ""
    obj["Length"] = 0
    obj["FileName"] = filename

    return obj
end

---Read Functions

_BINARY_STREAM.ReadByte = function(self)
    self.Position = self.Position + 1
    return self.Buffer:byte(self.Position)
end

_BINARY_STREAM.ReadInt16 = function(self)

    local l1 = self:ReadByte()
    local l2 = bit.lshift(self:ReadByte(), 8)


    return l1 + l2
end

_BINARY_STREAM.ReadInt32 = function(self)
    local l1 = self:ReadByte()
    local l2 = bit.lshift(self:ReadByte(), 8)
    local l3 = bit.lshift(self:ReadByte(), 16)
    local l4 = bit.lshift(self:ReadByte(), 24)


    return l1 + l2 + l3 + l4
end

--Write Functions

_BINARY_STREAM.WriteByte = function(self, byte, insert)
    self.Position = self.Position + 1
    if not(insert) then
        self.Buffer = self.Buffer:sub(0,self.Position-1)..string.char(byte)..self.Buffer:sub(self.Position+1)
    else
        self.Buffer = self.Buffer:sub(0,self.Position-1)..string.char(byte)..self.Buffer:sub(self.Position)
    end
end

_BINARY_STREAM.WriteInt16 = function(self, int16, insert)
    local l1 = bit.rshift(bit.lshift(int16, 24), 24)
    local l2 = bit.rshift(bit.lshift(int16, 16), 24)


    WriteByte(l1, insert)
    WriteByte(l2, insert)
end

_BINARY_STREAM.WriteInt32 = function(self, int32, insert)
    local l1 = bit.rshift(bit.lshift(int32, 24), 24)
    local l2 = bit.rshift(bit.lshift(int32, 16), 24)
    local l3 = bit.rshift(bit.lshift(int32, 8), 24)
    local l4 = bit.rshift(int32, 24)

    WriteByte(l1, insert)
    WriteByte(l2, insert)
    WriteByte(l3, insert)
    WriteByte(l4, insert)
end

--Insert Function

_BINARY_STREAM.InsertByte = function(self, byte)
    self:WriteByte(byte, true)
end

_BINARY_STREAM.InsertInt16 = function(self, int16)
    self:WriteInt16(int16, true)
end

_BINARY_STREAM.InsertInt32 = function(self, int32)
    self:WriteInt32(int32, true)
end



--Position Functions

_BINARY_STREAM.Skip = function(self, bytes)
    self.Position = self.Position + bytes
end

_BINARY_STREAM.Seek = function(self, pos, origin)
    if (origin == 0) then --Begin
        self.Position = pos
    elseif (origin == 1) then --Current Position
        self.Position = self.Position + pos
    elseif (origin == 2) then --End
        self.Position = self.length + pos
    end
end


--Save function

_BINARY_STREAM.Save = function(self, filename)
    filename = filename or self.FileName
    local file = io.open(filename, "wb")
    file:write(self.Buffer)
    file:close()
end


  • XSpriter.lua

--[[
    XSpriter v0.1
Extract Sprites from a Tibia.spr

Developed by Colex (Alexandre Santos)
]]--

require("bit")
require("gd")
require("os")
require("BinaryStream")



---------Sprite Reader---------

local ExtractSprites = function()
    spriter = BinaryStream("Tibia.spr")
    if not(spriter) then
        print("Ficheiro Tibia.spr não encontrado!")
        return
    end

    spriter:Skip(4)

    local n_sprites = spriter:ReadInt16()
    os.execute("mkdir Sprites")

    print("Iniciando extração...")
    for n_sprite=1, n_sprites do

        print("Extraindo: " .. (math.floor(n_sprite/n_sprites*100)) .. "%")

        spriter:Seek(6 + n_sprite * 4, 0)

        spriter:Seek(spriter:ReadInt32() + 3, 0)

        local pixel = 0
        local r, g, b, color

        local sprite = gd.createTrueColor(32, 32)
        sprite:filledRectangle(0, 0, 32, 32, sprite:colorAllocate(255, 0,255))

        local offset = spriter.Position + spriter:ReadInt16();

        while spriter.Position < offset do
            local tp = spriter:ReadInt16()
            local colored = spriter:ReadInt16()
            pixel = pixel + tp
            for x = 1, colored do
                r = spriter:ReadByte()
                g = spriter:ReadByte()
                b = spriter:ReadByte()
                color = sprite:colorAllocate(r, g, b)
                sprite:setPixel(pixel%32, math.floor(pixel/32), color)
                pixel = pixel + 1
            end
        end

        sprite:png("Sprites\\"..n_sprite..".png")

    end
end



ExtractSprites()


Para executar-lo poderá utilizar o programa SciTE, ponha o XSpriter.lua do BinaryStream.lua e execute o XSpriter.lua.

Créditos a Jo3 pela estrutura do Tibia.spr

Editado por Colex
Link para o comentário
Compartilhar em outros sites

Muito bom, realmente da pra tirar um proveito disso.

Dps vo dar uma olhada sobre essa BinaryStream.lua

 

Pra melhorar um pouco acho que deveria ter um modo de extrair somente 1 sprite, mas com algumas modificações consegue-se facil.

 

Bom script :smile_positivo:

Editado por kydrai
Link para o comentário
Compartilhar em outros sites

  • 5 years later...
×
×
  • Criar Novo...