Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DarkBASIC Discussion / Color rotation "Hue"

Author
Message
Ashingda 27
17
Years of Service
User Offline
Joined: 15th Feb 2008
Location:
Posted: 4th Dec 2008 04:03 Edited at: 4th Dec 2008 04:03
I've been trying for hours and can't find a good way to change one color to another. I have found some topics about this altho very few.

What I want to do is change the clothing color of my ninja charator from green to red, the other methods I've tried works to an extent but it's not satisfying.

How would I change/rotate the colors so that dark and light colors will stay in that shade. Is there a way to keep white and black untouched?

If you're wondering what's the point in all this, it's because here's my ninja and he's color coded.


I want to be able to customize each area with a different color. I'm using memblock and also testing with array. But the problem is I dont know how to rotate/change the color very well.
Latch
19
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 4th Dec 2008 07:11 Edited at: 4th Dec 2008 07:13
Hello,

So things are nice and easy, I'm gonna create an example using 32 bit color depth.

There are a couple of ways to do this. One way is to binary AND (&) the current pixel color with the color components minus the color you want to remove. Let's say we want to remove all of the green from your ninja we would check for green pixels then & them with all colors except green. Then we binary OR ( | ) the pixel with the color we want to replace it with.

This example replaces green with blue. One thing that was tricky was PNG files contain an alpha channel. This set transparency except for in DBC. When the alpha channel is set in a memblock that has been created from an image, it gives back the wrong color so in the example, you'll see that I am zeroing out the alpha channel:



Enjoy your day.
Ashingda 27
17
Years of Service
User Offline
Joined: 15th Feb 2008
Location:
Posted: 4th Dec 2008 17:06 Edited at: 4th Dec 2008 17:09
Thanks and very nice codes Latch, your usage of ( & ), ( | ) are new and confusing for me LOL. The codes worked for the lower colors but not for the higher color.

See as the lighter color of green doesn't change to light blue.

I think the problem is while it's checking for the green color.

Maybe it only checks a certain range of green. Is there a way to figure out what the individual R, G, or B value there are from a color?

My though was while checking a color and the values are RGB(100,255,150), if green was the higest value then the pixel being checked is "Green" so it doesn't skip out the lighter colors.
Latch
19
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 4th Dec 2008 21:15 Edited at: 4th Dec 2008 21:28
& and | are binary operators. That means they affect the smallest part of a number - the BITS. Computer numbers are made up of BYTES. Each BYTE of a number is made up of BITS. Bit values can only be 0s and 1s . A 0 means the bit if off. A 1 means the bit is on. A BYTE is 8 BITS. Each bit represents a value of 2^bit. The bits number left to right starting at 7 and end at zero:

7 6 5 4 3 2 1 0

If a bit is 1, then the value of 2^bit is added to the number as a whole:

1 0 0 1 0 1 0 1

=2^7 + 2^4 + 2^2 + 2^0 = 128+16+4+1 = 149

A byte's maximum value is 255 and it's lowest value is 0. A color has 3 bytes Red, Green, and Blue. Each color has 8 BITS. Now, finally about & and |. The & (AND) operator, compares the BITS of two numbers. If the BITS are on in BOTH numbers, then the resulting number has those BITS on:

1 0 0 1 0 1 0 1
&
1 0 0 0 1 0 0 1
=
1 0 0 0 0 0 0 1

The | (OR) operator also compares the BITS of two numbers, but if ANY of the bits in EITHER of the 2 numbers are on, the resulting number's bits are also on:

1 0 0 1 0 1 0 1
|
1 0 0 0 1 0 0 1
=
1 0 0 1 1 1 0 1

I used these operators to filter out Green in the colors. If I & two colors
RGB(255,255,0) & RGB(255,0,255)
the result in this case would be RGB(255,0,0).

If I | the result with Blue only
RGB(255,0,0) | RGB(0,0,255)
I get RGB(255,0,255)

Quote: "Maybe it only checks a certain range of green. Is there a way to figure out what the individual R, G, or B value there are from a color?

My though was while checking a color and the values are RGB(100,255,150), if green was the higest value then the pixel being checked is "Green" so it doesn't skip out the lighter colors."


