[{"data":1,"prerenderedAt":1639},["ShallowReactive",2],{"doc:\u002Fspatial-data-processing-automation\u002Fautomated-map-layout-generation\u002Fexport-layout-to-image-and-svg-pyqgis":3},{"id":4,"title":5,"body":6,"description":1628,"extension":1629,"meta":1630,"navigation":209,"path":1635,"seo":1636,"stem":1637,"__hash__":1638},"docs\u002Fspatial-data-processing-automation\u002Fautomated-map-layout-generation\u002Fexport-layout-to-image-and-svg-pyqgis\u002Findex.md","Export a Layout to Image and SVG in PyQGIS",{"type":7,"value":8,"toc":1613},"minimark",[9,13,22,31,149,154,169,173,176,472,498,502,505,553,625,634,638,641,710,732,736,739,846,859,863,866,930,1048,1064,1068,1071,1255,1260,1264,1267,1450,1471,1475,1495,1499,1528,1532,1535,1539,1545,1559,1569,1575,1579,1609],[10,11,5],"h1",{"id":12},"export-a-layout-to-image-and-svg-in-pyqgis",[14,15,16,17,21],"p",{},"PDF is the default output for print layouts, but many maps end up elsewhere: a PNG for a web page or a slide, a georeferenced TIFF to load back into GIS, an SVG for a designer to finish in Inkscape or Illustrator. ",[18,19,20],"code",{},"QgsLayoutExporter"," produces all of these from the same layout, with settings that control resolution, cropping, georeferencing and how vector content is structured.",[14,23,24,25,30],{},"This recipe belongs to ",[26,27,29],"a",{"href":28},"\u002Fspatial-data-processing-automation\u002Fautomated-map-layout-generation\u002F","Automated Map Layout Generation",". It exports to raster images with a chosen resolution, writes world files for georeferencing, crops to content with transparent backgrounds, exports SVG with separate layers for editing, handles multi-page layouts, and checks every export's result.",[14,32,33],{},[34,35,40,44,48,55,64,74,80,86,90,94,99,103,106,109,112,117,121,124,127,130,136,140,143,146],"svg",{"viewBox":36,"role":37,"ariaLabel":38,"xmlns":39},"0 0 760 262","img","A layout exported as PDF, PNG or JPEG images, a georeferenced TIFF with a world file, or layered SVG","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg",[41,42,43],"title",{},"One layout, several outputs",[45,46,47],"desc",{},"QgsLayoutExporter writes the same layout as PDF for print, as PNG or JPEG raster images for web and slides with a chosen dots per inch, as a georeferenced TIFF with a world file for reuse in GIS, and as SVG with optional separate layers for editing in illustration software.",[49,50],"rect",{"x":51,"y":51,"width":52,"height":53,"fill":54},"0","760","262","#f6f3ea",[56,57,63],"text",{"x":58,"y":59,"style":60,"fill":61,"textAnchor":62},"380","28","text-anchor:middle;font-size:14px;font-family:sans-serif;font-weight:bold","#17211d","middle","Pick the format by where the map is going",[49,65],{"x":66,"y":67,"width":68,"height":69,"rx":70,"fill":71,"stroke":72,"style":73},"24","56","168","190","8","#fffdf7","#59645f","stroke-width:2",[56,75,79],{"x":76,"y":77,"style":78,"fill":61,"textAnchor":62},"108","109.78","text-anchor:middle;font-size:11.5px;font-family:sans-serif;font-weight:bold","PDF",[56,81,85],{"x":76,"y":82,"style":83,"fill":84,"textAnchor":62},"139.78","text-anchor:middle;font-size:10.5px;font-family:sans-serif","#2f3b35","print",[56,87,89],{"x":76,"y":88,"style":83,"fill":84,"textAnchor":62},"169.78","vector + raster",[56,91,93],{"x":76,"y":92,"style":83,"fill":72,"textAnchor":62},"199.78","exportToPdf",[49,95],{"x":96,"y":67,"width":68,"height":69,"rx":70,"fill":97,"stroke":98,"style":73},"206","#eff3ff","#2563eb",[56,100,102],{"x":101,"y":77,"style":78,"fill":98,"textAnchor":62},"290","PNG \u002F JPEG",[56,104,105],{"x":101,"y":82,"style":83,"fill":84,"textAnchor":62},"web, slides",[56,107,108],{"x":101,"y":88,"style":83,"fill":84,"textAnchor":62},"dpi decides size",[56,110,111],{"x":101,"y":92,"style":83,"fill":72,"textAnchor":62},"exportToImage",[49,113],{"x":114,"y":67,"width":68,"height":69,"rx":70,"fill":115,"stroke":116,"style":73},"388","#eef7f4","#0f766e",[56,118,120],{"x":119,"y":77,"style":78,"fill":116,"textAnchor":62},"472","TIFF + world",[56,122,123],{"x":119,"y":82,"style":83,"fill":84,"textAnchor":62},"back into GIS",[56,125,126],{"x":119,"y":88,"style":83,"fill":84,"textAnchor":62},"georeferenced",[56,128,129],{"x":119,"y":92,"style":83,"fill":72,"textAnchor":62},"generateWorldFile",[49,131],{"x":132,"y":67,"width":133,"height":69,"rx":70,"fill":134,"stroke":135,"style":73},"570","166","#fdf2e2","#b45309",[56,137,139],{"x":138,"y":77,"style":78,"fill":135,"textAnchor":62},"653","SVG",[56,141,142],{"x":138,"y":82,"style":83,"fill":84,"textAnchor":62},"illustration tools",[56,144,145],{"x":138,"y":88,"style":83,"fill":84,"textAnchor":62},"layers per item",[56,147,148],{"x":138,"y":92,"style":83,"fill":72,"textAnchor":62},"exportToSvg",[150,151,153],"h2",{"id":152},"prerequisites","Prerequisites",[155,156,157,161],"ul",{},[158,159,160],"li",{},"QGIS 3.34 LTR or newer, or the QGIS 4 series.",[158,162,163,164,168],{},"A finished layout, either in the project or built in code. Exports in headless scripts need the QGIS application initialised, as in ",[26,165,167],{"href":166},"\u002Fpyqgis-fundamentals-environment-setup\u002Fvirtual-environments-for-gis\u002Frunning-python-scripts-outside-qgis-desktop\u002F","running Python scripts outside QGIS Desktop",".",[150,170,172],{"id":171},"export-a-png-at-a-chosen-resolution","Export a PNG at a chosen resolution",[14,174,175],{},"Image exports render each page at a resolution in dots per inch; the pixel size follows from the page size and the dpi.",[177,178,183],"pre",{"className":179,"code":180,"language":181,"meta":182,"style":182},"language-python shiki shiki-themes github-dark","from qgis.core import QgsProject, QgsLayoutExporter\n\nlayout = QgsProject.instance().layoutManager().layoutByName(\"District report\")\nexporter = QgsLayoutExporter(layout)\n\nsettings = QgsLayoutExporter.ImageExportSettings()\nsettings.dpi = 150\nsettings.antialiasing = True\nresult = exporter.exportToImage(\"\u002Fdata\u002Fexports\u002Fdistrict_report.png\", settings)\nif result != QgsLayoutExporter.Success:\n    raise RuntimeError(f\"export failed: {result} {exporter.errorMessage()}\")\n\npage = layout.pageCollection().page(0).pageSize()\nprint(f\"{page.width():.0f} × {page.height():.0f} mm at {settings.dpi} dpi ≈ \"\n      f\"{page.width() \u002F 25.4 * settings.dpi:.0f} × {page.height() \u002F 25.4 * settings.dpi:.0f} px\")\n","python","",[18,184,185,204,211,230,241,246,257,269,280,297,312,352,357,373,419],{"__ignoreMap":182},[186,187,190,194,198,201],"span",{"class":188,"line":189},"line",1,[186,191,193],{"class":192},"snl16","from",[186,195,197],{"class":196},"s95oV"," qgis.core ",[186,199,200],{"class":192},"import",[186,202,203],{"class":196}," QgsProject, QgsLayoutExporter\n",[186,205,207],{"class":188,"line":206},2,[186,208,210],{"emptyLinePlaceholder":209},true,"\n",[186,212,214,217,220,223,227],{"class":188,"line":213},3,[186,215,216],{"class":196},"layout ",[186,218,219],{"class":192},"=",[186,221,222],{"class":196}," QgsProject.instance().layoutManager().layoutByName(",[186,224,226],{"class":225},"sU2Wk","\"District report\"",[186,228,229],{"class":196},")\n",[186,231,233,236,238],{"class":188,"line":232},4,[186,234,235],{"class":196},"exporter ",[186,237,219],{"class":192},[186,239,240],{"class":196}," QgsLayoutExporter(layout)\n",[186,242,244],{"class":188,"line":243},5,[186,245,210],{"emptyLinePlaceholder":209},[186,247,249,252,254],{"class":188,"line":248},6,[186,250,251],{"class":196},"settings ",[186,253,219],{"class":192},[186,255,256],{"class":196}," QgsLayoutExporter.ImageExportSettings()\n",[186,258,260,263,265],{"class":188,"line":259},7,[186,261,262],{"class":196},"settings.dpi ",[186,264,219],{"class":192},[186,266,268],{"class":267},"sDLfK"," 150\n",[186,270,272,275,277],{"class":188,"line":271},8,[186,273,274],{"class":196},"settings.antialiasing ",[186,276,219],{"class":192},[186,278,279],{"class":267}," True\n",[186,281,283,286,288,291,294],{"class":188,"line":282},9,[186,284,285],{"class":196},"result ",[186,287,219],{"class":192},[186,289,290],{"class":196}," exporter.exportToImage(",[186,292,293],{"class":225},"\"\u002Fdata\u002Fexports\u002Fdistrict_report.png\"",[186,295,296],{"class":196},", settings)\n",[186,298,300,303,306,309],{"class":188,"line":299},10,[186,301,302],{"class":192},"if",[186,304,305],{"class":196}," result ",[186,307,308],{"class":192},"!=",[186,310,311],{"class":196}," QgsLayoutExporter.Success:\n",[186,313,315,318,321,324,327,330,333,336,339,342,345,347,350],{"class":188,"line":314},11,[186,316,317],{"class":192},"    raise",[186,319,320],{"class":267}," RuntimeError",[186,322,323],{"class":196},"(",[186,325,326],{"class":192},"f",[186,328,329],{"class":225},"\"export failed: ",[186,331,332],{"class":267},"{",[186,334,335],{"class":196},"result",[186,337,338],{"class":267},"}",[186,340,341],{"class":267}," {",[186,343,344],{"class":196},"exporter.errorMessage()",[186,346,338],{"class":267},[186,348,349],{"class":225},"\"",[186,351,229],{"class":196},[186,353,355],{"class":188,"line":354},12,[186,356,210],{"emptyLinePlaceholder":209},[186,358,360,363,365,368,370],{"class":188,"line":359},13,[186,361,362],{"class":196},"page ",[186,364,219],{"class":192},[186,366,367],{"class":196}," layout.pageCollection().page(",[186,369,51],{"class":267},[186,371,372],{"class":196},").pageSize()\n",[186,374,376,378,380,382,384,386,389,392,394,397,399,402,404,406,409,411,414,416],{"class":188,"line":375},14,[186,377,85],{"class":267},[186,379,323],{"class":196},[186,381,326],{"class":192},[186,383,349],{"class":225},[186,385,332],{"class":267},[186,387,388],{"class":196},"page.width()",[186,390,391],{"class":192},":.0f",[186,393,338],{"class":267},[186,395,396],{"class":225}," × ",[186,398,332],{"class":267},[186,400,401],{"class":196},"page.height()",[186,403,391],{"class":192},[186,405,338],{"class":267},[186,407,408],{"class":225}," mm at ",[186,410,332],{"class":267},[186,412,413],{"class":196},"settings.dpi",[186,415,338],{"class":267},[186,417,418],{"class":225}," dpi ≈ \"\n",[186,420,422,425,427,429,432,435,438,441,444,446,448,450,452,455,457,459,461,463,465,467,470],{"class":188,"line":421},15,[186,423,424],{"class":192},"      f",[186,426,349],{"class":225},[186,428,332],{"class":267},[186,430,431],{"class":196},"page.width() ",[186,433,434],{"class":192},"\u002F",[186,436,437],{"class":267}," 25.4",[186,439,440],{"class":192}," *",[186,442,443],{"class":196}," settings.dpi",[186,445,391],{"class":192},[186,447,338],{"class":267},[186,449,396],{"class":225},[186,451,332],{"class":267},[186,453,454],{"class":196},"page.height() ",[186,456,434],{"class":192},[186,458,437],{"class":267},[186,460,440],{"class":192},[186,462,443],{"class":196},[186,464,391],{"class":192},[186,466,338],{"class":267},[186,468,469],{"class":225}," px\"",[186,471,229],{"class":196},[14,473,474,478,479,481,482,485,486,489,490,493,494,497],{},[475,476,477],"strong",{},"Breakdown:"," An A4 landscape page at 150 dpi is about 1,750 × 1,240 pixels — right for slides and web pages; 300 dpi doubles both dimensions for print-quality raster output. ",[18,480,111],{}," returns a result code; ",[18,483,484],{},"Success"," is the only good one, and ",[18,487,488],{},"errorMessage()"," explains the rest, typically an unwritable path. The file extension chooses the format: ",[18,491,492],{},".png"," for maps with sharp lines and text, ",[18,495,496],{},".jpg"," only when the content is mostly imagery and file size matters.",[150,499,501],{"id":500},"set-an-exact-pixel-size","Set an exact pixel size",[14,503,504],{},"When the target is a web page or a slide template with fixed dimensions, setting the pixel size directly is easier than calculating dpi.",[14,506,507],{},[34,508,511,514,517,520,523,527,532,536,540,543,547,550],{"viewBox":509,"role":37,"ariaLabel":510,"xmlns":39},"0 0 760 222","Controlling raster export by dpi, where pixel size follows page size, or by an exact image size, where effective dpi follows",[41,512,513],{},"Dpi or pixel size",[45,515,516],{},"Two ways to control raster output. Setting dpi scales the image with the page size: an A4 page at 150 dpi is about 1754 by 1240 pixels. Setting imageSize forces an exact pixel size, for example 1920 by 1080 for a slide; the page is scaled to fit, which changes the effective dpi and therefore how large text and lines appear.",[49,518],{"x":51,"y":51,"width":52,"height":519,"fill":54},"222",[56,521,522],{"x":58,"y":59,"style":60,"fill":61,"textAnchor":62},"Resolution from dpi, or from a pixel target",[49,524],{"x":66,"y":67,"width":525,"height":526,"rx":70,"fill":97,"stroke":98,"style":73},"340","150",[56,528,531],{"x":529,"y":530,"style":78,"fill":98,"textAnchor":62},"194","106.78","dpi = 150",[56,533,535],{"x":529,"y":534,"style":83,"fill":84,"textAnchor":62},"134.78","A4 → 1754 × 1240 px",[56,537,539],{"x":529,"y":538,"style":83,"fill":72,"textAnchor":62},"162.78","sizes stay physical",[49,541],{"x":542,"y":67,"width":525,"height":526,"rx":70,"fill":134,"stroke":135,"style":73},"396",[56,544,546],{"x":545,"y":530,"style":78,"fill":135,"textAnchor":62},"566","imageSize = 1920 × 1080",[56,548,549],{"x":545,"y":534,"style":83,"fill":84,"textAnchor":62},"page scaled to fit",[56,551,552],{"x":545,"y":538,"style":83,"fill":72,"textAnchor":62},"effective dpi changes",[177,554,556],{"className":179,"code":555,"language":181,"meta":182,"style":182},"from qgis.PyQt.QtCore import QSize\n\nslide = QgsLayoutExporter.ImageExportSettings()\nslide.imageSize = QSize(1920, 1080)\nslide.cropToContents = False\nexporter.exportToImage(\"\u002Fdata\u002Fexports\u002Fdistrict_report_slide.png\", slide)\n",[18,557,558,570,574,583,604,614],{"__ignoreMap":182},[186,559,560,562,565,567],{"class":188,"line":189},[186,561,193],{"class":192},[186,563,564],{"class":196}," qgis.PyQt.QtCore ",[186,566,200],{"class":192},[186,568,569],{"class":196}," QSize\n",[186,571,572],{"class":188,"line":206},[186,573,210],{"emptyLinePlaceholder":209},[186,575,576,579,581],{"class":188,"line":213},[186,577,578],{"class":196},"slide ",[186,580,219],{"class":192},[186,582,256],{"class":196},[186,584,585,588,590,593,596,599,602],{"class":188,"line":232},[186,586,587],{"class":196},"slide.imageSize ",[186,589,219],{"class":192},[186,591,592],{"class":196}," QSize(",[186,594,595],{"class":267},"1920",[186,597,598],{"class":196},", ",[186,600,601],{"class":267},"1080",[186,603,229],{"class":196},[186,605,606,609,611],{"class":188,"line":243},[186,607,608],{"class":196},"slide.cropToContents ",[186,610,219],{"class":192},[186,612,613],{"class":267}," False\n",[186,615,616,619,622],{"class":188,"line":248},[186,617,618],{"class":196},"exporter.exportToImage(",[186,620,621],{"class":225},"\"\u002Fdata\u002Fexports\u002Fdistrict_report_slide.png\"",[186,623,624],{"class":196},", slide)\n",[14,626,627,629,630,633],{},[475,628,477],{}," With ",[18,631,632],{},"imageSize"," set, the exporter scales the page into exactly that many pixels, so the effective dpi depends on the page size. Text and line widths, defined in millimetres and points in the layout, become larger or smaller in pixels accordingly; a layout designed for A4 exported to 1920 × 1080 is roughly 165 dpi. Match the page's aspect ratio to the target — 16:9 for slides — or the image will be letterboxed.",[150,635,637],{"id":636},"georeference-image-exports","Georeference image exports",[14,639,640],{},"A map exported as an image can be loaded back into GIS in the right place if a world file is written alongside it. The exporter derives it from a map item.",[177,642,644],{"className":179,"code":643,"language":181,"meta":182,"style":182},"geo = QgsLayoutExporter.ImageExportSettings()\ngeo.dpi = 300\ngeo.generateWorldFile = True\nmap_item = layout.itemById(\"main_map\")\nlayout.setReferenceMap(map_item)\nexporter.exportToImage(\"\u002Fdata\u002Fexports\u002Fdistrict_map.tif\", geo)\n# writes district_map.tif and district_map.tfw\n",[18,645,646,655,665,674,689,694,704],{"__ignoreMap":182},[186,647,648,651,653],{"class":188,"line":189},[186,649,650],{"class":196},"geo ",[186,652,219],{"class":192},[186,654,256],{"class":196},[186,656,657,660,662],{"class":188,"line":206},[186,658,659],{"class":196},"geo.dpi ",[186,661,219],{"class":192},[186,663,664],{"class":267}," 300\n",[186,666,667,670,672],{"class":188,"line":213},[186,668,669],{"class":196},"geo.generateWorldFile ",[186,671,219],{"class":192},[186,673,279],{"class":267},[186,675,676,679,681,684,687],{"class":188,"line":232},[186,677,678],{"class":196},"map_item ",[186,680,219],{"class":192},[186,682,683],{"class":196}," layout.itemById(",[186,685,686],{"class":225},"\"main_map\"",[186,688,229],{"class":196},[186,690,691],{"class":188,"line":243},[186,692,693],{"class":196},"layout.setReferenceMap(map_item)\n",[186,695,696,698,701],{"class":188,"line":248},[186,697,618],{"class":196},[186,699,700],{"class":225},"\"\u002Fdata\u002Fexports\u002Fdistrict_map.tif\"",[186,702,703],{"class":196},", geo)\n",[186,705,706],{"class":188,"line":259},[186,707,709],{"class":708},"sjoCn","# writes district_map.tif and district_map.tfw\n",[14,711,712,714,715,718,719,722,723,727,728,731],{},[475,713,477],{}," The reference map tells the exporter which map item's extent and scale to encode; with several map items, setting it explicitly avoids georeferencing from an inset by mistake. The world file (",[18,716,717],{},".tfw"," for TIFF, ",[18,720,721],{},".pgw"," for PNG) holds the pixel size and the coordinates of the top-left pixel, in the map item's CRS. It describes the ",[724,725,726],"em",{},"whole page",", so the page's non-map areas — title, legend — are georeferenced as if they were map, which is fine for overlays but means that for clean reuse a layout containing only the map item is best. QGIS writes a ",[18,729,730],{},".aux.xml"," with the CRS, so the image loads directly with the right projection.",[150,733,735],{"id":734},"crop-to-content-with-a-transparent-background","Crop to content with a transparent background",[14,737,738],{},"For maps embedded in documents or web pages, a tight crop and a transparent background avoid white borders and let the map sit on any colour.",[177,740,742],{"className":179,"code":741,"language":181,"meta":182,"style":182},"inset = QgsLayoutExporter.ImageExportSettings()\ninset.dpi = 200\ninset.cropToContents = True\n\nfrom qgis.core import QgsFillSymbol\nfrom qgis.PyQt.QtGui import QColor\npage_symbol = QgsFillSymbol.createSimple({\"color\": \"0,0,0,0\", \"outline_style\": \"no\"})\nlayout.pageCollection().setPageStyleSymbol(page_symbol)\nexporter.exportToImage(\"\u002Fdata\u002Fexports\u002Flocator_map.png\", inset)\n",[18,743,744,753,763,772,776,787,799,831,836],{"__ignoreMap":182},[186,745,746,749,751],{"class":188,"line":189},[186,747,748],{"class":196},"inset ",[186,750,219],{"class":192},[186,752,256],{"class":196},[186,754,755,758,760],{"class":188,"line":206},[186,756,757],{"class":196},"inset.dpi ",[186,759,219],{"class":192},[186,761,762],{"class":267}," 200\n",[186,764,765,768,770],{"class":188,"line":213},[186,766,767],{"class":196},"inset.cropToContents ",[186,769,219],{"class":192},[186,771,279],{"class":267},[186,773,774],{"class":188,"line":232},[186,775,210],{"emptyLinePlaceholder":209},[186,777,778,780,782,784],{"class":188,"line":243},[186,779,193],{"class":192},[186,781,197],{"class":196},[186,783,200],{"class":192},[186,785,786],{"class":196}," QgsFillSymbol\n",[186,788,789,791,794,796],{"class":188,"line":248},[186,790,193],{"class":192},[186,792,793],{"class":196}," qgis.PyQt.QtGui ",[186,795,200],{"class":192},[186,797,798],{"class":196}," QColor\n",[186,800,801,804,806,809,812,815,818,820,823,825,828],{"class":188,"line":259},[186,802,803],{"class":196},"page_symbol ",[186,805,219],{"class":192},[186,807,808],{"class":196}," QgsFillSymbol.createSimple({",[186,810,811],{"class":225},"\"color\"",[186,813,814],{"class":196},": ",[186,816,817],{"class":225},"\"0,0,0,0\"",[186,819,598],{"class":196},[186,821,822],{"class":225},"\"outline_style\"",[186,824,814],{"class":196},[186,826,827],{"class":225},"\"no\"",[186,829,830],{"class":196},"})\n",[186,832,833],{"class":188,"line":271},[186,834,835],{"class":196},"layout.pageCollection().setPageStyleSymbol(page_symbol)\n",[186,837,838,840,843],{"class":188,"line":282},[186,839,618],{"class":196},[186,841,842],{"class":225},"\"\u002Fdata\u002Fexports\u002Flocator_map.png\"",[186,844,845],{"class":196},", inset)\n",[14,847,848,850,851,854,855,858],{},[475,849,477],{}," ",[18,852,853],{},"cropToContents"," trims the exported image to the bounding box of the items on the page, so empty paper around a small locator map disappears; ",[18,856,857],{},"cropMargins"," adds padding if needed. A transparent page symbol — fill colour with zero alpha and no outline — makes the background transparent in PNG output (JPEG cannot store transparency). Remember to restore the page symbol afterwards if the same layout is also exported to PDF. Map items with their own background colour stay opaque; set the map item's background to transparent too if the map itself should float.",[150,860,862],{"id":861},"export-svg-for-further-editing","Export SVG for further editing",[14,864,865],{},"SVG keeps vector content as vectors, which makes it the format of choice when a designer will refine the map. Exporting with separate layers gives them items and map layers as distinct groups.",[14,867,868],{},[34,869,871,874,877,879,882,884,889,893,897,901,904,907,910,913,915,918,921,924,927],{"viewBox":509,"role":37,"ariaLabel":870,"xmlns":39},"A layered SVG export where layout items and map layers become named groups that designers can edit separately",[41,872,873],{},"SVG with layers",[45,875,876],{},"With exportAsLayers enabled, each layout item and each map layer within map items becomes a separate group in the SVG, named after the item or layer. A designer can hide, restyle or rearrange groups in Inkscape or Illustrator. Labels can be exported as text or as outlines; text keeps them editable but depends on installed fonts.",[49,878],{"x":51,"y":51,"width":52,"height":519,"fill":54},[56,880,881],{"x":58,"y":59,"style":60,"fill":61,"textAnchor":62},"Named groups a designer can work with",[49,883],{"x":66,"y":67,"width":519,"height":526,"rx":70,"fill":115,"stroke":116,"style":73},[56,885,888],{"x":886,"y":887,"style":78,"fill":116,"textAnchor":62},"135","92.78","layout items",[56,890,892],{"x":886,"y":891,"style":83,"fill":84,"textAnchor":62},"120.78","title · legend",[56,894,896],{"x":886,"y":895,"style":83,"fill":84,"textAnchor":62},"148.78","scale bar",[56,898,900],{"x":886,"y":899,"style":83,"fill":72,"textAnchor":62},"176.78","one group each",[49,902],{"x":903,"y":67,"width":519,"height":526,"rx":70,"fill":97,"stroke":98,"style":73},"269",[56,905,906],{"x":58,"y":887,"style":78,"fill":98,"textAnchor":62},"map layers",[56,908,909],{"x":58,"y":891,"style":83,"fill":84,"textAnchor":62},"roads · buildings",[56,911,912],{"x":58,"y":895,"style":83,"fill":84,"textAnchor":62},"labels",[56,914,900],{"x":58,"y":899,"style":83,"fill":72,"textAnchor":62},[49,916],{"x":917,"y":67,"width":519,"height":526,"rx":70,"fill":134,"stroke":135,"style":73},"514",[56,919,56],{"x":920,"y":887,"style":78,"fill":135,"textAnchor":62},"625",[56,922,923],{"x":920,"y":891,"style":83,"fill":84,"textAnchor":62},"as text: editable",[56,925,926],{"x":920,"y":895,"style":83,"fill":84,"textAnchor":62},"as outlines: exact",[56,928,929],{"x":920,"y":899,"style":83,"fill":72,"textAnchor":62},"fonts decide",[177,931,933],{"className":179,"code":932,"language":181,"meta":182,"style":182},"from qgis.core import Qgis\n\nsvg = QgsLayoutExporter.SvgExportSettings()\nsvg.dpi = 96\nsvg.exportAsLayers = True\nsvg.exportMetadata = True\nsvg.forceVectorOutput = True\nsvg.textRenderFormat = Qgis.TextRenderFormat.AlwaysText\nresult = exporter.exportToSvg(\"\u002Fdata\u002Fexports\u002Fdistrict_report.svg\", svg)\nprint(\"ok\" if result == QgsLayoutExporter.Success else exporter.errorMessage())\n",[18,934,935,946,950,960,970,979,988,997,1007,1022],{"__ignoreMap":182},[186,936,937,939,941,943],{"class":188,"line":189},[186,938,193],{"class":192},[186,940,197],{"class":196},[186,942,200],{"class":192},[186,944,945],{"class":196}," Qgis\n",[186,947,948],{"class":188,"line":206},[186,949,210],{"emptyLinePlaceholder":209},[186,951,952,955,957],{"class":188,"line":213},[186,953,954],{"class":196},"svg ",[186,956,219],{"class":192},[186,958,959],{"class":196}," QgsLayoutExporter.SvgExportSettings()\n",[186,961,962,965,967],{"class":188,"line":232},[186,963,964],{"class":196},"svg.dpi ",[186,966,219],{"class":192},[186,968,969],{"class":267}," 96\n",[186,971,972,975,977],{"class":188,"line":243},[186,973,974],{"class":196},"svg.exportAsLayers ",[186,976,219],{"class":192},[186,978,279],{"class":267},[186,980,981,984,986],{"class":188,"line":248},[186,982,983],{"class":196},"svg.exportMetadata ",[186,985,219],{"class":192},[186,987,279],{"class":267},[186,989,990,993,995],{"class":188,"line":259},[186,991,992],{"class":196},"svg.forceVectorOutput ",[186,994,219],{"class":192},[186,996,279],{"class":267},[186,998,999,1002,1004],{"class":188,"line":271},[186,1000,1001],{"class":196},"svg.textRenderFormat ",[186,1003,219],{"class":192},[186,1005,1006],{"class":196}," Qgis.TextRenderFormat.AlwaysText\n",[186,1008,1009,1011,1013,1016,1019],{"class":188,"line":282},[186,1010,285],{"class":196},[186,1012,219],{"class":192},[186,1014,1015],{"class":196}," exporter.exportToSvg(",[186,1017,1018],{"class":225},"\"\u002Fdata\u002Fexports\u002Fdistrict_report.svg\"",[186,1020,1021],{"class":196},", svg)\n",[186,1023,1024,1026,1028,1031,1034,1036,1039,1042,1045],{"class":188,"line":299},[186,1025,85],{"class":267},[186,1027,323],{"class":196},[186,1029,1030],{"class":225},"\"ok\"",[186,1032,1033],{"class":192}," if",[186,1035,305],{"class":196},[186,1037,1038],{"class":192},"==",[186,1040,1041],{"class":196}," QgsLayoutExporter.Success ",[186,1043,1044],{"class":192},"else",[186,1046,1047],{"class":196}," exporter.errorMessage())\n",[14,1049,1050,850,1052,1055,1056,1059,1060,1063],{},[475,1051,477],{},[18,1053,1054],{},"exportAsLayers"," writes each layout item, and each map layer inside map items, as a separate SVG group named after it, which is what makes the file workable in an illustration program. ",[18,1057,1058],{},"forceVectorOutput"," avoids rasterising items that would otherwise be drawn as images, at the cost of larger files for complex symbology. Text as text keeps labels editable but depends on the designer having the same fonts; text as outlines (",[18,1061,1062],{},"AlwaysOutlines",") looks exactly right everywhere but cannot be edited. Effects such as blur and blending modes cannot be represented in SVG and are rasterised or lost — check the result.",[150,1065,1067],{"id":1066},"export-thumbnails-for-catalogues","Export thumbnails for catalogues",[14,1069,1070],{},"Map catalogues, web galleries and README files want small previews. Exporting a low-resolution PNG of each layout, then scaling it to a fixed width, produces consistent thumbnails in one pass.",[177,1072,1074],{"className":179,"code":1073,"language":181,"meta":182,"style":182},"from qgis.PyQt.QtGui import QImage\nfrom qgis.PyQt.QtCore import Qt\n\ndef thumbnail(layout, out_png, width_px=480):\n    tmp = out_png.replace(\".png\", \"_full.png\")\n    s = QgsLayoutExporter.ImageExportSettings()\n    s.dpi = 72\n    s.pages = [0]                         # first page only\n    QgsLayoutExporter(layout).exportToImage(tmp, s)\n    img = QImage(tmp).scaledToWidth(width_px, Qt.SmoothTransformation)\n    img.save(out_png)\n    Path(tmp).unlink()\n\nfor lay in QgsProject.instance().layoutManager().printLayouts():\n    thumbnail(lay, f\"\u002Fdata\u002Fexports\u002Fthumbs\u002F{lay.name().replace(' ', '_')}.png\")\n",[18,1075,1076,1087,1098,1102,1122,1142,1151,1161,1179,1184,1194,1199,1204,1208,1222],{"__ignoreMap":182},[186,1077,1078,1080,1082,1084],{"class":188,"line":189},[186,1079,193],{"class":192},[186,1081,793],{"class":196},[186,1083,200],{"class":192},[186,1085,1086],{"class":196}," QImage\n",[186,1088,1089,1091,1093,1095],{"class":188,"line":206},[186,1090,193],{"class":192},[186,1092,564],{"class":196},[186,1094,200],{"class":192},[186,1096,1097],{"class":196}," Qt\n",[186,1099,1100],{"class":188,"line":213},[186,1101,210],{"emptyLinePlaceholder":209},[186,1103,1104,1107,1111,1114,1116,1119],{"class":188,"line":232},[186,1105,1106],{"class":192},"def",[186,1108,1110],{"class":1109},"svObZ"," thumbnail",[186,1112,1113],{"class":196},"(layout, out_png, width_px",[186,1115,219],{"class":192},[186,1117,1118],{"class":267},"480",[186,1120,1121],{"class":196},"):\n",[186,1123,1124,1127,1129,1132,1135,1137,1140],{"class":188,"line":243},[186,1125,1126],{"class":196},"    tmp ",[186,1128,219],{"class":192},[186,1130,1131],{"class":196}," out_png.replace(",[186,1133,1134],{"class":225},"\".png\"",[186,1136,598],{"class":196},[186,1138,1139],{"class":225},"\"_full.png\"",[186,1141,229],{"class":196},[186,1143,1144,1147,1149],{"class":188,"line":248},[186,1145,1146],{"class":196},"    s ",[186,1148,219],{"class":192},[186,1150,256],{"class":196},[186,1152,1153,1156,1158],{"class":188,"line":259},[186,1154,1155],{"class":196},"    s.dpi ",[186,1157,219],{"class":192},[186,1159,1160],{"class":267}," 72\n",[186,1162,1163,1166,1168,1171,1173,1176],{"class":188,"line":271},[186,1164,1165],{"class":196},"    s.pages ",[186,1167,219],{"class":192},[186,1169,1170],{"class":196}," [",[186,1172,51],{"class":267},[186,1174,1175],{"class":196},"]                         ",[186,1177,1178],{"class":708},"# first page only\n",[186,1180,1181],{"class":188,"line":282},[186,1182,1183],{"class":196},"    QgsLayoutExporter(layout).exportToImage(tmp, s)\n",[186,1185,1186,1189,1191],{"class":188,"line":299},[186,1187,1188],{"class":196},"    img ",[186,1190,219],{"class":192},[186,1192,1193],{"class":196}," QImage(tmp).scaledToWidth(width_px, Qt.SmoothTransformation)\n",[186,1195,1196],{"class":188,"line":314},[186,1197,1198],{"class":196},"    img.save(out_png)\n",[186,1200,1201],{"class":188,"line":354},[186,1202,1203],{"class":196},"    Path(tmp).unlink()\n",[186,1205,1206],{"class":188,"line":359},[186,1207,210],{"emptyLinePlaceholder":209},[186,1209,1210,1213,1216,1219],{"class":188,"line":375},[186,1211,1212],{"class":192},"for",[186,1214,1215],{"class":196}," lay ",[186,1217,1218],{"class":192},"in",[186,1220,1221],{"class":196}," QgsProject.instance().layoutManager().printLayouts():\n",[186,1223,1224,1227,1229,1232,1234,1237,1240,1242,1245,1248,1250,1253],{"class":188,"line":421},[186,1225,1226],{"class":196},"    thumbnail(lay, ",[186,1228,326],{"class":192},[186,1230,1231],{"class":225},"\"\u002Fdata\u002Fexports\u002Fthumbs\u002F",[186,1233,332],{"class":267},[186,1235,1236],{"class":196},"lay.name().replace(",[186,1238,1239],{"class":225},"' '",[186,1241,598],{"class":196},[186,1243,1244],{"class":225},"'_'",[186,1246,1247],{"class":196},")",[186,1249,338],{"class":267},[186,1251,1252],{"class":225},".png\"",[186,1254,229],{"class":196},[14,1256,1257,1259],{},[475,1258,477],{}," Rendering at a low dpi keeps exports fast, and restricting to the first page avoids writing every page of long layouts. Scaling with smooth transformation to a fixed width gives every thumbnail the same width for a tidy gallery, whatever the page size. File names are derived from layout names with spaces replaced; sanitise further if names contain slashes or other characters that are invalid in paths.",[150,1261,1263],{"id":1262},"handle-multi-page-layouts-and-check-results","Handle multi-page layouts and check results",[14,1265,1266],{},"Image and SVG exports write one file per page. The exporter appends page numbers automatically; a script should know which files to expect and check them.",[177,1268,1270],{"className":179,"code":1269,"language":181,"meta":182,"style":182},"from pathlib import Path\n\npages = layout.pageCollection().pageCount()\nresult = exporter.exportToImage(\"\u002Fdata\u002Fexports\u002Fatlas_report.png\",\n                                QgsLayoutExporter.ImageExportSettings())\nexpected = [\"\u002Fdata\u002Fexports\u002Fatlas_report.png\"] + [\n    f\"\u002Fdata\u002Fexports\u002Fatlas_report_{i}.png\" for i in range(2, pages + 1)]\nmissing = [p for p in expected if not Path(p).exists()]\nprint(pages, \"pages;\", \"all written\" if not missing else f\"missing {missing}\")\n",[18,1271,1272,1284,1288,1298,1312,1317,1337,1381,1409],{"__ignoreMap":182},[186,1273,1274,1276,1279,1281],{"class":188,"line":189},[186,1275,193],{"class":192},[186,1277,1278],{"class":196}," pathlib ",[186,1280,200],{"class":192},[186,1282,1283],{"class":196}," Path\n",[186,1285,1286],{"class":188,"line":206},[186,1287,210],{"emptyLinePlaceholder":209},[186,1289,1290,1293,1295],{"class":188,"line":213},[186,1291,1292],{"class":196},"pages ",[186,1294,219],{"class":192},[186,1296,1297],{"class":196}," layout.pageCollection().pageCount()\n",[186,1299,1300,1302,1304,1306,1309],{"class":188,"line":232},[186,1301,285],{"class":196},[186,1303,219],{"class":192},[186,1305,290],{"class":196},[186,1307,1308],{"class":225},"\"\u002Fdata\u002Fexports\u002Fatlas_report.png\"",[186,1310,1311],{"class":196},",\n",[186,1313,1314],{"class":188,"line":243},[186,1315,1316],{"class":196},"                                QgsLayoutExporter.ImageExportSettings())\n",[186,1318,1319,1322,1324,1326,1328,1331,1334],{"class":188,"line":248},[186,1320,1321],{"class":196},"expected ",[186,1323,219],{"class":192},[186,1325,1170],{"class":196},[186,1327,1308],{"class":225},[186,1329,1330],{"class":196},"] ",[186,1332,1333],{"class":192},"+",[186,1335,1336],{"class":196}," [\n",[186,1338,1339,1342,1345,1347,1350,1352,1354,1357,1360,1362,1365,1367,1370,1373,1375,1378],{"class":188,"line":259},[186,1340,1341],{"class":192},"    f",[186,1343,1344],{"class":225},"\"\u002Fdata\u002Fexports\u002Fatlas_report_",[186,1346,332],{"class":267},[186,1348,1349],{"class":196},"i",[186,1351,338],{"class":267},[186,1353,1252],{"class":225},[186,1355,1356],{"class":192}," for",[186,1358,1359],{"class":196}," i ",[186,1361,1218],{"class":192},[186,1363,1364],{"class":267}," range",[186,1366,323],{"class":196},[186,1368,1369],{"class":267},"2",[186,1371,1372],{"class":196},", pages ",[186,1374,1333],{"class":192},[186,1376,1377],{"class":267}," 1",[186,1379,1380],{"class":196},")]\n",[186,1382,1383,1386,1388,1391,1393,1396,1398,1401,1403,1406],{"class":188,"line":271},[186,1384,1385],{"class":196},"missing ",[186,1387,219],{"class":192},[186,1389,1390],{"class":196}," [p ",[186,1392,1212],{"class":192},[186,1394,1395],{"class":196}," p ",[186,1397,1218],{"class":192},[186,1399,1400],{"class":196}," expected ",[186,1402,302],{"class":192},[186,1404,1405],{"class":192}," not",[186,1407,1408],{"class":196}," Path(p).exists()]\n",[186,1410,1411,1413,1416,1419,1421,1424,1426,1428,1431,1433,1436,1439,1441,1444,1446,1448],{"class":188,"line":282},[186,1412,85],{"class":267},[186,1414,1415],{"class":196},"(pages, ",[186,1417,1418],{"class":225},"\"pages;\"",[186,1420,598],{"class":196},[186,1422,1423],{"class":225},"\"all written\"",[186,1425,1033],{"class":192},[186,1427,1405],{"class":192},[186,1429,1430],{"class":196}," missing ",[186,1432,1044],{"class":192},[186,1434,1435],{"class":192}," f",[186,1437,1438],{"class":225},"\"missing ",[186,1440,332],{"class":267},[186,1442,1443],{"class":196},"missing",[186,1445,338],{"class":267},[186,1447,349],{"class":225},[186,1449,229],{"class":196},[14,1451,1452,1454,1455,598,1458,1461,1462,1466,1467,1470],{},[475,1453,477],{}," The first page keeps the given name and later pages get ",[18,1456,1457],{},"_2",[18,1459,1460],{},"_3"," and so on before the extension. Checking that every expected file exists, and is not tiny, catches failures that a single result code can hide — such as a page whose map failed to render. For many layouts in one go, the same result checking applies to each, as in ",[26,1463,1465],{"href":1464},"\u002Fspatial-data-processing-automation\u002Fautomated-map-layout-generation\u002Fexporting-multiple-qgis-layouts-to-pdf\u002F","exporting multiple layouts to PDF","; for atlases, ",[18,1468,1469],{},"QgsLayoutExporter.exportToImage(atlas, …)"," writes one image per feature with names from an expression.",[150,1472,1474],{"id":1473},"qgis-version-compatibility","QGIS version compatibility",[14,1476,1477,1479,1480,1483,1484,1487,1488,1491,1492,168],{},[18,1478,20],{}," image and SVG export settings shown work on QGIS 3.34 LTR, 3.40 LTR and QGIS 4. ",[18,1481,1482],{},"Qgis.TextRenderFormat"," replaced ",[18,1485,1486],{},"QgsRenderContext.TextRenderFormat"," in 3.30. On QGIS 4, ",[18,1489,1490],{},"QgsLayoutExporter.Success"," is ",[18,1493,1494],{},"QgsLayoutExporter.ExportResult.Success",[150,1496,1498],{"id":1497},"troubleshooting","Troubleshooting",[155,1500,1501,1510,1516,1522],{},[158,1502,1503,1506,1507,1509],{},[475,1504,1505],{},"Text looks tiny or huge in a fixed-size export."," Effective dpi changed with ",[18,1508,632],{},"; design the page for the target size.",[158,1511,1512,1515],{},[475,1513,1514],{},"The world file places the image wrongly."," The reference map was an inset, or the page includes non-map areas.",[158,1517,1518,1521],{},[475,1519,1520],{},"The PNG background is white despite transparency."," The page symbol or a map item background is still opaque.",[158,1523,1524,1527],{},[475,1525,1526],{},"SVG lost effects."," Blending and effects are not representable in SVG; avoid them for SVG exports.",[150,1529,1531],{"id":1530},"conclusion","Conclusion",[14,1533,1534],{},"Export images with a dpi for physical sizes or an exact pixel size for screens, write world files from an explicit reference map, crop to content with a transparent page for embedded maps, export layered SVG with vector output for designers, and check every page file and result code.",[150,1536,1538],{"id":1537},"frequently-asked-questions","Frequently Asked Questions",[14,1540,1541,1544],{},[475,1542,1543],{},"Which is better for web maps, PNG or SVG?","\nPNG for complex maps — SVG files with many features can be large and slow in browsers. SVG for simple diagrams and logos.",[14,1546,1547,1550,1551,1554,1555,168],{},[475,1548,1549],{},"Can I export only the map item without the page?","\nRender the map with ",[18,1552,1553],{},"QgsMapRendererParallelJob"," instead, as in ",[26,1556,1558],{"href":1557},"\u002Fpyqgis-cartography-visualization\u002Fmap-canvas-and-image-export\u002Frender-layer-to-image-without-gui-pyqgis\u002F","rendering a layer to an image without the GUI",[14,1560,1561,1564,1565,1568],{},[475,1562,1563],{},"Why is the TIFF so large?","\nUncompressed RGBA at 300 dpi; convert with ",[18,1566,1567],{},"gdal:translate"," and compression for archiving.",[14,1570,1571,1574],{},[475,1572,1573],{},"Do exports include hidden items?","\nNo — items hidden in the layout, or excluded from exports, are skipped.",[150,1576,1578],{"id":1577},"related","Related",[155,1580,1581,1586,1591,1597,1603],{},[158,1582,1583,1585],{},[26,1584,29],{"href":28}," — the guide this recipe belongs to",[158,1587,1588],{},[26,1589,1590],{"href":1464},"Exporting Multiple QGIS Layouts to PDF",[158,1592,1593],{},[26,1594,1596],{"href":1595},"\u002Fpyqgis-cartography-visualization\u002Fmap-canvas-and-image-export\u002Fexport-map-to-svg-and-pdf-pyqgis\u002F","Export a Map to SVG and PDF in PyQGIS",[158,1598,1599],{},[26,1600,1602],{"href":1601},"\u002Fspatial-data-processing-automation\u002Fautomated-map-layout-generation\u002Fload-layout-from-qpt-template-pyqgis\u002F","Load a Print Layout from a QPT Template in PyQGIS",[158,1604,1605],{},[26,1606,1608],{"href":1607},"\u002Fspatial-data-processing-automation\u002Fautomating-atlas-map-series\u002Fexport-atlas-pages-to-individual-pdfs-pyqgis\u002F","Export Atlas Pages to Individual PDFs in PyQGIS",[1610,1611,1612],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sjoCn, html code.shiki .sjoCn{--shiki-default:#9AA79F}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}",{"title":182,"searchDepth":206,"depth":206,"links":1614},[1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627],{"id":152,"depth":206,"text":153},{"id":171,"depth":206,"text":172},{"id":500,"depth":206,"text":501},{"id":636,"depth":206,"text":637},{"id":734,"depth":206,"text":735},{"id":861,"depth":206,"text":862},{"id":1066,"depth":206,"text":1067},{"id":1262,"depth":206,"text":1263},{"id":1473,"depth":206,"text":1474},{"id":1497,"depth":206,"text":1498},{"id":1530,"depth":206,"text":1531},{"id":1537,"depth":206,"text":1538},{"id":1577,"depth":206,"text":1578},"Export print layouts to PNG, JPEG, TIFF and SVG with QgsLayoutExporter — resolution and size, world files and georeferencing, transparent backgrounds, cropping to content, SVG layers for editing in illustration software, and checking the result of every export.","md",{"slug":1631,"type":1632,"breadcrumb":1633,"datePublished":1634,"dateModified":1634},"export-layout-to-image-and-svg-pyqgis","article","Export a Layout to Image and SVG","2026-10-02","\u002Fspatial-data-processing-automation\u002Fautomated-map-layout-generation\u002Fexport-layout-to-image-and-svg-pyqgis",{"title":5,"description":1628},"spatial-data-processing-automation\u002Fautomated-map-layout-generation\u002Fexport-layout-to-image-and-svg-pyqgis\u002Findex","h_rbVIRt293UZ2IsgD6Bzble0ppO2jti0KWQS8j-17w",1790966260489]