Ai's ramp stuff inspired this idea: a palette-tool/colour-select-mode which extracts all possible/practical ramps from the palette within given thresholds. Could also be a handy tool for testing the development of generic palettes.
This is possible -- I've tried it! It's quite demanding in terms of making a system that does it well.
Some things it needs:
* sane color system (standard sRGB is right out. so is linear RGB, probably, and of course so is HSV/HSL/HWB/what-have-you-variant of hue-something-something. XYZ might be possible, I know LAB works, and LCH might work even better, YCbCr or YiQ might have some value (I haven't really played with them much))
* graph algorithms. Essentially, we are building a graph with colors as nodes, and each node connected (directionally) to every other node which satisfies the threshold. We then need to iterate through the graph with the constraint that we move monotonically (ie. either always brighter, or always darker). The iteration is like iterating over multiple trees, and each subtree produces multiple output ramps.
EDIT: actually, we only ever need to move in one direction (say brighter). We can just store the output in reversed order if the user wants that.
* a reasonable display method. Even for quite small numbers of source colors, the number of output ramps can become quite large.
Might be helpful to partition the ramps (eg ramps including color1, ramps including color2, ramps 3..5 entries long, ramps 4..8 entries long..)
For example, supposing you have a simple single ramp of length 4. the number of ramps of length >=2 equals 2**4 - (4 + 1) = 11 including the original ramp. Supposing instead that you have 4 ramps of length 4 in which every color in a given position is similar enough to the neighbouring colors that it can be between any two colors, this is (calculated through brute-force with my function iterate_ordered_permutations:) 608 ramps totalling 1996 entries, with 256 of those ramps having the full 4 colors per ramp (also 256 of the ramps have 3 colors, and the remaining ramps of length 2 number 96).
This is actually close to an best-case. I've calculated some statistics using a graphing library, and with a set of 16 colors randomly assigned intensities 0..32, the total number of entries in the result ranges from 10000 to 26623 entries (65535 being the maximum for an input set of 16 colors -- (2**16) - 1) with about 120 edges in the graph on average.
With a threshold of 2 (that amounts to 1/16th of total intensity, which implicitly limits ramp length to <= 16) we get from 3167 ... 13823 entries, with average 111 edges.(There are more possible ramps as the ramps become longer, btw.. so the largest ramps occupy most of that space.). doubling it to 4 (1/8th of total intensity, limiting ramp length to <=
produces 539 .. 1439 with average 96 edges
threshold = 6 (effective max ramp length == 5) produces 259...923 entries with average 82 edges. This is approaching the realm of reasonableness.
Now, lets see what happens when I increase the number of source colors by 1. 384..881 entries, avg 88 edges
If I double the number of source 'color's to 32 (and double the threshold to compensate), 2552... 4979 entries, avg 330 edges
If I reduce threshold to 4 (4/64 intensity step, max ramp len = 16), we get : 354815 ... 1892735 entries, avg 450 edges.
With threshold = 5 (5/64 intensity step, max ramp len = 13), we get : 148031 ... 602111 entries, avg 440 edges.
We should divide these figures by about 3, since the threshold would most likely be expressed in units of delta-E
http://www.colorwiki.com/wiki/Delta_E:_The_Color_Difference#Delta-E_1976 which will involve three criteria (each of the LAB color channels)
and these figures are still fairly ludicrously large after that. You're only safe from being overwhelmed if you're looking for a short ramp (<= 6 colors), since for each increment of ramp length, number of possible ramps balloons hugely.
One good point is that it's computationally undemanding for typical numbers of input colors: we must compare all colors with all other colors to create the graph; with 256 input colors this is only 32640 color comparisons. then we must iterate through all nodes recursively, rejecting paths that are only one point long, and storing paths as they terminate (or as we finish processing a branch node, we store the path leading up to it but no further). This may require 2 * sum_of_path_lengths (the often huge number I've calculated several times above, eg. 148031..602111) bytes of memory.
EDIT:
I have an algorithm to do this. It does everything except actually store the results -- currently it just counts tree sum_of_path_lengths by accumulating the lengths of all subpaths.
The color comparison/thresholding and building the graph is trivial.
the current implementation of path length calculation looks like:
def lengths (graph, node):
"""Return the lengths of the paths originating at node.
Graph must not be circular.
"""
successors = graph.successors (node)
count = 1
if len (successors) == 0:
return 1 # just ourself
for succ in successors:
count += lengths (graph, succ)
return count
Then the overall counting code just sums the result of calling this on every node (omitting nodes that have no successors, ie. length = 1).
with a slight change of parameters, this could be readily adapted to store results.
This idea needs more work. Perhaps by specifying colors that must be in the output ramp, you could reduce the number of outputs sufficiently.One other thing -- a sample colorization would be essential for previewing ramps. Using some carefully-picked grayscale images to demonstrate what the ramp will look like.
- Having to box select each tile to copy, even aided by grid snapping, was annoyingly inefficient. The simplest of mockup tools would be two hot-key invoked commands: copy-grid-box-under-cursor, paste-to-grid-box-under-cursor. Maybe also with a size option to work with multiple tile features.
Thanks for mentioning this!!!
It inspired this idea for tile reorganization, where you can click on a number of tiles to copy them collectively.
(sort of like a tilemap-chunk brush)