How to generate drop shadow in lua with transparent background? #4364
Replies: 3 comments 1 reply
-
Hello @philocalyst, your code seems to work for me. With this test image: And this program: #!/usr/bin/luajit
local vips = require "vips"
local function add_drop_shadow(img, shadow_colour, shadow_offset, shadow_radius, background_colour)
-- Default parameters
shadow_colour = shadow_colour or { 100, 100, 100 }
shadow_offset = shadow_offset or 10
shadow_radius = shadow_radius or 5
background_colour = background_colour or { 0, 0, 0 }
-- Add alpha channel if missing
if img:bands() < 4 then
img = img:addalpha()
end
-- Extract alpha channel for shadow shape
local shadow_alpha = img:extract_band(img:bands() - 1)
-- Create shadow alpha with padding and blur
local padded_alpha = shadow_alpha:embed(
shadow_radius,
shadow_radius,
shadow_alpha:width() + 2 * shadow_radius,
shadow_alpha:height() + 2 * shadow_radius,
{ extend = vips.ExtendBackground }
)
local blurred_alpha = padded_alpha:gaussblur(shadow_radius / 2)
-- Create shadow RGB from color
local shadow_rgb = blurred_alpha:new_from_image(shadow_colour)
local shadow = shadow_rgb:bandjoin(blurred_alpha)
-- Create background canvas
local extra_border = math.max(0, math.abs(shadow_offset) - shadow_radius)
local background = shadow:new_from_image(background_colour)
background = background:embed(
0,
0,
background:width() + extra_border,
background:height() + extra_border,
{ extend = "copy" }
)
-- Calculate final composite positions
local final_offset = math.max(0, shadow_offset - shadow_radius)
local image_offset = final_offset - shadow_offset + shadow_radius
-- Composite layers (background first, then shadow, then image)
local result = background:composite(
{ shadow, img },
"over",
{ x = { final_offset, image_offset }, y = { final_offset, image_offset } }
)
return result
end
local image = vips.Image.new_from_file(arg[1])
local with_shadow = add_drop_shadow(image, {255, 0, 0}, 10, 10, {0, 0, 255})
with_shadow:write_to_file(arg[2]) I can run:
To generate: Did you want the background to remain transparent? |
Beta Was this translation helpful? Give feedback.
-
Haha yes, specifically that part is important to me. Thank you for replying so quickly @jcupitt ! |
Beta Was this translation helpful? Give feedback.
-
Sorry, can I take this question back and pass in a new one? How would I allow for transparency of the shadow? Got the removed background part, no biggie. I tried straight up passing in an rgba array but to no avail. Is this because it's just the alpha? Sorry for the frequent questions, been a rushed introduction to color theory and image mechanics over here!! How we looking rn: local function add_drop_shadow(img, shadow_colour, shadow_offset, shadow_radius)
-- Default parameters
shadow_colour = shadow_colour or { 0, 0, 0}
shadow_offset = shadow_offset or 5
shadow_radius = shadow_radius or 5
-- Add alpha channel if nonexistent
if img:bands() < 4 then
img = img:addalpha()
end
-- Extract alpha channel to isolate that shape
local shadow_alpha = img:extract_band(img:bands() - 1)
-- Add padding and blur for the real shadow
local padded_alpha = shadow_alpha:embed(
shadow_radius,
shadow_radius,
shadow_alpha:width() + 2 * shadow_radius,
shadow_alpha:height() + 2 * shadow_radius,
{ extend = vips.ExtendBackground }
)
local blurred_alpha = padded_alpha:gaussblur(shadow_radius / 2)
-- Add glorious color
local shadow_rgb = blurred_alpha:new_from_image(shadow_colour)
local shadow = shadow_rgb:bandjoin(blurred_alpha)
-- Calculate final composite positions for shadow offsets
local final_offset = math.max(0, shadow_offset - shadow_radius)
-- Composite layers (shadow, then image)
local result = shadow:composite(img, "over", { x = final_offset }, { y = final_offset })
return result
end |
Beta Was this translation helpful? Give feedback.
-
Hello! I've really tried to get this working -- It seems to be working effectively with a set background, but I want to have a transparent background here. This is my latest attempt. I looked at the other discussions but wasn't able to translate effectively it seems.
Beta Was this translation helpful? Give feedback.
All reactions