Plugin: get filepath of current loaded file

Discussion about writing code for Inkscape.
bliako
Posts: 3
Joined: Thu Jul 11, 2019 10:11 pm

Plugin: get filepath of current loaded file

Postby bliako » Thu Jul 11, 2019 10:47 pm

Hi,
I have started learning how to write a plugin for inkscape using Python. My mileage is very short. And so is my taste and skills for Python. But I am a relatively skilled programmer (C/C++/Perl/Java). I am posting here an outline of the problem/use-case as a RFC for not re-inventing the wheel.

    0. Another software (AS) is some sort of typesetting software with zero capabilities when drawing paths and squigles and calligraphy BUT it can load SVG files, scale them and place them at (x,y).

    1. Inkscape is started by AS with an input PNG filename which is the background image currently in AS. This is always true, an image will be loaded to inkscape when called by AS.

    2. User creates one or more curves/paths in inkscape, for example using the calligraphy tool.

    3. When finished, user runs the proposed inkscape plugin which does the following:
      a. find convex hull (*) of all selected paths
      b. write top-left corner coordinates of convex hull to file
      c. somehow find the scale-factor of the selected paths wrt the whole image and write it to same output file (OF)

    4. Background image is deleted and all paths saved to an SVG file

    5. the "other software" (AS) loads the SVG file and positions the paths at the location specified by the text file (OF) and scales it accordingly.

    6. Ideally the paths created by inkscape and loaded into AS should fall exactly where user drew them in inkscape.

