From 4467859b5d0c1c2eabbf674be7bc459302f36740 Mon Sep 17 00:00:00 2001 From: fredrikr79 Date: Sun, 24 Aug 2025 10:49:29 +0200 Subject: [PATCH] ex0: solve :) --- exercise0/main | Bin 0 -> 16328 bytes exercise0/main.c | 93 +++++++++++++++++++++++++++++++++++++++++++++-- flake.nix | 1 + 3 files changed, 91 insertions(+), 3 deletions(-) create mode 100755 exercise0/main diff --git a/exercise0/main b/exercise0/main new file mode 100755 index 0000000000000000000000000000000000000000..9d728cb31c4d999cda1807115f057a65ca4b6890 GIT binary patch literal 16328 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 yl>?wL3YdFf7O literal 0 HcmV?d00001 diff --git a/exercise0/main.c b/exercise0/main.c index 90cb014..2930b5d 100644 --- a/exercise0/main.c +++ b/exercise0/main.c @@ -1,18 +1,105 @@ #include "bitmap.h" +#include #include #include #define XSIZE 2560 // Size of before image #define YSIZE 2048 +#define INDEX(row, col) ((row) * XSIZE * 3 + (col) * 3) + +// scale a color channel by a factor from an rgb-pixel array, +// - channel = 0: scales red +// - channel = 1: scales green +// - channel = 2: scales blue +void modulo_scale_channel(uchar *data, int channel, float factor) { + if (channel > 2 || channel < 0) + return; + for (int row = 0; row < YSIZE; row++) { + for (int col = 0; col < XSIZE; col++) { + int i = INDEX(row, col); + // `2 - channel` because we get data as bgr, not rgb + data[i + 2 - channel] = (uchar)(data[i] * factor) % 256; + } + } +} + +// scale the entire image data by a given factor in both width and height. +void scale(uchar **data, int factor) { + uchar *scaled_data = calloc(XSIZE * YSIZE * 3 * factor * factor, 1); + for (int row = 0; row < YSIZE * factor; row++) { + for (int col = 0; col < XSIZE * factor; col++) { + int old = INDEX(row / factor, col / factor); + int new = INDEX(row * factor, col); // `* factor` for new row size. + for (int c = 0; c < 3; c++) // each color channel. + scaled_data[new + c] = (*data)[old + c]; + } + } + free(*data); + *data = scaled_data; +} + +// rotate the image data by 180 degrees. +void rotate(uchar *data) { + for (int row = 0; row < YSIZE; row++) { + for (int col = 0; col < XSIZE; col++) { + int old = INDEX(row, col); + int new = INDEX(YSIZE - row - 1, XSIZE - col - 1); // `- 1` for 0-index + + // swap all 3 color channels using the XOR swap algorithm to avoid temp. + // `i < j` to only do the swap once for the lower triangle. + if (old < new) { + for (int c = 0; c < 3; c++) { + data[old + c] = data[old + c] ^ data[new + c]; + data[new + c] = data[old + c] ^ data[new + c]; + data[old + c] = data[old + c] ^ data[new + c]; + } + } + } + } +} + +uchar color(int row, int col) { + // reverse row to apply gradient from upper left + row = YSIZE - row - 1; + // AI: combine row and col and scale with width and height + return (uchar)(((float)(row + col) / (XSIZE + YSIZE - 2)) * 255); +} + +// apply a gradient from upper left to lower right +void gradient(uchar *data, uchar (*color)(int, int), float alpha) { + for (int row = 0; row < YSIZE; row++) { + for (int col = 0; col < XSIZE; col++) { + int i = INDEX(row, col); + for (int c = 0; c < 3; c++) { + // AI: blend color channel with color of position and given alpha value + float t = alpha + (1.0f - alpha) * color(row, col) / 255.0f; + data[i + c] = (uchar)(data[i + c] * t); + } + } + } +} + int main(void) { uchar *image = calloc(XSIZE * YSIZE * 3, 1); // Three uchars per pixel (RGB) readbmp("before.bmp", image); - // Alter the image here - ; + // change colors + modulo_scale_channel(image, 2, 2); + modulo_scale_channel(image, 1, 0.420); + modulo_scale_channel(image, 0, 0.69); - savebmp("after.bmp", image, XSIZE, YSIZE); + // apply gradient + gradient(image, &color, 0.05); + + // rotate by 180 degrees + rotate(image); + + // scale image + const int factor = 2; + scale(&image, factor); + + savebmp("after.bmp", image, XSIZE * factor, YSIZE * factor); free(image); return 0; diff --git a/flake.nix b/flake.nix index 36e4dbc..63a4851 100644 --- a/flake.nix +++ b/flake.nix @@ -23,6 +23,7 @@ typstyle zip unzip + feh ]; shellHook = '' echo welcome!