### Thread: Can you help to understand this function?

1. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Jan 2011
Posts
23
Rep Power
0

#### Can you help to understand this function?

I am not C programmer, but I need to understand this because want to do something similar for ahk. I am used to work with php and ahk so some parts of the syntax I understand.

Code:
```MagickExport MagickBooleanType IsMagickColorSimilar(const MagickPixelPacket *p,
const MagickPixelPacket *q)
{
MagickRealType
fuzz,
pixel;

register MagickRealType
scale,
distance;

if ((p->fuzz == 0.0) && (q->fuzz == 0.0))
return(IsMagickColorEqual(p,q));
if (p->fuzz == 0.0)
fuzz=MagickMax(q->fuzz,MagickSQ1_2)*MagickMax(q->fuzz,MagickSQ1_2);
else if (q->fuzz == 0.0)
fuzz=MagickMax(p->fuzz,MagickSQ1_2)*MagickMax(p->fuzz,MagickSQ1_2);
else
fuzz=MagickMax(p->fuzz,MagickSQ1_2)*MagickMax(q->fuzz,MagickSQ1_2);
scale=1.0;
distance=0.0;
if ((p->matte != MagickFalse) || (q->matte != MagickFalse))
{
/*
Transparencies are involved - set alpha distance.
*/
pixel=(p->matte != MagickFalse ? GetPixelOpacity(p) : OpaqueOpacity)-
(q->matte != MagickFalse ? q->opacity : OpaqueOpacity);
distance=pixel*pixel;
if (distance > fuzz)
return(MagickFalse);
/*
Generate a alpha scaling factor to generate a 4D cone on colorspace.
Note that if one color is transparent, distance has no color component
*/
if (p->matte != MagickFalse)
scale=(QuantumScale*GetPixelAlpha(p));
if (q->matte != MagickFalse)
scale*=(QuantumScale*GetPixelAlpha(q));
if ( scale <= MagickEpsilon )
return(MagickTrue);
}
/*
CMYK create a CMY cube with a multi-dimensional cone toward black.
*/
if (p->colorspace == CMYKColorspace)
{
pixel=p->index-q->index;
distance+=pixel*pixel*scale;
if (distance > fuzz)
return(MagickFalse);
scale*=(MagickRealType) (QuantumScale*(QuantumRange-p->index));
scale*=(MagickRealType) (QuantumScale*(QuantumRange-q->index));
}
/*
RGB or CMY color cube.
*/
distance*=3.0;  /* rescale appropriately */
fuzz*=3.0;
pixel=p->red-q->red;
if ((p->colorspace == HCLColorspace) || (p->colorspace == HSBColorspace) ||
(p->colorspace == HSLColorspace) || (p->colorspace == HWBColorspace))
{
/* This calculates a arc distance for hue
Really if should be a vector angle of 'S'/'W' length
with 'L'/'B' forming appropriate cones.
In other words this is a hack - Anthony
*/
if (fabs((double) pixel) > (QuantumRange/2))
pixel-=QuantumRange;
pixel*=2;
}
distance+=pixel*pixel*scale;
if (distance > fuzz)
return(MagickFalse);
pixel=GetPixelGreen(p)-q->green;
distance+=pixel*pixel*scale;
if (distance > fuzz)
return(MagickFalse);
pixel=GetPixelBlue(p)-q->blue;
distance+=pixel*pixel*scale;
if (distance > fuzz)
return(MagickFalse);
return(MagickTrue);
}```
http://paste.ofcode.org/nkaJTrbSag34Dj9gYjAvE3

Here is description to the function:
http://paste.ofcode.org/mfe2Zy7L4h7A8KRAqDGWEE

What I know about the function:
It is function to compare two colors, weather they are in tolerance (fuzz). It is designer for CIALAB/Lab colorspace but it can work also with RGB.

u object contains scaled values in range 0 to 1. u.r is red channel.

After doing the match, it is needed to convert back to normal color range by multiplying by quantumrange (Q16=65535).

sqrt((reddiff^2+greendiff^2+bluediff^2)/3)

This implements the equivalent of...
fuzz < sqrt( color_distance^2 * u.a*v.a + alpha_distance^2 )

For example for an RGB
color_distance^2 = ( (u.r-v.r)^2 + (u.g-v.g)^2 + (u.b-v.b)^2 ) / 3

so fuzz=color_distance if only RGB and no alpha

However, you can apply the same formula in normal Q range if you want using each color in the range 0 to quantumrange or 0 to 255 (however, you want to see the values) or even multiply by 100 for percent.

My problem is that I am not good on math, but maybe you can help me to understand some C commands esspecialy on the begin of the function, it's definition on begin and arguments:

please explain me the arguments - meaning of
Code:
```MagickPixelPacket *p,
const MagickPixelPacket *q```
Code:
```MagickRealType
fuzz,
pixel;```
Code:
```register MagickRealType
scale,
distance;```
Code:
`static inline double`
Also this functions and constants are in the code...
Code:
```#define MagickSQ1_2  0.70710678118654752440084436210484903928483593768847

static inline double MagickMax(const double x,const double y)
{
if (x > y)
return(x);
return(y);
}

{
}```
Code:
```MagicPixel packed is defined here:
typedef struct _MagickPixelPacket
{
ClassType
storage_class;

ColorspaceType
colorspace;

MagickBooleanType
matte;

double
fuzz;

size_t
depth;

MagickRealType
red,
green,
blue,
opacity,
index;
} MagickPixelPacket;```
I tried to find out where MagickRealType
is defined in source files but no success.
2. > MagickPixelPacket *p,
> const MagickPixelPacket *q
p and q are pointers to two MagickPixelPacket's.

In the caller function, you might have
Code:
```MagickPixelPacket pix1, pix2;
pix1.red = 0.5;
MagickBooleanType result = IsMagickColorSimilar(&pix1, &pix2);```
Here, the structure is accessed using the .member notation to assign a value to the red member.
Inside the function, all you have is a pointer (signified by the &pix1 in the function call). With a pointer to a struct, you would use the ->member notation.

The const on the parameter variable informs the compiler that the code will not attempt to modify any q->member variables.

> I tried to find out where MagickRealType
From the context, you can guess that it would either be 'float' or 'double'.
For the purposes of code analysis, you can safely assume it will be a suitable numeric type capable of holding floating point values.

> register MagickRealType
The register keyword serves no real purpose in modern C or C++ programming. Historically (this is 40 years ago), compilers had no optimisation features at all, and the register keyword was meant as some kind of hint. Modern compilers have dozens (if not hundreds) of optimisation tricks, and are thus able to work out what is best placed in a register far better than any coder. It is safe to ignore this.

> static inline double
static means the function is visible to this source file only.
inline is a hint to the compiler to try and inline the code, thus saving a function call overhead.
double means it returns a double (this is also a hint as to how MagickRealType is declared).

> #define MagickSQ1_2 0.70710678118654752440084436210484903928483593768847
This is just 1 / sqrt(2)
3. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Jan 2011
Posts
23
Rep Power
0