#1
  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).

    I read about the formula for this function:
    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);
    }
    
    static inline MagickRealType RadiansToDegrees(const MagickRealType radians)
    {
      return((MagickRealType) (180.0*radians/MagickPI));
    }
    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. #2
  3. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,387
    Rep Power
    1871
    > 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)
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2011
    Posts
    23
    Rep Power
    0
    Thanks for your explanations.

    One more question. This is just for interest. I have found the reference guide for ImageMagick so I have found definition of _MagickPixelPacket where ColorspaceType is defined:

    "colorspace.h" line 25
    www imagemagick.org / api / MagickCore / color_8c_source.html

    Where are defined the types or the keywords of the type? I know they are on line 25 but are these words part of C language or are they defined by ImageMagick? I did not find any other reference to them.

IMN logo majestic logo threadwatch logo seochat tools logo