5

I am trying to create svg image using svg raw data which i am getting from fabric js. I have used below code to generate the svg using svg raw data but its not working properly.

public function generate_svg($raw_svg='',$prefix='',$folder_name='card_image')
{
    $file_name = '';       
    if($raw_svg!='')
    {
        try{           
            $file_name = uniqid($prefix).".svg";
            $image = new \Imagick();
            $image->readImageBlob($raw_svg);
            $image->setImageFormat("svg");
            $image->writeImage($folder_name.$file_name);
        } catch (ImagickException $ex) {
            echo $ex->getMessage();
        }
    }
     return $file_name;
}

Now the issue is background image is kind of Look like below:

enter image description here

So what should i do to fix that?

It should look like below (ignore the square and round), the issue is whole background looks like black instead of bg image.:

enter image description here

So the issue is background image is not loading, so do i have to add additional library to do that or any thing else?

Imagick Version: 6.7.7

    convert -list delegate | grep svg  

    cdr =>          "uniconvertor' '%i' '%o.svg'; /bin/mv '%o.svg' '%o"
    cgm =>          "uniconvertor' '%i' '%o.svg'; /bin/mv '%o.svg' '%o"
    dot =>          "dot' -Tsvg '%i' -o '%o"
    dxf =>          "uniconvertor' '%i' '%o.svg'; /bin/mv '%o.svg' '%o"
    fig =>          "uniconvertor' '%i' '%o.svg'; /bin/mv '%o.svg' '%o"
    svg =>          "rsvg-convert' -o '%o' '%i"

 convert -list format | grep SVG

 MSVG  rw+   ImageMagick's own SVG internal renderer
  SVG  rw+   Scalable Vector Graphics (XML 2.9.1)
 SVGZ  rw+   Compressed Scalable Vector Graphics (XML 2.9.1)
DS9
  • 2,995
  • 4
  • 52
  • 102
  • How is it supposed to look? You haven't provided the images. – Mark Setchell Nov 23 '17 at 09:13
  • @MarkSetchell Updated the question. – DS9 Nov 23 '17 at 09:27
  • @MarkSetchell here is the raw data: https://codepen.io/dhavalsisodiya/pen/XewGey – DS9 Nov 23 '17 at 09:32
  • How ever, i am using same raw data to generate png file, the only change in above code is set image format to png24. Earlier i have same issue with png conversation and i have used this one: SVG rw+ Scalable Vector Graphics (XML 2.9.1). So do i need to install any other library which will create svg file. – DS9 Nov 23 '17 at 09:53
  • That is the basic IM converter. Install librsvg (prefered) or Inkscape. ImageMagick should be able to automatically delegate to one of these. You can test for that with `convert -list delegate | grep svg` – ccprog Nov 29 '17 at 17:29
  • @ccprog updated the question. – DS9 Nov 30 '17 at 04:48
  • I only just noticed you want to export to SVG again - sorry, scratch the previous comment. – ccprog Nov 30 '17 at 17:14

3 Answers3

1

I think you are on the wrong track. Image Magick is basically a pixel-oriented library. While rendering the background image might be a question of configuration, your picture shows that the font "embedding" you wanted to achieve isn't happening. And there lies the real problem.

What you want to achieve is representing the font information inside the SVG file. There are two ways to do that, and for both there is absolutely no support in IM:

  • converting the font to the SVG font format and embedding it inline in the file (produces large files)
  • converting all glyphs to paths (texts are no longer editable)

From your description I think you should be aiming for the second variant. You would basically exchange <text> elements in your string with <path> elements and otherwise write out the SVG file including the embeded image data as you received it.

How to convert text to SVG paths? is an older look at that problem.

EasySVG for PHP is a library that resulted from that question for the glyph-to-path conversion, but only provided you have the font already in SVG format. For typical desktop font formats like ttf, you might first have to look at font conversion tools like FontForge.

You might get a direct svg data transformation working via Cairo, but that is only a hunch, I haven't worked with it.

Finally, as a workaround, you could delegate the whole task to Inkscape. It can be called on the command line without starting the GUI as

inkscape in.svg --export-text-to-path --export-plain-svg=out.svg
ccprog
  • 20,308
  • 4
  • 27
  • 44
1

I have ended up by storing fonts in raw svg and after that created svg file using fopen instead of using imagick.

So my svg is look like below:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="600" height="400" viewBox="0 0 600 400" xml:space="preserve">
<desc>Created with Fabric.js 2.0.0-beta7</desc>
<defs>
<style>
    //... base64 data of font
    @font-face {
        font-family: "Elsie";
        src: url("data:application/font-truetype;charset=utf-8;base64,...")
    }
</style>
</defs>

After that i have created svg file using below:

$file_name = uniqid($prefix).".svg";
$file_handle = fopen("$folder_name/".$file_name, 'w');
fwrite($file_handle, $raw_svg);
fclose($file_handle);
DS9
  • 2,995
  • 4
  • 52
  • 102
  • I'm curious about the file sizes you get that way. Does base64-encoding reduce the size of a ttf? – ccprog Dec 01 '17 at 16:41
  • @ccprog base64-encoding increase the file size. But using that method all fonts are loading into final svg image. – DS9 Dec 02 '17 at 04:52
0

In addition to @ccprog's fantastic answer, I'd like to mention you can generate the pixels you want using phantomjs, just feed the phantomjs with your input html file and output as a png.

Felipe Valdes
  • 1,998
  • 15
  • 26