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 a46a94b..44bc9a1 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 @@ -5,7 +5,7 @@ import android.content.Context import android.content.res.Configuration import android.graphics.Point import android.os.Handler -import android.os.Looper +import android.os.HandlerThread import android.util.Log import android.util.Size import android.view.PixelCopy @@ -25,58 +25,72 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.withContext import android.graphics.Bitmap -import android.graphics.Matrix - -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 ?: Bitmap.Config.ARGB_8888) - - 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 ?: Bitmap.Config.ARGB_8888) - for (y in 0 until height) { - for (x in 0 until width) { - transposedBitmap.setPixel(y, width - 1 - x, getPixel(x, y)) + val srcWidth = width + val srcHeight = height + val sourcePixels = IntArray(srcWidth * srcHeight) + getPixels(sourcePixels, 0, srcWidth, 0, 0, srcWidth, srcHeight) + + val dstWidth = srcHeight + val dstHeight = srcWidth + val destinationPixels = IntArray(dstWidth * dstHeight) + for (y in 0 until srcHeight) { + for (x in 0 until srcWidth) { + val dstX = y + val dstY = srcWidth - 1 - x + destinationPixels[dstY * dstWidth + dstX] = sourcePixels[y * srcWidth + x] } } - transposedBitmap + + val transformedBitmap = Bitmap.createBitmap(dstWidth, dstHeight, config ?: Bitmap.Config.ARGB_8888) + transformedBitmap.setPixels(destinationPixels, 0, dstWidth, 0, 0, dstWidth, dstHeight) + transformedBitmap } Orientation.PORTRAIT_UPSIDE_DOWN -> { - // Invert vertically and horizontally (180-degree rotation) - val invertedBitmap = Bitmap.createBitmap(width, height, config ?: Bitmap.Config.ARGB_8888) - for (y in 0 until height) { - for (x in 0 until width) { - invertedBitmap.setPixel(width - 1 - x, height - 1 - y, getPixel(x, y)) + val srcWidth = width + val srcHeight = height + val sourcePixels = IntArray(srcWidth * srcHeight) + getPixels(sourcePixels, 0, srcWidth, 0, 0, srcWidth, srcHeight) + + val dstWidth = srcWidth + val dstHeight = srcHeight + val destinationPixels = IntArray(dstWidth * dstHeight) + for (y in 0 until srcHeight) { + for (x in 0 until srcWidth) { + val dstX = srcWidth - 1 - x + val dstY = srcHeight - 1 - y + destinationPixels[dstY * dstWidth + dstX] = sourcePixels[y * srcWidth + x] } } - invertedBitmap + + val transformedBitmap = Bitmap.createBitmap(dstWidth, dstHeight, config ?: Bitmap.Config.ARGB_8888) + transformedBitmap.setPixels(destinationPixels, 0, dstWidth, 0, 0, dstWidth, dstHeight) + transformedBitmap } Orientation.LANDSCAPE_RIGHT -> { - // Transpose (swap width and height) and invert vertically - val transposedBitmap = Bitmap.createBitmap(height, width, config ?: Bitmap.Config.ARGB_8888) - for (y in 0 until height) { - for (x in 0 until width) { - transposedBitmap.setPixel(height - 1 - y, x, getPixel(x, y)) + val srcWidth = width + val srcHeight = height + val sourcePixels = IntArray(srcWidth * srcHeight) + getPixels(sourcePixels, 0, srcWidth, 0, 0, srcWidth, srcHeight) + + val dstWidth = srcHeight + val dstHeight = srcWidth + val destinationPixels = IntArray(dstWidth * dstHeight) + for (y in 0 until srcHeight) { + for (x in 0 until srcWidth) { + val dstX = srcHeight - 1 - y + val dstY = x + destinationPixels[dstY * dstWidth + dstX] = sourcePixels[y * srcWidth + x] } } - transposedBitmap + + val transformedBitmap = Bitmap.createBitmap(dstWidth, dstHeight, config ?: Bitmap.Config.ARGB_8888) + transformedBitmap.setPixels(destinationPixels, 0, dstWidth, 0, 0, dstWidth, dstHeight) + transformedBitmap } } } @@ -186,7 +200,7 @@ class PreviewView(context: Context, callback: SurfaceHolder.Callback) : ) } }, - Handler(Looper.getMainLooper()) + pixelCopyHandler ) } } @@ -256,5 +270,10 @@ class PreviewView(context: Context, callback: SurfaceHolder.Callback) : companion object { private const val TAG = "PreviewView" + private val pixelCopyHandler: Handler by lazy { + val handlerThread = HandlerThread("VisionCamera.PixelCopy") + handlerThread.start() + Handler(handlerThread.looper) + } } }