jump to navigation

Convertir PDFs a texto (o por qué los PDFs no son un buen formato para eBooks) 29 agosto 2006

Posted by Jesús in Informática, Libros, Linux.
add a comment

Siempre que se convierte un fichero PDF a texto, aparecen una serie de problemas que, aunque se pueden resolver, son francamente molestos. Básicamente son:

  • Problemas con la codificación de caracteres
  • Desastres con la maquetación: cada línea del txt de salida tiene un salto de línea manual al final, y otras lindezas como incluir encabezados y números de página entre el texto, etc.

Después de cacharrear un poco, me ha salido el siguiente proceso para tener un resultado aceptable:

1) Convertir a texto con el comando (linuxero, no sé en windows cómo iría la cosa):

pdftotext -layout -enc Latin1 -nopgbrk fichero.pdf

Así se creará un fichero.txt con la codificación de caracteres correcta (-enc), sin encabezados ni pies de página mezclados con el texto (-nopgbrk) y con una estructura parecida al fichero pdf original (-layout). Justamente esto último da muchos problemas, ya que, al respetar el maquetado original, añade saltos de línea a tutiplén que no deberían estar. Lo malo es que la alternativa (no poner el -layout) da como resultado un párrafo infinito, por lo que es preferible dejar que haga desastres con el maquetado y arreglarlos después.

2) Abrir el fichero de texto en nuestro editor favorito (que sea un poco potable, con expresiones regulares y tal, por ejemplo vi, kate u openoffice writer).

3) A partir de aquí la cosa depende de cómo haya quedado el resultado. El objetivo es el mismo en cualquier caso: identificar los saltos de línea “correctos” y marcarlos para distinguirlos del resto.

¿Cómo distinguir los saltos de línea “correctos”? Bueno, en muchos textos, la primera línea de cada párrafo tiene una sangría adicional, que en la conversión se habrá traducido a unos cuantos espacios más que el resto de líneas, que podemos aprovechar para distinguirlos. Otra forma es aprovechar que en muchas ocasiones se deja un espacio extra entre párrafos, que en el txt se convierte en saltos de línea adicionales. De esta manera, los saltos a conservar serán aquellos que aparezcan de dos en dos (uno el del párrafo, y otro el del espacio). En el peor caso (no hay manera de distinguirlos) se puede usar una regla no infalible pero que funciona bien en la mayoría de casos, que dice que un salto de línea correcto es el que va precedido de un punto (u otros caracteres como :, interrogantes, admiraciones y tal vez otras cosas).

Sea como sea, una vez sabemos cómo identificar el salto de línea que hay que conservar, lo sustituimos por una cadena arbitraria, por ejemplo INTROREAL. La idea es que si marcamos así todos los saltos de línea “buenos”, eliminamos el resto, y sustituimos estos marcadores que hemos añadido por un salto de línea, el resultado será un texto maquetado como toca.

4) Eliminar todos los saltos de línea innecesarios
Ahora toca quitar todos los saltos de línea, y aquí nos encontramos con una de las miserias del tratamiento de textos bajo linux. Lo ideal sería poder buscar todos los “\n”, sustituyéndolos por “” (o sea, nada), pero mucho me temo que las cosas no funcionan así.

La mayoría de editores de texto que he probado en linux funcionan línea a línea, lo cual quiere decir que, en búsquedas y demás, no se puede operar con textos en diferentes líneas. Esto hace que eliminar los saltos de línea sea algo más bien imposible, ya que en el tratamiento del texto línea a línea ya se da por implícito que la línea de texto es lo que va entre un intro y el siguiente, por lo que el intro en sí no se puede tocar. Así he visto que funcionan OpenOffice y Kate. Mi bienamado vi, por otra parte, si bien no tiene esta limitación, no parece muy optimizado para estas cosas, y en mi ordenador, a la que intento hacer algo así como eliminar todos los fines de línea, empieza a consumir memoria hasta que acaba con la RAM y el swap, por lo que no es muy usable que digamos.

Al final he resuelto la cosa escribiendo un mini-programa en Python (cómo me mola este lenguaje) que sustituye los saltos de línea de un texto por espacios. Al mismo tiempo, también va sustituyendo los marcadores que hemos puesto antes por un salto de línea, total, ¿para qué hacer las cosas dos veces cuando se pueden hacer de una vez? 🙂

import sys
import re

for l in sys.stdin:
	print re.sub("INTROREAL","n",l[:-1]),

