fogleman / gg

Go Graphics - 2D rendering in Go with a simple API.
https://godoc.org/github.com/fogleman/gg
MIT License
4.37k stars 354 forks source link

Mixing colours #119

Closed StarsoftAnalysis closed 3 years ago

StarsoftAnalysis commented 3 years ago

I've noticed that when overlaying colours with alpha < 1.0, the result depends on the order in which the colours are added. For example, green on red produces a dark green, whereas red on green gives brown.

The attached bit of code shows what I mean: it shows that rgba(1, 0, 0, 0.5) covered by rgba(0, 1, 0, 0.5) gives rgba(0.33, 0.67, 0, 0.75), but rgba(0, 1, 0, 0.5) covered by rgba(1, 0, 0, 0.5) gives rgba(0.67, 0.33, 0, 0.75).

This is probably done for a good reason, but I'd like to be able to mix colours evenly, so that, for example, rgba(1,0,0,0.5) plus rgba(0,1,0,0.5) always gives rgba(0.5, 0.5, 0, 0.75), irrespective of which is drawn first.

Is there a way of doing that? I couldn't find the bit in the code that sets the one-third/two thirds ratio.

Here's my code:

package main

import (
    "github.com/fogleman/gg"
)   

func main() {
    dc := gg.NewContext(500, 500)

    dc.SetRGBA(0.0, 0.0, 0.0, 1.0)
    dc.DrawString("Green over Red:", 100, 90)
    dc.SetRGBA(1.0, 0.0, 0.0, 0.5)
    dc.DrawRectangle(100, 100, 200, 50)
    dc.Fill()
    dc.SetRGBA(0.0, 1.0, 0.0, 0.5)
    dc.DrawRectangle(200, 100, 200, 50)
    dc.Fill()

    dc.SetRGBA(0.0, 0.0, 0.0, 1.0)
    dc.DrawString("Red over Green:", 100, 240)
    dc.SetRGBA(0.0, 1.0, 0.0, 0.5)
    dc.DrawRectangle(100, 250, 200, 50)
    dc.Fill()
    dc.SetRGBA(1.0, 0.0, 0.0, 0.5)
    dc.DrawRectangle(200, 250, 200, 50)
    dc.Fill()

    dc.SavePNG("ggmixing.png")
}   

ggmixing

StarsoftAnalysis commented 3 years ago

Further investigation reveals that other packages (e.g. draw2d) do the same thing.

In fact the formula given in Wikipedia does too, so I obviously need a different approach to get the effect I want.