From bf4e0ce7ec7aec43b1932a931309f3b8710d719c Mon Sep 17 00:00:00 2001 From: Utsab Dahal Date: Sat, 20 Sep 2025 22:12:53 +0545 Subject: [PATCH 1/9] Fix save_img(): support 'jpg' format and handle RGBA --- integration_tests/test_save_img.py | 15 +++++++++++++++ keras/src/utils/image_utils.py | 4 +++- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 integration_tests/test_save_img.py diff --git a/integration_tests/test_save_img.py b/integration_tests/test_save_img.py new file mode 100644 index 000000000000..c0691bfa6fa4 --- /dev/null +++ b/integration_tests/test_save_img.py @@ -0,0 +1,15 @@ +import numpy as np +import os +from keras.utils import save_img + +def test_save_jpg_rgb(tmp_path): + img = np.random.randint(0, 256, size=(50, 50, 3), dtype=np.uint8) + path = tmp_path / "rgb.jpg" + save_img(path, img, file_format="jpg") + assert os.path.exists(path) + +def test_save_jpg_rgba(tmp_path): + img = np.random.randint(0, 256, size=(50, 50, 4), dtype=np.uint8) + path = tmp_path / "rgba.jpg" + save_img(path, img, file_format="jpg") + assert os.path.exists(path) diff --git a/keras/src/utils/image_utils.py b/keras/src/utils/image_utils.py index ca8289c9f9b7..c2cfd2354262 100644 --- a/keras/src/utils/image_utils.py +++ b/keras/src/utils/image_utils.py @@ -175,8 +175,10 @@ def save_img(path, x, data_format=None, file_format=None, scale=True, **kwargs): **kwargs: Additional keyword arguments passed to `PIL.Image.save()`. """ data_format = backend.standardize_data_format(data_format) + if file_format is not None and file_format.lower() == 'jpg': + file_format = 'jpeg' img = array_to_img(x, data_format=data_format, scale=scale) - if img.mode == "RGBA" and (file_format == "jpg" or file_format == "jpeg"): + if img.mode == "RGBA" and file_format in ["jpeg", "jpg"]: warnings.warn( "The JPG format does not support RGBA images, converting to RGB." ) From b2a56683408d2182b7b7f9662b1ed39cc05c65e0 Mon Sep 17 00:00:00 2001 From: Utsab Dahal Date: Sat, 20 Sep 2025 22:31:14 +0545 Subject: [PATCH 2/9] Fix save_img: support 'jpg' format (normalize to JPEG) and add tests --- integration_tests/test_save_img.py | 29 +++++++++++++++++++++++++---- keras/src/utils/image_utils.py | 21 ++++++++++++++++----- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/integration_tests/test_save_img.py b/integration_tests/test_save_img.py index c0691bfa6fa4..bf4a358ef55d 100644 --- a/integration_tests/test_save_img.py +++ b/integration_tests/test_save_img.py @@ -1,15 +1,36 @@ import numpy as np import os +import pytest from keras.utils import save_img -def test_save_jpg_rgb(tmp_path): + +def test_save_jpg_rgb_with_format(tmp_path): + """Saving RGB image with explicit file_format='jpg'.""" img = np.random.randint(0, 256, size=(50, 50, 3), dtype=np.uint8) - path = tmp_path / "rgb.jpg" + path = tmp_path / "rgb_explicit.jpg" save_img(path, img, file_format="jpg") assert os.path.exists(path) -def test_save_jpg_rgba(tmp_path): + +def test_save_jpg_rgb_infer_from_extension(tmp_path): + """Saving RGB image where format is inferred from .jpg extension.""" + img = np.random.randint(0, 256, size=(50, 50, 3), dtype=np.uint8) + path = tmp_path / "rgb_infer.jpg" + save_img(path, img) # no file_format passed + assert os.path.exists(path) + + +def test_save_jpg_rgba_with_format(tmp_path): + """Saving RGBA image with explicit file_format='jpg' (should auto-convert).""" img = np.random.randint(0, 256, size=(50, 50, 4), dtype=np.uint8) - path = tmp_path / "rgba.jpg" + path = tmp_path / "rgba_explicit.jpg" save_img(path, img, file_format="jpg") assert os.path.exists(path) + + +def test_save_jpg_rgba_infer_from_extension(tmp_path): + """Saving RGBA image where format is inferred from .jpg extension (should auto-convert).""" + img = np.random.randint(0, 256, size=(50, 50, 4), dtype=np.uint8) + path = tmp_path / "rgba_infer.jpg" + save_img(path, img) # no file_format passed + assert os.path.exists(path) diff --git a/keras/src/utils/image_utils.py b/keras/src/utils/image_utils.py index c2cfd2354262..e036d1ef14b3 100644 --- a/keras/src/utils/image_utils.py +++ b/keras/src/utils/image_utils.py @@ -175,16 +175,27 @@ def save_img(path, x, data_format=None, file_format=None, scale=True, **kwargs): **kwargs: Additional keyword arguments passed to `PIL.Image.save()`. """ data_format = backend.standardize_data_format(data_format) - if file_format is not None and file_format.lower() == 'jpg': - file_format = 'jpeg' + + # Determine format: prioritize explicit param, otherwise infer from path + _format = file_format + if _format is None and isinstance(path, (str, pathlib.Path)): + suffix = pathlib.Path(path).suffix.lower() + if suffix.startswith("."): + suffix = suffix[1:] + _format = suffix + + if _format is not None and _format.lower() in ["jpg", "jpeg"]: + _format = "JPEG" + img = array_to_img(x, data_format=data_format, scale=scale) - if img.mode == "RGBA" and file_format in ["jpeg", "jpg"]: + + if _format == "JPEG" and img.mode == "RGBA": warnings.warn( - "The JPG format does not support RGBA images, converting to RGB." + "The JPEG format does not support RGBA images, converting to RGB." ) img = img.convert("RGB") - img.save(path, format=file_format, **kwargs) + img.save(path, format=_format, **kwargs) @keras_export(["keras.utils.load_img", "keras.preprocessing.image.load_img"]) def load_img( From d93f3c569688e30f9f82d3f368a2ada01e8af233 Mon Sep 17 00:00:00 2001 From: Utsab Dahal Date: Sun, 21 Sep 2025 19:47:13 +0545 Subject: [PATCH 3/9] =?UTF-8?q?Fix=20save=5Fimg:=20normalize=20jpg?= =?UTF-8?q?=E2=86=92jpeg,=20handle=20RGBA=E2=86=92RGB,=20and=20improve=20t?= =?UTF-8?q?ests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- integration_tests/test_save_img.py | 55 ++++++++++++++---------------- keras/src/utils/image_utils.py | 30 +++++++++------- 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/integration_tests/test_save_img.py b/integration_tests/test_save_img.py index bf4a358ef55d..f04e09cc477c 100644 --- a/integration_tests/test_save_img.py +++ b/integration_tests/test_save_img.py @@ -1,36 +1,31 @@ -import numpy as np import os +import numpy as np import pytest -from keras.utils import save_img - - -def test_save_jpg_rgb_with_format(tmp_path): - """Saving RGB image with explicit file_format='jpg'.""" - img = np.random.randint(0, 256, size=(50, 50, 3), dtype=np.uint8) - path = tmp_path / "rgb_explicit.jpg" - save_img(path, img, file_format="jpg") - assert os.path.exists(path) - - -def test_save_jpg_rgb_infer_from_extension(tmp_path): - """Saving RGB image where format is inferred from .jpg extension.""" - img = np.random.randint(0, 256, size=(50, 50, 3), dtype=np.uint8) - path = tmp_path / "rgb_infer.jpg" - save_img(path, img) # no file_format passed - assert os.path.exists(path) - - -def test_save_jpg_rgba_with_format(tmp_path): - """Saving RGBA image with explicit file_format='jpg' (should auto-convert).""" - img = np.random.randint(0, 256, size=(50, 50, 4), dtype=np.uint8) - path = tmp_path / "rgba_explicit.jpg" +from keras.utils import save_img, load_img, img_to_array + + +@pytest.mark.parametrize( + "shape, filename", + [ + ((50, 50, 3), "rgb.jpg"), + ((50, 50, 4), "rgba.jpg"), + ((50, 50, 3), "rgb.jpeg"), + ((50, 50, 4), "rgba.jpeg"), + ], +) +def test_save_img_jpg_and_jpeg(tmp_path, shape, filename): + # Create random RGB or RGBA image + img = np.random.randint(0, 256, size=shape, dtype=np.uint8) + path = tmp_path / filename + + # Save using explicit format save_img(path, img, file_format="jpg") assert os.path.exists(path) + # Load back and check shape (RGBA → RGB if JPEG) + loaded_img = load_img(path) + loaded_array = img_to_array(loaded_img) -def test_save_jpg_rgba_infer_from_extension(tmp_path): - """Saving RGBA image where format is inferred from .jpg extension (should auto-convert).""" - img = np.random.randint(0, 256, size=(50, 50, 4), dtype=np.uint8) - path = tmp_path / "rgba_infer.jpg" - save_img(path, img) # no file_format passed - assert os.path.exists(path) + # Always 3 channels after save (JPEG does not support RGBA) + assert loaded_array.shape == (50, 50, 3) + assert loaded_array.dtype == np.float32 # keras.load_img returns float32 diff --git a/keras/src/utils/image_utils.py b/keras/src/utils/image_utils.py index e036d1ef14b3..78e28dd93798 100644 --- a/keras/src/utils/image_utils.py +++ b/keras/src/utils/image_utils.py @@ -70,8 +70,7 @@ def array_to_img(x, data_format=None, scale=True, dtype=None): dtype = backend.floatx() if pil_image is None: raise ImportError( - "Could not import PIL.Image. " - "The use of `array_to_img` requires PIL." + "Could not import PIL.Image. " "The use of `array_to_img` requires PIL." ) x = np.asarray(x, dtype=dtype) if x.ndim != 3: @@ -184,18 +183,27 @@ def save_img(path, x, data_format=None, file_format=None, scale=True, **kwargs): suffix = suffix[1:] _format = suffix - if _format is not None and _format.lower() in ["jpg", "jpeg"]: - _format = "JPEG" + # Normalize 'jpg' to 'jpeg' for Pillow compatibility + if _format is not None and _format.lower() == "jpg": + _format = "jpeg" img = array_to_img(x, data_format=data_format, scale=scale) - if _format == "JPEG" and img.mode == "RGBA": + # Handle RGBA to RGB conversion for JPEG format + if _format and _format.lower() == "jpeg" and img.mode == "RGBA": warnings.warn( "The JPEG format does not support RGBA images, converting to RGB." ) img = img.convert("RGB") - img.save(path, format=_format, **kwargs) + # Use the original file_format parameter if it was provided, + # otherwise use _format + save_format = file_format if file_format is not None else _format + if save_format and save_format.lower() == "jpg": + save_format = "jpeg" + + img.save(path, format=save_format, **kwargs) + @keras_export(["keras.utils.load_img", "keras.preprocessing.image.load_img"]) def load_img( @@ -248,9 +256,7 @@ def load_img( with open(path, "rb") as f: img = pil_image.open(io.BytesIO(f.read())) else: - raise TypeError( - f"path should be path-like or io.BytesIO, not {type(path)}" - ) + raise TypeError(f"path should be path-like or io.BytesIO, not {type(path)}") if color_mode == "grayscale": # if image is not already an 8-bit, 16-bit or 32-bit grayscale image @@ -408,8 +414,7 @@ def smart_resize( crop_box_wstart = int(float(width - crop_width) / 2) else: crop_height = backend_module.cast( - backend_module.cast(width * target_height, "float32") - / target_width, + backend_module.cast(width * target_height, "float32") / target_width, "int32", ) crop_height = backend_module.numpy.minimum(height, crop_height) @@ -417,8 +422,7 @@ def smart_resize( crop_height = backend_module.cast(crop_height, "int32") crop_width = backend_module.cast( - backend_module.cast(height * target_width, "float32") - / target_height, + backend_module.cast(height * target_width, "float32") / target_height, "int32", ) crop_width = backend_module.numpy.minimum(width, crop_width) From 9ab0b4f1f8b2a9567f69a782735325ba9e39cfeb Mon Sep 17 00:00:00 2001 From: Utsab Dahal Date: Sun, 21 Sep 2025 20:35:36 +0545 Subject: [PATCH 4/9] Regenerate API directory --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index afd700b49952..416f213f2c82 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ __pycache__ **/.vscode test/** **/.vscode-smoke/** **/.venv*/ +venv bin/** build/** obj/** From b652534999d52f6c3fce29667bef0e9e25089ac4 Mon Sep 17 00:00:00 2001 From: Utsab Dahal Date: Thu, 25 Sep 2025 17:32:03 +0545 Subject: [PATCH 5/9] Add save_img to image_utils.py and integration tests for JPG/RGBA handling --- integration_tests/test_save_img.py | 21 +++++++-------------- keras/src/utils/image_utils.py | 17 +++++++++-------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/integration_tests/test_save_img.py b/integration_tests/test_save_img.py index f04e09cc477c..04179e74f065 100644 --- a/integration_tests/test_save_img.py +++ b/integration_tests/test_save_img.py @@ -1,31 +1,24 @@ import os + import numpy as np import pytest -from keras.utils import save_img, load_img, img_to_array +from keras.utils import img_to_array, load_img, save_img @pytest.mark.parametrize( - "shape, filename", + "shape, name", [ ((50, 50, 3), "rgb.jpg"), ((50, 50, 4), "rgba.jpg"), - ((50, 50, 3), "rgb.jpeg"), - ((50, 50, 4), "rgba.jpeg"), ], ) -def test_save_img_jpg_and_jpeg(tmp_path, shape, filename): - # Create random RGB or RGBA image +def test_save_jpg(tmp_path, shape, name): img = np.random.randint(0, 256, size=shape, dtype=np.uint8) - path = tmp_path / filename - - # Save using explicit format + path = tmp_path / name save_img(path, img, file_format="jpg") assert os.path.exists(path) - # Load back and check shape (RGBA → RGB if JPEG) + # Check that the image was saved correctly and converted to RGB if needed. loaded_img = load_img(path) loaded_array = img_to_array(loaded_img) - - # Always 3 channels after save (JPEG does not support RGBA) - assert loaded_array.shape == (50, 50, 3) - assert loaded_array.dtype == np.float32 # keras.load_img returns float32 + assert loaded_array.shape == (50, 50, 3) \ No newline at end of file diff --git a/keras/src/utils/image_utils.py b/keras/src/utils/image_utils.py index 78e28dd93798..b735ccdcfd18 100644 --- a/keras/src/utils/image_utils.py +++ b/keras/src/utils/image_utils.py @@ -175,7 +175,7 @@ def save_img(path, x, data_format=None, file_format=None, scale=True, **kwargs): """ data_format = backend.standardize_data_format(data_format) - # Determine format: prioritize explicit param, otherwise infer from path + # Determine output format _format = file_format if _format is None and isinstance(path, (str, pathlib.Path)): suffix = pathlib.Path(path).suffix.lower() @@ -183,28 +183,29 @@ def save_img(path, x, data_format=None, file_format=None, scale=True, **kwargs): suffix = suffix[1:] _format = suffix - # Normalize 'jpg' to 'jpeg' for Pillow compatibility + # Normalize jpg → jpeg for both file_format and _format + if file_format is not None and file_format.lower() == "jpg": + file_format = "jpeg" if _format is not None and _format.lower() == "jpg": _format = "jpeg" + # Convert array to PIL Image img = array_to_img(x, data_format=data_format, scale=scale) - # Handle RGBA to RGB conversion for JPEG format - if _format and _format.lower() == "jpeg" and img.mode == "RGBA": + # Handle RGBA → RGB if saving to JPEG + if img.mode == "RGBA" and (_format in ("jpeg", "jpg")): warnings.warn( "The JPEG format does not support RGBA images, converting to RGB." ) img = img.convert("RGB") - # Use the original file_format parameter if it was provided, - # otherwise use _format + # Finalize save format (explicit file_format wins) save_format = file_format if file_format is not None else _format - if save_format and save_format.lower() == "jpg": - save_format = "jpeg" img.save(path, format=save_format, **kwargs) + @keras_export(["keras.utils.load_img", "keras.preprocessing.image.load_img"]) def load_img( path, From 4a6a78e69571354a991754ebb9c68e21647ab35a Mon Sep 17 00:00:00 2001 From: Utsab Dahal Date: Tue, 30 Sep 2025 19:15:16 +0545 Subject: [PATCH 6/9] style: fix formatting with format.sh --- integration_tests/test_save_img.py | 7 +++++-- keras/src/utils/image_utils.py | 14 +++++++++----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/integration_tests/test_save_img.py b/integration_tests/test_save_img.py index 04179e74f065..6ec7951564cb 100644 --- a/integration_tests/test_save_img.py +++ b/integration_tests/test_save_img.py @@ -2,7 +2,10 @@ import numpy as np import pytest -from keras.utils import img_to_array, load_img, save_img + +from keras.utils import img_to_array +from keras.utils import load_img +from keras.utils import save_img @pytest.mark.parametrize( @@ -21,4 +24,4 @@ def test_save_jpg(tmp_path, shape, name): # Check that the image was saved correctly and converted to RGB if needed. loaded_img = load_img(path) loaded_array = img_to_array(loaded_img) - assert loaded_array.shape == (50, 50, 3) \ No newline at end of file + assert loaded_array.shape == (50, 50, 3) diff --git a/keras/src/utils/image_utils.py b/keras/src/utils/image_utils.py index b735ccdcfd18..64a6dc909593 100644 --- a/keras/src/utils/image_utils.py +++ b/keras/src/utils/image_utils.py @@ -70,7 +70,8 @@ def array_to_img(x, data_format=None, scale=True, dtype=None): dtype = backend.floatx() if pil_image is None: raise ImportError( - "Could not import PIL.Image. " "The use of `array_to_img` requires PIL." + "Could not import PIL.Image. " + "The use of `array_to_img` requires PIL." ) x = np.asarray(x, dtype=dtype) if x.ndim != 3: @@ -205,7 +206,6 @@ def save_img(path, x, data_format=None, file_format=None, scale=True, **kwargs): img.save(path, format=save_format, **kwargs) - @keras_export(["keras.utils.load_img", "keras.preprocessing.image.load_img"]) def load_img( path, @@ -257,7 +257,9 @@ def load_img( with open(path, "rb") as f: img = pil_image.open(io.BytesIO(f.read())) else: - raise TypeError(f"path should be path-like or io.BytesIO, not {type(path)}") + raise TypeError( + f"path should be path-like or io.BytesIO, not {type(path)}" + ) if color_mode == "grayscale": # if image is not already an 8-bit, 16-bit or 32-bit grayscale image @@ -415,7 +417,8 @@ def smart_resize( crop_box_wstart = int(float(width - crop_width) / 2) else: crop_height = backend_module.cast( - backend_module.cast(width * target_height, "float32") / target_width, + backend_module.cast(width * target_height, "float32") + / target_width, "int32", ) crop_height = backend_module.numpy.minimum(height, crop_height) @@ -423,7 +426,8 @@ def smart_resize( crop_height = backend_module.cast(crop_height, "int32") crop_width = backend_module.cast( - backend_module.cast(height * target_width, "float32") / target_height, + backend_module.cast(height * target_width, "float32") + / target_height, "int32", ) crop_width = backend_module.numpy.minimum(width, crop_width) From 524252e4983b3b60ddc0015b24d878a4ddd24e65 Mon Sep 17 00:00:00 2001 From: Utsab Dahal Date: Sat, 4 Oct 2025 18:11:35 +0545 Subject: [PATCH 7/9] =?UTF-8?q?Simplify=20save=5Fimg:=20remove=20=5Fformat?= =?UTF-8?q?,=20normalize=20jpg=E2=86=92jpeg,=20add=20RGBA=E2=86=92RGB=20ha?= =?UTF-8?q?ndling=20and=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- keras/src/utils/image_utils.py | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/keras/src/utils/image_utils.py b/keras/src/utils/image_utils.py index 64a6dc909593..111cfff0ab1a 100644 --- a/keras/src/utils/image_utils.py +++ b/keras/src/utils/image_utils.py @@ -176,34 +176,20 @@ def save_img(path, x, data_format=None, file_format=None, scale=True, **kwargs): """ data_format = backend.standardize_data_format(data_format) - # Determine output format - _format = file_format - if _format is None and isinstance(path, (str, pathlib.Path)): - suffix = pathlib.Path(path).suffix.lower() - if suffix.startswith("."): - suffix = suffix[1:] - _format = suffix - - # Normalize jpg → jpeg for both file_format and _format + # Normalize jpg → jpeg if file_format is not None and file_format.lower() == "jpg": file_format = "jpeg" - if _format is not None and _format.lower() == "jpg": - _format = "jpeg" # Convert array to PIL Image img = array_to_img(x, data_format=data_format, scale=scale) # Handle RGBA → RGB if saving to JPEG - if img.mode == "RGBA" and (_format in ("jpeg", "jpg")): + if img.mode == "RGBA" and file_format in ("jpeg", "jpg"): warnings.warn( "The JPEG format does not support RGBA images, converting to RGB." ) img = img.convert("RGB") - - # Finalize save format (explicit file_format wins) - save_format = file_format if file_format is not None else _format - - img.save(path, format=save_format, **kwargs) + img.save(path, format=file_format, **kwargs) @keras_export(["keras.utils.load_img", "keras.preprocessing.image.load_img"]) From 97d00f51b8135ada29d371ee397a3e8adf239164 Mon Sep 17 00:00:00 2001 From: Utsab Dahal Date: Sat, 4 Oct 2025 18:11:35 +0545 Subject: [PATCH 8/9] =?UTF-8?q?Simplify=20save=5Fimg:=20remove=20=5Fformat?= =?UTF-8?q?,=20normalize=20jpg=E2=86=92jpeg,=20add=20RGBA=E2=86=92RGB=20ha?= =?UTF-8?q?ndling=20and=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- keras/src/utils/image_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keras/src/utils/image_utils.py b/keras/src/utils/image_utils.py index 111cfff0ab1a..bba91448c916 100644 --- a/keras/src/utils/image_utils.py +++ b/keras/src/utils/image_utils.py @@ -176,7 +176,7 @@ def save_img(path, x, data_format=None, file_format=None, scale=True, **kwargs): """ data_format = backend.standardize_data_format(data_format) - # Normalize jpg → jpeg + # Normalize jpg → jpeg if file_format is not None and file_format.lower() == "jpg": file_format = "jpeg" From 2a24eaa938a8a33fdaca16c679a20f49be7f5284 Mon Sep 17 00:00:00 2001 From: Utsab Dahal Date: Mon, 6 Oct 2025 11:21:28 +0545 Subject: [PATCH 9/9] fix: use save_format variable to avoid modifying file_format parameter --- keras/src/utils/image_utils.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/keras/src/utils/image_utils.py b/keras/src/utils/image_utils.py index bba91448c916..4ff3e3454c6c 100644 --- a/keras/src/utils/image_utils.py +++ b/keras/src/utils/image_utils.py @@ -176,20 +176,27 @@ def save_img(path, x, data_format=None, file_format=None, scale=True, **kwargs): """ data_format = backend.standardize_data_format(data_format) - # Normalize jpg → jpeg + # Determine the actual save format (normalize jpg → jpeg for internal use) + save_format = file_format if file_format is not None and file_format.lower() == "jpg": - file_format = "jpeg" + save_format = "jpeg" + elif file_format is None and isinstance(path, (str, pathlib.Path)): + # Infer format from file extension + ext = pathlib.Path(path).suffix[1:].lower() + if ext == "jpg": + save_format = "jpeg" # Convert array to PIL Image img = array_to_img(x, data_format=data_format, scale=scale) # Handle RGBA → RGB if saving to JPEG - if img.mode == "RGBA" and file_format in ("jpeg", "jpg"): + if img.mode == "RGBA" and save_format == "jpeg": warnings.warn( "The JPEG format does not support RGBA images, converting to RGB." ) img = img.convert("RGB") - img.save(path, format=file_format, **kwargs) + + img.save(path, format=save_format, **kwargs) @keras_export(["keras.utils.load_img", "keras.preprocessing.image.load_img"])