diff --git a/package/android/src/main/java/com/mrousavy/camera/core/PreviewView.kt b/package/android/src/main/java/com/mrousavy/camera/core/PreviewView.kt index 8e8f7f5..aecdafc 100644 --- a/package/android/src/main/java/com/mrousavy/camera/core/PreviewView.kt +++ b/package/android/src/main/java/com/mrousavy/camera/core/PreviewView.kt @@ -25,9 +25,58 @@ import kotlinx.coroutines.withContext import android.graphics.Bitmap import android.graphics.Matrix -fun Bitmap.rotateBitmap(degrees: Float): Bitmap { - val matrix = android.graphics.Matrix().apply { postRotate(degrees) } - return Bitmap.createBitmap(this, 0, 0, width, height, matrix, true) +fun rotateBitmap90CounterClockwise(source: Bitmap): Bitmap { + val width = source.width + val height = source.height + + // Create a new Bitmap with swapped width and height + val rotatedBitmap = Bitmap.createBitmap(height, width, source.config) + + for (y in 0 until height) { + for (x in 0 until width) { + // Set the pixel in the new position + rotatedBitmap.setPixel(y, width - 1 - x, source.getPixel(x, y)) + } + } + + return rotatedBitmap +} + + +fun Bitmap.transformBitmap(orientation: Orientation): Bitmap { + return when (orientation) { + Orientation.PORTRAIT -> this // No transformation needed + Orientation.LANDSCAPE_LEFT -> { + // Transpose (swap width and height) + val transposedBitmap = Bitmap.createBitmap(height, width, config) + for (y in 0 until height) { + for (x in 0 until width) { + transposedBitmap.setPixel(y, width - 1 - x, getPixel(x, y)) + } + } + transposedBitmap + } + Orientation.PORTRAIT_UPSIDE_DOWN -> { + // Invert vertically and horizontally (180-degree rotation) + val invertedBitmap = Bitmap.createBitmap(width, height, config) + for (y in 0 until height) { + for (x in 0 until width) { + invertedBitmap.setPixel(width - 1 - x, height - 1 - y, getPixel(x, y)) + } + } + invertedBitmap + } + Orientation.LANDSCAPE_RIGHT -> { + // Transpose (swap width and height) and invert vertically + val transposedBitmap = Bitmap.createBitmap(height, width, config) + for (y in 0 until height) { + for (x in 0 until width) { + transposedBitmap.setPixel(height - 1 - y, x, getPixel(x, y)) + } + } + transposedBitmap + } + } } @@ -97,10 +146,11 @@ class PreviewView(context: Context, callback: SurfaceHolder.Callback) : suspend fun getBitmap(): Bitmap? = withContext(Dispatchers.Main) { val frame = holder.getSurfaceFrame() + val width = frame.width() val height = frame.height() - val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) + val bitmap = Bitmap.createBitmap(height, width, Bitmap.Config.ARGB_8888) // Use a coroutine to suspend until the PixelCopy request is complete suspendCancellableCoroutine { continuation -> @@ -109,9 +159,7 @@ class PreviewView(context: Context, callback: SurfaceHolder.Callback) : bitmap, { copyResult -> if (copyResult == PixelCopy.SUCCESS) { - val rotationDegrees = inputOrientation.toDegrees().toFloat() - val rotatedBitmap = bitmap.rotateBitmap(rotationDegrees) - continuation.resume(bitmap) + continuation.resume(rotateBitmap90CounterClockwise(bitmap)) } else { continuation.resumeWithException( RuntimeException("PixelCopy failed with error code $copyResult") @@ -120,7 +168,7 @@ class PreviewView(context: Context, callback: SurfaceHolder.Callback) : }, Handler(Looper.getMainLooper()) ) - } + } } diff --git a/package/android/src/main/java/com/mrousavy/camera/utils/FileUtils.kt b/package/android/src/main/java/com/mrousavy/camera/utils/FileUtils.kt index 667ce9d..0b46475 100644 --- a/package/android/src/main/java/com/mrousavy/camera/utils/FileUtils.kt +++ b/package/android/src/main/java/com/mrousavy/camera/utils/FileUtils.kt @@ -11,7 +11,7 @@ class FileUtils { companion object { fun writeBitmapTofile(bitmap: Bitmap, file: File, quality: Int) { FileOutputStream(file).use { stream -> - bitmap.compress(Bitmap.CompressFormat.PNG, quality, stream) + bitmap.compress(Bitmap.CompressFormat.JPEG, 50, stream) } }