Rewrite and rename parseLength
This commit is contained in:
parent
e3719dcfe0
commit
4eee8dcc5e
|
@ -10,9 +10,9 @@ import oupson.apng.exceptions.NotPngException
|
|||
import oupson.apng.utils.Utils
|
||||
import oupson.apng.utils.Utils.Companion.isApng
|
||||
import oupson.apng.utils.Utils.Companion.isPng
|
||||
import oupson.apng.utils.Utils.Companion.parseLength
|
||||
import oupson.apng.utils.Utils.Companion.pngSignature
|
||||
import oupson.apng.utils.Utils.Companion.to4Bytes
|
||||
import oupson.apng.utils.Utils.Companion.uIntFromBytesBigEndian
|
||||
import java.io.InputStream
|
||||
import java.util.*
|
||||
import java.util.zip.CRC32
|
||||
|
@ -47,7 +47,7 @@ class APNGDisassembler {
|
|||
if (isApng(byteArray)) {
|
||||
var cursor = 8
|
||||
while (cursor < byteArray.size) {
|
||||
val length = parseLength(byteArray.copyOfRange(cursor, cursor + 4))
|
||||
val length = uIntFromBytesBigEndian(byteArray.copyOfRange(cursor, cursor + 4).map { it -> it.toInt() })
|
||||
val chunk = byteArray.copyOfRange(cursor, cursor + length + 12)
|
||||
parseChunk(chunk)
|
||||
cursor += length + 12
|
||||
|
@ -80,7 +80,7 @@ class APNGDisassembler {
|
|||
|
||||
if (byteRead == -1)
|
||||
break
|
||||
val length = parseLength(lengthChunk)
|
||||
val length = uIntFromBytesBigEndian(lengthChunk.map(Byte::toInt))
|
||||
|
||||
val chunk = ByteArray(length + 8)
|
||||
byteRead = input.read(chunk)
|
||||
|
@ -133,7 +133,7 @@ class APNGDisassembler {
|
|||
*/
|
||||
private fun parseChunk(byteArray: ByteArray) {
|
||||
val i = 4
|
||||
val chunkCRC = parseLength(byteArray.copyOfRange(byteArray.size - 4, byteArray.size))
|
||||
val chunkCRC = uIntFromBytesBigEndian(byteArray.copyOfRange(byteArray.size - 4, byteArray.size).map(Byte::toInt))
|
||||
val crc = CRC32()
|
||||
crc.update(byteArray.copyOfRange(i, byteArray.size - 4))
|
||||
if (chunkCRC == crc.value.toInt()) {
|
||||
|
@ -264,7 +264,7 @@ class APNGDisassembler {
|
|||
cover?.addAll(generateIhdr(ihdr, maxWidth, maxHeight).asList())
|
||||
}
|
||||
// Find the chunk length
|
||||
val bodySize = parseLength(byteArray.copyOfRange(i - 4, i))
|
||||
val bodySize = uIntFromBytesBigEndian(byteArray.copyOfRange(i - 4, i).map(Byte::toInt))
|
||||
cover?.addAll(byteArray.copyOfRange(i - 4, i).asList())
|
||||
val body = ArrayList<Byte>()
|
||||
body.addAll(byteArrayOf(0x49, 0x44, 0x41, 0x54).asList())
|
||||
|
@ -276,7 +276,7 @@ class APNGDisassembler {
|
|||
cover?.addAll(to4Bytes(crC32.value.toInt()).asList())
|
||||
} else {
|
||||
// Find the chunk length
|
||||
val bodySize = parseLength(byteArray.copyOfRange(i - 4, i))
|
||||
val bodySize = uIntFromBytesBigEndian(byteArray.copyOfRange(i - 4, i).map(Byte::toInt))
|
||||
png?.addAll(byteArray.copyOfRange(i - 4, i).asList())
|
||||
val body = ArrayList<Byte>()
|
||||
body.addAll(byteArrayOf(0x49, 0x44, 0x41, 0x54).asList())
|
||||
|
@ -290,7 +290,7 @@ class APNGDisassembler {
|
|||
}
|
||||
name.contentEquals(Utils.fdAT) -> {
|
||||
// Find the chunk length
|
||||
val bodySize = parseLength(byteArray.copyOfRange(i - 4, i))
|
||||
val bodySize = uIntFromBytesBigEndian(byteArray.copyOfRange(i - 4, i).map(Byte::toInt))
|
||||
png?.addAll(to4Bytes(bodySize - 4).asList())
|
||||
val body = ArrayList<Byte>()
|
||||
body.addAll(byteArrayOf(0x49, 0x44, 0x41, 0x54).asList())
|
||||
|
|
|
@ -57,9 +57,9 @@ class Frame // Get width and height for image
|
|||
// Get width and height for image
|
||||
var cursor = 8
|
||||
while (cursor < byteArray.size) {
|
||||
val chunk = byteArray.copyOfRange(cursor, cursor + Utils.parseLength(byteArray.copyOfRange(cursor, cursor + 4)) + 12)
|
||||
val chunk = byteArray.copyOfRange(cursor, cursor + Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(cursor, cursor + 4).map(Byte::toInt)) + 12)
|
||||
parseChunk(chunk)
|
||||
cursor += Utils.parseLength(byteArray.copyOfRange(cursor, cursor + 4)) + 12
|
||||
cursor += Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(cursor, cursor + 4).map(Byte::toInt)) + 12
|
||||
}
|
||||
|
||||
this.delay = delay
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package oupson.apng.chunks
|
||||
|
||||
import oupson.apng.utils.Utils.Companion.parseLength
|
||||
import oupson.apng.utils.Utils
|
||||
|
||||
class IDAT : Chunk {
|
||||
@Suppress("PropertyName")
|
||||
|
@ -16,7 +16,7 @@ class IDAT : Chunk {
|
|||
// Find IDAT chunk
|
||||
if (byteArray[i] == 0x49.toByte() && byteArray[i + 1] == 0x44.toByte() && byteArray[i + 2] == 0x41.toByte() && byteArray[i + 3] == 0x54.toByte()) {
|
||||
// Find the chunk length
|
||||
val bodySize = parseLength(byteArray.copyOfRange(i - 4, i))
|
||||
val bodySize = Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(i - 4, i).map(Byte::toInt))
|
||||
// Get image bytes
|
||||
IDATBody.add(byteArray.copyOfRange(i + 4, i + 4 + bodySize))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package oupson.apng.chunks
|
||||
|
||||
import oupson.apng.utils.Utils.Companion.parseLength
|
||||
import oupson.apng.utils.Utils
|
||||
|
||||
class IHDR : Chunk {
|
||||
override var body = byteArrayOf()
|
||||
|
@ -16,11 +16,11 @@ class IHDR : Chunk {
|
|||
// Find IHDR chunk
|
||||
if (byteArray[i] == 0x49.toByte() && byteArray[i + 1] == 0x48.toByte() && byteArray[ i + 2 ] == 0x44.toByte() && byteArray[ i + 3 ] == 0x52.toByte()) {
|
||||
// Get length of the body of the chunk
|
||||
val bodySize = parseLength(byteArray.copyOfRange(i - 4, i))
|
||||
val bodySize = Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(i - 4, i).map(Byte::toInt))
|
||||
// Get the width of the png
|
||||
pngWidth = parseLength(byteArray.copyOfRange(i +4, i + 8))
|
||||
pngWidth = Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(i +4, i + 8).map(Byte::toInt))
|
||||
// Get the height of the png
|
||||
pngHeight = parseLength(byteArray.copyOfRange(i +8, i +12))
|
||||
pngHeight = Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(i +8, i +12).map(Byte::toInt))
|
||||
body = byteArray.copyOfRange(i + 4, i + bodySize + 4)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package oupson.apng.chunks
|
|||
import oupson.apng.utils.Utils
|
||||
import oupson.apng.utils.Utils.Companion.getBlendOp
|
||||
import oupson.apng.utils.Utils.Companion.getDisposeOp
|
||||
import oupson.apng.utils.Utils.Companion.parseLength
|
||||
|
||||
@Suppress("ClassName")
|
||||
class fcTL : Chunk {
|
||||
|
@ -32,19 +31,19 @@ class fcTL : Chunk {
|
|||
// Find fcTL chunk
|
||||
if (byteArray[i] == 0x66.toByte() && byteArray[i + 1] == 0x63.toByte() && byteArray[i + 2] == 0x54.toByte() && byteArray[i + 3] == 0x4C.toByte()) {
|
||||
// Get length of the body of the chunk
|
||||
val bodySize = parseLength(byteArray.copyOfRange(i - 4, 1))
|
||||
val bodySize = Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(i - 4, i+1).map{it .toInt()})
|
||||
// Get the width of the png
|
||||
pngWidth = parseLength(byteArray.copyOfRange(i + 8, i + 12))
|
||||
pngWidth = Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(i + 8, i + 12).map(Byte::toInt))
|
||||
// Get the height of the png
|
||||
pngHeight = parseLength(byteArray.copyOfRange(i + 12, i + 16))
|
||||
pngHeight = Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(i + 12, i + 16).map(Byte::toInt))
|
||||
/*
|
||||
* The `delay_num` and `delay_den` parameters together specify a fraction indicating the time to display the current frame, in seconds.
|
||||
* If the the value of the numerator is 0 the decoder should render the next frame as quickly as possible, though viewers may impose a reasonable lower bound.
|
||||
*/
|
||||
// Get delay numerator
|
||||
val delayNum = parseLength(byteArray.copyOfRange(i + 24, i + 26)).toFloat()
|
||||
val delayNum = Utils.uShortFromBytesBigEndian(byteArray.copyOfRange(i + 24, i + 26).map(Byte::toInt)).toFloat()
|
||||
// Get delay denominator
|
||||
var delayDen = parseLength(byteArray.copyOfRange(i + 26, i + 28)).toFloat()
|
||||
var delayDen = Utils.uShortFromBytesBigEndian(byteArray.copyOfRange(i + 26, i + 28).map(Byte::toInt)).toFloat()
|
||||
|
||||
// If the denominator is 0, it is to be treated as if it were 100 (that is, `delay_num` then specifies 1/100ths of a second).
|
||||
if (delayDen == 0f) {
|
||||
|
@ -52,8 +51,8 @@ class fcTL : Chunk {
|
|||
}
|
||||
delay = (delayNum / delayDen * 1000)
|
||||
// Get x and y offsets
|
||||
xOffset = parseLength(byteArray.copyOfRange(i + 16, i + 20))
|
||||
yOffset = parseLength(byteArray.copyOfRange(i + 20, i + 24))
|
||||
xOffset = Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(i + 16, i + 20).map(Byte::toInt))
|
||||
yOffset = Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(i + 20, i + 24).map(Byte::toInt))
|
||||
body = byteArray.copyOfRange(i + 4, i + bodySize + 4)
|
||||
blendOp = getBlendOp(String.format("%02x", byteArray[33]).toLong(16).toInt())
|
||||
disposeOp = getDisposeOp(String.format("%02x", byteArray[32]).toLong(16).toInt())
|
||||
|
|
|
@ -111,7 +111,7 @@ class ApngDecoder {
|
|||
|
||||
if (byteRead == -1)
|
||||
break
|
||||
val length = Utils.parseLength(lengthChunk)
|
||||
val length = Utils.uIntFromBytesBigEndian(lengthChunk.map(Byte::toInt))
|
||||
|
||||
val chunk = ByteArray(length + 8)
|
||||
byteRead = inputStream.read(chunk)
|
||||
|
@ -119,7 +119,7 @@ class ApngDecoder {
|
|||
val byteArray = lengthChunk.plus(chunk)
|
||||
val i = 4
|
||||
val chunkCRC =
|
||||
Utils.parseLength(byteArray.copyOfRange(byteArray.size - 4, byteArray.size))
|
||||
Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(byteArray.size - 4, byteArray.size).map(Byte::toInt))
|
||||
val crc = CRC32()
|
||||
crc.update(byteArray.copyOfRange(i, byteArray.size - 4))
|
||||
if (chunkCRC == crc.value.toInt()) {
|
||||
|
@ -400,16 +400,16 @@ class ApngDecoder {
|
|||
}
|
||||
// Find the chunk length
|
||||
val bodySize =
|
||||
Utils.parseLength(byteArray.copyOfRange(i - 4, i))
|
||||
Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(i - 4, i).map(Byte::toInt))
|
||||
cover.addAll(byteArray.copyOfRange(i - 4, i).asList())
|
||||
val body = ArrayList<Byte>()
|
||||
body.addAll(Utils.IDAT.asList())
|
||||
// Get image bytes
|
||||
body.addAll(
|
||||
byteArray.copyOfRange(
|
||||
i + 4,
|
||||
byteArray.slice(
|
||||
i + 4..
|
||||
i + 4 + bodySize
|
||||
).asList()
|
||||
)
|
||||
)
|
||||
val crC32 = CRC32()
|
||||
crC32.update(body.toByteArray(), 0, body.size)
|
||||
|
@ -418,7 +418,7 @@ class ApngDecoder {
|
|||
} else {
|
||||
// Find the chunk length
|
||||
val bodySize =
|
||||
Utils.parseLength(byteArray.copyOfRange(i - 4, i))
|
||||
Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(i - 4, i).map(Byte::toInt))
|
||||
png.addAll(byteArray.copyOfRange(i - 4, i).asList())
|
||||
val body = ArrayList<Byte>()
|
||||
body.addAll(Utils.IDAT.asList())
|
||||
|
@ -437,7 +437,7 @@ class ApngDecoder {
|
|||
}
|
||||
name.contentEquals(Utils.fdAT) -> {
|
||||
// Find the chunk length
|
||||
val bodySize = Utils.parseLength(byteArray.copyOfRange(i - 4, i))
|
||||
val bodySize = Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(i - 4, i).map(Byte::toInt))
|
||||
png?.addAll(Utils.to4Bytes(bodySize - 4).asList())
|
||||
val body = ArrayList<Byte>()
|
||||
body.addAll(Utils.IDAT.asList())
|
||||
|
|
|
@ -71,10 +71,10 @@ class ApngEncoder(
|
|||
}
|
||||
var cursor = 8
|
||||
while (cursor < byteArray.size) {
|
||||
val chunk = byteArray.copyOfRange(cursor, cursor + Utils.parseLength(byteArray.copyOfRange(cursor, cursor + 4)) + 12)
|
||||
val chunk = byteArray.copyOfRange(cursor, cursor + Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(cursor, cursor + 4).map(Byte::toInt)) + 12)
|
||||
parse(chunk)
|
||||
|
||||
cursor += Utils.parseLength(byteArray.copyOfRange(cursor, cursor + 4)) + 12
|
||||
cursor += Utils.uIntFromBytesBigEndian(byteArray.copyOfRange(cursor, cursor + 4).map(Byte::toInt)) + 12
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,19 +178,25 @@ class Utils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Parse the length of chunks
|
||||
* [byteArray] The beginning of the chunk, containing the length
|
||||
* [Int] The length of the chunk
|
||||
* Parse an unsigned int
|
||||
* [bytes] The bytes, in big endian order
|
||||
* [Int] The parsed int
|
||||
*/
|
||||
// TODO REWRITE THIS ... THING
|
||||
fun parseLength(byteArray: ByteArray): Int {
|
||||
var lengthString = ""
|
||||
byteArray.forEach {
|
||||
lengthString += String.format("%02x", it)
|
||||
}
|
||||
// TODO CHECK IF THERE IS NO SHITTY STRING CONVERSION INSTEAD OF USING THIS FUNCTION
|
||||
fun uIntFromBytesBigEndian(bytes: List<Int>): Int =
|
||||
((bytes[0] and 0xFF) shl 24) or
|
||||
((bytes[1] and 0xFF) shl 16) or
|
||||
((bytes[2] and 0xFF) shl 8) or
|
||||
(bytes[3] and 0xFF)
|
||||
|
||||
return lengthString.toLong(16).toInt()
|
||||
}
|
||||
/**
|
||||
* Parse an unsigned short
|
||||
* [bytes] The bytes, in big endian order
|
||||
* [Short] The parsed short
|
||||
*/
|
||||
fun uShortFromBytesBigEndian(bytes: List<Int>): Short =
|
||||
(((bytes[1] and 0xFF) shl 8) or
|
||||
(bytes[0] and 0xFF)).toShort()
|
||||
|
||||
val fcTL: ByteArray by lazy { byteArrayOf(0x66, 0x63, 0x54, 0x4c) }
|
||||
val IEND: ByteArray by lazy { byteArrayOf(0x49, 0x45, 0x4e, 0x44) }
|
||||
|
|
Loading…
Reference in New Issue