Overview
Batch processing allows you to apply the same operations to multiple files automatically. This is essential for managing large projects with many sprites.Running Batch Scripts from Command Line
Aseprite can run scripts in batch mode without opening the GUI:aseprite -b --script batch-process.lua
Basic File Processing Loop
Here’s a template for processing multiple files:-- List of files to process
local files = {
"sprites/character1.aseprite",
"sprites/character2.aseprite",
"sprites/character3.aseprite"
}
-- Process each file
for _, filename in ipairs(files) do
print("Processing: " .. filename)
-- Open the file
local sprite = app.open(filename)
if sprite then
-- Do processing here
-- sprite:resize(64, 64)
-- app.command.Flatten()
-- Save the changes
sprite:save()
-- Close the sprite
sprite:close()
print("Completed: " .. filename)
else
print("Error opening: " .. filename)
end
end
print("Batch processing complete!")
Discovering Files Automatically
Use the file system API to find files automatically:local fs = app.fs
-- Get the current directory
local inputDir = fs.currentPath .. "/sprites"
if not fs.isDirectory(inputDir) then
print("Directory not found: " .. inputDir)
return
end
-- List all files
local files = fs.listFiles(inputDir)
for _, filename in ipairs(files) do
local fullPath = fs.joinPath(inputDir, filename)
-- Process only .aseprite files
if fs.fileExtension(filename) == "aseprite" then
print("Processing: " .. filename)
local sprite = app.open(fullPath)
if sprite then
-- Process sprite...
sprite:save()
sprite:close()
end
end
end
Batch Export to PNG
Convert all Aseprite files to PNG:local fs = app.fs
local inputDir = "./input"
local outputDir = "./output"
-- Create output directory if it doesn't exist
if not fs.isDirectory(outputDir) then
fs.makeDirectory(outputDir)
end
local files = fs.listFiles(inputDir)
for _, filename in ipairs(files) do
if fs.fileExtension(filename) == "aseprite" then
local inputPath = fs.joinPath(inputDir, filename)
local baseName = fs.fileTitle(filename)
local outputPath = fs.joinPath(outputDir, baseName .. ".png")
print("Converting: " .. filename)
local sprite = app.open(inputPath)
if sprite then
sprite:saveCopyAs(outputPath)
sprite:close()
print("Saved: " .. outputPath)
end
end
end
print("Export complete!")
Batch Resize All Sprites
local fs = app.fs
local inputDir = "./sprites"
local targetWidth = 64
local targetHeight = 64
local files = fs.listFiles(inputDir)
local processedCount = 0
for _, filename in ipairs(files) do
if fs.fileExtension(filename) == "aseprite" then
local fullPath = fs.joinPath(inputDir, filename)
local sprite = app.open(fullPath)
if sprite then
local oldSize = sprite.width .. "x" .. sprite.height
sprite:resize(targetWidth, targetHeight)
sprite:save()
print(string.format("%s: %s -> %dx%d",
filename, oldSize, targetWidth, targetHeight))
sprite:close()
processedCount = processedCount + 1
end
end
end
print("Resized " .. processedCount .. " sprites")
Batch Export Sprite Sheets
Export all animations as sprite sheets:local fs = app.fs
local inputDir = "./animations"
local outputDir = "./spritesheets"
if not fs.isDirectory(outputDir) then
fs.makeDirectory(outputDir)
end
local files = fs.listFiles(inputDir)
for _, filename in ipairs(files) do
if fs.fileExtension(filename) == "aseprite" then
local inputPath = fs.joinPath(inputDir, filename)
local baseName = fs.fileTitle(filename)
local outputPath = fs.joinPath(outputDir, baseName .. ".png")
print("Exporting sprite sheet: " .. filename)
local sprite = app.open(inputPath)
if sprite then
app.sprite = sprite
app.command.ExportSpriteSheet{
type = SpriteSheetType.HORIZONTAL,
textureFilename = outputPath,
shapePadding = 1,
borderPadding = 0
}
sprite:close()
print("Saved: " .. outputPath)
end
end
end
print("Sprite sheet export complete!")
Batch Apply Color Adjustments
local fs = app.fs
local inputDir = "./sprites"
local brightnessAdjust = 20
local contrastAdjust = 10
local files = fs.listFiles(inputDir)
for _, filename in ipairs(files) do
if fs.fileExtension(filename) == "aseprite" then
local fullPath = fs.joinPath(inputDir, filename)
print("Adjusting: " .. filename)
local sprite = app.open(fullPath)
if sprite then
app.sprite = sprite
app.command.BrightnessContrast{
brightness = brightnessAdjust,
contrast = contrastAdjust
}
sprite:save()
sprite:close()
end
end
end
print("Applied color adjustments")
Batch Add Copyright Layer
Add a copyright layer to all sprites:local fs = app.fs
local inputDir = "./sprites"
local copyrightText = "Copyright 2024"
local files = fs.listFiles(inputDir)
for _, filename in ipairs(files) do
if fs.fileExtension(filename) == "aseprite" then
local fullPath = fs.joinPath(inputDir, filename)
local sprite = app.open(fullPath)
if sprite then
-- Create copyright layer
local layer = sprite:newLayer()
layer.name = "Copyright"
-- Lock the layer so it's not accidentally edited
layer.isEditable = false
print("Added copyright layer to: " .. filename)
sprite:save()
sprite:close()
end
end
end
print("Added copyright layers")
Batch Flatten Layers
local fs = app.fs
local inputDir = "./sprites"
local outputDir = "./flattened"
if not fs.isDirectory(outputDir) then
fs.makeDirectory(outputDir)
end
local files = fs.listFiles(inputDir)
for _, filename in ipairs(files) do
if fs.fileExtension(filename) == "aseprite" then
local inputPath = fs.joinPath(inputDir, filename)
local outputPath = fs.joinPath(outputDir, filename)
local sprite = app.open(inputPath)
if sprite then
local layerCount = #sprite.layers
sprite:flatten()
print(string.format("%s: flattened %d layers",
filename, layerCount))
sprite:saveAs(outputPath)
sprite:close()
end
end
end
print("Flattening complete!")
Batch Convert Color Mode
Convert all sprites to indexed color:local fs = app.fs
local inputDir = "./sprites"
local files = fs.listFiles(inputDir)
local convertedCount = 0
for _, filename in ipairs(files) do
if fs.fileExtension(filename) == "aseprite" then
local fullPath = fs.joinPath(inputDir, filename)
local sprite = app.open(fullPath)
if sprite then
local oldMode = sprite.colorMode
if oldMode ~= ColorMode.INDEXED then
app.sprite = sprite
app.command.ChangePixelFormat{ format="indexed" }
sprite:save()
print(string.format("%s: converted to indexed", filename))
convertedCount = convertedCount + 1
else
print(string.format("%s: already indexed", filename))
end
sprite:close()
end
end
end
print("Converted " .. convertedCount .. " sprites to indexed color")
Batch Trim Transparent Pixels
local fs = app.fs
local inputDir = "./sprites"
local files = fs.listFiles(inputDir)
for _, filename in ipairs(files) do
if fs.fileExtension(filename) == "aseprite" then
local fullPath = fs.joinPath(inputDir, filename)
local sprite = app.open(fullPath)
if sprite then
local oldSize = sprite.width .. "x" .. sprite.height
app.sprite = sprite
app.command.AutocropSprite()
local newSize = sprite.width .. "x" .. sprite.height
if oldSize ~= newSize then
sprite:save()
print(string.format("%s: trimmed from %s to %s",
filename, oldSize, newSize))
else
print(string.format("%s: no trim needed", filename))
end
sprite:close()
end
end
end
print("Trim complete!")
Batch Add Grid Overlay
local fs = app.fs
local inputDir = "./sprites"
local gridWidth = 16
local gridHeight = 16
local files = fs.listFiles(inputDir)
for _, filename in ipairs(files) do
if fs.fileExtension(filename) == "aseprite" then
local fullPath = fs.joinPath(inputDir, filename)
local sprite = app.open(fullPath)
if sprite then
-- Set grid bounds
sprite.gridBounds = Rectangle(0, 0, gridWidth, gridHeight)
sprite:save()
print(string.format("%s: set grid to %dx%d",
filename, gridWidth, gridHeight))
sprite:close()
end
end
end
print("Grid settings applied")
Batch Export at Different Scales
Export sprites at multiple scales (1x, 2x, 4x):local fs = app.fs
local inputDir = "./sprites"
local outputDir = "./exports"
local scales = { 1, 2, 4 }
for _, scale in ipairs(scales) do
local scaleDir = fs.joinPath(outputDir, scale .. "x")
if not fs.isDirectory(scaleDir) then
fs.makeAllDirectories(scaleDir)
end
end
local files = fs.listFiles(inputDir)
for _, filename in ipairs(files) do
if fs.fileExtension(filename) == "aseprite" then
local inputPath = fs.joinPath(inputDir, filename)
local baseName = fs.fileTitle(filename)
print("Exporting: " .. filename)
local sprite = app.open(inputPath)
if sprite then
app.sprite = sprite
for _, scale in ipairs(scales) do
local outputPath = fs.joinPath(
outputDir,
scale .. "x",
baseName .. ".png"
)
app.command.SaveFileCopyAs{
filename = outputPath,
scale = scale
}
print(string.format(" Saved %dx: %s", scale, outputPath))
end
sprite:close()
end
end
end
print("Multi-scale export complete!")
Command-Line Usage
You can pass arguments to your batch scripts:# Run batch script
aseprite -b --script batch-export.lua
# Process specific file
aseprite -b sprite.aseprite --script resize.lua --save-as output.png
# Chain multiple operations
aseprite -b input.aseprite --script process.lua --scale 2 --save-as output.png
Error Handling in Batch Processing
local fs = app.fs
local inputDir = "./sprites"
local errors = {}
local files = fs.listFiles(inputDir)
for _, filename in ipairs(files) do
if fs.fileExtension(filename) == "aseprite" then
local fullPath = fs.joinPath(inputDir, filename)
-- Use pcall for error handling
local success, err = pcall(function()
local sprite = app.open(fullPath)
if not sprite then
error("Failed to open file")
end
-- Process sprite...
sprite:resize(64, 64)
sprite:save()
sprite:close()
print("Processed: " .. filename)
end)
if not success then
table.insert(errors, { file = filename, error = err })
print("ERROR with " .. filename .. ": " .. err)
end
end
end
print("\nProcessing complete!")
if #errors > 0 then
print("Errors encountered: " .. #errors)
for _, e in ipairs(errors) do
print(" " .. e.file .. ": " .. e.error)
end
end
Next Steps
Automation Examples
Automate repetitive tasks
Custom Tools
Create custom drawing tools
Scripting Introduction
Learn the basics of scripting

