diff --git a/src/align/__tests__/__image_snapshots__/align-min-difference-test-ts-id-crops-1-snap.png b/src/align/__tests__/__image_snapshots__/align-min-difference-test-ts-id-crops-1-snap.png index c9f5657b4..124959b69 100644 Binary files a/src/align/__tests__/__image_snapshots__/align-min-difference-test-ts-id-crops-1-snap.png and b/src/align/__tests__/__image_snapshots__/align-min-difference-test-ts-id-crops-1-snap.png differ diff --git a/src/align/__tests__/__image_snapshots__/align-min-difference-test-ts-other-id-crops-1-snap.png b/src/align/__tests__/__image_snapshots__/align-min-difference-test-ts-other-id-crops-1-snap.png index 9241bae7a..0802a5944 100644 Binary files a/src/align/__tests__/__image_snapshots__/align-min-difference-test-ts-other-id-crops-1-snap.png and b/src/align/__tests__/__image_snapshots__/align-min-difference-test-ts-other-id-crops-1-snap.png differ diff --git a/src/align/affineTransfrom/__tests__/__image_snapshots__/get-affine-transform-test-ts-crosscheck-false-1-snap.png b/src/align/affineTransfrom/__tests__/__image_snapshots__/get-affine-transform-test-ts-crosscheck-false-1-snap.png index cb7a03940..d81975da3 100644 Binary files a/src/align/affineTransfrom/__tests__/__image_snapshots__/get-affine-transform-test-ts-crosscheck-false-1-snap.png and b/src/align/affineTransfrom/__tests__/__image_snapshots__/get-affine-transform-test-ts-crosscheck-false-1-snap.png differ diff --git a/src/align/affineTransfrom/__tests__/__image_snapshots__/get-affine-transform-test-ts-debug-true-1-snap.png b/src/align/affineTransfrom/__tests__/__image_snapshots__/get-affine-transform-test-ts-debug-true-1-snap.png index 332caf9c4..5fcf46f30 100644 Binary files a/src/align/affineTransfrom/__tests__/__image_snapshots__/get-affine-transform-test-ts-debug-true-1-snap.png and b/src/align/affineTransfrom/__tests__/__image_snapshots__/get-affine-transform-test-ts-debug-true-1-snap.png differ diff --git a/src/align/affineTransfrom/__tests__/__image_snapshots__/get-affine-transform-test-ts-rgb-images-1-snap.png b/src/align/affineTransfrom/__tests__/__image_snapshots__/get-affine-transform-test-ts-rgb-images-1-snap.png index acd553fa9..8fd7154f7 100644 Binary files a/src/align/affineTransfrom/__tests__/__image_snapshots__/get-affine-transform-test-ts-rgb-images-1-snap.png and b/src/align/affineTransfrom/__tests__/__image_snapshots__/get-affine-transform-test-ts-rgb-images-1-snap.png differ diff --git a/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-centroid-patch-diameter-31-scalene-triangle-2-snap.png b/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-centroid-patch-diameter-31-scalene-triangle-2-snap.png index c64851794..d862d3ab1 100644 Binary files a/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-centroid-patch-diameter-31-scalene-triangle-2-snap.png and b/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-centroid-patch-diameter-31-scalene-triangle-2-snap.png differ diff --git a/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-centroid-patch-diameter-31-scalene-triangle-3-snap.png b/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-centroid-patch-diameter-31-scalene-triangle-3-snap.png index a5464fa25..37ef818cf 100644 Binary files a/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-centroid-patch-diameter-31-scalene-triangle-3-snap.png and b/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-centroid-patch-diameter-31-scalene-triangle-3-snap.png differ diff --git a/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-centroid-patch-diameter-31-scalene-triangle-rotated-90-2-snap.png b/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-centroid-patch-diameter-31-scalene-triangle-rotated-90-2-snap.png index c64851794..b2f25b020 100644 Binary files a/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-centroid-patch-diameter-31-scalene-triangle-rotated-90-2-snap.png and b/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-centroid-patch-diameter-31-scalene-triangle-rotated-90-2-snap.png differ diff --git a/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-centroid-patch-diameter-31-scalene-triangle-rotated-90-3-snap.png b/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-centroid-patch-diameter-31-scalene-triangle-rotated-90-3-snap.png index a5464fa25..ff23b18f4 100644 Binary files a/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-centroid-patch-diameter-31-scalene-triangle-rotated-90-3-snap.png and b/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-centroid-patch-diameter-31-scalene-triangle-rotated-90-3-snap.png differ diff --git a/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-default-options-scalene-triangle-2-snap.png b/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-default-options-scalene-triangle-2-snap.png index 3a1832cdc..f72951959 100644 Binary files a/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-default-options-scalene-triangle-2-snap.png and b/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-default-options-scalene-triangle-2-snap.png differ diff --git a/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-default-options-scalene-triangle-3-snap.png b/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-default-options-scalene-triangle-3-snap.png index 0b6b8fd1f..23c677237 100644 Binary files a/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-default-options-scalene-triangle-3-snap.png and b/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-default-options-scalene-triangle-3-snap.png differ diff --git a/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-default-options-scalene-triangle-rotated-90-2-snap.png b/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-default-options-scalene-triangle-rotated-90-2-snap.png index 3a1832cdc..0a185528b 100644 Binary files a/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-default-options-scalene-triangle-rotated-90-2-snap.png and b/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-default-options-scalene-triangle-rotated-90-2-snap.png differ diff --git a/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-default-options-scalene-triangle-rotated-90-3-snap.png b/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-default-options-scalene-triangle-rotated-90-3-snap.png index 0b6b8fd1f..598cc72ea 100644 Binary files a/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-default-options-scalene-triangle-rotated-90-3-snap.png and b/src/featureMatching/descriptors/utils/__tests__/__image_snapshots__/get-keypoint-patch-test-ts-default-options-scalene-triangle-rotated-90-3-snap.png differ diff --git a/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-polygon-rotated-10-1-snap.png b/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-polygon-rotated-10-1-snap.png index 5847d77c2..1c605878e 100644 Binary files a/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-polygon-rotated-10-1-snap.png and b/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-polygon-rotated-10-1-snap.png differ diff --git a/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-polygon-rotated-180-1-snap.png b/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-polygon-rotated-180-1-snap.png index 88c4dfb67..83ce05e45 100644 Binary files a/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-polygon-rotated-180-1-snap.png and b/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-polygon-rotated-180-1-snap.png differ diff --git a/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-scalene-triangle-rotated-10-1-snap.png b/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-scalene-triangle-rotated-10-1-snap.png index 295dbe332..70a6ac565 100644 Binary files a/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-scalene-triangle-rotated-10-1-snap.png and b/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-scalene-triangle-rotated-10-1-snap.png differ diff --git a/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-scalene-triangle-rotated-180-1-snap.png b/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-scalene-triangle-rotated-180-1-snap.png index e7f176a6a..e0c90cd3e 100644 Binary files a/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-scalene-triangle-rotated-180-1-snap.png and b/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-scalene-triangle-rotated-180-1-snap.png differ diff --git a/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-scalene-triangle-rotated-90-1-snap.png b/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-scalene-triangle-rotated-90-1-snap.png index 32c2a5b10..f22459a86 100644 Binary files a/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-scalene-triangle-rotated-90-1-snap.png and b/src/featureMatching/matching/__tests__/__image_snapshots__/brute-force-match-test-ts-various-polygons-centroid-patch-diameter-31-scalene-triangle-rotated-90-1-snap.png differ diff --git a/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-polygon-1-snap.png b/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-polygon-1-snap.png index 1ce1a6b78..934748ea7 100644 Binary files a/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-polygon-1-snap.png and b/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-polygon-1-snap.png differ diff --git a/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-polygon-rotated-10-1-snap.png b/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-polygon-rotated-10-1-snap.png deleted file mode 100644 index b4bd5400a..000000000 Binary files a/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-polygon-rotated-10-1-snap.png and /dev/null differ diff --git a/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-polygon-rotated-180-1-snap.png b/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-polygon-rotated-180-1-snap.png deleted file mode 100644 index e9ef90c47..000000000 Binary files a/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-polygon-rotated-180-1-snap.png and /dev/null differ diff --git a/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-scalene-triangle-1-snap.png b/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-scalene-triangle-1-snap.png index 59c39aec2..9cd7282c0 100644 Binary files a/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-scalene-triangle-1-snap.png and b/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-scalene-triangle-1-snap.png differ diff --git a/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-scalene-triangle-90-1-snap.png b/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-scalene-triangle-90-1-snap.png index 8d85cc0f3..cf8f22ea8 100644 Binary files a/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-scalene-triangle-90-1-snap.png and b/src/featureMatching/matching/__tests__/__image_snapshots__/get-crosscheck-matches-test-ts-get-crosscheck-matches-various-polygons-centroid-patch-diameter-31-scalene-triangle-90-1-snap.png differ diff --git a/src/featureMatching/visualize/__tests__/__image_snapshots__/draw-matches-test-ts-alphabet-image-as-source-and-destination-nb-keypoint-10-1-snap.png b/src/featureMatching/visualize/__tests__/__image_snapshots__/draw-matches-test-ts-alphabet-image-as-source-and-destination-nb-keypoint-10-1-snap.png index 7271c7564..f18c0687b 100644 Binary files a/src/featureMatching/visualize/__tests__/__image_snapshots__/draw-matches-test-ts-alphabet-image-as-source-and-destination-nb-keypoint-10-1-snap.png and b/src/featureMatching/visualize/__tests__/__image_snapshots__/draw-matches-test-ts-alphabet-image-as-source-and-destination-nb-keypoint-10-1-snap.png differ diff --git a/src/featureMatching/visualize/__tests__/__image_snapshots__/draw-matches-test-ts-destination-rotated-10-1-snap.png b/src/featureMatching/visualize/__tests__/__image_snapshots__/draw-matches-test-ts-destination-rotated-10-1-snap.png index 20dde0e32..8bbc3b134 100644 Binary files a/src/featureMatching/visualize/__tests__/__image_snapshots__/draw-matches-test-ts-destination-rotated-10-1-snap.png and b/src/featureMatching/visualize/__tests__/__image_snapshots__/draw-matches-test-ts-destination-rotated-10-1-snap.png differ diff --git a/src/featureMatching/visualize/__tests__/__image_snapshots__/draw-matches-test-ts-destination-rotated-2-1-snap.png b/src/featureMatching/visualize/__tests__/__image_snapshots__/draw-matches-test-ts-destination-rotated-2-1-snap.png index 5dc140f54..16f9bf136 100644 Binary files a/src/featureMatching/visualize/__tests__/__image_snapshots__/draw-matches-test-ts-destination-rotated-2-1-snap.png and b/src/featureMatching/visualize/__tests__/__image_snapshots__/draw-matches-test-ts-destination-rotated-2-1-snap.png differ diff --git a/src/featureMatching/visualize/__tests__/__image_snapshots__/draw-matches-test-ts-show-distance-true-1-snap.png b/src/featureMatching/visualize/__tests__/__image_snapshots__/draw-matches-test-ts-show-distance-true-1-snap.png index 9fba9ddb9..80e780c19 100644 Binary files a/src/featureMatching/visualize/__tests__/__image_snapshots__/draw-matches-test-ts-show-distance-true-1-snap.png and b/src/featureMatching/visualize/__tests__/__image_snapshots__/draw-matches-test-ts-show-distance-true-1-snap.png differ diff --git a/src/featureMatching/visualize/__tests__/__image_snapshots__/montage-test-ts-draw-keypoints-disposition-vertical-1-snap.png b/src/featureMatching/visualize/__tests__/__image_snapshots__/montage-test-ts-draw-keypoints-disposition-vertical-1-snap.png index 8befeef81..85f8a2c44 100644 Binary files a/src/featureMatching/visualize/__tests__/__image_snapshots__/montage-test-ts-draw-keypoints-disposition-vertical-1-snap.png and b/src/featureMatching/visualize/__tests__/__image_snapshots__/montage-test-ts-draw-keypoints-disposition-vertical-1-snap.png differ diff --git a/src/featureMatching/visualize/__tests__/__image_snapshots__/montage-test-ts-draw-keypoints-scale-2-1-snap.png b/src/featureMatching/visualize/__tests__/__image_snapshots__/montage-test-ts-draw-keypoints-scale-2-1-snap.png index 6f60edb73..240e05d37 100644 Binary files a/src/featureMatching/visualize/__tests__/__image_snapshots__/montage-test-ts-draw-keypoints-scale-2-1-snap.png and b/src/featureMatching/visualize/__tests__/__image_snapshots__/montage-test-ts-draw-keypoints-scale-2-1-snap.png differ diff --git a/src/featureMatching/visualize/__tests__/__image_snapshots__/montage-test-ts-draw-matches-disposition-vertical-1-snap.png b/src/featureMatching/visualize/__tests__/__image_snapshots__/montage-test-ts-draw-matches-disposition-vertical-1-snap.png index f05ef2e57..191b72ed2 100644 Binary files a/src/featureMatching/visualize/__tests__/__image_snapshots__/montage-test-ts-draw-matches-disposition-vertical-1-snap.png and b/src/featureMatching/visualize/__tests__/__image_snapshots__/montage-test-ts-draw-matches-disposition-vertical-1-snap.png differ diff --git a/src/featureMatching/visualize/__tests__/__image_snapshots__/montage-test-ts-draw-matches-scale-2-1-snap.png b/src/featureMatching/visualize/__tests__/__image_snapshots__/montage-test-ts-draw-matches-scale-2-1-snap.png index aa9b59a90..638fd6a9f 100644 Binary files a/src/featureMatching/visualize/__tests__/__image_snapshots__/montage-test-ts-draw-matches-scale-2-1-snap.png and b/src/featureMatching/visualize/__tests__/__image_snapshots__/montage-test-ts-draw-matches-scale-2-1-snap.png differ diff --git a/src/featureMatching/visualize/__tests__/__image_snapshots__/overlap-images-test-ts-two-triangles-1-snap.png b/src/featureMatching/visualize/__tests__/__image_snapshots__/overlap-images-test-ts-two-triangles-1-snap.png index 50bb8e8e6..e48ffed7c 100644 Binary files a/src/featureMatching/visualize/__tests__/__image_snapshots__/overlap-images-test-ts-two-triangles-1-snap.png and b/src/featureMatching/visualize/__tests__/__image_snapshots__/overlap-images-test-ts-two-triangles-1-snap.png differ diff --git a/src/geometry/__tests__/__image_snapshots__/resize-test-ts-has-to-match-snapshot-1-snap.png b/src/geometry/__tests__/__image_snapshots__/resize-test-ts-has-to-match-snapshot-1-snap.png index d29ff8734..6019c455d 100644 Binary files a/src/geometry/__tests__/__image_snapshots__/resize-test-ts-has-to-match-snapshot-1-snap.png and b/src/geometry/__tests__/__image_snapshots__/resize-test-ts-has-to-match-snapshot-1-snap.png differ diff --git a/src/geometry/__tests__/__image_snapshots__/transform-rotate-test-ts-full-image-option-1-snap.png b/src/geometry/__tests__/__image_snapshots__/transform-rotate-test-ts-full-image-option-1-snap.png index e6df19c55..c481bd0b4 100644 Binary files a/src/geometry/__tests__/__image_snapshots__/transform-rotate-test-ts-full-image-option-1-snap.png and b/src/geometry/__tests__/__image_snapshots__/transform-rotate-test-ts-full-image-option-1-snap.png differ diff --git a/src/geometry/__tests__/__image_snapshots__/transform-rotate-test-ts-rotate-around-center-1-snap.png b/src/geometry/__tests__/__image_snapshots__/transform-rotate-test-ts-rotate-around-center-1-snap.png index 48cdf4834..c95652ce5 100644 Binary files a/src/geometry/__tests__/__image_snapshots__/transform-rotate-test-ts-rotate-around-center-1-snap.png and b/src/geometry/__tests__/__image_snapshots__/transform-rotate-test-ts-rotate-around-center-1-snap.png differ diff --git a/src/geometry/__tests__/__image_snapshots__/transform-rotate-test-ts-rotate-around-corner-1-snap.png b/src/geometry/__tests__/__image_snapshots__/transform-rotate-test-ts-rotate-around-corner-1-snap.png index c942ede33..985db2bbf 100644 Binary files a/src/geometry/__tests__/__image_snapshots__/transform-rotate-test-ts-rotate-around-corner-1-snap.png and b/src/geometry/__tests__/__image_snapshots__/transform-rotate-test-ts-rotate-around-corner-1-snap.png differ diff --git a/src/geometry/__tests__/resize.test.ts b/src/geometry/__tests__/resize.test.ts index df8c0e21d..3c1e19639 100644 --- a/src/geometry/__tests__/resize.test.ts +++ b/src/geometry/__tests__/resize.test.ts @@ -1,7 +1,10 @@ -import { encodePng } from '../../save'; +import * as path from 'node:path'; -test.skip('compare result of resize with opencv (nearest)', () => { +import { encodePng, write } from '../../save'; + +test('compare result of resize with opencv (nearest)', async () => { const img = testUtils.load('opencv/test.png'); + const expectedImg = testUtils.load('opencv/testResizeNearest.png'); const resized = img.resize({ xFactor: 10, @@ -9,18 +12,35 @@ test.skip('compare result of resize with opencv (nearest)', () => { interpolationType: 'nearest', }); + const substraction = expectedImg.clone().subtract(resized); + await write( + path.join(__dirname, 'resize_nearest_substraction.png'), + substraction, + ); + await write(path.join(__dirname, 'resize_nearest.png'), resized); + expect(resized).toMatchImage('opencv/testResizeNearest.png'); }); -test.skip('compare result of resize with opencv (bilinear)', () => { +test('compare result of resize with opencv (bilinear)', async () => { const img = testUtils.load('opencv/test.png'); + const expectedImg = testUtils.load('opencv/testResizeBilinear.png'); const resized = img.resize({ xFactor: 10, yFactor: 10, + interpolationType: 'bilinear', }); - expect(resized).toMatchImage('opencv/testResizeBilinear.png'); + const substraction = expectedImg.clone().subtract(resized); + await write( + path.join(__dirname, 'resize_bilinear_substraction.png'), + substraction, + ); + await write(path.join(__dirname, 'resize_bilinear.png'), resized); + + // OpenCV bilinear interpolation is less precise for speed. + expect(resized).toMatchImage('opencv/testResizeBilinear.png', { error: 25 }); }); test('result should have correct dimensions', () => { diff --git a/src/geometry/resize.ts b/src/geometry/resize.ts index 92fa4a496..b2f641f5f 100644 --- a/src/geometry/resize.ts +++ b/src/geometry/resize.ts @@ -1,10 +1,6 @@ import { Image } from '../Image'; -import { getClamp } from '../utils/clamp'; -import { getBorderInterpolation, BorderType } from '../utils/interpolateBorder'; -import { - getInterpolationFunction, - InterpolationType, -} from '../utils/interpolatePixel'; +import { BorderType } from '../utils/interpolateBorder'; +import { InterpolationType } from '../utils/interpolatePixel'; import { assert } from '../utils/validators/assert'; export interface ResizeOptions { @@ -53,36 +49,26 @@ export interface ResizeOptions { * @returns The new image. */ export function resize(image: Image, options: ResizeOptions): Image { + const { interpolationType = 'bilinear' } = options; const { - interpolationType = 'bilinear', - borderType = 'constant', + borderType = interpolationType === 'bilinear' ? 'replicate' : 'constant', borderValue = 0, } = options; - const { width, height } = checkOptions(image, options); - const newImage = Image.createFrom(image, { width, height }); - const interpolate = getInterpolationFunction(interpolationType); - const interpolateBorder = getBorderInterpolation(borderType, borderValue); - const clamp = getClamp(newImage); - const intervalX = (image.width - 1) / (width - 1); - const intervalY = (image.height - 1) / (height - 1); - for (let row = 0; row < newImage.height; row++) { - for (let column = 0; column < newImage.width; column++) { - const nx = column * intervalX; - const ny = row * intervalY; - for (let channel = 0; channel < newImage.channels; channel++) { - const newValue = interpolate( - image, - nx, - ny, - channel, - interpolateBorder, - clamp, - ); - newImage.setValue(column, row, channel, newValue); - } - } - } - return newImage; + const { width, height, xFactor, yFactor } = checkOptions(image, options); + + return image.transform( + [ + [xFactor, 0, 0], + [0, yFactor, 0], + ], + { + width, + height, + borderType, + borderValue, + interpolationType, + }, + ); } /** diff --git a/src/geometry/transform.ts b/src/geometry/transform.ts index 67ef53846..ce1a1f569 100644 --- a/src/geometry/transform.ts +++ b/src/geometry/transform.ts @@ -4,7 +4,7 @@ import { Image } from '../Image'; import { getClamp } from '../utils/clamp'; import { BorderType, getBorderInterpolation } from '../utils/interpolateBorder'; import { - getInterpolationFunction, + getInterpolationNeighbourFunction, InterpolationType, } from '../utils/interpolatePixel'; @@ -130,11 +130,12 @@ export function transform( const interpolateBorder = getBorderInterpolation(borderType, borderValue); const clamp = getClamp(newImage); - const interpolate = getInterpolationFunction(interpolationType); + const interpolate = getInterpolationNeighbourFunction(interpolationType); for (let row = 0; row < newImage.height; row++) { for (let column = 0; column < newImage.width; column++) { const nx = transformPoint(transformMatrix[0], column, row); const ny = transformPoint(transformMatrix[1], column, row); + for (let channel = 0; channel < newImage.channels; channel++) { const newValue = interpolate( image, diff --git a/src/utils/interpolatePixel.ts b/src/utils/interpolatePixel.ts index de9203391..83cd35a99 100644 --- a/src/utils/interpolatePixel.ts +++ b/src/utils/interpolatePixel.ts @@ -12,32 +12,50 @@ export const InterpolationType = { export type InterpolationType = (typeof InterpolationType)[keyof typeof InterpolationType]; -type InterpolationFunction = ( +type InterpolationNeighbourFunction = ( + /** + * The image to interpolate. + */ image: Image, - column: number, - row: number, + /** + * interpolation of original column (float) from target column. + */ + nx: number, + /** + * interpolation of original row (float) from target row. + */ + ny: number, + /** + * channel index. + */ channel: number, - intepolateBorder: BorderInterpolationFunction, + /** + * Border interpolation function. + */ + interpolateBorder: BorderInterpolationFunction, + /** + * Clamp function. + */ clamp: ClampFunction, ) => number; /** - * Get the interpolation function based on its name. + * Get the interpolation neighbour function based on its name. * @param interpolationType - Specified interpolation type. * @returns The interpolation function. */ -export function getInterpolationFunction( +export function getInterpolationNeighbourFunction( interpolationType: InterpolationType, -): InterpolationFunction { +): InterpolationNeighbourFunction { switch (interpolationType) { case 'nearest': { - return interpolateNearest; + return interpolateNeighbourNearest; } case 'bilinear': { - return interpolateBilinear; + return interpolateNeighbourBilinear; } case 'bicubic': { - return interpolateBicubic; + return interpolateNeighbourBicubic; } default: { throw new RangeError(`invalid interpolationType: ${interpolationType}`); @@ -46,23 +64,23 @@ export function getInterpolationFunction( } /** - * Interpolate using nearest neighbor. + * Interpolate using the nearest neighbour. * @param image - The image to interpolate. - * @param column - Column index. - * @param row - Row index. - * @param channel - Channel index. + * @param nx - column (float) of the point to interpolate + * @param ny - row (float) of the point to interpolate + * @param channel - channel index. * @param interpolateBorder - Border interpolation function. * @returns The interpolated value. */ -function interpolateNearest( +function interpolateNeighbourNearest( image: Image, - column: number, - row: number, + nx: number, + ny: number, channel: number, interpolateBorder: BorderInterpolationFunction, ): number { - column = Math.round(column); - row = Math.round(row); + const column = Math.floor(nx); + const row = Math.floor(ny); return interpolateBorder(column, row, channel, image); } @@ -70,73 +88,69 @@ function interpolateNearest( /** * Interpolate using bilinear interpolation. * @param image - The image to interpolate. - * @param column - Column index. - * @param row - Row index. - * @param channel - Channel index. + * @param nx - column (float) of the point to interpolate + * @param ny - row (float) of the point to interpolate + * @param channel - channel index. * @param interpolateBorder - Border interpolation function. * @returns The interpolated value. */ -function interpolateBilinear( +function interpolateNeighbourBilinear( image: Image, - column: number, - row: number, + nx: number, + ny: number, channel: number, interpolateBorder: BorderInterpolationFunction, ): number { - const px0 = Math.floor(column); - const py0 = Math.floor(row); + nx = Math.max(0, Math.min(nx - 0.5, image.width)); + ny = Math.max(0, Math.min(ny - 0.5, image.height)); + const px0 = Math.floor(nx); + const py0 = Math.floor(ny); const px1 = px0 + 1; const py1 = py0 + 1; - if (px1 < image.width && py1 < image.height && px0 >= 0 && py0 >= 0) { - const vx0y0 = image.getValue(px0, py0, channel); - const vx1y0 = image.getValue(px1, py0, channel); - const vx0y1 = image.getValue(px0, py1, channel); - const vx1y1 = image.getValue(px1, py1, channel); - - const r1 = (px1 - column) * vx0y0 + (column - px0) * vx1y0; - const r2 = (px1 - column) * vx0y1 + (column - px0) * vx1y1; - return round((py1 - row) * r1 + (row - py0) * r2); - } else { - const vx0y0 = interpolateBorder(px0, py0, channel, image); - const vx1y0 = interpolateBorder(px1, py0, channel, image); - const vx0y1 = interpolateBorder(px0, py1, channel, image); - const vx1y1 = interpolateBorder(px1, py1, channel, image); - - const r1 = (px1 - column) * vx0y0 + (column - px0) * vx1y0; - const r2 = (px1 - column) * vx0y1 + (column - px0) * vx1y1; - return round((py1 - row) * r1 + (row - py0) * r2); - } + const vx0y0 = interpolateBorder(px0, py0, channel, image); + const vx1y0 = interpolateBorder(px1, py0, channel, image); + const vx0y1 = interpolateBorder(px0, py1, channel, image); + const vx1y1 = interpolateBorder(px1, py1, channel, image); + + const px1nx = px1 - nx; + const nxpx0 = nx - px0; + const py1ny = py1 - ny; + const nypy0 = ny - py0; + + const r1 = px1nx * vx0y0 + nxpx0 * vx1y0; + const r2 = px1nx * vx0y1 + nxpx0 * vx1y1; + return py1ny * r1 + nypy0 * r2; } /** * Interpolate using bicubic interpolation. * @param image - The image to interpolate. - * @param column - Column index. - * @param row - Row index. - * @param channel - Channel index. + * @param nx - interpolation of original column (float) from target column. + * @param ny - interpolation of original row (float) from target row. + * @param channel - channel index. * @param interpolateBorder - Border interpolation function. * @param clamp - Clamp function. * @returns The interpolated value. */ -function interpolateBicubic( +function interpolateNeighbourBicubic( image: Image, - column: number, - row: number, + nx: number, + ny: number, channel: number, interpolateBorder: BorderInterpolationFunction, clamp: ClampFunction, ): number { - const px1 = Math.floor(column); - const py1 = Math.floor(row); + const px1 = Math.floor(nx); + const py1 = Math.floor(ny); - if (px1 === column && py1 === row) { + if (px1 === nx && py1 === ny) { return interpolateBorder(px1, py1, channel, image); } - const xNorm = column - px1; - const yNorm = row - py1; + const xNorm = nx - px1; + const yNorm = ny - py1; const vx0y0 = interpolateBorder(px1 - 1, py1 - 1, channel, image); const vx1y0 = interpolateBorder(px1, py1 - 1, channel, image);