Simple Question BYTE->float C++

Started by
10 comments, last by mynameisnafe 10 years, 1 month ago

I have


unsigned char RGBA =[] { 255, 255, 255, 255 };

struct vector4 { float r, float g, float b, float a; } colour;

That's probably not valid C++, still

How do I set colour?

.

Advertisement

unsigned char RGBA[] = { 255, 255, 255, 255 };
struct vector4 { float r, float g, float b, float a; } colour;

float* ptr = (float*)colour;
for ( unsigned char i : RGBA )
	*ptr++ = i / 255.f;
* Untested
* Subject to compiler scrutiny; check generated assembly

Beautiful, thank you. I should know this..!

Actually come to think of it - what kind of cast should that be for a C++? Just a std::static_cast ?

On a more generic level, floating point color values range from 0.0 to 1.0, so all thats required is a simple scaling of the ratios. To squash anything to be between 0 and 1, just divide by the max value of that other thing. (There is slightly more work involved if the ranges don't both start at 0.0)

More idiomatic C++ solution:

struct ColorRGBA
{
    ColorRGBA(unsigned char rgba[4])
    {
        r = static_cast<float>(rgba[0]) / 255.0f;
        g = static_cast<float>(rgba[1]) / 255.0f;
        b = static_cast<float>(rgba[2]) / 255.0f;
        a = static_cast<float>(rgba[3]) / 255.0f;
    }

    float r, g, b, a;
};



unsigned char RGBA[] = { 255, 255, 255, 255 };
ColorRGBA c = ColorRGBA(RGBA);

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

I don't believe the static cast is needed, unless your compiler has a nonstandard warning message.

Dividing the types char / float is going to follow a standards-required implicit conversion to make them the same types, float/float. Since the char value can be exactly represented by a float, no compiler message is required.

I don't believe the static cast is needed, unless your compiler has a nonstandard warning message.

Dividing the types char / float is going to follow a standards-required implicit conversion to make them the same types, float/float. Since the char value can be exactly represented by a float, no compiler message is required.

I'd argue that in the general case it would be better to use a solution with explicit static_casts as presented by ApochPiQ, because you can immediately see the four casts (and can also search for them), also making it easier to spot potentially expensive operations (load-hit-stores on PowerPC architectures).

But that's probably a matter of taste.

Okay a lot of replies and a lot to bear in mind - I'm young, I've cut my chops coding C-like languages a bit and I do need to know more about compilers I find. I just got my first job out of uni a few months ago and it sometimes feels like I just know nothing at all aha!

I like what you say about having explicit static_cast s -- I read Effective C++ recently. ApochPiQ - that looks perfect for my needs.

I like the ptr++ for-loop I must say - I get the impression it'd be fast, and it's pretty to look at, but it wouldn't let me cast with static_cast or (float*) -c-style cast, to cast the struct of floats to a (float*) - is this something to do with the virtual function table of the struct Colour ( since it has constructor, copy constructor, and a method) ? This is where a dynamic_cast comes in? And I don't really need it to be doing a dynamic cast, right?

I've deleted the code that I wrote based on the ptr++ approach so I'm unable to show you what I tried but it was pretty much verbatim - I didn't get to the for loop! (Oh yeah I'm using VS2010)



Essentially, the first post was an attempt to simplify:


class GLBitmap
{
	private:
		Pixel *pixels;	// BYTE rgba[4]
		int width;
		int height;
...
        public:
		Pixel* FetchPixel( int x, int y )
		{
			return ( pixels ? &pixels[ (x * height) + y] : nullptr );
	        }

Usage:


const Pixel* pixel = bmp.FetchPixel(x, z); // GLBitmap bmp;

float r = b2f(pixel->R); // Did this macro work?

// Elsewhere:
inline float b2f(BYTE b) { return float(b / 255.0f); }

Turns out this inline float function 'just works' ?!

So is this an implicit static cast on the compilers request because it sees me not using static_cast<float>(b) ?

Edit - as you say - it 'just works' because a BYTE or unsigned fits a float, and that's kind of the point of bitmaps?

You do not need the explicit cast, and the explicit cast offers nothing other than extra typing. It is a standard behaviour of a C++ compiler to promote chars to floats in these calculations. The casts actually make it less readable imho, as they imply there's something non-standard going on and forces someone to parse it all with their eyes.

A straight forward rgba[ 0 ] / 255.0f etc. is plenty enough.imho

n!

I don't really care if the cast is "necessary." I still like having it there because implicit type conversions are evil and stupid, and having the cast relieves me from having to remember the inane C++ implicit conversion rules every time I visit the function.

Just a personal preference thing.


*shrug*

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

This topic is closed to new replies.

Advertisement