Skip to content

Instantly share code, notes, and snippets.

@ruccho
Created May 20, 2025 12:23
Show Gist options
  • Save ruccho/589615b38cc8abbb9648a8b4f7e56a7c to your computer and use it in GitHub Desktop.
Save ruccho/589615b38cc8abbb9648a8b4f7e56a7c to your computer and use it in GitHub Desktop.
Aseprite script that generates SDF (Signed Distance Field)
----------------------------------------------------------------------
-- Generate SDF
--
-- It works only for RGB color mode.
----------------------------------------------------------------------
if app.apiVersion < 1 then
return app.alert("Unsupported version")
end
local currentCel = app.activeCel
if not currentCel then
return app.alert("There is no active image")
end
local dlg = Dialog()
dlg:slider{ id="width",
label="Distance",
min=1,
max=16,
value=16 }
dlg:button{ id="confirm", text="Generate" }
dlg:button{ id="cancel", text="Cancel" }
dlg:show()
if dlg.data.confirm == false then
return
end
local width = dlg.data.width
local function processLayer(layer)
local sprite = app.activeSprite
local newLayerName = layer.name .. "_SDF"
local newLayer = nil
for i, layer in ipairs(sprite.layers) do
if layer.name == newLayerName then
newLayer = layer
end
end
if newLayer == nil then
newLayer = sprite:newLayer()
newLayer.name = newLayerName
end
for i, cel in ipairs(layer.cels) do
local frame = cel.frame
local img = Image(cel.image.width + width * 2, cel.image.height + width * 2)
local position = cel.position
if img.colorMode == ColorMode.RGB then
local rgba = app.pixelColor.rgba
local rgbaA = app.pixelColor.rgbaA
for it in img:pixels() do
local x = it.x - width
local y = it.y - width
local s = false
if x < 0 or y < 0 or x >= cel.image.width or y >= cel.image.height then
s = true
else
s = rgbaA(cel.image:getPixel(x, y)) < 255
end
local nearest = width
for dx = -width, width do
for dy = -width, width do
local px = x + dx
local py = y + dy
local ps = false
if px < 0 or py < 0 or px >= cel.image.width or py >= cel.image.height then
ps = true
else
ps = rgbaA(cel.image:getPixel(px, py)) < 255
end
if ps ~= s then
local d = math.sqrt(dx * dx + dy * dy)
if d < nearest then
nearest = d
end
end
end
end
if s then
nearest = -nearest
end
local value = 128 + nearest / width * 128
local color = rgba(value, value, value, 255)
it(color)
end
elseif img.colorMode == ColorMode.GRAY then
return app.alert("This script is only for RGB Color Mode")
elseif img.colorMode == ColorMode.INDEXED then
return app.alert("This script is only for RGB Color Mode")
end
local newCel = sprite:newCel(newLayer, frame, img, Point(position.x - width, position.y - width))
end
end
for i, layer in ipairs(app.range.layers) do
processLayer(layer)
end
app.refresh()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment