Создать PDF-файлы из картинок по схожим признакам в именах

Обсуждение вопросов автоматизации Total Commander с помощью сторонних программ и скриптовых технологий.

Модераторы: Avada, CaptainFlint, Nik, d-view, Моторокер

kabatov
Сообщения: 12
Зарегистрирован: Сб янв 19, 2019 14:56

Создать PDF-файлы из картинок по схожим признакам в именах

Сообщение kabatov »

Добрый день.

Есть потребность автоматизировать процесс создания многостраничных pdf. Суть такова: в активной панели открыта папка с большим количеством tiff. Имена файлов не совсем произвольные и имеют следующий вид: scan_001-01.tif, scan_001-02.tif <...> scan_001-55.tif, image_001.tif, image_002.tif <...> image_850.tif, pic 00.tif, pic 01.tif <...> pic 99.tif и т. д. Необходимо сделать так, чтобы по нажатии кнопки на панели TC в открытой в другой панели папке были созданы многостраничные pdf из групп файлов, определяемых умным скриптом автоматически (т. е. scan_001.pdf, image.pdf, pic.pdf). На деле в именах файлов обычно гораздо больше порядка, но хотелось бы получить средство, не зависящее от наличия разделителя и четко заданной маски имени. Однако, если последнее условие в принципе не выполнимо, подойдет и что-то раз и навсегда настроенное на работу с файлами, именованными строго определенным образом.
Для создания pdf используется утилита NConvert разработчика программы XnView.
Все, что удалось сделать самостоятельно по прочтении большого количества здешних тем, это кнопка, создающая pdf из выделенных в активной панели файлов:

Код: Выделить всё

TOTALCMD#BAR#DATA
%COMMANDER_PATH%\Utils\NConvert\nconvert.exe
-multi -o "%T%%" -out pdf -q 100 -c 3 -l "%L"
shell32.dll,250
выделенные файлы — в многостраничный PDF
Из кода кнопки видно, какие параметры конвертации требуются. Эта кнопка, конечно, облегчит работу, но не решает описанной задачи. Заранее спасибо всем, кто готов поломать голову над решением.
Аватара пользователя
Flasher
Сообщения: 14229
Зарегистрирован: Пт ноя 06, 2009 00:33
Откуда: Москва

Сообщение Flasher »

Код: Выделить всё

'================================ VBS ================================
' Создать PDFs из картинок активного каталога согласно именным группам

' Условие:   Путь запуска — пустой

' Параметры: "<путь назначения>" <маска расширений> <формат сжатия>
' Форматы сжатия: 1 (Fax), 2 (Rle), 3 (LZW), 4 (ZIP), 5 (JPEG)
' /min — ключ cмены скрытой консоли на свёрнутую в панель задач

' Примеры:   "%T" *.tif 3 /min
'            "%T" *.jpg;*jpeg;*.png;*.tif;*.tiff 5

Option Explicit
'========================== Путь к NConvert ==========================
Const NConv = "%COMMANDER_PATH%\Utils\NConvert\nconvert.exe"
'================================================ Автор: Flasher © ===

Dim A, WSS, ShA, Dic, Kit, FSO, Coll, Sort, Rgx, CDir, _
Itms, Items, ODir, M, List, F, Name, BN0, BN, Item, i, S
Const Title = " Объединение картинок в PDF       "
Set A = WSH.Arguments: If A.UnNamed.Count <> 3 Then _
MsgBox "Укажите 3 параметра!", 4144, Title : WSH.Quit

Set WSS = CreateObject("WScript.Shell")
Set ShA = CreateObject("Shell.Application")
Set Dic = CreateObject("Scripting.Dictionary")
Set Kit = CreateObject("Scripting.Dictionary")
Set FSO = CreateObject("Scripting.FileSystemObject")
Set Coll = CreateObject("System.Collections.ArrayList")
Set Sort = CreateObject("System.Collections.SortedList")
Set Rgx = New RegExp : CDir = WSS.CurrentDirectory
Set Itms  = ShA.NameSpace(CDir).Items
Set Items = ShA.NameSpace(CDir).Items

