diff --git a/.gitignore b/.gitignore
index aa724b7..87f66f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 26d3352..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/.idea/androidTestResultsUserPreferences.xml b/.idea/androidTestResultsUserPreferences.xml
deleted file mode 100644
index b9e23ad..0000000
--- a/.idea/androidTestResultsUserPreferences.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index fb7f4a8..0000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
deleted file mode 100644
index 8a7298b..0000000
--- a/.idea/gradle.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index ed76bea..0000000
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index bdd9278..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/easycrop/src/main/java/com/mr0xf00/easycrop/CropState.kt b/easycrop/src/main/java/com/mr0xf00/easycrop/CropState.kt
index 9726e1f..f0cfd17 100644
--- a/easycrop/src/main/java/com/mr0xf00/easycrop/CropState.kt
+++ b/easycrop/src/main/java/com/mr0xf00/easycrop/CropState.kt
@@ -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
@@ -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
diff --git a/easycrop/src/main/java/com/mr0xf00/easycrop/ui/Controls.kt b/easycrop/src/main/java/com/mr0xf00/easycrop/ui/Controls.kt
index 97d73fc..4f04eb9 100644
--- a/easycrop/src/main/java/com/mr0xf00/easycrop/ui/Controls.kt
+++ b/easycrop/src/main/java/com/mr0xf00/easycrop/ui/Controls.kt
@@ -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
+// )
+// }
+// }
}
}
}
diff --git a/easycrop/src/main/java/com/mr0xf00/easycrop/ui/CropperPreview.kt b/easycrop/src/main/java/com/mr0xf00/easycrop/ui/CropperPreview.kt
index 310f236..02d1deb 100644
--- a/easycrop/src/main/java/com/mr0xf00/easycrop/ui/CropperPreview.kt
+++ b/easycrop/src/main/java/com/mr0xf00/easycrop/ui/CropperPreview.kt
@@ -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)
@@ -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) {
diff --git a/easycrop/src/main/java/com/mr0xf00/easycrop/ui/ImageCropperDialog.kt b/easycrop/src/main/java/com/mr0xf00/easycrop/ui/ImageCropperDialog.kt
index 8ee9ab1..64de358 100644
--- a/easycrop/src/main/java/com/mr0xf00/easycrop/ui/ImageCropperDialog.kt
+++ b/easycrop/src/main/java/com/mr0xf00/easycrop/ui/ImageCropperDialog.kt
@@ -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
@@ -27,7 +28,7 @@ import com.mr0xf00.easycrop.R
private val CropperDialogProperties = @OptIn(ExperimentalComposeUiApi::class) (DialogProperties(
usePlatformDefaultWidth = false,
- dismissOnBackPress = false,
+ dismissOnBackPress = true,
dismissOnClickOutside = false
))
@@ -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) }
) {
@@ -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)
}
}
@@ -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)
)
}
diff --git a/gradle.properties b/gradle.properties
index 728a09c..00bdf35 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -4,4 +4,7 @@ kotlin.code.style=official
android.nonTransitiveRClass=true
composeBomVersion=2023.01.00
-composeCompilerVersion=1.4.0
\ No newline at end of file
+composeCompilerVersion=1.4.0
+
+ossrh.user=dummy
+ossrh.pass=dummy
\ No newline at end of file
diff --git a/sample/src/main/java/com/mr0xf00/easycrop/presentation/ImagesViewModel.kt b/sample/src/main/java/com/mr0xf00/easycrop/presentation/ImagesViewModel.kt
index e24d525..3e2133a 100644
--- a/sample/src/main/java/com/mr0xf00/easycrop/presentation/ImagesViewModel.kt
+++ b/sample/src/main/java/com/mr0xf00/easycrop/presentation/ImagesViewModel.kt
@@ -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
@@ -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 -> {
diff --git a/sample/src/main/java/com/mr0xf00/easycrop/ui/DemoContent.kt b/sample/src/main/java/com/mr0xf00/easycrop/ui/DemoContent.kt
index a239a18..f3b4b50 100644
--- a/sample/src/main/java/com/mr0xf00/easycrop/ui/DemoContent.kt
+++ b/sample/src/main/java/com/mr0xf00/easycrop/ui/DemoContent.kt
@@ -17,11 +17,12 @@ fun DemoContent(
loadingStatus: CropperLoading?,
selectedImage: ImageBitmap?,
onPick: () -> Unit,
+ onDrawingError: (Exception) -> Unit,
modifier: Modifier = Modifier,
) {
if (cropState != null) {
EasyCropTheme(darkTheme = true) {
- ImageCropperDialog(state = cropState)
+ ImageCropperDialog(state = cropState, onDrawingError = onDrawingError)
}
}
if (cropState == null && loadingStatus != null) {
diff --git a/sample/src/main/java/com/mr0xf00/easycrop/ui/SimpleDemo.kt b/sample/src/main/java/com/mr0xf00/easycrop/ui/SimpleDemo.kt
index 2ea67b7..0a95bb2 100644
--- a/sample/src/main/java/com/mr0xf00/easycrop/ui/SimpleDemo.kt
+++ b/sample/src/main/java/com/mr0xf00/easycrop/ui/SimpleDemo.kt
@@ -28,6 +28,7 @@ fun SimpleDemo(modifier: Modifier = Modifier) {
cropState = imageCropper.cropState,
loadingStatus = imageCropper.loadingStatus,
selectedImage = selectedImage,
+ onDrawingError = {},
onPick = { imagePicker.pick() },
modifier = modifier
)
diff --git a/sample/src/main/java/com/mr0xf00/easycrop/ui/ViewModelDemo.kt b/sample/src/main/java/com/mr0xf00/easycrop/ui/ViewModelDemo.kt
index 23a4675..0c3e8c9 100644
--- a/sample/src/main/java/com/mr0xf00/easycrop/ui/ViewModelDemo.kt
+++ b/sample/src/main/java/com/mr0xf00/easycrop/ui/ViewModelDemo.kt
@@ -7,12 +7,17 @@ import com.mr0xf00.easycrop.rememberImagePicker
@Composable
fun ViewModelDemo(viewModel: ImagesViewModel, modifier: Modifier = Modifier) {
- val imagePicker = rememberImagePicker(onImage = { uri -> viewModel.setSelectedImage(uri) })
+ val imagePicker = rememberImagePicker(onImage = { uri ->
+ viewModel.setSelectedImage(uri)
+ })
DemoContent(
cropState = viewModel.imageCropper.cropState,
loadingStatus = viewModel.imageCropper.loadingStatus,
selectedImage = viewModel.selectedImage.collectAsState().value,
onPick = { imagePicker.pick() },
+ onDrawingError = {
+
+ },
modifier = modifier
)
viewModel.cropError.collectAsState().value?.let { error ->
diff --git a/settings.gradle b/settings.gradle
index c7bb7c8..15c1275 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -12,6 +12,7 @@ dependencyResolutionManagement {
mavenCentral()
}
}
-rootProject.name = "EasyCrop"
+rootProject.name = "easy-crop"
+
include ':sample'
include ':easycrop'