Sprite sheet exporter script with scaling (outputs .json and png)

Hello,
I want to share a script I wrote that allows to export the each tag in sprites sheets, both png and json, with a scalable option. There was a script already exporting each tag as separate png sheets done by @dacap , so I took that and extended it with scaling features that output .png and json files as mentioned before.
See the image bellow

sheetExporter

I will add some more features like setting custom path, etc… but in the mean time feel free to use the script and modify it as you wish.

note: I literally learn lua and Aseprite Api a couple of days a go, so the code is a bit rough, but it works.
Make sure you have the module JSON.lua and dkjson.lua in the right path and it shoulf work.

Cheers,
R

local json = dofile("_modules/JSON.lua")
local dkJson = dofile("_modules/dkjson.lua")


local spr = app.activeSprite
if not spr then return print('No active sprite') end

local path,title = spr.filename:match("^(.+[/\\])(.-).([^.]*)$")
local msg = { "Do you want to export/overwrite the following files?" }

for i,tag in ipairs(spr.tags) do
  local fn = path .. title .. '-' .. tag.name
  table.insert(msg, '-' .. fn .. '.[png|json]')
end

-- uncomment to run the overrite alert
--if app.alert{ title="Export Sprite Sheets", text=msg,
--              buttons={ "&Yes", "&No" } } ~= 1 then
--  return
--end

function decodeFileIntoTable(path)

    local pathToJsonfile = io.open(path, "r")
    local contentAsString = pathToJsonfile:read("*all")  -- *all is one of the arguments of read()
    pathToJsonfile:close()
    local myTable = dkJson.decode(contentAsString)
    return myTable
    
end


function exportFunc(scaleFactor)

    for i,tag in ipairs(spr.tags) do
        local fn = path  .. title .. '_' .. tag.name .. '_sheet' 
        app.command.ExportSpriteSheet{
        ui = false,
        type = SpriteSheetType.HORIZONTAL,
        textureFilename = fn .. '.png',
        dataFilename = fn .. '.json',
        dataFormat = SpriteSheetDataFormat.JSON_ARRAY,
        filenameFormat = "{tag}_{frame}.{extension}",
        tag = tag.name,
        listLayers = false,
        listTags = false,
        listSlices = false
        }

        -- ##########################################################################
        -- scale png sheets (open as Aseprite file, resize and close)
        -- ##########################################################################
        local sprite = app.open(fn .. '.png')
        sprite:resize(sprite.width * scaleFactor,sprite.height * scaleFactor)
        local resizeFileName = sprite.filename
        local resizeFileNamePath = path  .. resizeFileName 
        
        app.command.SaveFile(fn .. '.png')
        app.command.CloseFile(fn .. '.png')

        
        -- ##########################################################################
        -- scale json sheets (decode saved json and multiply the "frame" key values by the scale)
        -- ##########################################################################
        -- 1. get all the values of the key "frame". Those are dicts containing "frame" key
        local dataTable = decodeFileIntoTable(fn .. '.json')
        local framesKeyTable = dataTable["frames"]
        -- 2. get all the values of the key "frame", which are x, y, w and h, multiply them by the scale
        -- (also multiply any other related keys)
        for k, v in pairs(framesKeyTable) do
            v["frame"]["x"] = v["frame"]["x"] * scaleFactor
            v["frame"]["y"] = v["frame"]["y"] * scaleFactor
            v["frame"]["w"] = v["frame"]["w"] * scaleFactor
            v["frame"]["h"] = v["frame"]["h"] * scaleFactor
            
            v["spriteSourceSize"]["x"] = v["spriteSourceSize"]["x"] * scaleFactor
            v["spriteSourceSize"]["y"] = v["spriteSourceSize"]["y"] * scaleFactor
            v["spriteSourceSize"]["w"] = v["spriteSourceSize"]["w"] * scaleFactor
            v["spriteSourceSize"]["h"] = v["spriteSourceSize"]["h"] * scaleFactor
            
            v["sourceSize"]["w"] = v["sourceSize"]["w"] * scaleFactor
            v["sourceSize"]["h"] = v["sourceSize"]["h"] * scaleFactor

                        
        end
        
        
        -- 4. save the json with those updated values
        local json_as_string = json.encode_pretty(json, dataTable)
        
        local myFilePath= fn .. '.json'
        local newFile = io.open(myFilePath, "w")  -- "w" for writing mode
        newFile.write(newFile, json_as_string)
        newFile.close(newFile)
      
    end
    
end



-- UI

local dlg = Dialog{ title="Scalar sheet exporter" }

dlg:number {
    id="scaleId",
    label="Scale: ",
    text=string.format("%.1f", 1),
    decimals=integer
}

dlg:button {
    id="myButtonId",
    text="Save sheets",
    onclick=function()
        local dlgData = dlg.data
        exportFunc(dlgData.scaleId)
    end
}


dlg:show()
3 Likes

Love to see someone learning the api and sharing. Thank you!

1 Like

No problem. Aseprite is really cool.

“cannot open _modules/JSON.lua: No such file or directory” how i fix?

Check You have JSON.lua and dkjson.lua in the right path. In my case I hace a folder called _modeles and thise scripts inside (ser the fiesta 2lines of the script).
Just check the right path

Sorry, I’m very beginner with scripts and codes and English haha can you explain with images, or video? please

  1. go your scripts folder something like C:\Users\Rafaelbstan\AppData\Roaming\Aseprite\scripts
    and create a folder named _modules. Inside that folder copy the two scripts JSON.lua and dkjson.lua. They can be found anywhere on git hub or googling.

2.copy the code of this post in a file and name it sheetExporter.lua

3.copy it in C:\Users\Rafaelbstan\AppData\Roaming\Aseprite\scripts (now if you restart asprite it will appear in the menu scritps.

1 Like

thanks man, u saved me haha

1 Like

For those still searching the _modules:

The script is nice, although it’d benefit from parameters in UI to become a fully flexible utility script. It could have fields for:

  • custom output file format (currently hardcoded in exportFunc as local fn = path … title … ‘_’ … tag.name … ‘_sheet’)
  • options to choose what to export, like the native export window (spritesheet, JSON, both)

Yeah, the script could have more option so anyone feel free to take it and expand it. I am currently a bit busy so I don’t have much time.
Maybe future aseprite version might include something similar?

cheers

In the meantime I wrote a bash script for this on How can I export multiple spritesheets at once? - #5 by hsandt

but I need to dive into Aseprite Lua API to make it a proper plugin. Also, it’s very simple, also uses hardcoded paths and doesn’t have extra options like scaling.

It would be nice to merge all our ideas into one super script for Aseprite with a parameterable popup, at the end.

1 Like