diff --git a/apng_library/src/main/java/oupson/apng/APNGDisassembler.kt b/apng_library/src/main/java/oupson/apng/APNGDisassembler.kt index 5694594..668e622 100644 --- a/apng_library/src/main/java/oupson/apng/APNGDisassembler.kt +++ b/apng_library/src/main/java/oupson/apng/APNGDisassembler.kt @@ -8,228 +8,207 @@ import oupson.apng.utils.Utils import oupson.apng.utils.Utils.Companion.isApng import oupson.apng.utils.Utils.Companion.pngSignature import oupson.apng.utils.Utils.Companion.to4Bytes +import java.util.* import java.util.zip.CRC32 class APNGDisassembler { companion object { + private var png: ArrayList? = null + private var cover: ArrayList? = null + private var delay = -1f + private var yOffset = -1 + private var xOffset = -1 + private var plte: ByteArray? = null + private var tnrs: ByteArray? = null + private var maxWidth = 0 + 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() fun disassemble(byteArray: ByteArray) : Apng { - val pngList = ArrayList() - var png: ArrayList? = null - var cover: ArrayList? = null - var delay = -1f - var yOffset = -1 - var xOffset = -1 - var plte: ByteArray? = null - var tnrs: ByteArray? = null - var maxWidth = 0 - var maxHeight = 0 - 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 - val apng: Apng if (isApng(byteArray)) { apng = Apng() - val ihdr = IHDR() ihdr.parseIHDR(byteArray) maxWidth = ihdr.pngWidth maxHeight = ihdr.pngHeight - for (i in 0 until byteArray.size) { - // find new Frame with fcTL - if (byteArray[i] == 0x66.toByte() && byteArray[i + 1] == 0x63.toByte() && byteArray[i + 2] == 0x54.toByte() && byteArray[i + 3] == 0x4C.toByte()) { - if (png == null) { - if (cover != null) { - cover.addAll(to4Bytes(0).toList()) - // Add IEND - val iend = byteArrayOf(0x49, 0x45, 0x4E, 0x44) - // Generate crc for IEND - val crC32 = CRC32() - crC32.update(iend, 0, iend.size) - cover.addAll(iend.toList()) - cover.addAll(to4Bytes(crC32.value.toInt()).toList()) - apng.cover = BitmapFactory.decodeByteArray(cover.toByteArray(), 0, cover.size) - } + var cursor = 8 + while (cursor < byteArray.size) { + val chunk = byteArray.copyOfRange(cursor, cursor + parseLength(byteArray.copyOfRange(cursor, cursor + 4)) + 12) + parseChunk(chunk) + cursor += parseLength(byteArray.copyOfRange(cursor, cursor + 4)) + 12 + } + return apng + } else { + throw NotApngException() + } + } - png = ArrayList() - val fcTL = fcTL(byteArray.copyOfRange(i - 4, i + 36)) - 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 - val height = fcTL.pngHeight - png.addAll(pngSignature.toList()) - png.addAll(generate_ihdr(ihdr, width, height).toList()) + private fun parseLength(byteArray: ByteArray) : Int { + var lengthString = "" + byteArray.forEach { + lengthString += String.format("%02x", it) + } + return lengthString.toLong(16).toInt() + } - if (plte != null) { - png.addAll(plte.toList()) - } + private fun generateIhdr(ihdrOfApng: IHDR, width : Int, height : Int) : ByteArray { + val ihdr = ArrayList() + // We need a body var to know body length and generate crc + val ihdrBody = ArrayList() + // Add chunk body length + ihdr.addAll(to4Bytes(ihdrOfApng.ihdrCorps.size).toList()) + // Add IHDR + ihdrBody.addAll(byteArrayOf(0x49.toByte(), 0x48.toByte(), 0x44.toByte(), 0x52.toByte()).toList()) + // Add the max width and height + ihdrBody.addAll(to4Bytes(width).toList()) + 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()) + // Generate CRC + val crC32 = CRC32() + crC32.update(ihdrBody.toByteArray(), 0, ihdrBody.size) + ihdr.addAll(ihdrBody) + ihdr.addAll(to4Bytes(crC32.value.toInt()).toList()) + return ihdr.toByteArray() + } - if (tnrs != null) { - png.addAll(tnrs.toList()) - } - } else { - // Add IEND body length : 0 - png.addAll(to4Bytes(0).toList()) + private fun parseChunk(byteArray: ByteArray) { + val i = 4 + val name = Arrays.toString(byteArray.copyOfRange(i, i +4)) + when (name) { + Utils.fcTL -> { + if (png == null) { + cover?.let { + it.addAll(to4Bytes(0).toList()) // Add IEND val iend = byteArrayOf(0x49, 0x45, 0x4E, 0x44) // Generate crc for IEND val crC32 = CRC32() crC32.update(iend, 0, iend.size) - png.addAll(iend.toList()) - png.addAll(to4Bytes(crC32.value.toInt()).toList()) - pngList.add(Frame(png.toByteArray(), delay, xOffset, yOffset, maxWidth, maxHeight, blend_op, dispose_op)) - - png = ArrayList() - - val bodySize = { - var lengthString = "" - byteArray.copyOfRange(i - 4, i).forEach { - lengthString += String.format("%02x", it) - } - lengthString.toLong(16).toInt() - }() - val newBytes = byteArray.copyOfRange(i - 4, i + 4 + bodySize) - val fcTL = fcTL(newBytes) - delay = fcTL.delay + it.addAll(iend.toList()) + it.addAll(to4Bytes(crC32.value.toInt()).toList()) + apng.cover = BitmapFactory.decodeByteArray(it.toByteArray(), 0, it.size) + } - yOffset = fcTL.y_offset - xOffset = fcTL.x_offset + png = ArrayList() + val fcTL = fcTL(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 + val height = fcTL.pngHeight + png!!.addAll(pngSignature.toList()) + png!!.addAll(generateIhdr(ihdr, width, height).toList()) - blend_op = fcTL.blend_op - dispose_op = fcTL.dispose_op - val width = fcTL.pngWidth - val height = fcTL.pngHeight - png.addAll(pngSignature.toList()) - png.addAll(generate_ihdr(ihdr, width, height).toList()) - if (plte != null) { - png.addAll(plte.toList()) - } + plte?.let { + png!!.addAll(it.toList()) + } - if (tnrs != null) { - png.addAll(tnrs.toList()) - } + tnrs?.let { + png!!.addAll(it.toList()) } - } else if (i == byteArray.size - 1) { + } else { + // Add IEND body length : 0 png!!.addAll(to4Bytes(0).toList()) // Add IEND val iend = byteArrayOf(0x49, 0x45, 0x4E, 0x44) // Generate crc for IEND val crC32 = CRC32() crC32.update(iend, 0, iend.size) - png.addAll(iend.toList()) - png.addAll(to4Bytes(crC32.value.toInt()).toList()) - pngList.add(Frame(png.toByteArray(), delay, xOffset, yOffset, maxWidth, maxHeight, blend_op, dispose_op)) - } - // Check if is IDAT - else if (byteArray[i] == 0x49.toByte() && byteArray[i + 1] == 0x44.toByte() && byteArray[i + 2] == 0x41.toByte() && byteArray[i + 3] == 0x54.toByte()) { - if (png == null) { - if (cover == null) { - cover = ArrayList() - cover.addAll(pngSignature.toList()) - cover.addAll(generate_ihdr(ihdr, maxWidth, maxHeight).toList()) - } - // Find the chunk length - var lengthString = "" - byteArray.copyOfRange(i - 4, i).forEach { - lengthString += String.format("%02x", it) - } - val bodySize = lengthString.toLong(16).toInt() - cover.addAll(byteArray.copyOfRange(i - 4, i).toList()) - val body = ArrayList() - body.addAll(byteArrayOf(0x49, 0x44, 0x41, 0x54).toList()) - // Get image bytes - for (j in i + 4 until i + 4 + bodySize) { - body.add(byteArray[j]) - } - val crC32 = CRC32() - crC32.update(body.toByteArray(), 0, body.size) - cover.addAll(body) - cover.addAll(to4Bytes(crC32.value.toInt()).toList()) - } else { - // Find the chunk length - var lengthString = "" - byteArray.copyOfRange(i - 4, i).forEach { - lengthString += String.format("%02x", it) - } - val bodySize = lengthString.toLong(16).toInt() - png.addAll(byteArray.copyOfRange(i - 4, i).toList()) - val body = ArrayList() - body.addAll(byteArrayOf(0x49, 0x44, 0x41, 0x54).toList()) - // Get image bytes - for (j in i + 4 until i + 4 + bodySize) { - body.add(byteArray[j]) - } - val crC32 = CRC32() - crC32.update(body.toByteArray(), 0, body.size) - png.addAll(body) - png.addAll(to4Bytes(crC32.value.toInt()).toList()) + 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) + 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 + 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()) } } - // Check if is fdAT - else 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) + } + Utils.IEND -> { + png!!.addAll(to4Bytes(0).toList()) + // Add IEND + val iend = byteArrayOf(0x49, 0x45, 0x4E, 0x44) + // Generate crc for IEND + val crC32 = CRC32() + crC32.update(iend, 0, iend.size) + 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)) + } + Utils.IDAT -> { + if (png == null) { + if (cover == null) { + cover = ArrayList() + cover!!.addAll(pngSignature.toList()) + cover!!.addAll(generateIhdr(ihdr, maxWidth, maxHeight).toList()) } - val bodySize = lengthString.toLong(16).toInt() - png!!.addAll(to4Bytes(bodySize - 4).toList()) + // Find the chunk length + val bodySize = parseLength(byteArray.copyOfRange(i - 4, i)) + cover!!.addAll(byteArray.copyOfRange(i - 4, i).toList()) val body = ArrayList() body.addAll(byteArrayOf(0x49, 0x44, 0x41, 0x54).toList()) // Get image bytes - for (j in i + 8 until i + 4 + bodySize) { - body.add(byteArray[j]) - } + body.addAll(byteArray.copyOfRange(i + 4,i + 4 + bodySize).toList()) val crC32 = CRC32() crC32.update(body.toByteArray(), 0, body.size) - png.addAll(body) - png.addAll(to4Bytes(crC32.value.toInt()).toList()) - } - // Get plte chunks if exist. The PLTE chunk contains from 1 to 256 palette entries, each a three-byte series of the form: - else if (byteArray[i] == 0x50.toByte() && byteArray[i + 1] == 0x4C.toByte() && byteArray[i + 2] == 0x54.toByte() && byteArray[i + 3] == 0x45.toByte()) { - var lengthString = "" - byteArray.copyOfRange(i - 4, i).forEach { - lengthString += String.format("%02x", it) - } - val bodySize = lengthString.toLong(16).toInt() - plte = byteArray.copyOfRange(i - 4, i + 8 + bodySize) - } - // Get tnrs chunk if exist. Used for transparency - else if (byteArray[i] == 0x74.toByte() && byteArray[i + 1] == 0x52.toByte() && byteArray[i + 2] == 0x4E.toByte() && byteArray[i + 3] == 0x53.toByte()) { - var lengthString = "" - byteArray.copyOfRange(i - 4, i).forEach { - lengthString += String.format("%02x", it) - } - val bodySize = lengthString.toLong(16).toInt() - tnrs = byteArray.copyOfRange(i - 4, i + 8 + bodySize) + cover!!.addAll(body) + cover!!.addAll(to4Bytes(crC32.value.toInt()).toList()) + } else { + // Find the chunk length + val bodySize = parseLength(byteArray.copyOfRange(i - 4, i)) + png!!.addAll(byteArray.copyOfRange(i - 4, i).toList()) + val body = ArrayList() + body.addAll(byteArrayOf(0x49, 0x44, 0x41, 0x54).toList()) + // Get image bytes + body.addAll(byteArray.copyOfRange(i + 4,i + 4 + bodySize).toList()) + val crC32 = CRC32() + crC32.update(body.toByteArray(), 0, body.size) + png!!.addAll(body) + png!!.addAll(to4Bytes(crC32.value.toInt()).toList()) } } - apng.frames = pngList - return apng - } else { - throw NotApngException() + Utils.fdAT -> { + // Find the chunk length + val bodySize = parseLength(byteArray.copyOfRange(i - 4, i)) + png!!.addAll(to4Bytes(bodySize - 4).toList()) + val body = ArrayList() + body.addAll(byteArrayOf(0x49, 0x44, 0x41, 0x54).toList()) + // Get image bytes + body.addAll(byteArray.copyOfRange(i + 8,i + 4 + bodySize).toList()) + val crC32 = CRC32() + crC32.update(body.toByteArray(), 0, body.size) + png!!.addAll(body) + png!!.addAll(to4Bytes(crC32.value.toInt()).toList()) + } + Utils.plte -> { + plte = byteArray + } + Utils.tnrs -> { + tnrs = byteArray + } } } - private fun generate_ihdr(ihdrOfApng: IHDR, width : Int, height : Int) : ByteArray { - val ihdr = ArrayList() - // We need a body var to know body length and generate crc - val ihdr_body = ArrayList() - // Add chunk body length - ihdr.addAll(to4Bytes(ihdrOfApng.ihdrCorps.size).toList()) - // Add IHDR - ihdr_body.addAll(byteArrayOf(0x49.toByte(), 0x48.toByte(), 0x44.toByte(), 0x52.toByte()).toList()) - // Add the max width and height - ihdr_body.addAll(to4Bytes(width).toList()) - ihdr_body.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. - ihdr_body.addAll(ihdrOfApng.ihdrCorps.copyOfRange(8, 13).toList()) - // Generate CRC - val crC32 = CRC32() - crC32.update(ihdr_body.toByteArray(), 0, ihdr_body.size) - ihdr.addAll(ihdr_body) - ihdr.addAll(to4Bytes(crC32.value.toInt()).toList()) - return ihdr.toByteArray() - } } } \ No newline at end of file diff --git a/apng_library/src/main/java/oupson/apng/ApngAnimator.kt b/apng_library/src/main/java/oupson/apng/ApngAnimator.kt index 6fb1da5..d512e9a 100644 --- a/apng_library/src/main/java/oupson/apng/ApngAnimator.kt +++ b/apng_library/src/main/java/oupson/apng/ApngAnimator.kt @@ -150,7 +150,7 @@ class ApngAnimator(private val context: Context) { this@ApngAnimator.speed = speed scaleType = apngAnimatorOptions?.scaleType // Download PNG - snapshotAPNGDisassembler.disassemble(this).frames.apply { + APNGDisassembler.disassemble(this).frames.apply { draw(this).apply { setupAnimationDrawableAndStart(this) } diff --git a/apng_library/src/main/java/oupson/apng/snapshotAPNGDisassembler.kt b/apng_library/src/main/java/oupson/apng/snapshotAPNGDisassembler.kt deleted file mode 100644 index 95c4249..0000000 --- a/apng_library/src/main/java/oupson/apng/snapshotAPNGDisassembler.kt +++ /dev/null @@ -1,219 +0,0 @@ -package oupson.apng - -import android.graphics.BitmapFactory -import android.os.Debug -import android.util.Log -import oupson.apng.chunks.IHDR -import oupson.apng.chunks.fcTL -import oupson.apng.exceptions.NotApngException -import oupson.apng.utils.Utils -import oupson.apng.utils.Utils.Companion.fcTL -import oupson.apng.utils.Utils.Companion.isApng -import oupson.apng.utils.Utils.Companion.pngSignature -import oupson.apng.utils.Utils.Companion.to4Bytes -import java.util.* -import java.util.zip.CRC32 - -class snapshotAPNGDisassembler { - companion object { - val pngList = ArrayList() - var png: ArrayList? = null - var cover: ArrayList? = null - var delay = -1f - var yOffset = -1 - var xOffset = -1 - var plte: ByteArray? = null - var tnrs: ByteArray? = null - var maxWidth = 0 - var maxHeight = 0 - 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 - var apng: Apng = Apng() - val ihdr = IHDR() - fun disassemble(byteArray: ByteArray) : Apng { - if (isApng(byteArray)) { - apng = Apng() - ihdr.parseIHDR(byteArray) - maxWidth = ihdr.pngWidth - maxHeight = ihdr.pngHeight - var cursor = 8 - while (cursor < byteArray.size) { - var chunk = byteArray.copyOfRange(cursor, cursor + parseLength(byteArray.copyOfRange(cursor, cursor + 4)) + 12) - parseChunk(chunk) - cursor += parseLength(byteArray.copyOfRange(cursor, cursor + 4)) + 12 - } - apng.frames = pngList - return apng - } else { - throw NotApngException() - } - } - - private fun parseLength(byteArray: ByteArray) : Int { - var lengthString = "" - byteArray.forEach { - lengthString += String.format("%02x", it) - } - return lengthString.toLong(16).toInt() - } - - private fun generate_ihdr(ihdrOfApng: IHDR, width : Int, height : Int) : ByteArray { - val ihdr = ArrayList() - // We need a body var to know body length and generate crc - val ihdr_body = ArrayList() - // Add chunk body length - ihdr.addAll(to4Bytes(ihdrOfApng.ihdrCorps.size).toList()) - // Add IHDR - ihdr_body.addAll(byteArrayOf(0x49.toByte(), 0x48.toByte(), 0x44.toByte(), 0x52.toByte()).toList()) - // Add the max width and height - ihdr_body.addAll(to4Bytes(width).toList()) - ihdr_body.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. - ihdr_body.addAll(ihdrOfApng.ihdrCorps.copyOfRange(8, 13).toList()) - // Generate CRC - val crC32 = CRC32() - crC32.update(ihdr_body.toByteArray(), 0, ihdr_body.size) - ihdr.addAll(ihdr_body) - ihdr.addAll(to4Bytes(crC32.value.toInt()).toList()) - return ihdr.toByteArray() - } - - private fun parseChunk(byteArray: ByteArray) { - val i = 4 - val name = Arrays.toString(byteArray.copyOfRange(i, i +4)) - when (name) { - Utils.fcTL -> { - if (png == null) { - cover?.let { - it.addAll(to4Bytes(0).toList()) - // Add IEND - val iend = byteArrayOf(0x49, 0x45, 0x4E, 0x44) - // Generate crc for IEND - val crC32 = CRC32() - crC32.update(iend, 0, iend.size) - it.addAll(iend.toList()) - it.addAll(to4Bytes(crC32.value.toInt()).toList()) - apng.cover = BitmapFactory.decodeByteArray(it.toByteArray(), 0, it.size) - } - - png = ArrayList() - val fcTL = fcTL(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 - val height = fcTL.pngHeight - png!!.addAll(pngSignature.toList()) - png!!.addAll(generate_ihdr(ihdr, width, height).toList()) - - plte?.let { - png!!.addAll(it.toList()) - } - - tnrs?.let { - png!!.addAll(it.toList()) - } - } else { - // Add IEND body length : 0 - png!!.addAll(to4Bytes(0).toList()) - // Add IEND - val iend = byteArrayOf(0x49, 0x45, 0x4E, 0x44) - // Generate crc for IEND - val crC32 = CRC32() - crC32.update(iend, 0, iend.size) - png!!.addAll(iend.toList()) - png!!.addAll(to4Bytes(crC32.value.toInt()).toList()) - pngList.add(Frame(png!!.toByteArray(), delay, xOffset, yOffset, maxWidth, maxHeight, blend_op, dispose_op)) - - png = ArrayList() - - val fcTL = fcTL(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 - val height = fcTL.pngHeight - png!!.addAll(pngSignature.toList()) - png!!.addAll(generate_ihdr(ihdr, width, height).toList()) - plte?.let { - png!!.addAll(it.toList()) - } - - tnrs?.let { - png!!.addAll(it.toList()) - } - } - } - Utils.IEND -> { - png!!.addAll(to4Bytes(0).toList()) - // Add IEND - val iend = byteArrayOf(0x49, 0x45, 0x4E, 0x44) - // Generate crc for IEND - val crC32 = CRC32() - crC32.update(iend, 0, iend.size) - png!!.addAll(iend.toList()) - png!!.addAll(to4Bytes(crC32.value.toInt()).toList()) - pngList.add(Frame(png!!.toByteArray(), delay, xOffset, yOffset, maxWidth, maxHeight, blend_op, dispose_op)) - } - Utils.IDAT -> { - if (png == null) { - if (cover == null) { - cover = ArrayList() - cover!!.addAll(pngSignature.toList()) - cover!!.addAll(generate_ihdr(ihdr, maxWidth, maxHeight).toList()) - } - // Find the chunk length - val bodySize = parseLength(byteArray.copyOfRange(i - 4, i)) - cover!!.addAll(byteArray.copyOfRange(i - 4, i).toList()) - val body = ArrayList() - body.addAll(byteArrayOf(0x49, 0x44, 0x41, 0x54).toList()) - // Get image bytes - body.addAll(byteArray.copyOfRange(i + 4,i + 4 + bodySize).toList()) - val crC32 = CRC32() - crC32.update(body.toByteArray(), 0, body.size) - cover!!.addAll(body) - cover!!.addAll(to4Bytes(crC32.value.toInt()).toList()) - } else { - // Find the chunk length - val bodySize = parseLength(byteArray.copyOfRange(i - 4, i)) - png!!.addAll(byteArray.copyOfRange(i - 4, i).toList()) - val body = ArrayList() - body.addAll(byteArrayOf(0x49, 0x44, 0x41, 0x54).toList()) - // Get image bytes - body.addAll(byteArray.copyOfRange(i + 4,i + 4 + bodySize).toList()) - val crC32 = CRC32() - crC32.update(body.toByteArray(), 0, body.size) - png!!.addAll(body) - png!!.addAll(to4Bytes(crC32.value.toInt()).toList()) - } - } - Utils.fdAT -> { - // Find the chunk length - val bodySize = parseLength(byteArray.copyOfRange(i - 4, i)) - png!!.addAll(to4Bytes(bodySize - 4).toList()) - val body = ArrayList() - body.addAll(byteArrayOf(0x49, 0x44, 0x41, 0x54).toList()) - // Get image bytes - body.addAll(byteArray.copyOfRange(i + 8,i + 4 + bodySize).toList()) - val crC32 = CRC32() - crC32.update(body.toByteArray(), 0, body.size) - png!!.addAll(body) - png!!.addAll(to4Bytes(crC32.value.toInt()).toList()) - } - Utils.plte -> { - plte = byteArray - } - Utils.tnrs -> { - tnrs = byteArray - } - } - } - } -} \ No newline at end of file diff --git a/app-test/src/main/java/oupson/apngcreator/MainActivity.kt b/app-test/src/main/java/oupson/apngcreator/MainActivity.kt index 5e39fcc..b712c8a 100644 --- a/app-test/src/main/java/oupson/apngcreator/MainActivity.kt +++ b/app-test/src/main/java/oupson/apngcreator/MainActivity.kt @@ -13,9 +13,9 @@ import java.util.* class MainActivity : AppCompatActivity() { lateinit var animator: ApngAnimator - val imageUrl = "https://metagif.files.wordpress.com/2015/01/bugbuckbunny.png" - // val imageUrl = "http://orig06.deviantart.net/7812/f/2012/233/7/5/twilight_rapidash_shaded_and_animated_by_tamalesyatole-d5bz7hd.png" - //val imageUrl = "https://raw.githubusercontent.com/tinify/iMessage-Panda-sticker/master/StickerPackExtension/Stickers.xcstickers/Sticker%20Pack.stickerpack/panda.sticker/panda.png" + //val imageUrl = "https://metagif.files.wordpress.com/2015/01/bugbuckbunny.png" + //val imageUrl = "http://orig06.deviantart.net/7812/f/2012/233/7/5/twilight_rapidash_shaded_and_animated_by_tamalesyatole-d5bz7hd.png" + val imageUrl = "https://raw.githubusercontent.com/tinify/iMessage-Panda-sticker/master/StickerPackExtension/Stickers.xcstickers/Sticker%20Pack.stickerpack/panda.sticker/panda.png" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main)