diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2024-08-03 12:58:43 +0200 |
|---|---|---|
| committer | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2024-08-03 12:58:43 +0200 |
| commit | 90e573c54a76d3b1292cbe99102731abd6937305 (patch) | |
| tree | 39d88d3fc49eca55ce1d41ce650b38f00777bdd7 /core/image | |
| parent | ac483f72ebcec12548cbfd95f8296807e0851492 (diff) | |
Add image.premultiply_alpha helper.
Diffstat (limited to 'core/image')
| -rw-r--r-- | core/image/common.odin | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/core/image/common.odin b/core/image/common.odin index 94321f644..6ae9850da 100644 --- a/core/image/common.odin +++ b/core/image/common.odin @@ -1320,6 +1320,42 @@ blend_pixel :: #force_inline proc(fg: [$N]$T, alpha: T, bg: [N]T) -> (res: [N]T) } blend :: proc{blend_single_channel, blend_pixel} +// For all pixels of the image, multiplies R, G and B by Alpha. This is useful mainly for games rendering anti-aliased transparent sprites. +// Grayscale with alpha images are supported as well. +// Note that some image formats like QOI explicitly do NOT support premultiplied alpha, so you will end up with a non-standard file. +premultiply_alpha :: proc(img: ^Image) -> (ok: bool) { + switch { + case img.channels == 2 && img.depth == 8: + pixels := mem.slice_data_cast([]GA_Pixel, img.pixels.buf[:]) + for &pixel in pixels { + pixel.r = u8(u32(pixel.r) * u32(pixel.g) / 0xFF) + } + return true + case img.channels == 2 && img.depth == 16: + pixels := mem.slice_data_cast([]GA_Pixel_16, img.pixels.buf[:]) + for &pixel in pixels { + pixel.r = u16(u32(pixel.r) * u32(pixel.g) / 0xFFFF) + } + return true + case img.channels == 4 && img.depth == 8: + pixels := mem.slice_data_cast([]RGBA_Pixel, img.pixels.buf[:]) + for &pixel in pixels { + pixel.r = u8(u32(pixel.r) * u32(pixel.a) / 0xFF) + pixel.g = u8(u32(pixel.g) * u32(pixel.a) / 0xFF) + pixel.b = u8(u32(pixel.b) * u32(pixel.a) / 0xFF) + } + return true + case img.channels == 4 && img.depth == 16: + pixels := mem.slice_data_cast([]RGBA_Pixel_16, img.pixels.buf[:]) + for &pixel in pixels { + pixel.r = u16(u32(pixel.r) * u32(pixel.a) / 0xFFFF) + pixel.g = u16(u32(pixel.g) * u32(pixel.a) / 0xFFFF) + pixel.b = u16(u32(pixel.b) * u32(pixel.a) / 0xFFFF) + } + return true + case: return false + } +} // Replicates grayscale values into RGB(A) 8- or 16-bit images as appropriate. // Returns early with `false` if already an RGB(A) image. |