diff --git a/apng_library/src/main/java/oupson/apng/ApngAnimator.kt b/apng_library/src/main/java/oupson/apng/ApngAnimator.kt index 9261ba0..e070fbb 100644 --- a/apng_library/src/main/java/oupson/apng/ApngAnimator.kt +++ b/apng_library/src/main/java/oupson/apng/ApngAnimator.kt @@ -48,14 +48,31 @@ class ApngAnimator(val context: Context) { fun load(file: File) { // Download PNG val extractedFrame = APNGDisassembler(file.readBytes()).pngList + draw(extractedFrame) + nextFrame() + } + private fun draw(extractedFrame : ArrayList) { // Set last frame lastFrame = extractedFrame[0] - - // Init image buffer - bitmapBuffer = BitmapFactory.decodeByteArray(lastFrame?.byteArray, 0, lastFrame?.byteArray!!.size) - generatedFrame.add(BitmapFactory.decodeByteArray(lastFrame?.byteArray, 0, lastFrame?.byteArray!!.size)) Frames = extractedFrame + // Init image buffer + bitmapBuffer = BitmapFactory.decodeByteArray(lastFrame?.byteArray!!, 0, lastFrame?.byteArray!!.size) + generatedFrame.add(BitmapFactory.decodeByteArray(lastFrame?.byteArray, 0, lastFrame?.byteArray!!.size)) + if (lastFrame!!.dispose_op == Utils.Companion.dispose_op.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. + else if (lastFrame!!.dispose_op == Utils.Companion.dispose_op.APNG_DISPOSE_OP_BACKGROUND) { + val res = Bitmap.createBitmap(Frames[0].maxWidth!!, Frames[0].maxHeight!!, Bitmap.Config.ARGB_8888) + val can = Canvas(res) + can.drawBitmap(BitmapFactory.decodeByteArray(lastFrame?.byteArray!!, 0, lastFrame?.byteArray!!.size), 0f, 0f, null) + can.drawRect(lastFrame!!.x_offsets!!.toFloat(), lastFrame!!.y_offsets!!.toFloat(), lastFrame!!.x_offsets!! + lastFrame!!.width.toFloat(), lastFrame!!.y_offsets!! + lastFrame!!.height.toFloat(), { val paint = Paint(); paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR); paint }()) + bitmapBuffer = res + } else { + bitmapBuffer = BitmapFactory.decodeByteArray(lastFrame?.byteArray!!, 0, lastFrame?.byteArray!!.size) + } for (i in 1 until Frames.size) { // Iterator val it = Frames.get(i) @@ -79,70 +96,28 @@ class ApngAnimator(val context: Context) { } // 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. - else if (it.dispose_op == Utils.Companion.dispose_op.APNG_DISPOSE_OP_BACKGROUND){ - val res = Bitmap.createBitmap(Frames[0].maxWidth!!, Frames[0].maxHeight!!, Bitmap.Config.ARGB_8888) + else if (it.dispose_op == Utils.Companion.dispose_op.APNG_DISPOSE_OP_BACKGROUND) { + val res = Bitmap.createBitmap(Frames[0].maxWidth!!, Frames[0].maxHeight!!, Bitmap.Config.ARGB_8888) val can = Canvas(res) can.drawBitmap(btm, 0f, 0f, null) can.drawRect(lastFrame!!.x_offsets!!.toFloat(), lastFrame!!.y_offsets!!.toFloat(), lastFrame!!.x_offsets!! + lastFrame!!.width.toFloat(), lastFrame!!.y_offsets!! + lastFrame!!.height.toFloat(), { val paint = Paint(); paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR); paint }()) bitmapBuffer = res - } - else { + } else { bitmapBuffer = btm } - } - nextFrame() - } + } + } /** * Load an APNG file * @param url URL to load * @throws NotApngException */ private fun loadUrl(url : URL) { - doAsync(exceptionHandler = {e -> throw e}) { + doAsync(exceptionHandler = {e -> e.printStackTrace()}) { // Download PNG - val extractedFrame = APNGDisassembler(Loader().load(context!!, url)).pngList - // Set last frame - lastFrame = extractedFrame[0] - - // Init image buffer - bitmapBuffer = BitmapFactory.decodeByteArray(lastFrame?.byteArray!!, 0, lastFrame?.byteArray!!.size) - generatedFrame.add(BitmapFactory.decodeByteArray(lastFrame?.byteArray, 0, lastFrame?.byteArray!!.size)) - Frames = extractedFrame - for (i in 1 until Frames.size) { - // Iterator - val it = Frames.get(i) - // Current bitmap for the frame - val btm = Bitmap.createBitmap(Frames[0].maxWidth!!, Frames[0].maxHeight!!, Bitmap.Config.ARGB_8888) - val canvas = Canvas(btm) - val current = BitmapFactory.decodeByteArray(it.byteArray, 0, it.byteArray.size).copy(Bitmap.Config.ARGB_8888, true) - // 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 }()) - } - // Draw the bitmap - canvas.drawBitmap(current, it.x_offsets!!.toFloat(), it.y_offsets!!.toFloat(), null) - generatedFrame.add(btm) - // Don't add current frame to bitmap buffer - if (Frames[i].dispose_op == Utils.Companion.dispose_op.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. - else if (it.dispose_op == Utils.Companion.dispose_op.APNG_DISPOSE_OP_BACKGROUND){ - val res = Bitmap.createBitmap(Frames[0].maxWidth!!, Frames[0].maxHeight!!, Bitmap.Config.ARGB_8888) - val can = Canvas(res) - can.drawBitmap(btm, 0f, 0f, null) - can.drawRect(lastFrame!!.x_offsets!!.toFloat(), lastFrame!!.y_offsets!!.toFloat(), lastFrame!!.x_offsets!! + lastFrame!!.width.toFloat(), lastFrame!!.y_offsets!! + lastFrame!!.height.toFloat(), { val paint = Paint(); paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR); paint }()) - bitmapBuffer = res - } - else { - bitmapBuffer = btm - } - } + val extractedFrame = APNGDisassembler(Loader().load(context, url)).pngList + draw(extractedFrame) uiThread { nextFrame() } @@ -152,56 +127,7 @@ class ApngAnimator(val context: Context) { fun load(byteArray: ByteArray) { // Download PNG val extractedFrame = APNGDisassembler(byteArray).pngList - - // Set last frame - lastFrame = extractedFrame[0] - - // Init image buffer - bitmapBuffer = BitmapFactory.decodeByteArray(lastFrame?.byteArray, 0, lastFrame?.byteArray!!.size) - generatedFrame.add(BitmapFactory.decodeByteArray(lastFrame?.byteArray, 0, lastFrame?.byteArray!!.size)) - Frames = extractedFrame - for (i in 1 until Frames.size) { - // Iterator - val it = Frames.get(i) - - // Current bitmap for the frame - val btm = Bitmap.createBitmap(Frames[0].maxWidth!!, Frames[0].maxHeight!!, Bitmap.Config.ARGB_8888) - val canvas = Canvas(btm) - - val current = BitmapFactory.decodeByteArray(it.byteArray, 0, it.byteArray.size).copy(Bitmap.Config.ARGB_8888, true) - - // 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 }()) - } - - // Draw the bitmap - canvas.drawBitmap(current, it.x_offsets!!.toFloat(), it.y_offsets!!.toFloat(), null) - generatedFrame.add(btm) - - // Don't add current frame to bitmap buffer - if (Frames[i].dispose_op == Utils.Companion.dispose_op.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. - else if (it.dispose_op == Utils.Companion.dispose_op.APNG_DISPOSE_OP_BACKGROUND){ - val res = Bitmap.createBitmap(Frames[0].maxWidth!!, Frames[0].maxHeight!!, Bitmap.Config.ARGB_8888) - val can = Canvas(res) - can.drawBitmap(btm, 0f, 0f, null) - can.drawRect(lastFrame!!.x_offsets!!.toFloat(), lastFrame!!.y_offsets!!.toFloat(), lastFrame!!.x_offsets!! + lastFrame!!.width.toFloat(), lastFrame!!.y_offsets!! + lastFrame!!.height.toFloat(), { val paint = Paint(); paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR); paint }()) - bitmapBuffer = res - } - else { - bitmapBuffer = btm - } - } + draw(extractedFrame) nextFrame() }