PerfectVector
Autor: Irene Kim8 min czytania

CairoSVG: eksport SVG do PDF i PNG we właściwym rozmiarze

Konwertuj grafikę SVG za pomocą CairoSVG, wybierz szerokość wyjściową lub skalę, poznaj działanie DPI i wymiarów kontenera nadrzędnego oraz sprawdź wymiary PNG w pikselach i rozmiar strony PDF przed przekazaniem plików.

Na tej stronie

Użyj cairosvg.svg2png() do eksportu rastrowego, a cairosvg.svg2pdf() do eksportu PDF. Aby uzyskać konkretną szerokość PNG, ustaw output_width; do proporcjonalnego powiększenia użyj scale. Parametr parent_width określa kontener używany do obliczania wymiarów procentowych. Parametr dpi określa zależność między pikselami a jednostkami fizycznymi, więc jego zmiana może różnie wpływać na rozmiary PNG i PDF.

Poniższy przykład zaczyna się od niewielkiego emblematu SVG i sprawdza pliki utworzone przy poszczególnych ustawieniach. Przyda się projektantom automatyzującym eksport logo i programistom przygotowującym grafikę do dokumentów. CairoSVG renderuje istniejącą zawartość SVG. Nie przekształca logo PNG w edytowalne ścieżki przez wektoryzację.

Zacznij od samodzielnego pliku SVG

Te przykłady uruchomiliśmy w Pythonie 3.12.11 z CairoSVG 2.9.1. Zainstaluj konwerter w przypiętej wersji w środowisku projektu:

python -m pip install "CairoSVG==2.9.1"

CairoSVG wymaga również natywnej biblioteki Cairo. Jeśli instalacja lub import się nie powiedzie, skorzystaj z uwag dotyczących Twojego systemu operacyjnego w dokumentacji instalacji.

Zapisz ten oryginalny emblemat złożony z trzech ścieżek jako emblem.svg. Kwadratowy otwór ułatwia zauważenie brakującej reguły wypełnienia, a wąski pasek pozwala sprawdzić odwzorowanie drobnego szczegółu. To ręcznie przygotowana grafika demonstracyjna, a nie wynik konwersji w PerfectVector.

<svg xmlns="http://www.w3.org/2000/svg"
     width="240" height="120" viewBox="0 0 240 120">
  <path fill="#176b63" fill-rule="evenodd"
        d="M20 100 V20 H100 V100 Z M40 40 V80 H80 V40 Z"/>
  <path fill="#e5a43a" d="M110 100 L160 20 L210 100 Z"/>
  <path fill="#24435d" d="M220 20 H230 V100 H220 Z"/>
</svg>

Wymiary elementu głównego określają wyjściowy obszar wyświetlania. Atrybut viewBox określa prostokątny obszar wewnętrznego układu współrzędnych grafiki. Tutaj oba mają te same proporcje 2:1. Dostosowując przykład do swojego logo, świadomie ustal tę zależność.

Wyeksportuj jeden plik wzorcowy w wymaganym rozmiarze

Zapisz ten kod jako export_emblem.py obok pliku SVG, a następnie uruchom python export_emblem.py:

import cairosvg
 
cairosvg.svg2png(
    url="emblem.svg",
    write_to="emblem-480.png",
    output_width=480,
)
cairosvg.svg2pdf(
    url="emblem.svg",
    write_to="emblem.pdf",
)

Nasz PNG miał 480 × 240 pikseli. Strona PDF miała 180 × 90 punktów, co odpowiada 2,5 × 1,25 cala. To wyniki pomiarów dostarczonego pliku testowego, a nie wymiary, których należy oczekiwać dla każdego SVG.

Odpowiedniki w wierszu poleceń to:

cairosvg emblem.svg --output-width 480 -o emblem-480.png
cairosvg emblem.svg -o emblem.pdf

Dokumentacja API i wiersza poleceń CairoSVG opisuje przekazywanie nazw plików wejściowych przez url, bajtów SVG przez bytestring oraz zapisywanie pliku wyjściowego przez write_to. W CLI rozszerzenie nazwy pliku wyjściowego określa format.

Ilustracja jednego geometrycznego emblematu rozgałęziającego się na dwa eksporty o podobnych proporcjach na obszarach roboczych o różnych rozmiarach
Ilustracja decyzji dotyczącej eksportu: zachowaj wektorowy plik wzorcowy, a następnie wybierz wymagane wymiary dla każdego zestawu przekazywanych plików. Zmierzone wyniki CairoSVG podano poniżej.

Wybierz parametr pasujący do problemu

Opcje o podobnych nazwach odpowiadają na różne pytania. Dokumentacja ustawień rozmiaru CairoSVG rozróżnia kontener nadrzędny i żądane wymiary wyjściowe.

