Will export the page only (excluding anything outside the page)
However, it does this by cropping, so if you have an object spanning the canvas boundary, it will be cropped not removed.
You would have to write a script to remove objects outside the bounding box of the svg.
From the cli, that would normally involve using --query-all to get all bounding boxes (which includes the svg canvas itself ) and compile a list of ids to remove.
Would require 2 command calls, the first for --query-all and a second to hide or remove the offending objects.
[Edit - the scripting would depend on the OS you are using ]
Well After much hacking around, and looking on Stackoverflow - I managed to hack together this script.
# First lets get the canvas dimensions by exporting to png # We have to do this because query-all gets the drawing dimensions for the svg entry # Which is the smallest bounding box which can contain all objects
# Divide the pixel width and height by the dpi mutiple # It might be necessary to adust the final float value in some cases
svg_pixel_width=$(echo $pixel_width/$dpi_multiple | bc -l ) svg_pixel_height=$(echo $pixel_height/$dpi_multiple | bc -l )
# Remove the temp folder
rm -R ${temp_dir}
# Create an empty string to store the id list we wish to delete id_list_string=""
# This loop checks to make sure the bounding box of each element is within the canvas # Start at 1 rather than 0 to ignore the svg entry line for i in "${query_all_array[@]:1}" do
# This is a simple way to check for the word 'layer' in the object id # This excludes layers from selection list so they are not deleted # It's a hack and will also ingore elements with the work 'layer' in the id # A better way would be: inkscape --actions="select-by-selector:g[inkscape\3A groupmode="layer"];select-list" ./drawing.svg # and process the output, but it requires an additional inkscape command line to be run so would be slower STR=$element_id SUB='layer' if [[ "$STR" == *"$SUB"* ]]; then continue fi
# Test the sides of the element bounding box against the canvas if (( $(echo "$element_left<0" |bc -l) )); then id_list_string+=$element_id, continue elif (( $(echo "$element_right>$svg_pixel_width" |bc -l) )); then id_list_string+=$element_id, continue elif (( $(echo "$element_top<0" |bc -l) )); then id_list_string+=$element_id, continue elif (( $(echo "$element_bottom>$svg_pixel_height" |bc -l) )); then id_list_string+=$element_id, continue else continue fi
done
# Check if there is anything to do ( is id_string_list empty ? )
echo $id_list_string
if [ "$id_list_string" = "" ]; then echo Nothing to do exit else # Lets build a command line id_list_string=${id_list_string:0:-1} $(inkscape --actions="select-by-id:$id_list_string;delete;export-do;" $1) fi
exit
# Remove the last comma id_list_string=${id_list_string:0:-1}
# Lets build a command line $(inkscape --actions="select-by-id:$id_list_string;delete;export-do;" $1)
However it might just be easier to write the script in python - and import inkex which is the Inkscape extension api - you can use it without Inkscape - just with python
Hi.
I want to export the objects inside the page as an individual svg file. When I try to export using the CLI I still get the objects outside the page.
Is there a way to obtain only the objects inside the page or delete the objects outside the page?
Also, is there a way to select the objects inside the page?
Thnx
inkscape --actions="export-area-page;export-filename:out.png;export-do" drawing.svg
Will export the page only (excluding anything outside the page)
However, it does this by cropping, so if you have an object spanning the canvas boundary, it will be cropped not removed.
You would have to write a script to remove objects outside the bounding box of the svg.
From the cli, that would normally involve using
--query-all
to get all bounding boxes (which includes the svg canvas itself ) and compile a list of ids to remove.Would require 2 command calls, the first for
--query-all
and a second to hide or remove the offending objects.[Edit - the scripting would depend on the OS you are using ]
Wow! I did not know about query-all.
It solves the problem. Thanks a lot!
I tested this solution. However, it seems that query-all does not provide the position and dimensions of the page.
Is there a way to query that information?
Thanks.
What OS and what script are you using ?
Ubuntu Linux
Well After much hacking around, and looking on Stackoverflow - I managed to hack together this script.
# First lets get the canvas dimensions by exporting to png
# We have to do this because query-all gets the drawing dimensions for the svg entry
# Which is the smallest bounding box which can contain all objects
temp_dir=$(mktemp -d)
temp_filepath=$temp_dir/inkscape_png.png
# Default export dpi is 96, lets times it by 3 to give more accuracy
dpi_multiple=3
png_dpi=$((96*dpi_multiple))
# Lets export the png and read the query-all action into an array in one step
IFS=$'\n' readarray query_all_array -r -d$'\1' <<< $(inkscape --actions="export-dpi:$png_dpi;export-filename:$temp_filepath;export-do;query-all" $1)
# Now lets read the png pixel dimensions into another array (identify is bundled with most Linux distros)
IFS=$'\n' readarray array -r -d$'\1' <<< $(identify -format '%w %h' $temp_filepath)
# Assign png width and height to variables
IFS=$' ' read -r -d$'\1' pixel_width pixel_height <<< "${array[0]}"
pixel_width="$(echo -e "${pixel_width}" | tr -d '[:space:]')"
pixel_height="$(echo -e "${pixel_height}" | tr -d '[:space:]')"
#~ echo $pixel_width
#~ echo $pixel_height
# Divide the pixel width and height by the dpi mutiple
# It might be necessary to adust the final float value in some cases
svg_pixel_width=$(echo $pixel_width/$dpi_multiple | bc -l )
svg_pixel_height=$(echo $pixel_height/$dpi_multiple | bc -l )
# Remove the temp folder
rm -R ${temp_dir}
# Create an empty string to store the id list we wish to delete
id_list_string=""
# This loop checks to make sure the bounding box of each element is within the canvas
# Start at 1 rather than 0 to ignore the svg entry line
for i in "${query_all_array[@]:1}"
do
# ElementId, Left, Top, Width, Height
IFS=$',' read -r -d$'\1' element_id element_left element_top element_width element_height <<< "${i}"
element_right=$(bc <<< "$element_left+$element_width")
element_bottom=$(bc <<< "$element_top+$element_height")
# This is a simple way to check for the word 'layer' in the object id
# This excludes layers from selection list so they are not deleted
# It's a hack and will also ingore elements with the work 'layer' in the id
# A better way would be: inkscape --actions="select-by-selector:g[inkscape\3A groupmode="layer"];select-list" ./drawing.svg
# and process the output, but it requires an additional inkscape command line to be run so would be slower
STR=$element_id
SUB='layer'
if [[ "$STR" == *"$SUB"* ]]; then
continue
fi
# Test the sides of the element bounding box against the canvas
if (( $(echo "$element_left<0" |bc -l) )); then
id_list_string+=$element_id,
continue
elif (( $(echo "$element_right>$svg_pixel_width" |bc -l) )); then
id_list_string+=$element_id,
continue
elif (( $(echo "$element_top<0" |bc -l) )); then
id_list_string+=$element_id,
continue
elif (( $(echo "$element_bottom>$svg_pixel_height" |bc -l) )); then
id_list_string+=$element_id,
continue
else
continue
fi
done
# Check if there is anything to do ( is id_string_list empty ? )
echo $id_list_string
if [ "$id_list_string" = "" ];
then
echo Nothing to do
exit
else
# Lets build a command line
id_list_string=${id_list_string:0:-1}
$(inkscape --actions="select-by-id:$id_list_string;delete;export-do;" $1)
fi
exit
# Remove the last comma
id_list_string=${id_list_string:0:-1}
# Lets build a command line
$(inkscape --actions="select-by-id:$id_list_string;delete;export-do;" $1)
echo $id_list_string
Of course, it does not deal with the consequences of deleting objects which reference other objects.
It might be wise to add an unlink clone action at the beginning of the script.
I've attached a screen shot of what the script does.
If any part of the element pokes out beyond the boundary of the canvas it is removed.
Wow, your script is very instructive!
In the beginning, I thought it was going to be easy. I see now that it requires some knowledge of several tools.
I suppose that the page position and dimensions can also be obtained by parsing the SVG file, right?
Wow, your script is very instructive!
In the beginning, I thought it was going to be easy. I see now that it requires some knowledge of several tools.
I suppose that the page position and dimensions can also be obtained by parsing the SVG file, right?
Wow, your script is very instructive!
In the beginning, I thought it was going to be easy. I see now that it requires some knowledge of several tools.
I suppose that the page position and dimensions can also be obtained by parsing the SVG file, right?
Wow, your script is very instructive!
In the beginning, I thought it was going to be easy. I see now that it requires some knowledge of several tools.
I suppose that the page position and dimensions can also be obtained by parsing the SVG file, right?
Wow, your script is very instructive!
In the beginning, I thought it was going to be easy. I see now that it requires some knowledge of several tools.
I suppose that the page position and dimensions can also be obtained by parsing the SVG file, right?
(some crazy thing happened when I pressed the Submit Reply button.. so my comment got posted many times)
Yes, I've done the multiple post thing before :)
Yes you can parse the SVG file to get the width/height and the viewbox, but it requires another tool.
I had a go using xmlstarlet https://inkscape.org/forums/beyond/actions-query-and-set-attribute-dont-use-the-same-units/
However it might just be easier to write the script in python - and import
inkex
which is the Inkscape extension api - you can use it without Inkscape - just with pythonhttps://inkscape.gitlab.io/extensions/documentation/source/index.html
Certainly using python it would be a lot simpler.