Skip to content

Commit

Permalink
Merge pull request #29 from skydoves/improve/radius-limits
Browse files Browse the repository at this point in the history
Allow to use radius up to 25 by iterating the blur transformation
  • Loading branch information
skydoves authored Jul 6, 2024
2 parents 4adb955 + 5767de5 commit cffcb6b
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 27 deletions.
2 changes: 1 addition & 1 deletion app/src/main/kotlin/com/skydoves/cloudydemo/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fun Main() {
) {
var animationPlayed by remember { mutableStateOf(false) }
val radius by animateIntAsState(
targetValue = if (animationPlayed) 15 else 0,
targetValue = if (animationPlayed) 45 else 0,
animationSpec = tween(
durationMillis = 1000,
delayMillis = 500,
Expand Down
16 changes: 6 additions & 10 deletions app/src/main/kotlin/com/skydoves/cloudydemo/posters/HomePosters.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import com.skydoves.cloudy.Cloudy
import com.skydoves.cloudy.internals.cloudy
import com.skydoves.cloudydemo.model.MockUtil
import com.skydoves.cloudydemo.model.Poster
import com.skydoves.cloudydemo.theme.PosterTheme
Expand All @@ -53,16 +53,12 @@ fun HomePosters(
applyBlur = true
}

Cloudy(
radius = 20,
key1 = applyBlur
LazyVerticalGrid(
modifier = Modifier.cloudy(radius = 20),
columns = GridCells.Fixed(2)
) {
LazyVerticalGrid(
columns = GridCells.Fixed(2)
) {
items(key = { it.id }, items = posters) {
HomePoster(poster = it)
}
items(key = { it.id }, items = posters) {
HomePoster(poster = it)
}
}
}
Expand Down
14 changes: 7 additions & 7 deletions cloudy/src/main/kotlin/com/skydoves/cloudy/Cloudy.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import androidx.compose.ui.viewinterop.AndroidView
import com.skydoves.cloudy.internals.CloudyModifier
import com.skydoves.cloudy.internals.InternalLaunchedEffect
import com.skydoves.cloudy.internals.LayoutInfo
import com.skydoves.cloudy.internals.render.RenderScriptToolkit
import com.skydoves.cloudy.internals.render.iterativeBlur
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
Expand All @@ -54,7 +54,7 @@ import kotlinx.coroutines.withContext
* History: The [blur] modifier supports only Android 12 and higher, and [RenderScript] was also deprecated.
*
* @param modifier Adjust the drawing layout or drawing decoration of the content.
* @param radius Radius of the blur along both the x and y axis. It must be in 0 to 25.
* @param radius Radius of the blur along both the x and y axis.
* @param key1 Key value for trigger recomposition.
* @param key2 Key value for trigger recomposition.
* @param onStateChanged Lambda function that will be invoked when the blur process has been updated.
Expand All @@ -63,7 +63,7 @@ import kotlinx.coroutines.withContext
@Composable
public fun Cloudy(
modifier: Modifier = Modifier,
@androidx.annotation.IntRange(from = 0, to = 25) radius: Int = 10,
radius: Int = 10,
key1: Any? = null,
key2: Any? = null,
allowAccumulate: (CloudyState) -> Boolean = { false },
Expand Down Expand Up @@ -105,7 +105,7 @@ public fun Cloudy(
*/
private fun ComposeView.composeCloudy(
modifier: Modifier,
@androidx.annotation.IntRange(from = 0, to = 25) radius: Int,
radius: Int,
key1: Any? = null,
key2: Any? = null,
key3: Any? = null,
Expand Down Expand Up @@ -173,7 +173,7 @@ private fun Modifier.cloudy(
key3: Any? = null,
initialBitmap: Bitmap? = null,
graphicsLayer: GraphicsLayer,
@androidx.annotation.IntRange(from = 0, to = 25) radius: Int,
radius: Int,
layoutInfo: LayoutInfo,
onStateChanged: (CloudyState) -> Unit
): Modifier = composed(
Expand All @@ -194,8 +194,8 @@ private fun Modifier.cloudy(
val targetBitmap = blurredBitmap ?: graphicsLayer.toImageBitmap().asAndroidBitmap()
.copy(Bitmap.Config.ARGB_8888, true)

blurredBitmap = RenderScriptToolkit.blur(
inputBitmap = targetBitmap,
blurredBitmap = iterativeBlur(
androidBitmap = targetBitmap,
radius = radius
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package com.skydoves.cloudy.internals

import android.graphics.Bitmap
import androidx.annotation.IntRange
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.asAndroidBitmap
Expand All @@ -37,12 +36,12 @@ import androidx.compose.ui.platform.InspectorInfo
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.offset
import com.skydoves.cloudy.CloudyState
import com.skydoves.cloudy.internals.render.RenderScriptToolkit
import com.skydoves.cloudy.internals.render.iterativeBlur
import kotlinx.coroutines.runBlocking

@Composable
public fun Modifier.cloudy(
@IntRange(from = 0, to = 25) radius: Int = 10,
radius: Int = 10,
onStateChanged: (CloudyState) -> Unit = {}
): Modifier {
return this then CloudyModifierNodeElement(
Expand All @@ -54,7 +53,7 @@ public fun Modifier.cloudy(

private data class CloudyModifierNodeElement(
private val graphicsLayer: GraphicsLayer,
@IntRange(from = 0, to = 25) val radius: Int = 10,
val radius: Int = 10,
val onStateChanged: (CloudyState) -> Unit = {}
) : ModifierNodeElement<CloudyModifierNode>() {

Expand All @@ -76,7 +75,7 @@ private data class CloudyModifierNodeElement(

private class CloudyModifierNode(
val graphicsLayer: GraphicsLayer,
@IntRange(from = 0, to = 25) var radius: Int = 10,
var radius: Int = 10,
private val onStateChanged: (CloudyState) -> Unit = {}
) : LayoutModifierNode, GlobalPositionAwareModifierNode, DrawModifierNode, Modifier.Node() {

Expand Down Expand Up @@ -111,13 +110,13 @@ private class CloudyModifierNode(
onStateChanged.invoke(CloudyState.Loading)

try {
val targetBitmap: Bitmap? = runBlocking {
val targetBitmap: Bitmap = runBlocking {
graphicsLayer.toImageBitmap().asAndroidBitmap()
.copy(Bitmap.Config.ARGB_8888, true)
}
} ?: throw RuntimeException("Couldn't capture a bitmap from the composable tree")

val blurredBitmap = RenderScriptToolkit.blur(
inputBitmap = targetBitmap,
val blurredBitmap = iterativeBlur(
androidBitmap = targetBitmap,
radius = radius
)?.apply {
drawImage(this.asImageBitmap())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,23 @@ internal fun vectorSize(bitmap: Bitmap): Int {
)
}
}

internal fun iterativeBlur(
androidBitmap: Bitmap,
radius: Int
): Bitmap? {
val iterate = (radius + 1) / 25
var bitmap: Bitmap? = RenderScriptToolkit.blur(
inputBitmap = androidBitmap,
radius = (radius + 1) % 25
)

for (i in 0 until iterate) {
bitmap = RenderScriptToolkit.blur(
inputBitmap = bitmap,
radius = 25
)
}

return bitmap
}

0 comments on commit cffcb6b

Please sign in to comment.