diff --git a/Tests/test_file_apng.py b/Tests/test_file_apng.py index da02b42b25f..c8711afb3e5 100644 --- a/Tests/test_file_apng.py +++ b/Tests/test_file_apng.py @@ -669,11 +669,18 @@ def test_save_all_progress(): out = BytesIO() progress = [] - def callback(filename, frame_number, n_frames): - progress.append((filename, frame_number, n_frames)) + def callback(state): + progress.append(state) Image.new("RGB", (1, 1)).save(out, "PNG", save_all=True, progress=callback) - assert progress == [(0, 1, 1)] + assert progress == [ + { + "image_index": 0, + "image_filename": None, + "completed_frames": 1, + "total_frames": 1, + } + ] out = BytesIO() progress = [] @@ -685,13 +692,48 @@ def callback(filename, frame_number, n_frames): ) assert progress == [ - (0, 1, 7), - (1, 2, 7), - (2, 3, 7), - (2, 4, 7), - (2, 5, 7), - (2, 6, 7), - (2, 7, 7), + { + "image_index": 0, + "image_filename": "Tests/images/apng/single_frame.png", + "completed_frames": 1, + "total_frames": 7, + }, + { + "image_index": 1, + "image_filename": "Tests/images/apng/single_frame.png", + "completed_frames": 2, + "total_frames": 7, + }, + { + "image_index": 2, + "image_filename": "Tests/images/apng/delay.png", + "completed_frames": 3, + "total_frames": 7, + }, + { + "image_index": 2, + "image_filename": "Tests/images/apng/delay.png", + "completed_frames": 4, + "total_frames": 7, + }, + { + "image_index": 2, + "image_filename": "Tests/images/apng/delay.png", + "completed_frames": 5, + "total_frames": 7, + }, + { + "image_index": 2, + "image_filename": "Tests/images/apng/delay.png", + "completed_frames": 6, + "total_frames": 7, + }, + { + "image_index": 2, + "image_filename": "Tests/images/apng/delay.png", + "completed_frames": 7, + "total_frames": 7, + }, ] diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index 7478176dd34..f2d1f499205 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -269,11 +269,18 @@ def test_save_all_progress(): out = BytesIO() progress = [] - def callback(filename, frame_number, n_frames): - progress.append((filename, frame_number, n_frames)) + def callback(state): + progress.append(state) Image.new("RGB", (1, 1)).save(out, "GIF", save_all=True, progress=callback) - assert progress == [(0, 1, 1)] + assert progress == [ + { + "image_index": 0, + "image_filename": None, + "completed_frames": 1, + "total_frames": 1, + } + ] out = BytesIO() progress = [] @@ -282,9 +289,23 @@ def callback(filename, frame_number, n_frames): with Image.open("Tests/images/chi.gif") as im2: im.save(out, "GIF", save_all=True, append_images=[im2], progress=callback) - expected = [(0, 1, 32)] + expected = [ + { + "image_index": 0, + "image_filename": "Tests/images/hopper.gif", + "completed_frames": 1, + "total_frames": 32, + } + ] for i in range(31): - expected.append((1, i + 2, 32)) + expected.append( + { + "image_index": 1, + "image_filename": "Tests/images/chi.gif", + "completed_frames": i + 2, + "total_frames": 32, + } + ) assert progress == expected diff --git a/Tests/test_file_mpo.py b/Tests/test_file_mpo.py index bb659929673..8330506373f 100644 --- a/Tests/test_file_mpo.py +++ b/Tests/test_file_mpo.py @@ -284,11 +284,18 @@ def test_save_all_progress(): out = BytesIO() progress = [] - def callback(filename, frame_number, n_frames): - progress.append((filename, frame_number, n_frames)) + def callback(state): + progress.append(state) Image.new("RGB", (1, 1)).save(out, "MPO", save_all=True, progress=callback) - assert progress == [(0, 1, 1)] + assert progress == [ + { + "image_index": 0, + "image_filename": None, + "completed_frames": 1, + "total_frames": 1, + } + ] out = BytesIO() progress = [] @@ -298,8 +305,28 @@ def callback(filename, frame_number, n_frames): im.save(out, "MPO", save_all=True, append_images=[im2], progress=callback) assert progress == [ - (0, 1, 4), - (0, 2, 4), - (1, 3, 4), - (1, 4, 4), + { + "image_index": 0, + "image_filename": "Tests/images/sugarshack.mpo", + "completed_frames": 1, + "total_frames": 4, + }, + { + "image_index": 0, + "image_filename": "Tests/images/sugarshack.mpo", + "completed_frames": 2, + "total_frames": 4, + }, + { + "image_index": 1, + "image_filename": "Tests/images/frozenpond.mpo", + "completed_frames": 3, + "total_frames": 4, + }, + { + "image_index": 1, + "image_filename": "Tests/images/frozenpond.mpo", + "completed_frames": 4, + "total_frames": 4, + }, ] diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py index 71112ddb462..178c0193fed 100644 --- a/Tests/test_file_pdf.py +++ b/Tests/test_file_pdf.py @@ -173,11 +173,18 @@ def test_save_all_progress(): out = BytesIO() progress = [] - def callback(filename, frame_number, n_frames): - progress.append((filename, frame_number, n_frames)) + def callback(state): + progress.append(state) Image.new("RGB", (1, 1)).save(out, "PDF", save_all=True, progress=callback) - assert progress == [(0, 1, 1)] + assert progress == [ + { + "image_index": 0, + "image_filename": None, + "completed_frames": 1, + "total_frames": 1, + } + ] out = BytesIO() progress = [] @@ -187,10 +194,30 @@ def callback(filename, frame_number, n_frames): im.save(out, "PDF", save_all=True, append_images=[im2], progress=callback) assert progress == [ - (0, 1, 4), - (0, 2, 4), - (1, 3, 4), - (1, 4, 4), + { + "image_index": 0, + "image_filename": "Tests/images/sugarshack.mpo", + "completed_frames": 1, + "total_frames": 4, + }, + { + "image_index": 0, + "image_filename": "Tests/images/sugarshack.mpo", + "completed_frames": 2, + "total_frames": 4, + }, + { + "image_index": 1, + "image_filename": "Tests/images/frozenpond.mpo", + "completed_frames": 3, + "total_frames": 4, + }, + { + "image_index": 1, + "image_filename": "Tests/images/frozenpond.mpo", + "completed_frames": 4, + "total_frames": 4, + }, ] diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index e957f2371dc..6cc4afc70bd 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -692,11 +692,18 @@ def test_save_all_progress(self): out = BytesIO() progress = [] - def callback(filename, frame_number, n_frames): - progress.append((filename, frame_number, n_frames)) + def callback(state): + progress.append(state) Image.new("RGB", (1, 1)).save(out, "TIFF", save_all=True, progress=callback) - assert progress == [(0, 1, 1)] + assert progress == [ + { + "image_index": 0, + "image_filename": None, + "completed_frames": 1, + "total_frames": 1, + } + ] out = BytesIO() progress = [] @@ -708,10 +715,30 @@ def callback(filename, frame_number, n_frames): ) assert progress == [ - (0, 1, 4), - (1, 2, 4), - (1, 3, 4), - (1, 4, 4), + { + "image_index": 0, + "image_filename": "Tests/images/hopper.tif", + "completed_frames": 1, + "total_frames": 4, + }, + { + "image_index": 1, + "image_filename": "Tests/images/multipage.tiff", + "completed_frames": 2, + "total_frames": 4, + }, + { + "image_index": 1, + "image_filename": "Tests/images/multipage.tiff", + "completed_frames": 3, + "total_frames": 4, + }, + { + "image_index": 1, + "image_filename": "Tests/images/multipage.tiff", + "completed_frames": 4, + "total_frames": 4, + }, ] def test_saving_icc_profile(self, tmp_path): diff --git a/Tests/test_file_webp.py b/Tests/test_file_webp.py index 420464e199d..da757237034 100644 --- a/Tests/test_file_webp.py +++ b/Tests/test_file_webp.py @@ -127,11 +127,18 @@ def test_save_all_progress(self): out = BytesIO() progress = [] - def callback(filename, frame_number, n_frames): - progress.append((filename, frame_number, n_frames)) + def callback(state): + progress.append(state) Image.new("RGB", (1, 1)).save(out, "WEBP", save_all=True, progress=callback) - assert progress == [(0, 1, 1)] + assert progress == [ + { + "image_index": 0, + "image_filename": None, + "completed_frames": 1, + "total_frames": 1, + } + ] out = BytesIO() progress = [] @@ -142,8 +149,22 @@ def callback(filename, frame_number, n_frames): expected = [] for i in range(42): - expected.append((0, i + 1, 43)) - expected.append((1, 43, 43)) + expected.append( + { + "image_index": 0, + "image_filename": "Tests/images/iss634.webp", + "completed_frames": i + 1, + "total_frames": 43, + } + ) + expected.append( + { + "image_index": 1, + "image_filename": None, + "completed_frames": 43, + "total_frames": 43, + } + ) assert progress == expected def test_icc_profile(self, tmp_path): diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 7d2d9c3ae1e..56cfec4e4d3 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -618,7 +618,14 @@ def _write_multiple_frames(im, fp, palette): if encoderinfo.get("duration"): previous["encoderinfo"]["duration"] += encoderinfo["duration"] if progress: - progress(i, frame_count, n_frames) + progress( + { + "image_index": i, + "image_filename": getattr(imSequence, "filename", None), + "completed_frames": frame_count, + "total_frames": n_frames, + } + ) continue if encoderinfo.get("disposal") == 2: if background_im is None: @@ -633,7 +640,14 @@ def _write_multiple_frames(im, fp, palette): bbox = None im_frames.append({"im": im_frame, "bbox": bbox, "encoderinfo": encoderinfo}) if progress: - progress(i, frame_count, n_frames) + progress( + { + "image_index": i, + "image_filename": getattr(imSequence, "filename", None), + "completed_frames": frame_count, + "total_frames": n_frames, + } + ) if len(im_frames) > 1: for frame_data in im_frames: diff --git a/src/PIL/MpoImagePlugin.py b/src/PIL/MpoImagePlugin.py index 4a9498c8b84..509ec340a06 100644 --- a/src/PIL/MpoImagePlugin.py +++ b/src/PIL/MpoImagePlugin.py @@ -51,7 +51,14 @@ def _save_all(im, fp, filename): if not animated: _save(im, fp, filename) if progress: - progress(0, 1, 1) + progress( + { + "image_index": 0, + "image_filename": getattr(im, "filename", None), + "completed_frames": 1, + "total_frames": 1, + } + ) return mpf_offset = 28 @@ -83,7 +90,14 @@ def _save_all(im, fp, filename): offsets.append(fp.tell() - offsets[-1]) if progress: frame_number += 1 - progress(i, frame_number, n_frames) + progress( + { + "image_index": i, + "image_filename": getattr(imSequence, "filename", None), + "completed_frames": frame_number, + "total_frames": n_frames, + } + ) ifd = TiffImagePlugin.ImageFileDirectory_v2() ifd[0xB000] = b"0100" diff --git a/src/PIL/PdfImagePlugin.py b/src/PIL/PdfImagePlugin.py index 27e79bd8bf2..9b87f30ce17 100644 --- a/src/PIL/PdfImagePlugin.py +++ b/src/PIL/PdfImagePlugin.py @@ -283,7 +283,14 @@ def _save(im, fp, filename, save_all=False): page_number += 1 if progress: - progress(i, page_number, number_of_pages) + progress( + { + "image_index": i, + "image_filename": getattr(im_sequence, "filename", None), + "completed_frames": page_number, + "total_frames": number_of_pages, + } + ) # # trailer diff --git a/src/PIL/PngImagePlugin.py b/src/PIL/PngImagePlugin.py index 8d2173dc76e..6a44f1b6ef9 100644 --- a/src/PIL/PngImagePlugin.py +++ b/src/PIL/PngImagePlugin.py @@ -1155,7 +1155,14 @@ def _write_multiple_frames(im, fp, chunk, rawmode, default_image, append_images) "duration", duration ) if progress: - progress(i, frame_count, n_frames) + progress( + { + "image_index": i, + "image_filename": getattr(imSequence, "filename", None), + "completed_frames": frame_count, + "total_frames": n_frames, + } + ) continue else: bbox = None @@ -1163,7 +1170,14 @@ def _write_multiple_frames(im, fp, chunk, rawmode, default_image, append_images) encoderinfo["duration"] = duration im_frames.append({"im": im_frame, "bbox": bbox, "encoderinfo": encoderinfo}) if progress: - progress(i, frame_count, n_frames) + progress( + { + "image_index": i, + "image_filename": getattr(imSequence, "filename", None), + "completed_frames": frame_count, + "total_frames": n_frames, + } + ) # animation control chunk( diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index 71af42b757e..29968de285c 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -2122,7 +2122,14 @@ def _save_all(im, fp, filename): if not hasattr(im, "n_frames") and not append_images: _save(im, fp, filename) if progress: - progress(0, 1, 1) + progress( + { + "image_index": 0, + "image_filename": getattr(im, "filename", None), + "completed_frames": 1, + "total_frames": 1, + } + ) return cur_idx = im.tell() @@ -2148,7 +2155,14 @@ def _save_all(im, fp, filename): _save(ims, tf, filename) if progress: frame_number += 1 - progress(i, frame_number, n_frames) + progress( + { + "image_index": i, + "image_filename": getattr(ims, "filename", None), + "completed_frames": frame_number, + "total_frames": n_frames, + } + ) tf.newFrame() finally: diff --git a/src/PIL/WebPImagePlugin.py b/src/PIL/WebPImagePlugin.py index c3113ea89af..ba92bb30453 100644 --- a/src/PIL/WebPImagePlugin.py +++ b/src/PIL/WebPImagePlugin.py @@ -188,7 +188,14 @@ def _save_all(im, fp, filename): if total == 1: _save(im, fp, filename) if progress: - progress(0, 1, 1) + progress( + { + "image_index": 0, + "image_filename": getattr(im, "filename", None), + "completed_frames": 1, + "total_frames": 1, + } + ) return background = (0, 0, 0, 0) @@ -304,7 +311,14 @@ def _save_all(im, fp, filename): timestamp += duration frame_idx += 1 if progress: - progress(i, frame_idx, total) + progress( + { + "image_index": i, + "image_filename": getattr(ims, "filename", None), + "completed_frames": frame_idx, + "total_frames": total, + } + ) finally: im.seek(cur_idx)