Adding support for first frame not in animation
Fixing a bug
This commit is contained in:
parent
39fdc31aaa
commit
dfc427a54f
|
@ -15,7 +15,6 @@ import java.util.zip.DeflaterOutputStream
|
|||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
// TODO ADD SUPPORT FOR FIRST FRAME NOT IN ANIM
|
||||
// TODO OPTIMISE APNG
|
||||
/**
|
||||
* A class to write APNG.
|
||||
|
@ -90,6 +89,9 @@ class ExperimentalApngEncoder(
|
|||
/** Number of loop of the animation, zero to infinite **/
|
||||
private var repetitionCount: Int = 0
|
||||
|
||||
/** If the first frame should be included in the animation **/
|
||||
private var firstFrameInAnim: Boolean = true
|
||||
|
||||
init {
|
||||
outputStream.write(Utils.pngSignature)
|
||||
writeHeader()
|
||||
|
@ -139,9 +141,9 @@ class ExperimentalApngEncoder(
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the compression level
|
||||
* @param compressionLevel A integer between 0 and 9 (not include)
|
||||
* @return [ExperimentalApngEncoder] for chaining
|
||||
* Set the compression level.
|
||||
* @param compressionLevel A integer between 0 and 9 (not include).
|
||||
* @return [ExperimentalApngEncoder] for chaining.
|
||||
*/
|
||||
fun compressionLevel(compressionLevel: Int): ExperimentalApngEncoder {
|
||||
if (compressionLevel in 0..9) {
|
||||
|
@ -156,6 +158,16 @@ class ExperimentalApngEncoder(
|
|||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the first frame should be included in the animation.
|
||||
* @param firstFrameInAnim A boolean.
|
||||
* @return [ExperimentalApngEncoder] for chaining.
|
||||
*/
|
||||
fun firstFrameInAnim(firstFrameInAnim: Boolean): ExperimentalApngEncoder {
|
||||
this.firstFrameInAnim = firstFrameInAnim
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a frame into the output stream.
|
||||
* @param inputStream An input stream that will be decoded in order to be written in the animation. Not freed.
|
||||
|
@ -221,9 +233,10 @@ class ExperimentalApngEncoder(
|
|||
else if (btm.height > height)
|
||||
throw InvalidFrameSizeException("Frame height must be inferior or equal at the animation height")
|
||||
|
||||
writeFCTL(btm, delay, disposeOp, blendOp, xOffsets, yOffsets)
|
||||
if (firstFrameInAnim || currentFrame != 0)
|
||||
writeFCTL(btm, delay, disposeOp, blendOp, xOffsets, yOffsets)
|
||||
writeImageData(btm)
|
||||
currentSeq++
|
||||
currentFrame++
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,6 +39,7 @@ class CreatorActivity : AppCompatActivity() {
|
|||
|
||||
private var items: ArrayList<Pair<Uri, Int>> = ArrayList()
|
||||
private var adapter: ImageAdapter? = null
|
||||
private var firstFrameInAnim = true
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -84,6 +85,7 @@ class CreatorActivity : AppCompatActivity() {
|
|||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
menuInflater.inflate(R.menu.creator_menu, menu)
|
||||
menu?.findItem(R.id.menu_first_frame_in_anim)?.isChecked = true
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -128,6 +130,7 @@ class CreatorActivity : AppCompatActivity() {
|
|||
maxHeight,
|
||||
items.size
|
||||
).compressionLevel(9)
|
||||
.firstFrameInAnim(firstFrameInAnim)
|
||||
items.forEachIndexed { i, uri ->
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.v(TAG, "Encoding frame $i")
|
||||
|
@ -213,6 +216,8 @@ class CreatorActivity : AppCompatActivity() {
|
|||
maxHeight,
|
||||
items.size
|
||||
).compressionLevel(9)
|
||||
.firstFrameInAnim(firstFrameInAnim)
|
||||
|
||||
items.forEach { uri ->
|
||||
println("delay : ${uri.second.toFloat()}ms")
|
||||
val str = contentResolver.openInputStream(uri.first) ?: return@forEach
|
||||
|
@ -236,6 +241,7 @@ class CreatorActivity : AppCompatActivity() {
|
|||
)
|
||||
)
|
||||
type = "image/png"
|
||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
}
|
||||
startActivity(
|
||||
Intent.createChooser(
|
||||
|
@ -285,6 +291,11 @@ class CreatorActivity : AppCompatActivity() {
|
|||
adapter?.notifyDataSetChanged()
|
||||
true
|
||||
}
|
||||
R.id.menu_first_frame_in_anim -> {
|
||||
item.isChecked = !item.isChecked
|
||||
firstFrameInAnim = item.isChecked
|
||||
true
|
||||
}
|
||||
else -> if (item != null) super.onOptionsItemSelected(item) else true
|
||||
}
|
||||
}
|
||||
|
@ -333,6 +344,8 @@ class CreatorActivity : AppCompatActivity() {
|
|||
maxHeight,
|
||||
items.size
|
||||
).compressionLevel(9)
|
||||
.firstFrameInAnim(firstFrameInAnim)
|
||||
|
||||
items.forEach { uri ->
|
||||
// println("delay : ${adapter?.delay?.get(i)?.toFloat() ?: 1000f}ms")
|
||||
val str =
|
||||
|
|
|
@ -1,38 +1,43 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_save_apng"
|
||||
android:icon="@drawable/ic_save_white_24dp"
|
||||
android:title="@string/save"
|
||||
app:showAsAction="ifRoom"
|
||||
app:iconTint="@color/control"/>
|
||||
app:iconTint="@color/control"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_create_apng"
|
||||
android:icon="@drawable/ic_play_arrow_white_24dp"
|
||||
android:title="@string/create"
|
||||
app:showAsAction="ifRoom"
|
||||
app:iconTint="@color/control"/>
|
||||
app:iconTint="@color/control"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_share_apng"
|
||||
android:icon="@drawable/ic_share_share_24dp"
|
||||
android:title="@string/share"
|
||||
app:showAsAction="ifRoom"
|
||||
app:iconTint="@color/control"/>
|
||||
app:iconTint="@color/control"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_set_all_duration"
|
||||
android:icon="@drawable/ic_access_time_white_24dp"
|
||||
android:title="@string/set_all_duration"
|
||||
app:showAsAction="ifRoom"
|
||||
app:iconTint="@color/control"/>
|
||||
app:iconTint="@color/control"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_clear"
|
||||
android:title="@string/clear"
|
||||
app:showAsAction="never"
|
||||
app:iconTint="@color/control" />
|
||||
android:id="@+id/menu_clear"
|
||||
android:title="@string/clear"
|
||||
app:iconTint="@color/control"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/menu_first_frame_in_anim"
|
||||
android:checkable="true"
|
||||
android:title="@string/menu_first_frame_in_anim"
|
||||
app:showAsAction="never|withText" />
|
||||
</menu>
|
|
@ -16,6 +16,7 @@
|
|||
<string name="set_all_duration">Set duration of all frames</string>
|
||||
<string name="done">Done</string>
|
||||
<string name="clear">Clear</string>
|
||||
<string name="menu_first_frame_in_anim">First frame in animation</string>
|
||||
|
||||
<string name="open">open</string>
|
||||
<string name="close">close</string>
|
||||
|
|
Loading…
Reference in New Issue