ritwik sinha ritwik sinha - 6 months ago 18
Java Question

Weird interpolation between colors in hsv?

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 ?

Answer

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

Comments