From 62b895eb07a938bf39b6bcab9c0893f586481819 Mon Sep 17 00:00:00 2001 From: Nicolas Pomepuy Date: Thu, 19 Mar 2020 07:36:20 +0100 Subject: [PATCH] Fix bitmap decoding for vector drawables --- .../videolan/television/ui/CardPresenter.kt | 5 ++-- .../java/org/videolan/tools/BitmapCache.kt | 11 -------- .../src/org/videolan/vlc/PlaybackService.kt | 4 +-- .../vlc/gui/browser/BaseBrowserAdapter.kt | 20 ++++++------- .../videolan/vlc/gui/helpers/BitmapUtil.kt | 28 +++++++++++++++++++ .../videolan/vlc/gui/helpers/ImageLoader.kt | 4 +-- .../vlc/gui/view/CoverMediaSwitcher.kt | 5 ++-- .../videolan/vlc/media/MediaSessionBrowser.kt | 6 ++-- 8 files changed, 48 insertions(+), 35 deletions(-) diff --git a/application/television/src/main/java/org/videolan/television/ui/CardPresenter.kt b/application/television/src/main/java/org/videolan/television/ui/CardPresenter.kt index 684dca8dc..fac1f9719 100644 --- a/application/television/src/main/java/org/videolan/television/ui/CardPresenter.kt +++ b/application/television/src/main/java/org/videolan/television/ui/CardPresenter.kt @@ -23,7 +23,6 @@ package org.videolan.television.ui import android.annotation.TargetApi import android.app.Activity import android.graphics.Bitmap -import android.graphics.BitmapFactory import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable import android.net.Uri @@ -106,9 +105,9 @@ class CardPresenter(private val context: Activity, private val isPoster: Boolean val res = cardView.resources picture = if (mediaLibraryItem.itemType == MediaLibraryItem.TYPE_MEDIA && (mediaLibraryItem as MediaWrapper).type == MediaWrapper.TYPE_DIR) { if (TextUtils.equals(mediaLibraryItem.uri.scheme, "file")) - BitmapFactory.decodeResource(res, R.drawable.ic_menu_folder_big) + context.getBitmapFromDrawable(R.drawable.ic_menu_folder_big) else - BitmapFactory.decodeResource(res, R.drawable.ic_menu_network_big) + context.getBitmapFromDrawable(R.drawable.ic_menu_network_big) } else AudioUtil.readCoverBitmap(Uri.decode(mediaLibraryItem.artworkMrl), res.getDimensionPixelSize(R.dimen.tv_grid_card_thumb_width)) if (picture == null) picture = getBitmapFromDrawable(context, getTvIconRes(mediaLibraryItem)) diff --git a/application/tools/src/main/java/org/videolan/tools/BitmapCache.kt b/application/tools/src/main/java/org/videolan/tools/BitmapCache.kt index 44d96ce4a..0b60919b4 100644 --- a/application/tools/src/main/java/org/videolan/tools/BitmapCache.kt +++ b/application/tools/src/main/java/org/videolan/tools/BitmapCache.kt @@ -44,9 +44,7 @@ package org.videolan.tools -import android.content.res.Resources import android.graphics.Bitmap -import android.graphics.BitmapFactory import android.util.Log import androidx.collection.LruCache import videolan.org.commontools.BuildConfig @@ -101,13 +99,4 @@ object BitmapCache { fun clear() { mMemCache.evictAll() } - - fun getFromResource(res: Resources, resId: Int): Bitmap? { - var bitmap = getBitmapFromMemCache(resId) - if (bitmap == null) { - bitmap = BitmapFactory.decodeResource(res, resId) - addBitmapToMemCache(resId, bitmap) - } - return bitmap - } } diff --git a/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt b/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt index f6026b635..dd3de1769 100644 --- a/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt +++ b/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt @@ -23,7 +23,6 @@ import android.annotation.TargetApi import android.app.* import android.appwidget.AppWidgetManager import android.content.* -import android.graphics.BitmapFactory import android.media.AudioManager import android.media.audiofx.AudioEffect import android.net.Uri @@ -70,6 +69,7 @@ import org.videolan.tools.* import org.videolan.vlc.gui.helpers.AudioUtil import org.videolan.vlc.gui.helpers.BitmapUtil import org.videolan.vlc.gui.helpers.NotificationHelper +import org.videolan.vlc.gui.helpers.getBitmapFromDrawable import org.videolan.vlc.gui.video.PopupManager import org.videolan.vlc.gui.video.VideoPlayerActivity import org.videolan.vlc.media.MediaSessionBrowser @@ -711,7 +711,7 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner { else AudioUtil.readCoverBitmap(Uri.decode(mw.artworkMrl), 256) if (cover == null || cover.isRecycled) - cover = BitmapFactory.decodeResource(ctx.resources, R.drawable.ic_no_media) + cover = ctx.getBitmapFromDrawable(R.drawable.ic_no_media) notification = NotificationHelper.createPlaybackNotification(ctx, canSwitchToVideo(), title, artist, album, diff --git a/application/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserAdapter.kt b/application/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserAdapter.kt index ec253274f..9828bb20a 100644 --- a/application/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserAdapter.kt +++ b/application/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserAdapter.kt @@ -23,7 +23,6 @@ package org.videolan.vlc.gui.browser import android.annotation.TargetApi -import android.graphics.BitmapFactory import android.graphics.drawable.BitmapDrawable import android.os.Build import android.os.Handler @@ -54,6 +53,7 @@ import org.videolan.vlc.gui.DiffUtilAdapter import org.videolan.vlc.gui.helpers.MarqueeViewHolder import org.videolan.vlc.gui.helpers.SelectorViewHolder import org.videolan.vlc.gui.helpers.enableMarqueeEffect +import org.videolan.vlc.gui.helpers.getBitmapFromDrawable import java.util.* @@ -89,15 +89,15 @@ open class BaseBrowserAdapter(protected val fragment: BaseBrowserFragment) : Dif specialIcons = filesRoot || fileBrowser && mrl != null && mrl.endsWith(AndroidDevices.EXTERNAL_PUBLIC_DIRECTORY) // Setup resources val res = fragment.requireContext().resources - folderDrawable = BitmapDrawable(res, BitmapFactory.decodeResource(res, R.drawable.ic_menu_folder)) - audioDrawable = BitmapDrawable(res, BitmapFactory.decodeResource(res, R.drawable.ic_browser_audio_normal)) - videoDrawable = BitmapDrawable(res, BitmapFactory.decodeResource(res, R.drawable.ic_browser_video_normal)) - subtitleDrawable = BitmapDrawable(res, BitmapFactory.decodeResource(res, R.drawable.ic_browser_subtitle_normal)) - unknownDrawable = BitmapDrawable(res, BitmapFactory.decodeResource(res, R.drawable.ic_browser_unknown_normal)) - qaMoviesDrawable = BitmapDrawable(res, BitmapFactory.decodeResource(res, R.drawable.ic_browser_movies_normal)) - qaMusicDrawable = BitmapDrawable(res, BitmapFactory.decodeResource(res, R.drawable.ic_browser_music_normal)) - qaPodcastsDrawable = BitmapDrawable(res, BitmapFactory.decodeResource(res, R.drawable.ic_browser_podcasts_normal)) - qaDownloadDrawable = BitmapDrawable(res, BitmapFactory.decodeResource(res, R.drawable.ic_browser_download_normal)) + folderDrawable = BitmapDrawable(res, fragment.requireActivity().getBitmapFromDrawable(R.drawable.ic_menu_folder)) + audioDrawable = BitmapDrawable(res, fragment.requireActivity().getBitmapFromDrawable(R.drawable.ic_browser_audio_normal)) + videoDrawable = BitmapDrawable(res, fragment.requireActivity().getBitmapFromDrawable(R.drawable.ic_browser_video_normal)) + subtitleDrawable = BitmapDrawable(res, fragment.requireActivity().getBitmapFromDrawable(R.drawable.ic_browser_subtitle_normal)) + unknownDrawable = BitmapDrawable(res, fragment.requireActivity().getBitmapFromDrawable(R.drawable.ic_browser_unknown_normal)) + qaMoviesDrawable = BitmapDrawable(res, fragment.requireActivity().getBitmapFromDrawable(R.drawable.ic_browser_movies_normal)) + qaMusicDrawable = BitmapDrawable(res, fragment.requireActivity().getBitmapFromDrawable(R.drawable.ic_browser_music_normal)) + qaPodcastsDrawable = BitmapDrawable(res, fragment.requireActivity().getBitmapFromDrawable(R.drawable.ic_browser_podcasts_normal)) + qaDownloadDrawable = BitmapDrawable(res, fragment.requireActivity().getBitmapFromDrawable(R.drawable.ic_browser_download_normal)) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { diff --git a/application/vlc-android/src/org/videolan/vlc/gui/helpers/BitmapUtil.kt b/application/vlc-android/src/org/videolan/vlc/gui/helpers/BitmapUtil.kt index 9e55c6cfb..c870f94bc 100644 --- a/application/vlc-android/src/org/videolan/vlc/gui/helpers/BitmapUtil.kt +++ b/application/vlc-android/src/org/videolan/vlc/gui/helpers/BitmapUtil.kt @@ -20,9 +20,19 @@ package org.videolan.vlc.gui.helpers +import android.content.Context import android.graphics.Bitmap import android.graphics.BitmapFactory +import android.graphics.Canvas +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.Drawable +import android.graphics.drawable.VectorDrawable import android.net.Uri +import android.os.Build +import androidx.annotation.DrawableRes +import androidx.core.content.ContextCompat +import androidx.core.graphics.drawable.DrawableCompat +import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat import org.videolan.medialibrary.interfaces.media.MediaWrapper import org.videolan.resources.AppContextProvider import org.videolan.tools.BitmapCache @@ -104,3 +114,21 @@ object BitmapUtil { } } + +fun Context.getBitmapFromDrawable(@DrawableRes drawableId: Int): Bitmap? { + var drawable: Drawable = ContextCompat.getDrawable(this, drawableId) ?: return null + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + drawable = DrawableCompat.wrap(drawable).mutate() + } + return when (drawable) { + is BitmapDrawable -> drawable.bitmap + is VectorDrawableCompat, is VectorDrawable -> { + val bitmap = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888) + val canvas = Canvas(bitmap) + drawable.setBounds(0, 0, canvas.width, canvas.height) + drawable.draw(canvas) + bitmap + } + else -> BitmapFactory.decodeResource(this.resources, drawableId) + } +} \ No newline at end of file diff --git a/application/vlc-android/src/org/videolan/vlc/gui/helpers/ImageLoader.kt b/application/vlc-android/src/org/videolan/vlc/gui/helpers/ImageLoader.kt index e48de8fcd..70e56795a 100644 --- a/application/vlc-android/src/org/videolan/vlc/gui/helpers/ImageLoader.kt +++ b/application/vlc-android/src/org/videolan/vlc/gui/helpers/ImageLoader.kt @@ -3,7 +3,6 @@ package org.videolan.vlc.gui.helpers import android.annotation.TargetApi import android.content.Context import android.graphics.Bitmap -import android.graphics.BitmapFactory import android.graphics.Canvas import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable @@ -31,7 +30,6 @@ import org.videolan.medialibrary.media.MediaLibraryItem import org.videolan.resources.AppContextProvider import org.videolan.resources.HEADER_MOVIES import org.videolan.resources.HEADER_TV_SHOW -import org.videolan.tools.AppScope import org.videolan.tools.BitmapCache import org.videolan.tools.HttpImageLoader import org.videolan.tools.Settings @@ -228,7 +226,7 @@ private suspend fun getImage(v: View, item: MediaLibraryItem, binding: ViewDataB } val image = if (!bindChanged) obtainBitmap(item, width) else null if (image == null && tv) { - val imageTV = BitmapFactory.decodeResource(v.resources, getTvIconRes(item)) + val imageTV = v.context.getBitmapFromDrawable(getTvIconRes(item)) // binding is set to null to be sure to set the src and not the cover (background) if (!bindChanged) updateImageView(bitmap = imageTV, target = v, vdb = null, updateScaleType = false, tv = tv, card = card) binding?.removeOnRebindCallback(rebindCallbacks!!) diff --git a/application/vlc-android/src/org/videolan/vlc/gui/view/CoverMediaSwitcher.kt b/application/vlc-android/src/org/videolan/vlc/gui/view/CoverMediaSwitcher.kt index c8d8326ad..a8ef5ba9c 100644 --- a/application/vlc-android/src/org/videolan/vlc/gui/view/CoverMediaSwitcher.kt +++ b/application/vlc-android/src/org/videolan/vlc/gui/view/CoverMediaSwitcher.kt @@ -22,14 +22,13 @@ package org.videolan.vlc.gui.view import android.content.Context import android.graphics.Bitmap -import android.graphics.BitmapFactory import android.util.AttributeSet import android.view.LayoutInflater import android.widget.ImageView import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ObsoleteCoroutinesApi - import org.videolan.vlc.R +import org.videolan.vlc.gui.helpers.getBitmapFromDrawable @ExperimentalCoroutinesApi @ObsoleteCoroutinesApi @@ -38,7 +37,7 @@ class CoverMediaSwitcher(context: Context, attrs: AttributeSet) : AudioMediaSwit override fun addMediaView(inflater: LayoutInflater, title: String?, artist: String?, cover: Bitmap?) { var cover = cover - if (cover == null) cover = BitmapFactory.decodeResource(resources, R.drawable.icon) + if (cover == null) cover = context.getBitmapFromDrawable(R.drawable.icon) val imageView = ImageView(context) imageView.scaleType = ImageView.ScaleType.FIT_CENTER diff --git a/application/vlc-android/src/org/videolan/vlc/media/MediaSessionBrowser.kt b/application/vlc-android/src/org/videolan/vlc/media/MediaSessionBrowser.kt index caaa5739e..4166ed6ca 100644 --- a/application/vlc-android/src/org/videolan/vlc/media/MediaSessionBrowser.kt +++ b/application/vlc-android/src/org/videolan/vlc/media/MediaSessionBrowser.kt @@ -30,7 +30,6 @@ import android.content.ServiceConnection import android.content.pm.PackageManager import android.content.res.Resources import android.graphics.Bitmap -import android.graphics.BitmapFactory import android.graphics.drawable.BitmapDrawable import android.net.Uri import android.os.IBinder @@ -50,6 +49,7 @@ import org.videolan.vlc.extensions.ExtensionsManager import org.videolan.vlc.extensions.api.VLCExtensionItem import org.videolan.vlc.gui.helpers.AudioUtil.readCoverBitmap import org.videolan.vlc.gui.helpers.UiTools.getDefaultAudioDrawable +import org.videolan.vlc.gui.helpers.getBitmapFromDrawable import org.videolan.vlc.media.MediaUtils.getMediaSubtitle import java.util.* import java.util.concurrent.Semaphore @@ -164,7 +164,7 @@ class MediaSessionBrowser : ExtensionManagerActivity { try { extensionRes = context.packageManager .getResourcesForApplication(extension.componentName().packageName) - b = BitmapFactory.decodeResource(extensionRes, iconRes) + b = context.getBitmapFromDrawable(iconRes) } catch (ignored: PackageManager.NameNotFoundException) { } } @@ -172,7 +172,7 @@ class MediaSessionBrowser : ExtensionManagerActivity { b = (context.packageManager.getApplicationIcon(extension.componentName().packageName) as BitmapDrawable).bitmap item.setIconBitmap(b) } catch (e: PackageManager.NameNotFoundException) { - b = BitmapFactory.decodeResource(res, R.drawable.icon) + b = context.getBitmapFromDrawable(R.drawable.icon) item.setIconBitmap(b) } results.add(MediaBrowserCompat.MediaItem(item.build(), MediaBrowserCompat.MediaItem.FLAG_BROWSABLE))