• jan@cosmigo.com

Palette conversion bug


#1

Seems if I save a palette after reducing the color depth from 888 to 555 my reds are off quite a bit. You can see the reds are off mainly. Any ideas?


#2

As discussed on Twitter, it’s not really a bug, but some special, yet unsupported BMP file feature as it seems.
You referred to BMP extra settings in a tweet showing options to save 555-RGB within BMP. Will have a look at this.


#3

One more thing. Can you please attach such a file that is the way you want to have it. This would help me playing around with it.


#4

Yeah I’ll get a example snippet of what I need, but how specific would you like? If you’re willing to accommodate my needs on this then you’ve earned a customer for life.

But, I think your looking too far into the bitmap aspect of things on 1 of the 2 issues. For the bitmap format, I’d like to see an option for flipped/reversed rows when saving.

Now the bigger problem would be the palette conversion. This has nothing to do with a file format but rather the equation probably as it’s a universal conversion.

This is how I do it in a javascript form:

		function convert555()
		{
			var rgbInput = document.getElementById('888RGB');

			rgbPadLeft(rgbInput);

			var rgb = parseInt(rgbInput.value, 16);

			var r = (((rgb & 0xFF0000) >> 16) * 31) / 255;
			var g = (((rgb & 0xFF00) >> 8) * 31) / 255;
			var b = ((rgb & 0xFF) * 31) / 255;

			var color = ((r << 10) | (g << 5) | b);

            document.getElementById('555RGB').value = padLeft(color.toString(16), 4);
		}

		function reset()
		{
			document.getElementById('888RGB').value = "";
			document.getElementById('555RGB').value = "";
			document.getElementById('888RGB').focus();
		}

		function padLeft(num, len) 
		{
			var str = num;

			while (str.length < len) {
    			str = '0' + str;
			}

			return str;
		}

		function rgbPadLeft(ctrl)
		{
			ctrl.value = padLeft(ctrl.value, 6);
		}

image


#5

Can you give me an example BMP image file that includes the data correctly? I still don’t understand how it’s possible to save a BMP using a color palette having 16 Bits per color instead of 24.
Also, the simplest thing overall would be if you just applied the calculation above on your own.

Let me explain:
The use case of the 555 option in Pro Motion is that it limits you to only use 2^5 = 32 different values per channel. But those are stretched to 8 Bit. This ensures that you can create an image in PM that looks the same when you remove the lowest 3 Bits of every channel and use it on a hardware that only uses 5Bits per channel because you then still have 32 different values (0…31). Stretching to 8 Bit is only done because the image would be too dark when viewed on a “normal” system.
Since you already post process the image I strongly recommend to do exactly the calculation you gave converting the 8Bit entries to 5 Bit. When displayed on the target hardware the image should look “the same” as it did within Pro Motion because 7ffff = 31-31-31 (packed Bits 555 for RGB) on the hardware looks the same as FFFFFF within PM and creating the image in Pro Motion with only 32 values per channel ensures that you don’t loose colors or “color depth”.

BTW, I guess the Photoshop export options refer to saving an image as 16Bit per Pixel and not an index based image. This would make sense and if you gave me a sample BMP file I can check this.


#6

So i’s kind of a weird thing that PS does with that format, the bitmap is indexed, but the colors are laid out in the file as 8-bit.


That image shows the colors highlighted in blue and the indexes below it. What I’d like to see is the same thing, but have the colors laid out in 555 mode. If you want to truly make the format perfect for the hardware, a palette size would precede the colors.

This can be considered specific, but also something that isn’t in any application so it’s your choice on the matter. I’d just like to see something that has indexes and 5-bit palettes in a file.


#7

The simplest thing would then be to create a file export plugin based on the samples (image or animation):
https://www.cosmigo.com/pixel_animation_software/plugins/developer-interface#Sample_FileIO_Plugins
What if the file format mentioned there would be changed to what you need? :

  • storing channel bits
  • storing the palette as packed channel bits
    This would be pretty simple to do actually on a copy of the existing sources.

#8

That sounds pretty good. Given the fact that with this particular hardware, the sprites and palettes are not stored together, I could do it that way just to give PM a way to draw it. I’m still trying to figure out in which order the colors are indexed in the palette originally for proper import, but that’s another issue.

So if this format were done, I’d just copy what I need from the “image” into my hex editor as usual. We’ll see, because like I don’t program in standard languages and to write a plug-in for an app that I’d have to purchase just to make make said plug-in is a bit of a gamble.


#9

Understood. But when creating a special exporter (I don’t mind doing the plugin when the format keeps being simple) we should create a file format that matches the hardware requirements. So, the best would be if you figured out how that data would be used natively by the system and then we create a plugin that stores the files as required.


#10

Special formats aside, it seems your formula to convert 888 to 555 is off across the map. I’m comparing your 555 palette exported file to what’s show in PM and the values are off. Fix please.


#11

