SVG как тег изображения SVG не работает при использовании с резким - PullRequest
0 голосов
/ 16 октября 2019

Я использую sharp для преобразования файла, но Sharp дает мне пустой файл PNG.

Я хочу использовать SVG-изображение в формате base64 в качестве источника тега <image> и хочу преобразовать его в файл png.

Вот пример, показывающий, что я пытаюсь сделать;

const sharp = require('sharp');
sharp(Buffer.from(<look below js file to see the SVG>))
    .toFormat('png')
    .toFile('output.png')

А вот JS , чтобы показать, что я пытался сделать. По сути, я хочу преобразовать этот SVG-файл в png-файл, используя sharp, но sharp дает пустой png.

1 Ответ

0 голосов
/ 16 октября 2019

Похоже, sharp плохо обрабатывает внешние изображения.

Вы можете попробовать "сплющить" SVG перед передачей его в sharp.

Быстрая и грязная реализация

Это очень подвержено ошибкам. В идеале вы должны использовать что-то вроде Cheerio для анализа и изменения входных данных SVG.

Он также сохраняет только атрибуты x, y, width, height и opacity. Другие атрибуты потребуют дальнейших изменений.

function flattenSVG (svg) {
  const images = svg.match(/<image [^>]+>/g);
  if (!images || images.length < 1) {
    return svg;
  }

  var result = svg;
  images.forEach(image => {
    const [,data] = image.match(/ xlink:href="data:image\/svg\+xml;base64,([^"]+)"/) || [];
    if (!data) {
      return;
    }

    const innerSVG = Buffer.from(data, 'base64').toString();
    const [,width] = image.match(/ width="([^"]+)"/) || [];
    const [,height] = image.match(/ height="([^"]+)"/) || [];
    const [,opacity] = image.match(/ opacity="([^"]+)"/) || [];
    const [,x] = image.match(/ x="([^"]+)"/) || [];
    const [,y] = image.match(/ y="([^"]+)"/) || [];
    const [header] = innerSVG && innerSVG.match(/<svg[^>]+>/) || [];
    const fixedHeader = header
      .replace(/ (x|y|width|height)="([^"]+)"/g, '')
      .replace('<svg', `<svg x="${x}" y="${y}" width="${width}" height="${height}" opacity="${opacity || 1.0}"`);
    const replacement = innerSVG && innerSVG.replace(header, fixedHeader);
    result = result.replace(image, replacement);
  });

  return result;
}

Итак, в вашем коде вы должны использовать что-то вроде:

sharp(Buffer.from(flattenSVG(testSVG)))
      .toFormat('png')
      .toFile('output.png')

Вы можете проверить рабочий код (немного другой для целей тестирования,поскольку он использует буфер вместо вывода файла) в Glitch .

...