Skip to content

Instantly share code, notes, and snippets.

@appgurueu
Last active February 5, 2022 15:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save appgurueu/b6fab0f1e11e394705a6bb216507cf32 to your computer and use it in GitHub Desktop.
Save appgurueu/b6fab0f1e11e394705a6bb216507cf32 to your computer and use it in GitHub Desktop.
Average texture colors in Minetest using modlib
average_texture_color = setmetatable({}, {__index = function(self, filename)
local file = io.open(assert(modlib.minetest.media.paths[filename], filename), "rb")
local status, png = pcall(modlib.minetest.decode_png, file)
if not status then
error(filename .. ": " .. png)
end
assert(not file:read(1), "EOF expected")
file:close()
modlib.minetest.convert_png_to_argb8(png)
-- TODO make colorspecs extend vectors
local avg_color = modlib.vector.new{r = 0, g = 0, b = 0}
local total_alpha = 0
for _, color in pairs(png.data) do
color = modlib.minetest.colorspec.from_number(color)
-- Squared average
avg_color = modlib.vector.add(avg_color, modlib.vector.multiply_scalar(
modlib.vector.pow_scalar({r = color.r, g = color.g, b = color.b}, 2), color.a))
total_alpha = total_alpha + color.a
end
if total_alpha == 0 then total_alpha = 1 end -- Avoid division by zero
-- Round & convert back to colorspec
avg_color = modlib.minetest.colorspec.new(avg_color:divide_scalar(total_alpha):apply(math.sqrt):add_scalar(0.5):floor())
self[filename] = avg_color
return avg_color
end})
-- To initialize it all at startup (remove if you want lazy loading):
for filename in pairs(modlib.minetest.media.paths) do
if modlib.file.get_extension(filename) == "png" then
local _ = average_texture_color[filename]
end
end
return average_texture_color
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment