lunes, 15 de febrero de 2010

7.1. El ejemplo de Mike Terry.

Ha llegado el momento de hacer nuestro primer script-fu completo y la mejor manera de hacerlo es siguiento lo descrito aquí, que como verás pertenece al tutorial ya mencionado

Obtendremos el siguiente resultado:

ANEXO II: Plantilla para script-fu

; Plantilla para hacer script-fu
; Haz todos los cambios que creas necesarios antes de darla por buena
; sobre todo el directorio de ubicación, en la última línea
;
; Guardar con extención distinta a .scm en el directorio
; que nos parezca conveniente. Yo lo guardo en:
; /home/tu-carpeta-usuario/.gimp-2.6/scripts
;
; Cuando lo necesites, abrir con gedit, p.e.
; añadir y quitar lo necesario
; NO olvidar cambiar el nombre del script-fu
;
; Completado el script-fu, guardar con extensión .scm
(script-fu-register "script-fu-mi-plantilla"  ;OJO nombre del script-fu
      "Mi Plantilla"   ;texto que aparecerá en el menú
      "Plantilla con todo lo imprescindible" 
      "Andres" 
      "emi.script@gmail.com" 
      "2010-03-08" 
      "RGB* GRAY*"                 ; tipos de imagen aceptadas
      SF-IMAGE "Input Image" 0                ; PONER PARÁMETROS 
      SF-DRAWABLE "Input Drawable" 0        ; segundo parámetro
      SF-COLOR "Rectangle Color" '(10 80 256)   ; tercer parámetro
) 


