mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-26 20:55:10 +00:00
Fix PNG animations.
Adds an `InputStreamFactory` APNG decoder so images animate correctly when loaded via the new `DecryptableUriStreamLoader`.
This commit is contained in:
44
app/src/main/java/org/thoughtcrime/securesms/glide/cache/ApngStreamFactoryDecoder.kt
vendored
Normal file
44
app/src/main/java/org/thoughtcrime/securesms/glide/cache/ApngStreamFactoryDecoder.kt
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.glide.cache
|
||||
|
||||
import com.bumptech.glide.load.Options
|
||||
import com.bumptech.glide.load.ResourceDecoder
|
||||
import com.bumptech.glide.load.engine.Resource
|
||||
import org.signal.core.util.StreamUtil
|
||||
import org.signal.glide.apng.decode.APNGDecoder
|
||||
import org.signal.glide.apng.decode.APNGParser
|
||||
import org.signal.glide.common.io.StreamReader
|
||||
import org.thoughtcrime.securesms.glide.GlideStreamConfig
|
||||
import org.thoughtcrime.securesms.mms.InputStreamFactory
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
/**
|
||||
* A variant of [ApngStreamCacheDecoder] that decodes animated PNGs from [org.thoughtcrime.securesms.mms.InputStreamFactory] sources.
|
||||
*/
|
||||
class ApngStreamFactoryDecoder(
|
||||
private val byteBufferDecoder: ResourceDecoder<ByteBuffer, APNGDecoder>
|
||||
) : ResourceDecoder<InputStreamFactory, APNGDecoder> {
|
||||
|
||||
override fun handles(source: InputStreamFactory, options: Options): Boolean {
|
||||
return if (options.get(ApngOptions.ANIMATE) == true) {
|
||||
return APNGParser.isAPNG(LimitedReader(StreamReader(source.create()), GlideStreamConfig.markReadLimitBytes))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
override fun decode(
|
||||
source: InputStreamFactory,
|
||||
width: Int,
|
||||
height: Int,
|
||||
options: Options
|
||||
): Resource<APNGDecoder>? {
|
||||
val data = StreamUtil.readFully(source.create())
|
||||
val byteBuffer = ByteBuffer.wrap(data)
|
||||
return byteBufferDecoder.decode(byteBuffer, width, height, options)
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import org.thoughtcrime.securesms.glide.OkHttpUrlLoader;
|
||||
import org.thoughtcrime.securesms.glide.cache.ApngBufferCacheDecoder;
|
||||
import org.thoughtcrime.securesms.glide.cache.ApngFrameDrawableTranscoder;
|
||||
import org.thoughtcrime.securesms.glide.cache.ApngStreamCacheDecoder;
|
||||
import org.thoughtcrime.securesms.glide.cache.ApngStreamFactoryDecoder;
|
||||
import org.thoughtcrime.securesms.glide.cache.EncryptedApngCacheEncoder;
|
||||
import org.thoughtcrime.securesms.glide.cache.EncryptedBitmapResourceEncoder;
|
||||
import org.thoughtcrime.securesms.glide.cache.EncryptedCacheDecoder;
|
||||
@@ -78,10 +79,12 @@ public class SignalGlideComponents implements RegisterGlideComponents {
|
||||
registry.prepend(Bitmap.class, new EncryptedBitmapResourceEncoder(secret));
|
||||
registry.prepend(BitmapDrawable.class, new BitmapDrawableEncoder(glide.getBitmapPool(), encryptedBitmapResourceEncoder));
|
||||
|
||||
ApngBufferCacheDecoder apngBufferCacheDecoder = new ApngBufferCacheDecoder();
|
||||
ApngStreamCacheDecoder apngStreamCacheDecoder = new ApngStreamCacheDecoder(apngBufferCacheDecoder);
|
||||
ApngBufferCacheDecoder apngBufferCacheDecoder = new ApngBufferCacheDecoder();
|
||||
ApngStreamCacheDecoder apngStreamCacheDecoder = new ApngStreamCacheDecoder(apngBufferCacheDecoder);
|
||||
ApngStreamFactoryDecoder apngStreamFactoryDecoder = new ApngStreamFactoryDecoder(apngBufferCacheDecoder);
|
||||
|
||||
registry.prepend(InputStream.class, APNGDecoder.class, apngStreamCacheDecoder);
|
||||
registry.prepend(InputStreamFactory.class, APNGDecoder.class, apngStreamFactoryDecoder);
|
||||
registry.prepend(ByteBuffer.class, APNGDecoder.class, apngBufferCacheDecoder);
|
||||
registry.prepend(APNGDecoder.class, new EncryptedApngCacheEncoder(secret));
|
||||
registry.prepend(File.class, APNGDecoder.class, new EncryptedCacheDecoder<>(secret, apngStreamCacheDecoder));
|
||||
|
||||
Reference in New Issue
Block a user