Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Opacity blending without background causing colours to darken #3125

Open
NickStafford opened this issue Jan 8, 2025 · 1 comment
Open

Opacity blending without background causing colours to darken #3125

NickStafford opened this issue Jan 8, 2025 · 1 comment

Comments

@NickStafford
Copy link

Describe the bug

During rendering, when a map is rendered with data layers that have an opacity value less than fully opaque, and no background layers, colours are darkened.

For example, if I render a single tile using a data layer and simple styling (put white circles where the data points are), the more transparent parts of the circles (around the edges) are darkened, as if they've been blended with a black colour.

I believe this opacity issue is also effecting other types of data layer generated with no background, for example filled geometries.

This issue does not impact rendered layers that have a background beneath them. Only when there's nothing beneath the

To Reproduce

Steps to reproduce the behavior:

  1. Create a map style with:
    • No background layer
    • A single simple data layer that uses colours with opacity < 1
  2. Setup any data source for that layer (for example, I'm using data from our database, that plots certain locations as points)
  3. Render the map
  4. Inspect the result
Example style JSON I've been using. Note: I've had to redact the data source (`sources`) info.
{
    "version": 8,
    "name": "MapLibre Demo Tiles",
    "sources": {
        "8A9831F9711C36E62C5902Ccb6443A9312B": {
            "type": "vector",
            "tiles": [
            ]
        }
    },
    "layers": [
        {
            "id": "8A9831F9711C36E62C5902Ccb6443A9312B-9999-circle",
            "source": "8A9831F9711C36E62C5902Ccb6443A9312B",
            "source-layer": "data",
            "minzoom": 0,
            "filter": [
                "all",
                [
                    ">=",
                    "dv",
                    0
                ],
                [
                    "<",
                    "dv",
                    10000000000
                ]
            ],
            "type": "circle",
            "paint": {
                "circle-radius": 4.2854956435548335,
                "circle-color": "white",
                "circle-opacity": 1,
                "circle-stroke-color": "white",
                "circle-stroke-opacity": 1
            }
        }
    ],
    "sprite": "mapbox://sprites/mapbox/bright-v9",
    "glyphs": "mapbox://fonts/mapbox/{fontstack}/{range}.pbf",
    "zoom": "10"
}

Expected behavior

I would expect the colours to remain true, with just an alpha channel applied to them.

My use-case is to be able to render data layers on their own, with opacity/transparency and colours correct that it can be overlayed on other images in a separate system.

Screenshots
Example using a simple white circles layer:
Image

Example of the same white circles when rendered with a white-background:
Image

Note that in the second example, the colours of the transparent sections are not "darkened" as they are in the first example.

And a final example:
Image

This time using a red background to show that the opacity blends with the underlying background layer totally fine when there is one. It's just a problem that it weirdly darkens the more transparent pixels when there's no underlying colour.

Platform information (please complete the following information):

  • Operating System: Linux
  • Platform (e.g. Node.js, Qt): Node.js
  • Version: "@maplibre/maplibre-gl-native": "5.1.1"

Additional context

To be sure I'm not contaminating the render result with my own code post-render. The code I'm using to "save" the render result is:

        map.render(renderOptions, async function (err, buffer) {
            if (err) throw err;

            map.release();

            var image = sharp(buffer, {
                raw: {
                    width: 512,
                    height: 512,
                    channels: 4
                }
            });

            // Convert raw image buffer to PNG
            await new Promise<void>((resolve, reject) => {
                image.toFile('image.png', function (err) {
                    if (err) throw reject(err);
                    
                    resolve();        
                });
            });

        });
@NickStafford
Copy link
Author

Note:

For a while there's also been interest in a feature to control blending modes. Which I'm not certain but I'd guess if that had ever been implemented it would help give control over this. (Issue maplibre/maplibre#170)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant