tranforming images for adaptive shortcuts within glides transformations
- avoid creating new bitmaps each time the room list changes
This commit is contained in:
parent
eeb9785651
commit
9f44975b4a
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.home
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
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.security.MessageDigest
|
||||
|
||||
private const val ADAPTIVE_TRANSFORMATION_ID = "adaptive-icon-transform"
|
||||
private val ID_BYTES = ADAPTIVE_TRANSFORMATION_ID.toByteArray()
|
||||
|
||||
class AdaptiveIconTransformation(private val adaptiveIconSize: Int, private val adaptiveIconOuterSides: Float) : BitmapTransformation() {
|
||||
|
||||
override fun updateDiskCacheKey(messageDigest: MessageDigest) {
|
||||
messageDigest.update(ID_BYTES)
|
||||
messageDigest.update(ByteBuffer.allocate(4).putInt(adaptiveIconSize).putFloat(adaptiveIconOuterSides).array())
|
||||
}
|
||||
|
||||
override fun transform(pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int): Bitmap {
|
||||
val insetBmp = Bitmap.createBitmap(adaptiveIconSize, adaptiveIconSize, Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(insetBmp)
|
||||
canvas.drawBitmap(toTransform, adaptiveIconOuterSides, adaptiveIconOuterSides, null)
|
||||
canvas.setBitmap(null)
|
||||
return insetBmp
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return if (other is AdaptiveIconTransformation) {
|
||||
other.adaptiveIconSize == adaptiveIconSize && other.adaptiveIconOuterSides == adaptiveIconOuterSides
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
override fun hashCode() = Util.hashCode(ADAPTIVE_TRANSFORMATION_ID.hashCode(), Util.hashCode(adaptiveIconSize, Util.hashCode(adaptiveIconOuterSides)))
|
||||
}
|
@ -26,6 +26,7 @@ import androidx.core.graphics.drawable.toBitmap
|
||||
import com.amulyakhare.textdrawable.TextDrawable
|
||||
import com.bumptech.glide.load.MultiTransformation
|
||||
import com.bumptech.glide.load.Transformation
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop
|
||||
import com.bumptech.glide.load.resource.bitmap.CircleCrop
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
||||
@ -157,25 +158,41 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
|
||||
fun shortcutDrawable(glideRequests: GlideRequests, matrixItem: MatrixItem, iconSize: Int): Bitmap {
|
||||
return glideRequests
|
||||
.asBitmap()
|
||||
.let {
|
||||
val resolvedUrl = resolvedUrl(matrixItem.avatarUrl)
|
||||
if (resolvedUrl != null) {
|
||||
it.load(resolvedUrl)
|
||||
} else {
|
||||
val avatarColor = matrixItemColorProvider.getColor(matrixItem)
|
||||
it.load(TextDrawable.builder()
|
||||
.beginConfig()
|
||||
.bold()
|
||||
.endConfig()
|
||||
.buildRect(matrixItem.firstLetterOfDisplayName(), avatarColor)
|
||||
.toBitmap(width = iconSize, height = iconSize))
|
||||
}
|
||||
}
|
||||
.avatarOrText(matrixItem, iconSize)
|
||||
.apply(RequestOptions.centerCropTransform())
|
||||
.submit(iconSize, iconSize)
|
||||
.get()
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@Throws
|
||||
fun adaptiveShortcutDrawable(glideRequests: GlideRequests, matrixItem: MatrixItem, iconSize: Int, adaptiveIconSize: Int, adaptiveIconOuterSides: Float): Bitmap {
|
||||
return glideRequests
|
||||
.asBitmap()
|
||||
.avatarOrText(matrixItem, iconSize)
|
||||
.transform(CenterCrop(), AdaptiveIconTransformation(adaptiveIconSize, adaptiveIconOuterSides))
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.submit(adaptiveIconSize, adaptiveIconSize)
|
||||
.get()
|
||||
}
|
||||
|
||||
private fun GlideRequest<Bitmap>.avatarOrText(matrixItem: MatrixItem, iconSize: Int): GlideRequest<Bitmap> {
|
||||
return this.let {
|
||||
val resolvedUrl = resolvedUrl(matrixItem.avatarUrl)
|
||||
if (resolvedUrl != null) {
|
||||
it.load(resolvedUrl)
|
||||
} else {
|
||||
val avatarColor = matrixItemColorProvider.getColor(matrixItem)
|
||||
it.load(TextDrawable.builder()
|
||||
.beginConfig()
|
||||
.bold()
|
||||
.endConfig()
|
||||
.buildRect(matrixItem.firstLetterOfDisplayName(), avatarColor)
|
||||
.toBitmap(width = iconSize, height = iconSize))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun renderBlur(matrixItem: MatrixItem,
|
||||
imageView: ImageView,
|
||||
|
@ -19,7 +19,6 @@ package im.vector.app.features.home
|
||||
import android.content.Context
|
||||
import android.content.pm.ShortcutInfo
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.os.Build
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.core.content.pm.ShortcutInfoCompat
|
||||
@ -61,7 +60,12 @@ class ShortcutCreator @Inject constructor(
|
||||
fun create(roomSummary: RoomSummary, rank: Int = 1): ShortcutInfoCompat {
|
||||
val intent = RoomDetailActivity.shortcutIntent(context, roomSummary.roomId)
|
||||
val bitmap = try {
|
||||
avatarRenderer.shortcutDrawable(GlideApp.with(context), roomSummary.toMatrixItem(), iconSize)
|
||||
val glideRequests = GlideApp.with(context)
|
||||
val matrixItem = roomSummary.toMatrixItem()
|
||||
when (useAdaptiveIcon) {
|
||||
true -> avatarRenderer.adaptiveShortcutDrawable(glideRequests, matrixItem, iconSize, adaptiveIconSize, adaptiveIconOuterSides.toFloat())
|
||||
false -> avatarRenderer.shortcutDrawable(glideRequests, matrixItem, iconSize)
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
null
|
||||
}
|
||||
@ -83,11 +87,7 @@ class ShortcutCreator @Inject constructor(
|
||||
|
||||
private fun Bitmap.toProfileImageIcon(): IconCompat {
|
||||
return if (useAdaptiveIcon) {
|
||||
val insetBmp = Bitmap.createBitmap(adaptiveIconSize, adaptiveIconSize, Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(insetBmp)
|
||||
canvas.drawBitmap(this, adaptiveIconOuterSides.toFloat(), adaptiveIconOuterSides.toFloat(), null)
|
||||
|
||||
IconCompat.createWithAdaptiveBitmap(insetBmp)
|
||||
IconCompat.createWithAdaptiveBitmap(this)
|
||||
} else {
|
||||
IconCompat.createWithBitmap(this)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user