Skip to content

Commit

Permalink
Added grayscale filter
Browse files Browse the repository at this point in the history
  • Loading branch information
Anthonyy232 committed Oct 3, 2024
1 parent 9b7f9c9 commit 18ca628
Show file tree
Hide file tree
Showing 15 changed files with 518 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,7 @@ object SettingsConstants {
const val LOCK_NEXT_SET_TIME = "next_set_time_2"
const val NEXT_HOME_WALLPAPER = "next_home_wallpaper"
const val NEXT_LOCK_WALLPAPER = "next_lock_wallpaper"
const val GRAYSCALE = "grayscale"
const val HOME_GRAYSCALE_PERCENTAGE = "home_grayscale_percentage"
const val LOCK_GRAYSCALE_PERCENTAGE = "lock_grayscale_percentage"
}
73 changes: 49 additions & 24 deletions app/src/main/java/com/anthonyla/paperize/core/WallpaperUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -306,14 +306,50 @@ fun vignetteBitmap(source: Bitmap, percent: Int): Bitmap {
}
}

/**
* Apply a grey filter to the bitmap based on a percentage
*/
fun grayBitmap(bitmap: Bitmap, percent: Int): Bitmap {
val factor = percent / 100f
val colorMatrix = ColorMatrix().apply {
setSaturation(1 - factor)
}
val paint = Paint().apply {
colorFilter = ColorMatrixColorFilter(colorMatrix)
}
val grayBitmap = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(grayBitmap)
canvas.drawBitmap(bitmap, 0f, 0f, paint)

return grayBitmap
}

