Я получил функцию, которая может считывать значение DPI из JPEG здесь.
function get_dpi($filename){
$a = fopen($filename,'r');
$string = fread($a,20);
fclose($a);
$data = bin2hex(substr($string,14,4));
$x = substr($data,0,4);
$y = substr($data,4,4);
return array(hexdec($x),hexdec($y));
}
Однако, когда я проверяю изображение, созданное Photoshop с разрешением 300 точек на дюйм, оно неправильно возвращает значение 42 точки на дюйм.
Что я пропустил?
Проблемное изображение, сгенерированное Photoshop: https://drive.google.com/open?id=117LHlgpefXZsuiVSl_nMG6MUQfKcT1MI
ОБНОВИТЬ: я попытался с помощью онлайн конвертер DPI регенерировать JPEG с разрешением 300 точек на дюйм, функция PHP сообщает правильное значение, 300 точек на дюйм.
Восстановленное изображение: https://drive.google.com/open?id=1-C4GZ8_K4wit3sISz21ngd4OVlLXuL72
Я сравнил метаданные двух файлов JPEG, сгенерированный файл JPEG имеет информацию JIFF, а исходный файл JPEG — нет. Это причина проблемы?
Учитывая, что у меня нет библиотеки Imagick, я не могу использовать ее функцию getImageResolution() для чтения значения.
обновлено в вопросе.
Может, потому что заголовок в формате exif. Может быть, вы можете попробовать использовать exif_read_data()? lastcode.net/2013/01/read-php-exif-image-meta-data.html и stackoverflow.com/questions/36332823/…
Если вы не можете использовать пред. упомянутая функция, и вам все еще нужно выяснить, чем вам нужно прочитать спецификации exif: media.mit.edu/pia/Research/deepview/exif.htmlsno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html пример программы (не в php): codeproject.com/Articles/47486/…






Спасибо за помощь от @golddragon007, мое окончательное решение состоит в том, чтобы объединить данные из различных функций следующим образом:
function get_dpi($filename){
$new_filename = time() . '_' . rand(1000, 999999) . '.jpg';
$result = move_uploaded_file($filename, 'upload/' . $new_filename);
$dpi_from_exif = get_exif ('upload/' . $new_filename);
if ($dpi_from_exif !== false) {
unlink('upload/' . $new_filename);
return $dpi_from_exif;
} else {
$a = fopen('upload/' . $new_filename,'r');
$string = fread($a, 20);
fclose($a);
$data = bin2hex(substr($string, 14, 4));
$x = substr($data, 0, 4);
$y = substr($data, 4, 4);
unlink('upload/' . $new_filename);
return hexdec($x);
}
}
function get_exif ($filename) {
$exif = exif_read_data($filename);
if ($exif === false) {
return false;
} else {
if (array_key_exists('XResolution', $exif)) {
return do_maths($exif['XResolution']);
} else {
return false;
}
}
}
function do_maths($expression) {
eval('$o = ' . preg_replace('/[^0-9\+\-\*/\(\)\.]/', '', $expression) . ';');
return $o;
}
Использование следующее:
$dpi_in_int = get_dpi($the_image_file);
Если я использую изображение, которое я указал в вопросе, функция вернет:
300
Объяснение функции:
В моем сценарии я прочитал загруженный файл (из <input type = "file" />), get_dpi($filename) сначала переместил временный загружаемый файл в папку upload/ (необязательный шаг), а затем прочитал DPI из EXIF с помощью функции get_exif ($filename).
Если DPI можно прочитать из данных EXIF, значение DPI будет возвращено; в противном случае значение DPI извлекается из метаданных JPEG (первые несколько байтов файла JPEG), что в некоторых случаях оказывается неточным (например, первое изображение, которое я предоставил).
Функция do_maths() состоит в том, чтобы проанализировать значение из XResolution данных EXIF IPF0 (что является 3000000/10000, по-видимому, математическим уравнением) и вычислить окончательное значение. Обратите внимание, что у eval() есть некоторые потенциальные проблемы с безопасностью, поэтому входные данные сначала очищаются с помощью preg_replace() регулярного выражения, чтобы гарантировать отсутствие кода инъекции. Эта функция do_maths() от https://stackoverflow.com/a/5805773/188331
Наконец, функция get_dpi() удалит загруженный файл, чтобы сэкономить место на диске сервера (необязательно).
Можете ли вы поделиться примером изображения, чтобы другие могли воспроизвести проблему?