Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
bf4e0ce
Fix save_img(): support 'jpg' format and handle RGBA
utsab345 Sep 20, 2025
b2a5668
Fix save_img: support 'jpg' format (normalize to JPEG) and add tests
utsab345 Sep 20, 2025
d93f3c5
Fix save_img: normalize jpg→jpeg, handle RGBA→RGB, and improve tests
utsab345 Sep 21, 2025
9ab0b4f
Regenerate API directory
utsab345 Sep 21, 2025
b652534
Add save_img to image_utils.py and integration tests for JPG/RGBA han…
utsab345 Sep 25, 2025
4a6a78e
style: fix formatting with format.sh
utsab345 Sep 30, 2025
2b65f89
Simplify save_img: remove _format, normalize jpg→jpeg, add RGBA→RGB h…
utsab345 Oct 4, 2025
2a5bb21
Merge branch 'keras-team:master' into master
utsab345 Oct 4, 2025
524252e
Simplify save_img: remove _format, normalize jpg→jpeg, add RGBA→RGB h…
utsab345 Oct 4, 2025
97d00f5
Simplify save_img: remove _format, normalize jpg→jpeg, add RGBA→RGB h…
utsab345 Oct 4, 2025
2a24eaa
fix: use save_format variable to avoid modifying file_format parameter
utsab345 Oct 6, 2025
6e0340b
Merge branch 'keras-team:master' into master
utsab345 Oct 8, 2025
5c96717
fix: handle .jpg format without renaming file, improve tests
utsab345 Oct 16, 2025
7b84f95
Merge branch 'keras-team:master' into master
utsab345 Oct 17, 2025
95c3e34
Move save_img tests to unit tests and convert to Keras TestCase
utsab345 Oct 18, 2025
323ca8d
Merge branch 'keras-team:master' into master
utsab345 Oct 18, 2025
29afd91
Move save_img tests to unit tests and convert to Keras TestCase
utsab345 Oct 18, 2025
effc784
Move save_img tests to unit tests and convert to Keras TestCase
utsab345 Oct 18, 2025
305e3d9
Move save_img tests to unit tests and convert to Keras TestCase
utsab345 Oct 18, 2025
913ec5e
Move save_img tests to unit tests and convert to Keras TestCase
utsab345 Oct 18, 2025
1fa75a0
Merge branch 'keras-team:master' into master
utsab345 Oct 25, 2025
80f4d4e
Merge branch 'keras-team:master' into master
utsab345 Oct 28, 2025
ce9e776
fix: simplify file format handling and add inferred format test
utsab345 Oct 28, 2025
4f4e22b
fix: simplify file format handling and add inferred format test
utsab345 Oct 28, 2025
655e9f2
fix: simplify file format handling and add inferred format test
utsab345 Oct 28, 2025
f6b8345
fix: simplify file format handling and add inferred format test
utsab345 Oct 28, 2025
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
15 changes: 15 additions & 0 deletions integration_tests/test_save_img.py
Original file line number Diff line number Diff line change
@@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

These tests are a good start, but they can be improved. The two test functions are very similar and can be combined into a single parameterized test using pytest.mark.parametrize for better maintainability. Also, the assertions only check for file existence. It would be more robust to load the saved image and verify its content, especially to confirm that RGBA images are correctly converted to RGB.

import os

import numpy as np
import pytest
from keras.utils import img_to_array, load_img, save_img


@pytest.mark.parametrize(
    "shape, name",
    [
        ((50, 50, 3), "rgb.jpg"),
        ((50, 50, 4), "rgba.jpg"),
    ],
)
def test_save_jpg(tmp_path, shape, name):
    img = np.random.randint(0, 256, size=shape, dtype=np.uint8)
    path = tmp_path / name
    save_img(path, img, file_format="jpg")
    assert os.path.exists(path)

    # 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)

4 changes: 3 additions & 1 deletion keras/src/utils/image_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This change correctly handles file_format='jpg', but it misses the case where file_format is None and the path ends with .jpg. This will cause a crash when saving an RGBA image. The logic can be made more robust by also inspecting the path extension to determine if the output is a JPEG. Also, the condition on line 181 becomes partially redundant after converting jpg to jpeg.

Suggested change
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"]:
_format = file_format
if _format is None and isinstance(path, (str, pathlib.Path)):
_format = pathlib.Path(path).suffix[1:].lower()
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 _format in ("jpeg", "jpg"):

warnings.warn(
"The JPG format does not support RGBA images, converting to RGB."
)
Expand Down
Loading