Skip to content

Instantly share code, notes, and snippets.

@jack0088 jack0088/Color.lua
Last active Aug 29, 2015

Embed
What would you like to do?
Simplified Painting App, made with Codea.
--# Color
-- modified version from https://github.com/EmmanuelOga/columns/blob/master/utils/color.lua
--[[
* Converts an RGB color value to HSL. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes r, g, and b are contained in the set [0, 255] and
* returns h, s, and l in the set [0, 1].
*
* @param Number r The red color value
* @param Number g The green color value
* @param Number b The blue color value
* @return Array The HSL representation
]]
function rgb2hsl(r, g, b)
r,g,b = r/255, g/255, b/255
local max, min = math.max(r,g,b), math.min(r,g,b)
local h, s, l = 0, 0, (max + min)/2 -- achromatic
if max ~= min then
local d = max - min
if l > .5 then s = d/(2 - max - min) else s = d/(max + min) end
if max == r then
h = (g - b)/d
if g < b then h = h + 6 end
elseif max == g then h = (b - r)/d + 2
elseif max == b then h = (r - g)/d + 4
end
h = h/6
end
return h,s,l
end
--[[
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes h, s, and l are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
*
* @param Number h The hue
* @param Number s The saturation
* @param Number l The lightness
* @return Array The RGB representation
]]
function hsl2rgb(h, s, l)
local r,g,b = l,l,l -- achromatic
if s ~= 0 then
local function hue2rgb(p, q, t)
if t < 0 then t = t + 1 end
if t > 1 then t = t - 1 end
if t < 1/6 then return p + (q - p) * 6 * t end
if t < 1/2 then return q end
if t < 2/3 then return p + (q - p) * (2/3 - t) * 6 end
return p
end
local q = l < .5 and l*(1 + s) or l + s - l*s
local p = 2 * l - q
r = hue2rgb(p, q, h + 1/3)
g = hue2rgb(p, q, h)
b = hue2rgb(p, q, h - 1/3)
end
return r*255, g*255, b*255
end
--[[
* Converts an RGB color value to HSV. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSV_color_space.
* Assumes r, g, and b are contained in the set [0, 255] and
* returns h, s, and v in the set [0, 1].
*
* @param Number r The red color value
* @param Number g The green color value
* @param Number b The blue color value
* @return Array The HSV representation
]]
function rgb2hsv(r, g, b)
r, g, b = r / 255, g / 255, b / 255
local max, min = math.max(r, g, b), math.min(r, g, b)
local h, s, v = nil, nil, max
local d = max - min
if max == 0 then s = 0 else s = d / max end
if max == min then h = 0
else
if max == r then h = g < b and h + 6 or (g - b) / d
elseif max == g then h = (b - r) / d + 2
elseif max == b then h = (r - g) / d + 4 end
h = h / 6
end
return h, s, v
end
--[[
* Converts an HSV color value to RGB. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSV_color_space.
* Assumes h, s, and v are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
*
* @param Number h The hue
* @param Number s The saturation
* @param Number v The value
* @return Array The RGB representation
]]
function hsv2rgb(h, s, v)
local r, g, b
local i = math.floor(h * 6);
local f = h * 6 - i;
local p = v * (1 - s);
local q = v * (1 - f * s);
local t = v * (1 - (1 - f) * s);
i = i % 6
if i == 0 then r, g, b = v, t, p
elseif i == 1 then r, g, b = q, v, p
elseif i == 2 then r, g, b = p, v, t
elseif i == 3 then r, g, b = p, q, v
elseif i == 4 then r, g, b = t, p, v
elseif i == 5 then r, g, b = v, p, q
end
return r * 255, g * 255, b * 255
end
--# Main
Scale = .25 -- image quality settings (may affect speed also)
Canvas = readImage("Documents:Canvas")
if not Canvas then
supportedOrientations(CurrentOrientation, (CurrentOrientation~=3 and CurrentOrientation~=1) and CurrentOrientation+1 or CurrentOrientation-1)
Canvas = image(WIDTH * Scale, HEIGHT * Scale)
else
if Canvas.width < Canvas.height then
supportedOrientations(PORTRAIT_ANY)
else
supportedOrientations(LANDSCAPE_ANY)
end
end
function setup()
noSmooth()
displayMode(OVERLAY)
parameter.boolean("Mirror", false)
parameter.color("BG", loadstring(readLocalData("BG", "return color(221,219,199,255)"))(), function()
if BG.a < 255 then BG.a = 255 end
saveLocalData("BG", "return color"..tostring(BG))
end)
parameter.color("Color", loadstring(readLocalData("Color", "return color(41,151,176,255)"))(), function()
if Colorpicker then Colorpicker = false end
if Color.a > 0 then Color.a = 255 end
Schade = select(3, rgb2hsl(Color.r, Color.g, Color.b))
saveLocalData("Color", "return color"..tostring(Color))
end)
parameter.boolean("Colorpicker", false)
parameter.number("Schade", .001, .999, Schade, function()
if Colorpicker then Colorpicker = false end
local h, s, l = rgb2hsl(Color.r, Color.g, Color.b)
Color = color(hsl2rgb(h, s, Schade))
saveLocalData("Color", "return color"..tostring(Color)) -- fix because Color = color() doesn't trigger its prameter callback
end)
parameter.integer("Size", 1, 50, loadstring(readLocalData("Size", "return 2"))(), function()
saveLocalData("Size", "return "..tostring(Size))
end)
end
function orientationChanged()
if _allowFlipping then
local flipped = image(Canvas.width, Canvas.height)
setContext(flipped)
sprite(Canvas, WIDTH/2 * Scale, HEIGHT/2 * Scale, -Canvas.width, Canvas.height)
setContext()
Canvas = flipped
else
_allowFlipping = true
end
end
local function deviceShaking()
local acceleration = UserAcceleration
local intensity = 2 -- adjust min. shaking intensity to trigger this event!
if UserAcceleration.x > intensity or acceleration.y > intensity or acceleration.z > intensity then
_deviceShakingUpdatedAt = ElapsedTime
_deviceShakingBegunAt = _deviceShakingBegunAt or ElapsedTime
-- first shake triggers listening process
-- listen if shaking continues for [x] seconds then device is considered shaking on purpose
if (ElapsedTime - _deviceShakingBegunAt) >= .5 then return true end
end
if _deviceShakingUpdatedAt and (ElapsedTime > (_deviceShakingUpdatedAt + .5)) then
_deviceShakingUpdatedAt = nil
_deviceShakingBegunAt = nil
end
return false
end
function draw()
background(BG)
sprite(Canvas, WIDTH/2, HEIGHT/2, WIDTH, HEIGHT)
if Mirror then
stroke(127)
strokeWidth(1)
line(WIDTH/2, 0, WIDTH/2, HEIGHT)
end
if Touch then
local size = not Colorpicker and Size*2 or 50
local pos = not Colorpicker and vec2(Touch.x, Touch.y) or vec2(Touch.x, Touch.y + size)
fill(Color)
strokeWidth(1)
stroke(0)
ellipse(pos.x, pos.y, size + strokeWidth())
stroke(255)
ellipse(pos.x, pos.y, size)
end
if deviceShaking() then
saveLocalData("BG", "return color(221,219,199,255)")
saveLocalData("Color", "return color(41,151,176,255)")
saveLocalData("Size", "return 2")
saveImage("Documents:Canvas", nil)
restart()
end
end
function touched(touch)
if not Touch or Touch.id == touch.id then Touch = touch end
if Touch.state == BEGAN then tween.resetAll() end
if Touch.state == ENDED then
if Touch.id == touch.id then
Touch = nil
if Colorpicker then Colorpicker = false end
if _SaveCanvas then
tween.delay(.375, function() saveImage("Documents:Canvas", Canvas) end)
_SaveCanvas = nil
end
end
else
if not Colorpicker then
setContext(Canvas)
noFill()
strokeWidth(Size/2)
stroke(Color)
if Color.a == 0 then
stroke(0,0,0,255)
blendMode(ZERO, ONE_MINUS_SRC_ALPHA)
end
line(Touch.prevX * Scale, Touch.prevY * Scale, Touch.x * Scale, Touch.y * Scale, ROUND)
if Mirror then line((WIDTH - Touch.prevX) * Scale, Touch.prevY * Scale, (WIDTH - Touch.x) * Scale, Touch.y * Scale, ROUND) end
setContext()
blendMode(NORMAL)
_SaveCanvas = true
else
local col = color(Canvas:get(Touch.x * Scale, Touch.y * Scale))
if col == color(0,0,0,0) then col = BG end
if col.a < 255 then col = Color end
Color = col
Schade = select(3, rgb2hsl(Color.r, Color.g, Color.b))
saveLocalData("Color", "return color"..tostring(Color)) -- fix because Color = color() doesn't trigger its prameter callback
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.