Saturday, February 21, 2009

Inkscape slicer

Download Inkscape slice effect a.k.a. 'slicer' 0.1.1 (bugfix)

Usage:

1.) Create layer e.g. named 'slices'.
2.) Create rectangles as your slices, set their Label* (select rect and Object -> Object properties) as the output filename (without extension).
3.) Run Effects -> Export -> Slicer, specify directory where you want your slices to be saved and Apply.

What program does:

1.) It takes all rectangles you give, puts opacity 0, stroke to none.
2.) And tries to save contents inside rectangles to new files.
3.) Returns the style to original value.

Installation:

Copy these two files (slicer.py, slicer.inx) to share/extensions directory inside inkscape, do not create directory for these files.

Extensions dir in common platforms:
Ubuntu 8.10 user scope: ~/.inkscape/extensions/
Ubuntu 8.10 global scope: /usr/share/inkscape/extensions/
Windows: c:\Program Files\Inkscape\share\extensions\

Thanks

Original idea from Matt Harrison:
WARNING, Matt's version didn't work with latest Ubuntu (8.10) and Inkscape 0.46, major API differences, that was the reason I rewrote whole script with features I needed. I have no intention to ripoff Matt's effort, so I fully thank Matt for his work, and if you somehow feel that I have broken the license in Matt's file you can contact me through comments in this blog.

* Label allows all characters, where as ID allows only few. I need ability to use spaces in filenames so ID is no go. One can switch it to back to ID by changing line in slicer.py:
basename = rect_label.lstrip("#")
to
basename = rect_id

7 comments:

Aldi said...
This comment has been removed by the author.
Aldi said...

Great work!

Anyway, I'm using Windows XP and I was just wondering, though, why use the object 'Label' property instead of it's 'ID' for the sliced filename? Usually Inkscape uses 'ID' for filename when exporting selected objects.

Also, I get image error when slicing imported images with relative path (eg. ..\images\pic.jpg). The path has to be absolute (eg. d:\folder\images\pic.jpg) to be able to be sliced. Could you probably fix this?

Nice work, though. Keep it up.

Cheers.

Ciantic said...

ID Does not allow spaces, only numbers, ".", "_" chars. So for instance spaces is not allowed, Label allows all kind of chars for the filename.

The problem with relative paths is that Inkscape does not send the information where the actual file is, just temp file, to the effects. I could probably make a new field for "where is your file?" which would work as a workaround... but I'd prefer to get the full filename/path of *actual* file also.

Inkscape effects works like this:
1.) It creates temp file of actual file,
2.) Sends temp file to effect(s)
3.) And after effect is done replaces actual file with temp file.

Thus it cannot work with relative paths with current Inkscape implementation.

matt harrison said...

I've updated my original code. Code is on github

cheers

joehudson said...

thanks for this! just want I want. I just tried it on inkscape .47 on vista and got 'layer slices not found' (I had created a layer called slices). so I guess the api has changed again.. hopefully it wont require another total re-write!

joehudson said...

ok, having never used python before, I've started trying to figure out why it's not working with inkscape 0.47 I added some debug code to the script where it looks for the slices layer, so it reports all the layer names if not found:

sliceLayer = None
layernames = []
# For each group (layer):
for group in imageRoot.findall("{http://www.w3.org/2000/svg}g"): # TODO: This: {http://www.w3.org/2000/svg}g[@

{http://www.inkscape.org/namespaces/inkscape}label='slices'] didn't work, why?
#~ logging.debug(group)
#~ logging.debug(group.attrib)

# If group's label attribute is wanted, then we found the layer
try:
if group.attrib['{http://www.inkscape.org/namespaces/inkscape}label'] == self.options.layer:
sliceLayer = group
break
else:
layernames.append(group.attrib['{http://www.inkscape.org/namespaces/inkscape}label'])
except KeyError, ker:
pass

# If slice layer was not found:
if sliceLayer is None:
lns = " ".join(map(str, layernames))
sys.stderr.write('Layer named \'%s\' was not found! layer names were: \'%s\'.' % (self.options.layer, lns) )
sys.exit(1)



running this, only the first layer 'Layer 1' is reported, even when there are several layers in the svg.. I'm not sure where to go from here...

joehudson said...

update. :) got it working. looking at the svg source it seems somehow when I created a new layer it was being created as a sub-layer to 'Layer 1'. Going to the layers... tool box I was able to create a top level layer called slices and then all worked as I'd hoped. thanks again!

as a thought for additional features, how about being able to select a target layer for exporting, so if you've got overlapping elements making up your design you can export those layers separately, perhaps using a slices sub-layer.. handy if you're layering png backgrounds in your webpage. anyway, just a thought for an already extremely useful script.