Что сделал - 7

Сжатие файлов PDF

На прошлой неделе я узнал о прекрасной практике, когда люди, чтобы получить электронный документ меньшего размера, для отправки его, например, по почте или прикрепления куда-то на сторонний сайт, распечатывают его и сканируют заново. Я мог бы написать о своих впечатлениях от этого знания пару абзацев, но не буду, просто опишу конкретную реализацию моего решения этой проблемы.

Оказалось, что практически все программы, которые работают с PDF и не принадлежат компании Adobe, «под капотом» используют инструмент под названием Ghostscript. У него невероятная куча непонятных опций и жутковатый синтаксис, но для простоты в интернете рекомендуют использование предустановленных значений: ebook и screen. Первый вариант даёт разрешение конечного документа 150 точек/дюйм, что даёт порой недостаточно компактный размер, а второй — 72, что даёт ужасное качество. Нужно было найти некий промежуточный вариант, и я остановился на таком:

& "$ghostScript" -q -o "$outputFile" `
-sDEVICE=pdfwrite -dPDFSETTINGS=/screen `
-dColorImageDownsampleType=/Bicubic -dColorImageResolution=110 `
-dGrayImageDownsampleType=/Bicubic -dGrayImageResolution=110 `
-dMonoImageDownsampleType=/Bicubic -dMonoImageResolution=200 `
-f "$inputFile"

То есть, берётся предустановка screen, у которой принудительно повышается разрешение цветных, серых и чёрно-белых картинок, и режим их пересчёта меняется на более качественный. Значение точек на дюйм я тупо взял примерно среднее между 150 и 72, для чёрно-белых надо всегда ставить больше — они и так компактные сами по себе, и сильнее страдают от низкого разрешения.

Пример выше хорошо подходит для файлов с изображениями и цветной графикой, вроде детских учебников, но нужен ещё один компактный вариант для полностью чёрно-белых документов. Изучение вопроса показало, что в современных версиях Ghostscript нет простого способа переделывать документы в ч/б. Вкратце — раньше можно было сначала конвертировать исходный PDF в монохромный PS (PostScript) через опцию -sDEVICE=psmono, а потом обратно в PDF, добавляя ещё одну хитрую команду; потом psmono убрали, и если сейчас и есть способ такого преобразования, то какой-то совсем нетривиальный, а привязываться к старой версии не хочется. Можно делать документ в оттенках серого, но в этом нет смысла, потому что выяснилось, что разница в размерах с цветным вариантом ничтожна.

Чтобы решить задачу преобразования в ч/б, я задействовал ImageMagick, получилось так:

& "$imageMagick" -density 200 "$inputFile" `
-monochrome -compress Group4 `
"$bwFile"

Density — это указание рассматривать исходный документ с таким-то разрешением, а Group4 — это великолепный алгоритм сжатия ч/б изображений, используемый в факсах. ImageMagick при работе с PDF использует тот же Ghostscript, поэтому на сервере они должны стоять оба.

В результате система выглядит так: есть каталог, куда люди кладут PDF-файлы, каждые 3 минуты запускается задание в планировщике, скрипт читает каталог, берёт подходящие по критериям файлы в обработку, перенося их во временный каталог с текущим временем, а потом результат кладёт обратно в одноимённый подкаталог с добавлением к имени файла «(сжатый)» и «(сжатый чб)». Оригинал после обработки удаляется сразу, результаты — через час. В свойствах задания в планировщике нужно разрешить запуск нескольких экземпляров — ведь обработка может идти больше 3 минут.

Примеры обработки:

  1. Нотный сборник, 49 страниц:
Оригинал (22,8 МБ) Сжатый (5,5 МБ) Сжатый ч/б (1,8 МБ)
  1. Какой-то договор из интернета, 27 страниц:
Оригинал (15,7 МБ) Сжатый (4,5 МБ) Сжатый ч/б (2,4 МБ)

Позже обнаружился способ задания порога для устранения зернистости букв и уменьшения шума для ч/б режима. Нужно добавить -level 10%,90% +dither, но это существенно замедляет обработку.

Дополнительно я нашёл способ прописывания метаинформации в свойства PDF-документа, проще всего для этого использовать ExifTool:

gci "$temp\*.pdf" |% {
& "$exifTool" -charset filename=Cyrillic -charset Cyrillic `
-Author="Обработано в Институте сжатия ПДФ им. Красноглазова" "$($_.FullName)" > $null
}

Результат:

