Fixing a bug on ApngEncoder.kt

Working on CreatorActivity.kt
This commit is contained in:
Oupson 2020-12-06 23:49:07 +01:00
parent 4e807e8b06
commit 6eff6f0f45
2 changed files with 88 additions and 143 deletions

View File

@ -374,7 +374,7 @@ class ApngEncoder(
* @return [Boolean] true if no errors; false if error grabbing pixels
*/
private fun writeImageData(image: Bitmap): Boolean {
var rowsLeft = height // number of rows remaining to write
var rowsLeft = image.height // number of rows remaining to write
var startRow = 0 // starting row to process this time through
var nRows: Int // how many rows to grab at a time
@ -395,31 +395,31 @@ class ApngEncoder(
val compBytes = DeflaterOutputStream(outBytes, scrunch)
try {
while (rowsLeft > 0) {
nRows = min(32767 / (width * (bytesPerPixel + 1)), rowsLeft)
nRows = min(32767 / ( image.width * (bytesPerPixel + 1)), rowsLeft)
nRows = max(nRows, 1)
val pixels = IntArray(width * nRows)
val pixels = IntArray( image.width * nRows)
//pg = new PixelGrabber(image, 0, startRow, width, nRows, pixels, 0, width);
image.getPixels(pixels, 0, width, 0, startRow, width, nRows)
image.getPixels(pixels, 0, image.width, 0, startRow, image.width, nRows)
/*
* Create a data chunk. scanLines adds "nRows" for
* the filter bytes.
*/
scanLines = ByteArray(width * nRows * bytesPerPixel + nRows)
scanLines = ByteArray( image.width * nRows * bytesPerPixel + nRows)
if (filter == FILTER_SUB) {
leftBytes = ByteArray(16)
}
if (filter == FILTER_UP) {
priorRow = ByteArray(width * bytesPerPixel)
priorRow = ByteArray( image.width * bytesPerPixel)
}
scanPos = 0
startPos = 1
for (i in 0 until width * nRows) {
if (i % width == 0) {
for (i in 0 until image.width * nRows) {
if (i % image.width == 0) {
scanLines[scanPos++] = filter.toByte()
startPos = scanPos
}
@ -429,12 +429,12 @@ class ApngEncoder(
if (encodeAlpha) {
scanLines[scanPos++] = (pixels[i] shr 24 and 0xff).toByte()
}
if (i % width == width - 1 && filter != FILTER_NONE) {
if (i % image.width == image.width - 1 && filter != FILTER_NONE) {
if (filter == FILTER_SUB) {
filterSub(scanLines, startPos, width)
filterSub(scanLines, startPos, image.width)
}
if (filter == FILTER_UP) {
filterUp(scanLines, startPos, width)
filterUp(scanLines, startPos, image.width)
}
}
}

View File

@ -28,6 +28,7 @@ import oupson.apngcreator.adapter.ImageAdapter
import oupson.apngcreator.dialogs.DelayInputDialog
import java.io.File
import java.io.FileOutputStream
import java.io.OutputStream
class CreatorActivity : AppCompatActivity() {
@ -101,74 +102,7 @@ class CreatorActivity : AppCompatActivity() {
}
}
val out = FileOutputStream(f)
var maxWidth = 0
var maxHeight = 0
items.forEach {
val str = contentResolver.openInputStream(it.first)
if (str == null) {
Log.e(TAG, "Input Stream is null : ${it.first}")
return@forEach
}
val btm = BitmapFactory.decodeStream(str)
if (btm != null) {
if (btm.width > maxWidth)
maxWidth = btm.width
if (btm.height > maxHeight)
maxHeight = btm.height
} else {
Log.e(TAG, "Btm is null")
}
str.close()
}
if (BuildConfig.DEBUG)
Log.i(TAG, "MaxWidth : $maxWidth; MaxHeight : $maxHeight")
val encoder = ApngEncoder(
out,
maxWidth,
maxHeight,
items.size
).compressionLevel(9)
.firstFrameInAnim(firstFrameInAnim)
items.forEachIndexed { i, uri ->
if (BuildConfig.DEBUG)
Log.v(TAG, "Encoding frame $i")
// println("delay : ${adapter?.delay?.get(i)?.toFloat() ?: 1000f}ms")
try {
val str = contentResolver.openInputStream(uri.first)
?: return@forEachIndexed
if (i == 0) {
val btm =
BitmapFactory.decodeStream(str) ?: return@forEachIndexed
str.close()
encoder.writeFrame(
if (btm.width != maxWidth && btm.height != maxHeight)
Bitmap.createScaledBitmap(
btm,
maxWidth,
maxHeight,
false
)
else
btm,
delay = uri.second.toFloat(),
disposeOp = Utils.Companion.DisposeOp.APNG_DISPOSE_OP_NONE
)
//input.close()
} else {
encoder.writeFrame(
str,
delay = uri.second.toFloat(),
)
}
str.close()
} catch (e: Exception) {
Log.e(TAG, "Error when creating apng", e)
}
}
encoder.writeEnd()
saveToOutputStream(out)
out.close()
if (BuildConfig.DEBUG)
@ -198,36 +132,7 @@ class CreatorActivity : AppCompatActivity() {
}
}
val out = FileOutputStream(f)
var maxWidth = 0
var maxHeight = 0
items.forEach {
val str = contentResolver.openInputStream(it.first)
val btm = BitmapFactory.decodeStream(str)
if (btm.width > maxWidth)
maxWidth = btm.width
if (btm.height > maxHeight)
maxHeight = btm.height
str?.close()
}
val encoder = ApngEncoder(
out,
maxWidth,
maxHeight,
items.size
).compressionLevel(9)
.firstFrameInAnim(firstFrameInAnim)
items.forEach { uri ->
println("delay : ${uri.second.toFloat()}ms")
val str = contentResolver.openInputStream(uri.first) ?: return@forEach
encoder.writeFrame(
str,
delay = uri.second.toFloat()
)
}
encoder.writeEnd()
saveToOutputStream(out)
out.close()
withContext(Dispatchers.Main) {
@ -300,6 +205,78 @@ class CreatorActivity : AppCompatActivity() {
}
}
private fun saveToOutputStream(outputStream: OutputStream) {
var maxWidth = 0
var maxHeight = 0
items.forEach {
val str = contentResolver.openInputStream(it.first)
if (str == null) {
Log.e(TAG, "Input Stream is null : ${it.first}")
return@forEach
}
val btm = BitmapFactory.decodeStream(str)
if (btm != null) {
if (btm.width > maxWidth)
maxWidth = btm.width
if (btm.height > maxHeight)
maxHeight = btm.height
} else {
Log.e(TAG, "Btm is null")
}
str.close()
}
if (BuildConfig.DEBUG)
Log.i(TAG, "MaxWidth : $maxWidth; MaxHeight : $maxHeight")
val encoder = ApngEncoder(
outputStream,
maxWidth,
maxHeight,
items.size
).compressionLevel(9)
.firstFrameInAnim(firstFrameInAnim)
items.forEachIndexed { i, uri ->
if (BuildConfig.DEBUG)
Log.v(TAG, "Encoding frame $i")
try {
val str = contentResolver.openInputStream(uri.first)
?: return@forEachIndexed
if (i == 0) {
val btm =
BitmapFactory.decodeStream(str) ?: return@forEachIndexed
str.close()
encoder.writeFrame(
if (btm.width != maxWidth && btm.height != maxHeight)
Bitmap.createScaledBitmap(
btm,
maxWidth,
maxHeight,
false
)
else
btm,
delay = uri.second.toFloat(),
disposeOp = Utils.Companion.DisposeOp.APNG_DISPOSE_OP_NONE
)
} else {
encoder.writeFrame(
str,
delay = uri.second.toFloat(),
)
}
str.close()
} catch (e: Exception) {
Log.e(TAG, "Error when creating apng", e)
}
}
encoder.writeEnd()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
@ -321,42 +298,10 @@ class CreatorActivity : AppCompatActivity() {
if (data?.data != null) {
if (BuildConfig.DEBUG)
Log.i(TAG, "Intent data : ${data.data}")
GlobalScope.launch(Dispatchers.IO) {
val out = contentResolver.openOutputStream(data.data!!) ?: return@launch
var maxWidth = 0
var maxHeight = 0
items.forEach {
val str = contentResolver.openInputStream(it.first)
val btm = BitmapFactory.decodeStream(str)
if (btm.width > maxWidth)
maxWidth = btm.width
if (btm.height > maxHeight)
maxHeight = btm.height
str?.close()
}
if (BuildConfig.DEBUG)
Log.i(TAG, "MaxWidth : $maxWidth; MaxHeight : $maxHeight")
val encoder = ApngEncoder(
out,
maxWidth,
maxHeight,
items.size
).compressionLevel(9)
.firstFrameInAnim(firstFrameInAnim)
items.forEach { uri ->
// println("delay : ${adapter?.delay?.get(i)?.toFloat() ?: 1000f}ms")
val str =
contentResolver.openInputStream(uri.first) ?: return@forEach
encoder.writeFrame(
str,
delay = uri.second.toFloat()
)
}
encoder.writeEnd()
saveToOutputStream(out)
out.close()
withContext(Dispatchers.Main) {