From 3563e84b7fc60b5384087a94f215ca98f24d9d8a Mon Sep 17 00:00:00 2001 From: Tim Griesser Date: Thu, 17 Apr 2025 16:44:31 -0400 Subject: [PATCH] feat: add captureCoords option to retrieve x,y diff information --- .gitattributes | 3 +- README.md | 4 + bin/Main.ml | 8 +- bin/ODiffBin.ml | 9 +- bin/Print.ml | 29 +- npm_package/odiff.d.ts | 4 + npm_package/odiff.js | 26 +- src/Diff.ml | 63 +++- test/Test_Core.ml | 14 +- test/Test_IO_BMP.ml | 10 +- test/Test_IO_JPG.ml | 10 +- test/Test_IO_PNG.ml | 12 +- test/Test_IO_TIFF.ml | 10 +- test/coords-fixture.json | 631 +++++++++++++++++++++++++++++++++++++ test/node-binding.test.cjs | 17 + 15 files changed, 796 insertions(+), 54 deletions(-) create mode 100644 test/coords-fixture.json diff --git a/.gitattributes b/.gitattributes index 4be6d337..089c7325 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ *.yaml linguist-detectable=false -.ci/* linguist-vendored \ No newline at end of file +.ci/* linguist-vendored +test/coords-fixture.json linguist-generated diff --git a/README.md b/README.md index 46863e69..259f3ceb 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,8 @@ export type ODiffOptions = Partial<{ antialiasing: boolean; /** If `true` reason: "pixel-diff" output will contain the set of line indexes containing different pixels */ captureDiffLines: boolean; + /** If `true` the diff result will include coordinates of all different pixels, grouped by x coordinate */ + captureDiffCoords: boolean; /** If `true` odiff will use less memory but will be slower with larger images */ reduceRamUsage: boolean; /** An array of regions to ignore in the diff. */ @@ -142,6 +144,8 @@ declare function compare( diffPercentage: number; /** Individual line indexes containing different pixels. Guaranteed to be ordered and distinct. */ diffLines?: number[]; + /** Array of [x, y[]] pairs where x is the x coordinate and y[] is an array of y coordinates that changed at that x position */ + diffCoords?: [number, ...Array<[number, number]][]; } | { match: false; diff --git a/bin/Main.ml b/bin/Main.ml index afe820f4..8c4961c3 100644 --- a/bin/Main.ml +++ b/bin/Main.ml @@ -18,7 +18,7 @@ type 'output diffResult = { exitCode : int; diff : 'output option } (* Arguments must remain positional for the cmd parser lib that we use *) let main img1Path img2Path diffPath threshold outputDiffMask failOnLayoutChange diffColorHex toEmitStdoutParsableString antialiasing ignoreRegions diffLines - disableGcOptimizations = + captureDiffCoords disableGcOptimizations = (* Increase amount of allowed overhead to reduce amount of GC work and cycles. we target 1-2 minor collections per run which is the best tradeoff between @@ -47,7 +47,7 @@ let main img1Path img2Path diffPath threshold outputDiffMask failOnLayoutChange let img2 = IO2.loadImage img2Path in let { diff; exitCode } = Diff.diff img1 img2 ~outputDiffMask ~threshold ~failOnLayoutChange - ~antialiasing ~ignoreRegions ~diffLines + ~antialiasing ~ignoreRegions ~diffLines ~captureDiffCoords ~diffPixel: (match Color.ofHexString diffColorHex with | Some c -> c @@ -56,10 +56,10 @@ let main img1Path img2Path diffPath threshold outputDiffMask failOnLayoutChange |> Print.printDiffResult toEmitStdoutParsableString |> function | Layout -> { diff = None; exitCode = 21 } - | Pixel (diffOutput, diffCount, stdoutParsableString, _) when diffCount = 0 + | Pixel (diffOutput, diffCount, stdoutParsableString, _, _) when diffCount = 0 -> { exitCode = 0; diff = Some diffOutput } - | Pixel (diffOutput, diffCount, diffPercentage, _) -> + | Pixel (diffOutput, diffCount, diffPercentage, _, _) -> diffPath |> Option.iter (IO1.saveImage diffOutput); { exitCode = 22; diff = Some diffOutput } in diff --git a/bin/ODiffBin.ml b/bin/ODiffBin.ml index 7c18bfcd..bf48d52e 100644 --- a/bin/ODiffBin.ml +++ b/bin/ODiffBin.ml @@ -56,6 +56,13 @@ let diffLines = "With this flag enabled, output result in case of different images \ will output lines for all the different pixels" +let captureDiffCoords = + value & flag + & info [ "capture-diff-coords" ] + ~doc: + "With this flag enabled, the diff result will include coordinates of \ + all different pixels, grouped by x coordinate" + let disableGcOptimizations = value & flag & info [ "reduce-ram-usage" ] @@ -76,7 +83,7 @@ let ignoreRegions = let cmd = const Main.main $ base $ comp $ diffPath $ threshold $ diffMask $ failOnLayout $ diffColor $ parsableOutput $ antialiasing $ ignoreRegions $ diffLines - $ disableGcOptimizations + $ captureDiffCoords $ disableGcOptimizations let version = match Build_info.V1.version () with diff --git a/bin/Print.ml b/bin/Print.ml index aec5e3fe..bd60ef73 100644 --- a/bin/Print.ml +++ b/bin/Print.ml @@ -13,23 +13,36 @@ let printDiffResult makeParsableOutput result = | Layout, false -> Format.printf "%s%sFailure!%s Images have different layout.\n" red bold reset - | Pixel (_output, diffCount, diffPercentage, stack), true - when not (Stack.is_empty stack) -> + | Pixel (_output, diffCount, diffPercentage, stack, coords), true + when not (Stack.is_empty stack) || coords <> [] -> + let lines_str = + if Stack.is_empty stack then ";" else + ";" ^ (stack |> Stack.fold (fun acc line -> (line |> Int.to_string) ^ "," ^ acc) "") + in + let coords_str = + if coords = [] then "" else + let coord_to_str (y, ranges) = + let ranges_str = ranges |> List.map (fun (start, end_) -> + Printf.sprintf "%d-%d" start end_) |> String.concat "," + in + Printf.sprintf "%d:%s" y ranges_str + in + ";" ^ String.concat "|" (List.map coord_to_str coords) + in Int.to_string diffCount ^ ";" ^ Float.to_string diffPercentage - ^ ";" - ^ (stack - |> Stack.fold (fun acc line -> (line |> Int.to_string) ^ "," ^ acc) "") + ^ lines_str + ^ coords_str |> print_endline - | Pixel (_output, diffCount, diffPercentage, _), true -> + | Pixel (_output, diffCount, diffPercentage, _, _), true -> Int.to_string diffCount ^ ";" ^ Float.to_string diffPercentage |> print_endline - | Pixel (_output, diffCount, _percentage, _lines), false when diffCount == 0 + | Pixel (_output, diffCount, _percentage, _lines, _), false when diffCount == 0 -> Format.printf "%s%sSuccess!%s Images are equal.\n%sNo diff output created.%s\n" green bold reset dim reset - | Pixel (_output, diffCount, diffPercentage, _lines), false -> + | Pixel (_output, diffCount, diffPercentage, _lines, _), false -> Format.printf "%s%sFailure!%s Images are different.\n\ Different pixels: %s%s%i (%f%%)%s\n" diff --git a/npm_package/odiff.d.ts b/npm_package/odiff.d.ts index da12b132..8fb34e75 100644 --- a/npm_package/odiff.d.ts +++ b/npm_package/odiff.d.ts @@ -13,6 +13,8 @@ export type ODiffOptions = Partial<{ antialiasing: boolean; /** If `true` reason: "pixel-diff" output will contain the set of line indexes containing different pixels */ captureDiffLines: boolean; + /** If `true` the diff result will include coordinates of all different pixels, grouped by x coordinate */ + captureDiffCoords: boolean; /** If `true` odiff will use less memory but will be slower with larger images */ reduceRamUsage: boolean; /** An array of regions to ignore in the diff. */ @@ -41,6 +43,8 @@ declare function compare( diffPercentage: number; /** Individual line indexes containing different pixels. Guaranteed to be ordered and distinct. */ diffLines?: number[]; + /** Array of [y, ranges[]] pairs where y is the y coordinate and ranges[] is an array of [startX, endX] pairs representing continuous ranges of x coordinates */ + diffCoords?: [number, ...Array<[number, number]>][]; } | { match: false; diff --git a/npm_package/odiff.js b/npm_package/odiff.js index e4998288..286017ee 100644 --- a/npm_package/odiff.js +++ b/npm_package/odiff.js @@ -54,6 +54,10 @@ function optionsToArgs(options) { setFlag("reduce-ram-usage", value); break; + case "captureDiffCoords": + setFlag("capture-diff-coords", value); + break; + case "ignoreRegions": { const regions = value .map( @@ -70,7 +74,7 @@ function optionsToArgs(options) { return argArray; } -/** @type {(stdout: string) => Partial<{ diffCount: number, diffPercentage: number, diffLines: number[] }>} */ +/** @type {(stdout: string) => Partial<{ diffCount: number, diffPercentage: number, diffLines: number[], diffCoords: Array<[number, ...Array<[number, number]>]> }>} */ function parsePixelDiffStdout(stdout) { try { const parts = stdout.split(";"); @@ -94,6 +98,26 @@ function parsePixelDiffStdout(stdout) { return isNaN(parsedInt) ? [] : parsedInt; }), }; + } else if (parts.length >= 3) { + const [diffCount, diffPercentage, linesPart, coordsPart] = parts; + + return { + diffCount: parseInt(diffCount), + diffPercentage: parseFloat(diffPercentage), + diffLines: linesPart.split(",").flatMap((line) => { + let parsedInt = parseInt(line); + return isNaN(parsedInt) ? [] : parsedInt; + }), + diffCoords: coordsPart.split("|").map((coord) => { + const [y, ranges] = coord.split(":"); + /** @type {[number, number][]} */ + const parsedRanges = ranges.split(",").map((range) => { + const [start, end] = range.split("-"); + return [parseInt(start), parseInt(end)]; + }); + return [parseInt(y), ...parsedRanges]; + }), + }; } else { throw new Error(`Weird pixel diff stdout: ${stdout}`); } diff --git a/src/Diff.ml b/src/Diff.ml index 09dbba2f..b4b7014f 100644 --- a/src/Diff.ml +++ b/src/Diff.ml @@ -6,7 +6,7 @@ let redPixel = Int32.of_int 4278190335 (* Decimal representation of the RGBA in32 pixel green pixel *) let maxYIQPossibleDelta = 35215. -type 'a diffVariant = Layout | Pixel of ('a * int * float * int Stack.t) +type 'a diffVariant = Layout | Pixel of ('a * int * float * int Stack.t * (int * (int * int) list) list) let unrollIgnoreRegions width list = list @@ -29,7 +29,7 @@ module MakeDiff (IO1 : ImageIO.ImageIO) (IO2 : ImageIO.ImageIO) = struct let compare (base : IO1.t ImageIO.img) (comp : IO2.t ImageIO.img) ?(antialiasing = false) ?(outputDiffMask = false) ?(diffLines = false) - ?diffPixel ?(threshold = 0.1) ?ignoreRegions ?(captureDiff = true) () = + ?diffPixel ?(threshold = 0.1) ?ignoreRegions ?(captureDiff = true) ?(captureDiffCoords = false) () = let maxDelta = maxYIQPossibleDelta *. (threshold ** 2.) in let diffPixel = match diffPixel with Some x -> x | None -> redPixel in let diffOutput = @@ -44,10 +44,40 @@ module MakeDiff (IO1 : ImageIO.ImageIO) (IO2 : ImageIO.ImageIO) = struct let diffCount = ref 0 in let diffLinesStack = Stack.create () in + let diffCoords = ref [] in + let currentRanges = ref [] in + let lastY = ref (-1) in + let lastX = ref (-1) in + let currentRange = ref None in + let countDifference x y = incr diffCount; diffOutput |> Option.iter (IO1.setImgColor ~x ~y diffPixel); + if captureDiffCoords then ( + if !lastY <> y then ( + !currentRange |> Option.iter (fun (start, _) -> + currentRanges := (start, !lastX) :: !currentRanges); + if !currentRanges <> [] then ( + diffCoords := (!lastY, List.rev !currentRanges) :: !diffCoords; + currentRanges := [] + ); + lastY := y; + lastX := -1; + currentRange := None + ); + + if !lastX = -1 || x <> !lastX + 1 then ( + !currentRange |> Option.iter (fun (start, _) -> + currentRanges := (start, !lastX) :: !currentRanges); + currentRange := Some (x, x) + ) else ( + !currentRange |> Option.iter (fun (start, _) -> + currentRange := Some (start, x)) + ); + lastX := x + ); + if diffLines && (diffLinesStack |> Stack.is_empty || diffLinesStack |> Stack.top < y) @@ -109,33 +139,44 @@ module MakeDiff (IO1 : ImageIO.ImageIO) (IO2 : ImageIO.ImageIO) = struct 100.0 *. Float.of_int !diffCount /. (Float.of_int base.width *. Float.of_int base.height) in - (diffOutput, !diffCount, diffPercentage, diffLinesStack) + + if captureDiffCoords then ( + if !currentRange <> None then ( + currentRanges := (Option.get !currentRange) :: !currentRanges; + currentRange := None + ); + if !currentRanges <> [] then + diffCoords := (!lastY, List.rev !currentRanges) :: !diffCoords + ); + + let diffCoords = List.rev !diffCoords in + (diffOutput, !diffCount, diffPercentage, diffLinesStack, diffCoords) let diff (base : IO1.t ImageIO.img) (comp : IO2.t ImageIO.img) ~outputDiffMask ?(threshold = 0.1) ~diffPixel ?(failOnLayoutChange = true) - ?(antialiasing = false) ?(diffLines = false) ?ignoreRegions () = + ?(antialiasing = false) ?(diffLines = false) ?ignoreRegions ?(captureDiffCoords = false) () = if failOnLayoutChange = true && (base.width <> comp.width || base.height <> comp.height) then Layout else - let diffOutput, diffCount, diffPercentage, diffLinesStack = + let diffOutput, diffCount, diffPercentage, diffLinesStack, diffCoords = compare base comp ~threshold ~diffPixel ~outputDiffMask ~antialiasing - ~diffLines ?ignoreRegions ~captureDiff:true () + ~diffLines ?ignoreRegions ~captureDiff:true ~captureDiffCoords () in - Pixel (Option.get diffOutput, diffCount, diffPercentage, diffLinesStack) + Pixel (Option.get diffOutput, diffCount, diffPercentage, diffLinesStack, diffCoords) let diffWithoutOutput (base : IO1.t ImageIO.img) (comp : IO2.t ImageIO.img) ?(threshold = 0.1) ?(failOnLayoutChange = true) ?(antialiasing = false) - ?(diffLines = false) ?ignoreRegions () = + ?(diffLines = false) ?ignoreRegions ?(captureDiffCoords = false) () = if failOnLayoutChange = true && (base.width <> comp.width || base.height <> comp.height) then Layout else - let diffResult = + let diffOutput, diffCount, diffPercentage, diffLinesStack, diffCoords = compare base comp ~threshold ~outputDiffMask:false ~antialiasing - ~diffLines ?ignoreRegions ~captureDiff:false () + ~diffLines ?ignoreRegions ~captureDiff:false ~captureDiffCoords () in - Pixel diffResult + Pixel (diffOutput, diffCount, diffPercentage, diffLinesStack, diffCoords) end diff --git a/test/Test_Core.ml b/test/Test_Core.ml index 4399f540..fbf33d25 100644 --- a/test/Test_Core.ml +++ b/test/Test_Core.ml @@ -5,7 +5,7 @@ let test_antialiasing () = Sys.getcwd () |> print_endline; let img1 = Png.IO.loadImage "test-images/aa/antialiasing-on.png" in let img2 = Png.IO.loadImage "test-images/aa/antialiasing-off.png" in - let _, diffPixels, diffPercentage, _ = + let _, diffPixels, diffPercentage, _, _ = PNG_Diff.compare img1 img2 ~outputDiffMask:false ~antialiasing:true () in check int "diffPixels" 46 diffPixels; @@ -14,7 +14,7 @@ let test_antialiasing () = let test_different_sized_aa_images () = let img1 = Png.IO.loadImage "test-images/aa/antialiasing-on.png" in let img2 = Png.IO.loadImage "test-images/aa/antialiasing-off-small.png" in - let _, diffPixels, diffPercentage, _ = + let _, diffPixels, diffPercentage, _, _ = PNG_Diff.compare img1 img2 ~outputDiffMask:true ~antialiasing:true () in check int "diffPixels" 417 diffPixels; @@ -23,7 +23,7 @@ let test_different_sized_aa_images () = let test_threshold () = let img1 = Png.IO.loadImage "test-images/png/orange.png" in let img2 = Png.IO.loadImage "test-images/png/orange_changed.png" in - let _, diffPixels, diffPercentage, _ = + let _, diffPixels, diffPercentage, _, _ = PNG_Diff.compare img1 img2 ~threshold:0.5 () in check int "diffPixels" 25 diffPixels; @@ -32,7 +32,7 @@ let test_threshold () = let test_ignore_regions () = let img1 = Png.IO.loadImage "test-images/png/orange.png" in let img2 = Png.IO.loadImage "test-images/png/orange_changed.png" in - let _diffOutput, diffPixels, diffPercentage, _ = + let _diffOutput, diffPixels, diffPercentage, _, _ = PNG_Diff.compare img1 img2 ~ignoreRegions:[ ((150, 30), (310, 105)); ((20, 175), (105, 200)) ] () @@ -43,7 +43,7 @@ let test_ignore_regions () = let test_diff_color () = let img1 = Png.IO.loadImage "test-images/png/orange.png" in let img2 = Png.IO.loadImage "test-images/png/orange_changed.png" in - let diffOutput, _, _, _ = + let diffOutput, _, _, _, _ = PNG_Diff.compare img1 img2 ~diffPixel:(Int32.of_int 4278255360 (*int32 representation of #00ff00*)) () @@ -51,7 +51,7 @@ let test_diff_color () = check bool "diffOutput" (Option.is_some diffOutput) true; let diffOutput = Option.get diffOutput in let originalDiff = Png.IO.loadImage "test-images/png/orange_diff_green.png" in - let diffMaskOfDiff, diffOfDiffPixels, diffOfDiffPercentage, _ = + let diffMaskOfDiff, diffOfDiffPixels, diffOfDiffPercentage, _, _ = PNG_Diff.compare originalDiff diffOutput () in check bool "diffMaskOfDiff" (Option.is_some diffMaskOfDiff) true; @@ -81,7 +81,7 @@ let test_different_layouts () = Sys.getcwd () |> print_endline; let img1 = Png.IO.loadImage "test-images/png/white4x4.png" in let img2 = Png.IO.loadImage "test-images/png/purple8x8.png" in - let _, diffPixels, diffPercentage, _ = + let _, diffPixels, diffPercentage, _, _ = PNG_Diff.compare img1 img2 ~outputDiffMask:false ~antialiasing:false () in check int "diffPixels" 16 diffPixels; diff --git a/test/Test_IO_BMP.ml b/test/Test_IO_BMP.ml index c8c87e79..124deb04 100644 --- a/test/Test_IO_BMP.ml +++ b/test/Test_IO_BMP.ml @@ -16,28 +16,28 @@ let load_png_image path = let test_finds_difference_between_images () = let img1 = load_image "test-images/bmp/clouds.bmp" in let img2 = load_image "test-images/bmp/clouds-2.bmp" in - let _, diffPixels, diffPercentage, _ = Diff.compare img1 img2 () in + let _, diffPixels, diffPercentage, _, _ = Diff.compare img1 img2 () in check int "diffPixels" 191 diffPixels; check (float 0.001) "diffPercentage" 0.076 diffPercentage let test_diff_mask_no_mask_equal () = let img1 = load_image "test-images/bmp/clouds.bmp" in let img2 = load_image "test-images/bmp/clouds-2.bmp" in - let _, diffPixels, diffPercentage, _ = Diff.compare img1 img2 ~outputDiffMask:false () in + let _, diffPixels, diffPercentage, _, _ = Diff.compare img1 img2 ~outputDiffMask:false () in let img1 = load_image "test-images/bmp/clouds.bmp" in let img2 = load_image "test-images/bmp/clouds-2.bmp" in - let _, diffPixelsMask, diffPercentageMask, _ = Diff.compare img1 img2 ~outputDiffMask:true () in + let _, diffPixelsMask, diffPercentageMask, _, _ = Diff.compare img1 img2 ~outputDiffMask:true () in check int "diffPixels" diffPixels diffPixelsMask; check (float 0.001) "diffPercentage" diffPercentage diffPercentageMask let test_creates_correct_diff_output_image () = let img1 = load_image "test-images/bmp/clouds.bmp" in let img2 = load_image "test-images/bmp/clouds-2.bmp" in - let diffOutput, _, _, _ = Diff.compare img1 img2 () in + let diffOutput, _, _, _, _ = Diff.compare img1 img2 () in check bool "diffOutput" (Option.is_some diffOutput) true; let diffOutput = Option.get diffOutput in let originalDiff = load_png_image "test-images/bmp/clouds-diff.png" in - let diffMaskOfDiff, diffOfDiffPixels, diffOfDiffPercentage, _ = Output_Diff.compare originalDiff diffOutput () in + let diffMaskOfDiff, diffOfDiffPixels, diffOfDiffPercentage, _, _ = Output_Diff.compare originalDiff diffOutput () in check bool "diffMaskOfDiff" (Option.is_some diffMaskOfDiff) true; let diffMaskOfDiff = Option.get diffMaskOfDiff in if diffOfDiffPixels > 0 then ( diff --git a/test/Test_IO_JPG.ml b/test/Test_IO_JPG.ml index 00fd8946..c339459d 100644 --- a/test/Test_IO_JPG.ml +++ b/test/Test_IO_JPG.ml @@ -21,19 +21,19 @@ let load_png_image path = let test_finds_difference_between_images () = let img1 = load_image "test-images/jpg/tiger.jpg" in let img2 = load_image "test-images/jpg/tiger-2.jpg" in - let _, diffPixels, diffPercentage, _ = Diff.compare img1 img2 () in + let _, diffPixels, diffPercentage, _, _ = Diff.compare img1 img2 () in check int "diffPixels" 7789 diffPixels; check (float 0.001) "diffPercentage" 1.1677 diffPercentage let test_diff_mask_no_mask_equal () = let img1 = load_image "test-images/jpg/tiger.jpg" in let img2 = load_image "test-images/jpg/tiger-2.jpg" in - let _, diffPixels, diffPercentage, _ = + let _, diffPixels, diffPercentage, _, _ = Diff.compare img1 img2 ~outputDiffMask:false () in let img1 = load_image "test-images/jpg/tiger.jpg" in let img2 = load_image "test-images/jpg/tiger-2.jpg" in - let _, diffPixelsMask, diffPercentageMask, _ = + let _, diffPixelsMask, diffPercentageMask, _, _ = Diff.compare img1 img2 ~outputDiffMask:true () in check int "diffPixels" diffPixels diffPixelsMask; @@ -42,11 +42,11 @@ let test_diff_mask_no_mask_equal () = let test_creates_correct_diff_output_image () = let img1 = load_image "test-images/jpg/tiger.jpg" in let img2 = load_image "test-images/jpg/tiger-2.jpg" in - let diffOutput, _, _, _ = Diff.compare img1 img2 () in + let diffOutput, _, _, _, _ = Diff.compare img1 img2 () in check bool "diffOutput" (Option.is_some diffOutput) true; let diffOutput = Option.get diffOutput in let originalDiff = load_png_image "test-images/jpg/tiger-diff.png" in - let diffMaskOfDiff, diffOfDiffPixels, diffOfDiffPercentage, _ = + let diffMaskOfDiff, diffOfDiffPixels, diffOfDiffPercentage, _, _ = Output_Diff.compare originalDiff diffOutput () in check bool "diffMaskOfDiff" (Option.is_some diffMaskOfDiff) true; diff --git a/test/Test_IO_PNG.ml b/test/Test_IO_PNG.ml index 208603d0..2c608533 100644 --- a/test/Test_IO_PNG.ml +++ b/test/Test_IO_PNG.ml @@ -17,7 +17,7 @@ let () = test_case "finds difference between 2 images" `Quick (fun () -> let img1 = load_image "test-images/png/orange.png" in let img2 = load_image "test-images/png/orange_changed.png" in - let _, diffPixels, diffPercentage, _ = + let _, diffPixels, diffPercentage, _, _ = Diff.compare img1 img2 () in check int "diffPixels" 1366 diffPixels; @@ -25,12 +25,12 @@ let () = test_case "Diff of mask and no mask are equal" `Quick (fun () -> let img1 = load_image "test-images/png/orange.png" in let img2 = load_image "test-images/png/orange_changed.png" in - let _, diffPixels, diffPercentage, _ = + let _, diffPixels, diffPercentage, _, _ = Diff.compare img1 img2 ~outputDiffMask:false () in let img1 = load_image "test-images/png/orange.png" in let img2 = load_image "test-images/png/orange_changed.png" in - let _, diffPixelsMask, diffPercentageMask, _ = + let _, diffPixelsMask, diffPercentageMask, _, _ = Diff.compare img1 img2 ~outputDiffMask:true () in check int "diffPixels" diffPixels diffPixelsMask; @@ -39,11 +39,11 @@ let () = test_case "Creates correct diff output image" `Quick (fun () -> let img1 = load_image "test-images/png/orange.png" in let img2 = load_image "test-images/png/orange_changed.png" in - let diffOutput, _, _, _ = Diff.compare img1 img2 () in + let diffOutput, _, _, _, _ = Diff.compare img1 img2 () in check bool "diffOutput" (Option.is_some diffOutput) true; let diffOutput = Option.get diffOutput in let originalDiff = load_image "test-images/png/orange_diff.png" in - let diffMaskOfDiff, diffOfDiffPixels, diffOfDiffPercentage, _ = + let diffMaskOfDiff, diffOfDiffPixels, diffOfDiffPercentage, _, _ = Diff.compare originalDiff diffOutput () in check bool "diffMaskOfDiff" (Option.is_some diffMaskOfDiff) true; @@ -59,7 +59,7 @@ let () = `Quick (fun () -> let img1 = load_image "test-images/png/extreme-alpha.png" in let img2 = load_image "test-images/png/extreme-alpha-1.png" in - let _, diffPixels, _, _ = Diff.compare img1 img2 () in + let _, diffPixels, _, _, _ = Diff.compare img1 img2 () in check int "diffPixels" 0 diffPixels); ] ); ] diff --git a/test/Test_IO_TIFF.ml b/test/Test_IO_TIFF.ml index d2845387..c8d8c410 100644 --- a/test/Test_IO_TIFF.ml +++ b/test/Test_IO_TIFF.ml @@ -26,7 +26,7 @@ let run_tiff_tests () = test_case "finds difference between 2 images" `Quick (fun () -> let img1 = load_tiff_image "test-images/tiff/laptops.tiff" in let img2 = load_tiff_image "test-images/tiff/laptops-2.tiff" in - let _, diffPixels, diffPercentage, _ = + let _, diffPixels, diffPercentage, _, _ = Diff.compare img1 img2 () in check int "diffPixels" 8569 diffPixels; @@ -34,12 +34,12 @@ let run_tiff_tests () = test_case "Diff of mask and no mask are equal" `Quick (fun () -> let img1 = load_tiff_image "test-images/tiff/laptops.tiff" in let img2 = load_tiff_image "test-images/tiff/laptops-2.tiff" in - let _, diffPixels, diffPercentage, _ = + let _, diffPixels, diffPercentage, _, _ = Diff.compare img1 img2 ~outputDiffMask:false () in let img1 = load_tiff_image "test-images/tiff/laptops.tiff" in let img2 = load_tiff_image "test-images/tiff/laptops-2.tiff" in - let _, diffPixelsMask, diffPercentageMask, _ = + let _, diffPixelsMask, diffPercentageMask, _, _ = Diff.compare img1 img2 ~outputDiffMask:true () in check int "diffPixels" diffPixels diffPixelsMask; @@ -48,13 +48,13 @@ let run_tiff_tests () = test_case "Creates correct diff output image" `Quick (fun () -> let img1 = load_tiff_image "test-images/tiff/laptops.tiff" in let img2 = load_tiff_image "test-images/tiff/laptops-2.tiff" in - let diffOutput, _, _, _ = Diff.compare img1 img2 () in + let diffOutput, _, _, _, _ = Diff.compare img1 img2 () in check bool "diffOutput" (Option.is_some diffOutput) true; let diffOutput = Option.get diffOutput in let originalDiff = load_png_image "test-images/tiff/laptops-diff.png" in - let diffMaskOfDiff, diffOfDiffPixels, diffOfDiffPercentage, _ = + let diffMaskOfDiff, diffOfDiffPixels, diffOfDiffPercentage, _, _ = Output_Diff.compare originalDiff diffOutput () in check bool "diffMaskOfDiff" (Option.is_some diffMaskOfDiff) true; diff --git a/test/coords-fixture.json b/test/coords-fixture.json new file mode 100644 index 00000000..ec744a02 --- /dev/null +++ b/test/coords-fixture.json @@ -0,0 +1,631 @@ +[ + [1169, [886, 888], [890, 892]], + [1170, [885, 894], [896, 896]], + [1171, [882, 899]], + [1172, [878, 901]], + [1173, [878, 902], [904, 904]], + [1174, [877, 910]], + [1175, [877, 911]], + [1176, [876, 913]], + [1177, [877, 915]], + [1178, [878, 916]], + [1179, [878, 918]], + [1180, [878, 921]], + [1181, [878, 924]], + [1182, [879, 926]], + [1183, [881, 925]], + [1184, [881, 929]], + [1185, [882, 927]], + [1186, [883, 932]], + [1187, [885, 933]], + [1188, [885, 935]], + [1189, [885, 940]], + [1190, [885, 939]], + [1191, [885, 943]], + [1192, [886, 944]], + [1193, [886, 945]], + [1194, [885, 944]], + [1195, [885, 945]], + [1196, [886, 946]], + [1197, [887, 950]], + [1198, [886, 949]], + [1199, [885, 951]], + [1200, [886, 953]], + [1201, [886, 955]], + [1202, [886, 956]], + [1203, [886, 958]], + [1204, [887, 958]], + [1205, [887, 959]], + [1206, [887, 959]], + [1207, [887, 959]], + [1208, [885, 962]], + [1209, [885, 964]], + [1210, [886, 964]], + [1211, [885, 965]], + [1212, [885, 965]], + [1213, [885, 966]], + [1214, [886, 968]], + [1215, [887, 970]], + [1216, [884, 971]], + [1217, [884, 971]], + [1218, [884, 972]], + [1219, [884, 978], [981, 985]], + [1220, [883, 988]], + [1221, [883, 994]], + [1222, [880, 881], [883, 995], [998, 1000]], + [1223, [880, 1000], [1003, 1003]], + [1224, [879, 1004]], + [1225, [880, 1008]], + [1226, [878, 1010], [1012, 1015], [1018, 1018]], + [1227, [878, 1018]], + [1228, [879, 1020]], + [1229, [878, 1022]], + [1230, [878, 1023]], + [1231, [877, 1030]], + [1232, [876, 1031]], + [1233, [875, 1033]], + [1234, [875, 1039]], + [1235, [876, 1040]], + [1236, [877, 1044]], + [1237, [876, 1046]], + [1238, [877, 1046]], + [1239, [876, 1049]], + [1240, [875, 1052]], + [1241, [875, 1053], [1071, 1089]], + [1242, [874, 1055], [1061, 1065], [1067, 1095]], + [1243, [875, 1100], [1102, 1102], [1104, 1104]], + [1244, [875, 1109]], + [1245, [875, 1118]], + [1246, [876, 1124]], + [1247, [875, 1127]], + [1248, [875, 1132]], + [1249, [875, 1132]], + [1250, [874, 1137]], + [1251, [874, 1142]], + [1252, [877, 1146]], + [1253, [877, 1145]], + [1254, [877, 1150]], + [1255, [877, 1151]], + [1256, [877, 1153]], + [1257, [876, 1154]], + [1258, [876, 1154]], + [1259, [876, 1155]], + [1260, [875, 1156]], + [1261, [874, 1156]], + [1262, [872, 1157]], + [1263, [870, 1156]], + [1264, [866, 1156]], + [1265, [866, 1156]], + [1266, [864, 1156]], + [1267, [863, 1156]], + [1268, [863, 1155]], + [1269, [862, 1154]], + [1270, [863, 1152]], + [1271, [861, 1152]], + [1272, [862, 1151]], + [1273, [862, 1151]], + [1274, [862, 1149]], + [1275, [861, 1148]], + [1276, [861, 1146]], + [1277, [859, 1146]], + [1278, [858, 1145]], + [1279, [856, 1144]], + [1280, [856, 1143]], + [1281, [855, 1142]], + [1282, [852, 1142]], + [1283, [851, 1140]], + [1284, [852, 1138]], + [1285, [852, 1137]], + [1286, [850, 1136]], + [1287, [848, 1136]], + [1288, [849, 1135]], + [1289, [850, 1136]], + [1290, [846, 1135]], + [1291, [847, 1135]], + [1292, [845, 1136]], + [1293, [843, 1135]], + [1294, [682, 686], [842, 1134]], + [1295, [680, 687], [702, 702], [704, 704], [842, 1134]], + [1296, [679, 681], [686, 687], [701, 702], [704, 705], [841, 1129]], + [ + 1297, + [678, 679], + [686, 687], + [692, 692], + [694, 694], + [698, 701], + [706, 706], + [840, 1129] + ], + [ + 1298, + [677, 678], + [685, 687], + [693, 693], + [697, 699], + [705, 706], + [837, 837], + [839, 1128] + ], + [ + 1299, + [678, 678], + [681, 682], + [686, 687], + [689, 692], + [697, 697], + [706, 706], + [831, 1127] + ], + [ + 1300, + [676, 678], + [685, 686], + [689, 691], + [696, 697], + [705, 705], + [831, 1126] + ], + [ + 1301, + [675, 677], + [679, 679], + [689, 690], + [694, 695], + [704, 704], + [832, 1127] + ], + [ + 1302, + [674, 676], + [679, 679], + [685, 686], + [688, 690], + [693, 695], + [833, 1127] + ], + [ + 1303, + [674, 675], + [677, 678], + [683, 683], + [685, 689], + [691, 694], + [832, 1127] + ], + [1304, [673, 682], [684, 692], [829, 1128]], + [ + 1305, + [673, 674], + [676, 676], + [684, 688], + [691, 692], + [698, 699], + [701, 703], + [709, 709], + [712, 713], + [719, 720], + [723, 724], + [728, 732], + [827, 1128] + ], + [ + 1306, + [672, 674], + [676, 676], + [683, 688], + [690, 692], + [697, 698], + [701, 703], + [705, 713], + [719, 728], + [730, 732], + [828, 1129] + ], + [ + 1307, + [672, 674], + [676, 676], + [682, 687], + [690, 692], + [696, 698], + [701, 702], + [704, 709], + [711, 714], + [717, 728], + [730, 732], + [828, 1125], + [1127, 1129] + ], + [ + 1308, + [672, 674], + [676, 677], + [681, 683], + [685, 685], + [690, 692], + [696, 697], + [699, 702], + [704, 708], + [710, 715], + [717, 721], + [724, 727], + [729, 731], + [734, 734], + [826, 1124], + [1129, 1129] + ], + [ + 1309, + [672, 674], + [676, 676], + [682, 682], + [684, 686], + [690, 692], + [694, 697], + [699, 700], + [703, 705], + [707, 712], + [714, 718], + [720, 722], + [724, 726], + [728, 731], + [733, 733], + [829, 1124] + ], + [ + 1310, + [674, 674], + [678, 679], + [683, 685], + [690, 691], + [694, 695], + [698, 701], + [703, 705], + [709, 710], + [713, 714], + [716, 721], + [723, 732], + [828, 1123] + ], + [ + 1311, + [673, 673], + [681, 683], + [690, 691], + [695, 697], + [699, 700], + [704, 707], + [709, 717], + [720, 722], + [724, 731], + [828, 1123] + ], + [ + 1312, + [674, 674], + [676, 676], + [678, 680], + [691, 692], + [694, 696], + [699, 700], + [704, 706], + [712, 712], + [715, 717], + [720, 722], + [725, 727], + [729, 730], + [826, 1122] + ], + [1313, [823, 1121]], + [1314, [823, 1120]], + [1315, [823, 1119]], + [1316, [821, 1120]], + [1317, [821, 1120]], + [1318, [820, 1120]], + [1319, [819, 1121]], + [1320, [817, 1121]], + [1321, [817, 1122]], + [1322, [817, 1122]], + [1323, [815, 1122]], + [1324, [816, 1122]], + [1325, [817, 1122]], + [1326, [817, 1121]], + [1327, [816, 1121]], + [1328, [816, 1121]], + [1329, [815, 1122]], + [1330, [816, 1121]], + [1331, [818, 1121]], + [1332, [817, 1121]], + [1333, [815, 878], [881, 1120]], + [1334, [815, 878], [881, 1121]], + [1335, [813, 1120]], + [1336, [811, 1120]], + [1337, [814, 1120]], + [1338, [814, 1120]], + [1339, [815, 1005], [1007, 1119]], + [1340, [814, 1119]], + [1341, [813, 1120]], + [1342, [813, 1018], [1020, 1120]], + [1343, [813, 1118]], + [1344, [813, 1117]], + [1345, [809, 1117]], + [1346, [809, 1117]], + [1347, [810, 1118]], + [1348, [812, 1118]], + [1349, [811, 1116]], + [1350, [812, 1117]], + [1351, [813, 1116]], + [1352, [812, 1115]], + [1353, [812, 1116]], + [1354, [808, 1116]], + [1355, [809, 1116]], + [1356, [810, 1117]], + [1357, [809, 1118]], + [1358, [810, 1117]], + [1359, [809, 1117]], + [1360, [809, 1117]], + [1361, [809, 1117]], + [1362, [811, 1116]], + [1363, [812, 1116]], + [1364, [814, 1115]], + [1365, [810, 1115]], + [1366, [812, 1115]], + [1367, [815, 989], [991, 1117]], + [1368, [816, 988], [992, 1117]], + [1369, [815, 989], [991, 1119]], + [1370, [815, 1121]], + [1371, [814, 1119], [1122, 1122]], + [1372, [815, 1121]], + [1373, [817, 1122]], + [1374, [816, 1122]], + [1375, [816, 1122]], + [1376, [817, 1121]], + [1377, [818, 1123]], + [1378, [819, 1123]], + [1379, [819, 1124]], + [1380, [819, 1122]], + [1381, [819, 1122]], + [1382, [818, 1124]], + [1383, [807, 809], [816, 1124]], + [1384, [808, 813], [815, 1123]], + [1385, [811, 1124]], + [1386, [813, 1123]], + [1387, [815, 1125]], + [1388, [818, 1131]], + [1389, [818, 1135]], + [1390, [819, 1136]], + [1391, [798, 815], [817, 1128]], + [1392, [798, 798], [814, 1129]], + [1393, [816, 1126]], + [1394, [803, 1125]], + [1395, [799, 813], [815, 1126]], + [1396, [795, 805], [816, 1126]], + [1397, [791, 800], [817, 1126]], + [1398, [788, 796], [817, 1126]], + [1399, [785, 792], [813, 1124]], + [1400, [783, 789], [817, 1124]], + [1401, [780, 787], [819, 1124]], + [1402, [779, 783], [818, 1120]], + [1403, [776, 779], [819, 1122]], + [1404, [773, 776], [817, 1125]], + [1405, [770, 773], [819, 1126]], + [1406, [768, 769], [820, 1121]], + [1407, [818, 1121]], + [1408, [815, 896], [898, 1124]], + [1409, [808, 896], [899, 1126]], + [1410, [803, 809], [813, 814], [819, 895], [897, 1124]], + [1411, [798, 803], [815, 891], [893, 894], [897, 1120]], + [1412, [793, 800], [806, 889], [893, 893], [898, 898], [900, 1120]], + [1413, [789, 796], [800, 890], [898, 899], [902, 1116]], + [1414, [785, 792], [797, 892], [898, 900], [904, 1117]], + [1415, [781, 787], [794, 802], [812, 893], [895, 901], [904, 1118]], + [1416, [778, 782], [790, 796], [812, 891], [893, 902], [904, 1116]], + [1417, [774, 779], [787, 792], [812, 891], [895, 902], [904, 1117]], + [1418, [770, 775], [782, 789], [814, 891], [897, 900], [902, 1116]], + [1419, [766, 771], [779, 785], [813, 893], [903, 903], [906, 1115]], + [1420, [764, 768], [813, 893], [906, 1115]], + [1421, [763, 764], [813, 895], [907, 1115]], + [1422, [813, 897], [902, 903], [907, 1116]], + [1423, [812, 887], [890, 899], [906, 1116]], + [1424, [814, 888], [894, 900], [906, 1117]], + [1425, [812, 891], [894, 901], [907, 1117]], + [1426, [813, 893], [896, 901], [907, 1117]], + [1427, [813, 895], [907, 1118]], + [1428, [811, 894], [908, 1118]], + [1429, [810, 893], [908, 1119]], + [1430, [808, 894], [896, 897], [904, 944], [952, 1120]], + [1431, [806, 899], [906, 942], [944, 944], [956, 1121]], + [1432, [804, 899], [906, 939], [957, 1121]], + [1433, [802, 892], [895, 900], [907, 938], [959, 1123]], + [1434, [800, 903], [907, 935], [959, 1124]], + [1435, [798, 804], [808, 889], [894, 903], [907, 934], [960, 1124]], + [ + 1436, + [796, 802], + [808, 903], + [906, 934], + [946, 946], + [949, 949], + [952, 953], + [961, 1124] + ], + [ + 1437, + [795, 800], + [809, 897], + [901, 901], + [904, 933], + [946, 951], + [954, 955], + [961, 1126] + ], + [ + 1438, + [807, 896], + [898, 898], + [900, 932], + [946, 951], + [956, 958], + [961, 1127] + ], + [1439, [805, 930], [946, 952], [957, 1128]], + [1440, [805, 929], [947, 953], [959, 1128]], + [1441, [806, 929], [947, 955], [959, 1129]], + [1442, [804, 929], [948, 1129]], + [1443, [801, 930], [940, 940], [943, 944], [947, 1128]], + [ + 1444, + [799, 931], + [934, 934], + [937, 939], + [941, 945], + [947, 951], + [954, 1129] + ], + [1445, [797, 928], [930, 934], [937, 939], [941, 945], [947, 1129]], + [1446, [797, 928], [930, 933], [937, 938], [941, 948], [950, 1130]], + [1447, [795, 929], [931, 934], [937, 938], [941, 947], [950, 1130]], + [1448, [794, 939], [941, 948], [950, 1128]], + [1449, [793, 929], [932, 940], [942, 1127]], + [1450, [799, 1128]], + [1451, [799, 1128]], + [1452, [799, 1129]], + [1453, [798, 1129]], + [1454, [797, 1128]], + [1455, [796, 1128]], + [1456, [795, 1129]], + [1457, [795, 1129]], + [1458, [795, 1130]], + [1459, [795, 1130]], + [1460, [794, 1129]], + [1461, [794, 1129]], + [1462, [793, 1129]], + [1463, [794, 1130]], + [1464, [794, 1130]], + [1465, [796, 1130]], + [1466, [794, 1130]], + [1467, [792, 1129]], + [1468, [792, 1129]], + [1469, [792, 1130]], + [1470, [791, 1129]], + [1471, [790, 1129]], + [1472, [790, 1128]], + [1473, [789, 1128]], + [1474, [790, 1128]], + [1475, [788, 1129]], + [1476, [787, 1130]], + [1477, [786, 1130]], + [1478, [784, 1130]], + [1479, [783, 1129]], + [1480, [783, 1129]], + [1481, [784, 1130]], + [1482, [785, 1128]], + [1483, [784, 1128]], + [1484, [784, 818], [827, 1129]], + [1485, [784, 812], [826, 1129]], + [1486, [786, 808], [824, 1129]], + [1487, [786, 804], [826, 1129]], + [1488, [786, 800], [827, 1129]], + [1489, [786, 796], [824, 1130]], + [1490, [786, 792], [826, 1129]], + [1491, [786, 788], [823, 1130]], + [1492, [825, 1130]], + [1493, [826, 1130]], + [1494, [824, 1130]], + [1495, [824, 1130]], + [1496, [826, 1131]], + [1497, [823, 1131]], + [1498, [822, 908], [910, 1132]], + [1499, [824, 905], [910, 926], [929, 1133]], + [1500, [824, 906], [911, 911], [913, 922], [932, 1132]], + [1501, [823, 906], [914, 920], [932, 1132]], + [1502, [823, 906], [929, 1131]], + [1503, [824, 906], [928, 1131]], + [1504, [823, 907], [929, 1131]], + [1505, [823, 906], [929, 1130]], + [1506, [824, 906], [928, 1131]], + [1507, [823, 906], [926, 1132]], + [1508, [823, 907], [927, 1132]], + [1509, [822, 908], [927, 1131]], + [1510, [824, 907], [926, 1132]], + [1511, [824, 907], [927, 1133]], + [1512, [823, 908], [928, 1132]], + [1513, [822, 907], [927, 1132]], + [1514, [822, 908], [927, 1132]], + [1515, [821, 907], [927, 1132]], + [1516, [823, 908], [927, 1132]], + [1517, [825, 905], [907, 908], [924, 1132]], + [1518, [825, 906], [924, 1132]], + [1519, [825, 905], [924, 1133]], + [1520, [827, 905], [923, 1133]], + [1521, [827, 904], [922, 1134]], + [1522, [827, 828], [831, 904], [924, 1133]], + [1523, [827, 827], [831, 904], [924, 1133]], + [1524, [830, 901], [904, 904], [923, 1132]], + [1525, [834, 902], [923, 1133]], + [1526, [834, 899], [901, 901], [925, 1132]], + [1527, [834, 900], [924, 1132]], + [1528, [835, 897], [923, 1132]], + [1529, [837, 896], [927, 1133]], + [1530, [839, 889], [891, 896], [927, 1134]], + [ + 1531, + [844, 844], + [847, 884], + [886, 889], + [891, 893], + [895, 896], + [927, 1135] + ], + [1532, [850, 850], [852, 880], [882, 884], [889, 889], [928, 1135]], + [1533, [854, 874], [876, 878], [882, 883], [929, 1136]], + [1534, [857, 873], [929, 1134]], + [1535, [862, 863], [866, 873], [929, 1135]], + [1536, [868, 868], [872, 873], [931, 1136]], + [1537, [930, 1133]], + [1538, [931, 1133]], + [1539, [934, 1133]], + [1540, [934, 1134]], + [1541, [934, 1134]], + [1542, [934, 1134]], + [1543, [934, 1132]], + [1544, [934, 1133]], + [1545, [935, 1133]], + [1546, [935, 1133]], + [1547, [934, 1133]], + [1548, [934, 1132]], + [1549, [936, 1133]], + [1550, [937, 1018], [1020, 1133]], + [1551, [936, 1017], [1021, 1133]], + [1552, [939, 1016], [1022, 1134]], + [1553, [940, 1016], [1022, 1134]], + [1554, [940, 1016], [1023, 1134]], + [1555, [940, 1014], [1024, 1133]], + [1556, [939, 1013], [1025, 1133]], + [1557, [940, 1014], [1026, 1134]], + [1558, [942, 1013], [1026, 1134]], + [1559, [942, 1013], [1027, 1133]], + [1560, [945, 946], [948, 1014], [1028, 1134]], + [1561, [948, 952], [954, 1013], [1028, 1132]], + [1562, [950, 951], [954, 960], [962, 962], [964, 1013], [1029, 1133]], + [ + 1563, + [950, 950], + [954, 956], + [958, 959], + [962, 962], + [964, 964], + [966, 966], + [970, 972], + [974, 1014], + [1030, 1134] + ], + [1564, [970, 970], [974, 1010], [1013, 1014], [1031, 1134]], + [1565, [974, 976], [979, 1008], [1010, 1011], [1031, 1133]], + [1566, [975, 976], [979, 1008], [1011, 1011], [1032, 1134]], + [1567, [979, 1008], [1032, 1135]], + [1568, [980, 997], [999, 1005], [1007, 1008], [1033, 1135]], + [1569, [986, 988], [990, 993], [1034, 1134]], + [1570, [988, 988], [1036, 1135]] +] diff --git a/test/node-binding.test.cjs b/test/node-binding.test.cjs index 86f5f725..f6aa64c6 100644 --- a/test/node-binding.test.cjs +++ b/test/node-binding.test.cjs @@ -1,5 +1,7 @@ const path = require("path"); const test = require("ava"); +const fs = require("fs"); + const { compare } = require("../npm_package/odiff"); const IMAGES_PATH = path.resolve(__dirname, "..", "images"); @@ -145,6 +147,21 @@ test("Correctly outputs diff lines", async (t) => { t.is(diffLines.length, 402); }); +test("Correctly outputs diff coords", async (t) => { + const { match, diffCoords } = await compare( + path.join(IMAGES_PATH, "donkey.png"), + path.join(IMAGES_PATH, "donkey-2.png"), + path.join(IMAGES_PATH, "diff.png"), + { + captureDiffCoords: true, + ...options, + } + ); + t.is(match, false); + t.is(diffCoords.length, 402); + t.deepEqual(diffCoords, JSON.parse(fs.readFileSync(path.join(__dirname, "./coords-fixture.json")))); +}); + test("Returns meaningful error if file does not exist and noFailOnFsErrors", async (t) => { const { match, reason, file } = await compare( path.join(IMAGES_PATH, "not-existing.png"),