Version 1 (modified by chriz, 10 years ago) (diff)

Migrated from old trac wiki

Using vector images in WikidPad

Advantages over bitmap images:

  • Easier to draw sketches and hand-made diagrams
  • Easier to modify graphics
  • Scale and rotate without degrading
  • Don't have to worry about image resolution and color-depth
  • Lower file sizes (for most cases)

There's no support for vector images in WikidPad's internal preview renderer, so they have to be rasterized (converted to png) before they can be displayed.

It makes no difference which format you use (SVG, WMF, DXF), as long as your external application supports command line conversion to PNG. For sake of clarity, in the following examples I assume you are using SVG format.

To use, configure the plugin options and insert [:vector: filename.svg] where you want image to be displayed. Select [:vector: filename.svg] text and use toolbar and menu items to launch vector image editor.
Vector image file filename.svg should be located in YourWikiFolder?\data\


To use this plugin, you'll need external vector image rasterizer and editor. So far, the plugin was tested on Windows XP, with either Inkscape or TpX. Both editors can be used for image rasterization without GUI (command line options).

Using with Inkscape
Inkscape is popular heavy-weight vector editor.

Set the plugin options (Wiki -> Options -> Rasterizer):

  • Input file switch: -f
  • Output file switch: -e (for png)
  • Other commandline options: leave blank
  • Path to editor: same as Path to rasterizer

Using with TpX
TpX is a light-weight vector editor, with support for command line options for image conversion. TpX is much faster then Inkscape, but it has some rough edges.

  • Converted images are often too big, to fix this set File -> TpX Settings -> BitmapRes_Default to value 4000
  • When saving, tpx also creates .eps and .pdf files. To disable this set File -> TpX Settings -> TeXFormat_Deafult and PdfTexFormat_Default to None
  • If you notice similar behaviour, set mentioned options in Edit -> Picture Properties
  • SVG format is supported, but it's much easier to use .tpx format, as it's default format when saving image (if you opt for .SVG, use File -> Save As)

Set the plugin options (Wiki -> Options -> Rasterizer):

  • Input file switch: leave blank
  • Output file switch: -o
  • Other commandline options: -x png
  • Path to editor: same as Path to rasterizer (ie. TpX\tpx.exe if you place TpX in WikidPad directory)

Source goes to WikidPad\user_extensions\.

import os, urllib, re
import wx

# Extension handles :vector: insertion by calling external rasterizer to convert vector image to png.
# Also adds toolbar and menu options to launch external vector graphics editor.

from pwiki.StringOps import mbcsEnc

WIKIDPAD_PLUGIN = (("InsertionByKey", 1), ("Options", 1), ("MenuFunctions",1), ("ToolbarFunctions",1))

def describeMenuItems(wiki):
    return ((VectorEditor, "Vector graphics editor\t", "Run external graphics editor"),)

def describeToolbarItems(wiki):
    return ((VectorEditor, "Vector graphics editor", "Run external graphics editor", ("brush",)),)

def VectorEditor(wiki, evt):
    editor_path = wiki.getConfig().get("main", "plugin_rasterizer_editor", "")
    seltext = wiki.getActiveEditor().GetSelectedText()
    seltext_files = re.findall('[a-zA-Z0-9]+\.[a-zA-Z0-9]{3}',seltext)
    if len(seltext_files) !=0:
        cmdline = '"%s\\%s"' % (wiki.wikiData.wikiData.dataDir, seltext_files[0])
        cmdline = '"%s\\sketch.svg"' % (wiki.wikiData.wikiData.dataDir)
        wiki.getActiveEditor().AddText('[:vector: sketch.svg]')
        os.spawnl(os.P_NOWAIT, editor_path, editor_path, cmdline)
        wiki.stdDialog('o', 'Error running external graphics editor', 'Please check plugin options.\nCommand line:\n%s %s' % (editor_path, cmdline), additional=None)

def describeInsertionKeys(ver, app):
    return ((u"vector", ("html_single", "html_previewWX", "html_preview",
            "html_multi"), RasterizerHandler),)

class RasterizerHandler:
    Class fulfilling the "insertion by key" protocol.
    def __init__(self, app): = app
        self.RasterizerExe = None

    def taskStart(self, exporter, exportType):
        # Find rasterizer executable by configuration setting
        self.RasterizerExe ="main", "plugin_rasterizer_exePath", "")
        self.inSwitch ="main", "plugin_rasterizer_inSwitch", "")
        self.outSwitch ="main", "plugin_rasterizer_outSwitch", "")
        self.otherSwitch ="main", "plugin_rasterizer_otherSwitch", "")

    def taskEnd(self):

    def createContent(self, exporter, exportType, insToken):

        file_path = exporter.wikiData.wikiData.dataDir + '\\' + insToken.value
        if not os.access(file_path, os.F_OK):
            return u"<pre>[Image unavailable: %s]</pre>" % file_path

        if self.RasterizerExe == "":
            # No path to rasterizer executable -> show message
            return "<pre>[Please set path to Rasterizer executable]</pre>"

        # Get exporters temporary file set (manages creation and deletion of
        # temporary files)
        tfs = exporter.getTempFileSet()

        pythonUrl = (exportType != "html_previewWX")
        dstFullPath = tfs.createTempFile("", ".png", relativeTo="")
        url = tfs.getRelativeUrl(None, dstFullPath, pythonUrl=pythonUrl)
        cmdline = '%s "%s" %s "%s" %s' % (self.inSwitch, file_path, self.outSwitch, dstFullPath, self.otherSwitch)
            # Run external application
            os.spawnl(os.P_WAIT, self.RasterizerExe, self.RasterizerExe, cmdline)
            return u"<pre>[ Error occured while converting to png] </pre>"

        # Return appropriate HTML code for the image
        if exportType == "html_previewWX":
            # Workaround for internal HTML renderer
            return u'<img src="%s" border="0" align="bottom" />&nbsp;' % url
            return u'<img src="%s" border="0" align="bottom" />' % url

    def getExtraFeatures(self):
        return ()

def registerOptions(ver, app):
    # Register option
    app.getDefaultGlobalConfigDict()[("main", "plugin_rasterizer_exePath")] = u""
    app.getDefaultGlobalConfigDict()[("main", "plugin_rasterizer_inSwitch")] = u""
    app.getDefaultGlobalConfigDict()[("main", "plugin_rasterizer_outSwitch")] = u"-o"
    app.getDefaultGlobalConfigDict()[("main", "plugin_rasterizer_otherSwitch")] = u"-x png"
    app.getDefaultGlobalConfigDict()[("main", "plugin_rasterizer_editor")] = u""
    # Register panel in options dialog
    app.addOptionsDlgPanel(RasterizerOptionsPanel, u"  Rasterizer")

class RasterizerOptionsPanel(wx.Panel):
    def __init__(self, parent, optionsDlg, app):
        wx.Panel.__init__(self, parent) = app

        pt ="main", "plugin_rasterizer_exePath", u"")
        self.rsPath = wx.TextCtrl(self, -1, pt)

        pt ="main", "plugin_rasterizer_inSwitch", u"")
        self.inSwitch = wx.TextCtrl(self, -1, pt)

        pt ="main", "plugin_rasterizer_outSwitch", u"-o")
        self.outSwitch = wx.TextCtrl(self, -1, pt)

        pt ="main", "plugin_rasterizer_otherSwitch", u"-x png")
        self.otherSwitch = wx.TextCtrl(self, -1, pt)

        pt ="main", "plugin_rasterizer_editor", u"-x png")
        self.edPath = wx.TextCtrl(self, -1, pt)

        mainsizer = wx.FlexGridSizer(5, 2, 0, 0)

        mainsizer.AddGrowableCol(1, 1)

        mainsizer.Add(wx.StaticText(self, -1, _(u"Path to rasterizer:")), 0,
                wx.ALL | wx.EXPAND, 5)
        mainsizer.Add(self.rsPath, 1, wx.ALL | wx.EXPAND, 5)

        mainsizer.Add(wx.StaticText(self, -1, _(u"Input file switch:")), 0,
                wx.ALL | wx.EXPAND, 5)
        mainsizer.Add(self.inSwitch, 1, wx.ALL | wx.EXPAND, 5)

        mainsizer.Add(wx.StaticText(self, -1, _(u"Output file switch:")), 0,
                wx.ALL | wx.EXPAND, 5)
        mainsizer.Add(self.outSwitch, 1, wx.ALL | wx.EXPAND, 5)

        mainsizer.Add(wx.StaticText(self, -1, _(u"Other commandline options:")), 0,
                wx.ALL | wx.EXPAND, 5)
        mainsizer.Add(self.otherSwitch, 1, wx.ALL | wx.EXPAND, 5)

        mainsizer.Add(wx.StaticText(self, -1, _(u"Path to editor:")), 0,
                wx.ALL | wx.EXPAND, 5)
        mainsizer.Add(self.edPath, 1, wx.ALL | wx.EXPAND, 5)


    def setVisible(self, vis):
        return True

    def checkOk(self):
        return True

    def handleOk(self):
        pt = self.rsPath.GetValue()"main", "plugin_rasterizer_exePath", pt)

        pt = self.inSwitch.GetValue()"main", "plugin_rasterizer_inSwitch", pt)

        pt = self.outSwitch.GetValue()"main", "plugin_rasterizer_outSwitch", pt)

        pt = self.otherSwitch.GetValue()"main", "plugin_rasterizer_otherSwitch", pt)

        pt = self.edPath.GetValue()"main", "plugin_rasterizer_editor", pt)


Just add them here or use Yahoo! User Group.

Attachments (2)

Download all attachments as: .zip