From 4bdd9ba823da792beae6dd4340b4d320437908cb Mon Sep 17 00:00:00 2001 From: Syndamia Date: Sat, 14 Mar 2026 22:38:38 +0200 Subject: feat: Implement color opacity --- graphics.c | 69 +++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 26 deletions(-) (limited to 'graphics.c') diff --git a/graphics.c b/graphics.c index 2100cc8..71365af 100644 --- a/graphics.c +++ b/graphics.c @@ -20,23 +20,35 @@ typedef uint8_t byte; typedef uint16_t byte2; typedef uint32_t byte4; -typedef struct RGB { +typedef struct ARGB { + byte a; byte r; byte g; byte b; -} RGB; +} ARGB; void -RGB_set(RGB* rgb, byte4 color) { - rgb->r = (0xFF0000 & color) >> 16; - rgb->g = (0x00FF00 & color) >> 8; - rgb->b = (0x0000FF & color); +ARGB_set(ARGB* rgb, byte4 color) { + rgb->a = (0xFF000000 & color) >> 24; + rgb->r = (0x00FF0000 & color) >> 16; + rgb->g = (0x0000FF00 & color) >> 8; + rgb->b = (0x000000FF & color); +} + +void +ARGB_merge(ARGB* bottom, ARGB top) { + bottom->a = 255; + double perc = top.a / 255.0; + + bottom->r = (bottom->r * (1.0 - perc)) + (top.r * perc); + bottom->g = (bottom->g * (1.0 - perc)) + (top.g * perc); + bottom->b = (bottom->b * (1.0 - perc)) + (top.b * perc); } typedef struct RGBImage { u32 width; u32 height; - RGB* img; + ARGB* img; } RGBImage; RGBImage @@ -44,7 +56,7 @@ RGBImage_new(u32 width, u32 height) { return (RGBImage){ .width = width, .height = height, - .img = malloc(sizeof(RGB) * width * height) + .img = malloc(sizeof(ARGB) * width * height) }; } @@ -60,7 +72,7 @@ RGBImage_delete(RGBImage* img) { img->img = NULL; } -RGB* +ARGB* RGBImage_at(RGBImage img, int row, int col) { return img.img + (row % img.height) * img.width + col % img.width; } @@ -68,7 +80,12 @@ RGBImage_at(RGBImage img, int row, int col) { int ppm6_write(FILE* f, RGBImage img) { fprintf(f, "P6\n%d %d\n255\n", img.width, img.height); - fwrite(img.img, sizeof(*img.img), img.width * img.height, f); + size_t size = img.width * img.height; + for (size_t i = 0; i < size; ++i) { + fputc(img.img[i].r, f); + fputc(img.img[i].g, f); + fputc(img.img[i].b, f); + } return fflush(f); } @@ -86,7 +103,7 @@ typedef struct Animation { AnimationEventNode* events; } Animation; -typedef RGB (*PixelRenderer)(const Animation* anim, u32 currentFrame, const RGB* pixel, u32 row, u32 col, void* priv); +typedef ARGB (*PixelRenderer)(const Animation* anim, u32 currentFrame, const ARGB* pixel, u32 row, u32 col, void* priv); struct AnimationEventNode { AnimationEventNode* next; @@ -167,9 +184,9 @@ Animation_render(Animation* anim) { for (int r = 0; r < anim->frameBuffer.width; ++r) for (int c = 0; c < anim->frameBuffer.height; ++c) { for (AnimationEventNode* aen = anim->events; aen != NULL && aen->startFrame <= currFrame; aen = aen->next) { - RGB* pixel = RGBImage_at(anim->frameBuffer, r, c); - RGB newPixel = aen->renderCallback(anim, currFrame, pixel, r, c, aen->privateData); - memcpy(pixel, &newPixel, sizeof(RGB)); + ARGB* pixel = RGBImage_at(anim->frameBuffer, r, c); + ARGB newPixel = aen->renderCallback(anim, currFrame, pixel, r, c, aen->privateData); + ARGB_merge(pixel, newPixel); } AnimationEventNode* prevNode = NULL, *currNode = anim->events; @@ -194,18 +211,18 @@ Animation_render(Animation* anim) { ////main//// -RGB -MovingBackground(const Animation* anim, u32 frameIndex, const RGB* currentPixel, u32 r, u32 c, void* priv) { - RGB pixel; +ARGB +MovingBackground(const Animation* anim, u32 frameIndex, const ARGB* currentPixel, u32 r, u32 c, void* priv) { + ARGB pixel; r = (r + frameIndex) / 32; c = (c + frameIndex) / 32; if ((r + c) % 2 == 0) { - RGB_set(&pixel, 0x000000); + ARGB_set(&pixel, 0xFF000000); } else { - RGB_set(&pixel, 0xFF00FF); + ARGB_set(&pixel, 0xFFFF00FF); } return pixel; @@ -217,10 +234,10 @@ struct SquareSettings { byte4 color; }; -RGB -Square(const Animation* anim, u32 frameIndex, const RGB* currentPixel, u32 r, u32 c, void* priv) { - RGB pixel; - memcpy(&pixel, currentPixel, sizeof(RGB)); +ARGB +Square(const Animation* anim, u32 frameIndex, const ARGB* currentPixel, u32 r, u32 c, void* priv) { + ARGB pixel; + memcpy(&pixel, currentPixel, sizeof(ARGB)); struct SquareSettings* set = (struct SquareSettings*)priv; @@ -228,7 +245,7 @@ Square(const Animation* anim, u32 frameIndex, const RGB* currentPixel, u32 r, u3 c = (c - frameIndex * 8) % anim->height; if (0 <= r && r <= set->width && 0 <= c && c <= set->height) { - RGB_set(&pixel, set->color); + ARGB_set(&pixel, set->color); } return pixel; @@ -241,12 +258,12 @@ main() { Animation_pushEvent(&anim, 0, 120, MovingBackground, NULL); struct SquareSettings s1 = { - .width = 20, .height = 20, .color = 0xFFFF00, + .width = 20, .height = 20, .color = 0xFFFFFF00, }; Animation_pushEvent(&anim, 0, 30, Square, &s1); struct SquareSettings s2 = { - .width = 10, .height = 25, .color = 0x09FAA5, + .width = 10, .height = 25, .color = 0x5009FAA5, }; Animation_pushEvent(&anim, 60, 100, Square, &s2); -- cgit v1.2.3