# BatchPhotoGeo **Repository Path**: wangdl23/batch-photo-geo ## Basic Information - **Project Name**: BatchPhotoGeo - **Description**: 本项目是基于 ArcObjects (10.8.2) 开发的 ArcGIS Desktop Add-in 插件,用于解决大批量航拍照片无法直接作为编辑底图的问题,直接利用行列矩阵算法和图片像素尺寸,配合 .jgw 坐标定位文件,将多张航拍影像无缝导入 ArcMap 并精确对齐到网格中。导入后的影像层可作为矢量化编辑的基底(背景图),结合 ArcGIS 布局工具,能够高效生成图例并批量导出成果。 - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-01 - **Last Updated**: 2026-11-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # BatchPhotoGeo - 航拍照片入图工具 **当前版本:v2.0.0**(2026-11-04) 项目主页:https://gitee.com/wangdl23/batch-photo-geo 📄 **配套文章**:[GISer的工程图册:400 张照片,铺成一本能编辑的图册](https://mp.weixin.qq.com/s/SX-qJ6Vn4thm34ntxNFh5A)(公众号「山行借路」· 赶路利器 01) 📖 **操作手册:[docs/操作手册.md](docs/操作手册.md)** —— 图文分步:安装启动 / 批量导入(新建渔网 / 追加已有渔网) / 单张照片导入 / 单元选片入图 / 页面设置 / 常见问题(**含 5 张界面截图**) --- ## ⬇ 下载 **普通用户(推荐)**:直接下载打包好的插件安装包 —— 见 **Gitee 发行版**: 1. 下载 `BatchPhotoGeo_v2.0.0.esriAddIn` 2. **先关闭 ArcMap** → 双击该文件安装(双击无反应时,用 ArcMap「自定义 → Add-In 管理器 → 选项 → 从文件添加」) 3. 启动 ArcMap,工具栏出现 **BatchPhotoGeo** —— 含 5 个按钮:批量导入 / 单张照片导入 / 单元选片入图 / 页面设置 / 打开在线帮助文档 4. ⚠️ **仅支持 ArcMap 10.8.2**(基于 ArcObjects 10.8.2 编译),**不支持 ArcGIS Pro**;需 .NET Framework 4.5.2 > 装上后按钮显示"缺失"、或想换版本?通过 Add-In 管理器**卸载后重装**,必要时重置 `Normal.mxt` 模板 —— 详见 [操作手册](docs/操作手册.md) §3.4 卸载与重装。 **开发者 / 想自行编译**:源码就在仓库里,见下方「[开发编译](#开发编译)」。 --- 基于 ArcObjects 10.8.2 SDK 编译的 ArcGIS Desktop Add-in 插件(**当前仅兼容 ArcMap 10.8.2**),用于解决大批量航拍照片无法直接作为编辑底图的问题。自动读取图片像素尺寸并分组(单张照片导入按缩放后的尺寸匹配),配合行列矩阵算法与世界文件(jgw/pgw/tfw),将多张航拍影像导入 ArcMap 并精确对齐到网格中。 提供三种入图方式: 1. **批量导入**:一个窗口、两种模式——**新建渔网**(递归扫描文件夹及所有子文件夹,覆盖式建库)/ **追加到已有渔网**(追加新增照片、按完整路径去重,不影响已有成果) 2. **单张照片导入**:停靠式窗口(可停靠在 ArcMap 左/右/上/下侧或浮动),拖入单张照片归集到照片集文件夹,在渔网中新增或原地更新对应要素,可连续操作 3. **单元选片入图**:读取《dji_metadata_单元归属.xlsx》只取主片,走与批量导入相同的两种模式 ## 功能特性 - **像素尺寸自动分组**:自动读取文件夹及其所有子文件夹内每张图片的真实像素宽高(System.Drawing)。批量导入(新建与追加)按"宽×高"像素尺寸聚合(追加的新照片沿用所匹配分组的缩放系数);**单张照片导入按缩放后的"宽×高"聚合**(像素尺寸 × 缩放系数,例如 5280×3950@0.1 与 2640×1975@0.2 同属 528×395 组) - **EXIF / DJI XMP 元数据读取**:读取 EXIF 的 GPS 经纬度、拍摄时间、相机制造商与型号;对 JPG/JPEG 额外解析 DJI XMP(参考 DJI 工具箱工具1),把 GPS/绝对高程/相对航高/GPS 高程、云台三轴、飞行三轴、GPS 状态、Version/ImageSource、标定焦距/焦距/光圈/曝光/ISO、拍摄点坐标写入渔网(仅作属性记录,不参与定位);各导入窗口均有「是否写入元数据」勾选项,可关闭元数据入库;单张照片拖入窗口时仍会读取显示 - **组间水平错开**:多组影像在 X 方向依次向右平移排列(每组按前一组"每行照片数 × 宽度 × 缩放系数 × 2"累加偏移),互不重叠,渔网更直观 - **缩放系数**:控制影像投影到地图后的实际尺寸(地图尺寸 = 像素尺寸 × 缩放系数)。例如 5280×3956 像素、缩放系数 0.1 时投影为 528m×395.6m,避免影像过大 - **坐标定位**:绝对坐标系(原点默认 0,0,可自定义),上下、左右相邻图片之间间隔一个标准渔网间隔(即一张缩放后图片的宽/高) - **配准文件生成**:按图片格式自动匹配世界文件后缀——JPG→`.jgw`、PNG→`.pgw`、TIF→`.tfw`(另支持 BMP→`.bpw`、GIF→`.gfw`),像元大小 = 缩放系数 - **渔网生成**:按网格四角坐标批量创建矩形面要素类(Shapefile / File GDB),含网格编号、分组编号、每行照片数、缩放系数、像素宽高、完整路径与 EXIF 元数据等属性 - **批量加载**:自动将 JPG/JPEG/TIF/TIFF/PNG 影像作为栅格图层加载至当前地图 - **批量导入**:工具栏"批量导入"按钮,一个窗口两种模式——**新建渔网**(递归扫描文件夹及所有子文件夹,覆盖式建库:像素尺寸分组 → 行列排布 → 组间水平错开 → 生成渔网与全部配准文件)与**追加到已有渔网**(按像素尺寸归组,同组图片在所在分组后继续排布、沿用该组缩放系数;全新尺寸另起分组排在右侧;按完整路径去重,重复照片自动跳过,不重复生成配准文件与图层) - **单张照片导入**:工具栏"单张照片导入"按钮,打开/收起 ArcMap **停靠式窗口**(可停靠在左/右/上/下侧或拖出浮动,跟随 ArcMap 一同显示):拖入单张照片即显示缩略图、源路径与 EXIF 元数据;自动将照片复制归集到指定照片集文件夹(目标文件已存在时弹窗确认覆盖),并在指定渔网中写入要素——**按 ImageName 已存在则原地更新**(改几何+属性,不新增行),否则按缩放后尺寸归组续排或另起新组;「单元名称」写入渔网 UnitName,勾选「同步修改文件名称」时按单元名称重命名归集照片,不勾选则保留源文件名;点「导入」后窗口内容清空(保留文件夹/shp/缩放系数/勾选项),可立即拖入下一张 - **单元选片入图**:工具栏"单元选片入图"按钮,读取 DJI 工具箱(djiexifs)工具3 输出的 **《dji_metadata_单元归属.xlsx》**——**只导入「单元名」非空且「主副=主」的照片(副片不导入)**。支持**两种模式**,分别复用既有的两个功能:**新建渔网**(同「批量导入·新建」:像素尺寸分组 → 行列排布 → 组间错开 → 新渔网 + 配准文件)与**追加到已有渔网**(同「批量导入·追加」:匹配已有分组续排 → 完整路径去重 → 追加要素 + 仅新照片配准文件)。渔网另写 **UnitName(单元名)/ PhotoRole(主副)** 两列。内置 xlsx 读取器,**不依赖 Excel 或第三方库** - **页面设置**:工具栏"页面设置"按钮,按锚点可视化设置数据框的大小、位置(保留纵横比),宽高同步应用到页面大小(自动清除"使用打印机纸张设置") - **按 MXD 记忆配置**:批量导入、单元选片、单张照片导入在窗口关闭/导入成功后,按**当前 MXD 的完整路径**保存上次参数(模式、路径、每行数、缩放系数、原点、自动加载、是否写入元数据;单张导入还包括“同步修改文件名称”勾选状态);再次打开同一 MXD 时自动恢复。配置位于 `%APPDATA%\BatchPhotoGeo\MxdConfigs\`,不同目录下的同名 MXD 不会互相覆盖 - **转化日志**:每次生成配准文件或单张照片归集时,追加 CSV 记录——时间、MXD、操作、转化类型、**转化前文件路径**、**转化后文件路径**、结果、说明;按月在 `%APPDATA%\BatchPhotoGeo\Logs\Conversion\conversion_yyyyMM.csv` 留存,UTF-8 BOM 可直接用 Excel 打开 - **制图辅助**:渔网层可直接作为 ArcGIS"数据驱动页面"索引图层,配合布局模板批量出图 - **在线帮助**:工具栏"打开在线帮助文档"按钮,一键跳转至项目 Gitee 页面 ## 渔网属性字段 | 字段 | 类型 | 说明 | |------|------|------| | GridNumber | 整型 | 网格递增编号(从1开始,跨组连续) | | GroupId | 整型 | 分组编号(按缩放后尺寸分组,从0开始) | | PerRow | 整型 | 每行照片数(全局,逐要素冗余存储便于恢复) | | Scale | 双精度 | 缩放系数(逐要素冗余存储便于恢复) | | PixWidth | 整型 | 像素宽度 | | PixHeight | 整型 | 像素高度 | | Name | 文本(200) | 名称(不含扩展名的文件名) | | Row | 整型 | 行号(组内从0开始) | | Column | 整型 | 列号(组内从0开始) | | ImageName | 文本(254) | 图片文件名(含扩展名) | | FullPath | 文本(254) | 对象完整路径(含文件名,用于追加模式去重) | | Longitude | 双精度 | 经度(WGS84 十进制度,无 GPS 为空) | | Latitude | 双精度 | 纬度(WGS84 十进制度,无 GPS 为空) | | ShotTime | 文本(24) | 拍摄时间(YYYY-MM-DD HH:MM:SS) | | Make | 文本(64) | 相机制造商 | | Model | 文本(64) | 相机型号 | | AbsAlt | 双精度 | 绝对高程(m,DJI XMP;无则空) | | RelAlt | 双精度 | 相对起飞点航高(m,DJI XMP;无则空) | | GimbalYaw | 双精度 | 云台偏航角(°,DJI XMP) | | GimbalPit | 双精度 | 云台俯仰角(°,DJI XMP) | | GimbalRol | 双精度 | 云台翻滚角(°,DJI XMP) | | FlightYaw | 双精度 | 飞行器航向角(°,DJI XMP) | | FlightPit | 双精度 | 飞行器俯仰角(°,DJI XMP) | | FlightRol | 双精度 | 飞行器翻滚角(°,DJI XMP) | | GpsStatus | 文本(32) | GPS 状态(如 RTK / GPS,DJI XMP) | | Version | 文本(32) | DJI XMP Version | | ImgSource | 文本(64) | 图像来源 ImageSource | | GpsAlt | 双精度 | GPS 高程(m) | | CalFocal | 双精度 | 标定焦距(像素,CalibratedFocalLength) | | FocalLen | 双精度 | 焦距(mm) | | FNumber | 双精度 | 光圈 | | Exposure | 双精度 | 曝光时间(秒) | | ISO | 整型 | ISO 感光度 | | CaptureX | 双精度 | 拍摄点 X(若 XMP 提供) | | CaptureY | 双精度 | 拍摄点 Y(若 XMP 提供) | | CaptureZ | 双精度 | 拍摄点 Z(若 XMP 提供) | | UnitName | 文本(200) | 单元名(单元选片入图或单张照片导入写入) | | PhotoRole | 文本(8) | 主副:恒为「主」(仅单元选片入图写入,副片不导入) | | TopLeftX | 双精度 | 左上角X坐标 | | TopLeftY | 双精度 | 左上角Y坐标 | > 导入时取消「是否写入元数据」后,`Longitude`/`Latitude`、`ShotTime`、`Make`/`Model` 及全部 DJI XMP 字段不写入(数值型显示为 Shapefile 默认值 0,文本型为空);几何、路径、像素尺寸、`UnitName`/`PhotoRole` 仍正常写入。 ## 环境要求 - ArcGIS Desktop **10.8.2**(ArcMap) - .NET Framework 4.5.2 - Windows x86 / x64(ArcMap 为 32 位进程) ## 安装使用 1. 关闭 ArcMap 2. 双击 `BatchPhotoGeo\bin\x86\Debug\BatchPhotoGeo.esriAddIn` 安装(或通过 ArcMap 自定义 → Add-In 管理器安装) 3. 启动 ArcMap,工具栏("BatchPhotoGeo")包含五个按钮: - **批量导入**:一个窗体两种模式——新建渔网(递归扫描文件夹及子文件夹,覆盖式建库)/ 追加到已有渔网(追加新照片、去重) - **单张照片导入**:打开/收起停靠窗口,拖拽单张照片归集并写入渔网 - **单元选片入图**:读取《dji_metadata_单元归属.xlsx》,只取主片按单元排片并建渔网 - **页面设置**:按锚点设置数据框大小与位置,宽高同步应用到页面 - **打开在线帮助文档**:跳转至 Gitee 在线帮助页面 4. 在「批量导入」窗体中填写(默认 **新建渔网** 模式;追加模式改为选择已有渔网,排布参数沿用渔网): - 图片文件夹路径 - 每行照片数量(全局,所有分组共用) - 坐标推算原点 X / Y(默认 0,0) - 缩放系数(默认 1;像素即地图单位) - 渔网输出路径(*.shp) - 是否自动加载至地图 - 是否写入元数据(默认勾选;不勾选时 GPS/时间/机型/DJI XMP 字段留空) 5. 点击 **"开始执行"**,自动完成:读取像素尺寸、EXIF 与 DJI XMP 并分组 → 矩阵推算 → 清理旧配准文件 → 生成世界文件 → 渔网构建 → 影像加载 6. 执行完成后弹窗汇总:处理的组数 / 图片数,以及因元数据读取失败被跳过的图片数量 ### 单张照片导入 1. 点击工具栏 **"单张照片导入"**,在 ArcMap 左侧打开停靠窗口(可拖到右/上/下侧停靠,或拖出变为浮动窗口;再次点击按钮收起) 2. 在停靠窗口中选择/确认参数:**照片集文件夹**(归集目录,可自动创建)、**单元名称**、是否**同步修改文件名称**、**照片矢量**(shp,可选择尚不存在的新路径)、**缩放系数**、是否**自动加载到地图**、是否**写入元数据**(默认勾选) 3. 将一张照片拖入虚线拖放区(jpg/jpeg/tif/tiff/png),窗口立即显示缩略图、源路径,以及照片元数据:像素尺寸、缩放后尺寸、GPS 经纬度、拍摄时间、相机制造商、型号;「单元名称」默认取源文件名(可改) 4. 点击 **"导入"**:照片复制到照片集文件夹(目标文件已存在时弹窗确认覆盖)→ 生成世界文件 → 渔网写入(ImageName 已存在则原地更新,否则新增),同时把单元名称写入 `UnitName` → 可选加载到地图 5. 导入后**清空拖放区与单元名称**、保留文件夹/shp/缩放系数/勾选项,状态栏回显结果,可立即拖入下一张 > **同步修改文件名称**:勾选(默认)时,归集后的照片文件名 = 单元名称 + 原扩展名;不勾选时保留源文件名,只把单元名称写入渔网 `UnitName` 字段。 ### 单元选片入图(v1.5.0 新增) 适合"已用 DJI 工具箱(djiexifs)工具3 完成单元选片与归属标注"的批次,不再人工挑片: 1. 点击工具栏 **"单元选片入图"**,打开「BatchPhotoGeo - 单元选片入图」窗体 2. **选择操作模式**:**新建渔网**(同「批量导入·新建」)/ **追加到已有渔网**(同「批量导入·追加」);追加模式下排布参数置灰,沿用已有渔网 3. 选择 **单元归属 Excel**(`dji_metadata_单元归属.xlsx`);如需按文件名兜底查找,再选 **照片根目录**(可留空,优先用 Excel 的 FilePath) 4. 新建模式:设置 **每行照片数**(默认 1)、**缩放系数**、**原点 X/Y**,指定 **渔网输出路径**(*.shp,已存在会被覆盖重建);追加模式:选择 **已有渔网**(只追加不重建) 5. 点击 **"开始执行"**(勾选自动加载时:新建模式加载影像与渔网,追加模式只加载新影像(渔网已在图中)) 6. 插件**只取主片**:新建模式走批量导入·新建流水线(分组 → 行列排布 → 组间错开 → 新渔网);追加模式走批量导入·追加流水线(尺寸匹配续排 → 完整路径去重 → 追加要素);两种模式都另写 UnitName / PhotoRole 7. 完成弹窗汇总:与对应原功能同一文案,末尾追加"选片口径"一行(主片数、跳过的副片、无主片单元数) > 前置要求:Excel 第一个工作表同时含 `FileName`、`单元名` 与 `主副` 三列(工具3 的产物,只认「主副=主」的行);只支持 `.xlsx`。 ## 工作原理 ``` 分组: 批量导入(新建与追加)按"宽×高"像素尺寸聚合图片(追加的新照片沿用组内缩放系数);单张照片导入按"缩放后宽×高"聚合(组内按文件名排序) 矩阵推算:组行数 = ⌈组内图片数 ÷ 每行数量⌉ 坐标推算:第N列左上角X = 原点X + N × (宽度×缩放系数) × 2 (间隔 = 一个缩放后渔网间隔) 第M行左上角Y = 组顶Y - (M × (高度×缩放系数) × 2) (Y轴向上为正,向下取负) 右下角 = 左上角 + (宽度×缩放系数, -高度×缩放系数) (渔网格紧贴对应图片) 组间错开:下一组顶X = 上一组顶X + 上一组每行照片数 × 宽度×缩放系数 × 2 世界文件:缩放系数 / 0 / 0 / -缩放系数 / 左上角X / 左上角Y(按图片格式匹配后缀) 渔网面: 按四角坐标创建矩形Polygon,写入网格编号、分组编号、每行照片数、缩放系数、像素宽高、EXIF 元数据等属性 ``` - 坐标推算原点(默认 (0,0))位于矩阵第一组左上角第一张图的左上角,可在参数窗体中自定义 - 渔网空间参考跟随当前地图首个要素图层;地图无投影时采用未知坐标系(纯整数平面) - 执行前自动递归清理所选文件夹及所有子文件夹内已有的旧世界文件(.jgw/.pgw/.tfw/.bpw/.gfw/.wld) - 世界文件数值以固定小数点格式(InvariantCulture)写入,避免区域设置导致的小数点差异 ## 后续工作流 1. 影像按网格间隔排列加载后,直接在底图上用 ArcGIS 编辑工具进行点、线、面矢量化 2. 布局视图插入图例,展示图层名称和样式 3. 将渔网层设为"数据驱动页面"索引图层,一键批量导出各分幅成果图 ## 项目结构 ``` BatchPhotoGeo.sln ├── BatchPhotoGeo/ # Add-in 项目(入口 + 配置) │ ├── Config.esriaddinx # 插件配置清单(版本 2.0.0) │ ├── Config.Designer.cs # 清单对应代码 │ ├── BatchImportButton.cs # 按钮入口:批量导入(新建渔网 / 追加已有渔网) │ ├── SinglePhotoButton.cs # 按钮入口:打开/收起单张照片导入停靠窗 │ ├── SinglePhotoDockWindow.cs # 单张照片导入停靠式窗口宿主(DockableWindow) │ ├── UnitSelectionButton.cs # 按钮入口:单元选片入图(读单元归属 Excel) │ ├── PageSetupButton.cs # 按钮入口:页面设置 │ ├── OpenHelpButton.cs # 按钮入口:打开在线帮助文档 │ ├── Images/ # 按钮图标(BatchPhotoGeo.png / FoldePhotoGeo16.png / OnePhotoGeo16.png / SelectorPhotoGeo16.png / LayoutFile16.png / Help16.png) │ └── Properties/AssemblyInfo.cs └── BatchPhotoGeoLib/ # 业务逻辑库 ├── Models/ │ ├── GridCell.cs # 网格单元模型(含分组编号、每行照片数、缩放系数、像素宽高、完整路径、EXIF 元数据) │ ├── ImageFileInfo.cs # 单张图片信息(像素 + EXIF 元数据) │ ├── ImageGroup.cs # 像素尺寸分组模型 │ ├── DjiXmpMetadata.cs # DJI XMP 元数据模型 │ ├── MxdSettings.cs # 按 MXD 保存的界面配置模型 │ ├── PhotoMatrixConfig.cs # 配置参数模型(含缩放系数) │ └── UnitPhotoEntry.cs # 单元选片条目与排布结果模型 ├── Services/ │ ├── MetadataReader.cs # 像素尺寸与 EXIF 读取、分组、单张读取 │ ├── MatrixCalculator.cs # 矩阵推算 + 坐标定位(含缩放与组间水平错开) │ ├── JgwGenerator.cs # 世界文件生成(jgw/pgw/tfw) │ ├── FishnetGenerator.cs # 渔网生成(含追加写入、Upsert 与旧版字段补建) │ ├── FishnetStateReader.cs # 已有渔网状态读取(分组/原点/已存在要素索引) │ ├── CellLayoutHelper.cs # 行列推进/缩放后尺寸匹配/单元构建共享逻辑 │ ├── SupplementService.cs # 批量导入·追加流水线(读状态 + 续排 + 完整路径去重;与单元选片共用) │ ├── SinglePhotoService.cs # 单张照片导入服务(归集 + Upsert + 地图联动) │ ├── BatchImportService.cs # 批量导入·新建流水线(批量导入 / 单元选片共用) │ ├── ImageGrouper.cs # 像素尺寸分组(两条入口共用) │ ├── UnitSelectionPicker.cs # 选片:只取主片(纯逻辑,可脱离 ArcObjects 验证) │ ├── UnitSelectionService.cs # 单元选片入图(读 xlsx → 选片 → 共用流水线) │ ├── PageSetupService.cs # 数据框位置/大小设置 │ └── BatchLoader.cs # 批量加载影像 ├── UI/ │ ├── BatchImportForm.cs # 批量导入窗体 (WinForms,新建 / 追加两种模式) │ ├── SinglePhotoControl.cs # 单张照片导入面板(UserControl,由停靠窗承载) │ ├── UnitSelectionForm.cs # 单元选片入图窗体 (WinForms) │ └── PageSetupForm.cs # 页面设置窗体 (WinForms) └── Helpers/ ├── ComHelper.cs # COM 释放 ├── ConfigValueHelper.cs # 配置数值恢复/范围收敛 ├── ConversionLogService.cs # 转化日志(转化前/后文件路径 CSV) ├── DjiXmpReader.cs # JPEG XMP 读取(DJI drone-dji 元数据) ├── FileScanner.cs # 递归文件枚举(跳过无权限目录) ├── LogHelper.cs # 日志(%APPDATA%\BatchPhotoGeo\Logs\) ├── MapLayerHelper.cs # 渔网图层添加/去重/刷新 ├── MxdConfigStore.cs # 按 MXD 读写配置(XML) ├── IMxApplicationHolder.cs # ArcMap 应用持有者(含当前 MXD 路径) ├── XlsxReader.cs # 极简 xlsx 读取器(OOXML,无第三方依赖) └── SpatialReferenceHelper.cs # 空间参考解析 ``` ## 版本历史 | 版本 | 日期 | 更新内容 | |------|------|---------| | **2.0.0** | **2026-11-04** | 整合 v1.6~v1.8 全部改动并发布正式版:按 MXD 记忆配置、转化日志、单张导入“单元名称 / 同步修改文件名称”、DJI XMP 全字段(渔网共 40 个字段)、**是否写入元数据**开关;修复 Shapefile 数值字段写空导致的 `字段不可为空` 错误 | | **1.8.0** | **2026-11-04** | 参考 DJI 工具箱工具1,新增 **DJI XMP 元数据**自动读取:JPG/JPEG 的绝对高程、相对航高、GPS 高程、云台偏航/俯仰/翻滚、飞行航向/俯仰/翻滚、GPS 状态、Version/ImageSource、标定焦距/焦距/光圈/曝光/ISO、拍摄点坐标写入渔网新增的 20 个字段;新增 **「是否写入元数据」** 勾选项(按 MXD 记忆),可整体关闭元数据入库;旧渔网追加时自动补建字段 | | **1.7.0** | **2026-11-04** | ① 单张照片导入:**「照片名称」改为「单元名称」**,并新增 **「同步修改文件名称」** 勾选项——勾选时按单元名称重命名归集照片,不勾选时保留源文件名、只更新渔网 UnitName;② MXD 配置同步记忆该勾选状态 | | **1.6.0** | **2026-10-29** | ① **按 MXD 记忆配置**:批量导入/单元选片/单张导入按 MXD 完整路径保存并恢复上次参数;② **转化日志**:记录配准文件生成与单张照片归集的“转化前文件路径 / 转化后文件路径”;③ 单张原地更新保留 UnitName / PhotoRole,避免覆盖单元归属;④ 批量导入·新建重跑时不再重复添加渔网图层 | | **1.5.0** | **2026-10-20** | 新增"单元选片入图"按钮:读取《dji_metadata_单元归属.xlsx》**只取「主副=主」的照片**,支持**两种模式**——新建渔网(复用 BatchImportService 流水线)/ 追加到已有渔网(复用 SupplementService 流水线),唯一差别是照片来源;渔网新增 UnitName / PhotoRole 两列;内置 xlsx 读取器(OOXML,不依赖 Excel);**原「批量照片入图」与「批量补充」合并为「批量导入」(新建渔网 / 追加已有渔网)** | | 1.4.0 | 2026-09-26 | ① 新增"单张照片入图":ArcMap 停靠式窗口(可停靠四边或浮动,跟随 ArcMap,按钮一键打开/收起),拖拽单张照片即显示缩略图与 EXIF,归集复制到照片集文件夹并在渔网中按 ImageName 原地更新或新增要素(目标文件已存在弹窗确认覆盖,新分组每行照片数兜底为 1),分组按**缩放后"宽×高"**匹配;② 原"补充照片"改名为"批量补充"并更换图标;渔网字段无变化 | | 1.3.1 | 2026-09-20 | 修复"页面设置":① 修正锚点换算(页面坐标系 Y 轴向上,原逻辑导致 Y 位置错位);② 宽高同步应用到页面大小(原仅设置数据框,页面仍保持 A4) | | 1.3.0 | 2026-09-20 | 读取 EXIF 元数据写入渔网:经度/纬度/拍摄时间/相机制造商/相机型号(仅作属性记录,不改变定位) | | 1.2.0 | 2026-09-20 | ① 组间错开由 Y 方向改为 X 方向水平错开;② 渔网新增 PerRow/Scale/PixWidth/PixHeight/FullPath 字段;③ 新增"补充照片"按钮:在已有渔网中续排新增照片并按完整路径去重 | | 1.1.0 | 2026-09-09 | ① 渔网新增"名称"(Name)字段;② 新增"缩放系数"参数,影像可按比例缩放投影;③ 世界文件后缀按图片格式匹配(jpg→jgw、png→pgw、tif→tfw);④ 按像素尺寸自动分组(v1.1 系列功能) | | 1.0.0 | 2026-08-28 | 首个发布版本:行列矩阵推算、.jgw 配准文件、渔网生成、批量加载、页面设置、在线帮助 | ## 开发编译 1. Visual Studio 打开 `BatchPhotoGeo.sln` 2. 确认 ArcGIS SDK 引用路径:`C:\Program Files (x86)\ArcGIS\DeveloperKit10.8\DotNet\`(程序集版本 10.8,`SpecificVersion=False`) 3. 编译(x86 平台),产物位于 `BatchPhotoGeo\bin\x86\Debug\BatchPhotoGeo.esriAddIn` > 迁移到其他 ArcGIS Desktop 版本时,需将引用指向对应 DeveloperKit 的 DLL 重新编译,并在目标版本上实测。**当前版本仅在 ArcMap 10.8.2 上验证过。** ## 注意事项 - **「批量导入·新建渔网」是覆盖式建库** —— 同一个文件夹(含子文件夹)重跑一次,已有成果会被按当前参数重排;要**追加**新照片,请切到「追加到已有渔网」 - **批量导入递归扫描子文件夹** —— 新建模式会清理所选文件夹及所有子文件夹内的旧世界文件;若父目录混放其他工程成果,请选择更精确的子目录 - **「批量导入·追加」按完整路径去重** —— 照片挪过位置(换盘符、改目录)会被当成新照片重新排入 - **「单张照片导入」遇到同名文件会弹窗确认覆盖** —— 拖入前先确认是不是同一张 - **DJI XMP 仅对 JPG/JPEG 读取** —— TIF/PNG 或普通手机照片仍写 EXIF,但高度/云台/飞行/GPS 状态字段为空 - **MXD 配置按完整路径归属** —— 配置文件在 `%APPDATA%\BatchPhotoGeo\MxdConfigs\`;MXD 改名/移动后会被视为新 MXD(原配置仍保留) - **转化日志按月留存** —— `%APPDATA%\BatchPhotoGeo\Logs\Conversion\conversion_yyyyMM.csv`,包含“转化前文件路径 / 转化后文件路径”,可用 Excel 直接打开 - 世界文件规范以像素中心定位,影像整体相对所在渔网格边界存在约 0.5 像元(缩放后地面单位)的系统性偏移,可忽略不计 - 无法读取像素尺寸的图片(损坏文件)将被跳过,执行结束后统一汇总提示,详见日志 - 若 ArcMap 工具栏按钮显示"缺失",请通过 Add-In 管理器卸载后重装,必要时重置 Normal.mxt 模板