CairoSVG: ส่งออก SVG เป็น PDF และ PNG ในขนาดที่ถูกต้อง
แปลงงาน SVG ด้วย CairoSVG เลือกความกว้างเอาต์พุตหรือมาตราส่วน เข้าใจ DPI และขนาดองค์ประกอบแม่ พร้อมตรวจพิกเซล PNG และขนาดหน้า PDF ก่อนส่งมอบ
ในหน้านี้
ใช้ cairosvg.svg2png() เพื่อส่งออกภาพราสเตอร์ และ cairosvg.svg2pdf() เพื่อสร้าง PDF หากต้องการความกว้าง PNG เฉพาะ ให้ตั้ง output_width หากต้องการขยายตามสัดส่วน ให้ใช้ scale ส่วน parent_width กำหนดคอนเทนเนอร์ที่ใช้คำนวณขนาดแบบเปอร์เซ็นต์ dpi ควบคุมความสัมพันธ์ระหว่างพิกเซลกับหน่วยทางกายภาพ ดังนั้นการเปลี่ยนค่านี้อาจส่งผลต่อขนาด PNG และ PDF ต่างกัน
ตัวอย่างด้านล่างเริ่มจากตราสัญลักษณ์ SVG ขนาดเล็กและตรวจไฟล์ที่แต่ละการตั้งค่าสร้างขึ้น เหมาะกับนักออกแบบที่ส่งออกโลโก้อัตโนมัติและนักพัฒนาที่เตรียมงานภาพสำหรับเอกสาร CairoSVG เรนเดอร์เนื้อหา SVG ที่มีอยู่ ไม่ได้ลากพาธจากโลโก้ PNG ให้แก้ไขได้
เริ่มด้วย SVG ที่มีทรัพยากรครบในตัว
เรารันตัวอย่างเหล่านี้ด้วย Python 3.12.11 และ CairoSVG 2.9.1 ติดตั้งตัวแปลงที่ล็อกเวอร์ชันในสภาพแวดล้อมโปรเจกต์:
python -m pip install "CairoSVG==2.9.1"CairoSVG ต้องใช้ไลบรารี Cairo แบบเนทีฟด้วย หากติดตั้งหรือนำเข้าไม่ได้ ให้ทำตามหมายเหตุสำหรับระบบปฏิบัติการใน เอกสารการติดตั้ง
บันทึกตราสัญลักษณ์สามพาธที่เราสร้างนี้เป็น emblem.svg ช่องเปิดสี่เหลี่ยมทำให้สังเกตได้ง่ายหากกฎเติมสีหายไป และแท่งแคบเป็นจุดตรวจรายละเอียดเล็ก นี่เป็นงานสาธิตที่เขียนขึ้นเอง ไม่ใช่ผลแปลงจาก 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>ขนาดที่องค์ประกอบรากอธิบายวิวพอร์ตเอาต์พุต ส่วน viewBox อธิบายสี่เหลี่ยมพิกัดภายในของงานภาพ ในที่นี้ทั้งสองมีอัตราส่วน 2:1 เดียวกัน รักษาความสัมพันธ์นี้อย่างตั้งใจเมื่อปรับตัวอย่างไปใช้กับโลโก้ของคุณ
ส่งออกไฟล์หลักหนึ่งไฟล์ตามขนาดที่ต้องการ
บันทึกเป็น export_emblem.py ไว้ข้าง SVG แล้วรัน 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",
)PNG ของเรามีขนาด 480 × 240 พิกเซล หน้า PDF มีขนาด 180 × 90 พอยต์ เทียบเท่า 2.5 × 1.25 นิ้ว นี่เป็นค่าที่วัดจากตัวอย่างที่ให้มา ไม่ใช่ขนาดที่ควรคาดหวังจาก SVG ทุกไฟล์
คำสั่งบรรทัดคำสั่งที่เทียบเท่ากันคือ:
cairosvg emblem.svg --output-width 480 -o emblem-480.png
cairosvg emblem.svg -o emblem.pdfเอกสารอ้างอิง API และบรรทัดคำสั่งของ CairoSVG อธิบายการรับชื่อไฟล์อินพุตผ่าน url ไบต์ SVG ผ่าน bytestring และส่งออกไฟล์ผ่าน write_to ใน CLI นามสกุลชื่อไฟล์เอาต์พุตเป็นตัวเลือกรูปแบบ

