📜 ⬆️ ⬇️

We create notebooks for the book in automatic mode

How it all began


It all started with laziness. Laziness is productive and not very, in my case, it seems - the first.

Recently I bought a book by Nassim Taleb “Anti-fragility” on “Liters”. I downloaded it, threw it on the reading room, but I did not get to it, then my wife would drag her off to read it, then the child ... And then this article “The best gift - book.” Arrived in the newsletter . We make a beautiful cover . I looked, everything seems to be beautiful, but now there was no machine with “Vents” near at hand, well, we don’t use them, but to run these WordPages through a strip like Wine or somehow non-comfortably in Qemu. However, I have the opportunity to print books and normally trim (mini-printing house on the first floor of the house in which I live) in the desired format. This means that you should use the opportunities available at hand.

Idea


In my office, I have been using a small bash script for half a year to assemble the scattered PDF nicknames together and form a single structure of project documentation. So, there is one candidate for parts.

Actually the idea was to separate the individual pages in a certain sequence into notebooks of arbitrary size multiple 4. If you look carefully, one notebook sheet contains exactly 4, not three or five pages, and the pages are arranged in a certain order on the sheet, though , I later finished it, but for now it was as it is, namely (for a 48-page notebook):
')
Pairs of pagesaddiction
1-48m = (1) n = (48)
2-47m = (1 + 1) n = (48-1)
3-46m = (1 + 2) n = (48-2)
......
24-25m = (1 + 23) n = (48-23)

This means that, first, the book should be divided into i pages, then into j notebooks, k pages each, then each notebook should be divided into pairs of pages, which should be placed on sheets, which should be combined into single files of notebooks, which should be placed next to the original Pdf nickname. F-Fu, barely formulated ...

In general, the dependence is simple, the first page of the sheet is a + b, and the last is kb, where a is the sequence number of the notebook, with 0 <a <j, and b is the sequence number of the paired page, and 0 <b <k / 2 Those. this is a for ((b = 0; b <k / 2; b ++) loop ) in which all these pages should be processed.

We push this cycle into another one, which runs through the notebooks for ((a = 0; a <j; a ++)) .

Next we use the GhostScript, ImageMagic and djvulibre packages, and some bash and Linux built-in commands.

In the process of elaboration, it turned out that part of the code is better to be rendered into separate functions, and bash divides everything completely, which means that it is necessary to refine the assembly of the remaining pages, which turned out to be primitive:

 echo "The pages of the main set were assembled, now you can put together an additional notebook."
 letsgo
 let "LAST_W_BOOK = $ W_BOOK + 1" # Create a variable indicating the number of the last notebook
 if ["` expr $ TAIL_PAGES% 4` "-eq" 0 "] # If the number of pages in the last notebook is a multiple of 4
   then
     echo "Everything is fine, we continue to create the last notebook"
     assembly $ LAST_W_BOOK $ TAIL_PAGES
   else # If the number of pages in the last notebook is NOT a multiple of 4
     echo "Notebook lacks expr 4 - $ TAIL_PAGES% 4` pages (s)"
     echo "You should add them. You can add them manually or let the program do it."
     letsgo
     # add the required number of empty files and then proceed to build
 fi


For a snack, it turned out that the order of the pages on the sheets is not quite the same as it was in the tablet above, but this one:

Pairs of pagesaddiction
48-1n = (48) m = (1)
2-47m = (1 + 1) n = (48-1)
46-3n = (48-2) m = (1 + 2)
......


What is decided is quite simple:

       if ["` expr $ b% 2` "-gt" 0 "]
	 then # If the PAIR of pages is odd
	   extract $ ba first.bmp
	   extract $ bb second.bmp
	   echo "Putting up the pages $ ba - $ bb"
	 else # If the PAIR of the pages is even
	   extract $ bb first.bmp
	   extract $ ba second.bmp
	   echo "Putting $ bb pages - $ ba"
       fi


To draw pages from the source PDF, GhostScript was used as a command:

  gs -q -sDEVICE = bmpmono -r $ DPI -dFirstPage = $ 1 -dLastPage = $ 1 -sOutputFile = "$ TMP_DIR / $ 2" -dNOPAUSE -dBATCH * pdf 


Since my original PDF nickname was borderless (it’s more convenient for a reader), I added ImageMagic fields around the page:

  convert "$ TMP_DIR / $ 2" -define bordercolor = # ffffff -border 10% "$ TMP_DIR / $ 2" 

Then everything is primitive, we use the djvulibre software package:
       if ["$ b" -eq "0"]
       then
	 cjb2 -lossy "$ TMP_DIR / $ ba- $ bb" .pbm "$ 2" .djvu
       else
	 cjb2 -lossy "$ TMP_DIR / $ ba- $ bb" .pbm "$ TMP_DIR / $ ba- $ bb" .djvu
	 djvm -i "$ 2" .djvu "$ TMP_DIR / $ ba- $ bb" .djvu
       fi

Create the first page of the notebook file, then successively cling to it the rest of the page until the end of the cycle.

