I wanted a tool to help me import a large folder of asset .pngs (such as one you might get from https://kenney.nl/) into .gfx files. I know there are tools such as @pancelor 's helpful importpng.p64 (or just click-n-dragging onto the gfx editor), but I didn't want to do that for hundreds of files.
Using importpng.p64 as a foundation, I create a command-line utility for Picotron that will import entire folders of assets into .gfx files! Below is the snippet that you'll put in /appdata/system/utils/simport.lua
-- a tool to import all pngs in a folder into a single .gfx file -- tool by @fletch_pico -- version 1.1 -- -- makes use of: -- importpng.p64 code by @pancelor -- https://www.lexaloffle.com/bbs/?tid=141149 cd(env().path) local argv = env().argv if (argv[1] == "--help") then print("Usage: simport [FOLDER]") print("Populate the .gfx file using a folder of PNGs.") print("") print("OPTIONS") print(" -e") print(" --empty-sprite-0") print(" keep sprite 0 empty on every .gfx file") print(" (default is to write data to sprite 0)") exit(0) end -- check if argv[1] is a folder local path = fullpath(env().argv[1]) if (not path) then print("could not resolve path") exit(1) end -- loop through items in this folder looking for pngs local dir_items = ls(path) local pngs = {} for i=1,#dir_items do local item = dir_items[i] if (#item > 4 and sub(item,-4) == ".png") then add(pngs,item) end end if (#pngs < 1) then print("no PNGs found, exiting early...") exit(1) end if (argv[2] == "-e" or argv[2] == "--empty-sprite-0") then local i = 0 while i < #pngs do add(pngs, "empty", i+1) -- gotta add 1 because pngs is not 0-indexed here i += 256 end end -- ------------------------------------------ -- @pancelor's importpng.p64 code starts here -- ------------------------------------------ function sprite_from_image(png_path) local img_i32 = fetch(png_path) if not img_i32 then return nil end local rgb = {} for i=0,31 do rgb[i] = rgb_from_int(peek4(0x5000+i*4)) end local w,h = img_i32:attribs() local img_u8 = userdata("u8",w,h) for i=0,w*h-1 do img_u8[i] = best_match(rgb,img_i32[i]) end return { bmp=img_u8, flags=0x0, pan_x=0, pan_y=0, zoom=8 } end local _memo={} function best_match(rgb,now_i32) local res=_memo[now_i32] if res then return res end local now = rgb_from_int(now_i32) local v,k = minby0(rgb,function(cvec) cvec -= now return cvec:dot(cvec) --distance squared to now end) _memo[now_i32]=k return k end -- rgb: vec(r,g,b), each in [0,1] range -- returns: 0xRRGGBB function int_from_rgb(rgb) return (rgb.x*255\1<<16)+(rgb.y*255\1<<8)+(rgb.z*255\1) end -- int: 0xRRGGBB -- returns: vec(r,g,b), each in [0,1] range function rgb_from_int(int) return vec((int>>16&0xff)/255,(int>>8&0xff)/255,(int&0xff)/255) end function minby0(arr, fn) fn = fn or function(x) return x end local best,besti = fn(arr[0]),0 for i=1,#arr do local now = fn(arr[i]) if now<best then best,besti = now,i end end return best,besti end -- ------------------------------------------ -- @pancelor's importpng.p64 code stops here -- ------------------------------------------ -- loop through pngs table and start copying their userdata local total_files = #pngs local idx = 0 -- core loop - get a png userdata, copy to .gfx, go next local gfx_data = {} for i=0,flr(#pngs/256) do -- create a new gfx "page" gfx_data[i] = {} -- calculate how many sprites are in this page local num_sprites = #pngs-(i*256) -- loop through each sprite and populate the current page for j=0,num_sprites-1 do -- check if this is the "empty" sprite if (pngs[i*256+j+1] == "empty") then gfx_data[i][j] = { bmp=userdata("u8", 16, 16), -- empty 16x16 userdata flags=0x0, pan_x=0, pan_y=0, zoom=8 } -- this is a real file to attempt to import else local data = sprite_from_image(path.."/"..pngs[i*256+j+1]) if (data ~= nil) then gfx_data[i][j] = data print("imported "..pngs[i*256+j+1].." ("..(i*256+j+1).."/"..total_files..")") else print("failed to import "..pngs[i].."; continuing") end end end end -- write to gfx file(s) for i=0,flr(#pngs/256) do print("storing "..i..".gfx") store(path.."/"..i..".gfx", gfx_data[i]) end |
Usage:
simport [FOLDER] Populate .gfx file(s) using a folder of PNGs. OPTIONS -e --empty-sprite-0 keep sprite 0 empty on every .gfx file (default is to write data to sprite 0) |
[Please log in to post a comment]