Получить изображение mimetype от ресурса в PHP/GD?

Я пытаюсь найти тип пантомимы изображения. PHP имеет функцию getimagesize но это только берет имя файла, тогда как у меня есть изображение "ресурс" вместо этого - т.е. изображение, созданное из imagecreatefromstring.

Я нашел функции imagesx и imagesy которые возвращают ширину/высоту из ресурса, но я не могу найти функцию, которые говорят мне тип пантомимы от ресурса. Кто-либо знает о способе сделать это?

Примечание: Из-за странного настроенного сервера, мы не можем файлы чтения-записи с сервера обычно, только через уровень FTP (который является, где я считал данные изображения из).

9
задан DisgruntledGoat 5 February 2010 в 12:42
поделиться

3 ответа

Вы могли бы использовать функции PHP fileinfo.

$image_buffer = SomeFunctionToGetStringBufferFromGD();

$fileinfo = finfo_open();

$type = finfo_buffer($fileinfo, $image_buffer);

Он использует магические числа (такие же, как команда файла unix) для определения типа файла.

0
ответ дан 4 December 2019 в 07:23
поделиться

Образ, созданный с использованием imagecreatefromstring , больше не имеет типа MIME, он декодируется из своего собственного формата и сохраняется во внутреннем формате GD.

Тот же вопрос был задан некоторое время назад с тем же результатом.

Единственный способ сделать это - поймать изображение до того, как оно получит imagecreatefromstring , и каким-то образом уловить из него информацию о размере.

Вы говорите, что не можете выполнять операции чтения / записи файлов в своей системе, поэтому просто о записи файла не может быть и речи.

Тот факт, что getimagesize () не может читать из переменных, известен и причитается: http://bugs.php.net/bug.php?id=44239

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

Это опция в настройках вашего сервера?

10
ответ дан 4 December 2019 в 07:23
поделиться

Если у вас есть доступ к двоичным данным изображения (например, использование imagecreatefromstring ( ) предлагает), вы можете определить тип файла «вручную»:


function image_file_type_from_binary($binary) {
    if (
        !preg_match(
            '/\A(?:(\xff\xd8\xff)|(GIF8[79]a)|(\x89PNG\x0d\x0a)|(BM)|(\x49\x49(?:\x2a\x00|\x00\x4a))|(FORM.{4}ILBM))/',
            $binary, $hits
        )
    ) {
        return 'application/octet-stream';
    }
    static $type = array (
        1 => 'image/jpeg',
        2 => 'image/gif',
        3 => 'image/png',
        4 => 'image/x-windows-bmp',
        5 => 'image/tiff',
        6 => 'image/x-ilbm',
    );
    return $type[count($hits) - 1];
}

Злоупотребление оболочкой потока становится немного сложнее. По крайней мере, если мы не хотим возиться с глобальными переменными.


// getimagesize() from string
class GisFromString {
    const proto_default = 'gisfromstring';
    protected static $proto = null;
    protected static $imgdata = null;

    static function getImageSize($imgdata) {
        if (null === self::$proto) {
            self::register();
        }
        self::$imgdata = $imgdata;
        // note: @ suppresses "Read error!" notices if $imgdata isn't valid
        return @getimagesize(self::$proto . '://');
    }

    static function getMimeType($imgdata) {
        return is_array($gis = self::getImageSize($imgdata))
            ? $gis['mime']
            : $gis;
    }

    // streamwrapper helper:

    const unregister = null;

    // register|unregister wrapper for the given protocol|scheme
    // return registered protocol or null
    static function register(
        $proto = self::proto_default // protocol or scheme
    ) {
        if (self::unregister === $proto) { // unregister if possible
            if (null === self::$proto) {
                return null;
            }
            if (!stream_wrapper_unregister(self::$proto)) {
                return null;
            }
            $return = self::$proto;
            self::$proto = null;
            return $return;
        }
        if (!preg_match('/\A([a-zA-Z][a-zA-Z0-9.+\-]*)(:([\/\x5c]{0,3}))?/', $proto, $h)) {
            throw new Exception(
                sprintf('could not register invalid scheme or protocol name "%s" as streamwrapper', $proto)
            );
        }
        if (!stream_wrapper_register($proto = $h[1], __CLASS__)) {
            throw new Exception(
                sprintf('protocol "%s" already registered as streamwrapper', $proto)
            );
        }
        return self::$proto = $proto;
    }

    // streamwrapper API:

    function stream_open($path, $mode) {
        $this->str = (string) self::$imgdata;
        $this->fsize = strlen($this->str);
        $this->fpos = 0;
        return true;
    }

    function stream_close() {
        self::$imgdata = null;
    }

    function stream_read($num_bytes) {
        if (!is_numeric($num_bytes) || $num_bytes < 1) {
            return false;
        }
        /* uncomment this if needed
        if ($this->fpos + $num_bytes > 65540 * 4) {
            // prevent getimagesize() from scanning the whole file
            // 65_540 is the maximum possible bytesize of a JPEG segment
            return false;
        }
        */
        if ($this->fpos + $num_bytes > $this->fsize) {
            $num_bytes = $this->fsize - $this->fpos;
        }
        $read = substr($this->str, $this->fpos, $num_bytes);
        $this->fpos += strlen($read);
        return $read;
    }

    function stream_eof() {
        return $this->fpos >= $this->fsize;
    }

    function stream_tell() {
        return $this->fpos;
    }

    function stream_seek($off, $whence = SEEK_SET) {
        if (SEEK_CUR === $whence) {
            $off = $this->fpos + $off;
        }
        elseif (SEEK_END === $whence) {
            $off = $this->fsize + $off;
        }
        if ($off < 0 || $off > $this->fsize) {
            return false;
        }
        $this->fpos = $off;
        return true;
    }
}


// usage:
//$imgdata = file_get_contents('path/lenna.jpg');


// if the default protocol is already registered
//GisFromString::register('other');

var_dump(GisFromString::getImageSize($imgdata));

echo GisFromString::getMimeType($imgdata);
12
ответ дан 4 December 2019 в 07:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: