Skip to content

Commit 12445ee

Browse files
committed
Implement Outpainted / Generative Expand to Imagen Editing Sample
1 parent 7b1d972 commit 12445ee

File tree

8 files changed

+113
-259
lines changed

8 files changed

+113
-259
lines changed

ai-catalog/app/src/main/res/values/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<string name="open_sample_button">Open sample</string>
1515
<string name="imagen_sample_title">Image generation with Imagen</string>
1616
<string name="imagen_sample_description">Generate images with Imagen, Google image generation model</string>
17-
<string name="imagen_editing_sample_title">Imagen Editing using Inpainting</string>
17+
<string name="imagen_editing_sample_title">Inpainting &amp; Outpainting with Imagen</string>
1818
<string name="imagen_editing_sample_description">Generate images and edit only specific areas of a generated image with Inpainting</string>
1919
<string name="magic_selfie_sample_title">Magic Selfie with Imagen and ML Kit</string>
2020
<string name="magic_selfie_sample_description">Change the background of your selfies with Imagen and the ML Kit Segmentation API</string>

ai-catalog/samples/imagen-editing/src/main/java/com/android/ai/samples/imagenediting/data/ImagenEditingDataSource.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,17 @@ package com.android.ai.samples.imagenediting.data
1818
import android.graphics.Bitmap
1919
import com.google.firebase.Firebase
2020
import com.google.firebase.ai.ai
21+
import com.google.firebase.ai.type.Dimensions
2122
import com.google.firebase.ai.type.GenerativeBackend
2223
import com.google.firebase.ai.type.ImagenAspectRatio
2324
import com.google.firebase.ai.type.ImagenEditMode
2425
import com.google.firebase.ai.type.ImagenEditingConfig
2526
import com.google.firebase.ai.type.ImagenGenerationConfig
2627
import com.google.firebase.ai.type.ImagenImageFormat
28+
import com.google.firebase.ai.type.ImagenMaskReference
2729
import com.google.firebase.ai.type.ImagenRawImage
2830
import com.google.firebase.ai.type.ImagenRawMask
31+
import com.google.firebase.ai.type.ImagenStyleReference
2932
import com.google.firebase.ai.type.PublicPreviewAPI
3033
import com.google.firebase.ai.type.toImagenInlineImage
3134
import javax.inject.Inject
@@ -120,4 +123,29 @@ class ImagenEditingDataSource @Inject constructor() {
120123
)
121124
return imageResponse.images.first().asBitmap()
122125
}
126+
127+
/**
128+
* Outpaints an image to the target dimensions using the Firebase Imagen API.
129+
* This function extends the original image by generating content around it
130+
* based on the provided prompt and target dimensions.
131+
*
132+
* @param sourceImage The original bitmap image to be outpainted.
133+
* @param targetDimensions The desired dimensions of the outpainted image.
134+
* @param prompt An optional text prompt to guide the outpainting process.
135+
* @return The outpainted bitmap image.
136+
*/
137+
@OptIn(PublicPreviewAPI::class)
138+
suspend fun outpaintImage(
139+
sourceImage: Bitmap,
140+
targetDimensions: Dimensions,
141+
prompt: String = "",
142+
): Bitmap {
143+
val imageResponse = editingModel.outpaintImage(
144+
image = sourceImage.toImagenInlineImage(),
145+
newDimensions = targetDimensions,
146+
prompt = prompt,
147+
)
148+
149+
return imageResponse.images.first().asBitmap()
150+
}
123151
}

ai-catalog/samples/imagen-editing/src/main/java/com/android/ai/samples/imagenediting/ui/ImagenEditingGeneratedContent.kt

Lines changed: 0 additions & 241 deletions
This file was deleted.

ai-catalog/samples/imagen-editing/src/main/java/com/android/ai/samples/imagenediting/ui/ImagenEditingGenerationInput.kt

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717

1818
package com.android.ai.samples.imagenediting.ui
1919

20+
import android.graphics.Bitmap
2021
import androidx.compose.foundation.layout.Arrangement
2122
import androidx.compose.foundation.layout.Column
23+
import androidx.compose.foundation.layout.Row
2224
import androidx.compose.foundation.layout.Spacer
2325
import androidx.compose.foundation.layout.fillMaxWidth
2426
import androidx.compose.foundation.layout.size
@@ -47,6 +49,7 @@ import com.android.ai.samples.imagenediting.R
4749
fun GenerationInput(
4850
uiState: ImagenEditingUIState,
4951
onGenerateClick: (String) -> Unit,
52+
onOutpaintClick: (prompt: String) -> Unit,
5053
onInpaintClick: (prompt: String) -> Unit,
5154
enabled: Boolean,
5255
modifier: Modifier = Modifier,
@@ -81,21 +84,39 @@ fun GenerationInput(
8184
)
8285

8386
if (uiState !is ImagenEditingUIState.ImageMasked) {
84-
Button(
85-
onClick = {
86-
onGenerateClick(promptTextField)
87-
},
88-
enabled = canGenerate,
89-
contentPadding = ButtonDefaults.ButtonWithIconContentPadding,
90-
modifier = Modifier.fillMaxWidth(),
91-
) {
92-
Icon(
93-
Icons.Default.SmartToy,
94-
contentDescription = null,
95-
modifier = Modifier.size(ButtonDefaults.IconSize),
96-
)
97-
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
98-
Text(text = stringResource(R.string.editing_generate_button))
87+
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
88+
Button(
89+
onClick = {
90+
onGenerateClick(promptTextField)
91+
},
92+
enabled = canGenerate,
93+
contentPadding = ButtonDefaults.ButtonWithIconContentPadding,
94+
modifier = Modifier.weight(1f),
95+
) {
96+
Icon(
97+
Icons.Default.SmartToy,
98+
contentDescription = null,
99+
modifier = Modifier.size(ButtonDefaults.IconSize),
100+
)
101+
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
102+
Text(text = stringResource(R.string.editing_generate_button))
103+
}
104+
105+
val bitmap: Bitmap? = (uiState as? ImagenEditingUIState.ImageGenerated)?.bitmap
106+
if (bitmap != null) {
107+
Button(
108+
onClick = {
109+
onOutpaintClick(promptTextField)
110+
},
111+
enabled = enabled && bitmap.width < 4096 && bitmap.height < 4096,
112+
contentPadding = ButtonDefaults.ButtonWithIconContentPadding,
113+
modifier = Modifier.weight(1f),
114+
) {
115+
Icon(Icons.Default.AutoFixHigh, contentDescription = null)
116+
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
117+
Text(text = stringResource(R.string.editing_expand_button))
118+
}
119+
}
99120
}
100121
}
101122

@@ -109,7 +130,7 @@ fun GenerationInput(
109130
modifier = Modifier.fillMaxWidth(),
110131
) {
111132
Icon(
112-
Icons.Default.AutoFixHigh, // Using a different icon for inpainting
133+
Icons.Default.AutoFixHigh,
113134
contentDescription = null,
114135
modifier = Modifier.size(ButtonDefaults.IconSize),
115136
)

0 commit comments

Comments
 (0)