Как конвертировать несколько файлов SVG в PDF-файлы

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

Эти файлы SVG включают в себя:

  • Персидские шрифты
  • Некоторые тексты имеют градиент
  • Внешние файлы SVG в качестве фоновых рисунков или даже изображений.

Я ищу, могу ли я автоматизировать этот процесс с помощью сценария Python или какого-либо инструмента Linux. Буду очень признателен за вашу помощь в данной конкретной ситуации.

Я пробовал использовать Cairosvg и Inkscape, но безуспешно. Есть несколько проблем, с которыми я сталкиваюсь:

  • При использовании Cairosvg персидские шрифты не поддерживаются.
  • При использовании Inkscape градиент текста и внешние файлы SVG не экспортируются (я тоже пробовал --export-area-drawing, безуспешно)

Я использовал этот скрипт Python, но столкнулся с некоторыми проблемами:

svg_files = [f for f in os.listdir(svg_dir) if f.endswith(".svg")]

for svg_file in svg_files:
    base_name = os.path.splitext(svg_file)[0]
    svg_path = os.path.join(svg_dir, svg_file)
    pdf_path = os.path.join(temp_pdf_dir, f"{base_name}.pdf")

    subprocess.run(["rsvg-convert", "-f", "pdf", "-o", pdf_path, svg_path])

pdf_files = [
    os.path.join(temp_pdf_dir, f)
    for f in os.listdir(temp_pdf_dir)
    if f.endswith(".pdf")
]
subprocess.run(["pdftk"] + pdf_files + ["cat", "output", final_pdf_path])

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

Вот несколько примеров того, как я использовал пользовательские шрифты, градиенты и изображения в своем SVG-файле:

<svg width = "273mm" height = "165mm" xmlns = "http://www.w3.org/2000/svg">
    <style>
        @font-face {
            font-family: "Gungsuh W33 Regular";
            src: url("/path/fonts/Gungsuh W33 Regular.woff") format("woff");
        }
    </style>
    <defs>
        <pattern id = "imagePattern" patternUnits = "userSpaceOnUse" width = "91mm" height = "55mm">
            <image href = "/path/image.svg" x = "0" y = "0" width = "91mm" height = "55mm" />
        </pattern>
        
        <linearGradient id = "gradient" x1 = "0%" y1 = "0%" x2 = "100%" y2 = "0%">
            <stop offset = "0%" style = "stop-color:rgb(220,50,50); stop-opacity:1" />
            <stop offset = "100%" style = "stop-color:rgb(62,62,150); stop-opacity:1" />
        </linearGradient>
    </defs>
...
    <rect x = "182mm" y = "0mm" width = "91mm" height = "55mm" fill = "url(#imagePattern)" />
    <text x = "46mm" y = "67.25mm" font-family = "Gungsuh W33 Regular" font-size = "10" letter-spacing = "2.5" fill = "url(#gradient)">
</svg>

PDF не использует графику SVG, а использует альтернативные методы, которые плохо переводятся, если только они не являются очень простыми. Таким образом, шрифты SVG, такие как эмодзи, должны быть преобразованы в изображения поверх обычного текста (очень неэффективно, поскольку возможно использование килобайтов для 1 однобайтового символа). Как и в случае с кругом, в SVG это 1 элемент, но в PDF его должно быть 4, и поэтому он может стать в десятки раз больше. Что касается градиентов, они часто плохо преобразуются во множество полос, а не в собственный объект градиента PDF. Очевидно, что один из более простых методов заключается в том, что SVG - это система HTML, использующая HTML-страницы и позволяющая это сделать эффективному конвертеру HTML в PDF.

K J 29.08.2024 15:07

Не то чтобы librsvg был очень ясен. НЕ «заменяет промышленные механизмы рендеринга SVG в современных веб-браузерах». github.com/GNOME/…

K J 29.08.2024 15:19

Спасибо. осознание этого очень помогло. Думаю, мне придется использовать HTML.

Alireza Saffariyan 29.08.2024 17:48

Попробуйте изучить Apache FOP: xmlgraphics.apache.org/fop/dev/design/svg.html

chrwahl 29.08.2024 22:16
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
4
78
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, что возможным подходом было бы просто создать html-файл, создать 1 или 2 страницы по вашему выбору и попытаться распечатать его с помощью встроенной печати Chrome, чтобы проверить, нравится ли вам стиль, вы можете использовать CSS для полей, и если эти страницы Кажется, вам это нравится, тогда вы можете использовать JS, чтобы сделать эти страницы динамическими, при этом обновляются только svgs. поместите их в один HTML-файл, и я думаю, что касается вашего конечного продукта, существует множество библиотек Python, которые могут конвертировать эти HTML-файлы в PDF-файлы. Это лучшее решение, если что-то ни в чем не поддерживается. вы можете использовать библиотеку Python и организовать ее. Вот демонстрация того, как будет выглядеть код:

import asyncio
from pyppeteer import launch

async def generate_pdf(html_file, pdf_output):
    browser = await launch()
    page = await browser.newPage()
    
    # Load your HTML file (local or remote)
    await page.goto(f'file://{html_file}', {'waitUntil': 'networkidle0'})
    
    # Generate PDF with specific settings
    await page.pdf({
        'path': pdf_output,
        'format': 'A4',
        'landscape': True,
        'printBackground': True,  # Ensures background images and colors are included
        'margin': {
            'top': '20mm',
            'bottom': '20mm',
            'left': '25mm',
            'right': '25mm'
        }
    })
    
    await browser.close()

# Run the script
html_path = '/path/to/your/input.html'
output_pdf = '/path/to/your/output.pdf'

asyncio.get_event_loop().run_until_complete(generate_pdf(html_path, output_pdf))

Здесь вам не нужно создавать несколько HTML-файлов, а автоматизировать один HTML-файл, который в конечном итоге может распечатать несколько страниц в одном PDF-файле.

Спасибо за ответ. Я также попробовал этот подход, но он мне не понравился, поскольку это проект печати, и он должен быть очень высокого качества, и, честно говоря, наша команда дизайнеров использует CorelDraw для разработки одной из страниц и предоставления мне вывода в формате SVG. Затем я использую Python для создания нескольких его версий, редактируя цвета, текст и некоторые другие элементы. У меня также есть шрифты с расширением woff и другие изображения в виде файлов SVG в каталогах, и я включил пути в SVG, который создаю с помощью Python.

Alireza Saffariyan 29.08.2024 10:35

Привет, если у вас возникла проблема с тем, что шрифт или изображение, которое вы импортируете по пути, не отображаются, вы можете преобразовать эти файлы в двоичную строку base64 и включить ее в путь к файлу, например: <image href = "data:image/png;base64,yourBase64String" /> или для шрифтов вы можете изменить изображение на шрифт и png в woff или другой формат, хотя они могут занимать больше места по сравнению с оригиналом, но это гарантирует правильную загрузку файла. Вы можете использовать библиотеку Python base64.

Rohit Rajput 29.08.2024 12:09

Большое спасибо за ваш ответ и комментарий. Думаю, мне все-таки придется заставить его работать с HTML.

Alireza Saffariyan 29.08.2024 17:49

Другие вопросы по теме