EXIF фотогалереи выводит информацию в некорректном виде

InstantCMS 2.X
#1 27 июля 2019 в 23:04
Здравствуйте.

Использую InstantCMS 2.12.2.
Загружаю фотографии в альбомы стандартной Галереи. При просмотре фотографии система отображает данные EXIF из фотографий.
В не корректном виде отображаются:
1. Выдержка. Показывает 10/900 вместо 1/90 (на фото сделанное на Fujifilm X-T10). При этом на фото с Nikon D750 выдержка выводится корректно.
2. Фокусное расстояние. Показывает 5500/100 вместо 55[мм] или 4000/10 вместо 400[мм]. Этот параметр на фото с Nikon и с Fujifilm отображается одинаково некорректно. Примеры фото прикладываю.

Впечатление такое, что или в библиотеке exif или потом при выводе на экран зачем то умножаются числитель и знаменатель на 10. Но не всегда, т.к. выдержка на фото с Nikon 1/250 — отобразилась корректно.

Подскажите, пожалуйста, где и что можно исправить?

p.s. дополню, что указанные значения хранятся уже в некорректном виде в БД.
значение поля 'exif' для утят:
---
aperturefnumber: f/8.0
exposuretime: 1/250
isospeedratings: 200
focallength: 4000/10

значение поля 'exif' для иконы:
---
aperturefnumber: f/4.0
exposuretime: 10/900
isospeedratings: 3200
focallength: 5500/100
Прикрепленный файл
fuji_3u80e.jpg 88 Кб
#2 29 июля 2019 в 22:54
Дополняю.
Выводимая "дата съемки" не соответствует данным EXIF-а.
Фотографии иконы по exif сделана 16.06.2019 10:38
А выводится сейчас в качестве даты съемки дата загрузки этого фото в альбом.
В БД в таблице cms_photos есть два поля с датой:
date_pub и date_photo. Первая, как я понимаю, дата публикации. А вторая, по идее, должна быть датой съемки из exif. Но сейчас здесь сохраняется дата загрузки фотографии в альбом.

Подведу итого.
Данные из exif забираются, но обработка и сохранение некоторых значений не совсем корректны.

focallength:нужно сохранять в БД одним целым числом, поделив числитель на знаменатель. Т.е. вместо 4000/10 записать 400. Вместо 1960/100 нужно, округлив до целого, записать 20.

exposuretime: тут неоднозначно. Для зеркалки Nikon D750 и Canon EOS 5D Mark II все выводится корректно! Для старой мыльницы Canon PowerShot A520, и беззеркалки Fujifilm X-T10 (2015 год) и числитель и знаменатель нужно делить на 10. Вместо 10/900 записать в БД 1/90

Дата съемки из exif или не считывается или присутствует логическая ошибка при ее сохранении в БД. Т.к. сейчас сохраняется дата загрузки этого фото.
#3 31 июля 2019 в 23:32
Мой вариант решения. Немного исправил обработку данных exif в функции img_get_params в /system/libs/files.helper.php

1. Модель камеры выводится корректно с именем производителя. Протестировал на имеющихся фото от Nikon, Canon, Fujifilm, Nokia Lumia, Apple iPhone, Meizu, Lenovo, Sony Errcsson.
Здесь оказалось, что в параметр exif 'IFD0.Model' Canon и Nikon, а также смартфон Lenovo прописывают не только модель аппарата, но и имя компании. Хотя для этого есть отдельное поле 'IFD0.Make'. Для этих берем только 'Model' Остальные фирмы разделяют данные на два поля, поэтому для них данные объединяем Make+Model.

2. Выдержка (exposuretime) отображается всегда в виде 1/число (в сек.)

3. Фокусное расстояние (focallength) отображается целым числом (в мм.)

4. Дополнительно вывел эквивалентное фокусное расстояние (focallengthin35mmfilm). Отображается целым числом (в мм.) Мне это интересно.

