Paletas "a la" MS Office 2007-2010 para LibreOffice

Enviado por Frost el 29 Enero, 2012 - 17:17.

Infame primer entrada de mi Blog meparto

Buenas y santas a todos.

Una vez más, ando con los esquemas de colores que usa LibreOffice. Ya he mencionado anteriormente que no me gusta mucho el que viene por defecto: lo encuentro sobrecargado y desordenado.

Siendo que desde la versión 3.4 LibreOffice viene con una matriz uniforme de 8 columnas, no es defícil crear un esquema completo desde el menú Herramientas\Opciones\Colores es una tarea engorrosa. Por eso, sería bueno en principio alguna herramienta que genere un esquema de colores automáticamente.

La segunda cuestión, es que MS Office desde la versión 2007, cuenta con una especie de "acedor de esquemas de color". Uno define 12 colores, le da un nombre, y automáticamente tiene un "tema" de colores con sus respectivos gradientes de tonos.

Cuestión, por puro vicio he creado una pequeña aplicación, ejecutable desde consola (nada de GUI, mis conocimientos no me lo permiten) para generar un esquema de colores a la MS Office, partiendo desde el que llama "Texto 2" hasta "Énfasis 6", siendo 8 colores en total. Estos colores pueden ser cualquiera, en formato RGB decimal.

El programa -escrito en Fortan 90- lee las 8 coordenadas RGB sea en pantalla o archivo de texto. Luego, genera automáticamente un archivo XML, con estensión .SOC = paleta de colores de OpenOffice.org/LibreOffice. Este archivo es posible renombrarlo como más les guste, para luego copiarse en la carpeta $(HOME)/.libreoffice/3/user/config.

Si uno quiere que la paleta creada aparezca por defecto, tiene que copiarla en la ruta antes mencionada como "standard.soc". Sino, si sólo se quiere que ésta nueva paleta aparezca como una opción más, no he encontrado otra cosa que no sea:

  1. Crear una figura
  2. Click derecho->Área
  3. Pestaña "Colores"

Ahí aparece un botón "Abrir". Si alguien sabe alguna forma más fácil, avise por favor.

Sin más, éste es el código. No se trata de un programa muy complejo, ni me he tomado el trabajo de escribirle una licencia (aunque supongo que lo mejor sería GPLv3)

program paleta
!
integer R(150), G(150), B(150),nombre(150), tipo1,tipo2,tipo3
character*2 colorHexa(3,150)
character*31 Toba
character*81 aux
character*63 aux2
character*82 aux3
character*47 aux4
character*30 enfasis
character*14 draw
real*8 aa(3,5),bb(3,5),cc(3,5),dd(3,5)

write(*,'("Para ingreso de colores en pantalla, ingrese 5",//,"Para ingreso por archivo de texto ingrese 0")')
read(*,*) IN
if(IN.EQ.0)then

  open(unit=IN,file="entrada.txt")

endif
open(unit=2,file="paleta.soc")
!
! Inicio del archivo XML
write(2,'(A38)')'<?xml version="1.0" encoding="UTF-8"?>'
aux=' <ooo:color-table xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"'
aux2=' xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"'
aux3=' xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg"'
aux4=' xmlns:ooo="http://openoffice.org/2004/office">'
write(2,'(A81,A63,A82,A47)')aux, aux2, aux3, aux4
!
! Número de colores: 8 en MS Office 2007, sin contar blanco y negro.
N = 8
!*******************************************************************
! Se leerá luego, en otra versión, para generar más tipos de paletas..
!
! if(IN.EQ.5)write(IN,'(/,"Ingrese número de colores:")')
! read(in,*,err=100,end=100)N
!*******************************************************************
!
! Lectura de los colores. En MS Offce 2007, los 2 primeros colores son Blanco (Fondo 1) y negro (texto 1)
tipo2 = 1
tipo3 = 1
do i = 1,8

  read(IN,*,err=101,end=101)R(i),G(i),B(i)
!
!   Límites de valor
  if(R(i).LT.0)R(i) = 0
  if(R(i).GT.255)R(i) = 255
  if(G(i).LT.0)G(i) = 0
  if(G(i).GT.255)G(i) = 255
  if(B(i).LT.0)B(i) = 0
  if(B(i).GT.255)B(i) = 255
!
!   Asignación auxiliar. La subroutina ToB cambia el valor del número ingresado.
  iR = R(i)
  iG = G(i)
  iB = B(i)
!
!   Números hexadecimales correspondientes a cada R,G,B
  call ToB(16,iR,colorHexa(1,i))
  call ToB(16,iG,colorHexa(2,i))
  call ToB(16,iB,colorHexa(3,i))
!
!   Colores énfasis y/o texto-fondo.
  tipo1 = 3
  if(i.LT.3)then

    tipo1 = i

  endif
  call escritura(i,colorHexa(1:3,i),tipo1,tipo2,tipo3)

enddo
!
! Gradiente blanco-negro reemplaza la separación entre colores ppales y sus gradientes
a = 255/7
tipo1 = 4
do i = 1,8

  R(i+8) = a*float(8-i)
  G(i+8) = R(i+8)
  B(i+8) = R(i+8)
!   Asignación auxiliar
  iR = R(i+8)
  iG = G(i+8)
  iB = B(i+8)
!   Números hexadecimales correspondientes a RGB
  call ToB(16,iR,colorHexa(1,i+8))
  call ToB(16,iG,colorHexa(2,i+8))
  call ToB(16,iB,colorHexa(3,i+8))
  if(i.EQ.8)tipo1 = 6
  call escritura(i,colorHexa(1:3,i+8),tipo1,tipo2,tipo3)
  tipo1 = 5

enddo
!
! Coeficientes para gradientes de colores intermedios:
aa(1,1) = 0D0;       bb(1,1) =-3.3528e-4; cc(1,1) = 3.1200e-1; dd(1,1) = 195.4 ! Claro 80%
aa(1,2) = 2.5651e-6; bb(1,2) =-1.7050e-3; cc(1,2) = 7.4328e-1; dd(1,2) = 132.5 ! Claro 60%
aa(1,3) =-3.8630e-6; bb(1,3) = 1.1441e-3; cc(1,3) = 5.7159e-1; dd(1,3) = 95.0 ! Claro 40%
aa(1,4) = 3.0641e-6; bb(1,4) =-1.0588e-4; cc(1,4) = 6.8830e-1; dd(1,4) = 0D0 ! Oscuro 25%
aa(1,5) = 2.1981e-6; bb(1,5) =-9.6452e-5; cc(1,5) = 4.5496E-1; dd(1,5) = 0D0 ! Oscuro 50%
!
! Coeficientes para gradientes de colores oscuros:
aa(2,1) = 0D0;       bb(2,1) = 0D0;       cc(2,1) = 0.42;      dd(2,1) = 213.5 ! Claro 90%
aa(2,2) = 0D0;       bb(2,2) = 0D0;       cc(2,2) = 1.09;      dd(2,2) = 150.0 ! Claro 75%
aa(2,3) = 0D0;       bb(2,3) = 0D0;       cc(2,3) = 2.17;      dd(2,3) = 46.77 ! Claro 50%
aa(2,4) = 0D0;       bb(2,4) = 0D0;       cc(2,4) = 2.09;      dd(2,4) = -1.24 ! Claro 25%
aa(2,5) = 0D0;       bb(2,5) = 0D0;       cc(2,5) = 1.44;      dd(2,5) = -1.17 ! Claro 10%
!
! Coeficientes para gradientes de colores claros:
aa(3,1) = 0D0;       bb(3,1) = 0D0;       cc(3,1) = 0.97;      dd(3,1) = -14.42 ! Oscuro 10%
aa(3,2) = 0D0;       bb(3,2) = 0D0;       cc(3,2) = 1.34;      dd(3,2) = -131.84 ! Oscuro 25%
aa(3,3) = 0D0;       bb(3,3) = 0D0;       cc(3,3) = 1.54;      dd(3,3) = -231.33 ! Oscuro 50%
aa(3,4) = 0D0;       bb(3,4) = 0D0;       cc(3,4) = 0.79;      dd(3,4) = -119.48 ! Oscuro 75%
aa(3,5) = 0D0;       bb(3,5) = 0D0;       cc(3,5) = 0.31;      dd(3,5) = -46.45 ! Oscuro 90%
!
! Gradientes.
tipo1 = 3
do j = 1,5

  tipo2 = j + 1
  do i = 1,8
!
!     Subíndice auxiliar
    k = (j+1)*8
!
!     Definición de gradiente a usar
    Vpromedio = int(float(R(i) + G(i) + B(i))/3.)
    tipo3 = 1
    if(Vpromedio.GT.204)tipo3 = 3
    if(Vpromedio.LT.51)tipo3 = 2
!
!     Polinomio para cada valor de cada gradiente:
    R(i+k) = aa(tipo3,j)*float(R(i))**3 + bb(tipo3,j)*float(R(i))**2 + cc(tipo3,j)*float(R(i)) + dd(tipo3,j)
    G(i+k) = aa(tipo3,j)*float(G(i))**3 + bb(tipo3,j)*float(G(i))**2 + cc(tipo3,j)*float(G(i)) + dd(tipo3,j)
    B(i+k) = aa(tipo3,j)*float(B(i))**3 + bb(tipo3,j)*float(B(i))**2 + cc(tipo3,j)*float(B(i)) + dd(tipo3,j)
!
!     Límites de valor
    if(R(i+k).GT.255)R(i+k) = 255
    if(G(i+k).GT.255)G(i+k) = 255
    if(B(i+k).GT.255)B(i+k) = 255
    if(R(i+k).LT.0)R(i+k) = 0
    if(G(i+k).LT.0)G(i+k) = 0
    if(B(i+k).LT.0)B(i+k) = 0
!
!     Asignación auxiliar
    iR = R(i+k)
    iG = G(i+k)
    iB = B(i+k)
!
!     Colores Énfasis...
    tipo1 = 3
    if(i.LT.3)then
!
!       "Fondo 2" y "Texto 2"
      tipo1 = i

    endif
!     Números hexadecimales correspondientes a RGB
    call ToB(16,iR,colorHexa(1,i+k))
    call ToB(16,iG,colorHexa(2,i+k))
    call ToB(16,iB,colorHexa(3,i+k))
    call escritura(i,colorHexa(1:3,i+k),tipo1,tipo2,tipo3)

  enddo
enddo
!
! Cierre del archivo XML
write(2,'("</ooo:color-table>")')
stop
!
! **************************************************************
!
! Errores **************************************************
!
! Ha habido un error en la lectura de los colores
100 write(*,'(//,"Error en la lectura de número de colores.",/,"La cantidad de colores debe ser un número entero.")')
101 write(*,'(//,"Error en la lectura de colores",/,"Los colores deben ingresarse en R,G,B;",/,&
&               "ya sea por pantalla o por archivo <entrada.txt>")')
end
!*******************************************************************************************************************
!
! Conversión decimal->hexadecimal, tomada de RosettaCode:
!
! http://rosettacode.org/wiki/Non-decimal_radices/Convert#Fortran
!
subroutine ToB(base, number,toBase)

CHARACTER(36) :: alphanum = "0123456789abcdefghijklmnopqrstuvwxyz"
CHARACTER(31) :: ToBase
INTEGER :: base, number, i, rem

ToBase = "                             00"
DO i = 31, 1, -1

  IF(number < base) THEN

    ToBase(i:i) = alphanum(number+1:number+1)
    EXIT

  END IF
  rem = MOD(number, base)
  ToBase(i:i) = alphanum(rem+1:rem+1)
  number = number / base

END DO
ToBase = ADJUSTL(ToBase)

ENDsubroutine ToB
!*******************************************************************************************************************
!
! Escritura
!
subroutine escritura(i,colorHexa,tipo1,tipo2,tipo3)

implicit none
integer tipo1,tipo2,i,j,tipo3
character*22 texto,head,tail
character*14 draw
character*2 colorHexa(3)

! Etiquetas en cada color
texto='<draw:color draw:name='
draw=' draw:color="#'
if(tipo2.EQ.1)then

  tail = '"'
!
! Color intermedio
elseif(tipo2.EQ.2.AND.tipo3.EQ.1)then

  tail = ', Claro 80%"'

elseif(tipo2.EQ.3.AND.tipo3.EQ.1)then

  tail = ', Claro 60%"'

elseif(tipo2.EQ.4.AND.tipo3.EQ.1)then

  tail = ', Claro 40%"'

elseif(tipo2.EQ.5.AND.tipo3.EQ.1)then

  tail = ', Oscuro 25%"'

elseif(tipo2.EQ.6.AND.tipo3.EQ.1)then

  tail = ', Oscuro 50%"'
!
!*********************************************************************
!
! Color oscuro
elseif(tipo2.EQ.2.AND.tipo3.EQ.2)then

  tail = ', Claro 90%"'

elseif(tipo2.EQ.3.AND.tipo3.EQ.2)then

  tail = ', Claro 75%"'

elseif(tipo2.EQ.4.AND.tipo3.EQ.2)then

  tail = ', Claro 50%"'

elseif(tipo2.EQ.5.AND.tipo3.EQ.2)then

  tail = ', Claro 25%"'

