function table.print(src, offset, ret)
	if type(src) ~= "table" then print("table.print has no table:", src) return end
	offset = offset or ""
	for k, e in pairs(src) do
		-- Deep copy subtables, but not objects!
		if type(e) == "table" and not e.__ATOMIC then
			print(("%s[%s] = {"):format(offset, tostring(k)))
			table.print(e, offset.."  ")
			print(("%s}"):format(offset))
		else
			print(("%s[%s] = %s"):format(offset, tostring(k), tostring(e)))
		end
	end
end
--- This is a really naive algorithm, it will not handle objects and such.
-- Use only for small tables
function table.serialize(src, sub, no_G)
	local str = ""
	if sub then str = "{" end
	for k, e in pairs(src) do
		local nk, ne = k, e
		local tk, te = type(k), type(e)

		if no_G then
			if tk == "table" then nk = "["..table.serialize(nk, true).."]"
			elseif tk == "string" then -- nothing
			else nk = "["..nk.."]"
			end
		else
			if tk == "table" then nk = "["..table.serialize(nk, true).."]"
			elseif tk == "string" then nk = string.format("[%q]", nk)
			else nk = "["..nk.."]"
			end
			if not sub then nk = "_G"..nk end
		end

		if te == "table" then
			str = str..string.format("%s=%s ", nk, table.serialize(ne, true))
		elseif te == "number" then
			str = str..string.format("%s=%f ", nk, ne)
		elseif te == "string" then
			str = str..string.format("%s=%q ", nk, ne)
		elseif te == "boolean" then
			str = str..string.format("%s=%s ", nk, tostring(ne))
		end
		if sub then str = str..", " end
	end
	if sub then str = str.."}" end
	return str
end


local gd = require "gd"

local list = {...}
local ts_size_w, ts_size_h = tonumber(table.remove(list, 1)) or 1024, tonumber(table.remove(list, 1)) or 1024
local basename = table.remove(list, 1)
local prefix = table.remove(list, 1)

function makeSet(w, h)
	local used = {}
	local im = gd.createTrueColor(w, h)
	im:alphaBlending(false)
	im:saveAlpha(true)
	im:filledRectangle(0, 0, w, h, im:colorAllocateAlpha(0, 0, 0, 127))

	for i = 0, ts_size_w-64, 68 do
		used[i/68] = {}
		for j = 0, ts_size_h-64, 68 do
			used[i/68][j/68] = false
		end
	end

	return im, used
end

local w, h = ts_size_w, ts_size_h
local id = 1

local pos = {}
pos.__width = w
pos.__height = h

function findPlace(used, d)
	for i = 0, #used do
		for j = 0, #used[i] do if not used[i][j] then
			-- print("Spot", i, j)
			local ok = true
			for a = i, i + d.sw - 1 do for b = j, j + d.sh - 1 do
				-- print("SubSpot", a, b)
				if not used[a] or used[a][b] == true or used[a][b] == nil then ok = false end
			end end
			if ok then return i, j end
		end end
	end
end

function fillSet(rlist)
	local im, used = makeSet(w, h)
	local i, j = 0, 0
	while #rlist > 0 do
		local d = table.remove(rlist)
		print("SRC", d.file, d.mw, d.mh, d.sw, d.sh)

		local i, j = findPlace(used, d)
		if not i then
			im:png(basename..id..".png")
			im, used = makeSet(w, h)
			i, j = findPlace(used, d)
			id = id + 1
		end

		local ri, rj = i * 68, j * 68
		im:copyResampled(d.src, ri, rj, 0, 0, d.mw, d.mh, d.mw, d.mh)
		pos[prefix..d.file] = {x=ri/w, y=rj/h, factorx=d.mw/w, factory=d.mh/h, w=d.mw, h=d.mh, set=prefix..basename..id..".png"}

		for x = i, i - 1 + d.sw do for y = j, j - 1 + d.sh do 
			used[x][y] = true
		end end

		i = i + d.mw
	end
	-- table.print(used)
	im:png(basename..id..".png")
end

local total = 0

local rlist = {}
for i = #list, 1, -1 do
	local file = list[i]
	if file:sub(1, 2) == "./" then file = file:sub(3) end

	local src = gd.createFromPng(file)
	local mw, mh = src:sizeXY()
	rlist[#rlist+1] = {file=file, src=src, mw=mw, mh=mh, sw=math.ceil(mw/64), sh=math.ceil(mh/64)}
	table.remove(list, i)
end
table.sort(rlist, function(a,b)
	return a.file < b.file
	-- local ai, bi = a.mw + a.mh, b.mw + b.mh
	-- if ai == bi then return a.file < b.file end
	-- return ai < bi
end)

total = total + #rlist
fillSet(rlist)

-- Missing ones ?
for i = #list, 1, -1 do
	local file = list[i]
	if file:sub(1, 2) == "./" then file = file:sub(3) end

	local src = gd.createFromPng(file)
	local mw, mh = src:sizeXY()
	print("Missed: ", mw, mh, file)
end

local f = io.open(basename..".lua", "w")
f:write(table.serialize(pos))
f:close()

print("Total for", basename, " contains ", total, "images")