From bdb9acc4c5390ba7b3dd4c8ff7e44e9fe93753ea Mon Sep 17 00:00:00 2001 From: Lukas Jiriste Date: Wed, 3 Apr 2024 22:21:20 +0200 Subject: [PATCH] Add transparency handling Unfortunately this makes the program even slower... --- solution/main.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 126 insertions(+), 5 deletions(-) diff --git a/solution/main.c b/solution/main.c index 3f4c812..7695c4e 100644 --- a/solution/main.c +++ b/solution/main.c @@ -6,7 +6,7 @@ /* By: ljiriste +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/02 08:44:53 by ljiriste #+# #+# */ -/* Updated: 2024/04/03 22:18:06 by ljiriste ### ########.fr */ +/* Updated: 2024/04/03 22:20:56 by ljiriste ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -64,6 +65,61 @@ void decompress_to_image(struct jpeg_decompress_struct *cinfo, return ; } +typedef struct s_argb +{ + unsigned char a; + unsigned char r; + unsigned char g; + unsigned char b; +} t_argb; + +t_argb uint_to_argb(unsigned int uint_color) +{ + t_argb res; + + res.a = uint_color >> (8 * 3); + res.r = uint_color >> (8 * 2); + res.g = uint_color >> (8 * 1); + res.b = uint_color >> (8 * 0); + return (res); +} + +unsigned int argb_to_uint(t_argb color) +{ + unsigned int res; + + res = 0; + res |= color.a << (8 * 3); + res |= color.r << (8 * 2); + res |= color.g << (8 * 1); + res |= color.b << (8 * 0); + return (res); +} + +void flip_alpha(t_mlx_data *img) +{ + char *pixel; + int x; + int y; + t_argb color; + + x = 0; + while (x < img->width) + { + y = 0; + while (y < img->height) + { + pixel = (char *)img->addr + y * img->line_length + x * img->bits_per_pixel / CHAR_BIT; + color = uint_to_argb(*(unsigned int *)pixel); + color.a = 255 - color.a; + *(unsigned int *)pixel = argb_to_uint(color); + ++y; + } + ++x; + } + return ; +} + // This function is written as to have // the same signature as mlx_png_file_to_image void *mlx_jpeg_file_to_image(void *mlx_ptr, char *filename, @@ -92,9 +148,74 @@ void *mlx_jpeg_file_to_image(void *mlx_ptr, char *filename, jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); fclose(source); + flip_alpha(&img); return (img.img); } +// This function probably could do the arithmetic in uint form +// but this way it is more legible I think +unsigned int mix_colors(unsigned int back_uint, unsigned int front_uint) +{ + t_argb back; + t_argb front; + t_argb res; + + back = uint_to_argb(back_uint); + front = uint_to_argb(front_uint); + res.a = front.a - (255 - back.a) * front.a / 255; + res.r = (front.r * (255 - front.a) + back.r * (255 - back.a) * front.a / 255) / (255 - res.a); + res.g = (front.g * (255 - front.a) + back.g * (255 - back.a) * front.a / 255) / (255 - res.a); + res.b = (front.b * (255 - front.a) + back.b * (255 - back.a) * front.a / 255) / (255 - res.a); + return (argb_to_uint(res)); +} + +void copy_image(t_mlx_data *dest, t_mlx_data *src, int x, int y) +{ + char *dest_pix; + char *src_pix; + int i; + int j; + + i = 0; + while (i + x < dest->width && i < src->width) + { + j = 0; + while (j + y < dest->height && j < src->height) + { + dest_pix = (char *)dest->addr + ((j + y) * dest->line_length + (i + x) * dest->bits_per_pixel / CHAR_BIT); + src_pix = (char *)src->addr + (j * src->line_length + i * src->bits_per_pixel / CHAR_BIT); + *(unsigned int *)dest_pix = mix_colors(*(unsigned int *)dest_pix, *(unsigned int *)src_pix); + ++j; + } + ++i; + } + return ; +} + +// First use has to be with the largest picture, as that initializes the image +int mlx_put_image_to_window_transparency(t_mlx_session *s, t_mlx_data *img, int x, int y) +{ + static t_mlx_data to_print; + + if (!s->mlx_win) + { + mlx_destroy_image(s->mlx, to_print.img); + return (0); + } + if (!to_print.img) + { + to_print.img = mlx_new_image(s->mlx, img->width, img->height); + if (!to_print.img) + return (1); + to_print.addr = mlx_get_data_addr(to_print.img, &to_print.bits_per_pixel, &to_print.line_length, &to_print.endian); + to_print.width = img->width; + to_print.height = img->height; + } + copy_image(&to_print, img, x, y); + mlx_put_image_to_window(s->mlx, s->mlx_win, to_print.img, 0, 0); + return (0); +} + int mlx_close_win(t_mlx_session *s) { mlx_destroy_window(s->mlx, s->mlx_win); @@ -140,12 +261,12 @@ int no_event_handle(t_graphics *g) } if (y + g->red_frame.height < g->background.height) { - mlx_put_image_to_window(g->mlx_ses.mlx, g->mlx_ses.mlx_win, g->background.img, 0, 0); - mlx_put_image_to_window(g->mlx_ses.mlx, g->mlx_ses.mlx_win, g->red_frame.img, x, y); + mlx_put_image_to_window_transparency(&g->mlx_ses, &g->background, 0, 0); + mlx_put_image_to_window_transparency(&g->mlx_ses, &g->red_frame, x, y); /* if (emoji_encountered(image, emoji, x, y)) { - mlx_put_image_to_window(s->mlx, s->mlx_win, green_frame, x, y); + mlx_put_image_to_window_transparency(s->mlx, s->mlx_win, green_frame, x, y); record_pos(state, x, y); } */ @@ -180,7 +301,7 @@ void display(char **argv) mlx_hook(graphics.mlx_ses.mlx_win, DestroyNotify, NoEventMask, mlx_close_win, &graphics.mlx_ses); mlx_loop_hook(graphics.mlx_ses.mlx, no_event_handle, &graphics); - mlx_put_image_to_window(graphics.mlx_ses.mlx, graphics.mlx_ses.mlx_win, graphics.background.img, 0, 0); + mlx_put_image_to_window_transparency(&graphics.mlx_ses, &graphics.background, 0, 0); mlx_loop(graphics.mlx_ses.mlx); } cleanup(&graphics); -- 2.30.2