better organization of modules for the tools

This commit is contained in:
Andre Leiradella 2015-06-14 11:37:11 -03:00
parent c1a895f4fa
commit 9fea973eb0
14 changed files with 590 additions and 672 deletions

10
etc/luai/lua/djb2.lua Normal file
View File

@ -0,0 +1,10 @@
return function( str )
local hash = 5381
for i = 1, #str do
hash = hash * 33 + str:byte( i )
hash = hash & 0xffffffff
end
return hash
end

16
etc/luai/lua/mkis.lua Normal file
View File

@ -0,0 +1,16 @@
local writer = require 'writer'
local mkrle = require 'mkrle'
return function( images, limit )
local out = writer()
out:add16( #images )
for _, png in ipairs( images ) do
local rle = mkrle( png, limit )
out:add32( rle:getsize() )
out:addwriter( rle )
end
return out
end

115
etc/luai/lua/mkrle.lua Normal file
View File

@ -0,0 +1,115 @@
local image = require 'image'
local rgbto16 = require 'rgbto16'
local writer = require 'writer'
local function getpixel( png, x, y, transp )
local r, g, b, a = image.split( png:getPixel( x, y ) )
local c = rgbto16( r, g, b )
if c == transp then
r, g, b, a = 0, 0, 0, 0
end
if a >= 0 and a <= 31 then
a = 0 -- transparent
elseif a >= 32 and a <= 95 then
a = 1 -- 25%
elseif a >= 96 and a <= 159 then
a = 2 -- 50%
elseif a >= 160 and a <= 223 then
a = 3 -- 75%
else
a = 4 -- opaque
end
return rgbto16( r, g, b ), a
end
local function rlerow( png, y, limit, transp )
local rle = {}
local width = png:getWidth()
local used = 0
local numcols = ( width + ( limit - 1 ) ) // limit
for i = 1, numcols do
rle[ #rle + 1 ] = 0
end
for xx = 0, width - 1, limit do
rle[ xx // limit + 1 ] = #rle
local x = xx
rle[ #rle + 1 ] = 0
local runs = #rle
while x < ( xx + limit ) and x < width do
local _, a = getpixel( png, x, y, transp )
local count = 0
local xsave = x
while x < ( xx + limit ) and x < width do
local c, aa = getpixel( png, x, y, transp )
if aa ~= a then
break
end
count = count + 1
x = x + 1
end
rle[ #rle + 1 ] = ( a << 13 | count )
rle[ runs ] = rle[ runs ] + 1
if a ~= 0 then
for i = 0, count - 1 do
local c = getpixel( png, xsave + i, y, transp )
rle[ #rle + 1 ] = c
used = used + 1
end
end
end
end
local final = writer()
for i = 1, #rle do
final:add16( rle[ i ] )
end
return final, used
end
return function( png, limit, transp )
local width, height = png:getSize()
local rows = {}
local used = 0
limit = limit or 1e10
for y = 0, height - 1 do
local row, u = rlerow( png, y, limit, transp )
rows[ y ] = row
used = used + u
end
local rle = writer()
rle:add16( width )
rle:add16( height )
rle:add32( used )
local count = 0
for y = 0, height - 1 do
rle:add32( count )
count = count + rows[ y ]:getsize()
end
for y = 0, height - 1 do
rle:addwriter( rows[ y ] )
end
return rle
end

19
etc/luai/lua/mkts.lua Normal file
View File

@ -0,0 +1,19 @@
local writer = require 'writer'
return function( images )
local res = writer()
res:add16( images[ 1 ]:getWidth() )
res:add16( images[ 1 ]:getHeight() )
res:add16( #images )
for _, img in pairs( images ) do
for y = 0, img:getHeight() - 1 do
for x = 0, img:getWidth() - 1 do
res:add16( getpixel( img, x, y ) )
end
end
end
return res
end

7
etc/luai/lua/rgbto16.lua Normal file
View File

@ -0,0 +1,7 @@
return function( r, g, b )
r = r * 32 // 256
g = g * 64 // 256
b = b * 32 // 256
return ( r << 11 ) | ( g << 5 ) | b
end

169
etc/luai/lua/tmx.lua Normal file
View File

@ -0,0 +1,169 @@
local image = require 'xml'
local xml = require 'xml'
return {
load = function( filename )
local dir = path.split( filename ) .. path.separator
local file = assert( io.open( filename ) )
file:read( '*l' ) -- skip <?xml ... ?>
local contents = file:read( '*a' )
file:close()
local tmx = xml.parse( contents )
local map = {}
map.version = xml.findAttr( tmx, 'version' )
map.orientation = xml.findAttr( tmx, 'orientation' )
map.width = tonumber( xml.findAttr( tmx, 'width' ) )
map.height = tonumber( xml.findAttr( tmx, 'height' ) )
map.tilewidth = tonumber( xml.findAttr( tmx, 'tilewidth' ) )
map.tileheight = tonumber( xml.findAttr( tmx, 'tileheight' ) )
map.widthpixels = map.width * map.tilewidth
map.heightpixels = map.height * map.tileheight
map.backgroundcolor = image.color( 0, 0, 0 )
local backgroundcolor = xml.findAttr( tmx, 'backgroundcolor' )
if backgroundcolor then
backgroundcolor = tonumber( backgroundcolor, 16 )
local r = backgroundcolor >> 16
local g = backgroundcolor >> 8 & 255
local b = backgroundcolor & 255
map.backgroundcolor = image.color( r, g, b )
end
local tilesets = {}
map.tilesets = tilesets
local gids = {}
map.gids = gids
for _, child in ipairs( tmx ) do
if child.label == 'tileset' then
local tileset =
{
firstgid = tonumber( xml.findAttr( child, 'firstgid' ) ),
name = xml.findAttr( child, 'name' ),
tilewidth = tonumber( xml.findAttr( child, 'tilewidth' ) ),
tileheight = tonumber( xml.findAttr( child, 'tileheight' ) )
}
if map.tilewidth ~= tileset.tilewidth or map.tileheight ~= tileset.tileheight then
error( string.format( 'tile dimensions in %s are different from tile dimensions in map', tileset.name ) )
end
for _, child2 in ipairs( child ) do
if child2.label == 'image' then
local filename = path.realpath( dir .. xml.findAttr( child2, 'source' ) )
tileset.image = image.load( filename )
local trans = xml.findAttr( child2, 'trans' )
if trans then
trans = tonumber( trans, 16 )
local r = trans >> 16
local g = trans >> 8 & 255
local b = trans & 255
trans = image.color( r, g, b )
tileset.image:colorToAlpha( trans )
end
end
end
tileset.lastgid = tileset.firstgid + ( tileset.image:getWidth() // tileset.tilewidth ) * ( tileset.image:getHeight() // tileset.tileheight ) - 1
local imagewidth = tileset.image:getWidth()
local tilewidth = tileset.tilewidth
local tileheight = tileset.tileheight
for i = tileset.firstgid, tileset.lastgid do
local id = i - tileset.firstgid
local j = id * tileset.tilewidth
local x = j % imagewidth
local y = math.floor( j / imagewidth ) * tileset.tileheight
gids[ i ] =
{
tileset = tileset,
id = id,
x = x,
y = y,
width = tilewidth,
height = tileheight,
image = tileset.image:sub( x, y, x + tilewidth - 1, y + tileheight - 1 )
}
end
tilesets[ #tilesets + 1 ] = tileset
end
end
local layers = {}
map.layers = layers
for _, child in ipairs( tmx ) do
if child.label == 'layer' then
local layer =
{
name = xml.findAttr( child, 'name' ),
width = tonumber( xml.findAttr( child, 'width' ) ),
height = tonumber( xml.findAttr( child, 'height' ) ),
tiles = {}
}
for _, child2 in ipairs( child ) do
if child2.label == 'data' then
local index = 1
for y = 1, layer.height do
local row = {}
layer.tiles[ y ] = row
for x = 1, layer.width do
local tile = child2[ index ]
index = index + 1
row[ x ] = tonumber( xml.findAttr( tile, 'gid' ) )
end
end
end
end
layers[ #layers + 1 ] = layer
end
end
return map
end,
render = function( map, layers )
local png = image.create( map.widthpixels, map.heightpixels, image.color( 0, 0, 0, 0 ) )
for _, layer in ipairs( map.layers ) do
if layers[ layer.name ] then
local yy = 0
for y = 1, layer.height do
local row = layer.tiles[ y ]
local xx = 0
for x = 1, layer.width do
if row[ x ] ~= 0 then
local tile = map.gids[ row[ x ] ]
if not tile then
error( 'Unknown gid ' .. row[ x ] .. ' in layer ' .. layer.name )
end
tile.image:blit( png, xx, yy )
end
xx = xx + map.tilewidth
end
yy = yy + map.tileheight
end
end
end
return png
end
}

41
etc/luai/lua/writer.lua Normal file
View File

@ -0,0 +1,41 @@
return function()
return {
bytes = {},
add8 = function( self, x )
self.bytes[ #self.bytes + 1 ] = string.char( x & 255 )
end,
add16 = function( self, x )
self.bytes[ #self.bytes + 1 ] = string.char( ( x >> 8 ) & 255, x & 255 )
end,
add32 = function( self, x )
self.bytes[ #self.bytes + 1 ] = string.char( ( x >> 24 ) & 255, ( x >> 16 ) & 255, ( x >> 8 ) & 255, x & 255 )
end,
addstring = function( self, str )
self.bytes[ #self.bytes + 1 ] = str
end,
addwriter = function( self, rle )
self.bytes[ #self.bytes + 1 ] = table.concat( rle.bytes )
end,
align = function( self, x )
local size = self:getsize()
local new_size = ( size + x - 1 ) & -x
while size < new_size do
self:add8( 0 )
size = size + 1
end
end,
getbytes = function( self )
self.bytes = { table.concat( self.bytes ) }
return self.bytes[ 1 ]
end,
getsize = function( self )
return #self:getbytes()
end,
save = function( self, name )
local file = assert( io.open( name, 'wb' ) )
file:write( self:getbytes() )
file:close()
end
}
end

105
etc/luai/lua/xml.lua Normal file
View File

@ -0,0 +1,105 @@
local function prettyPrint( node, file, ident )
file = file or io.stdout
ident = ident or 0
if type( node ) == 'table' then
file:write( ( ' ' ):rep( ident ), '<', node.label )
for attr, value in pairs( node.xarg ) do
file:write( ' ', attr, '="', value, '"' )
end
if node.empty then
file:write( '/>\n' )
else
file:write( '>\n' )
for _, child in ipairs( node ) do
prettyPrint( child, file, ident + 2 )
end
file:write( ( ' ' ):rep( ident ), '</', node.label, '>\n' )
end
else
file:write( ( ' ' ):rep( ident ), node, '\n' )
end
end
local function findNode( node, label )
if type( node ) == 'table' then
if node.label == label then
return node
end
for i = 1, #node do
local res = findNode( node[ i ], label )
if res then
return res
end
end
end
end
local function parseargs(s)
local arg = {}
string.gsub(s, "([%w:]+)=([\"'])(.-)%2", function (w, _, a)
arg[w] = a
end)
return arg
end
return {
parse = function(s)
local stack = {}
local top = {}
table.insert(stack, top)
local ni,c,label,xarg, empty
local i, j = 1, 1
while true do
ni,j,c,label,xarg, empty = string.find(s, "<(%/?)([%w:]+)(.-)(%/?)>", i)
if not ni then break end
local text = string.sub(s, i, ni-1)
if not string.find(text, "^%s*$") then
table.insert(top, text)
end
if empty == "/" then -- empty element tag
table.insert(top, {label=label, xarg=parseargs(xarg), empty=1})
elseif c == "" then -- start tag
top = {label=label, xarg=parseargs(xarg)}
table.insert(stack, top) -- new level
else -- end tag
local toclose = table.remove(stack) -- remove top
top = stack[#stack]
if #stack < 1 then
error("nothing to close with "..label)
end
if toclose.label ~= label then
error("trying to close "..toclose.label.." with "..label)
end
table.insert(top, toclose)
end
i = j+1
end
local text = string.sub(s, i)
if not string.find(text, "^%s*$") then
table.insert(stack[#stack], text)
end
if #stack > 1 then
error("unclosed "..stack[#stack].label)
end
return stack[1][1]
end,
findNode = findNode,
findAttr = function( node, name )
for key, value in pairs( node.xarg ) do
if key == name then
return value
end
end
end,
prettyPrint = prettyPrint
}

45
etc/rlimageset.lua Normal file
View File

@ -0,0 +1,45 @@
local image = require 'image'
local mkis = require 'mkis'
return function( args )
if #args == 0 then
io.write[[
rlimageset.lua creates an imageset containing all files given on the command
line.
Usage: luai rlimageset.lua [ options ] images...
--output <file> writes the imageset to the given file
--margin x sets the pixel limit on RLE runs on a row (must be equal to
RL_BACKGRND_MARGIN)
]]
return 0
end
local output, limit
local images = {}
do
local i = 1
while i <= #args do
if args[ i ] == '--output' then
i = i + 1
output = args[ i ]
elseif args[ i ] == '--margin' then
i = i + 1
limit = tonumber( args[ i ] )
else
images[ #images + 1 ] = image.load( args[ i ] )
end
i = i + 1
end
end
local out = mkis( images, limit )
out:save( output )
return 0
end

View File

@ -1,118 +1,8 @@
local image = require 'image'
local path = require 'path'
local rleimage
local xml = [===[
local function prettyPrint( node, file, ident )
file = file or io.stdout
ident = ident or 0
if type( node ) == 'table' then
file:write( ( ' ' ):rep( ident ), '<', node.label )
for attr, value in pairs( node.xarg ) do
file:write( ' ', attr, '="', value, '"' )
end
if node.empty then
file:write( '/>\n' )
else
file:write( '>\n' )
for _, child in ipairs( node ) do
prettyPrint( child, file, ident + 2 )
end
file:write( ( ' ' ):rep( ident ), '</', node.label, '>\n' )
end
else
file:write( ( ' ' ):rep( ident ), node, '\n' )
end
end
local function findNode( node, label )
if type( node ) == 'table' then
if node.label == label then
return node
end
for i = 1, #node do
local res = findNode( node[ i ], label )
if res then
return res
end
end
end
end
local function parseargs(s)
local arg = {}
string.gsub(s, "([%w:]+)=([\"'])(.-)%2", function (w, _, a)
arg[w] = a
end)
return arg
end
return
{
parse = function(s)
local stack = {}
local top = {}
table.insert(stack, top)
local ni,c,label,xarg, empty
local i, j = 1, 1
while true do
ni,j,c,label,xarg, empty = string.find(s, "<(%/?)([%w:]+)(.-)(%/?)>", i)
if not ni then break end
local text = string.sub(s, i, ni-1)
if not string.find(text, "^%s*$") then
table.insert(top, text)
end
if empty == "/" then -- empty element tag
table.insert(top, {label=label, xarg=parseargs(xarg), empty=1})
elseif c == "" then -- start tag
top = {label=label, xarg=parseargs(xarg)}
table.insert(stack, top) -- new level
else -- end tag
local toclose = table.remove(stack) -- remove top
top = stack[#stack]
if #stack < 1 then
error("nothing to close with "..label)
end
if toclose.label ~= label then
error("trying to close "..toclose.label.." with "..label)
end
table.insert(top, toclose)
end
i = j+1
end
local text = string.sub(s, i)
if not string.find(text, "^%s*$") then
table.insert(stack[#stack], text)
end
if #stack > 1 then
error("unclosed "..stack[#stack].label)
end
return stack[1][1]
end,
findNode = findNode,
findAttr = function( node, name )
for key, value in pairs( node.xarg ) do
if key == name then
return value
end
end
end,
prettyPrint = prettyPrint
}
]===]
xml = load( xml, 'xml.lua' )()
local image = require 'image'
local path = require 'path'
local tmx = require 'tmx'
local mkrle = require 'mkrle'
local writer = require 'writer'
local function dump( t, i )
i = i or 0
@ -151,213 +41,8 @@ local function split( str, sep )
return res
end
local function loadtmx( filename )
local dir = path.split( filename ) .. path.separator
local file, err = io.open( filename )
if not file then
error( err )
end
file:read( '*l' ) -- skip <?xml ... ?>
local contents = file:read( '*a' )
file:close()
local tmx = xml.parse( contents )
local map = {}
map.version = xml.findAttr( tmx, 'version' )
map.orientation = xml.findAttr( tmx, 'orientation' )
map.width = tonumber( xml.findAttr( tmx, 'width' ) )
map.height = tonumber( xml.findAttr( tmx, 'height' ) )
map.tilewidth = tonumber( xml.findAttr( tmx, 'tilewidth' ) )
map.tileheight = tonumber( xml.findAttr( tmx, 'tileheight' ) )
map.widthpixels = map.width * map.tilewidth
map.heightpixels = map.height * map.tileheight
map.backgroundcolor = image.color( 0, 0, 0 )
local backgroundcolor = xml.findAttr( tmx, 'backgroundcolor' )
if backgroundcolor then
backgroundcolor = tonumber( backgroundcolor, 16 )
local r = backgroundcolor >> 16
local g = backgroundcolor >> 8 & 255
local b = backgroundcolor & 255
map.backgroundcolor = image.color( r, g, b )
end
local tilesets = {}
map.tilesets = tilesets
local gids = {}
map.gids = gids
for _, child in ipairs( tmx ) do
if child.label == 'tileset' then
local tileset =
{
firstgid = tonumber( xml.findAttr( child, 'firstgid' ) ),
name = xml.findAttr( child, 'name' ),
tilewidth = tonumber( xml.findAttr( child, 'tilewidth' ) ),
tileheight = tonumber( xml.findAttr( child, 'tileheight' ) )
}
if map.tilewidth ~= tileset.tilewidth or map.tileheight ~= tileset.tileheight then
error( string.format( 'tile dimensions in %s are different from tile dimensions in map', tileset.name ) )
end
for _, child2 in ipairs( child ) do
if child2.label == 'image' then
local filename = path.realpath( dir .. xml.findAttr( child2, 'source' ) )
tileset.image = image.load( filename )
local trans = xml.findAttr( child2, 'trans' )
if trans then
trans = tonumber( trans, 16 )
local r = trans >> 16
local g = trans >> 8 & 255
local b = trans & 255
trans = image.color( r, g, b )
tileset.image:colorToAlpha( trans )
end
end
end
tileset.lastgid = tileset.firstgid + ( tileset.image:getWidth() // tileset.tilewidth ) * ( tileset.image:getHeight() // tileset.tileheight ) - 1
local imagewidth = tileset.image:getWidth()
local tilewidth = tileset.tilewidth
local tileheight = tileset.tileheight
for i = tileset.firstgid, tileset.lastgid do
local id = i - tileset.firstgid
local j = id * tileset.tilewidth
local x = j % imagewidth
local y = math.floor( j / imagewidth ) * tileset.tileheight
gids[ i ] =
{
tileset = tileset,
id = id,
x = x,
y = y,
width = tilewidth,
height = tileheight,
image = tileset.image:sub( x, y, x + tilewidth - 1, y + tileheight - 1 )
}
end
tilesets[ #tilesets + 1 ] = tileset
end
end
local layers = {}
map.layers = layers
for _, child in ipairs( tmx ) do
if child.label == 'layer' then
local layer =
{
name = xml.findAttr( child, 'name' ),
width = tonumber( xml.findAttr( child, 'width' ) ),
height = tonumber( xml.findAttr( child, 'height' ) ),
tiles = {}
}
for _, child2 in ipairs( child ) do
if child2.label == 'data' then
local index = 1
for y = 1, layer.height do
local row = {}
layer.tiles[ y ] = row
for x = 1, layer.width do
local tile = child2[ index ]
index = index + 1
row[ x ] = tonumber( xml.findAttr( tile, 'gid' ) )
end
end
end
end
layers[ #layers + 1 ] = layer
end
end
return map
end
local function render( map, layers )
local png = image.create( map.widthpixels, map.heightpixels, image.color( 0, 0, 0, 0 ) )
for _, layer in ipairs( map.layers ) do
if layers[ layer.name ] then
local yy = 0
for y = 1, layer.height do
local row = layer.tiles[ y ]
local xx = 0
for x = 1, layer.width do
if row[ x ] ~= 0 then
local tile = map.gids[ row[ x ] ]
if not tile then
error( 'Unknown gid ' .. row[ x ] .. ' in layer ' .. layer.name )
end
tile.image:blit( png, xx, yy )
end
xx = xx + map.tilewidth
end
yy = yy + map.tileheight
end
end
end
return png
end
local function newwriter()
return {
content = {},
writeu8 = function( self, x )
self.content[ #self.content + 1 ] = string.char( x & 255 )
end,
writeu16 = function( self, x )
self.content[ #self.content + 1 ] = string.char( ( x >> 8 ) & 255, x & 255 )
end,
writeu32 = function( self, x )
self.content[ #self.content + 1 ] = string.char( ( x >> 24 ) & 255, ( x >> 16 ) & 255, ( x >> 8 ) & 255, x & 255 )
end,
prependu32 = function( self, x )
table.insert( self.content, 1, string.char( ( x >> 24 ) & 255, ( x >> 16 ) & 255, ( x >> 8 ) & 255, x & 255 ) )
end,
append = function( self, bytes )
self.content[ #self.content + 1 ] = bytes
end,
save = function( self, filename )
local file, err = io.open( filename, 'wb' )
if not file then error( err ) end
file:write( table.concat( self.content ) )
file:close()
end,
size = function( self, filename )
self.content = { table.concat( self.content ) }
return #self.content[ 1 ]
end,
getcontent = function( self )
self.content = { table.concat( self.content ) }
return self.content[ 1 ]
end
}
end
local function list_cmd( args )
local map = loadtmx( args[ 1 ] )
local map = tmx.load( args[ 1 ] )
local layers = false
local tilesets = false
@ -389,7 +74,7 @@ local function list_cmd( args )
end
local function render_cmd( args )
local map = loadtmx( args[ 1 ] )
local map = tmx.load( args[ 1 ] )
local layers = {}
for i = 3, #args do
@ -403,11 +88,11 @@ local function render_cmd( args )
end
local dir, name, ext = path.split( args[ 1 ] )
render( map, layers ):save( dir .. path.separator .. name .. '.png' )
tmx.render( map, layers ):save( dir .. path.separator .. name .. '.png' )
end
local function compile_cmd( args )
local map = loadtmx( args[ 1 ] )
local map = tmx.load( args[ 1 ] )
local layers = {}
local coll, limit
@ -515,18 +200,18 @@ local function compile_cmd( args )
-- rl_tileset_t
do
local out = newwriter()
local out = writer()
out:writeu16( map.tilewidth )
out:writeu16( map.tileheight )
out:writeu16( #built.tiles )
out:add16( map.tilewidth )
out:add16( map.tileheight )
out:add16( #built.tiles )
for _, tile in ipairs( built.tiles ) do
for y = 0, map.tileheight - 1 do
for x = 0, map.tilewidth - 1 do
local r, g, b = image.split( tile:getPixel( x, y ) )
r, g, b = r * 31 // 255, g * 63 // 255, b * 31 // 255
out:writeu16( ( r << 11 ) | ( g << 5 ) | b )
out:add16( ( r << 11 ) | ( g << 5 ) | b )
end
end
end
@ -536,14 +221,14 @@ local function compile_cmd( args )
-- rl_imageset_t
do
local out = newwriter()
local out = writer()
out:writeu16( #built.images )
out:add16( #built.images )
for _, image in ipairs( built.images ) do
local rle = rleimage( image, limit ):get()
out:writeu32( #rle )
out:append( rle )
local res = mkrle( image, limit )
out:add32( res:getsize() )
out:addwriter( res )
end
out:save( filename .. '.ims' )
@ -551,22 +236,22 @@ local function compile_cmd( args )
-- rl_map_t
do
local out = newwriter()
local out = writer()
out:writeu16( map.width )
out:writeu16( map.height )
out:writeu16( 1 + #built.layers ) -- layer count
out:add16( map.width )
out:add16( map.height )
out:add16( 1 + #built.layers ) -- layer count
-- map flags
local flags = 0
flags = flags | ( coll and 1 or 0 ) -- has collision bits
out:writeu16( flags )
out:add16( flags )
-- rl_layer0
for y = 1, map.height do
for x = 1, map.width do
out:writeu16( built.layer0[ y ][ x ] )
out:add16( built.layer0[ y ][ x ] )
end
end
@ -574,7 +259,7 @@ local function compile_cmd( args )
for _, layer in ipairs( built.layers ) do
for y = 1, map.height do
for x = 1, map.width do
out:writeu16( layer[ y ][ x ] )
out:add16( layer[ y ][ x ] )
end
end
end
@ -597,7 +282,7 @@ local function compile_cmd( args )
end
if bit == 0x80000000 then
out:writeu32( bits )
out:add32( bits )
bits, bit = 0, 1
else
bit = bit << 1
@ -606,7 +291,7 @@ local function compile_cmd( args )
end
if bit ~= 1 then
out:writeu32( bits )
out:add32( bits )
end
end
@ -660,12 +345,6 @@ Commands:
return 0
end
do
local dir, _, _ = path.split( args[ 0 ] )
local ok
ok, rleimage = loadfile( dir .. path.separator .. 'rlrle.lua' )()
end
args[ 1 ] = path.realpath( args[ 1 ] )
local commands = {

View File

@ -1,77 +1,13 @@
local function djb2( str )
local hash = 5381
for i = 1, #str do
hash = hash * 33 + str:byte( i )
hash = hash & 0xffffffff
end
return hash
end
local djb2 = require 'djb2'
local writer = require 'writer'
local function filesize( path )
local file, err = io.open( path, 'rb' )
if not file then
error( err )
end
local size, err = file:seek( 'end' )
if not size then
file:close()
error( err )
end
local file = assert( io.open( path, 'rb' ) )
local size = assert( file:seek( 'end' ) )
file:close()
return size
end
local function newwriter()
return {
bytes = {},
write8 = function( self, x )
self.bytes[ #self.bytes + 1 ] = string.char( x & 255 )
end,
write16 = function( self, x )
self.bytes[ #self.bytes + 1 ] = string.char( ( x >> 8 ) & 255, x & 255 )
end,
write32 = function( self, x )
self.bytes[ #self.bytes + 1 ] = string.char( ( x >> 24 ) & 255, ( x >> 16 ) & 255, ( x >> 8 ) & 255, x & 255 )
end,
writestr = function( self, str )
self.bytes[ #self.bytes + 1 ] = str
end,
append = function( self, rle )
self.bytes[ #self.bytes + 1 ] = table.concat( rle.bytes )
end,
align = function( self, x )
local size = self:size()
local new_size = ( size + x - 1 ) & -x
while size < new_size do
self:write8( 0 )
size = size + 1
end
end,
get = function( self )
self.bytes = { table.concat( self.bytes ) }
return self.bytes[ 1 ]
end,
size = function( self )
self.bytes = { table.concat( self.bytes ) }
return #self.bytes[ 1 ]
end,
save = function( self, name )
local file, err = io.open( name, 'wb' )
if not file then error( err ) end
self.bytes = { table.concat( self.bytes ) }
file:write( self.bytes[ 1 ] )
file:close()
end
}
end
return function( args )
if #args < 2 then
io.write[[
@ -164,33 +100,33 @@ Usage: luai rlpack.lua cuts <filename.pak> files...
end
end
local out = newwriter()
out:write32( num_entries )
out:write32( 0 )
local out = writer()
out:add32( num_entries )
out:add32( 0 )
for i = 0, num_entries - 1 do
if map[ i ] then
local entry = map[ i ]
out:write32( entry.name_hash )
out:write32( entry.name_offset )
out:write32( entry.data_offset )
out:write32( entry.data_size )
out:write32( 0 )
out:add32( entry.name_hash )
out:add32( entry.name_offset )
out:add32( entry.data_offset )
out:add32( entry.data_size )
out:add32( 0 )
else
out:write32( 0 )
out:write32( 0 )
out:write32( 0 )
out:write32( 0 )
out:write32( 0 )
out:add32( 0 )
out:add32( 0 )
out:add32( 0 )
out:add32( 0 )
out:add32( 0 )
end
end
for i = 0, num_entries - 1 do
if map[ i ] then
out:align( 4 )
out:writestr( map[ i ].name )
out:write8( 0 )
out:addstring( map[ i ].name )
out:add8( 0 )
end
end
@ -206,7 +142,7 @@ Usage: luai rlpack.lua cuts <filename.pak> files...
file:close()
out:align( 16 )
out:writestr( all )
out:addstring( all )
end
end

View File

@ -1,160 +1,9 @@
local image = require 'image'
local path = require 'path'
local image = require 'image'
local path = require 'path'
local rgbto16 = require 'rgbto16'
local mkrle = require 'mkrle'
local function newwriter()
return {
bytes = {},
write8 = function( self, x )
self.bytes[ #self.bytes + 1 ] = string.char( x & 255 )
end,
write16 = function( self, x )
self.bytes[ #self.bytes + 1 ] = string.char( ( x >> 8 ) & 255, x & 255 )
end,
write32 = function( self, x )
self.bytes[ #self.bytes + 1 ] = string.char( ( x >> 24 ) & 255, ( x >> 16 ) & 255, ( x >> 8 ) & 255, x & 255 )
end,
append = function( self, rle )
self.bytes[ #self.bytes + 1 ] = table.concat( rle.bytes )
end,
get = function( self )
self.bytes = { table.concat( self.bytes ) }
return self.bytes[ 1 ]
end,
size = function( self )
self.bytes = { table.concat( self.bytes ) }
return #self.bytes[ 1 ]
end,
save = function( self, name )
local file, err = io.open( name, 'wb' )
if not file then error( err ) end
self.bytes = { table.concat( self.bytes ) }
file:write( self.bytes[ 1 ] )
file:close()
end
}
end
local function rgbto16( r, g, b )
r = r * 31 // 255
g = g * 63 // 255
b = b * 31 // 255
return ( r << 11 ) | ( g << 5 ) | b
end
local function getpixel( png, x, y, transp )
local r, g, b, a = image.split( png:getPixel( x, y ) )
local c = rgbto16( r, g, b )
if c == transp then
r, g, b, a = 0, 0, 0, 0
end
if a >= 0 and a <= 31 then
a = 0 -- transparent
elseif a >= 32 and a <= 95 then
a = 1 -- 25%
elseif a >= 96 and a <= 159 then
a = 2 -- 50%
elseif a >= 160 and a <= 223 then
a = 3 -- 75%
else
a = 4 -- opaque
end
return rgbto16( r, g, b ), a
end
local function rlerow( png, y, limit, transp )
local rle = {}
local width = png:getWidth()
local used = 0
local numcols = ( width + ( limit - 1 ) ) // limit
for i = 1, numcols do
rle[ #rle + 1 ] = 0
end
for xx = 0, width - 1, limit do
rle[ xx // limit + 1 ] = #rle
local x = xx
rle[ #rle + 1 ] = 0
local runs = #rle
while x < ( xx + limit ) and x < width do
local _, a = getpixel( png, x, y, transp )
local count = 0
local xsave = x
while x < ( xx + limit ) and x < width do
local c, aa = getpixel( png, x, y, transp )
if aa ~= a then
break
end
count = count + 1
x = x + 1
end
rle[ #rle + 1 ] = ( a << 13 | count )
rle[ runs ] = rle[ runs ] + 1
if a ~= 0 then
for i = 0, count - 1 do
local c = getpixel( png, xsave + i, y, transp )
rle[ #rle + 1 ] = c
used = used + 1
end
end
end
end
local final = newwriter()
for i = 1, #rle do
final:write16( rle[ i ] )
end
return final, used
end
local function rleimage( png, limit, transp )
local width, height = png:getSize()
local rows = {}
local used = 0
limit = limit or 1e10
for y = 0, height - 1 do
local row, u = rlerow( png, y, limit, transp )
rows[ y ] = row
used = used + u
end
local rle = newwriter()
rle:write16( width )
rle:write16( height )
rle:write32( used )
local count = 0
for y = 0, height - 1 do
rle:write32( count )
count = count + rows[ y ]:size()
end
for y = 0, height - 1 do
rle:append( rows[ y ] )
end
return rle
end
local function main( args )
return function( args )
if #args == 0 then
io.write[[
RLE-encodes an image to a format ready to be used with rl_image_create. The
@ -207,10 +56,8 @@ Usage: luai rlrle.lua [ options ] <image>
transp = rgbto16( image.split( png:getPixel( png:getWidth() - 1, png:getHeight() - 1 ) ) )
end
local rle = rleimage( png, limit, transp )
local res = mkrle( png, limit, transp )
local dir, name, ext = path.split( name )
rle:save( dir .. path.separator .. name .. '.rle' )
res:save( dir .. path.separator .. name .. '.rle' )
return 0
end
return main, rleimage

View File

@ -1,13 +1,6 @@
local image = require 'image'
local path = require 'path'
local function rgbto16( r, g, b )
r = r * 31 // 255
g = g * 63 // 255
b = b * 31 // 255
return ( r << 11 ) | ( g << 5 ) | b
end
local image = require 'image'
local path = require 'path'
local rgbto16 = require 'rgbto16'
return function( args )
if #args == 0 then
@ -41,9 +34,7 @@ Usage: luai rltile.lua <image>
end
local dir, name, ext = path.split( name )
local file, err = io.open( dir .. path.separator .. name .. '.h', 'w' )
if not file then error( err ) end
local file = assert( io.open( dir .. path.separator .. name .. '.h', 'w' ) )
local array = string.gsub( name .. ext, '[^a-zA-Z0-9_]', '_' )
file:write( 'const uint16_t ', array, '[] = {\n' )

View File

@ -1,67 +1,7 @@
local image = require 'image'
local path = require 'path'
local mkts = require 'mkts'
local function newwriter()
return {
bytes = {},
write8 = function( self, x )
self.bytes[ #self.bytes + 1 ] = string.char( x & 255 )
end,
write16 = function( self, x )
self.bytes[ #self.bytes + 1 ] = string.char( ( x >> 8 ) & 255, x & 255 )
end,
write32 = function( self, x )
self.bytes[ #self.bytes + 1 ] = string.char( ( x >> 24 ) & 255, ( x >> 16 ) & 255, ( x >> 8 ) & 255, x & 255 )
end,
append = function( self, rle )
self.bytes[ #self.bytes + 1 ] = table.concat( rle.bytes )
end,
size = function( self )
self.bytes = { table.concat( self.bytes ) }
return #self.bytes[ 1 ]
end,
save = function( self, name )
local file, err = io.open( name, 'wb' )
if not file then error( err ) end
self.bytes = { table.concat( self.bytes ) }
file:write( self.bytes[ 1 ] )
file:close()
end
}
end
local function rgbto16( r, g, b )
r = r * 31 // 255
g = g * 63 // 255
b = b * 31 // 255
return ( r << 11 ) | ( g << 5 ) | b
end
local function getpixel( png, x, y )
local r, g, b = image.split( png:getPixel( x, y ) )
return rgbto16( r, g, b )
end
local function mktileset( images )
local writer = newwriter()
writer:write16( images[ 1 ]:getWidth() )
writer:write16( images[ 1 ]:getHeight() )
writer:write16( #images )
for _, img in pairs( images ) do
for y = 0, img:getHeight() - 1 do
for x = 0, img:getWidth() - 1 do
writer:write16( getpixel( img, x, y ) )
end
end
end
return writer
end
local function main( args )
return function( args )
if #args == 0 then
io.write[[
rltileset.lua reads all images in the given directory and writes tileset data
@ -119,19 +59,17 @@ Usage: luai rltileset.lua [ options ] <directory>
end
if #images ~= 0 then
local writer = mktileset( images )
local out = mkts( images )
if not output then
local dir, name, ext = path.split( dir )
output = dir .. path.separator .. name .. '.tls'
end
writer:save( output )
out:save( output )
else
io.write( 'no images were found\n' )
end
return 0
end
return main, mktileset