Похоже, 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 .