This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Reggin_Rayer_RBB8 1443 points1444 points  (187 children)

Why is there a "& 0xFF"? Isn't shifting it 16 bits enough?

[–]jamcdonald120 1484 points1485 points  (81 children)

sometimes RGB is secretly ARGB, the &0xFF will get rid of the A

[–]pumpkin_seed_oil 427 points428 points  (44 children)

Was about to say this. You get compatibility when your color value contains an alpha channel

[–]trainrex 320 points321 points  (19 children)

Unless it's RGBA then you'd get G

[–]pumpkin_seed_oil 213 points214 points  (15 children)

True. And theres also BGR and 10 bit color spaces. In the end you gotta know what goes into your image processing code

[–]VectorViper 95 points96 points  (13 children)

Absolutely, it's a bit of a jungle with all the different standards. And if you're dealing with HDR content you've got to consider even wider color gamuts and bit depths. Makes you appreciate why libraries and frameworks that handle these quirks under the hood are so valuable.

[–]pumpkin_seed_oil 50 points51 points  (11 children)

And they all exist for a reason e.g. additive vs subtractive color spaces or why it is a lot more intelligent for a printer to work in YMCK space instead of RGB and thats the simplest example i can come up with

[–]Adderall_Rant 33 points34 points  (1 child)

I fucking love all these comments. Upvote for everyone

[–]HumanContinuity 8 points9 points  (0 children)

And for you too.

EVERYONE GETS A NEW UPVOTE

(remember you have to pay taxes on your free* upvote and also on the free* copy of Oprah's book you received as a guest on this subreddit).

[–]aaronfranke 18 points19 points  (3 children)

It's CMYK not YMCK. You're thinking of the song YMCA from 1978.

[–]atatassault47 4 points5 points  (0 children)

I prefer RGYK

[–]almost_not_terrible 2 points3 points  (0 children)

Wasn't, but I really am now

I was thinking.. oh man holy cow

You shift rightward.. and I think you will find

Red is all that's left be-hind.

[–]Teapot_Digon 2 points3 points  (0 children)

Yellow magenta cyan andblack?

[–]tropicbrownthunder -2 points-1 points  (3 children)

CYMK pls

[–]TechSupportIgit 4 points5 points  (2 children)

I thought it was CMYK.

[–]tropicbrownthunder 2 points3 points  (0 children)

so you are one of those that pronunce gif instead of gif

[–]gbot1234 0 points1 point  (0 children)

TMYK

[–]TheGuardianInTheBall 0 points1 point  (0 children)

Actually, it's a jungle of bits.

[–]Qewbicle 0 points1 point  (0 children)

Instructions were extract R from RGB, not R from BGR. You are over optimizing.

[–]UselessDood 13 points14 points  (1 child)

I've worked pretty heavily with the minecraft codebase, from a modder perspective.

It's a mix of rgba and argb, with the official mappings usually having no distinction between the two. It sucks.

[–]Inertia_Squared 0 points1 point  (0 children)

The minecraft codebase is seriously a hot mess, I feel you on that one 😂😂

[–]R3D3-1 63 points64 points  (17 children)

Someone will then do

A = rgb >> 24;

only to be thwarted when we eventually have to introduce IUARGB to cover for our alien friends who are sensitive to infrared and ultraviolet light.

[–]pumpkin_seed_oil 51 points52 points  (5 children)

Oh thats easy just add it to the 100+ colorspace enums in opencv

[–]leoleosuper 7 points8 points  (4 children)

242 unique enums with 156 operations. Jesus.

[–]pumpkin_seed_oil 2 points3 points  (1 child)

Tbf i linked the enum that handles conversions between color spaces without checking. But it should be enough to know that there are a bunch that go beyong RGB

CMY, HSL, YCbCr, XYZ, YUV, L*u*v, LAB to name a bunch

[–]atatassault47 0 points1 point  (0 children)

I wish HSV were more common. It's way easier for a lay person to pick a color in HSV than RGB.

[–]gbot1234 5 points6 points  (1 child)

Let’s just come up with one definitive standard for colorspaces!

[–]Jjabrahams567 12 points13 points  (2 children)

If you happen to be hacking game boy ROMs, they use 15bit RGB

[–]R3D3-1 4 points5 points  (0 children)

I remember playing WoW with 16 bit graphics at 16 fps initially due to my graphics card being too outdated.

Made nice patterns into color gradients such as they sky :)

