Автор Тема: Консольное создание DjVu-оглавления  (Прочитано 4704 раз)

monday2000

  • Администратор
  • *****
  • Сообщений: 985
    • AOL клиент - -
    • Yahoo клиент - -
    • Просмотр профиля
    • Создание книг в электронном виде из бумажных книг (в формате DjVu)
    • E-mail
Я сделал консольную утилиту для облегчения создания DjVu-букмарков. Назвал её "bookm".

Скачать утилиту:

bookm

http://www.djvu-soft.narod.ru/soft/bookm.rar  (70 КБ)  (Исходники внутри)

Эта утилита принимает на входе табулированный текстовый файл, т.е. такой, где в начале каждой строки стоят один или несколько Tab-символов, обозначающие иерархию вложенности строк будущего оглавления.

В конце каждой строки должна стоять цифра, обозначающая номер строки, куда будет ссылаться этот пункт будущего оглавления. Вот пример такого файла:
Цитировать
Line1 1
   Line2 2
   Line3 3
   Line4 4
      Line5 5
      Line6 6
      Line7 7
Line8 8
Line9 9

Утилита bookm преобразует такой файл в формат букмарков, непосредственно понятный djvused. Т.е. можно вручную подготовить файл букмарков, и при помощи bookm создать букмарки в DjVu. Мне понравилось использовать для ручного создания табулированного файла текстовый редактор Notepad++ - потому что там можно оптом (выделив мышью) сдвигать несколько строк текста табом.

Теперь о том, зачем я это сделал (т.е. утилиту bookm):

Как известно, таких программ имеется уже несколько, которые умеют создавать DjVu-букмарки из ничего, причём многие такие программы - визуальные. Зачем же я тогда сделал ещё одну, да ещё консольную?

Причин тому несколько:

1. Мне не нравится привязка большинства похожих программ к .NET. Моя утилита написана просто на чистом С++ STL, и может скомилироваться на любой платформе.

2. Бывают изредка столь заковыристые оглавления, что ни одна из существующих программ не предусматривает работу с ними. Например, мне попалась книга, где номер страницы имеет вид "1-1" - где первая единица - номер тома, и только вторая - номер страницы. В этом случае проще поправить исходник и перекомпилировать утилиту заново, чем страдать от невозможности простой вставки букмарков.

3. Не все аналогичные утилиты имеют открытые исходники.

4. В дальнейшем можно будет прикрутить к bookm визуальный интерфейс.

Раньше я пользовался для вставки DjVu-букмарков китайской утилитой PdgCntEditor. Но в последний раз она что-то не поняла кодировки моего файла. Пришлось делать свою утилиту.

bookm ещё предусматривает опцию прибавления некоего заданного числа ко всем номерам страниц (считываемых из табулированного файла). Это удобно для DjVu-книг, имеющих обложку - там идёт сдвиг нумерации всего оглавления на 1.
« Последнее редактирование: 26 јРЩ 2011, 18:07:51 от monday2000 »

57an

  • Постоялец
  • ***
  • Сообщений: 201
    • Просмотр профиля
    • Djvu Bookmarker on SF.net
Re: Консольное создание DjVu-оглавления
« Ответ #1 : 26 јРЩ 2011, 19:30:56 »
Цитировать
В конце каждой строки должна стоять цифра, обозначающая номер строки
Видимо, имелось в виду "страницы".

Цитировать
В этом случае проще поправить исходник и перекомпилировать утилиту заново
Ну этим точно никто заниматься не будет. Я такие оглавления в Excele приводил к линейной нумерации. Да и то потом плевался, подгоняя страницы (потому что это был pdf, а Pdf-функционала в Букмаркере тогда еще не было).

Кстати, об опен-сорсе - DjvuOutline развить разве не проще было? Прога в принципе небезуспешная, 1000 скачек за год.

Но все-таки, по-моему, лучше бы Вы "оконсолили" Djvu Imager. Там уже вся цепочка готова, даже в СТ есть подержка командной строки. Но вот в Djvu Imager обязательно придется тыкать мышкой...


monday2000

  • Администратор
  • *****
  • Сообщений: 985
    • AOL клиент - -
    • Yahoo клиент - -
    • Просмотр профиля
    • Создание книг в электронном виде из бумажных книг (в формате DjVu)
    • E-mail
Re: Консольное создание DjVu-оглавления
« Ответ #2 : 27 јРЩ 2011, 09:22:51 »
57an
Цитировать
Видимо, имелось в виду "страницы".
Да, точно. :)
Цитировать
Ну этим точно никто заниматься не будет.
Из пользователей - да, а из тех, кто программирует - может кто-то и найдётся. Там всего лишь одну функцию подправить - всё там понятно. Или же я сам оперативно поправлю по чьей-нибудь просьбе.
Цитировать
Кстати, об опен-сорсе - DjvuOutline развить разве не проще было?
Там сложно ковыряться, там код довольно навороченный мне показался. Я старался как можно попроще код сделать.
Цитировать
Но все-таки, по-моему, лучше бы Вы "оконсолили" Djvu Imager.
Да я, собственно, наоборот старался уйти там от консольных приложений - чтобы облегчить жизнь пользователю. :) А вообще, главный управляющий код в DjVu Imager настолько примитивен, что мне даже в голову не пришло делать для него отдельное консольное приложение.

