parent
5235a6b3a4
commit
d2d4978180
Binary file not shown.
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,98 +36,28 @@ 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) {
|
||||
@Suppress("unused")
|
||||
fun addFrames(frame : Frame, index: Int? = null) {
|
||||
if (index == null)
|
||||
frames.add(frame)
|
||||
}
|
||||
|
||||
fun addFrames(index: Int,frame : 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.
|
||||
*/
|
||||
@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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
|
@ -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)
|
|
@ -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
|
|
@ -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))
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue