Skip to content

Commit 08d5d30

Browse files
committed
Add chunk interface
Prepare for release
1 parent cefb4ca commit 08d5d30

File tree

14 files changed

+88
-201
lines changed

14 files changed

+88
-201
lines changed

.idea/caches/build_file_checksums.ser

0 Bytes
Binary file not shown.

apng_library/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ android {
55
compileSdkVersion 27
66
defaultConfig {
77
minSdkVersion 21
8-
targetSdkVersion 26
8+
targetSdkVersion 27
99
versionCode 1
1010
versionName "1.0.8"
1111

apng_library/src/main/java/oupson/apng/APNGDisassembler.kt

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import oupson.apng.chunks.fcTL
66
import oupson.apng.exceptions.NotApngException
77
import oupson.apng.utils.Utils
88
import oupson.apng.utils.Utils.Companion.isApng
9+
import oupson.apng.utils.Utils.Companion.parseLength
910
import oupson.apng.utils.Utils.Companion.pngSignature
1011
import oupson.apng.utils.Utils.Companion.to4Bytes
1112
import java.util.*
@@ -24,12 +25,17 @@ class APNGDisassembler {
2425
private var maxHeight = 0
2526
private var blend_op: Utils.Companion.blend_op = Utils.Companion.blend_op.APNG_BLEND_OP_SOURCE
2627
private var dispose_op: Utils.Companion.dispose_op = Utils.Companion.dispose_op.APNG_DISPOSE_OP_NONE
27-
var apng: Apng = Apng()
2828
private val ihdr = IHDR()
29+
30+
var apng: Apng = Apng()
31+
/**
32+
* Disassemble an Apng file
33+
* @param byteArray The Byte Array of the file
34+
* @return The apng decoded
35+
*/
2936
fun disassemble(byteArray: ByteArray) : Apng {
3037
if (isApng(byteArray)) {
31-
apng = Apng()
32-
ihdr.parseIHDR(byteArray)
38+
ihdr.parse(byteArray)
3339
maxWidth = ihdr.pngWidth
3440
maxHeight = ihdr.pngHeight
3541
var cursor = 8
@@ -44,28 +50,20 @@ class APNGDisassembler {
4450
}
4551
}
4652

47-
private fun parseLength(byteArray: ByteArray) : Int {
48-
var lengthString = ""
49-
byteArray.forEach {
50-
lengthString += String.format("%02x", it)
51-
}
52-
return lengthString.toLong(16).toInt()
53-
}
54-
5553
private fun generateIhdr(ihdrOfApng: IHDR, width : Int, height : Int) : ByteArray {
5654
val ihdr = ArrayList<Byte>()
5755
// We need a body var to know body length and generate crc
5856
val ihdrBody = ArrayList<Byte>()
5957
// Add chunk body length
60-
ihdr.addAll(to4Bytes(ihdrOfApng.ihdrCorps.size).toList())
58+
ihdr.addAll(to4Bytes(ihdrOfApng.body.size).toList())
6159
// Add IHDR
6260
ihdrBody.addAll(byteArrayOf(0x49.toByte(), 0x48.toByte(), 0x44.toByte(), 0x52.toByte()).toList())
6361
// Add the max width and height
6462
ihdrBody.addAll(to4Bytes(width).toList())
6563
ihdrBody.addAll(to4Bytes(height).toList())
6664
// Add complicated stuff like depth color ...
6765
// If you want correct png you need same parameters. Good solution is to create new png.
68-
ihdrBody.addAll(ihdrOfApng.ihdrCorps.copyOfRange(8, 13).toList())
66+
ihdrBody.addAll(ihdrOfApng.body.copyOfRange(8, 13).toList())
6967
// Generate CRC
7068
val crC32 = CRC32()
7169
crC32.update(ihdrBody.toByteArray(), 0, ihdrBody.size)
@@ -91,9 +89,9 @@ class APNGDisassembler {
9189
it.addAll(to4Bytes(crC32.value.toInt()).toList())
9290
apng.cover = BitmapFactory.decodeByteArray(it.toByteArray(), 0, it.size)
9391
}
94-
9592
png = ArrayList()
96-
val fcTL = fcTL(byteArray)
93+
val fcTL = fcTL()
94+
fcTL.parse(byteArray)
9795
delay = fcTL.delay
9896
yOffset = fcTL.y_offset
9997
xOffset = fcTL.x_offset
@@ -103,11 +101,9 @@ class APNGDisassembler {
103101
val height = fcTL.pngHeight
104102
png!!.addAll(pngSignature.toList())
105103
png!!.addAll(generateIhdr(ihdr, width, height).toList())
106-
107104
plte?.let {
108105
png!!.addAll(it.toList())
109106
}
110-
111107
tnrs?.let {
112108
png!!.addAll(it.toList())
113109
}
@@ -122,15 +118,12 @@ class APNGDisassembler {
122118
png!!.addAll(iend.toList())
123119
png!!.addAll(to4Bytes(crC32.value.toInt()).toList())
124120
apng.frames.add(Frame(png!!.toByteArray(), delay, xOffset, yOffset, maxWidth, maxHeight, blend_op, dispose_op))
125-
126121
png = ArrayList()
127-
128-
val fcTL = fcTL(byteArray)
122+
val fcTL = fcTL()
123+
fcTL.parse(byteArray)
129124
delay = fcTL.delay
130-
131125
yOffset = fcTL.y_offset
132126
xOffset = fcTL.x_offset
133-
134127
blend_op = fcTL.blend_op
135128
dispose_op = fcTL.dispose_op
136129
val width = fcTL.pngWidth
@@ -140,7 +133,6 @@ class APNGDisassembler {
140133
plte?.let {
141134
png!!.addAll(it.toList())
142135
}
143-
144136
tnrs?.let {
145137
png!!.addAll(it.toList())
146138
}

apng_library/src/main/java/oupson/apng/Apng.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@ import oupson.apng.utils.Utils.Companion.to4Bytes
1414
import oupson.apng.utils.Utils.Companion.toByteArray
1515
import java.util.zip.CRC32
1616

17-
1817
/**
1918
* Create an APNG file
2019
*/
2120
class Apng {
22-
2321
var maxWidth : Int? = null
2422
var maxHeight : Int? = null
2523

@@ -226,7 +224,7 @@ class Apng {
226224
// Add cover image : Not part of animation
227225
// region IDAT
228226
val idat = IDAT()
229-
idat.parseIDAT(toByteArray(cover!!))
227+
idat.parse(toByteArray(cover!!))
230228
idat.IDATBody.forEach {
231229
val idatByteArray = ArrayList<Byte>()
232230
framesByte.addAll(to4Bytes(it.size).toList())
@@ -427,7 +425,7 @@ class Apng {
427425
}
428426

429427
// Add chunk body length
430-
ihdr.addAll(to4Bytes(frames[0].ihdr.ihdrCorps.size).toList())
428+
ihdr.addAll(to4Bytes(frames[0].ihdr.body.size).toList())
431429
// Add IHDR
432430
ihdr_body.addAll(byteArrayOf(0x49.toByte(), 0x48.toByte(), 0x44.toByte(), 0x52.toByte()).toList())
433431

@@ -437,7 +435,7 @@ class Apng {
437435

438436
// Add complicated stuff like depth color ...
439437
// If you want correct png you need same parameters. Good solution is to create new png.
440-
ihdr_body.addAll(frames[0].ihdr.ihdrCorps.copyOfRange(8, 13).toList())
438+
ihdr_body.addAll(frames[0].ihdr.body.copyOfRange(8, 13).toList())
441439

442440
// Generate CRC
443441
val crC32 = CRC32()

apng_library/src/main/java/oupson/apng/ApngAnimator.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,14 @@ class ApngAnimator(private val context: Context) {
3939
private var anim: CustomAnimationDrawable? = null
4040
private var activeAnimation: CustomAnimationDrawable? = null
4141
private var doOnLoaded : (ApngAnimator) -> Unit = {}
42+
@SuppressWarnings("WeakerAccess")
4243
private var AnimationLoopListener : () -> Unit = {}
4344
private var duration : ArrayList<Float>? = null
4445
private var scaleType : ImageView.ScaleType? = null
45-
4646
var isApng = false
47+
@SuppressWarnings("WeakerAccess")
4748
var loadNotApng = true
49+
4850
private val sharedPreferences : SharedPreferences = context.getSharedPreferences("apngAnimator", Context.MODE_PRIVATE)
4951

5052
init {
@@ -54,6 +56,7 @@ class ApngAnimator(private val context: Context) {
5456
/**
5557
* Specify if the library could load non apng file
5658
*/
59+
@SuppressWarnings("WeakerAccess")
5760
fun loadNotApng(boolean: Boolean) {
5861
val editor = sharedPreferences.edit()
5962
editor.putBoolean("loadNotApng", boolean)
@@ -75,7 +78,7 @@ class ApngAnimator(private val context: Context) {
7578
* @param speed The speed
7679
* @throws NotApngException
7780
*/
78-
@JvmOverloads
81+
@SuppressWarnings("WeakerAccess")
7982
fun load(file: File, speed: Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) {
8083
doAsync {
8184
val bytes = file.readBytes()
@@ -140,6 +143,7 @@ class ApngAnimator(private val context: Context) {
140143
* @param speed The speed
141144
* @throws NotApngException
142145
*/
146+
@SuppressWarnings("WeakerAccess")
143147
fun loadUrl(url: URL, speed: Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) {
144148
doAsync(exceptionHandler = { e -> e.printStackTrace() }) {
145149
this@ApngAnimator.speed = speed
@@ -171,13 +175,13 @@ class ApngAnimator(private val context: Context) {
171175
}
172176
}
173177

174-
175178
/**
176179
* Load an APNG file and starts playing the animation.
177180
* @param byteArray ByteArray of the file
178181
* @param speed The speed
179182
* @throws NotApngException
180183
*/
184+
@SuppressWarnings("WeakerAccess")
181185
fun load(byteArray: ByteArray, speed: Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) {
182186
doAsync {
183187
this@ApngAnimator.speed = speed

apng_library/src/main/java/oupson/apng/Frame.kt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@ class Frame {
4545
this.byteArray = bytes
4646
// Get width and height for image
4747
ihdr = IHDR()
48-
ihdr.parseIHDR(bytes)
48+
ihdr.parse(bytes)
4949

5050
width = ihdr.pngWidth
5151
height = ihdr.pngHeight
5252

5353
// Get IDAT Bytes
5454
idat = IDAT()
55-
idat.parseIDAT(bytes)
55+
idat.parse(bytes)
5656

5757
delay = 1000f
5858

@@ -69,14 +69,14 @@ class Frame {
6969
this.byteArray = bytes
7070
// Get width and height for image
7171
ihdr = IHDR()
72-
ihdr.parseIHDR(bytes)
72+
ihdr.parse(bytes)
7373

7474
width = ihdr.pngWidth
7575
height = ihdr.pngHeight
7676

7777
// Get IDAT Bytes
7878
idat = IDAT()
79-
idat.parseIDAT(bytes)
79+
idat.parse(bytes)
8080

8181
this.delay = delay
8282
blend_op = Utils.Companion.blend_op.APNG_BLEND_OP_SOURCE
@@ -93,14 +93,14 @@ class Frame {
9393
this.byteArray = bytes
9494
// Get width and height for image
9595
ihdr = IHDR()
96-
ihdr.parseIHDR(bytes)
96+
ihdr.parse(bytes)
9797

9898
width = ihdr.pngWidth
9999
height = ihdr.pngHeight
100100

101101
// Get IDAT Bytes
102102
idat = IDAT()
103-
idat.parseIDAT(bytes)
103+
idat.parse(bytes)
104104

105105
this.delay = delay
106106

@@ -121,14 +121,14 @@ class Frame {
121121
this.byteArray = bytes
122122
// Get width and height for image
123123
ihdr = IHDR()
124-
ihdr.parseIHDR(bytes)
124+
ihdr.parse(bytes)
125125

126126
width = ihdr.pngWidth
127127
height = ihdr.pngHeight
128128

129129
// Get IDAT Bytes
130130
idat = IDAT()
131-
idat.parseIDAT(bytes)
131+
idat.parse(bytes)
132132

133133
this.delay = delay
134134

@@ -149,14 +149,14 @@ class Frame {
149149
this.byteArray = byteArray
150150
// Get width and height for image
151151
ihdr = IHDR()
152-
ihdr.parseIHDR(byteArray)
152+
ihdr.parse(byteArray)
153153

154154
width = ihdr.pngWidth
155155
height = ihdr.pngHeight
156156

157157
// Get IDAT Bytes
158158
idat = IDAT()
159-
idat.parseIDAT(byteArray)
159+
idat.parse(byteArray)
160160

161161
this.delay = delay
162162

apng_library/src/main/java/oupson/apng/Loader.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ import java.net.URL
88

99
class Loader {
1010
companion object {
11+
/**
12+
* Download file from given url
13+
* @param context Context of app
14+
* @param url Url of the file to download
15+
* @return [ByteArray] of the file
16+
*/
1117
@Throws(IOException::class)
1218
fun load(context: Context, url: URL): ByteArray {
1319
val currentDir = context.filesDir
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package oupson.apng.chunks
2+
3+
interface Chunk {
4+
var body : ByteArray
5+
fun parse(byteArray: ByteArray)
6+
}
Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,20 @@
11
package oupson.apng.chunks
22

3-
class IDAT {
4-
private var bodySize = -1
3+
import oupson.apng.utils.Utils.Companion.parseLength
4+
5+
class IDAT : Chunk {
56
var IDATBody: ArrayList<ByteArray> = ArrayList()
7+
override var body = byteArrayOf()
68

7-
fun parseIDAT(byteArray: ByteArray) {
9+
override fun parse(byteArray: ByteArray) {
810
for (i in 0 until byteArray.size) {
911
// Find IDAT chunk
1012
if (byteArray[i] == 0x49.toByte() && byteArray[i + 1] == 0x44.toByte() && byteArray[ i + 2 ] == 0x41.toByte() && byteArray[ i + 3 ] == 0x54.toByte()) {
11-
1213
// Find the chunk length
13-
var lengthString = ""
14-
byteArray.copyOfRange( i - 4, i).forEach {
15-
lengthString += String.format("%02x", it)
16-
}
17-
bodySize = lengthString.toLong(16).toInt()
18-
14+
val bodySize = parseLength(byteArray.copyOfRange(i - 4, i))
1915
// Get image bytes
20-
val _IDATbody = ArrayList<Byte>()
21-
for (j in i +4 until i + 4 + bodySize) {
22-
_IDATbody.add(byteArray[j])
23-
}
24-
IDATBody.add(_IDATbody.toByteArray())
16+
IDATBody.add(byteArray.copyOfRange(i + 4, i + 4 + bodySize))
2517
}
2618
}
27-
2819
}
29-
3020
}

0 commit comments

Comments
 (0)