mirror of
https://github.com/immich-app/immich
synced 2025-10-17 18:19:27 +00:00
add b/w filter to random widget (android)
This commit is contained in:
parent
03dafba522
commit
b42a627c82
4 changed files with 71 additions and 1 deletions
|
|
@ -2,6 +2,10 @@ package app.alextran.immich.widget
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.ColorMatrix
|
||||||
|
import android.graphics.ColorMatrixColorFilter
|
||||||
|
import android.graphics.Paint
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
fun loadScaledBitmap(file: File, reqWidth: Int, reqHeight: Int): Bitmap? {
|
fun loadScaledBitmap(file: File, reqWidth: Int, reqHeight: Int): Bitmap? {
|
||||||
|
|
@ -31,3 +35,24 @@ fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeig
|
||||||
|
|
||||||
return inSampleSize
|
return inSampleSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun applyBlackWhiteFilter(src: Bitmap): Bitmap {
|
||||||
|
|
||||||
|
val config = src.config ?: Bitmap.Config.ARGB_8888
|
||||||
|
val outputBitmap = Bitmap.createBitmap(src.width, src.height, config)
|
||||||
|
outputBitmap.setHasAlpha(src.hasAlpha())
|
||||||
|
|
||||||
|
val canvas = Canvas(outputBitmap)
|
||||||
|
|
||||||
|
val paint = Paint().apply {
|
||||||
|
isFilterBitmap = true
|
||||||
|
val colorMatrix = ColorMatrix().apply {
|
||||||
|
setSaturation(0f)
|
||||||
|
}
|
||||||
|
colorFilter = ColorMatrixColorFilter(colorMatrix)
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.drawBitmap(src, 0f, 0f, paint)
|
||||||
|
|
||||||
|
return outputBitmap
|
||||||
|
}
|
||||||
|
|
@ -122,6 +122,13 @@ class ImageDownloadWorker(
|
||||||
WidgetType.MEMORIES -> fetchMemory(serverConfig)
|
WidgetType.MEMORIES -> fetchMemory(serverConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if needed apply our filter
|
||||||
|
val filter = WidgetImageFilter.fromString(widgetConfig[kImageFilter])
|
||||||
|
val filteredImage = when (filter) {
|
||||||
|
WidgetImageFilter.BLACK_WHITE -> applyBlackWhiteFilter(entry.image)
|
||||||
|
WidgetImageFilter.NONE -> entry.image
|
||||||
|
}
|
||||||
|
|
||||||
// clear current image if it exists
|
// clear current image if it exists
|
||||||
if (!currentImgUUID.isNullOrEmpty()) {
|
if (!currentImgUUID.isNullOrEmpty()) {
|
||||||
deleteImage(currentImgUUID)
|
deleteImage(currentImgUUID)
|
||||||
|
|
@ -129,7 +136,7 @@ class ImageDownloadWorker(
|
||||||
|
|
||||||
// save a new image
|
// save a new image
|
||||||
val imgUUID = UUID.randomUUID().toString()
|
val imgUUID = UUID.randomUUID().toString()
|
||||||
saveImage(entry.image, imgUUID)
|
saveImage(filteredImage, imgUUID)
|
||||||
|
|
||||||
// trigger the update routine with new image uuid
|
// trigger the update routine with new image uuid
|
||||||
updateWidget(glanceId, imgUUID, entry.subtitle, entry.deeplink)
|
updateWidget(glanceId, imgUUID, entry.subtitle, entry.deeplink)
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ fun RandomConfiguration(context: Context, appWidgetId: Int, glanceId: GlanceId,
|
||||||
|
|
||||||
var selectedAlbum by remember { mutableStateOf<DropdownItem?>(null) }
|
var selectedAlbum by remember { mutableStateOf<DropdownItem?>(null) }
|
||||||
var showAlbumName by remember { mutableStateOf(false) }
|
var showAlbumName by remember { mutableStateOf(false) }
|
||||||
|
var selectedFilter by remember { mutableStateOf<DropdownItem?>(null) }
|
||||||
var availableAlbums by remember { mutableStateOf<List<DropdownItem>>(listOf()) }
|
var availableAlbums by remember { mutableStateOf<List<DropdownItem>>(listOf()) }
|
||||||
var state by remember { mutableStateOf(WidgetConfigState.LOADING) }
|
var state by remember { mutableStateOf(WidgetConfigState.LOADING) }
|
||||||
|
|
||||||
|
|
@ -104,6 +105,16 @@ fun RandomConfiguration(context: Context, appWidgetId: Int, glanceId: GlanceId,
|
||||||
val albumEntity = availableAlbums.firstOrNull { it.id == currentAlbumId }
|
val albumEntity = availableAlbums.firstOrNull { it.id == currentAlbumId }
|
||||||
selectedAlbum = albumEntity ?: availableAlbums.first()
|
selectedAlbum = albumEntity ?: availableAlbums.first()
|
||||||
|
|
||||||
|
// load filter configuration
|
||||||
|
val availableFilters = listOf(
|
||||||
|
DropdownItem("None", WidgetImageFilter.NONE.name),
|
||||||
|
DropdownItem("Black & White", WidgetImageFilter.BLACK_WHITE.name)
|
||||||
|
)
|
||||||
|
|
||||||
|
val savedFilterId = currentState[kImageFilter] ?: WidgetImageFilter.NONE.name
|
||||||
|
val selectedFilterItem = availableFilters.firstOrNull { it.id == savedFilterId }
|
||||||
|
selectedFilter = selectedFilterItem ?: availableFilters.first()
|
||||||
|
|
||||||
// load showAlbumName
|
// load showAlbumName
|
||||||
showAlbumName = currentState[kShowAlbumName] == true
|
showAlbumName = currentState[kShowAlbumName] == true
|
||||||
}
|
}
|
||||||
|
|
@ -113,6 +124,7 @@ fun RandomConfiguration(context: Context, appWidgetId: Int, glanceId: GlanceId,
|
||||||
prefs[kSelectedAlbum] = selectedAlbum?.id ?: ""
|
prefs[kSelectedAlbum] = selectedAlbum?.id ?: ""
|
||||||
prefs[kSelectedAlbumName] = selectedAlbum?.label ?: ""
|
prefs[kSelectedAlbumName] = selectedAlbum?.label ?: ""
|
||||||
prefs[kShowAlbumName] = showAlbumName
|
prefs[kShowAlbumName] = showAlbumName
|
||||||
|
prefs[kImageFilter] = selectedFilter?.id ?: WidgetImageFilter.NONE.name
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageDownloadWorker.singleShot(context, appWidgetId, WidgetType.RANDOM)
|
ImageDownloadWorker.singleShot(context, appWidgetId, WidgetType.RANDOM)
|
||||||
|
|
@ -187,6 +199,17 @@ fun RandomConfiguration(context: Context, appWidgetId: Int, glanceId: GlanceId,
|
||||||
enabled = (state != WidgetConfigState.NO_CONNECTION)
|
enabled = (state != WidgetConfigState.NO_CONNECTION)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Text("Filter")
|
||||||
|
Dropdown(
|
||||||
|
items = listOf(
|
||||||
|
DropdownItem("None", WidgetImageFilter.NONE.name),
|
||||||
|
DropdownItem("Black & White", WidgetImageFilter.BLACK_WHITE.name)
|
||||||
|
),
|
||||||
|
selectedItem = selectedFilter,
|
||||||
|
onItemSelected = { selectedFilter = it },
|
||||||
|
enabled = (state != WidgetConfigState.NO_CONNECTION)
|
||||||
|
)
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,20 @@ enum class WidgetConfigState {
|
||||||
LOADING, SUCCESS, LOG_IN, NO_CONNECTION
|
LOADING, SUCCESS, LOG_IN, NO_CONNECTION
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class WidgetImageFilter {
|
||||||
|
NONE, BLACK_WHITE;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromString(value: String?): WidgetImageFilter {
|
||||||
|
return try {
|
||||||
|
valueOf(value ?: NONE.name)
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data class WidgetEntry (
|
data class WidgetEntry (
|
||||||
val image: Bitmap,
|
val image: Bitmap,
|
||||||
val subtitle: String?,
|
val subtitle: String?,
|
||||||
|
|
@ -70,6 +84,7 @@ val kSelectedAlbum = stringPreferencesKey("albumID")
|
||||||
val kSelectedAlbumName = stringPreferencesKey("albumName")
|
val kSelectedAlbumName = stringPreferencesKey("albumName")
|
||||||
val kShowAlbumName = booleanPreferencesKey("showAlbumName")
|
val kShowAlbumName = booleanPreferencesKey("showAlbumName")
|
||||||
val kDeeplinkURL = stringPreferencesKey("deeplink")
|
val kDeeplinkURL = stringPreferencesKey("deeplink")
|
||||||
|
val kImageFilter = stringPreferencesKey("imageFiler")
|
||||||
|
|
||||||
const val kWorkerWidgetType = "widgetType"
|
const val kWorkerWidgetType = "widgetType"
|
||||||
const val kWorkerWidgetID = "widgetId"
|
const val kWorkerWidgetID = "widgetId"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue