Skip to content

[FR] Scaling algorithms #580

Open
Open

Description

@radry

I couldn't find any information about which scaling algorithm is used, so I assume it's bilinear.

It would be good to have a selection of alternative algorithms which can be used, like lanczos.

Activity

  1. lord-ne commented on Aug 5, 2026

    @lord-ne

    Currently, as far as I can tell the scaling is done here*:

    if (matrix == null) { matrix = new Matrix(); }
    matrix.reset();
    setMatrixArray(srcArray, 0, 0, tile.bitmap.getWidth(), 0, tile.bitmap.getWidth(), tile.bitmap.getHeight(), 0, tile.bitmap.getHeight());
    if (getRequiredRotation() == ORIENTATION_0) {
    setMatrixArray(dstArray, tile.vRect.left, tile.vRect.top, tile.vRect.right, tile.vRect.top, tile.vRect.right, tile.vRect.bottom, tile.vRect.left, tile.vRect.bottom);
    } else if (getRequiredRotation() == ORIENTATION_90) {
    setMatrixArray(dstArray, tile.vRect.right, tile.vRect.top, tile.vRect.right, tile.vRect.bottom, tile.vRect.left, tile.vRect.bottom, tile.vRect.left, tile.vRect.top);
    } else if (getRequiredRotation() == ORIENTATION_180) {
    setMatrixArray(dstArray, tile.vRect.right, tile.vRect.bottom, tile.vRect.left, tile.vRect.bottom, tile.vRect.left, tile.vRect.top, tile.vRect.right, tile.vRect.top);
    } else if (getRequiredRotation() == ORIENTATION_270) {
    setMatrixArray(dstArray, tile.vRect.left, tile.vRect.bottom, tile.vRect.left, tile.vRect.top, tile.vRect.right, tile.vRect.top, tile.vRect.right, tile.vRect.bottom);
    }
    matrix.setPolyToPoly(srcArray, 0, dstArray, 0, 4);
    canvas.drawBitmap(tile.bitmap, matrix, bitmapPaint);

    The code calculates a transformation matrix, which is then passed to Android's Canvas.drawBitmap which does the scaling.

    We could create some kind of Scaler interface with a drawScaledBitmapToCanvas method, pull out these lines into an implementation of that interface, and then pass an instance of that interface as an argument to the constructor of SubsamplingScaleImageView. That would be an easy way to allow users to implement their own scaling algorithms. Although all of this runs blocking, so performance may be an issue with more intense scaling algorithms.

    *It's possible that the scaling is done earlier, in the decoder, but that doesn't seem to be the case for the general fit-to-screen decoding.

  2. lord-ne commented on Aug 5, 2026

    @lord-ne

    Looking further, the correct place to deal with better scaling algorithms is actually probably the ImageRegionDecoder. The main view uses that class to subsample the images by a power of two factor, and the results are cached between canvas draws.

    Now ultimately, the sampled images are still up to 2x the screen resolution, so whether using a fancier algorithm is helpful remains to be seen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions