如何转换阴影地貌GeoTIFF投影以适配D3地图并转JPEG?
嘿,刚好折腾过类似的需求,给你一套完整的流程,从投影转换到D3里实现缩放平移,一步一步来:
第一步:准备原始数据
- 先下载你提到的Natural Earth灰度地貌GeoTIFF,它默认的投影是WGS84(EPSG:4326,也就是经纬度坐标)。
- 你给的D3示例用的是Albers USA投影(看示例里的
d3.geoAlbersUsa()),所以我们需要把栅格转换成和这个投影完全匹配的坐标系。
第二步:用GDAL做投影转换(核心步骤)
GDAL是处理栅格数据的行业标准工具,先确保你已经安装了(Linux/macOS可以用包管理器,Windows可以装OSGeo4W)。
用gdalwarp命令来转换投影,参数要和D3的Albers USA参数完全一致,不然会错位:
gdalwarp -t_srs "+proj=aea +lat_1=29.5 +lat_2=45.5 +lat_0=37.5 +lon_0=-96 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs" -r bilinear -of GTiff ne_10m_gray.tif albers_gray.tif
-t_srs:指定目标投影,这里的参数和D3的geoAlbersUsa()底层用的完全一样;-r bilinear:双线性重采样,保证转换后的图像平滑,比默认的最近邻采样效果好;-of GTiff:先输出TIFF,方便之后转JPEG。
第三步:转JPEG减小体积
用gdal_translate把转换好的TIFF转成JPEG,同时控制质量平衡体积:
gdal_translate -of JPEG -co QUALITY=90 albers_gray.tif final_basemap.jpg
-co QUALITY=90:质量设为90(范围1-100),这个值既能保证清晰度,体积也比原始TIFF小很多;如果还想更小,可以降到80,肉眼差别不大。
第四步:在D3中加载并实现缩放平移
首先得知道转换后栅格的地理范围,用gdalinfo albers_gray.tif命令查看,找到类似这样的行:
Upper Left (-2351733.900, 3174942.800) (124d41'53.78"W, 49d30'33.97"N) Lower Right ( 2535893.500, 1330215.500) ( 66d53'32.01"W, 24d31'14.29"N)
提取出左上角和右下角的经纬度:[-124.69827, 49.50944]和[-66.89222, 24.52064]。
然后在D3里写代码,把图像和投影对齐,再加缩放平移:
const width = 800; const height = 600; // 定义和转换时一致的投影 const projection = d3.geoAlbersUsa() .fitSize([width, height], { type: "Polygon", coordinates: [[ [-124.69827, 49.50944], // 左上角经纬度 [-66.89222, 49.50944], [-66.89222, 24.52064], [-124.69827, 24.52064], [-124.69827, 49.50944] ]] }); const svg = d3.select("#map") .append("svg") .attr("width", width) .attr("height", height); // 用来承载图像的容器,缩放平移会作用在这个g元素上 const mapGroup = svg.append("g"); // 加载转换好的JPEG底图 mapGroup.append("image") .attr("href", "final_basemap.jpg") // 计算图像的屏幕宽高:用投影转换四个角点的坐标差 .attr("width", projection([-66.89222, 24.52064])[0] - projection([-124.69827, 49.50944])[0]) .attr("height", projection([-124.69827, 24.52064])[1] - projection([-124.69827, 49.50944])[1]) // 设置图像的左上角位置 .attr("x", projection([-124.69827, 49.50944])[0]) .attr("y", projection([-124.69827, 49.50944])[1]); // 添加缩放平移功能 const zoom = d3.zoom() .scaleExtent([1, 8]) // 限制缩放范围,防止过度缩放 .on("zoom", (event) => { mapGroup.attr("transform", event.transform); }); svg.call(zoom);
- 这里用
fitSize让投影适配SVG的尺寸,然后把图像的位置和投影的地理范围对齐; d3.zoom直接作用在SVG上,通过修改mapGroup的transform来实现缩放和平移,非常方便。
一些注意事项
- 一定要保证GDAL转换时的投影参数和D3里的完全一致,不然底图会和矢量图层(如果有的话)错位;
- 如果原始TIFF有透明区域,可以在转换时加上
-dstnodata 255(假设透明值是255),转JPEG时如果需要透明可以用PNG,但JPEG不支持透明; - 要是觉得GDAL命令太麻烦,也可以用QGIS图形界面来做投影转换,操作更直观:导入TIFF,右键选择“导出->保存为...”,然后选择目标投影和输出格式。
内容的提问来源于stack exchange,提问作者Noobster
相关产品推荐
相关产品推荐

