Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

On draw crash workaround #10

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.idea/
.DS_Store
/build
/captures
Expand Down
3 changes: 0 additions & 3 deletions .idea/.gitignore

This file was deleted.

74 changes: 0 additions & 74 deletions .idea/androidTestResultsUserPreferences.xml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/compiler.xml

This file was deleted.

21 changes: 0 additions & 21 deletions .idea/gradle.xml

This file was deleted.

37 changes: 0 additions & 37 deletions .idea/inspectionProfiles/Project_Default.xml

This file was deleted.

10 changes: 0 additions & 10 deletions .idea/misc.xml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/vcs.xml

This file was deleted.

4 changes: 2 additions & 2 deletions easycrop/src/main/java/com/mr0xf00/easycrop/CropState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ internal fun CropState(
): CropState = object : CropState {
val defaultTransform: ImgTransform = ImgTransform.Identity
val defaultShape: CropShape = RectCropShape
val defaultAspectLock: Boolean = false
val defaultAspectLock: Boolean = true
override val src: ImageSrc get() = src
private var _transform: ImgTransform by mutableStateOf(defaultTransform)
override var transform: ImgTransform
Expand All @@ -43,7 +43,7 @@ internal fun CropState(
_transform = value
}

val defaultRegion = src.size.toSize().toRect()
val defaultRegion = src.size.toSize().toRect().setAspect(AspectRatio(1, 1))

private var _region by mutableStateOf(defaultRegion)
override var region
Expand Down
54 changes: 27 additions & 27 deletions easycrop/src/main/java/com/mr0xf00/easycrop/ui/Controls.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,33 +51,33 @@ internal fun CropperControls(
IconButton(onClick = { state.flipVertical() }) {
Icon(painterResource(id = R.drawable.flip_ver), null)
}
Box {
var menu by remember { mutableStateOf(false) }
IconButton(onClick = { menu = !menu }) {
Icon(painterResource(id = R.drawable.resize), null)
}
if (menu) AspectSelectionMenu(
onDismiss = { menu = false },
region = state.region,
onRegion = { state.region = it },
lock = state.aspectLock,
onLock = { state.aspectLock = it }
)
}
LocalCropperStyle.current.shapes?.let { shapes ->
Box {
var menu by remember { mutableStateOf(false) }
IconButton(onClick = { menu = !menu }) {
Icon(Icons.Default.Star, null)
}
if (menu) ShapeSelectionMenu(
onDismiss = { menu = false },
selected = state.shape,
onSelect = { state.shape = it },
shapes = shapes
)
}
}
// Box {
// var menu by remember { mutableStateOf(false) }
// IconButton(onClick = { menu = !menu }) {
// Icon(painterResource(id = R.drawable.resize), null)
// }
// if (menu) AspectSelectionMenu(
// onDismiss = { menu = false },
// region = state.region,
// onRegion = { state.region = it },
// lock = state.aspectLock,
// onLock = { state.aspectLock = it }
// )
// }
// LocalCropperStyle.current.shapes?.let { shapes ->
// Box {
// var menu by remember { mutableStateOf(false) }
// IconButton(onClick = { menu = !menu }) {
// Icon(Icons.Default.Star, null)
// }
// if (menu) ShapeSelectionMenu(
// onDismiss = { menu = false },
// selected = state.shape,
// onSelect = { state.shape = it },
// shapes = shapes
// )
// }
// }
}
}
}
Expand Down
16 changes: 11 additions & 5 deletions easycrop/src/main/java/com/mr0xf00/easycrop/ui/CropperPreview.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ import kotlinx.coroutines.delay
@Composable
fun CropperPreview(
state: CropState,
modifier: Modifier = Modifier
modifier: Modifier = Modifier,
onDrawingError: (Exception) -> Unit
) {
val style = LocalCropperStyle.current
val imgTransform by animateImgTransform(target = state.transform)
Expand Down Expand Up @@ -58,10 +59,15 @@ fun CropperPreview(
) {
withTransform({ transform(totalMat) }) {
image?.let { (params, bitmap) ->
drawImage(
bitmap, dstOffset = params.subset.topLeft,
dstSize = params.subset.size
)
try {
drawImage(
bitmap, dstOffset = params.subset.topLeft,
dstSize = params.subset.size
)
} catch (e: Exception) {
state.done(false)
onDrawingError(e)
}
}
}
with(style) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.painterResource
Expand All @@ -27,7 +28,7 @@ import com.mr0xf00.easycrop.R

private val CropperDialogProperties = @OptIn(ExperimentalComposeUiApi::class) (DialogProperties(
usePlatformDefaultWidth = false,
dismissOnBackPress = false,
dismissOnBackPress = true,
dismissOnClickOutside = false
))

Expand All @@ -38,6 +39,7 @@ fun ImageCropperDialog(
dialogProperties: DialogProperties = CropperDialogProperties,
dialogPadding: PaddingValues = PaddingValues(16.dp),
dialogShape: Shape = RoundedCornerShape(8.dp),
onDrawingError: (Exception) -> Unit,
topBar: @Composable (CropState) -> Unit = { DefaultTopBar(it) },
cropControls: @Composable BoxScope.(CropState) -> Unit = { DefaultControls(it) }
) {
Expand All @@ -57,7 +59,11 @@ fun ImageCropperDialog(
.weight(1f)
.clipToBounds()
) {
CropperPreview(state = state, modifier = Modifier.fillMaxSize())
CropperPreview(
state = state,
modifier = Modifier.fillMaxSize(),
onDrawingError = onDrawingError
)
cropControls(state)
}
}
Expand All @@ -84,16 +90,29 @@ private fun DefaultTopBar(state: CropState) {
TopAppBar(title = {},
navigationIcon = {
IconButton(onClick = { state.done(accept = false) }) {
Icon(Icons.Default.ArrowBack, null)
Icon(
imageVector = Icons.Default.ArrowBack,
tint = Color.White,
contentDescription = null
)
}
},
actions = {
IconButton(onClick = { state.reset() }) {
Icon(painterResource(R.drawable.restore), null)
Icon(
painter = painterResource(R.drawable.restore),
tint = Color.White,
contentDescription = null
)
}
IconButton(onClick = { state.done(accept = true) }, enabled = !state.accepted) {
Icon(Icons.Default.Done, null)
Icon(
imageVector = Icons.Default.Done,
tint = Color.White,
contentDescription = null
)
}
}
},
backgroundColor = Color(0xFF202020)
)
}
5 changes: 4 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ kotlin.code.style=official
android.nonTransitiveRClass=true

composeBomVersion=2023.01.00
composeCompilerVersion=1.4.0
composeCompilerVersion=1.4.0

ossrh.user=dummy
ossrh.pass=dummy
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.mr0xf00.easycrop.presentation

import android.app.Application
import android.graphics.BitmapFactory
import android.net.Uri
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.mr0xf00.easycrop.CropError
Expand All @@ -26,7 +28,11 @@ class ImagesViewModel(private val app: Application) : AndroidViewModel(app) {

fun setSelectedImage(uri: Uri) {
viewModelScope.launch {
when(val result = imageCropper.crop(uri, app)) {

val bitmap = app.contentResolver.openInputStream(uri).use { inputStream ->
BitmapFactory.decodeStream(inputStream)
}
when(val result = imageCropper.crop(bmp = bitmap.asImageBitmap())) {
CropResult.Cancelled -> {}
is CropError -> _cropError.value = result
is CropResult.Success -> {
Expand Down
Loading