Получить тип изображения из ресурса в PHP / GD?
Я пытаюсь найти тип mime изображения. PHP имеет функцию getimagesize
но для этого требуется только имя файла, тогда как у меня есть "ресурс" изображения-то есть изображение, созданное из imagecreatefromstring
.
Я нашел функции imagesx
и imagesy
которые возвращают ширину / высоту из ресурса, но я не могу найти функцию, которая говорит мне тип mime из ресурса. Кто-нибудь знает, как это сделать?
Примечание: из-за странной настройки сервера, мы не могу читать/писать файлы С сервера обычно, только через FTP-слой (где я читаю данные изображения).
4 ответов
Я знаю, что это довольно старый, но на всякий случай кто-то наткнулся на этот пост, как я...
лучший вариант он был выпущен из PHP 5.4.0: getimagesizefromstring
эта новая функция точно такая же, как и getimagesize, но позволяет вам извлекать информацию из потока.
Если у вас есть доступ к двоичным данным изображения (как предполагает использование 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);
изображение, созданное с помощью imagecreatefromstring
больше не имеет типа MIME, он декодируется из собственного формата и хранится во внутреннем формате GD.
тот же вопрос попросил некоторое время назад С тем же результатом.
единственный способ пойти-поймать изображение, прежде чем оно получит imagecreatefromstring
ed, и как-то поймать информацию о размере из него.
вы говорите, что не можете выполнять операции чтения/записи файлов в вашей системе, поэтому просто напишите файл находится вне вопрос.
тот факт, что getimagesize() не может читать из переменных, известен и оплакивается:http://bugs.php.net/bug.php?id=44239
парень там упоминает отличный обходной путь:регистрация новой обертки потока, которая позволяет файловые операции с переменными.
это опция в вашей настройке сервера?
вы можете использовать функции PHP fileinfo.
$image_buffer = SomeFunctionToGetStringBufferFromGD();
$fileinfo = finfo_open();
$type = finfo_buffer($fileinfo, $image_buffer);
использует магия чисел (то же, что и команда Unix file) для идентификации типа файла.