1
Fork 0
mirror of https://github.com/Steffo99/twom.git synced 2024-11-21 23:54:26 +00:00

Complete CreateActivityContent

This commit is contained in:
Steffo 2023-12-02 03:26:37 +01:00
parent 6804058474
commit 8d32d17d32
Signed by: steffo
GPG key ID: 2A24051445686895
3 changed files with 118 additions and 80 deletions

View file

@ -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<Uri?>(null) }
var avatarBitmap by remember { mutableStateOf<ImageBitmap?>(null) }
var avatarBitmap by rememberSaveable { mutableStateOf<ImageBitmap?>(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))
}
}
}
}

View file

@ -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
}
}
}

View file

@ -30,4 +30,6 @@
<string name="create_title">Create a new happening</string>
<string name="create_name_label">Name</string>
<string name="create_avatar_label">Select happening avatar</string>
<string name="create_description_label">Description</string>
<string name="create_complete_text">Create</string>
</resources>