• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2025 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.jetpackcamera.feature.preview.ui
17 
18 import android.graphics.RectF
19 import android.net.Uri
20 import androidx.compose.animation.AnimatedContent
21 import androidx.compose.foundation.Canvas
22 import androidx.compose.foundation.border
23 import androidx.compose.foundation.clickable
24 import androidx.compose.foundation.layout.Box
25 import androidx.compose.foundation.layout.padding
26 import androidx.compose.foundation.layout.size
27 import androidx.compose.foundation.shape.RoundedCornerShape
28 import androidx.compose.runtime.Composable
29 import androidx.compose.ui.Modifier
30 import androidx.compose.ui.draw.clip
31 import androidx.compose.ui.graphics.Color
32 import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
33 import androidx.compose.ui.graphics.nativeCanvas
34 import androidx.compose.ui.platform.LocalContext
35 import androidx.compose.ui.unit.dp
36 import com.google.jetpackcamera.core.common.loadAndRotateBitmap
37 import kotlin.math.min
38 
39 @Composable
40 fun ImageWell(
41     modifier: Modifier = Modifier,
42     imageWellUiState: ImageWellUiState = ImageWellUiState.NoPreviousCapture,
43     onClick: (uri: Uri?) -> Unit
44 ) {
45     val context = LocalContext.current
46 
47     when (imageWellUiState) {
48         is ImageWellUiState.LastCapture -> {
49             val bitmap = loadAndRotateBitmap(context, imageWellUiState.uri, 270f)
50 
51             bitmap?.let {
52                 Box(
53                     modifier = modifier
54                         .size(120.dp)
55                         .padding(18.dp)
56                         .border(2.dp, Color.White, RoundedCornerShape(16.dp))
57                         .clip(RoundedCornerShape(16.dp))
58                         .clickable(onClick = { onClick(imageWellUiState.uri) })
59                 ) {
60                     AnimatedContent(
61                         targetState = bitmap
62                     ) { targetBitmap ->
63                         Canvas(
64                             modifier = Modifier
65                                 .size(110.dp)
66                         ) {
67                             drawIntoCanvas { canvas ->
68                                 val canvasSize = min(size.width, size.height)
69 
70                                 val scale = canvasSize / min(
71                                     targetBitmap.width,
72                                     targetBitmap.height
73                                 )
74 
75                                 val imageWidth = targetBitmap.width * scale
76                                 val imageHeight = targetBitmap.height * scale
77 
78                                 val offsetX = (canvasSize - imageWidth) / 2f
79                                 val offsetY = (canvasSize - imageHeight) / 2f
80 
81                                 canvas.nativeCanvas.drawBitmap(
82                                     targetBitmap,
83                                     null,
84                                     RectF(
85                                         offsetX,
86                                         offsetY,
87                                         offsetX + imageWidth,
88                                         offsetY + imageHeight
89                                     ),
90                                     null
91                                 )
92                             }
93                         }
94                     }
95                 }
96             }
97         }
98 
99         is ImageWellUiState.NoPreviousCapture -> {
100         }
101     }
102 }
103 
104 // TODO(yasith): Add support for Video
105 sealed interface ImageWellUiState {
106     data object NoPreviousCapture : ImageWellUiState
107 
108     data class LastCapture(val uri: Uri) : ImageWellUiState
109 }
110