I explained how it works and I don’t see a bug. It is subject to a file format and not the conversion itself.


#12

Thanks for the fast reply. Check out my converter here: http://mortalkombatplus.com/index.php?option=com_content&view=article&id=24&Itemid=312

My Example on why I think it’s not correct:

In image 1 you’ll see the palette laid out in PM, I exported this palette as the 555 format and opened it in a hex editor to double check it. And I’m assuming the index arrangement matches what’s being seen in PM.

In image 2 you can clearly see color index(3) is wrong. Are you reds and blues swapped? I think so…

7F9A bit breakdown: (correct value for FFE7D6)
R: 11111
G: 11100
B: 11010

6B9F bit breakdown: (incorrect value for FFE7D6)
R: 11010
G: 11100
B: 11111

Sorry for being persistent, I’m just trying to help as I’d love to purchase the program once eventually.

-Paul


#13

Hi Paul,

thanks for the sample. This helps! So here we go with the details…
First of all, when you define 555 in Pro Motion for the channels then you can’t use FFE7D6.
The next valid value is FFE6D5:
RGB-888: FF E6 D5
Bits-888: 11111111 11100110 11010101
When transferring from 888 to 555, all three bytes must be shifted to the right 3 bits to only use the upper (most significant) 5 bits
Bits-555 (still as 8 bits per channel): 00011111 00011100 00011010
Now we only use the lowest 5 Bits of each channel, starting with a “0” to fill up 16 Bits.

Bits-555 (plus one zero to the left): 01111111 10011010
RGB-555: 7F9A

So this is all fine, but YOU must do the operations mentioned above. This is suobject to transferring to certain format.
PM works with 8 Bits per channel and only guarantees that, when defining a 5 Bit limit only 64 different values can be used per channel,
so the result should look the same on the destination system when doing the shifting mentioned above.

-Jan


#14

I understand color space loss when going from 8 to 5-bit but I think the shifting technique you’re using isn’t accurate. You can see my method used here as I posted back in July.
image

I think the shifting may be 1 of the problems. Try this for an accurate conversion:

For each color byte apply this forumla: ((hex * 1Fh) / FFh)

So if we break it down FF E6 D5
We’ll get:
FF=1F (11111)
E6=1B (11011)
D5=19 (11001)

Then in RGB order you’ll have 111111101111001 which = 7F79.

With this conversion, you don’t have to worry about those colors that fall in the gaps as it will convert it to the closest value regardless. So I could convert FFE7D6 and get 7F7A :wink:

But this doesn’t address the main issue, as I believe the order in which you build your 3 color values back into 1 color value is in the wrong sequence. I still think your Reds and Blues are swapped.

-Paul


#15

Okay, we are talking about two problems. The easy one first:
The file format defines which bits use which color channel. If you code a format that writes red in the lowest bits 0-4 then it works like that. If you write them to 10 -14 then it’s okay, two. But this is subject to the format you need. This has nothing to do with how PM handles channels.

Now for the channel calculation. Let me explain from another view. Your target is to have 5 bits per channel. This results in values from 0 to 63, right? This is required for a machine that uses 5 bits per channel instead of 8 as your PC does.
Something that is clear at once is:
0 is the lowest value and 63 is the largest. Let’s go for gray. There is black, white and 62 other values.

Now you want to draw on a PC using 8 Bit per channel to display. What are the exact values in your mind that match to the 64 of the 5 bits?
0 = 0

63 = 255

1 = ?
33 = ?
60 = ?
(just to see where we get)

This is the relation we have and we talk about, a method to convert from 5 to 8 bits making the equally spread, as a first step and then we calculate backwards from an 8 Bit value to the corresponding 5 Bit value.
Maybe your approach is a different one. This could be the case.
When calculating please lets concentrate on a single channel, so we don’t get confused by mixing up three of them. It’s per channel operations after all.
I’m sure we get this sorted and maybe I indeed have to tweak my calculations :slight_smile:
-Jan


#16

OK great. For now, I’m going to drop the conversion debate as both methods will work.

Let’s focus on the channel sequence as I feel either I’m missing something or the Reds and Blues are swapped.
Now I fully understand the channel sequence can be format dependent, but in my case it’s standard order or R-G-B.

So my question boils down to, why are your 555 plain palettes being exported with their color arrangements as BBBBB-GGGGG-RRRRR instead of RRRRR-GGGGG-BBBBB which is considered standard.


#17

Within the BMP file? It’s because Microsoft says to do so in palette based files :slight_smile:


#18

PNG if that makes a difference. If that’s the case it shouldn’t be difficult to write an export of the palette to reverse the channel sequence?


#19

A program must write the data according to the file format spec. If you define a format that needs a certain order then it must be programmed to work that way. Usually it’s not hard to create a file i/o plugin for a simple file type. But the spec mus come first.


#20

Update, you were right all along. I never realized BMP were BGR sequence. That seems so backwards LoL.

Thank you for your patience.