Семейный альбом растет и справляется с объемом изображений, хранящихся под 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());
Само собой разумеется, но все равно скажут — используйте на свой страх и риск!