1212# See the License for the specific language governing permissions and
1313# limitations under the License.
1414#
15+ # pylint: disable=bad-continuation, line-too-long, protected-access
1516"""Classes for working with vision models."""
1617
1718import base64
@@ -99,15 +100,22 @@ def load_from_file(location: str) -> "Image":
99100 image = Image (image_bytes = image_bytes )
100101 return image
101102
103+ @property
104+ def _blob (self ) -> storage .Blob :
105+ if self ._gcs_uri is None :
106+ raise AttributeError ("_blob is only supported when gcs_uri is set." )
107+ storage_client = storage .Client (
108+ credentials = aiplatform_initializer .global_config .credentials
109+ )
110+ blob = storage .Blob .from_string (uri = self ._gcs_uri , client = storage_client )
111+ # Needed to populate `blob.content_type`
112+ blob .reload ()
113+ return blob
114+
102115 @property
103116 def _image_bytes (self ) -> bytes :
104117 if self ._loaded_bytes is None :
105- storage_client = storage .Client (
106- credentials = aiplatform_initializer .global_config .credentials
107- )
108- self ._loaded_bytes = storage .Blob .from_string (
109- uri = self ._gcs_uri , client = storage_client
110- ).download_as_bytes ()
118+ self ._loaded_bytes = self ._blob .download_as_bytes ()
111119 return self ._loaded_bytes
112120
113121 @_image_bytes .setter
@@ -117,13 +125,27 @@ def _image_bytes(self, value: bytes):
117125 @property
118126 def _pil_image (self ) -> "PIL_Image.Image" :
119127 if self ._loaded_image is None :
128+ if not PIL_Image :
129+ raise RuntimeError (
130+ "The PIL module is not available. Please install the Pillow package."
131+ )
120132 self ._loaded_image = PIL_Image .open (io .BytesIO (self ._image_bytes ))
121133 return self ._loaded_image
122134
123135 @property
124136 def _size (self ):
125137 return self ._pil_image .size
126138
139+ @property
140+ def _mime_type (self ) -> str :
141+ """Returns the MIME type of the image."""
142+ if self ._gcs_uri :
143+ return self ._blob .content_type
144+ if PIL_Image :
145+ return PIL_Image .MIME .get (self ._pil_image .format , "image/jpeg" )
146+ # Fall back to jpeg
147+ return "image/jpeg"
148+
127149 def show (self ):
128150 """Shows the image.
129151
@@ -146,7 +168,7 @@ def _as_base64_string(self) -> str:
146168 Returns:
147169 Base64 encoding of the image as a string.
148170 """
149- # ! b64encode returns `bytes` object, not `` str.
171+ # ! b64encode returns `bytes` object, not `str` .
150172 # We need to convert `bytes` to `str`, otherwise we get service error:
151173 # "received initial metadata size exceeds limit"
152174 return base64 .b64encode (self ._image_bytes ).decode ("ascii" )
@@ -196,21 +218,36 @@ def load_from_file(location: str) -> "Video":
196218 video = Video (video_bytes = video_bytes )
197219 return video
198220
221+ @property
222+ def _blob (self ) -> storage .Blob :
223+ if self ._gcs_uri is None :
224+ raise AttributeError ("_blob is only supported when gcs_uri is set." )
225+ storage_client = storage .Client (
226+ credentials = aiplatform_initializer .global_config .credentials
227+ )
228+ blob = storage .Blob .from_string (uri = self ._gcs_uri , client = storage_client )
229+ # Needed to populate `blob.content_type`
230+ blob .reload ()
231+ return blob
232+
199233 @property
200234 def _video_bytes (self ) -> bytes :
201235 if self ._loaded_bytes is None :
202- storage_client = storage .Client (
203- credentials = aiplatform_initializer .global_config .credentials
204- )
205- self ._loaded_bytes = storage .Blob .from_string (
206- uri = self ._gcs_uri , client = storage_client
207- ).download_as_bytes ()
236+ self ._loaded_bytes = self ._blob .download_as_bytes ()
208237 return self ._loaded_bytes
209238
210239 @_video_bytes .setter
211240 def _video_bytes (self , value : bytes ):
212241 self ._loaded_bytes = value
213242
243+ @property
244+ def _mime_type (self ) -> str :
245+ """Returns the MIME type of the video."""
246+ if self ._gcs_uri :
247+ return self ._blob .content_type
248+ # Fall back to mp4
249+ return "video/mp4"
250+
214251 def save (self , location : str ):
215252 """Saves video to a file.
216253
@@ -225,7 +262,7 @@ def _as_base64_string(self) -> str:
225262 Returns:
226263 Base64 encoding of the video as a string.
227264 """
228- # ! b64encode returns `bytes` object, not `` str.
265+ # ! b64encode returns `bytes` object, not `str` .
229266 # We need to convert `bytes` to `str`, otherwise we get service error:
230267 # "received initial metadata size exceeds limit"
231268 return base64 .b64encode (self ._video_bytes ).decode ("ascii" )
@@ -582,8 +619,7 @@ def generate_images(
582619 * "16:9" : 16:9 aspect ratio
583620 * "4:3" : 4:3 aspect ratio
584621 * "3:4" : 3:4 aspect_ratio
585- guidance_scale: Controls the strength of the prompt. Suggested values
586- are:
622+ guidance_scale: Controls the strength of the prompt. Suggested values are:
587623 * 0-9 (low strength)
588624 * 10-20 (medium strength)
589625 * 21+ (high strength)
@@ -667,8 +703,7 @@ def edit_image(
667703 * 0-9 (low strength)
668704 * 10-20 (medium strength)
669705 * 21+ (high strength)
670- edit_mode: Describes the editing mode for the request. Supported values
671- are:
706+ edit_mode: Describes the editing mode for the request. Supported values are:
672707 * inpainting-insert: fills the mask area based on the text prompt
673708 (requires mask and text)
674709 * inpainting-remove: removes the object(s) in the mask area.
@@ -677,7 +712,6 @@ def edit_image(
677712 (Requires mask)
678713 * product-image: Changes the background for the predominant product
679714 or subject in the image
680- segmentation_classes: List of class IDs for segmentation. Max of 5 IDs
681715 mask_mode: Solicits generation of the mask (v/s providing mask as an
682716 input). Supported values are:
683717 * background: Automatically generates a mask for all regions except
@@ -686,6 +720,7 @@ def edit_image(
686720 subjects(s) of the image.
687721 * semantic: Segment one or more of the segmentation classes using
688722 class ID
723+ segmentation_classes: List of class IDs for segmentation. Max of 5 IDs
689724 mask_dilation: Defines the dilation percentage of the mask provided.
690725 Float between 0 and 1. Defaults to 0.03
691726 product_position: Defines whether the product should stay fixed or be
@@ -1241,7 +1276,7 @@ class WatermarkVerificationResponse:
12411276
12421277
12431278class WatermarkVerificationModel (_model_garden_models ._ModelGardenModel ):
1244- """Verifies if an image has a watermark"""
1279+ """Verifies if an image has a watermark. """
12451280
12461281 __module__ = "vertexai.preview.vision_models"
12471282
0 commit comments