Skip to content

Commit 59a4c8d

Browse files
lukstbitdavid-allison
authored andcommitted
Refactor and improve BackgroundImage.getBackgroundImageDimensions()
The method was extracted from BackgroundImage to make it more general as an extension on Context. Also switch to using inJustDecodeBounds because we only need the dimensions so there's no need to load the entire bitmap for this.
1 parent 1a40074 commit 59a4c8d

File tree

3 files changed

+38
-18
lines changed

3 files changed

+38
-18
lines changed

AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ import com.ichi2.anki.ui.animations.fadeOut
169169
import com.ichi2.anki.ui.windows.permissions.PermissionsActivity
170170
import com.ichi2.anki.utils.Destination
171171
import com.ichi2.anki.utils.ext.dismissAllDialogFragments
172+
import com.ichi2.anki.utils.ext.getSizeOfBitmapFromCollection
172173
import com.ichi2.anki.utils.ext.setFragmentResultListener
173174
import com.ichi2.anki.utils.ext.showDialogFragment
174175
import com.ichi2.anki.widgets.DeckAdapter
@@ -1084,8 +1085,14 @@ open class DeckPicker :
10841085
// TODO: Temporary fix to stop a crash on startup [15450], it can be removed either:
10851086
// * by moving this check to an upgrade path
10861087
// * once enough time has passed
1087-
val size = BackgroundImage.getBackgroundImageDimensions(this)
1088-
if (size.width * size.height * BITMAP_BYTES_PER_PIXEL > BackgroundImage.MAX_BITMAP_SIZE) {
1088+
// null shouldn't happen as we check for the file being present above this call
1089+
val (bitmapWidth, bitmapHeight) = getSizeOfBitmapFromCollection(BackgroundImage.FILENAME) ?: return false
1090+
if (bitmapWidth <= 0 || bitmapHeight <= 0) {
1091+
Timber.w("Decoding background image for dimensions info failed")
1092+
deckPickerBinding.background.setBackgroundResource(0)
1093+
return false
1094+
}
1095+
if (bitmapWidth * bitmapHeight * BITMAP_BYTES_PER_PIXEL > BackgroundImage.MAX_BITMAP_SIZE) {
10891096
Timber.w("DeckPicker background image dimensions too large")
10901097
deckPickerBinding.background.setBackgroundResource(0)
10911098
return false

AnkiDroid/src/main/java/com/ichi2/anki/deckpicker/BackgroundImage.kt

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package com.ichi2.anki.deckpicker
1818

1919
import android.content.Context
20-
import android.graphics.BitmapFactory
2120
import android.net.Uri
2221
import android.provider.MediaStore
2322
import com.ichi2.anki.CollectionHelper
@@ -105,21 +104,6 @@ object BackgroundImage {
105104
Prefs.isBackgroundEnabled = true
106105
}
107106

108-
data class Size(
109-
val width: Int,
110-
val height: Int,
111-
)
112-
113-
fun getBackgroundImageDimensions(context: Context): Size {
114-
val currentAnkiDroidDirectory = CollectionHelper.getCurrentAnkiDroidDirectory(context)
115-
val destFile = File(currentAnkiDroidDirectory, FILENAME)
116-
val bmp = BitmapFactory.decodeFile(destFile.absolutePath)
117-
val w = bmp.width
118-
val h = bmp.height
119-
bmp.recycle()
120-
return Size(width = w, height = h)
121-
}
122-
123107
/**
124108
* @return `true` if the image no longer exists. `false` if an error occurred
125109
*/

AnkiDroid/src/main/java/com/ichi2/anki/utils/ext/Context.kt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@ package com.ichi2.anki.utils.ext
1818
import android.content.BroadcastReceiver
1919
import android.content.Context
2020
import android.content.res.TypedArray
21+
import android.graphics.Bitmap
22+
import android.graphics.BitmapFactory
2123
import android.util.AttributeSet
2224
import androidx.annotation.AttrRes
2325
import androidx.annotation.StyleRes
26+
import com.ichi2.anki.CollectionHelper
2427
import timber.log.Timber
28+
import java.io.File
2529
import kotlin.contracts.ExperimentalContracts
2630
import kotlin.contracts.InvocationKind
2731
import kotlin.contracts.contract
@@ -61,3 +65,28 @@ fun Context.unregisterReceiverSilently(receiver: BroadcastReceiver) {
6165
Timber.d(e, "BroadcastReceiver was not previously registered")
6266
}
6367
}
68+
69+
/**
70+
* Encapsulates the dimensions of a [Bitmap].
71+
* Note: width and height might be set to -1 if there are errors when decoding the file.
72+
*/
73+
data class BitmapSize(
74+
val width: Int,
75+
val height: Int,
76+
)
77+
78+
/**
79+
* Calculate the size of a [Bitmap] from [com.ichi2.anki.libanki.Collection].
80+
* @param filename the full name of the [Bitmap] file
81+
* @return a [BitmapSize] containing the calculated dimensions or null if the file was not found in
82+
* the collection directory
83+
*/
84+
fun Context.getSizeOfBitmapFromCollection(filename: String): BitmapSize? {
85+
val currentAnkiDroidDirectory = CollectionHelper.getCurrentAnkiDroidDirectory(this)
86+
val destFile = File(currentAnkiDroidDirectory, filename)
87+
if (!destFile.exists()) return null
88+
val opts = BitmapFactory.Options().apply { inJustDecodeBounds = true }
89+
// returned bitmap will be null, we just calculate the size
90+
BitmapFactory.decodeFile(destFile.absolutePath, opts)
91+
return BitmapSize(opts.outWidth, opts.outHeight)
92+
}

0 commit comments

Comments
 (0)