Created
November 13, 2018 00:10
-
-
Save 1bardesign/68c34f9b772c8b10372abde78d429553 to your computer and use it in GitHub Desktop.
recolour.lua
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
example use | |
]] | |
local recolour = require("recolour") | |
--we want to recolour this asset image | |
local to_recolour = love.image.newImageData("path/to/image.png") | |
--using this palette image | |
local palette = love.image.newImageData("path/to/palette.png") | |
--using this palette (first non-source palette) | |
local palette_number = 1 | |
--get the recoloured image data | |
local recoloured = recolour(to_recolour, palette, palette_number) | |
--load into an image so we can render it | |
local image = love.graphics.newImage(recoloured) | |
--now free to render it as normal using lg.draw or whatever! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
(math helpers required) | |
(recommend having stuff like this in some central math.lua) | |
]] | |
--clamp v to range [lo, hi] | |
function math.clamp(v, lo, hi) | |
return math.max(lo, math.min(v, hi)) | |
end | |
--round v to nearest whole | |
function math.round(v) | |
return math.floor(v + 0.5) | |
end | |
--(required bitops) | |
local bit = require("bit") | |
local band, bor, lshift = bit.band, bit.bor, bit.lshift | |
--rgb hex -> r g b a (full alpha) | |
function math.getColorRGBHex(rgb) | |
local r = rshift(band(rgb, 0x00ff0000), 16) / 255.0 | |
local g = rshift(band(rgb, 0x0000ff00), 8) / 255.0 | |
local b = rshift(band(rgb, 0x000000ff), 0) / 255.0 | |
local a = 1.0 | |
return r, g, b, a | |
end | |
--r g b -> rgb hex (no alpha stored) | |
function math.colorToRGBHex(r, g, b) | |
local br = lshift(band(0xff, r * 255), 16) | |
local bg = lshift(band(0xff, g * 255), 8) | |
local bb = lshift(band(0xff, b * 255), 0) | |
return bor( br, bg, bb ) | |
end | |
--[[ | |
recolouring an asset based on an input palette | |
asset_data imagedata to recolour (in "source colours") | |
palette_data imagedata of palette | |
organised in vertical columns | |
first column = "input" palette | |
other columns = "output" palettes | |
palette_number which palette to use (0 for no recolour) | |
any colours not found in the palette will NOT be recoloured | |
this allows recolouring hair and skin and armour as separate | |
passes, without needing a super complicated palette | |
]] | |
local function recolour(asset_data, palette_data, palette_number) | |
--load | |
local data = asset_data:clone() | |
--recolour only if needed | |
palette_number = math.round(math.clamp(palette_number, 0, palette_data:getWidth() - 1)) | |
if palette_number ~= 0 then | |
--build mapping | |
local pixel_mapping = {} | |
for i = 0, palette_data:getHeight() - 1 do | |
local in_rgb = math.colorToRGBHex(palette_data:getPixel(0, i)) | |
local out_rgb = math.colorToRGBHex(palette_data:getPixel(palette_number, i)) | |
pixel_mapping[in_rgb] = out_rgb | |
end | |
--apply mapping | |
data:mapPixel(function(x, y, r, g, b, a) | |
--(don't need to remap totally transparent pixels) | |
if a ~= 0 then | |
local mapped = pixel_mapping[math.colorToRGBHex(r, g, b)] | |
if mapped ~= nil then | |
r, g, b = math.getColorRGBHex(mapped) | |
end | |
--(keep alpha the same) | |
end | |
return r, g, b, a | |
end) | |
end | |
return data | |
end | |
return recolour |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example tiles and palette file for brbl.
NOT for redistribution, all rights reserved