Создать PDF-файлы из картинок по схожим признакам в именах
Select messages from
# through # FAQ
[/[Print]\]
Goto page 1, 2  Next  :| |:
Total Commander -> Автоматизация Total Commander

#1: Создать PDF-файлы из картинок по схожим признакам в именах Author: kabatov PostPosted: Sun Jan 20, 2019 16:18
    —
Добрый день.

Есть потребность автоматизировать процесс создания многостраничных 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 из выделенных в активной панели файлов:
Code:
TOTALCMD#BAR#DATA
%COMMANDER_PATH%\Utils\NConvert\nconvert.exe
-multi -o "%T%%" -out pdf -q 100 -c 3 -l "%L"
shell32.dll,250
выделенные файлы — в многостраничный PDF

Из кода кнопки видно, какие параметры конвертации требуются. Эта кнопка, конечно, облегчит работу, но не решает описанной задачи. Заранее спасибо всем, кто готов поломать голову над решением.

#2:  Author: FlasherLocation: Москва PostPosted: Sun Jan 20, 2019 21:40
    —
Code:
'================================ 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


Last edited by Flasher on Wed Jan 23, 2019 09:54; edited 7 times in total

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

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

Тестирую работу скрипта. Обнаружилось следующее:
1. Опытным путем выяснил, что при записи pdf почти наверняка применяется компрессия JPEG (совпадают размеры выходных pdf, написанных скриптом и XnView, при соответствующих настройках).
2. Если в параметрах задано:
Code:
"%T" *.jpg;*jpeg;*.png;*.tiff

файлы с расширением tif скрипт ожидаемо пропускает.
Если и в параметрах указано *.tiff, и расширения файлов tiff, появляется сообщение об ошибке:
Quote:
Сценарий: C\totalcmd\Utils\TC_pdf.vbs
Строка: 29
Символ: 3
Ошибка: Недопустимый вызов или аргумент процедуры
Код: 800A0005
Источник: Ошибка выполнения Microsoft VBScrit

Та же ошибка с параметром *.tif для файлов с расширением tif.

#4:  Author: FlasherLocation: Москва PostPosted: Mon Jan 21, 2019 06:55
    —
kabatov wrote:
т. к. файлы получаются значительно меньшего веса
Для jpg/jpeg делал -с 5, для остальных — -с 3.
kabatov wrote:
файлы с расширением tif скрипт ожидаемо пропускает.
Логично. И?
kabatov wrote:
появляется сообщение об ошибке:
Значит, вы где-то промахнулись с исходными данными:
kabatov wrote:
имеют следующий вид: 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

#5:  Author: kabatov PostPosted: Mon Jan 21, 2019 12:24
    —
Правильно я понимаю, что, если строку
Code:
If InStr("|jpg|jpeg|", "|" & LCase(Ext) & "|") Then C = 5 Else C = 3

заменить на
Code:
C = 3

во всех случаях будет применяться компрессия LZW?

#6:  Author: FlasherLocation: Москва PostPosted: Mon Jan 21, 2019 12:32
    —
Лучше иначе сделать. Я исправлю на LZW, если так надо. Сперва с ошибкой разберёмся.

#7:  Author: kabatov PostPosted: Mon Jan 21, 2019 12:53
    —
Спасибо еще раз.
Вот еще два наблюдения:
1. Файлы с именами вида img___1.jpg, img___2.jpg скрипт обрабатывает, а вот на img___1_.jpg, img___2_.jpg выдает упомянутую ошибку.
2. Если встречаются файлы в разных форматах, но идентичные по части имени, например:
Quote:
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. Как при необходимости остановить работу скрипта?

#8:  Author: FlasherLocation: Москва PostPosted: Mon Jan 21, 2019 13:01
    —
1. Ну, как я и сказал, вы промахнулись (не дополнили) с условием. Считаете, что такое именование окончаний №_.<ext> целесообразно?
Я ещё не видел, чтобы в конце базовых имён после счётчика ставился знак подчёркивания.
К тому же в исходных примерах указано наличии передних нулей в счётчике, что упрощало ситуацию. Теперь же вы приводите пример с их отсутствием. Нужно такие моменты заранее уточнять.
2. Да, я это специально сделал, чтобы разделять группы расширений. По-вашему, image_1.jpg и image_1.tif должны оказаться в одной группе? На мой взгляд, это неестественно.
kabatov wrote:
Еще два маленьких вопроса.
1. Ну, в конце же есть уведомление об окончании. Его разве недостаточно?
2. Завершить процессы wscript.exe и nconvert.exe:
Code:
TOTALCMD#BAR#DATA
*%WINDIR%\SYSTEM32\taskkill.exe /f /im wscript.exe /im nconvert.exe

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

1

#9:  Author: kabatov PostPosted: Mon Jan 21, 2019 14:10
    —
1. По этому пункту согласен. Такое именование надо рассматривать как ошибку, поэтому правильно было бы приводить перед конвертацией имеющиеся исходные файлы в порядок. Собственно, так и делаю. В общем, буду следить за этим. Этот вопрос, будем считать, разрешен.

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

3. Уведомления достаточно, чтобы понять, что работа завершена. Просто речь о том, что, когда в течение 20—30 минут компьютер занят конвертацией, имеет смысл как-то дать знать об этом оператору. Разумеется, можно пользоваться скриптом и без этого. Это совершенно не принципиальное пожелание, не более.

#10:  Author: FlasherLocation: Москва PostPosted: Mon Jan 21, 2019 14:27
    —
1. А по поводу цифр в счётчике?
2. Хотелось бы на поставленный вопрос ответ получить. Два файла с одним номером и разным расширением.
Возьмём даже 4: image_001.jpg, image_002.jpg, image_001.tif, image_002.tif. Что на выходе?
3. Отрисовка прогресса — это лишний забор времени. Могу добавить ключ на свёрнутую консоль, если устроит.

#11:  Author: kabatov PostPosted: Mon Jan 21, 2019 16:46
    —
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. Не принципиально. Можно оставить, как есть.


Last edited by kabatov on Mon Jan 21, 2019 22:34; edited 1 time in total

#12:  Author: FlasherLocation: Москва PostPosted: Mon Jan 21, 2019 18:33
    —
1. Начинается... Вообще я писал о нулях в счётчике. Прочтите внимательно.
a,в) Это ладно.
б) А если scan.tif, scan-01.tif, scan-001.tif scan_01.tif, scan 01.tif?

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

3. Так нужна минимизация или нет? Это самое простое из обсуждаемого.

#13:  Author: kabatov PostPosted: Mon Jan 21, 2019 22:56
    —
1.
Quote:
А если 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. Минимизация нужна.

Спасибо.

#14:  Author: kabatov PostPosted: Tue Jan 22, 2019 16:09
    —
Уважаемый Flasher!
Первый раз использовал Ваш скрипт в работе. Искренняя Вам благодарность от коллег по сектору репрографии Российской национальной библиотеки. Некоторые считают Вашу услугу достойной памятника. С сегодняшнего дня в деле пополнения электронной библиотеки РНБ есть часть Вашего труда.

#15:  Author: FlasherLocation: Москва PostPosted: Tue Jan 22, 2019 20:49
    —
kabatov
Ах, вон откуда ноги растут. Почётно. Smile Привет коллегам. Скрипт обновил. Проверяйте.
P.S.: Я памятник себе воздвиг нерукотворный ... ( )



Total Commander -> Автоматизация Total Commander


output generated using printer-friendly topic mod. All times are GMT + 4 Hours

Goto page 1, 2  Next  :| |:
Page 1 of 2

Powered by phpBB © 2001, 2005 phpBB Group