Optimise APNG

This commit is contained in:
Oupson 2021-02-06 17:20:10 +01:00
parent 919feee3e9
commit 338a875b9c
7 changed files with 33 additions and 10 deletions

View File

@ -12,6 +12,8 @@ import oupson.apng.utils.Utils
class ApngEncoderInstrumentedTest { class ApngEncoderInstrumentedTest {
// TODO TEST IF OPTIMISED ANIMATIONS AND NON-OPTIMISED ANIMATIONS ARE THE SAME
@Test @Test
fun testDiffBunny() { fun testDiffBunny() {
val context = InstrumentationRegistry.getInstrumentation().context val context = InstrumentationRegistry.getInstrumentation().context

View File

@ -16,7 +16,7 @@ import java.io.File
import java.util.zip.CRC32 import java.util.zip.CRC32
// TODO CREATE A BETTER CLASS // TODO REMOVE
/** /**
* Create an APNG file * Create an APNG file
* If you want to create an APNG, use ApngEncoder instead * If you want to create an APNG, use ApngEncoder instead

View File

@ -19,8 +19,7 @@ import oupson.apng.utils.Utils.Companion.isPng
import java.io.File import java.io.File
import java.net.URL import java.net.URL
// TODO REWRITE WITH CALLBACKS // TODO REMOVE
// TODO REWRITE
/** /**
* Class to play APNG * Class to play APNG

View File

@ -8,7 +8,6 @@ import java.io.IOException
import java.net.HttpURLConnection import java.net.HttpURLConnection
import java.net.URL import java.net.URL
// TODO DOCUMENTATION (MAYBE WIKI) FOR THE CACHE
class Loader { class Loader {
companion object { companion object {
/** /**

View File

@ -245,12 +245,30 @@ class ApngEncoder(
throw InvalidFrameSizeException(btm.width, btm.height, width, height, currentFrame == 0) throw InvalidFrameSizeException(btm.width, btm.height, width, height, currentFrame == 0)
} }
var frameBtm = btm
var frameXOffsets = xOffsets
var frameYOffsets = yOffsets
var frameBlendOp = blendOp
if (currentFrame != 0 || (currentFrame == 0 && firstFrameInAnim)) {
if (bitmapBuffer == null && optimise) {
bitmapBuffer = btm.copy(btm.config, false)
} else if (optimise) {
val diff = Utils.getDiffBitmap(bitmapBuffer!!, btm)
frameBtm = diff.bitmap
frameXOffsets = diff.offsetX
frameYOffsets = diff.offsetY
frameBlendOp = diff.blendOp
bitmapBuffer = btm.copy(btm.config, false)
}
}
if (btm.width > width || btm.height > height) if (btm.width > width || btm.height > height)
throw InvalidFrameSizeException(btm.width, btm.height, width, height, currentFrame == 0) throw InvalidFrameSizeException(btm.width, btm.height, width, height, currentFrame == 0)
if (firstFrameInAnim || currentFrame != 0) if (firstFrameInAnim || currentFrame != 0)
writeFCTL(btm, delay, disposeOp, blendOp, xOffsets, yOffsets) writeFCTL(frameBtm, delay, disposeOp, frameBlendOp, frameXOffsets, frameYOffsets)
writeImageData(btm) writeImageData(frameBtm)
currentFrame++ currentFrame++
} }

View File

@ -26,5 +26,8 @@ class InvalidFrameSizeException(animationWidth : Int, animationHeight : Int, fra
"Unknown problem" "Unknown problem"
} }
} }
}
class BadFrameDiffSize(firstFrameWidth : Int, firstFrameHeight : Int, secondFrameWidth : Int, secondFrameHeight : Int) : Exception() {
override val message: String = "${firstFrameWidth}x${firstFrameHeight} must be smaller than ${secondFrameWidth}x${secondFrameHeight}"
} }

View File

@ -2,6 +2,7 @@ package oupson.apng.utils
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Color import android.graphics.Color
import oupson.apng.exceptions.BadFrameDiffSize
import oupson.apng.utils.Utils.Companion.BlendOp.APNG_BLEND_OP_OVER import oupson.apng.utils.Utils.Companion.BlendOp.APNG_BLEND_OP_OVER
import oupson.apng.utils.Utils.Companion.BlendOp.APNG_BLEND_OP_SOURCE import oupson.apng.utils.Utils.Companion.BlendOp.APNG_BLEND_OP_SOURCE
import oupson.apng.utils.Utils.Companion.DisposeOp.* import oupson.apng.utils.Utils.Companion.DisposeOp.*
@ -224,12 +225,13 @@ class Utils {
* @param secondBitmap A [Bitmap], a second bitmap * @param secondBitmap A [Bitmap], a second bitmap
* @return [DiffResult], the difference between the second and the first bitmap * @return [DiffResult], the difference between the second and the first bitmap
*/ */
@Throws(BadFrameDiffSize::class)
fun getDiffBitmap(firstBitmap : Bitmap, secondBitmap : Bitmap) : DiffResult { fun getDiffBitmap(firstBitmap : Bitmap, secondBitmap : Bitmap) : DiffResult {
if (firstBitmap.width < secondBitmap.width || firstBitmap.height < secondBitmap.height) { if (firstBitmap.width < secondBitmap.width || firstBitmap.height < secondBitmap.height) {
TODO("EXCEPTION BAD IMAGE SIZE") throw BadFrameDiffSize(firstBitmap.width, firstBitmap.height, firstBitmap.width, firstBitmap.height)
} }
var resultBtm = Bitmap.createBitmap(secondBitmap.width, secondBitmap.height, Bitmap.Config.ARGB_8888) val resultBtm = Bitmap.createBitmap(secondBitmap.width, secondBitmap.height, Bitmap.Config.ARGB_8888)
var offsetX = resultBtm.width + 1 var offsetX = resultBtm.width + 1
var offsetY = resultBtm.height + 1 var offsetY = resultBtm.height + 1
@ -269,9 +271,9 @@ class Utils {
val newHeight = lastY - offsetY val newHeight = lastY - offsetY
// Resize bitmap // Resize bitmap
resultBtm = Bitmap.createBitmap(resultBtm, offsetX, offsetY, newWidth, newHeight) val resizedResultBtm = Bitmap.createBitmap(resultBtm, offsetX, offsetY, newWidth, newHeight)
return DiffResult(resultBtm, offsetX, offsetY, blendOp) return DiffResult(resizedResultBtm, offsetX, offsetY, blendOp)
} }
/** /**