#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); // change colors modulo_scale_channel(image, 2, 2); modulo_scale_channel(image, 1, 0.420); modulo_scale_channel(image, 0, 0.69); // 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; }