Working on optimiser functionality to reduce APNG size.

Add KDOC
This commit is contained in:
oupson 2018-11-14 16:21:12 +01:00
parent ed00672b0f
commit 0150810541
3 changed files with 52 additions and 14 deletions

View File

@ -30,9 +30,6 @@ class Apng {
* If it's null the library generate a cover with the first frame
*/
var cover : Bitmap? = null
set(value) {
field = value!!
}
var frames : ArrayList<Frame> = ArrayList()
@ -412,6 +409,10 @@ class Apng {
return Bitmap.createScaledBitmap(bitmap, maxWidth, maxHeight, false)
}
/**
* Generate the IHDR chunks.
* @return The byteArray generated
*/
private fun generateIhdr(): ByteArray {
val ihdr = ArrayList<Byte>()
@ -447,7 +448,10 @@ class Apng {
return ihdr.toByteArray()
}
// Animation Control chunk
/**
* Generate the animation control chunk
* @return The byteArray generated
*/
private fun generateACTL(): ArrayList<Byte> {
val res = ArrayList<Byte>()
val actl = ArrayList<Byte>()
@ -472,16 +476,38 @@ class Apng {
return res
}
fun optimise(quality : Int, maxColor : Int) {
val apng = Apng()
val pnn = PnnQuantizer(cover)
cover = pnn.convert(maxColor, false)
/**
* Reduce the apng size
* @param maxColor Max color you want in the image
* @param keepCover Keep the cover
* @param sizePercent Reduce image width/height by percents.
*/
fun reduceSize( maxColor : Int, keepCover : Boolean? = null, sizePercent : Int? = null) {
val apng = Apng()
if (keepCover != false) {
if (cover != null) {
if (sizePercent != null) {
cover = Bitmap.createScaledBitmap(cover, (cover!!.width.toFloat() * sizePercent.toFloat() / 100f).toInt(), (cover!!.height.toFloat() * sizePercent.toFloat() / 100f).toInt(), false)
val pnn = PnnQuantizer(cover)
cover = pnn.convert(maxColor, false)
}
}
} else {
cover = null
}
frames.forEach {
val btm = BitmapFactory.decodeByteArray(it.byteArray, 0 , it.byteArray.size)
var btm = BitmapFactory.decodeByteArray(it.byteArray, 0, it.byteArray.size)
if (sizePercent != null) {
btm = Bitmap.createScaledBitmap(btm, (btm!!.width.toFloat() * sizePercent.toFloat() / 100f).toInt(), (btm.height.toFloat() * sizePercent.toFloat() / 100f).toInt(), false)
}
val pnn = PnnQuantizer(btm)
val btmOptimised = pnn.convert(maxColor, false)
apng.addFrames(btmOptimised, it.delay, it.x_offsets ?: 0, it.y_offsets ?: 0, it.dispose_op, it.blend_op)
if (sizePercent != null) {
apng.addFrames(btmOptimised, it.delay, ((it.x_offsets ?: 0).toFloat() * sizePercent.toFloat() / 100f).toInt(), ((it.y_offsets ?: 0).toFloat() * sizePercent.toFloat() / 100f).toInt(), it.dispose_op, it.blend_op)
} else {
apng.addFrames(btmOptimised, it.delay, it.x_offsets ?: 0, it.y_offsets ?: 0, it.dispose_op, it.blend_op)
}
}
frames = apng.frames
}

View File

@ -6,18 +6,25 @@ import java.io.ByteArrayOutputStream
class Utils {
companion object {
// Return true if png
/**
* @return True if is a png
*/
fun isPng(byteArray: ByteArray): Boolean {
return byteArray.copyOfRange(0, 8).contentToString() == pngSignature.contentToString()
}
/**
* Know if file is an APNG
* @return True if is an APNG
*/
fun isApng(byteArray: ByteArray): Boolean {
// if byteArray contain acTL
return byteArray.toList().containsAll(byteArrayOf(0x66, 0x63, 0x54, 0x4c).toList())
}
// Signature for png
/**
* Signature for png / APNG files
*/
val pngSignature: ByteArray = byteArrayOf(0x89.toByte(), 0x50.toByte(), 0x4E.toByte(), 0x47.toByte(), 0x0D.toByte(), 0x0A.toByte(), 0x1A.toByte(), 0x0A.toByte())

View File

@ -11,6 +11,7 @@ import kotlinx.android.synthetic.main.activity_main.*
import oupson.apng.ApngAnimator
import android.widget.Toast
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.toast
import oupson.apng.APNGDisassembler
import oupson.apng.Apng
import oupson.apng.Loader
@ -23,6 +24,7 @@ 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"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -40,8 +42,11 @@ class MainActivity : AppCompatActivity() {
doAsync {
Loader().load(applicationContext, URL(imageUrl)).apply {
val a = APNGDisassembler(this).apng
a.optimise(100, 75)
a.reduceSize(100, false, 75)
File(File(Environment.getExternalStorageDirectory(), "Documents"), "apng.png").writeBytes(a.toByteArray())
runOnUiThread {
toast("Converted ! ")
}
}
}