You are right! I was checking for pixels that had no red or blue in them. I was trying to avoid WHITE being turned to blue, but you're idea is better. If Green is the HIGHEST value, we'll consider that a shade and handle it appropriately.

There are 3 functions that return the individual components:
RGBR(color)
RGBG(color)
RGBB(color)

Since we are using memblocks, I can either use those commands, or check each BYTE individually. I think I'll use the commands:



Enjoy your day.
Ashingda 27
17
Years of Service
User Offline
Joined: 15th Feb 2008
Location:
Posted: 4th Dec 2008 23:32
What the heck I didn't know DBC had RGBR()...etc. I guess wasn't looking hard enough.

@Latch
You got it working really good, I'll keep messing around with it and see what I can learn, Thanks!
Ashingda 27
17
Years of Service
User Offline
Joined: 15th Feb 2008
Location:
Posted: 31st Dec 2008 18:48 Edited at: 31st Dec 2008 19:25
@Latch
When I set the display depth to 16 or use the default display there's an error in the memblock.

Could this only work with 32 bit depth?

Or is there also a work-around for the 16 bit depth?


[edit]


OK I figured it out, 16 bit uses Word and 32 bit uses DWord.
Ashingda 27
17
Years of Service
User Offline
Joined: 15th Feb 2008
Location:
Posted: 3rd Jan 2009 01:35 Edited at: 3rd Jan 2009 01:44
Ok I'm stumped again, when the display mode is set to 16bit depth the memblock made from image is hiding the Red color. I cannot find it!

I learned 32bit depth uses 4 bytes to store the values that's enough for R,G,B,and Alpha. But 16bit depth only has 2 bytes and I can only recall the G and B values.



This is using the same ninja image as befor.
Latch
19
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 3rd Jan 2009 01:36 Edited at: 3rd Jan 2009 01:38
The code would have to be rewritten a little to allow for 16 bit.

check out:

16 bit pixel format

You won't be able to use the standard RGB() commands because that always returns a DWORD. You'll have to extract the individual r g b values from the 2 bytes. You seem to be figuring it out. If you really get stumped I'll show you how.

Enjoy your day.
Ashingda 27
17
Years of Service
User Offline
Joined: 15th Feb 2008
Location:
Posted: 3rd Jan 2009 03:40 Edited at: 3rd Jan 2009 17:38
Ok I'm starting to understand more about how the bit works, I was way confused at first but it's making sense now after re-reading your explanation above.

That link was pretty cool, it had some wild info.

Ok I got it to work, found your method of extrating from the 2 bytes.



I'm still not sure where the values 31, 2016, and 63488 came from but while I was playing with it, those values would constantly show up befor it's reseted to zero. I'm still very new to playing with binary.
Ashingda 27
17
Years of Service
User Offline
Joined: 15th Feb 2008
Location:
Posted: 9th Jan 2009 18:59 Edited at: 9th Jan 2009 18:59
Ok so this extracts color from 2 bytes.



Next question is how to write a color into 2 bytes?

I've started using memblock in collision detection and image manipulation such as floodfill, color swap, etc and found it very useful. But the 16bit depth mode I was completely unaware of til recently.
Latch
19
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 10th Jan 2009 10:03
Quote: "I learned 32bit depth uses 4 bytes to store the values that's enough for R,G,B,and Alpha"

To comment on this, DBC won't treat the 4th byte as an alpha channel when using memblocks for images. It will only use the first 3 bytes. If you use the 4th byte, then DBC will treat the 4 bytes like a float when you convert the memblock to an image. If you decide to bypass the make image from memblock command and write your own header for whatever image type you want to create, you could save the memblock as a proper image type with an alpha channel. But it will not work with make image from memblock.

Anyway, on to 16 bit:

There's another dimension. If you read through the post from the link I supplied, you'll realize that there could be other formats for 16bit color representation based on the graphics card. While the most common is probably 565 (what your code is using) there could be other formats. The 565 or 555 formats are telling you what bits are used for r b g in a 16 bit color.

