Update to androidx

Clean code
This commit is contained in:
oupson 2019-05-17 18:48:32 +02:00
parent 5235a6b3a4
commit d2d4978180
19 changed files with 173 additions and 231 deletions

View File

@ -10,7 +10,7 @@ android {
versionCode 1
versionName "1.0.9"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
@ -26,11 +26,11 @@ android {
}
dependencies {
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'androidx.appcompat:appcompat:1.0.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
implementation "org.jetbrains.anko:anko:$anko_version"

View File

@ -1,9 +1,8 @@
package oupson.apng;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;

View File

@ -25,8 +25,8 @@ class APNGDisassembler {
private var tnrs: ByteArray? = null
private var maxWidth = 0
private var maxHeight = 0
private var blend_op: Utils.Companion.blend_op = Utils.Companion.blend_op.APNG_BLEND_OP_SOURCE
private var dispose_op: Utils.Companion.dispose_op = Utils.Companion.dispose_op.APNG_DISPOSE_OP_NONE
private var blendOp: Utils.Companion.BlendOp = Utils.Companion.BlendOp.APNG_BLEND_OP_SOURCE
private var disposeOp: Utils.Companion.DisposeOp = Utils.Companion.DisposeOp.APNG_DISPOSE_OP_NONE
private var ihdr = IHDR()
var apng: Apng = Apng()
@ -98,17 +98,17 @@ class APNGDisassembler {
val fcTL = fcTL()
fcTL.parse(byteArray)
delay = fcTL.delay
yOffset = fcTL.y_offset
xOffset = fcTL.x_offset
blend_op = fcTL.blend_op
dispose_op = fcTL.dispose_op
yOffset = fcTL.yOffset
xOffset = fcTL.xOffset
blendOp = fcTL.blendOp
disposeOp = fcTL.disposeOp
val width = fcTL.pngWidth
val height = fcTL.pngHeight
if (xOffset + width > maxWidth) {
throw BadApng("`y_offset` + `height` must be <= `IHDR` height")
throw BadApng("`yOffset` + `height` must be <= `IHDR` height")
} else if (yOffset + height > maxHeight) {
throw BadApng("`y_offset` + `height` must be <= `IHDR` height")
throw BadApng("`yOffset` + `height` must be <= `IHDR` height")
}
png?.addAll(pngSignature.toList())
@ -129,15 +129,15 @@ class APNGDisassembler {
crC32.update(iend, 0, iend.size)
png!!.addAll(iend.toList())
png!!.addAll(to4Bytes(crC32.value.toInt()).toList())
apng.frames.add(Frame(png!!.toByteArray(), delay, xOffset, yOffset, maxWidth, maxHeight, blend_op, dispose_op))
apng.frames.add(Frame(png!!.toByteArray(), delay, xOffset, yOffset, maxWidth, maxHeight, blendOp, disposeOp))
png = ArrayList()
val fcTL = fcTL()
fcTL.parse(byteArray)
delay = fcTL.delay
yOffset = fcTL.y_offset
xOffset = fcTL.x_offset
blend_op = fcTL.blend_op
dispose_op = fcTL.dispose_op
yOffset = fcTL.yOffset
xOffset = fcTL.xOffset
blendOp = fcTL.blendOp
disposeOp = fcTL.disposeOp
val width = fcTL.pngWidth
val height = fcTL.pngHeight
png!!.addAll(pngSignature.toList())
@ -159,7 +159,7 @@ class APNGDisassembler {
crC32.update(iend, 0, iend.size)
png!!.addAll(iend.toList())
png!!.addAll(to4Bytes(crC32.value.toInt()).toList())
apng.frames.add(Frame(png!!.toByteArray(), delay, xOffset, yOffset, maxWidth, maxHeight, blend_op, dispose_op))
apng.frames.add(Frame(png!!.toByteArray(), delay, xOffset, yOffset, maxWidth, maxHeight, blendOp, disposeOp))
}
Utils.IDAT -> {
if (png == null) {

View File

@ -3,14 +3,14 @@ package oupson.apng
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Environment
import oupson.apng.ImageUtils.BitmapDiffCalculator
import oupson.apng.ImageUtils.PngEncoder
import oupson.apng.ImageUtils.PnnQuantizer
import oupson.apng.chunks.IDAT
import oupson.apng.exceptions.NoFrameException
import oupson.apng.imageUtils.BitmapDiffCalculator
import oupson.apng.imageUtils.PngEncoder
import oupson.apng.imageUtils.PnnQuantizer
import oupson.apng.utils.Utils
import oupson.apng.utils.Utils.Companion.getBlend_op
import oupson.apng.utils.Utils.Companion.getDispose_op
import oupson.apng.utils.Utils.Companion.getBlendOp
import oupson.apng.utils.Utils.Companion.getDisposeOp
import oupson.apng.utils.Utils.Companion.pngSignature
import oupson.apng.utils.Utils.Companion.to2Bytes
import oupson.apng.utils.Utils.Companion.to4Bytes
@ -21,7 +21,9 @@ import java.util.zip.CRC32
* Create an APNG file
*/
class Apng {
@Suppress("MemberVisibilityCanBePrivate")
var maxWidth : Int? = null
@Suppress("MemberVisibilityCanBePrivate")
var maxHeight : Int? = null
/**
@ -34,99 +36,29 @@ class Apng {
var frames : ArrayList<Frame> = ArrayList()
// region addFrames
/**
* Add a frame to the APNG
* @param bitmap The bitamp to add
*/
fun addFrames(bitmap: Bitmap) {
frames.add(Frame(PngEncoder.encode(bitmap, true)))
}
/**
* Add a frame to the APNG
* @param bitmap The bitamp to add
* @param delay Delay of the frame
*/
fun addFrames(bitmap: Bitmap, delay : Float) {
frames.add(Frame(PngEncoder.encode(bitmap, true), delay))
}
/**
* Add a frame to the APNG
* @param bitmap The bitamp to add
* @param delay Delay of the frame
* @param dispose_op `dispose_op` specifies how the output buffer should be changed at the end of the delay (before rendering the next frame).
* @param blend_op `blend_op` 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.
*/
fun addFrames(bitmap: Bitmap, delay: Float, dispose_op: Utils.Companion.dispose_op, blend_op: Utils.Companion.blend_op) {
frames.add(Frame(PngEncoder.encode(bitmap, true), delay, blend_op, dispose_op))
}
/**
* Add a frame to the APNG
* @param bitmap The bitamp to add
* @param bitmap The bitmap to add
* @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
* @param dispose_op `dispose_op` specifies how the output buffer should be changed at the end of the delay (before rendering the next frame).
* @param blend_op `blend_op` 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 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.
*/
fun addFrames(bitmap: Bitmap, delay: Float, xOffset : Int, yOffset : Int, dispose_op: Utils.Companion.dispose_op, blend_op: Utils.Companion.blend_op) {
frames.add(Frame(PngEncoder.encode(bitmap, true), delay, xOffset, yOffset, blend_op, dispose_op))
fun addFrames(bitmap : Bitmap, index : Int? = null, delay : Float = 1000f, xOffset : Int = 0, yOffset : Int = 0, disposeOp: Utils.Companion.DisposeOp = Utils.Companion.DisposeOp.APNG_DISPOSE_OP_NONE, blendOp: Utils.Companion.BlendOp = Utils.Companion.BlendOp.APNG_BLEND_OP_SOURCE) {
if (index == null)
frames.add(Frame(PngEncoder.encode(bitmap, true), delay, xOffset, yOffset, blendOp, disposeOp))
else
frames.add(index, Frame(PngEncoder.encode(bitmap, true), delay, xOffset, yOffset, blendOp, disposeOp))
}
/**
* Add a frame to the APNG
* @param index Index where we add the frame
* @param bitmap The bitamp to add
*/
fun addFrames(index : Int, bitmap: Bitmap) {
frames.add(index, Frame(PngEncoder.encode(bitmap, true)))
}
/**
* Add a frame to the APNG
* @param index Index where we add the frame
* @param bitmap The bitamp to add
* @param delay Delay of the frame
*/
fun addFrames(index : Int, bitmap: Bitmap, delay : Float) {
frames.add(index, Frame(PngEncoder.encode(bitmap, true), delay))
}
/**
* Add a frame to the APNG
* @param index Index where we add the frame
* @param bitmap The bitamp to add
* @param delay Delay of the frame
* @param dispose_op `dispose_op` specifies how the output buffer should be changed at the end of the delay (before rendering the next frame).
* @param blend_op `blend_op` 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.
*/
fun addFrames(index: Int, bitmap: Bitmap, delay: Float, dispose_op: Utils.Companion.dispose_op, blend_op: Utils.Companion.blend_op) {
frames.add(index, Frame(PngEncoder.encode(bitmap, true), delay, blend_op, dispose_op))
}
/**
* Add a frame to the APNG
* @param index Index where we add the frame
* @param bitmap The bitamp to add
* @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
* @param dispose_op `dispose_op` specifies how the output buffer should be changed at the end of the delay (before rendering the next frame).
* @param blend_op `blend_op` 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.
*/
fun addFrames(index: Int, bitmap: Bitmap, delay: Float, xOffset : Int, yOffset : Int, dispose_op: Utils.Companion.dispose_op, blend_op: Utils.Companion.blend_op) {
frames.add(index, Frame(PngEncoder.encode(bitmap, true), delay, xOffset, yOffset, blend_op, dispose_op))
}
fun addFrames(frame : Frame) {
frames.add(frame)
}
fun addFrames(index: Int,frame : Frame) {
frames.add(index, frame)
@Suppress("unused")
fun addFrames(frame : Frame, index: Int? = null) {
if (index == null)
frames.add(frame)
else
frames.add(index, frame)
}
//endregion
@ -139,7 +71,6 @@ class Apng {
val res = ArrayList<Byte>()
// Add PNG signature
res.addAll(pngSignature.toList())
// Add Image Header
res.addAll(generateIhdr().toList())
@ -178,9 +109,9 @@ class Apng {
fcTL.addAll(to2Bytes(frames[0].delay.toInt()).toList())
fcTL.addAll(to2Bytes(1000).toList())
// Add dispose_op and blend_op
fcTL.add(getDispose_op(frames[0].dispose_op).toByte())
fcTL.add(getBlend_op(frames[0].blend_op).toByte())
// Add DisposeOp and BlendOp
fcTL.add(getDisposeOp(frames[0].disposeOp).toByte())
fcTL.add(getBlendOp(frames[0].blendOp).toByte())
// Create CRC
val crc = CRC32()
@ -247,9 +178,9 @@ class Apng {
fcTL.addAll(to2Bytes(frames[0].delay.toInt()).toList())
fcTL.addAll(to2Bytes(1000).toList())
// Add dispose_op and blend_op
fcTL.add(getDispose_op(frames[0].dispose_op).toByte())
fcTL.add(getBlend_op(frames[0].blend_op).toByte())
// Add DisposeOp and BlendOp
fcTL.add(getDisposeOp(frames[0].disposeOp).toByte())
fcTL.add(getBlendOp(frames[0].blendOp).toByte())
// Generate CRC
val crc = CRC32()
@ -302,8 +233,8 @@ class Apng {
fcTL.addAll(to2Bytes(frames[i].delay.toInt()).toList())
fcTL.addAll(to2Bytes(1000).toList())
fcTL.add(getDispose_op(frames[i].dispose_op).toByte())
fcTL.add(getBlend_op(frames[i].blend_op).toByte())
fcTL.add(getDisposeOp(frames[i].disposeOp).toByte())
fcTL.add(getBlendOp(frames[i].blendOp).toByte())
val crc = CRC32()
crc.update(fcTL.toByteArray(), 0, fcTL.size)
@ -359,6 +290,7 @@ class Apng {
* @param maxHeight Max height of the APNG
* @return An image cover
*/
@Suppress("MemberVisibilityCanBePrivate")
fun generateCover(bitmap: Bitmap, maxWidth : Int, maxHeight : Int) : Bitmap {
return Bitmap.createScaledBitmap(bitmap, maxWidth, maxHeight, false)
}
@ -371,7 +303,7 @@ class Apng {
val ihdr = ArrayList<Byte>()
// We need a body var to know body length and generate crc
val ihdr_body = ArrayList<Byte>()
val ihdrBody = ArrayList<Byte>()
// Get max height and max width of all the frames
maxHeight = frames.sortedByDescending { it.height }[0].height
@ -384,20 +316,20 @@ class Apng {
// Add chunk body length
ihdr.addAll(to4Bytes(frames[0].ihdr.body.size).toList())
// Add IHDR
ihdr_body.addAll(byteArrayOf(0x49.toByte(), 0x48.toByte(), 0x44.toByte(), 0x52.toByte()).toList())
ihdrBody.addAll(byteArrayOf(0x49.toByte(), 0x48.toByte(), 0x44.toByte(), 0x52.toByte()).toList())
// Add the max width and height
ihdr_body.addAll(to4Bytes(maxWidth!!).toList())
ihdr_body.addAll(to4Bytes(maxHeight!!).toList())
ihdrBody.addAll(to4Bytes(maxWidth!!).toList())
ihdrBody.addAll(to4Bytes(maxHeight!!).toList())
// Add complicated stuff like depth color ...
// If you want correct png you need same parameters. Good solution is to create new png.
ihdr_body.addAll(frames[0].ihdr.body.copyOfRange(8, 13).toList())
ihdrBody.addAll(frames[0].ihdr.body.copyOfRange(8, 13).toList())
// Generate CRC
val crC32 = CRC32()
crC32.update(ihdr_body.toByteArray(), 0, ihdr_body.size)
ihdr.addAll(ihdr_body)
crC32.update(ihdrBody.toByteArray(), 0, ihdrBody.size)
ihdr.addAll(ihdrBody)
ihdr.addAll(to4Bytes(crC32.value.toInt()).toList())
return ihdr.toByteArray()
}
@ -437,12 +369,13 @@ class Apng {
* @param keepCover Keep the cover
* @param sizePercent Reduce image width/height by percents.
*/
fun reduceSize( maxColor : Int, keepCover : Boolean? = null, sizePercent : Int? = null) {
@Suppress("unused")
fun reduceSize(maxColor : Int, keepCover : Boolean? = null, sizePercent : Int? = null) {
val apng = Apng()
if (keepCover != false) {
if (cover != null) {
if (sizePercent != null) {
cover = Bitmap.createScaledBitmap(cover, (cover!!.width.toFloat() * sizePercent.toFloat() / 100f).toInt(), (cover!!.height.toFloat() * sizePercent.toFloat() / 100f).toInt(), false)
cover = Bitmap.createScaledBitmap(cover!!, (cover!!.width.toFloat() * sizePercent.toFloat() / 100f).toInt(), (cover!!.height.toFloat() * sizePercent.toFloat() / 100f).toInt(), false)
val pnn = PnnQuantizer(cover)
cover = pnn.convert(maxColor, false)
}
@ -458,9 +391,9 @@ class Apng {
val pnn = PnnQuantizer(btm)
val btmOptimised = pnn.convert(maxColor, false)
if (sizePercent != null) {
apng.addFrames(btmOptimised, it.delay, (it.x_offsets.toFloat() * sizePercent.toFloat() / 100f).toInt(), (it.y_offsets.toFloat() * sizePercent.toFloat() / 100f).toInt(), it.dispose_op, it.blend_op)
apng.addFrames(btmOptimised, 0, it.delay, (it.x_offsets.toFloat() * sizePercent.toFloat() / 100f).toInt(), (it.y_offsets.toFloat() * sizePercent.toFloat() / 100f).toInt(), it.disposeOp, it.blendOp)
} else {
apng.addFrames(btmOptimised, it.delay, it.x_offsets, it.y_offsets, it.dispose_op, it.blend_op)
apng.addFrames(btmOptimised, 0, it.delay, it.x_offsets, it.y_offsets, it.disposeOp, it.blendOp)
}
}
frames = apng.frames
@ -481,7 +414,7 @@ class Apng {
frames[i].byteArray = PngEncoder.encode(diffCalculator.res, true)
frames[i].x_offsets = diffCalculator.xOffset
frames[i].y_offsets = diffCalculator.yOffset
frames[i].blend_op = Utils.Companion.blend_op.APNG_BLEND_OP_OVER
frames[i].blendOp = Utils.Companion.BlendOp.APNG_BLEND_OP_OVER
}
}
}

View File

@ -39,10 +39,12 @@ class ApngAnimator(private val context: Context?) {
var anim: CustomAnimationDrawable? = null
private var activeAnimation: CustomAnimationDrawable? = null
private var doOnLoaded : (ApngAnimator) -> Unit = {}
@Suppress("PrivatePropertyName")
@SuppressWarnings("WeakerAccess")
private var AnimationLoopListener : () -> Unit = {}
private var duration : ArrayList<Float>? = null
private var scaleType : ImageView.ScaleType? = null
@Suppress("MemberVisibilityCanBePrivate")
var isApng = false
@SuppressWarnings("WeakerAccess")
var loadNotApng = true
@ -56,6 +58,7 @@ class ApngAnimator(private val context: Context?) {
/**
* Specify if the library could load non apng file
*/
@Suppress("unused")
@SuppressWarnings("WeakerAccess")
fun loadNotApng(boolean: Boolean) {
val editor = sharedPreferences?.edit()
@ -78,6 +81,7 @@ class ApngAnimator(private val context: Context?) {
* @param speed The speed
* @throws NotApngException
*/
@Suppress("unused")
@SuppressWarnings("WeakerAccess")
fun load(file: File, speed: Float? = null, apngAnimatorOptions: ApngAnimatorOptions? = null) : ApngAnimator {
doAsync {
@ -230,12 +234,13 @@ class ApngAnimator(private val context: Context?) {
} else if (File(string).exists()) {
var pathToLoad = if (string.startsWith("content://")) string else "file://$string"
pathToLoad = pathToLoad.replace("%", "%25").replace("#", "%23")
val bytes = context!!.contentResolver.openInputStream(Uri.parse(pathToLoad)).readBytes()
val bytes = context?.contentResolver?.openInputStream(Uri.parse(pathToLoad))?.readBytes()
bytes ?: throw Exception("File are empty")
if (isApng(bytes)) {
load(bytes, speed, apngAnimatorOptions)
} else {
if (loadNotApng) {
context.runOnUiThread {
context?.runOnUiThread {
imageView?.setImageBitmap(BitmapFactory.decodeByteArray(bytes, 0, bytes.size))
}
} else {
@ -284,25 +289,25 @@ class ApngAnimator(private val context: Context?) {
// Write buffer to canvas
canvas.drawBitmap(bitmapBuffer, 0f, 0f, null)
// Clear current frame rect
// If `blend_op` is APNG_BLEND_OP_SOURCE all color components of the frame, including alpha, overwrite the current contents of the frame's output buffer region.
if (it.blend_op == Utils.Companion.blend_op.APNG_BLEND_OP_SOURCE) {
canvas.drawRect(it.x_offsets!!.toFloat(), it.y_offsets!!.toFloat(), it.x_offsets!! + current.width.toFloat(), it.y_offsets!! + current.height.toFloat(), { val paint = Paint(); paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR); paint }())
// If `BlendOp` is APNG_BLEND_OP_SOURCE all color components of the frame, including alpha, overwrite the current contents of the frame's output buffer region.
if (it.blendOp == Utils.Companion.BlendOp.APNG_BLEND_OP_SOURCE) {
canvas.drawRect(it.x_offsets.toFloat(), it.y_offsets.toFloat(), it.x_offsets + current.width.toFloat(), it.y_offsets + current.height.toFloat(), { val paint = Paint(); paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR); paint }())
}
// Draw the bitmap
canvas.drawBitmap(current, it.x_offsets!!.toFloat(), it.y_offsets!!.toFloat(), null)
canvas.drawBitmap(current, it.x_offsets.toFloat(), it.y_offsets.toFloat(), null)
generatedFrame.add(btm)
// Don't add current frame to bitmap buffer
when {
extractedFrame[i].dispose_op == Utils.Companion.dispose_op.APNG_DISPOSE_OP_PREVIOUS -> {
extractedFrame[i].disposeOp == Utils.Companion.DisposeOp.APNG_DISPOSE_OP_PREVIOUS -> {
//Do nothings
}
// Add current frame to bitmap buffer
// APNG_DISPOSE_OP_BACKGROUND: the frame's region of the output buffer is to be cleared to fully transparent black before rendering the next frame.
it.dispose_op == Utils.Companion.dispose_op.APNG_DISPOSE_OP_BACKGROUND -> {
it.disposeOp == Utils.Companion.DisposeOp.APNG_DISPOSE_OP_BACKGROUND -> {
val res = Bitmap.createBitmap(extractedFrame[0].maxWidth!!, extractedFrame[0].maxHeight!!, Bitmap.Config.ARGB_8888)
val can = Canvas(res)
can.drawBitmap(btm, 0f, 0f, null)
can.drawRect(it.x_offsets!!.toFloat(), it.y_offsets!!.toFloat(), it.x_offsets!! + it.width.toFloat(), it.y_offsets!! + it.height.toFloat(), { val paint = Paint(); paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR); paint }())
can.drawRect(it.x_offsets.toFloat(), it.y_offsets.toFloat(), it.x_offsets + it.width.toFloat(), it.y_offsets + it.height.toFloat(), { val paint = Paint(); paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR); paint }())
bitmapBuffer = res
}
else -> bitmapBuffer = btm

View File

@ -37,8 +37,8 @@ class Frame {
var maxWidth : Int? = null
var maxHeight : Int? = null
var blend_op: Utils.Companion.blend_op
var dispose_op : Utils.Companion.dispose_op
var blendOp: Utils.Companion.BlendOp
var disposeOp : Utils.Companion.DisposeOp
constructor(byteArray: ByteArray) {
if (isPng(byteArray)) {
@ -46,8 +46,8 @@ class Frame {
Log.e("tag", byteArray.size.toString())
// Get width and height for image
delay = 1000f
blend_op = Utils.Companion.blend_op.APNG_BLEND_OP_SOURCE
dispose_op = Utils.Companion.dispose_op.APNG_DISPOSE_OP_NONE
blendOp = Utils.Companion.BlendOp.APNG_BLEND_OP_SOURCE
disposeOp = Utils.Companion.DisposeOp.APNG_DISPOSE_OP_NONE
var cursor = 8
while (cursor < byteArray.size) {
val chunk = byteArray.copyOfRange(cursor, cursor + Utils.parseLength(byteArray.copyOfRange(cursor, cursor + 4)) + 12)
@ -70,14 +70,14 @@ class Frame {
}
this.delay = delay
blend_op = Utils.Companion.blend_op.APNG_BLEND_OP_SOURCE
dispose_op = Utils.Companion.dispose_op.APNG_DISPOSE_OP_NONE
blendOp = Utils.Companion.BlendOp.APNG_BLEND_OP_SOURCE
disposeOp = Utils.Companion.DisposeOp.APNG_DISPOSE_OP_NONE
} else {
throw NotPngException()
}
}
constructor(byteArray: ByteArray, delay : Float, blend_op: Utils.Companion.blend_op, dispose_op: Utils.Companion.dispose_op) {
constructor(byteArray: ByteArray, delay : Float, blendOp: Utils.Companion.BlendOp, disposeOp: Utils.Companion.DisposeOp) {
if (isPng(byteArray)) {
this.byteArray = byteArray
// Get width and height for image
@ -93,14 +93,14 @@ class Frame {
this.maxWidth = -1
this.maxHeight = -1
this.blend_op = blend_op
this.dispose_op = dispose_op
this.blendOp = blendOp
this.disposeOp = disposeOp
} else {
throw NotPngException()
}
}
constructor(byteArray: ByteArray, delay : Float, xOffsets : Int, yOffsets : Int, blend_op: Utils.Companion.blend_op, dispose_op: Utils.Companion.dispose_op) {
constructor(byteArray: ByteArray, delay : Float, xOffsets : Int, yOffsets : Int, blendOp: Utils.Companion.BlendOp, disposeOp: Utils.Companion.DisposeOp) {
if (isPng(byteArray)) {
this.byteArray = byteArray
// Get width and height for image
@ -118,14 +118,14 @@ class Frame {
this.maxWidth = -1
this.maxHeight = -1
this.blend_op = blend_op
this.dispose_op = dispose_op
this.blendOp = blendOp
this.disposeOp = disposeOp
} else {
throw NotPngException()
}
}
constructor(byteArray: ByteArray, delay : Float, xOffsets : Int, yOffsets : Int, maxWidth : Int, maxHeight : Int, blend_op: Utils.Companion.blend_op, dispose_op: Utils.Companion.dispose_op) {
constructor(byteArray: ByteArray, delay : Float, xOffsets : Int, yOffsets : Int, maxWidth : Int, maxHeight : Int, blendOp: Utils.Companion.BlendOp, disposeOp: Utils.Companion.DisposeOp) {
if (isPng(byteArray)) {
this.byteArray = byteArray
// Get width and height for image
@ -143,8 +143,8 @@ class Frame {
this.maxWidth = maxWidth
this.maxHeight = maxHeight
this.blend_op = blend_op
this.dispose_op = dispose_op
this.blendOp = blendOp
this.disposeOp = disposeOp
} else {
throw NotPngException()
}

View File

@ -3,6 +3,7 @@ package oupson.apng.chunks
import oupson.apng.utils.Utils.Companion.parseLength
class IDAT : Chunk {
@Suppress("PropertyName")
var IDATBody: ArrayList<ByteArray> = ArrayList()
override var body = byteArrayOf()

View File

@ -1,10 +1,11 @@
package oupson.apng.chunks
import oupson.apng.utils.Utils
import oupson.apng.utils.Utils.Companion.getBlend_op
import oupson.apng.utils.Utils.Companion.getDispose_op
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 {
override var body : ByteArray = byteArrayOf()
@ -16,11 +17,11 @@ class fcTL : Chunk {
var delay : Float = -1f
// x and y offsets
var x_offset : Int = 0
var y_offset : Int = 0
var xOffset : Int = 0
var yOffset : Int = 0
var blend_op : Utils.Companion.blend_op = Utils.Companion.blend_op.APNG_BLEND_OP_SOURCE
var dispose_op : Utils.Companion.dispose_op = Utils.Companion.dispose_op.APNG_DISPOSE_OP_NONE
var blendOp : Utils.Companion.BlendOp = Utils.Companion.BlendOp.APNG_BLEND_OP_SOURCE
var disposeOp : Utils.Companion.DisposeOp = Utils.Companion.DisposeOp.APNG_DISPOSE_OP_NONE
override fun parse(byteArray: ByteArray) {
val i = 4
@ -37,21 +38,21 @@ class fcTL : Chunk {
* 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 delay_num = parseLength(byteArray.copyOfRange(i + 24, i + 26)).toFloat()
val delayNum = parseLength(byteArray.copyOfRange(i + 24, i + 26)).toFloat()
// Get delay denominator
var delay_den = parseLength(byteArray.copyOfRange(i + 26, i + 28)).toFloat()
var delayDen = parseLength(byteArray.copyOfRange(i + 26, i + 28)).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 (delay_den == 0f) {
delay_den = 100f
if (delayDen == 0f) {
delayDen = 100f
}
delay = (delay_num / delay_den * 1000)
delay = (delayNum / delayDen * 1000)
// Get x and y offsets
x_offset = parseLength(byteArray.copyOfRange(i + 16, i + 20))
y_offset = parseLength(byteArray.copyOfRange(i + 20, i + 24))
xOffset = parseLength(byteArray.copyOfRange(i + 16, i + 20))
yOffset = parseLength(byteArray.copyOfRange(i + 20, i + 24))
body = byteArray.copyOfRange(i + 4, i + bodySize + 4)
blend_op = getBlend_op(String.format("%02x", byteArray[33]).toLong(16).toInt())
dispose_op = getDispose_op(String.format("%02x", byteArray[32]).toLong(16).toInt())
blendOp = getBlendOp(String.format("%02x", byteArray[33]).toLong(16).toInt())
disposeOp = getDisposeOp(String.format("%02x", byteArray[32]).toLong(16).toInt())
}
}
}

View File

@ -1,10 +1,10 @@
package oupson.apng.ImageUtils
package oupson.apng.imageUtils
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.support.annotation.ColorInt
import androidx.annotation.ColorInt
import oupson.apng.utils.Utils
import java.util.*
@ -12,7 +12,7 @@ class BitmapDiffCalculator(firstBitmap: Bitmap, secondBitmap : Bitmap) {
val res : Bitmap
var xOffset : Int = 0
var yOffset : Int = 0
var blend_op = Utils.Companion.blend_op.APNG_BLEND_OP_OVER
var blendOp = Utils.Companion.BlendOp.APNG_BLEND_OP_OVER
init {
val difBitmap = Bitmap.createBitmap(firstBitmap.width, firstBitmap.height, Bitmap.Config.ARGB_8888)
val difCanvas = Canvas(difBitmap)

View File

@ -1,4 +1,4 @@
package oupson.apng.ImageUtils
package oupson.apng.imageUtils
import android.graphics.Bitmap
import java.io.ByteArrayOutputStream
@ -182,6 +182,7 @@ class PngEncoder {
* @param offset The starting point to write to.
* @return The next place to be written to in the pngBytes array.
*/
@Suppress("unused")
private fun writeInt2(n: Int, offset: Int): Int {
val temp = byteArrayOf((n shr 8 and 0xff).toByte(), (n and 0xff).toByte())
return writeBytes(temp, offset)

View File

@ -1,4 +1,4 @@
package oupson.apng.ImageUtils;
package oupson.apng.imageUtils;
/* Fast pairwise nearest neighbor based algorithm for multilevel thresholding
Copyright (C) 2004-2016 Mark Tyler and Dmitry Groshev

View File

@ -19,7 +19,7 @@ class Utils {
if (!isPng(byteArray)) return false
try {
val acTL = byteArrayOf(0x61, 0x63, 0x54, 0x4c)
val IDAT = byteArrayOf(0x49, 0x44, 0x41, 0x54)
@Suppress("LocalVariableName") val IDAT = byteArrayOf(0x49, 0x44, 0x41, 0x54)
for (i in 0 until byteArray.size) {
val it = byteArray.copyOfRange(i, i + 4)
// if byteArray contain acTL
@ -40,66 +40,66 @@ class Utils {
*/
val pngSignature: ByteArray = byteArrayOf(0x89.toByte(), 0x50.toByte(), 0x4E.toByte(), 0x47.toByte(), 0x0D.toByte(), 0x0A.toByte(), 0x1A.toByte(), 0x0A.toByte())
enum class dispose_op {
enum class DisposeOp {
APNG_DISPOSE_OP_NONE,
APNG_DISPOSE_OP_BACKGROUND,
APNG_DISPOSE_OP_PREVIOUS
}
/**
* Get the int equivalent to the dispose_op
* @param dispose_op The dispose_op
* @return An int equivalent to the dispose_op
* Get the int equivalent to the DisposeOp
* @param disposeOp The DisposeOp
* @return An int equivalent to the DisposeOp
*/
fun getDispose_op(dispose_op: dispose_op) : Int {
return when(dispose_op) {
Companion.dispose_op.APNG_DISPOSE_OP_NONE -> 0
Companion.dispose_op.APNG_DISPOSE_OP_BACKGROUND -> 1
Companion.dispose_op.APNG_DISPOSE_OP_PREVIOUS -> 2
fun getDisposeOp(disposeOp: DisposeOp) : Int {
return when(disposeOp) {
Companion.DisposeOp.APNG_DISPOSE_OP_NONE -> 0
Companion.DisposeOp.APNG_DISPOSE_OP_BACKGROUND -> 1
Companion.DisposeOp.APNG_DISPOSE_OP_PREVIOUS -> 2
}
}
/**
* Get the dispose_op enum equivalent to the int
* @param int Int of the dispose_op
* @return A dispose_op
* Get the DisposeOp enum equivalent to the int
* @param int Int of the DisposeOp
* @return A DisposeOp
*/
fun getDispose_op(int: Int) : dispose_op {
fun getDisposeOp(int: Int) : DisposeOp {
return when(int) {
0 -> dispose_op.APNG_DISPOSE_OP_NONE
1 -> dispose_op.APNG_DISPOSE_OP_BACKGROUND
2 -> dispose_op.APNG_DISPOSE_OP_PREVIOUS
else -> dispose_op.APNG_DISPOSE_OP_NONE
0 -> DisposeOp.APNG_DISPOSE_OP_NONE
1 -> DisposeOp.APNG_DISPOSE_OP_BACKGROUND
2 -> DisposeOp.APNG_DISPOSE_OP_PREVIOUS
else -> DisposeOp.APNG_DISPOSE_OP_NONE
}
}
enum class blend_op() {
enum class BlendOp {
APNG_BLEND_OP_SOURCE,
APNG_BLEND_OP_OVER
}
/**
* Get the int equivalent to the blend_op
* @param blend_op The blend_op
* @return An int equivalent to the blend_op
* Get the int equivalent to the BlendOp
* @param blendOp The BlendOp
* @return An int equivalent to the BlendOp
*/
fun getBlend_op(blend_op: blend_op) : Int {
return when(blend_op) {
Companion.blend_op.APNG_BLEND_OP_SOURCE -> 0
Companion.blend_op.APNG_BLEND_OP_OVER -> 1
fun getBlendOp(blendOp: BlendOp) : Int {
return when(blendOp) {
Companion.BlendOp.APNG_BLEND_OP_SOURCE -> 0
Companion.BlendOp.APNG_BLEND_OP_OVER -> 1
}
}
/**
* Get the blend_op enum equivalent to the int
* @param int Int of the blend_op
* @return A blend_op
* Get the BlendOp enum equivalent to the int
* @param int Int of the BlendOp
* @return A BlendOp
*/
fun getBlend_op(int : Int) : blend_op {
fun getBlendOp(int : Int) : BlendOp {
return when(int) {
0 -> blend_op.APNG_BLEND_OP_SOURCE
1 -> blend_op.APNG_BLEND_OP_OVER
else -> blend_op.APNG_BLEND_OP_SOURCE
0 -> BlendOp.APNG_BLEND_OP_SOURCE
1 -> BlendOp.APNG_BLEND_OP_OVER
else -> BlendOp.APNG_BLEND_OP_SOURCE
}
}
@ -137,12 +137,12 @@ class Utils {
return lengthString.toLong(16).toInt()
}
val fcTL = Arrays.toString(byteArrayOf(0x66, 0x63, 0x54, 0x4c))
val IEND = Arrays.toString(byteArrayOf(0x49, 0x45, 0x4e, 0x44))
val IDAT = Arrays.toString(byteArrayOf(0x49, 0x44, 0x41, 0x54))
val fdAT = Arrays.toString(byteArrayOf(0x66, 0x64, 0x41, 0x54))
val plte = Arrays.toString(byteArrayOf(0x50, 0x4c, 0x54, 0x45))
val tnrs = Arrays.toString(byteArrayOf(0x74, 0x52, 0x4e, 0x53))
val IHDR = Arrays.toString(byteArrayOf(0x49, 0x48, 0x44, 0x52))
val fcTL : String = Arrays.toString(byteArrayOf(0x66, 0x63, 0x54, 0x4c))
val IEND : String = Arrays.toString(byteArrayOf(0x49, 0x45, 0x4e, 0x44))
val IDAT : String = Arrays.toString(byteArrayOf(0x49, 0x44, 0x41, 0x54))
val fdAT : String = Arrays.toString(byteArrayOf(0x66, 0x64, 0x41, 0x54))
val plte : String = Arrays.toString(byteArrayOf(0x50, 0x4c, 0x54, 0x45))
val tnrs : String = Arrays.toString(byteArrayOf(0x74, 0x52, 0x4e, 0x53))
val IHDR : String = Arrays.toString(byteArrayOf(0x49, 0x48, 0x44, 0x52))
}
}

View File

@ -12,7 +12,7 @@ android {
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
// Configure only for each module that uses Java 8
// language features (either in its source code or
@ -35,17 +35,17 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
//noinspection GradleCompatible
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
implementation "org.jetbrains.anko:anko:$anko_version"
implementation 'com.squareup.picasso:picasso:2.71828'
implementation project(":apng_library")
// implementation fileTree(include: ['*.aar'], dir: 'libs')
//implementation 'com.github.oupson:Kapng-Android:1.0.0'
implementation 'com.android.support:design:27.1.1' // where X.X.X version
implementation 'com.google.android.material:material:1.0.0' // where X.X.X version
implementation "org.jetbrains.anko:anko-appcompat-v7:$anko_version"
implementation "org.jetbrains.anko:anko-design:$anko_version"
implementation "org.jetbrains.anko:anko-constraint-layout:$anko_version"

View File

@ -1,7 +1,7 @@
package oupson.apngcreator
import android.support.test.InstrumentationRegistry
import android.support.test.runner.AndroidJUnit4
import androidx.test.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith

View File

@ -8,11 +8,11 @@ import android.graphics.BitmapFactory
import android.graphics.Color
import android.os.Bundle
import android.os.Environment
import android.support.design.widget.FloatingActionButton
import android.support.v7.app.AppCompatActivity
import android.text.Html
import android.view.View
import android.widget.ListView
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.floatingactionbutton.FloatingActionButton
import org.jetbrains.anko.*
import org.jetbrains.anko.design.appBarLayout
import org.jetbrains.anko.design.floatingActionButton

View File

@ -4,11 +4,11 @@ import android.Manifest
import android.content.pm.PackageManager
import android.graphics.Color
import android.os.Bundle
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
import android.support.v7.app.AppCompatActivity
import android.view.View
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import org.jetbrains.anko.backgroundColor
import org.jetbrains.anko.imageView
import org.jetbrains.anko.matchParent

View File

@ -3,12 +3,12 @@ package oupson.apngcreator
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.support.constraint.ConstraintLayout
import android.support.v7.app.AppCompatActivity
import android.text.Html
import android.util.Log
import android.view.View
import android.widget.Toolbar
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import com.squareup.picasso.Picasso
import org.jetbrains.anko.*
import org.jetbrains.anko.constraint.layout.ConstraintSetBuilder

View File

@ -6,6 +6,8 @@
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit