Importar SVG
Editar los dibujos de las animaciones previamente en un editor de vectores suele ser una muy buena idea, por que no perdemos resolución y con editores como Inkscape este trabajo resulta mucho más practico que hacerlo directamente en Synfig Studio.
Extensión para Inkscape
La Extensión de Inkscape que convierte SVG en Synfig Studio (.sif) es la herramienta más recomendada para este trabajo.
Desde la versión de Ikscape 0.91 la extensión vienen en la versión oficial de Inkscape "<Archivo> → <Salvar Como> → Animation synfig (.sif)". Esta es la mejor opción por que Inkscape exporta pero no abre archivos .sif.
Sí deseas instalarla manualmente puedes buscarla en sección de descargas de Herramientas y Script
Svgtosif
Esta es un programa en C realizado por akagogo que utiliza libxml para convertir SVG al formato de Synfig.
Descargar del Sitio web o el wiki File:Svgtosif.zip
Instalación
En GNU/Linux:
wget http://none.carlos.googlepages.com/svgtosif.zip unzip svgtosif.zip cd svgtosif ./autogen.sh ./configure make && sudo make install
En nuevas versiones de gcc puede falla la compilación esto se arregla con:
gcc svgtosif-list.o svgtosif-reader1.o svgtosif-strext.o `xml2-config --cflags` -g -O2 -lm `xml2-config --libs` -o svgtosif
Utilización
Los archivos SVG deben estar en una carpeta llamada data. Debe ejecutar el comando desde el directorio padre, pero usando el nombre del archivo como argumento del comando. Así, si:
- Tiene crear una carpeta llamada "data" y colocar allí el archivo "file.svg".
- Ahora ejecute svgtosif file.svg
Más practico
Como puede ver, esto no es realmente muy amigable. Para solucionar rápidamente el problema, utilice el siguiente script de bash:
#!/bin/bash mkdir data cp "$1" data/ /usr/local/bin/svgtosif "$1" mv "data/${1%%.*}.sif" . rm -r data echo "Conversion complete!"
Ponga estas líneas en un archivo llamado "svg2sif" (llámele como prefiera, pero evite llamarle "svgtosif") y guárdelo en un directorio PATH (se sugiere /usr/bin). Entonces:
chmod +x /usr/bin/svg2sif
Eso es todo. Ahora utilice:
svg2sif <file.svg>
y obtendrá un archivo .sif en la misma carpeta en que esté trabajando.
Saxon
Esta opción utiliza una hoja de estilo XSLT 2.0 para transformar el XML de SVG a XML de Synfig.
Objetivo
Convertir una imagen SVG en un archivo Synfig para importarlo. Publicado por primera vez en el foro: http://synfig.org/forums/viewtopic.php?t=30
Prerrequisitos
- Asegúrese de tener instalado un entorno de ejecución Java (JRE).
- Obtenga una versión reciente del procesador de XSLT SAXON para Java de http://saxon.sourceforge.net/. Versión recomendada: Saxon-SA 9.0 (saxonsa9-0-0-2j.zip).
- Extraiga el paquete SAXON a una carpeta de su elección, la carpeta contendrá varios archivos JAR.
- Copiar el archivo #svg2synfig.xsl en el mismo directorio de SAXON
Línea de comandos
- Entrar al directorio SAXON.
- Introduzca el siguiente comando (sustituya your_input.svg por la ruta a su archivo SVG):
java -jar saxon9.jar -xsl:svg2synfig.xsl your_input.svg > synfig.sif
Archivo de proceso por lotes de Windows
Si no desea utilizar la línea de comandos, cree un archivo de procesamiento por lotes svg2synfig.bat, en el mismo directorio de SAXON, con este contenido:
@java -jar %0\..\saxon9.jar -xsl:%0\..\svg2synfig.xsl %1 > %0\..\synfig.sif @pause
Simplemente suelte el archivo SVG sobre svg2synfig.bat.
Resultado
Si la conversión ha tenido éxito, el resultado se escribirá en el archivo synfig.sif, en la misma carpeta. Puede abrir este archivo en Synfig.
Limitaciones
- No parece funcionar con ls nuevas versiones de Saxon
- Los SVG comprimidos (svgz) deben ser descomprimidos primero.
- Únicamente los trayectos de objetos SVG están soportados. Intente convertir todos los objetos a trayectos.
- Sólo un subconjunto de elementos de trayecto está soportado. Intente modificar todos los nodos de trayecto de forma que tengan tangentes divididas, y todos los segmentos de trayecto sean curvas.
- El coloreado sofisticado (gradientes, por ejemplo) no está soportado.
- Sólo las transformaciones básicas están soportadas.
- Relleno y contorno en el mismo objeto no está soportado.
svg2synfig.xsl
<xsl:stylesheet version="2.0" exclude-result-prefixes="#all" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:math="http://exslt.org/math"> <xsl:output method="xml" indent="yes" encoding="UTF-8"/> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="svg:svg"> <xsl:variable name="width" select="math:units_to_px(@width)"/> <xsl:variable name="height" select="math:units_to_px(@height)"/> <xsl:variable name="has_view_box" select="matches(@viewBox, '(\d+\s){3}\d+')"/> <canvas version="0.2" id="{@id}" width="{if ($has_view_box) then replace(@viewBox, '(\d+)\s(\d+)\s(\d+)\s(\d+)', '$3') else $width}" height="{if ($has_view_box) then replace(@viewBox, '(\d+)\s(\d+)\s(\d+)\s(\d+)', '$4') else $height}" view-box="{if ($has_view_box) then @viewBox else concat('0 0 ', $width, ' ', $height)}"> <xsl:apply-templates select="svg:g|svg:svg|svg:path"/> </canvas> </xsl:template> <xsl:template match="svg:g"> <layer type="PasteCanvas" active="true" version="0.1" desc="{@id}"> <param name="canvas"> <canvas> <xsl:apply-templates/> </canvas> </param> </layer> </xsl:template> <xsl:template match="svg:path"> <xsl:variable name="style"> <xsl:for-each select="ancestor-or-self::*"> <xsl:sort select="position()" data-type="number" order="descending"/> <xsl:value-of select="concat(@style, ';fill:', @fill, ';stroke:', @stroke, ';stroke-width:', @stroke-width, ';')"/> </xsl:for-each> </xsl:variable> <xsl:variable name="self" select="."/> <xsl:variable name="is_fill" select="not(matches(replace($style, 'fill:[^n;][^o].*', ''), 'fill:none'))"/> <xsl:analyze-string select="@d" regex="m[^z]+(z|$)" flags="i"> <xsl:matching-substring> <layer type="{if ($is_fill) then 'region' else 'outline'}" version="0.1" desc="{$self/@id}"> <xsl:call-template name="style-to-color"> <xsl:with-param name="style" select="replace(replace($style, ':none.*', ''), if ($is_fill) then '.*fill:([^;]+).*' else '.*stroke:([^;]+).*', '$1')"/> </xsl:call-template> <xsl:if test="not ($is_fill)"> <xsl:call-template name="style-to-width"> <xsl:with-param name="style" select="replace($style, '.*stroke-width:([^;]+).*', '$1')"/> </xsl:call-template> </xsl:if> <param name="bline"> <bline type="bline_point" loop="{matches(., 'z', 'i')}"> <xsl:call-template name="path-to-bline"> <xsl:with-param name="path" select="."/> <xsl:with-param name="node" select="$self" tunnel="yes"/> </xsl:call-template> </bline> </param> </layer> </xsl:matching-substring> </xsl:analyze-string> </xsl:template> <xsl:template name="path-to-bline"> <xsl:param name="path"/> <xsl:variable name="stripped" select="replace(replace(translate($path, ',', ' '), '(\d)-', '$1 -'), '\s*([a-z]+)\s*', '$1', 'i')"/> <xsl:variable name="closed" select="if (matches($stripped, 'z', 'i')) then $stripped else replace($stripped, 'm([-\d.]+\s[-\d.]+).*$', '$0l$1z', 'i')"/> <xsl:variable name="tmp" select="replace($closed, '([-\d.]+\s[-\d.]+)l([-\d.]+\s[-\d.]+)', '$1c$1 $2 $2', 'i')"/> <xsl:variable name="curve" select="replace($tmp, '([-\d.]+\s[-\d.]+)l([-\d.]+\s[-\d.]+)', '$1c$1 $2 $2', 'i')"/> <xsl:analyze-string select="$curve" regex="\s([-\d.]+\s[-\d.]+)\s[-\d.]+\s[-\d.]+z" flags="i"> <xsl:matching-substring> <xsl:analyze-string select="concat(regex-group(1), $curve)" regex="([-\d.]+)\s([-\d.]+)[m\s]([-\d.]+)\s([-\d.]+)c([-\d.]+)\s([-\d.]+)" flags="i"> <xsl:matching-substring> <xsl:call-template name="node-to-bline-point"> <xsl:with-param name="c1_x" select="regex-group(1)"/> <xsl:with-param name="c1_y" select="regex-group(2)"/> <xsl:with-param name="x" select="regex-group(3)"/> <xsl:with-param name="y" select="regex-group(4)"/> <xsl:with-param name="c2_x" select="regex-group(5)"/> <xsl:with-param name="c2_y" select="regex-group(6)"/> </xsl:call-template> </xsl:matching-substring> </xsl:analyze-string> </xsl:matching-substring> </xsl:analyze-string> </xsl:template> <xsl:template name="node-to-bline-point"> <xsl:param name="x"/> <xsl:param name="y"/> <xsl:param name="c1_x"/> <xsl:param name="c1_y"/> <xsl:param name="c2_x"/> <xsl:param name="c2_y"/> <xsl:param name="node" tunnel="yes"/> <xsl:variable name="transform"> <xsl:for-each select="$node/ancestor-or-self::*/@transform"> <xsl:value-of select="."/> </xsl:for-each> </xsl:variable> <xsl:variable name="t" select="math:resolve_transform($transform)"/> <xsl:variable name="transformed_x" select="$t[5] + $t[1] * xs:float($x) + $t[3] * xs:float($y)"/> <xsl:variable name="transformed_y" select="$t[6] + $t[2] * xs:float($x) + $t[4] * xs:float($y)"/> <xsl:variable name="transformed_c1_x" select="$t[5] + $t[1] * xs:float($c1_x) + $t[3] * xs:float($c1_y)"/> <xsl:variable name="transformed_c1_y" select="$t[6]+ $t[2] * xs:float($c1_x) + $t[4] * xs:float($c1_y)"/> <xsl:variable name="transformed_c2_x" select="$t[5] + $t[1] * xs:float($c2_x) + $t[3] * xs:float($c2_y)"/> <xsl:variable name="transformed_c2_y" select="$t[6]+ $t[2] * xs:float($c2_x) + $t[4] * xs:float($c2_y)"/> <entry> <composite type="bline_point"> <point> <vector> <x><xsl:value-of select="$transformed_x"/></x> <y><xsl:value-of select="$transformed_y"/></y> </vector> </point> <width> <real value="1"/> </width> <origin> <real value="0.5"/> </origin> <split> <bool value="true"/> </split> <t1> <xsl:call-template name="vector-pair-to-radial"> <xsl:with-param name="origin-x" select="$transformed_c1_x"/> <xsl:with-param name="origin-y" select="$transformed_c1_y"/> <xsl:with-param name="x" select="$transformed_x"/> <xsl:with-param name="y" select="$transformed_y"/> </xsl:call-template> </t1> <t2> <xsl:call-template name="vector-pair-to-radial"> <xsl:with-param name="origin-x" select="$transformed_x"/> <xsl:with-param name="origin-y" select="$transformed_y"/> <xsl:with-param name="x" select="$transformed_c2_x"/> <xsl:with-param name="y" select="$transformed_c2_y"/> </xsl:call-template> </t2> </composite> </entry> </xsl:template> <xsl:template name="vector-pair-to-radial"> <xsl:param name="x"/> <xsl:param name="y"/> <xsl:param name="origin-x"/> <xsl:param name="origin-y"/> <xsl:variable name="dx" select="xs:float($x) - xs:float($origin-x)"/> <xsl:variable name="dy" select="xs:float($y) - xs:float($origin-y)"/> <xsl:variable name="d" select="math:sqrt($dx * $dx + $dy * $dy)"/> <xsl:variable name="angle" select="math:atan2($dy, $dx)"/> <radial_composite type="vector"> <radius> <real value="{$d * 3}"/> </radius> <theta> <angle value="{$angle * 57.295779513082320876798154814105}"/> </theta> </radial_composite> </xsl:template> <xsl:template name="style-to-width"> <xsl:param name="style"/> <xsl:if test="matches($style, '^\d')"> <param name="width"> <real value="{math:units_to_px($style)}"/> </param> </xsl:if> </xsl:template> <xsl:template name="style-to-color"> <xsl:param name="style"/> <xsl:if test="matches($style, '#')"> <xsl:analyze-string select="concat($style, ';')" regex="#([\da-f]{{2}})([\da-f]{{2}})([\da-f]{{2}});"> <xsl:matching-substring> <param name="color"> <color> <r><xsl:value-of select="math:hex_to_color(regex-group(1))"/></r> <g><xsl:value-of select="math:hex_to_color(regex-group(2))"/></g> <b><xsl:value-of select="math:hex_to_color(regex-group(3))"/></b> <a><xsl:value-of select="if (matches($style, 'fill-opacity:')) then math:power(xs:float(replace($style, '.*fill-opacity:([-\d.]+).*', '$1')), 1 div 2.2) else 1"/></a> </color> </param> </xsl:matching-substring> </xsl:analyze-string> </xsl:if> <xsl:if test="matches($style, 'rgb')"> <xsl:analyze-string select="concat($style, ';')" regex="rgb[(\s]+([-\d.]+)[,\s]+([-\d.]+)[,\s]+([-\d.]+)[\s)]+;"> <xsl:matching-substring> <param name="color"> <color> <r><xsl:value-of select="math:power(xs:float(regex-group(1)) div 255, 2.2)"/></r> <g><xsl:value-of select="math:power(xs:float(regex-group(2)) div 255, 2.2)"/></g> <b><xsl:value-of select="math:power(xs:float(regex-group(3)) div 255, 2.2)"/></b> <a>1</a> </color> </param> </xsl:matching-substring> </xsl:analyze-string> </xsl:if> <xsl:if test="matches($style, 'url')"> <param name="color"> <color><r>0.5</r><g>0.5</g><b>0.5</b><a>0.5</a> </color> </param> </xsl:if> </xsl:template> <xsl:function name="math:resolve_transform"> <xsl:param name="transform"/> <xsl:variable name="stripped" select="replace(replace($transform, 'translate\(', 'X(1,0,0,1,'), 'matrix', 'X')"/> <xsl:analyze-string select="concat('X(1,0,0,1,0,0)', $stripped)" regex="(.*)X\((-?[\d.]+),(-?[\d.]+),(-?[\d.]+),(-?[\d.]+),(-?[\d.]+),(-?[\d.]+)\)[^X]*X\((-?[\d.]+),(-?[\d.]+),(-?[\d.]+),(-?[\d.]+),(-?[\d.]+),(-?[\d.]+)\).*"> <xsl:non-matching-substring> <xsl:sequence select="(1,0,0,1,0,0)"/> </xsl:non-matching-substring> <xsl:matching-substring> <xsl:variable name="a2" select="xs:float(regex-group(8))"/> <xsl:variable name="b2" select="xs:float(regex-group(9))"/> <xsl:variable name="c2" select="xs:float(regex-group(10))"/> <xsl:variable name="d2" select="xs:float(regex-group(11))"/> <xsl:variable name="e2" select="xs:float(regex-group(12))"/> <xsl:variable name="f2" select="xs:float(regex-group(13))"/> <xsl:variable name="a1" select="xs:float(regex-group(2))"/> <xsl:variable name="b1" select="xs:float(regex-group(3))"/> <xsl:variable name="c1" select="xs:float(regex-group(4))"/> <xsl:variable name="d1" select="xs:float(regex-group(5))"/> <xsl:variable name="e1" select="xs:float(regex-group(6))"/> <xsl:variable name="f1" select="xs:float(regex-group(7))"/> <xsl:variable name="p" select="($a1*$a2+$c1*$b2,$b1*$a2+$d1*$b2,$a1*$c2+$c1*$d2,$b1*$c2+$d1*$d2,$a1*$e2+$c1*$f2+$e1,$b1*$e2+$d1*$f2+$f1)"/> <xsl:variable name="remainder" select="replace(regex-group(1), 'X\(1,0,0,1,0,0\)', '')"/> <xsl:choose> <xsl:when test="matches($remainder, 'X')"> <xsl:variable name="recursion" select="concat($remainder, 'X(', $p[1], ',', $p[2], ',', $p[3], ',', $p[4], ',', $p[5], ',', $p[6], ')')"/> <xsl:sequence select="math:resolve_transform($recursion)"/> </xsl:when> <xsl:otherwise> <xsl:sequence select="$p"/> </xsl:otherwise> </xsl:choose> </xsl:matching-substring> </xsl:analyze-string> </xsl:function> <xsl:function name="math:hex_to_color" as="xs:float"> <xsl:param name="hex"/> <xsl:value-of select="math:power(xs:float(string-length(substring-before('0123456789abcdef', substring($hex,1,1))) * 16 + string-length(substring-before('0123456789abcdef', substring($hex,2,1)))) div 255, 2.2)"/> </xsl:function> <xsl:function name="math:units_to_px" as="xs:float"> <xsl:param name="size"/> <xsl:analyze-string select="$size" regex="^([-\d.]+)([a-z%]*)$"> <xsl:matching-substring> <xsl:variable name="factor"> <xsl:choose> <xsl:when test="regex-group(2) = 'pt'">1.25</xsl:when> <xsl:when test="regex-group(2) = 'em'">16</xsl:when> <xsl:when test="regex-group(2) = 'mm'">3.54</xsl:when> <xsl:when test="regex-group(2) = 'pc'">15</xsl:when> <xsl:when test="regex-group(2) = 'cm'">35.43</xsl:when> <xsl:when test="regex-group(2) = 'in'">90</xsl:when> <xsl:otherwise>1</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:value-of select="xs:float($factor) * xs:float(regex-group(1))"/> </xsl:matching-substring> </xsl:analyze-string> </xsl:function> </xsl:stylesheet>