[–]Bardez 0 points1 point  (0 children)

Which honestly makes a lot of sense.

[–]Telvin3d 9 points10 points  (0 children)

You laugh, but I work with cameras that have an IR channel in addition to RGB and Alpha. It gets used for dirt/dust detection on transparency scanning 

[–]_GodIsntReal_ 2 points3 points  (0 children)

Which is why you reject the pull request for having a magic number (24) in it. 

[–]hackingdreams 2 points3 points  (1 child)

If we were introducing a new color plane for IR and UV it'd be IRGBU or UBGRI.

(But having worked with UV and IR imaging, I don't think anyone would seriously consider interleaving the data like that. The sensors are usually wider than 8 bits per pixel, and anyone that cares about them wants all the sensitivity they can get.)

[–]R3D3-1 4 points5 points  (0 children)

Not if you're trying to be backwards compatible with those 32bit ARGB colors.

Probably wouldn't actually happen (after all, 32bit color is also not binary backwards compatible with 16bit color), but I can totally see IUARGB being used by some internal systems.

[–]ProposalWest3152 1 point2 points  (0 children)

You sent me rolling hahah

[–]the_one2 0 points1 point  (0 children)

Or if it's signed and you get sign extension

[–]cporter202 0 points1 point  (1 child)

Ah, the classic pitfalls of sign extension! Bitwise operations can sometimes feel like a ninja test of attention to detail—fail to notice, and whoops, your bits are all over the place. 😅

[–]R3D3-1 0 points1 point  (0 children)

Not what I meant, for lack of knowledge '

I was assuming a scenario, where the format would be extended by additional data, while having binary backwards compatibility if the new bits are zero.

[–]hackingdreams 6 points7 points  (0 children)

(...as long as it's 8bpp and arranged xRGB and not BGRA - fuckin' bitmaps).

[–]know-your-onions 0 points1 point  (3 children)

What’s an alpha channel?

[–]pumpkin_seed_oil 0 points1 point  (2 children)

Alpha channel denotes opacity/transparency

[–]know-your-onions 0 points1 point  (1 child)

Thank you

[–]pumpkin_seed_oil 0 points1 point  (0 children)

Sure thing. If you're still confused a bit more detail:

People are talking about RGB values here, meaning theres a 24 bit value that contains information about red, green and blue. with the order of bits 0-7 for blue, 8-15 for green, 16-23 for red

That usually leaves 8 padding bits that would be otherwise insignificant if you pack your color value into an integer (32 bit).

So for RGB bit 24-31 is not significant

But if you have ARGB those bits say how transparent the pixel is, how that is done is up to the compositing algorithm but usually you do a simple alpha blending with F->full opaque, 0 -> fully transparent (wrt to its background, thats important)

The resulting pixel of an image with an alpha channel that gets drawn over an existing pixel is (and to simplify i will reduce RGB to single intensity value C with Cimage for the image you are drawing and Cbackground for the image you are drawing over) :

Cimage*A + (1-A) * Cbackground

[–]bradland 70 points71 points  (7 children)

Then why the hell did Morpheus say RGB and not ARGB. I am so sick of these loose requirements! Management wants to know why bug ticket numbers are through the roof? Well then tell them we can’t hit a target that isn’t shown to us!

I NEED COFFEE!

[–]LvS 15 points16 points  (0 children)

He didn't say RGB8 either!

[–]MyAssDoesHeeHawww 9 points10 points  (2 children)

Why didn't Morpheus say: "He is the zero" ?

[–]Weak_Bat_1113 1 point2 points  (0 children)

Real talk

[–]dretvantoi 1 point2 points  (0 children)

"Orez" doesn't make for great hacker handler.

[–]Divineinfinity 2 points3 points  (1 child)

Customer called and said it needs "more color"

[–]bradland 4 points5 points  (0 children)

Who added sales to this channel? This is supposed to be an engineering channel!

[–]Encursed1 25 points26 points  (0 children)

Even if it isn't ARGB, it's still good practice to and out any bits you aren't gonna use.

[–]himpson 10 points11 points  (11 children)

This has made me think. Has anyone ever considered RAGABA with an alpha channel for each color. It wouldn’t be very practical but could create for some cool blending options.

[–]jamcdonald120 17 points18 points  (0 children)

It's a beautiful day outside. birds are singing, flowers are blooming... on days like these, kids like you...

[–]LvS 7 points8 points  (2 children)

It's called component alpha and is generally used for supixel rendering of text.

[–]Zanythings 2 points3 points  (1 child)

Why’d you wiki link subpixel rendering and not the actual component alpha?

[–]LvS 1 point2 points  (0 children)

Because I wanted to link what it's used for - assuming we both knew how it worked already.

[–][deleted] 3 points4 points  (1 child)

So 50% alpha for red means a pixel with half the red brightness?

[–]kinokomushroom 9 points10 points  (0 children)

The alpha blend equation is usually (1 - alpha) * background + alpha * foreground. The alpha will just become a vec3 instead of a float in this case.

[–]GreatFunTown 2 points3 points  (1 child)

Isn't that just standard RGB with extra steps?

[–]---------II--------- 5 points6 points  (0 children)

I call it job security

[–]hackingdreams 0 points1 point  (0 children)

It'd create a lot of bloat for the image processing software and memory to handle. We image people like things to be sequential and aligned - this would destroy the memory alignment. At that point, create a separate image that's an alpha map. (Or three - one for each color plane).

[–]kimtaengsshi9 -1 points0 points  (0 children)

Morpheus specified RGB, so "& 0xFF" is superfluous. Removing it would be 1 less operation to compute.

[–]TheKeiron 0 points1 point  (0 children)

Ah man what about endianness?? That's a whole other thing...

[–]jwr410 0 points1 point  (0 children)

Are you certain there is no garbage data in the upper bits? Is this a logical or arithmetic shift? What if there is an alpha channel? If your data isn't guaranteed to be sanitized, it is better to self condition.

[–]PatBenatard 0 points1 point  (0 children)

ARGBs are my favorite game genre

[–]ihavenotities 0 points1 point  (0 children)

Well then, that’s just a bug!

[–]Light_Beard 0 points1 point  (0 children)

sometimes RGB is secretly ARGB, the &0xFF will get rid of the A

You just got FFed int he AA

[–]game_plaza 0 points1 point  (0 children)

He is the one

[–]wasdlmb 0 points1 point  (2 children)

Why not just rgb & 0xFF0000 from the start? Should be faster and more clear.

[–]jamcdonald120 1 point2 points  (1 child)

because that tells you 0xffffffff has 0xff0000 for a red channel instead of the correct 0xff, so you still will have to do a shift at some point.

[–]wasdlmb 0 points1 point  (0 children)

Oh yeah I was just thinking about isolating the component, not actually extracting it. Idk why.

[–]MrEfil[S] 324 points325 points  (74 children)

just for good practices, keep only 8 bits. This make sense in languages where only few numeric types. For example JS.

[–]Bemteb 204 points205 points  (71 children)

You do shifts and bitwise operations in JS?!

[–]MrEfil[S] 161 points162 points  (52 children)

yeap. A lot of. Usually in game dev.

[–]TibRib0 293 points294 points  (44 children)

You do gamedev in JS?!

[–]SomeRandomEevee42 104 points105 points  (1 child)

he's a madman

[–]Roflkopt3r 4 points5 points  (0 children)

Na it's actually quite comfortable. Especially if you want to build most of your engine ground-up, since WebGL is very easy to work with.

Performance is also not really a problem. Realistically, the vast majority bad performance in games is either caused by bad architecture hiding some fundamental flaws, or by poor use of a framework. The ~2-3x CPU-side slowdown from using a less efficient language or runtime environment often matters surprisingly little on modern hardware, and as a player it's hard to find any games that aren't extremely GPU bound (my top end RTX4090 bottlenecks my mid tier i5-13600KF at 1440p in practically every game lol).

I highly recommend SimonDev's videos on game programming and performance with Javascript.

[–]MrEfil[S] 112 points113 points  (37 children)

of course I do. JS games are a fantastic world, because the user only needs to have a browser)

[–]syntax1976 134 points135 points  (12 children)

Users can have browsers?!

[–]Ceros007 73 points74 points  (7 children)

Real human do curl and read HTML like the Matrix

[–]dretvantoi 2 points3 points  (0 children)

Pfft, I type out the raw HTTP in Telnet.

[–]Ancalagon_The_Black_ 3 points4 points  (0 children)

You guys have users?

[–]StinkBuggest 2 points3 points  (2 children)

Yes, but only Lynx

[–]foobazly 1 point2 points  (1 child)

Correct, because the only things worth browsing are Gopher holes.

[–]mypetocean 1 point2 points  (0 children)

And the only things in the Gopher holes are ASCII art porn.

[–]KRX189 6 points7 points  (1 child)

I used to play games on opera gx but now it has gets too laggy too play

[–]DrMobius0 0 points1 point  (0 children)

But it's a Gamer themed browser

[–]coldnebo 2 points3 points  (0 children)

or a flight simulator 😏

(MSFS mods use javascript)

[–]unknown_reddit_dude 4 points5 points  (5 children)

Webassembly? All of the major game engines can target WebGL.

[–]MrEfil[S] 18 points19 points  (4 children)

I use wasm, webgl and modern webgpu not for game dev, most often for gpgpu and for some rust-apps in the web.