El programa funciona a través de la entrada/salida estándar, por lo que se puede guardar con un nombre tipo quitaintros.py y ejecutar:

cat fichero.txt | python quitaintros.py > fichero_bien.txt

Y con esto ya estaría todo lo que se refiere al texto. Ahora faltaría idear alguna manera de arreglar los títulos de capítulo y demás, pero teniendo un poco de ojo se puede usar el mismo método (buscar algún rasgo que los distinga del resto del texto, y con un par de buscar/reemplazar bien puestos ponerlos como queramos).

Es verdad que es un poco trabajoso, pero el resultado final vale la pena. Lo triste es que recuerdo que en mis tiempos windowseros tenía automatizado todo esto como una macro de Word, pero mucho me temo que en el OpenOffice (dejando de lado el horrendo lenguaje de macros que tiene, que es tema para otro día), algunos de los pasos son imposibles de llevar a cabo, y hacen falta herramientas externas.

Moraleja: ¡No usar PDF para eBooks! La gracia de un eBook es poder adaptarlo a las necesidades de visualización de cada cual: unos querrán leer en pantalla, otros imprimírselo en A4, otros en A5, otros leer en un PDA… Esto requiere un mínimo de acceso al documento, que un PDF no da ni mucho menos y que obliga a hacer pirulas como las descritas arriba. Por tanto, es mucho más deseable, a la hora de trabajar con libros electrónicos, utilizar formatos como el ODT/DOC/RTF, HTML o el texto plano.

Harry Potter y el misterio del príncipe 25 agosto 2006

Posted by Jesús in Comentarios de Libros, Libros.
2 comments

Cada vez que digo que me gustan los libros de Harry Potter, me gano alguna mirada extraña por parte de gente que cree que eso son “cosas de niños”. A toda esta gente siempre les digo lo mismo: sí, vale, el primero y tal vez el segundo libro son algo más infantilotes, pero a partir de “El prisionero de Azkabán” (e imagino que teniendo en cuenta que el público objetivo también va creciendo), la verdad es que la cosa coge un tono siniestro muy poco infantil, y la historia comienza a complicarse y volverse muy interesante. En realidad, no veo que la complejidad y profundidad de los argumentos tenga nada que envidiar, ni mucho menos, a otros libros mucho mejor considerados, y que si no has leído parece que eres un bicho raro.

El caso es que por fin he podido hacerme con una copia del último libro de Harry Potter, y la verdad es que me ha dejado bastante frío. Bueno, eso no es muy exacto, ya que precisamente la parte más aprovechable del libro son las 100 últimas páginas, que, con un final impactante (con muerte de personaje principal incluida) y muy peliculero (falta el “continuará”) te deja con ganas de más. Ahora bien, las otras tres cuartas partes del libro son casi exclusivamente puro relleno, y no está ni mucho menos al nivel de libros anteriores como “El prisionero de Azkabán” o “El cáliz de fuego”.

En fin, que “El misterio del príncipe” es más bien un libro de transición para el séptimo y último libro de la saga, en el que ya se rumorea que el protagonista no va a acabar muy bien parado…

Hemos evolucionado 24 agosto 2006

Posted by Jesús in Programación.
add a comment

Desde hace tiempo, tenía la sensación de que en la programación no habíamos evolucionado mucho. Al fin y al cabo, hoy en día casi todo se sigue moviendo en torno a C++/Java y alguna cosilla más, lo cual no es muy diferente a cómo estábamos hace 4 o 5 años. Ahora bien, estos días he tenido que hacer un poco de flashback en mi forma de programar debido a mis cacharreos con la DS, y me he dado cuenta de que hemos evolucionado, y mucho.

Veamos un ejemplo práctico: para manejar imágenes en Python, basta hacer algo como:

import Image  

img=Image.open("fichero.png")
img.resize((640,480))
img.save("fichero_salida.png")

Fácil, ¿no? Pues bien, estos días intento hacer algo parecido en C pelado, y mirando la documentación de libpng, me sale que para abrir un PNG hay que hacer algo parecido a esto:

char header[8];	// 8 is the maximum size that can be checked

/* open file and test for it being a png */
FILE *fp = fopen(file_name, "rb");
if (!fp)
	abort_("[read_png_file] File %s could not be opened for reading", file_name);
fread(header, 1, 8, fp);
if (png_sig_cmp(header, 0, 8))
	abort_("[read_png_file] File %s is not recognized as a PNG file", file_name);

/* initialize stuff */
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

if (!png_ptr)
	abort_("[read_png_file] png_create_read_struct failed");

