I'm part of a small group getting started on an inkstitch like extension for using projectors for sewing patterns. The very small (and, in theory simple) module to invert colors (basically, mimicking evince's and the kindle app's night mode) I'm working on is giving me some fits - no code yet because I can't even find the references I need, at least without resorting to command line, which may not actually solve the problem.
The two problems I need to solve right now
1: Is it possible to programmatically select all (if in gui equivalent of Ctrl+A or Ctrl+Alt+A, or, even better, if it was possible to just select all the visible paths, not text or objects)
2: Is it possible to implement the Colors -> Invert... filter from a python script, using parameters the script sets, without resorting to the inkex command module?
I did find a command line call that kind of does this - it requires the user to have set the filters options in the gui first, and we are trying to avoid requiring that.
Final question before I go too far with how I want things to work, versus how it CAN work, is it possible to set the menu item for the extension to work as a checkbox/toggle (similar to View -> Guides) when writing the extension in python?
Thank you! So, self.svg does work differently than the way I was reading the docs - to me it implied that self.svg was not populated unless the user had already selected something (in my defense, I was tired when going through that, I know better than to read the docs on a language that I'm still learning when I'm tired). As for the naughty way on the filter, that is absolutely not an option, this has to be an on/off at will, so, I guess I'm building a filter (even though one already exists that does what I need, working out the color math should be fun, unless someone can point to where the code for the Invert... filter is, I found one example that uses the rgb tuple to do the math, so, might just need to dive deeper into that part of the inkex docs).
Edit: I just found that the Negative extension actually does the path color inversion I need much better than the Invert... filter (it's not a complete solution to what I'm needing to do, but examining the code has explained a few things for me, including simplifying the color math).
Filters <filter> are definitions which sits inside the <svg><defs> element.
The filter is applied to the object with a filter url entry in the style attribute of the object in question.
Adding or removing / changing that entry simply changes which predefined filter is being pointed to.
Since the invert filter you are using is never going to change ? It's sufficient to have a single filter for that purpose in <defs> with a unique ID
You can then reference it in any object, or pop it out to remove the filter - or swap to another.
You certainly do not need to build the filter in terms of a simple invert.
If you see the attached extension on the post above - the filter is the copied text from the application of the invert filter - in this case with red/blue invert.
Using Inkscape to generate that code for you is a good idea :)
If you need a better example, say with toggle built in. Let me know.
I really appreciate the work you've done - still need to take a look at your example. I was editing while you were posting, so may have missed a development. The Invert filter doesn't quite give the right color change - we found an option combination that came close, and were willing to work with that - although building our own would have been a better solution - but, the Negative extension does invert the way we were looking for, found that just a little while ago. If you have the time, I would absolutely love an example showing how to do the toggle and/or assigning shortcut keys within the extension, it would save me from having to dig through the inx specifications, but only if you have the time, I'm sure it's in the specification somewhere.
The negative extension is not a filter, it will only work with vector information ( it cannot affect bitmaps for example )
To add a shortcut for any extension.
Edit>Preferences>Interface>Keyboard and search for 'negative'. You will find Extensions (no prefs) Negative. Click the Shortcut column to add a shortcut.
For a toggleable filter of your choosing, the following code will do it.
All you have to do is apply a filter to an object in a brand new file. Then copy the <filter>.......</filter> section into the code below
The code will toggle the filter. You can find it as above in the shortcut preferences in the same way.
import inkex
from lxml import etree
class AddFilter(inkex.EffectExtension):
def add_arguments(self, pars):
pass
def effect(self):
# A dummy SVG which contains a copy and paste of a user saved filter
# Replace <filter>.....</filter> with your saved filter
filter_text = """
<svg
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Invert"
id="filter1"
x="-0.0064236886"
y="-0.0064236886"
width="1.0128474"
height="1.0128474">
<feColorMatrix
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
result="fbSourceGraphic"
id="feColorMatrix1" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix2" />
<feColorMatrix
id="feColorMatrix3"
values="0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 -0.21 -0.72 -0.07 2 0 "
result="color2"
in="fbSourceGraphic" />
</filter>
</defs>
</svg>
"""
# Use etree to encode the filter text to an etree element
my_filter_svg = etree.fromstring(f'{filter_text}')
# Lets set a custom filter id
my_filter_id = 'custom_filter_01'
# Check if this filter already exists in defs
filter_id_list = []
for _filter in self.svg.defs.xpath('//svg:filter'):
filter_id_list.append(_filter.get_id())
if my_filter_id in filter_id_list:
pass
else:
# Append the filter element to the svg defs
my_filter = my_filter_svg.findall('.//{http://www.w3.org/2000/svg}filter')[0]
# Set the id
my_filter.set('id', my_filter_id)
self.svg.defs.append(my_filter)
# build a url for the id
my_filter_url = f'url(#{my_filter_id})'
# apply the filter to any selected elements
for item in self.svg.selected:
if item.style.get('filter') == my_filter_url:
item.style.pop('filter')
else:
item.style['filter'] = my_filter_url
if __name__ == '__main__':
AddFilter().run()
Oooooo, toggling is simpler than I thought. Is there a way to change the menu entry to show that it's on? Something like a checkbox that fills when it's on and empties when it's off (see attachment), or, even just a Filter On/Filter Off flip?
Is there a way to change the menu entry to show that it's on?
Only if you use a custom gui. Inx files cannot change their content dynamically. You could call the menu point toggle filter if you want to avoid a custom gui.
That sounds quite interesting. Is there a repository you can link to? I'm curious :)
Hi Kaalleen, the repository only has a very very alpha version right now, still working to optimize the code, it's crazy slow and gets kind of weird with patterns with lots of paths (and the readme assumes you already know about projector sewing, I'm not very good with making readme files). Are you more interested in the code, and how it will help with projector sewing, or projector sewing in general? I want to answer your questions properly.
You could call the menu point toggle filter if you want to avoid a custom gui.
Duh! Didn't even think to call it `toggle filter`, that will definitely smooth things a bit. A custom gui will come into play with some of the later modules, probably, as there will be some that need input, and we're looking into the possibility of having a floating dialog that will release focus, if it can be made fairly small, maybe with some icons instead of labels (more like an undocked/floating toolbar than anything).
I am interested in both. Projector sewing in general and the code as well.
I haven't done projector sewing myself (yet), but I heard about it quite a while ago and thought this was very interesting and worth a try.
So hearing now, that Inkscape is the tool of your choice makes it even more interesting. So I was curious which adaptions are needed to make it work well with Inkscape.
Sorry for the delay, too many projects in the works. Projector sewing is using a projector as a second screen to display a pdf format pattern instead of printing and taping it together. The idea has gotten a lot more popular in the last year thanks to the Ditto system being released, but there is an older segment that has been repurposing business/educational/multimedia projectors for a while. Before the inkscape v1.3 release, the patterns were displayed using a layer aware pdf reader (mostly adobe acrobat reader or evince depending on operating system, a few people were using competing vector graphics programs). In that time, inkscape was still being used (after pre-processing) for making fit adjustments and other modifications, but, since the 1.3 release, inkscape is proving to be an excellent (and free) one program for everything, it just needs a few minor improvements. The small bit of code I have right now implements what some pdf readers call "night mode", which just inverts all the colors used - you get a black background, black text becomes white, red becomes a cyan like color, etc - by combining the color->negative extension and changing the page background color (because that is not changed with the existing negative extension) into one single menu item. We have people planning/working on other small efficiency type improvements - solving minor annoyance type things.
Thank you for your explanation. It'd be definitely worth to follow the efforts of your group if possible.
Actually two weeks ago I did send a merge request to your repo to show how the filter can be applied without a dummy svg. I think this is a bit nicer. But your code works fine as is, so no worries.
Thank you for your merge request, that is definitely a simpler way (sorry I didn't see it sooner, apparently I need to adjust notification settings). The coding group doesn't have a group chat anywhere, we hang out mostly with the users in a Facebook group, and mostly speak one on one - all of us have way to many projects in addition to work and family obligations, so, it's slow progress. Please check the repo again in a few days, I'll have some updates, at least to the readme, at that point.
I'm part of a small group getting started on an inkstitch like extension for using projectors for sewing patterns. The very small (and, in theory simple) module to invert colors (basically, mimicking evince's and the kindle app's night mode) I'm working on is giving me some fits - no code yet because I can't even find the references I need, at least without resorting to command line, which may not actually solve the problem.
The two problems I need to solve right now
1: Is it possible to programmatically select all (if in gui equivalent of Ctrl+A or Ctrl+Alt+A, or, even better, if it was possible to just select all the visible paths, not text or objects)
2: Is it possible to implement the Colors -> Invert... filter from a python script, using parameters the script sets, without resorting to the inkex command module?
I did find a command line call that kind of does this - it requires the user to have set the filters options in the gui first, and we are trying to avoid requiring that.
Final question before I go too far with how I want things to work, versus how it CAN work, is it possible to set the menu item for the extension to work as a checkbox/toggle (similar to View -> Guides) when writing the extension in python?
It depends how naughty you want to be:
Correct way
build a filter using the objects provided by inkex
Filter(), feColorMatrix() etc and append to defs, then link the url for the filter on the selected object.
Naughty way
Apply your filter of choice to an object, then save the file.
Open the file in a text editor, and copy <filter>.......</filter> text.
use etree to encode that text into an etree element.
Apend that to defs and link the set the object filter url.
The first method is flexible and allows for settings to be adjusted, the 2nd method is a one shot - effectively a copy and paste of an exiting filter.
The attached extension shows the 2nd naughty method.
Appears under Extensions>Apply Filter
for selecting all paths I just use xpath:
all_paths = self.svg.xpath('//svg:path')
Thank you! So, self.svg does work differently than the way I was reading the docs - to me it implied that self.svg was not populated unless the user had already selected something (in my defense, I was tired when going through that, I know better than to read the docs on a language that I'm still learning when I'm tired). As for the naughty way on the filter, that is absolutely not an option, this has to be an on/off at will, so, I guess I'm building a filter (even though one already exists that does what I need, working out the color math should be fun, unless someone can point to where the code for the Invert... filter is, I found one example that uses the rgb tuple to do the math, so, might just need to dive deeper into that part of the inkex docs).
Edit: I just found that the Negative extension actually does the path color inversion I need much better than the Invert... filter (it's not a complete solution to what I'm needing to do, but examining the code has explained a few things for me, including simplifying the color math).
You can still toggle no problem.
Just to explain.
Filters <filter> are definitions which sits inside the <svg><defs> element.
The filter is applied to the object with a filter url entry in the style attribute of the object in question.
Adding or removing / changing that entry simply changes which predefined filter is being pointed to.
Since the invert filter you are using is never going to change ? It's sufficient to have a single filter for that purpose in <defs> with a unique ID
You can then reference it in any object, or pop it out to remove the filter - or swap to another.
You certainly do not need to build the filter in terms of a simple invert.
If you see the attached extension on the post above - the filter is the copied text from the application of the invert filter - in this case with red/blue invert.
Using Inkscape to generate that code for you is a good idea :)
If you need a better example, say with toggle built in. Let me know.
I really appreciate the work you've done - still need to take a look at your example. I was editing while you were posting, so may have missed a development. The Invert filter doesn't quite give the right color change - we found an option combination that came close, and were willing to work with that - although building our own would have been a better solution - but, the Negative extension does invert the way we were looking for, found that just a little while ago. If you have the time, I would absolutely love an example showing how to do the toggle and/or assigning shortcut keys within the extension, it would save me from having to dig through the inx specifications, but only if you have the time, I'm sure it's in the specification somewhere.
The negative extension is not a filter, it will only work with vector information ( it cannot affect bitmaps for example )
To add a shortcut for any extension.
Edit>Preferences>Interface>Keyboard and search for 'negative'. You will find Extensions (no prefs) Negative. Click the Shortcut column to add a shortcut.
For a toggleable filter of your choosing, the following code will do it.
All you have to do is apply a filter to an object in a brand new file. Then copy the
<filter>.......</filter>
section into the code belowThe code will toggle the filter. You can find it as above in the shortcut preferences in the same way.
Oooooo, toggling is simpler than I thought. Is there a way to change the menu entry to show that it's on? Something like a checkbox that fills when it's on and empties when it's off (see attachment), or, even just a Filter On/Filter Off flip?
That sounds quite interesting. Is there a repository you can link to? I'm curious :)
Only if you use a custom gui. Inx files cannot change their content dynamically. You could call the menu point
toggle filter
if you want to avoid a custom gui.Hi Kaalleen, the repository only has a very very alpha version right now, still working to optimize the code, it's crazy slow and gets kind of weird with patterns with lots of paths (and the readme assumes you already know about projector sewing, I'm not very good with making readme files). Are you more interested in the code, and how it will help with projector sewing, or projector sewing in general? I want to answer your questions properly.
Duh! Didn't even think to call it `toggle filter`, that will definitely smooth things a bit. A custom gui will come into play with some of the later modules, probably, as there will be some that need input, and we're looking into the possibility of having a floating dialog that will release focus, if it can be made fairly small, maybe with some icons instead of labels (more like an undocked/floating toolbar than anything).
I am interested in both. Projector sewing in general and the code as well.
I haven't done projector sewing myself (yet), but I heard about it quite a while ago and thought this was very interesting and worth a try.
So hearing now, that Inkscape is the tool of your choice makes it even more interesting. So I was curious which adaptions are needed to make it work well with Inkscape.
Sorry for the delay, too many projects in the works. Projector sewing is using a projector as a second screen to display a pdf format pattern instead of printing and taping it together. The idea has gotten a lot more popular in the last year thanks to the Ditto system being released, but there is an older segment that has been repurposing business/educational/multimedia projectors for a while. Before the inkscape v1.3 release, the patterns were displayed using a layer aware pdf reader (mostly adobe acrobat reader or evince depending on operating system, a few people were using competing vector graphics programs). In that time, inkscape was still being used (after pre-processing) for making fit adjustments and other modifications, but, since the 1.3 release, inkscape is proving to be an excellent (and free) one program for everything, it just needs a few minor improvements. The small bit of code I have right now implements what some pdf readers call "night mode", which just inverts all the colors used - you get a black background, black text becomes white, red becomes a cyan like color, etc - by combining the color->negative extension and changing the page background color (because that is not changed with the existing negative extension) into one single menu item. We have people planning/working on other small efficiency type improvements - solving minor annoyance type things.
Thank you for your explanation. It'd be definitely worth to follow the efforts of your group if possible.
Actually two weeks ago I did send a merge request to your repo to show how the filter can be applied without a dummy svg. I think this is a bit nicer. But your code works fine as is, so no worries.
Thank you for your merge request, that is definitely a simpler way (sorry I didn't see it sooner, apparently I need to adjust notification settings). The coding group doesn't have a group chat anywhere, we hang out mostly with the users in a Facebook group, and mostly speak one on one - all of us have way to many projects in addition to work and family obligations, so, it's slow progress. Please check the repo again in a few days, I'll have some updates, at least to the readme, at that point.
> all of us have way to many projects in addition to work and family obligations
Sounds so familiar :)
> Please check the repo again in a few days, I'll have some updates, at least to the readme, at that point.
I will, thank you :)