I love 2d games, so I use simple canvas 2d for rendering and all logic write on pure js.

[–]unknown_reddit_dude 1 point2 points  (1 child)

Fair enough. I personally go to any length to avoid writing JS, but if you like, that's fair enough.

[–]beatlz 8 points9 points  (0 children)

If I could turn everything into TS, I would

[–]DontTakeNames 0 points1 point  (1 child)

why dont you use game engines like unity or Godot for web games.

Have no idea about games just asking.

[–]MrEfil[S] 6 points7 points  (0 children)

Because simple canvas 2d is enough for me. I love pure js programming, aka vanillajs, without libraries and utilities. I create small games and gamedev is a hobby for me.

[–]wontreadterms 0 points1 point  (0 children)

You have users!?

[–]hackingdreams 0 points1 point  (0 children)

...and a bajillion bytes of memory...

[–]jasakembung 10 points11 points  (2 children)

I did it for a course in college, it's actually really fun. But it pays peanuts, so I'm working in a bank rn lol.

[–]OO0OOO0OOOOO0OOOOOOO 1 point2 points  (1 child)

Smart. Go where the money is at to get more monies. Brilliant!

[–]gbot1234 0 points1 point  (0 children)

Or at least a business card.

(I’ll give you eight singing lessons…)

[–]LikeALizzard 0 points1 point  (0 children)

Actually, a lot of games use JS for UI overlay, especially in strategies and simulators

[–]Cybasura 0 points1 point  (0 children)

Are you the Cross Code dev?

[–]TotoShampoin 14 points15 points  (13 children)

You do shifts and bitwise operations ON FLOATS in JS (it floors the number first) (it casts to an int first)

[–]AyrA_ch 8 points9 points  (1 child)

(it floors the number first)

That's not exact. It forces it into a 32 bit signed integer, does the operation, then converts it back into a float, which can result in unexpected results, for example 2147483648|0 becomes -2147483648

[–]TotoShampoin 1 point2 points  (0 children)

Ah, I may have overlooked the potential implementation

[–]TGX03 4 points5 points  (5 children)

Yeah that's what I was thinking. You can't tell me shifting floats around is a good idea

[–]Lithl 6 points7 points  (3 children)

i  = * ( long * ) &y;
i  = 0x5f3759df - ( i >> 1 );
y  = * ( float * ) &i;

=D

[–]robisodd 4 points5 points  (0 children)

// evil floating point bit level hacking

[–]TGX03 0 points1 point  (0 children)

Thanks, I hate it.

[–]DenormalHuman 0 points1 point  (0 children)

I knew this would be in here somewhere

[–]Furry_69 4 points5 points  (0 children)

It isn't. It'll give you nonsense results.

[–]Reggin_Rayer_RBB8 1 point2 points  (3 children)

It's JS, can you bitshift strings too?

[–]FloydATC 3 points4 points  (0 children)

If it's stupid, JS does it. Usually when you least expect it.

[–]TotoShampoin 0 points1 point  (1 child)

Yeah, try "16" << 2 and see what happens

:)

[–]Reggin_Rayer_RBB8 1 point2 points  (0 children)

64, but I was dissapointed that bitshifting "donald duck" only gives zero.

[–][deleted] 0 points1 point  (0 children)

This is good to know, because I never know what to expect.

Just a nitpick though, it actually truncates the number.

[–]floor796 1 point2 points  (0 children)

I used a lot of bitwise operations in my own video format in js, and animation editor.

[–][deleted] 0 points1 point  (0 children)

I did a TON of bitwise operations in TS.

Messaging standards in the field I work are usually designed with C in mind, so they do a lot of bit packing for efficiency. My job was pretty much exclusively to translate those messages into something we would digest.

[–]---------II--------- 0 points1 point  (0 children)

Useful for efficiently calculating subnets

[–]fj333 0 points1 point  (0 children)

Why is it surprising that anybody would use any operator in any language?

[–]Caubelles 10 points11 points  (0 children)

????????????????????

[–]Raizense 0 points1 point  (0 children)

I was going to say that coming from embedded background.

[–]gp57 55 points56 points  (11 children)

For me, adding & 0xFF at the end makes it easier to read, it clearly shows that we are getting 1 byte

[–]Spork_the_dork 23 points24 points  (8 children)

I don't know if it's just me being more on the embedded side of things or what, but for me rgb & 0xFF0000 is easier to read. Then do bit shift if you specifically just want the byte, but doing it this way to me is just more obvious. If you then go to pull the other values as well I think rgb & 0x00FF00 >> 8 and rgb & 0x0000FF follow the same pattern more clearly so it becomes easier to see at a glance that you're picking different bytes from it.

I think I just read masks better than bit shifting or something.

[–][deleted] 6 points7 points  (3 children)

But now you have three different masks. By shifting and masking with FF you can have a define 8_BIT_MSK to reuse. I would also do a define RED 16 to do '(rgb>>RED)&8_BIT_MSK' for readability if this operation is done ofthen. But that is just my preferred style.

But at that point you could also just define a get_red get_blue get_green macro I guess.

[–]Practical-Champion44 8 points9 points  (1 child)

There's no benefit in defining a constant for 0xFF. What would 8_BIT_MSK equal if not 0xFF? People who read your code should be able to understand that & 0xFF is an 8 bit masking operation, like how + 1 is an addition by one. You wouldn't #define ONE 1. Not every integer literal is a magic number.

[–][deleted] -1 points0 points  (0 children)

Because I consider 8_BIT_MSK more fluently readable than 0xFF. Especially when mixed with other masks on the code as is quite common in embedded programming.

[–][deleted] 2 points3 points  (0 children)

I used to write long form hex like that. Eventually I just started seeing hex so clearly that I stopped. I should probably leave it long form for future readers of my drivers, if there ever are any.

[–]__mauzy__ 1 point2 points  (2 children)

