From d89e3f2d1dc34f4d71bc9365fc06e8e889f46655 Mon Sep 17 00:00:00 2001 From: youngpar Date: Thu, 21 Mar 2024 16:58:04 +0900 Subject: [PATCH 1/9] FEAT Interface For ImageType Add a common interface for the extension of the ImageType enum. --- .../springframework/ai/image/ImageType.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 spring-ai-core/src/main/java/org/springframework/ai/image/ImageType.java diff --git a/spring-ai-core/src/main/java/org/springframework/ai/image/ImageType.java b/spring-ai-core/src/main/java/org/springframework/ai/image/ImageType.java new file mode 100644 index 00000000000..fcf50c94c0b --- /dev/null +++ b/spring-ai-core/src/main/java/org/springframework/ai/image/ImageType.java @@ -0,0 +1,63 @@ +/* + * Copyright 2023 - 2024 the original author or authors. + * + * 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 + * + * https://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 org.springframework.ai.image; + +/** + * A generic interface for defining types of images in an extensible enum pattern. This + * interface allows for the creation of type-safe enums that can be extended to include + * new types of image references. + * + * @param The concrete enum type that implements this interface. This type parameter + * enables the enum to use methods defined in this interface in a type-safe manner. + * @param The type of the constants used by the enum implementing this interface. It + * represents the type of the values associated with each enum constant. + *

+ * Example Usage: + *

+ *
+ * // Example of an enum using String constants
+ * public enum DefaultImageType implements ImageType<DefaultImageType, String> {
+ *           URL("url"),
+ *           BASE64("b64");
+ *           ...
+ * }
+ *
+ * // Example of an enum using Integer constants
+ * public enum IntConstType implements ImageType<IntConstType, Integer> {
+ *           URL(1),
+ *           BASE64(2);
+ *           ...
+ * }
+ * 
+ */ +public interface ImageType, E> { + + /** + * Returns the value associated with the enum constant. + * @return The value of the enum constant of type {@code E}. + */ + E getValue(); + + /** + * Returns an enum constant of type {@code T} corresponding to the specified value of + * type {@code E}. + * @param value The value of the enum constant to be returned. + * @return An enum constant of type {@code T}. + * @throws IllegalArgumentException if no constant with the specified value is found. + */ + T fromValue(final E value); + +} From 48efde110d534f5ce96e0e18c4fb8e44e105f429 Mon Sep 17 00:00:00 2001 From: youngpar Date: Thu, 21 Mar 2024 17:21:34 +0900 Subject: [PATCH 2/9] FEAT implement Image Types Implemented image type objects for each provider. --- .../ai/openai/image/OpenAiImageType.java | 57 +++++++++++++++++++ .../image/StabilityAiImageType.java | 57 +++++++++++++++++++ .../ai/image/DefaultImageType.java | 49 ++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 models/spring-ai-openai/src/main/java/org/springframework/ai/openai/image/OpenAiImageType.java create mode 100644 models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiImageType.java create mode 100644 spring-ai-core/src/main/java/org/springframework/ai/image/DefaultImageType.java diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/image/OpenAiImageType.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/image/OpenAiImageType.java new file mode 100644 index 00000000000..67b30ea1e88 --- /dev/null +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/image/OpenAiImageType.java @@ -0,0 +1,57 @@ +/* + * Copyright 2023 - 2024 the original author or authors. + * + * 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 + * + * https://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 org.springframework.ai.openai.image; + +import java.util.Arrays; +import org.springframework.ai.image.ImageType; + +/** + * Represents the types of images supported by the OpenAI image generation API. This enum + * provides a type-safe way to specify and retrieve the image types used in OpenAI image + * generation requests and responses. + *

+ * It includes standard image types such as URL and Base64 encoded JSON. + *

+ * + * @implNote This enum implements the {@link ImageType} interface, enabling it to be used + * in a generic manner across the image processing. + * @author youngmon + * @version 0.8.1 + */ +public enum OpenAiImageType implements ImageType { + + URL("url"), BASE64("b64_json"); + + private final String value; + + OpenAiImageType(final String value) { + this.value = value; + } + + @Override + public String getValue() { + return this.value; + } + + @Override + public OpenAiImageType fromValue(String value) { + return Arrays.stream(values()) + .filter(v -> v.value.equals(value)) + .findAny() + .orElseThrow(() -> new IllegalArgumentException("Invalid Value")); + } + +} diff --git a/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiImageType.java b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiImageType.java new file mode 100644 index 00000000000..33f87452d90 --- /dev/null +++ b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiImageType.java @@ -0,0 +1,57 @@ +/* + * Copyright 2023 - 2024 the original author or authors. + * + * 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 + * + * https://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 org.springframework.ai.stabilityai.image; + +import java.util.Arrays; +import org.springframework.ai.image.ImageType; + +/** + * Represents the types of images supported by the StabilityAi image generation API. This + * enum provides a type-safe way to specify and retrieve the image types used in + * StabilityAi image generation requests and responses. + *

+ * It includes standard image types such as Base64. + *

+ * + * @implNote This enum implements the {@link ImageType} interface, enabling it to be used + * in a generic manner across the image processing framework. + * @author youngmon + * @version 0.8.1 + */ +public enum StabilityAiImageType implements ImageType { + + BASE64("base64"); + + private final String value; + + StabilityAiImageType(final String value) { + this.value = value; + } + + @Override + public String getValue() { + return this.value; + } + + @Override + public StabilityAiImageType fromValue(String value) { + return Arrays.stream(values()) + .filter(v -> v.value.equals(value)) + .findAny() + .orElseThrow(() -> new IllegalArgumentException("Invalid Value")); + } + +} diff --git a/spring-ai-core/src/main/java/org/springframework/ai/image/DefaultImageType.java b/spring-ai-core/src/main/java/org/springframework/ai/image/DefaultImageType.java new file mode 100644 index 00000000000..14b7e56a12b --- /dev/null +++ b/spring-ai-core/src/main/java/org/springframework/ai/image/DefaultImageType.java @@ -0,0 +1,49 @@ +/* + * Copyright 2023 - 2024 the original author or authors. + * + * 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 + * + * https://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 org.springframework.ai.image; + +import java.util.Arrays; + +/** + * Default Image Type + * + * @author youngmon + * @version 0.8.1 + */ +public enum DefaultImageType implements ImageType { + + URL("url"), B64("b64"); + + private final String value; + + DefaultImageType(final String value) { + this.value = value; + } + + @Override + public String getValue() { + return this.value; + } + + @Override + public DefaultImageType fromValue(final String value) { + return Arrays.stream(values()) + .filter(v -> v.value.equals(value)) + .findAny() + .orElseThrow(() -> new IllegalArgumentException("Invalid Value")); + } + +} From 755e5406a0701a7280cf393b68f58d700c7658d6 Mon Sep 17 00:00:00 2001 From: youngpar Date: Thu, 21 Mar 2024 17:26:34 +0900 Subject: [PATCH 3/9] FEAT Image Interface And Abstract Class Added Image interface and abstract class for flexible extension. --- .../ai/image/AbstractImage.java | 73 +++++++++++++++++++ .../org/springframework/ai/image/Image.java | 64 +++++----------- 2 files changed, 90 insertions(+), 47 deletions(-) create mode 100644 spring-ai-core/src/main/java/org/springframework/ai/image/AbstractImage.java diff --git a/spring-ai-core/src/main/java/org/springframework/ai/image/AbstractImage.java b/spring-ai-core/src/main/java/org/springframework/ai/image/AbstractImage.java new file mode 100644 index 00000000000..254d04c25e1 --- /dev/null +++ b/spring-ai-core/src/main/java/org/springframework/ai/image/AbstractImage.java @@ -0,0 +1,73 @@ +/* + * Copyright 2023 - 2024 the original author or authors. + * + * 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 + * + * https://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 org.springframework.ai.image; + +import java.util.Objects; + +/** + * An abstract class that provides a skeletal implementation of the Image interface. This + * class is designed to be extended by specific types of images (e.g., UrlImage, + * Base64Image, ByteArrayImage) that can be represented by different types of data. + * + * @param the type of the image data this class handles. + */ +public abstract class AbstractImage implements Image { + + private final T data; + + private final ImageType type; + + /** + * Constructs an AbstractImage with the specified data and image type. + * @param data the image data of this image. + * @param type the type of the image, as defined by the implementation of the + * ImageType interface. + */ + protected AbstractImage(final T data, final ImageType type) { + this.data = data; + this.type = type; + } + + @Override + public T getData() { + return this.data; + } + + @Override + public ImageType getType() { + return this.type; + } + + @Override + public String toString() { + return String.format("%s{type='%s', data='%s'}", getClass(), this.type.getValue(), getData()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) + return true; + if (o instanceof AbstractImage other) + return Objects.equals(this.data, other.getData()) && Objects.equals(this.type, other.getType()); + return false; + } + + @Override + public int hashCode() { + return Objects.hash(this.data, this.type); + } + +} diff --git a/spring-ai-core/src/main/java/org/springframework/ai/image/Image.java b/spring-ai-core/src/main/java/org/springframework/ai/image/Image.java index 8adc3677e09..0fe7727aeed 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/image/Image.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/image/Image.java @@ -15,58 +15,28 @@ */ package org.springframework.ai.image; -import java.util.Objects; - -public class Image { +/** + * An extensible interface for handling various types of image data. + * + * @param The type of the image data this interface deals with. For instance, it could + * be a byte array, a file path, or a Base64 encoded string of the image. + * @author youngmon + * @version 0.8.1 + */ +public interface Image { /** - * The URL where the image can be accessed. + * Returns the image data. The type of the data is determined by the type parameter + * {@code T} of this interface. + * @return Image data of type T. */ - private String url; + T getData(); /** - * Base64 encoded image string. + * Returns the type of the image. The image type is defined by the {@link ImageType}. + * Through this method, it's possible to know the type of the image. + * @return The {@link ImageType} of the image. */ - private String b64Json; - - public Image(String url, String b64Json) { - this.url = url; - this.b64Json = b64Json; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getB64Json() { - return b64Json; - } - - public void setB64Json(String b64Json) { - this.b64Json = b64Json; - } - - @Override - public String toString() { - return "Image{" + "url='" + url + '\'' + ", b64Json='" + b64Json + '\'' + '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof Image image)) - return false; - return Objects.equals(url, image.url) && Objects.equals(b64Json, image.b64Json); - } - - @Override - public int hashCode() { - return Objects.hash(url, b64Json); - } + ImageType getType(); } From f72828aab1a3d68a864462d271ce67e2f2bfcb7c Mon Sep 17 00:00:00 2001 From: youngpar Date: Thu, 21 Mar 2024 17:39:03 +0900 Subject: [PATCH 4/9] FEAT Image Class for Each Provider Developed image implementations for each provider. --- .../ai/openai/image/OpenAiBase64Image.java | 45 +++++++++++++++++++ .../ai/openai/image/OpenAiUrlImage.java | 45 +++++++++++++++++++ .../image/StabilityAiBase64Image.java | 45 +++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 models/spring-ai-openai/src/main/java/org/springframework/ai/openai/image/OpenAiBase64Image.java create mode 100644 models/spring-ai-openai/src/main/java/org/springframework/ai/openai/image/OpenAiUrlImage.java create mode 100644 models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiBase64Image.java diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/image/OpenAiBase64Image.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/image/OpenAiBase64Image.java new file mode 100644 index 00000000000..e435aaa59bb --- /dev/null +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/image/OpenAiBase64Image.java @@ -0,0 +1,45 @@ +/* + * Copyright 2023 - 2024 the original author or authors. + * + * 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 + * + * https://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 org.springframework.ai.openai.image; + +import org.springframework.ai.image.AbstractImage; + +/** + * Represents an image encoded in b64_json format within the OpenAI image processing + * context. This class extends {@link AbstractImage} to cater specifically to images that + * are provided as b64_json encoded strings. This format is useful for directly embedding + * image data within JSON or other text-based data structures without relying on external + * references. + *

+ * An instance of this class is associated with the {@link OpenAiImageType#BASE64} image + * type, signifying that the image data is encoded in b64_json format. + *

+ * + * @author youngmon + * @version 0.8.1 + */ +public class OpenAiBase64Image extends AbstractImage { + + /** + * Constructs a new {@code OpenAiBase64Image} with the specified b64_json data. + * @param b64Json The Base64 encoded string that encapsulates the image data. The + * string should be a valid b64_json representation of an image file. + */ + public OpenAiBase64Image(final String b64Json) { + super(b64Json, OpenAiImageType.BASE64); + } + +} diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/image/OpenAiUrlImage.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/image/OpenAiUrlImage.java new file mode 100644 index 00000000000..2bafc524da9 --- /dev/null +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/image/OpenAiUrlImage.java @@ -0,0 +1,45 @@ +/* + * Copyright 2023 - 2024 the original author or authors. + * + * 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 + * + * https://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 org.springframework.ai.openai.image; + +import org.springframework.ai.image.AbstractImage; + +/** + * Represents an image sourced from a URL, specifically designed for use within the OpenAI + * image processing context. This class extends {@link AbstractImage} to provide a + * specialized representation for images that are accessible via web URLs. + *

+ * Each instance of {@code OpenAiUrlImage} is associated with the + * {@link OpenAiImageType#URL} image type, indicating the source of the image data is from + * an external URL. This is particularly useful for scenarios where images need to be + * referenced rather than stored directly within the application. + *

+ * + * @author youngmon + * @version 0.8.1 + */ +public class OpenAiUrlImage extends AbstractImage { + + /** + * Constructs a new {@code OpenAiUrlImage} with the specified image URL. + * @param url The URL of the image. This should be a valid, fully qualified URL that + * points directly to an image file accessible over the internet. + */ + public OpenAiUrlImage(final String url) { + super(url, OpenAiImageType.URL); + } + +} diff --git a/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiBase64Image.java b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiBase64Image.java new file mode 100644 index 00000000000..9233fffd08d --- /dev/null +++ b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiBase64Image.java @@ -0,0 +1,45 @@ +/* + * Copyright 2023 - 2024 the original author or authors. + * + * 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 + * + * https://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 org.springframework.ai.stabilityai.image; + +import org.springframework.ai.image.AbstractImage; + +/** + * Represents an image encoded in Base64 format used within the Stability AI context. This + * class extends {@link AbstractImage} with a specific focus on images that are + * represented as Base64 encoded strings. It is particularly useful for handling image + * data that is transmitted over networks where binary data needs to be encoded as text. + *

+ * Instances of this class are associated with the {@link StabilityAiImageType#BASE64} + * image type, indicating that the image data is in Base64 format. + *

+ * + * @author youngmon + * @version 0.8.1 + */ +public class StabilityAiBase64Image extends AbstractImage { + + /** + * Constructs a new {@code StabilityAiBase64Image} with the specified Base64 image + * data. + * @param data The Base64 encoded string that represents the image. This should be a + * valid Base64 encoding of an image file's contents. + */ + public StabilityAiBase64Image(final String data) { + super(data, StabilityAiImageType.BASE64); + } + +} From 5afb02c032dcbb1953c57b517e1299bc074fb224 Mon Sep 17 00:00:00 2001 From: youngpar Date: Thu, 21 Mar 2024 17:54:00 +0900 Subject: [PATCH 5/9] Fix ImageGeneration creation section --- .../org/springframework/ai/openai/OpenAiImageClient.java | 7 +++---- .../springframework/ai/openai/api/OpenAiImageApi.java | 9 +++++++++ .../ai/stabilityai/StabilityAiImageClient.java | 3 +-- .../ai/stabilityai/api/StabilityAiApi.java | 8 ++++++++ 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiImageClient.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiImageClient.java index 69863ef9ffc..0cd7b97f174 100644 --- a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiImageClient.java +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiImageClient.java @@ -17,10 +17,10 @@ import java.util.List; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.ai.image.Image; import org.springframework.ai.image.ImageClient; import org.springframework.ai.image.ImageGeneration; import org.springframework.ai.image.ImageOptions; @@ -109,9 +109,8 @@ private ImageResponse convertResponse(ResponseEntity imageGenerationList = imageApiResponse.data().stream().map(entry -> { - return new ImageGeneration(new Image(entry.url(), entry.b64Json()), - new OpenAiImageGenerationMetadata(entry.revisedPrompt())); - }).toList(); + return new ImageGeneration(entry.getImage(), new OpenAiImageGenerationMetadata(entry.revisedPrompt())); + }).collect(Collectors.toList()); ImageResponseMetadata openAiImageResponseMetadata = OpenAiImageResponseMetadata.from(imageApiResponse); return new ImageResponse(imageGenerationList, openAiImageResponseMetadata); diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiImageApi.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiImageApi.java index 18b3d0bff4e..14f789cf9d1 100644 --- a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiImageApi.java +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiImageApi.java @@ -20,6 +20,9 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import org.springframework.ai.image.Image; +import org.springframework.ai.openai.image.OpenAiBase64Image; +import org.springframework.ai.openai.image.OpenAiUrlImage; import org.springframework.ai.retry.RetryUtils; import org.springframework.http.ResponseEntity; import org.springframework.util.Assert; @@ -129,6 +132,12 @@ public record Data( @JsonProperty("url") String url, @JsonProperty("b64_json") String b64Json, @JsonProperty("revised_prompt") String revisedPrompt) { + // TODO : Develop Image Factory + public Image getImage() { + if (url != null) return new OpenAiUrlImage(url); + if (b64Json != null) return new OpenAiBase64Image(b64Json); + throw new IllegalArgumentException("Entry must have either url or b64Json"); + } } // @formatter:onn diff --git a/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/StabilityAiImageClient.java b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/StabilityAiImageClient.java index e632e5235b5..d0b26ab4e45 100644 --- a/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/StabilityAiImageClient.java +++ b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/StabilityAiImageClient.java @@ -21,7 +21,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.ai.image.Image; import org.springframework.ai.image.ImageClient; import org.springframework.ai.image.ImageGeneration; import org.springframework.ai.image.ImageOptions; @@ -115,7 +114,7 @@ private static StabilityAiApi.GenerateImageRequest getGenerateImageRequest(Image private ImageResponse convertResponse(StabilityAiApi.GenerateImageResponse generateImageResponse) { List imageGenerationList = generateImageResponse.artifacts().stream().map(entry -> { - return new ImageGeneration(new Image(null, entry.base64()), + return new ImageGeneration(entry.getImage(), new StabilityAiImageGenerationMetadata(entry.finishReason(), entry.seed())); }).toList(); diff --git a/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/api/StabilityAiApi.java b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/api/StabilityAiApi.java index 2ee5b2f7f24..41780120905 100644 --- a/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/api/StabilityAiApi.java +++ b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/api/StabilityAiApi.java @@ -21,7 +21,9 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import org.springframework.ai.image.Image; import org.springframework.ai.retry.RetryUtils; +import org.springframework.ai.stabilityai.image.StabilityAiBase64Image; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.util.Assert; @@ -190,6 +192,12 @@ public record GenerateImageResponse(@JsonProperty("result") String result, @JsonProperty("artifacts") List artifacts) { public record Artifacts(@JsonProperty("seed") long seed, @JsonProperty("base64") String base64, @JsonProperty("finishReason") String finishReason) { + // TODO : Develop Image Factory + public Image getImage() { + if (base64 != null) + return new StabilityAiBase64Image(base64); + throw new IllegalArgumentException("Entry must have base64"); + } } } From 6262c1af0310bfa01adf49697eae7184c8556d80 Mon Sep 17 00:00:00 2001 From: youngpar Date: Thu, 21 Mar 2024 17:57:45 +0900 Subject: [PATCH 6/9] Refactor Test Code modified Test code --- .../springframework/ai/openai/chat/OpenAiRetryTests.java | 2 +- .../ai/openai/image/OpenAiImageClientIT.java | 5 ++--- .../ai/stabilityai/StabilityAiImageClientIT.java | 7 +++++-- .../ai/autoconfigure/openai/OpenAiAutoConfigurationIT.java | 6 ++++-- .../stabilityai/StabilityAiAutoConfigurationIT.java | 4 +++- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiRetryTests.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiRetryTests.java index dcf0f303ff0..5c78677e135 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiRetryTests.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiRetryTests.java @@ -256,7 +256,7 @@ public void openAiImageTransientError() { var result = imageClient.call(new ImagePrompt(List.of(new ImageMessage("Image Message")))); assertThat(result).isNotNull(); - assertThat(result.getResult().getOutput().getUrl()).isEqualTo("url678"); + assertThat(result.getResult().getOutput().getData()).isEqualTo("url678"); assertThat(retryListener.onSuccessRetryCount).isEqualTo(2); assertThat(retryListener.onErrorRetryCount).isEqualTo(2); } diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/image/OpenAiImageClientIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/image/OpenAiImageClientIT.java index 1a36b449a78..934ccb68f70 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/image/OpenAiImageClientIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/image/OpenAiImageClientIT.java @@ -48,9 +48,8 @@ void imageAsUrlTest() { var generation = imageResponse.getResult(); Image image = generation.getOutput(); - assertThat(image.getUrl()).isNotEmpty(); - // System.out.println(image.getUrl()); - assertThat(image.getB64Json()).isNull(); + assertThat(image.getType()).isEqualTo(OpenAiImageType.URL); + assertThat(image.getData()).isNotNull(); var imageGenerationMetadata = generation.getMetadata(); Assertions.assertThat(imageGenerationMetadata).isInstanceOf(OpenAiImageGenerationMetadata.class); diff --git a/models/spring-ai-stability-ai/src/test/java/org/springframework/ai/stabilityai/StabilityAiImageClientIT.java b/models/spring-ai-stability-ai/src/test/java/org/springframework/ai/stabilityai/StabilityAiImageClientIT.java index 1148cd6a973..cb1d3fe3ebc 100644 --- a/models/spring-ai-stability-ai/src/test/java/org/springframework/ai/stabilityai/StabilityAiImageClientIT.java +++ b/models/spring-ai-stability-ai/src/test/java/org/springframework/ai/stabilityai/StabilityAiImageClientIT.java @@ -19,6 +19,8 @@ import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.springframework.ai.image.*; import org.springframework.ai.stabilityai.api.StabilityAiImageOptions; +import org.springframework.ai.stabilityai.image.StabilityAiBase64Image; +import org.springframework.ai.stabilityai.image.StabilityAiImageType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -54,13 +56,14 @@ void imageAsBase64Test() throws IOException { ImageGeneration imageGeneration = imageResponse.getResult(); Image image = imageGeneration.getOutput(); - assertThat(image.getB64Json()).isNotEmpty(); + assertThat(image.getType()).isEqualTo(StabilityAiImageType.BASE64); + assertThat(image.getData()).isNotNull(); writeFile(image); } private static void writeFile(Image image) throws IOException { - byte[] imageBytes = Base64.getDecoder().decode(image.getB64Json()); + byte[] imageBytes = Base64.getDecoder().decode((String) image.getData()); String systemTempDir = System.getProperty("java.io.tmpdir"); String filePath = systemTempDir + File.separator + "dog.png"; File file = new File(filePath); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfigurationIT.java index 70102002fce..bcd284f8861 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfigurationIT.java @@ -28,6 +28,7 @@ import org.springframework.ai.image.ImagePrompt; import org.springframework.ai.image.ImageResponse; import org.springframework.ai.openai.OpenAiImageClient; +import org.springframework.ai.openai.image.OpenAiImageType; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import reactor.core.publisher.Flux; @@ -139,8 +140,9 @@ void generateImage() { OpenAiImageClient client = context.getBean(OpenAiImageClient.class); ImageResponse imageResponse = client.call(new ImagePrompt("forest")); assertThat(imageResponse.getResults()).hasSize(1); - assertThat(imageResponse.getResult().getOutput().getUrl()).isNotEmpty(); - logger.info("Generated image: " + imageResponse.getResult().getOutput().getUrl()); + assertThat(imageResponse.getResult().getOutput().getData()).isNotNull(); + assertThat(imageResponse.getResult().getOutput().getType()).isEqualTo(OpenAiImageType.URL); + logger.info("Generated image: " + imageResponse.getResult().getOutput().getData()); }); } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/stabilityai/StabilityAiAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/stabilityai/StabilityAiAutoConfigurationIT.java index f1b2042913d..e1b4df98560 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/stabilityai/StabilityAiAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/stabilityai/StabilityAiAutoConfigurationIT.java @@ -20,6 +20,7 @@ import org.springframework.ai.image.*; import org.springframework.ai.stabilityai.StyleEnum; import org.springframework.ai.stabilityai.api.StabilityAiImageOptions; +import org.springframework.ai.stabilityai.image.StabilityAiImageType; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -50,7 +51,8 @@ void generate() { ImageGeneration imageGeneration = imageResponse.getResult(); Image image = imageGeneration.getOutput(); - assertThat(image.getB64Json()).isNotEmpty(); + assertThat(image.getType()).isEqualTo(StabilityAiImageType.BASE64); + assertThat(image.getData()).isNotNull(); }); } From b9347a97290008ab8eb455b97fffc3d4db38804b Mon Sep 17 00:00:00 2001 From: youngpar Date: Thu, 21 Mar 2024 19:49:30 +0900 Subject: [PATCH 7/9] Test Create Simple Test Code --- .../image/OpenAiImageCreationTests.java | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 models/spring-ai-openai/src/test/java/org/springframework/ai/openai/image/OpenAiImageCreationTests.java diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/image/OpenAiImageCreationTests.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/image/OpenAiImageCreationTests.java new file mode 100644 index 00000000000..98b91154267 --- /dev/null +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/image/OpenAiImageCreationTests.java @@ -0,0 +1,78 @@ +/* + * Copyright 2023 - 2024 the original author or authors. + * + * 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 + * + * https://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 org.springframework.ai.openai.image; + +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.ai.image.Image; +import org.springframework.ai.openai.api.OpenAiImageApi.*; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(MockitoExtension.class) +public class OpenAiImageCreationTests { + + @Mock + OpenAiImageRequest req; + + @Mock + OpenAiImageResponse res; + + @Test + public void urlCreationTest() { + String testData = "test.url"; + + when(req.responseFormat()).thenReturn("url"); + when(res.toString()).thenReturn(testData); + + Image urlImg = tmpImageFactory(req, res); + + assertThat(urlImg).isNotNull(); + + assertThat(urlImg.getType()).isEqualTo(OpenAiImageType.URL); + assertThat(urlImg.getType().getValue()).isEqualTo("url"); + assertThat(urlImg.getData()).isEqualTo(testData); + } + + @Test + public void b64CreationTest() { + String testData = "test.b64"; + + when(req.responseFormat()).thenReturn("b64_json"); + when(res.toString()).thenReturn(testData); + + Image b64Img = tmpImageFactory(req, res); + + assertThat(b64Img).isNotNull(); + + assertThat(b64Img.getType()).isEqualTo(OpenAiImageType.BASE64); + assertThat(b64Img.getType().getValue()).isEqualTo("b64_json"); + assertThat(b64Img.getData()).isEqualTo(testData); + } + + private Image tmpImageFactory(OpenAiImageRequest req, OpenAiImageResponse res) { + return switch (req.responseFormat()) { + case "b64_json" -> new OpenAiBase64Image(res.toString()); + case "url" -> new OpenAiUrlImage(res.toString()); + default -> null; + }; + } + +} From 9949b017c558779aeb820379b622a9fadb64553c Mon Sep 17 00:00:00 2001 From: youngpar Date: Thu, 21 Mar 2024 20:59:10 +0900 Subject: [PATCH 8/9] Refactor Enhancing Type Safety --- .../ai/openai/image/OpenAiImageType.java | 3 +-- .../image/OpenAiImageCreationTests.java | 7 +++---- .../image/StabilityAiImageType.java | 3 +-- .../ai/image/DefaultImageType.java | 3 +-- .../springframework/ai/image/ImageType.java | 20 ++++++------------- 5 files changed, 12 insertions(+), 24 deletions(-) diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/image/OpenAiImageType.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/image/OpenAiImageType.java index 67b30ea1e88..ba986eedae9 100644 --- a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/image/OpenAiImageType.java +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/image/OpenAiImageType.java @@ -46,8 +46,7 @@ public String getValue() { return this.value; } - @Override - public OpenAiImageType fromValue(String value) { + public static OpenAiImageType fromValue(final String value) { return Arrays.stream(values()) .filter(v -> v.value.equals(value)) .findAny() diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/image/OpenAiImageCreationTests.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/image/OpenAiImageCreationTests.java index 98b91154267..5fdc131810f 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/image/OpenAiImageCreationTests.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/image/OpenAiImageCreationTests.java @@ -68,10 +68,9 @@ public void b64CreationTest() { } private Image tmpImageFactory(OpenAiImageRequest req, OpenAiImageResponse res) { - return switch (req.responseFormat()) { - case "b64_json" -> new OpenAiBase64Image(res.toString()); - case "url" -> new OpenAiUrlImage(res.toString()); - default -> null; + return switch (OpenAiImageType.fromValue(req.responseFormat())) { + case BASE64 -> new OpenAiBase64Image(res.toString()); + case URL -> new OpenAiUrlImage(res.toString()); }; } diff --git a/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiImageType.java b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiImageType.java index 33f87452d90..be5c0694879 100644 --- a/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiImageType.java +++ b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiImageType.java @@ -46,8 +46,7 @@ public String getValue() { return this.value; } - @Override - public StabilityAiImageType fromValue(String value) { + public static StabilityAiImageType fromValue(final String value) { return Arrays.stream(values()) .filter(v -> v.value.equals(value)) .findAny() diff --git a/spring-ai-core/src/main/java/org/springframework/ai/image/DefaultImageType.java b/spring-ai-core/src/main/java/org/springframework/ai/image/DefaultImageType.java index 14b7e56a12b..7c9f632bf4a 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/image/DefaultImageType.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/image/DefaultImageType.java @@ -38,8 +38,7 @@ public String getValue() { return this.value; } - @Override - public DefaultImageType fromValue(final String value) { + public static DefaultImageType fromValue(final String value) { return Arrays.stream(values()) .filter(v -> v.value.equals(value)) .findAny() diff --git a/spring-ai-core/src/main/java/org/springframework/ai/image/ImageType.java b/spring-ai-core/src/main/java/org/springframework/ai/image/ImageType.java index fcf50c94c0b..0238d0cc911 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/image/ImageType.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/image/ImageType.java @@ -20,10 +20,11 @@ * interface allows for the creation of type-safe enums that can be extended to include * new types of image references. * - * @param The concrete enum type that implements this interface. This type parameter - * enables the enum to use methods defined in this interface in a type-safe manner. - * @param The type of the constants used by the enum implementing this interface. It - * represents the type of the values associated with each enum constant. + * @param The concrete enum type that extends Enum and implements this interface. This + * type parameter allows the enum to be part of the extensible enum pattern and to use + * methods defined in this interface in a type-safe manner. + * @param The type of the value associated with the enum constants. It represents the + * data type of the values that each enum constant holds. *

* Example Usage: *

@@ -43,7 +44,7 @@ * } * */ -public interface ImageType, E> { +public interface ImageType & ImageType, E> { /** * Returns the value associated with the enum constant. @@ -51,13 +52,4 @@ public interface ImageType, E> { */ E getValue(); - /** - * Returns an enum constant of type {@code T} corresponding to the specified value of - * type {@code E}. - * @param value The value of the enum constant to be returned. - * @return An enum constant of type {@code T}. - * @throws IllegalArgumentException if no constant with the specified value is found. - */ - T fromValue(final E value); - } From 35caf03e5caf6ca4efc46c919dbf544ea469b5ec Mon Sep 17 00:00:00 2001 From: youngpar Date: Wed, 27 Mar 2024 18:14:32 +0900 Subject: [PATCH 9/9] feat Add StabilityAi Image Implementations Implemented Image Types and Implementations --- .../image/StabilityAiImageType.java | 2 +- .../image/StabilityAiPngImage.java | 39 +++++++++++++++++++ .../image/StabilityAiWebpImage.java | 39 +++++++++++++++++++ .../stabilityai/image/StabilityJpegImage.java | 39 +++++++++++++++++++ 4 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiPngImage.java create mode 100644 models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiWebpImage.java create mode 100644 models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityJpegImage.java diff --git a/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiImageType.java b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiImageType.java index be5c0694879..d00afd3b742 100644 --- a/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiImageType.java +++ b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiImageType.java @@ -33,7 +33,7 @@ */ public enum StabilityAiImageType implements ImageType { - BASE64("base64"); + BASE64("base64"), PNG("png"), JPEG("jpeg"), WEBP("webp"); private final String value; diff --git a/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiPngImage.java b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiPngImage.java new file mode 100644 index 00000000000..f891ed9cfbe --- /dev/null +++ b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiPngImage.java @@ -0,0 +1,39 @@ +/* + * Copyright 2023 - 2024 the original author or authors. + * + * 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 + * + * https://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 org.springframework.ai.stabilityai.image; + +import org.springframework.ai.image.AbstractImage; + +/** + * Represents an image Png format used within the Stability AI context. This class extends + * {@link AbstractImage} with a specific focus on images that are represented as Bytes of + * Png. It is particularly useful for handling image data that is transmitted over + * networks where binary data needs to be encoded as text. + *

+ * Instances of this class are associated with the {@link StabilityAiImageType#PNG} image + * type, indicating that the image data is in Png format. + *

+ * + * @author youngmon + * @version 0.8.1 + */ +public class StabilityAiPngImage extends AbstractImage { + + StabilityAiPngImage(final String data) { + super(data, StabilityAiImageType.PNG); + } + +} diff --git a/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiWebpImage.java b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiWebpImage.java new file mode 100644 index 00000000000..fa86e71d11a --- /dev/null +++ b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityAiWebpImage.java @@ -0,0 +1,39 @@ +/* + * Copyright 2023 - 2024 the original author or authors. + * + * 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 + * + * https://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 org.springframework.ai.stabilityai.image; + +import org.springframework.ai.image.AbstractImage; + +/** + * Represents an image Webp format used within the Stability AI context. This class + * extends {@link AbstractImage} with a specific focus on images that are represented as + * Bytes of Webp. It is particularly useful for handling image data that is transmitted + * over networks where binary data needs to be encoded as text. + *

+ * Instances of this class are associated with the {@link StabilityAiImageType#WEBP} image + * type, indicating that the image data is in Webp format. + *

+ * + * @author youngmon + * @version 0.8.1 + */ +public class StabilityAiWebpImage extends AbstractImage { + + StabilityAiWebpImage(final String data) { + super(data, StabilityAiImageType.WEBP); + } + +} diff --git a/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityJpegImage.java b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityJpegImage.java new file mode 100644 index 00000000000..8c3422cb64c --- /dev/null +++ b/models/spring-ai-stability-ai/src/main/java/org/springframework/ai/stabilityai/image/StabilityJpegImage.java @@ -0,0 +1,39 @@ +/* + * Copyright 2023 - 2024 the original author or authors. + * + * 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 + * + * https://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 org.springframework.ai.stabilityai.image; + +import org.springframework.ai.image.AbstractImage; + +/** + * Represents an image Jpeg format used within the Stability AI context. This class + * extends {@link AbstractImage} with a specific focus on images that are represented as + * Bytes of Jpeg. It is particularly useful for handling image data that is transmitted + * over networks where binary data needs to be encoded as text. + *

+ * Instances of this class are associated with the {@link StabilityAiImageType#JPEG} image + * type, indicating that the image data is in Jpeg format. + *

+ * + * @author youngmon + * @version 0.8.1 + */ +public class StabilityJpegImage extends AbstractImage { + + StabilityJpegImage(final String data) { + super(data, StabilityAiImageType.JPEG); + } + +}