c++ - Linear color gradient not working -


i'm attempting create color gradient class mandelbrot set explorer.

it reads color constraints (rgba8888 color , position between 0 , 1) text file , adds them vector, lateron used determine colors @ position.

to compute color, algorithm searches next constraint either side given position, splits color 4 single channels, , then, each one, searches lower of both , adds portion of difference equal ratio (x-lpos)/(upos-lpos) lower color. afterwards, channels shifted , ored together, , returned rgba8888 unsigned integer. (see code below.)

edit: rewrote gradient class, fixing issues , making more readable sake of debugging (it gets slow hell, though, -os more or less takes care of that). however, it's still not it's supposed be.

class gradient { //remade, irrelevant methods , de-/constructors removed private:     map<double, unsigned int> constraints; public:     unsigned int operator[](double value) {         //forbid out-of-range values, return black         if (value < 0 || value > 1+1e-10) return 0xff;         //find upper , lower constraint         auto upperc = constraints.lower_bound(value);         if (upperc == constraints.end()) upperc = constraints.begin();         auto lowerc = upperc == constraints.begin() ? prev(constraints.end(), 1) : prev(upperc, 1);         if (value == lowerc->first) return lowerc->second;         double lpos = lowerc->first;         double upos = upperc->first;         if (upos < lpos) upos += 1;         //lower color channels         unsigned char lred = (lowerc->second >> 24) & 0xff;         unsigned char lgreen = (lowerc->second >> 16) & 0xff;         unsigned char lblue = (lowerc->second >> 8) & 0xff;         unsigned char lalpha = lowerc->second & 0xff;         //upper color channels         unsigned char ured = (upperc->second >> 24) & 0xff;         unsigned char ugreen = (upperc->second >> 16) & 0xff;         unsigned char ublue = (upperc->second >> 8) & 0xff;         unsigned char ualpha = upperc->second & 0xff;         unsigned char red = 0, green = 0, blue = 0, alpha = 0xff;         //compute each channel using         //  lower color + dist(lower, x)/dist(lower, upper) * diff(lower color, upper color)         if (lred < ured)             red = lred + (value - lpos)/(upos - lpos) * (ured - lred);         else red = ured + (upos - value)/(upos - lpos) * (ured - lred);         if (lgreen < ugreen)             green = lgreen + (value - lpos)/(upos - lpos) * (ugreen - green);         else green = ugreen + (upos - value)/(upos - lpos) * (ugreen - lgreen);         if (lblue < ublue)             blue = lblue + (value - lpos)/(upos - lpos) * (ublue - lblue);         else blue = ublue + (upos - value)/(upos - lpos) * (ublue - lblue);         if (lalpha < ualpha)             alpha = lalpha + (value - lpos)/(upos - lpos) * (ualpha - lalpha);         else alpha = ualpha + (upos - value)/(upos - lpos) * (ualpha - lalpha);         //merge channels , return         return (red << 24) | (green << 16) | (blue << 8 ) | alpha;     }     void addconstraint(unsigned int color, double position) {         constraints[position] = color;     } }; 

usage in update method:

image[r + rres*i] = grd[ratio]; //with image being vector<unsigned int>, used data source `sdl_texture` using `sdl_updatetexture` 

it works partially, though. when use black/white gradient, resulting image intended:

black-white works flawlessly

gradient file:

2 0 000000ff 1 ffffffff 

however, when use more colorful gradient (a linear version of ultra fractal gradient, input file below), the image far intended result image still doesn't show desired coloring:

enter image description here

gradient file:

5 0       000764ff .16     206bcbff .42     edffffff .6425   ffaa00ff 0.8575  000200ff 

what doing wrong? i've rewritten operator[] method multiple times, without changing.

questions clarification or general remarks on code welcome.

your problem due over-complicated interpolation function.

when linearly interpolating in range a .. b using factor r (with range 0 .. 1) indicate position in range it's unnecessary determine whether a or b greater. either way around can use:

result = + r * (b - a) 

if r == 0 trivially shown a, , if r == 1 a - a cancels out leaving b. if r == 0.5 result (a + b) / 2. doesn't matter if a > b or vice-versa.

the preferred formulation in case, since avoids b - a subtraction possibly hits range clamping limits is:

result = (1 - r) * + r * b; 

which given appropriate * , + operators on new rgba class gives trivial implementation of mid function (with no need per-component operations since they're handled in operators):

static rgba mid(const rgba& a, const rgba& b, double r) {     return (1.0 - r)  * + r * b; } 

see https://gist.github.com/raybellis/4f69345d8e0c4e83411b, i've refactored rgba class put clamping operations in constructor rather within individual operators.


Comments

Popular posts from this blog

How to group boxplot outliers in gnuplot -

cakephp - simple blog with croogo -

bash - Performing variable substitution in a string -