Now library contains simple picker for selection from photo gallery or create photo from camera with system UI.
but for case when we add cameraview on own screen we not have any complete solution. With this reason on one project we already implement logic of photo capturing with:
after photo capturing we save photo to file and pass between screens only path to temporary file with photo, with this class:
expect:
import dev.icerock.moko.media.Bitmap
expect class ImageFile {
fun toBitmap(maxWidthPx: Int? = null, maxHeightPx: Int? = null): Bitmap
}
fun ImageFile.toBitmap(maxDimensionPx: Int): Bitmap = toBitmap(
maxDimensionPx,
maxDimensionPx
)
android actual:
```kotlin
import android.graphics.BitmapFactory
import android.graphics.Matrix
import androidx.exifinterface.media.ExifInterface
import dev.icerock.moko.media.Bitmap
import dev.icerock.moko.parcelize.Parcelable
import dev.icerock.moko.parcelize.Parcelize
import java.io.File
import android.graphics.Bitmap as AndroidBitmap
@Parcelize
actual class ImageFile(
private val path: String
) : Parcelable {
actual fun toBitmap(maxWidthPx: Int?, maxHeightPx: Int?): Bitmap {
val file = File(this.path)
val bitmapOptions: BitmapFactory.Options = readImageSize(file)
val rotationDegrees: Int = readImageRotation(file)
val sampleSize: Int? = calculateSampleSize(maxWidthPx, maxHeightPx, bitmapOptions)
val sampledBitmap: AndroidBitmap = readSampledBitmap(file, sampleSize)
val rotatedBitmap: AndroidBitmap = getRotatedBitmap(rotationDegrees, sampledBitmap)
return Bitmap(rotatedBitmap)
}
private fun getRotatedBitmap(
rotationDegrees: Int,
sampledBitmap: AndroidBitmap
): AndroidBitmap {
return if (rotationDegrees != 0) {
val matrix = Matrix()
matrix.postRotate(rotationDegrees.toFloat())
AndroidBitmap.createBitmap(
sampledBitmap,
0, 0,
sampledBitmap.width, sampledBitmap.height,
matrix,
true
)
} else {
sampledBitmap
}
}
private fun readSampledBitmap(
file: File,
sampleSize: Int?
): AndroidBitmap {
val readingBitmapOptions = BitmapFactory.Options().apply {
inJustDecodeBounds = false
inSampleSize = sampleSize ?: 1
}
return file.inputStream().use { inputStream ->
BitmapFactory.decodeStream(inputStream, null, readingBitmapOptions)
} ?: throw IllegalArgumentException("can't decode file $file with $readingBitmapOptions")
}
private fun calculateSampleSize(
maxWidthPx: Int?,
maxHeightPx: Int?,
bitmapOptions: BitmapFactory.Options
): Int? {
return if (maxWidthPx != null || maxHeightPx != null) {
val widthLimit = maxWidthPx ?: bitmapOptions.outWidth
val heightLimit = maxHeightPx ?: bitmapOptions.outHeight
calculateInSampleSize(
options = bitmapOptions,
maxWidth = widthLimit,
maxHeight = heightLimit
)
} else {
null
}
}
private fun readImageRotation(file: File): Int {
return file.inputStream().use { inputStream ->
ExifInterface(inputStream)
}.rotationDegrees
}
private fun readImageSize(file: File): BitmapFactory.Options {
return file.inputStream().use { inputStream ->
val bitmapOptions = BitmapFactory.Options().apply {
inJustDecodeBounds = true
}
BitmapFactory.decodeStream(inputStream, null, bitmapOptions)
bitmapOptions
}
}
private fun calculateInSampleSize(
options: BitmapFactory.Options,
maxWidth: Int,
maxHeight: Int
): Int {
val (height: Int, width: Int) = options.run { outHeight to outWidth }
var inSampleSize = 1
if (height > maxHeight || width > maxWidth) {
val halfHeight: Int = height / 2
val halfWidth: Int = width / 2
while (halfHeight / inSampleSize >= maxHeight && halfWidth / inSampleSize >= maxWidth) {
inSampleSize *= 2
}
}
return inSampleSize
}
}
ios actual:
import dev.icerock.moko.media.Bitmap
actual class ImageFile(
private val bitmap: Bitmap
) {
actual fun toBitmap(maxWidthPx: Int?, maxHeightPx: Int?): Bitmap {
return bitmap
}
}
in application we can use multiple ImageFile without OutOfMemory on android, because all images just on storage, not in RAM. on iOS now logic with files not implemented (here more available memory for images)...
i think we should have in moko-media out of box solution for this case and allow devs to not think about photo capturing problems.
Now library contains simple picker for selection from photo gallery or create photo from camera with system UI. but for case when we add cameraview on own screen we not have any complete solution. With this reason on one project we already implement logic of photo capturing with:
expect class ImageFile { fun toBitmap(maxWidthPx: Int? = null, maxHeightPx: Int? = null): Bitmap }
fun ImageFile.toBitmap(maxDimensionPx: Int): Bitmap = toBitmap( maxDimensionPx, maxDimensionPx )
ios actual:
ImageFile
without OutOfMemory on android, because all images just on storage, not in RAM. on iOS now logic with files not implemented (here more available memory for images)...i think we should have in moko-media out of box solution for this case and allow devs to not think about photo capturing problems.
also for android i think we can try https://developer.android.com/training/camerax