Skip to content
This repository was archived by the owner on Oct 4, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions jpegexport.inx
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>
Copy link
Copy Markdown
Contributor

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?

Copy link
Copy Markdown
Author

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:) Thanks!

<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".
Expand All @@ -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">
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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>
106 changes: 54 additions & 52 deletions jpegexport.py
Original file line number Diff line number Diff line change
Expand Up @@ -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="")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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="")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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="")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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:
https://gitlab.com/Moini/inkscape-guide-tools/-/blob/master/src/guide_creation_tools.py#L51

def effect(self):
"""get selected item coords and call command line command to export as a png"""
Expand All @@ -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}$')
Expand All @@ -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:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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()

Expand All @@ -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)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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]
Expand All @@ -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)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't there a function for this in inkex already?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The 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)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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"""
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exit() should not be needed.


if __name__=="__main__":
_main()