M = mask (top), I = image (bottom)
- normal: E = M
- dissolve: E = M or I, randomly picked per pixel
- multiply: E = M × I / 255
- darker
- divide: E = I × (256 / (M+1))
- brighter, brightens dark M parts strongly
- screen: E = 255 − (255 − M)(255 − I)/255
- brighter, equiv. "multiply" conjugated by inversion
- dodge: E = I × (256 / (256−M))
- brighter, brightens bright M parts strongly; equivalent to divide with inverted mask
- burn: E = 255 − (255 − I) × (256 / (M+1))
- darker, darkens dark M parts strongly
- hard light: super complicated
- for M in [0,128] it's multiply with 2M; for larger M it's all conjugated with inversion
- soft light: also complicated, I somehow doubt the documentation...
- grain extract: E = I − M + 128
- grain merge: E = I + M − 128
- difference: E = |I − M|
- addition: E = M + I
- subtraction: E = I − M
- darken: E = min
- lighten: E = max
- hue, saturation, brightness, value: takes that component from M and others from I