// // fcolour.cc // // Colour class // // Copyright (C) J. Belson 2000.05.20 // #include #include #include "fcolour.h" using namespace std; /** * Constructor */ fcolour::fcolour(float red, float green, float blue, float transparency) { r = red; g = green; b = blue; alpha = transparency; } /** * Construct from RGBA format */ fcolour::fcolour(uint32 col) { #if __POWERPC__ r = ((col >> 24)&0x000000ff)/255.0; g = ((col >> 16)&0x000000ff)/255.0; b = ((col >> 8)&0x000000ff)/255.0; #else r = ((col >> 16)&0x000000ff)/255.0; g = ((col >> 8)&0x000000ff)/255.0; b = ((col >> 0)&0x000000ff)/255.0; #endif } /** * Add another colour to this */ fcolour fcolour::operator+(fcolour c) { #if 0 float red = c.alpha*c.r + (1.0 - c.alpha)*r; float green = c.alpha*c.g + (1.0 - c.alpha)*g; float blue = c.alpha*c.b + (1.0 - c.alpha)*b; fcolour temp(red, green, blue); #else fcolour temp(r + c.r, g + c.g, b + c.b); #endif return temp; } /** * Subtract another colour from this * @todo Fix for alpha blending. */ fcolour fcolour::operator-(fcolour c) { fcolour temp(r - c.r, g - c.g, b - c.b); return temp; } /** * Scale this colour by factor 'f'. Transparency * is unaffected. */ fcolour fcolour::operator*(float f) { // assert(f >= 0.0); // assert(f <= 1.0); fcolour temp(r*f, g*f, b*f); return temp; } /** * Scale another colour by this (redundant) */ fcolour fcolour::operator/(float f) { // assert(f >= 0.0); // assert(f <= 1.0); fcolour temp(r/f, g/f, b/f); return temp; } /** * Multiply this colour by another.

* Eg. a red light striking a blue surface. * @note Fix this for transparency. */ fcolour fcolour::operator*(fcolour c) { fcolour temp(r*c.r, g*c.g, b*c.b); return temp; } /** * Exposure function */ void fcolour::exposure(fcolour& c, float exp) { c.r = 1.0 - expf(-c.r*exp); c.g = 1.0 - expf(-c.g*exp); c.b = 1.0 - expf(-c.b*exp); } /** * Write colour components of a given colour to a stream * @param str stream to write to * @param c colour to write */ ostream& operator<<(ostream& str, fcolour& c) { str << "(" << c.r << ", " << c.g << ", " << c.b << ")"; return str; } /** * Clamp this colour's range to displayable values */ void fcolour::clamp(void) { if (r > 1.0) r = 1.0; if (g > 1.0) g = 1.0; if (b > 1.0) b = 1.0; if (r < 0.0) r = 0.0; if (g < 0.0) g = 0.0; if (b < 0.0) b = 0.0; } /** * Normalise this colour to range 0.0 - 1.0 by desaturating */ void fcolour::normalise(void) { // Find component with greatest magnitude float max = (r > g) ? r : g; max = (b > max) ? b : max; // Only need to desaturate if a component is out of range if (max > 1.0) { r /= max; g /= max; b /= max; } } /** * Alpha blend this colour with another colour. * @param Colour to blend with. * @return Blended colour. */ fcolour fcolour::blend(fcolour& c) { float red = c.alpha*c.r + (1.0 - c.alpha)*r; float green = c.alpha*c.g + (1.0 - c.alpha)*g; float blue = c.alpha*c.b + (1.0 - c.alpha)*b; fcolour temp(red, green, blue); return temp; } /** * Convert rgb triplet to uint32 RGB * @todo Hopefully this handles the little endian case for PowerPC * processors, but I don't know if there is a generic define for * little endian in general. */ uint32 fcolour::make_rgb32(uint8 r, uint8 g, uint8 b) { #if __POWERPC__ return (uint32(r) << 24) | (uint32(g) << 16) | (uint32(b) << 8); #else return (uint32(r) << 16) | (uint32(g) << 8) | (uint32(b) << 0); #endif } /** * Return this colour as RGBA value (or ARGB for little endian). * @todo Hopefully this handles the little endian case for PowerPC * processors, but I don't know if there is a generic define for * little endian in general. */ uint32 fcolour::get_rgb32(const fcolour& col) { #if __POWERPC__ return (uint32(col.r*255) << 24) | (uint32(col.g*255) << 16) | (uint32(col.b*255) << 8); #else return (uint32(col.r*255) << 16) | (uint32(col.g*255) << 8) | (uint32(col.b*255) << 0); #endif } /** * Convert fcolour to rgb components */ void fcolour::get_rgb8(uint8* red, uint8* green, uint8* blue) { *red = uint8(255*r); *green = uint8(255*g); *blue = uint8(255*b); }