5. Что касается даты, оказалось, что Photoshop меняет при обработке exif параметр 'IFD0.DateTime'. Сносит дату съемки и ставит дату сохранения файла. Ну типа, "того ты же пофотошопил, значит это уже не оригинал". Поэтому из 3-х вариантов получения даты создания в функции, этот исключил (комментирован).

  1.  
  2. function img_get_params($path){
  3.  
  4. $s = getimagesize($path);
  5. if ($s === false) { return false; }
  6.  
  7. $exif_data = array();
  8. $exif = (function_exists('exif_read_data') && $s['mime'] === 'image/jpeg' ? (@exif_read_data($path, null, true)) : null);
  9. if($exif){
  10. if(isset($exif['COMPUTED']['ApertureFNumber'])){
  11. $exif_data['aperturefnumber'] = $exif['COMPUTED']['ApertureFNumber'];
  12. } elseif(isset($exif['EXIF']['FNumber'])){
  13. $num = explode('/', $exif['EXIF']['FNumber']);
  14. $exif_data['aperturefnumber'] = 'f/'.($num[0]/$num[1]);
  15. }
  16. if(isset($exif['EXIF']['ExposureTime'])){
  17. $num = explode('/', $exif['EXIF']['ExposureTime']);
  18. $exif_data['exposuretime'] = ($num[0] == 1) ? $exif['EXIF']['ExposureTime'] : '1/'.round($num[1]/$num[0]).'s';
  19. } elseif(isset($exif['IFD0']['ExposureTime'])){
  20. $exif_data['exposuretime'] = $exif['IFD0']['ExposureTime'];
  21. }
  22. $make = false;
  23. if(isset($exif['IFD0']['Make'])){
  24. if ($exif['IFD0']['Make']!='NIKON CORPORATION'&&$exif['IFD0']['Make']!='Canon'&&$exif['IFD0']['Make']!='Lenovo '){
  25. $exif_data['camera'] = $exif['IFD0']['Make'];
  26. $make = true;
  27. }
  28. }
  29. if(isset($exif['IFD0']['Model'])){
  30. $exif_data['camera'] = $make ? $exif['IFD0']['Make'].' '.$exif['IFD0']['Model'] : $exif['IFD0']['Model'];
  31. }
  32. // if(isset($exif['IFD0']['DateTime'])){
  33. // $exif_data['date'] = $exif['IFD0']['DateTime'];
  34. // } elseif(isset($exif['EXIF']['DateTimeOriginal'])){
  35. if(isset($exif['EXIF']['DateTimeOriginal'])){
  36. $exif_data['date'] = $exif['EXIF']['DateTimeOriginal'];
  37. } elseif(isset($exif['EXIF']['DateTimeDigitized'])){
  38. $exif_data['date'] = $exif['EXIF']['DateTimeDigitized'];
  39. }
  40.  
  41. if(isset($exif['EXIF']['ISOSpeedRatings'])){
  42. $exif_data['isospeedratings'] = $exif['EXIF']['ISOSpeedRatings'];
  43. if(is_array($exif_data['isospeedratings'])){
  44. $exif_data['isospeedratings'] = current($exif_data['isospeedratings']);
  45. }
  46. }
  47.  
  48. if(isset($exif['EXIF']['FocalLength'])){
  49. $num = explode('/', $exif['EXIF']['FocalLength']);
  50. $exif_data['focallength'] = floor($num[0]/$num[1]).'mm';
  51. }
  52.  
  53. if(isset($exif['EXIF']['FocalLengthIn35mmFilm'])){
  54. $exif_data['focallengthin35mmfilm'] = $exif['EXIF']['FocalLengthIn35mmFilm'].'mm';
  55. }
  56.  
  57. if(isset($exif['IFD0']['Orientation'])){
  58. $exif_data['orientation'] = $exif['IFD0']['Orientation'];
  59. }
  60. }
  61.  
  62. $orientation = 'square';
  63. if($s[0] > $s[1]){
  64. $orientation = 'landscape';
  65. }
  66. if($s[0] < $s[1]){
  67. $orientation = 'portrait';
  68. }
  69.  
  70. return array(
  71. 'orientation' => $orientation,
  72. 'width' => $s[0],
  73. 'height' => $s[1],
  74. 'mime' => $s['mime'],
  75. 'exif' => $exif_data,
  76. 'filesize' => round(filesize($path))
  77. );
  78.  
  79. }
  80.  
Пример:
#4 1 августа 2019 в 00:29
@bestit, спасибо, изучу ваши правки и внесу в релиз.
#5 1 августа 2019 в 00:44
Поддержу @bestit, сам занимаюсь фото и замечал что или в библиотеке exif или потом при выводе на экран умножаются числитель и знаменатель.
Хорошо бы что бы были настройки. Ну и конечно настройки скрывать или показывать эти данные.
Очень не хватает гибких настроек в фотоальбомах+ добавление стандартных полей.
Спасибо Fuze что обратили на это внимание.
#6 1 августа 2019 в 04:25
Скажите пожалуйста как отключить все эти данные кроме кнопки скачать
#7 1 августа 2019 в 07:55
Я отключаю их с помощью
Функция скрыть элемент
#8 1 августа 2019 в 11:44

@bestit, спасибо, изучу ваши правки и внесу в релиз.

Fuze
Fuze, благодарю, что обратили внимание на мой пост.

Дополню, что к сожалению, производители оборудования по-своему заполняют поля exif, хотя и существует стандарт (который, правда, тоже меняется со временем).

Вот, например, смартфон Lenovo так заполняет поля о себе:


Поэтому в моем коде в месте проверки на совпадение Make со значением 'Lenovo' нужно обернуть trim()-ом
Ну или вообще как-то иначе реализовать этот блок. Плохо, что в коде явно что-то прописывается. Решение не получается универсальным, я ведь далеко не все камеры проверил, только те, фото с которых были под рукой.
Может быть лучше получать оба поля, затем проверять вхождение первого во второе и по результату записывать в $camera только Model или Make.' '.Model.

Но тут Nikon выпендрился из всех. Он записывает в Make не просто 'Nikon', а 'NIKON CORPORATION'. Это снова усложняет предложенную проверку.
Вы не можете отвечать в этой теме.
Войдите или зарегистрируйтесь, чтобы писать на форуме.
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.