Ok, so I have made lots of changes to the code.
I have left comments starting with >>>
's all over the code to note what I have changed and why.
I didn't really look into what the code is for and there could probably be more things I would like to have changed if I did. For some of the parts I didn't understand I checked The Pattern in Pi's code, thanks.
I have made some style changes along the way, I generally follow the PHP Framework Interop Group's standards.
And now the code:
<?php
define('I_DONT_KNOW_WHAT_THIS_NUMBER_IS', 5);
// >>> I have made it so that the images are passed in as resources
// this makes the function more flexible and might stop you from
// needing to read the images from disk at a later point
// >>> Hmm, I have also changed the name of this function as it doesn't 'find' so much as 'measure'
// >>> Ok, so I have added some phpdoc style commenting to this function
// It is important here and not in the helper functions as the idea behind this function would
// otherwise seem vague.
/**
* This measures the similarity between two images.
* It does so by sampling the image at certain points (determined by the accuracy
* setting) and comparing the rgb color values for an almost exact match (See COLOR_COMPARISON_FUZZYNESS). The number of
* matches per number of samples determines the similarity.
*
* @arg $imageA Resource An image to compare, should be an image resource
* @arg $imageB Resource An image to compare, should be an image resource
* @arg $accuracy Integer This number gets timesed by 5 for some reason and then becomes the number of samples per a dimension
*
* @returns float The ratio between the number of matcher per the number of samples for the two images
*/
function measureSimilarityBetweenImages($imageA, $imageB, $accuracy)
{
// >>> I don't understand this part at all... If you explain it I will check it out
// >>> Ok after looking at @The Pattern in Pi's answer I sort of understand,
// I also couldn't help but use some of his variable names, thanks
// >>> Note that I have changed this comment
// Get the image size of the first image and assume it is the same as the second
$imageWidth = imagesx($imageA);
$imageHeight = imagesy($imageA);
// >>> What was this 5, magic numbers should be constants!
// >>> I still don't know what density means in this context
// >>> Ok, I know know what density means, I would call it numberOfSamples
// density normally means means units per (some other unit)^3
// and have it be the total number of samples over the image
// but I still don't know where accuracy and the 5 comes in
$samplesPerDimension = $accuracy * I_DONT_KNOW_WHAT_THIS_NUMBER_IS;
// >>> I like to use units as variable names
$xPixelsPerSample = round($imageWidth/$samplesPerDimension);
$yPixelsPerSample = round($imageHeight/$samplesPerDimension);
// >>> This is not the best way to do this but it should work, a
// better solution might involve changing the above 'round' function
// to a 'floor'. Be careful with rounding.
$totalSamples = floor($xPixelsPerSample * $imageWidth) * floor($yPixels * $imageHeight);
// >>> Again I don't understand this part, these loops look very convoluted
// >>> After looking at The Pattern in Pi's code, again I sort of understand
// again I sort of can't help use his code...
// >>> Actually on second thought, it doesn't look like pointsWidth or
// pointsHeight is defined anywhere in his revision...
// >>> EDIT: ok I have fixed this up
// >>> I have changed this name so it is clearer what it represents
$matchedSamples = 0;
// >>> Note how I have inlined these loops
for ($y = 0; $y < $imageHeight; $y =+ $yPixelsPerSample) {
for ($x = 0; $x < $imageWidth; $x =+ $xPixelsPerSample) {
// >>> So I cleaned up this part through the use of functions below
if (comparePixels(getPixel($imageA, $x, $y), getPixel($imageB, $x, $y))) {
$matchedSamples++; //Match between points.
}
}
}
// >>> I like to leave ratios alone, it can be converted to a percentage when it needs to be output
return $matchedSamples/$totalSamples;
}
// Composing these two functions together
function getPixel($image, $x, $y)
{
return imagecolorsforindex($image, imagecolorat($image, $x, $y));
}
// >>> With compare functions I like to just use $a and $b, this is just a preference of mine
function comparePixels($a, $b)
{
// >>> Note the usage of the array and the foreach loop
foreach (array('red', 'blue', 'green') as $color) {
if (! compareColors($a[$color], $b[$color])) {
return false;
}
}
return true;
}
// >>> Constants are normally together at the top (or in a separate parameters file) but I have put it here for effect
define('COLOR_COMPARISON_FUZZYNESS', 2)
// >>> I changed this functions name, this is largely a matter of preference and consistancy.
// The pattern I use here seems to be verb then noun, see how it matches all the other functions
// including your `findSimilarityBetweenImages' function.
function compareColors($a, $b)
{
// >>> I have clarified what you are doing here, it shows that the difference between the two values
// must be less a certain amount, which I have made a constant
if(abs($a - $b) <= COLOR_COMPARISON_FUZZYNESS)) {
return true;
}
return false;
}
// >>> So you would call it like this to get the same effect
measureSimilarityBetweenImages(imagecreatefrompng($imagePathA), imagecreatefrompng($imagePathB));
?>
Some tips:
Keep in mind magic numbers and subtle naming patterns.
Checkout functional programming (it is not just programing using functions), at least the philosophy/paradigm if not a functional language (such as haskel and clojure). Functional programming is definitely not mutually exclusive to object orientated programming, they both can work together.
Your comments didn't prove very useful to me, important things to comment about is the domain specific things. It would be useful for you to explain how you are finding the similarities and what you define a similarity is, I suspect that is where density comes in.
I don't normally comment on what code is doing, I try to make the code readable enough so that I don't have to, in the very rare cases I can't make it readable I put comments in. There is also a style of coding called literate programming which is the opposite of this.
Function signature comments can be useful as well (what nibra's answer was about).