时间:2025-11-25 16:33
人气:
作者:admin
版权声明:
本文为原创内容,作者:[Yzi321]。
转载请注明出处:
原博主主页:https://www.cnblogs.com/Yzi321
本文链接:https://www.cnblogs.com/Yzi321/p/19269003
许可协议:CC BY 4.0
Qt版本:5.11.2
编译平台:MSVC 2017 x64
在高分辨率图像浏览、地图渲染或工业视觉中,单张完整图像往往非常大,直接加载会导致内存占用过高甚至崩溃。因此,常采用 瓦片化(Tile-based)策略,将大图切分为小块(Tile),按需加载和渲染。
与地图瓦片结构不同,本文瓦片图格式使用 level.x.y.ext 的格式,其中level是当前瓦片实际缩放的倍数。
如:1:1显示的最底层的level是1,上一层使用1:2的缩放的level是2,再上一层使用1:4的缩放的level是4,以此类推。
所以最高层的level最大,也是最大的鸟瞰图,同时level也一定是2的倍数。
这次层级关系是与常见的GIS模式不用, 如果需要兼容,可以重写以下部分 即可:
MXTGraphicsTileLoader::Private::ParseLevelInfo,修改瓦片文件夹的解析流程,进行层级转化到本文的level模式
MXTGraphicsTileLoader::Private::MakeTilePath,生成瓦片文件的路径
(x, y) 作为瓦片坐标,且从(1,1)开始计算level.x.y.png 或 level.x.y.tif// 瓦片加载器配置信息
struct MXTGraphicsTileLoaderConfig {
QString folderPath; // 文件夹路径,瓦片所在根目录
QByteArray format = "tif"; // 瓦片图像格式(tif/png/jpg/bmp)
QSize tileSize = QSize(1024, 1024); // 每个瓦片在 scene 中显示的大小
// 影响缩放比例,可与真实瓦片不一致,实现缩放/拉伸
// 若原图512x512,设置为256x256则缩小显示
int ringRadius = 1; // 环形加载半径(视野扩展加载优化)
int crossLevelRadius = 1; // 交叉层加载跨度(通常用于多层级预加载)
int debounceMs = 80; // 加载请求防抖控制(毫秒)
// 避免鼠标滚轮或平移时过多请求
long long maxCacheCount = 200; // Tile 最大缓存数量(LRU 淘汰)
int mutexSleepTime = 200; // 互斥锁等待超时(毫秒)
LayerFilterMode filterMode = LayerFilterMode::Auto; // 层级过滤模式(自动/手动)
QSet<ZLEVEL> filterLevels; // 若为手动模式,这里指定要加载的层级
bool autoCropEdges = true; // 自动裁剪右/下边缘黑边(不规则大图常用)
};
计算当前需要显示哪一个层级时,获取参数显示视图尺寸visibleRect,获取显示视图内物理显示屏的像素尺寸physicalViewportSize,去计算不同层级下显示视图尺寸在当前缩放倍数下和像素尺寸的差距,以最小值作为显示层级。
详细代码如下:
static ZLEVEL FindClosestLevel( const QMap<ZLEVEL, TileLevelInfo>& levels,
const QRectF& visibleRect,
const QSize& physicalViewportSize)
{
ZLEVEL bestLevel = 0;
double minDist2 = std::numeric_limits<double>::max();
for (auto it = levels.constBegin(); it != levels.constEnd(); ++it) {
const TileLevelInfo& info = it.value();
// 计算当前 level 对应的 point
double w = visibleRect.width() / info.level_;
double h = visibleRect.height() / info.level_;
QPointF pt(w, h);
// 计算与 physicalViewportSize 的平方距离
double dx = pt.x() - physicalViewportSize.width();
double dy = pt.y() - physicalViewportSize.height();
double dist2 = dx * dx + dy * dy;
if (dist2 < minDist2) {
minDist2 = dist2;
bestLevel = it.key();
}
}
return bestLevel;
}
// 创建瓦片图 Item
MXTGraphicsTilePixmapItem* item = new MXTGraphicsTilePixmapItem();
// 构建加载配置
MXTGraphicsTileLoaderConfig lConfig;
lConfig.folderPath = "D:/TEST_IMAGES";
lConfig.tileSize = QSize(500, 500); // 控制瓦片显示的缩放比例
lConfig.format = "tif";
lConfig.maxCacheCount = 200;
// 初始化加载器
item->InitializeLoader(lConfig);
// 添加到 scene
view->scene()->addItem(item);
// !!! 必须绑定 view,触发视图更新瓦片缓存
item->bindView(view);
// 删除当前图片
item->ClearLoader();
// 加载新图片
item->InitializeLoader(lAnotherConfig);
例程环境:VS2022 Qt5.11.2 MSVC2017_x64
这是文件下载链接1(GoogleDrive)、文件下载链接2(百度网盘)。(包含了演示里的两个测试用例)
优势:
代码实现了一个派生QGraphicsItem,可以直接作为一个item使用简单,不与scene和view的耦合过多
不足:
瓦片文件夹结构需要根据自己的环境重写,且定义的层级结构和当前流行的GIS结构相反

瓦片图策略核心是 分块 + 层级 + 按需加载,能够在保证大图可视化的同时控制内存占用和性能。
在工业图像处理、地图可视化、高分辨率图像浏览等场景中都非常实用。
https://www.cnblogs.com/IntelligencePointer/p/18443664
© 原创作者:[Yzi321]
原文链接:https://www.cnblogs.com/Yzi321/p/19269003
转载请注明出处。
协议:CC BY 4.0