Add ApngAnimatorOptions and move oupson.apng.Utils to oupson.apng.utils.Utils

This commit is contained in:
oupson 2018-11-17 20:45:49 +01:00
parent 351ee29639
commit 6c46efc929
8 changed files with 68 additions and 30 deletions

View File

@ -1,12 +1,13 @@
package oupson.apng
import android.graphics.BitmapFactory
import oupson.apng.Utils.Companion.isApng
import oupson.apng.Utils.Companion.pngSignature
import oupson.apng.Utils.Companion.to4Bytes
import oupson.apng.utils.Utils.Companion.isApng
import oupson.apng.utils.Utils.Companion.pngSignature
import oupson.apng.utils.Utils.Companion.to4Bytes
import oupson.apng.chunks.IHDR
import oupson.apng.chunks.fcTL
import oupson.apng.exceptions.NotApngException
import oupson.apng.utils.Utils
import java.util.zip.CRC32
class APNGDisassembler {

View File

@ -3,14 +3,15 @@ package oupson.apng
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import oupson.apng.ImageUtils.PnnQuantizer
import oupson.apng.Utils.Companion.getBlend_op
import oupson.apng.Utils.Companion.getDispose_op
import oupson.apng.Utils.Companion.pngSignature
import oupson.apng.Utils.Companion.to2Bytes
import oupson.apng.Utils.Companion.to4Bytes
import oupson.apng.Utils.Companion.toByteArray
import oupson.apng.utils.Utils.Companion.getBlend_op
import oupson.apng.utils.Utils.Companion.getDispose_op
import oupson.apng.utils.Utils.Companion.pngSignature
import oupson.apng.utils.Utils.Companion.to2Bytes
import oupson.apng.utils.Utils.Companion.to4Bytes
import oupson.apng.utils.Utils.Companion.toByteArray
import oupson.apng.chunks.IDAT
import oupson.apng.exceptions.NoFrameException
import oupson.apng.utils.Utils
import java.util.zip.CRC32

View File

@ -6,10 +6,13 @@ import android.graphics.*
import android.net.Uri
import android.widget.ImageView
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.image
import org.jetbrains.anko.runOnUiThread
import org.jetbrains.anko.uiThread
import oupson.apng.Utils.Companion.isApng
import oupson.apng.utils.Utils.Companion.isApng
import oupson.apng.exceptions.NotApngException
import oupson.apng.utils.ApngAnimatorOptions
import oupson.apng.utils.Utils
import java.io.File
import java.net.URL
@ -41,6 +44,7 @@ class ApngAnimator(private val context: Context) {
private var doOnLoaded : (ApngAnimator) -> Unit = {}
private var AnimationLoopListener : () -> Unit = {}
private var duration : ArrayList<Float>? = null
private var scaleType : ImageView.ScaleType? = null
var isApng = false
var loadNotApng = true
@ -74,7 +78,7 @@ class ApngAnimator(private val context: Context) {
* @param speed The speed
* @throws NotApngException
*/
fun load(file: File, speed: Float? = null) {
fun load(file: File, speed: Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) {
doAsync {
val bytes = file.readBytes()
if (isApng(bytes)) {
@ -84,10 +88,12 @@ class ApngAnimator(private val context: Context) {
APNGDisassembler.disassemble(file.readBytes()).frames.apply {
draw(this)
}
scaleType = apngAnimatorOptions?.scaleType
setupAnimationDrawableAndStart()
} else {
if (loadNotApng) {
context.runOnUiThread {
imageView?.scaleType = this@ApngAnimator.scaleType ?: ImageView.ScaleType.FIT_CENTER
imageView?.setImageBitmap(BitmapFactory.decodeByteArray(bytes, 0, bytes.size))
}
} else {
@ -103,7 +109,7 @@ class ApngAnimator(private val context: Context) {
* @param speed The speed
* @throws NotApngException
*/
fun load(uri : Uri, speed: Float? = null) {
fun load(uri : Uri, speed: Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) {
doAsync {
val bytes = context.contentResolver.openInputStream(uri).readBytes()
if (isApng(bytes)) {
@ -113,10 +119,12 @@ class ApngAnimator(private val context: Context) {
APNGDisassembler.disassemble(bytes).frames.apply {
draw(this)
}
scaleType = apngAnimatorOptions?.scaleType
setupAnimationDrawableAndStart()
} else {
if (loadNotApng) {
context.runOnUiThread {
imageView?.scaleType = this@ApngAnimator.scaleType ?: ImageView.ScaleType.FIT_CENTER
imageView?.setImageBitmap(BitmapFactory.decodeByteArray(bytes, 0, bytes.size))
}
} else {
@ -132,7 +140,7 @@ class ApngAnimator(private val context: Context) {
* @param speed The speed
* @throws NotApngException
*/
fun loadUrl(url: URL, speed: Float? = null) {
fun loadUrl(url: URL, speed: Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) {
doAsync(exceptionHandler = { e -> e.printStackTrace() }) {
this@ApngAnimator.speed = speed
// Download PNG
@ -142,10 +150,12 @@ class ApngAnimator(private val context: Context) {
APNGDisassembler.disassemble(this).frames.apply {
draw(this)
}
scaleType = apngAnimatorOptions?.scaleType
setupAnimationDrawableAndStart()
} else {
if (loadNotApng) {
context.runOnUiThread {
imageView?.scaleType = this@ApngAnimator.scaleType ?: ImageView.ScaleType.FIT_CENTER
imageView?.setImageBitmap(BitmapFactory.decodeByteArray(this@apply, 0, this@apply.size))
}
} else {
@ -165,7 +175,7 @@ class ApngAnimator(private val context: Context) {
* @param speed The speed
* @throws NotApngException
*/
fun load(byteArray: ByteArray, speed: Float? = null) {
fun load(byteArray: ByteArray, speed: Float? = null, apngAnimatorOptions: ApngAnimatorOptions?) {
doAsync {
this@ApngAnimator.speed = speed
if (isApng(byteArray)) {
@ -173,10 +183,12 @@ class ApngAnimator(private val context: Context) {
APNGDisassembler.disassemble(byteArray).frames.apply {
draw(this)
}
scaleType = apngAnimatorOptions?.scaleType
setupAnimationDrawableAndStart()
} else {
if (loadNotApng) {
context.runOnUiThread {
imageView?.scaleType = this@ApngAnimator.scaleType ?: ImageView.ScaleType.FIT_CENTER
imageView?.setImageBitmap(BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size))
}
} else {
@ -192,18 +204,18 @@ class ApngAnimator(private val context: Context) {
* @param speed The speed
* @throws NotApngException
*/
fun load(string: String, speed : Float? = null) {
fun load(string: String, speed : Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) {
doAsync {
this@ApngAnimator.speed = speed
if (string.contains("http") || string.contains("https")) {
val url = URL(string)
loadUrl(url, speed)
loadUrl(url, speed, apngAnimatorOptions)
} else if (File(string).exists()) {
var pathToLoad = if (string.startsWith("content://")) string else "file://$string"
pathToLoad = pathToLoad.replace("%", "%25").replace("#", "%23")
val bytes = context.contentResolver.openInputStream(Uri.parse(pathToLoad)).readBytes()
if (isApng(bytes)) {
load(bytes, speed)
load(bytes, speed, apngAnimatorOptions)
} else {
if (loadNotApng) {
context.runOnUiThread {
@ -226,10 +238,12 @@ class ApngAnimator(private val context: Context) {
activeAnimation = anim
uiThread {
imageView?.apply {
scaleType = this@ApngAnimator.scaleType ?: ImageView.ScaleType.FIT_CENTER
setImageBitmap(generatedFrame[0])
setImageDrawable(activeAnimation)
}
activeAnimation?.start()
isPlaying = true
doOnLoaded(this@ApngAnimator)
}
}
@ -343,6 +357,20 @@ class ApngAnimator(private val context: Context) {
doOnLoaded = f
}
fun centerCrop(boolean: Boolean) {
if (isApng) {
if (boolean) {
imageView?.scaleType = ImageView.ScaleType.CENTER_CROP
pause()
play()
} else {
imageView?.scaleType = null
pause()
play()
}
}
}
/**
* Converts the generated frames into an animation drawable ([CustomAnimationDrawable])
* in the APNG will be used instead.

View File

@ -1,11 +1,12 @@
package oupson.apng
import android.graphics.BitmapFactory
import oupson.apng.Utils.Companion.isPng
import oupson.apng.Utils.Companion.toByteArray
import oupson.apng.utils.Utils.Companion.isPng
import oupson.apng.utils.Utils.Companion.toByteArray
import oupson.apng.chunks.IDAT
import oupson.apng.chunks.IHDR
import oupson.apng.exceptions.NotPngException
import oupson.apng.utils.Utils
/**
* A frame for an animated png

View File

@ -1,8 +1,8 @@
package oupson.apng.chunks
import oupson.apng.Utils
import oupson.apng.Utils.Companion.getBlend_op
import oupson.apng.Utils.Companion.getDispose_op
import oupson.apng.utils.Utils
import oupson.apng.utils.Utils.Companion.getBlend_op
import oupson.apng.utils.Utils.Companion.getDispose_op
class fcTL(byteArray: ByteArray) {

View File

@ -0,0 +1,5 @@
package oupson.apng.utils
import android.widget.ImageView
class ApngAnimatorOptions(val scaleType : ImageView.ScaleType? = ImageView.ScaleType.FIT_CENTER)

View File

@ -1,4 +1,4 @@
package oupson.apng
package oupson.apng.utils
import android.graphics.Bitmap
import android.graphics.Canvas
@ -69,9 +69,9 @@ class Utils {
*/
fun getDispose_op(int: Int) : dispose_op {
return when(int) {
0 -> Companion.dispose_op.APNG_DISPOSE_OP_NONE
1 -> Companion.dispose_op.APNG_DISPOSE_OP_BACKGROUND
2 -> Companion.dispose_op.APNG_DISPOSE_OP_PREVIOUS
0 -> dispose_op.APNG_DISPOSE_OP_NONE
1 -> dispose_op.APNG_DISPOSE_OP_BACKGROUND
2 -> dispose_op.APNG_DISPOSE_OP_PREVIOUS
else -> dispose_op.APNG_DISPOSE_OP_NONE
}
}
@ -98,10 +98,10 @@ class Utils {
* @param int Int of the blend_op
* @return A blend_op
*/
fun getBlend_op(int : Int) : blend_op{
fun getBlend_op(int : Int) : blend_op {
return when(int) {
0 -> Companion.blend_op.APNG_BLEND_OP_SOURCE
1 -> Companion.blend_op.APNG_BLEND_OP_OVER
0 -> blend_op.APNG_BLEND_OP_SOURCE
1 -> blend_op.APNG_BLEND_OP_OVER
else -> blend_op.APNG_BLEND_OP_SOURCE
}
}

View File

@ -7,9 +7,11 @@ import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
import android.support.v7.app.AppCompatActivity
import android.view.View
import android.widget.ImageView
import kotlinx.android.synthetic.main.activity_main2.*
import org.jetbrains.anko.sdk27.coroutines.onClick
import oupson.apng.ApngAnimator
import oupson.apng.utils.ApngAnimatorOptions
class Main2Activity : AppCompatActivity() {
@ -40,7 +42,7 @@ class Main2Activity : AppCompatActivity() {
fun load() {
val animator = ApngAnimator(applicationContext).loadInto(imageView3)
val uri = intent.data
animator.load(uri)
animator.load(uri, null, ApngAnimatorOptions(ImageView.ScaleType.CENTER_CROP))
imageView3.onClick {
try {
if (animator.isPlaying) {