2

With 8 bit color depth there are 256 colors. With 24 bit color depth there are 16,777,216 colors. Is there a direct mapping between every color in the 8 bit space to a color in the 24 bit space? I would think the answer to this question is yes, but the comments to this answer suggest the mapping is only an approximation.

What I would like to do is create a palette of 8 bit colors in the 24 bit color space by specifying a 24 bit RGB value. I figured I could do this using this (obviously broken) logic:

3 bits for red == 8 unique values of red, 0-7

3 bits for green == 8 unique values of green, 0-7

2 bits for blue == 4 unique values of blue, 0-3

255/8 = 32 for red and green increment value

255/4 = 64 for blue increment value

{
    "Red": [0,31,63,95,127,159,191,223,255],
    "Green": [0,31,63,95,127,159,191,223,255],
    "Blue": [0,63,127,191, 255]
}

So with 9 values of red, 9 values of green, and 5 values of blue I get 405 colors which is wrong. I know I need 8 values of red and green and 4 values of blue so I just adjusted things a bit:

255/87 = 36.57142857142857 for red and green increment value

255/43 = 85 for blue increment value

So this works for blue, but now my red and green increment value is not a whole number.

Once I got the mapping figured out I was going to loop through it like this:

for(r in rgbData.get("Red")) {
    for(g in rgbData.get("Green")) {
        for(b in rgbData.get("Blue")) {
            colors.add("rgb ${r} ${g} ${b}")
        }
    }
}

This may be a totally incorrect approach to do what I want, just wanted to show I have tried something :)

UPDATE:

I tried the approach @Marc B suggested but it doesn't seem right. For instance, there is no white in the map I generated (which is 255, 255, 255 using 24 bit RGB). Using his approach this makes sense to me because the highest RGB value is 224, 224, 192 as can be seen:

full red == 111

111 >> 5 == 11100000

full green == 111

111 >> 5 == 11100000

full blue == 11

11 >> 6 == 11000000

11100000 11100000 11000000 == 224, 224, 192

224, 224, 192 != white

Here is the map generated using his approach:

{
    "Red": [0,32,64,96,128,160,196,224],
    "Green": [0,32,64,96,128,160,196,224],
    "Blue": [0,64,128,192]
}

And the palette it generates:

enter image description here

UPDATE 2:

After doing some more research I have realized that when "X colors" (X being some number like 256, 16,777,216, etc.) are referred to that those colors can be just about anything. There is not a predefined set of 256 colors that are "the" 256 colors, though there are (as several have already mentioned) predefined sets of 256 colors that are "the" 256 colors for a specific implementation. I was also able to find a GIMP .gpl palette file on my organizations wiki that specified the 256 colors I am concerned with, so I can just copy the values out of there.

Community
  • 1
  • 1
ubiquibacon
  • 10,451
  • 28
  • 109
  • 179
  • 2
    You just bitshift the 8bit components, e.g. red `101` becomes `10100000` in the 24bit space (decimal 5 -> decimal 160). – Marc B Jul 18 '13 at 16:17
  • @MarcB So blue will also get will also get 8 bits? – ubiquibacon Jul 18 '13 at 16:21
  • 2
    yes. in 24bit rgb, each color component gets 8 bits. – Marc B Jul 18 '13 at 16:22
  • @MarcB This doesn't seem quite right to me. I updated my question. – ubiquibacon Jul 18 '13 at 16:49
  • 1
    I'm confused by your statement, "there is no white which is 255, 255, 255 using 24 bit RGB" 255,255,255 = 0xffffff = 1111 1111 1111 1111 1111 1111 . In most hardware implementations this means full bright red, full bright green and full bright blue, which assuming they got the balance (I forget the proper name for "balance" in this context) right is white. – tallen Jul 18 '13 at 18:24
  • @tallen White in the 24 bit color space has an RGB value of `255, 255, 255` which means all bits set as you described. I would agree with you that full red, green, and blue == white. What I am saying is that the method of mapping that @Marc B has suggested by shifting bits will never give me a value of `11111111 11111111 11111111`, the max value I will get using his method is `11100000 11100000 11000000`. – ubiquibacon Jul 18 '13 at 18:49

3 Answers3

2

The practical answer is probably yes. Having said that, it's really a hardware dependant thing. @Marc B is close to correct (probably close enough for most people) but the real answer is it depends, it depends on the hardware, and it wont be exact from (hardware)implementation to implementation, but it will likely be exact enough for most people.

tallen
  • 677
  • 6
  • 17
  • Using the approach @Marc B suggested yields an RGB value of `224, 224, 192` as the highest/brightest value. I wouldn't even consider that color a shade of white, it is more like beige. I know pure white exists in the 8 bit color space and in the 24 bit color space. With that said I know the mapping suggested by @Marc B cannot be correct. – ubiquibacon Jul 18 '13 at 17:57
  • okay so for red, you'd and the 8 bit colour with 0xe0 and then bit shift 8 times, for green you'd and with 0x1c and then bit shift 11 times and for blue you'd and with 0x03 and then bit shift 14 times. Did I get that right? :-) – tallen Jul 18 '13 at 18:35
1

The way to convert is to multiply each channel by the highest level you want output and divide by the highest level of input.

{
    "Red": [0,36,72,109,145,182,218,255],
    "Green": [0,36,72,109,145,182,218,255],
    "Blue": [0,85,170,255]
}

With this method you don't need to devote an even number of bits to each channel, you can use an arbitrary number of levels for each. You can get a more even distribution, but you don't get to use all 256 colors. One common arrangement is 6/7/6 for 252 colors:

{
    "Red": [0,51,102,153,204,255],
    "Green": [0,42,85,127,170,212,255],
    "Blue": [0,51,102,153,204,255]
}
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • This will work too. I assumed, though @ubiquibacon said nothing to the affect, that he/she wanted to stay off the math co-processor. Naturally you'll wanna do all this as a vector operation (if the processor in question supports such things) :-) – tallen Jul 18 '13 at 19:12
1

I know this answer is probably a bit late, but it might be useful for others. If someone knows what the algorithm outlined below is called, please let me know in a comment.

I'm currently working with different display hardware and I've run into the problem of converting a channel with m bits to one with n bits, where m < n; for example: convert a 5 bit channel to an 8 bits channel. White (b11111) should map to white (b11111111) and black should map to black.

To map, for example, 5-bits b10111 to 8 bits, I pad the missing bits with the MSBs from the original data:

b10111
 ^^^--- we need these three MSB again later, as 8-5 = 3 missing bits

shift left 3 bits:

b10111000

and pad with MSBs:

b10111101
      ^^^--- the MSBs

That maps quite well (you might want to apply rounding for values that are not all 1s) and round-trips (you can convert less than 8 bits to 8 bits, convert back and the result is the same as the original value).

If the narrower channel is less than 4 bits wide (like 3), the whole value will repeat completely:

b101 -> b10110110
Christoph
  • 1,040
  • 3
  • 14
  • 29
  • This seems to work reasonably well. For 5 bit to 8 bit I believe it can simply be written like- 5bitTo8bitColor(C) : (C>>2)|(C<<3) – imjosh Sep 04 '14 at 19:12