เลือกตัวควบคุมที่ตรงกับปัญหา
ตัวเลือกที่ชื่อคล้ายกันตอบคำถามต่างกัน เอกสารอ้างอิงการกำหนดขนาด CairoSVG แยกคอนเทนเนอร์แม่ออกจากขนาดเอาต์พุตที่ขอ
| สิ่งที่ต้องการ | ตัวเลือก Python | ตัวเลือก CLI | สิ่งที่ต้องตรวจ |
|---|---|---|---|
| ทำ PNG ให้กว้าง 480 พิกเซลพอดี | output_width=480 | --output-width 480 | ความสูงและสัดส่วนงานภาพ |
| เพิ่มขนาดเอาต์พุตที่คำนวณแล้วเป็นสองเท่า | scale=2 | --scale 2 | ขนาดทั้งสองด้านเพิ่มเป็นสองเท่า |
| คำนวณความกว้างหรือสูงของรากที่ระบุเป็นเปอร์เซ็นต์ | parent_width, parent_height | --width, --height | เปอร์เซ็นต์ของคอนเทนเนอร์ที่ให้มา |
| แปลหน่วยทางกายภาพ เช่น นิ้ว | dpi | --dpi | ขนาดพิกเซล PNG กับขนาดทางกายภาพ PDF แยกกัน |
สำหรับต้นฉบับที่กำหนดขนาดเป็นพิกเซล เรารันแต่ละตัวเลือกแยกกัน:
| การตั้งค่า | ขนาด PNG | ขนาดหน้า PDF |
|---|---|---|
| ค่าปริยาย | 240 × 120 px | 180 × 90 pt |
output_width=480 | 480 × 240 px | 360 × 180 pt |
scale=2 | 480 × 240 px | 360 × 180 pt |
dpi=192 | 240 × 120 px | 90 × 45 pt |
แถวสุดท้ายคือจุดที่ชวนให้เข้าใจผิด: การเพิ่ม DPI เป็นสองเท่าไม่ได้ทำให้ SVG ที่กำหนดขนาดเป็นพิกเซลนี้มีพิกเซล PNG มากขึ้น แต่ทำให้ขนาดพิกเซลเท่าเดิมกินพื้นที่ทางกายภาพใน PDF น้อยลง ใช้ขนาดเอาต์พุตเมื่อข้อกำหนดส่งมอบคือจำนวนพิกเซล
การระบุขนาดเอาต์พุตทั้งสองด้านกำหนดสี่เหลี่ยมผืนภาพ แต่ไม่ได้รับประกันว่าโลโก้จะเต็มกรอบอย่างกระชับ กฎอัตราส่วนภาพของ SVG และพื้นที่ว่างภายใน viewBox ยังสำคัญ เริ่มด้วยขนาดเอาต์พุตด้านเดียวเมื่อต้องการสัดส่วนเดิม แล้วตรวจผล
ขนาดเปอร์เซ็นต์ต้องมีองค์ประกอบแม่
สำหรับสำเนาตัวอย่างที่รากใช้ width="50%" height="50%" การเรียกนี้กำหนดองค์ประกอบแม่ขนาด 960 × 480 พิกเซล:
cairosvg.svg2png(
url="emblem-percent.svg",
parent_width=960,
parent_height=480,
write_to="emblem-percent.png",
)เอาต์พุตของเรามีขนาด 480 × 240 พิกเซล: ครึ่งหนึ่งของความกว้างแม่และครึ่งหนึ่งของความสูง นี่อธิบายว่าเหตุใด parent_width=480 จึงใช้แทน output_width=480 ไม่ได้
หาก CairoSVG รายงานว่าขนาด SVG ไม่ได้ถูกกำหนด ให้ตรวจขนาดที่รากก่อน กำหนดขนาดบวกที่เหมาะกับการใช้งานให้เอกสาร หรือระบุขนาดแม่เมื่อเปอร์เซ็นต์ขึ้นอยู่กับมัน อย่าอนุมานขนาดหน้าที่ตั้งใจใช้จากขนาดที่เบราว์เซอร์บังเอิญแสดงงานภาพ
ขนาดทางกายภาพทำงานต่างออกไป
เปลี่ยนรากต้นฉบับเป็น width="2.5in" height="1.25in" โดยคง viewBox ไว้ ในการทดสอบของเรา dpi=96 ให้ PNG ขนาด 240 × 120 และ dpi=192 ให้ PNG ขนาด 480 × 240 PDF ทั้งสองยังคงมีขนาด 180 × 90 พอยต์
ในที่นี้ต้นฉบับกำหนดขนาดทางกายภาพ ดังนั้นการเพิ่มพิกเซลต่อนิ้วเพิ่มความละเอียดราสเตอร์โดยรักษาขนาดหน้าทางกายภาพของ PDF หลักการเดียวกันทำให้หน้าที่สร้างอย่างตั้งใจใช้มิลลิเมตรหรือนิ้วได้ ตรวจกรอบหน้าของ PDF ที่ส่งออก แทนการสมมติว่าจำนวนพิกเซลมากหมายถึงหน้า A4 หรือ letter
หากโลโก้ต้องอยู่ในรายงานที่มีข้อความ ระยะขอบ และองค์ประกอบหลายอย่าง ให้ใช้ขั้นตอนจัดเลย์เอาต์เอกสาร คู่มือวาง SVG ด้วย ReportLab ของเราครอบคลุมการสร้าง PDF โดยตรง ส่วน การตรวจทรัพยากรและขนาด WeasyPrint ครอบคลุมเอกสาร HTML
ตรวจผลส่งออก รวมทั้งส่วนที่ยังเป็นเวกเตอร์
เราอ่านส่วนหัว PNG ด้วย Pillow และกรอบหน้ากับสตรีมเนื้อหา PDF ด้วย pypdf 6.10.0 PDF จากต้นฉบับแบบพิกเซลทั้งสี่ไฟล์มีคำสั่งวาดพาธและไม่มีรูปภาพบนหน้า ซึ่งยืนยันรูปทรงเวกเตอร์สำหรับตัวอย่างเรียบง่ายที่ไม่มีรูปภาพนี้ แต่ไม่ได้ยืนยันความตรงต้นฉบับทั้งหมดสำหรับ SVG ใด ๆ
หากต้องการตรวจขนาดเอาต์พุตของคุณเอง ให้ติดตั้ง pillow และ pypdf ในสภาพแวดล้อมเดียวกันแล้วรัน:
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))เอกสารอ้างอิง PageObject อธิบาย mediabox และ images จำนวนรูปภาพเป็นข้อมูลวินิจฉัยที่มีประโยชน์ แต่ไม่อาจพิสูจน์ว่ารูปทรง ฟอนต์ หรือเอฟเฟกต์ทุกอย่างยังถูกต้อง
ก่อนส่งมอบ:
- เปิด PNG และ PDF แล้วเปรียบเทียบตราสัญลักษณ์กับ SVG ตรวจช่องเปิด สามเหลี่ยม แท่ง และระยะขอบ
- ตรวจขนาดพิกเซล PNG และขนาดทางกายภาพ PDF แยกกัน
- ตรวจงานภาพตามขนาดที่ตั้งใจใช้งาน รวมทั้งช่องแคบและรายละเอียดเล็ก
- เก็บ SVG ต้นฉบับและตรวจซ้ำหลังเปลี่ยนไฟล์หรืออัปเกรดตัวแปลง
หน้าการรองรับ SVG ของ CairoSVG ระบุว่าจะรักษาเอาต์พุตเวกเตอร์เมื่อทำได้ ภาพราสเตอร์ที่ฝังไว้ยังคงเป็นราสเตอร์ หากไฟล์มี PNG อยู่ในกรอบห่อ SVG วิธีวินิจฉัยภาพฝัง ช่วยระบุมันก่อนส่งออก
CairoSVG เป็นตัวเรนเดอร์ภาพนิ่ง แอนิเมชัน สคริปต์ การจัดข้อความขั้นสูง และฟิลเตอร์จำนวนมากอยู่นอกกระบวนการที่รองรับ เอกสารระบุว่ารองรับฟิลเตอร์เพียง feOffset, feBlend และ feFlood สำหรับงานภาพที่พึ่งเอฟเฟกต์อื่น ให้เปรียบเทียบผลอย่างระมัดระวังหรือส่งออกผ่านแอปพลิเคชันที่รองรับฟีเจอร์เหล่านั้น การเรียกแปลงสำเร็จเพียงอย่างเดียวยังไม่เพียงพอ
กู้คืนไฟล์หลักเวกเตอร์เฉพาะเมื่อต้นฉบับต้องการ
หากโลโก้เหลือเพียง PNG หรือ JPG PerfectVector สามารถทำขั้นตอนแปลงราสเตอร์เป็น SVG ก่อน CairoSVG ส่งออกได้ ตรวจรูปทรง ช่องเปิดเล็ก และตัวอักษรแบรนด์ที่กู้คืนมาในโปรแกรมแก้ไข แล้วบันทึกไฟล์หลัก SVG ที่มีทรัพยากรครบในตัว กระบวนการแปลงโลโก้เป็นเวกเตอร์ ของเราอธิบายการตรวจนั้น
SVG ที่แก้ไขได้อยู่แล้วเข้าสู่ขั้นตอนส่งออกได้ทันที การแปลงเป็น PNG แล้วลากพาธใหม่จะทิ้งรูปทรงต้นทางที่มีประโยชน์ ภาพถ่ายคงเป็นภาพราสเตอร์ได้หากนั่นคือเนื้อหาที่ต้องการ
สำหรับโลโก้ที่มีเพียงราสเตอร์ ให้ ลองภาพของคุณเองใน PerfectVector ตรวจเส้นรอบรูปและช่องเปิดใน SVG แล้วตรวจทั้งขนาดพิกเซลและขนาดหน้าทางกายภาพของผลส่งออก CairoSVG
คำถามที่พบบ่อย
ทำไมเปลี่ยน DPI แล้ว PNG ยังมีขนาดเท่าเดิม? หากราก SVG ใช้ขนาดพิกเซล การเปลี่ยน DPI ไม่จำเป็นต้องเปลี่ยนจำนวนพิกเซล PNG ในตัวอย่างนี้ SVG ขนาด 240 คูณ 120 พิกเซลยังมีขนาดเท่าเดิมที่ 192 DPI ใช้ output_width หรือ scale เมื่อต้องการพิกเซลเอาต์พุตมากขึ้น
ความกว้างแม่เหมือนความกว้างเอาต์พุตหรือไม่? ไม่ parent_width กำหนดคอนเทนเนอร์ที่ใช้คำนวณขนาดเปอร์เซ็นต์ ส่วน output_width ขอความกว้างเอาต์พุตสุดท้าย ในตัวอย่าง รากที่กว้าง 50% และมี parent_width เท่ากับ 960 คำนวณได้ 480 พิกเซล
CairoSVG สร้าง PDF ที่เป็นเวกเตอร์ทั้งหมดเสมอหรือไม่? ไม่ CairoSVG รักษาเอาต์พุตเวกเตอร์เมื่อทำได้ แต่ SVG อาจมีภาพราสเตอร์และฟีเจอร์ที่ไม่รองรับ ตรวจเนื้อหาและรูปลักษณ์ PDF แทนการถือนามสกุลไฟล์เป็นหลักฐาน
แหล่งอ้างอิง
- เอกสาร CairoSVG — อธิบายการติดตั้ง API แปลง ตัวควบคุมขนาด และข้อจำกัดการเรนเดอร์
- การรองรับ SVG 1.1 ของ CairoSVG — อธิบายการรักษาเวกเตอร์ ภาพฝัง และฟีเจอร์ที่ไม่รองรับ
- เอกสารอ้างอิง pypdf PageObject — อธิบายอินเทอร์เฟซกรอบหน้าและรูปภาพที่ใช้ตรวจ PDF
เพิ่มเติมจากบล็อก

ภาพ SVG ใน fpdf2: เก็บพาธใน PDF จาก Python
วางโลโก้ SVG ใน PDF จาก Python ด้วย fpdf2 ควบคุมขนาด ตรวจพาธที่บันทึก และวินิจฉัยข้อความหรือรูปร่างที่หายก่อนเลือกใช้ราสเตอร์แทน

SVG ใน PDFKit: วางโลโก้เวกเตอร์โดยไม่แบนเป็นภาพ
แทรกโลโก้ SVG ทั้งไฟล์ในเอกสาร PDFKit ตั้งขนาดเป็นพอยต์ และตรวจ PDF ที่บันทึกว่ามีพาธ ช่องเปิด คุณสมบัติที่หาย และภาพฝังหรือไม่