Skip to content

Commit

Permalink
Tests: set a minimum number of accepted different pixels in `ImageCom…
Browse files Browse the repository at this point in the history
…parator`

It applies when the allowance is greater than zero but less than 1%.
  • Loading branch information
carlosame committed Jun 25, 2024
1 parent ec7dc3d commit 37967d6
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,28 @@ public class ImageComparator {
*/
private static final int diffPixelFactor = 10;

private static int minDiffPixelsForNonzeroAllowance = 30;

/**
* Set the bare minimum number of accepted different pixels, to apply when the
* allowance is greater than zero but less than 1%, and when it is smaller than
* the smallest of the image sides.
* <p>
* Applies independently to pixels above and below the threshold.
* </p>
* <p>
* This is useful for small images. Default value is 30.
* </p>
*
* @param minDiffPixelsForNonzeroAllowance a positive integer.
*/
public static void setMinDiffPixelsForNonzeroAllowance(int minDiffPixelsForNonzeroAllowance) {
if (minDiffPixelsForNonzeroAllowance < 0) {
throw new IllegalArgumentException("Number of pixels must be at least 0.");
}
ImageComparator.minDiffPixelsForNonzeroAllowance = minDiffPixelsForNonzeroAllowance;
}

/**
* Compare two images, allowing a percentage of different pixels according to a
* threshold value.
Expand Down Expand Up @@ -151,8 +173,9 @@ public static short compareImages(BufferedImage ref, BufferedImage can, int pixe

final int numBands = ref.getSampleModel().getNumBands();
final float numpxFrac = w * h * numBands * 0.01f;
final int maxDiffPx = Math.round(numpxFrac * allowedPercentOverThreshold);
final int maxDiffPxBelow = Math.round(numpxFrac * allowedPercentBelowThreshold);
final int maxDiffPx = computeMaxDiffPixels(numpxFrac, allowedPercentOverThreshold, w, h);
final int maxDiffPxBelow = computeMaxDiffPixels(numpxFrac, allowedPercentBelowThreshold, w,
h);

WritableRaster refWR = ref.getRaster();
WritableRaster canWR = can.getRaster();
Expand Down Expand Up @@ -217,6 +240,29 @@ public static short compareImages(BufferedImage ref, BufferedImage can, int pixe
return result;
}

private static int computeMaxDiffPixels(float numpxFrac, float allowedPercent, int width,
int height) {
int maxDiffPx;

if (allowedPercent == 0f) {
maxDiffPx = 0;
} else {
maxDiffPx = Math.round(numpxFrac * allowedPercent);
// If allowedPercent is small but nonzero, maybe there are too few accepted misses.
if (maxDiffPx < minDiffPixelsForNonzeroAllowance && allowedPercent < 1f) {
// We want to accept at most the number of pixels in a side, minus one.
int minDiff = Math.min(width, height) - 1;
minDiff = Math.min(minDiff, minDiffPixelsForNonzeroAllowance);
if (maxDiffPx < minDiff) {
// Allow at least minDiff pixels for (0 < allowedPercent < 1).
maxDiffPx = minDiff;
}
}
}

return maxDiffPx;
}

/**
* Compare a candidate image to a reference, taking into account one or more
* possible variations.
Expand Down Expand Up @@ -288,8 +334,9 @@ public static short compareVariantImages(BufferedImage ref, BufferedImage can, i

final int numBands = ref.getSampleModel().getNumBands();
final float numpxFrac = w * h * numBands * 0.01f;
final int maxDiffPx = Math.round(numpxFrac * allowedPercentOverThreshold);
final int maxDiffPxBelow = Math.round(numpxFrac * allowedPercentBelowThreshold);
final int maxDiffPx = computeMaxDiffPixels(numpxFrac, allowedPercentOverThreshold, w, h);
final int maxDiffPxBelow = computeMaxDiffPixels(numpxFrac, allowedPercentBelowThreshold, w,
h);

WritableRaster refWR = ref.getRaster();
WritableRaster canWR = can.getRaster();
Expand Down Expand Up @@ -521,6 +568,42 @@ public interface ImageVariants {
BufferedImage getVariantImage(int index);
}

public static String getResultDescription(short code) {
String desc;
switch (code) {
case MATCH:
desc = "Match";
break;
case DIFFERENT_SIZES:
desc = "The images have different sizes";
break;
case DIFFERENT_TRANSPARENCIES:
desc = "The images have different sizes";
break;
case DIFFERENT_TYPES:
desc = "The images are of different types";
break;
case DIFFERENT_COLOR_SPACES:
desc = "The images have different color spaces";
break;
case DIFFERENT_PIXELS_BELOW_THRESHOLD:
desc = "The images have have too many below-threshold different pixels";
break;
case DIFFERENT_PIXELS_OVER_THRESHOLD:
desc = "The images have have too many over-threshold different pixels";
break;
case NO_VARIANTS:
desc = "A variant comparison was executed but no variants were found";
break;
case VARIANT_ERROR:
desc = "At least one of the image variants is wrong (wrong size, etc)";
break;
default:
desc = "unknown code";
}
return desc;
}

/**
* Creates an image comparing the two given images, one on each side.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,8 @@ public void runTest(float allowedPercentBelowThreshold, float allowedPercentOver
tmpFile.delete();
}

fail("Rendering not accurate [code " + result + "], see generated images: " + diffFile.getAbsolutePath() + ", "
fail("Rendering not accurate [" + ImageComparator.getResultDescription(result)
+ "], see generated images: " + diffFile.getAbsolutePath() + ", "
+ cmpFile.getAbsolutePath());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ public String compare(float allowedPercentBelowThreshold, float allowedPercentOv
File tmpDiff = imageToFile(diff, IMAGE_TYPE_DIFFERENCE);
File tmpCmp = imageToFile(cmp, IMAGE_TYPE_COMPARISON);

return "Images are different [code " + result + "]. Comp: " + tmpCmp.getAbsolutePath() + " diff: "
+ tmpDiff.getAbsolutePath();
return "Images are different [" + ImageComparator.getResultDescription(result) + "]. Comp: "
+ tmpCmp.getAbsolutePath() + " diff: " + tmpDiff.getAbsolutePath();

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1308,17 +1308,14 @@ public void testSwz721b_webfont() throws TranscoderException, IOException {
testNV("samples/canvg/swz721b-webfont.svg");
}

/*
* Put larger thresholds due to smaller file sizes.
*/
@Override
float getBelowThresholdAllowed() {
return 0.3f;
return 0.15f;
}

@Override
float getOverThresholdAllowed() {
return 0.1f;
return 0.05f;
}

}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 37967d6

Please sign in to comment.