565 = r r r r r g g g g g g b b b b b
So those mysterious values 31, 2016 and 63488 come from
red mask = 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 = 63488
green mask = 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 = 2016
blue mask = 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 = 31

So when you pull a WORD out of a memblock and you & it against one of the masks, you'll be left with the bits that are set in that particular color.

When you are converting the color to R G and B values that can each be a full byte (0 to 255 in value), you multiply the masked color * 255. If all of the bit colors were set in a particular mask & color combo, then the maximum value, in the case of green say, would be 2016*255 = 514080 . But that's too big to be within a 0 to 255 range. Since we want to be left with a value up to 255, we have to divide by the mask (in this case 2016) so we are left with a percentage of 255. It might be easier to think of it like
255 * ((color & mask)/mask) but you'd have to use floats to get a percentage if you calculate it out in this format.

Remember, you are creating your own RGB() command essentially for 16 bit, so a value returned by the DBC RGB() command will only be a DWORD. Just keep that in the back of your mind.

Quote: "Next question is how to write a color into 2 bytes"

So, with a little algebra, you can juggle things around to get the conversion of R,G,B 24 bit into 16 bit:
r=(r*63488)/255
g=(g*2016)/255
b=(b*31)/255

OR the final values together to get the word:
WORD = R | G | B




Also keep in mind that when you convert a WORD into R G B values, they will be a little different than the original 24 bit R G and B values. This means if you convert a WORD then take those R G B values and convert those back into a WORD, you'll most like end up with a different value. This is due to what's called down sampling. The assumption with these formulas is the taking of a 24 bit input and forcing it into the space of 16 bits. 3 bytes into 2.

If you want an 16bit RGB routine without the down sampling from a vonversion from 24bit you can do a few different things. One of which is to limit the input to the max bit values of the 16 bit format:
r = 0 to 31 g = 0 to 63 and b = 0 to 31. So the 16 bit RGB function could only take max values such as rgb_16(31,63,31) for white. Though, with the conversion from 24 bit or the direct input at 16 bit, you'll end up with the same color. So, take that as you will. Just remember, if you use the RGB values from a conversion and convert them again, the resulting WORD will be different.

I'll leave that up to you - probably added a layer of confusion that I didn't need to.

Enjoy your day.
Ashingda 27
17
Years of Service
User Offline
Joined: 15th Feb 2008
Location:
Posted: 21st Jan 2009 23:21
LOL silly me, everything makes sense now, took me long enough to get it. It was so simple, format 565 meant 5 bits for red, 6 bits for green and 5 bits for blue. Must be the same thing for format 555 as well if I'm not mistaken.

Wrote a function to help me figure the 32 bit colors.


Is there an easier way to do this?

I can somewhat emulate the rgbr(),rgbg(),rgbb() functions but it's not as fast.

Phaelax
DBPro Master
22
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 22nd Jan 2009 01:48
not sure if this is of any use, but it'll allow you to fade from one color to another.




Latch
19
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 22nd Jan 2009 02:03
Quote: "Is there an easier way to do this?"

Since there isn't a binary data type in DBC, I can't think of any other way except looping through a string of 1s and 0s . Your function could be sped up, but that's the only method I can think of for the binary to decimal conversion.

Enjoy your day.
Ashingda 27
17
Years of Service
User Offline
Joined: 15th Feb 2008
Location:
Posted: 22nd Jan 2009 03:07
@Phaelax
Nice function, I do have a use for it
Quadrazar
16
Years of Service
User Offline
Joined: 7th Jan 2009
Location: onboard the Kobayashi Maru
Posted: 22nd Jan 2009 03:14 Edited at: 22nd Jan 2009 03:36
Quote: "I can somewhat emulate the rgbr(),rgbg(),rgbb() functions but it's not as fast."


use bit shift operators '>>' or '<<' , they are faster then * and /.




or


example
32 << 1 = 64; ( 0001 0000 converted 0010 0000 )
32 >> 1 = 16; ( 0001 0000 converted 0000 1000 )
32 >> 2 = 8; ( 0001 0000 converted 0000 0100 )

syntax
[variable] << [number of bits to the left]
[variable] >> [number of bits to the right]


0000 1100 << 2 = 0011 0000
0000 1100 >> 2 = 0000 0011


