Hi Raul -

did you ever see my paper "Good Taste in Color and Soft Palettes" - written
for APL2001?  It's available on the ACM's digital library, if you
subscribe.  It is basically a rant in favor of array languages for
flexibility and ease of experimentation but the problem I address is coming
up with a "good" color palette by navigating the edges of the RGB cube.

It's mostly in APL but I steal some good ideas from Cliff Reiter's J code.
I've since re-written the APL from that paper in J.  Maybe your work will
inspire me to update it.

The basic code I stole from Cliff are these two things:

NB.* pwlin: piecewise linear function
pwlin=: 4 : 0"_ 0
   'p c'=. x
   i=. i.&0 p<y
   ((1-r),r=.(y-~i{p)%-/(i-0 1){p)+/ .* (i- 0 1){c
)

hue=: <.@(0.5&+)@(((6%~i.7);255*|."1#:7|3^i.7)&pwlin)"0
NB.EG hue 10%~i.10

So, the example use of "hue" shown here gives you 10 colors:
   hue 10%~i.10
255   0   0
255 153   0
204 255   0
 51 255   0
  0 255 102
  0 255 255
  0 102 255
 51   0 255
204   0 255
255   0 153





On Fri, Aug 9, 2013 at 12:25 PM, Raul Miller <[email protected]> wrote:

> I should probably document this color-thing somewhat.
>
> From a top down view, let's pretend that I researched how we perceive
> color (and how this can vary from person to person), and how that
> relates to various implementations of how computers implement color.
> But really, this is something of cubic representation of color, with
> the slider representing the white-black range, and the colored part
> representing a cross section of that cube perpendicular to the
> white/black axis.
>
> Anyways, this line:
>
> CORNERSETS=: ((+/&.:*:"1) <@(({~ giftwrap)^:(6=#))@~./. ]) ,/(([ +"1
> (85%~i.86) */ -~)/)"2 ((#~ </"1)8 8 #:I. ,/1=|+/&.:  *:"1 -"1/~ #:i.8)
> { #:i.8
>
> represents that cube.
>
> This value - CORNERSETS - is a boxed list with 256.  The first box
> represents black (color: 0 0 0 - red, green, blue) and the last box
> represents white (color: 1 1 1). This concept of representing a color
> as a sequence of three numbers in the range 0..1 is convenient for use
> with opengl.
>
> The rest of the boxes contain slices of a polygon (either three sided
> or six sided) corresponding to a slice across a color cube
> perpendicular to the white/black access.  Each element of a box can be
> thought of as an rgb color value, or as a corner of the face of a
> polygon.
>
> So let's go bottom-up, for a bit, to see how this gets constructed.
>
> A cube has eight corners, and we can number them:
>    i. 8
> 0 1 2 3 4 5 6 7
>
> The binary representation of these numbers can be thought of as rgb
> coordinates for these eight colors.
>    #:i.8
> 0 0 0
> 0 0 1
> 0 1 0
> 0 1 1
> 1 0 0
> 1 0 1
> 1 1 0
> 1 1 1
>
> But that's not enough for the color palette that I wanted. I want not
> just the corners, but lines between them.  And, for that, I decided to
> pair up adjacent corners, so that I could draw lines between them.
> That's this:
>
>     ((#~ </"1)8 8 #:I. ,/1=|+/&.:*:"1 -"1/~ #:i.8) { #:i.8
>
> The part in parenthesis first finds differences between all corner pairs:
>    -"1/~ #:i.8
>
> and then finds the distance described by that pair
>    +/&.:*:"1 -"1/~ #:i.8
>
> And then I take an absolute value for no good reason - it's a holdover
> from an earlier version that's not useful here.  (I built this code
> "artistically" - thinking of the effect I wanted and using trial and
> error, based on appearance and taste, and then posted it before doing
> any final cleanup - I felt that give some of you some of the flavor of
> my code building process might be useful to you?)
>
> Anyways, the edges I am interested in have a length of 1, so that's
> easy to define:
>    1=+/&.:*:"1 -"1/~ #:i.8
>
> wait, I'm throwing away all that work! oh no!
>
> But the interesting bit is in the coordinates of the array, so I
> haven't lost anything essential here.  All I need to do is ravel it
> and use I. and I almost have the coordinates of the interesting edges.
>  (And I should have just used , instead of ,/ to flatten the cube - at
> the time I wrote it, I wasn't thinking clearly there - ,/ gets rid of
> just the leading dimension, and I was not looking at my data and had
> forgotten that I only had two dimensions here.)  But the problem with
> I., is that I just get a single number for each 1 bit, and I want a
> pair of numbers.  But I can recover the information as separate
> numbers by using an octal representation:
>
>    8 8 #:I.,1=+/&.:*:"1 -"1/~ #:i.8
>
> That gives me 24 rows of result, and a cube only has 12 edges. I went
> a bit over board here, and am representing each edge twice.  I can
> throw away half of them, but which half?  One easy approach discards
> edges where the first index is greater than the second index.  (#~
> </"1) accomplishes this, but there's another way:
>
>    ~./:"1~8 8 #:I.,1=+/&.:*:"1 -"1/~ #:i.8
> 0 1
> 0 2
> 0 4
> 1 3
> 1 5
> 2 3
> 2 6
> 3 7
> 4 5
> 4 6
> 5 7
> 6 7
>
> Now all I need are the corresponding rgb values for each of these cube
> indices.  I had used (expression) { #:i.8 to get those values, but
> there's another way:
>
>       #: ~./:"1~8 8 #:I.,1=+/&.:*:"1 -"1/~ #:i.8
>
> Here, I've a rank three array:
>
>    $#:~./:"1~8 8 #:I.,1=+/&.:*:"1 -"1/~ #:i.8
> 12 2 3
>
> The 12 is the number of edges of a cube, the 2 is the number of ends
> of each edge, and the 3 is the number of dimensions (which I will
> think of as red, green, and blue).
>
> If I could think up a good name, I'd probably stuff this in a variable
> to make the rest of it easy.
>
> Since this is getting long, I'll save the rest of it for another day
> (unless someone else wants to take up the banner here?)
>
> But, briefly, 255=3*85 so I if I make each edge 85 units long (which
> becomes 86 values if I include the zero of the axis) I get a total of
> 256 values making up my cube diagonal. And, since we have a fair bit
> of hardware designed around a 256 division scale for color rendering
> that seemed like a nice choice.
>
> Also, these edges are not arranged in any particular order, so I use a
> convex hull algorithm (giftwrap) to arrange them in a form useful for
> opengl rendering.
>
> (And, yes, I am aware that some opengl hardware is... less than ideal?
> in terms of color quality. That's not a priority issue for me, at this
> stage of the game.)
>
> So... time for lunch for me. And then I need to do something useful
> for the people I work for. I may or may not come back to this bit of
> code at a later time. Meanwhile, hopefully I will be able to have
> provoked at least a little speculation about what I've written here
> and what other mistakes I've made?
>
> Thanks,
>
> --
> Raul
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
>



-- 
Devon McCormick, CFA
^me^ at acm.
org is my
preferred e-mail
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to