Twoje wymaganieOpcja w PythonieOpcja CLICo sprawdzić
Utwórz PNG o szerokości dokładnie 480 pikselioutput_width=480--output-width 480Wysokość i proporcje grafiki
Podwój obliczone wymiary wyjściowescale=2--scale 2Czy oba wymiary zostały podwojone
Oblicz szerokość lub wysokość elementu głównego wyrażoną procentowoparent_width, parent_height--width, --heightWartość procentową względem podanego kontenera
Zinterpretuj jednostki fizyczne, takie jak caledpi--dpiOsobno wymiary PNG w pikselach i rozmiar fizyczny PDF

Dla naszego pliku źródłowego o wymiarach podanych w pikselach uruchomiliśmy każdą opcję niezależnie:

UstawieniaWymiary PNGWymiary strony PDF
Domyślne240 × 120 px180 × 90 pt
output_width=480480 × 240 px360 × 180 pt
scale=2480 × 240 px360 × 180 pt
dpi=192240 × 120 px90 × 45 pt

Ostatni wiersz pokazuje pułapkę: podwojenie DPI nie zwiększyło liczby pikseli PNG dla tego SVG o wymiarach podanych w pikselach. Sprawiło, że te same wymiary w pikselach zajęły mniej miejsca fizycznego w PDF. Użyj wymiaru wyjściowego, gdy wymaganiem dotyczącym przekazywanego pliku jest liczba pikseli.

Podanie obu wymiarów wyjściowych ustala prostokątny obszar roboczy; nie gwarantuje jednak, że logo szczelnie go wypełni. Nadal mają znaczenie reguły proporcji SVG oraz puste miejsce wewnątrz jego viewBox. Zacznij od jednego wymiaru wyjściowego, jeśli chcesz zachować oryginalne proporcje, a następnie sprawdź wynik.

Wymiary procentowe wymagają kontenera nadrzędnego

Dla kopii pliku testowego, której element główny używa width="50%" height="50%", to wywołanie określa kontener nadrzędny o wymiarach 960 × 480 pikseli:

cairosvg.svg2png(
    url="emblem-percent.svg",
    parent_width=960,
    parent_height=480,
    write_to="emblem-percent.png",
)

Nasz plik wyjściowy miał 480 × 240 pikseli: połowę szerokości i połowę wysokości kontenera nadrzędnego. To wyjaśnia, dlaczego ustawień parent_width=480 i output_width=480 nie można stosować zamiennie.

Jeśli CairoSVG zgłasza, że rozmiar SVG jest niezdefiniowany, najpierw sprawdź wymiary elementu głównego. Nadaj dokumentowi dodatnie wymiary odpowiednie do jego zastosowania lub podaj wymiary kontenera nadrzędnego, gdy zależą od nich wartości procentowe. Nie wnioskuj o zamierzonym rozmiarze strony na podstawie tego, jak dużą grafikę akurat wyświetla przeglądarka.

Wymiary fizyczne zachowują się inaczej

Zmień wymiary oryginalnego elementu głównego na width="2.5in" height="1.25in", zachowując jego viewBox. W naszym teście dpi=96 dało PNG o wymiarach 240 × 120, a dpi=192 dało PNG o wymiarach 480 × 240. Oba pliki PDF nadal miały 180 × 90 punktów.

Tutaj źródło określa rozmiar fizyczny, więc większa liczba pikseli na cal zwiększa rozdzielczość rastrową, zachowując fizyczny rozmiar strony PDF. Ta sama zasada pozwala świadomie przygotować stronę z użyciem milimetrów lub cali. Sprawdź granice strony w wyeksportowanym PDF, zamiast zakładać, że duża liczba pikseli oznacza stronę A4 lub letter.

Jeśli logo ma znaleźć się w raporcie z tekstem, marginesami i kilkoma elementami, dodaj etap składania dokumentu. Nasz poradnik umieszczania SVG za pomocą ReportLab omawia bezpośrednie tworzenie PDF; kontrole zasobów i rozmiarów w WeasyPrint dotyczą dokumentów HTML.

Sprawdź eksport, w tym elementy, które pozostały wektorowe

Nagłówki PNG odczytaliśmy za pomocą Pillow, a granice stron PDF i strumienie zawartości za pomocą pypdf 6.10.0. Każdy z czterech plików PDF utworzonych ze źródła o wymiarach w pikselach zawierał operacje rysowania ścieżek i zero obrazów na stronie. Potwierdza to zachowanie geometrii wektorowej dla tego prostego pliku testowego bez obrazów. Nie dowodzi pełnej wierności odwzorowania dowolnego SVG.

Aby sprawdzić wymiary własnych plików wyjściowych, zainstaluj pillow i pypdf w tym samym środowisku i uruchom:

