translate palette defined to rgb variable

With palette it is easy to create color gradients

set view map
set samp 50,50

set palette defined (0 "blue", 1 "green", 2 "red")
spl "++" us 1:2:1 palette pt 5

Now I would like to apply transparency in vertical direction. The option lc rbg variable supports transparency via the alpha channel (see also here):

spl "++" us 1:2:1:(int(($2+5)/10*255)<<24) lc rgb var pt 5

But how can I translate the palette colors into rgb colors?

A second question: why I get only 10 horizontal rows, albeit I specified 50 in samp?

Upvotes: 1

Views: 409

Answers (2)

Ethan
Ethan

Reputation: 15093

Easy answer first: When there is 2-dimensional sampling, either automatically from splot or explicitly from plot '++', the number of samples in the first dimension is controlled by set sample and the number of samples in the second dimension is controlled by set isosample.

Now the harder one. In gnuplot versions through the current 5.2.8 you cannot add transparency directly to the palette. You can, however, go through a multi-step process of saving the palette into a file or datablock and then reading it back it as an array of RGB colors. Once you have that array you can add an alpha channel value so that it expresses transparency as well. I will show this process using the datablock created by the command test palette. In older versions of gnuplot you may have to instead use the file created by set print "palette.save"; show palette palette 256;.

# save current palette to a datablock as a list of 256 RGB colors, one per line
set palette defined (0 "blue", 1 "green", 2 "red")
test palette
# print one line to show the format (cbval R G B NTSCval)
print $PALETTE[4]
# Create an array of packed RGB values
array RGB[256]
do for [i=1:256] {
    Red = int(255. * word($PALETTE[i],2))
    Green = int(255. * word($PALETTE[i],3))
    Blue = int(255. * word($PALETTE[i],4))
    RGB[i] = Red << 16 | Green << 8 | Blue
}

# Sample from '++' are generated to span ranges on the u and v axes
# I choose 1:256 so that the y coordinates match the range of array indices
set sample 50
set isosample 50
set urange [1:256]
set vrange [1:256]
set xrange [*:*] noextend
set yrange [*:*] noextend

# Now you can use colors stored in the array via colorspec `rgb variable`
# which will also accept an alpha channel in the high bits
plot "++" using 1:2:(RGB[int($2)]) with points pt 5 lc rgb variable

# The final step is to add an alpha channel as a function of y
# Here I go from opaque (Alpha = 0) to 50% transparent (Alpha = 127)
# This works because I know y will run from 1-256 
ARGB(y) = RGB[int(y)] + (int(y/2)<<24)
plot "++" using 1:2:(ARGB($2)) with points pt 5 lc rgb variable

Output shown below. enter image description here

The required command sequence, as you can see, is a mess. It will be much easier in the next gnuplot release (5.4). The new version will provide a function palette(z) that converts from the current palette directly to a packed RGB value. Note that the palette() function isn't in the -rc1 testing version but will be in -rc2. So in version 5.4 all that palette/array/RGB manipulation can be replaced by

  plot '++' using 1:2:(palette($2) + (int($2)<<24)) with points pt 5 lc rgb variable

Upvotes: 3

theozh
theozh

Reputation: 25724

Check also this: Gnuplot: transparency of data points when using palette

First of all, you can check what your defined palette is doing:

set palette defined (0 "blue", 1 "green", 2 "red")
test palette

You will get this:

enter image description here

Each channel (R,G,B) has a function with an input range [0:1] and an output range [0:1]. In this case it is a linear gradient.

So, you have to define such a function and put the channels together with the transparency (alpha) channel using the bit shift (see help operators binary).

The nice thing about a palette is that gnuplot takes care about the range. Here, you have to know minimum and maximum in advance and scale the color accordingly. You could use stats for this.

Code:

### your own palette with transparency
reset session

r(x) = x < 0.5 ? 0 : 2*x -1
g(x) = x < 0.5 ? 2*x : 2-2*x
b(x) = x < 0.5 ? 1-2*x : 0
a(y) = y

myColor(x,y) = (int(a((y-yMin)/(yMax-yMin))*0xff)<<24) + \
               (int(r((x-xMin)/(xMax-xMin))*0xff)<<16) + \
               (int(g((x-xMin)/(xMax-xMin))*0xff)<<8) + \
                int(b((x-xMin)/(xMax-xMin))*0xff)

set samples 50
set isosamples 50
set size square

xMin=-5; xMax=5
yMin=-5; yMax=5

plot '++' u 1:2::(myColor($1,$2)) w p pt 5 ps 0.5 lc rgb var notitle

### end of code

Result:

enter image description here

Upvotes: 3

Related Questions