Initial commit
This commit is contained in:
parent
498f336466
commit
46d26d66ee
Binary file not shown.
|
@ -32,6 +32,7 @@ dependencies {
|
||||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
implementation "org.jetbrains.anko:anko:0.10.6"
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|
|
@ -1,26 +1,27 @@
|
||||||
package oupson.apng
|
package oupson.apng
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import oupson.apng.APNG.Companion.isApng
|
|
||||||
import java.util.zip.CRC32
|
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import oupson.apng.ApngFactory.Companion.isApng
|
||||||
|
import oupson.apng.ApngFactory.Companion.isApng
|
||||||
|
import oupson.apng.ApngFactory.Companion.pngSignature
|
||||||
|
import java.util.zip.CRC32
|
||||||
|
|
||||||
|
|
||||||
class APNGDisassembler(val byteArray: ByteArray) {
|
class APNGDisassembler(val byteArray: ByteArray) {
|
||||||
val pngList = ArrayList<ByteArray>()
|
val pngList = ArrayList<Frame>()
|
||||||
var png : ArrayList<Byte>? = null
|
var png : ArrayList<Byte>? = null
|
||||||
|
|
||||||
var delayList = ArrayList<Float>()
|
var delay = -1f
|
||||||
|
|
||||||
var yOffset= ArrayList<Int>()
|
var yOffset= -1
|
||||||
|
|
||||||
var xOffset = ArrayList<Int>()
|
var xOffset = -1
|
||||||
|
|
||||||
var maxWidth = 0
|
var maxWidth = 0
|
||||||
var maxHeight = 0
|
var maxHeight = 0
|
||||||
init {
|
init {
|
||||||
if (isApng(byteArray)) {
|
if (ApngFactory.isApng(byteArray)) {
|
||||||
val ihdr = IHDR()
|
val ihdr = IHDR()
|
||||||
ihdr.parseIHDR(byteArray)
|
ihdr.parseIHDR(byteArray)
|
||||||
maxWidth = ihdr.pngWidth
|
maxWidth = ihdr.pngWidth
|
||||||
|
@ -32,14 +33,13 @@ class APNGDisassembler(val byteArray: ByteArray) {
|
||||||
png = ArrayList()
|
png = ArrayList()
|
||||||
|
|
||||||
val fcTL = fcTL(byteArray.copyOfRange(i-4, i + 28))
|
val fcTL = fcTL(byteArray.copyOfRange(i-4, i + 28))
|
||||||
delayList.add(fcTL.delay)
|
delay = fcTL.delay
|
||||||
|
yOffset = fcTL.y_offset
|
||||||
yOffset.add(fcTL.y_offset)
|
xOffset = fcTL.x_offset
|
||||||
xOffset.add(fcTL.x_offset)
|
|
||||||
Log.e("APNG", "delay : + ${fcTL.delay}")
|
Log.e("APNG", "delay : + ${fcTL.delay}")
|
||||||
val width = fcTL.pngWidth
|
val width = fcTL.pngWidth
|
||||||
val height = fcTL.pngHeight
|
val height = fcTL.pngHeight
|
||||||
png!!.addAll(APNG.pngSignature.toList())
|
png!!.addAll(pngSignature.toList())
|
||||||
png!!.addAll(generate_ihdr(ihdr, width, height).toList())
|
png!!.addAll(generate_ihdr(ihdr, width, height).toList())
|
||||||
} else {
|
} else {
|
||||||
// Add IEND body length : 0
|
// Add IEND body length : 0
|
||||||
|
@ -51,20 +51,19 @@ class APNGDisassembler(val byteArray: ByteArray) {
|
||||||
crC32.update(iend, 0, iend.size)
|
crC32.update(iend, 0, iend.size)
|
||||||
png!!.addAll(iend.toList())
|
png!!.addAll(iend.toList())
|
||||||
png!!.addAll(to4Bytes(crC32.value.toInt()).toList())
|
png!!.addAll(to4Bytes(crC32.value.toInt()).toList())
|
||||||
|
pngList.add(Frame(png!!.toByteArray(), delay, xOffset, yOffset, maxWidth, maxHeight))
|
||||||
pngList.add(png!!.toByteArray())
|
|
||||||
|
|
||||||
png = ArrayList()
|
png = ArrayList()
|
||||||
|
|
||||||
val fcTL = fcTL(byteArray.copyOfRange(i-4, i + 28))
|
val fcTL = fcTL(byteArray.copyOfRange(i-4, i + 28))
|
||||||
delayList.add(fcTL.delay)
|
delay = fcTL.delay
|
||||||
|
|
||||||
yOffset.add(fcTL.y_offset)
|
yOffset = fcTL.y_offset
|
||||||
xOffset.add(fcTL.x_offset)
|
xOffset = fcTL.x_offset
|
||||||
|
|
||||||
val width = fcTL.pngWidth
|
val width = fcTL.pngWidth
|
||||||
val height = fcTL.pngHeight
|
val height = fcTL.pngHeight
|
||||||
png!!.addAll(APNG.pngSignature.toList())
|
png!!.addAll(pngSignature.toList())
|
||||||
png!!.addAll(generate_ihdr(ihdr, width, height).toList())
|
png!!.addAll(generate_ihdr(ihdr, width, height).toList())
|
||||||
}
|
}
|
||||||
} else if (byteArray[i] == 0x49.toByte() && byteArray[i + 1] == 0x44.toByte() && byteArray[ i + 2 ] == 0x41.toByte() && byteArray[ i + 3 ] == 0x54.toByte()) {
|
} else if (byteArray[i] == 0x49.toByte() && byteArray[i + 1] == 0x44.toByte() && byteArray[ i + 2 ] == 0x41.toByte() && byteArray[ i + 3 ] == 0x54.toByte()) {
|
||||||
|
@ -75,7 +74,7 @@ class APNGDisassembler(val byteArray: ByteArray) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var bodySize = lengthString.toLong(16).toInt()
|
val bodySize = lengthString.toLong(16).toInt()
|
||||||
png!!.addAll(byteArray.copyOfRange(i-4, i).toList())
|
png!!.addAll(byteArray.copyOfRange(i-4, i).toList())
|
||||||
val body = ArrayList<Byte>()
|
val body = ArrayList<Byte>()
|
||||||
body.addAll(byteArrayOf(0x49, 0x44, 0x41, 0x54).toList())
|
body.addAll(byteArrayOf(0x49, 0x44, 0x41, 0x54).toList())
|
||||||
|
@ -114,20 +113,13 @@ class APNGDisassembler(val byteArray: ByteArray) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
var p = ""
|
||||||
|
p += String(byteArray.copyOfRange(0, 50))
|
||||||
|
Log.e("TAG", "Not a apng : $p")
|
||||||
throw NotApngException()
|
throw NotApngException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getbitmapList() : ArrayList<Frame>
|
|
||||||
{
|
|
||||||
var res = ArrayList<Frame>()
|
|
||||||
Log.e("APNG", "pngList : ${pngList.size}, delayList : ${delayList.size}")
|
|
||||||
for (i in 0 until pngList.size) {
|
|
||||||
res.add(Frame(pngList[i], delayList[i], xOffset[i], yOffset[i], maxWidth, maxHeight))
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generate_ihdr(ihdrOfApng: IHDR, width : Int, height : Int) : ByteArray {
|
private fun generate_ihdr(ihdrOfApng: IHDR, width : Int, height : Int) : ByteArray {
|
||||||
val ihdr = ArrayList<Byte>()
|
val ihdr = ArrayList<Byte>()
|
||||||
|
|
||||||
|
@ -179,6 +171,4 @@ class APNGDisassembler(val byteArray: ByteArray) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
class extractedFrame(val bitmap: Bitmap, val delay : Float, val xoffset : Int, val yoffset : Int, val maxWidth : Int, val maxHeight : Int) {
|
|
||||||
}
|
}
|
|
@ -6,7 +6,10 @@ import android.graphics.Canvas
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
|
import org.jetbrains.anko.doAsync
|
||||||
|
import org.jetbrains.anko.uiThread
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
class ApngAnimator(val imageView : ImageView) {
|
class ApngAnimator(val imageView : ImageView) {
|
||||||
var play = true
|
var play = true
|
||||||
|
@ -23,7 +26,52 @@ class ApngAnimator(val imageView : ImageView) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun load(file: File) {
|
fun load(file: File) {
|
||||||
val extractedFrame = APNGDisassembler(file.readBytes()).getbitmapList()
|
val extractedFrame = APNGDisassembler(file.readBytes()).pngList
|
||||||
|
Frames = extractedFrame
|
||||||
|
|
||||||
|
Frames.forEach {
|
||||||
|
val btm = Bitmap.createBitmap(Frames[0].maxWidth, Frames[0].maxHeight, Bitmap.Config.ARGB_8888)
|
||||||
|
val canvas = Canvas(btm)
|
||||||
|
canvas.drawBitmap(BitmapFactory.decodeByteArray(it.byteArray, 0, it.byteArray.size), it.x_offsets.toFloat(), it.y_offsets.toFloat(), null)
|
||||||
|
generatedFrame.add(btm)
|
||||||
|
}
|
||||||
|
|
||||||
|
nextFrame()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun load(string: String) {
|
||||||
|
if (string.contains("http") || string.contains("https")) {
|
||||||
|
val url = URL(string)
|
||||||
|
doAsync {
|
||||||
|
val extractedFrame = APNGDisassembler(Loader().load(url)).pngList
|
||||||
|
Frames = extractedFrame
|
||||||
|
|
||||||
|
Frames.forEach {
|
||||||
|
val btm = Bitmap.createBitmap(Frames[0].maxWidth, Frames[0].maxHeight, Bitmap.Config.ARGB_8888)
|
||||||
|
val canvas = Canvas(btm)
|
||||||
|
canvas.drawBitmap(BitmapFactory.decodeByteArray(it.byteArray, 0, it.byteArray.size), it.x_offsets.toFloat(), it.y_offsets.toFloat(), null)
|
||||||
|
generatedFrame.add(btm)
|
||||||
|
}
|
||||||
|
uiThread {
|
||||||
|
nextFrame()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (File(string).exists()) {
|
||||||
|
val extractedFrame = APNGDisassembler(Loader().load(File(string))).pngList
|
||||||
|
Frames = extractedFrame
|
||||||
|
|
||||||
|
Frames.forEach {
|
||||||
|
val btm = Bitmap.createBitmap(Frames[0].maxWidth, Frames[0].maxHeight, Bitmap.Config.ARGB_8888)
|
||||||
|
val canvas = Canvas(btm)
|
||||||
|
canvas.drawBitmap(BitmapFactory.decodeByteArray(it.byteArray, 0, it.byteArray.size), it.x_offsets.toFloat(), it.y_offsets.toFloat(), null)
|
||||||
|
generatedFrame.add(btm)
|
||||||
|
}
|
||||||
|
nextFrame()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun load(byteArray: ByteArray) {
|
||||||
|
val extractedFrame = APNGDisassembler(byteArray).pngList
|
||||||
Frames = extractedFrame
|
Frames = extractedFrame
|
||||||
|
|
||||||
Frames.forEach {
|
Frames.forEach {
|
||||||
|
@ -53,8 +101,10 @@ class ApngAnimator(val imageView : ImageView) {
|
||||||
|
|
||||||
}
|
}
|
||||||
fun play() {
|
fun play() {
|
||||||
play = true
|
if (!play) {
|
||||||
mustPlay()
|
play = true
|
||||||
|
mustPlay()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun mustPlay() {
|
private fun mustPlay() {
|
||||||
|
|
|
@ -15,7 +15,7 @@ import java.util.zip.CRC32
|
||||||
* @throws NoFrameException
|
* @throws NoFrameException
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class APNG {
|
class ApngFactory {
|
||||||
|
|
||||||
private var seq = 0
|
private var seq = 0
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ class APNG {
|
||||||
*
|
*
|
||||||
* @throws NoFrameException
|
* @throws NoFrameException
|
||||||
*/
|
*/
|
||||||
fun create() : ByteArray {
|
fun create(): ByteArray {
|
||||||
|
|
||||||
if (frames.isNotEmpty()) {
|
if (frames.isNotEmpty()) {
|
||||||
val res = ArrayList<Byte>()
|
val res = ArrayList<Byte>()
|
||||||
|
@ -191,7 +191,7 @@ class APNG {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Animation Control chunk
|
// Animation Control chunk
|
||||||
private fun generateACTL() : ArrayList<Byte> {
|
private fun generateACTL(): ArrayList<Byte> {
|
||||||
val res = ArrayList<Byte>()
|
val res = ArrayList<Byte>()
|
||||||
val actl = ArrayList<Byte>()
|
val actl = ArrayList<Byte>()
|
||||||
|
|
||||||
|
@ -242,14 +242,14 @@ class APNG {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// Return true if png
|
// Return true if png
|
||||||
fun isPng(byteArray: ByteArray) : Boolean {
|
fun isPng(byteArray: ByteArray): Boolean {
|
||||||
return byteArray.copyOfRange(0, 8).contentToString() == pngSignature.contentToString()
|
return byteArray.copyOfRange(0, 8).contentToString() == pngSignature.contentToString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isApng(byteArray: ByteArray) : Boolean {
|
fun isApng(byteArray: ByteArray): Boolean {
|
||||||
for (i in 0 until byteArray.size) {
|
for (i in 0 until byteArray.size) {
|
||||||
// if byteArray contain acTL
|
// if byteArray contain acTL
|
||||||
if (byteArray[i] == 0x66.toByte() && byteArray[i + 1] == 0x63.toByte() && byteArray[ i + 2] == 0x54.toByte() && byteArray[ i + 3] == 0x4c.toByte()) {
|
if (byteArray[i] == 0x66.toByte() && byteArray[i + 1] == 0x63.toByte() && byteArray[i + 2] == 0x54.toByte() && byteArray[i + 3] == 0x4c.toByte()) {
|
||||||
// It's an apng
|
// It's an apng
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -259,7 +259,7 @@ class APNG {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signature for png
|
// Signature for png
|
||||||
val pngSignature : ByteArray = byteArrayOf(0x89.toByte(), 0x50.toByte(), 0x4E.toByte(), 0x47.toByte(), 0x0D.toByte(), 0x0A.toByte(), 0x1A.toByte(), 0x0A.toByte())
|
val pngSignature: ByteArray = byteArrayOf(0x89.toByte(), 0x50.toByte(), 0x4E.toByte(), 0x47.toByte(), 0x0D.toByte(), 0x0A.toByte(), 0x1A.toByte(), 0x0A.toByte())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -273,7 +273,7 @@ class APNG {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate Image Header chunk
|
// Generate Image Header chunk
|
||||||
private fun generate_ihdr() : ByteArray {
|
private fun generate_ihdr(): ByteArray {
|
||||||
val ihdr = ArrayList<Byte>()
|
val ihdr = ArrayList<Byte>()
|
||||||
|
|
||||||
// We need a body var to know body length and generate crc
|
// We need a body var to know body length and generate crc
|
|
@ -1,6 +1,6 @@
|
||||||
package oupson.apng
|
package oupson.apng
|
||||||
|
|
||||||
import oupson.apng.APNG.Companion.isPng
|
import oupson.apng.ApngFactory.Companion.isPng
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A frame for an animated png
|
* A frame for an animated png
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package oupson.apng
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.ImageView
|
||||||
|
import java.io.*
|
||||||
|
import java.net.URI
|
||||||
|
import java.net.URL
|
||||||
|
import java.net.URLConnection
|
||||||
|
|
||||||
|
class Loader {
|
||||||
|
fun load(url : URL) : ByteArray {
|
||||||
|
try {
|
||||||
|
val connection = url.openConnection()
|
||||||
|
connection.connect()
|
||||||
|
// this will be useful so that you can show a typical 0-100% progress bar
|
||||||
|
val fileLength = connection.contentLength
|
||||||
|
// download the file
|
||||||
|
val input = BufferedInputStream(connection.getInputStream())
|
||||||
|
val output = ByteArrayOutputStream()
|
||||||
|
|
||||||
|
val data = ByteArray(1024)
|
||||||
|
var count: Int = 0
|
||||||
|
while ({count = input.read(data); count}() != -1) {
|
||||||
|
output.write(data, 0, count)
|
||||||
|
}
|
||||||
|
output.flush()
|
||||||
|
output.close()
|
||||||
|
input.close()
|
||||||
|
|
||||||
|
return output.toByteArray()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun load(file : File) : ByteArray {
|
||||||
|
return file.readBytes()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package oupson.apng
|
||||||
|
|
||||||
|
class Utils {
|
||||||
|
companion object {
|
||||||
|
enum class dispose_op {
|
||||||
|
APNG_DISPOSE_OP_NONE,
|
||||||
|
APNG_DISPOSE_OP_BACKGROUND,
|
||||||
|
APNG_DISPOSE_OP_PREVIOUS
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDispose_op(dispose_op: dispose_op) : Int {
|
||||||
|
return when(dispose_op) {
|
||||||
|
Companion.dispose_op.APNG_DISPOSE_OP_NONE -> 0
|
||||||
|
Companion.dispose_op.APNG_DISPOSE_OP_BACKGROUND -> 1
|
||||||
|
Companion.dispose_op.APNG_DISPOSE_OP_PREVIOUS -> 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
else -> dispose_op.APNG_DISPOSE_OP_NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class blend_op() {
|
||||||
|
APNG_BLEND_OP_SOURCE,
|
||||||
|
APNG_BLEND_OP_OVER
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBlend_op(blend_op: blend_op) : Int {
|
||||||
|
return when(blend_op) {
|
||||||
|
Companion.blend_op.APNG_BLEND_OP_SOURCE -> 0
|
||||||
|
Companion.blend_op.APNG_BLEND_OP_OVER -> 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
else -> blend_op.APNG_BLEND_OP_SOURCE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,46 +0,0 @@
|
||||||
package oupson.apng.customView
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.widget.ImageView
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.os.Handler
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import oupson.apng.extractedFrame
|
|
||||||
|
|
||||||
|
|
||||||
class ApngImageView(context: Context, attrs: AttributeSet) : ImageView(context, attrs) {
|
|
||||||
var Frames = ArrayList<extractedFrame>()
|
|
||||||
var myHandler: Handler
|
|
||||||
var counter = 0
|
|
||||||
|
|
||||||
val generatedFrame = ArrayList<Bitmap>()
|
|
||||||
|
|
||||||
init {
|
|
||||||
myHandler = Handler()
|
|
||||||
}
|
|
||||||
fun load(frames : ArrayList<extractedFrame>) {
|
|
||||||
Frames = frames
|
|
||||||
|
|
||||||
Frames.forEach {
|
|
||||||
val btm = Bitmap.createBitmap(Frames[0].maxWidth, Frames[0].maxHeight, Bitmap.Config.ARGB_8888)
|
|
||||||
val canvas = Canvas(btm)
|
|
||||||
canvas.drawBitmap(it.bitmap, it.xoffset.toFloat(), it.yoffset.toFloat(), null)
|
|
||||||
generatedFrame.add(btm)
|
|
||||||
}
|
|
||||||
|
|
||||||
nextFrame()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun nextFrame() {
|
|
||||||
if (counter == Frames.size) {
|
|
||||||
counter = 0
|
|
||||||
}
|
|
||||||
val delay = Frames[counter].delay
|
|
||||||
this.setImageBitmap(generatedFrame[counter])
|
|
||||||
counter++
|
|
||||||
myHandler.postDelayed({
|
|
||||||
nextFrame()
|
|
||||||
}, delay.toLong())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,5 @@
|
||||||
package oupson.apng
|
package oupson.apng
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
|
|
||||||
class fcTL(byteArray: ByteArray) {
|
class fcTL(byteArray: ByteArray) {
|
||||||
|
|
||||||
private var corpsSize = -1
|
private var corpsSize = -1
|
||||||
|
|
|
@ -30,7 +30,7 @@ android {
|
||||||
productFlavors {
|
productFlavors {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ext.anko_version='0.10.6'
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
implementation 'com.android.support:appcompat-v7:27.1.1'
|
implementation 'com.android.support:appcompat-v7:27.1.1'
|
||||||
|
@ -39,4 +39,6 @@ dependencies {
|
||||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||||
implementation project(':apng_library')
|
implementation project(':apng_library')
|
||||||
|
implementation "org.jetbrains.anko:anko:$anko_version"
|
||||||
|
implementation 'com.squareup.picasso:picasso:2.71828'
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="oupson.apngcreator">
|
package="oupson.apngcreator">
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
|
|
@ -10,18 +10,32 @@ import oupson.apng.APNGDisassembler
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import android.os.Environment.getExternalStorageDirectory
|
import android.os.Environment.getExternalStorageDirectory
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
|
import org.jetbrains.anko.doAsync
|
||||||
import oupson.apng.ApngAnimator
|
import oupson.apng.ApngAnimator
|
||||||
|
import java.nio.file.Files.exists
|
||||||
|
import android.system.Os.mkdir
|
||||||
|
import android.util.Log
|
||||||
|
import android.widget.Toast
|
||||||
|
import com.squareup.picasso.Picasso
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
|
import java.net.HttpURLConnection
|
||||||
|
import java.net.HttpURLConnection.HTTP_OK
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
lateinit var animator : ApngAnimator
|
lateinit var animator : ApngAnimator
|
||||||
|
|
||||||
|
val imageUrl = "http://oupson.oupsman.fr/apng/image.apng"
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
animator = ApngAnimator(imageView)
|
animator = ApngAnimator(imageView)
|
||||||
animator.load(File(File(Environment.getExternalStorageDirectory(), "documents"), "image_3.png"))
|
animator.load(imageUrl)
|
||||||
|
|
||||||
|
Picasso.get().load(imageUrl).into(imageView2);
|
||||||
|
|
||||||
|
|
||||||
play.setOnClickListener {
|
play.setOnClickListener {
|
||||||
animator.play()
|
animator.play()
|
||||||
|
|
|
@ -26,6 +26,18 @@
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imageView2"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/play"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/imageView"
|
||||||
|
app:srcCompat="@android:color/transparent" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/imageView"
|
android:id="@+id/imageView"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
@ -33,8 +45,7 @@
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginBottom="8dp"
|
app:layout_constraintBottom_toTopOf="@+id/imageView2"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/play"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
|
Loading…
Reference in New Issue