Reputation: 1048
In the view World we can just use View.draw(canvas) to draw view on our Canvas (which might be connected to bitmap). But here in compose how can we achieve the same.
We have a draw modifier but it has no method draw(canvas)
Update
I wanted to blur a composable function by wrapping it inside a Blur Composable. Suppose xyz() is any random composabel function.
@Composable
fun xyz(){
// compose logic.
}
I want to create another fun called Blur().
@Composable
fun Blur(content: @Composable() -> Unit){
//Blur logic.
}
The Blur composable takes any composable function (say xyz()) as input and Blurs it.
I thought I would take the same approach which the BlurView (A view blur library) takes.
view.draw(canvas: Canvas)
I thought of creating my version of BlurView in compose. I know in compose there is a Modifier.blur; but since this is only supported in api 31( I guess) so I can't use it in my project.
Upvotes: 2
Views: 856
Reputation: 67313
If you want to have a Bitmap
that has been blurred from your View function or methods like RenderScript mentioned here, and draw landmarks or shapes on it you can use
androidx.compose.ui.graphics.Canvas
instead of androidx.compose.foundation.Canvas
val option = BitmapFactory.Options()
option.apply {
inPreferredConfig = Bitmap.Config.ARGB_8888
inMutable = true
}
val imageBitmap = RenderEffect.createBitmapEffect(Bitmap bitmap)
for api 31-
private Bitmap blur(Bitmap original, float radius) {
Bitmap bitmap = Bitmap.createBitmap(
original.getWidth(), original.getHeight(),
Bitmap.Config.ARGB_8888);
RenderScript rs = RenderScript.create(this);
Allocation allocIn = Allocation.createFromBitmap(rs, original);
Allocation allocOut = Allocation.createFromBitmap(rs, bitmap);
ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(
rs, Element.U8_4(rs));
blur.setInput(allocIn);
blur.setRadius(radius);
blur.forEach(allocOut);
allocOut.copyTo(bitmap);
rs.destroy();
return bitmap;
}
I'm not on my PC at the moment, when i'm available i will add it as modifier.
// 🔥 This is a function that returns Canvas which can be used to draw on an
// ImageBitmap that was sent as param. ImageBitmap that returned can be
// be used to display on Image or can be saved to a physical file.
val canvas: androidx.compose.ui.graphics.Canvas = Canvas(imageBitmap)
val paint = remember {
Paint().apply {
style = PaintingStyle.Stroke
strokeWidth = 10f
color = Color(0xff29B6F6)
}
}
canvas.drawRect(0f, 0f, 200f, 200f, paint = paint)
canvas.drawCircle(
Offset(
imageBitmap.width / 2 - 75f,
imageBitmap.height / 2 + 75f
), 150.0f, paint
)
// This bitmap has image and the drawing from canvas
Image(bitmap = imageBitmap, contentDescription = null)
Upvotes: 0
Reputation: 1937
As noted in another reply you can create a composable that uses a canvas and this will give you access to many of the same drawing methods you have in a regular View canvas.
@Composable
fun MyCanvasComposable(
data: List<Int>, //some example data to pass in
modifier: Modifier = Modifier
) {
Canvas() {
.. content here
}
}
Within the canvas you will be inside a DrawScope, which will allow you to do the canvas drawing as previous.
I'll add some examples assuming we're pulling the drawing logic into extension methods.Examples:
Drawing some Text
internal fun DrawScope.drawSomeText() {
//some logic here before drawing the text
drawContext.canvas.nativeCanvas.drawText(
[[your text]],
positionX,
positionY,
paint
)
}
Drawing a Path
internal fun DrawScope.plotXAxis(
//some custom rendering here followed by this method
drawPath(path, pathBrush, 0.5f)
}
In order to put your canvas on another layout you would call MyCanvasComposable with whatever layout modifiers are appropriate.
If you're trying to render other composables on top of the canvas the way you would do that is to just wrap the whole thing in a box and add the views before or after the canvas draw.
Example:
val myPainter = painterResource(id = R.drawable.src_image)
Box {
Image(
painter = myPainter
)
Canvas() {
.. content here ..
}
Text( "some text")
}
In the above example you could also just call MyCanvasComposable instead of Canvas().
Note also Image will render before the canvas and Text will render after, which is to say on top of the canvas.Upvotes: 0
Reputation: 214
In Compose
there is a Canvas composable function available with DrawScope
.
You can make use of that to draw.
DrawScope has drawImage
function to take ImageBitmap.
As you have Bitmap need to convert that using Bitmap.asImageBitmap()
Upvotes: 2