Script itself


 #! / bin / bash
 letsgo () {
   echo "Continue? (Yes / [No])"
   read CONTINUE
   if [-n "$ CONTINUE"] && [["$ CONTINUE" == y *]] ||  [["$ CONTINUE" == Y *]] # The line is not empty and starts with "y" or "Y"
   then echo "Well then, we continue ..."
   else
   rm -R $ TMP_DIR
   exit
   fi
 }

 extract () {#FirstPage and LastPage = $ 1, OutputFile = $ 2 - WITHOUT PREFIX!
   gs -q -sDEVICE = bmpmono -r $ DPI -dFirstPage = $ 1 -dLastPage = $ 1 -sOutputFile = "$ TMP_DIR / $ 2" -dNOPAUSE -dBATCH * pdf
   convert "$ TMP_DIR / $ 2" -define bordercolor = # ffffff -border 10% "$ TMP_DIR / $ 2" # Add a white frame
 }

 assembly () {

   sub_a () {
     for ((b = 0; b <$ 1/2; b ++)) do
       let "ba = $ 3 + $ b" # number of the first page on the sheet
       let "bb = $ 4- $ b" # number of the second page on the sheet
       if ["` expr $ b% 2` "-gt" 0 "]
	 then # If the PAIR of pages is odd
	   extract $ ba first.bmp
	   extract $ bb second.bmp
	   echo "Putting up the pages $ ba - $ bb"
	 else # If the PAIR of pages is even
	   extract $ bb first.bmp
	   extract $ ba second.bmp
	   echo "Putting $ bb pages - $ ba"
       fi
       convert + append $ TMP_DIR / first.bmp $ TMP_DIR / second.bmp "$ TMP_DIR / $ ba- $ bb" .pbm
       if ["$ b" -eq "0"]
       then
	 cjb2 -lossy "$ TMP_DIR / $ ba- $ bb" .pbm "$ 2" .djvu
       else
	 cjb2 -lossy "$ TMP_DIR / $ ba- $ bb" .pbm "$ TMP_DIR / $ ba- $ bb" .djvu
	 djvm -i "$ 2" .djvu "$ TMP_DIR / $ ba- $ bb" .djvu
       fi
       rm "$ TMP_DIR / $ ba- $ bb". * 
     done
   }

   if ["$ 1" -gt "` expr $ FILE_COUNT / $ PAGES_IN_W_BOOK` "]
     then # build the last notebook
     for ((a = 0; a <1; a ++)) do
       let "aa = $ 1" # notebook number
       let "ab = $ FILE_COUNT / $ PAGES_IN_W_BOOK * $ PAGES_IN_W_BOOK + 1" # number of the first page in the notebook
       let "ac = $ FILE_COUNT" # last page number in notebook
       echo "Putting together a notebook $ aa consisting of pages $ ab ... $ ac"
       sub_a $ 2 $ aa $ ab $ ac
     done
     else # normal execution
     for ((a = 0; a <$ 1; a ++)) do
       let "aa = $ a + 1" # iteration number in the current cycle, it is the same - notebook number
       let "ab = $ a * $ 2 + 1" # number of the first page in the notebook
       let "ac = $ a * $ 2 + $ 2" # number of the last page in the notebook
       echo "Putting together a notebook $ aa consisting of pages $ ab ... $ ac"
       sub_a $ 2 $ aa $ ab $ ac
     done
   fi
 }

 mkdir / tmp / brochure_converter # Create a temporary directory
 TMP_DIR = "/ tmp / brochure_converter" # Assign a variable to reflect the path to the temporary directory 
 FILE_COUNT = `pdfinfo * pdf |  awk '/ Pages / {print $ 2}' `# Count the number of pages in the document
 echo "Specify the number of pages in one notebook multiple of 4, for example \" 8, 12, 16 \ ", etc."
 read PAGES_IN_W_BOOK # Read the variable number of pages in a notebook
 let "W_BOOK = $ FILE_COUNT / $ PAGES_IN_W_BOOK" # We calculate the number of pages in one notebook
 echo "There will be $ W_BOOK full notebooks of $ PAGES_IN_W_BOOK pages each"
 let "TAIL_PAGES = $ FILE_COUNT% $ PAGES_IN_W_BOOK" # Calculates the number of pages in the last notebook
 echo "There is an incomplete notebook on the $ TAIL_PAGES pages"
 echo "Specify the desired image resolution (DPI), for example 72"
 read DPI # Assign a resolution variable for images of a future document
 letsgo
 assembly $ W_BOOK $ PAGES_IN_W_BOOK # Passing the positional parameters of the number of notebooks and the number of pages to the procedure
 echo "The pages of the main set were assembled, now you can put together an additional notebook."
 letsgo
 let "LAST_W_BOOK = $ W_BOOK + 1" # Create a variable indicating the number of the last notebook
 if ["` expr $ TAIL_PAGES% 4` "-eq" 0 "] # If the number of pages in the last notebook 
   then
     echo "Everything is fine, we continue to create the last notebook"
     assembly $ LAST_W_BOOK $ TAIL_PAGES
   else
     echo "Notebook lacks expr 4 - $ TAIL_PAGES% 4` pages (s)"
     echo "You should add them. You can add them manually or let the program do it."
     letsgo
     # add the required number of empty files and then proceed to build
 fi
 rm -R $ TMP_DIR


Problems


I really do not like this solution:

  gs -q -sDEVICE = bmpmono -r2x2 -sOutputFile = $ TMP_DIR /% d.bmp -dNOPAUSE -dBATCH * pdf # Extract pages from PDF in low resolution
 FILE_COUNT = `ls -l $ TMP_DIR / * bmp |  grep ^ - |  wc -l` # Count the number of pages in the document by counting the number of files in the directory


Thanks klirichek, now it looks like this:
  FILE_COUNT = `pdfinfo * pdf |  awk '/ Pages / {print $ 2}' ` 


Therefore, I will be grateful for the hint how to find out the number of pages in the PDF-nick without unpacking it.

Conclusion


The script is raw. The processing of a PDF-file containing the number of pages is not a multiple of 4 has not been completed, it was not originally planned to be published here, because the Chukchi is a reader.

I plan to add a launch from the command line indicating the parameters and batch processing of a series of files, while this creation processes only one, even though it says "* pdf".

The first experience, please do not kick.

For ideas and corrections thanks in advance.

Source: https://habr.com/ru/post/240489/


All Articles