Partial fix of a bug with ApngAnimator and system style change
Working on documentation
This commit is contained in:
parent
323623b5fa
commit
f52b9e4563
|
@ -17,8 +17,8 @@ import java.io.InputStream
|
|||
import java.util.*
|
||||
import java.util.zip.CRC32
|
||||
|
||||
// TODO REWRITE
|
||||
class APNGDisassembler {
|
||||
companion object {
|
||||
private var png: ArrayList<Byte>? = null
|
||||
private var cover: ArrayList<Byte>? = null
|
||||
private var delay = -1f
|
||||
|
@ -29,7 +29,8 @@ class APNGDisassembler {
|
|||
private var maxWidth = 0
|
||||
private var maxHeight = 0
|
||||
private var blendOp: Utils.Companion.BlendOp = Utils.Companion.BlendOp.APNG_BLEND_OP_SOURCE
|
||||
private var disposeOp: Utils.Companion.DisposeOp = Utils.Companion.DisposeOp.APNG_DISPOSE_OP_NONE
|
||||
private var disposeOp: Utils.Companion.DisposeOp =
|
||||
Utils.Companion.DisposeOp.APNG_DISPOSE_OP_NONE
|
||||
private var ihdr = IHDR()
|
||||
private var isApng = false
|
||||
|
||||
|
@ -103,7 +104,14 @@ class APNGDisassembler {
|
|||
// Add chunk body length
|
||||
ihdr.addAll(to4Bytes(ihdrOfApng.body.size).asList())
|
||||
// Add IHDR
|
||||
ihdrBody.addAll(byteArrayOf(0x49.toByte(), 0x48.toByte(), 0x44.toByte(), 0x52.toByte()).asList())
|
||||
ihdrBody.addAll(
|
||||
byteArrayOf(
|
||||
0x49.toByte(),
|
||||
0x48.toByte(),
|
||||
0x44.toByte(),
|
||||
0x52.toByte()
|
||||
).asList()
|
||||
)
|
||||
// Add the max width and height
|
||||
ihdrBody.addAll(to4Bytes(width).asList())
|
||||
ihdrBody.addAll(to4Bytes(height).asList())
|
||||
|
@ -178,7 +186,18 @@ class APNGDisassembler {
|
|||
crC32.update(iend, 0, iend.size)
|
||||
png?.addAll(iend.asList())
|
||||
png?.addAll(to4Bytes(crC32.value.toInt()).asList())
|
||||
apng.frames.add(Frame(png!!.toByteArray(), delay, xOffset, yOffset, blendOp, disposeOp, maxWidth, maxHeight))
|
||||
apng.frames.add(
|
||||
Frame(
|
||||
png!!.toByteArray(),
|
||||
delay,
|
||||
xOffset,
|
||||
yOffset,
|
||||
blendOp,
|
||||
disposeOp,
|
||||
maxWidth,
|
||||
maxHeight
|
||||
)
|
||||
)
|
||||
png = ArrayList()
|
||||
val fcTL = fcTL()
|
||||
fcTL.parse(byteArray)
|
||||
|
@ -317,4 +336,3 @@ class APNGDisassembler {
|
|||
isApng = false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -183,7 +183,7 @@ class ApngAnimator(private val context: Context?) {
|
|||
// Download PNG
|
||||
|
||||
val inputStream = file.inputStream()
|
||||
APNGDisassembler.disassemble(inputStream).also {
|
||||
APNGDisassembler().disassemble(inputStream).also {
|
||||
inputStream.close()
|
||||
if (it.isApng) {
|
||||
it.frames.also {frames ->
|
||||
|
@ -231,7 +231,7 @@ class ApngAnimator(private val context: Context?) {
|
|||
// Download PNG
|
||||
|
||||
val inputStream = context.contentResolver.openInputStream(uri)!!
|
||||
APNGDisassembler.disassemble(inputStream).also {
|
||||
APNGDisassembler().disassemble(inputStream).also {
|
||||
inputStream.close()
|
||||
if (it.isApng) {
|
||||
isApng = true
|
||||
|
@ -319,7 +319,8 @@ class ApngAnimator(private val context: Context?) {
|
|||
this@ApngAnimator.speed = speed
|
||||
scaleType = apngAnimatorOptions?.scaleType
|
||||
// Download PNG
|
||||
APNGDisassembler.disassemble(byteArray).frames.also { frames ->
|
||||
println(byteArray.size)
|
||||
APNGDisassembler().disassemble(byteArray).frames.also { frames ->
|
||||
draw(frames).apply {
|
||||
setupAnimationDrawableAndStart(this)
|
||||
}
|
||||
|
@ -391,7 +392,7 @@ class ApngAnimator(private val context: Context?) {
|
|||
this@ApngAnimator.speed = speed
|
||||
scaleType = apngAnimatorOptions?.scaleType
|
||||
// Download PNG
|
||||
APNGDisassembler.disassemble(byteArray).frames.also { frames ->
|
||||
APNGDisassembler().disassemble(byteArray).frames.also { frames ->
|
||||
draw(frames).apply {
|
||||
setupAnimationDrawableAndStart(this)
|
||||
}
|
||||
|
|
|
@ -8,12 +8,15 @@ import java.io.IOException
|
|||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
|
||||
// TODO DOCUMENTATION (MAYBE WIKI) FOR THE CACHE
|
||||
class Loader {
|
||||
companion object {
|
||||
/**
|
||||
* Download file from given url.
|
||||
* Download file from given url on the [Dispatchers.IO] scope.
|
||||
* @param url Url of the file to download.
|
||||
* @return [ByteArray] of the file.
|
||||
* @throws IOException thrown when retrieving the file.
|
||||
* @throws Exception when returned code of the [HttpURLConnection] is not 200 (OK).
|
||||
*/
|
||||
@Throws(IOException::class, Exception::class)
|
||||
suspend fun load(url: URL): ByteArray =
|
||||
|
|
|
@ -15,7 +15,6 @@ import kotlinx.coroutines.Dispatchers
|
|||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import oupson.apng.APNGDisassembler
|
||||
import oupson.apng.BuildConfig
|
||||
import oupson.apng.Loader
|
||||
import oupson.apng.chunks.IHDR
|
||||
|
@ -31,13 +30,23 @@ import java.util.zip.CRC32
|
|||
|
||||
class ApngDecoder {
|
||||
interface Callback {
|
||||
/**
|
||||
* Function called when the file was successfully decoded.
|
||||
* @param drawable Can be an [AnimationDrawable] if successful and an [AnimatedImageDrawable] if the image decoded is not an APNG but a gif. If it is not an animated image, it is a [Drawable].
|
||||
*/
|
||||
fun onSuccess(drawable: Drawable)
|
||||
|
||||
/**
|
||||
* Function called when something gone wrong.
|
||||
* @param error The problem.
|
||||
*/
|
||||
fun onError(error: java.lang.Exception)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "ApngDecoder"
|
||||
|
||||
// Paint used to clear the buffer
|
||||
private val clearPaint: Paint by lazy {
|
||||
Paint().apply {
|
||||
xfermode = PorterDuffXfermode(
|
||||
|
@ -52,11 +61,17 @@ class ApngDecoder {
|
|||
* @param inStream Input Stream to decode. Will be close at the end.
|
||||
* @param speed Optional parameter.
|
||||
* @param config Configuration applied to the bitmap added to the animation. Please note that the frame is decoded in ARGB_8888 and converted after, for the buffer.
|
||||
* @return [AnimationDrawable] if successful and an [AnimatedImageDrawable] if the image decoded is not an APNG but a gif. If it is not an animated image, it is a [Drawable].
|
||||
*/
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun decodeApng(context: Context, inStream: InputStream, speed: Float = 1f, config : Bitmap.Config = Bitmap.Config.ARGB_8888): Drawable {
|
||||
fun decodeApng(
|
||||
context: Context,
|
||||
inStream: InputStream,
|
||||
speed: Float = 1f,
|
||||
config: Bitmap.Config = Bitmap.Config.ARGB_8888
|
||||
): Drawable {
|
||||
val inputStream = BufferedInputStream(inStream)
|
||||
val bytes = ByteArray(8)
|
||||
inputStream.mark(8)
|
||||
|
@ -115,11 +130,11 @@ class ApngDecoder {
|
|||
crC32.update(iend, 0, iend.size)
|
||||
it.addAll(iend.asList())
|
||||
it.addAll(Utils.to4Bytes(crC32.value.toInt()).asList())
|
||||
APNGDisassembler.apng.cover = BitmapFactory.decodeByteArray(
|
||||
/**APNGDisassembler.apng.cover = BitmapFactory.decodeByteArray(
|
||||
it.toByteArray(),
|
||||
0,
|
||||
it.size
|
||||
)
|
||||
)*/ // TODO
|
||||
}
|
||||
png = ArrayList()
|
||||
val fcTL = fcTL()
|
||||
|
@ -198,7 +213,10 @@ class ApngDecoder {
|
|||
context.resources,
|
||||
if (btm.config != config) {
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.v(TAG, "Bitmap Config : ${btm.config}, Config : $config")
|
||||
Log.v(
|
||||
TAG,
|
||||
"Bitmap Config : ${btm.config}, Config : $config"
|
||||
)
|
||||
btm.copy(config, btm.isMutable)
|
||||
} else {
|
||||
btm
|
||||
|
@ -306,7 +324,10 @@ class ApngDecoder {
|
|||
context.resources,
|
||||
if (btm.config != config) {
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.v(TAG, "Bitmap Config : ${btm.config}, Config : $config")
|
||||
Log.v(
|
||||
TAG,
|
||||
"Bitmap Config : ${btm.config}, Config : $config"
|
||||
)
|
||||
btm.copy(config, btm.isMutable)
|
||||
} else {
|
||||
btm
|
||||
|
@ -478,10 +499,16 @@ class ApngDecoder {
|
|||
* @param file File to decode.
|
||||
* @param speed Optional parameter.
|
||||
* @param config Configuration applied to the bitmap added to the animation. Please note that the frame is decoded in ARGB_8888 and converted after, for the buffer.
|
||||
* @return [AnimationDrawable] if successful and an [AnimatedImageDrawable] if the image decoded is not an APNG but a gif. If it is not an animated image, it is a [Drawable].
|
||||
*/
|
||||
@Suppress("unused")
|
||||
@JvmStatic
|
||||
fun decodeApng(context: Context, file: File, speed: Float = 1f, config : Bitmap.Config = Bitmap.Config.ARGB_8888): Drawable =
|
||||
fun decodeApng(
|
||||
context: Context,
|
||||
file: File,
|
||||
speed: Float = 1f,
|
||||
config: Bitmap.Config = Bitmap.Config.ARGB_8888
|
||||
): Drawable =
|
||||
decodeApng(
|
||||
context,
|
||||
FileInputStream(file), speed, config
|
||||
|
@ -493,12 +520,17 @@ class ApngDecoder {
|
|||
* @param uri Uri to open.
|
||||
* @param speed Optional parameter.
|
||||
* @param config Configuration applied to the bitmap added to the animation. Please note that the frame is decoded in ARGB_8888 and converted after, for the buffer.
|
||||
* @return [AnimationDrawable] if successful and an [AnimatedImageDrawable] if the image decoded is not an APNG but a gif.
|
||||
*/
|
||||
@Suppress("unused")
|
||||
@JvmStatic
|
||||
fun decodeApng(context: Context, uri: Uri, speed: Float = 1f, config : Bitmap.Config = Bitmap.Config.ARGB_8888): Drawable {
|
||||
val inputStream = context.contentResolver.openInputStream(uri)
|
||||
?: throw Exception("Failed to open InputStream, InputStream is null")
|
||||
fun decodeApng(
|
||||
context: Context,
|
||||
uri: Uri,
|
||||
speed: Float = 1f,
|
||||
config: Bitmap.Config = Bitmap.Config.ARGB_8888
|
||||
): Drawable {
|
||||
val inputStream = context.contentResolver.openInputStream(uri)!!
|
||||
return decodeApng(
|
||||
context,
|
||||
inputStream,
|
||||
|
@ -513,10 +545,16 @@ class ApngDecoder {
|
|||
* @param res Resource to decode.
|
||||
* @param speed Optional parameter.
|
||||
* @param config Configuration applied to the bitmap added to the animation. Please note that the frame is decoded in ARGB_8888 and converted after, for the buffer.
|
||||
* @return [AnimationDrawable] if successful and an [AnimatedImageDrawable] if the image decoded is not an APNG but a gif.
|
||||
*/
|
||||
@Suppress("unused")
|
||||
@JvmStatic
|
||||
fun decodeApng(context: Context, @RawRes res: Int, speed: Float = 1f, config : Bitmap.Config = Bitmap.Config.ARGB_8888): Drawable =
|
||||
fun decodeApng(
|
||||
context: Context,
|
||||
@RawRes res: Int,
|
||||
speed: Float = 1f,
|
||||
config: Bitmap.Config = Bitmap.Config.ARGB_8888
|
||||
): Drawable =
|
||||
decodeApng(
|
||||
context,
|
||||
context.resources.openRawResource(res),
|
||||
|
@ -530,10 +568,16 @@ class ApngDecoder {
|
|||
* @param url URL to decode.
|
||||
* @param speed Optional parameter.
|
||||
* @param config Configuration applied to the bitmap added to the animation. Please note that the frame is decoded in ARGB_8888 and converted after, for the buffer.
|
||||
* @return [AnimationDrawable] if successful and an [AnimatedImageDrawable] if the image decoded is not an APNG but a gif.
|
||||
*/
|
||||
@Suppress("unused")
|
||||
@JvmStatic
|
||||
suspend fun decodeApng(context: Context, url: URL, speed: Float = 1f, config : Bitmap.Config = Bitmap.Config.ARGB_8888) =
|
||||
suspend fun decodeApng(
|
||||
context: Context,
|
||||
url: URL,
|
||||
speed: Float = 1f,
|
||||
config: Bitmap.Config = Bitmap.Config.ARGB_8888
|
||||
) =
|
||||
withContext(Dispatchers.IO) {
|
||||
decodeApng(
|
||||
context,
|
||||
|
@ -608,8 +652,7 @@ class ApngDecoder {
|
|||
callback: Callback? = null,
|
||||
config: Bitmap.Config = Bitmap.Config.ARGB_8888
|
||||
) {
|
||||
val inputStream = context.contentResolver.openInputStream(uri)
|
||||
?: throw Exception("Failed to open InputStream, InputStream is null")
|
||||
val inputStream = context.contentResolver.openInputStream(uri)!!
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val drawable =
|
||||
|
|
|
@ -11,6 +11,8 @@ import java.io.OutputStream
|
|||
import java.util.zip.CRC32
|
||||
|
||||
// TODO DOCUMENTATION
|
||||
// TODO BITMAP ENCODING
|
||||
// TODO BUFFER AND BUFFER DEACTIVATION WHEN BITMAP CONFIG DOES NOT CONTAIN AN ALPHA CHANNEL
|
||||
class ApngEncoder(
|
||||
private val outputStream: OutputStream,
|
||||
private val width : Int,
|
||||
|
|
Loading…
Reference in New Issue