Re: SVG to PNG

Bob Friesenhahn <[email protected]> Sat, 14 Nov 2020 09:16:25 -0600 (CST)
Newsgroups gmane.comp.video.graphicsmagick.help
Message-ID <[email protected]>
On Sat, 14 Nov 2020, Pro Turm wrote:

> (StaticModules[index].name_length == name_length)
>
> My problem is the above line (346) in static.c. The name_length is 7
> (svg+xml), which is the mime type of the svg, whereas the
> StaticModules.name_length is 3 - SVG.
> Since this is the case, the module is not registered, and svg doesnt
> work. I can bruteforcefully fix it (by adjusting the string in
> StaticModules),
> but I want to understand how it is intended to work?

GraphicsMagick is driven by a 'magick' string which is not a MIME type 
string.  If you need to go from a MIME type string to a 'magick' 
string, you may need to provide your own translation.  There is a 
MagickToMime() function, but for some reason there is not a 
MimeToMagick() function.

The following is a brief summary as to how things "work":

Any C program should be invoking InitializeMagick() or 
InitializeMagickEx().  InitializeMagickEx() invokes 
InitializeMagickInfoList() which invokes InitializeMagickModules(). 
There are two different implementations of InitializeMagickModules().

If the build is a static build (not based on loadable DLL modules) 
then the implementation used should be the one from magick/static.c.

In magick/static.c there is a static array called StaticModules[], 
which provides the mappings between 'magick' identifier strings (e.g. 
"SVG") and the coder register/unregister functions.  A little farther 
down in the code we seen an OpenModule() function.  If the build was a 
DLL module based build, then there is a different OpenModule() 
function which would be used (from magick/module.c).

The driving force behind everything (after initialization) is 
GetMagickInfo() in magick/magick.c.

If GetMagickInfo() is invoked with its 'name' argument set to "SVG", 
and if the module supporting "SVG" was not yet loaded, then 
OpenModule() is invoked and 'name' is passed as an argument.  If the 
module was not already opened, then the module registration function 
is invoked.  The difference between the "static" module loader and the 
dynamic module loader is that with the static module loader, the 
callback function is already available because it is a static build. 
If loadable modules were used, then the module is located and loaded, 
and then we use an operating system specific method to get the 
addresses of the module register/unregister functions.

A goal of the above is to avoid doing as little work as possible. 
Given a large number of modules, we don't want to be executing code 
from modules which are not actually used.  If we are using a dynamic 
modules build, then we don't want to even load the code from the 
module (and the DLLs/libraries it depends on) if it is not being used. 
The only time we attempt to initialize all of the modules is when we 
are producing a list of available modules or supported formats.

Now looking at the problem from a different direction, we can start 
with ReadImage() in magick/constitute.c.  ReadImage() is provided with 
an ImageInfo argument which can be used to provide options such as the 
file name to read.  In this function we see that there is code which 
looks at the filename prefix or suffix, and then intuits the file 
'magick' from the provided filename.  The input file is also opened 
and the file header is "tasted" to see if it can be identified by the 
first part of the file content (see GetMagickFileFormat() in 
magick/magic.c for how that is done).

Once the all-important 'magick' string has been determined, then we 
see that GetMagickInfo() is called.  As described above, 
GetMagickInfo() will cause the supporting module to be loaded and 
registered if it is not already.  If GetMagickInfo() succeeds, then we 
move on ahead.  Things get a bit complicated because the input could 
be from a file, or from a pipe/socket and we need to make sure that 
the decoder can handle what is provided to it.  Once everything is 
read, we invoke the registered decoder callback function to actually 
read the file (in the case of SVG it reads the XML file, translates it 
to MVG, and then renders the MVG).

After describing all of the above, it should be seen that there is a 
subtle (yet huge) difference between a "static" build and a DLL 
modules build.  In the Visual Studio build, a few pre-processor 
definitions guide how the code should be compiled.  If the 
pre-processor definitions applied are wrong, then things won't work.

Please see a comment around line 454 of magick/studio.h which provides 
some info about the pre-processor definitions provided by the Visual 
Studio project files and how they are used.

Bob
-- 
Bob Friesenhahn
[email protected], http://www.simplesystems.org/users/bfriesen/
GraphicsMagick Maintainer,    http://www.GraphicsMagick.org/
Public Key,     http://www.simplesystems.org/users/bfriesen/public-key.txt