PHP Библиотека GD: не сохранять дубликаты изображений - PullRequest
0 голосов
/ 20 апреля 2020

Я начал сценарий, который преобразует RSS-каналы в веб-контент. Чтобы ускорить время загрузки для повторных посещений, я стараюсь использовать миниатюры:

(1) Извлечение внешнего изображения из URL (2) Изменение его размера. (3) Сохраните его в папке миниатюр.

Однако я не хочу сохранять дубликаты.

Дубликаты могут иметь разные имена файлов, но иметь одинаковый размер, mimetype et c.

Вместо этого я хочу пропустить сохранение.


Я хочу объяснить мой вопрос немного больше.

Я получаю удаленное изображение из

https://cdn.podigee.com/uploads/u1980/4f93a227-6fb8-4ff3-bf39-50b87130709e.jpg

Затем я создаю миниатюру с помощью библиотеки imagick или gd. Затем я сохраняю этот эскиз для дальнейшего использования в специальной папке.

4f93a227-6fb8-4ff3-bf39-50b87130709e_250.jpg

В этой папке уже есть идентичные файлы с разными именами файлов:

./images/thumbs/bc221023-93fe-472b-8adb-a763588a4faf-_250.jpg
./images/thumbs/dea40aed-969c-48e3-96f0-73664b78c1d8-_250.jpg
./images/thumbs/e47e116e-c4e5-4ff5-bc8f-2a664b0d0686-_250.jpg
./images/thumbs/ed1cda0e-53fa-427a-b187-e33256b27622-_250.jpg
./images/thumbs/f144e91c-ac7e-4b28-9e4f-d20557dc02f2-_250.jpg
./images/thumbs/f740480d-c86b-4b1d-998a-c360bfea8fb2-_250.jpg
./images/thumbs/fbe2378b-a003-4990-bcf5-2780eed06093-_250.jpg
./images/thumbs/fc8142d0-e8f0-46e1-a0de-5c3babb3e809-_250.jpg

Но я хочу сохранить только один и сохранить путь к этому исходному файлу в качестве ссылки.

Помощь приветствуется!


Расстояние Хемминга между двумя файлами может сказать мне, если оба файла идентичны, вариант или разные.

Я нашел там интересный код: https://gist.github.com/pranid/a48b322631eb16ba1052 // https://www.phpclasses.org/blog/post/584-How-Can-PHP-Compare-Two-Images-for-Similarity.html

Я адаптировал код для своих целей:

$image1="https://cdn.podigee.com/uploads/u1980/4f93a227-6fb8-4ff3-bf39-50b87130709e.jpg";
//$image1="./images/thumbs/40de1239-3d9a-486a-b4b1-99799cefdcc6-_250.jpg";
$image2="./images/thumbs/ed1cda0e-53fa-427a-b187-e33256b27622-_250.jpg";

$class = new compareImages;
echo $class->compare($image1,$image2);


class compareImages
{
    private function mimeType($i)
    {
        /*returns array with mime type and if its jpg or png. Returns false if it isn't jpg or png*/
        $mime = getimagesize($i);
        $return = array($mime[0],$mime[1]);

        switch ($mime['mime'])
        {
            case 'image/jpeg':
                $return[] = 'jpg';
                return $return;
            case 'image/png':
                $return[] = 'png';
                return $return;
            default:
                return false;
        }
    }  

    private function createImage($i)
    {
        /*retuns image resource or false if its not jpg or png*/
        $mime = $this->mimeType($i);

        if($mime[2] == 'jpg')
        {
            return imagecreatefromjpeg ($i);
        } 
        else if ($mime[2] == 'png') 
        {
            return imagecreatefrompng ($i);
        } 
        else 
        {
            return false; 
        } 
    }

    private function resizeImage($i,$source)
    {
        /*resizes the image to a 8x8 squere and returns as image resource*/
        $mime = $this->mimeType($source);

        $t = imagecreatetruecolor(8, 8);

        $source = $this->createImage($source);

        imagecopyresized($t, $source, 0, 0, 0, 0, 8, 8, $mime[0], $mime[1]);

        return $t;
    }

        private function colorMeanValue($i)
    {
        /*returns the mean value of the colors and the list of all pixel's colors*/
        $colorList = array();
        $colorSum = 0;
        for($a = 0;$a<8;$a++)
        {

            for($b = 0;$b<8;$b++)
            {

                $rgb = imagecolorat($i, $a, $b);
                $colorList[] = $rgb & 0xFF;
                $colorSum += $rgb & 0xFF;

            }

        }

        return array($colorSum/64,$colorList);
    }

        private function bits($colorMean)
    {
        /*returns an array with 1 and zeros. If a color is bigger than the mean value of colors it is 1*/
        $bits = array();

        foreach($colorMean[1] as $color){$bits[]= ($color>=$colorMean[0])?1:0;}

        return $bits;

    }

        public function compare($a,$b)
    {
        /*main function. returns the hammering distance of two images' bit value*/
        $i1 = $this->createImage($a);
        $i2 = $this->createImage($b);

        if(!$i1 || !$i2){return false;}

        $i1 = $this->resizeImage($i1,$a);
        $i2 = $this->resizeImage($i2,$b);

        imagefilter($i1, IMG_FILTER_GRAYSCALE);
        imagefilter($i2, IMG_FILTER_GRAYSCALE);

        $colorMean1 = $this->colorMeanValue($i1);
        $colorMean2 = $this->colorMeanValue($i2);

        $bits1 = $this->bits($colorMean1);
        $bits2 = $this->bits($colorMean2);

        $hammingDistance = 0;

        for($a = 0;$a<64;$a++)
        {

            if($bits1[$a] != $bits2[$a])
            {
                $hammingDistance++;
            }

        }

        return $hammingDistance;
    }
}

Расстояние Хемминга между внешним изображением и локальными миниатюрами равно 5, что означает, что они являются вариантами. Менее 10 достаточно точно для меня. Это означает, что не сохраняйте файл, вместо этого получите путь к локальному файлу.

Но существует серьезная проблема со временем загрузки, особенно при сравнении с некоторыми другими файлами в папке большого пальца.

$image1="https://cdn.podigee.com/uploads/u1980/4f93a227-6fb8-4ff3-bf39-50b87130709e.jpg";
$image2="./images/thumbs/ed1cda0e-53fa-427a-b187-e33256b27622-_250.jpg";

 ********** 
* BEGINN DEBUG AUSGABE 
* Datei:  
* ZEILE 19: Hamming Distance=5
* ENDE DEBUG AUSGABE 
**********

 ********** 
* BEGINN DEBUG AUSGABE 
* Datei:  
* ZEILE 20: Time elapsed=2.8849399089813 sec
* ENDE DEBUG AUSGABE 
**********

Сравнение локальных идентичных локальных файлов выполняется намного быстрее:

$image1="./images/thumbs/40de1239-3d9a-486a-b4b1-99799cefdcc6-_250.jpg";
$image2="./images/thumbs/ed1cda0e-53fa-427a-b187-e33256b27622-_250.jpg";

 ********** 
* BEGINN DEBUG AUSGABE 
* Datei:  
* ZEILE 19: Hamming Distance=0
* ENDE DEBUG AUSGABE 
**********

 ********** 
* BEGINN DEBUG AUSGABE 
* Datei:  
* ZEILE 20: Time elapsed=0.0089261531829834
* ENDE DEBUG AUSGABE 
**********

Кто-нибудь знает другой, может быть, быстрый и грязный подход для решения проблемы истекшего времени ?

...