Принцип работы DjVu Imager расписан тут:
http://www.djvu-soft.narod.ru/scan/back_glue.htm
http://www.djvu-soft.narod.ru/scan/mask_color.htm

На основании этих 2 статей можно элементарно написать какой-нибудь скрипт, управляющий консольными утилитами а-ля DjVu Imager. То есть, для общественности принцип работы DjVu Imager вовсе не потерян и не скрыт. Как раз по этим статьям легче будет разобраться, чем если бы я сделал управляющее консольное приложение.

DjVu Imager - это, конечно, не навсегда. Но замена DjVu Imager должна быть ИМХО визуальной - т.е. с выводом изображения кодируемых страниц до и после кодирования. Т.е. это должно быть нечто внешне похожее на СТ, только работающее аналогично DjVu Imager.

m7876

  • Новичок
  • *
  • Сообщений: 38
    • Просмотр профиля
Re: Консольное создание DjVu-оглавления
« Ответ #3 : 01 ёоЭм 2011, 10:16:06 »
Вы не подскажете, как Вашу программу скомпилировать под gcc/g++?
Сначала были такие ошибки:
===
$gcc bookm.cpp -o bookm
bookm.cpp: In function ‘int get_line_info(std::string&, std::string&)’:
bookm.cpp:75: error: ‘atoi’ was not declared in this scope
bookm.cpp: In function ‘int put_line(std::ifstream&, std::ofstream&, std::string)’:
bookm.cpp:156: error: ‘itoa’ was not declared in this scope
bookm.cpp: In function ‘int main(int, char**)’:
bookm.cpp:236: error: ‘atoi’ was not declared in this scope

===
Потом я (следуя советам отсюда http://www.velocityreviews.com/forums/t285100-itoa-function-in-gcc.html) вставил ссылку на библиотеку (#include <stdlib.h>) и заменил itoa() на sprintf(), появилась такая ошибка:
===
$ gcc bookm.cpp -o bookm
bookm.cpp: In function ‘int put_line(std::ifstream&, std::ofstream&, std::string)’:
bookm.cpp:158: error: invalid conversion from ‘int’ to ‘char*’
bookm.cpp:158: error:   initializing argument 1 of ‘int sprintf(char*, const char*, ...)’

===
« Последнее редактирование: 01 ёоЭм 2011, 10:19:50 от m7876 »

nbl

  • Новичок
  • *
  • Сообщений: 23
    • Просмотр профиля
Re: Консольное создание DjVu-оглавления
« Ответ #4 : 01 ёоЭм 2011, 14:24:36 »
Покажите что у Вас получилось после замены itoa на sprintf.

Я бы заменил строку itoa(page_num + page_shift,buf,10); на sprintf(buf, "%d", page_num + page_shift);

monday2000

  • Администратор
  • *****
  • Сообщений: 985
    • AOL клиент - -
    • Yahoo клиент - -
    • Просмотр профиля
    • Создание книг в электронном виде из бумажных книг (в формате DjVu)
    • E-mail
Re: Консольное создание DjVu-оглавления
« Ответ #5 : 01 ёоЭм 2011, 15:11:46 »
У меня эта замена
Цитировать
Я бы заменил строку itoa(page_num + page_shift,buf,10); на sprintf(buf, "%d", page_num + page_shift);
прошла отлично, всё работает, как и прежде.

Несколько слов о принципе работы утилиты:

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

Основную работу выполняет рекурсивная функция put_line. Она делает следующее:

1. Пишет в вывод открывающую скобку.
2. Читает текущую строку, пишет её в вывод и берёт из последующей строки число её табов.
3. Если у текущей строки есть непосредственные дети (не глубже 1 уровня вложенности - по табам), то функция в цикле для каждого непосредственного ребёнка вызывает саму себя.
4. Если в процессе перебора детей попадается не-ребёнок - то функция возвращается столько раз, насколько встретившийся не-ребёнок выше уровнем ребёнка (при каждом возврате счётчик возвратов уменьшается на 1).
5. Пишет в вывод закрывающую скобку.

При самом первом вызове на put_line подаётся строка "bookmarks" - т.к. её неоткуда считать из исходного файла, а она должна быть корнем сформированного дерева.

Если вдруг потребуется модифицировать утилиту, то менять нужно будет только содержимое раздела "processing the output line". Именно там программа как-либо манипулирует считанной целиком из файла текущей строкой - перед тем, как записать её в вывод.
« Последнее редактирование: 01 ёоЭм 2011, 15:14:45 от monday2000 »

m7876

  • Новичок
  • *
  • Сообщений: 38
    • Просмотр профиля
Re: Консольное создание DjVu-оглавления
« Ответ #6 : 04 ёоЭм 2011, 01:22:08 »
Покажите что у Вас получилось после замены itoa на sprintf.
Я бы заменил строку itoa(page_num + page_shift,buf,10); на sprintf(buf, "%d", page_num + page_shift);
Спасибо!
Но теперь выводится вообще какой-то кошмар: http://rghost.ru/9295541
Как же все-таки скомпилировать? Я знаю про несовместимость C++, но должен же быть какой-то способ, ведь утилита невелика...

nbl

  • Новичок
  • *
  • Сообщений: 23
    • Просмотр профиля
Re: Консольное создание DjVu-оглавления
« Ответ #7 : 04 ёоЭм 2011, 19:07:32 »
Покажите файл, который компилируете.

m7876

  • Новичок
  • *
  • Сообщений: 38
    • Просмотр профиля

nbl

  • Новичок
  • *
  • Сообщений: 23
    • Просмотр профиля
Re: Консольное создание DjVu-оглавления
« Ответ #9 : 07 ёоЭм 2011, 11:01:22 »
В общем, я скачал GCC под Windows вот отсюда: http://www.bloodshed.net/ Ваш файл откомпилировался нормально, он результат работы был отвратительный. В конце концов, в результате разбирательства у меня сложилось ощущение, что функция tellg() в этом компиляторе возвращает совсем не то, что надо. Отбило дальнейшую охоту разбираться с программой  >:(

monday2000

  • Администратор
  • *****
  • Сообщений: 985
    • AOL клиент - -
    • Yahoo клиент - -
    • Просмотр профиля
    • Создание книг в электронном виде из бумажных книг (в формате DjVu)
    • E-mail
Re: Консольное создание DjVu-оглавления
« Ответ #10 : 07 ёоЭм 2011, 13:11:00 »
nbl
Цитировать
результат работы был отвратительный
Я тоже попробовал этим компилятором скомпилировать. М-да, ну и бред же получился. :) Просто какая-то каша вместо правильного результата. :D