Может пригодиться, например, при дополнительной фильтрации входящих файлов с помощью того же ExifTool, чтобы отбрасывать на входе уже ранее сжатые этим скриптом. Вся эта возня с метаинформацией, конечно, увеличивает время обработки (при её записи файлы пересоздаются заново), так что тут надо подумать, стоит ли затеваться с этим вообще.

Включение Wake-on-LAN на Windows 8 и новее

В связи с тем, что куча народу сейчас работает из дома, пользовательские компьютеры стали работать в режиме 24/7, прямо как сервера. Тем временем, периодически проводятся какие-то работы по электрике, моргает свет и т. п., и компьютеры остаются выключенными. Чтобы включить их, сотрудник техподдержки идёт открывает кабинеты (под подпись актов, с охранником), и жмёт кнопочки включения. Есть разные способы решения этой проблемы, но, например, идея настраивать пользовательские тачки в BIOS так, чтобы они автоматически включались при обрыве питания — идея не очень; всё же есть надежда, что жизнь вернётся в нормальное русло, а в обычной ситуации такую настройку включать не нужно, да и чтобы включить её, опять же надо открыть все кабинеты, перезапустить все компьютеры, зайти им в BIOS и настроить руками, что наводит тоску, когда у тебя в хозяйстве больше полутысячи машин. Мне рассказали, что техподдержка уже несколько лет как включает в BIOS опцию пробуждения компьютера при запросе из сети (Wake-on-LAN), но проблема заключалась в том, что старые системы, типа Windows 7, нормально пробуждаются, а вот новые, вроде Windows 10 — нет. Соответственно, возникла необходимость разобраться, в чём дело.

Полез читать интернеты. Выяснилось, что поведение WoL на системах Windows 8 и новее отличается от более старых. Грубо говоря, в новых системах статус S5 (т. е., «компьютер выключен») стал более строгим — если компьютер выключен, значит, он должен быть реально выключен, т. е., энергопотребление должно быть равным нулю. В связи с этим, чтобы можно было будить комп с новой системой, он при выборе пользователем пункта «выключить компьютер» должен переходить в некое промежуточное состояние S4 (гибридное выключение или «быстрый запуск»). Этот быстрый запуск, или Fast boot, включён в новых системах изначально, но если он выключен, его нужно включить либо через групповую политику, либо через реестр.

Второй момент — в системе должен стоять свежий драйвер сетевой карты, чтобы в его настройках была вкладка «Управление электропитанием». В варианте Windows 10 1809, широко распространённом у меня на работе, стандартный драйвер не имеет этой вкладки, соответственно, комп не просыпается и настроить его невозможно. Пришлось писать скрипт, обновляющий драйверы на машинах в зависимости от модели адаптера. В варианте 1909 уже всё в порядке изначально.

Третий момент — на этой вкладке должны быть включены как минимум две верхних галки из трёх, а лучше все три, чтобы не будить комп зазря (как их включить удалённо, см. статью Information about power management setting on a network adapter). Причём, обнаружилось, что если снять верхнюю галку, компьютер перестаёт просыпаться (а отключать этот пункт — широко распространённая практика).

Я был удивлён тем фактом, что настройки операционной системы влияют на пробуждение компьютера, когда, казалось бы, она не загружена и не должна ни на что влиять, но это реальность. Наверное, через драйвер меняются настройки самого железа, которые и срабатывают впоследствии, не знаю.

Четвёртый момент — в тех же настройках драйвера на вкладке «Дополнительно» чаще всего нужно отключить настройки типа «зелёный ethernet» и «энергосберегающий ethernet», чтобы адаптер не засыпал. Например, это указано в инструкции по настройке WoL для компьютеров Dell, которые встречаются в моей сети, в общем, надо смотреть инструкции на сайтах производителей по поводу тонкостей. А вот настройки со словами «wake» и «magic packet», наверное, стоит включить все, надо просмотреть их и разбираться в каждом отдельном случае. Для управления электропитанием сетевого адаптера в Powershell существуют удобные команды

Get-NetAdapterPowerManagement
Enable-NetAdapterPowerManagement
Disable-NetAdapterPowerManagement
# Для доп. опций
Get-NetAdapterAdvancedProperty
Set-NetAdapterAdvancedProperty

После сбора информации, тестировании на выделенном мне неттопе HP, массового обновления драйверов на компьютерах в рабочей сети, для чего был написан отдельный скрипт, и реализации всего вышеупомянутого добра в групповой политике, тачки с «десяткой», где был правильно настроен BIOS, начали включаться.

Так как, в числе прочего, у меня в AD пишется и MAC-адрес активных сетевых адаптеров компьютеров, то не проблема будить их, используя Wake-on-LAN, прямо из Powershell просто по имени машины, и это отлично.