News:

Simutrans Tools
Know our tools that can help you to create add-ons, install and customize Simutrans.

Support 24-bit / 32-bit Colour Depth

Started by THLeaderH, July 07, 2026, 09:42:57 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

THLeaderH

Hello,

I would like to raise a proposal regarding Simutrans' internal colour depth and the image format used in pak files.

Currently, Simutrans renders graphics in a 16-bit RGB565 colour space. However, in the Japanese Simutrans community, there has been increasing demand for higher-quality graphical expression. In response to this, Simutrans OTRP, a Japanese fork of Simutrans, is planning to support 24-bit colour depth, or 32-bit colour depth for images with an alpha channel.

With the current 16-bit colour representation, colour degradation caused by colour reduction is especially noticeable for images that contain alpha channel information. This has become a practical issue for creators who want to use more detailed or higher-quality images.

To support higher colour depth, the image format inside pak files would also need to be changed. In OTRP, we have a policy of avoiding differences between Standard and OTRP in the add-on format as much as possible. The reason is that if "OTRP-only add-ons" become common, add-ons created by the community may no longer be usable by Standard players, which could divide the community.

For this reason, I would like to propose that Simutrans Standard also consider supporting 24-bit colour depth.

One possible approach would be to increase the version of the `obj_image` node in pak files from the current version 3 to version 4. In version 4, image data could be stored using 24-bit colour depth, or 32-bit colour depth when an alpha channel is present.

Even if Standard does not support actual 24-bit rendering for the time being, another possible approach would be for Standard to support loading 24-bit or 32-bit image data from pak files, while still converting it to the existing 16-bit RGB565 colour space for rendering. This would at least allow the same pak files and add-ons to be used in both Standard and OTRP, while leaving the rendering implementation in Standard unchanged or mostly unchanged.

On the OTRP side, we have already started working on 24-bit colour depth support. We are currently implementing it for the Windows GDI and SDL2 backends. Based on the work so far, it seems that this feature can be implemented with a reasonable amount of code changes.

If Simutrans Standard is also interested in supporting 24-bit colour depth, or at least supporting the loading of higher-colour-depth image data, we would be willing to contribute our work upstream.

Thank you for joining the discussion.

makie

That would be nice; I would very much welcome that.

prissi

#2
Simutrans 124.5 introduced a flexible render backend, so it can change the depth during execution even ... The only routines inside the program that had not been outsourced and need to change are the blending of ground tiles which for now assume 16 bit images. Everything else is hidden by the external layer. Also, this was made in preparation for a Hardware OpenGL renderer, which becomes more urgent with twice the data to process at each frame.

This render change went with a consistent renaming of nearly all graphical functions which means, however, that the changes will need to be ported manually (unless OPTR applies the flexible render approach too). SO I guess the low hanging fruit is first to support loading of similar images for both. (This will, of course, slow down the loading of larger sizes again dramatically ...)

One important question is of how to handle player colours. In OpenTTD, player colours use another 8 bit mask inside the sprite for recolouring. That would require a different approach for makeobj dat files syntax.

Then the question of how to encode this in the pak files. One option could be, that version 4 has alpha channel and version 5 has player colors as 8 bit information, with bits 0.127 for player color 1 blending and 128...255 for player color2 blending.

The changes to GDI and SDL are very small compared to the changes of the graphic routines. Rendering at higher depth will be mostly affecting high zoom levels.

EDIT: I looked at the OTPR source code but I saw no 32 bit code yet. Where should I fook for? Otherwise, maybe I should do the next release first before starting something as big as this.

THLeaderH

I agree that we should start from supporting loading the same format images.

For the player colors and other special colors, I am thinking of reusing the existing pre-defined colors. These special colors are encoded as it is drawn in the source png file. The descriptor reader can convert the pre-defined special colors to the internal expression.

However, we may add some more special colors for 24/32bit images. With the current special color table, the primary player color can be expressed only in 8 levels, but this may be increased. We may add other lighting colors as well.

makie

Quote from: THLeaderH on July 08, 2026, 03:17:07 PMHowever, we may add some more special colors for 24/32bit images. With the current special color table, the primary player color can be expressed only in 8 levels, but this may be increased. We may add other lighting colors as well.
No, that lead to many lighting pixel in old graphics.
All the old PNG files would then have to be reworked.
The glowing pixels are a real nuisance.

Just leave it as it is.

---
Or split it into two files. One for the graphics an the other for the mask.
All other tricks makes it incompatible with normal graphics programs like gimp.

prissi

I think a mask file with different colors could do the trick even better. Like Blue for player color 1, Red for player color 2 and several greens for special colors. (And then black for transparent mask ... )

Then, if makeobj finds extra text after the image definition, if will assume that is the mask to that image and encode the mask accordingly.

THLeaderH

Mask file sounds good for ensuring the backward compatibility. However, it adds one extra single image to each image, which increases the pak file size almost twice. Is it acceptable?

makie

One of the biggest paks is pak128.german and this one has no player colors.
If pak64 doubles its size it doesn't matter.

Buildings, factories and trees has no player colors. This are the biggest images. 

THLeaderH

@prissi

QuoteI looked at the OTPR source code but I saw no 32 bit code yet. Where should I fook for? Otherwise, maybe I should do the next release first before starting something as big as this.

I have just pushed my working branch at https://github.com/teamhimeh/simutrans/commits/24-bit-color/ . But this implementation assumes that the special colors (light colors, player colors) are written directly to the same source png image as the original.

Converting the internal pixel value type to 32bit integer was implemented with a reasonable implementation amount. However, it increased the memory consumption to twice for holding the loaded addon images even though all the loaded images are 16bit color depth. Keeping the 16bit color images in 16bit color pixel value made the implementation quite complicated...

prissi

We could use a simgraph32.cc for the main branch that is switched on load time.

And for images that do not specify a mask, the old plazer colors and special colours would be converted to new colours.
And the overlay images needed for 32 bit with the special and player colors are usually quite empty, so it would not add much extra memory.


victor_18993

I may be able to help with the first, more limited step: adding support in Standard for loading the new higher-colour-depth obj_image format and converting it to RGB565 during loading, while leaving the current renderer unchanged.

This seems reasonably self-contained and would already allow Standard and OTRP to use the same pak format.

Before starting, I would need confirmation of the intended on-disk format, particularly:

- the obj_image version number;
- RGB888/RGBA8888 layout and byte order;
- how alpha presence is indicated;
- whether special/player colours remain embedded in the source image for this first stage, or whether the separate mask format should be included from the beginning.

Once that is agreed, I can prepare the implementation together with compatibility and regression tests.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

prissi

I think the specification is still in flux. It looks like the Japanese side also thinks that a second mask might open up new possibilities from the Japanese discord. A backward compatible code is more or less already there, it needs renaming only and some copying.

I mean 24 bit images with seven player colours will look strange, so we will probably need something for this too. Same for some extra lightening colors, so street lamps could make circles on the ground and so on.

Maybe r+g player colours 1/2 0..127 and blue 0...63 blueish night colors and 64...127 yellowish night colors and the rest for other night colors?

The real work will be the 32 bit render, with all the blending and special color handling and new landscape tile creation. Also, so far the darkening was done via lookup tables, which for 32 bit is out of the question. So one has to darken the images algorithmically while caching them.

But for going forward, we first need to agree on the specs.

victor_18993

Thanks, that makes sense. I agree that the specification needs to be settled before starting the implementation.

Since this is already being discussed by several people, I do not want to duplicate or interfere with the work in progress. I will follow the discussion, and if it would be useful, I would be happy to help review or test the agreed format once the main decisions have been made.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)