Items.Filter 8416, A(1)
ODir = FSO.BuildPath(A(0), "\")
If A.Named.Exists("min") Then M = 2 Else M = 0
Rgx.Pattern = "((.+)[ \-—_])(\d+)\w?\.[A-z]{3,4}$"
List = FSO.GetSpecialFolder(2) & "\" & FSO.GetTempName

For Each F In Items
  Name = FSO.GetFileName(F.Path) : BN = FSO.GetBaseName(Name)
  If Rgx.Test(Name) Then
    Set Name = Rgx.Execute(Name)(0) : BN0 = Name.Submatches(0)
    If Not Dic.Exists(BN0) Then
      Dic.Add BN0, Empty : Item = " -l """ & List
      Itms.Filter 8416, Replace(A(1), "*", BN0 & "*")
      If Itms.Count > 1 Then
        For Each i in Itms
          Sort.Add CLng(Rgx.Execute(i.Path)(0).Submatches(2)), i.Path
        Next : Coll.Addrange Sort.Values
        BN = Name.Submatches(1) : S = ""
        Itms.Filter 8416, Replace(A(1), "*", BN)
        If Itms.Count = 1 Then i = Itms.Item(0).Path : KitAdd i : S = i & vbCrLf
        FSO.CreateTextFile(List, 1).Write S & Join(Coll.ToArray, vbCrLf)
        Sort.Clear : Coll.Clear
      Else Item = " """ & F.Path End If
      Call Run
    End If
  Else KitAdd F.Path
  End if
Next

For Each F in Kit.Keys
  Item = " """ & F : Call Run
Next

If Len(BN) Then
  If FSO.FileExists(List) Then FSO.DeleteFile List, 1
  WSS.Popup "     Выполнено!",        1.5, Title, 4160
Else
  WSS.Popup "Нет подходящих файлов!", 1.5, Title, 4144
End If
For Each i in Array(Name, Itms, Items, Coll, Sort, Dic, Kit, FSO, Rgx, WSS)
  Set i = Nothing
Next

Sub Run
  WSS.Run """" & NConv & """ -quiet -multi -o """ & ODir & BN &_
  ".pdf" & """ -out pdf -q 100 -c " & A(2) & Item & """", M, 1
End Sub

Sub KitAdd(FPath)
  If Kit.Exists(FPath) Then Kit.Remove(FPath) Else Kit.Add FPath, Empty
End Sub
Последний раз редактировалось Flasher Ср янв 23, 2019 08:54, всего редактировалось 7 раз.
Автору сборки TC Image (Andrey_A) настоятельно рекомендуется не распространять на иных ресурсах любую предоставленную мной где-либо техническую информацию по автоматизации и оптимизации в работе с ТС и системой.
kabatov
Сообщения: 12
Зарегистрирован: Сб янв 19, 2019 14:56

Сообщение kabatov »

Спасибо большое. Скрипт работает, но pdf генерируются, по всей видимости, с ошибкой в каких-то параметрах, т. к. файлы получаются значительно меньшего веса, чем те, что сделаны Nconvert с помощью упомянутой выше кнопки или непосредственно из XnView. Важно, чтобы соблюдались следующие два параметра: качество 100 (-q 100) и тип сжатия LZW (-c 3).

Добавлено спустя 1 час 10 минут:

Тестирую работу скрипта. Обнаружилось следующее:
1. Опытным путем выяснил, что при записи pdf почти наверняка применяется компрессия JPEG (совпадают размеры выходных pdf, написанных скриптом и XnView, при соответствующих настройках).
2. Если в параметрах задано:

Код: Выделить всё

"%T" *.jpg;*jpeg;*.png;*.tiff
файлы с расширением tif скрипт ожидаемо пропускает.
Если и в параметрах указано *.tiff, и расширения файлов tiff, появляется сообщение об ошибке:
Сценарий: C\totalcmd\Utils\TC_pdf.vbs
Строка: 29
Символ: 3
Ошибка: Недопустимый вызов или аргумент процедуры
Код: 800A0005
Источник: Ошибка выполнения Microsoft VBScrit
Та же ошибка с параметром *.tif для файлов с расширением tif.
Аватара пользователя
Flasher
Сообщения: 14229
Зарегистрирован: Пт ноя 06, 2009 00:33
Откуда: Москва

Сообщение Flasher »

kabatov писал(а):т. к. файлы получаются значительно меньшего веса
Для jpg/jpeg делал -с 5, для остальных — -с 3.
kabatov писал(а):файлы с расширением tif скрипт ожидаемо пропускает.
Логично. И?
kabatov писал(а):появляется сообщение об ошибке:
Значит, вы где-то промахнулись с исходными данными:
kabatov писал(а):имеют следующий вид: scan_001-01.tif, scan_001-02.tif <...> scan_001-55.tif, image_001.tif, image_002.tif <...> image_850.tif, pic 00.tif, pic 01.tif <...> pic 99.tif
Автору сборки TC Image (Andrey_A) настоятельно рекомендуется не распространять на иных ресурсах любую предоставленную мной где-либо техническую информацию по автоматизации и оптимизации в работе с ТС и системой.
kabatov
Сообщения: 12
Зарегистрирован: Сб янв 19, 2019 14:56

Сообщение kabatov »

Правильно я понимаю, что, если строку

Код: Выделить всё

If InStr("|jpg|jpeg|", "|" & LCase(Ext) & "|") Then C = 5 Else C = 3
заменить на во всех случаях будет применяться компрессия LZW?
Аватара пользователя
Flasher
Сообщения: 14229
Зарегистрирован: Пт ноя 06, 2009 00:33
Откуда: Москва

Сообщение Flasher »

Лучше иначе сделать. Я исправлю на LZW, если так надо. Сперва с ошибкой разберёмся.
Автору сборки TC Image (Andrey_A) настоятельно рекомендуется не распространять на иных ресурсах любую предоставленную мной где-либо техническую информацию по автоматизации и оптимизации в работе с ТС и системой.
kabatov
Сообщения: 12
Зарегистрирован: Сб янв 19, 2019 14:56

Сообщение kabatov »

Спасибо еще раз.
Вот еще два наблюдения:
1. Файлы с именами вида img___1.jpg, img___2.jpg скрипт обрабатывает, а вот на img___1_.jpg, img___2_.jpg выдает упомянутую ошибку.
2. Если встречаются файлы в разных форматах, но идентичные по части имени, например:
image_1.jpg
image_2.jpg
image_3.tif
image_4.tif
image_5.tif

или

image_1.tif
image_2.tif
image_3.tif
image_4.jpg
image_5.jpg
то скрипт делает pdf только из первой группы. То есть в первом примере получится двухстраничный pdf из jpeg, во втором — трехстраничный из tiff. Обычно работать приходится с файлами одного формата, но, если встретится такая, как в приведенных примерах, смесь, необходимо иметь на выходе пятистраничный pdf.

Добавлено спустя 7 минут:

Еще два маленьких вопроса.
1. Можно ли как-то дать понять пользователю, что скрипт в процессе работы? Просто часто обрабатывать приходится тысячи файлов, это занимает много времени, и хотелось бы понимать, что происходит в данный момент.
2. Как при необходимости остановить работу скрипта?
Аватара пользователя
Flasher
Сообщения: 14229
Зарегистрирован: Пт ноя 06, 2009 00:33
Откуда: Москва

Сообщение Flasher »

1. Ну, как я и сказал, вы промахнулись (не дополнили) с условием. Считаете, что такое именование окончаний №_.<ext> целесообразно?
Я ещё не видел, чтобы в конце базовых имён после счётчика ставился знак подчёркивания.
К тому же в исходных примерах указано наличии передних нулей в счётчике, что упрощало ситуацию. Теперь же вы приводите пример с их отсутствием. Нужно такие моменты заранее уточнять.
2. Да, я это специально сделал, чтобы разделять группы расширений. По-вашему, image_1.jpg и image_1.tif должны оказаться в одной группе? На мой взгляд, это неестественно.
kabatov писал(а):Еще два маленьких вопроса.
1. Ну, в конце же есть уведомление об окончании. Его разве недостаточно?
2. Завершить процессы wscript.exe и nconvert.exe:

Код: Выделить всё

TOTALCMD#BAR#DATA
*%WINDIR%\SYSTEM32\taskkill.exe /f /im wscript.exe /im nconvert.exe

gpedit.dll,1
Завершить WScript и NConvert

1
Автору сборки TC Image (Andrey_A) настоятельно рекомендуется не распространять на иных ресурсах любую предоставленную мной где-либо техническую информацию по автоматизации и оптимизации в работе с ТС и системой.
kabatov
Сообщения: 12
Зарегистрирован: Сб янв 19, 2019 14:56

Сообщение kabatov »

1. По этому пункту согласен. Такое именование надо рассматривать как ошибку, поэтому правильно было бы приводить перед конвертацией имеющиеся исходные файлы в порядок. Собственно, так и делаю. В общем, буду следить за этим. Этот вопрос, будем считать, разрешен.

2. Несколько форматов в исходных файлах могут встретиться, если последние делались с одного оригинала, но в разное время разными людьми. Здесь принципиально ориентироваться на имена.

3. Уведомления достаточно, чтобы понять, что работа завершена. Просто речь о том, что, когда в течение 20—30 минут компьютер занят конвертацией, имеет смысл как-то дать знать об этом оператору. Разумеется, можно пользоваться скриптом и без этого. Это совершенно не принципиальное пожелание, не более.
Аватара пользователя
Flasher
Сообщения: 14229
Зарегистрирован: Пт ноя 06, 2009 00:33
Откуда: Москва

Сообщение Flasher »

1. А по поводу цифр в счётчике?
2. Хотелось бы на поставленный вопрос ответ получить. Два файла с одним номером и разным расширением.
Возьмём даже 4: image_001.jpg, image_002.jpg, image_001.tif, image_002.tif. Что на выходе?
3. Отрисовка прогресса — это лишний забор времени. Могу добавить ключ на свёрнутую консоль, если устроит.
Автору сборки TC Image (Andrey_A) настоятельно рекомендуется не распространять на иных ресурсах любую предоставленную мной где-либо техническую информацию по автоматизации и оптимизации в работе с ТС и системой.
kabatov
Сообщения: 12
Зарегистрирован: Сб янв 19, 2019 14:56

Сообщение kabatov »

1. Счетчика в именах может и не быть. В общем, пока вижу, что все работает, как надо, за исключением подобных случаев:

а) иногда встречаются буквенные обозначения: image_004.jpg, image_005a.jpg, image_005b.jpg (на выходе надо бы получить image.pdf),
б) scan.tif, scan-01.tif, scan-02.tif (на выходе — scan.pdf),
в) одиночные файлы с уникальными именами должны конвертироваться в одностраничный pdf с сохранением полного имени:
<...>
image-01.tif
image-02.tif
pic-01.tif
scan-01.tif
scan-02.tif
<...>
Результат: <...> image.pdf, pic-01.pdf, scan.pdf <...>

2. Случаев полного совпадения имен с разным расширением (image_001.jpg, image_001.tif) вообще-то быть не должно. Но, если такое встретилось, хорошо бы выдавать предупреждение либо игнорировать jpeg.

3. Не принципиально. Можно оставить, как есть.
Последний раз редактировалось kabatov Пн янв 21, 2019 21:34, всего редактировалось 1 раз.
Аватара пользователя
Flasher
Сообщения: 14229
Зарегистрирован: Пт ноя 06, 2009 00:33
Откуда: Москва

Сообщение Flasher »

1. Начинается... Вообще я писал о нулях в счётчике. Прочтите внимательно.
a,в) Это ладно.
б) А если scan.tif, scan-01.tif, scan-001.tif scan_01.tif, scan 01.tif?

2. Это лишний гемор. Задаются любые расширения, а не только эти два. Т. е. фактически придётся каждое имя сопоставлять с потенциальным множеством файлов с заданными расширениями. Это и на скорости выполнения отразится.

3. Так нужна минимизация или нет? Это самое простое из обсуждаемого.
Автору сборки TC Image (Andrey_A) настоятельно рекомендуется не распространять на иных ресурсах любую предоставленную мной где-либо техническую информацию по автоматизации и оптимизации в работе с ТС и системой.
kabatov
Сообщения: 12
Зарегистрирован: Сб янв 19, 2019 14:56

Сообщение kabatov »

1.
А если scan.tif, scan-01.tif, scan-001.tif scan_01.tif, scan 01.tif?
Вряд ли я смогу сформулировать задачу исчерпывающе точно, так, чтобы формулировка эта включила бы все множество возможных вариантов. Для этого нужен опыт и мозги программиста. Вполне вероятно, что Вы снова поймаете меня на неточности, смоделировав новую ситуацию. Сейчас Ваш скрип делает то, что и было мне нужно, за что я Вам очень благодарен. Все файлы я готовлю в нужном формате, с правильными характеристиками и именами. Поэтому давайте исходить из того, что имена файлов заканчиваются счетчиком, в котором может быть любое количество цифр, и первая из которых не обязательно ноль, а слева от счетчика — один из трех символов: пробел, дефис или знак подчеркивания.
2.
а) При разбиении списка файлов на группы скрипт не должен принимать во внимание расширение: image-01.jpg, image-02.jpeg, image-03.tif — одна группа, три страницы файла image.pdf
б) Файлы разных форматов, но с идентичными именами отправляются в один pdf: scan_55.jpg, scan_55.tif, scan_56.tif, scan_57.tif — четыре страницы файла scan.pdf
3. Минимизация нужна.

Спасибо.
kabatov
Сообщения: 12
Зарегистрирован: Сб янв 19, 2019 14:56

Сообщение kabatov »

Уважаемый Flasher!
Первый раз использовал Ваш скрипт в работе. Искренняя Вам благодарность от коллег по сектору репрографии Российской национальной библиотеки. Некоторые считают Вашу услугу достойной памятника. С сегодняшнего дня в деле пополнения электронной библиотеки РНБ есть часть Вашего труда.
Аватара пользователя
Flasher
Сообщения: 14229
Зарегистрирован: Пт ноя 06, 2009 00:33
Откуда: Москва

Сообщение Flasher »

kabatov
Ах, вон откуда ноги растут. Почётно. :) Привет коллегам. Скрипт обновил. Проверяйте.
P.S.: Я памятник себе воздвиг нерукотворный ... Изображение ( Изображение )
Автору сборки TC Image (Andrey_A) настоятельно рекомендуется не распространять на иных ресурсах любую предоставленную мной где-либо техническую информацию по автоматизации и оптимизации в работе с ТС и системой.
Ответить