info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
	abort_("[read_png_file] png_create_info_struct failed");

if (setjmp(png_jmpbuf(png_ptr)))
	abort_("[read_png_file] Error during init_io");

png_init_io(png_ptr, fp);
png_set_sig_bytes(png_ptr, 8);

png_read_info(png_ptr, info_ptr);

width = info_ptr->width;
height = info_ptr->height;
color_type = info_ptr->color_type;
bit_depth = info_ptr->bit_depth;

number_of_passes = png_set_interlace_handling(png_ptr);
png_read_update_info(png_ptr, info_ptr);
...

…y paro porque la cosa sigue un rato más (el que quiera el ejemplo entero lo puede encontrar aquí). Y esto es sólo para abrir el PNG, ni hablemos ya de empezar a procesarlo y demás.

En fin, que juro por la cobertura de mi móvil que no volveré a decir que la programación no evoluciona (y que el monstruo espagueti volador bendiga a los creadores de Python 🙂 )

Programando en la Nintendo DS 23 agosto 2006

Posted by Jesús in Programación.
9 comments

Como orgulloso poseedor de una flamante Nintendo DS, y asiduo lector de libros, una de las primeras cosas que me pasó por la cabeza al ver las dos pantallas que tiene fue “esto como lector de libros puede estar muy bien”. Después de mirar un poco a ver si alguien había pensado lo mismo y había hecho ya un lector de libros, vi que la cosa estaba muy verde aún, y como a veces me pega el punto de cacharrear con estas cosas, busqué un poco qué posibilidades de desarrollo en la DS hay hoy en día.

Pues bien, la cosa está bastante factible: hay un kit de desarrollo basado en software libre y creado por aficionados, que se puede instalar en Windows con un asistente de los de siguiente->siguiente y lo deja todo listo para empezar a programar (en linux es un pelín más complicado montar el tinglado, pero tampoco mucho). La programación se hace usando la librería PALib, que es bastante completita y está muy bien documentada, tienen un wiki con toda la documentación y un montón de tutoriales. El principal problema es que para ejecutar software casero hay que comprarse el típico copión, que se enchufa al slot de cartuchos de la DS y permite meterle ROMs en tarjetas SD. La verdad es que vale una pasta, pero entre las posibilidades de desarrollo que da, y que además permite probar los juegos antes de comprarlos, creo que merece la pena.

Lo que sí me ha sorprendido es lo fácil que es programar un trasto de estos. Yo me esperaba una cosa más a bajo nivel (ensamblador por un tubo, interrupciones y tal), pero resulta que toda la gestión de sprites, fondos, planos de scroll, música y demás la hace ya por hardware la consola, por lo que el programador se puede centrar en el juego en sí. Imagino que el esquema es similar a todas las antiguas consolas de 16 bits tipo Megadrive y Super Nintendo, pero como es mi primer contacto con estas cosas, me ha llamado la atención. De momento, en los pocos días que llevo trasteando, ya he podido mostrar texto por pantalla(s) sin problemas (en un programa de 15 líneas, mirad si es fácil), y aunque el soporte de texto en PALib es un poco precario, la DS promete como lector de libros. Si al final encuentro el tiempo y consigo sacar adelante algo usable, ya lo publicaré en alguna parte…

¿Es el futuro funcional? 23 agosto 2006

Posted by Jesús in Programación.
add a comment

He encontrado estos días (no me acuerdo dónde) un articulín en el que se muestran las virguerías que permiten hacer algunos lenguajes de programación modernos, en este caso javascript (sí, esa cosa tan chunga que parece que sólo sirve para mostrar popups, quién lo iba a decir) pero que también son aplicables a otros lenguajes tipo Python o Ruby. El asunto se basa en hacer cosas que suenan como a sacrilegio a cualquier programador de C, Pascal o hasta diría que Java, como pasar funciones como parámetro y cosas así, pero que, bien usadas, pueden conseguir resultados sorprendentes.

Planteémosnos una pregunta: hoy en día, que cada vez vemos procesadores más paralelos (ya es normal tener una CPU con dos cores, el año que viene salen las de 4, y ya se habla de 8, 16, etc.), ¿podremos aprovechar todo ese paralelismo con los lenguajes convencionales? Al fin y al cabo, muchos de los lenguajes que conocemos a día de hoy no dejan de ser envoltorios sintácticamente atractivos para un paradigma totalmente lineal: la arquitectura von Neumann, usease, una instrucción detrás de otra, y saltamos de vez en cuando. Vale que tenemos toda una serie de facilidades tipo procesos, threads y demás, pero teniendo en cuenta que generan casi tantos problemas como solucionan (que si exclusión mutua, que si interbloqueos, etc.), podría parecer más un apaño que otra cosa.

