diff --git a/presidio-image-redactor/presidio_image_redactor/image_analyzer_engine.py b/presidio-image-redactor/presidio_image_redactor/image_analyzer_engine.py index f8e6a9c922..ad514fc606 100644 --- a/presidio-image-redactor/presidio_image_redactor/image_analyzer_engine.py +++ b/presidio-image-redactor/presidio_image_redactor/image_analyzer_engine.py @@ -390,45 +390,50 @@ def add_custom_bboxes( image_r = 70 fig.set_size_inches(image_x / image_r, image_y / image_r) - if len(bboxes) == 0: - ax.imshow(image_custom) - return image_custom - else: - for box in bboxes: - try: - entity_type = box["entity_type"] - except KeyError: - entity_type = "UNKNOWN" - - try: - if box["is_PII"]: - bbox_color = "r" - else: - bbox_color = "b" - except KeyError: + for box in bboxes: + try: + entity_type = box["entity_type"] + except KeyError: + entity_type = "UNKNOWN" + + try: + if box["is_PII"]: + bbox_color = "r" + else: bbox_color = "b" - - # Get coordinates and dimensions - x0 = box["left"] - y0 = box["top"] - x1 = x0 + box["width"] - y1 = y0 + box["height"] - rect = matplotlib.patches.Rectangle( - (x0, y0), x1 - x0, y1 - y0, edgecolor=bbox_color, facecolor="none" + except KeyError: + bbox_color = "b" + + # Get coordinates and dimensions + x0 = box["left"] + y0 = box["top"] + x1 = x0 + box["width"] + y1 = y0 + box["height"] + rect = matplotlib.patches.Rectangle( + (x0, y0), x1 - x0, y1 - y0, edgecolor=bbox_color, facecolor="none" + ) + ax.add_patch(rect) + if show_text_annotation: + ax.annotate( + entity_type, + xy=(x0 - 3, y0 - 3), + xycoords="data", + bbox=dict(boxstyle="round4,pad=.5", fc="0.9"), ) - ax.add_patch(rect) - if show_text_annotation: - ax.annotate( - entity_type, - xy=(x0 - 3, y0 - 3), - xycoords="data", - bbox=dict(boxstyle="round4,pad=.5", fc="0.9"), - ) - if use_greyscale_cmap: - ax.imshow(image_custom, cmap="gray") - else: - ax.imshow(image_custom) - im_from_fig = cls.fig2img(fig) - im_resized = im_from_fig.resize((image_x, image_y)) + + # When there are no bboxes and no greyscale colormap is needed, return the + # image directly to avoid unnecessary matplotlib rendering overhead and to + # preserve the original image fidelity (e.g. for RGB verification images). + if not bboxes and not use_greyscale_cmap: + plt.close(fig) + return image_custom + + if use_greyscale_cmap: + ax.imshow(image_custom, cmap="gray") + else: + ax.imshow(image_custom) + im_from_fig = cls.fig2img(fig) + im_resized = im_from_fig.resize((image_x, image_y)) + plt.close(fig) return im_resized diff --git a/presidio-image-redactor/tests/test_image_analyzer_engine.py b/presidio-image-redactor/tests/test_image_analyzer_engine.py index d8ef672194..bbc0ed5416 100644 --- a/presidio-image-redactor/tests/test_image_analyzer_engine.py +++ b/presidio-image-redactor/tests/test_image_analyzer_engine.py @@ -251,6 +251,16 @@ def test_get_pii_bboxes_happy_path( @pytest.mark.parametrize( "bboxes, show_text_annotation, use_greyscale_cmap", [ + ( + [], + False, + False, + ), + ( + [], + False, + True, + ), ( [ {"left": 50, "top": 0, "width": 30, "height": 10, "is_PII": True}, @@ -329,15 +339,20 @@ def compare_color(actual_pixels, expected_color, threshold=10): color_match = False return color_match - for dim in test_img_arr: - for pixel in dim: - if compare_color(list(pixel), color_red): - red_pixels += 1 - if compare_color(list(pixel), color_blue): - blue_pixels += 1 + if bboxes: + for dim in test_img_arr: + for pixel in dim: + if compare_color(list(pixel), color_red): + red_pixels += 1 + if compare_color(list(pixel), color_blue): + blue_pixels += 1 # Assert - if is_any_PII: + if not bboxes: + assert test_img is not None + assert isinstance(test_img, PIL.Image.Image) + assert test_img.size == (100, 100) + elif is_any_PII: assert red_pixels > 0 else: assert blue_pixels > 0