3 de marzo de 2019

GIMP: Trabajando con Python en GIMP

Vamos a trabajar con python desde gimp, para esto vamos a abrir algun archivo XCF con imagenes. Luego abrir la consola en el menu Filtros --> Python Fu, como se ve a continuación:

Obtener la lista de Archivos Abiertos en GIMP:

  • Esta comando entrega una lista con todos los archivos (que se muestran en pestañas) abiertos en la pantalla de GIMP. El primer archivo en la lista corresponde al ultimo archivo abierto.
>>> gimp.image_list()
[<gimp.Image 'Los Grandes Rios.xcf'>, <gimp.Image 'Epoca Clasica.xcf'>, <gimp.Image 'Caratula.xcf'>, <gimp.Image 'Dibujo Para Editar.xcf'>]
>>> gimp.image_list()[0]
<gimp.Image 'Los Grandes Rios.xcf'>

Y podemos guardarlo en una variable:
>>> ListaDeArchivosAbiertos = gimp.image_list()
>>> PrimerArchivo = ListaDeArchivosAbiertos[0]

Obtener la lista de Capas de un archivo XCF de GIMP: 

>>> PrimerArchivo = gimp.image_list()[0]
>>> PrimerArchivo.layers
[<gimp.Layer 'Capa pegada'>, <gimp.Layer 'imagen01'>, <gimp.Layer 'fondo blanco'>]

Modificar una Capa (Layer): 

Vamos a trabajar con 'image01', entonces hacemos:
>>> layer1 = PrimerArchivo.layers[1]
Con dir() podemos ver todos los métodos y propiedades que tiene layers
>>> dir(layer1)
['ID', '__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'add_alpha', 'add_mask', 'apply_mask', 'attach_new_parasite', 'bpp', 'children', 'copy', 'create_mask', 'edit_mask', 'fill', 'flush', 'free_shadow', 'from_id', 'get_pixel', 'get_pixel_rgn', 'get_tile', 'get_tile2', 'has_alpha', 'height', 'image', 'is_floating_sel', 'is_gray', 'is_grey', 'is_indexed', 'is_layer_mask', 'is_rgb', 'linked', 'lock_alpha', 'mask', 'mask_bounds', 'mask_intersect', 'merge_shadow', 'mode', 'name', 'offset', 'offsets', 'opacity', 'parasite_attach', 'parasite_detach', 'parasite_find', 'parasite_list', 'parent', 'preserve_trans', 'remove_mask', 'resize', 'resize_to_image_size', 'scale', 'set_offsets', 'set_pixel', 'show_mask', 'tattoo', 'transform_2d', 'transform_2d_default', 'transform_flip', 'transform_flip_default', 'transform_flip_simple', 'transform_matrix', 'transform_matrix_default', 'transform_perspective', 'transform_perspective_default', 'transform_rotate', 'transform_rotate_default', 'transform_rotate_simple', 'transform_scale', 'transform_scale_default', 'transform_shear', 'transform_shear_default', 'translate', 'type', 'type_with_alpha', 'update', 'visible', 'width']
>>> layer1.width
1111
Para modificar el ancho y alto de la capa y colocarlo a la misma que la imagen:
>>> layer1.resize_to_image_size()
y para todas las capas seria:
>>> for n in range(len(PrimerArchivo.layers)):
...     PrimerArchivo.layers[n].resize_to_image_size()

Canal Alpha o Canal de Transparencia: 

Vamos a trabajar con el canal alpha de una Capa (Layer), de tal forma que dejamos intactos las otras capas:
Verificar si la Capa ya tiene un canal Alpha:
  • >>> layer1.has_alpha
  • False
Como no tiene un canal Alpha. Vamos a agregarle un canal Alpha:
  • >>> layer1.add_alpha()
ya esta agregado el canal de transparencia, si recortas una porción de la imagen, vas ha ver la transparencia que queda.
Vamos a borrar el canal Alpha y veamos que sucede:
  • >>> pdb.gimp_layer_flatten(layer1)
El canal Alpha o de Transparencia se ha eliminado, solo de la capa l1 y las zonas transparentes se han coloreado de blanco, del color de fondo (background). Si cambias el color de fondo y eliminas la capa de transparencia, las zonas transparentes se colorearan de este nuevo color. Y para eliminar o borrar el canal Alpha de todas las capas y para que la imagen final de la capa sea del mismo tamaño del lienzo principal, seria:
>>> for n in range(len(PrimerArchivo.layers)):
...     PrimerArchivo.layers[n].resize_to_image_size()
...     pdb.gimp_layer_flatten(PrimerArchivo.layers[n])

Aplanar toda la Imagen: 

Todas las capas visibles son combinadas en una sola, todas las demás capas se borran, también se borra el canal alfa (canal de transparencia), al final solo queda la capa combinada.
>>> pdb.gimp_image_flatten(PrimerArchivo)
<gimp.Layer '3'>
También se puede utilizar:
>>> PrimerArchivo.flatten()
<gimp.Layer '3'>

Crear una Selección Poligonal en la Imagen:

Para crear una selección en la imagen con forma de polígono se usa:

  • pdb.gimp_image_select_polygon (ImagenOperación, CantidadPuntos, ListaPuntos)

Donde:
Imagen: Es el ID de la Imagen. En nuestro ejemplo PrimerArchivo
Operación: El contenido de la región poligonal se puede agregar, sustraer o reemplazar a la máscara de la selección anterior. Las operaciones son:
         GIMP_CHANNEL_OP_ADD, Añadir a la selección actual.
         GIMP_CHANNEL_OP_SUBTRACT, Restar de la selección actual
         GIMP_CHANNEL_OP_REPLACE, Reemplazar la selección actual
         GIMP_CHANNEL_OP_INTERSECT, Intersección con la selección actual.


CantidadPuntos: Es un numero que indica cuantos puntos van ha formar el polígono, no son pares ordenados, son puntos individuales.
ListaPuntos: Es la lista de puntos [x1, y1, x2, y2, ... xn, yn], que indica las coordenadas que forman el polígono.
>>> ListaPuntos = [200, 300, 260, 250, 320, 300, 280, 350, 240, 350]
>>> pdb.gimp_image_select_polygon(PrimerArchivo, CHANNEL_OP_REPLACE, len(ListaPuntos), ListaPuntos)


1 de marzo de 2019

PYTHON: Funciones Útiles de Python


Leer el Código Numérico Completo de cualquier Tecla

Para leer una tecla presionada de forma inmediata, hay que hacer un muestreo en bucle abierto, permanente y activamente sobre el estado del dispositivo de entrada stdin (select, timeout=0). Tan pronto como se detecte que hay un carácter en stdin (select ⇄ rlist ⇄ stdin) hay que leerlos (os.read ← sys.stdin.fileno) todos (while → if → select), hasta detectar que no hay ninguno (elif → break). Hay que anotar que este código solo funciona en Linux.
  • El método fileno() devuelve el descriptor de un archivo (un numero entero), en este caso el descriptor de stdin, para solicitar operaciones de E/S del sistema operativo. En cualquier otro caso generará un error.
  • select.select( rlist , wlist , xlist [ , timeout ] ) 
  • select se utiliza para hacer una llamada múltiple de E/S, Con esta llamada podemos saber si un dispositivo E/S esta listo para una lectura o escritura. Aquí hay que diferenciar dos situaciones de este proceso, (1) El Estado Actual de los dispositivos E/S y (2) Estar listos para una lectura o escritura del dispositivo E/S. Sus parámetros son:
    • rlist es la lista de dispositivos a los cuales se hace un llamada de entrada. Con esta llamada podemos saber si el dispositivo esta listo para leer lo que contiene su buffer. Si el dispositivo es stdin, indica que hay un carácter en el buffer esperando su lectura.
    • wlist es la lista de dispositivos a los cuales se hace un llamada de salida. Con esta llamada podemos saber si el dispositivo esta lista para poder rescribir en ella.
    • xlist es la lista de dispositivos que esperan una "condición excepcional"
    • timeout es el tiempo de espera. Si timeout > 0.0, esperar timeout hasta obtener el resultado de la llamada, este resultado debe ser (2): ' Estar listos para una lectura o escritura'. Si timeout expira, salir inmediatamente y solo devuelve (1): 'El estado actual'.
    • Si timeout = 0.0, salir inmediatamente sin esperar que el resultado de la llamada sea (2), es decir que devuelva inmediatamente lo que encuentre, aquí (1) y (2) son lo mismo.
  • keycode almacena el numero de la tecla como '05A42634'h, si la tecla tiene mas de un número, será: keycode = N3 * 2¹⁶ + N2 * 2⁸ + N1.
def GetKeyBoard(): keycode = 0 DefaultConfig = termios.tcgetattr(sys.stdin) try: tty.setcbreak(sys.stdin.fileno()) while True: if select.select([sys.stdin, ], [], [], 0.0)[0]: #keycode <<= 8 #keycode |= ord(os.read(sys.stdin.fileno(), 1)) keycode = (keycode << 8) | ord(os.read(sys.stdin.fileno(), 1)) elif keycode != 0: break finally: termios.tcsetattr(sys.stdin, termios.TCSADRAIN, DefaultConfig) return(keycode)



Sumar un Numero Entero de Meses a una Fecha Especifica

          Estaba buscando una función que sume una cantidad 'n' de meses a una fecha. Como no quería reinventar la pólvora me puse a buscar un buen código de python por Internet, ¡busqué!... y ¡busqué! pero no lo encontré, o al menos un código que satisfaga mis expectativas: sencillez y rapidez. Bueno tampoco hice una búsqueda muy exhaustiva, seguro que hay buen código desarrollado por ahí, pero ya no quise buscar mas, así que hice mi propia función. Abrí una pagina de Libreoffice Calc y escribí todas las combinaciones resultantes de sumar 'Meses' a una fecha y fui encontrando las ecuaciones para generar estos resultados, una vez que verifique que funcionaban para todos los casos, lo simplifiqué y lo reescribí en código python y bueno aquí esta. Por cualquier caso, todos estos código están con licencia GPL V3.0.  (https://www.gnu.org/licenses/gpl-3.0.en.html)

def AgregarMes(FechaIni, Meses): NuevoYear = FechaIni.year + int((FechaIni.month + Meses - 1)/12) NuevoMes = (FechaIni.month + Meses) % 12 return(datetime.date(NuevoYear, NuevoMes if NuevoMes != 0 else 12, FechaIni.day))

GIMP: Trabajando con Python en GIMP

Vamos a trabajar con python desde gimp, para esto vamos a abrir algun archivo XCF con imagenes. Luego abrir la consola en el menu Filtros -...