commit 198532fd3b87d1210230e221be416b5d482d6547 Author: Jon Michael Aanes Date: Sun Jun 9 17:39:28 2019 +0200 Initial commit of new palette swapping library. Uses `colors` library for certain functionality. diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..7fe60d8 --- /dev/null +++ b/init.lua @@ -0,0 +1,134 @@ + +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 +