Jetpack Compose中Bitmap擦除区域显示黑色而非透明的问题解决
问题:Jetpack Compose中Bitmap擦除像素显示黑色而非透明
我在Jetpack Compose中尝试实现将Bitmap像素擦除为透明色,但加载Bitmap到Canvas时,擦除的像素显示为黑色。以下是我的Composable代码:
@RequiresApi(Build.VERSION_CODES.Q) @Composable fun EraseByHandCanvasContent( modifier: Modifier = Modifier, eraseByHandViewModel: EraseByHandViewModel = koinViewModel() ) { val drawingByHandState = eraseByHandViewModel.drawingByHandState.collectAsState() val bitmap = eraseByHandViewModel.pickedImage.collectAsState() val paint = remember { derivedStateOf { Paint().apply { isAntiAlias = true color = Color.Transparent.toArgb() style = Paint.Style.STROKE strokeWidth = drawingByHandState.value.eraseBrushSize xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) } } } Box( modifier = modifier.fillMaxWidth(), contentAlignment = Alignment.TopCenter, ) { Canvas(modifier = Modifier .fillMaxSize() .onPlaced { layoutCoordinates -> eraseByHandViewModel.setCanvasSize(layoutCoordinates.size) } .pointerInput(Unit) { detectDragGestures( onDrag = { change, _ -> eraseByHandViewModel.onDrawingAction( DrawingByHandAction.onDraw( offset = change.position ) ) change.consume() }, onDragStart = { offset -> eraseByHandViewModel.onDrawingAction( DrawingByHandAction.onNewPathDraw( offset = offset ) ) }, onDragEnd = { eraseByHandViewModel.onDrawingAction( DrawingByHandAction.onPathEnd() ) } ) }) { val currentBitmap = drawingByHandState.value.tempBitmap ?: bitmap.value?.copy(Bitmap.Config.ARGB_8888, true)?.apply { isPremultiplied = true setHasAlpha(true) } currentBitmap?.let { baseBitmap -> val outputBitmap = Bitmap.createScaledBitmap( baseBitmap, size.width.toInt(), size.height.toInt(), false, ) val combinedCanvas = android.graphics.Canvas(outputBitmap) combinedCanvas.drawPath( drawingByHandState.value.currentPath.asAndroidPath(), paint.value, ) eraseByHandViewModel.setTempBitmap(outputBitmap) drawImage( image = outputBitmap.asImageBitmap(), ) } } } }
为了调试,我检查了Bitmap像素,发现countTransparent值始终为0,说明绘制过程存在问题:
private fun countTransparentPixels(bitmap: Bitmap) { var countTransparent = 0 var countNonTransparent = 0 val copyBitmap = bitmap.copy(Bitmap.Config.ARGB_8888,true).apply { setHasAlpha(true) isPremultiplied = true } for (x in 0 until copyBitmap.width) { for (y in 0 until copyBitmap.height) { val pixel = copyBitmap.getPixel(x, y) if (pixel == androidx.compose.ui.graphics.Color.Transparent.toArgb()){ countTransparent++ } else { countNonTransparent++ } } } Log.d("COUNTERS", "$countTransparent---$countNonTransparent") }
我在应用中使用Coil展示Bitmap图片,将擦除后的Bitmap加载到图库时(擦除像素在图库中显示为白色),SubcomposeAsyncImage同样将擦除像素显示为黑色,和EraseByHandCanvasContent组件表现一致。我尝试了Paint对象和drawImage()方法的多种BlendMode组合,但始终无法得到透明Bitmap:
val copyBitmap = selectedImageState.value?.copy(Bitmap.Config.ARGB_8888,true) copyBitmap?.apply { setHasAlpha(true) isPremultiplied = true } SubcomposeAsyncImage( modifier = Modifier .fillMaxWidth() .weight(1f) .clickable { onPickImage() }, model = copyBitmap, contentDescription = "", alignment = Alignment.TopCenter, contentScale = ContentScale.Crop, )
解决方案
找到问题了。如果使用图片裁剪库,需要为裁剪选项设置以下参数:
val cropOption = CropImageContractOptions( uri = uri, cropImageOptions = CropImageOptions( backgroundColor = Color.Transparent.toArgb(), outputCompressFormat = Bitmap.CompressFormat.PNG ) )
编程愉快。
内容的提问来源于stack exchange,提问作者samedhrmn
相关产品推荐
相关产品推荐

