PHP: Как определить, является ли jpeg полностью черным (без изображения)? - PullRequest
5 голосов
/ 31 января 2011

Я создал веб-сайт сообщества, где пользователи загружают свои фотографии и могут обрезать миниатюру, аля Facebook, чтобы было понятно.

Но по какой-то причине некоторые из них генерируют пробел (на самом деле это черный jpeg thumbnail).

Я пробовал разные решения, но похоже, что это происходит с большими изображениями или, может быть, на компьютерах, где JS не включен? Я не знаю ...

Суть в том, что количество пользователей с этим очень мало, я думал о создании патча: определить, когда пользователь генерирует пустой JPEG.

Ты знаешь, как это сделать?

Ответы [ 7 ]

5 голосов
/ 31 января 2011

Измените размер изображения до 1x1 PX.Затем проверьте, является ли один пиксель черным.Не идеально, но если в оригинале присутствует значительное количество не черного, то 1px не будет черным.Преимущество в том, что это будет быстро.

3 голосов
/ 31 января 2011

I думаю, нет более быстрого пути, чем ходьба, хотя каждый пиксель использует imagecolorat().

Что касается того, почему это происходит, это может быть из-за CMYK JPG файлы, которые GD не может переварить.Не уверен - вам придется попробовать.Если это причина, вы можете обнаружить CMYK, используя getimagesize() и его channels info.

2 голосов
/ 22 июня 2015

Мне нравится этот случайный алгоритм,

function check_if_black($src){

    $img = imagecreatefromjpeg($src);
    list($width_orig, $height_orig)=getimagesize($src);
    for($i=0;$i<20;$i++){
        $rand_width=rand ( 0 , $width_orig );
        $rand_height=rand ( 0 , $height_orig );
        $rgb = imagecolorat($img, $rand_width, $rand_height);
        if($rgb!=0){
            return "not black";
        }
    }
    return "black";
}

Даже если 80% изображения чёрного цвета, у него есть 99% успеха. Вы также можете увеличить цикл для лучшего процента.

1 голос
/ 23 октября 2018

Если все ваши миниатюры имеют одинаковый размер, вот простой пример:

// b3122965acb460720824611e8e17b960 = 64x64 black image

if (md5(file_get_contents("images/test.jpg")) == "b3122965acb460720824611e8e17b960")
{
  echo "Black image";
}
1 голос
/ 31 января 2011

Предполагая, что это действительное черное изображение, вы можете:

длинный путь - сканирование пиксель за пикселем на цвет черный

короткий путь (если всегда используется одно и то же черное изображение) - сравните файл побайтно (или хэш md5) с образцом черного изображения

0 голосов
/ 09 ноября 2018

Вот мой код:

<?php

namespace App\Traits;

trait BlacknessCheck {

    public static function fileIsBlack($filename, $throw_error = false) {

        if (exif_imagetype($filename) === IMAGETYPE_JPEG) {

            return self::imageIsBlack(imagecreatefromjpeg($filename));

        } elseif ($isimage === IMAGETYPE_PNG) {

            return self::imageIsBlack(imagecreatefrompng($filename));

        } else {

            if ($throw_error) {
                throw new \Exception("Provided file is not an image.");
            } else {
                return false;
            }

        }

    }

    public static function imageIsBlack($image) {

        $scaled_image = self::scaleImage($image);

        $added_colors =
            imagecolorat($scaled_image, 0, 0) +
            imagecolorat($scaled_image, 0, 1) +
            imagecolorat($scaled_image, 0, 2) +
            imagecolorat($scaled_image, 1, 0) +
            imagecolorat($scaled_image, 1, 1) +
            imagecolorat($scaled_image, 1, 2) +
            imagecolorat($scaled_image, 2, 0) +
            imagecolorat($scaled_image, 2, 1) +
            imagecolorat($scaled_image, 2, 2);

        imagedestroy($scaled_image);
        imagedestroy($image);

        return ($added_colors === 0);

    }

    public static function scaleImage($image) {
        $newimage = imagecreatetruecolor(3, 3);
        imagecopyresampled(
            $newimage, $image,
            0, 0, 0, 0,
            3, 3, imagesx($image), imagesy($image)
        );
        return $newimage;
    }

}

Я использую его для удаления черных пальцев.

private function removeBlackness() {

    $files = $this->glob_recursive(public_path('img/collection/*.jpg'));
    foreach ($files as $filename) {

        if (self::fileIsBlack($filename)) {
            unlink($filename);
        }

    }

}
0 голосов
/ 31 января 2011

Если все черное, размер файла будет низким, так как он сжат. Я знаю, что JPG использует восприятие, а не RLE, но оно все равно будет меньше. Почему бы не запретить JPG до 20 КБ, например? Сделайте несколько примеров, сравните размеры, установите ваши пороги.

...