ex0: solve :)
This commit is contained in:
BIN
exercise0/main
Executable file
BIN
exercise0/main
Executable file
Binary file not shown.
@@ -1,18 +1,105 @@
|
||||
#include "bitmap.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
|
||||
Reference in New Issue
Block a user