Skip to content

Commit 5a57486

Browse files
author
Cristy
committed
robust significant error detection based on fuzz
1 parent 4764bd3 commit 5a57486

File tree

4 files changed

+32
-27
lines changed

4 files changed

+32
-27
lines changed

magick/color.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1693,7 +1693,7 @@ MagickExport MagickBooleanType IsColorSimilar(const Image *image,
16931693
GetPixelOpacity(p) : OpaqueOpacity)-(image->matte != MagickFalse ?
16941694
q->opacity : OpaqueOpacity));
16951695
distance=pixel*pixel;
1696-
if (distance > (fuzz*(1.0+FLT_EPSILON)))
1696+
if (MagickSafeSignificantError(distance,fuzz) != MagickFalse)
16971697
return(MagickFalse);
16981698
/*
16991699
Generate a alpha scaling factor to generate a 4D cone on colorspace
@@ -1722,15 +1722,15 @@ MagickExport MagickBooleanType IsColorSimilar(const Image *image,
17221722
pixel*=2.0;
17231723
}
17241724
distance+=scale*pixel*pixel;
1725-
if (distance > (fuzz*(1.0+FLT_EPSILON)))
1725+
if (MagickSafeSignificantError(distance,fuzz) != MagickFalse)
17261726
return(MagickFalse);
17271727
pixel=(double) GetPixelGreen(p)-(double) q->green;
17281728
distance+=scale*pixel*pixel;
1729-
if (distance > (fuzz*(1.0+FLT_EPSILON)))
1729+
if (MagickSafeSignificantError(distance,fuzz) != MagickFalse)
17301730
return(MagickFalse);
17311731
pixel=(double) GetPixelBlue(p)-(double) q->blue;
17321732
distance+=scale*pixel*pixel;
1733-
if (distance > (fuzz*(1.0+FLT_EPSILON)))
1733+
if (MagickSafeSignificantError(distance,fuzz) != MagickFalse)
17341734
return(MagickFalse);
17351735
return(MagickTrue);
17361736
}
@@ -1906,7 +1906,7 @@ MagickPrivate MagickBooleanType IsIntensitySimilar(const Image *image,
19061906
return(MagickTrue);
19071907
fuzz=GetFuzzyColorDistance(image,(const Image *) NULL);
19081908
pixel=GetPixelIntensity(image,p)-GetPixelIntensity(image,q);
1909-
if ((pixel*pixel) > (fuzz*(1.0+FLT_EPSILON)))
1909+
if (MagickSafeSignificantError(pixel*pixel,fuzz) != MagickFalse)
19101910
return(MagickFalse);
19111911
return(MagickTrue);
19121912
}
@@ -1979,7 +1979,7 @@ MagickExport MagickBooleanType IsMagickColorSimilar(const MagickPixelPacket *p,
19791979
OpaqueOpacity)-(q->matte != MagickFalse ? (double) q->opacity :
19801980
(double) OpaqueOpacity);
19811981
distance=pixel*pixel;
1982-
if (distance > (fuzz*(1.0+FLT_EPSILON)))
1982+
if (MagickSafeSignificantError(distance,fuzz) != MagickFalse)
19831983
return(MagickFalse);
19841984
/*
19851985
Generate a alpha scaling factor to generate a 4D cone on colorspace.
@@ -1999,7 +1999,7 @@ MagickExport MagickBooleanType IsMagickColorSimilar(const MagickPixelPacket *p,
19991999
{
20002000
pixel=p->index-q->index;
20012001
distance+=pixel*pixel*scale;
2002-
if (distance > (fuzz*(1.0+FLT_EPSILON)))
2002+
if (MagickSafeSignificantError(distance,fuzz) != MagickFalse)
20032003
return(MagickFalse);
20042004
scale*=(MagickRealType) (QuantumScale*((double) QuantumRange-p->index));
20052005
scale*=(MagickRealType) (QuantumScale*((double) QuantumRange-q->index));
@@ -2022,15 +2022,15 @@ MagickExport MagickBooleanType IsMagickColorSimilar(const MagickPixelPacket *p,
20222022
pixel*=2.0;
20232023
}
20242024
distance+=pixel*pixel*scale;
2025-
if (distance > (fuzz*(1.0+FLT_EPSILON)))
2025+
if (MagickSafeSignificantError(distance,fuzz) != MagickFalse)
20262026
return(MagickFalse);
20272027
pixel=GetPixelGreen(p)-q->green;
20282028
distance+=pixel*pixel*scale;
2029-
if (distance > (fuzz*(1.0+FLT_EPSILON)))
2029+
if (MagickSafeSignificantError(distance,fuzz) != MagickFalse)
20302030
return(MagickFalse);
20312031
pixel=GetPixelBlue(p)-q->blue;
20322032
distance+=pixel*pixel*scale;
2033-
if (distance > (fuzz*(1.0+FLT_EPSILON)))
2033+
if (MagickSafeSignificantError(distance,fuzz) != MagickFalse)
20342034
return(MagickFalse);
20352035
return(MagickTrue);
20362036
}
@@ -2078,7 +2078,7 @@ MagickExport MagickBooleanType IsOpacitySimilar(const Image *image,
20782078
return(MagickTrue);
20792079
fuzz=GetFuzzyColorDistance(image,(const Image *) NULL);
20802080
pixel=(MagickRealType) GetPixelOpacity(p)-(MagickRealType) GetPixelOpacity(q);
2081-
if ((pixel*pixel) > (fuzz*(1.0+FLT_EPSILON)))
2081+
if (MagickSafeSignificantError(pixel*pixel,fuzz) != MagickFalse)
20822082
return(MagickFalse);
20832083
return(MagickTrue);
20842084
}

magick/compare.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ static MagickBooleanType GetAESimilarity(const Image *image,
451451
{
452452
error=Sa*(double) GetPixelRed(p)-Da*(double)
453453
GetPixelRed(q);
454-
if ((error*error) > (fuzz*(1.0+FLT_EPSILON)))
454+
if (MagickSafeSignificantError(error*error,fuzz) != MagickFalse)
455455
{
456456
channel_similarity[RedChannel]++;
457457
count++;
@@ -461,7 +461,7 @@ static MagickBooleanType GetAESimilarity(const Image *image,
461461
{
462462
error=Sa*(double) GetPixelGreen(p)-Da*(double)
463463
GetPixelGreen(q);
464-
if ((error*error) > (fuzz*(1.0+FLT_EPSILON)))
464+
if (MagickSafeSignificantError(error*error,fuzz) != MagickFalse)
465465
{
466466
channel_similarity[GreenChannel]++;
467467
count++;
@@ -471,7 +471,7 @@ static MagickBooleanType GetAESimilarity(const Image *image,
471471
{
472472
error=Sa*(double) GetPixelBlue(p)-Da*(double)
473473
GetPixelBlue(q);
474-
if ((error*error) > (fuzz*(1.0+FLT_EPSILON)))
474+
if (MagickSafeSignificantError(error*error,fuzz) != MagickFalse)
475475
{
476476
channel_similarity[BlueChannel]++;
477477
count++;
@@ -480,9 +480,8 @@ static MagickBooleanType GetAESimilarity(const Image *image,
480480
if (((channel & OpacityChannel) != 0) &&
481481
(image->matte != MagickFalse))
482482
{
483-
error=(double) GetPixelOpacity(p)-(double)
484-
GetPixelOpacity(q);
485-
if ((error*error) > (fuzz*(1.0+FLT_EPSILON)))
483+
error=(double) GetPixelOpacity(p)-(double) GetPixelOpacity(q);
484+
if (MagickSafeSignificantError(error*error,fuzz) != MagickFalse)
486485
{
487486
channel_similarity[OpacityChannel]++;
488487
count++;
@@ -491,9 +490,8 @@ static MagickBooleanType GetAESimilarity(const Image *image,
491490
if (((channel & IndexChannel) != 0) &&
492491
(image->colorspace == CMYKColorspace))
493492
{
494-
error=Sa*(double) indexes[x]-Da*(double)
495-
reconstruct_indexes[x];
496-
if ((error*error) > (fuzz*(1.0+FLT_EPSILON)))
493+
error=Sa*(double) indexes[x]-Da*(double) reconstruct_indexes[x];
494+
if (MagickSafeSignificantError(error*error,fuzz) != MagickFalse)
497495
{
498496
channel_similarity[IndexChannel]++;
499497
count++;
@@ -593,7 +591,7 @@ static MagickBooleanType GetFUZZSimilarity(const Image *image,
593591
if ((channel & RedChannel) != 0)
594592
{
595593
error=QuantumScale*(Sa*GetPixelRed(p)-Da*GetPixelRed(q));
596-
if ((error*error) > (fuzz*(1.0+FLT_EPSILON)))
594+
if (MagickSafeSignificantError(error*error,fuzz) != MagickFalse)
597595
{
598596
channel_similarity[RedChannel]+=error*error;
599597
channel_similarity[CompositeChannels]+=error*error;
@@ -603,7 +601,7 @@ static MagickBooleanType GetFUZZSimilarity(const Image *image,
603601
if ((channel & GreenChannel) != 0)
604602
{
605603
error=QuantumScale*(Sa*GetPixelGreen(p)-Da*GetPixelGreen(q));
606-
if ((error*error) > (fuzz*(1.0+FLT_EPSILON)))
604+
if (MagickSafeSignificantError(error*error,fuzz) != MagickFalse)
607605
{
608606
channel_similarity[GreenChannel]+=error*error;
609607
channel_similarity[CompositeChannels]+=error*error;
@@ -613,7 +611,7 @@ static MagickBooleanType GetFUZZSimilarity(const Image *image,
613611
if ((channel & BlueChannel) != 0)
614612
{
615613
error=QuantumScale*(Sa*GetPixelBlue(p)-Da*GetPixelBlue(q));
616-
if ((error*error) > (fuzz*(1.0+FLT_EPSILON)))
614+
if (MagickSafeSignificantError(error*error,fuzz) != MagickFalse)
617615
{
618616
channel_similarity[BlueChannel]+=error*error;
619617
channel_similarity[CompositeChannels]+=error*error;
@@ -623,7 +621,7 @@ static MagickBooleanType GetFUZZSimilarity(const Image *image,
623621
if (((channel & OpacityChannel) != 0) && (image->matte != MagickFalse))
624622
{
625623
error=QuantumScale*((double) GetPixelOpacity(p)-GetPixelOpacity(q));
626-
if ((error*error) > (fuzz*(1.0+FLT_EPSILON)))
624+
if (MagickSafeSignificantError(error*error,fuzz) != MagickFalse)
627625
{
628626
channel_similarity[OpacityChannel]+=error*error;
629627
channel_similarity[CompositeChannels]+=error*error;
@@ -635,7 +633,7 @@ static MagickBooleanType GetFUZZSimilarity(const Image *image,
635633
{
636634
error=QuantumScale*(Sa*GetPixelIndex(indexes+x)-Da*
637635
GetPixelIndex(reconstruct_indexes+x));
638-
if ((error*error) > (fuzz*(1.0+FLT_EPSILON)))
636+
if (MagickSafeSignificantError(error*error,fuzz) != MagickFalse)
639637
{
640638
channel_similarity[BlackChannel]+=error*error;
641639
channel_similarity[CompositeChannels]+=error*error;

magick/statistic-private.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@
2222
extern "C" {
2323
#endif
2424

25+
static inline MagickBooleanType MagickSafeSignificantError(const double error,
26+
const double fuzz)
27+
{
28+
double threshold = (fuzz > 0.0 ? fuzz : MagickEpsilon)*(1.0+MagickEpsilon);
29+
return(error > threshold ? MagickTrue : MagickFalse);
30+
}
31+
2532
static inline double MagickSafeLog10(const double x)
2633
{
2734
if (x < MagickEpsilon)

tests/validate.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,7 +1565,7 @@ static size_t ValidateImageFormatsInMemory(ImageInfo *image_info,
15651565
continue;
15661566
}
15671567
difference_image=DestroyImage(difference_image);
1568-
if ((QuantumScale*distortion) > (fuzz*(1.0+FLT_EPSILON)))
1568+
if (MagickSafeSignificantError(QuantumScale*distortion,fuzz) != MagickFalse)
15691569
{
15701570
(void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
15711571
QuantumScale*distortion);
@@ -1802,7 +1802,7 @@ static size_t ValidateImageFormatsOnDisk(ImageInfo *image_info,
18021802
continue;
18031803
}
18041804
difference_image=DestroyImage(difference_image);
1805-
if ((QuantumScale*distortion) > (fuzz*(1.0+FLT_EPSILON)))
1805+
if (MagickSafeSignificantError(QuantumScale*distortion,fuzz) != MagickFalse)
18061806
{
18071807
(void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
18081808
QuantumScale*distortion);

0 commit comments

Comments
 (0)