-
Notifications
You must be signed in to change notification settings - Fork 25
Update for InkScape 1.0 #27
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,13 @@ | ||
| <inkscape-extension> | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> | ||
| <_name>JPEG Export</_name> | ||
| <id>id.giac.export.jpg</id> | ||
| <dependency type="executable" location="extensions">jpegexport.py</dependency> | ||
| <param name="path" type="string" _gui-text="Export path" _gui-description="Full path to your file, e.g. 'C:\Users\User_Name\Documents\myimage.jpg'"></param> | ||
| <id>fablabchemnitz.de.jpegexport</id> | ||
| <dependency type="executable" location="extensions">fablabchemnitz_jpegexport.py</dependency> | ||
| <param name="path" type="path" _gui-text="Export path" _gui-description="Full path to your file, e.g. 'C:\Users\User_Name\Documents\myimage.jpg'" filetypes="jpg" mode="file_new">C:\Users\</param> | ||
| <param name="bgcol" type="string" _gui-text="Background color (leave blank for white)" _gui-description="Background color hex code, e.g. '#abc123'"></param> | ||
| <param name="quality" type="int" min="0" max="100" _gui-text="Quality %" _gui-description="JPG compression quality">100</param> | ||
| <param name="density" type="int" min="30" max="2400" _gui-text="Resolution (ppi)" _gui-description="Recommended: 90 (screens) or 300 (print)">90</param> | ||
| <param name="page" type="boolean" _gui-text="Export whole page" _gui-description="If checked, the whole page will be exported, else the selection.">false</param> | ||
| <param name="page" type="boolean" _gui-text="Export whole page" _gui-description="If checked, the whole page will be exported, else the selection.">true</param> | ||
| <param name="fast" type="boolean" _gui-text="Fast export (suggested)" _gui-description="Will use an approximate bounding box. If unchecked, export will take longer.">true</param> | ||
| <_param name="usage" type="description" appearance="header">Usage</_param> | ||
| <param name="help" type="description" xml:space="preserve">Select the objects in the drawing that you wish to export, or make a check at "Export whole page". | ||
|
|
@@ -19,10 +20,12 @@ This extension requires that imagemagick is installed, more info and download at | |
| <effect needs-live-preview="false"> | ||
| <object-type>all</object-type> | ||
| <effects-menu> | ||
| <submenu _name="Export" /> | ||
| <submenu _name="FabLab Chemnitz"> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ? |
||
| <submenu _name="Import/Export/Transfer"/> | ||
| </submenu> | ||
| </effects-menu> | ||
| </effect> | ||
| <script> | ||
| <command reldir="extensions" interpreter="python">jpegexport.py</command> | ||
| <command reldir="extensions" interpreter="python">fablabchemnitz_jpegexport.py</command> | ||
| </script> | ||
| </inkscape-extension> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,20 +27,20 @@ | |
| import inkex | ||
| import simpletransform | ||
|
|
||
| inkex.localize() | ||
| inkex.localization.localize | ||
|
|
||
| class JPEGExport(inkex.Effect): | ||
|
|
||
| def __init__(self): | ||
| """Init the effect library and get options from gui.""" | ||
| inkex.Effect.__init__(self) | ||
|
|
||
| self.OptionParser.add_option("--path", action="store", type="string", dest="path", default="", help="") | ||
| self.OptionParser.add_option("--bgcol", action="store", type="string", dest="bgcol", default="#ffffff", help="") | ||
| self.OptionParser.add_option("--quality", action="store", type="int", dest="quality", default="90", help="") | ||
| self.OptionParser.add_option("--density", action="store", type="int", dest="density", default="90", help="") | ||
| self.OptionParser.add_option("--page", action="store", type="inkbool", dest="page", default=False, help="") | ||
| self.OptionParser.add_option("--fast", action="store", type="inkbool", dest="fast", default=True, help="") | ||
| self.arg_parser.add_argument("--path", action="store", type=str, dest="path", default="", help="") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. action="store" and type=str can be removed. A help text would be quite useful, though. It will appear when the extension is used from the command line. |
||
| self.arg_parser.add_argument("--bgcol", action="store", type=str, dest="bgcol", default="#ffffff", help="") | ||
| self.arg_parser.add_argument("--quality", action="store", type=int, dest="quality", default="90", help="") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the int values, a min and max should be indicated. The default values for int entries are something like 0 to 10 (or something similarly useless). |
||
| self.arg_parser.add_argument("--density", action="store", type=int, dest="density", default="90", help="") | ||
| self.arg_parser.add_argument("--page", action="store", type=inkex.Boolean, dest="page", default=False, help="") | ||
| self.arg_parser.add_argument("--fast", action="store", type=inkex.Boolean, dest="fast", default=True, help="") | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dest="" can be removed, too, from all of them, it's not needed. Find an example here: |
||
| def effect(self): | ||
| """get selected item coords and call command line command to export as a png""" | ||
|
|
@@ -61,7 +61,8 @@ def effect(self): | |
| exit() | ||
|
|
||
| outfile=self.options.path | ||
| curfile = self.args[-1] | ||
| curfile = self.options.input_file | ||
| #inkex.utils.debug("curfile:" + curfile) | ||
|
|
||
| # Test if color is valid | ||
| _rgbhexstring = re.compile(r'#[a-fA-F0-9]{6}$') | ||
|
|
@@ -72,7 +73,7 @@ def effect(self): | |
| bgcol = self.options.bgcol | ||
|
|
||
| if self.options.page == False: | ||
| if len(self.selected) == 0: | ||
| if len(self.svg.selected) == 0: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is going to be deprecated again in the next version. Just a heads up - will work with 1.0 and 1.1.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hey. what will be the replacement in newer InkScape? Can you give some point for this? I am working hard to migrate all my used plugins to python 3 where nobody else did it yet. i dont want to do this twice per year :-D
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here's a list of currently known deprecations for 1.1: https://gitlab.com/inkscape/extensions/-/commit/4838d285b01106d243399e6bf36e7956a291eb98 There's also the bounding box thing among them (but it's for the current selection, so maybe not what you need). |
||
| inkex.errormsg(_('Please select something.')) | ||
| exit() | ||
|
|
||
|
|
@@ -94,16 +95,18 @@ def processSelected(self): | |
| scale = self.getUnittouu('1px') | ||
| props=['x', 'y', 'width', 'height'] | ||
|
|
||
| for id in self.selected: | ||
| for id in self.svg.selected: | ||
| if self.options.fast == True: # uses simpletransform | ||
| nodelist.append(self.getElementById(id)) | ||
| nodelist.append(self.svg.getElementById(id)) | ||
| else: # uses command line | ||
| rawprops=[] | ||
| for prop in props: | ||
| command=("inkscape", "--without-gui", "--query-id", id, "--query-"+prop, self.args[-1]) | ||
| command=("inkscape", "--without-gui", "--query-id", id, "--query-"+prop, self.options.input_file) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this actually work? The without-gui option no longer exists. |
||
| proc=subprocess.Popen(command,stdout=subprocess.PIPE,stderr=subprocess.PIPE) | ||
| proc.wait() | ||
| rawprops.append(math.ceil(self.getUnittouu(proc.stdout.read()))) | ||
| proc.stdout.close() | ||
| proc.stderr.close() | ||
| nodeEndX = rawprops[0] + rawprops[2] | ||
| nodeStartY = toty - rawprops[1] - rawprops[3] | ||
| nodeEndY = toty - rawprops[1] | ||
|
|
@@ -122,76 +125,75 @@ def processSelected(self): | |
|
|
||
|
|
||
| if self.options.fast == True: # uses simpletransform | ||
| bbox = simpletransform.computeBBox(nodelist) | ||
| startx = math.ceil(bbox[0]) | ||
| endx = math.ceil(bbox[1]) | ||
| h = -bbox[2] + bbox[3] | ||
| starty = toty - math.ceil(bbox[2]) -h | ||
| endy = toty - math.ceil(bbox[2]) | ||
| bbox = sum([node.bounding_box() for node in nodelist], None) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't there a function for this in inkex already?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm i updated this using the provided tip from deprecation warning. did not find some shorter line for this |
||
| #inkex.utils.debug(bbox) - see transform.py | ||
| ''' | ||
| width = property(lambda self: self.x.size) | ||
| height = property(lambda self: self.y.size) | ||
| top = property(lambda self: self.y.minimum) | ||
| left = property(lambda self: self.x.minimum) | ||
| bottom = property(lambda self: self.y.maximum) | ||
| right = property(lambda self: self.x.maximum) | ||
| center_x = property(lambda self: self.x.center) | ||
| center_y = property(lambda self: self.y.center) | ||
| ''' | ||
| startx = math.ceil(bbox.left) | ||
| endx = math.ceil(bbox.right) | ||
| h = -bbox.top + bbox.bottom | ||
| starty = toty - math.ceil(bbox.top) -h | ||
| endy = toty - math.ceil(bbox.top) | ||
|
|
||
| coords = [startx / scale, starty / scale, endx / scale, endy / scale] | ||
| return coords | ||
|
|
||
| def exportArea(self, x0, y0, x1, y1, curfile, outfile, bgcol): | ||
| tmp = self.getTmpPath() | ||
| command="inkscape -a %s:%s:%s:%s -d %s -e \"%sjpinkexp.png\" -b \"%s\" %s" % (x0, y0, x1, y1, self.options.density, tmp, bgcol, curfile) | ||
|
|
||
| p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | ||
| command="inkscape --export-area %s:%s:%s:%s -d %s --export-filename \"%sjpinkexp.png\" -b \"%s\" \"%s\"" % (x0, y0, x1, y1, self.options.density, tmp, bgcol, curfile) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inkscape also has export functions that will use the same Inkscape and environment that is currently in use. I couldn't make it work on Windows, but here's a link that uses it and works on Linux: https://gitlab.com/Moini/nextgenerator/-/blob/master/next_gen.py#L125
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (If you figure out why this doesn't work on Windows, I'd be very glad for the help, see https://gitlab.com/Moini/nextgenerator/-/issues/5 ) |
||
| p = subprocess.Popen(command, shell=True) | ||
| return_code = p.wait() | ||
| f = p.stdout | ||
| err = p.stderr | ||
|
|
||
| self.tojpeg(outfile) | ||
| #inkex.utils.debug("command:" + command) | ||
| #inkex.utils.debug("Errorcode:" + str(return_code)) | ||
|
|
||
| def exportPage(self, curfile, outfile, bgcol): | ||
| tmp = self.getTmpPath() | ||
| command = "inkscape -C -d %s -e \"%sjpinkexp.png\" -b\"%s\" %s" % (self.options.density, tmp,bgcol, curfile) | ||
|
|
||
| p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | ||
| command = "inkscape --export-area-drawing -d %s --export-filename \"%sjpinkexp.png\" -b \"%s\" \"%s\"" % (self.options.density, tmp, bgcol, curfile) | ||
| p = subprocess.Popen(command, shell=True) | ||
| return_code = p.wait() | ||
| f = p.stdout | ||
| err = p.stderr | ||
|
|
||
| self.tojpeg(outfile) | ||
|
|
||
|
|
||
| #inkex.utils.debug("command:" + command) | ||
| #inkex.utils.debug("Errorcode:" + str(return_code)) | ||
|
|
||
| def tojpeg(self,outfile): | ||
| tmp = self.getTmpPath() | ||
| if os.name == 'nt': | ||
| outfile = outfile.encode('string-escape') | ||
|
|
||
| outfile = outfile.replace("\\","\\\\") | ||
| # set the ImageMagick command to run based on what's installed | ||
| if find_executable('magick'): | ||
| command = "magick -sampling-factor 4:4:4 -strip -interlace JPEG -colorspace RGB -quality %s -density %s \"%sjpinkexp.png\" \"%s\" " % (self.options.quality, self.options.density, tmp, outfile) | ||
| command = "magick \"%sjpinkexp.png\" -sampling-factor 4:4:4 -strip -interlace JPEG -colorspace RGB -quality %s -density %s \"%s\" " % (tmp, self.options.quality, self.options.density, outfile) | ||
| # inkex.debug(command) | ||
| elif find_executable('convert'): | ||
| command = "convert \"%sjpinkexp.png\" -sampling-factor 4:4:4 -strip -interlace JPEG -colorspace RGB -quality %s -density %s \"%s\" " % (tmp, self.options.quality, self.options.density, outfile) | ||
| command = "convert \"%sjpinkexp.png\" -sampling-factor 4:4:4 -strip -interlace JPEG -colorspace RGB -quality %s -density %s \%s\" " % (tmp, self.options.quality, self.options.density, outfile) | ||
| # inkex.debug(command) | ||
| else: | ||
| inkex.errormsg(_('ImageMagick does not appear to be installed.')) | ||
| exit() | ||
|
|
||
| p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | ||
| exit() | ||
| p = subprocess.Popen(command, shell=True) | ||
| return_code = p.wait() | ||
| f = p.stdout | ||
| err = p.stderr | ||
| #inkex.utils.debug("command:" + command) | ||
| #inkex.utils.debug("Errorcode:" + str(return_code)) | ||
|
|
||
| def getTmpPath(self): | ||
| """Define the temporary folder path depending on the operating system""" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. inkex comes with functionality for this. |
||
| if os.name == 'nt': | ||
| return 'C:\\WINDOWS\\Temp\\' | ||
| return os.getenv('TEMP') + '\\' | ||
| else: | ||
| return '/tmp/' | ||
|
|
||
| def getUnittouu(self, param): | ||
| try: | ||
| return inkex.unittouu(param) | ||
|
|
||
| except AttributeError: | ||
| return self.unittouu(param) | ||
| return self.svg.unittouu(param) | ||
|
|
||
| def _main(): | ||
| if __name__=="__main__": | ||
| e = JPEGExport() | ||
| e.affect() | ||
| e.run() | ||
| exit() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The exit() should not be needed. |
||
|
|
||
| if __name__=="__main__": | ||
| _main() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi - why did you change id and the submenu where the extension appears? Is this helping users?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry no. i did it change in my own desktop package because i have a lot of extensions and marked all other extension than default with fablab to have better overview of what i put next to them. for this repo we should keep as is/was
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:) Thanks!