(define (script-fu-mi-plantilla inImg inDrawable color) 

; guardamos el contexto de trabajo
      (gimp-context-push)   


;iniciamos el grupo para una solo acción deshacer
    (gimp-image-undo-group-start inImg)  

; Definimos nuestras funciones locales  PUEDE SOBRAR TODA LA FUNCIÓN
          
    (define (funcionInterna1 param1 para2) 
            (let* 
               ( 
                 ( ) 
        ) 
            ) 
    )

;A continuación irían todas las demás funciones. 

;Vamos a comenzar el cuerpo principal de nuestro script-fu y lo haremos declarando
;las variables

    (let* 
            (  
               (variable1)  ; PERSONALIZAR TODA LA DECLARACIÓN DE VARIABLES
        (variable2  ( car  (gimp-drawable-height inDrawable))) 
        (variable3     ( car  (gimp-drawable-offsets inDrawable))) 
        (variable2     ( cadr (gimp-drawable-offsets inDrawable))) 
            
        ) ; cierra  declaración de variables * ( 


;A continuación pondríamos todas las sentencias necesarias CAMBIAR POR LA PROPIAS

        (gimp-rect-select inImg 
           (+ x0 (* width 0.25)) 
           (+ y0 (* height 0.25)) 
           (* width 0.5) 
           (* height 0.5) 
           CHANNEL-OP-REPLACE 
           0 0) 
       (gimp-context-set-foreground color) 
       (gimp-edit-fill inDrawable FOREGROUND-FILL) 

       


    )  ; Cierrra (let* 

;Aqui pueden ir sentencias que no necesitan las variables locales


;recuperamos el contexto de trabajo
    (gimp-context-pop) 

;cerramos  la lista de sentencias de la acción deshacer
    (gimp-image-undo-group-end inImg) 

;vaciamos todos los procesos internos del script 
    (gimp-displays-flush) 
 
)  ; Fin Define 


(script-fu-menu-register "script-fu-mi-plantilla"    ;OJO con el nombre
                         "<imgen>/Script-Fu/MisScript")

domingo, 14 de febrero de 2010

8. Plantilla para escribir script-fu

Vamos a ver dos plantillas, la propuesta por Simon Budig y la que yo utilizo, que será la que explicaré con más detalle, ayudando a comprender la anterior, ya que fue en la que yo me basé.

8.1 La plantilla de Simon Budig
Simon Buding es el autor del tutorial Script-Fu and plug-ins for The GIMP
Su plantilla, en la que yo me he basado como ya he apuntado, la encontraréis aquí, con completas explicaciones en inglés.

8.2 Mi plantilla
Iremos viendo el código, sentencia a sentencia, con pequeñas explicaciones cuando sea necesario, y pondré todo el código junto en un anexo:

Comenzamos con la función script-fu-register. Como ya comenté, cuando empiezo a escribir un nuevo script-fu prefiero que esta función esté al principio, seguida de la función define, y así me aseguro de que ambas sentencias tienen los mismos parámetros y que tipo es cada uno de ellos.
Esta función tiene, como ya hemos visto, contiene el nombre, texto del menú, etc. y los parametros de entrada y su tipo

(script-fu-register "script-fu-miPlantilla"      ;nombre del script-fu
                   "Rectangle..."                            ;texto que aparecerá en el menú
                   "Pinta un circulo"                        ;explicacion de lo que hace
                    "Mi nombre "
                    "Mi direccion de correos"
                    "2009-01-08"
                    "RGB* GRAY*"                             ;tipos de imagen aceptadas
                    SF-IMAGE "Input Image" 0                 ;  primer parámetro
                    SF-DRAWABLE "Input Drawable" 0           ; segundo parámetro
                    SF-COLOR "Rectangle Color" '(10 80 256)    ; tercer parámetro


)

A continuación la sentencia que inicia verdaderamente el script-fu propiamente dicho



(define (script-fu-template inImg inDrawable color) 

Durante la ejecución de los script-fu a veces se cambian los colores de fondo, fuentes, etc, cambiando el contexto de trabajo, que si nos acordamos de restaurar antes de salir puede que nos lleve a alguna equivocación, a veces sin darnos cuenta de que esta ha ocurrido. Es conviente guardar antes de empezar todos los dtos del contexo de trabajo previo, para recuperarlo antes de salir . Esta sentencia y la siguiente prefiero ponerlas al principio para evitarme tener que analizar, caso de ponerlas más atrás, si me dejo alguna sentencia importante fuera. Esta sentencia tiene que ser cerrada al final. (1)

            (gimp-context-push) 



Sin le decimos lo contrario, Gimp apunta cada una de las acciones que realiza el script-fu en la lista de acciones a deshacer. Si no indicáramos a Gimp que agrupe todo el script-fu en una sola anotación en la lista de deshacer, si después de ejecutar un script quisiérmos deshacerlo tendríamos que ir acción a acción, ya que no sabríamos donde empezo la anotación del script-fu, con el riesgo probable de dejar alguna del script-fu o borrar alguna de las anteriores.
Con la siguiene sentencia Gimp inicia el registro de las acciones que agrupará en una sola acción para deshacer. Durante la depuración del script viene muy bien desactivar, comentando, esta sentencia y su cierre.Esta sentencia tiene que ser cerrada al final. (2)

            (gimp-image-undo-group-start inImg) 

Habíamos dicho que los script-fu pueden declarar, para luego ser usadas, funciones locales. Aquí es donde coloco las funciones internas del script-fu

            (define (funcionInterna1 param1 para2)
                   (let*
                         (
                               ( )
                         )
                   )
              )

A continuación irían todas las demás funciones.

Vamos a comenzar el cuerpo principal de nuestro script-fu y lo haremos declarando las variables

             (let*
                    (  
                          (variable1)   ; sin inicializar
                          (variable2  ( car  (gimp-drawable-height inDrawable)))
                          (variable3     ( car  (gimp-drawable-offsets inDrawable)))
                          (variable2     ( cadr (gimp-drawable-offsets inDrawable)))
                            …...........  ;también pueden ir sentencias
                    ) ; cierra  declaración de variables * ( 


A continuación pondríamos todas las sentencias necesarias para lleva a cabo las acciones de nuestro script-fu. Por ejemplo

(gimp-rect-select inImg
(+ x0 (* width 0.25))
(+ y0 (* height 0.25))
(* width 0.5)
(* height 0.5)
CHANNEL-OP-REPLACE
0 0
)   :terminan los parámetros de la función
(gimp-context-set-foreground color)
(gimp-edit-fill inDrawable FOREGROUND-FILL)                
                   (set!(variable1 125))
…...........
)  ; Cierrra (let* 



El paréntesis que cierra la sentencia (let* cierra el espacio en que son válidas la variables locales definidas por esta. Quiere decir esto que fuera no pueden ir sentencias que utilicen las variables definidas por dicha sentencia. Si pueden ir sentencias que no las utilicen como vemos.

Finalizado ya el trabajo del script-fu, recuperamos el contexto de trabajo, cerrando la sentencia (1) anteriror.


 (gimp-context-pop) 



Igualmente, cerramos la lista de sentencias que vamos a incluir dentro de una sola acción deshacer, cerrando la sentencia (2) anterior.

(gimp-image-undo-group-end inImg)




Así mismo, antes de finalizar el script-fu, vaciamos todos los procesos internos del script

(gimp-displays-flush)



)  ; Fin Define 

Por último, vamos a registrar nuestro script-fu en el menú de Gimp.


          (script-fu-menu-register "script-fu-mi-plantilla" 
 "<Image>/Script-Fu/ACP")


7.4. Guardar y ejecutar el script-fu

Hasta ahora, hemos trabajado en la consola de Script-Fu. Ahora, sin embargo, vamos a cambiar para editar códigos de archivos de texto.
Para ejecutar este script,
  1. Hay que pensar que ruta ponemos en el script. A mi me gusta crear una opción de menú nueva donde incluyo todos los script personales. Si en la ruta ponemos, p.e., "/Script-Fu/Mis script/Demo Box...", se creará una opción en el menú principal llamada Script-Fu, con una opción llamda Mis Script, donde se encontrarán todos los script que yo prepare.
  2. Crear un archivo de texto copiando el texto en un archivo con extensión .scm.
  3. Copiar el archivo en la carpeta /home/tu-carpeta-usuario/.gimp-2.6/scripts. Me gusta incluirlos aquí para diferenciarlos de los que incluye Gimp en su instalación.
  4. A continuación, necesitamos que Gimp nos muestre el nuevo Script-fu en su menús, para lo cual es necesario refrescar los script, lo cual se logra al ejecutar la opción del menú Filtros → Scrip-Fu → Refrescar script (Cuando se trabaja con la programación de script esta opción es conveniente asociarla a una combinación de teclas en Gimp, lo que se realiza en la opción del menú : Edición-> Configurar las combinaciones de teclas... Lo que buscamos está en Complementos, en mi versión, casi al final
  5. Finalmente, si abre el examinador de procedimientos Filtros → Script-Fu → Consola → Examinar, notará que nuestro script aparece en la base de datos.

Prueba a grabar los dos ejemplos vistos anteriormente, y ejecútalos desde el menú correspondiente.
  • my-demo-box (copiando en un archivo de texto el código que tienes en el punto 7.3.1)
  • test-sphere (Puedes descargarlo de aquí)

Ahora estamos en disposición de comprender como se escribe un script-fu completo, pero antes vamos a preparar nuestra plantilla, en el punto 8., que nos facilitará la escritura de sucesivos script-fu.

7.3.1. Ejemplos

Ejemplo 1
El siguiente código crea una ventana con algunos de los posibles tipos de datos de entrada:
    (define (my-demo-box value adj1 adj2 image drawable toggle pattern string font color option gradient)
(print "Do nothing"))

(script-fu-register "my-demo-box"
"/Xtns/Script-Fu/My Stuff/Demo Box..."
"Do nothing"
"Joe User"
"Joe User"
"August 2000"
""
SF-ADJUSTMENT "SF-ADJUSTMENT (slider)" '( 30 1 2000 1 10 1 0)
SF-ADJUSTMENT "SF-ADJUSTMENT" '(400 1 2000 1 10 1 1)
SF-COLOR "SF-COLOR" '(255 0 255)
SF-DRAWABLE "SF-DRAWABLE" 0
SF-FONT "SF-FONT" ""
SF-GRADIENT "SF-GRADIENT" "Golden"
SF-IMAGE "SF-IMAGE" 0
SF-OPTION "SF-OPTION" '("Option 1" "Option 2" "Option 3")
SF-PATTERN "SF-PATTERN" "Wood"
SF-STRING "SF-STRING" "Test String"
SF-TOGGLE "SF-TOGGLE" TRUE
SF-VALUE "SF-VALUE" "0"
SF-FILENAME "SF-FILENAME" "/")

El resultado es el siguiente:



Ejemplo 2

El código del archivo test-sphere.scm muestra diversos tipos de parámetros, como vemos en la sentencia script-fu-register y en al imagen
    (script-fu-register "script-fu-test-sphere"
_"_Sphere..."
"Simple script to test and show the usage of the new Script-Fu API extensions."
"Spencer Kimball, Sven Neumann"
"Spencer Kimball"
"1996, 1998"
""
SF-ADJUSTMENT "Radius (in pixels)" '(100 1 5000 1 10 0 0)
SF-ADJUSTMENT "Lighting (degrees)" '(45 0 360 1 10 1 1)
SF-TOGGLE "Shadow" TRUE
SF-COLOR "Background color" "white"
SF-COLOR "Sphere color" "red"
SF-BRUSH "Brush" '("Circle (03)" 1.0 44 0)
SF-STRING "Text" "Tiny-Fu rocks!"
SF-TEXT "Multi-line text" "Hello,\nWorld!"
SF-PATTERN "Pattern" "Maple Leaves"
SF-GRADIENT "Gradient" "Deep Sea"
SF-TOGGLE "Gradient reverse" FALSE
SF-FONT "Font" "Agate"
SF-ADJUSTMENT "Font size (pixels)" '(50 1 1000 1 10 0 1)
SF-PALETTE "Palette" "Default"
SF-FILENAME "Environment map"
(string-append gimp-data-directory
"/scripts/images/beavis.jpg")
SF-OPTION "Orientation" '("Horizontal"
"Vertical")
SF-ENUM "Interpolation" '("InterpolationType" "linear")
SF-DIRNAME "Output directory" "/var/tmp/"
SF-IMAGE "Image" -1
SF-LAYER "Layer" -1
SF-CHANNEL "Channel" -1
SF-DRAWABLE "Drawable" -1
SF-VECTORS "Vectors" -1
)

(script-fu-menu-register "script-fu-test-sphere"
"/Xtns/Languages/Script-Fu/Test")

El código completo del script-fu pude bajarse de aquí

7.3. Tipos de parámetros de entrada

Necesitamos listar los parámetros que corresponden a los valores de entrada que nuestro script necesita. Cuando listamos estos parámetros, les damos indicación de como son. También podemos proporcionar valores predefinidos.
A continuación el listado, ordenado, salvo los dos primeros, por orden alfabético:
Tipo de parámetro
Descripción
SF-IMAGE
Si su script opera en una imagen nueva, esta debería ser el primer parámetro después de los parámetros requeridos. GIMP pasará una referencia a la imagen en este parámetro.
SF-DRAWABLE
Si su script opera sobre una imagen abierta, este sería el segundo parámetro después del parámetro SF-IMAGE. Se refiere a la capa activa. GIMP pasará una referencia a la capa activa en este parámetro
SF-ADJUSTMENT
Is only useful in interactive mode, if you call a script from the console, it acts just like a normal SF-VALUE
In interactive mode it creates an adjustment widget in the dialog.

Usage:
SF-ADJUSTMENT "label" '(value lower upper step_inc page_inc digits type)

Widget arguments list

Element
Descripción
"label" Text printed before the widget.
value Value print at the start.
lower / upper
The lower / upper values (range of choice).
step_inc Increment/decrement value.
page_inc Increment/decrement value using page key.
digits Digits after the point (decimal part).
type One of: SF-SLIDER or 0, SF-SPINNER or 1

SF-BRUSH
is only useful in interactive mode. It will create a widget in the control dialog. The widget consists of a preview area (which when pressed will produce a popup preview ) and a button with the "..." label. The button will popup a dialog where brushes can be selected and each of the characteristics of the brush can be modified.

The actual value returned when the script is invoked is a list consisting of Brush name, opacity, spacing and brush mode in the same units as passed in as the default value.

Usage:
SF-BRUSH "Brush" '("Circle (03)" 100 44 0)

Here the brush dialog will be popped up with a default brush of Circle (03) opacity 100 spacing 44 and paint mode of Normal (value 0).
If this selection was unchanged the value passed to the function as a parameter would be '("Circle (03)" 100 44 0).
SF-COLOR
creates a color button in the dialog. It accepts either a list of three values for the red, green and blue components or a color name in CSS notatation

SF-COLOR "label" '(red green blue)
or
SF-COLOR "label" "color"
Widget arguments list

Element Descripción
"label" Text printed before the widget.
'(red green blue) List of three values for the red, green and blue components.
"color" Color name in CSS notatation.
SF-DIRNAME
Only useful in interactive mode. Very similar to SF-FILENAME, but the created widget allows to choose a directory instead of a file.

Usage:
SF-DIRNAME "Image Directory" "/var/tmp/images"

The value returned when the script is invoked is a string containing the dirname.
SF-ENUM
Only useful in interactive mode. It will create a widget in the control dialog. The widget is a combo-box showing all enum values for the given enum type. This has to be the name of a registered enum, without the "Gimp" prefix. The second parameter speficies the default value, using the enum value's nick.

Usage:
SF-ENUM "Interpolation" '("InterpolationType" "linear")

The value returned when the script is invoked corresponds to chosen enum value.
SF-FILENAME
Only useful in interactive mode. It will create a widget in the control dialog. The widget consists of a button containing the name of a file.
If the button is pressed a file selection dialog will popup.

Usage:
SF-FILENAME "Environment Map"
(string-append "" gimp-data-directory "/scripts/beavis.jpg")

The value returned when the script is invoked is a string containing the filename.
SF-FONT
creates a font-selection widget in the dialog. It returns a fontname as a string. There are two new gimp-text procedures to ease the use of this return parameter:

(gimp-text-fontname image drawable
x-pos y-pos text border antialias size unit font)
(gimp-text-get-extents-fontname text size unit font))

where font is the fontname you get. The size specified in the fontname is silently ignored. It is only used in the font-selector. So you are asked to set it to a useful value (24 pixels is a good choice) when using SF-FONT.

Usage:
SF-FONT "label" "fontname"

Widget arguments list

Element Descripción
"label" Text printed before the widget.
"fontname" Name of the default font.

SF-GRADIENT
Only useful in interactive mode. It will create a widget in the control dialog. The widget consists of a button containing a preview of the selected gradient. If the button is pressed a gradient selection dialog will popup.

Usage:
SF-GRADIENT "Gradient" "Deep Sea"

The value returned when the script is invoked is a string containing the gradient name. If the above selection was not altered the string would contain "Deep Sea"
SF-OPTION
Only useful in interactive mode. It will create a widget in the control dialog. The widget is a combo-box showing the options that are passed as a list. The first option is the default choice.

Usage:
SF-OPTION "Orientation" '("Horizontal" "Vertical")

The value returned when the script is invoked is the number of the chosen option, where the option first is counted as 0.
SF-PALETTE
Only useful in interactive mode. It will create a widget in the control dialog. The widget consists of a button containing a preview of the selected palette. If the button is pressed a palette selection dialog will popup.

Usage:
SF-PALETTE "Palette" "Named Colors"

The value returned when the script is invoked is a string containing the palette name. If the above selection was not altered the string would contain "Named Colors"
SF-PATTERN
Only useful in interactive mode. It will create a widget in the control dialog. The widget consists of a preview area (which when pressed will produce a popup preview ) and a button with the "..." label. The button will popup a dialog where patterns can be selected.

Usage:
SF-PATTERN "Pattern" "Maple Leaves"

The value returned when the script is invoked is a string containing the pattern name. If the above selection was not altered the string would contain "Maple Leaves"
SF-STRING Acepta cadenas “Un texto"
SF-TOGGLE Se muestra una caja, para obtener un valor Booleano. TRUE o FALSE
SF-VALUE
Acepta números y cadenas. Notese que las cuotas deben eludir el texto predefinido, mejor usar SF-STRING.