parent
cefb4ca9f4
commit
08d5d307c7
Binary file not shown.
|
@ -5,7 +5,7 @@ android {
|
|||
compileSdkVersion 27
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 26
|
||||
targetSdkVersion 27
|
||||
versionCode 1
|
||||
versionName "1.0.8"
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import oupson.apng.chunks.fcTL
|
|||
import oupson.apng.exceptions.NotApngException
|
||||
import oupson.apng.utils.Utils
|
||||
import oupson.apng.utils.Utils.Companion.isApng
|
||||
import oupson.apng.utils.Utils.Companion.parseLength
|
||||
import oupson.apng.utils.Utils.Companion.pngSignature
|
||||
import oupson.apng.utils.Utils.Companion.to4Bytes
|
||||
import java.util.*
|
||||
|
@ -24,12 +25,17 @@ class APNGDisassembler {
|
|||
private var maxHeight = 0
|
||||
private var blend_op: Utils.Companion.blend_op = Utils.Companion.blend_op.APNG_BLEND_OP_SOURCE
|
||||
private var dispose_op: Utils.Companion.dispose_op = Utils.Companion.dispose_op.APNG_DISPOSE_OP_NONE
|
||||
var apng: Apng = Apng()
|
||||
private val ihdr = IHDR()
|
||||
|
||||
var apng: Apng = Apng()
|
||||
/**
|
||||
* Disassemble an Apng file
|
||||
* @param byteArray The Byte Array of the file
|
||||
* @return The apng decoded
|
||||
*/
|
||||
fun disassemble(byteArray: ByteArray) : Apng {
|
||||
if (isApng(byteArray)) {
|
||||
apng = Apng()
|
||||
ihdr.parseIHDR(byteArray)
|
||||
ihdr.parse(byteArray)
|
||||
maxWidth = ihdr.pngWidth
|
||||
maxHeight = ihdr.pngHeight
|
||||
var cursor = 8
|
||||
|
@ -44,20 +50,12 @@ class APNGDisassembler {
|
|||
}
|
||||
}
|
||||
|
||||
private fun parseLength(byteArray: ByteArray) : Int {
|
||||
var lengthString = ""
|
||||
byteArray.forEach {
|
||||
lengthString += String.format("%02x", it)
|
||||
}
|
||||
return lengthString.toLong(16).toInt()
|
||||
}
|
||||
|
||||
private fun generateIhdr(ihdrOfApng: IHDR, width : Int, height : Int) : ByteArray {
|
||||
val ihdr = ArrayList<Byte>()
|
||||
// We need a body var to know body length and generate crc
|
||||
val ihdrBody = ArrayList<Byte>()
|
||||
// Add chunk body length
|
||||
ihdr.addAll(to4Bytes(ihdrOfApng.ihdrCorps.size).toList())
|
||||
ihdr.addAll(to4Bytes(ihdrOfApng.body.size).toList())
|
||||
// Add IHDR
|
||||
ihdrBody.addAll(byteArrayOf(0x49.toByte(), 0x48.toByte(), 0x44.toByte(), 0x52.toByte()).toList())
|
||||
// Add the max width and height
|
||||
|
@ -65,7 +63,7 @@ class APNGDisassembler {
|
|||
ihdrBody.addAll(to4Bytes(height).toList())
|
||||
// Add complicated stuff like depth color ...
|
||||
// If you want correct png you need same parameters. Good solution is to create new png.
|
||||
ihdrBody.addAll(ihdrOfApng.ihdrCorps.copyOfRange(8, 13).toList())
|
||||
ihdrBody.addAll(ihdrOfApng.body.copyOfRange(8, 13).toList())
|
||||
// Generate CRC
|
||||
val crC32 = CRC32()
|
||||
crC32.update(ihdrBody.toByteArray(), 0, ihdrBody.size)
|
||||
|
@ -91,9 +89,9 @@ class APNGDisassembler {
|
|||
it.addAll(to4Bytes(crC32.value.toInt()).toList())
|
||||
apng.cover = BitmapFactory.decodeByteArray(it.toByteArray(), 0, it.size)
|
||||
}
|
||||
|
||||
png = ArrayList()
|
||||
val fcTL = fcTL(byteArray)
|
||||
val fcTL = fcTL()
|
||||
fcTL.parse(byteArray)
|
||||
delay = fcTL.delay
|
||||
yOffset = fcTL.y_offset
|
||||
xOffset = fcTL.x_offset
|
||||
|
@ -103,11 +101,9 @@ class APNGDisassembler {
|
|||
val height = fcTL.pngHeight
|
||||
png!!.addAll(pngSignature.toList())
|
||||
png!!.addAll(generateIhdr(ihdr, width, height).toList())
|
||||
|
||||
plte?.let {
|
||||
png!!.addAll(it.toList())
|
||||
}
|
||||
|
||||
tnrs?.let {
|
||||
png!!.addAll(it.toList())
|
||||
}
|
||||
|
@ -122,15 +118,12 @@ class APNGDisassembler {
|
|||
png!!.addAll(iend.toList())
|
||||
png!!.addAll(to4Bytes(crC32.value.toInt()).toList())
|
||||
apng.frames.add(Frame(png!!.toByteArray(), delay, xOffset, yOffset, maxWidth, maxHeight, blend_op, dispose_op))
|
||||
|
||||
png = ArrayList()
|
||||
|
||||
val fcTL = fcTL(byteArray)
|
||||
val fcTL = fcTL()
|
||||
fcTL.parse(byteArray)
|
||||
delay = fcTL.delay
|
||||
|
||||
yOffset = fcTL.y_offset
|
||||
xOffset = fcTL.x_offset
|
||||
|
||||
blend_op = fcTL.blend_op
|
||||
dispose_op = fcTL.dispose_op
|
||||
val width = fcTL.pngWidth
|
||||
|
@ -140,7 +133,6 @@ class APNGDisassembler {
|
|||
plte?.let {
|
||||
png!!.addAll(it.toList())
|
||||
}
|
||||
|
||||
tnrs?.let {
|
||||
png!!.addAll(it.toList())
|
||||
}
|
||||
|
|
|
@ -14,12 +14,10 @@ import oupson.apng.utils.Utils.Companion.to4Bytes
|
|||
import oupson.apng.utils.Utils.Companion.toByteArray
|
||||
import java.util.zip.CRC32
|
||||
|
||||
|
||||
/**
|
||||
* Create an APNG file
|
||||
*/
|
||||
class Apng {
|
||||
|
||||
var maxWidth : Int? = null
|
||||
var maxHeight : Int? = null
|
||||
|
||||
|
@ -226,7 +224,7 @@ class Apng {
|
|||
// Add cover image : Not part of animation
|
||||
// region IDAT
|
||||
val idat = IDAT()
|
||||
idat.parseIDAT(toByteArray(cover!!))
|
||||
idat.parse(toByteArray(cover!!))
|
||||
idat.IDATBody.forEach {
|
||||
val idatByteArray = ArrayList<Byte>()
|
||||
framesByte.addAll(to4Bytes(it.size).toList())
|
||||
|
@ -427,7 +425,7 @@ class Apng {
|
|||
}
|
||||
|
||||
// Add chunk body length
|
||||
ihdr.addAll(to4Bytes(frames[0].ihdr.ihdrCorps.size).toList())
|
||||
ihdr.addAll(to4Bytes(frames[0].ihdr.body.size).toList())
|
||||
// Add IHDR
|
||||
ihdr_body.addAll(byteArrayOf(0x49.toByte(), 0x48.toByte(), 0x44.toByte(), 0x52.toByte()).toList())
|
||||
|
||||
|
@ -437,7 +435,7 @@ class Apng {
|
|||
|
||||
// Add complicated stuff like depth color ...
|
||||
// If you want correct png you need same parameters. Good solution is to create new png.
|
||||
ihdr_body.addAll(frames[0].ihdr.ihdrCorps.copyOfRange(8, 13).toList())
|
||||
ihdr_body.addAll(frames[0].ihdr.body.copyOfRange(8, 13).toList())
|
||||
|
||||
// Generate CRC
|
||||
val crC32 = CRC32()
|
||||
|
|
|
@ -39,12 +39,14 @@ class ApngAnimator(private val context: Context) {
|
|||
private var anim: CustomAnimationDrawable? = null
|
||||
private var activeAnimation: CustomAnimationDrawable? = null
|
||||
private var doOnLoaded : (ApngAnimator) -> Unit = {}
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
private var AnimationLoopListener : () -> Unit = {}
|
||||
private var duration : ArrayList<Float>? = null
|
||||
private var scaleType : ImageView.ScaleType? = null
|
||||
|
||||
var isApng = false
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
var loadNotApng = true
|
||||
|
||||
private val sharedPreferences : SharedPreferences = context.getSharedPreferences("apngAnimator", Context.MODE_PRIVATE)
|
||||
|
||||
init {
|
||||
|
@ -54,6 +56,7 @@ class ApngAnimator(private val context: Context) {
|
|||
/**
|
||||
* Specify if the library could load non apng file
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
fun loadNotApng(boolean: Boolean) {
|
||||
val editor = sharedPreferences.edit()
|
||||
editor.putBoolean("loadNotApng", boolean)
|
||||
|
@ -75,7 +78,7 @@ class ApngAnimator(private val context: Context) {
|
|||
* @param speed The speed
|
||||
* @throws NotApngException
|
||||
*/
|
||||
@JvmOverloads
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
fun load(file: File, speed: Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) {
|
||||
doAsync {
|
||||
val bytes = file.readBytes()
|
||||
|
@ -140,6 +143,7 @@ class ApngAnimator(private val context: Context) {
|
|||
* @param speed The speed
|
||||
* @throws NotApngException
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
fun loadUrl(url: URL, speed: Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) {
|
||||
doAsync(exceptionHandler = { e -> e.printStackTrace() }) {
|
||||
this@ApngAnimator.speed = speed
|
||||
|
@ -171,13 +175,13 @@ class ApngAnimator(private val context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load an APNG file and starts playing the animation.
|
||||
* @param byteArray ByteArray of the file
|
||||
* @param speed The speed
|
||||
* @throws NotApngException
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
fun load(byteArray: ByteArray, speed: Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) {
|
||||
doAsync {
|
||||
this@ApngAnimator.speed = speed
|
||||
|
|
|
@ -45,14 +45,14 @@ class Frame {
|
|||
this.byteArray = bytes
|
||||
// Get width and height for image
|
||||
ihdr = IHDR()
|
||||
ihdr.parseIHDR(bytes)
|
||||
ihdr.parse(bytes)
|
||||
|
||||
width = ihdr.pngWidth
|
||||
height = ihdr.pngHeight
|
||||
|
||||
// Get IDAT Bytes
|
||||
idat = IDAT()
|
||||
idat.parseIDAT(bytes)
|
||||
idat.parse(bytes)
|
||||
|
||||
delay = 1000f
|
||||
|
||||
|
@ -69,14 +69,14 @@ class Frame {
|
|||
this.byteArray = bytes
|
||||
// Get width and height for image
|
||||
ihdr = IHDR()
|
||||
ihdr.parseIHDR(bytes)
|
||||
ihdr.parse(bytes)
|
||||
|
||||
width = ihdr.pngWidth
|
||||
height = ihdr.pngHeight
|
||||
|
||||
// Get IDAT Bytes
|
||||
idat = IDAT()
|
||||
idat.parseIDAT(bytes)
|
||||
idat.parse(bytes)
|
||||
|
||||
this.delay = delay
|
||||
blend_op = Utils.Companion.blend_op.APNG_BLEND_OP_SOURCE
|
||||
|
@ -93,14 +93,14 @@ class Frame {
|
|||
this.byteArray = bytes
|
||||
// Get width and height for image
|
||||
ihdr = IHDR()
|
||||
ihdr.parseIHDR(bytes)
|
||||
ihdr.parse(bytes)
|
||||
|
||||
width = ihdr.pngWidth
|
||||
height = ihdr.pngHeight
|
||||
|
||||
// Get IDAT Bytes
|
||||
idat = IDAT()
|
||||
idat.parseIDAT(bytes)
|
||||
idat.parse(bytes)
|
||||
|
||||
this.delay = delay
|
||||
|
||||
|
@ -121,14 +121,14 @@ class Frame {
|
|||
this.byteArray = bytes
|
||||
// Get width and height for image
|
||||
ihdr = IHDR()
|
||||
ihdr.parseIHDR(bytes)
|
||||
ihdr.parse(bytes)
|
||||
|
||||
width = ihdr.pngWidth
|
||||
height = ihdr.pngHeight
|
||||
|
||||
// Get IDAT Bytes
|
||||
idat = IDAT()
|
||||
idat.parseIDAT(bytes)
|
||||
idat.parse(bytes)
|
||||
|
||||
this.delay = delay
|
||||
|
||||
|
@ -149,14 +149,14 @@ class Frame {
|
|||
this.byteArray = byteArray
|
||||
// Get width and height for image
|
||||
ihdr = IHDR()
|
||||
ihdr.parseIHDR(byteArray)
|
||||
ihdr.parse(byteArray)
|
||||
|
||||
width = ihdr.pngWidth
|
||||
height = ihdr.pngHeight
|
||||
|
||||
// Get IDAT Bytes
|
||||
idat = IDAT()
|
||||
idat.parseIDAT(byteArray)
|
||||
idat.parse(byteArray)
|
||||
|
||||
this.delay = delay
|
||||
|
||||
|
|
|
@ -8,6 +8,12 @@ import java.net.URL
|
|||
|
||||
class Loader {
|
||||
companion object {
|
||||
/**
|
||||
* Download file from given url
|
||||
* @param context Context of app
|
||||
* @param url Url of the file to download
|
||||
* @return [ByteArray] of the file
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
fun load(context: Context, url: URL): ByteArray {
|
||||
val currentDir = context.filesDir
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package oupson.apng.chunks
|
||||
|
||||
interface Chunk {
|
||||
var body : ByteArray
|
||||
fun parse(byteArray: ByteArray)
|
||||
}
|
|
@ -1,30 +1,20 @@
|
|||
package oupson.apng.chunks
|
||||
|
||||
class IDAT {
|
||||
private var bodySize = -1
|
||||
var IDATBody: ArrayList<ByteArray> = ArrayList()
|
||||
import oupson.apng.utils.Utils.Companion.parseLength
|
||||
|
||||
fun parseIDAT(byteArray: ByteArray) {
|
||||
class IDAT : Chunk {
|
||||
var IDATBody: ArrayList<ByteArray> = ArrayList()
|
||||
override var body = byteArrayOf()
|
||||
|
||||
override fun parse(byteArray: ByteArray) {
|
||||
for (i in 0 until byteArray.size) {
|
||||
// Find IDAT chunk
|
||||
if (byteArray[i] == 0x49.toByte() && byteArray[i + 1] == 0x44.toByte() && byteArray[ i + 2 ] == 0x41.toByte() && byteArray[ i + 3 ] == 0x54.toByte()) {
|
||||
|
||||
// Find the chunk length
|
||||
var lengthString = ""
|
||||
byteArray.copyOfRange( i - 4, i).forEach {
|
||||
lengthString += String.format("%02x", it)
|
||||
}
|
||||
bodySize = lengthString.toLong(16).toInt()
|
||||
|
||||
val bodySize = parseLength(byteArray.copyOfRange(i - 4, i))
|
||||
// Get image bytes
|
||||
val _IDATbody = ArrayList<Byte>()
|
||||
for (j in i +4 until i + 4 + bodySize) {
|
||||
_IDATbody.add(byteArray[j])
|
||||
}
|
||||
IDATBody.add(_IDATbody.toByteArray())
|
||||
IDATBody.add(byteArray.copyOfRange(i + 4, i + 4 + bodySize))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,44 +1,22 @@
|
|||
package oupson.apng.chunks
|
||||
|
||||
class IHDR {
|
||||
private var corpsSize = -1
|
||||
|
||||
var ihdrCorps = byteArrayOf()
|
||||
import oupson.apng.utils.Utils.Companion.parseLength
|
||||
|
||||
class IHDR : Chunk {
|
||||
override var body = byteArrayOf()
|
||||
var pngWidth = -1
|
||||
var pngHeight = -1
|
||||
|
||||
fun parseIHDR(byteArray: ByteArray) {
|
||||
override fun parse(byteArray: ByteArray) {
|
||||
for (i in 0 until byteArray.size) {
|
||||
// Find IHDR chunk
|
||||
if (byteArray[i] == 0x49.toByte() && byteArray[i + 1] == 0x48.toByte() && byteArray[ i + 2 ] == 0x44.toByte() && byteArray[ i + 3 ] == 0x52.toByte()) {
|
||||
// Get length of the corps of the chunk
|
||||
var lengthString = ""
|
||||
byteArray.copyOfRange(i - 4, i).forEach {
|
||||
lengthString += String.format("%02x", it)
|
||||
}
|
||||
corpsSize = lengthString.toLong(16).toInt()
|
||||
|
||||
// Get length of the body of the chunk
|
||||
val bodySize = parseLength(byteArray.copyOfRange(i - 4, i))
|
||||
// Get the width of the png
|
||||
var pngwidth = ""
|
||||
byteArray.copyOfRange(i + 4, i + 8).forEach {
|
||||
pngwidth += String.format("%02x", it)
|
||||
}
|
||||
pngWidth = pngwidth.toLong(16).toInt()
|
||||
|
||||
pngWidth = parseLength(byteArray.copyOfRange(i +4, i + 8))
|
||||
// Get the height of the png
|
||||
var pngheight = ""
|
||||
byteArray.copyOfRange(i + 8, i + 12).forEach {
|
||||
pngheight += String.format("%02x", it)
|
||||
}
|
||||
pngHeight = pngheight.toLong(16).toInt()
|
||||
|
||||
val _ihdrCorps = ArrayList<Byte>()
|
||||
byteArray.copyOfRange(i + 4, i + corpsSize + 4).forEach {
|
||||
_ihdrCorps.add(it)
|
||||
}
|
||||
ihdrCorps = _ihdrCorps.toByteArray()
|
||||
|
||||
pngHeight = parseLength(byteArray.copyOfRange(i +8, i +12))
|
||||
body = byteArray.copyOfRange(i + 4, i + bodySize + 4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,10 @@ package oupson.apng.chunks
|
|||
import oupson.apng.utils.Utils
|
||||
import oupson.apng.utils.Utils.Companion.getBlend_op
|
||||
import oupson.apng.utils.Utils.Companion.getDispose_op
|
||||
import oupson.apng.utils.Utils.Companion.parseLength
|
||||
|
||||
class fcTL(byteArray: ByteArray) {
|
||||
|
||||
private var corpsSize = -1
|
||||
lateinit var fcTLBody : ByteArray
|
||||
class fcTL : Chunk {
|
||||
override var body : ByteArray = byteArrayOf()
|
||||
|
||||
// Height and width of frame
|
||||
var pngWidth = -1
|
||||
|
@ -22,83 +21,36 @@ class fcTL(byteArray: ByteArray) {
|
|||
|
||||
var blend_op : Utils.Companion.blend_op = Utils.Companion.blend_op.APNG_BLEND_OP_SOURCE
|
||||
var dispose_op : Utils.Companion.dispose_op = Utils.Companion.dispose_op.APNG_DISPOSE_OP_NONE
|
||||
init {
|
||||
|
||||
override fun parse(byteArray: ByteArray) {
|
||||
for (i in 0 until byteArray.size) {
|
||||
// Find fcTL chunk
|
||||
if (byteArray[i] == 0x66.toByte() && byteArray[i + 1] == 0x63.toByte() && byteArray[ i + 2 ] == 0x54.toByte() && byteArray[ i + 3 ] == 0x4C.toByte()) {
|
||||
// Get length of the body of the chunk
|
||||
var lengthString = ""
|
||||
byteArray.copyOfRange(i - 4, i).forEach {
|
||||
lengthString += String.format("%02x", it)
|
||||
}
|
||||
corpsSize = lengthString.toLong(16).toInt()
|
||||
|
||||
var bodySize = parseLength(byteArray.copyOfRange(i - 4, 1))
|
||||
// Get the width of the png
|
||||
var pngwidth = ""
|
||||
byteArray.copyOfRange(i + 8, i + 12).forEach {
|
||||
pngwidth += String.format("%02x", it)
|
||||
}
|
||||
pngWidth = pngwidth.toLong(16).toInt()
|
||||
|
||||
pngWidth = parseLength(byteArray.copyOfRange(i + 8, i + 12))
|
||||
// Get the height of the png
|
||||
var pngheight = ""
|
||||
byteArray.copyOfRange(i + 12, i + 16).forEach {
|
||||
pngheight += String.format("%02x", it)
|
||||
}
|
||||
pngHeight = pngheight.toLong(16).toInt()
|
||||
|
||||
/**
|
||||
pngHeight = parseLength(byteArray.copyOfRange(i + 12, i + 16))
|
||||
/*
|
||||
* The `delay_num` and `delay_den` parameters together specify a fraction indicating the time to display the current frame, in seconds.
|
||||
* If the the value of the numerator is 0 the decoder should render the next frame as quickly as possible, though viewers may impose a reasonable lower bound.
|
||||
*/
|
||||
|
||||
// Get delay numerator
|
||||
var delayNum = ""
|
||||
byteArray.copyOfRange(i + 24, i+ 26).forEach {
|
||||
delayNum += String.format("%02x", it)
|
||||
}
|
||||
val delay_num = delayNum.toLong(16).toFloat()
|
||||
|
||||
val delay_num = parseLength(byteArray.copyOfRange(i + 24, i + 26)).toFloat()
|
||||
// Get delay denominator
|
||||
var delayDen = ""
|
||||
byteArray.copyOfRange(i + 26, i+ 28).forEach {
|
||||
delayDen += String.format("%02x", it)
|
||||
}
|
||||
var delay_den = delayDen.toLong(16).toFloat()
|
||||
var delay_den = parseLength(byteArray.copyOfRange(i + 26, i + 28)).toFloat()
|
||||
|
||||
/**
|
||||
* If the denominator is 0, it is to be treated as if it were 100 (that is, `delay_num` then specifies 1/100ths of a second).
|
||||
*/
|
||||
// If the denominator is 0, it is to be treated as if it were 100 (that is, `delay_num` then specifies 1/100ths of a second).
|
||||
if (delay_den == 0f) {
|
||||
delay_den = 100f
|
||||
}
|
||||
|
||||
delay = (delay_num / delay_den * 1000)
|
||||
|
||||
|
||||
// Get x and y offsets
|
||||
var xOffset = ""
|
||||
byteArray.copyOfRange(i + 16, i+ 20).forEach {
|
||||
xOffset += String.format("%02x", it)
|
||||
}
|
||||
|
||||
x_offset = xOffset.toLong(16).toInt()
|
||||
|
||||
var yOffset = ""
|
||||
byteArray.copyOfRange(i + 20, i+ 24).forEach {
|
||||
yOffset += String.format("%02x", it)
|
||||
}
|
||||
|
||||
y_offset = yOffset.toLong(16).toInt()
|
||||
|
||||
val _fcTLBody = ArrayList<Byte>()
|
||||
byteArray.copyOfRange(i + 4, i + corpsSize + 3 ).forEach {
|
||||
_fcTLBody.add(it)
|
||||
}
|
||||
fcTLBody= _fcTLBody.toByteArray()
|
||||
|
||||
x_offset = parseLength(byteArray.copyOfRange(i + 16, i+ 20))
|
||||
y_offset = parseLength( byteArray.copyOfRange(i + 20, i+ 24))
|
||||
body = byteArray.copyOfRange(i +4, i + bodySize + 4)
|
||||
blend_op = getBlend_op(String.format("%02x", byteArray[33]).toLong(16).toInt())
|
||||
|
||||
dispose_op = getDispose_op(String.format("%02x", byteArray[32]).toLong(16).toInt())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
package oupson.apng.chunks
|
||||
|
||||
class fdAT {
|
||||
private var bodySize = -1
|
||||
var fdATBody: ArrayList<ByteArray> = ArrayList()
|
||||
|
||||
fun parsefdAT(byteArray: ByteArray, position: Int) {
|
||||
for (i in position until byteArray.size) {
|
||||
// Find fdAT chunk
|
||||
if (byteArray[i] == 0x66.toByte() && byteArray[i + 1] == 0x64.toByte() && byteArray[ i + 2 ] == 0x41.toByte() && byteArray[ i + 3 ] == 0x54.toByte()) {
|
||||
|
||||
// Find the chunk length
|
||||
var lengthString = ""
|
||||
byteArray.copyOfRange( i - 4, i).forEach {
|
||||
lengthString += String.format("%02x", it)
|
||||
}
|
||||
bodySize = lengthString.toLong(16).toInt()
|
||||
|
||||
// Get image bytes
|
||||
val _fdATbody = ArrayList<Byte>()
|
||||
for (j in i +4 until i + 4 + bodySize) {
|
||||
_fdATbody.add(byteArray[j])
|
||||
}
|
||||
fdATBody.add(_fdATbody.toByteArray())
|
||||
}
|
||||
// Find idat chunk
|
||||
else if (byteArray[i] == 0x49.toByte() && byteArray[i + 1] == 0x44.toByte() && byteArray[ i + 2 ] == 0x41.toByte() && byteArray[ i + 3 ] == 0x54.toByte()) {
|
||||
// Find the chunk length
|
||||
var lengthString = ""
|
||||
byteArray.copyOfRange( i - 4, i).forEach {
|
||||
lengthString += String.format("%02x", it)
|
||||
}
|
||||
bodySize = lengthString.toLong(16).toInt()
|
||||
|
||||
// Get image bytes
|
||||
val _fdATbody = ArrayList<Byte>()
|
||||
for (j in i +4 until i + 4 + bodySize) {
|
||||
_fdATbody.add(byteArray[j])
|
||||
}
|
||||
fdATBody.add(_fdATbody.toByteArray())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -157,6 +157,14 @@ class Utils {
|
|||
return result
|
||||
}
|
||||
|
||||
fun parseLength(byteArray: ByteArray) : Int {
|
||||
var lengthString = ""
|
||||
byteArray.forEach {
|
||||
lengthString += String.format("%02x", it)
|
||||
}
|
||||
return lengthString.toLong(16).toInt()
|
||||
}
|
||||
|
||||
val fcTL = Arrays.toString(byteArrayOf(0x66, 0x63, 0x54, 0x4c))
|
||||
val IEND = Arrays.toString(byteArrayOf(0x49, 0x45, 0x4e, 0x44))
|
||||
val IDAT = Arrays.toString(byteArrayOf(0x49, 0x44, 0x41, 0x54))
|
||||
|
|
|
@ -7,11 +7,9 @@ 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() {
|
||||
|
@ -42,7 +40,7 @@ class Main2Activity : AppCompatActivity() {
|
|||
fun load() {
|
||||
val animator = ApngAnimator(applicationContext).loadInto(imageView3)
|
||||
val uri = intent.data
|
||||
animator.load(uri, null, ApngAnimatorOptions(ImageView.ScaleType.CENTER_CROP))
|
||||
animator.load(uri, null)
|
||||
imageView3.onClick {
|
||||
try {
|
||||
if (animator.isPlaying) {
|
||||
|
|
Loading…
Reference in New Issue