Skip to content

Imagen Editing #7075

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Jul 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion firebase-ai/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Unreleased

* [feature] added support for Imagen Editing, including inpainting, outpainting, control, style
transfer, and subject references (#7075)

# 17.0.0
* [feature] Added support for configuring the "thinking" budget when using Gemini
Expand Down
126 changes: 126 additions & 0 deletions firebase-ai/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ package com.google.firebase.ai {
}

@com.google.firebase.ai.type.PublicPreviewAPI public final class ImagenModel {
method public suspend Object? editImage(java.util.List<? extends com.google.firebase.ai.type.ImagenReferenceImage> referenceImages, String prompt, com.google.firebase.ai.type.ImagenEditingConfig? config = null, kotlin.coroutines.Continuation<? super com.google.firebase.ai.type.ImagenGenerationResponse<com.google.firebase.ai.type.ImagenInlineImage>>);
method public suspend Object? generateImages(String prompt, kotlin.coroutines.Continuation<? super com.google.firebase.ai.type.ImagenGenerationResponse<com.google.firebase.ai.type.ImagenInlineImage>>);
method public suspend Object? inpaintImage(com.google.firebase.ai.type.ImagenInlineImage image, String prompt, com.google.firebase.ai.type.ImagenMaskReference mask, com.google.firebase.ai.type.ImagenEditingConfig config, kotlin.coroutines.Continuation<? super com.google.firebase.ai.type.ImagenGenerationResponse<com.google.firebase.ai.type.ImagenInlineImage>>);
method public suspend Object? outpaintImage(com.google.firebase.ai.type.ImagenInlineImage image, com.google.firebase.ai.type.Dimensions newDimensions, com.google.firebase.ai.type.ImagenImagePlacement newPosition = com.google.firebase.ai.type.ImagenImagePlacement.CENTER, String prompt = "", com.google.firebase.ai.type.ImagenEditingConfig? config = null, kotlin.coroutines.Continuation<? super com.google.firebase.ai.type.ImagenGenerationResponse<com.google.firebase.ai.type.ImagenInlineImage>>);
}

@com.google.firebase.ai.type.PublicPreviewAPI public final class LiveGenerativeModel {
Expand Down Expand Up @@ -107,9 +110,13 @@ package com.google.firebase.ai.java {
}

@com.google.firebase.ai.type.PublicPreviewAPI public abstract class ImagenModelFutures {
method public abstract com.google.common.util.concurrent.ListenableFuture<com.google.firebase.ai.type.ImagenGenerationResponse<com.google.firebase.ai.type.ImagenInlineImage>> editImage(java.util.List<? extends com.google.firebase.ai.type.ImagenReferenceImage> referenceImages, String prompt);
method public abstract com.google.common.util.concurrent.ListenableFuture<com.google.firebase.ai.type.ImagenGenerationResponse<com.google.firebase.ai.type.ImagenInlineImage>> editImage(java.util.List<? extends com.google.firebase.ai.type.ImagenReferenceImage> referenceImages, String prompt, com.google.firebase.ai.type.ImagenEditingConfig? config = null);
method public static final com.google.firebase.ai.java.ImagenModelFutures from(com.google.firebase.ai.ImagenModel model);
method public abstract com.google.common.util.concurrent.ListenableFuture<com.google.firebase.ai.type.ImagenGenerationResponse<com.google.firebase.ai.type.ImagenInlineImage>> generateImages(String prompt);
method public abstract com.google.firebase.ai.ImagenModel getImageModel();
method public abstract com.google.common.util.concurrent.ListenableFuture<com.google.firebase.ai.type.ImagenGenerationResponse<com.google.firebase.ai.type.ImagenInlineImage>> inpaintImage(com.google.firebase.ai.type.ImagenInlineImage image, String prompt, com.google.firebase.ai.type.ImagenMaskReference mask, com.google.firebase.ai.type.ImagenEditingConfig config);
method public abstract com.google.common.util.concurrent.ListenableFuture<com.google.firebase.ai.type.ImagenGenerationResponse<com.google.firebase.ai.type.ImagenInlineImage>> outpaintImage(com.google.firebase.ai.type.ImagenInlineImage image, com.google.firebase.ai.type.Dimensions newDimensions, com.google.firebase.ai.type.ImagenImagePlacement newPosition = com.google.firebase.ai.type.ImagenImagePlacement.CENTER, String prompt = "", com.google.firebase.ai.type.ImagenEditingConfig? config = null);
field public static final com.google.firebase.ai.java.ImagenModelFutures.Companion Companion;
}

Expand Down Expand Up @@ -262,6 +269,14 @@ package com.google.firebase.ai.type {
property public final int totalTokens;
}

public final class Dimensions {
ctor public Dimensions(int width, int height);
method public int getHeight();
method public int getWidth();
property public final int height;
property public final int width;
}

public final class FileDataPart implements com.google.firebase.ai.type.Part {
ctor public FileDataPart(String uri, String mimeType);
method public String getMimeType();
Expand Down Expand Up @@ -533,6 +548,43 @@ package com.google.firebase.ai.type {
public static final class ImagenAspectRatio.Companion {
}

@com.google.firebase.ai.type.PublicPreviewAPI public final class ImagenBackgroundMask extends com.google.firebase.ai.type.ImagenMaskReference {
ctor public ImagenBackgroundMask(Double? dilation = null);
}

@com.google.firebase.ai.type.PublicPreviewAPI public final class ImagenControlReference extends com.google.firebase.ai.type.ImagenReferenceImage {
ctor public ImagenControlReference(com.google.firebase.ai.type.ImagenControlType type, com.google.firebase.ai.type.ImagenInlineImage? image = null, Integer? referenceId = null, Boolean? enableComputation = null, Integer? superpixelRegionSize = null, Integer? superpixelRuler = null);
}

public final class ImagenControlType {
field public static final com.google.firebase.ai.type.ImagenControlType CANNY;
field public static final com.google.firebase.ai.type.ImagenControlType COLOR_SUPERPIXEL;
field public static final com.google.firebase.ai.type.ImagenControlType.Companion Companion;
field public static final com.google.firebase.ai.type.ImagenControlType FACE_MESH;
field public static final com.google.firebase.ai.type.ImagenControlType SCRIBBLE;
}

public static final class ImagenControlType.Companion {
}

public final class ImagenEditMode {
field public static final com.google.firebase.ai.type.ImagenEditMode.Companion Companion;
field public static final com.google.firebase.ai.type.ImagenEditMode INPAINT_INSERTION;
field public static final com.google.firebase.ai.type.ImagenEditMode INPAINT_REMOVAL;
field public static final com.google.firebase.ai.type.ImagenEditMode OUTPAINT;
}

public static final class ImagenEditMode.Companion {
}

@com.google.firebase.ai.type.PublicPreviewAPI public final class ImagenEditingConfig {
ctor public ImagenEditingConfig(com.google.firebase.ai.type.ImagenEditMode? editMode = null, Integer? editSteps = null);
}

@com.google.firebase.ai.type.PublicPreviewAPI public final class ImagenForegroundMask extends com.google.firebase.ai.type.ImagenMaskReference {
ctor public ImagenForegroundMask(Double? dilation = null);
}

@com.google.firebase.ai.type.PublicPreviewAPI public final class ImagenGenerationConfig {
ctor public ImagenGenerationConfig(String? negativePrompt = null, Integer? numberOfImages = 1, com.google.firebase.ai.type.ImagenAspectRatio? aspectRatio = null, com.google.firebase.ai.type.ImagenImageFormat? imageFormat = null, Boolean? addWatermark = null);
method public Boolean? getAddWatermark();
Expand Down Expand Up @@ -593,6 +645,28 @@ package com.google.firebase.ai.type {
method public com.google.firebase.ai.type.ImagenImageFormat png();
}

public final class ImagenImagePlacement {
method public static com.google.firebase.ai.type.ImagenImagePlacement fromCoordinate(int x, int y);
method public Integer? getX();
method public Integer? getY();
property public final Integer? x;
property public final Integer? y;
field public static final com.google.firebase.ai.type.ImagenImagePlacement BOTTOM_CENTER;
field public static final com.google.firebase.ai.type.ImagenImagePlacement BOTTOM_LEFT;
field public static final com.google.firebase.ai.type.ImagenImagePlacement BOTTOM_RIGHT;
field public static final com.google.firebase.ai.type.ImagenImagePlacement CENTER;
field public static final com.google.firebase.ai.type.ImagenImagePlacement.Companion Companion;
field public static final com.google.firebase.ai.type.ImagenImagePlacement LEFT_CENTER;
field public static final com.google.firebase.ai.type.ImagenImagePlacement RIGHT_CENTER;
field public static final com.google.firebase.ai.type.ImagenImagePlacement TOP_CENTER;
field public static final com.google.firebase.ai.type.ImagenImagePlacement TOP_LEFT;
field public static final com.google.firebase.ai.type.ImagenImagePlacement TOP_RIGHT;
}

public static final class ImagenImagePlacement.Companion {
method public com.google.firebase.ai.type.ImagenImagePlacement fromCoordinate(int x, int y);
}

@com.google.firebase.ai.type.PublicPreviewAPI public final class ImagenInlineImage {
method public android.graphics.Bitmap asBitmap();
method public byte[] getData();
Expand All @@ -601,6 +675,21 @@ package com.google.firebase.ai.type {
property public final String mimeType;
}

public final class ImagenInlineImageKt {
method @com.google.firebase.ai.type.PublicPreviewAPI public static com.google.firebase.ai.type.ImagenInlineImage toImagenInlineImage(android.graphics.Bitmap);
}

@com.google.firebase.ai.type.PublicPreviewAPI public abstract class ImagenMaskReference extends com.google.firebase.ai.type.ImagenReferenceImage {
method public static final java.util.List<com.google.firebase.ai.type.ImagenReferenceImage> generateMaskAndPadForOutpainting(com.google.firebase.ai.type.ImagenInlineImage image, com.google.firebase.ai.type.Dimensions newDimensions);
method public static final java.util.List<com.google.firebase.ai.type.ImagenReferenceImage> generateMaskAndPadForOutpainting(com.google.firebase.ai.type.ImagenInlineImage image, com.google.firebase.ai.type.Dimensions newDimensions, com.google.firebase.ai.type.ImagenImagePlacement newPosition = com.google.firebase.ai.type.ImagenImagePlacement.CENTER);
field public static final com.google.firebase.ai.type.ImagenMaskReference.Companion Companion;
}

public static final class ImagenMaskReference.Companion {
method public java.util.List<com.google.firebase.ai.type.ImagenReferenceImage> generateMaskAndPadForOutpainting(com.google.firebase.ai.type.ImagenInlineImage image, com.google.firebase.ai.type.Dimensions newDimensions);
method public java.util.List<com.google.firebase.ai.type.ImagenReferenceImage> generateMaskAndPadForOutpainting(com.google.firebase.ai.type.ImagenInlineImage image, com.google.firebase.ai.type.Dimensions newDimensions, com.google.firebase.ai.type.ImagenImagePlacement newPosition = com.google.firebase.ai.type.ImagenImagePlacement.CENTER);
}

@com.google.firebase.ai.type.PublicPreviewAPI public final class ImagenPersonFilterLevel {
field public static final com.google.firebase.ai.type.ImagenPersonFilterLevel ALLOW_ADULT;
field public static final com.google.firebase.ai.type.ImagenPersonFilterLevel ALLOW_ALL;
Expand All @@ -611,6 +700,21 @@ package com.google.firebase.ai.type {
public static final class ImagenPersonFilterLevel.Companion {
}

@com.google.firebase.ai.type.PublicPreviewAPI public final class ImagenRawImage extends com.google.firebase.ai.type.ImagenReferenceImage {
ctor public ImagenRawImage(com.google.firebase.ai.type.ImagenInlineImage image);
}

@com.google.firebase.ai.type.PublicPreviewAPI public final class ImagenRawMask extends com.google.firebase.ai.type.ImagenMaskReference {
ctor public ImagenRawMask(com.google.firebase.ai.type.ImagenInlineImage mask, Double? dilation = null);
}

@com.google.firebase.ai.type.PublicPreviewAPI public abstract class ImagenReferenceImage {
method public final com.google.firebase.ai.type.ImagenInlineImage? getImage();
method public final Integer? getReferenceId();
property public final com.google.firebase.ai.type.ImagenInlineImage? image;
property public final Integer? referenceId;
}

@com.google.firebase.ai.type.PublicPreviewAPI public final class ImagenSafetyFilterLevel {
field public static final com.google.firebase.ai.type.ImagenSafetyFilterLevel BLOCK_LOW_AND_ABOVE;
field public static final com.google.firebase.ai.type.ImagenSafetyFilterLevel BLOCK_MEDIUM_AND_ABOVE;
Expand All @@ -626,6 +730,28 @@ package com.google.firebase.ai.type {
ctor public ImagenSafetySettings(com.google.firebase.ai.type.ImagenSafetyFilterLevel safetyFilterLevel, com.google.firebase.ai.type.ImagenPersonFilterLevel personFilterLevel);
}

@com.google.firebase.ai.type.PublicPreviewAPI public final class ImagenSemanticMask extends com.google.firebase.ai.type.ImagenMaskReference {
ctor public ImagenSemanticMask(java.util.List<java.lang.Integer> classes, Double? dilation = null);
}

@com.google.firebase.ai.type.PublicPreviewAPI public final class ImagenStyleReference extends com.google.firebase.ai.type.ImagenReferenceImage {
ctor public ImagenStyleReference(com.google.firebase.ai.type.ImagenInlineImage image, Integer? referenceId = null, String? description = null);
}

@com.google.firebase.ai.type.PublicPreviewAPI public final class ImagenSubjectReference extends com.google.firebase.ai.type.ImagenReferenceImage {
ctor public ImagenSubjectReference(com.google.firebase.ai.type.ImagenInlineImage image, Integer? referenceId = null, String? description = null, com.google.firebase.ai.type.ImagenSubjectReferenceType? subjectType = null);
}

public final class ImagenSubjectReferenceType {
field public static final com.google.firebase.ai.type.ImagenSubjectReferenceType ANIMAL;
field public static final com.google.firebase.ai.type.ImagenSubjectReferenceType.Companion Companion;
field public static final com.google.firebase.ai.type.ImagenSubjectReferenceType PERSON;
field public static final com.google.firebase.ai.type.ImagenSubjectReferenceType PRODUCT;
}

public static final class ImagenSubjectReferenceType.Companion {
}

public final class InlineDataPart implements com.google.firebase.ai.type.Part {
ctor public InlineDataPart(byte[] inlineData, String mimeType);
method public byte[] getInlineData();
Expand Down
2 changes: 1 addition & 1 deletion firebase-ai/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@
# See the License for the specific language governing permissions and
# limitations under the License.

version=17.0.1
version=17.1.0
latestReleasedVersion=17.0.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.firebase.ai

import com.google.firebase.ai.AIModels.Companion.app
import com.google.firebase.ai.type.ImagenBackgroundMask
import com.google.firebase.ai.type.ImagenEditMode
import com.google.firebase.ai.type.ImagenEditingConfig
import com.google.firebase.ai.type.ImagenRawImage
import com.google.firebase.ai.type.PublicPreviewAPI
import kotlinx.coroutines.runBlocking
import org.junit.Test

@OptIn(PublicPreviewAPI::class)
class ImagenTests {
@Test
fun testGenerateAndEditImage() {
val imageGenerationModel = FirebaseAI.getInstance(app()).imagenModel("imagen-3.0-generate-002")
val imageEditingModel = FirebaseAI.getInstance(app()).imagenModel("imagen-3.0-capability-001")

runBlocking {
val catImage = imageGenerationModel.generateImages("A cat").images.first()
val editedCatImage =
imageEditingModel.editImage(
listOf(ImagenRawImage(catImage), ImagenBackgroundMask()),
"A cat flying through space",
ImagenEditingConfig(ImagenEditMode.INPAINT_INSERTION)
)
assert(editedCatImage.images.size == 1)
}
}
}
Loading
Loading