/**
* Calculate the brightness of a bitmap (0-100)
* https://gist.github.com/httnn/b1d772caf76cdc0c11e2
*/
fun calculateBrightness(bitmap: Bitmap, pixelSpacing: Int = 1): Int {
var brightness = 0.0
val pixels = IntArray(bitmap.width * bitmap.height)
bitmap.getPixels(pixels, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
for (i in pixels.indices step pixelSpacing.coerceAtLeast(1)) {
val color = pixels[i]
val R = Color.red(color)
val G = Color.green(color)
val B = Color.blue(color)
brightness += 0.299*R + 0.587*G + 0.114*B
}
return (brightness / (pixels.size / pixelSpacing)).toInt()
}

/**
* Retrieve wallpaper URIs from a folder directory URI
*/
fun getWallpaperFromFolder(folderUri: String, context: Context): List<String> {
return try {
val folderDocumentFile = DocumentFileCompat.fromTreeUri(context, folderUri.toUri())
listFilesRecursive(folderDocumentFile, context)
} catch (e: Exception) {
} catch (_: Exception) {
val folderDocumentFile = DocumentFile.fromTreeUri(context, folderUri.toUri())
listFilesRecursive(folderDocumentFile, context)
}
Expand Down Expand Up @@ -364,7 +400,7 @@ fun findFirstValidUri(context: Context, wallpapers: List<Wallpaper>, folders: Li
if (file?.exists() == true) {
return wallpaper.wallpaperUri
}
} catch (e: Exception) {
} catch (_: Exception) {
val file = DocumentFile.fromSingleUri(context, wallpaper.wallpaperUri.toUri())
if (file?.exists() == true) {
return wallpaper.wallpaperUri
Expand All @@ -378,7 +414,7 @@ fun findFirstValidUri(context: Context, wallpapers: List<Wallpaper>, folders: Li
if (file?.exists() == true) {
return wallpaper
}
} catch (e: Exception) {
} catch (_: Exception) {
val file = DocumentFile.fromSingleUri(context, wallpaper.toUri())
if (file?.exists() == true) {
return wallpaper
Expand All @@ -395,7 +431,7 @@ fun findFirstValidUri(context: Context, wallpapers: List<Wallpaper>, folders: Li
fun getFolderNameFromUri(folderUri: String, context: Context): String? {
return try {
DocumentFileCompat.fromTreeUri(context, folderUri.toUri())?.name
} catch (e: Exception) {
} catch (_: Exception) {
DocumentFile.fromTreeUri(context, folderUri.toUri())?.name
}
}
Expand All @@ -411,25 +447,7 @@ fun isValidUri(context: Context, uriString: String?): Boolean {
inputStream?.close()
}
true
} catch (e: Exception) { false }
}

/**
* Calculate the brightness of a bitmap (0-100)
* https://gist.github.com/httnn/b1d772caf76cdc0c11e2
*/
fun calculateBrightness(bitmap: Bitmap, pixelSpacing: Int = 1): Int {
var brightness = 0.0
val pixels = IntArray(bitmap.width * bitmap.height)
bitmap.getPixels(pixels, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
for (i in pixels.indices step pixelSpacing.coerceAtLeast(1)) {
val color = pixels[i]
val R = Color.red(color)
val G = Color.green(color)
val B = Color.blue(color)
brightness += 0.299*R + 0.587*G + 0.114*B
}
return (brightness / (pixels.size / pixelSpacing)).toInt()
} catch (_: Exception) { false }
}

/**
Expand All @@ -446,7 +464,9 @@ fun processBitmap(
blur: Boolean,
blurPercent: Int,
vignette: Boolean,
vignettePercent: Int
vignettePercent: Int,
grayscale: Boolean,
grayscalePercent: Int
): Bitmap? {
try {
var processedBitmap = source
Expand Down Expand Up @@ -474,6 +494,11 @@ fun processBitmap(
processedBitmap = vignetteBitmap(processedBitmap, vignettePercent)
}

// Apply gray effect
if (grayscale && grayscalePercent > 0) {
processedBitmap = grayBitmap(processedBitmap, grayscalePercent)
}

return processedBitmap
} catch (e: Exception) {
Log.e("PaperizeWallpaperChanger", "Error darkening bitmap", e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ fun PaperizeApp(
vignette = settingsState.value.vignette,
homeVignettePercentage = settingsState.value.homeVignettePercentage,
lockVignettePercentage = settingsState.value.lockVignettePercentage,
grayscale = settingsState.value.grayscale,
homeGrayscalePercentage = settingsState.value.homeGrayscalePercentage,
lockGrayscalePercentage = settingsState.value.lockGrayscalePercentage,
onSettingsClick = { navController.navigate(Settings) },
navigateToAddWallpaperScreen = {
navController.navigate(AddEdit(it))
Expand Down Expand Up @@ -708,6 +711,26 @@ fun PaperizeApp(
}
}
},
onGrayscaleChange = {
settingsViewModel.onEvent(SettingsEvent.SetGrayscale(it))
if (settingsState.value.enableChanger) {
job?.cancel()
job = scope.launch {
delay(1000)
scheduler.updateWallpaper(settingsState.value.scheduleSeparately, settingsState.value.setHomeWallpaper, settingsState.value.setLockWallpaper)
}
}
},
onGrayscalePercentageChange = { home, lock ->
settingsViewModel.onEvent(SettingsEvent.SetGrayscalePercentage(home, lock))
if (settingsState.value.enableChanger && settingsState.value.grayscale) {
job?.cancel()
job = scope.launch {
delay(3000)
scheduler.updateWallpaper(settingsState.value.scheduleSeparately, settingsState.value.setHomeWallpaper, settingsState.value.setLockWallpaper)
}
}
},
)
}
// Navigate to the add album screen to create a new album and add wallpapers to it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,12 @@ fun HomeScreen(
lockVignettePercentage: Int,
onVignettePercentageChange: (Int, Int) -> Unit,
onVignetteChange: (Boolean) -> Unit,
vignette: Boolean
vignette: Boolean,
homeGrayscalePercentage: Int,
lockGrayscalePercentage: Int,
onGrayscalePercentageChange: (Int, Int) -> Unit,
onGrayscaleChange: (Boolean) -> Unit,
grayscale: Boolean
) {
val tabItems = getTabItems()
val pagerState = rememberPagerState(0) { tabItems.size }
Expand Down Expand Up @@ -178,7 +183,12 @@ fun HomeScreen(
lockVignettePercentage = lockVignettePercentage,
onVignettePercentageChange = onVignettePercentageChange,
onVignetteChange = onVignetteChange,
vignette = vignette
vignette = vignette,
homeGrayscalePercentage = homeGrayscalePercentage,
lockGrayscalePercentage = lockGrayscalePercentage,
onGrayscalePercentageChange = onGrayscalePercentageChange,
onGrayscaleChange = onGrayscaleChange,
grayscale = grayscale
)
else -> LibraryScreen(
albums = albums,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ sealed class SettingsEvent {
data class SetDarken(val darken: Boolean): SettingsEvent()
data class SetBlur(val blur: Boolean): SettingsEvent()
data class SetVignette(val vignette: Boolean): SettingsEvent()
data class SetGrayscale(val grayscale: Boolean): SettingsEvent()
data class SetLock(val lock: Boolean): SettingsEvent()
data class SetHome(val home: Boolean): SettingsEvent()
data class SetCurrentHomeWallpaper(val currentHomeWallpaper: String?): SettingsEvent()
Expand All @@ -29,6 +30,7 @@ sealed class SettingsEvent {
data class SetDarkenPercentage(val homeDarkenPercentage: Int?, val lockDarkenPercentage: Int?): SettingsEvent()
data class SetBlurPercentage(val homeBlurPercentage: Int?, val lockBlurPercentage: Int?): SettingsEvent()
data class SetVignettePercentage(val homeVignettePercentage: Int?, val lockVignettePercentage: Int?): SettingsEvent()
data class SetGrayscalePercentage(val homeGrayscalePercentage: Int?, val lockGrayscalePercentage: Int?): SettingsEvent()
data class SetChangerToggle(val toggle: Boolean): SettingsEvent()
data class SetWallpaperScaling(val scaling: ScalingConstants): SettingsEvent()
data class SetNextHomeWallpaper(val nextHomeWallpaper: String?): SettingsEvent()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ data class SettingsState(
val vignette: Boolean = false,
val homeVignettePercentage: Int = 0,
val lockVignettePercentage: Int = 0,
val grayscale: Boolean = false,
val homeGrayscalePercentage: Int = 0,
val lockGrayscalePercentage: Int = 0,
val wallpaperScaling: ScalingConstants = ScalingConstants.FILL,
val nextHomeWallpaper: String? = null,
val nextLockWallpaper: String? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ class SettingsViewModel @Inject constructor (
val vignette = async { settingsDataStoreImpl.getBoolean(SettingsConstants.VIGNETTE) ?: false }
val homeVignettePercentage = async { settingsDataStoreImpl.getInt(SettingsConstants.HOME_VIGNETTE_PERCENTAGE) ?: 0 }
val lockVignettePercentage = async { settingsDataStoreImpl.getInt(SettingsConstants.LOCK_VIGNETTE_PERCENTAGE) ?: 0 }
val grayscale = async { settingsDataStoreImpl.getBoolean(SettingsConstants.GRAYSCALE) ?: false }
val homeGrayscalePercentage = async { settingsDataStoreImpl.getInt(SettingsConstants.HOME_GRAYSCALE_PERCENTAGE) ?: 0 }
val lockGrayscalePercentage = async { settingsDataStoreImpl.getInt(SettingsConstants.LOCK_GRAYSCALE_PERCENTAGE) ?: 0 }
val nextHomeWallpaper = async { settingsDataStoreImpl.getString(SettingsConstants.HOME_NEXT_SET_TIME) }
val nextLockWallpaper = async { settingsDataStoreImpl.getString(SettingsConstants.LOCK_NEXT_SET_TIME) }

Expand Down Expand Up @@ -94,7 +97,10 @@ class SettingsViewModel @Inject constructor (
nextLockWallpaper = nextLockWallpaper.await(),
vignette = vignette.await(),
homeVignettePercentage = homeVignettePercentage.await(),
lockVignettePercentage = lockVignettePercentage.await()
lockVignettePercentage = lockVignettePercentage.await(),
grayscale = grayscale.await(),
homeGrayscalePercentage = homeGrayscalePercentage.await(),
lockGrayscalePercentage = lockGrayscalePercentage.await()
)
}
setKeepOnScreenCondition = false
Expand Down Expand Up @@ -156,6 +162,9 @@ class SettingsViewModel @Inject constructor (
val vignette = async { settingsDataStoreImpl.getBoolean(SettingsConstants.VIGNETTE) ?: false }
val homeVignettePercentage = async { settingsDataStoreImpl.getInt(SettingsConstants.HOME_VIGNETTE_PERCENTAGE) ?: 0 }
val lockVignettePercentage = async { settingsDataStoreImpl.getInt(SettingsConstants.LOCK_VIGNETTE_PERCENTAGE) ?: 0 }
val grayscale = async { settingsDataStoreImpl.getBoolean(SettingsConstants.GRAYSCALE) ?: false }
val homeGrayscalePercentage = async { settingsDataStoreImpl.getInt(SettingsConstants.HOME_GRAYSCALE_PERCENTAGE) ?: 0 }
val lockGrayscalePercentage = async { settingsDataStoreImpl.getInt(SettingsConstants.LOCK_GRAYSCALE_PERCENTAGE) ?: 0 }

_state.update {
it.copy(
Expand Down Expand Up @@ -186,7 +195,10 @@ class SettingsViewModel @Inject constructor (
nextLockWallpaper = nextLockWallpaper.await(),
vignette = vignette.await(),
homeVignettePercentage = homeVignettePercentage.await(),
lockVignettePercentage = lockVignettePercentage.await()
lockVignettePercentage = lockVignettePercentage.await(),
grayscale = grayscale.await(),
homeGrayscalePercentage = homeGrayscalePercentage.await(),
lockGrayscalePercentage = lockGrayscalePercentage.await()
)
}
}
Expand Down Expand Up @@ -467,6 +479,34 @@ class SettingsViewModel @Inject constructor (
}
}

is SettingsEvent.SetGrayscale -> {
viewModelScope.launch(Dispatchers.IO) {
settingsDataStoreImpl.putBoolean(SettingsConstants.GRAYSCALE, event.grayscale)
_state.update {
it.copy(
grayscale = event.grayscale
)
}
}
}

is SettingsEvent.SetGrayscalePercentage -> {
viewModelScope.launch(Dispatchers.IO) {
if (event.lockGrayscalePercentage != null) {
settingsDataStoreImpl.putInt(SettingsConstants.LOCK_GRAYSCALE_PERCENTAGE, event.lockGrayscalePercentage)
}
if (event.homeGrayscalePercentage != null) {
settingsDataStoreImpl.putInt(SettingsConstants.HOME_GRAYSCALE_PERCENTAGE, event.homeGrayscalePercentage)
}
_state.update {
it.copy(
homeGrayscalePercentage = event.homeGrayscalePercentage ?: it.homeGrayscalePercentage,
lockGrayscalePercentage = event.lockGrayscalePercentage ?: it.lockGrayscalePercentage
)
}
}
}

is SettingsEvent.SetCurrentHomeWallpaper -> {
viewModelScope.launch(Dispatchers.IO) {
if (event.currentHomeWallpaper != null) {
Expand Down Expand Up @@ -703,6 +743,9 @@ class SettingsViewModel @Inject constructor (
settingsDataStoreImpl.deleteBoolean(SettingsConstants.VIGNETTE)
settingsDataStoreImpl.deleteInt(SettingsConstants.HOME_VIGNETTE_PERCENTAGE)
settingsDataStoreImpl.deleteInt(SettingsConstants.LOCK_VIGNETTE_PERCENTAGE)
settingsDataStoreImpl.deleteBoolean(SettingsConstants.GRAYSCALE)
settingsDataStoreImpl.deleteInt(SettingsConstants.HOME_GRAYSCALE_PERCENTAGE)
settingsDataStoreImpl.deleteInt(SettingsConstants.LOCK_GRAYSCALE_PERCENTAGE)

_state.update {
it.copy(
Expand Down Expand Up @@ -734,7 +777,10 @@ class SettingsViewModel @Inject constructor (
nextLockWallpaper = null,
vignette = false,
homeVignettePercentage = 0,
lockVignettePercentage = 0
lockVignettePercentage = 0,
grayscale = false,
homeGrayscalePercentage = 0,
lockGrayscalePercentage = 0
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import com.anthonyla.paperize.feature.wallpaper.presentation.wallpaper_screen.co
import com.anthonyla.paperize.feature.wallpaper.presentation.wallpaper_screen.components.CurrentAndNextChange
import com.anthonyla.paperize.feature.wallpaper.presentation.wallpaper_screen.components.CurrentSelectedAlbum
import com.anthonyla.paperize.feature.wallpaper.presentation.wallpaper_screen.components.DarkenSwitchAndSlider
import com.anthonyla.paperize.feature.wallpaper.presentation.wallpaper_screen.components.GrayscaleSwitchAndSlider
import com.anthonyla.paperize.feature.wallpaper.presentation.wallpaper_screen.components.IndividualSchedulingAndToggleRow
import com.anthonyla.paperize.feature.wallpaper.presentation.wallpaper_screen.components.TimeSliders
import com.anthonyla.paperize.feature.wallpaper.presentation.wallpaper_screen.components.VignetteSwitchAndSlider
Expand Down Expand Up @@ -85,7 +86,12 @@ fun WallpaperScreen(
lockVignettePercentage: Int,
onVignettePercentageChange: (Int, Int) -> Unit,
onVignetteChange: (Boolean) -> Unit,
vignette: Boolean
vignette: Boolean,
homeGrayscalePercentage: Int,
lockGrayscalePercentage: Int,
onGrayscalePercentageChange: (Int, Int) -> Unit,
onGrayscaleChange: (Boolean) -> Unit,
grayscale: Boolean,
) {
val shouldShowScreen = homeEnabled || lockEnabled
val shouldShowSettings = shouldShowScreen && homeSelectedAlbum != null && lockSelectedAlbum != null
Expand Down Expand Up @@ -208,7 +214,10 @@ fun WallpaperScreen(
lockBlurPercentage = lockBlurPercentage,
vignette = vignette,
homeVignettePercentage = homeVignettePercentage,
lockVignettePercentage = lockVignettePercentage
lockVignettePercentage = lockVignettePercentage,
grayscale = grayscale,
homeGrayscalePercentage = homeGrayscalePercentage,
lockGrayscalePercentage = lockGrayscalePercentage
)
CurrentAndNextChange(lastSetTime, nextSetTime)
TimeSliders(
Expand Down Expand Up @@ -256,6 +265,15 @@ fun WallpaperScreen(
animate = animate,
bothEnabled = homeEnabled && lockEnabled
)
GrayscaleSwitchAndSlider(
onGrayscalePercentageChange = onGrayscalePercentageChange,
onGrayscaleChange = onGrayscaleChange,
grayscale = grayscale,
homeGrayscalePercentage = homeGrayscalePercentage,
lockGrayscalePercentage = lockGrayscalePercentage,
animate = animate,
bothEnabled = homeEnabled && lockEnabled
)
}
}
}
Expand Down
Loading

0 comments on commit 18ca628

Please sign in to comment.