[{"data":1,"prerenderedAt":813},["ShallowReactive",2],{"doc:\u002Fspatial-data-processing-automation\u002Fcoordinate-reference-systems\u002Fbatch-reprojecting-raster-datasets":3},{"id":4,"title":5,"body":6,"description":806,"extension":807,"meta":808,"navigation":92,"path":809,"seo":810,"stem":811,"__hash__":812},"docs\u002Fspatial-data-processing-automation\u002Fcoordinate-reference-systems\u002Fbatch-reprojecting-raster-datasets\u002Findex.md","Batch Reprojecting Raster Datasets in QGIS",{"type":7,"value":8,"toc":800},"minimark",[9,13,32,37,49,499,503,612,616,636,716,776,780,796],[10,11,5],"h1",{"id":12},"batch-reprojecting-raster-datasets-in-qgis",[14,15,16,17,22,23,27,28,31],"p",{},"Batch reprojecting raster datasets requires a consistent ",[18,19,21],"a",{"href":20},"\u002Fspatial-data-processing-automation\u002Fcoordinate-reference-systems\u002F","Coordinate Reference Systems"," framework to ensure spatial alignment across layers. In QGIS, the fastest approach uses the ",[24,25,26],"code",{},"processing.run()"," API with the ",[24,29,30],{},"gdal:warpreproject"," algorithm inside a Python loop. This method scans a source directory, applies a target CRS, and writes transformed outputs without GUI overhead.",[33,34,36],"h3",{"id":35},"core-pyqgis-script","Core PyQGIS Script",[14,38,39,40,44,45,48],{},"Run this directly in the ",[41,42,43],"strong",{},"QGIS Python Console"," (",[24,46,47],{},"Ctrl+Alt+P","). It handles directory scanning, CRS assignment, and error logging.",[50,51,56],"pre",{"className":52,"code":53,"language":54,"meta":55,"style":55},"language-python shiki shiki-themes github-dark","import os\nimport glob\nimport processing\n\n# Configuration\nINPUT_DIR = \"\u002Fpath\u002Fto\u002Fsource\u002Frasters\"\nOUTPUT_DIR = \"\u002Fpath\u002Fto\u002Freprojected\u002Frasters\"\nTARGET_CRS = \"EPSG:3857\" # Replace with your target EPSG\nRESAMPLING = 1 # 0=Nearest, 1=Bilinear, 2=Cubic, 3=CubicSpline\n\nos.makedirs(OUTPUT_DIR, exist_ok=True)\nraster_files = glob.glob(os.path.join(INPUT_DIR, \"*.tif\"))\n\nfor raster_path in raster_files:\n out_name = os.path.basename(raster_path).replace(\".tif\", \"_reproj.tif\")\n out_path = os.path.join(OUTPUT_DIR, out_name)\n \n params = {\n \"INPUT\": raster_path,\n \"SOURCE_CRS\": None, # Auto-detect from file metadata\n \"TARGET_CRS\": TARGET_CRS,\n \"RESAMPLING\": RESAMPLING,\n \"NODATA\": None,\n \"TARGET_RESOLUTION\": None,\n \"OPTIONS\": \"\",\n \"DATA_TYPE\": 0, # 0=Auto, 1=Byte, 2=UInt16, etc.\n \"OUTPUT\": out_path\n }\n \n try:\n processing.run(\"gdal:warpreproject\", params)\n print(f\"✔ Success: {out_name}\")\n except Exception as e:\n print(f\"✘ Failed {raster_path}: {e}\")\n","python","",[24,57,58,71,79,87,94,101,115,126,140,154,159,183,204,209,224,245,261,267,278,287,304,317,329,341,353,366,382,391,397,402,411,423,452,467],{"__ignoreMap":55},[59,60,63,67],"span",{"class":61,"line":62},"line",1,[59,64,66],{"class":65},"snl16","import",[59,68,70],{"class":69},"s95oV"," os\n",[59,72,74,76],{"class":61,"line":73},2,[59,75,66],{"class":65},[59,77,78],{"class":69}," glob\n",[59,80,82,84],{"class":61,"line":81},3,[59,83,66],{"class":65},[59,85,86],{"class":69}," processing\n",[59,88,90],{"class":61,"line":89},4,[59,91,93],{"emptyLinePlaceholder":92},true,"\n",[59,95,97],{"class":61,"line":96},5,[59,98,100],{"class":99},"sAwPA","# Configuration\n",[59,102,104,108,111],{"class":61,"line":103},6,[59,105,107],{"class":106},"sDLfK","INPUT_DIR",[59,109,110],{"class":65}," =",[59,112,114],{"class":113},"sU2Wk"," \"\u002Fpath\u002Fto\u002Fsource\u002Frasters\"\n",[59,116,118,121,123],{"class":61,"line":117},7,[59,119,120],{"class":106},"OUTPUT_DIR",[59,122,110],{"class":65},[59,124,125],{"class":113}," \"\u002Fpath\u002Fto\u002Freprojected\u002Frasters\"\n",[59,127,129,132,134,137],{"class":61,"line":128},8,[59,130,131],{"class":106},"TARGET_CRS",[59,133,110],{"class":65},[59,135,136],{"class":113}," \"EPSG:3857\"",[59,138,139],{"class":99}," # Replace with your target EPSG\n",[59,141,143,146,148,151],{"class":61,"line":142},9,[59,144,145],{"class":106},"RESAMPLING",[59,147,110],{"class":65},[59,149,150],{"class":106}," 1",[59,152,153],{"class":99}," # 0=Nearest, 1=Bilinear, 2=Cubic, 3=CubicSpline\n",[59,155,157],{"class":61,"line":156},10,[59,158,93],{"emptyLinePlaceholder":92},[59,160,162,165,167,170,174,177,180],{"class":61,"line":161},11,[59,163,164],{"class":69},"os.makedirs(",[59,166,120],{"class":106},[59,168,169],{"class":69},", ",[59,171,173],{"class":172},"s9osk","exist_ok",[59,175,176],{"class":65},"=",[59,178,179],{"class":106},"True",[59,181,182],{"class":69},")\n",[59,184,186,189,191,194,196,198,201],{"class":61,"line":185},12,[59,187,188],{"class":69},"raster_files ",[59,190,176],{"class":65},[59,192,193],{"class":69}," glob.glob(os.path.join(",[59,195,107],{"class":106},[59,197,169],{"class":69},[59,199,200],{"class":113},"\"*.tif\"",[59,202,203],{"class":69},"))\n",[59,205,207],{"class":61,"line":206},13,[59,208,93],{"emptyLinePlaceholder":92},[59,210,212,215,218,221],{"class":61,"line":211},14,[59,213,214],{"class":65},"for",[59,216,217],{"class":69}," raster_path ",[59,219,220],{"class":65},"in",[59,222,223],{"class":69}," raster_files:\n",[59,225,227,230,232,235,238,240,243],{"class":61,"line":226},15,[59,228,229],{"class":69}," out_name ",[59,231,176],{"class":65},[59,233,234],{"class":69}," os.path.basename(raster_path).replace(",[59,236,237],{"class":113},"\".tif\"",[59,239,169],{"class":69},[59,241,242],{"class":113},"\"_reproj.tif\"",[59,244,182],{"class":69},[59,246,248,251,253,256,258],{"class":61,"line":247},16,[59,249,250],{"class":69}," out_path ",[59,252,176],{"class":65},[59,254,255],{"class":69}," os.path.join(",[59,257,120],{"class":106},[59,259,260],{"class":69},", out_name)\n",[59,262,264],{"class":61,"line":263},17,[59,265,266],{"class":69}," \n",[59,268,270,273,275],{"class":61,"line":269},18,[59,271,272],{"class":69}," params ",[59,274,176],{"class":65},[59,276,277],{"class":69}," {\n",[59,279,281,284],{"class":61,"line":280},19,[59,282,283],{"class":113}," \"INPUT\"",[59,285,286],{"class":69},": raster_path,\n",[59,288,290,293,296,299,301],{"class":61,"line":289},20,[59,291,292],{"class":113}," \"SOURCE_CRS\"",[59,294,295],{"class":69},": ",[59,297,298],{"class":106},"None",[59,300,169],{"class":69},[59,302,303],{"class":99},"# Auto-detect from file metadata\n",[59,305,307,310,312,314],{"class":61,"line":306},21,[59,308,309],{"class":113}," \"TARGET_CRS\"",[59,311,295],{"class":69},[59,313,131],{"class":106},[59,315,316],{"class":69},",\n",[59,318,320,323,325,327],{"class":61,"line":319},22,[59,321,322],{"class":113}," \"RESAMPLING\"",[59,324,295],{"class":69},[59,326,145],{"class":106},[59,328,316],{"class":69},[59,330,332,335,337,339],{"class":61,"line":331},23,[59,333,334],{"class":113}," \"NODATA\"",[59,336,295],{"class":69},[59,338,298],{"class":106},[59,340,316],{"class":69},[59,342,344,347,349,351],{"class":61,"line":343},24,[59,345,346],{"class":113}," \"TARGET_RESOLUTION\"",[59,348,295],{"class":69},[59,350,298],{"class":106},[59,352,316],{"class":69},[59,354,356,359,361,364],{"class":61,"line":355},25,[59,357,358],{"class":113}," \"OPTIONS\"",[59,360,295],{"class":69},[59,362,363],{"class":113},"\"\"",[59,365,316],{"class":69},[59,367,369,372,374,377,379],{"class":61,"line":368},26,[59,370,371],{"class":113}," \"DATA_TYPE\"",[59,373,295],{"class":69},[59,375,376],{"class":106},"0",[59,378,169],{"class":69},[59,380,381],{"class":99},"# 0=Auto, 1=Byte, 2=UInt16, etc.\n",[59,383,385,388],{"class":61,"line":384},27,[59,386,387],{"class":113}," \"OUTPUT\"",[59,389,390],{"class":69},": out_path\n",[59,392,394],{"class":61,"line":393},28,[59,395,396],{"class":69}," }\n",[59,398,400],{"class":61,"line":399},29,[59,401,266],{"class":69},[59,403,405,408],{"class":61,"line":404},30,[59,406,407],{"class":65}," try",[59,409,410],{"class":69},":\n",[59,412,414,417,420],{"class":61,"line":413},31,[59,415,416],{"class":69}," processing.run(",[59,418,419],{"class":113},"\"gdal:warpreproject\"",[59,421,422],{"class":69},", params)\n",[59,424,426,429,432,435,438,441,444,447,450],{"class":61,"line":425},32,[59,427,428],{"class":106}," print",[59,430,431],{"class":69},"(",[59,433,434],{"class":65},"f",[59,436,437],{"class":113},"\"✔ Success: ",[59,439,440],{"class":106},"{",[59,442,443],{"class":69},"out_name",[59,445,446],{"class":106},"}",[59,448,449],{"class":113},"\"",[59,451,182],{"class":69},[59,453,455,458,461,464],{"class":61,"line":454},33,[59,456,457],{"class":65}," except",[59,459,460],{"class":106}," Exception",[59,462,463],{"class":65}," as",[59,465,466],{"class":69}," e:\n",[59,468,470,472,474,476,479,481,484,486,488,490,493,495,497],{"class":61,"line":469},34,[59,471,428],{"class":106},[59,473,431],{"class":69},[59,475,434],{"class":65},[59,477,478],{"class":113},"\"✘ Failed ",[59,480,440],{"class":106},[59,482,483],{"class":69},"raster_path",[59,485,446],{"class":106},[59,487,295],{"class":113},[59,489,440],{"class":106},[59,491,492],{"class":69},"e",[59,494,446],{"class":106},[59,496,449],{"class":113},[59,498,182],{"class":69},[33,500,502],{"id":501},"compatibility-requirements","Compatibility & Requirements",[504,505,506,522],"table",{},[507,508,509],"thead",{},[510,511,512,516,519],"tr",{},[513,514,515],"th",{},"Component",[513,517,518],{},"Requirement",[513,520,521],{},"Notes",[523,524,525,548,565,578,595],"tbody",{},[510,526,527,533,536],{},[528,529,530],"td",{},[41,531,532],{},"QGIS Version",[528,534,535],{},"3.28 LTR+",[528,537,538,540,541,543,544,547],{},[24,539,30],{}," parameters stabilized in 3.24+. Older versions require ",[24,542,131],{}," as a ",[24,545,546],{},"QgsCoordinateReferenceSystem"," object.",[510,549,550,555,558],{},[528,551,552],{},[41,553,554],{},"Python Env",[528,556,557],{},"QGIS Bundled (3.10+)",[528,559,560,561,564],{},"Must run inside QGIS. Standalone execution requires ",[24,562,563],{},"QgsApplication"," initialization.",[510,566,567,572,575],{},[528,568,569],{},[41,570,571],{},"GDAL\u002FPROJ",[528,573,574],{},"GDAL ≥3.4, PROJ ≥8.2",[528,576,577],{},"Required for accurate datum shifts. Missing PROJ grids cause silent fallbacks or coordinate drift.",[510,579,580,585,588],{},[528,581,582],{},[41,583,584],{},"File Paths",[528,586,587],{},"UTF-8, no spaces",[528,589,590,591,594],{},"Use raw strings (",[24,592,593],{},"r\"C:\\data\"",") or forward slashes on Windows. Network drives may timeout on large batches.",[510,596,597,602,605],{},[528,598,599],{},[41,600,601],{},"Memory",[528,603,604],{},"RAM ≥ 2× largest raster",[528,606,607,608,611],{},"GDAL tiles into memory. For >4GB files, set ",[24,609,610],{},"\"OPTIONS\": \"-co TILED=YES -co COMPRESS=LZW\""," to reduce I\u002FO pressure.",[33,613,615],{"id":614},"troubleshooting-fallbacks","Troubleshooting & Fallbacks",[617,618,619,630],"ul",{},[620,621,622,625,626,629],"li",{},[41,623,624],{},"GUI Alternative",": Open ",[24,627,628],{},"Processing Toolbox → GDAL → Warp (Reproject) → Right-click → Execute as Batch Process",". Drag files in, set the target CRS column, and run. Bypasses Python but lacks programmatic error recovery.",[620,631,632,635],{},[41,633,634],{},"CLI Fallback",": If QGIS bindings fail, run a shell loop with native GDAL:",[50,637,641],{"className":638,"code":639,"language":640,"meta":55,"style":55},"language-bash shiki shiki-themes github-dark","mkdir -p reproj_output\nfor f in source\u002F*.tif; do\ngdalwarp -t_srs EPSG:3857 -r bilinear \"$f\" \"reproj_output\u002F$(basename \"$f\" .tif)_reproj.tif\"\ndone\n","bash",[24,642,643,655,673,711],{"__ignoreMap":55},[59,644,645,649,652],{"class":61,"line":62},[59,646,648],{"class":647},"svObZ","mkdir",[59,650,651],{"class":106}," -p",[59,653,654],{"class":113}," reproj_output\n",[59,656,657,659,662,664,667,670],{"class":61,"line":73},[59,658,214],{"class":65},[59,660,661],{"class":69}," f ",[59,663,220],{"class":65},[59,665,666],{"class":113}," source\u002F*.tif",[59,668,669],{"class":69},"; ",[59,671,672],{"class":65},"do\n",[59,674,675,678,681,684,687,690,693,696,698,701,704,706,708],{"class":61,"line":81},[59,676,677],{"class":647},"gdalwarp",[59,679,680],{"class":106}," -t_srs",[59,682,683],{"class":113}," EPSG:3857",[59,685,686],{"class":106}," -r",[59,688,689],{"class":113}," bilinear",[59,691,692],{"class":113}," \"",[59,694,695],{"class":69},"$f",[59,697,449],{"class":113},[59,699,700],{"class":113}," \"reproj_output\u002F$(",[59,702,703],{"class":647},"basename",[59,705,692],{"class":113},[59,707,695],{"class":69},[59,709,710],{"class":113},"\" .tif)_reproj.tif\"\n",[59,712,713],{"class":61,"line":89},[59,714,715],{"class":65},"done\n",[617,717,718,740,758],{},[620,719,720,723,724,727,728,731,732,735,736,739],{},[41,721,722],{},"Missing Source CRS",": If ",[24,725,726],{},"SOURCE_CRS: None"," throws a ",[24,729,730],{},"CRS not defined"," error, manually extract it first: ",[24,733,734],{},"QgsRasterLayer(raster_path, \"temp\").crs().authid()"," and pass the string to ",[24,737,738],{},"params[\"SOURCE_CRS\"]",".",[620,741,742,745,746,749,750,753,754,757],{},[41,743,744],{},"Resampling Artifacts",": Use ",[24,747,748],{},"RESAMPLING = 0"," (Nearest Neighbor) for categorical data (land cover, classes). Use ",[24,751,752],{},"1"," or ",[24,755,756],{},"2"," for continuous data (DEM, temperature). Mismatched methods introduce false pixel values.",[620,759,760,763,764,767,768,771,772,775],{},[41,761,762],{},"Large Dataset Limits",": For >50GB batches, process in chunks or build a Virtual Raster (",[24,765,766],{},"gdal:buildvirtualraster",") first. Add ",[24,769,770],{},"\"-co BIGTIFF=YES\""," to ",[24,773,774],{},"OPTIONS"," to bypass 4GB file limits.",[33,777,779],{"id":778},"validation-workflow-integration","Validation & Workflow Integration",[14,781,782,783,786,787,790,791,795],{},"Always verify output headers and check for pixel alignment shifts after processing. Use ",[24,784,785],{},"gdalinfo"," or QGIS Raster Properties to confirm the embedded ",[24,788,789],{},"Coordinate Reference System"," matches your target exactly. Integrating this script into broader ",[18,792,794],{"href":793},"\u002Fspatial-data-processing-automation\u002F","Spatial Data Processing & Automation"," pipelines requires automated validation: log failures immediately, as silent GDAL errors typically stem from missing projection metadata or incompatible data types rather than syntax issues.",[797,798,799],"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 .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}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 .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}",{"title":55,"searchDepth":73,"depth":73,"links":801},[802,803,804,805],{"id":35,"depth":81,"text":36},{"id":501,"depth":81,"text":502},{"id":614,"depth":81,"text":615},{"id":778,"depth":81,"text":779},"Batch reprojecting raster datasets requires a consistent Coordinate Reference Systems framework to ensure spatial alignment across layers. In QGIS, the fastest approach uses the processing.run() API with the gdal:warpreproject algorithm inside a Python loop. This method scans a source directory, applies a target CRS, and writes transformed outputs without GUI overhead.","md",{},"\u002Fspatial-data-processing-automation\u002Fcoordinate-reference-systems\u002Fbatch-reprojecting-raster-datasets",{"title":5,"description":806},"spatial-data-processing-automation\u002Fcoordinate-reference-systems\u002Fbatch-reprojecting-raster-datasets\u002Findex","wj2aAEUJoxnwU-fNNMsRVQ82oAB_ZkqxWdbIrmxG8aI",1777824788945]