-
-
Save zoltish/1705dc27a3a35ef2731b2ef018aac2e0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context | |
import android.graphics.Bitmap | |
import android.renderscript.Allocation | |
import android.renderscript.Allocation.MipmapControl.MIPMAP_NONE | |
import android.renderscript.Allocation.USAGE_SCRIPT | |
import android.renderscript.Allocation.createFromBitmap | |
import android.renderscript.Allocation.createTyped | |
import android.renderscript.Element.U8_4 | |
import android.renderscript.RenderScript | |
import android.renderscript.RenderScript.RSMessageHandler | |
import android.renderscript.ScriptIntrinsicBlur | |
import android.renderscript.ScriptIntrinsicBlur.create | |
import androidx.compose.foundation.Image | |
import androidx.compose.foundation.layout.fillMaxSize | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.getValue | |
import androidx.compose.runtime.mutableStateOf | |
import androidx.compose.runtime.remember | |
import androidx.compose.runtime.setValue | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.graphics.ImageBitmap | |
import androidx.compose.ui.graphics.asImageBitmap | |
import progression.presentation.design.animation.TransitionValue | |
import progression.presentation.design.token.Alpha | |
import progression.presentation.design.util.scrim | |
@Composable | |
fun Blur( | |
content: @Composable () -> Unit, | |
modifier: Modifier = Modifier, | |
) { | |
var bitmap by remember { | |
mutableStateOf<ImageBitmap?>(null) | |
} | |
Capture( | |
content = content, | |
transformation = BlurTransformation(), | |
callback = { capturedBitmap -> | |
bitmap = capturedBitmap.asImageBitmap() | |
}, | |
) | |
TransitionValue( | |
value = bitmap, | |
content = { currentBitmap -> | |
Image( | |
modifier = modifier | |
.fillMaxSize() | |
.scrim(alpha = Alpha.low), | |
bitmap = currentBitmap, | |
contentDescription = null, | |
) | |
}, | |
) | |
} | |
@JvmInline | |
private value class BlurTransformation( | |
private val radius: Float = 25f, | |
) : Transformation { | |
override suspend fun transform( | |
context: Context, | |
bitmap: Bitmap, | |
): Bitmap { | |
var script: RenderScript? = null | |
var input: Allocation? = null | |
var output: Allocation? = null | |
var blur: ScriptIntrinsicBlur? = null | |
try { | |
script = RenderScript.create(context) | |
script.messageHandler = RSMessageHandler() | |
input = createFromBitmap( | |
script, | |
bitmap, | |
MIPMAP_NONE, | |
USAGE_SCRIPT, | |
) | |
output = createTyped( | |
script, | |
input.type, | |
) | |
blur = create( | |
script, | |
U8_4(script), | |
) | |
blur.setInput(input) | |
blur.setRadius(radius) | |
blur.forEach(output) | |
output.copyTo(bitmap) | |
} finally { | |
script?.destroy() | |
input?.destroy() | |
output?.destroy() | |
blur?.destroy() | |
} | |
return bitmap | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context | |
import android.graphics.Bitmap | |
import android.graphics.Bitmap.Config.ARGB_8888 | |
import android.graphics.Bitmap.createBitmap | |
import android.graphics.Canvas | |
import android.util.SparseArray | |
import android.view.View | |
import android.view.View.INVISIBLE | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.LaunchedEffect | |
import androidx.compose.runtime.Stable | |
import androidx.compose.runtime.currentCompositeKeyHash | |
import androidx.compose.runtime.remember | |
import androidx.compose.runtime.rememberCoroutineScope | |
import androidx.compose.ui.layout.SubcomposeLayout | |
import androidx.compose.ui.platform.ComposeView | |
import androidx.compose.ui.platform.LocalContext | |
import androidx.compose.ui.viewinterop.AndroidView | |
import kotlinx.coroutines.Dispatchers.Default | |
import kotlinx.coroutines.launch | |
import kotlinx.coroutines.withContext | |
@Composable | |
fun Capture( | |
key: Int = currentCompositeKeyHash, | |
transformation: Transformation = NoTransformation, | |
content: @Composable () -> Unit, | |
callback: (Bitmap) -> Unit, | |
) { | |
SubcomposeLayout { constraints -> | |
layout( | |
width = constraints.maxWidth, | |
height = constraints.maxHeight, | |
) { | |
val placeable = subcompose(0) { | |
val context = LocalContext.current | |
val view = remember { | |
ComposeView(context).apply { visibility = INVISIBLE } | |
} | |
LaunchedEffect(view) { | |
val bitmap = withContext(Default) { | |
view.createTransformedBitmap( | |
transformation = transformation, | |
width = constraints.maxWidth, | |
height = constraints.maxHeight, | |
) | |
} | |
callback(bitmap) | |
} | |
AndroidView( | |
factory = { | |
view.apply { setContent(content) } | |
}, | |
) | |
}.single() | |
placeable | |
.measure(constraints) | |
.place( | |
x = 0, | |
y = 0, | |
) | |
} | |
} | |
} | |
private suspend fun View.createTransformedBitmap( | |
transformation: Transformation, | |
width: Int, | |
height: Int, | |
): Bitmap { | |
val bitmap = createBitmap( | |
width = width, | |
height = height, | |
) | |
return transformation.transform( | |
context = context, | |
bitmap = bitmap, | |
) | |
} | |
private fun View.createBitmap( | |
width: Int, | |
height: Int, | |
): Bitmap { | |
return createBitmap( | |
width, | |
height, | |
ARGB_8888, | |
).apply { | |
val canvas = Canvas(this) | |
draw(canvas) | |
} | |
} | |
@Stable | |
interface Transformation { | |
suspend fun transform( | |
context: Context, | |
bitmap: Bitmap, | |
): Bitmap | |
} | |
private object NoTransformation : Transformation { | |
override suspend fun transform( | |
context: Context, | |
bitmap: Bitmap, | |
): Bitmap { | |
return bitmap | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment