diff --git a/TIASshot/Cameras/CameraBase.cs b/TIASshot/Cameras/CameraBase.cs
index d90bce6..1b1d3d2 100644
--- a/TIASshot/Cameras/CameraBase.cs
+++ b/TIASshot/Cameras/CameraBase.cs
@@ -141,7 +141,7 @@
var filename = Config.GetString("File/RgbImage");
filename = filename.Replace("{NO}", $"{idx + 1:0000}");
- Cv2.ImWrite(Path.Combine(_saveFolder, filename), img);
+ Cv2.ImWrite(IoUtil.CombineSaveFilePath(_saveFolder, filename), img);
foreach (var channel in _colorCorrector.Channels) {
// ConvertImage は src を in-place で CV_64FC3 に変換するため、
@@ -152,7 +152,7 @@
using (var converted = _colorCorrector.ConvertImage(imgClone, channel)) {
filename = GetFilenameWithChannel("File/SrgbImage", channel);
filename = filename.Replace("{NO}", $"{idx + 1:0000}");
- Cv2.ImWrite(Path.Combine(_saveFolder, filename), converted);
+ Cv2.ImWrite(IoUtil.CombineSaveFilePath(_saveFolder, filename), converted);
}
}
}
@@ -223,7 +223,7 @@
PreviewProfiler.MarkEvent("SHOT_START");
#endif
var filename = Config.GetString("File/Info");
- using (var csv = new StreamWriter(Path.Combine(_saveFolder, filename))) {
+ using (var csv = new StreamWriter(IoUtil.CombineSaveFilePath(_saveFolder, filename))) {
WriteInfo(csv);
csv.WriteLine("Shot,Time(ms)");
@@ -288,8 +288,8 @@
// データ保存
SetSaveFolder("校正");
SetInfo("校正データ", _saveFolder);
- Cv2.ImWrite(Path.Combine(_saveFolder, Config.GetString("File/TccImage")), img);
- Cv2.ImWrite(Path.Combine(_saveFolder, Config.GetString("File/TccRoisImage")), imgRois);
+ Cv2.ImWrite(IoUtil.CombineSaveFilePath(_saveFolder, Config.GetString("File/TccImage")), img);
+ Cv2.ImWrite(IoUtil.CombineSaveFilePath(_saveFolder, Config.GetString("File/TccRoisImage")), imgRois);
// 変換行列の計算・保存は ColorCorrector に委譲する(tccRgb の所有権は渡さない)
_colorCorrector.CalcTcc(tccRgb, _saveFolder, IoUtil.SaveMatToCsv);
diff --git a/TIASshot/ColorCorrection/ColorCorrector.cs b/TIASshot/ColorCorrection/ColorCorrector.cs
index eadebea..5ee6184 100644
--- a/TIASshot/ColorCorrection/ColorCorrector.cs
+++ b/TIASshot/ColorCorrection/ColorCorrector.cs
@@ -89,7 +89,7 @@
/// Mat を CSV へ保存する処理(呼び出し側が提供)
public void CalcTcc(Mat tccRgb, string saveFolder, Action saveMatToCsv) {
- saveMatToCsv(Path.Combine(saveFolder, Config.GetString("File/TccRgbValues")), tccRgb);
+ saveMatToCsv(IoUtil.CombineSaveFilePath(saveFolder, Config.GetString("File/TccRgbValues")), tccRgb);
// 再校正時,古い変換行列のネイティブ資源を解放してから作り直す(Mat リーク防止)
foreach (var mat in _convRGB2SRGB.Values) {
@@ -99,11 +99,11 @@
foreach (var channel in ChannelList) {
var convRGB2SRGB = CalcConvertMatrix(tccRgb, TCC_SRGB, channel);
- saveMatToCsv(Path.Combine(saveFolder, GetFilenameWithChannel("File/ConvRgb2Srgb", channel)), convRGB2SRGB);
+ saveMatToCsv(IoUtil.CombineSaveFilePath(saveFolder, GetFilenameWithChannel("File/ConvRgb2Srgb", channel)), convRGB2SRGB);
// 以降の中間 Mat は辞書に保持しないため,使用後に確実に解放する
using (var convRGB2XYZ = CalcConvertMatrix(tccRgb, TCC_XYZ, channel)) {
- saveMatToCsv(Path.Combine(saveFolder, GetFilenameWithChannel("File/ConvRgb2Xyz", channel)), convRGB2XYZ);
+ saveMatToCsv(IoUtil.CombineSaveFilePath(saveFolder, GetFilenameWithChannel("File/ConvRgb2Xyz", channel)), convRGB2XYZ);
if (channel == 17) {
using (var convOld = new Mat(convRGB2XYZ.Size(), MatType.CV_64FC1)) {
for (var row = 0; row < convRGB2XYZ.Rows; row++) {
@@ -112,16 +112,16 @@
convOld.At(row, col) = convRGB2XYZ.At(rowFrom, col);
}
}
- saveMatToCsv(Path.Combine(saveFolder, GetFilenameWithChannel("File/ConvRgb2XyzOld", channel)), convOld);
+ saveMatToCsv(IoUtil.CombineSaveFilePath(saveFolder, GetFilenameWithChannel("File/ConvRgb2XyzOld", channel)), convOld);
}
}
}
using (var tccSrgb = ConvertColor(tccRgb, convRGB2SRGB)) {
- saveMatToCsv(Path.Combine(saveFolder, GetFilenameWithChannel("File/TccSrgbValues", channel)), tccSrgb);
+ saveMatToCsv(IoUtil.CombineSaveFilePath(saveFolder, GetFilenameWithChannel("File/TccSrgbValues", channel)), tccSrgb);
using (var convSrgb2Xyz = CalcConvertMatrix(tccSrgb, TCC_XYZ, channel)) {
- saveMatToCsv(Path.Combine(saveFolder, GetFilenameWithChannel("File/ConvSrgb2Xyz", channel)), convSrgb2Xyz);
+ saveMatToCsv(IoUtil.CombineSaveFilePath(saveFolder, GetFilenameWithChannel("File/ConvSrgb2Xyz", channel)), convSrgb2Xyz);
}
// 変換精度検証
diff --git a/TIASshot/Utils/IoUtil.cs b/TIASshot/Utils/IoUtil.cs
index bf45a8b..925d032 100644
--- a/TIASshot/Utils/IoUtil.cs
+++ b/TIASshot/Utils/IoUtil.cs
@@ -99,12 +99,16 @@
///
/// 設定ファイル由来のファイル名を保存フォルダと結合し,保存先ファイルパスを返す.
+ /// ファイル名に含まれる不正なファイル名文字(パス区切り \ /・ドライブ区切り : 等)を
+ /// _ に置換してから結合するため,設定の破損・誤設定(絶対パス指定・..\ トラバーサル)でも
+ /// 保存先が保存フォルダの外へ出ない.同梱 config.xml の既存値では従来の
+ /// Path.Combine と完全に同一の結果を返す(挙動不変).
///
/// 保存フォルダのパス
/// 設定ファイル由来のファイル名({CN}/{NO} 置換後)
- /// 保存先ファイルパス
+ /// 保存先ファイルパス(必ず saveFolder 配下)
public static string CombineSaveFilePath(string saveFolder, string filename) {
- return Path.Combine(saveFolder, filename);
+ return Path.Combine(saveFolder, SanitizeFolderNameElement(filename));
}
///