¿No sería genial programar en un lenguaje verdaderamente de alto nivel, que no estuviera atado a la arquitectura von Neumann? Así, bastaría escribir el programa y luego, al ejecutarlo en nuestro flamante Athlon X64 (no porque sea de 64 bits, sino porque tendría 64 cores), automágicamente se haría uso de tanto paralelismo junto.

Y aquí llego al asunto: todo esto ya existe, y de hecho es casi tan viejo como la informática. Los lenguajes funcionales, tipo Lisp y compañía, se basan en un paradigma que no tiene nada que ver con el clásico modelo lineal, y por ello son altamente paralelizables. En realidad, y aunque tal vez Lisp tenga otros problemas, en los nuevos lenguajes que van apareciendo se deja ver una influencia funcional muy importante: basta ver las funciones anónimas o la definición de listas por comprensión. Con cosas como éstas se puede programar a muy alto nivel, de manera que, si el compilador/intérprete es lo bastante listo, la paralelización sea, no sólo posible (todo es posible en este mundo), sino bastante fácil.

En el artículo se pone el ejemplo del típico bucle para procesar todos los elementos de un array: si lo hacemos con el clásico for, estamos indicando explícitamente que el procesado debe hacerse linealmente, desde el primer elemento al último. Si por el contrario lo hacemos con una función como la map() de Python, a la que se le pasa el array implicado y la función que queremos aplicar, no indicamos explícitamente ningún orden, sólo que queremos procesar todo el array, por lo que el compilador es libre de hacer los cálculos en serie, en paralelo o como quiera. Mecanismos como éste son los que nos permitirán en el futuro seguir programando con independencia de los cambios arquitecturales en el hardware.

En fin, quién sabe, tal vez en 10 años estemos todos programando en Lisp (habrá que aprender, porque mi Lisp es bastante básico…), pero por lo menos hay que ir poniéndose las pilas con la programación de más alto nivel, ya que hasta cosas tan “clásicas” como Java se están apuntando al carro…

Fallo de arranque en Ubuntu Dapper 23 agosto 2006

Posted by Jesús in Linux.
add a comment

Si esta mañana, al encender el ordenador, os habéis encontrado que la cosa no arranca, que no cunda el pánico. Por lo visto ayer actualizaron en los repositorios de Dapper el servidor X a una nueva versión, con tan mala pata que uno de los parches que incluía da problemas a muchos usuarios y les impide arrancar la máquina.

De todas formas, la cosa tiene fácil solución. En la pantalla negra que seguramente se habrá quedado, hay que pulsar alt+f1 (o f2, o f3…) para abrir una consola de texto. Iniciamos sesión con nuestro usuario, y ejecutamos los típicos aptitude update y aptitude dist-upgrade (o con apt-get, como prefiera cada cual). De esta manera, se actualizará el servidor X a la nueva versión ya arreglada, y con un ctrl+alt+supr volverá a arrancar el ordenador como si nada.

En fin, que final feliz y tal, pero tengo sentimientos encontrados sobre esto: no sé si quejarme de que la gente de Ubuntu no revise un poco los paquetes antes de subirlos a los repositorios (se supone que la Dapper es bastante estable), o bien alegrarme de la rápida respuesta y de las maravillas de la gestión de paquetes de las distribuciones basadas en Debian. Lo dejaremos en empate técnico por esta vez…

Jem 22 agosto 2006

Posted by Jesús in Comentarios de Libros.
2 comments

PortadaEn estas últimas rebajas encontré este libro de Frederik Pohl a 5 leuritos de nada, y además con tapas duras y esas cosas tan fashion que tan poco acostumbrado estoy a manejar (no está la economía como para dejarse 20 y muchos euros en un libro). Como es raro encontrar hoy en día libros así de bien presentados a este precio, y ya me había leído bastantes cosillas del autor, pues lo compré, y la verdad es que no me decepcionó.

