bumptech / glide

An image loading and caching library for Android focused on smooth scrolling
https://bumptech.github.io/glide/
Other
34.67k stars 6.12k forks source link

4.15.1: Unexpected background resizes with MaterialShapeDrawable and/or custom transform operation #5218

Open nikclayton opened 1 year ago

nikclayton commented 1 year ago

Glide Version: 4.15.1

Integration libraries: None

Device/Android Version: Android emulator running API 34, Nexus 4a (5G) running Android 13

Issue details / Repro steps / Use case background:

Problem

I am seeing strange behaviour when loading a partially transparent image in to an ImageView that has a MaterialShapeDrawable as the background, using a custom transform. The image's background bounds appear to shrink after the load.

What I'm doing

I am displaying images that may be partially transparent. If this is the case I need to ensure that any partially transparent areas of the image are composited with a copy of the background colour, so that anything "underneath" the ImageView does not show through.

Here are before/after screenshots showing what I mean. In the before, on the left, the Jernej avatar is partially transparent, so the "thread" line drawn underneath it shows through. On the right is with the additional compositing. Note that the post in the middle of the page in the "after" screenshot does not have the line.

However, when the code to do this is used to load the same avatar images in to an ImageView that has a MaterialShapeDrawable as the background then the width and height of the MaterialShapeDrawable appears to shrink, and the loaded image overlaps the border.

Reproduction

I have produced a minimal sample app that reproduces the problem.

If you clone, build, and run https://github.com/nikclayton/glide-composite-issue you will see the following:

Click the "Load without compositing" button, and you will see:

Then click the "Load with compositing" button and you will see:

Note how the height and width of the background have shrunk, while the image itself remains the same size.

Here's the two images side by side, to make the comparison easier to see:

The problem does not occur if I remove my custom transformation from the transform-chain. So I originally thought this was a bug in my code.

But, the problem also goes away if I replace this code, which sets the background of the avatar ImageView:

        val background = MaterialShapeDrawable.createWithElevationOverlay(this, 1f).apply {
            fillColor = ColorStateList.valueOf(Color.DKGRAY)
            elevation = 1f
            shapeAppearanceModel = ShapeAppearanceModel.builder()
                .setAllCornerSizes(resources.getDimension(R.dimen.avatar_background_radius))
                .build()
        }
        binding.avatar.background = background

with this:

        val backgroundJustColor = ColorDrawable(Color.DKGRAY)
        binding.avatar.background = backgroundJustColor

Since I can't see how my custom transformation could affect the background of the ImageView I thought this might be a Glide issue (or a MaterialShapeDrawable issue).

There's one final bit of weirdness. If you restart the demo app, and click the buttons in the opposite order (i.e., "Load with compositing" first, then "Load without compositing") it works; there's no shrinkage.

Which had me wondering if I've messed up the equals / hashCode / updateDiskCacheKey implementations in my transformation. But if I have, I can't see where...

sjudd commented 1 year ago

I'd guess this is more about the size Glide is using to load the image than a rendering issue. There's some logic here you could try to step through: https://github.com/bumptech/glide/blob/ce2f4954b262e05baec301d4221bf3526009ea3c/library/src/main/java/com/bumptech/glide/request/target/ViewTarget.java#L435. You could also see if you can reproduce by using .override() with a fixed size.