optimzations
This commit is contained in:
@@ -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})
|
||||||
|
|||||||
+136
-86
@@ -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++)
|
{
|
||||||
|
for (int i = 0; i < img->len; i++)
|
||||||
{
|
{
|
||||||
fscanf(fptr, "%hhu %hhu %hhu", &r, &g, &b);
|
fscanf(fptr, "%hhu %hhu %hhu", &r, &g, &b);
|
||||||
unsigned int packed = encoder(r, g, b);
|
unsigned int packed = encoder(r, g, b);
|
||||||
buf[i] = set_alpha(packed, 255);
|
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);
|
|
||||||
ppm_decode(buf, (width * height), "../new.ppm", &width, &height);
|
|
||||||
free(buf);
|
free(buf);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user