This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch master
in repository legacy-imlib2.
View the commit online.
commit fdc6b49ffa3e22409e432e4cc7c43df4b8f26531
Author: NRK <[email protected]>
AuthorDate: Sun Apr 26 23:22:43 2026 +0000
third-party: update uscaler
---
third-party/uscaler.h | 111 ++++++++++++++++++++++++++++++++++++++------------
1 file changed, 86 insertions(+), 25 deletions(-)
diff --git a/third-party/uscaler.h b/third-party/uscaler.h
index a50e6bf..f83f02a 100644
--- a/third-party/uscaler.h
+++ b/third-party/uscaler.h
@@ -126,6 +126,16 @@ typedef struct UscBuffer {
/// flush the old cache before the next resize.
USC_API void usc_ctx_set_input_buffer(UscContext *ctx, UscBuffer input);
+/// Configure conceptual output flipping.
+/// This flips the input sampling while keeping output buffer layout and
+/// `usc_ctx_set_output_subrect()` coordinates unchanged.
+typedef enum {
+ USC_FLIP_NONE = 0,
+ USC_FLIP_X = 1 << 0,
+ USC_FLIP_Y = 1 << 1,
+} UscFlipFlags;
+USC_API void usc_ctx_set_flip(UscContext *ctx, UscFlipFlags flip);
+
/// Only output the specified subrectangle.
/// The subrectangle must not extend beyond the conceptual output dimensions
/// specified in `usc_ctx_init()`. If not set, defaults to the full output.
@@ -160,6 +170,7 @@ struct UscContext {
int64_t output_w, output_h;
int64_t output_subrect_x, output_subrect_y;
int64_t output_subrect_w, output_subrect_h;
+ UscFlipFlags flip;
UscBuffer input_buffer;
UscExtra extra;
float *decode_row;
@@ -175,8 +186,8 @@ struct UscContext {
float *ring_buf;
ptrdiff_t ring_buf_size;
float *ring[4];
- int ring_head;
- int ring_tail;
+ int64_t ring_head;
+ int64_t ring_tail;
ptrdiff_t bicubic_weights_size;
int use_box_x, use_box_y;
Usc__Fx64 map_x_start, map_delta_x;
@@ -578,6 +589,18 @@ usc__ctx_reset_decode_cache(UscContext *ctx)
ctx->ring_tail = 0;
}
+static int64_t
+usc__map_output_x(const UscContext *ctx, int64_t x)
+{
+ return (ctx->flip & USC_FLIP_X) ? (ctx->output_w - 1 - x) : x;
+}
+
+static int64_t
+usc__map_output_y(const UscContext *ctx, int64_t y)
+{
+ return (ctx->flip & USC_FLIP_Y) ? (ctx->output_h - 1 - y) : y;
+}
+
USC_API int
usc_ctx_init(
UscContext *ctx,
@@ -763,6 +786,16 @@ usc_ctx_set_input_buffer(UscContext *ctx, UscBuffer input)
usc__ctx_reset_decode_cache(ctx);
}
+USC_API void
+usc_ctx_set_flip(UscContext *ctx, UscFlipFlags flip)
+{
+ USC_ASSERT(ctx != NULL);
+ USC_ASSERT((flip & ~(USC_FLIP_X | USC_FLIP_Y)) == 0);
+ if (ctx->flip != flip)
+ usc__ctx_reset_decode_cache(ctx);
+ ctx->flip = flip;
+}
+
USC_API void
usc_ctx_set_output_subrect(
UscContext *ctx,
@@ -827,22 +860,31 @@ usc_resize_extended(
ctx->output_subrect_w == 0 || ctx->output_subrect_h == 0)
return;
+ int64_t sample_x0 = usc__map_output_x(ctx, ctx->output_subrect_x);
+ int64_t sample_x1 = usc__map_output_x(ctx, ctx->output_subrect_x + ctx->output_subrect_w - 1);
+ int64_t sample_x_lo = sample_x0 < sample_x1 ? sample_x0 : sample_x1;
+ int64_t sample_x_hi = sample_x0 > sample_x1 ? sample_x0 : sample_x1;
+ int64_t sample_x_step = (ctx->flip & USC_FLIP_X) ? -1 : 1;
+ Usc__Fx64 map_x_row = ctx->map_x_start + sample_x0 * ctx->map_delta_x;
+ Usc__Fx64 map_x_step = sample_x_step * ctx->map_delta_x;
int64_t decode_xoff = ctx->input_w;
int64_t decode_xend = 0;
if (ctx->use_box_x) {
- decode_xoff = ctx->box_x[ctx->output_subrect_x].left_idx;
- decode_xend = ctx->box_x[ctx->output_subrect_x + ctx->output_subrect_w - 1].right_idx + 1;
+ decode_xoff = ctx->box_x[sample_x_lo].left_idx;
+ decode_xend = ctx->box_x[sample_x_hi].right_idx + 1;
} else {
- Usc__Fx64 map_x0 = ctx->map_x_start + ctx->output_subrect_x * ctx->map_delta_x;
- Usc__Fx64 map_x1 = map_x0 + (ctx->output_subrect_w - 1) * ctx->map_delta_x;
- decode_xoff = usc__clamp((map_x0 >> FX_FRAC) - 1, 0, ctx->input_w - 1);
- decode_xend = usc__clamp((map_x1 >> FX_FRAC) + 3, 0, ctx->input_w);
+ Usc__Fx64 map_x_lo = ctx->map_x_start + sample_x_lo * ctx->map_delta_x;
+ Usc__Fx64 map_x_hi = ctx->map_x_start + sample_x_hi * ctx->map_delta_x;
+ decode_xoff = usc__clamp((map_x_lo >> FX_FRAC) - 1, 0, ctx->input_w - 1);
+ decode_xend = usc__clamp((map_x_hi >> FX_FRAC) + 3, 0, ctx->input_w);
}
- Usc__Fx64 map_y = ctx->map_y_start + ctx->output_subrect_y * ctx->map_delta_y;
+ int64_t sample_y = usc__map_output_y(ctx, ctx->output_subrect_y);
+ Usc__Fx64 map_y = ctx->map_y_start + sample_y * ctx->map_delta_y;
+ Usc__Fx64 map_y_step = (ctx->flip & USC_FLIP_Y) ? -ctx->map_delta_y : ctx->map_delta_y;
char *dst_row = output_buf.data;
for (int64_t dy = 0; dy < ctx->output_subrect_h;
- ++dy, map_y += ctx->map_delta_y,
+ ++dy, map_y += map_y_step,
dst_row += output_buf.stride_bytes)
{
int64_t base_y = (map_y >> FX_FRAC) - 1;
@@ -850,6 +892,7 @@ usc_resize_extended(
Usc__Fx64 top_box = map_y - (ctx->map_delta_y >> 1);
Usc__Fx64 bot_box = map_y + (ctx->map_delta_y >> 1);
int64_t start_y, end_y;
+ int64_t want_y0 = 0, want_y1 = -1;
if (ctx->use_box_y) {
start_y = top_box >> FX_FRAC;
@@ -858,18 +901,34 @@ usc_resize_extended(
end_y = usc__clamp(end_y, 0, ctx->input_h - 1);
usc__memzero(ctx->acc_row, ctx->acc_row_size);
} else {
- start_y = usc__clamp(base_y, 0, ctx->input_h - 1);
- end_y = usc__clamp(base_y + 3, 0, ctx->input_h - 1);
- if (start_y < ctx->ring_head || start_y > ctx->ring_tail) {
- ctx->ring_head = start_y;
- ctx->ring_tail = start_y;
+ want_y0 = usc__clamp(base_y, 0, ctx->input_h - 1);
+ want_y1 = usc__clamp(base_y + 3, 0, ctx->input_h - 1);
+ if (ctx->ring_head >= ctx->ring_tail ||
+ want_y1 < ctx->ring_head || want_y0 >= ctx->ring_tail ||
+ (want_y0 < ctx->ring_head && want_y1 >= ctx->ring_tail))
+ { /* empty/disjoint cache, or the new window extends past both ends: refill all. */
+ ctx->ring_head = want_y0;
+ ctx->ring_tail = want_y0;
+ }
+ start_y = want_y0;
+ end_y = want_y1;
+ if (want_y0 >= ctx->ring_head && want_y1 < ctx->ring_tail) {
+ /* fully covered by cache: decode nothing. */
+ start_y = 1;
+ end_y = 0;
+ } else if (want_y0 >= ctx->ring_head && want_y0 < ctx->ring_tail &&
+ want_y1 >= ctx->ring_tail - 1)
+ { /* overlap at the front only: append the missing suffix rows. */
+ start_y = ctx->ring_tail;
+ } else if (want_y1 >= ctx->ring_head && want_y1 < ctx->ring_tail &&
+ want_y0 <= ctx->ring_head)
+ { /* overlap at the back only: prepend the missing prefix rows. */
+ end_y = ctx->ring_head - 1;
}
- start_y = end_y < ctx->ring_tail ? end_y + 1 : ctx->ring_tail;
}
for (int64_t sy = start_y; sy <= end_y; ++sy) {
- float *out_row = ctx->use_box_y ? ctx->acc_row :
- ctx->ring[ctx->ring_tail++ % RING_ROWS];
+ float *out_row = ctx->use_box_y ? ctx->acc_row : ctx->ring[sy % RING_ROWS];
float *src_row = usc__decode_row(
ctx->decode_row, &ctx->decode_row_y, ctx->prefixsum_row,
decode_xoff, decode_xend, sy,
@@ -877,9 +936,6 @@ usc_resize_extended(
);
float wy = 0.0f;
- if (ctx->ring_tail - ctx->ring_head > RING_ROWS)
- ctx->ring_head = ctx->ring_tail - RING_ROWS;
-
if (ctx->use_box_y) {
Usc__Fx64 row_top = sy * FX_ONE;
Usc__Fx64 row_bot = (sy + 1) * FX_ONE;
@@ -889,12 +945,12 @@ usc_resize_extended(
wy = overlap * ctx->inv_map_delta_y;
}
- Usc__Fx64 map_x = ctx->map_x_start + ctx->output_subrect_x * ctx->map_delta_x;
- for (int64_t dx = 0; dx < ctx->output_subrect_w; ++dx, map_x += ctx->map_delta_x) {
- int64_t full_dx = ctx->output_subrect_x + dx;
+ Usc__Fx64 map_x = map_x_row;
+ int64_t sample_x = sample_x0;
+ for (int64_t dx = 0; dx < ctx->output_subrect_w; ++dx, sample_x += sample_x_step, map_x += map_x_step) {
usc__pix4 pix;
if (ctx->use_box_x) {
- usc__BoxInfo *bx = ctx->box_x + full_dx;
+ usc__BoxInfo *bx = ctx->box_x + sample_x;
ptrdiff_t lidx = bx->left_idx, ridx = bx->right_idx;
usc__pix4 lsum = usc__pix4_load(ctx->prefixsum_row + lidx * 4);
usc__pix4 rsum = usc__pix4_load(ctx->prefixsum_row + (ridx + 1) * 4);
@@ -920,6 +976,11 @@ usc_resize_extended(
}
}
+ if (!ctx->use_box_y) {
+ ctx->ring_head = want_y0;
+ ctx->ring_tail = want_y1 + 1;
+ }
+
if (ctx->use_box_y) {
for (int64_t dx = 0; dx < ctx->output_subrect_w; ++dx) {
usc__pix4 outpix = usc__pix4_load(ctx->acc_row + dx * channels);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.