- UID
- 2290
- 阅读权限
- 40
- 精华
- 魅力
-
- 信用
-
- 注册时间
- 2009-2-8
- 在线时间
- 小时
- 最后登录
- 1970-1-1
|
本文由 痕 原创
出处:http://langrisser.xyz/sfc-palette
网上找到的资料。(http://wiki.superfamicom.org/snes/show/Palettes)
这个跟PS版的应该是一样的。
15-Bit BGR Format
The Super Nintendo / Super Famicom stores it’s palette in 512 bytes in a 15-bit BGR format. Each BGR word is 2 bytes, thus it is 512 bytes for 256 colors (256 x 2). The format for each BGR word looks like this:Bit 15 is unused and should be set to 0. Each color value can range from 0 – 31. So a R, G, B value of 31, 31, 31 represents white. As you can see this is quite different from the usual 24-bit RGB where the colors range from 0 – 255.
Converting a 24-Bit RGB Color to a 15-Bit BGR Color
In order to convert a 24-bit RGB value into the 15-Bit BGR format, the 8-bit color value of the 24-Bit RGB color must be scaled down to 5-bits. Then the 3 color values must be packed into 2 bytes. This can be achieved by the following formula:- R = R / 8 (ie: 17 / 8 = 2)
- G = G / 8 (ie: 16 / 8 = 2)
- B = B / 8 (ie: 14 / 8 = 1)
- =========
- Color = B x 1024 + G x 32 + R
复制代码 The following example show how to convert white (255,255,255) to the 15-bit format:- R = 255 / 8 = 31
- G = 255 / 8 = 31
- B = 255 / 8 = 31
- ================
- Color = 31 x 1024 + 31 x 32 + 31 = 32767
复制代码 So white as a 15-bit BGR color is 32767 orin hex. And to clear up any confusion, YES, this value will be stored in LSB order (otherwise known as ‘bits reversed’). So you will see this asin the hex editor.- c = color;
- int r = (c & 0xF80000) >> 19;
- int g = (c & 0x00F800) >> 6;
- int b = (c & 0x0000F8) << 7;
- return b | g | r;
复制代码 Converting a 15-Bit BGR Color to a 24-Bit ColorTo convert a 15-BGR value into 24-RGB values, is simply the reverse operation. The formula is:- R = ((color ) % 32) * 8
- G = ((color / 32) % 32) * 8
- B = ((color / 1024) % 32) * 8
复制代码 The following example shows how to convert white (32767) to it’s respective RGB values:- Color = 32767
- R = (Color % 32) x 8
- R = (32767 % 32) x 8 = 31 x 8 = 248
- G = ((color / 32) % 32) x 8
- G = ((32767 / 32) % 32) x 8 = (1023 % 32) x 8 = 32 x 8 = 248
- B = ((color / 1024) % 32) x 8
- B = ((32767 / 1024) % 32) x 8 = (31 % 32) x 8 = 32 x 8 = 248
复制代码 Since we are using powers of 2 we can use a bitmask of (color & 0x1F) instead of (color mod 32) incase you are using a older compiler that doesn’t optimize mod division by a constant. Also, it may be easier to think in hex instead of decimal:- Color = 32767
- R = (Color & 31) * 8
- = (32767 & 31) * 8
- = (0x7FFF & 0x1F) << 3
- = 0x1F << 3
- = 0xF8
- = 248
- Similarly for green and blue ...
复制代码 So the final output is (248, 248, 248). Uh-oh, 24-bit RGB white is (255, 255, 255) not (248, 248, 248). Apparently, what happened is there was a precision loss during the conversion. Think about it, if you convert a 24-bit value into a 15-bit you would have loss some precision. The three least significant bits are lost in each component. Thus, the extra precision that 24-bit color provides is lost and is unrecoverable.
So you won’t get precision but you can stretch the range rather easily after the conversion (_ensure_ that you use unsigned integer math for this):
A naïve approach would be to do a multiplication and division scaling:- R = (255*R)/31;
- G = (255*G)/31;
- B = (255*B)/31;
复制代码 A faster approach is:- R = R + R / 32
- G = G + G / 32
- B = B + B / 32
复制代码 This seems strange at first glance, but what happens is that you replicate the top three bits of each component into the bottom three bits (which, as stated above, are empty after conversion). This, if you think long enough about it, has the effect of stretching the color values into the full (0,0,0) -> (255,255,255) range.
E.g. If red is close to 0, those three bits will also tend to be be 0 so you won’t lose the blackest black. If red is close to 248 (the maximum after conversion) those bits will all be 1’s, so you get full red. Between the extremes, it works out so you gradually get the required boost up to the real maximum (255).
|
|