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

fix gif also play when config turned off #159

Merged
merged 3 commits into from
May 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
package com.seiko.imageloader.component.decoder

import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Movie
import androidx.core.graphics.createBitmap
import com.seiko.imageloader.option.Options
import com.seiko.imageloader.toImage
import com.seiko.imageloader.util.FrameDelayRewritingSource
Expand Down Expand Up @@ -36,20 +38,30 @@ class GifDecoder private constructor(
} else {
bufferSource
}
val movie: Movie? = bufferedSource.use { Movie.decodeStream(it.inputStream()) }

val movie: Movie? = bufferedSource.use { Movie.decodeStream(it.inputStream()) }
check(movie != null && movie.width() > 0 && movie.height() > 0) { "Failed to decode GIF." }

val config = options.config.toBitmapConfig()
val movieConfig = when {
// movie.isOpaque && options.allowRgb565 -> Bitmap.Config.RGB_565
config.isHardware -> Bitmap.Config.ARGB_8888
else -> config
}

if (!options.playAnimate) {
val bitmap = createBitmap(movie.width(), movie.height(), movieConfig)
val canvas = Canvas(bitmap)
movie.draw(canvas, 0f, 0f)
return@runInterruptible DecodeResult.Bitmap(
bitmap = bitmap,
)
}

val drawable = MovieDrawable(
movie = movie,
config = when {
// movie.isOpaque && options.allowRgb565 -> Bitmap.Config.RGB_565
config.isHardware -> Bitmap.Config.ARGB_8888
else -> config
},
config = movieConfig,
scale = options.scale,
playAnimate = options.playAnimate,
)
drawable.setRepeatCount(options.repeatCount)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.graphics.drawable.AnimatedImageDrawable
import android.graphics.drawable.Drawable
import android.os.Build.VERSION.SDK_INT
import androidx.annotation.RequiresApi
import androidx.core.graphics.decodeBitmap
import androidx.core.graphics.decodeDrawable
import com.seiko.imageloader.component.fetcher.AssetUriFetcher
import com.seiko.imageloader.component.fetcher.ContentUriFetcher
Expand Down Expand Up @@ -45,20 +46,34 @@ class ImageDecoderDecoder private constructor(

override suspend fun decode(): DecodeResult {
var imageDecoder: ImageDecoder? = null
val drawable = try {
source.toImageDecoderSource().decodeDrawable { _, _ ->
// Capture the image decoder to manually close it later.
imageDecoder = this
val decoder = source.toImageDecoderSource()
return if (!options.playAnimate) {
val bitmap = try {
decoder.decodeBitmap { _, _ ->
imageDecoder = this
}
} finally {
imageDecoder?.close()
}
DecodeResult.Bitmap(
bitmap = bitmap,
)
} else {
val drawable = try {
decoder.decodeDrawable { _, _ ->
// Capture the image decoder to manually close it later.
imageDecoder = this

// Configure any other attributes.
configureImageDecoderProperties()
// Configure any other attributes.
configureImageDecoderProperties()
}
} finally {
imageDecoder?.close()
}
} finally {
imageDecoder?.close()
DecodeResult.Image(
image = wrapDrawable(drawable).toImage(),
)
}
return DecodeResult.Image(
image = wrapDrawable(drawable).toImage(),
)
}

private fun wrapBufferedSource(channel: BufferedSource): BufferedSource {
Expand Down Expand Up @@ -139,7 +154,7 @@ class ImageDecoderDecoder private constructor(
// }

// Wrap AnimatedImageDrawable in a ScaleDrawable so it always scales to fill its bounds.
return ScaleDrawable(baseDrawable, options.scale, options.playAnimate)
return ScaleDrawable(baseDrawable, options.scale)
}

class Factory @JvmOverloads constructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ internal class MovieDrawable @JvmOverloads constructor(
private val movie: Movie,
val config: Bitmap.Config = Bitmap.Config.ARGB_8888,
val scale: Scale = Scale.FIT,
private val playAnimate: Boolean = false,
) : Drawable(), Animatable2Compat {

private val paint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG)
Expand Down Expand Up @@ -250,8 +249,6 @@ internal class MovieDrawable @JvmOverloads constructor(
override fun isRunning() = isRunning

override fun start() {
if (!playAnimate) return

if (isRunning) return
isRunning = true

Expand All @@ -263,8 +260,6 @@ internal class MovieDrawable @JvmOverloads constructor(
}

override fun stop() {
if (!playAnimate) return

if (!isRunning) return
isRunning = false

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import kotlin.math.roundToInt
internal class ScaleDrawable @JvmOverloads constructor(
val child: Drawable,
val scale: Scale = Scale.FIT,
private val playAnimate: Boolean = false,
) : Drawable(), Drawable.Callback, Animatable {

private var childDx = 0f
Expand Down Expand Up @@ -110,10 +109,10 @@ internal class ScaleDrawable @JvmOverloads constructor(
override fun isRunning() = child is Animatable && child.isRunning

override fun start() {
if (child is Animatable && playAnimate) child.start()
if (child is Animatable) child.start()
}

override fun stop() {
if (child is Animatable && playAnimate) child.stop()
if (child is Animatable) child.stop()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,32 @@ import com.seiko.imageloader.util.isGif
import kotlinx.coroutines.CoroutineScope
import okio.BufferedSource
import okio.use
import org.jetbrains.skia.Bitmap
import org.jetbrains.skia.Codec
import org.jetbrains.skia.Data
import org.jetbrains.skia.Image

class GifDecoder private constructor(
private val source: BufferedSource,
private val imageScope: CoroutineScope,
private val options: Options,
) : Decoder {
override suspend fun decode(): DecodeResult {
if (!options.playAnimate) {
val image = source.use {
Image.makeFromEncoded(it.readByteArray())
}
return DecodeResult.Bitmap(
bitmap = Bitmap.makeFromImage(image),
)
}
val codec = source.use {
Codec.makeFromData(Data.makeFromBytes(it.readByteArray()))
}
return DecodeResult.Painter(
painter = GifPainter(
codec = codec,
imageScope = imageScope,
playAnimate = options.playAnimate,
repeatCount = options.repeatCount,
),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import kotlin.time.Duration.Companion.milliseconds
internal class GifPainter(
private val codec: Codec,
private val imageScope: CoroutineScope,
private val playAnimate: Boolean = true,
private val repeatCount: Int = Options.REPEAT_INFINITE,
) : Painter(), RememberObserver {

Expand All @@ -50,7 +49,7 @@ internal class GifPainter(
yield()
when {
codec.framesInfo.isEmpty() -> Unit
codec.framesInfo.size == 1 || !playAnimate -> {
codec.framesInfo.size == 1 -> {
emit(getImageBitmap(codec, 0))
}
else -> {
Expand Down