adding support for .apng files

This commit is contained in:
tibbi 2021-08-17 16:43:20 +02:00
parent 10663cd1da
commit 47f73e9f37
3 changed files with 36 additions and 14 deletions

View file

@ -78,7 +78,7 @@ android {
} }
dependencies { dependencies {
implementation 'com.github.SimpleMobileTools:Simple-Commons:e3c531cbd1' implementation 'com.github.SimpleMobileTools:Simple-Commons:94ece2461b'
implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0' implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0'
implementation 'it.sephiroth.android.exif:library:1.0.1' implementation 'it.sephiroth.android.exif:library:1.0.1'
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.22' implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.22'
@ -93,7 +93,8 @@ dependencies {
implementation 'com.github.tibbi:gestureviews:a8e8fa8d27' implementation 'com.github.tibbi:gestureviews:a8e8fa8d27'
implementation 'com.github.tibbi:subsampling-scale-image-view:60fb7362d5' implementation 'com.github.tibbi:subsampling-scale-image-view:60fb7362d5'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'com.github.penfeizhou.android.animation:awebp:2.9.0' implementation 'com.github.penfeizhou.android.animation:awebp:2.11.0'
implementation 'com.github.penfeizhou.android.animation:apng:2.11.0'
implementation('com.squareup.picasso:picasso:2.71828') { implementation('com.squareup.picasso:picasso:2.71828') {
exclude group: 'com.squareup.okhttp3', module: 'okhttp' exclude group: 'com.squareup.okhttp3', module: 'okhttp'
} }

View file

@ -36,6 +36,7 @@ import com.davemorrissey.labs.subscaleview.DecoderFactory
import com.davemorrissey.labs.subscaleview.ImageDecoder import com.davemorrissey.labs.subscaleview.ImageDecoder
import com.davemorrissey.labs.subscaleview.ImageRegionDecoder import com.davemorrissey.labs.subscaleview.ImageRegionDecoder
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import com.github.penfeizhou.animation.apng.APNGDrawable
import com.github.penfeizhou.animation.webp.WebPDrawable import com.github.penfeizhou.animation.webp.WebPDrawable
import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
@ -289,7 +290,7 @@ class PhotoFragment : ViewPagerFragment() {
super.setMenuVisibility(menuVisible) super.setMenuVisibility(menuVisible)
mIsFragmentVisible = menuVisible mIsFragmentVisible = menuVisible
if (mWasInit) { if (mWasInit) {
if (!mMedium.isGIF() && !mMedium.isWebP()) { if (!mMedium.isGIF() && !mMedium.isWebP() && !mMedium.isApng()) {
photoFragmentVisibilityChanged(menuVisible) photoFragmentVisibilityChanged(menuVisible)
} }
} }
@ -357,6 +358,7 @@ class PhotoFragment : ViewPagerFragment() {
when { when {
mMedium.isGIF() -> loadGif() mMedium.isGIF() -> loadGif()
mMedium.isSVG() -> loadSVG() mMedium.isSVG() -> loadSVG()
mMedium.isApng() -> loadAPNG()
else -> loadBitmap() else -> loadBitmap()
} }
} }
@ -396,6 +398,13 @@ class PhotoFragment : ViewPagerFragment() {
} }
} }
private fun loadAPNG() {
if (context != null) {
val drawable = APNGDrawable.fromFile(mMedium.path)
mView.gestures_view.setImageDrawable(drawable)
}
}
private fun loadBitmap(addZoomableView: Boolean = true) { private fun loadBitmap(addZoomableView: Boolean = true) {
if (context == null) { if (context == null) {
return return
@ -440,8 +449,15 @@ class PhotoFragment : ViewPagerFragment() {
return false return false
} }
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { override fun onResourceReady(
mView.gestures_view.controller.settings.isZoomEnabled = mMedium.isRaw() || mCurrentRotationDegrees != 0 || context?.config?.allowZoomingImages == false resource: Drawable?,
model: Any?,
target: Target<Drawable>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
val allowZoomingImages = context?.config?.allowZoomingImages ?: true
mView.gestures_view.controller.settings.isZoomEnabled = mMedium.isRaw() || mCurrentRotationDegrees != 0 || allowZoomingImages == false
if (mIsFragmentVisible && addZoomableView) { if (mIsFragmentVisible && addZoomableView) {
scheduleZoomableView() scheduleZoomableView()
} }
@ -469,7 +485,8 @@ class PhotoFragment : ViewPagerFragment() {
picasso.into(mView.gestures_view, object : Callback { picasso.into(mView.gestures_view, object : Callback {
override fun onSuccess() { override fun onSuccess() {
mView.gestures_view.controller.settings.isZoomEnabled = mMedium.isRaw() || mCurrentRotationDegrees != 0 || context?.config?.allowZoomingImages == false mView.gestures_view.controller.settings.isZoomEnabled =
mMedium.isRaw() || mCurrentRotationDegrees != 0 || context?.config?.allowZoomingImages == false
if (mIsFragmentVisible && addZoomableView) { if (mIsFragmentVisible && addZoomableView) {
scheduleZoomableView() scheduleZoomableView()
} }
@ -491,7 +508,7 @@ class PhotoFragment : ViewPagerFragment() {
val files = File(mMedium.parentPath).listFiles()?.toMutableList() as? ArrayList<File> val files = File(mMedium.parentPath).listFiles()?.toMutableList() as? ArrayList<File>
if (files != null) { if (files != null) {
val screenWidth = context!!.realScreenSize.x val screenWidth = context!!.realScreenSize.x
val itemWidth = context!!.resources.getDimension(R.dimen.portrait_photos_stripe_height).toInt() + context!!.resources.getDimension(R.dimen.one_dp).toInt() val itemWidth = resources.getDimension(R.dimen.portrait_photos_stripe_height).toInt() + resources.getDimension(R.dimen.one_dp).toInt()
val sideWidth = screenWidth / 2 - itemWidth / 2 val sideWidth = screenWidth / 2 - itemWidth / 2
val fakeItemsCnt = ceil(sideWidth / itemWidth.toDouble()).toInt() val fakeItemsCnt = ceil(sideWidth / itemWidth.toDouble()).toInt()
@ -552,9 +569,9 @@ class PhotoFragment : ViewPagerFragment() {
} }
private fun setupStripeBottomMargin() { private fun setupStripeBottomMargin() {
var bottomMargin = context!!.navigationBarHeight + context!!.resources.getDimension(R.dimen.normal_margin).toInt() var bottomMargin = context!!.navigationBarHeight + resources.getDimension(R.dimen.normal_margin).toInt()
if (context!!.config.bottomActions) { if (context!!.config.bottomActions) {
bottomMargin += context!!.resources.getDimension(R.dimen.bottom_actions_height).toInt() bottomMargin += resources.getDimension(R.dimen.bottom_actions_height).toInt()
} }
(mView.photo_portrait_stripe_wrapper.layoutParams as RelativeLayout.LayoutParams).bottomMargin = bottomMargin (mView.photo_portrait_stripe_wrapper.layoutParams as RelativeLayout.LayoutParams).bottomMargin = bottomMargin
} }
@ -692,7 +709,12 @@ class PhotoFragment : ViewPagerFragment() {
private fun checkIfPanorama() { private fun checkIfPanorama() {
mIsPanorama = try { mIsPanorama = try {
val inputStream = if (mMedium.path.startsWith("content:/")) context!!.contentResolver.openInputStream(Uri.parse(mMedium.path)) else File(mMedium.path).inputStream() val inputStream = if (mMedium.path.startsWith("content:/")) {
context!!.contentResolver.openInputStream(Uri.parse(mMedium.path))
} else {
File(mMedium.path).inputStream()
}
val imageParser = JpegImageParser().getXmpXml(ByteSourceInputStream(inputStream, mMedium.name), HashMap<String, Any>()) val imageParser = JpegImageParser().getXmpXml(ByteSourceInputStream(inputStream, mMedium.name), HashMap<String, Any>())
imageParser.contains("GPano:UsePanoramaViewer=\"True\"", true) || imageParser.contains("GPano:UsePanoramaViewer=\"True\"", true) ||
imageParser.contains("<GPano:UsePanoramaViewer>True</GPano:UsePanoramaViewer>", true) || imageParser.contains("<GPano:UsePanoramaViewer>True</GPano:UsePanoramaViewer>", true) ||

View file

@ -3,10 +3,7 @@ package com.simplemobiletools.gallery.pro.models
import android.content.Context import android.content.Context
import androidx.room.* import androidx.room.*
import com.bumptech.glide.signature.ObjectKey import com.bumptech.glide.signature.ObjectKey
import com.simplemobiletools.commons.extensions.formatDate import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.extensions.formatSize
import com.simplemobiletools.commons.extensions.getFilenameExtension
import com.simplemobiletools.commons.extensions.isWebP
import com.simplemobiletools.commons.helpers.SORT_BY_DATE_MODIFIED import com.simplemobiletools.commons.helpers.SORT_BY_DATE_MODIFIED
import com.simplemobiletools.commons.helpers.SORT_BY_NAME import com.simplemobiletools.commons.helpers.SORT_BY_NAME
import com.simplemobiletools.commons.helpers.SORT_BY_PATH import com.simplemobiletools.commons.helpers.SORT_BY_PATH
@ -53,6 +50,8 @@ data class Medium(
fun isPortrait() = type == TYPE_PORTRAITS fun isPortrait() = type == TYPE_PORTRAITS
fun isApng() = name.isApng()
fun isHidden() = name.startsWith('.') fun isHidden() = name.startsWith('.')
fun getBubbleText(sorting: Int, context: Context, dateFormat: String, timeFormat: String) = when { fun getBubbleText(sorting: Int, context: Context, dateFormat: String, timeFormat: String) = when {