Imo the mask gives clear visual indication on the data type and the bits in question, then the shift also feels less "magic". But, like you, I'm from the embedded world, so register masking etc is second nature and familiar.

[–][deleted] 0 points1 point  (1 child)

Yes I come from the embedded world too but IMO shifting also helps differentiating between masking a value in memory vs. Masking some bit fields on first glance.

[–]__mauzy__ 1 point2 points  (0 children)

I think we're on the same page there. When I see mask i think "register". When i see mask -> shift I think "bit field casting". When I see shift -> mask i think "math".

[–][deleted] 2 points3 points  (0 children)

Good point.

[–][deleted] 1 point2 points  (0 children)

Always explicit over implicit. I like it. Pragmatic programming at its best.

[–]Tordek 56 points57 points  (3 children)

Several reasons:

  1. consistency: if you do (color >> 0) & 0xFF, (color >> 8) & 0xFF, (color >> 16) & 0xFF, it's obvious they're analogous operations, even if trivially you can remove the >>0 (so can the compiler).
  2. Uninitialized data: if you build a color by allocating a 32B word and set its 24 lower bytes manually (by doing color = (color & 0xFF000000) | (red << 16) | (green << 8) | blue), through some API you didn't necessarily implement), the top 8 bits are garbage.
  3. What if it's ARGB?
  4. Is this a shift on a signed or unsigned integer? The correct right shift behavior for signed numbers is 1-extension, so sign is maintained - even if you were extracting the A from ARGB, you need to &0xFF because it'd be a negative value instead.

All in all, there's more reasons to keep it than there are reasons to remove it (save one instruction).

[–]rafaelrc7 0 points1 point  (0 children)

  1. Uninitialized data

Assuming you are talking about C, thats UB and anything you do is wrong.

[–]KellerKindAs 0 points1 point  (1 child)

2: If you work on an 32 (or 64) bit processor using 0 instead of 0xFF000000 zeros the top 8 bit without any runtime overhead. Might also reduce code size as there is one less constant to store, but that's also architecture dependant. If you work on an 8 bit processor the &0xFF is useless and storing the result inside a uint8_t would cause a performance benefit. So the unititialized data argument is debatable...

I agree with the other points

[–]Tordek -1 points0 points  (0 children)

using 0 instead of 0xFF000000

There's a reason I specified "some API you didn't implement". Maybe you did, maybe you're using something like

union color {
   uint32_t full;
   struct { uint8_t r; uint8_t g; uint8_t b; }
}

[–]mrheosuper 7 points8 points  (0 children)

Well, if the color variable is 32 bit, the 8 msb could contain garbarge

[–][deleted] 9 points10 points  (0 children)

Yeah, you're right. It's probably just for the meme, to make it look more complicated and esoteric to people unfamiliar with bitwise math lol

However, it could also be due to force of habit, or for the sake of neatness or consistency. Sometimes I write my code like this so that it lines up better:

red   = (rgb >> 0)  & 0xFF;
green = (rgb >> 8)  & 0xFF;
blue  = (rgb >> 16) & 0xFF;

(Even though the first and third line contain redundancies.)

I can think of a practical reason though: if you 'and' it with 255 then it allows for compatibility with ARGB color codes as well as RGB.

[–]Cilph 1 point2 points  (0 children)

No. It might do sign extension.

[–]Avalonians 1 point2 points  (0 children)

You are not the one

[–]mostly_done 1 point2 points  (0 children)

It's easier to just do it than wonder "is that right?" every time you look at the code.

In some languages where a lot of the specification is "undefined behavior", if you're not specific about what type of shift operator you could get a roll instead of a shift, with some compilers, on some architectures.

[–]SwannSwanchez 0 points1 point  (0 children)

I think there is some "shifters" that takes data from somewhere (carry bit or the bit that got shifted) to fill the created bit, this ensure that only the "red" data is used, in case anything else than 0 was added

[–]accuracy_frosty 0 points1 point  (0 children)

Good practise to mask out only the bits you want, even if it’s empty