Skip to content

Image quality degrades significantly when downscaling by >2× #1289

@grebmeg

Description

@grebmeg

Summary

Images downscaled by more than 2× display severe visual artifacts including pixelation, jagged edges, and loss of fine details like text and thin lines.

Technical Cause

When a transform has scale < 1.0 (downscaling), the renderer inverts it to map from output space back to source image space. The x_advance and y_advance vectors are calculated from this inverted transform to determine how far to step in the source image for each output pixel.

Example with scale(0.125) (8× downscale):

  1. User transform: scale(0.125) — render 800px image at 100px width
  2. Internal transform: scale(0.125).inverse() = scale(8.0) — maps output→source
  3. Advances computed: x_advance = (8.0, 0.0), y_advance = (0.0, 8.0)
  4. During rasterization:
    • The SIMD rasterizer processes 4 rows at once, calculating positions as [0, 1, 2, 3] × y_advance + start_pos
    • For output starting at position (10, 5) → source position (80, 40)
    • Four SIMD lanes sample at y-positions spaced 8 pixels apart: [40, 48, 56, 64]
    • Bilinear filter applies fixed offsets [-0.5, 0.5], sampling 2 pixels at each position
    • Result: Samples only 8 pixels total; should ideally sample 32 pixels (4 rows × 8 pixels per row) — 75% of data skipped

The x_advance and y_advance correctly determine where to sample based on the scale factor, but the sampling kernel remains fixed at 2×2 (bilinear) or 4×4 (bicubic) pixels regardless of how large the advance steps are. For proper 8× downscaling, each output pixel should ideally average an 8×8 block (64 pixels), but instead samples only 4-16 pixels, skipping 60-48 pixels respectively and causing severe aliasing and loss of fine details.

Solution

  • Add progressive downsampling for better image quality at small scales

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-cpuApplies to the vello_cpu crateC-hybridApplies to the vello_hybrid crateC-sparse-stripsApplies to sparse strips variants of vello in general

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions