0

I want to achieve interpolation between red and blue. something like this

img

but in a single line.

My java code:

private PixelData InterpolateColour(float totalLength, float curLength){
    float startColourV[] = new float[3];
    Color.RGBtoHSB(m_start.getColour().getR() & 0xFF, m_start.getColour().getG()  & 0xFF, m_start.getColour().getB()  & 0xFF, startColourV);

    float endColourV[] = new float[3];
    Color.RGBtoHSB(m_end.getColour().getR()  & 0xFF, m_end.getColour().getG()  & 0xFF, m_end.getColour().getB()  & 0xFF, endColourV);

    float endPercent = curLength / totalLength;
    float startPercent = 1 - curLength / totalLength;

    float h = endColourV[0] * endPercent + startColourV[0] * startPercent;  
    float s = endColourV[1] * endPercent + startColourV[1] * startPercent;
    float b = endColourV[2] * endPercent + startColourV[2] * startPercent;

    int colourRGB = Color.HSBtoRGB(h, s, b);

    byte[] ByteArray = ByteBuffer.allocate(4).putInt(colourRGB).array();


    return new PixelData(ByteArray[0], ByteArray[3], ByteArray[2], ByteArray[1]); 
}

and the result i am getting is this

img.

I don't understand, from where all that green is coming from. Can somebody please help me ?

Spektre
  • 49,595
  • 11
  • 110
  • 380
  • Somebody out there who can help me ? –  May 26 '16 at 23:50
  • Well, red is at 0 degrees, blue is at 240 degrees, and green is right there in the middle between them at 120 degrees. If you interpolate that direction, you're going to get green. Maybe you should try going from 240 to 360. – beaker May 27 '16 at 01:57
  • @beaker Ok i interpolated from $\frac{4\pi}{3}$ to $2\pi$ .But what if i don't know what color is on the given ends, then what do i do ? –  May 27 '16 at 09:01
  • Possible duplicate of http://stackoverflow.com/a/23713317/2605733 ? – Abdul Fatir May 28 '16 at 10:01
  • @AbdulFatir Do you have any reason of down voting this question ? –  May 28 '16 at 10:06
  • @ritwiksinha What makes you think I downvoted? Even I was wondering why this was downvoted. – Abdul Fatir May 28 '16 at 10:08
  • @AbdulFatir Ok sorry.. –  May 28 '16 at 10:21

2 Answers2

0

why not use just RGB with simple linear interpolation for this:

color(t)=(color0*t)+(color1*(1.0-t))

where t=<0.0,1.0> is the parameter. So just loop it in the full range with as many steps as you need.

Integer C++/VCL example (sorry not a JAVA coder):

// borland GDI clear screen
Canvas->Brush->Color=clBlack;
Canvas->FillRect(ClientRect);
// easy access to RGB channels
union _color
    {
    DWORD dd;
    BYTE db[4];
    } c0,c1,c;
//    0x00BBGGRR
c0.dd=0x000000FF; // Red
c1.dd=0x00FF0000; // Blue
int x,y,t0,t1;
for (x=0,y=ClientHeight/2;x<ClientWidth;x++)
    {
    t0=x;
    t1=ClientWidth-1-x;
    c.db[0]=((DWORD(c0.db[0])*t0)+(DWORD(c1.db[0])*t1))/(ClientWidth-1);
    c.db[1]=((DWORD(c0.db[1])*t0)+(DWORD(c1.db[1])*t1))/(ClientWidth-1);
    c.db[2]=((DWORD(c0.db[2])*t0)+(DWORD(c1.db[2])*t1))/(ClientWidth-1);
    c.db[3]=((DWORD(c0.db[3])*t0)+(DWORD(c1.db[3])*t1))/(ClientWidth-1);
    Canvas->Pixels[x][y]=c.dd;
    }

where ClientWidth,ClientHeight is my app form resolution, Canvas is access to the GDI interface of the form and Canvas->Pixels[x][y] is single pixel access (slow but for this example it is enough). The only important stuff is the for loop. Here resulting image:

img

Spektre
  • 49,595
  • 11
  • 110
  • 380
  • Thanks. Actually i was able to achieve a correct interpolation with hsb by converting it to values between 0 and 2 * pi. now my problem is when i convert from rgb to hsb my alpha channel gets lost. So i will only implement your interpolation, if in your code alpha is also interpolated correctly. So can you please tell me if it works with alpha of not ? thanks again. –  May 28 '16 at 09:56
  • @ritwiksinha yes of coarse it works but you need to interpolate all 4 channels for that I added it to the code just now (4th interpolation line). If you need any help with port to JAVA just comment but it is really simple so I doubt any problems willsurface. The only thing that can change is the channel order somewhere it is RGBA and BGRA but the code stays as is just the color constants are changed – Spektre May 28 '16 at 09:58
  • RGB is a terrible colorspace to interpolate in. If it's gamma-adjusted sRGB you'll get a muddy brown between saturated red and green. If it's linear RGB you get [perceptually non-linear lightness gradients](https://en.wikipedia.org/wiki/Gamma_correction#Power_law_for_video_display). For perceptual color interpolation you want something like [CIELab](https://en.wikipedia.org/wiki/Lab_color_space) – the8472 May 28 '16 at 10:03
  • @the8472 so if i didn't interpolate in rgb, then how i converse alpha channel in hsb ? –  May 28 '16 at 10:25
  • @the8472 i got i solution to the problem , first i will interpolate rgb in hsb then covert it to rgb and add the alpha channel to it, which is interpolate separately. –  May 28 '16 at 10:42
0

Color interpolation is actually a fairly complex topic due to the way human vision works.

Physical intensity and wavelengths don't map directly to perceived luminance and hues. After all human eyes are not photon spectrometers, they just measure the intensity + three primaries, each with different sensitivity.

To have a metric, linear space that represents human color perception instead of physical attributes we have the CIELab. Since it's a linear metric doing interpolation between points should generally give you a linear transition between hues and also luminance.

But CIELab may not be sufficient since it only models perceptual sensitivity. If you need to match real lighting you also have to take into account that natural light sources do not illuminate all colors evenly.

If you need to match photorealistic material then additionally correcting for the intensity spectrum of natural light may also be necessary. I.e. something illuminated by a candle will not have intense blue components simply because the candle emits very little blue light that could be reflected.

the8472
  • 40,999
  • 5
  • 70
  • 122