Test if optimised and non-optimised APNG are the same
This commit is contained in:
parent
f826afff86
commit
be9e5426e0
|
@ -4,11 +4,17 @@ import android.content.Context
|
|||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.AnimationDrawable
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import junit.framework.TestCase.assertFalse
|
||||
import junit.framework.TestCase.assertTrue
|
||||
import org.junit.Test
|
||||
import oupson.apng.decoder.ApngDecoder
|
||||
import oupson.apng.encoder.ApngEncoder
|
||||
import oupson.apng.utils.Utils
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
|
||||
class ApngEncoderInstrumentedTest {
|
||||
|
@ -38,7 +44,7 @@ class ApngEncoderInstrumentedTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun containTransparency() {
|
||||
fun testContainTransparency() {
|
||||
val context = InstrumentationRegistry.getInstrumentation().context
|
||||
|
||||
val bunnyFrame1 = getFrame(context, "bunny/frame_apngframe01.png")
|
||||
|
@ -48,6 +54,118 @@ class ApngEncoderInstrumentedTest {
|
|||
assertTrue(Utils.containTransparency(ballFrame1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOptimiseBall() {
|
||||
val context = InstrumentationRegistry.getInstrumentation().context
|
||||
val list = context.assets.list("ball")?.map { getFrame(context, "ball/$it") }!!
|
||||
|
||||
val optimisedOutputStream = ByteArrayOutputStream()
|
||||
val optimisedEncoder = ApngEncoder(optimisedOutputStream, list[0].width, list[0].height, list.size)
|
||||
.setOptimiseApng(true)
|
||||
|
||||
list.forEach {
|
||||
optimisedEncoder.writeFrame(it)
|
||||
}
|
||||
|
||||
optimisedEncoder.writeEnd()
|
||||
optimisedOutputStream.close()
|
||||
|
||||
val bytes = optimisedOutputStream.toByteArray()
|
||||
val optimisedInputStream = ByteArrayInputStream(bytes)
|
||||
|
||||
val optimisedApng =
|
||||
ApngDecoder.decodeApng(context, optimisedInputStream) as AnimationDrawable
|
||||
|
||||
optimisedInputStream.close()
|
||||
|
||||
|
||||
|
||||
val nonOptimisedOutputStream = ByteArrayOutputStream()
|
||||
|
||||
val nonOptimisedEncoder = ApngEncoder(nonOptimisedOutputStream, list[0].width, list[0].height, list.size)
|
||||
.setOptimiseApng(false)
|
||||
|
||||
list.forEach {
|
||||
nonOptimisedEncoder.writeFrame(it)
|
||||
}
|
||||
|
||||
nonOptimisedEncoder.writeEnd()
|
||||
|
||||
nonOptimisedOutputStream.close()
|
||||
|
||||
val nonOptimisedBytes = nonOptimisedOutputStream.toByteArray()
|
||||
val nonOptimisedInputStream = ByteArrayInputStream(nonOptimisedBytes)
|
||||
|
||||
val nonOptimisedApng =
|
||||
ApngDecoder.decodeApng(context, nonOptimisedInputStream) as AnimationDrawable
|
||||
nonOptimisedInputStream.close()
|
||||
|
||||
for (i in 0 until optimisedApng.numberOfFrames) {
|
||||
assertTrue(
|
||||
isBitmapSimilar(
|
||||
(optimisedApng.getFrame(i) as BitmapDrawable).bitmap,
|
||||
(nonOptimisedApng.getFrame(i) as BitmapDrawable).bitmap
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOptimiseBunny() {
|
||||
val context = InstrumentationRegistry.getInstrumentation().context
|
||||
val list = context.assets.list("bunny")?.map { getFrame(context, "bunny/$it") }!!
|
||||
|
||||
val optimisedOutputStream = ByteArrayOutputStream()
|
||||
val optimisedEncoder = ApngEncoder(optimisedOutputStream, list[0].width, list[0].height, list.size)
|
||||
.setOptimiseApng(true)
|
||||
|
||||
list.forEach {
|
||||
optimisedEncoder.writeFrame(it)
|
||||
}
|
||||
|
||||
optimisedEncoder.writeEnd()
|
||||
optimisedOutputStream.close()
|
||||
|
||||
val bytes = optimisedOutputStream.toByteArray()
|
||||
val optimisedInputStream = ByteArrayInputStream(bytes)
|
||||
|
||||
val optimisedApng =
|
||||
ApngDecoder.decodeApng(context, optimisedInputStream) as AnimationDrawable
|
||||
|
||||
optimisedInputStream.close()
|
||||
|
||||
|
||||
|
||||
val nonOptimisedOutputStream = ByteArrayOutputStream()
|
||||
|
||||
val nonOptimisedEncoder = ApngEncoder(nonOptimisedOutputStream, list[0].width, list[0].height, list.size)
|
||||
.setOptimiseApng(false)
|
||||
|
||||
list.forEach {
|
||||
nonOptimisedEncoder.writeFrame(it)
|
||||
}
|
||||
|
||||
nonOptimisedEncoder.writeEnd()
|
||||
|
||||
nonOptimisedOutputStream.close()
|
||||
|
||||
val nonOptimisedBytes = nonOptimisedOutputStream.toByteArray()
|
||||
val nonOptimisedInputStream = ByteArrayInputStream(nonOptimisedBytes)
|
||||
|
||||
val nonOptimisedApng =
|
||||
ApngDecoder.decodeApng(context, nonOptimisedInputStream) as AnimationDrawable
|
||||
nonOptimisedInputStream.close()
|
||||
|
||||
for (i in 0 until optimisedApng.numberOfFrames) {
|
||||
assertTrue(
|
||||
isBitmapSimilar(
|
||||
(optimisedApng.getFrame(i) as BitmapDrawable).bitmap,
|
||||
(nonOptimisedApng.getFrame(i) as BitmapDrawable).bitmap
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isSimilar(buffer : Bitmap, frame : Bitmap, diff : Utils.Companion.DiffResult) : Boolean {
|
||||
val btm = buffer.copy(Bitmap.Config.ARGB_8888, true)
|
||||
|
||||
|
@ -69,6 +187,17 @@ class ApngEncoderInstrumentedTest {
|
|||
return true
|
||||
}
|
||||
|
||||
fun isBitmapSimilar(btm1 : Bitmap, btm2 : Bitmap) : Boolean {
|
||||
for (y in 0 until btm1.height) {
|
||||
for (x in 0 until btm1.width) {
|
||||
if (btm1.getPixel(x, y) != btm2.getPixel(x, y)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun getFrame(context: Context, name: String) : Bitmap {
|
||||
val inputStream = context.assets.open(name)
|
||||
|
||||
|
|
|
@ -284,7 +284,13 @@ class ApngEncoder(
|
|||
) {
|
||||
if (currentFrame == 0) {
|
||||
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
|
||||
)
|
||||
}
|
||||
|
||||
var frameBtm = btm
|
||||
|
@ -292,10 +298,10 @@ class ApngEncoder(
|
|||
var frameYOffsets = yOffsets
|
||||
var frameBlendOp = blendOp
|
||||
|
||||
if (currentFrame != 0 || (currentFrame == 0 && firstFrameInAnim)) {
|
||||
if (bitmapBuffer == null && optimise) {
|
||||
if (optimise && currentFrame != 0 || (currentFrame == 0 && firstFrameInAnim)) {
|
||||
if (bitmapBuffer == null) {
|
||||
bitmapBuffer = btm.copy(btm.config, false)
|
||||
} else if (optimise) {
|
||||
} else {
|
||||
val diff = Utils.getDiffBitmap(bitmapBuffer!!, btm)
|
||||
frameBtm = diff.bitmap
|
||||
frameXOffsets = diff.offsetX
|
||||
|
@ -305,8 +311,8 @@ class ApngEncoder(
|
|||
}
|
||||
}
|
||||
|
||||
if (btm.width > width || btm.height > height)
|
||||
throw InvalidFrameSizeException(btm.width, btm.height, width, height, currentFrame == 0)
|
||||
if (frameBtm.width > width || frameBtm.height > height)
|
||||
throw InvalidFrameSizeException(frameBtm.width, frameBtm.height, width, height, currentFrame == 0)
|
||||
|
||||
if (firstFrameInAnim || currentFrame != 0)
|
||||
writeFCTL(frameBtm, delay, disposeOp, frameBlendOp, frameXOffsets, frameYOffsets)
|
||||
|
|
Loading…
Reference in New Issue