3

При связывании растровой графики PNG из документов Inkscape SVG кажется, что Inkscape всегда настаивает на записи абсолютного пути к PNG-графике в файл. Это имеет много недостатков (которые, очевидно, могут быть смягчены путем ручного редактирования файла SVG в текстовом редакторе после каждого сохранения, но это не может быть идеей для графического редактора, такого как Inkscape):

  • Я не могу переместить каталог с моей графикой, не нарушая SVG.
  • Я не могу сохранить каталог с моей графикой в переносной памяти для работы на нем с разных компьютеров, поскольку переносному устройству будут назначены разные буквы дисков.
  • Я не могу редактировать графику из разных операционных систем, поскольку они могут монтировать раздел, в котором хранятся файлы SVG и графику PNG, в разных точках монтирования.
  • Я не могу предоставить каталог с моей графикой коллегам по общему сетевому ресурсу, откуда они могут скопировать его, потому что пути не совпадают.
  • Файлы не могут быть напрямую переданы и переданы через системы контроля версий, такие как SVN или Git по той же причине. По крайней мере, каждый раз, когда кто-то фиксирует измененный файл, строки, содержащие полные пути, будут бессмысленно регистрироваться VCS как изменения.
  • С файлами, которые часто хранятся в домашнем каталоге пользователя, это даже создает риск для конфиденциальности, предоставляя имя пользователя создателя (в рабочих настройках, часто настоящее имя) или другую информацию о файловой системе создателя.

Даже сейчас, когда Inkscape, кажется, использует относительные пути и просто добавляет полный путь в дополнительный атрибут (sodipodi:absref), некоторые из вышеперечисленных проблем все еще существуют (в частности, проблема конфиденциальности не изменилась, как и проблема VCS). ).

Обратите внимание, что я не хочу вставлять данные PNG в документы Inkscape по разным причинам, две из которых:

  • Графика может измениться позже, и более гибко будет иметь изображение PNG в виде отдельного файла PNG, где я могу его отредактировать (и, таким образом, оно будет обновляться автоматически при повторном открытии Inkscape) вместо встраивания данных PNG в SVG. , по- прежнему сохраняя его в качестве дополнительного файла (так что я могу изменить изображение PNG позже) , и каждый раз , когда я изменить PNG; снова внедрить новую версию в Inkscape, вручную изменив ее положение и размер в соответствии с предыдущей версией, а затем удалив предыдущую версию.
  • Различные изображения PNG (например, логотипы или другая графика, связанная с фирменным стилем) используются во множестве документов SVG, поэтому было бы просто пустой тратой места вставить одно такое изображение в каждый отдельный документ SVG, а не хранить его. только один раз и ссылаясь на этот оригинальный рисунок PNG из каждого документа SVG. (И, конечно, усилие из предыдущего элемента умножается на каждый SVG-документ, в котором я использую данную модифицированную растровую графику.)

В качестве обходного пути я подумал о написании сценария, который должен запускаться поверх файлов SVG после сохранения, либо с помощью XSLT, либо с использованием какого-либо традиционного языка, который может загружать SVG. Возможно, это также может быть настроено как предварительная фиксация для вышеупомянутых систем контроля версий. Однако это кажется мне достаточно утомительным, поэтому я хочу пойти на все, только если другого пути нет.

Есть ли способ заставить Inkscape записывать только относительные пути к связанным изображениям в файл SVG? (Также для последнего использованного пути экспорта растрового изображения, если это возможно.)

1 ответ1

1

Это отличный вопрос, и я бы хотел, чтобы у меня было действительно хорошее решение. Все, что я смог придумать, это следующий хакерский скрипт:

#!/usr/bin/perl

use strict;

# usage:
#   relativise_svg.pl foo.svg
# Looks for absolute links in svg file and makes them relative.
# Also checks whether files linked to exist.

use File::Spec; 
use File::Basename;
use Cwd 'abs_path';
my $svg = $ARGV[0];

-e $svg or err("file $svg doesn't exist");
-w $svg or err("file $svg not writeable");

local $/; # slurp whole file

open(F,"<$svg");
my $xml = <F>;
close F;

# Absolute links look like this:
#   xlink:href="file:///home/bcrowell/Documents/writing/books/physics/share/..."
# After we relativise them, they look like this:
#   xlink:href="foo/bar.jpg"

my $cwd = Cwd::getcwd();
my $svg_dir = File::Basename::dirname(abs_path($svg));
my $original_xml = $xml;

my @changes = ();
while ($xml=~m@(file://(/[^'"]*))@g) {
  my $whole = $1;
  my $path = $2;
  my $rel = relativise($path,$svg_dir,$cwd);
  print "changing absolute path in $svg to $rel\n";
  push @changes,[$whole,$rel];
}
foreach my $change(@changes) {
  my $from = quotemeta($change->[0]);
  my $to = $change->[1];
  $xml =~ s/$from/$to/g;
}

while ($xml=~m@xlink:href\s*=\s*"([^'"]*)@g) {
  my $rel = $1;
  if ($rel=~/\.(png|jpg)$/ && !($rel=~/\A#/ || $rel=~/\Adata:;/)) {
    my $abs = File::Spec->rel2abs($rel,$svg_dir);
    -e $abs or err("file $rel doesn't exist, resolved to absolute path $abs");
  }
}

if ($xml ne $original_xml) {
  open(F,">$svg");
  print F $xml;
  close F;
}

sub err {
  my $message = shift;
  print "relativise_svg.pl, working on $svg, ",$message,"\n";
  exit(-1);
}

sub relativise {
  my ($abs,$rel_to,$within) = @_;
  my $rel = File::Spec->abs2rel($abs,$rel_to);
  if (File::Spec->abs2rel($rel,$within)=~/\.\./) {
    err("result, $rel, would have been outside $within");
  }
  return $rel;
}

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .