Skip to content

Commit 94f960d

Browse files
committed
Add the Gaussian function to blur a pixmap
Use Pascal's Triangle to approximate a 5x5 Gaussian Kernel, and apply Gaussian blur on the 'twin_pixmap_t' to implement the blurring technique. See: #34
1 parent 980bd4c commit 94f960d

File tree

4 files changed

+67
-0
lines changed

4 files changed

+67
-0
lines changed

include/twin.h

+2
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,8 @@ void twin_fill(twin_pixmap_t *dst,
648648

649649
void twin_premultiply_alpha(twin_pixmap_t *px);
650650

651+
void twin_gaussian_blur(twin_pixmap_t *px);
652+
651653
/*
652654
* event.c
653655
*/

include/twin_private.h

+15
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,21 @@ void _twin_button_init(twin_button_t *button,
586586

587587
/* utility */
588588

589+
#define min(x, y) \
590+
({ \
591+
typeof(x) _x = (x); \
592+
typeof(y) _y = (y); \
593+
(void) (&_x == &_y); \
594+
_x < _y ? _x : _y; \
595+
})
596+
597+
#define max(x, y) \
598+
({ \
599+
typeof(x) _x = (x); \
600+
typeof(y) _y = (y); \
601+
(void) (&_x == &_y); \
602+
_x > _y ? _x : _y; \
603+
})
589604
#ifdef _MSC_VER
590605
#include <intrin.h>
591606
static inline int twin_clz(uint32_t v)

src/draw.c

+49
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,55 @@ void twin_premultiply_alpha(twin_pixmap_t *px)
723723
}
724724
}
725725

726+
static twin_argb32_t _twin_apply_gaussian(twin_argb32_t v,
727+
uint8_t wght,
728+
twin_argb32_t *r,
729+
twin_argb32_t *g,
730+
twin_argb32_t *b)
731+
{
732+
*r += ((((v & 0x00ff0000) >> 16) * (twin_argb32_t) wght) << 8) & 0x00ff0000;
733+
*g += (((v & 0x0000ff00) >> 8) * (twin_argb32_t) wght) & 0x0000ff00;
734+
*b += ((((v & 0x000000ff) >> 0) * (twin_argb32_t) wght) >> 8) & 0x000000ff;
735+
}
736+
737+
void twin_gaussian_blur(twin_pixmap_t *px)
738+
{
739+
if (px->format != TWIN_ARGB32)
740+
return;
741+
742+
uint8_t kernel[5][5] = {{0x01, 0x04, 0x06, 0x04, 0x01},
743+
{0x04, 0x10, 0x18, 0x10, 0x04},
744+
{0x06, 0x18, 0x24, 0x18, 0x06},
745+
{0x04, 0x10, 0x18, 0x10, 0x04},
746+
{0x01, 0x04, 0x06, 0x04, 0x01}};
747+
twin_pointer_t ptr, tmp_ptr;
748+
twin_pixmap_t *tmp_px =
749+
twin_pixmap_create(px->format, px->width, px->height);
750+
memcpy(tmp_px->p.v, px->p.v,
751+
px->width * px->height * twin_bytes_per_pixel(px->format));
752+
753+
int radius = 2, _y, _x;
754+
twin_argb32_t r, g, b;
755+
for (int screen_y = 0; screen_y < px->height; screen_y++)
756+
for (int screen_x = 0; screen_x < px->width; screen_x++) {
757+
r = 0, g = 0, b = 0;
758+
ptr = twin_pixmap_pointer(px, screen_x, screen_y);
759+
for (int y = -radius; y <= radius; y++) {
760+
_y = min(max(screen_y + y, 0), px->height - 1);
761+
for (int x = -radius; x <= radius; x++) {
762+
_x = min(max(screen_x + x, 0), px->width - 1);
763+
tmp_ptr = twin_pixmap_pointer(tmp_px, _x, _y);
764+
_twin_apply_gaussian(*tmp_ptr.argb32,
765+
kernel[x + radius][y + radius], &r, &g,
766+
&b);
767+
}
768+
}
769+
*ptr.argb32 = (*ptr.argb32 & 0xff000000) | r | g | b;
770+
}
771+
772+
twin_pixmap_destroy(tmp_px);
773+
}
774+
726775
/*
727776
* array primary index is OVER SOURCE
728777
* array secondary index is ARGB32 RGB16 A8

src/image-png.c

+1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ twin_pixmap_t *_twin_png_to_pixmap(const char *filepath, twin_format_t fmt)
139139
_convertBGRtoARGB(pix->p.b, width, height);
140140
#endif
141141
twin_premultiply_alpha(pix);
142+
twin_gaussian_blur(pix);
142143
}
143144

144145
bail_free:

0 commit comments

Comments
 (0)