Я компилировал при помощи MS VC++ 6.0.
Цитировать
у меня сложилось ощущение, что функция tellg() в этом компиляторе возвращает совсем не то, что надо.
Очень похоже на это. Вырывает целые слова из вывода.

m7876

  • Новичок
  • *
  • Сообщений: 38
    • Просмотр профиля
Re: Консольное создание DjVu-оглавления
« Ответ #11 : 07 ёоЭм 2011, 22:05:44 »
Жаль. Получается, что я не смогу пользоваться этой программой на Linux.

monday2000

  • Администратор
  • *****
  • Сообщений: 985
    • AOL клиент - -
    • Yahoo клиент - -
    • Просмотр профиля
    • Создание книг в электронном виде из бумажных книг (в формате DjVu)
    • E-mail
Re: Консольное создание DjVu-оглавления
« Ответ #12 : 08 ёоЭм 2011, 11:46:12 »
m7876
Я не знаю, в чём дело. Один из 2-х компиляторов глючный - или MS VC++ 6.0, или Dev-C++. :)

Посмотрел я ещё раз компиляцию в Dev-C++ - tellg на первом же рекурсивном вызове почему-то выдаёт неправильную длину - как если бы getline считал 2 строки вместо одной.

Я подозреваю, что всё же Dev-C++ тут виноват. Хоть MS все и ругают, но там всё-таки деньгами отвечают за качество, а в бесплатном компиляторе - кто будет его гарантированно доводить до ума? :-\ Думаю, что это просто глюки в Dev-C++.

Другой вариант - может быть, срабатывает некая особенность MS VC++ 6.0. MS любит всякие штучки типа "Microsoft specific".

В любом случае, разбираться в этой проблеме мне неохота. Я и так уже убил уйму времени, чтобы написать эту программу. Она вообще-то очень непростая оказалась (в плане алгоритмики).

nbl

  • Новичок
  • *
  • Сообщений: 23
    • Просмотр профиля
Re: Консольное создание DjVu-оглавления
« Ответ #13 : 10 ёоЭм 2011, 12:10:09 »
Жаль. Получается, что я не смогу пользоваться этой программой на Linux.
Ну, не все так плохо. Я написал свою версию скрипта на AWK, который выполняет туже функциональность.
Правда, я точно не знаю формат выходного файла, поэтому делал по аналогии. Как мне кажется, должно работать.
Попробуйте: http://pastebin.com/VsPQGFjp
« Последнее редактирование: 10 ёоЭм 2011, 12:20:00 от nbl »

monday2000

  • Администратор
  • *****
  • Сообщений: 985
    • AOL клиент - -
    • Yahoo клиент - -
    • Просмотр профиля
    • Создание книг в электронном виде из бумажных книг (в формате DjVu)
    • E-mail
Re: Консольное создание DjVu-оглавления
« Ответ #14 : 11 ёоЭм 2011, 22:26:12 »
nbl
Цитировать
Правда, я точно не знаю формат выходного файла
Чтобы узнать этот формат, нужно взять любой DjVu-файл с букмарками, и экспортировать их в текстовый файл. Это вообще общий принцип DjVuLibre - обратимость экспорта-импорта.