From 66da2d165481d3e0c5c153a788b26aa23cc0ad97 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sun, 13 Jun 2021 22:15:05 +0200 Subject: Fix hole transparency in aperture macros --- .../tests/golden/example_am_exposure_modifier.png | Bin 10091 -> 6198 bytes .../resources/example_am_exposure_modifier.gbr | 16 +++--- gerbonara/gerber/tests/test_cairo_backend.py | 61 ++++++++++++++++++--- 3 files changed, 62 insertions(+), 15 deletions(-) (limited to 'gerbonara/gerber/tests') diff --git a/gerbonara/gerber/tests/golden/example_am_exposure_modifier.png b/gerbonara/gerber/tests/golden/example_am_exposure_modifier.png index dac951f..5ba3d7b 100644 Binary files a/gerbonara/gerber/tests/golden/example_am_exposure_modifier.png and b/gerbonara/gerber/tests/golden/example_am_exposure_modifier.png differ diff --git a/gerbonara/gerber/tests/resources/example_am_exposure_modifier.gbr b/gerbonara/gerber/tests/resources/example_am_exposure_modifier.gbr index 5f3f3dd..3f0b46f 100644 --- a/gerbonara/gerber/tests/resources/example_am_exposure_modifier.gbr +++ b/gerbonara/gerber/tests/resources/example_am_exposure_modifier.gbr @@ -1,16 +1,16 @@ G04 Umaco example for exposure modifier and clearing area* %FSLAX26Y26*% -%MOIN*% -%AMSQUAREWITHHOLE* -21,0.1,1,1,0,0,0* -1,0,0.5,0,0*% -%ADD10SQUAREWITHHOLE*% +%MOMM*% +%AMSquareWithHole* +21,1,10,10,0,0,0* +1,0,5,0,0*% +%ADD10SquareWithHole*% %ADD11C,1*% G01* %LPD*% D11* -X-1000000Y-250000D02* -X1000000Y250000D01* +X-08939393Y-2500000D02* +X08939393Y2500000D01* D10* X0Y0D03* -M02* \ No newline at end of file +M02* diff --git a/gerbonara/gerber/tests/test_cairo_backend.py b/gerbonara/gerber/tests/test_cairo_backend.py index b4b8ce3..d0386d8 100644 --- a/gerbonara/gerber/tests/test_cairo_backend.py +++ b/gerbonara/gerber/tests/test_cairo_backend.py @@ -7,6 +7,7 @@ import shutil import io import tempfile import uuid +import cv2 from pathlib import Path import pytest @@ -201,12 +202,16 @@ def test_holes_dont_clear(): ) -def _DISABLED_test_render_am_exposure_modifier(): +def test_render_am_exposure_modifier(): """Umaco example that an aperture macro with a hole does not clear the area""" _test_render( "resources/example_am_exposure_modifier.gbr", "golden/example_am_exposure_modifier.png", + scale = 50, + autocrop_golden = True, + auto_contrast = True, + max_delta = 0.005 # Take artifacts due to differences in anti-aliasing and thresholding into account ) @@ -252,19 +257,59 @@ def test_fine_lines_x(): def _resolve_path(path): return os.path.join(os.path.dirname(__file__), path) -def images_match(reference, output, max_delta): +def images_match(reference, output, max_delta, autocrop_golden=False, auto_contrast=False): global output_dir ref, out = Image.open(reference), Image.open(output) + if ref.mode == 'P': # palette mode + ref = ref.convert('RGB') + ref, out = np.array(ref), np.array(out) # convert to grayscale ref, out = ref.astype(float).mean(axis=2), out.astype(float).mean(axis=2) + + if autocrop_golden: + rows = ref.sum(axis=1) + cols = ref.sum(axis=0) + + x0 = np.argmax(cols > 0) + y0 = np.argmax(rows > 0) + x1 = len(cols) - np.argmax(cols[::-1] > 0) + y1 = len(rows) - np.argmax(rows[::-1] > 0) + print(f'{x0=} {y0=} {x1=} {y1=}') + + ref = ref[y0:y1, x0:x1] + ref = cv2.resize(ref, dsize=out.shape[::-1], interpolation=cv2.INTER_LINEAR) + + def print_stats(name, ref): + print(name, 'stats:', ref.min(), ref.mean(), ref.max(), 'std:', ref.std()) + + if auto_contrast: + print_stats('ref pre proc', ref) + print_stats('out pre proc', out) + + ref -= ref.min() + ref /= ref.max() + ref *= 255 + + out -= out.min() + out /= out.max() + out *= 255 + + def write_refout(): + nonlocal autocrop_golden, ref + if autocrop_golden: + global output_dir + with output_dir.create(suffix='.png') as ref_out: + cv2.imwrite(str(ref_out), ref) + print('Processed reference image:', ref_out) if ref.shape != out.shape: - print(f'Rendering image size mismatch') + print(f'Rendering image size mismatch: {ref.shape} != {out.shape}') print(f'Reference image: {Path(reference).absolute()}') print(f'Actual output: {output}') + write_refout() output_dir.keep() return False @@ -275,11 +320,13 @@ def images_match(reference, output, max_delta): print(f'Renderings mismatch: {delta.mean()=}, {max_delta=}') print(f'Reference image: {Path(reference).absolute()}') print(f'Actual output: {output}') - def print_stats(name, ref): - print(name, 'stats:', ref.min(), ref.mean(), ref.max(), 'std:', ref.std()) + with output_dir.create(suffix='.png') as proc_out: + cv2.imwrite(str(proc_out), out) + print('Processed output image:', proc_out) print_stats('reference', ref) print_stats('actual', out) + write_refout() output_dir.keep() return False @@ -287,7 +334,7 @@ def images_match(reference, output, max_delta): return True -def _test_render(gerber_path, png_expected_path, max_delta=1e-6, scale=300): +def _test_render(gerber_path, png_expected_path, max_delta=1e-6, scale=300, autocrop_golden=False, auto_contrast=False): """Render the gerber file and compare to the expected PNG output. Parameters @@ -314,7 +361,7 @@ def _test_render(gerber_path, png_expected_path, max_delta=1e-6, scale=300): with output_dir.create(suffix='.png') as outfile: actual_bytes = ctx.dump(outfile) - assert images_match(png_expected_path, outfile, max_delta) + assert images_match(png_expected_path, outfile, max_delta, autocrop_golden, auto_contrast) return gerber -- cgit