Skip to content

Commit

Permalink
Make blending (in scaling) respect alpha
Browse files Browse the repository at this point in the history
Signed-off-by: Abe Wieland <[email protected]>
  • Loading branch information
abewieland committed Nov 29, 2024
1 parent 0a73f32 commit 9f85f5b
Showing 1 changed file with 23 additions and 8 deletions.
31 changes: 23 additions & 8 deletions src/pixmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ static void scale_average(struct scale_param* sp, size_t start, size_t step)
const argb_t color =
sp->src->data[src_y * sp->src->width + src_x];
a += ARGB_GET_A(color);
r += ARGB_GET_R(color);
g += ARGB_GET_G(color);
b += ARGB_GET_B(color);
r += ARGB_GET_R(color) * ARGB_GET_A(color);
g += ARGB_GET_G(color) * ARGB_GET_A(color);
b += ARGB_GET_B(color) * ARGB_GET_A(color);
++count;
}
}
Expand All @@ -150,6 +150,11 @@ static void scale_average(struct scale_param* sp, size_t start, size_t step)
r /= count;
g /= count;
b /= count;
if (a) {
r /= a;
g /= a;
b /= a;
}
}

const argb_t color = ARGB(a, r, g, b);
Expand Down Expand Up @@ -222,7 +227,10 @@ static void scale_bicubic(struct scale_param* sp, size_t start, size_t step)
}
const argb_t pixel =
sp->src->data[iy * sp->src->width + ix];
pixels[pc][py][px] = (pixel >> (pc * 8)) & 0xff;
pixels[pc][py][px] = pc == 3
? ARGB_GET_A(pixel)
: ((pixel >> (pc * 8)) & 0xff) *
ARGB_GET_A(pixel);
}
}
// recalc state cache for the current area
Expand Down Expand Up @@ -266,17 +274,24 @@ static void scale_bicubic(struct scale_param* sp, size_t start, size_t step)
}
}

// set pixel
for (size_t pc = 0; pc < 4; ++pc) {
// set pixel - get alpha first, then rest
for (int pc = 3; pc >= 0; --pc) {
// clang-format off
const float inter =
(state[pc][0][0] + state[pc][0][1] * diff_x + state[pc][0][2] * diff_x2 + state[pc][0][3] * diff_x3) +
(state[pc][1][0] + state[pc][1][1] * diff_x + state[pc][1][2] * diff_x2 + state[pc][1][3] * diff_x3) * diff_y +
(state[pc][2][0] + state[pc][2][1] * diff_x + state[pc][2][2] * diff_x2 + state[pc][2][3] * diff_x3) * diff_y2 +
(state[pc][3][0] + state[pc][3][1] * diff_x + state[pc][3][2] * diff_x2 + state[pc][3][3] * diff_x3) * diff_y3;
// clang-format on
const uint8_t color = max(min(inter, 255), 0);
fg |= (color << (pc * 8));
if (pc == 3) {
const uint8_t alpha = max(min(inter, 255), 0);
fg |= ARGB_SET_A(alpha);
} else {
const uint16_t mul = max(min(inter, 255 * 255), 0);
const uint8_t color =
ARGB_GET_A(fg) ? mul / ARGB_GET_A(fg) : 0;
fg |= (color << (pc * 8));
}
}

if (sp->alpha) {
Expand Down

0 comments on commit 9f85f5b

Please sign in to comment.