Skip to content

Commit 9476fae

Browse files
committed
Add bilinear filtering to tiled image rendering
1 parent 85cc025 commit 9476fae

File tree

1 file changed

+49
-17
lines changed

1 file changed

+49
-17
lines changed

source/plutovg-blend.c

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,18 @@ static inline uint32_t INTERPOLATE_PIXEL_255(uint32_t x, uint32_t a, uint32_t y,
6868
return x;
6969
}
7070

71+
static inline uint32_t INTERPOLATE_PIXEL_256(uint32_t x, uint32_t a, uint32_t y, uint32_t b)
72+
{
73+
uint32_t t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
74+
t >>= 8;
75+
t &= 0xff00ff;
76+
77+
x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
78+
x &= 0xff00ff00;
79+
x |= t;
80+
return x;
81+
}
82+
7183
static inline uint32_t BYTE_MUL(uint32_t x, uint32_t a)
7284
{
7385
uint32_t t = (x & 0xff00ff) * a;
@@ -854,14 +866,23 @@ static void blend_untransformed_tiled_argb(plutovg_surface_t* surface, plutovg_o
854866
}
855867
}
856868

869+
static inline uint32_t interpolate_4_pixels(uint32_t tl, uint32_t tr, uint32_t bl, uint32_t br, uint32_t distx, uint32_t disty)
870+
{
871+
uint32_t idistx = 256 - distx;
872+
uint32_t idisty = 256 - disty;
873+
uint32_t xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
874+
uint32_t xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
875+
return INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
876+
}
877+
878+
#define HALF_POINT (1 << 15)
857879
static void blend_transformed_tiled_argb(plutovg_surface_t* surface, plutovg_operator_t op, const texture_data_t* texture, const plutovg_span_buffer_t* span_buffer)
858880
{
859881
composition_function_t func = composition_table[op];
860882
uint32_t buffer[BUFFER_SIZE];
861883

862884
int image_width = texture->width;
863885
int image_height = texture->height;
864-
const int scanline_offset = texture->stride / 4;
865886

866887
int fdx = (int)(texture->matrix.a * FIXED_SCALE);
867888
int fdy = (int)(texture->matrix.b * FIXED_SCALE);
@@ -870,35 +891,46 @@ static void blend_transformed_tiled_argb(plutovg_surface_t* surface, plutovg_ope
870891
const plutovg_span_t* spans = span_buffer->spans.data;
871892
while(count--) {
872893
uint32_t* target = (uint32_t*)(surface->data + spans->y * surface->stride) + spans->x;
873-
const uint32_t* image_bits = (const uint32_t*)texture->data;
874894

875895
const float cx = spans->x + 0.5f;
876896
const float cy = spans->y + 0.5f;
877897

878-
int x = (int)((texture->matrix.c * cy + texture->matrix.a * cx + texture->matrix.e) * FIXED_SCALE);
879-
int y = (int)((texture->matrix.d * cy + texture->matrix.b * cx + texture->matrix.f) * FIXED_SCALE);
898+
int fx = (int)((texture->matrix.c * cy + texture->matrix.a * cx + texture->matrix.e) * FIXED_SCALE);
899+
int fy = (int)((texture->matrix.d * cy + texture->matrix.b * cx + texture->matrix.f) * FIXED_SCALE);
900+
901+
fx -= HALF_POINT;
902+
fy -= HALF_POINT;
880903

881904
const int coverage = (spans->coverage * texture->const_alpha) >> 8;
882905
int length = spans->len;
883906
while(length) {
884907
int l = plutovg_min(length, BUFFER_SIZE);
885908
const uint32_t* end = buffer + l;
886909
uint32_t* b = buffer;
887-
while(b < end) {
888-
int px = x >> 16;
889-
int py = y >> 16;
890-
px %= image_width;
891-
py %= image_height;
892-
if(px < 0) px += image_width;
893-
if(py < 0) py += image_height;
894-
int y_offset = py * scanline_offset;
910+
while (b < end) {
911+
int x1 = (fx >> 16) % image_width;
912+
int y1 = (fy >> 16) % image_height;
895913

896-
assert(px >= 0 && px < image_width);
897-
assert(py >= 0 && py < image_height);
914+
if(x1 < 0) x1 += image_width;
915+
if(y1 < 0) y1 += image_height;
898916

899-
*b = image_bits[y_offset + px];
900-
x += fdx;
901-
y += fdy;
917+
int x2 = (x1 + 1) % image_width;
918+
int y2 = (y1 + 1) % image_height;
919+
920+
const uint32_t* s1 = (const uint32_t*)(texture->data + y1 * texture->stride);
921+
const uint32_t* s2 = (const uint32_t*)(texture->data + y2 * texture->stride);
922+
923+
uint32_t tl = s1[x1];
924+
uint32_t tr = s1[x2];
925+
uint32_t bl = s2[x1];
926+
uint32_t br = s2[x2];
927+
928+
int distx = (fx & 0x0000ffff) >> 8;
929+
int disty = (fy & 0x0000ffff) >> 8;
930+
*b = interpolate_4_pixels(tl, tr, bl, br, distx, disty);
931+
932+
fx += fdx;
933+
fy += fdy;
902934
++b;
903935
}
904936

0 commit comments

Comments
 (0)