*) For the convex hull I am using code by user ragstian (viewtopic.php?t=13622#p52785) which I also modified to write coordinates of top-left corner to file.

What I am asking from you is
    your opinion about my methodology,

    whether something like this or part of it exists,

    what's a good way to find the scale factor of selected paths relative to background image, as a percentage.

    pointers to inkscape's plugin API. For example I just found how to popup a warning/info message.

    But how do i get the filepath of the input image loaded originally to inkscape?



Moini
Posts: 3381
Joined: Mon Oct 05, 2015 10:44 am

Re: Plugin: get filepath of current loaded file

Postby Moini » Fri Jul 12, 2019 2:35 am

But how do i get the filepath of the input image loaded originally to inkscape?


In Inkscape 0.92.x, you don't get that info from Inkscape. You need to memorize what you put in.

Extensions only get a temporary file name, as they work by making a copy of the original SVG, then work on that, and then save it back.

Another idea would be to not embed the image, but just link to it. Then the file path will still be saved in the file.

I can't say anything about the other questions, as I don't get what the purpose of these things is. What convex hull? What scale?... What's the goal?
Something doesn't work? - Keeping an eye on the status bar can save you a lot of time!

Inkscape FAQ - Learning Resources - Website with tutorials (German and English)

bliako
Posts: 3
Joined: Thu Jul 11, 2019 10:11 pm

Re: Plugin: get filepath of current loaded file

Postby bliako » Fri Jul 12, 2019 3:16 am

The goal is to beat the limitations of one software by delegating drawing some elaborate graphics using Inkscape.

For example, suppose that there is a map editing software (the "other software") which is great but for drawing roads from A to B, it is lacking. So one roundabout way is to go to Inkscape, make the road nicely and import that SVG to our map editor. However, we need to have some kind of guide showing where places A and B are!

The workflow is as follows:
1. export portion of map showing places A and B as a PNG
2. start inkscape with that PNG file, which places at the background
3. now in inkscape we have an idea where to draw the road because we know from the background PNG where A and B are
4. draw the road with inkscape's tools
5. delete the PNG from the background
6. export to SVG and exit inkscape.
7. go to other software and import SVG of the roads.
8. To automate this a bit I need to place the road so that it starts at A and more importantly have the right scale so that it ends up in B.

I have the ability to write plugins to both softwares. So my Inkscape plugin creates a text file with some information about the path, namely its convex hull. Then the "other software"'s plugin places the graphic at hopefully the right place (more or less) and crucially the right scale.

the trivial question and hence the title was how should I extract the filepath of the input PNG filename so that my inkscape plugin writes the text file at same location, using same name, different extension.

The serious problems is how to know places A and B somehow and correct scale.

p.s. the "other software" is not a map editor, please allow me not to say as I am doing this for other people and don't want to say what they are working on.

Moini
Posts: 3381
Joined: Mon Oct 05, 2015 10:44 am

Re: Plugin: get filepath of current loaded file

Postby Moini » Fri Jul 12, 2019 10:49 pm

I see. Did the hint with embedding vs. linking help?

How far have you come wrt scale?

Inkscape imports PNG images either:
- with the dpi value that is set in the png file or
- optionally with a custom dpi value

You can set that in the settings, and you can specify a settings file when you run Inkscape from the command line.
Something doesn't work? - Keeping an eye on the status bar can save you a lot of time!

Inkscape FAQ - Learning Resources - Website with tutorials (German and English)

bliako
Posts: 3
Joined: Thu Jul 11, 2019 10:11 pm

Re: Plugin: get filepath of current loaded file

Postby bliako » Sun Jul 14, 2019 10:08 pm

By LINKing, I managed to get the href property in the svg root document which contains the linked filename. So your suggestion there solved that problem, thanks!

I found that the exported SVG contains width and height properties which can be set in real/absolute units mm or inches (in addition to pixels). If my plugin exports the SVG in real units then I assume DPI is redundant, there is no need to use it. Unfortunately the "other software" which imports the SVG seems to be buggy and so my testing is incomplete.

Here is what I learned so much for others:

Code: Select all

    # get the svg xml currently loaded
    svg = self.document.getroot()
    width  = self.unittouu(svg.get('width'))
    height = self.unittouu(svg.get('height'))
    # and here is how to modify viewbox (because importing software is buggy)
    svg.attrib['viewBox'] = "%f %f %f %f" % (viewBoxX0, viewBoxY0, viewBoxX1, viewBoxY1)

However, I have some confusion over how to get/set document units. Actually a lot of confusion because this is not working as I thought it shoud (canvas 700x978 pixels, which is the size of imported png):

Code: Select all

   # make sure the exported SVG contains its units explicitly because we plan to use absolute units (mm)
   # this adds the field to output SVG and works OK
   namedView = svg.find(inkex.addNS('namedview', 'sodipodi'))
   if namedView is not None:
      documentUnits = inkex.addNS('document-units', 'inkscape')
      namedView.set(documentUnits, "mm")

     width  = svg.get('width')
        height = svg.get('height')
        inkex.debug("canvas size: %s x %s %s (document units)" % (width, height,  self.getDocumentUnit()))
       # prints out 700 x 978 px
        width  = self.unittouu(svg.get('width')+"mm")
        height = self.unittouu(svg.get('height')+"mm")
        inkex.debug("canvas size %s x %s mm" % (width, height))
       #prints out 2646.190639 x 3697.159975 !!!!
       

Also, here is a way i found over scraping the net for gettting the LINKed filename (my original PNG)

Code: Select all

        imgs = self.document.xpath('//svg:image', namespaces=inkex.NSS)
        pngfilename = None
        # the exported SVG contains "absref" but the root document contains href, so we check like this
        if '{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}absref' in imgs:
                inkex.debug("absref")
                pngfilename = imgs[0].attrib['{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}absref']
        elif '{http://www.w3.org/1999/xlink}href' in imgs:
                inkex.debug("href")
                pngfilename = imgs[0].attrib['{http://www.w3.org/1999/xlink}href']
       else
               inkex.errormsg("you have not LINKed  (LINK not embed) any background image!")



Does that make sense?
Many thanks for your help,
bliako

Moini
Posts: 3381
Joined: Mon Oct 05, 2015 10:44 am

Re: Plugin: get filepath of current loaded file

Postby Moini » Mon Jul 15, 2019 3:18 am

I'm not 100% sure what exactly you're asking, but maybe this little essay about units in Inkscape will be useful:
wiki.inkscape.org/wiki/index.php/Units_In_Inkscape
Something doesn't work? - Keeping an eye on the status bar can save you a lot of time!

Inkscape FAQ - Learning Resources - Website with tutorials (German and English)


Return to “Programming”