Update kdoc

This commit is contained in:
oupson 2019-06-11 21:45:15 +02:00
parent e3f8614873
commit b4d40c5764
10 changed files with 139 additions and 34 deletions

View File

@ -34,7 +34,7 @@ class APNGDisassembler {
/**
* Disassemble an Apng file
* @param byteArray The Byte Array of the file
* @return The apng decoded
* @return [Apng] The apng decoded
*/
fun disassemble(byteArray: ByteArray) : Apng {
reset()
@ -51,6 +51,13 @@ class APNGDisassembler {
}
}
/**
* Generate a correct IHDR from the IHDR chunk of the APNG
* @param ihdrOfApng The IHDR of the APNG
* @param width The width of the frame
* @param height The height of the frame
* @return [ByteArray] The generated IHDR
*/
private fun generateIhdr(ihdrOfApng: IHDR, width : Int, height : Int) : ByteArray {
val ihdr = ArrayList<Byte>()
// We need a body var to know body length and generate crc
@ -73,6 +80,10 @@ class APNGDisassembler {
return ihdr.toByteArray()
}
/**
* Parse the chunk
* @param byteArray The chunk with length and crc
*/
private fun parseChunk(byteArray: ByteArray) {
val i = 4
val chunkCRC = parseLength(byteArray.copyOfRange(byteArray.size - 4, byteArray.size))
@ -220,6 +231,9 @@ class APNGDisassembler {
} else throw BadCRC()
}
/**
* Reset all var before parsing APNG
*/
private fun reset() {
png = null
cover = null

View File

@ -40,6 +40,7 @@ class Apng {
/**
* Add a frame to the APNG
* @param bitmap The bitmap to add
* @param index Index of the frame in the animation
* @param delay Delay of the frame
* @param xOffset The X offset where the frame should be rendered
* @param yOffset The Y offset where the frame should be rendered
@ -53,6 +54,11 @@ class Apng {
frames.add(index, Frame(PngEncoder.encode(bitmap, true), delay, xOffset, yOffset, blendOp, disposeOp))
}
/**
* Add a frame to the APNG
* @param frame The frame to add
* @param index Index of the frame in the animation
*/
fun addFrames(frame : Frame, index: Int? = null) {
if (index == null)
frames.add(frame)
@ -63,7 +69,7 @@ class Apng {
/**
* Generate a Bytes Array of the APNG
* @return The Bytes Array of the APNG
* @return [ByteArray] The Bytes Array of the APNG
*/
fun toByteArray() : ByteArray {
var seq = 0
@ -289,7 +295,7 @@ class Apng {
* @param bitmap The bitmap of the cover
* @param maxWidth Max width of APNG
* @param maxHeight Max height of the APNG
* @return An image cover
* @return [Bitmap] An image cover
*/
@Suppress("MemberVisibilityCanBePrivate")
fun generateCover(bitmap: Bitmap, maxWidth : Int, maxHeight : Int) : Bitmap {
@ -298,7 +304,7 @@ class Apng {
/**
* Generate the IHDR chunks.
* @return The byteArray generated
* @return [ByteArray] The byteArray generated
*/
private fun generateIhdr(): ByteArray {
val ihdr = ArrayList<Byte>()
@ -337,7 +343,7 @@ class Apng {
/**
* Generate the animation control chunk
* @return The byteArray generated
* @return [ArrayList] The byteArray generated
*/
private fun generateACTL(): ArrayList<Byte> {
val res = ArrayList<Byte>()
@ -399,6 +405,10 @@ class Apng {
frames = apng.frames
}
/**
* A function to optimise Frame
* WIP !
*/
fun optimiseFrame() {
maxHeight = frames.sortedByDescending { it.height }[0].height
maxWidth = frames.sortedByDescending { it.width }[0].width

View File

@ -17,26 +17,67 @@ import oupson.apng.utils.Utils.Companion.isApng
import java.io.File
import java.net.URL
/**
* @param file The APNG to load
* @param speed The speed of the APNG
* @param apngAnimatorOptions Options of the animator
* @return [ApngAnimator] The animator
*/
@Suppress("unused")
fun ImageView.loadApng(file: File, speed: Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) = ApngAnimator(this.context).loadInto(this).apply {
load(file, speed, apngAnimatorOptions)
}
/**
* @param uri The APNG to load
* @param speed The speed of the APNG
* @param apngAnimatorOptions Options of the animator
* @return [ApngAnimator] The animator
*/
@Suppress("unused")
fun ImageView.loadApng(uri : Uri, speed: Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) = ApngAnimator(this.context).loadInto(this).apply {
load(uri, speed, apngAnimatorOptions)
}
/**
* @param url The url of the APNG to load
* @param speed The speed of the APNG
* @param apngAnimatorOptions Options of the animator
* @return [ApngAnimator] The animator
*/
@Suppress("unused")
fun ImageView.loadApng(url: URL, speed: Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) = ApngAnimator(this.context).loadInto(this).apply {
loadUrl(url, speed, apngAnimatorOptions)
}
/**
* @param byteArray The APNG to load
* @param speed The speed of the APNG
* @param apngAnimatorOptions Options of the animator
* @return [ApngAnimator] The animator
*/
@Suppress("unused")
fun ImageView.loadApng(byteArray: ByteArray, speed: Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) = ApngAnimator(this.context).loadInto(this).apply {
load(byteArray, speed, apngAnimatorOptions)
}
/**
* @param string The path APNG to load
* @param speed The speed of the APNG
* @param apngAnimatorOptions Options of the animator
* @return [ApngAnimator] The animator
*/
@Suppress("unused")
fun ImageView.loadApng(string: String, speed : Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) = ApngAnimator(this.context).loadInto(this).apply {
load(string, speed, apngAnimatorOptions)
}
/**
* @param res The Resource Int of the APNG to load, must be in the raw folder
* @param speed The speed of the APNG
* @param apngAnimatorOptions Options of the animator
* @return [ApngAnimator] The animator
*/
@Suppress("unused")
fun ImageView.loadApng(@RawRes res : Int, speed : Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) = ApngAnimator(this.context).loadInto(this).apply {
load(res, speed, apngAnimatorOptions)
@ -90,6 +131,7 @@ class ApngAnimator(private val context: Context?) {
/**
* Specify if the library could load non apng file
* @param boolean If true the file will be loaded even if it is not an APNG
*/
@Suppress("unused")
@SuppressWarnings("WeakerAccess")
@ -102,6 +144,7 @@ class ApngAnimator(private val context: Context?) {
/**
* Load into an ImageView
* @param imageView Image view selected.
* @return [ApngAnimator] The Animator
*/
fun loadInto(imageView: ImageView): ApngAnimator {
this.imageView = imageView
@ -112,6 +155,7 @@ class ApngAnimator(private val context: Context?) {
* Load an APNG file and starts playing the animation.
* @param file The file to load
* @param speed The speed
* @return [ApngAnimator] The Animator
* @throws NotApngException
*/
@Suppress("unused")
@ -147,6 +191,7 @@ class ApngAnimator(private val context: Context?) {
* Load an APNG file and starts playing the animation.
* @param uri The uri to load
* @param speed The speed
* @return [ApngAnimator] The Animator
* @throws NotApngException
*/
fun load(uri : Uri, speed: Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) : ApngAnimator {
@ -181,6 +226,7 @@ class ApngAnimator(private val context: Context?) {
* Load an APNG file and starts playing the animation.
* @param url URL to load.
* @param speed The speed
* @return [ApngAnimator] The Animator
* @throws NotApngException
*/
@SuppressWarnings("WeakerAccess")
@ -220,6 +266,7 @@ class ApngAnimator(private val context: Context?) {
* Load an APNG file and starts playing the animation.
* @param byteArray ByteArray of the file
* @param speed The speed
* @return [ApngAnimator] The Animator
* @throws NotApngException
*/
@SuppressWarnings("WeakerAccess")
@ -254,6 +301,7 @@ class ApngAnimator(private val context: Context?) {
* Load an APNG file
* @param string Path of the file.
* @param speed The speed
* @return [ApngAnimator] The Animator
* @throws NotApngException
*/
fun load(string: String, speed : Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) : ApngAnimator {
@ -296,7 +344,13 @@ class ApngAnimator(private val context: Context?) {
}
return this
}
/**
* Load an APNG file
* @param res The res of the file
* @param speed The speed
* @return [ApngAnimator] The Animator
* @throws NotApngException
*/
fun load(@RawRes res : Int, speed : Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) : ApngAnimator {
GlobalScope.launch {
val byteArray = context?.resources?.openRawResource(res)?.readBytes() ?: byteArrayOf()
@ -327,6 +381,7 @@ class ApngAnimator(private val context: Context?) {
/**
* Sets up the animation drawable and any required listeners. The animation will automatically start.
* @param generatedFrame The frames generated by draw function
*/
private fun setupAnimationDrawableAndStart(generatedFrame: ArrayList<Bitmap>) {
GlobalScope.launch {
@ -346,6 +401,8 @@ class ApngAnimator(private val context: Context?) {
/**
* Draw frames
* @param extractedFrame The frames extracted by the disassembler
* @return [ArrayList] The drawed frames
*/
fun draw(extractedFrame: ArrayList<Frame>) : ArrayList<Bitmap> {
val generatedFrame = ArrayList<Bitmap>()
@ -455,6 +512,8 @@ class ApngAnimator(private val context: Context?) {
/**
* Converts the generated frames into an animation drawable ([CustomAnimationDrawable])
* in the APNG will be used instead.
* @param generatedFrame The frames
* @return [CustomAnimationDrawable] The animation drawable
*/
private fun toAnimationDrawable( generatedFrame : ArrayList<Bitmap> ): CustomAnimationDrawable {
if (isApng) {

View File

@ -10,13 +10,16 @@ import oupson.apng.utils.Utils.Companion.isPng
import java.util.*
/**
* A frame for an animated png
* @author oupson
* @param byteArray The byte Array of the png
* @param delay The delay in ms, default is 1000
* @throws NotPngException
* A frame of the APNG
* @param byteArray The bitmap to add
* @param delay Delay of the frame
* @param xOffsets The X offset where the frame should be rendered
* @param yOffsets The Y offset where the frame should be rendered
* @param disposeOp `DisposeOp` specifies how the output buffer should be changed at the end of the delay (before rendering the next frame).
* @param blendOp `BlendOp` specifies whether the frame is to be alpha blended into the current output buffer content, or whether it should completely replace its region in the output buffer.
* @param maxWidth The max width of the APNG
* @param maxHeight The max height of the APNG
*/
class Frame// Get width and height for image
(
byteArray: ByteArray,
@ -74,6 +77,10 @@ class Frame// Get width and height for image
}
}
/**
* Parse the Frame
* @param byteArray The frame
*/
private fun parseChunk(byteArray: ByteArray) {
when(Arrays.toString(byteArray.copyOfRange(4, 8))) {
IHDR -> {

View File

@ -1,6 +1,14 @@
package oupson.apng.chunks
/**
* An interface for the png chunks
*/
interface Chunk {
var body : ByteArray
/**
* Parse the chunk
* @param byteArray The chunk with the length and the crc
*/
fun parse(byteArray: ByteArray)
}

View File

@ -7,6 +7,10 @@ class IDAT : Chunk {
var IDATBody: ArrayList<ByteArray> = ArrayList()
override var body = byteArrayOf()
/**
* Parse the chunk
* @param byteArray The chunk with the length and the crc
*/
override fun parse(byteArray: ByteArray) {
val i = 4
// Find IDAT chunk

View File

@ -6,6 +6,11 @@ class IHDR : Chunk {
override var body = byteArrayOf()
var pngWidth = -1
var pngHeight = -1
/**
* Parse the chunk
* @param byteArray The chunk with the length and the crc
*/
override fun parse(byteArray: ByteArray) {
for (i in 0 until byteArray.size) {
// Find IHDR chunk

View File

@ -23,6 +23,10 @@ class fcTL : Chunk {
var blendOp : Utils.Companion.BlendOp = Utils.Companion.BlendOp.APNG_BLEND_OP_SOURCE
var disposeOp : Utils.Companion.DisposeOp = Utils.Companion.DisposeOp.APNG_DISPOSE_OP_NONE
/**
* Parse the chunk
* @param byteArray The chunk with the length and the crc
*/
override fun parse(byteArray: ByteArray) {
val i = 4
// Find fcTL chunk

View File

@ -5,7 +5,8 @@ import java.util.*
class Utils {
companion object {
/**
* @return True if is a png
* @param byteArray The PNG
* @return [Boolean] True if is a png
*/
fun isPng(byteArray: ByteArray): Boolean {
return byteArray.copyOfRange(0, 8).contentToString() == pngSignature.contentToString()
@ -13,6 +14,7 @@ class Utils {
/**
* Know if file is an APNG
* @param byteArray APNG
* @return True if is an APNG
*/
fun isApng(byteArray: ByteArray) : Boolean {
@ -60,7 +62,7 @@ class Utils {
/**
* Get the int equivalent to the DisposeOp
* @param disposeOp The DisposeOp
* @return An int equivalent to the DisposeOp
* @return [Int] An int equivalent to the DisposeOp
*/
fun getDisposeOp(disposeOp: DisposeOp) : Int {
return when(disposeOp) {
@ -73,7 +75,7 @@ class Utils {
/**
* Get the DisposeOp enum equivalent to the int
* @param int Int of the DisposeOp
* @return A DisposeOp
* @return [DisposeOp] A DisposeOp
*/
fun getDisposeOp(int: Int) : DisposeOp {
return when(int) {
@ -92,7 +94,7 @@ class Utils {
/**
* Get the int equivalent to the BlendOp
* @param blendOp The BlendOp
* @return An int equivalent to the BlendOp
* @return [Int] An int equivalent to the BlendOp
*/
fun getBlendOp(blendOp: BlendOp) : Int {
return when(blendOp) {
@ -104,7 +106,7 @@ class Utils {
/**
* Get the BlendOp enum equivalent to the int
* @param int Int of the BlendOp
* @return A BlendOp
* @return [BlendOp] A BlendOp
*/
fun getBlendOp(int : Int) : BlendOp {
return when(int) {
@ -117,7 +119,7 @@ class Utils {
/**
* Generate a 4 bytes array from an Int
* @param i The int
* @return 2 Bytes
* @return [ByteArray] 2 Bytes
*/
fun to4Bytes(i: Int): ByteArray {
return byteArrayOf((i shr 24).toByte(), (i shr 16).toByte(), (i shr 8).toByte(), i.toByte())
@ -126,15 +128,17 @@ class Utils {
/**
* Generate a 2 bytes array from an Int
* @param i The int
* @return 2 Bytes
* @return [ByteArray] 2 Bytes
*/
fun to2Bytes(i: Int): ByteArray {
val result = ByteArray(2)
result[0] = (i shr 8).toByte()
result[1] = i /*>> 0*/.toByte()
return result
return byteArrayOf((i shr 8).toByte(), i /*>> 0*/.toByte())
}
/**
* Parse the length of chunks
* [byteArray] The beginning of the chunk, containing the length
* [Int] The length of the chunk
*/
fun parseLength(byteArray: ByteArray) : Int {
var lengthString = ""
byteArray.forEach {

View File

@ -68,21 +68,11 @@ class Main2Activity : AppCompatActivity() {
permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
2 -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
load()
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return
}
}// other 'case' lines to check for other
// permissions this app might request.
}
}
}