optimzations

This commit is contained in:
Andrew Haynes
2026-03-05 15:22:04 -05:00
parent ce216b1879
commit 59b89a61b5
3 changed files with 145 additions and 90 deletions
Vendored
BIN
View File
Binary file not shown.
+5
View File
@@ -4,5 +4,10 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include_directories(include) include_directories(include)
project(ppm_image_processor LANGUAGES C) project(ppm_image_processor LANGUAGES C)
find_package(JPEG REQUIRED)
add_executable(ppm_image_processor src/main.c) add_executable(ppm_image_processor src/main.c)
target_include_directories(ppm_image_processor PRIVATE ${JPEG_INCLUDE_DIRS})
target_link_libraries(ppm_image_processor PRIVATE ${JPEG_LIBRARIES})
+140 -90
View File
@@ -1,15 +1,19 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
typedef struct
{
int width, height, len;
char* name;
char magic_number[3];
} Image;
unsigned int unsigned int
encoder(unsigned char r, unsigned char g, unsigned char b) encoder(unsigned char r, unsigned char g, unsigned char b)
{ {
unsigned int color = 0; return (b << 0) | (g << 8) | (r << 16);
color |= b << 0;
color |= g << 8;
color |= r << 16;
return color;
} }
unsigned char unsigned char
@@ -22,16 +26,6 @@ decoder(unsigned int clr, int byte)
return 0; return 0;
} }
// unsigned int
// decoder_int(unsigned int clr, int byte)
// {
// if (byte == 1) return (clr & 0x000000FF) >> 0;
// else if (byte == 2) return (clr & 0x0000FF00) >> 8;
// else if (byte == 3) return (clr & 0x00FF0000) >> 16;
// else if (byte == 4) return (clr & 0xFF000000) >> 24;
// return 0;
// }
unsigned int unsigned int
set_alpha(unsigned int clr, unsigned char alpha_value) set_alpha(unsigned int clr, unsigned char alpha_value)
{ {
@@ -41,9 +35,7 @@ set_alpha(unsigned int clr, unsigned char alpha_value)
unsigned int unsigned int
invert_rgb(unsigned int clr) invert_rgb(unsigned int clr)
{ {
unsigned char alpha = (clr & 0xFF000000) >> 24; return ((~clr) & 0x00FFFFFF) | (clr & 0xFF000000);
return ((~clr) & 0x00FFFFFF) | alpha << 24;
} }
unsigned int unsigned int
@@ -56,14 +48,10 @@ swap_rb(unsigned int clr)
unsigned int unsigned int
to_grayscale(unsigned int clr) to_grayscale(unsigned int clr)
{ {
unsigned char alpha = decoder(clr, 4); int average =
unsigned char red = decoder(clr, 3); (decoder(clr, 3) + decoder(clr, 2) + decoder(clr, 1)) * .33333;
unsigned char green = decoder(clr, 2);
unsigned char blue = decoder(clr, 1);
int average = (red + green + blue) / 3;
unsigned int mask = encoder(average, average, average); unsigned int mask = encoder(average, average, average);
mask = set_alpha(mask, alpha); mask = set_alpha(mask, decoder(clr, 4));
return mask; return mask;
} }
@@ -72,8 +60,7 @@ unsigned int
apply_threshold(unsigned int clr, unsigned char limit) apply_threshold(unsigned int clr, unsigned char limit)
{ {
unsigned int mask = 0; unsigned int mask = 0;
unsigned char average = decoder(to_grayscale(clr), 1); if (decoder(to_grayscale(clr), 1) < limit) mask = encoder(0, 0, 0);
if (average < limit) mask = encoder(0, 0, 0);
else mask = encoder(255, 255, 255); else mask = encoder(255, 255, 255);
mask = set_alpha(mask, decoder(clr, 4)); mask = set_alpha(mask, decoder(clr, 4));
return mask; return mask;
@@ -116,54 +103,74 @@ apply_opacity(unsigned clr_a, unsigned int clr_b, float ratio)
} }
unsigned int* unsigned int*
ppm_encode(char* file, int* w, int* h, int* max_val, char* magic_number) ppm_encode(char* file, Image* img)
{ {
unsigned char r, g, b; unsigned char r, g, b;
int max_val;
FILE* fptr; FILE* fptr;
fptr = fopen(file, "r"); fptr = fopen(file, "r");
if (!fptr) return NULL; if (!fptr) return NULL;
fscanf(fptr, "%s", magic_number); fscanf(fptr, "%s", img->magic_number);
fscanf(fptr, "%d %d", w, h); fscanf(fptr, "%d %d", &img->width, &img->height);
fscanf(fptr, "%d", max_val); img->len = img->width * img->height;
unsigned int* buf = malloc((*w) * (*h) * sizeof(unsigned int)); fscanf(fptr, "%d", &max_val);
fgetc(fptr);
unsigned int* buf = malloc(img->len * sizeof(unsigned int));
if (!buf) return NULL; if (!buf) return NULL;
if (img->magic_number[1] == '3')
for (int i = 0; i < (*w * *h); i++)
{ {
fscanf(fptr, "%hhu %hhu %hhu", &r, &g, &b); for (int i = 0; i < img->len; i++)
unsigned int packed = encoder(r, g, b); {
buf[i] = set_alpha(packed, 255); fscanf(fptr, "%hhu %hhu %hhu", &r, &g, &b);
unsigned int packed = encoder(r, g, b);
buf[i] = set_alpha(packed, 255);
}
} }
else if (img->magic_number[1] == '6')
{
for (int i = 0; i < img->len; i++)
{
fread(&r, sizeof(unsigned char), 1, fptr);
fread(&g, sizeof(unsigned char), 1, fptr);
fread(&b, sizeof(unsigned char), 1, fptr);
unsigned int packed = encoder(r, g, b);
buf[i] = set_alpha(packed, 255);
}
}
fclose(fptr); fclose(fptr);
return buf; return buf;
} }
void void
ppm_apply_brightness(unsigned int* buf, int buf_size, float factor) ppm_apply_brightness(unsigned int* buf, Image img, float factor)
{ {
for (int i = 0; i < buf_size; i++) for (int i = 0; i < img.len; i++)
{ {
buf[i] = adjust_brightness(buf[i], factor); buf[i] = adjust_brightness(buf[i], factor);
} }
} }
void void
ppm_decode(unsigned int* buf, int buf_size, char* name, int* w, int* h) ppm_decode(unsigned int* buf, Image img)
{ {
unsigned char red, green, blue; unsigned char red, green, blue;
FILE* fptr = fopen(name, "w"); FILE* fptr;
if (img.magic_number[1] == '3') fptr = fopen(img.name, "w");
if (img.magic_number[1] == '6') fptr = fopen(img.name, "wb");
if (!fptr) return; if (!fptr) return;
fprintf(fptr, "P3\n%d %d\n255\n", *w, *h);
for (int i = 0; i < buf_size; i++) fprintf(fptr, "%s\n%d %d\n255\n", img.magic_number, img.width,
img.height);
for (int i = 0; i < img.len; i++)
{ {
red = decoder(buf[i], 3); red = decoder(buf[i], 3);
green = decoder(buf[i], 2); green = decoder(buf[i], 2);
blue = decoder(buf[i], 1); blue = decoder(buf[i], 1);
fprintf(fptr, "%d %d %d ", red, green, blue); fwrite(&red, 1, 1, fptr);
if ((i + 1) % *w == 0) fwrite(&green, 1, 1, fptr);
{ fwrite(&blue, 1, 1, fptr);
fprintf(fptr, "\n");
}
} }
fclose(fptr); fclose(fptr);
} }
@@ -206,15 +213,16 @@ chromatic_circular_shift(unsigned int clr, int n)
} }
unsigned int* unsigned int*
horizontal_flip(unsigned int* buf, int size, int w, int h) horizontal_flip(unsigned int* buf, Image img)
{ {
unsigned int* flip = malloc((w * h) * sizeof(unsigned int)); unsigned int* flip = malloc(img.len * sizeof(unsigned int));
if (!flip) return NULL;
int idx = 0; int idx = 0;
for (int i = 0; i < w; i++) for (int i = 0; i < img.height; i++)
{ {
for (int k = h - 1; k >= 0; k--) for (int k = img.width - 1; k >= 0; k--)
{ {
flip[idx] = buf[i * w + k]; flip[idx] = buf[i * img.width + k];
idx++; idx++;
} }
} }
@@ -224,16 +232,17 @@ horizontal_flip(unsigned int* buf, int size, int w, int h)
} }
unsigned int* unsigned int*
vertical_flip(unsigned int* buf, int size, int w, int h) vertical_flip(unsigned int* buf, Image img)
{ {
unsigned int* flip = malloc((w * h) * sizeof(unsigned int)); unsigned int* flip = malloc(img.len * sizeof(unsigned int));
if (!flip) return NULL;
int idx = 0; int idx = 0;
for (int i = h - 1; i >= 0; i--) for (int i = img.height - 1; i >= 0; i--)
{ {
for (int k = 0; k < w; k++) for (int k = 0; k < img.width; k++)
{ {
flip[idx] = buf[i * w + k]; flip[idx] = buf[i * img.width + k];
idx++; idx++;
} }
} }
@@ -242,6 +251,62 @@ vertical_flip(unsigned int* buf, int size, int w, int h)
return flip; return flip;
} }
unsigned int
constrast_adjustment(unsigned int clr, float factor)
{
unsigned int mask = 0;
int r = factor * (decoder(clr, 3) - 128) + 128;
int g = factor * (decoder(clr, 2) - 128) + 128;
int b = factor * (decoder(clr, 1) - 128) + 128;
if (r > 255) r = 255;
if (g > 255) g = 255;
if (b > 255) b = 255;
if (r < 0) r = 0;
if (g < 0) g = 0;
if (b < 0) b = 0;
mask = encoder(r, g, b);
mask = set_alpha(mask, decoder(clr, 4));
return mask;
}
unsigned int*
rotate(unsigned int* buf, Image* img, int len)
{
unsigned int* mask = malloc(len * sizeof(unsigned int));
int old_width = img->width;
int old_height = img->height;
for (int y = 0; y < old_height; y++)
{
for (int x = 0; x < old_width; x++)
{
int new_height = x;
int new_width = (old_height - 1 - y);
mask[new_height * old_height + new_width] =
buf[y * old_width + x];
}
}
img->width = old_height;
img->height = old_width;
free(buf);
return mask;
}
Image
create_image(int w, int h, char* name, char* fmt)
{
Image image = {
.width = w,
.height = h,
.len = w * h,
.name = name,
};
image.magic_number[0] = fmt[0];
image.magic_number[1] = fmt[1];
image.magic_number[2] = '\0';
return image;
}
void void
print_bits_int(unsigned int n) print_bits_int(unsigned int n)
{ {
@@ -254,41 +319,26 @@ print_bits_int(unsigned int n)
write(1, "\n", 1); write(1, "\n", 1);
} }
void
print_bits_char(unsigned char n)
{
for (int i = 7; i >= 0; i--)
{
char bit = (n & (1 << i)) ? '1' : '0';
write(1, &bit, 1);
}
write(1, "\n", 1);
}
int int
main() main()
{ {
// unsigned int test = 40; Image image = create_image(3, 2, "../color.ppm", "P6");
// print_bits_int(test);
// test = (test << 3) | (test >> (8 - 3));
// print_bits_int(test);
// unsigned int color = encoder(200, 10, 50); unsigned int* buf = ppm_encode("../assets/4ktest.ppm", &image);
// color = set_alpha(color, 100); if (buf)
// print_bits_int(color); {
// // unsigned int channelled_color = channel_mask(color, 'g'); // ppm_apply_brightness(buf, image, 2);
// color = chromatic_circular_shift(color, 3); //
// print_bits_int(color); for (int i = 0; i < image.len; i++)
int width, height; {
char magic_number[3]; // buf[i] = channel_mask(buf[i], 'b');
int max_val; // buf[i] = chromatic_circular_shift(buf[i], (rand() % 10));
// buf[i] = constrast_adjustment(buf[i], 2);
unsigned int* buf = buf[i] = to_grayscale(buf[i]);
ppm_encode("../test.ppm", &width, &height, &max_val, magic_number); }
// ppm_apply_brightness(buf, (width * height), .5); // buf = rotate(buf, &image, image.len);
// buf = vertical_flip(buf, (width * height), width, height); ppm_decode(buf, image);
buf = horizontal_flip(buf, (width * height), width, height); free(buf);
ppm_decode(buf, (width * height), "../new.ppm", &width, &height); }
free(buf);
return 0; return 0;
} }