La historia se desarrolla en un futuro más o menos cercano, en el que la exploración espacial ya va bastante encaminada y se ha llegado a otros planetas en estrellas cercanas. A pesar de este progreso, el mundo sigue viviendo en una especie de guerra fría, en este caso entre tres grandes bloques de países: el bloque de combustibles (que controla las reservas de petróleo), el bloque de alimentos (que controla los principales cultivos) y el bloque de población (fuente de mano de obra). En este contexto, el libro cuenta cómo se lleva a cabo la colonización de Jem, el primer planeta habitable que se ha descubierto. A pesar de contar con el ejempo de la Tierra (contaminada, superpoblada y al borde de una guerra nuclear), la colonización de Jem se convierte en una carrera más entre las diferentes potencias, que no dudarán en utilizar todas las malas artes que se les ocurran para llegar a sus objetivos, pervirtiendo de paso a las razas pseudo-inteligentes que habitan Jem para adaptarlas a sus propósitos.

El libro es una fábula sobre la condición humana, que muestra de forma bastante pesimista el carácter autodestructivo de nuestra raza, buscando siempre el máximo beneficio personal aun cuando esté claro que en ocasiones es necesario cooperar para llegar a un bien común. Además, presenta a la humanidad como una plaga que, con sus continuas disputas internas, destruye todo lo que le rodea, en este caso el equilibro entre las razas inteligentes de Jem.

Además de suponer una reflexión interesante, es fácil entrar en la historia pasadas las primeras páginas, que si bien son un pelín más pesadas, lo son mucho menos de lo que pudiera parecer si se tiene en cuenta que se están presentando personajes de las diferentes potencias terrestres, así como de las razas autóctonas de Jem. Una vez metidos en materia, el libro engancha bastante, y el final, aunque lógico y previsible, no deja de ser satisfactorio. En conclusión, una lectura recomendable.

BookMooch, comunidad de intercambio de libros 22 agosto 2006

Posted by Jesús in Libros.
1 comment so far

Estos días he descubierto BookMooch, una comunidad de intercambio de libros que sigue un poco la idea de BookCrossing, aunque si en esta última la idea era dejar abandonados los libros por el mundo confiando en que cayeran en buenas manos, en BookMooch se toma un enfoque un poco más “tradicional” y se trata de una red de intercambio de libros.
Básicamente la cosa funciona publicando los libros de los que dispones y estarías dispuesto a deshacerte, así como aquellos que no tienes y te gustaría tener. El resto de usuarios hace lo mismo, y si en algún momento hay alguna coincidencia entre petición y disponibilidad, el sistema pone en contacto a los dos usuarios para que se pasen el libro. Por supuesto, también es posible explorar el listado de libros disponibles de todos los usuarios para ver si hay algo interesante.

El funcionamiento es muy sencillo, en gran parte porque la web está muy integrada con Amazon, de manera que, por ejemplo, para añadir un libro a nuestra lista de disponibles basta con introducir el ISBN o parte del título, obteniendo el resto de detalles (editorial, portada, etc.) de la propia web de Amazon. Además, para que nadie abuse de esto de pedir libros regalados, hay montado un sistema de puntos, de manera que no puedes pedir libros hasta que no has, por lo menos, ofrecido unos cuantos.

Es verdad que la web es muy nueva y aún tienen que pulir una serie de detalles (por ejemplo la traducción de la web al español es bastante pobre, aunque se puede colaborar en mejorarla). El catálogo de libros (al menos en español) es aún pequeño, pero me parece una excelente idea para dar salida a todos esos libros que ya no leemos y, por supuesto, para conseguir libros que leer sin dejarse un riñón en el intento. Yo de momento ya me he dado de alta y he puesto a compartir unos cuantos libros, a ver si entre todos llegamos a una masa crítica de libros y la cosa va creciendo, que buena falta iba haciendo algo como esto…

Empezamos… 22 agosto 2006

Posted by Jesús in General.
1 comment so far

Bueno, pues ya tengo weblog. La verdad es que hace tiempo que me rondaba la idea de montar uno, pero entre la pereza y (penoso pero cierto) que no se me ocurría qué nombre ponerle, pues ahí estaba. Lo de la pereza se ha resuelto fácil colgándolo en WordPress.com, que la verdad es que en 5 minutos tienes un weblog en marcha. Lo del nombre… en fin, al final he puesto lo primero que se me ha ocurrido, no tiene ningún sentido ni es representativo de nada, pero bueno, al menos es fácil buscarme en Google.

Ahora tendría que presentarme y esas cosas, pero como total no creo que lean esto más que cuatro amigos y algún familiar, y más por pena que por otra cosa, pues tampoco creo que valga la pena empezar a contar mi vida porque más o menos me conoce todo el mundo. Ya se irá viendo con el tiempo si acabo contando mis más oscuras intimidades o se queda en una cosa tirando a anónima…