Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with loading the AVIF image #118

Open
mrmike opened this issue Dec 9, 2024 · 4 comments
Open

Issue with loading the AVIF image #118

mrmike opened this issue Dec 9, 2024 · 4 comments

Comments

@mrmike
Copy link

mrmike commented Dec 9, 2024

Context

I've encountered an issue loading the AVIF image using the telephoto library. Interestingly, the same image loads correctly when using AsyncImage from the coil.

After comparing events generated by EventListener from coil and telephoto I've noticed that telephoto only reaches resolveSizeStart event. I suspect that the issue is related to resolving the image size. Further debugging revealed that canvasSize is never emitted b/c filter condition is always false but I have no clue why this is happening 🤔

  val resolved = key(image) {
    image.resolve(
      canvasSize = remember {
        snapshotFlow { canvasSize }.filter { it.isSpecified && !it.isEmpty() }
      }
    )
  }
  • Coil version 3.0.4
  • Telephoto version 0.14.0
  • Android SDK 35

Example

@Composable
fun AvifImageLoader() {
    val image = "https://raw.githubusercontent.com/link-u/avif-sample-images/refs/heads/master/fox.profile0.8bpc.yuv420.avif"

    // Using AsyncImage from Coil works fine
    ZoomableAsyncImage(
        model = image,
        contentDescription = null,
    )
}
@mrmike
Copy link
Author

mrmike commented Dec 9, 2024

Ok, I think the issue is caused by the fact that BitmapRegionDecoder is not supporting AVIF format

java.io.IOException: Image format not supported
at android.graphics.BitmapRegionDecoder.nativeNewInstance(Native Method)
at android.graphics.BitmapRegionDecoder.newInstance(BitmapRegionDecoder.java:102).   
at me.saket.telephoto.subsamplingimage.FileImageSource.decoder(SubSamplingImageSource.kt:167)
at me.saket.telephoto.subsamplingimage.internal.AndroidImageRegionDecoder$Companion$Factory$1$1.invokeSuspend(AndroidImageRegionDecoder.kt:100)

@saket
Copy link
Owner

saket commented Dec 9, 2024

We could disable sub-sampling if BitmapRegionDecoder throws an error. Wanna help me out? I'd start by adding an error reporter here:

val subSamplingState = rememberSubSamplingImageState(
imageSource = delegate.source,
zoomableState = state.zoomableState,
imageOptions = delegate.imageOptions
)

When a callback to onImageLoadingFailed() is received, ZoomableImage could override its resolved value by a fall-back ZoomableImageSource.PainterDelegate.

@mrmike
Copy link
Author

mrmike commented Dec 9, 2024

Providing empty SubSamplingImageErrorReporter was enough to make image to load. My assuption is that RealSubSamplingImageState is able to provide state when decoder is not present (just LoadImageTilesEffect is not going to work).

I was getting crash because I was testing on debug build where NoOpInRelease reporter rethrows exception for BuildConfig.DEBUG.

Do you think it is still beneficial to provide falback for ZoomableImageSource.PainterDelegate in that scenario?

@saket
Copy link
Owner

saket commented Dec 10, 2024

Lol that is a funny side-effect of the fact that SubSamplingImage() displays a placeholder image generated by Coil. I guess we could change the default error reporter to not crash for situations like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants