Optimize I/O code using Okio - part 2 (#4372)

- Read license resource using Okio inside a coroutine (instead of the
main thread) in `LicenseActivity`
- Use Okio and its buffer system to copy ContentProvider streams and
files to a temporary file in `MediaUploader.prepareMedia()`
- Properly close the input file after copying it to a temporary file in
`MediaUploader.prepareMedia()`
- Properly close sink in case of null body source during file copy in
`Uri.copyToFolder()` in `DraftHelper.kt`
- Add comment explaining the current value of `DEFAULT_CHUNK_SIZE` in
`UriRequestBody.kt` and indent the file properly
- Replace hardcoded `Charset` and `Int` byte size with the proper
constants, and align the `hashCode()` implementation with other
`BitmapTransformation` implementations in
`CompositeWithOpaqueBackground`
- Properly close `InputStream` in case of error during Bitmap size
decoding in `getImageSquarePixels()`
- return `Int` instead of `Long` in `getImageSquarePixels()`, since the
current code simply converts the `Int` result to a `Long` _after_
multiplication and not before (and `Int.MAX_VALUE` is already way above
the maximum number of pixels a decoded Bitmap could return)
- Simplify `getImageOrientation()`
- Add explicit dependency to the Okio library and upgrade it to its
latest version.
This commit is contained in:
Christophe Beyls 2024-04-14 16:39:29 +02:00 committed by GitHub
commit f69cae2315
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 77 additions and 76 deletions

View file

@ -24,11 +24,11 @@ import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter
import android.graphics.Paint
import android.graphics.Shader
import com.bumptech.glide.load.Key
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
import com.bumptech.glide.util.Util
import java.nio.ByteBuffer
import java.nio.charset.Charset
import java.security.MessageDigest
/**
@ -57,11 +57,11 @@ class CompositeWithOpaqueBackground(val backgroundColor: Int) : BitmapTransforma
return false
}
override fun hashCode() = Util.hashCode(ID.hashCode(), backgroundColor.hashCode())
override fun hashCode() = Util.hashCode(ID.hashCode(), Util.hashCode(backgroundColor))
override fun updateDiskCacheKey(messageDigest: MessageDigest) {
messageDigest.update(ID_BYTES)
messageDigest.update(ByteBuffer.allocate(4).putInt(backgroundColor.hashCode()).array())
messageDigest.update(ByteBuffer.allocate(Int.SIZE_BYTES).putInt(backgroundColor).array())
}
override fun transform(
@ -111,7 +111,7 @@ class CompositeWithOpaqueBackground(val backgroundColor: Int) : BitmapTransforma
@Suppress("unused")
private const val TAG = "CompositeWithOpaqueBackground"
private val ID = CompositeWithOpaqueBackground::class.qualifiedName!!
private val ID_BYTES = ID.toByteArray(Charset.forName("UTF-8"))
private val ID_BYTES = ID.toByteArray(Key.CHARSET)
/** Paint with a color filter that converts 8bpp alpha images to a 1bpp mask */
private val EXTRACT_MASK_PAINT = Paint().apply {

View file

@ -27,7 +27,6 @@ import androidx.exifinterface.media.ExifInterface
import java.io.File
import java.io.FileNotFoundException
import java.io.IOException
import java.io.InputStream
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@ -68,16 +67,18 @@ fun getMediaSize(contentResolver: ContentResolver, uri: Uri?): Long {
}
@Throws(FileNotFoundException::class)
fun getImageSquarePixels(contentResolver: ContentResolver, uri: Uri): Long {
fun getImageSquarePixels(contentResolver: ContentResolver, uri: Uri): Int {
val input = contentResolver.openInputStream(uri) ?: throw FileNotFoundException("Unavailable ContentProvider")
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeStream(input, null, options)
try {
BitmapFactory.decodeStream(input, null, options)
} finally {
input.closeQuietly()
}
input.closeQuietly()
return (options.outWidth * options.outHeight).toLong()
return options.outWidth * options.outHeight
}
fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
@ -147,30 +148,23 @@ fun reorientBitmap(bitmap: Bitmap?, orientation: Int): Bitmap? {
}
fun getImageOrientation(uri: Uri, contentResolver: ContentResolver): Int {
val inputStream: InputStream?
try {
inputStream = contentResolver.openInputStream(uri)
} catch (e: FileNotFoundException) {
Log.w(TAG, e)
return ExifInterface.ORIENTATION_UNDEFINED
}
if (inputStream == null) {
return ExifInterface.ORIENTATION_UNDEFINED
}
val exifInterface: ExifInterface
try {
exifInterface = ExifInterface(inputStream)
val inputStream = contentResolver.openInputStream(uri)
?: return ExifInterface.ORIENTATION_UNDEFINED
try {
val exifInterface = ExifInterface(inputStream)
return exifInterface.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL
)
} finally {
inputStream.closeQuietly()
}
} catch (e: IOException) {
Log.w(TAG, e)
inputStream.closeQuietly()
return ExifInterface.ORIENTATION_UNDEFINED
}
val orientation = exifInterface.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL
)
inputStream.closeQuietly()
return orientation
}
fun deleteStaleCachedMedia(mediaDirectory: File?) {