Inkscape.org
Beyond the Basics Export SVG without objetct outside the page using CLI
  1. #1
    Raul D Durand Raul D Durand @raul.durand

    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

  2. #2
    inklinea inklinea @inklinea⛰️
    *

     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 ]

  3. #3
    Raul D Durand Raul D Durand @raul.durand

    Wow! I did not know about query-all.

    It solves the problem. Thanks a lot!

  4. #4
    Raul D Durand Raul D Durand @raul.durand

    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.

  5. #5
    inklinea inklinea @inklinea⛰️

    What OS and what script are you using ? 

  6. #6
    Raul D Durand Raul D Durand @raul.durand

    Ubuntu Linux

  7. #7
    inklinea inklinea @inklinea⛰️

    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


     

  8. #8
    inklinea inklinea @inklinea⛰️
    *

    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.

     

    Remove Outside Elements
  9. #9
    Raul D Durand Raul D Durand @raul.durand

    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?

  10. #10
    Raul D Durand Raul D Durand @raul.durand

    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?

  11. #11
    Raul D Durand Raul D Durand @raul.durand

    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?

  12. #12
    Raul D Durand Raul D Durand @raul.durand

    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?

  13. #13
    Raul D Durand Raul D Durand @raul.durand

    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?

  14. #14
    Raul D Durand Raul D Durand @raul.durand

    (some crazy thing happened when I pressed the Submit Reply button.. so my comment got posted many times)

  15. #15
    inklinea inklinea @inklinea⛰️

    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 python

    https://inkscape.gitlab.io/extensions/documentation/source/index.html

    Certainly using python it would be a lot simpler. 

     

Inkscape Inkscape.org Inkscape Forum Beyond the Basics Export SVG without objetct outside the page using CLI