from PIL import Image
from pypdf import PdfReader
 
with Image.open("emblem-480.png") as image:
    print("PNG pixels:", image.size)
 
page = PdfReader("emblem.pdf").pages[0]
print("PDF points:", float(page.mediabox.width),
      float(page.mediabox.height))
print("Page images:", len(page.images))

Dokumentacja PageObject opisuje mediabox i images. Liczba obrazów jest przydatną wskazówką diagnostyczną, ale nie może dowieść, że każdy kształt, font lub efekt został zachowany poprawnie.

Przed przekazaniem plików:

  1. Otwórz PNG i PDF oraz porównaj emblemat z SVG. Sprawdź jego otwór, trójkąt, pasek i marginesy.
  2. Zweryfikuj niezależnie wymiary PNG w pikselach i fizyczne wymiary PDF.
  3. Sprawdź grafikę w rozmiarze, w jakim będzie używana, zwracając uwagę także na wąskie szczeliny i drobne szczegóły.
  4. Zachowaj oryginalny SVG i powtórz te kontrole po jego zmianie lub aktualizacji konwertera.

Strona dotycząca obsługi SVG w CairoSVG podaje, że zawartość wektorowa jest zachowywana tam, gdzie to możliwe. Osadzone obrazy rastrowe pozostają zawartością rastrową. Jeśli Twój plik zawiera PNG opakowany w SVG, diagnostyka osadzonych obrazów pomoże Ci go rozpoznać przed eksportem.

CairoSVG jest rendererem statycznym. Animacje, skrypty, zaawansowany układ tekstu i wiele filtrów wykraczają poza zakres jego obsługi. Jego dokumentacja wymienia tylko feOffset, feBlend i feFlood jako obsługiwane filtry. W przypadku grafiki zależnej od innych efektów starannie porównaj wynik lub wyeksportuj ją w aplikacji obsługującej te funkcje. Samo pomyślne wywołanie konwersji nie wystarczy.

Odzyskaj wektorowy plik wzorcowy tylko wtedy, gdy wymaga tego źródło

Jeśli Twoje logo zachowało się tylko jako PNG lub JPG, PerfectVector może wykonać wcześniejszy etap konwersji obrazu rastrowego do SVG, zanim CairoSVG go wyeksportuje. Sprawdź w edytorze odzyskane kształty, małe otwory i liternictwo marki; następnie zapisz samodzielny plik wzorcowy SVG. Nasz proces wektoryzacji logo wyjaśnia tę kontrolę.

Istniejący edytowalny SVG może przejść bezpośrednio do etapu eksportu. Konwersja do PNG i ponowna wektoryzacja oznaczałyby utratę przydatnej geometrii źródłowej. Zdjęcia mogą pozostać obrazami rastrowymi, jeśli taka jest zamierzona zawartość.

W przypadku logo dostępnego tylko w formacie rastrowym wypróbuj własny obraz w PerfectVector, sprawdź kontury i otwory w SVG, a następnie zweryfikuj zarówno wymiary w pikselach, jak i fizyczny rozmiar strony plików wyeksportowanych za pomocą CairoSVG.

Najczęściej zadawane pytania

Dlaczego zmiana DPI nie zmienia rozmiaru mojego PNG? Jeśli element główny SVG używa wymiarów w pikselach, zmiana DPI nie musi zmieniać liczby pikseli PNG. W tym przykładzie SVG o wymiarach 240 na 120 pikseli zachował ten rozmiar przy 192 DPI. Użyj output_width lub scale, gdy potrzebujesz więcej pikseli w pliku wyjściowym.

Czy szerokość kontenera nadrzędnego jest tym samym co szerokość wyjściowa? Nie. parent_width określa kontener używany do obliczania wymiarów procentowych. output_width określa żądaną końcową szerokość wyjściową. W przykładzie szerokość elementu głównego wynosząca 50% przy parent_width równym 960 została obliczona jako 480 pikseli.

Czy CairoSVG zawsze tworzy całkowicie wektorowy PDF? Nie. CairoSVG zachowuje zawartość wektorową tam, gdzie to możliwe, ale SVG może zawierać obrazy rastrowe i nieobsługiwane funkcje. Sprawdź zawartość i wygląd PDF, zamiast traktować rozszerzenie pliku jako dowód.

Źródła

  1. CairoSVG documentation — Opisuje instalację, API konwersji, parametry rozmiaru i ograniczenia renderowania.
  2. CairoSVG SVG 1.1 support — Wyjaśnia zachowanie zawartości wektorowej, osadzone obrazy i nieobsługiwane funkcje.
  3. pypdf PageObject reference — Dokumentuje interfejsy granic strony i obrazów używane do sprawdzania PDF.

Więcej z bloga

Zacznij od czystszego SVG,
który łatwiej edytować