Skip to content

Commit 2aefcd2

Browse files
authored
Merge pull request #96 from android/feature/negative-prompt
Added Negative prompt to the Background generation
2 parents 95b8c8d + c1f6843 commit 2aefcd2

File tree

9 files changed

+55
-18
lines changed

9 files changed

+55
-18
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ fontName="Roboto Flex"
4343

4444
For Googlers, get this info from go/androidify-api-setup
4545

46+
## Availability
47+
Due to the background vibe feature using
48+
`gemini-2.0-flash-preview-image-generation`, its not currently supported in a number of countries in Europe, Middle East & Africa.
49+
See [this](https://ai.google.dev/gemini-api/docs/models#gemini-2.0-flash-preview-image-generation) doc for more information.
50+
4651
## Contributing
4752

4853
See [Contributing](CONTRIBUTING.md).

core/network/src/main/java/com/android/developers/androidify/RemoteConfigDataSource.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ interface RemoteConfigDataSource {
4040
fun getFineTunedModelName(): String
4141

4242
fun getImageGenerationEditsModelName(): String
43+
44+
fun getBotBackgroundInstructionPrompt(): String
4345
}
4446

4547
@Singleton
@@ -100,4 +102,8 @@ class RemoteConfigDataSourceImpl @Inject constructor() : RemoteConfigDataSource
100102
override fun getImageGenerationEditsModelName(): String {
101103
return remoteConfig.getString("image_generation_model_edits")
102104
}
105+
106+
override fun getBotBackgroundInstructionPrompt(): String {
107+
return remoteConfig.getString("bot_background_instruction_prompt")
108+
}
103109
}

core/network/src/main/java/com/android/developers/androidify/vertexai/FirebaseAiDataSource.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,12 @@ class FirebaseAiDataSourceImpl @Inject constructor(
8585
return Firebase.ai(backend = GenerativeBackend.vertexAI()).imagenModel(
8686
remoteConfigDataSource.imageModelName(),
8787
safetySettings =
88-
ImagenSafetySettings(
89-
safetyFilterLevel = ImagenSafetyFilterLevel.BLOCK_LOW_AND_ABOVE,
90-
// Uses `ALLOW_ADULT` filter since `ALLOW_ALL` requires a special approval
91-
// See https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#person-face-gen
92-
personFilterLevel = ImagenPersonFilterLevel.ALLOW_ADULT,
93-
),
88+
ImagenSafetySettings(
89+
safetyFilterLevel = ImagenSafetyFilterLevel.BLOCK_LOW_AND_ABOVE,
90+
// Uses `ALLOW_ADULT` filter since `ALLOW_ALL` requires a special approval
91+
// See https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#person-face-gen
92+
personFilterLevel = ImagenPersonFilterLevel.ALLOW_ADULT,
93+
),
9494
)
9595
}
9696

core/network/src/main/res/xml/remote_config_defaults.xml

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,25 @@
1616
-->
1717
<defaults>
1818
<entry>
19-
<key>image_generation_model_edits</key>
20-
<value>gemini-2.0-flash-preview-image-generation</value>
19+
<key>bot_background_instruction_prompt</key>
20+
<value>Add the input image android bot as the main subject to the result,
21+
it should be the most prominent element of the resultant image, large and
22+
filling the foreground - more than 50% of the resultant frame,
23+
standing in the center of the frame with the central
24+
focus, and the background just underneath the content.
25+
26+
Always include the input Android Bot in the final result image as the subject of the image.
27+
It should be prominently featured in the foreground, center of the frame, without any adjustments other
28+
than the lighting of the surrounding environment. There should only be one of the bots in the image.
29+
style="3d animation style, simplified shapes, mouthless character, realistic physics simulation"
30+
31+
Do not alter the input Android Bot image, do not change its shape or add any hands, eyes, mouths etc. Do not change the characters color scheme.
32+
33+
The background is described as follows:</value>
2134
</entry>
2235
<entry>
2336
<key>use_imagen</key>
24-
<value>true</value>
37+
<value>false</value>
2538
</entry>
2639
<entry>
2740
<key>prompt_image_validation</key>
@@ -127,6 +140,10 @@
127140
<key>promo_video_link</key>
128141
<value>https://services.google.com/fh/files/misc/androidfy_storyboard_b_v07.mp4</value>
129142
</entry>
143+
<entry>
144+
<key>image_generation_model_edits</key>
145+
<value>gemini-2.0-flash-preview-image-generation</value>
146+
</entry>
130147
<entry>
131148
<key>text_model_name</key>
132149
<value>gemini-2.5-flash</value>

core/testing/src/main/java/com/android/developers/testing/network/TestRemoteConfigDataSource.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,8 @@ class TestRemoteConfigDataSource(private val useGeminiNano: Boolean) : RemoteCon
7171
override fun getImageGenerationEditsModelName(): String {
7272
return "test_image_model"
7373
}
74+
75+
override fun getBotBackgroundInstructionPrompt(): String {
76+
return "bot_background_instruction_prompt"
77+
}
7478
}

core/testing/src/main/java/com/android/developers/testing/repository/FakeImageGenerationRepository.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ class FakeImageGenerationRepository : ImageGenerationRepository {
5858
return imageUri
5959
}
6060

61-
override suspend fun generateImageWithEdit(
61+
override suspend fun addBackgroundToBot(
6262
image: Bitmap,
63-
editPrompt: String,
63+
backgroundPrompt: String,
6464
): Bitmap {
6565
return createBitmap(1, 1)
6666
}

data/src/main/java/com/android/developers/androidify/data/ImageGenerationRepository.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import android.graphics.Bitmap
1919
import android.graphics.BitmapFactory
2020
import android.net.Uri
2121
import android.util.Log
22+
import com.android.developers.androidify.RemoteConfigDataSource
2223
import com.android.developers.androidify.model.ValidatedDescription
2324
import com.android.developers.androidify.model.ValidatedImage
2425
import com.android.developers.androidify.util.LocalFileProvider
@@ -35,7 +36,8 @@ interface ImageGenerationRepository {
3536
suspend fun saveImage(imageBitmap: Bitmap): Uri
3637
suspend fun saveImageToExternalStorage(imageBitmap: Bitmap): Uri
3738
suspend fun saveImageToExternalStorage(imageUri: Uri): Uri
38-
suspend fun generateImageWithEdit(image: Bitmap, editPrompt: String): Bitmap
39+
40+
suspend fun addBackgroundToBot(image: Bitmap, backgroundPrompt: String) : Bitmap
3941
}
4042

4143
@Singleton
@@ -44,6 +46,7 @@ internal class ImageGenerationRepositoryImpl @Inject constructor(
4446
private val internetConnectivityManager: InternetConnectivityManager,
4547
private val geminiNanoDataSource: GeminiNanoGenerationDataSource,
4648
private val firebaseAiDataSource: FirebaseAiDataSource,
49+
private val remoteConfigDataSource: RemoteConfigDataSource
4750
) : ImageGenerationRepository {
4851

4952
override suspend fun initialize() {
@@ -126,7 +129,9 @@ internal class ImageGenerationRepositoryImpl @Inject constructor(
126129
}
127130
}
128131

129-
override suspend fun generateImageWithEdit(image: Bitmap, editPrompt: String): Bitmap {
130-
return firebaseAiDataSource.generateImageWithEdit(image, editPrompt)
132+
override suspend fun addBackgroundToBot(image: Bitmap, backgroundPrompt: String): Bitmap {
133+
val backgroundBotInstructions = remoteConfigDataSource.getBotBackgroundInstructionPrompt() +
134+
"\"" + backgroundPrompt + "\""
135+
return firebaseAiDataSource.generateImageWithEdit(image, backgroundBotInstructions)
131136
}
132137
}

feature/results/src/main/java/com/android/developers/androidify/customize/CustomizeExportViewModel.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,8 @@ class CustomizeExportViewModel @Inject constructor(
147147

148148
_state.update { it.copy(showImageEditProgress = true) }
149149
try {
150-
val bitmap = imageGenerationRepository.generateImageWithEdit(
151-
image,
152-
"Add the input image android bot as the main subject to the result, it should be the most prominent element of the resultant image, large and filling the foreground, standing in the center of the frame with the central focus, and the background just underneath the content. The background is described as follows: \"" + backgroundOption.prompt + "\"",
150+
val bitmap = imageGenerationRepository.addBackgroundToBot(
151+
image, backgroundOption.prompt,
153152
)
154153
_state.update {
155154
it.copy(

feature/results/src/main/java/com/android/developers/androidify/customize/ImageRenderer.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ fun BackgroundLayout(
158158
.then(safeAnimateBounds)
159159
.rotate(rotationAnimation),
160160
) {
161-
val clip = if (exportImageCanvas.selectedBackgroundOption == BackgroundOption.None) {
161+
val clip = if (exportImageCanvas.selectedBackgroundOption == BackgroundOption.None
162+
|| exportImageCanvas.selectedBackgroundOption.aiBackground) {
162163
Modifier
163164
} else {
164165
Modifier.clip(RoundedCornerShape(6))

0 commit comments

Comments
 (0)