<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ASandbox%2Fisaacl%2FColourSpace</id>
	<title>Module:Sandbox/isaacl/ColourSpace - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ASandbox%2Fisaacl%2FColourSpace"/>
	<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Sandbox/isaacl/ColourSpace&amp;action=history"/>
	<updated>2026-06-07T22:50:35Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://stockhub.co/index.php?title=Module:Sandbox/isaacl/ColourSpace&amp;diff=146521&amp;oldid=prev</id>
		<title>imported&gt;Toohool: clarify invocation of BaseConvert</title>
		<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Sandbox/isaacl/ColourSpace&amp;diff=146521&amp;oldid=prev"/>
		<updated>2013-03-11T19:57:31Z</updated>

		<summary type="html">&lt;p&gt;clarify invocation of BaseConvert&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;
local me = { }&lt;br /&gt;
&lt;br /&gt;
local bc = require(&amp;#039;Module:BaseConvert&amp;#039;)&lt;br /&gt;
local Tuple = require(&amp;#039;Module:Sandbox/isaacl/ColourSpace/Tuple&amp;#039;)&lt;br /&gt;
local Formats = require(&amp;#039;Module:Sandbox/isaacl/ColourSpace/Formats&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
local infoFor = {&lt;br /&gt;
    sRGB = {&lt;br /&gt;
        colourSpace = &amp;#039;sRGB&amp;#039;,&lt;br /&gt;
        formatType = &amp;#039;float&amp;#039;,&lt;br /&gt;
        defaultConversion = &amp;#039;sRGB24bit&amp;#039;,&lt;br /&gt;
        parseInput = function(args)&lt;br /&gt;
            local digitPattern = &amp;#039;^([%.%d]+)%%?$&amp;#039;&lt;br /&gt;
            local red = string.match(args[1], digitPattern)&lt;br /&gt;
            local green = string.match(args[2], digitPattern)&lt;br /&gt;
            local blue = string.match(args[3], digitPattern)&lt;br /&gt;
            return { red, green, blue }&lt;br /&gt;
        end,&lt;br /&gt;
        isInputFormat = function(args)&lt;br /&gt;
            local sRGBPattern = &amp;#039;^[%.%d]+%%$&amp;#039;&lt;br /&gt;
            if ( args[3] ~= nil and&lt;br /&gt;
                string.match(args[1], sRGBPattern) and&lt;br /&gt;
                string.match(args[2], sRGBPattern) and&lt;br /&gt;
                string.match(args[3], sRGBPattern) ) then&lt;br /&gt;
                return true&lt;br /&gt;
            end&lt;br /&gt;
            return false&lt;br /&gt;
        end,  -- end of isInputFormat function&lt;br /&gt;
        display = function(self, separator)&lt;br /&gt;
            local red   = self[1] .. &amp;#039;%&amp;#039;&lt;br /&gt;
            local green = self[2] .. &amp;#039;%&amp;#039;&lt;br /&gt;
            local blue  = self [3] .. &amp;#039;%&amp;#039;&lt;br /&gt;
            return Tuple.display({ red, green, blue }, separator)&lt;br /&gt;
        end,&lt;br /&gt;
        mapParametersFrom = {&lt;br /&gt;
            sRGB24bit =&lt;br /&gt;
                function( colourValue )&lt;br /&gt;
                    local red = colourValue[1] / 255 * 100&lt;br /&gt;
                    local green = colourValue[2] / 255 * 100&lt;br /&gt;
                    local blue = colourValue[3] / 255 * 100&lt;br /&gt;
                    return { red, green, blue }&lt;br /&gt;
                end,&lt;br /&gt;
        },  -- end of mapping functions&lt;br /&gt;
&lt;br /&gt;
    },  -- info for sRGB&lt;br /&gt;
&lt;br /&gt;
    sRGB24bit = {&lt;br /&gt;
        colourSpace = &amp;#039;sRGB&amp;#039;,&lt;br /&gt;
        formatType = &amp;#039;24bit&amp;#039;,&lt;br /&gt;
        defaultConversion = &amp;#039;sRGB&amp;#039;,&lt;br /&gt;
        isInputFormat = function(args)&lt;br /&gt;
            local digitPattern = &amp;#039;^%d+$&amp;#039;&lt;br /&gt;
            if ( args[3] ~= nil and&lt;br /&gt;
                 string.match(args[1], digitPattern) and&lt;br /&gt;
                 string.match(args[2], digitPattern) and&lt;br /&gt;
                 string.match(args[3], digitPattern)&lt;br /&gt;
                 -- for some reason, tonumber() is required for range checking to work&lt;br /&gt;
                 and (tonumber(args[1]) &amp;lt;= 255)&lt;br /&gt;
                 and (tonumber(args[2]) &amp;lt;= 255)&lt;br /&gt;
                 and (tonumber(args[3]) &amp;lt;= 255)&lt;br /&gt;
            ) then&lt;br /&gt;
                 return true&lt;br /&gt;
            end&lt;br /&gt;
            return false&lt;br /&gt;
        end,&lt;br /&gt;
        display = function(self, separator)&lt;br /&gt;
            return Tuple.display(self, separator)&lt;br /&gt;
        end,&lt;br /&gt;
        mapParametersFrom = {&lt;br /&gt;
            sRGB = function(colourValue)&lt;br /&gt;
                local red   = math.floor(colourValue[1] * 255 / 100 + 0.5)&lt;br /&gt;
                local green = math.floor(colourValue[2] * 255 / 100 + 0.5)&lt;br /&gt;
                local blue  = math.floor(colourValue[3] * 255 / 100 + 0.5)&lt;br /&gt;
                return { red, green, blue }&lt;br /&gt;
            end,&lt;br /&gt;
            sRGB24bitHexString = function(colourValue)&lt;br /&gt;
                return colourValue&lt;br /&gt;
            end,&lt;br /&gt;
        },  -- end of mapping functions&lt;br /&gt;
&lt;br /&gt;
    },  -- info for sRGB24bit&lt;br /&gt;
&lt;br /&gt;
    sRGB24bitHexString = {&lt;br /&gt;
        colourSpace = &amp;#039;sRGB&amp;#039;,&lt;br /&gt;
        formatType = &amp;#039;24bit&amp;#039;,&lt;br /&gt;
        defaultConversion = &amp;#039;sRGB24bit&amp;#039;,&lt;br /&gt;
        parseInput = function(args)&lt;br /&gt;
            local red&lt;br /&gt;
            local green&lt;br /&gt;
            local blue&lt;br /&gt;
            local hexString = args[1]&lt;br /&gt;
            local hexCharPattern = &amp;#039;^#?(%x%x)(%x%x)(%x%x)$&amp;#039;&lt;br /&gt;
            local fDoubleChar = false&lt;br /&gt;
            if ( #hexString == 3 or #hexString == 4 ) then&lt;br /&gt;
                hexCharPattern = &amp;#039;^#?(%x)(%x)(%x)$&amp;#039;&lt;br /&gt;
                fDoubleChar = true&lt;br /&gt;
            end&lt;br /&gt;
            red, green, blue = string.match(hexString, hexCharPattern)&lt;br /&gt;
            if ( fDoubleChar ) then&lt;br /&gt;
                red = red .. red;&lt;br /&gt;
                green = green .. green;&lt;br /&gt;
                blue = blue .. blue;&lt;br /&gt;
            end&lt;br /&gt;
    &lt;br /&gt;
            red = bc.convert({n = red, base = 10, from = 16})&lt;br /&gt;
            green = bc.convert({n = green, base = 10, from = 16})&lt;br /&gt;
            blue = bc.convert({n = blue, base = 10, from = 16})&lt;br /&gt;
            return { red, green, blue }&lt;br /&gt;
        end,&lt;br /&gt;
        isInputFormat = function(args)&lt;br /&gt;
            if (   string.match(args[1], &amp;#039;^#%x%x%x$&amp;#039;)&lt;br /&gt;
                or string.match(args[1], &amp;#039;^#%x%x%x%x%x%x$&amp;#039; ) ) then&lt;br /&gt;
                return true&lt;br /&gt;
            end&lt;br /&gt;
            return false&lt;br /&gt;
        end,&lt;br /&gt;
        display = function(self, separator)&lt;br /&gt;
            local red   = string.format(&amp;#039;&amp;amp;#35;%02X&amp;#039;, self[1])&lt;br /&gt;
            local green = string.format(&amp;#039;%02X&amp;#039;, self[2])&lt;br /&gt;
            local blue  = string.format(&amp;#039;%02X&amp;#039;, self[3])&lt;br /&gt;
            return Tuple.display({ red, green, blue }, &amp;#039;&amp;#039;)&lt;br /&gt;
        end,&lt;br /&gt;
        mapParametersFrom = {&lt;br /&gt;
            sRGB24bit = function( colourValue )&lt;br /&gt;
                return colourValue&lt;br /&gt;
            end,&lt;br /&gt;
        },  -- end of mapping functions&lt;br /&gt;
&lt;br /&gt;
    },  -- info for sRGB24bitHexString&lt;br /&gt;
&lt;br /&gt;
}  -- data for formats&lt;br /&gt;
&lt;br /&gt;
function me.buildColourTuple(args, parameters)&lt;br /&gt;
    local result = Tuple.clone(args)&lt;br /&gt;
    result.format = parameters.format&lt;br /&gt;
    result.colourSpace = parameters.colourSpace&lt;br /&gt;
    result.defaultConversion = parameters.defaultConversion&lt;br /&gt;
    result.fValid = true&lt;br /&gt;
    result.display = function(self, separator)&lt;br /&gt;
        return parameters.displayFunc(self, separator)&lt;br /&gt;
    end&lt;br /&gt;
    return result&lt;br /&gt;
end -- function buildColourTuple&lt;br /&gt;
&lt;br /&gt;
local options = {&lt;br /&gt;
    separator = &amp;#039;, &amp;#039;,&lt;br /&gt;
    displayPrefix = &amp;#039;&amp;#039;,&lt;br /&gt;
    displaySuffix = &amp;#039;&amp;#039;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local formatTypeFor = { }&lt;br /&gt;
&lt;br /&gt;
local checkInputFormatFor = { }&lt;br /&gt;
&lt;br /&gt;
me.create = { }&lt;br /&gt;
&lt;br /&gt;
local createFromParsedInput = { }&lt;br /&gt;
&lt;br /&gt;
me.mapTo = { }&lt;br /&gt;
&lt;br /&gt;
local colourSpaceFor = { }&lt;br /&gt;
&lt;br /&gt;
local commonFormatForColourSpace = {&lt;br /&gt;
    sRGB = {&lt;br /&gt;
        andFormatType = {&lt;br /&gt;
            float = &amp;#039;sRGB&amp;#039;,&lt;br /&gt;
            [&amp;#039;24bit&amp;#039;] = &amp;#039;sRGB24bit&amp;#039;,&lt;br /&gt;
        },&lt;br /&gt;
    },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local function createInvalidColourValue(errorMsg)&lt;br /&gt;
    local invalidColourValue = {&lt;br /&gt;
        -1, -1, -1,&lt;br /&gt;
        fValid = false,&lt;br /&gt;
        errorMessage = errorMsg,&lt;br /&gt;
        display = function(self, separator)&lt;br /&gt;
            return &amp;#039;InvalidValue &amp;#039; .. self.errorMessage&lt;br /&gt;
        end,&lt;br /&gt;
    }&lt;br /&gt;
    return invalidColourValue&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
me.configureFormatInfo = function(infoFor)&lt;br /&gt;
    for format, info in pairs(infoFor) do&lt;br /&gt;
        -- If basic information for the format has not been defined&lt;br /&gt;
        -- already, configure it&lt;br /&gt;
        if ( me.create[format] == nil ) then&lt;br /&gt;
            createFromParsedInput[format] = function(parsedArgs)&lt;br /&gt;
                return me.buildColourTuple(parsedArgs, {&lt;br /&gt;
                      format = format,&lt;br /&gt;
                      colourSpace = info.colourSpace,&lt;br /&gt;
                      defaultConversion = info.defaultConversion,&lt;br /&gt;
                      displayFunc = info.display,&lt;br /&gt;
                })&lt;br /&gt;
            end  -- function createFromParsedInput[format]&lt;br /&gt;
            me.create[format] = function (args)&lt;br /&gt;
                local parsedArgs&lt;br /&gt;
                if ( info.parseInput ~= nil ) then&lt;br /&gt;
                    parsedArgs = info.parseInput(args)&lt;br /&gt;
                else&lt;br /&gt;
                    parsedArgs = args &lt;br /&gt;
                end&lt;br /&gt;
                if ( parsedArgs == nil ) then&lt;br /&gt;
                    return createInvalidColourValue(&amp;#039;badInputValues&amp;#039;)&lt;br /&gt;
                end&lt;br /&gt;
&lt;br /&gt;
                return createFromParsedInput[format](parsedArgs)&lt;br /&gt;
            end  -- function me.create[format]&lt;br /&gt;
&lt;br /&gt;
            formatTypeFor[format] = info.formatType&lt;br /&gt;
            colourSpaceFor[format] = info.colourSpace&lt;br /&gt;
&lt;br /&gt;
            if ( info.isInputFormat ~= nil ) then&lt;br /&gt;
                checkInputFormatFor[format] = info.isInputFormat&lt;br /&gt;
            end&lt;br /&gt;
        end  -- if me.create[format] == nil, configure basic info for format&lt;br /&gt;
&lt;br /&gt;
        -- Define mapping functions from other formats to the&lt;br /&gt;
        -- current format being configured.&lt;br /&gt;
        for startFormat, mapper in pairs(info.mapParametersFrom) do&lt;br /&gt;
            if ( me.mapTo[format] == nil ) then&lt;br /&gt;
                me.mapTo[format] = { from = { } }&lt;br /&gt;
            end&lt;br /&gt;
            me.mapTo[format].from[startFormat] =&lt;br /&gt;
                function(parameters)&lt;br /&gt;
                    local copy = Tuple.clone(parameters)&lt;br /&gt;
                    local mappedParameters = mapper(copy)&lt;br /&gt;
&lt;br /&gt;
                    if ( mappedParameters == nil ) then&lt;br /&gt;
                        return createInvalidColourValue(&amp;#039;conversionError &amp;#039;&lt;br /&gt;
                            .. parameters:display()&lt;br /&gt;
                            )&lt;br /&gt;
                    end&lt;br /&gt;
                    &lt;br /&gt;
                    return createFromParsedInput[format]( mappedParameters )&lt;br /&gt;
                end&lt;br /&gt;
        end  -- loop over info.mapParametersFrom&lt;br /&gt;
    end  -- loop over infoFor table&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
me.configureFormatInfo(infoFor)&lt;br /&gt;
&lt;br /&gt;
for idx=1, #Formats do&lt;br /&gt;
    local formatInfo = require(&amp;#039;Module:Sandbox/isaacl/ColourSpace/Formats/&amp;#039; .. Formats[idx])&lt;br /&gt;
    me.configureFormatInfo(formatInfo.infoFor)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function me.loadFormatInfo(format)&lt;br /&gt;
    -- try to load the required module for the format&lt;br /&gt;
    local formatInfo = require(&amp;#039;Module:Sandbox/isaacl/ColourSpace/Formats/&amp;#039;&lt;br /&gt;
        .. format)&lt;br /&gt;
    if ( formatInfo ~= nil ) then&lt;br /&gt;
        me.configureFormatInfo(formatInfo.infoFor)&lt;br /&gt;
        return format&lt;br /&gt;
    end&lt;br /&gt;
    return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function me.determineInputFormat(frame)&lt;br /&gt;
    local args = frame.args&lt;br /&gt;
    local fromFormat = frame.args[&amp;quot;from&amp;quot;]&lt;br /&gt;
    if (fromFormat ~= nil) then&lt;br /&gt;
        if ( me.create[fromFormat] ~= nil ) then&lt;br /&gt;
            return fromFormat&lt;br /&gt;
        else&lt;br /&gt;
            -- try to load the required module for the format&lt;br /&gt;
            return me.loadFormatInfo(fromFormat)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    for format, isInputFormat in pairs(checkInputFormatFor) do&lt;br /&gt;
        if ( isInputFormat(args) ) then&lt;br /&gt;
            return format&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- unable to deduce format&lt;br /&gt;
    return nil&lt;br /&gt;
end  -- function determineInputFormat()&lt;br /&gt;
&lt;br /&gt;
local function determineOutputFormat(frame, startValue)&lt;br /&gt;
    local toFormat = frame.args[&amp;quot;to&amp;quot;]&lt;br /&gt;
    if (toFormat ~= nil) then&lt;br /&gt;
        if ( me.create[toFormat] ~= nil ) then&lt;br /&gt;
            return toFormat&lt;br /&gt;
        else&lt;br /&gt;
            -- try to load the required module for the format&lt;br /&gt;
            return me.loadFormatInfo(toFormat)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    -- use default conversion&lt;br /&gt;
    return startValue.defaultConversion&lt;br /&gt;
end  -- function determineOutputFormat()&lt;br /&gt;
&lt;br /&gt;
local function convertBetweenFormats(colourValue, listOfFormats)&lt;br /&gt;
    local convertedValue = colourValue&lt;br /&gt;
    for idx, nextFormat in ipairs(listOfFormats) do&lt;br /&gt;
        if (convertedValue.format ~= nextFormat) then&lt;br /&gt;
            if ( me.mapTo[nextFormat].from[convertedValue.format] == nil ) then&lt;br /&gt;
                return createInvalidColourValue(&amp;#039;noConversionAvailable from &amp;#039;&lt;br /&gt;
                    .. convertedValue.format .. &amp;#039; to &amp;#039; .. nextFormat)&lt;br /&gt;
            end&lt;br /&gt;
            convertedValue = me.mapTo[nextFormat].from[convertedValue.format](convertedValue)&lt;br /&gt;
            if (not convertedValue.fValid) then&lt;br /&gt;
                -- error in conversion; return immediately with the invalidValue&lt;br /&gt;
                return convertedValue&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end  -- loop over list of formats to convert between&lt;br /&gt;
    return convertedValue&lt;br /&gt;
end  -- function convertBetweenFormats&lt;br /&gt;
&lt;br /&gt;
function me.convertColour(frame)&lt;br /&gt;
    if ( frame.args[1] == nil ) then&lt;br /&gt;
        return &amp;#039;&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if ( frame.args.separator ~= nil ) then&lt;br /&gt;
        options.separator = frame.args.separator&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local startFormat = me.determineInputFormat(frame)&lt;br /&gt;
    if ( startFormat == nil ) then&lt;br /&gt;
        return &amp;#039;badInputFormat&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local startValue = me.create[startFormat](frame.args)&lt;br /&gt;
&lt;br /&gt;
    if ( not startValue.fValid ) then&lt;br /&gt;
        return startValue:display()&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local endFormat = determineOutputFormat(frame, startValue)&lt;br /&gt;
&lt;br /&gt;
    if ( endFormat == nil ) then&lt;br /&gt;
        return &amp;#039;badOutputFormat&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if ( startFormat == endFormat ) then&lt;br /&gt;
        return startValue:display(options.separator)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local result = { }&lt;br /&gt;
&lt;br /&gt;
    -- If a direct conversion exists, use it&lt;br /&gt;
    if (me.mapTo[endFormat].from[startFormat] ~= nil) then&lt;br /&gt;
        result = me.mapTo[endFormat].from[startFormat](startValue)&lt;br /&gt;
        return result:display(options.separator)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local listOfFormats = { }&lt;br /&gt;
&lt;br /&gt;
    -- If the start and end formats are in the same colour space:&lt;br /&gt;
    -- first, convert to the common format for the starting colour space and format type&lt;br /&gt;
    -- second, convert to the common format for the ending colour space and format type&lt;br /&gt;
    -- third, convert to the ending format type&lt;br /&gt;
&lt;br /&gt;
    if (colourSpaceFor[startFormat] == colourSpaceFor[endFormat]) then&lt;br /&gt;
        table.insert(listOfFormats,&lt;br /&gt;
            commonFormatForColourSpace[colourSpaceFor[startFormat]].andFormatType[formatTypeFor[startFormat]] )&lt;br /&gt;
        table.insert(listOfFormats,&lt;br /&gt;
            commonFormatForColourSpace[colourSpaceFor[endFormat]].andFormatType[formatTypeFor[endFormat]] )&lt;br /&gt;
        table.insert(listOfFormats, endFormat)&lt;br /&gt;
    &lt;br /&gt;
        result = convertBetweenFormats(startValue, listOfFormats)&lt;br /&gt;
    else&lt;br /&gt;
        -- if the start and end formats are in different colour spaces:&lt;br /&gt;
        -- first, convert to the common format for the starting colour space and format type&lt;br /&gt;
        -- second, convert to the common floating point format for the starting colour space&lt;br /&gt;
        -- third, convert to the common floating point format for the ending colour space&lt;br /&gt;
        -- fourth, convert to the common format for the ending colour space and format type&lt;br /&gt;
        -- fifth, convert to the ending format type&lt;br /&gt;
        table.insert(listOfFormats,&lt;br /&gt;
            commonFormatForColourSpace[colourSpaceFor[startFormat]].andFormatType[formatTypeFor[startFormat]] )&lt;br /&gt;
        table.insert(listOfFormats,&lt;br /&gt;
            commonFormatForColourSpace[colourSpaceFor[startFormat]].andFormatType.float )&lt;br /&gt;
        table.insert(listOfFormats,&lt;br /&gt;
            commonFormatForColourSpace[colourSpaceFor[endFormat]].andFormatType.float )&lt;br /&gt;
        table.insert(listOfFormats,&lt;br /&gt;
            commonFormatForColourSpace[colourSpaceFor[endFormat]].andFormatType[formatTypeFor[endFormat]] )&lt;br /&gt;
        table.insert(listOfFormats, endFormat)&lt;br /&gt;
    &lt;br /&gt;
        result = convertBetweenFormats(startValue, listOfFormats)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return result:display(options.separator)&lt;br /&gt;
end  -- function convertColour()&lt;br /&gt;
&lt;br /&gt;
function me.convertColour_fromTemplate(frame)&lt;br /&gt;
    return me.convertColour(frame:getParent())&lt;br /&gt;
end  -- function templateConvertColour()&lt;br /&gt;
&lt;br /&gt;
return me&lt;/div&gt;</summary>
		<author><name>imported&gt;Toohool</name></author>
	</entry>
</feed>