parent
f84419a6c0
commit
efbe651377
Binary file not shown.
|
@ -32,7 +32,7 @@ dependencies {
|
|||
androidTestImplementation 'com.android.support.test:runner:1.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.anko:anko:0.10.6"
|
||||
implementation "org.jetbrains.anko:anko:0.10.7"
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
|
|
@ -3,8 +3,8 @@ package oupson.apng
|
|||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Canvas
|
||||
import android.util.Log
|
||||
import oupson.apng.ApngFactory.Companion.pngSignature
|
||||
import oupson.apng.Utils.Companion.to4Bytes
|
||||
import java.util.zip.CRC32
|
||||
|
||||
class APNGDisassembler(val byteArray: ByteArray) {
|
||||
|
@ -105,11 +105,10 @@ class APNGDisassembler(val byteArray: ByteArray) {
|
|||
// 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) {
|
||||
png = ArrayList()
|
||||
if (cover == null) {
|
||||
cover = ArrayList()
|
||||
png!!.addAll(pngSignature.toList())
|
||||
png!!.addAll(generate_ihdr(ihdr, maxWidth, maxHeight).toList())
|
||||
cover!!.addAll(pngSignature.toList())
|
||||
cover!!.addAll(generate_ihdr(ihdr, maxWidth, maxHeight).toList())
|
||||
}
|
||||
// Find the chunk length
|
||||
var lengthString = ""
|
||||
|
@ -222,30 +221,11 @@ class APNGDisassembler(val byteArray: ByteArray) {
|
|||
return ihdr.toByteArray()
|
||||
}
|
||||
|
||||
fun to4Bytes(i: Int): ByteArray {
|
||||
val result = ByteArray(4)
|
||||
result[0] = (i shr 24).toByte()
|
||||
result[1] = (i shr 16).toByte()
|
||||
result[2] = (i shr 8).toByte()
|
||||
result[3] = i /*>> 0*/.toByte()
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a 2 bytes array from an Int
|
||||
* @param i The int
|
||||
*/
|
||||
fun to2Bytes(i: Int): ByteArray {
|
||||
val result = ByteArray(2)
|
||||
result[0] = (i shr 8).toByte()
|
||||
result[1] = i /*>> 0*/.toByte()
|
||||
return result
|
||||
}
|
||||
|
||||
fun genBitmap() : ArrayList<Bitmap> {
|
||||
val generatedFrame = ArrayList<Bitmap>()
|
||||
pngList.forEach {
|
||||
val btm = Bitmap.createBitmap(it.maxWidth, it.maxHeight, Bitmap.Config.ARGB_8888)
|
||||
val btm = Bitmap.createBitmap(it.maxWidth!!, it.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)
|
||||
|
|
|
@ -11,9 +11,11 @@ import oupson.apng.Utils.Companion.to4Bytes
|
|||
import oupson.apng.Utils.Companion.toByteArray
|
||||
import java.util.zip.CRC32
|
||||
|
||||
class Apng {
|
||||
|
||||
private var seq = 0
|
||||
/**
|
||||
* Create an APNG file
|
||||
*/
|
||||
class Apng {
|
||||
|
||||
var maxWidth : Int? = null
|
||||
var maxHeight : Int? = null
|
||||
|
@ -25,30 +27,101 @@ class Apng {
|
|||
|
||||
var frames : ArrayList<Frame> = ArrayList()
|
||||
|
||||
init {
|
||||
|
||||
}
|
||||
|
||||
// region addFrames
|
||||
|
||||
/**
|
||||
* Add a frame to the APNG
|
||||
* @param bitmap The bitamp to add
|
||||
*/
|
||||
fun addFrames(bitmap: Bitmap) {
|
||||
frames.add(Frame(toByteArray(bitmap)))
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a frame to the APNG
|
||||
* @param bitmap The bitamp to add
|
||||
* @param delay Delay of the frame
|
||||
*/
|
||||
fun addFrames(bitmap: Bitmap, delay : Float) {
|
||||
frames.add(Frame(toByteArray(bitmap), delay))
|
||||
}
|
||||
|
||||
fun addFrames(bitmap: Bitmap, delay: Float, blend_op: Utils.Companion.blend_op, dispose_op: Utils.Companion.dispose_op) {
|
||||
/**
|
||||
* Add a frame to the APNG
|
||||
* @param bitmap The bitamp to add
|
||||
* @param delay Delay of the frame
|
||||
* @param dispose_op `dispose_op` specifies how the output buffer should be changed at the end of the delay (before rendering the next frame).
|
||||
* @param blend_op `blend_op` specifies whether the frame is to be alpha blended into the current output buffer content, or whether it should completely replace its region in the output buffer.
|
||||
*/
|
||||
fun addFrames(bitmap: Bitmap, delay: Float, dispose_op: Utils.Companion.dispose_op, blend_op: Utils.Companion.blend_op) {
|
||||
frames.add(Frame(toByteArray(bitmap), delay, blend_op, dispose_op))
|
||||
}
|
||||
|
||||
fun addFrames(bitmap: Bitmap, delay: Float, xOffset : Int, yOffset : Int, blend_op: Utils.Companion.blend_op, dispose_op: Utils.Companion.dispose_op) {
|
||||
/**
|
||||
* Add a frame to the APNG
|
||||
* @param bitmap The bitamp to add
|
||||
* @param delay Delay of the frame
|
||||
* @param xOffset The X offset where the frame should be rendered
|
||||
* @param yOffset The Y offset where the frame should be rendered
|
||||
* @param dispose_op `dispose_op` specifies how the output buffer should be changed at the end of the delay (before rendering the next frame).
|
||||
* @param blend_op `blend_op` specifies whether the frame is to be alpha blended into the current output buffer content, or whether it should completely replace its region in the output buffer.
|
||||
*/
|
||||
fun addFrames(bitmap: Bitmap, delay: Float, xOffset : Int, yOffset : Int, dispose_op: Utils.Companion.dispose_op, blend_op: Utils.Companion.blend_op) {
|
||||
frames.add(Frame(toByteArray(bitmap), delay, xOffset, yOffset, blend_op, dispose_op))
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a frame to the APNG
|
||||
* @param index Index where we add the frame
|
||||
* @param bitmap The bitamp to add
|
||||
*/
|
||||
fun addFrames(index : Int, bitmap: Bitmap) {
|
||||
frames.add(index, Frame(toByteArray(bitmap)))
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a frame to the APNG
|
||||
* @param index Index where we add the frame
|
||||
* @param bitmap The bitamp to add
|
||||
* @param delay Delay of the frame
|
||||
*/
|
||||
fun addFrames(index : Int, bitmap: Bitmap, delay : Float) {
|
||||
frames.add(index, Frame(toByteArray(bitmap), delay))
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a frame to the APNG
|
||||
* @param index Index where we add the frame
|
||||
* @param bitmap The bitamp to add
|
||||
* @param delay Delay of the frame
|
||||
* @param dispose_op `dispose_op` specifies how the output buffer should be changed at the end of the delay (before rendering the next frame).
|
||||
* @param blend_op `blend_op` specifies whether the frame is to be alpha blended into the current output buffer content, or whether it should completely replace its region in the output buffer.
|
||||
*/
|
||||
fun addFrames(index: Int, bitmap: Bitmap, delay: Float, dispose_op: Utils.Companion.dispose_op, blend_op: Utils.Companion.blend_op) {
|
||||
frames.add(index, Frame(toByteArray(bitmap), delay, blend_op, dispose_op))
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a frame to the APNG
|
||||
* @param index Index where we add the frame
|
||||
* @param bitmap The bitamp to add
|
||||
* @param delay Delay of the frame
|
||||
* @param xOffset The X offset where the frame should be rendered
|
||||
* @param yOffset The Y offset where the frame should be rendered
|
||||
* @param dispose_op `dispose_op` specifies how the output buffer should be changed at the end of the delay (before rendering the next frame).
|
||||
* @param blend_op `blend_op` specifies whether the frame is to be alpha blended into the current output buffer content, or whether it should completely replace its region in the output buffer.
|
||||
*/
|
||||
fun addFrames(index: Int, bitmap: Bitmap, delay: Float, xOffset : Int, yOffset : Int, dispose_op: Utils.Companion.dispose_op, blend_op: Utils.Companion.blend_op) {
|
||||
frames.add(index, Frame(toByteArray(bitmap), delay, xOffset, yOffset, blend_op, dispose_op))
|
||||
}
|
||||
//endregion
|
||||
|
||||
fun generateAPNGByteArray() : ByteArray {
|
||||
seq = 0
|
||||
/**
|
||||
* Generate a Bytes Array of the APNG
|
||||
* @return The Bytes Array of the APNG
|
||||
*/
|
||||
fun toByteArray() : ByteArray {
|
||||
var seq = 0
|
||||
val res = ArrayList<Byte>()
|
||||
// Add PNG signature
|
||||
res.addAll(ApngFactory.pngSignature.toList())
|
||||
|
|
|
@ -4,9 +4,11 @@ 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
|
||||
|
@ -65,7 +67,7 @@ class ApngAnimator {
|
|||
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 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)
|
||||
|
@ -92,7 +94,7 @@ class ApngAnimator {
|
|||
// Add current frame to bitmap buffer
|
||||
// APNG_DISPOSE_OP_BACKGROUND: the frame's region of the output buffer is to be cleared to fully transparent black before rendering the next frame.
|
||||
else if (it.dispose_op == Utils.Companion.dispose_op.APNG_DISPOSE_OP_BACKGROUND){
|
||||
val res = Bitmap.createBitmap(Frames[0].maxWidth, Frames[0].maxHeight, Bitmap.Config.ARGB_8888)
|
||||
val res = Bitmap.createBitmap(Frames[0].maxWidth!!, Frames[0].maxHeight!!, Bitmap.Config.ARGB_8888)
|
||||
val can = Canvas(res)
|
||||
can.drawBitmap(btm, 0f, 0f, null)
|
||||
can.drawRect(lastFrame!!.x_offsets!!.toFloat(), lastFrame!!.y_offsets!!.toFloat(), lastFrame!!.x_offsets!! + lastFrame!!.width.toFloat(), lastFrame!!.y_offsets!! + lastFrame!!.height.toFloat(), { val paint = Paint(); paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR); paint }())
|
||||
|
@ -123,19 +125,36 @@ class ApngAnimator {
|
|||
// 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)
|
||||
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 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)
|
||||
|
@ -162,7 +181,7 @@ class ApngAnimator {
|
|||
// Add current frame to bitmap buffer
|
||||
// APNG_DISPOSE_OP_BACKGROUND: the frame's region of the output buffer is to be cleared to fully transparent black before rendering the next frame.
|
||||
else if (it.dispose_op == Utils.Companion.dispose_op.APNG_DISPOSE_OP_BACKGROUND){
|
||||
val res = Bitmap.createBitmap(Frames[0].maxWidth, Frames[0].maxHeight, Bitmap.Config.ARGB_8888)
|
||||
val res = Bitmap.createBitmap(Frames[0].maxWidth!!, Frames[0].maxHeight!!, Bitmap.Config.ARGB_8888)
|
||||
val can = Canvas(res)
|
||||
can.drawBitmap(btm, 0f, 0f, null)
|
||||
can.drawRect(lastFrame!!.x_offsets!!.toFloat(), lastFrame!!.y_offsets!!.toFloat(), lastFrame!!.x_offsets!! + lastFrame!!.width.toFloat(), lastFrame!!.y_offsets!! + lastFrame!!.height.toFloat(), { val paint = Paint(); paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR); paint }())
|
||||
|
@ -207,7 +226,7 @@ class ApngAnimator {
|
|||
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 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)
|
||||
|
@ -234,7 +253,7 @@ class ApngAnimator {
|
|||
// Add current frame to bitmap buffer
|
||||
// APNG_DISPOSE_OP_BACKGROUND: the frame's region of the output buffer is to be cleared to fully transparent black before rendering the next frame.
|
||||
else if (it.dispose_op == Utils.Companion.dispose_op.APNG_DISPOSE_OP_BACKGROUND){
|
||||
val res = Bitmap.createBitmap(Frames[0].maxWidth, Frames[0].maxHeight, Bitmap.Config.ARGB_8888)
|
||||
val res = Bitmap.createBitmap(Frames[0].maxWidth!!, Frames[0].maxHeight!!, Bitmap.Config.ARGB_8888)
|
||||
val can = Canvas(res)
|
||||
can.drawBitmap(btm, 0f, 0f, null)
|
||||
can.drawRect(lastFrame!!.x_offsets!!.toFloat(), lastFrame!!.y_offsets!!.toFloat(), lastFrame!!.x_offsets!! + lastFrame!!.width.toFloat(), lastFrame!!.y_offsets!! + lastFrame!!.height.toFloat(), { val paint = Paint(); paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR); paint }())
|
||||
|
|
|
@ -12,12 +12,12 @@ import oupson.apng.ApngFactory.Companion.isPng
|
|||
|
||||
class Frame {
|
||||
|
||||
val byteArray : ByteArray
|
||||
var byteArray : ByteArray
|
||||
|
||||
val width : Int
|
||||
val height : Int
|
||||
var width : Int
|
||||
var height : Int
|
||||
|
||||
val ihdr : IHDR
|
||||
var ihdr : IHDR
|
||||
|
||||
var idat : IDAT
|
||||
|
||||
|
@ -26,11 +26,11 @@ class Frame {
|
|||
var x_offsets : Int? = null
|
||||
var y_offsets : Int? = null
|
||||
|
||||
val maxWidth : Int
|
||||
val maxHeight : Int
|
||||
var maxWidth : Int? = null
|
||||
var maxHeight : Int? = null
|
||||
|
||||
val blend_op: Utils.Companion.blend_op
|
||||
val dispose_op : Utils.Companion.dispose_op
|
||||
var blend_op: Utils.Companion.blend_op
|
||||
var dispose_op : Utils.Companion.dispose_op
|
||||
|
||||
constructor(byteArray: ByteArray) {
|
||||
if (isPng(byteArray)) {
|
||||
|
@ -42,14 +42,12 @@ class Frame {
|
|||
width = ihdr.pngWidth
|
||||
height = ihdr.pngHeight
|
||||
|
||||
// Get image bytes
|
||||
// Get IDAT Bytes
|
||||
idat = IDAT()
|
||||
idat.parseIDAT(byteArray)
|
||||
|
||||
delay = 1000f
|
||||
|
||||
maxHeight = -1
|
||||
maxWidth = -1
|
||||
blend_op = Utils.Companion.blend_op.APNG_BLEND_OP_SOURCE
|
||||
dispose_op = Utils.Companion.dispose_op.APNG_DISPOSE_OP_NONE
|
||||
} else {
|
||||
|
@ -66,14 +64,11 @@ class Frame {
|
|||
width = ihdr.pngWidth
|
||||
height = ihdr.pngHeight
|
||||
|
||||
// Get image bytes
|
||||
// Get IDAT Bytes
|
||||
idat = IDAT()
|
||||
idat.parseIDAT(byteArray)
|
||||
|
||||
this.delay = delay
|
||||
|
||||
maxHeight = -1
|
||||
maxWidth = -1
|
||||
blend_op = Utils.Companion.blend_op.APNG_BLEND_OP_SOURCE
|
||||
dispose_op = Utils.Companion.dispose_op.APNG_DISPOSE_OP_NONE
|
||||
} else {
|
||||
|
@ -91,7 +86,7 @@ class Frame {
|
|||
width = ihdr.pngWidth
|
||||
height = ihdr.pngHeight
|
||||
|
||||
// Get image bytes
|
||||
// Get IDAT Bytes
|
||||
idat = IDAT()
|
||||
idat.parseIDAT(byteArray)
|
||||
|
||||
|
@ -117,7 +112,7 @@ class Frame {
|
|||
width = ihdr.pngWidth
|
||||
height = ihdr.pngHeight
|
||||
|
||||
// Get image bytes
|
||||
// Get IDAT Bytes
|
||||
idat = IDAT()
|
||||
idat.parseIDAT(byteArray)
|
||||
|
||||
|
@ -145,7 +140,7 @@ class Frame {
|
|||
width = ihdr.pngWidth
|
||||
height = ihdr.pngHeight
|
||||
|
||||
// Get image bytes
|
||||
// Get IDAT Bytes
|
||||
idat = IDAT()
|
||||
idat.parseIDAT(byteArray)
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package oupson.apng
|
||||
|
||||
import android.os.Bundle
|
||||
import android.widget.ImageView
|
||||
import java.io.*
|
||||
import java.net.URI
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.net.URL
|
||||
import java.net.URLConnection
|
||||
|
||||
class Loader {
|
||||
fun load(url : URL) : ByteArray {
|
||||
|
|
|
@ -12,6 +12,11 @@ class Utils {
|
|||
APNG_DISPOSE_OP_PREVIOUS
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the int equivalent to the dispose_op
|
||||
* @param dispose_op The dispose_op
|
||||
* @return An int equivalent to the dispose_op
|
||||
*/
|
||||
fun getDispose_op(dispose_op: dispose_op) : Int {
|
||||
return when(dispose_op) {
|
||||
Companion.dispose_op.APNG_DISPOSE_OP_NONE -> 0
|
||||
|
@ -20,6 +25,11 @@ class Utils {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dispose_op enum equivalent to the int
|
||||
* @param int Int of the dispose_op
|
||||
* @return A dispose_op
|
||||
*/
|
||||
fun getDispose_op(int: Int) : dispose_op {
|
||||
return when(int) {
|
||||
0 -> Companion.dispose_op.APNG_DISPOSE_OP_NONE
|
||||
|
@ -34,6 +44,11 @@ class Utils {
|
|||
APNG_BLEND_OP_OVER
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the int equivalent to the blend_op
|
||||
* @param blend_op The blend_op
|
||||
* @return An int equivalent to the blend_op
|
||||
*/
|
||||
fun getBlend_op(blend_op: blend_op) : Int {
|
||||
return when(blend_op) {
|
||||
Companion.blend_op.APNG_BLEND_OP_SOURCE -> 0
|
||||
|
@ -41,6 +56,11 @@ class Utils {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the blend_op enum equivalent to the int
|
||||
* @param int Int of the blend_op
|
||||
* @return A blend_op
|
||||
*/
|
||||
fun getBlend_op(int : Int) : blend_op{
|
||||
return when(int) {
|
||||
0 -> Companion.blend_op.APNG_BLEND_OP_SOURCE
|
||||
|
@ -49,12 +69,22 @@ class Utils {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get PNG ByteArray of Bitmap
|
||||
* @param bitmap The bitmap to convert
|
||||
* @return PNG ByteArray of the Bitmap
|
||||
*/
|
||||
fun toByteArray(bitmap: Bitmap) : ByteArray {
|
||||
val bos = ByteArrayOutputStream();
|
||||
convertImage(bitmap).compress(Bitmap.CompressFormat.PNG, 0 /*ignored for PNG*/, bos);
|
||||
return bos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the image
|
||||
* @param bitmap Bitmap to convert
|
||||
* @return Bitmap converted
|
||||
*/
|
||||
fun convertImage(bitmap: Bitmap) : Bitmap{
|
||||
val btm = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
|
||||
val canvas = Canvas(btm)
|
||||
|
@ -65,6 +95,7 @@ class Utils {
|
|||
/**
|
||||
* Generate a 4 bytes array from an Int
|
||||
* @param i The int
|
||||
* @return 2 Bytes
|
||||
*/
|
||||
fun to4Bytes(i: Int): ByteArray {
|
||||
val result = ByteArray(4)
|
||||
|
@ -78,6 +109,7 @@ class Utils {
|
|||
/**
|
||||
* Generate a 2 bytes array from an Int
|
||||
* @param i The int
|
||||
* @return 2 Bytes
|
||||
*/
|
||||
fun to2Bytes(i: Int): ByteArray {
|
||||
val result = ByteArray(2)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package oupson.apng
|
||||
|
||||
import android.util.Log
|
||||
import oupson.apng.Utils.Companion.getBlend_op
|
||||
import oupson.apng.Utils.Companion.getDispose_op
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ android {
|
|||
productFlavors {
|
||||
}
|
||||
}
|
||||
ext.anko_version = '0.10.6'
|
||||
ext.anko_version = '0.10.7'
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
//noinspection GradleCompatible
|
||||
|
|
|
@ -31,26 +31,17 @@ import java.net.URL
|
|||
class MainActivity : AppCompatActivity() {
|
||||
lateinit var animator : ApngAnimator
|
||||
|
||||
val imageUrl = "https://raw.githubusercontent.com/tinify/iMessage-Panda-sticker/master/Source/panda-original.png"
|
||||
val imageUrl = "https://metagif.files.wordpress.com/2015/01/bugbuckbunny.png"
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
val apng = Apng()
|
||||
val file1 = File(Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES), "hopital.jpg")
|
||||
val file2 = File(Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES), "test.jpg")
|
||||
apng.addFrames(BitmapFactory.decodeByteArray(file2.readBytes(), 0, file2.readBytes().size), 2000f, Utils.Companion.blend_op.APNG_BLEND_OP_OVER, Utils.Companion.dispose_op.APNG_DISPOSE_OP_NONE)
|
||||
|
||||
apng.addFrames(BitmapFactory.decodeByteArray(file1.readBytes(), 0, file1.readBytes().size), 1000f, Utils.Companion.blend_op.APNG_BLEND_OP_OVER, Utils.Companion.dispose_op.APNG_DISPOSE_OP_NONE)
|
||||
|
||||
animator = ApngAnimator(imageView)
|
||||
animator.load(apng.generateAPNGByteArray())
|
||||
animator.isDebug = true
|
||||
animator.load(imageUrl)
|
||||
|
||||
Picasso.get().load(imageUrl).into(imageView2);
|
||||
val out = File(Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES), "out.png")
|
||||
out.createNewFile()
|
||||
out.writeBytes(apng.generateAPNGByteArray())
|
||||
|
||||
play.setOnClickListener {
|
||||
animator.play()
|
||||
|
|
Loading…
Reference in New Issue