Prepare to first release
This commit is contained in:
parent
efbe651377
commit
13a6a7266e
Binary file not shown.
|
@ -5,28 +5,25 @@ import android.graphics.BitmapFactory
|
|||
import android.graphics.Canvas
|
||||
import oupson.apng.ApngFactory.Companion.pngSignature
|
||||
import oupson.apng.Utils.Companion.to4Bytes
|
||||
import oupson.apng.chunks.IHDR
|
||||
import oupson.apng.chunks.fcTL
|
||||
import oupson.apng.exceptions.NotApngException
|
||||
import java.util.zip.CRC32
|
||||
|
||||
class APNGDisassembler(val byteArray: ByteArray) {
|
||||
val pngList = ArrayList<Frame>()
|
||||
var png : ArrayList<Byte>? = null
|
||||
|
||||
var cover : ArrayList<Byte>? = 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
|
||||
|
||||
init {
|
||||
if (ApngFactory.isApng(byteArray)) {
|
||||
val ihdr = IHDR()
|
||||
|
@ -48,8 +45,7 @@ class APNGDisassembler(val byteArray: ByteArray) {
|
|||
cover!!.addAll(to4Bytes(crC32.value.toInt()).toList())
|
||||
}
|
||||
png = ArrayList()
|
||||
|
||||
val fcTL = fcTL(byteArray.copyOfRange(i-4, i + 32))
|
||||
val fcTL = fcTL(byteArray.copyOfRange(i - 4, i + 32))
|
||||
delay = fcTL.delay
|
||||
yOffset = fcTL.y_offset
|
||||
xOffset = fcTL.x_offset
|
||||
|
@ -81,7 +77,7 @@ class APNGDisassembler(val byteArray: ByteArray) {
|
|||
|
||||
png = ArrayList()
|
||||
|
||||
val fcTL = fcTL(byteArray.copyOfRange(i-4, i + 32))
|
||||
val fcTL = fcTL(byteArray.copyOfRange(i - 4, i + 32))
|
||||
delay = fcTL.delay
|
||||
|
||||
yOffset = fcTL.y_offset
|
||||
|
@ -154,8 +150,6 @@ class APNGDisassembler(val byteArray: ByteArray) {
|
|||
byteArray.copyOfRange( i - 4, i).forEach {
|
||||
lengthString += String.format("%02x", it)
|
||||
}
|
||||
|
||||
|
||||
val bodySize = lengthString.toLong(16).toInt()
|
||||
png!!.addAll(to4Bytes(bodySize - 4).toList())
|
||||
val body = ArrayList<Byte>()
|
||||
|
@ -168,22 +162,23 @@ class APNGDisassembler(val byteArray: ByteArray) {
|
|||
crC32.update(body.toByteArray(), 0, body.size)
|
||||
png!!.addAll(body)
|
||||
png!!.addAll(to4Bytes(crC32.value.toInt()).toList())
|
||||
} else if (byteArray[i] == 0x50.toByte() && byteArray[i + 1] == 0x4C.toByte() && byteArray[ i + 2 ] == 0x54.toByte() && byteArray[ i + 3 ] == 0x45.toByte()) {
|
||||
}
|
||||
// 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()
|
||||
val body = ArrayList<Byte>()
|
||||
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()
|
||||
val body = ArrayList<Byte>()
|
||||
tnrs = byteArray.copyOfRange( i -4, i + 8 + bodySize)
|
||||
}
|
||||
}
|
||||
|
@ -194,25 +189,18 @@ class APNGDisassembler(val byteArray: ByteArray) {
|
|||
|
||||
private fun generate_ihdr(ihdrOfApng: IHDR, width : Int, height : Int) : ByteArray {
|
||||
val ihdr = ArrayList<Byte>()
|
||||
|
||||
// We need a body var to know body length and generate crc
|
||||
val ihdr_body = ArrayList<Byte>()
|
||||
|
||||
// Get max height and max width of all the frames
|
||||
|
||||
// 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)
|
||||
|
@ -232,7 +220,4 @@ class APNGDisassembler(val byteArray: ByteArray) {
|
|||
}
|
||||
return generatedFrame
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -2,13 +2,14 @@ package oupson.apng
|
|||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.util.Log
|
||||
import oupson.apng.Utils.Companion.convertImage
|
||||
import oupson.apng.Utils.Companion.getBlend_op
|
||||
import oupson.apng.Utils.Companion.getDispose_op
|
||||
import oupson.apng.Utils.Companion.to2Bytes
|
||||
import oupson.apng.Utils.Companion.to4Bytes
|
||||
import oupson.apng.Utils.Companion.toByteArray
|
||||
import oupson.apng.chunks.IDAT
|
||||
import oupson.apng.exceptions.NoFrameException
|
||||
import java.util.zip.CRC32
|
||||
|
||||
|
||||
|
@ -20,6 +21,11 @@ class Apng {
|
|||
var maxWidth : Int? = null
|
||||
var maxHeight : Int? = null
|
||||
|
||||
/**
|
||||
* Image that will display in non compatible reader
|
||||
* It's not necessary if the first frame is the biggest image.
|
||||
* If it's null the library generate a cover with the first frame
|
||||
*/
|
||||
var cover : Bitmap? = null
|
||||
set(value) {
|
||||
field = convertImage(value!!)
|
||||
|
@ -141,6 +147,7 @@ class Apng {
|
|||
// region fcTL
|
||||
// Create the fcTL
|
||||
val fcTL = ArrayList<Byte>()
|
||||
|
||||
// Add the length of the chunk body
|
||||
framesByte.addAll(byteArrayOf(0x00, 0x00, 0x00, 0x1A).toList())
|
||||
|
||||
|
@ -149,6 +156,7 @@ class Apng {
|
|||
|
||||
// Add the frame number
|
||||
fcTL.addAll(to4Bytes(seq).toList())
|
||||
// foreach fcTL or fdAT we must increment seq
|
||||
seq++
|
||||
|
||||
// Add width and height
|
||||
|
@ -156,7 +164,6 @@ class Apng {
|
|||
fcTL.addAll(to4Bytes(frames[0].height).toList())
|
||||
|
||||
// Calculate offset
|
||||
|
||||
if (frames[0].x_offsets == null) {
|
||||
if (frames[0].width < maxWitdh) {
|
||||
val xOffset = (maxWitdh / 2) - (frames[0].width / 2)
|
||||
|
@ -179,9 +186,11 @@ class Apng {
|
|||
fcTL.addAll(to2Bytes(frames[0].delay.toInt()).toList())
|
||||
fcTL.addAll(to2Bytes(1000).toList())
|
||||
|
||||
// Add dispose_op and blend_op
|
||||
fcTL.add(getDispose_op(frames[0].dispose_op).toByte())
|
||||
fcTL.add(getBlend_op(frames[0].blend_op).toByte())
|
||||
|
||||
// Create CRC
|
||||
val crc = CRC32()
|
||||
crc.update(fcTL.toByteArray(), 0, fcTL.size)
|
||||
framesByte.addAll(fcTL)
|
||||
|
@ -190,25 +199,25 @@ class Apng {
|
|||
|
||||
// region idat
|
||||
frames[0].idat.IDATBody.forEach {
|
||||
val fdat = ArrayList<Byte>()
|
||||
val idat = ArrayList<Byte>()
|
||||
// Add the chunk body length
|
||||
framesByte.addAll(to4Bytes(it.size).toList())
|
||||
// Add IDAT
|
||||
fdat.addAll(byteArrayOf(0x49, 0x44, 0x41, 0x54).toList())
|
||||
idat.addAll(byteArrayOf(0x49, 0x44, 0x41, 0x54).toList())
|
||||
// Add chunk body
|
||||
fdat.addAll(it.toList())
|
||||
idat.addAll(it.toList())
|
||||
// Generate CRC
|
||||
val crc1 = CRC32()
|
||||
crc1.update(fdat.toByteArray(), 0, fdat.size)
|
||||
framesByte.addAll(fdat)
|
||||
crc1.update(idat.toByteArray(), 0, idat.size)
|
||||
framesByte.addAll(idat)
|
||||
framesByte.addAll(to4Bytes(crc1.value.toInt()).toList())
|
||||
}
|
||||
// endregion
|
||||
res.addAll(framesByte)
|
||||
} else {
|
||||
val framesByte = ArrayList<Byte>()
|
||||
// Add cover image : Not part of annimation
|
||||
// region idat
|
||||
// Add cover image : Not part of animation
|
||||
// region IDAT
|
||||
val idat = IDAT()
|
||||
idat.parseIDAT(toByteArray(cover!!))
|
||||
idat.IDATBody.forEach {
|
||||
|
@ -223,10 +232,10 @@ class Apng {
|
|||
}
|
||||
// endregion
|
||||
|
||||
//region fcTL
|
||||
val fcTL = ArrayList<Byte>()
|
||||
// Add the length of the chunk body
|
||||
framesByte.addAll(byteArrayOf(0x00, 0x00, 0x00, 0x1A).toList())
|
||||
|
||||
// Add fcTL
|
||||
fcTL.addAll(byteArrayOf(0x66, 0x63, 0x54, 0x4c).toList())
|
||||
|
||||
|
@ -261,9 +270,11 @@ class Apng {
|
|||
fcTL.addAll(to2Bytes(frames[0].delay.toInt()).toList())
|
||||
fcTL.addAll(to2Bytes(1000).toList())
|
||||
|
||||
// Add dispose_op and blend_op
|
||||
fcTL.add(getDispose_op(frames[0].dispose_op).toByte())
|
||||
fcTL.add(getBlend_op(frames[0].blend_op).toByte())
|
||||
|
||||
// Generate CRC
|
||||
val crc = CRC32()
|
||||
crc.update(fcTL.toByteArray(), 0, fcTL.size)
|
||||
framesByte.addAll(fcTL)
|
||||
|
@ -292,7 +303,6 @@ class Apng {
|
|||
}
|
||||
|
||||
for (i in 1 until frames.size) {
|
||||
Log.e("Seq", seq.toString())
|
||||
// If it's the first frame
|
||||
val framesByte = ArrayList<Byte>()
|
||||
val fcTL = ArrayList<Byte>()
|
||||
|
@ -362,8 +372,6 @@ class Apng {
|
|||
// endregion
|
||||
res.addAll(framesByte)
|
||||
}
|
||||
|
||||
|
||||
if (frames.isNotEmpty()) {
|
||||
|
||||
// Add IEND body length : 0
|
||||
|
@ -381,7 +389,14 @@ class Apng {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate a cover image that have the max width and height.
|
||||
* You could also set yours
|
||||
* @param bitmap The bitmap of the cover
|
||||
* @param maxWidth Max width of APNG
|
||||
* @param maxHeight Max height of the APNG
|
||||
* @return An image cover
|
||||
*/
|
||||
fun generateCover(bitmap: Bitmap, maxWidth : Int, maxHeight : Int) : Bitmap {
|
||||
return Bitmap.createScaledBitmap(bitmap, maxWidth, maxHeight, false)
|
||||
}
|
||||
|
|
|
@ -4,11 +4,9 @@ import android.graphics.*
|
|||
import android.graphics.drawable.AnimationDrawable
|
||||
import android.os.Environment
|
||||
import android.os.Handler
|
||||
import android.util.Log
|
||||
import android.widget.ImageView
|
||||
import org.jetbrains.anko.doAsync
|
||||
import org.jetbrains.anko.uiThread
|
||||
import oupson.apng.Utils.Companion.toByteArray
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
|
@ -17,12 +15,11 @@ import java.net.URL
|
|||
|
||||
class ApngAnimator {
|
||||
var isPlaying = true
|
||||
get() = field
|
||||
private set(value) {field = value}
|
||||
|
||||
var Frames = ArrayList<Frame>()
|
||||
|
||||
var myHandler: Handler
|
||||
var myHandler: Handler = Handler()
|
||||
|
||||
var counter = 0
|
||||
|
||||
|
@ -35,14 +32,8 @@ class ApngAnimator {
|
|||
|
||||
var background : Bitmap? = null
|
||||
|
||||
var isDebug = false
|
||||
|
||||
val imageView : ImageView?
|
||||
|
||||
init {
|
||||
myHandler = Handler()
|
||||
}
|
||||
|
||||
constructor() {
|
||||
imageView = null
|
||||
}
|
||||
|
@ -50,7 +41,11 @@ class ApngAnimator {
|
|||
this.imageView = imageView
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load an APNG file
|
||||
* @param file The file to load
|
||||
* @throws NotApngException
|
||||
*/
|
||||
fun load(file: File) {
|
||||
// Download PNG
|
||||
val extractedFrame = APNGDisassembler(file.readBytes()).pngList
|
||||
|
@ -65,28 +60,20 @@ class ApngAnimator {
|
|||
for (i in 1 until Frames.size) {
|
||||
// Iterator
|
||||
val it = Frames.get(i)
|
||||
|
||||
// Current bitmap for the frame
|
||||
val btm = Bitmap.createBitmap(Frames[0].maxWidth!!, Frames[0].maxHeight!!, Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(btm)
|
||||
|
||||
val current = BitmapFactory.decodeByteArray(it.byteArray, 0, it.byteArray.size).copy(Bitmap.Config.ARGB_8888, true)
|
||||
|
||||
// Write buffer to canvas
|
||||
canvas.drawBitmap(bitmapBuffer, 0f, 0f, null)
|
||||
|
||||
|
||||
|
||||
// Clear current frame rect
|
||||
// If `blend_op` is APNG_BLEND_OP_SOURCE all color components of the frame, including alpha, overwrite the current contents of the frame's output buffer region.
|
||||
if (it.blend_op == Utils.Companion.blend_op.APNG_BLEND_OP_SOURCE) {
|
||||
canvas.drawRect(it.x_offsets!!.toFloat(), it.y_offsets!!.toFloat(), it.x_offsets!! + current.width.toFloat(), it.y_offsets!! + current.height.toFloat(), { val paint = Paint(); paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR); paint }())
|
||||
}
|
||||
|
||||
// Draw the bitmap
|
||||
canvas.drawBitmap(current, it.x_offsets!!.toFloat(), it.y_offsets!!.toFloat(), null)
|
||||
generatedFrame.add(btm)
|
||||
|
||||
// Don't add current frame to bitmap buffer
|
||||
if (Frames[i].dispose_op == Utils.Companion.dispose_op.APNG_DISPOSE_OP_PREVIOUS) {
|
||||
//Do nothings
|
||||
|
@ -104,76 +91,42 @@ class ApngAnimator {
|
|||
bitmapBuffer = btm
|
||||
}
|
||||
}
|
||||
// DEBUG FUNCTION : WRITE RENDERED FRAME TO EXTERNAL STORAGE
|
||||
if (isDebug) {
|
||||
for (i in 0 until generatedFrame.size) {
|
||||
try {
|
||||
FileOutputStream(File(File(Environment.getExternalStorageDirectory(), "Documents"), "image_$i.png")).use { out ->
|
||||
generatedFrame[i].compress(Bitmap.CompressFormat.PNG, 100, out) // bmp is your Bitmap instance
|
||||
// PNG is a lossless format, the compression factor (100) is ignored
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
nextFrame()
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an APNG file
|
||||
* @param url URL to load
|
||||
* @throws NotApngException
|
||||
*/
|
||||
private fun loadUrl(url : URL) {
|
||||
doAsync(exceptionHandler = {e -> e.printStackTrace()}) {
|
||||
doAsync(exceptionHandler = {e -> throw e}) {
|
||||
// Download PNG
|
||||
val extractedFrame = APNGDisassembler(Loader().load(url)).pngList
|
||||
|
||||
// DEBUG FUNCTION : WRITE RENDERED FRAME TO EXTERNAL STORAGE
|
||||
if (isDebug) {
|
||||
for (i in 0 until extractedFrame.size) {
|
||||
try {
|
||||
FileOutputStream(File(File(Environment.getExternalStorageDirectory(), "Documents"), "image_$i.png")).use { out ->
|
||||
out.write(extractedFrame[i].byteArray)
|
||||
// PNG is a lossless format, the compression factor (100) is ignored
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set last frame
|
||||
lastFrame = extractedFrame[0]
|
||||
|
||||
// Init image buffer
|
||||
bitmapBuffer = BitmapFactory.decodeByteArray(lastFrame?.byteArray!!, 0, lastFrame?.byteArray!!.size)
|
||||
|
||||
Log.e("ApngAnimator", "bitmapBuffer is null : ${bitmapBuffer == null}")
|
||||
generatedFrame.add(BitmapFactory.decodeByteArray(lastFrame?.byteArray, 0, lastFrame?.byteArray!!.size))
|
||||
Frames = extractedFrame
|
||||
for (i in 1 until Frames.size) {
|
||||
Log.e("ApngAnimator", "Render $i frame")
|
||||
// Iterator
|
||||
val it = Frames.get(i)
|
||||
|
||||
// Current bitmap for the frame
|
||||
val btm = Bitmap.createBitmap(Frames[0].maxWidth!!, Frames[0].maxHeight!!, Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(btm)
|
||||
|
||||
val current = BitmapFactory.decodeByteArray(it.byteArray, 0, it.byteArray.size).copy(Bitmap.Config.ARGB_8888, true)
|
||||
|
||||
// Write buffer to canvas
|
||||
canvas.drawBitmap(bitmapBuffer, 0f, 0f, null)
|
||||
|
||||
|
||||
|
||||
// Clear current frame rect
|
||||
// If `blend_op` is APNG_BLEND_OP_SOURCE all color components of the frame, including alpha, overwrite the current contents of the frame's output buffer region.
|
||||
if (it.blend_op == Utils.Companion.blend_op.APNG_BLEND_OP_SOURCE) {
|
||||
canvas.drawRect(it.x_offsets!!.toFloat(), it.y_offsets!!.toFloat(), it.x_offsets!! + current.width.toFloat(), it.y_offsets!! + current.height.toFloat(), { val paint = Paint(); paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR); paint }())
|
||||
}
|
||||
|
||||
// Draw the bitmap
|
||||
canvas.drawBitmap(current, it.x_offsets!!.toFloat(), it.y_offsets!!.toFloat(), null)
|
||||
generatedFrame.add(btm)
|
||||
|
||||
// Don't add current frame to bitmap buffer
|
||||
if (Frames[i].dispose_op == Utils.Companion.dispose_op.APNG_DISPOSE_OP_PREVIOUS) {
|
||||
//Do nothings
|
||||
|
@ -191,19 +144,6 @@ class ApngAnimator {
|
|||
bitmapBuffer = btm
|
||||
}
|
||||
}
|
||||
// DEBUG FUNCTION : WRITE RENDERED FRAME TO EXTERNAL STORAGE
|
||||
if (isDebug) {
|
||||
for (i in 0 until generatedFrame.size) {
|
||||
try {
|
||||
FileOutputStream(File(File(Environment.getExternalStorageDirectory(), "Documents"), "image_$i.png")).use { out ->
|
||||
generatedFrame[i].compress(Bitmap.CompressFormat.PNG, 100, out) // bmp is your Bitmap instance
|
||||
// PNG is a lossless format, the compression factor (100) is ignored
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
uiThread {
|
||||
nextFrame()
|
||||
}
|
||||
|
@ -263,19 +203,6 @@ class ApngAnimator {
|
|||
bitmapBuffer = btm
|
||||
}
|
||||
}
|
||||
// DEBUG FUNCTION : WRITE RENDERED FRAME TO EXTERNAL STORAGE
|
||||
if (isDebug) {
|
||||
for (i in 0 until generatedFrame.size) {
|
||||
try {
|
||||
FileOutputStream(File(File(Environment.getExternalStorageDirectory(), "Documents"), "image_$i.png")).use { out ->
|
||||
generatedFrame[i].compress(Bitmap.CompressFormat.PNG, 100, out) // bmp is your Bitmap instance
|
||||
// PNG is a lossless format, the compression factor (100) is ignored
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
nextFrame()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package oupson.apng
|
||||
|
||||
import oupson.apng.exceptions.NoFrameException
|
||||
import java.util.zip.CRC32
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package oupson.apng
|
||||
|
||||
import oupson.apng.ApngFactory.Companion.isPng
|
||||
import oupson.apng.chunks.IDAT
|
||||
import oupson.apng.chunks.IHDR
|
||||
import oupson.apng.exceptions.NotPngException
|
||||
|
||||
/**
|
||||
* A frame for an animated png
|
||||
|
|
|
@ -2,7 +2,6 @@ package oupson.apng
|
|||
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.net.URL
|
||||
|
||||
|
@ -11,27 +10,19 @@ class Loader {
|
|||
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
|
||||
var count = 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()
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package oupson.apng
|
||||
package oupson.apng.chunks
|
||||
|
||||
class IDAT {
|
||||
private var bodySize = -1
|
|
@ -1,4 +1,4 @@
|
|||
package oupson.apng
|
||||
package oupson.apng.chunks
|
||||
|
||||
class IHDR {
|
||||
private var corpsSize = -1
|
|
@ -1,5 +1,6 @@
|
|||
package oupson.apng
|
||||
package oupson.apng.chunks
|
||||
|
||||
import oupson.apng.Utils
|
||||
import oupson.apng.Utils.Companion.getBlend_op
|
||||
import oupson.apng.Utils.Companion.getDispose_op
|
||||
|
||||
|
@ -20,7 +21,7 @@ class fcTL(byteArray: ByteArray) {
|
|||
var y_offset : Int = 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 dispose_op : Utils.Companion.dispose_op = Utils.Companion.dispose_op.APNG_DISPOSE_OP_NONE
|
||||
init {
|
||||
for (i in 0 until byteArray.size) {
|
||||
// Find fcTL chunk
|
|
@ -1,4 +1,4 @@
|
|||
package oupson.apng
|
||||
package oupson.apng.chunks
|
||||
|
||||
class fdAT {
|
||||
private var bodySize = -1
|
|
@ -1,4 +1,4 @@
|
|||
package oupson.apng
|
||||
package oupson.apng.exceptions
|
||||
|
||||
class NoFrameException() : Exception()
|
||||
class NotPngException() : Exception()
|
|
@ -1,3 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">apng</string>
|
||||
<string name="app_name">KAPNG</string>
|
||||
</resources>
|
||||
|
|
|
@ -32,6 +32,7 @@ android {
|
|||
}
|
||||
ext.anko_version = '0.10.7'
|
||||
dependencies {
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
//noinspection GradleCompatible
|
||||
implementation 'com.android.support:appcompat-v7:27.1.1'
|
||||
|
@ -39,9 +40,10 @@ dependencies {
|
|||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
implementation project(':apng_library')
|
||||
implementation "org.jetbrains.anko:anko:$anko_version"
|
||||
implementation 'com.squareup.picasso:picasso:2.71828'
|
||||
implementation project(":apng_library")
|
||||
// implementation fileTree(include: ['*.aar'], dir: 'libs')
|
||||
}
|
||||
kotlin {
|
||||
experimental {
|
||||
|
|
Binary file not shown.
|
@ -38,7 +38,6 @@ class MainActivity : AppCompatActivity() {
|
|||
setContentView(R.layout.activity_main)
|
||||
|
||||
animator = ApngAnimator(imageView)
|
||||
animator.isDebug = true
|
||||
animator.load(imageUrl)
|
||||
|
||||
Picasso.get().load(imageUrl).into(imageView2);
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.2.61'
|
||||
ext.kotlin_version = '1.2.60'
|
||||
ext.kotlin_version = '1.2.71'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
|
|
Loading…
Reference in New Issue