11 - PHP Online

Form of PHP Sandbox

Enter Your PHP code here for testing/debugging in the Online PHP Sandbox. As in the usual PHP files, you can also add HTML, but do not forget to add the tag <?php in the places where the PHP script should be executed.



Your result can be seen below.

Result of php executing





Full code of 11.php

  1. <?php
  2. class ImgCompare
  3. {
  4.     /** @var string $bigSrc */
  5.     protected $bigSrc;
  6.  
  7.     /** @var array $haystack */
  8.     protected $haystack = [];
  9.  
  10.     /** @var array $needle */
  11.     protected $needle = [];
  12.  
  13.     public function __construct(string $bigSrc)
  14.     {
  15.         $this->bigSrc = $bigSrc;
  16.     }
  17.  
  18.     public function find(string $smallSrc): array
  19.     {
  20.         $big = $this->loadImage($this->bigSrc);
  21.         $small = $this->loadImage($smallSrc);
  22.  
  23.         $scales = $this->calcScales($big, $small);
  24.         $suitable = [];
  25.         $prevScale = null;
  26.         foreach ($scales as $scale) {
  27.             $haystack = $this->resize($big, $scale);
  28.             $this->loadCache($haystack, $this->haystack);
  29.             imagedestroy($haystack);
  30.  
  31.             $needle = $this->resize($small, $scale);
  32.             $this->loadCache($needle, $this->needle);
  33.             imagedestroy($needle);
  34.  
  35.             if ($prevScale !== null) {
  36.                 $suitable = $this->expand($suitable, $prevScale / $scale);
  37.             }
  38.             $prevScale = $scale;
  39.  
  40.             $suitable = $this->compare($suitable);
  41.             $suitable = $this->crop($suitable);
  42.         }
  43.         return $suitable;
  44.     }
  45.  
  46.     protected function calcScales($big, $small): array
  47.     {
  48.         return [4, 2, 1];
  49.     }
  50.  
  51.     protected function loadImage($src)
  52.     {
  53.         $img = imagecreatefrompng($src);
  54.         return $img;
  55.     }
  56.  
  57.     protected function resize($src, int $scale)
  58.     {
  59.         $width = imagesx($src);
  60.         $height = imagesy($src);
  61.         $w = (int) round($width / $scale);
  62.         $h = (int) round($height / $scale);
  63.         $dest = imagecreatetruecolor($w, $h);
  64.         imagecopyresampled($dest, $src, 0, 0, 0, 0, $w, $h, $width, $height);
  65.         return $dest;
  66.     }
  67.  
  68.     protected function loadCache($img, &$arr)
  69.     {
  70.         $arr = [];
  71.         $w = imagesx($img);
  72.         $h = imagesy($img);
  73.         for ($row = 0; $row < $h; $row++) {
  74.             $arr[$row] = [];
  75.             for ($col = 0; $col < $w; $col++) {
  76.                 $arr[$row][$col] = imagecolorat($img, $col, $row);
  77.             }
  78.         }
  79.     }
  80.  
  81.     protected function compare(array $suitable): array
  82.     {
  83.         $width = count($this->haystack[0]);
  84.         $height = count($this->haystack);
  85.  
  86.         $w = count($this->needle[0]);
  87.         $h = count($this->needle);
  88.  
  89.         $arr = [];
  90.         for ($row = 0; $row <= $height - $h; $row++) {
  91.             if (empty($suitable) || isset($suitable[$row])) {
  92.                 for ($col = 0; $col <= $width - $w; $col++) {
  93.                     if (empty($suitable) || isset($suitable[$row][$col])) {
  94.                         $arr[$row][$col] = $this->weight($row, $col);
  95.                     }
  96.                 }
  97.             }
  98.         }
  99.         return $arr;
  100.     }
  101.  
  102.     protected function weight(int $row, int $col): int
  103.     {
  104.         $w = count($this->needle[0]);
  105.         $h = count($this->needle);
  106.  
  107.         $result = 0;
  108.         for ($r = 0; $r < $h; $r++) {
  109.             for ($c = 0; $c < $w; $c++) {
  110.                 $result += abs($this->needle[$r][$c] - $this->haystack[$row + $r][$col + $c]);
  111.             }
  112.         }
  113.         return $result;
  114.     }
  115.  
  116.     protected function crop(array $suitable): array
  117.     {
  118.         $arr = [];
  119.         foreach ($suitable as $row => $cols) {
  120.             foreach ($cols as $col => $weight) {
  121.                 $arr["{$row},{$col}"] = $weight;
  122.             }
  123.         }
  124.         asort($arr);
  125.         $arr = array_slice($arr, 0, 25, true);
  126.  
  127.         $suitable = [];
  128.         foreach ($arr as $entry => $weight) {
  129.             list($row, $col) = explode(",", $entry);
  130.             if (!isset($suitable[$row])) {
  131.                 $suitable[$row] = [];
  132.             }
  133.             $suitable[$row][$col] = $weight;
  134.         }
  135.         return $suitable;
  136.     }
  137.  
  138.     protected function expand(array $suitable, float $scale): array
  139.     {
  140.         $arr = [];
  141.         foreach ($suitable as $row => $cols) {
  142.             $arr[$row * $scale] = [];
  143.             foreach ($cols as $col => $weight) {
  144.                 $arr[$row * $scale][$col * $scale] = $weight;
  145.                 // + 8 around
  146.                 // upper
  147.                 if ($row > 0) {
  148.                     $arr[$row * $scale - 1][$col * $scale - 1] = $weight;
  149.                     $arr[$row * $scale - 1][$col * $scale] = $weight;
  150.                     $arr[$row * $scale - 1][$col * $scale + 1] = $weight;
  151.                 }
  152.                 // left, right
  153.                 if ($col > 0) {
  154.                     $arr[$row * $scale][$col * $scale - 1] = $weight;
  155.                 }
  156.                 if ($col < count($cols) - 1) {
  157.                     $arr[$row * $scale][$col * $scale + 1] = $weight;
  158.                 }
  159.                 // bottom
  160.                 if ($row < count($suitable) - 1) {
  161.                     $arr[$row * $scale + 1][$col * $scale - 1] = $weight;
  162.                     $arr[$row * $scale + 1][$col * $scale] = $weight;
  163.                     $arr[$row * $scale + 1][$col * $scale + 1] = $weight;
  164.                 }
  165.             }
  166.         }
  167.         return $arr;
  168.     }
  169. }
  170.  
  171. //$img = imagecreatetruecolor(200, 150);
  172. //$gray = imagecolorallocate($img, 150, 150, 150);
  173. //imagefill($img, 0, 0, $gray);
  174. //$red = imagecolorallocate($img, 255, 100, 100);
  175. //// 1
  176. //imagesetpixel($img, 0, 0, $red);
  177. //imagesetpixel($img, 1, 0, $red);
  178. //imagesetpixel($img, 0, 1, $red);
  179. //imagesetpixel($img, 1, 1, $red);
  180. //// 2
  181. //imagesetpixel($img, 20, 30, $red);
  182. //imagesetpixel($img, 21, 30, $red);
  183. //imagesetpixel($img, 20, 31, $red);
  184. //imagesetpixel($img, 21, 31, $red);
  185. //imagepng($img, __DIR__ . '/big.png');
  186. //imagedestroy($img);
  187. //
  188. //$img = imagecreatetruecolor(8, 11);
  189. //$gray = imagecolorallocate($img, 150, 150, 150);
  190. //imagefill($img, 0, 0, $gray);
  191. //$red = imagecolorallocate($img, 255, 100, 100);
  192. //imagesetpixel($img, 0, 0, $red);
  193. //imagesetpixel($img, 1, 0, $red);
  194. //imagesetpixel($img, 0, 1, $red);
  195. //imagesetpixel($img, 1, 1, $red);
  196. //imagepng($img, __DIR__ . '/small.png');
  197. //imagedestroy($img);
  198.  
  199. $start = microtime(true);
  200.  
  201. $c = new ImgCompare(__DIR__ . '/big.png');
  202. $suitable = $c->find(__DIR__ . '/small.png');
  203. foreach ($suitable as $row => $cols) {
  204.     foreach ($cols as $col => $weight) {
  205.         echo "{$row},{$col} = {$weight}\n";
  206.     }
  207. }
  208.  
  209. $stop = microtime(true);
  210. echo 'time: ' . round($stop - $start, 4) . ' sec.' . PHP_EOL;
  211.  
  212. class Test extends ImgCompare
  213. {
  214.     public function Test_loadCache()
  215.     {
  216.         $img = imagecreatetruecolor(3, 1);
  217.         $bgColor = imagecolorallocate($img, 255, 255, 255);
  218.         imagefill($img, 0, 0, $bgColor);
  219.         $r = imagecolorallocate($img, 255, 0, 0);
  220.         $g = imagecolorallocate($img, 0, 255, 0);
  221.         $b = imagecolorallocate($img, 0, 0, 255);
  222.         imagesetpixel($img, 0, 0, $r);
  223.         imagesetpixel($img, 1, 0, $g);
  224.         imagesetpixel($img, 2, 0, $b);
  225.  
  226.         $this->loadCache($img, $this->haystack);
  227.         assert(count($this->haystack) === 1);
  228.         assert(isset($this->haystack[0]));
  229.         assert(count($this->haystack[0]) === 3);
  230.         assert($this->haystack[0][0] === 255 * pow(256, 2) + 0 * pow(256, 1) + 0 * pow(256, 0));
  231.         assert($this->haystack[0][1] === 0 * pow(256, 2) + 255 * pow(256, 1) + 0 * pow(256, 0));
  232.         assert($this->haystack[0][2] === 0 * pow(256, 2) + 0 * pow(256, 1) + 255 * pow(256, 0));
  233.     }
  234.  
  235.     public function Test_weight()
  236.     {
  237.         $this->haystack = [
  238.             [10, 20, 30],
  239.             [40, 50, 60],
  240.             [70, 80, 90],
  241.         ];
  242.         $this->needle = [
  243.             [100, 20],
  244.             [200, 50],
  245.         ];
  246.  
  247.         assert($this->weight(0, 0) === abs(100 - 10) + abs(20 - 20) + abs(200 - 40) + abs(50 - 50));
  248.         assert($this->weight(0, 1) === abs(100 - 20) + abs(20 - 30) + abs(200 - 50) + abs(50 - 60));
  249.         assert($this->weight(1, 0) === abs(100 - 40) + abs(20 - 50) + abs(200 - 70) + abs(50 - 80));
  250.         assert($this->weight(1, 1) === abs(100 - 50) + abs(20 - 60) + abs(200 - 80) + abs(50 - 90));
  251.     }
  252.  
  253.     public function Test_compare()
  254.     {
  255.         $this->haystack = [
  256.             [10, 20, 30],
  257.             [40, 50, 60],
  258.             [70, 80, 90],
  259.         ];
  260.         $this->needle = [
  261.             [100, 20],
  262.             [200, 50],
  263.         ];
  264.  
  265.         $expected = [
  266.             [$this->weight(0, 0), $this->weight(0, 1)],
  267.             [$this->weight(1, 0), $this->weight(1, 1)],
  268.         ];
  269.         $actual = $this->compare([]);
  270.  
  271.         assert(
  272.             $expected === $actual,
  273.             'Expected: ' . var_export($expected, true) . '; actual: ' . var_export($actual, true)
  274.         );
  275.     }
  276. }
  277.  
  278. $test = new Test('');
  279. $test->Test_loadCache();
  280. $test->Test_weight();
  281. $test->Test_compare();
File Description
  • 11
  • PHP Code
  • 12 Oct-2021
  • 8.39 Kb
You can Share it: