diff --git a/app/src/main/java/eu/steffo/twom/create/CreateActivityContent.kt b/app/src/main/java/eu/steffo/twom/create/CreateActivityContent.kt index 1b32314..2ab440c 100644 --- a/app/src/main/java/eu/steffo/twom/create/CreateActivityContent.kt +++ b/app/src/main/java/eu/steffo/twom/create/CreateActivityContent.kt @@ -1,8 +1,5 @@ package eu.steffo.twom.create -import android.graphics.Bitmap -import android.graphics.BitmapFactory -import android.graphics.Matrix import android.net.Uri import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.PickVisualMediaRequest @@ -15,13 +12,13 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextField import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier @@ -34,7 +31,6 @@ import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.exifinterface.media.ExifInterface import eu.steffo.twom.R import eu.steffo.twom.matrix.avatar.AvatarFromBitmap import eu.steffo.twom.theme.TwoMPadding @@ -43,91 +39,21 @@ import eu.steffo.twom.theme.TwoMPadding @Preview fun CreateActivityContent( modifier: Modifier = Modifier, + onClickCreate: () -> Unit = {}, ) { val context = LocalContext.current var name by rememberSaveable { mutableStateOf("") } + var description by rememberSaveable { mutableStateOf("") } var avatarUri by rememberSaveable { mutableStateOf(null) } - var avatarBitmap by remember { mutableStateOf(null) } + var avatarBitmap by rememberSaveable { mutableStateOf(null) } // val avatarBitmap = if(avatarUri != null) BitmapFactory.decodeFile(avatarUri.toString()).asImageBitmap() else null val avatarSelectLauncher = rememberLauncherForActivityResult(ActivityResultContracts.PickVisualMedia()) { avatarUri = it - if (it == null) { - avatarBitmap = null - } else { - // Open two streams... - // One to read the EXIF metadata from: - val exifStream = context.contentResolver.openInputStream(it) - // One to read the image data itself from: - val bitmapStream = context.contentResolver.openInputStream(it) - - if (exifStream != null && bitmapStream != null) { - // Use the EXIF metadata to determine the orientation of the image - val exifInterface = ExifInterface(exifStream) - val orientation = - exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1) - exifStream.close() - - // Parse the image data as-is - val originalBitmap = BitmapFactory.decodeStream(bitmapStream) - bitmapStream.close() - - // Determine the starting points and the size to crop the image to a 1:1 square - val xStart: Int - val yStart: Int - val size: Int - if (originalBitmap.width > originalBitmap.height) { - yStart = 0 - xStart = (originalBitmap.width - originalBitmap.height) / 2 - size = originalBitmap.height - } else { - xStart = 0 - yStart = (originalBitmap.height - originalBitmap.width) / 2 - size = originalBitmap.width - } - - // Create a transformation matrix to rotate the bitmap based on the orientation - val transformationMatrix: Matrix = Matrix() - - // TODO: Make sure these transformations are valid - when (orientation) { - ExifInterface.ORIENTATION_FLIP_HORIZONTAL -> transformationMatrix.postScale( - -1f, - 1f - ) - - ExifInterface.ORIENTATION_ROTATE_180 -> transformationMatrix.postRotate(180f) - ExifInterface.ORIENTATION_FLIP_VERTICAL -> transformationMatrix.postScale( - 1f, - -1f - ) - - ExifInterface.ORIENTATION_TRANSPOSE -> {/* TODO: Transpose the image Matrix */ - } - - ExifInterface.ORIENTATION_ROTATE_90 -> transformationMatrix.postRotate(90f) - ExifInterface.ORIENTATION_TRANSVERSE -> {/* TODO: Flip horizontally the image Matrix, then transpose it */ - } - - ExifInterface.ORIENTATION_ROTATE_270 -> transformationMatrix.postRotate(270f) - } - - // Crop the bitmap - val croppedBitmap = Bitmap.createBitmap( - originalBitmap, - xStart, - yStart, - size, - size, - transformationMatrix, - true - ) - - avatarBitmap = croppedBitmap.asImageBitmap() - } - } + avatarBitmap = if (it != null) ImageHandler.uriToBitmap(context.contentResolver, it) + ?.asImageBitmap() else null } Column(modifier) { @@ -161,5 +87,28 @@ fun CreateActivityContent( onValueChange = { name = it } ) } + + Row(TwoMPadding.base) { + TextField( + modifier = Modifier + .height(180.dp) + .fillMaxWidth(), + label = { + Text(stringResource(R.string.create_description_label)) + }, + value = description, + onValueChange = { description = it } + ) + } + + Row(TwoMPadding.base) { + Button( + modifier = Modifier + .fillMaxWidth(), + onClick = onClickCreate, + ) { + Text(stringResource(R.string.create_complete_text)) + } + } } } \ No newline at end of file diff --git a/app/src/main/java/eu/steffo/twom/create/ImageHandler.kt b/app/src/main/java/eu/steffo/twom/create/ImageHandler.kt new file mode 100644 index 0000000..ab9c77a --- /dev/null +++ b/app/src/main/java/eu/steffo/twom/create/ImageHandler.kt @@ -0,0 +1,87 @@ +package eu.steffo.twom.create + +import android.content.ContentResolver +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.Matrix +import android.net.Uri +import androidx.exifinterface.media.ExifInterface + +class ImageHandler { + companion object { + fun uriToBitmap(contentResolver: ContentResolver, uri: Uri): Bitmap? { + // Open two streams... + // One to read the EXIF metadata from: + val exifStream = contentResolver.openInputStream(uri) + // One to read the image data itself from: + val bitmapStream = contentResolver.openInputStream(uri) + + if (exifStream == null || bitmapStream == null) { + return null + } + + // Use the EXIF metadata to determine the orientation of the image + val exifInterface = ExifInterface(exifStream) + val orientation = + exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1) + exifStream.close() + + // Parse the image data as-is + val originalBitmap = BitmapFactory.decodeStream(bitmapStream) + bitmapStream.close() + + // Determine the starting points and the size to crop the image to a 1:1 square + val xStart: Int + val yStart: Int + val size: Int + if (originalBitmap.width > originalBitmap.height) { + yStart = 0 + xStart = (originalBitmap.width - originalBitmap.height) / 2 + size = originalBitmap.height + } else { + xStart = 0 + yStart = (originalBitmap.height - originalBitmap.width) / 2 + size = originalBitmap.width + } + + // Create a transformation matrix to rotate the bitmap based on the orientation + val transformationMatrix = Matrix() + + // TODO: Make sure these transformations are valid + when (orientation) { + ExifInterface.ORIENTATION_FLIP_HORIZONTAL -> transformationMatrix.postScale( + -1f, + 1f + ) + + ExifInterface.ORIENTATION_ROTATE_180 -> transformationMatrix.postRotate(180f) + ExifInterface.ORIENTATION_FLIP_VERTICAL -> transformationMatrix.postScale( + 1f, + -1f + ) + + ExifInterface.ORIENTATION_TRANSPOSE -> {/* TODO: Transpose the image Matrix */ + } + + ExifInterface.ORIENTATION_ROTATE_90 -> transformationMatrix.postRotate(90f) + ExifInterface.ORIENTATION_TRANSVERSE -> {/* TODO: Flip horizontally the image Matrix, then transpose it */ + } + + ExifInterface.ORIENTATION_ROTATE_270 -> transformationMatrix.postRotate(270f) + } + + // Crop the bitmap + val croppedBitmap = Bitmap.createBitmap( + originalBitmap, + xStart, + yStart, + size, + size, + transformationMatrix, + true + ) + + return croppedBitmap + } + } +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 46a9ea2..fb51129 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -30,4 +30,6 @@ Create a new happening Name Select happening avatar + Description + Create \ No newline at end of file