1
0
palette-swap/init.lua

135 lines
3.7 KiB
Lua

local palette_swap = {}
--------------------------------------------------------------------------------
-- Main work functions
local function get_palette_of_image_data (data)
assert(data)
--
local palette = {}
local has_seen = {}
--
for x = 0, data:getWidth() - 1 do
for y = 0, data:getHeight() - 1 do
local r, g, b = data:getPixel(x, y)
if not has_seen[r] then has_seen[r] = {} end
if not has_seen[r][g] then has_seen[r][g] = {} end
if not has_seen[r][g][b] then
local color = {r,g,b,a}
has_seen[r][g][b] = color
palette[#palette+1] = color
end
end
end
--
return palette
end
local function change_palette_to_dim_tree (change_palette)
assert(type(change_palette) == 'table')
--
local tree = {}
--
for color_from, color_to in pairs(change_palette) do
assert(type(color_from) == 'table')
assert(type(color_to) == 'table')
--
local r, g, b = unpack(color_from)
if not tree[r] then tree[r] = {} end
if not tree[r][g] then tree[r][g] = {} end
--
assert(not tree[r][g][b])
tree[r][g][b] = color_to
end
--
return tree
end
local function apply_change_palette (data, change_palette)
assert(data)
assert(change_palette)
--
local change_tree = change_palette_to_dim_tree(change_palette)
local function map (x, y, r, g, b, a)
local c = change_tree[r][g][b]
return c[1], c[2], c[3], a
end
--
local new_data = data:clone()
new_data:mapPixel(map)
--
return new_data
end
local function change_palette_from_map (map_func, palette)
local change_palette = {}
for i = 1, #palette do
local from = palette[i]
local to = {[4] = 1, map_func(unpack(from))}
change_palette[from] = to
end
return change_palette
end
--------------------------------------------------------------------------------
-- API
palette_swap.get_palette_from_image_data = get_palette_of_image_data
function palette_swap.apply_color_map_to_image_data (img_data, map_fn)
assert(img_data)
assert(type(map_fn) == 'function')
--
return apply_change_palette(img_data, change_palette_from_map(map_fn, get_palette_of_image_data(img_data)))
end
--------------------------------------------------------------------------------
-- Example color maps
palette_swap.color_map = {}
function palette_swap.color_map.invert (r,g,b)
return 1 - r, 1 - g, 1 - b
end
function palette_swap.color_map.switch_channel (mode)
local channels = {'r', 'g', 'b'}
local channel_order = {}
for i = 1, #channels do
local index = (mode % #channels) + 1
mode = mode / #channels
channel_order[#channel_order+1] = table.remove(channels,index)
end
local func_s = ("return function (r, g, b) return %s, %s, %s end"):format(unpack(channel_order))
return loadstring (func_s)()
end
function palette_swap.color_map.rotate_hue (rad)
-- Only need to import colors when needed
local colors = require 'colors'
assert(type(colors) == 'table')
assert(type(colors.rgb1_to_rgb255) == 'function')
assert(type(colors.rgb_to_hsl) == 'function')
assert(type(colors.hsl_to_rgb1) == 'function')
-- Create function
return function (r, g, b)
local hsl = colors.rgb_to_hsl(colors.rgb1_to_rgb255(r, g, b))
--
hsl[1] = (hsl[1] + rad) % 1
--
local rgb1 = colors.hsl_to_rgb1(hsl)
return unpack(rgb1)
end
end
--------------------------------------------------------------------------------
-- Return
return palette_swap