so (6 >> 2) << 2 = 4
0000 0110 >> 2 = 0000 0001 and then 0000 0001 << 2 = 0000 0100.
so bits you shift out of the variable are lost forever and cannot be recoverd;

Personaly I like to use Hex values when working with colourvalues. It gives a better insight in the bitconfiguration of a value;



I hope this is usefull.
Ashingda 27
17
Years of Service
User Offline
Joined: 15th Feb 2008
Location:
Posted: 22nd Jan 2009 03:41 Edited at: 22nd Jan 2009 03:42
I find this very interesting but I cannot seem to get the << and >> to work, is there a special condition I'm missing or are we supose to be able to just run it?

I normally dont use any semicolons other than linking the print commands, does it have a specific use in your examples?
Quadrazar
16
Years of Service
User Offline
Joined: 7th Jan 2009
Location: onboard the Kobayashi Maru
Posted: 22nd Jan 2009 04:01 Edited at: 22nd Jan 2009 04:23
I don't know if the language supports the bitshift operator.

It's a stupid assumption from me, I'm sorry. I saw the use of | and & so I thought all bitwise operators would be supported. Stupid me.

maybe try the helpfile and search for bitwise operators. If you can't find it i'll erase my entery.
Latch
19
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 22nd Jan 2009 04:52
Quote: "maybe try the helpfile and search for bitwise operators. If you can't find it i'll erase my entery. "


I think maybe DBPro can use bitshift and hex data types, but unfortunately, DBC is a bit more limited. Don't erase your post though, it's still good information if one were to convert the code to C or similar and make a DLL out of it.

Quote: "I normally dont use any semicolons other than linking the print commands"

A semicolon is often a line terminator in many programming languages. In DBC it's only real function is to concatenate stuff that's printed using the print statement.

Enjoy your day.
Quadrazar
16
Years of Service
User Offline
Joined: 7th Jan 2009
Location: onboard the Kobayashi Maru
Posted: 22nd Jan 2009 06:28
I've tried to fix my error by making a bitshift.dll. Only thing, I never made a dll before , so chances are it won't work. If it works, let me know. I can try to expand it to to an RGB16 dll.
Ashingda 27
17
Years of Service
User Offline
Joined: 15th Feb 2008
Location:
Posted: 25th Jan 2009 03:29 Edited at: 25th Jan 2009 18:30
@Quadrazar
I haven't tried your dll yet but I will shortly.



Ok so I finnaly got on topic now. Been working on a function to swap a color to another and alow it to cycle through the color spectrum. It kinda works and I ran into a few problems.

First of all it's a bit unsightly, I'm sure there are better ways to do this but I cannot figure it out.

Secondly the function works when the color values are more variant (255,100,0) but when it's something closer like rgb(255,255,0) it has problems.

Use Left and Right to change colors.

Another note, I am not looking for a color transition as that does not do well when I'm trying to conver a whole gradient of red into blue.



[edit]
Actually I'm not very experienced in using dll.


[edit]
After playing around with the color settings in Photoshop an idea hit me, I notice that there was a constant high and low that does not change, if I can set the color back into the red state I can find the hue value and continue from there. I'm not good at explaining but the code now works with any color combination!

The only problem left is to optimaize it. I had to use a goto because there was a subroutine inside that function.


[edit]

Scratch that last one, it wasn't accurate because it used a percentage of 100, this updated one uses 255 and should work better.




[edit]

Made a few changes, It seems the last one didn't work with all color combination as well. Found that the High and Low values are very important. This update works better but the whole process is still rather slow.

Ashingda 27
17
Years of Service
User Offline
Joined: 15th Feb 2008
Location:
Posted: 25th Jan 2009 19:42 Edited at: 25th Jan 2009 21:13
Finally got this thing to work more like the way I want it. This example will change the hair color of this picture.




Anyone have any idea how to modify the brightness or saturation?

[edit]

Ok I've figured it out somehow and it works. If anyone is able to optimize the codes I'll appreciate it very much.

Login to post a reply

Server time is: 2025-08-08 20:42:18
Your offset time is: 2025-08-08 20:42:18