elseif(tipo2.EQ.6.AND.tipo3.EQ.2)then

  tail = ', Claro 10%"'
!
!*********************************************************************
!
! Color claro
elseif(tipo2.EQ.2.AND.tipo3.EQ.3)then

  tail = ', Oscuro 10%"'

elseif(tipo2.EQ.3.AND.tipo3.EQ.3)then

  tail = ', Oscuro 25%"'

elseif(tipo2.EQ.4.AND.tipo3.EQ.3)then

  tail = ', Oscuro 50%"'

elseif(tipo2.EQ.5.AND.tipo3.EQ.3)then

  tail = ', Oscuro 75%"'

elseif(tipo2.EQ.6.AND.tipo3.EQ.3)then

  tail = ', Oscuro 90%"'

endif
if(tipo1.EQ.1)then

  head = '"Fondo 2'

elseif(Tipo1.EQ.2)then

  head = '"Texto 2'

elseif(tipo1.EQ.3)then

!   head = '"Enfasis'
  write(head,'(A8,I2)')'"Enfasis',i-2

elseif(tipo1.EQ.4)then

  head = '"Blanco'

elseif(tipo1.EQ.5)then

  write(head,'(A4,I2)')'"Gris',i-1

elseif(tipo1.EQ.6)then

  head = '"Negro'

endif
!
! Escritura del color:
write(2,'(2X,A22,A10,A13,A14,3A2,A3)')texto,head,tail,draw,(colorHexa(j),j=1,3),'"/>'
!
return

endsubroutine

El siguiente script ayuda automatiza la creación de la paleta. Sólo se limita a leer primero el nombre de la paleta deseada y copiar el archivo SOC en la carpeta correspondiente. El mismo funciona sí y sólo sí el programa está copiado en una carpeta incluida en el $PATH

#!/bin/bash
#
# Script para crear nueva paleta y copiarla automáticamente en carpeta
# con las demás paletas.
#
# Ejecutando programa
paleta.x
#
# Copiando paleta en nuevo directorio
cp paleta.soc $(HOME)/.libreoffice/3/user/config/$1.soc
#
# Borrando archivo generado
rm paleta.soc
# Fin

Ejemplos de paletas
Voy a mostrar un par de ejemplos del resultado. Un posible uso de este programa es hacer una pequeña paleta con (algunos de) los colores que LibreOfffice usa para los gráficos:

Esta es una paleta alternativa a la que he llamado Neptuno. Muestro al mismo tiempo la misma creada en MS Office 2007, donde se ve que el resultado no es igual siendo la desviación más grande para colores claros/oscuros (50 < valor promedio < 205), siendo que sólo me limito a imitar el esquema.

Esta paleta que he llamado HP:

Y por último, la conocida paleta que viene por defecto en MS Office desde su versión 2007:


Compilando el programa
El programa es muy sencillo y se compila con GFortran u otro compilador Fortran 90 disponible. Si no tienen GFortran:

$ sudo aptitude install gfortran

ó

$ sudo apt-get install gfortran

si Aptitude les da inconvenientes.

Compilar el programa es tan solo

$ f95 paleta.f90 -o paleta

que les genera un ejecutable de nombre "paleta". Pueden cambiar el nombre del programa por el que más les guste. Un ejemplo de uso sería el siguiente:

$ paleta
Para ingreso de colores en pantalla, ingrese 5

Para ingreso por archivo de texto ingrese 0
5
0,69,134
255,66,14
255,211,32
87,157,28
126,0,33
131,202,255
49,64,4
75,31,111

el cual debería generar una paleta de nombre "paleta.soc" análoga a la primera imagen.


Trabajo a futuro

No tengo ni idea de cuál será mi disponibilidad de tiempo este año (de hecho, hice esto porque estoy de vacaciones) pero algunas idea incluyen:

  • Etiquetas más inteligentes para los colores: en lugar de llamarlos simplemente "Énfasis 1, 2, etc", llamarlos por su nombre: carmesí, lima, acero, etc. Una ayuda a esto está en Wikipedia
  • Interfaz de usuario. Quienquiera que quiera contribuir al respecto puede hacerlo
  • Extensión para LibO: es posible hacer todo directamente en java y en algún momento subirlo a la página de extensiones de LibreOffice.
  • Distribución de colores propia: en lugar de usar la de MS Office, usar una distribución de colores más acorde a la matriz de LibreOffice

Bueno, eso es todo al menos por ahora.

Un saludo