joe di castrohttp://joedicastro.com2012-07-16T23:32:00+02:00Productividad & Linux: zathura2012-07-16T23:32:00+02:00joe di castrohttp://joedicastro.com/productividad-linux-zathura.html<p><a href="http://pwmt.org/projects/zathura/">zathura</a> es un programa minimalista que procura seguir el principio de
<em>"menos es más"</em> que acuñara <a href="https://es.wikipedia.org/wiki/Ludwig_Mies_van_der_Rohe">Mies van der Rohe</a> en la arquitectura y que
en la informática se correspondería con el principio <a href="https://es.wikipedia.org/wiki/Principio_KISS">KISS</a> y la
<a href="http://en.wikipedia.org/wiki/Unix_philosophy">filosofía UNIX</a>. Siguiendo esta filosofía, zathura es una aplicación que
hace una sola cosa, la hace bien y consume muy pocos recursos. Sus autores, la
comunidad <a href="http://pwmt.org/about">PWMT.org</a> (<em>programas con nombre de película</em>), tienen como
propósito el crear aplicaciones de software libre que se centren en un interfaz
simple, que no malgaste espacio y que se maneje íntegramente desde el teclado.</p>
<p>La aplicación es un visor de documentos, y es modular, por lo que puedes
instalar los plugins que quieras en función del formato de documentos que
quieras que soporte. Actualmente están disponibles los siguientes plugins:</p>
<ul>
<li>
<p><em>pdf-poppler</em>: Lectura de <a href="http://es.wikipedia.org/wiki/Pdf">PDF</a> a través de la famosa librería
<a href="http://poppler.freedesktop.org/">Poppler</a>, que es empleada por aplicaciones como Evince, Okular o
Inkscape.</p>
</li>
<li>
<p><em>pdf-mupdf</em>: Lectura de PDF mediante la librería <a href="http://mupdf.com/">mupdf</a> empleada por
ejemplo por Sumatra PDF.</p>
</li>
<li>
<p><em>djvu</em>: Para visionar documentos <a href="https://es.wikipedia.org/wiki/Djvu">DJVU</a>. Emplea la librería
<a href="http://djvu.sourceforge.net/">djvulibre</a> que emplean por ejemplo Evince y Okular.</p>
</li>
<li>
<p><em>ps</em>: Para poder ver documentos <a href="https://es.wikipedia.org/wiki/Postscript">Postscript</a>. Usa la librería
<a href="http://libspectre.freedesktop.org/">libspectre</a> que es utilizada por Evince y Okular.</p>
</li>
<li>
<p><em>cb</em>: Para poder abrir archivos en formato <a href="https://es.wikipedia.org/wiki/Archivo_de_historieta">Comic Book</a>.</p>
</li>
</ul>
<p>Como se puede ver emplea las mismas librerías que emplean la mayoría de
programas similares para Linux, por lo tanto nos ofrecen la misma calidad que
estos pero con un interfaz minimalista donde el protagonista es el contenido, y
proporcionándonos un control absoluto del documento desde el teclado.</p>
<p style="text-align:center;"><img src="pictures/zathura.png" width="700"
height="957" alt="Zathura" /></p>
<p>El interfaz es simple, una ventana de contenido y una barra de estado/línea de
comandos. El control de la misma recae en el teclado (aunque puede usarse el
ratón para funciones básicas) y sus atajos están inspirados en los de Vim.</p>
<h2 id="caracter+sticas">Características</h2>
<p>Las características principales de Zathura son las siguientes:</p>
<ul>
<li>Interfaz minimalista</li>
<li>Controlable completamente desde el teclado, inspirado en vim y muy parecido a
pentadactyl. Permite seguir enlaces y saltos directos a páginas</li>
<li>Recarga automática de documentos si estos cambian. Útil para previsualizar la
salida en PDF de documentos de LaTeX, por ejemplo</li>
<li>Permite establecer marcadores y marcadores rápidos dentro de un documento. Muy
útil para labores de investigación y documentación</li>
<li>Exporta imágenes y adjuntos de un documento</li>
<li>Puede abrir documentos protegidos por contraseña (proporcionándosela, claro)</li>
<li>Imprime el documento completo o simplemente las hojas que deseemos</li>
<li>Permite buscar en el documento y desplazarse por los resultados</li>
<li>Se puede abrir y navegar por el indice del documento</li>
<li>Muestra la información disponible (metadatos) sobre el documento</li>
<li>Zoom y Rotar documentos</li>
<li>Permite cambiar el color del documento. Sirve para visualizar el documento en
duotono con los colores invertidos</li>
<li>Se pueden personalizar los atajos de teclado y los colores empleados</li>
<li>Se personaliza a través de un fichero de texto plano</li>
</ul>
<p>En esta imagen se puede apreciar el resultado de aplicar el comando <code>:info</code>
sobre un documento.</p>
<p style="text-align:center;"><img src="pictures/zathura_info.png" width="700"
height="957" alt="zathura info dialog" /></p>
<p>El poder cambiar los colores del documento, invirtiéndolos, es una
característica muy útil, por ejemplo, para leer largos documentos sin fatigar
demasiado nuestra vista. Aquí se puede ver la diferencia entre ver un documento
a pantalla completa en modo normal y con los colores invertidos.</p>
<p style="text-align:center;"><img src="pictures/zathura.gif" width="640"
height="400" alt="zathura full screen" /></p>
<h2 id="alternativas">Alternativas</h2>
<p>No hay demasiadas alternativas a Zathura que tengan un planteamiento parecido,
de hecho la única que conozco es <a href="http://naihe2010.github.com/apvlv/">apvlv</a>. Aunque para mi no es tan
completa como Zathura.</p>
<h2 id="mi_configuraci+n">Mi configuración</h2>
<p>Aunque mi configuración no tiene nada de particular, está disponible en mis
<em>dotfiles</em> alojados en <a href="http://github.com/joedicastro/dotfiles">GitHub</a>.</p>Convertir ficheros djvu a pdf en Linux2011-12-03T00:00:00+01:00joe di castrohttp://joedicastro.com/convertir-ficheros-djvu-a-pdf-en-linux.html<p>Tengo por costumbre almacenar mis documentos escaneados en el formato
<a href="http://es.wikipedia.org/wiki/DjVu">djvu</a>, que fue expresamente creado para esa tarea y que otorga la mejor
calidad posible en el menor espacio. Es el formato perfecto para documentos
complejos sobre los que no se va a realizar un <a href="http://es.wikipedia.org/wiki/Reconocimiento_%C3%B3ptico_de_caracteres">OCR</a> (aunque también lo soporta). Además es un formato abierto, por lo que nos garantiza que podrá seguir
empleándose en un futuro. Pero a veces necesito compartir estos ficheros con
otros y para evitarme problemas suelo convertirlos a un formato más conocido y
difundido como <a href="http://es.wikipedia.org/wiki/Pdf">PDF</a>.</p>
<p>Para realizar esta conversión empleo desde hace años (la primera versión es del
2009) un sencillo script en python. Ahora que he necesitado una conversión
masiva de documentos de un formato al otro, he modificado el script para hacer
esto más sencillo y he decidido compartirlo con cualquiera que pueda necesitarlo. </p>
<h2 id="los_requisitos_previos">Los requisitos previos</h2>
<p>Está diseñado para funcionar en Linux y necesita de la instalación de dos
pequeños programas que son los que realmente realizan la conversión. Estos dos
programas son <code>ddjvu</code> y <code>tiff2pdf</code>. Además de tener instalado <strong>Python</strong> en una
versión <em>2.7</em> o superior. Estos dos programas vienen en los repositorios de
prácticamente todas las distribuciones importantes dentro de los paquetes
<a href="http://djvu.sourceforge.net/">djvulibre</a> y <a href="http://libtiff.maptools.org">libtiff</a>.</p>
<p>En el caso de no tenerlos instalados, la instalación de los mismos es muy
sencilla, para distribuciones basadas en Debian/Ubuntu:</p>
<div class="codehilite"><pre><span class="gp">$</span> apt-get install djvulibre-bin libtiff-tools
</pre></div>
<p><code>ddjvu</code> nos extrae las páginas que conforman el documento <em>.djvu</em> a un archivo intermedio en formato <em>.tiff</em> y <code>tiff2pdf</code> nos lo convierte en <em>.pdf</em>.</p>
<h2 id="modo_de_empleo">Modo de empleo</h2>
<p>Emplearlo es muy sencillo, como se puede ver en la ayuda del mismo:</p>
<div class="codehilite"><pre><span class="gp">$</span> djvu2pdf -h
<span class="go">usage: djvu2pdf [-h] [-d | -z] [-v] file [file ...]</span>
<span class="go">Converts a djvu file into a pdf file</span>
<span class="go">positional arguments:</span>
<span class="go"> file The djvu file</span>
<span class="go">optional arguments:</span>
<span class="go"> -h, --help show this help message and exit</span>
<span class="go"> -d no compression. Best quality but big files.</span>
<span class="go"> -z zip compression. More quality, more size.</span>
<span class="go"> -v, --version show program's version number and exit</span>
</pre></div>
<p>Básicamente llamandalo desde python y poniendo a continuación el nombre del
fichero/s es lo único que necesitamos para ejecutarlo, por ejemplo:</p>
<div class="codehilite"><pre><span class="gp">$</span> ls
<span class="go">documento.djvu documento_2.djvu</span>
<span class="gp">$</span> python djvu2pdf.py documento.djvu documento_2.djvu
<span class="gp">$</span> ls
<span class="go">documento.djvu documento.pdf documento_2.djvu documento_2.pdf</span>
</pre></div>
<p>Opcionalmente tenemos las opciones <code>-d</code> y <code>-z</code>, que nos sirven para especificar
si queremos no emplear compresión en el <em>.pdf</em> (por defecto emplea compresión
<a href="http://es.wikipedia.org/wiki/Jpeg">jpeg</a>) o emplear compresión <a href="http://es.wikipedia.org/wiki/Formato_de_compresi%C3%B3n_ZIP">zip</a>, respectivamente. Si no empleamos compresión, la calidad final será la mejor posible, pero los archivos serán muy grandes. En cambio, empleando <em>zip</em>, tenemos unos ficheros ligeramente mayores a cambio de una calidad muy buena. Aunque la compresión <em>zip</em> puede dar problemas
con algunos visores y lectores de ebooks.</p>
<h2 id="el_script_djvu2pdfpy">El script, djvu2pdf.py</h2>
<p>El contenido del scipt es el que sigue. Este está disponible como el fichero
<code>djvu2pdf.py</code> dentro del repositorio <em>Python Recipes</em> que está alojado en
<a href="http://github.com/joedicastro/python-recipes">github</a> y actualizado siempre a la última versión.</p>
<div class="codehilite"><pre><span class="c">#!/usr/bin/env python</span>
<span class="c"># -*- coding: utf8 -*-</span>
<span class="sd">"""</span>
<span class="sd"> djvu2pdf.py: Converts a .djvu file into a .pdf file</span>
<span class="sd">"""</span>
<span class="c">#==============================================================================</span>
<span class="c"># This Script does exactly as the description above says.</span>
<span class="c">#==============================================================================</span>
<span class="c">#==============================================================================</span>
<span class="c"># Copyright 2011 joe di castro <joe@joedicastro.com></span>
<span class="c">#</span>
<span class="c"># This program is free software: you can redistribute it and/or modify</span>
<span class="c"># it under the terms of the GNU General Public License as published by</span>
<span class="c"># the Free Software Foundation, either version 3 of the License, or</span>
<span class="c"># (at your option) any later version.</span>
<span class="c">#</span>
<span class="c"># This program is distributed in the hope that it will be useful,</span>
<span class="c"># but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<span class="c"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span>
<span class="c"># GNU General Public License for more details.</span>
<span class="c">#</span>
<span class="c"># You should have received a copy of the GNU General Public License</span>
<span class="c"># along with this program. If not, see <http://www.gnu.org/licenses/>.</span>
<span class="c">#==============================================================================</span>
<span class="n">__author__</span> <span class="o">=</span> <span class="s">"joe di castro <joe@joedicastro.com>"</span>
<span class="n">__license__</span> <span class="o">=</span> <span class="s">"GNU General Public License version 3"</span>
<span class="n">__date__</span> <span class="o">=</span> <span class="s">"03/12/2011"</span>
<span class="n">__version__</span> <span class="o">=</span> <span class="s">"0.3"</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">from</span> <span class="nn">argparse</span> <span class="kn">import</span> <span class="n">ArgumentParser</span>
<span class="kn">from</span> <span class="nn">subprocess</span> <span class="kn">import</span> <span class="n">Popen</span><span class="p">,</span> <span class="n">PIPE</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
<span class="c"># Checks the installation of the necessary python modules</span>
<span class="k">print</span><span class="p">((</span><span class="n">os</span><span class="o">.</span><span class="n">linesep</span> <span class="o">*</span> <span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="s">"An error found importing one module:"</span><span class="p">,</span>
<span class="nb">str</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">1</span><span class="p">]),</span> <span class="s">"You need to install it"</span><span class="p">,</span> <span class="s">"Stopping..."</span><span class="p">]))</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">check_execs</span><span class="p">(</span><span class="o">*</span><span class="n">progs</span><span class="p">):</span>
<span class="sd">"""Check if the programs are installed, if not exit and report."""</span>
<span class="k">for</span> <span class="n">prog</span> <span class="ow">in</span> <span class="n">progs</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">Popen</span><span class="p">([</span><span class="n">prog</span><span class="p">,</span> <span class="s">'--help'</span><span class="p">],</span> <span class="n">stdout</span><span class="o">=</span><span class="n">PIPE</span><span class="p">,</span> <span class="n">stderr</span><span class="o">=</span><span class="n">PIPE</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">OSError</span><span class="p">:</span>
<span class="n">msg</span> <span class="o">=</span> <span class="s">'The {0} program is necessary to run the script'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">prog</span><span class="p">)</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="k">return</span>
<span class="k">def</span> <span class="nf">arguments</span><span class="p">():</span>
<span class="sd">"""Defines the command line arguments for the script."""</span>
<span class="n">main_desc</span> <span class="o">=</span> <span class="s">"""Converts a djvu file into a pdf file"""</span>
<span class="n">parser</span> <span class="o">=</span> <span class="n">ArgumentParser</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="n">main_desc</span><span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">"file"</span><span class="p">,</span> <span class="n">nargs</span><span class="o">=</span><span class="s">"+"</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">"The djvu file"</span><span class="p">)</span>
<span class="n">group</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">add_mutually_exclusive_group</span><span class="p">()</span>
<span class="n">group</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">"-d"</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s">"qlty"</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="s">"store_const"</span><span class="p">,</span> <span class="n">const</span><span class="o">=</span><span class="s">"-d"</span><span class="p">,</span>
<span class="n">help</span><span class="o">=</span><span class="s">"no compression. Best quality but big files."</span><span class="p">)</span>
<span class="n">group</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">"-z"</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s">"qlty"</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="s">"store_const"</span><span class="p">,</span> <span class="n">const</span><span class="o">=</span><span class="s">"-z"</span><span class="p">,</span>
<span class="n">help</span><span class="o">=</span><span class="s">"zip compression. More quality, more size."</span><span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">"-v"</span><span class="p">,</span> <span class="s">"--version"</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="s">"version"</span><span class="p">,</span>
<span class="n">version</span><span class="o">=</span><span class="s">"</span><span class="si">%(prog)s</span><span class="s"> {0}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">__version__</span><span class="p">),</span>
<span class="n">help</span><span class="o">=</span><span class="s">"show program's version number and exit"</span><span class="p">)</span>
<span class="k">return</span> <span class="n">parser</span>
<span class="k">def</span> <span class="nf">process</span><span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">fname</span><span class="p">):</span>
<span class="sd">"""Process the external commands and report the errors."""</span>
<span class="n">errors</span> <span class="o">=</span> <span class="n">Popen</span><span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">stderr</span><span class="o">=</span><span class="n">PIPE</span><span class="p">)</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">readlines</span><span class="p">()</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">errors</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"{0}: {1}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">fname</span><span class="o">.</span><span class="n">upper</span><span class="p">(),</span> <span class="n">line</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">linesep</span><span class="p">)))</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="sd">"""Main section."""</span>
<span class="n">args</span> <span class="o">=</span> <span class="n">arguments</span><span class="p">()</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span>
<span class="n">djvu_files</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">file</span>
<span class="k">for</span> <span class="n">djvu</span> <span class="ow">in</span> <span class="n">djvu_files</span><span class="p">:</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">djvu</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">"ERROR: cannot open '{0}' (No such file)"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">djvu</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">djvu_filename</span> <span class="o">=</span> <span class="n">djvu</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">".djvu"</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">tiff</span> <span class="o">=</span> <span class="s">'{0}.tif'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">djvu_filename</span><span class="p">)</span>
<span class="n">pdf</span> <span class="o">=</span> <span class="s">'{0}.pdf'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">djvu_filename</span><span class="p">)</span>
<span class="n">process</span><span class="p">([</span><span class="s">'ddjvu'</span><span class="p">,</span> <span class="s">'-format=tiff'</span><span class="p">,</span> <span class="n">djvu</span><span class="p">,</span> <span class="n">tiff</span><span class="p">],</span> <span class="n">tiff</span><span class="p">)</span>
<span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">tiff</span><span class="p">):</span>
<span class="n">quality</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">qlty</span> <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">qlty</span> <span class="k">else</span> <span class="s">"-j"</span>
<span class="n">process</span><span class="p">([</span><span class="s">'tiff2pdf'</span><span class="p">,</span> <span class="n">quality</span><span class="p">,</span> <span class="s">'-o'</span><span class="p">,</span> <span class="n">pdf</span><span class="p">,</span> <span class="n">tiff</span><span class="p">],</span> <span class="n">pdf</span><span class="p">)</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">tiff</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">"__main__"</span><span class="p">:</span>
<span class="n">check_execs</span><span class="p">(</span><span class="s">'ddjvu'</span><span class="p">,</span> <span class="s">'tiff2pdf'</span><span class="p">)</span>
<span class="n">main</span><span class="p">()</span>
</pre></div>