Problem with document base / xlink:href and embbed images
Hello everyone,
I just tried to embed images in a new Inkscape document, created with a recent SVN build of Inkscape, and it did not work. Here is the problem (it's quite tricky):
The SVG document comes from a computer with a different directory organization. It has images linked in it, that are in the same directory that the document. I open it on my machine and copy parts of it (some paths + some bitmaps) to a new, untilted document. Inkscape copies the images with xlink:href containing a relative link to the image (just the name in this case) and sodipodi:absref which is not valid anymore (it contains the directory structure of the other machine). In the new document, images initially appear as broken links since the absref is not valid and the document has not been saved, hence the root is unknown.
I save this new document next to the orignal one, so that the relative links are respected. Once saved, the xlink:href become valid but the images are still show as broken. I have to reopen the document to see the images (which is probably a problem in itself).
In the XML editor, just to be sure, I deleted the sodipodi:absref elements which were not valid anyway.
Then I tried to embbed the images and Inkscape complained saying "No xlink:href or sodipodi:absref attributes found, or they do not point to an existing file! Unable to embed image. Sorry we could not locate /Applications/Inkscape.app/ u_velocity_bottom.png" The absref attributes are not there so that's fine but the xlinks are valid. However Inkscape looks for images in /Applications/ Inkscape.app which is the default location where documents are saved on OS X. If I remember well there was a document root attribute that was removed some time ago. I suspect that embbed bitmaps was looking for the images as document root+xlink and since document root is inexistant the default is used. This means that embbed images only works when sodipodi:absref is present, now that document root does not exists. This seems like a bug to me but the problem was complicated so I would prefer having your advice. Did I explained it clearly?
Well currently I'll have to rewrite the sodipodi:abserf by hand and it will solve the problem but the solution may be quite hard to find for somebody who does not want to dive in the XML editor.
JiHO --- http://jo.irisson.free.fr/
On 9/22/07, jiho <jo.irisson@...400...> wrote:
on OS X. If I remember well there was a document root attribute that was removed some time ago. I suspect that embbed bitmaps was looking for the images as document root+xlink and since document root is inexistant the default is used. This means that embbed images only works when sodipodi:absref is present, now that document root does not exists.
No it's not how it works. Only the XML attribute for base dir was removed, but the base dir is still part of the document in memory. It is only empty for newly created and unsaved docs (and in that situation it was empty before the attribute was removed, so nothing changed). See the algorithm in sp-image.cpp (filename is xlink:href, base is the base dir):
if (!g_path_is_absolute (filename)) { /* try to load from relative pos combined with document base*/ docbase = base; if (!docbase) docbase = "."; fullname = g_build_filename(docbase, filename, NULL);
// document base can be wrong (on the temporary doc when importing bitmap from a // different dir) or unset (when doc is not saved yet), so we check for base+href existence first, // and if it fails, we also try to use bare href regardless of its g_path_is_absolute if (g_file_test (fullname, G_FILE_TEST_EXISTS) && !g_file_test (fullname, G_FILE_TEST_IS_DIR)) { pixbuf = Inkscape::IO::pixbuf_new_from_file( fullname, NULL ); g_free (fullname); if (pixbuf != NULL) return pixbuf; } }
/* if the above failed, try filename as absolute */ if (g_file_test (filename, G_FILE_TEST_EXISTS) && !g_file_test (filename, G_FILE_TEST_IS_DIR)) { pixbuf = Inkscape::IO::pixbuf_new_from_file( filename, NULL ); if (pixbuf != NULL) return pixbuf; }
Only if all that fails, sodipodi:absref is used as a last resort, so its presence should not affect anything.
This code is pretty easy to understand, so if you can suggest any fixes or improvement to this code based on your situation (without breaking of the way it now works) it will be appreciated.
Hello,
Sorry to get back on this so late.
On 2007-September-22 , at 20:46 , bulia byak wrote:
On 9/22/07, jiho <jo.irisson@...400...> wrote:
on OS X. If I remember well there was a document root attribute that was removed some time ago. I suspect that embbed bitmaps was looking for the images as document root+xlink and since document root is inexistant the default is used. This means that embbed images only works when sodipodi:absref is present, now that document root does not exists.
No it's not how it works. Only the XML attribute for base dir was removed, but the base dir is still part of the document in memory. It is only empty for newly created and unsaved docs (and in that situation it was empty before the attribute was removed, so nothing changed). See the algorithm in sp-image.cpp (filename is xlink:href, base is the base dir):
if (!g_path_is_absolute (filename)) { /* try to load from relative pos combined with
document base*/ docbase = base; if (!docbase) docbase = "."; fullname = g_build_filename(docbase, filename, NULL);
// document base can be wrong (on the temporary doc
when importing bitmap from a // different dir) or unset (when doc is not saved yet), so we check for base+href existence first, // and if it fails, we also try to use bare href regardless of its g_path_is_absolute if (g_file_test (fullname, G_FILE_TEST_EXISTS) && !g_file_test (fullname, G_FILE_TEST_IS_DIR)) { pixbuf = Inkscape::IO::pixbuf_new_from_file( fullname, NULL ); g_free (fullname); if (pixbuf != NULL) return pixbuf; } }
/* if the above failed, try filename as absolute */ if (g_file_test (filename, G_FILE_TEST_EXISTS) &&
!g_file_test (filename, G_FILE_TEST_IS_DIR)) { pixbuf = Inkscape::IO::pixbuf_new_from_file ( filename, NULL ); if (pixbuf != NULL) return pixbuf; }
Only if all that fails, sodipodi:absref is used as a last resort, so its presence should not affect anything.
This code is pretty easy to understand, so if you can suggest any fixes or improvement to this code based on your situation (without breaking of the way it now works) it will be appreciated.
Indeed this code is quite understandable and does what I would theoretically expect. It even works "for real" since the image was correctly shown when I reopened the document ;). The problems are then:
1- When is this code called. I re-tested the problem. A quick summary: copy an image with a bad absref but a correct href to a new document, save the document next to the original one so that the absref is still wrong but the href is right: the image does not show in the new doc. There are three solutions to make the images appear: close and reopen the doc, open image properties change the name and change it back to the original, or change it in the xml editor and change it back. I suspect the code above is called on these three occasions. So Inkscape gets it right eventually. It just does not "seem" right when copy-pasting the image. This code probably shouldn't be called on a regular basis since it could be quite resource hungry on a document with lots of bitmaps. But maybe it should be called after saving the doc, this would allow to resolve the dependencies which where wrong on a new document but right after it has been saved (like in my case). I don't know if saving th doc changes anything in the representation in memory though (is "docbase" changed?). An other, more powerful, solution may be to set a flag on the <image> element, telling if it has been found or if the link is dead. Then this code should be called when an image with a dead link is clicked. This would allow to solve problems where people move the image and then move it back afterwards, realizing they did something wrong, or any other similar trouble.
2- This is apparently not used by the "Embed All Images" extension. Here the problem seems different in fact, and I can reproduce it with a completely new document: . create a new doc . save it somewhere which is not the default location . put a bitmap along side it . import the bitmap in inkscape . delete the absref property of the bitmap (. save) . try to Embed All Images -> "No xlink:href or sodipodi:absref attributes found, or they do not point to an existing file! Unable to embed image. Sorry we could not locate /Applications/Inkscape.app/Picture.png" So "docbase" seems to be set to /Applications/Inkscape.app (on OS X at least, it is different in the other OSes. This location is the default save location for new docs) no matter where the document is actually saved. Hence, unless the bitmap is actually in the default location, it only leaves the absref as a last resort. When the absref is absent or wrong, one cannot embed bitmaps anymore. I don't really know how extensions work internally but, from what I understood, they are fed with the whole document, do their things in a temporary location and return the whole document possibly modified to Inkscape. Maybe this is where the problems comes from: in the temporary, unsaved, document, the docbase is the default location and not the docbase of the actual document.
I'll be happy to bug-report the second issue if needed but maybe that's just a quick fix. Who did the Embed Images extension?
Cheers,
JiHO --- http://jo.irisson.free.fr/
jiho wrote:
Maybe this is where the problems comes from: in the temporary, unsaved, document, the docbase is the default location and not the docbase of the actual document.
More likely that it doesn't check docbase at all, but I would have to check to be sure.
I'll be happy to bug-report the second issue if needed but maybe that's just a quick fix. Who did the Embed Images extension?
I wrote the original script but it has since been modified and inproved by at least one other person. It seems that if we are to fix the problem we need to duplicate the logic that lives inside of Inkscape in this script. You could file a bug for that.
Aaron Spike
On 2007-September-27 , at 14:02 , Aaron Spike wrote:
jiho wrote:
Maybe this is where the problems comes from: in the temporary, unsaved, document, the docbase is the default location and not the docbase of the actual document.
More likely that it doesn't check docbase at all, but I would have to check to be sure.
I'll be happy to bug-report the second issue if needed but maybe that's just a quick fix. Who did the Embed Images extension?
I wrote the original script but it has since been modified and inproved by at least one other person. It seems that if we are to fix the problem we need to duplicate the logic that lives inside of Inkscape in this script. You could file a bug for that.
It would be a shame to have to recode in Python something that is already done in Inkscape core, wouldn't it. An other approach would be: - inkscape checks wether xlink works: looks for the absolute path as docbase+xlink, filepath+xlink, xlink as absolute path (code quote by bulia in previous email) - xlink works? yes -> write the the absolute path found this way to absref (this is the new part: currently the path is only written when the image is imported initially, as far as i can see) no -> fallback on existing absref (and warn?) and then embed bitmap would only use absref to find the bitmaps. This way the extension benefits from the hard work done by the core, which is how they were designed to function I think. Embed bitmaps would only work if sodipodi:absref exists but since both are internal to inkscape, I don't think this is a problem. What do you think?
JiHO --- http://jo.irisson.free.fr/
participants (3)
-
Aaron Spike
-
bulia byak
-
jiho