Update kdoc
This commit is contained in:
parent
e3f8614873
commit
b4d40c5764
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 -> {
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue