Статьи

Дополнения Ubuntu с PHP

Семейный альбом растет и справляется с объемом изображений, хранящихся под Ubuntu , становится проблемой. С отношением — «тратить время, чтобы сэкономить время» — начал изучать варианты какого-то цифрового рабочего процесса, чтобы автоматизировать все, что я могу или, по крайней мере, сводить щелчки мыши к минимуму.

Одна конкретная проблема — добавление комментариев к изображениям; В большинстве программ архивирования (например, gthumb ) вы храните данные отдельно от изображений, сохраняя свои собственные базы данных (в случае gthumb — ~/.gnome2/gthumb ). Но я бы предпочел, чтобы комментарии оставались с изображением (например, используя Exif — есть и другие способы, но Exif выигрывает благодаря широкой поддержке).

Сценарий Наутилус

Случайно натолкнулся на g-scripts и идею, что вы можете расширить Nautilus (графический интерфейс файлового менеджера Ubuntu) своими собственными сценариями. На самом деле здесь есть краткое руководство. В примерах g-скриптов используются bash-скрипты, но я подумал, что это хорошая возможность неправильно использовать PHP.

Zenity

В дополнение к расширению Nautilus, также использовались преимущества Zenity (я использую Ubuntu, как в Gnome, а не Kbuntu), который позволяет вам выводить диалоги из сценариев оболочки. Например, если вы запустите $ zenity --question --text "Feeling OK?" , всплывает диалоговое окно, как …

Здесь больше о Зените. На самом деле это плохая идея использовать PHP для этого, учитывая, что в Perl это реализовано с помощью UI :: Dialog , который поддерживает несколько бэкэндов, включая Zenity и KDialog (то есть ваши сценарии могли бы тогда работать и под Kbuntu), но для интереса продолжим с PHP Вот.

подсказки

В любом случае — несколько быстрых советов (которые в значительной степени описаны в приведенных выше уроках), а затем код.

  • Вы храните свои скрипты в ~/.gnome2/nautilus-scripts
  • Убедитесь, что у вас установлен пакет php5-cli ( $ sudo apt-get install php5-cli )
  • Вам нужно добавить строку PHP shebang в верхней части вашего скрипта (я опустил расширение .php), например #!/usr/bin/php
  • Убедитесь, что вы делаете их исполняемыми ( $ chmod +x ~/.gnome2/nautilus-scripts/myscript )
  • Чтобы активировать сценарии, вам нужно указать Nautilus в каталоге сценариев (меню: Перейти> Местоположение). Возможно, вам придется перезагрузить, если вы создаете дополнительные сценарии
  • Чтобы запустить сценарии, щелкните правой кнопкой мыши файл и выберите меню сценариев.

Exif Manipulation

В любом случае — удалось объединить два скрипта, один для просмотра комментариев Exif (для которого было проще всего использовать функцию exif_read_data () ) в информационном диалоговом окне Zenity, а другой для редактирования комментариев с помощью диалогового окна ввода текста Zenity. Для второго я использовал превосходную библиотеку PEL Мартина Гайслера , в которой есть пример, который я мог бы в значительной степени скопировать и вставить, заменив интерфейс командной строки на Zenity (примечание: PEL 0.9 не совсем стабилен, кажется — если вы получаете сообщения об ошибках о переопределении констант, отредактируйте скрипт и прокомментируйте второе назначение констант). Итак, теперь щелкнув правой кнопкой мыши на изображении и выбрав мой скрипт exif_comment_edit я получаю диалог, похожий на

Код…

exif_view_comment

#!/usr/bin/php <?php function ohDearMe($msg) { `zenity --error --text="$msg" --title="Exif Info Error"`; exit(1); } if ( !isset($argv[1]) ) { ohDearMe("Image filename required"); exit(1); } $file = getcwd().'/'.$argv[1]; if (!is_readable($file)) { ohDearMe(sprintf("Unable to read: %s", $file)); exit(1); } $title = 'Exif Info for '.addslashes(basename($file)); $data = exif_read_data($file); if ( !$data ) { ohDearMe('Unrecognized image format!'); } if ( !isset($data['ImageDescription']) || trim($data['ImageDescription']) == '' ) { ohDearMe('Image contains no comment'); } $out = $data['ImageDescription']; `zenity --info --text="$out" --title="$title"`;
#!/usr/bin/php <?php function ohDearMe($msg) { `zenity --error --text="$msg" --title="Exif Info Error"`; exit(1); } if ( !isset($argv[1]) ) { ohDearMe("Image filename required"); exit(1); } $file = getcwd().'/'.$argv[1]; if (!is_readable($file)) { ohDearMe(sprintf("Unable to read: %s", $file)); exit(1); } $title = 'Exif Info for '.addslashes(basename($file)); $data = exif_read_data($file); if ( !$data ) { ohDearMe('Unrecognized image format!'); } if ( !isset($data['ImageDescription']) || trim($data['ImageDescription']) == '' ) { ohDearMe('Image contains no comment'); } $out = $data['ImageDescription']; `zenity --info --text="$out" --title="$title"`; 

exif_edit_comment

#!/usr/bin/php <?php require_once('pel/PelDataWindow.php'); require_once('pel/PelJpeg.php'); require_once('pel/PelTiff.php'); function ohDearMe($msg) { `zenity --error --text="$msg" --title="Exif Info Error"`; exit(1); } if ( !isset($argv[1]) ) { ohDearMe("Image filename required"); exit(1); } $in = getcwd().'/'.$argv[1]; if (!is_readable($in)) { ohDearMe(sprintf("Unable to read: %s", $in)); exit(1); } $title = 'Exif Info for '.addslashes(basename($in)); $data = new PelDataWindow(file_get_contents($in)); if (PelJpeg::isValid($data)) { $jpeg = $file = new PelJpeg(); $jpeg->load($data); $app1 = $jpeg->getSection(PelJpegMarker::APP1); if ($app1 == null) { $app1 = new PelExif(); $jpeg->insertSection(PelJpegMarker::APP1, $app1, 2); $tiff = new PelTiff(); $app1->setTiff($tiff); } else { $tiff = $app1->getTiff(); } } elseif (PelTiff::isValid($data)) { $tiff = $file = new PelTiff(); $tiff->load($data); } else { ohDearMe('Unrecognized image format!'); } $ifd0 = $tiff->getIfd(); if ($ifd0 == null) { $ifd0 = new PelIfd(); $tiff->setIfd($ifd0); } $desc = $ifd0->getEntry(PelTag::IMAGE_DESCRIPTION); if ($desc == null) { $description = exec( 'zenity --entry --title="Exif New Comment" --text="Enter comment" --width=800 2>&1' ); $desc = new PelEntryAscii(PelTag::IMAGE_DESCRIPTION, $description); $ifd0->addEntry($desc); } else { $entry_text = addslashes($desc->getValue()); $description = exec('zenity --entry --title="Exif Existing Comment" --entry-text="'. $entry_text.'" --text="Enter comment" --width=800 2>&1'); $desc->setValue($description); } file_put_contents($in, $file->getBytes()); - #!/usr/bin/php <?php require_once('pel/PelDataWindow.php'); require_once('pel/PelJpeg.php'); require_once('pel/PelTiff.php'); function ohDearMe($msg) { `zenity --error --text="$msg" --title="Exif Info Error"`; exit(1); } if ( !isset($argv[1]) ) { ohDearMe("Image filename required"); exit(1); } $in = getcwd().'/'.$argv[1]; if (!is_readable($in)) { ohDearMe(sprintf("Unable to read: %s", $in)); exit(1); } $title = 'Exif Info for '.addslashes(basename($in)); $data = new PelDataWindow(file_get_contents($in)); if (PelJpeg::isValid($data)) { $jpeg = $file = new PelJpeg(); $jpeg->load($data); $app1 = $jpeg->getSection(PelJpegMarker::APP1); if ($app1 == null) { $app1 = new PelExif(); $jpeg->insertSection(PelJpegMarker::APP1, $app1, 2); $tiff = new PelTiff(); $app1->setTiff($tiff); } else { $tiff = $app1->getTiff(); } } elseif (PelTiff::isValid($data)) { $tiff = $file = new PelTiff(); $tiff->load($data); } else { ohDearMe('Unrecognized image format!'); } $ifd0 = $tiff->getIfd(); if ($ifd0 == null) { $ifd0 = new PelIfd(); $tiff->setIfd($ifd0); } $desc = $ifd0->getEntry(PelTag::IMAGE_DESCRIPTION); if ($desc == null) { $description = exec( 'zenity --entry --title="Exif New Comment" --text="Enter comment" --width=800 2>&1' ); $desc = new PelEntryAscii(PelTag::IMAGE_DESCRIPTION, $description); $ifd0->addEntry($desc); } else { $entry_text = addslashes($desc->getValue()); $description = exec('zenity --entry --title="Exif Existing Comment" --entry-text="'. $entry_text.'" --text="Enter comment" --width=800 2>&1'); $desc->setValue($description); } file_put_contents($in, $file->getBytes()); - #!/usr/bin/php <?php require_once('pel/PelDataWindow.php'); require_once('pel/PelJpeg.php'); require_once('pel/PelTiff.php'); function ohDearMe($msg) { `zenity --error --text="$msg" --title="Exif Info Error"`; exit(1); } if ( !isset($argv[1]) ) { ohDearMe("Image filename required"); exit(1); } $in = getcwd().'/'.$argv[1]; if (!is_readable($in)) { ohDearMe(sprintf("Unable to read: %s", $in)); exit(1); } $title = 'Exif Info for '.addslashes(basename($in)); $data = new PelDataWindow(file_get_contents($in)); if (PelJpeg::isValid($data)) { $jpeg = $file = new PelJpeg(); $jpeg->load($data); $app1 = $jpeg->getSection(PelJpegMarker::APP1); if ($app1 == null) { $app1 = new PelExif(); $jpeg->insertSection(PelJpegMarker::APP1, $app1, 2); $tiff = new PelTiff(); $app1->setTiff($tiff); } else { $tiff = $app1->getTiff(); } } elseif (PelTiff::isValid($data)) { $tiff = $file = new PelTiff(); $tiff->load($data); } else { ohDearMe('Unrecognized image format!'); } $ifd0 = $tiff->getIfd(); if ($ifd0 == null) { $ifd0 = new PelIfd(); $tiff->setIfd($ifd0); } $desc = $ifd0->getEntry(PelTag::IMAGE_DESCRIPTION); if ($desc == null) { $description = exec( 'zenity --entry --title="Exif New Comment" --text="Enter comment" --width=800 2>&1' ); $desc = new PelEntryAscii(PelTag::IMAGE_DESCRIPTION, $description); $ifd0->addEntry($desc); } else { $entry_text = addslashes($desc->getValue()); $description = exec('zenity --entry --title="Exif Existing Comment" --entry-text="'. $entry_text.'" --text="Enter comment" --width=800 2>&1'); $desc->setValue($description); } file_put_contents($in, $file->getBytes()); - #!/usr/bin/php <?php require_once('pel/PelDataWindow.php'); require_once('pel/PelJpeg.php'); require_once('pel/PelTiff.php'); function ohDearMe($msg) { `zenity --error --text="$msg" --title="Exif Info Error"`; exit(1); } if ( !isset($argv[1]) ) { ohDearMe("Image filename required"); exit(1); } $in = getcwd().'/'.$argv[1]; if (!is_readable($in)) { ohDearMe(sprintf("Unable to read: %s", $in)); exit(1); } $title = 'Exif Info for '.addslashes(basename($in)); $data = new PelDataWindow(file_get_contents($in)); if (PelJpeg::isValid($data)) { $jpeg = $file = new PelJpeg(); $jpeg->load($data); $app1 = $jpeg->getSection(PelJpegMarker::APP1); if ($app1 == null) { $app1 = new PelExif(); $jpeg->insertSection(PelJpegMarker::APP1, $app1, 2); $tiff = new PelTiff(); $app1->setTiff($tiff); } else { $tiff = $app1->getTiff(); } } elseif (PelTiff::isValid($data)) { $tiff = $file = new PelTiff(); $tiff->load($data); } else { ohDearMe('Unrecognized image format!'); } $ifd0 = $tiff->getIfd(); if ($ifd0 == null) { $ifd0 = new PelIfd(); $tiff->setIfd($ifd0); } $desc = $ifd0->getEntry(PelTag::IMAGE_DESCRIPTION); if ($desc == null) { $description = exec( 'zenity --entry --title="Exif New Comment" --text="Enter comment" --width=800 2>&1' ); $desc = new PelEntryAscii(PelTag::IMAGE_DESCRIPTION, $description); $ifd0->addEntry($desc); } else { $entry_text = addslashes($desc->getValue()); $description = exec('zenity --entry --title="Exif Existing Comment" --entry-text="'. $entry_text.'" --text="Enter comment" --width=800 2>&1'); $desc->setValue($description); } file_put_contents($in, $file->getBytes());
#!/usr/bin/php <?php require_once('pel/PelDataWindow.php'); require_once('pel/PelJpeg.php'); require_once('pel/PelTiff.php'); function ohDearMe($msg) { `zenity --error --text="$msg" --title="Exif Info Error"`; exit(1); } if ( !isset($argv[1]) ) { ohDearMe("Image filename required"); exit(1); } $in = getcwd().'/'.$argv[1]; if (!is_readable($in)) { ohDearMe(sprintf("Unable to read: %s", $in)); exit(1); } $title = 'Exif Info for '.addslashes(basename($in)); $data = new PelDataWindow(file_get_contents($in)); if (PelJpeg::isValid($data)) { $jpeg = $file = new PelJpeg(); $jpeg->load($data); $app1 = $jpeg->getSection(PelJpegMarker::APP1); if ($app1 == null) { $app1 = new PelExif(); $jpeg->insertSection(PelJpegMarker::APP1, $app1, 2); $tiff = new PelTiff(); $app1->setTiff($tiff); } else { $tiff = $app1->getTiff(); } } elseif (PelTiff::isValid($data)) { $tiff = $file = new PelTiff(); $tiff->load($data); } else { ohDearMe('Unrecognized image format!'); } $ifd0 = $tiff->getIfd(); if ($ifd0 == null) { $ifd0 = new PelIfd(); $tiff->setIfd($ifd0); } $desc = $ifd0->getEntry(PelTag::IMAGE_DESCRIPTION); if ($desc == null) { $description = exec( 'zenity --entry --title="Exif New Comment" --text="Enter comment" --width=800 2>&1' ); $desc = new PelEntryAscii(PelTag::IMAGE_DESCRIPTION, $description); $ifd0->addEntry($desc); } else { $entry_text = addslashes($desc->getValue()); $description = exec('zenity --entry --title="Exif Existing Comment" --entry-text="'. $entry_text.'" --text="Enter comment" --width=800 2>&1'); $desc->setValue($description); } file_put_contents($in, $file->getBytes()); 

Само собой разумеется, но все равно скажут — используйте на свой страх и риск!