Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running Details

Test_IRC_Net10
he 2026-04-16 11:03:50 +08:00
commit be5c25ba5f
2 changed files with 305 additions and 241 deletions

View File

@ -196,72 +196,60 @@ public static class DicomPixelMasker
{
if (input == null) throw new ArgumentNullException(nameof(input));
if (output == null) throw new ArgumentNullException(nameof(output));
var regionList = regions?.ToList() ?? throw new ArgumentNullException(nameof(regions));
if (regionList.Count == 0)
throw new ArgumentException("At least one mask region is required.", nameof(regions));
options ??= new DicomMaskOptions();
if (input.CanSeek)
input.Position = 0;
var originalFile = await DicomFile.OpenAsync(input, FileReadOption.ReadAll).ConfigureAwait(false);
var originalDataset = originalFile.Dataset;
ValidateDataset(originalDataset);
var originalTs = originalFile.FileMetaInfo.TransferSyntax;
// 先解压到工作格式
var workingFile = await EnsureUncompressedAsync(originalFile, cancellationToken).ConfigureAwait(false);
var workingDataset = workingFile.Dataset;
var originalPhotometric = originalDataset.GetSingleValueOrDefault(DicomTag.PhotometricInterpretation, string.Empty);
Console.WriteLine($"Original Photometric={originalPhotometric}, Original TS={originalTs.UID.UID}");
var rows = originalDataset.GetSingleValue<int>(DicomTag.Rows);
var cols = originalDataset.GetSingleValue<int>(DicomTag.Columns);
var bitsAllocated = originalDataset.GetSingleValue<int>(DicomTag.BitsAllocated);
var bitsStored = originalDataset.GetSingleValueOrDefault(DicomTag.BitsStored, bitsAllocated);
var samplesPerPixel = originalDataset.GetSingleValue<int>(DicomTag.SamplesPerPixel);
var pixelRepresentation = originalDataset.GetSingleValueOrDefault(DicomTag.PixelRepresentation, (ushort)0);
var planarConfiguration = originalDataset.GetSingleValueOrDefault(DicomTag.PlanarConfiguration, (ushort)0);
Console.WriteLine($"Rows={rows}, Cols={cols}, BitsAllocated={bitsAllocated}, BitsStored={bitsStored}, SamplesPerPixel={samplesPerPixel}, PixelRepresentation={pixelRepresentation}, PlanarConfiguration={planarConfiguration}");
var rows = workingDataset.GetSingleValue<int>(DicomTag.Rows);
var cols = workingDataset.GetSingleValue<int>(DicomTag.Columns);
var bitsAllocated = workingDataset.GetSingleValue<int>(DicomTag.BitsAllocated);
var bitsStored = workingDataset.GetSingleValueOrDefault(DicomTag.BitsStored, bitsAllocated);
var samplesPerPixel = workingDataset.GetSingleValue<int>(DicomTag.SamplesPerPixel);
var pixelRepresentation = workingDataset.GetSingleValueOrDefault(DicomTag.PixelRepresentation, (ushort)0);
var planarConfiguration = workingDataset.GetSingleValueOrDefault(DicomTag.PlanarConfiguration, (ushort)0);
var workingPhotometric = workingDataset.GetSingleValueOrDefault(DicomTag.PhotometricInterpretation, string.Empty);
var isSupport = IsSupportedPhotometric(originalPhotometric, samplesPerPixel);
Console.WriteLine($"Working Photometric={workingPhotometric}, Working TS={workingFile.FileMetaInfo.TransferSyntax.UID.UID}");
if (isSupport)
Console.WriteLine($"Working Rows={rows}, Cols={cols}, BitsAllocated={bitsAllocated}, BitsStored={bitsStored}, SamplesPerPixel={samplesPerPixel}, PixelRepresentation={pixelRepresentation}, PlanarConfiguration={planarConfiguration}, Photometric={workingPhotometric}, TransferSyntax={workingFile.FileMetaInfo.TransferSyntax.UID.UID}");
var isSupport = IsSupportedPhotometric(workingPhotometric, samplesPerPixel);
if (!isSupport)
{
// 1. 转为工作用的未压缩 DICOM
var workingFile = await EnsureUncompressedAsync(originalFile, cancellationToken).ConfigureAwait(false);
// 2. 修改像素
MaskPixelDataInPlace(workingFile.Dataset, regionList, options);
// 3. 保持原 PhotometricInterpretation
if (!string.IsNullOrWhiteSpace(originalPhotometric))
{
workingFile.Dataset.AddOrUpdate(DicomTag.PhotometricInterpretation, originalPhotometric);
}
// 4. 可选更新 BurnedInAnnotation
if (options.UpdateBurnedInAnnotationToNo)
{
workingFile.Dataset.AddOrUpdate(DicomTag.BurnedInAnnotation, "NO");
}
// 5. 编码回原始传输语法
var finalFile = await ReEncodeToOriginalTransferSyntaxAsync(
workingFile,
originalTs,
options.StrictKeepTransferSyntax,
cancellationToken).ConfigureAwait(false);
finalFile.FileMetaInfo.TransferSyntax = originalTs;
if (output.CanSeek)
output.SetLength(0);
await finalFile.SaveAsync(output).ConfigureAwait(false);
if (output.CanSeek)
output.Position = 0;
throw new NotSupportedException(
$"Unsupported PhotometricInterpretation after decode: {workingPhotometric}, SamplesPerPixel={samplesPerPixel}");
}
else
// 修改 working dataset 的像素
MaskPixelDataInPlace(workingDataset, regionList, options);
if (options.UpdateBurnedInAnnotationToNo)
{
workingDataset.AddOrUpdate(DicomTag.BurnedInAnnotation, "NO");
}
// 不要把 original photometric 强行写回
var finalFile = await ReEncodeToOriginalTransferSyntaxAsync(
workingFile,
originalTs,
options.StrictKeepTransferSyntax,
cancellationToken).ConfigureAwait(false);
finalFile.FileMetaInfo.TransferSyntax = originalTs;
if (output.CanSeek)
output.SetLength(0);
await finalFile.SaveAsync(output).ConfigureAwait(false);
if (output.CanSeek)
output.Position = 0;
}
@ -285,35 +273,21 @@ public static class DicomPixelMasker
{
if (samplesPerPixel == 1)
{
if (string.Equals(photometric, "MONOCHROME1", StringComparison.OrdinalIgnoreCase) ||
string.Equals(photometric, "MONOCHROME2", StringComparison.OrdinalIgnoreCase) ||
string.Equals(photometric, "PALETTE COLOR", StringComparison.OrdinalIgnoreCase))
{
return true;
}
return false;
return string.Equals(photometric, "MONOCHROME1", StringComparison.OrdinalIgnoreCase)
|| string.Equals(photometric, "MONOCHROME2", StringComparison.OrdinalIgnoreCase)
|| string.Equals(photometric, "PALETTE COLOR", StringComparison.OrdinalIgnoreCase);
}
if (samplesPerPixel == 3)
{
if (string.Equals(photometric, "RGB", StringComparison.OrdinalIgnoreCase) ||
string.Equals(photometric, "YBR_FULL", StringComparison.OrdinalIgnoreCase))
{
return true;
}
// 对 YBR_FULL_422 不建议直接按当前布局改
if (string.Equals(photometric, "YBR_FULL_422", StringComparison.OrdinalIgnoreCase) ||
string.Equals(photometric, "YBR_PARTIAL_422", StringComparison.OrdinalIgnoreCase) ||
string.Equals(photometric, "YBR_PARTIAL_420", StringComparison.OrdinalIgnoreCase))
{
throw new NotSupportedException(
$"PhotometricInterpretation={photometric} uses subsampling layout and is not safely supported by this pixel masking implementation.");
}
return false;
//throw new NotSupportedException($"Unsupported color PhotometricInterpretation: {photometric}");
return string.Equals(photometric, "RGB", StringComparison.OrdinalIgnoreCase)
|| string.Equals(photometric, "YBR_FULL", StringComparison.OrdinalIgnoreCase)
|| string.Equals(photometric, "YBR_FULL_422", StringComparison.OrdinalIgnoreCase)
|| string.Equals(photometric, "YBR_PARTIAL_422", StringComparison.OrdinalIgnoreCase)
|| string.Equals(photometric, "YBR_PARTIAL_420", StringComparison.OrdinalIgnoreCase);
}
return false;
//throw new NotSupportedException($"Unsupported SamplesPerPixel={samplesPerPixel}");
}
/// <summary>
@ -491,13 +465,13 @@ public static class DicomPixelMasker
if (bitsAllocated == 8)
{
byte maskIndex = (byte)ResolvePaletteColorMaskIndex(dataset, bitsStored, options);
ApplyMask_Grayscale8(frameData, rows, cols, regions, maskIndex);
ApplyMask_SingleSample8(frameData, rows, cols, regions, maskIndex);
return;
}
if (bitsAllocated == 16)
{
ushort maskIndex = ResolvePaletteColorMaskIndex(dataset, bitsStored, options);
ApplyMask_Grayscale16(frameData, rows, cols, regions, maskIndex);
ApplyMask_SingleSample16(frameData, rows, cols, regions, maskIndex);
return;
}
throw new NotSupportedException(
@ -508,7 +482,7 @@ public static class DicomPixelMasker
if (bitsAllocated == 8)
{
byte maskValue8 = ResolveGrayscaleMaskValue8(photometric, options);
ApplyMask_Grayscale8(frameData, rows, cols, regions, maskValue8);
ApplyMask_SingleSample8(frameData, rows, cols, regions, maskValue8);
return;
}
if (bitsAllocated == 16)
@ -518,7 +492,7 @@ public static class DicomPixelMasker
bitsStored,
pixelRepresentation,
options);
ApplyMask_Grayscale16(frameData, rows, cols, regions, maskValue16);
ApplyMask_SingleSample16(frameData, rows, cols, regions, maskValue16);
return;
}
throw new NotSupportedException(
@ -534,22 +508,268 @@ public static class DicomPixelMasker
throw new NotSupportedException(
$"Unsupported color image: SamplesPerPixel=3, BitsAllocated={bitsAllocated}, Photometric={photometric}");
}
if (planarConfiguration == 0)
int expectedFull = rows * cols * 3;
int expected422 = rows * cols * 2;
int chromaRows = (rows + 1) / 2;
int chromaCols = (cols + 1) / 2;
int expected420 = rows * cols + 2 * chromaRows * chromaCols;
// 根据 photometric 自动解析默认颜色
var colorMask = ResolveColorMaskValue(photometric, options);
// 1) 先处理能通过长度明确识别的 subsampled YBR
if (frameData.Length == expected422)
{
ApplyMask_Color8_Interleaved(frameData, rows, cols, regions, options.ColorMaskValue);
if (string.Equals(photometric, "YBR_FULL_422", StringComparison.OrdinalIgnoreCase))
{
ApplyMask_YbrFull422(frameData, rows, cols, regions);
return;
}
if (string.Equals(photometric, "YBR_PARTIAL_422", StringComparison.OrdinalIgnoreCase))
{
ApplyMask_YbrPartial422(frameData, rows, cols, regions);
return;
}
throw new NotSupportedException(
$"Frame length matches 4:2:2 layout, but Photometric={photometric} is not supported for 422 masking.");
}
if (frameData.Length == expected420)
{
if (string.Equals(photometric, "YBR_PARTIAL_420", StringComparison.OrdinalIgnoreCase))
{
ApplyMask_YbrPartial420(frameData, rows, cols, regions);
return;
}
throw new NotSupportedException(
$"Frame length matches 4:2:0 layout, but Photometric={photometric} is not supported for 420 masking.");
}
// 2) full-resolution 三通道数据,长度无法区分 planar / interleaved
// 必须依赖 PlanarConfiguration
if (frameData.Length == expectedFull)
{
if (planarConfiguration == 1)
{
ApplyMask_Color8_Planar(frameData, rows, cols, regions, colorMask);
return;
}
// 包括 planarConfiguration == 0 以及很多解码后默认输出
ApplyMask_Color8_Interleaved(frameData, rows, cols, regions, colorMask);
return;
}
// 3) 最后兜底:如果长度异常,尝试按 PlanarConfiguration 处理
if (planarConfiguration == 1)
{
ApplyMask_Color8_Planar(frameData, rows, cols, regions, options.ColorMaskValue);
ApplyMask_Color8_Planar(frameData, rows, cols, regions, colorMask);
return;
}
if (planarConfiguration == 0)
{
ApplyMask_Color8_Interleaved(frameData, rows, cols, regions, colorMask);
return;
}
throw new NotSupportedException(
$"Unsupported PlanarConfiguration={planarConfiguration}, Photometric={photometric}");
$"Unsupported color frame layout: SamplesPerPixel={samplesPerPixel}, BitsAllocated={bitsAllocated}, " +
$"Photometric={photometric}, PlanarConfiguration={planarConfiguration}, FrameLength={frameData.Length}");
}
throw new NotSupportedException(
$"Unsupported format: SamplesPerPixel={samplesPerPixel}, BitsAllocated={bitsAllocated}, Photometric={photometric}");
}
private static byte[] ResolveColorMaskValue(string photometric, DicomMaskOptions options)
{
if (options.ColorMaskValue != null && options.ColorMaskValue.Length >= 3)
return options.ColorMaskValue;
if (string.Equals(photometric, "YBR_FULL", StringComparison.OrdinalIgnoreCase) ||
string.Equals(photometric, "YBR_FULL_422", StringComparison.OrdinalIgnoreCase))
{
// 黑色 in YCbCr full range
return new byte[] { 0, 128, 128 };
}
if (string.Equals(photometric, "YBR_PARTIAL_422", StringComparison.OrdinalIgnoreCase) ||
string.Equals(photometric, "YBR_PARTIAL_420", StringComparison.OrdinalIgnoreCase))
{
// 黑色 in YCbCr video range
return new byte[] { 16, 128, 128 };
}
// RGB 默认黑
return new byte[] { 0, 0, 0 };
}
#region ybr 422...
private static void ApplyMask_YbrFull422(
byte[] frameData,
int rows,
int cols,
IReadOnlyList<MaskRegion> regions)
{
const byte maskY = 0;
const byte maskCb = 128;
const byte maskCr = 128;
int bytesPerRow = cols * 2; // 2 pixels -> 4 bytes
foreach (var region in regions)
{
var (left, top, right, bottom) = ClipRegion(region, cols, rows);
if (left >= right || top >= bottom)
continue;
int alignedLeft = left & ~1;
int alignedRight = (right + 1) & ~1;
if (alignedRight > cols) alignedRight = cols;
for (int y = top; y < bottom; y++)
{
int rowOffset = y * bytesPerRow;
for (int x = alignedLeft; x < alignedRight; x += 2)
{
int offset = rowOffset + (x / 2) * 4;
// Y0 Cb Y1 Cr
frameData[offset + 0] = maskY;
frameData[offset + 1] = maskCb;
frameData[offset + 2] = maskY;
frameData[offset + 3] = maskCr;
}
}
}
}
private static void ApplyMask_YbrPartial422(
byte[] frameData,
int rows,
int cols,
IReadOnlyList<MaskRegion> regions)
{
const byte maskY = 16;
const byte maskCb = 128;
const byte maskCr = 128;
int bytesPerRow = cols * 2; // 2 pixels -> 4 bytes
foreach (var region in regions)
{
var (left, top, right, bottom) = ClipRegion(region, cols, rows);
if (left >= right || top >= bottom)
continue;
int alignedLeft = left & ~1;
int alignedRight = (right + 1) & ~1;
if (alignedRight > cols) alignedRight = cols;
for (int y = top; y < bottom; y++)
{
int rowOffset = y * bytesPerRow;
for (int x = alignedLeft; x < alignedRight; x += 2)
{
int offset = rowOffset + (x / 2) * 4;
// Y0 Cb Y1 Cr
frameData[offset + 0] = maskY;
frameData[offset + 1] = maskCb;
frameData[offset + 2] = maskY;
frameData[offset + 3] = maskCr;
}
}
}
}
private static void ApplyMask_YbrPartial420(
byte[] frameData,
int rows,
int cols,
IReadOnlyList<MaskRegion> regions)
{
const byte maskY = 16;
const byte maskCb = 128;
const byte maskCr = 128;
int yPlaneSize = rows * cols;
int chromaRows = (rows + 1) / 2;
int chromaCols = (cols + 1) / 2;
int chromaPlaneSize = chromaRows * chromaCols;
int cbBase = yPlaneSize;
int crBase = yPlaneSize + chromaPlaneSize;
foreach (var region in regions)
{
var (left, top, right, bottom) = ClipRegion(region, cols, rows);
if (left >= right || top >= bottom)
continue;
int alignedLeft = left & ~1;
int alignedTop = top & ~1;
int alignedRight = (right + 1) & ~1;
int alignedBottom = (bottom + 1) & ~1;
if (alignedRight > cols) alignedRight = cols;
if (alignedBottom > rows) alignedBottom = rows;
// Y plane
for (int y = top; y < bottom; y++)
{
int rowOffset = y * cols;
for (int x = left; x < right; x++)
{
frameData[rowOffset + x] = maskY;
}
}
// Cb / Cr plane, one chroma sample for each 2x2 block
for (int y = alignedTop; y < alignedBottom; y += 2)
{
int chromaY = y / 2;
for (int x = alignedLeft; x < alignedRight; x += 2)
{
int chromaX = x / 2;
int chromaIndex = chromaY * chromaCols + chromaX;
frameData[cbBase + chromaIndex] = maskCb;
frameData[crBase + chromaIndex] = maskCr;
}
}
}
}
private static bool TryApplyMaskForSubsampledYbr(
byte[] frameData,
int rows,
int cols,
string photometric,
IReadOnlyList<MaskRegion> regions)
{
if (string.IsNullOrWhiteSpace(photometric))
return false;
if (string.Equals(photometric, "YBR_FULL_422", StringComparison.OrdinalIgnoreCase))
{
ApplyMask_YbrFull422(frameData, rows, cols, regions);
return true;
}
if (string.Equals(photometric, "YBR_PARTIAL_422", StringComparison.OrdinalIgnoreCase))
{
ApplyMask_YbrPartial422(frameData, rows, cols, regions);
return true;
}
if (string.Equals(photometric, "YBR_PARTIAL_420", StringComparison.OrdinalIgnoreCase))
{
ApplyMask_YbrPartial420(frameData, rows, cols, regions);
return true;
}
return false;
}
#endregion
private static ushort ResolvePaletteColorMaskIndex(
DicomDataset dataset,
int bitsStored,
@ -664,162 +884,6 @@ public static class DicomPixelMasker
#region 尾彩
//private static ushort ResolvePaletteColorMaskIndex16(
//DicomDataset dataset,
//int bitsStored,
//DicomMaskOptions options)
//{
// int maxValue = bitsStored >= 16 ? 65535 : (1 << bitsStored) - 1;
// if (options.PaletteColorMaskIndex.HasValue)
// {
// int v = options.PaletteColorMaskIndex.Value;
// if (v < 0 || v > maxValue)
// {
// throw new ArgumentOutOfRangeException(
// nameof(options.PaletteColorMaskIndex),
// $"PaletteColorMaskIndex must be in range [0, {maxValue}] for BitsStored={bitsStored}");
// }
// return (ushort)v;
// }
// int autoIndex = FindDarkestPaletteIndex(dataset, maxValue);
// return (ushort)autoIndex;
//}
//private static int FindDarkestPaletteIndex(DicomDataset dataset, int maxPixelValue)
//{
// var redDesc = GetPaletteDescriptor(dataset, DicomTag.RedPaletteColorLookupTableDescriptor);
// var greenDesc = GetPaletteDescriptor(dataset, DicomTag.GreenPaletteColorLookupTableDescriptor);
// var blueDesc = GetPaletteDescriptor(dataset, DicomTag.BluePaletteColorLookupTableDescriptor);
// if (redDesc.EntryCount != greenDesc.EntryCount || redDesc.EntryCount != blueDesc.EntryCount ||
// redDesc.FirstMappedValue != greenDesc.FirstMappedValue || redDesc.FirstMappedValue != blueDesc.FirstMappedValue ||
// redDesc.BitsPerEntry != greenDesc.BitsPerEntry || redDesc.BitsPerEntry != blueDesc.BitsPerEntry)
// {
// throw new NotSupportedException("RGB palette LUT descriptors are inconsistent.");
// }
// ushort[] red = GetPaletteLutDataAsUShortArray(dataset, DicomTag.RedPaletteColorLookupTableData, redDesc);
// ushort[] green = GetPaletteLutDataAsUShortArray(dataset, DicomTag.GreenPaletteColorLookupTableData, greenDesc);
// ushort[] blue = GetPaletteLutDataAsUShortArray(dataset, DicomTag.BluePaletteColorLookupTableData, blueDesc);
// if (red.Length != redDesc.EntryCount || green.Length != greenDesc.EntryCount || blue.Length != blueDesc.EntryCount)
// {
// throw new NotSupportedException("Palette LUT data length does not match LUT descriptor.");
// }
// long bestScore = long.MaxValue;
// int bestLutIndex = 0;
// for (int i = 0; i < redDesc.EntryCount; i++)
// {
// long score = (long)red[i] + green[i] + blue[i];
// if (score < bestScore)
// {
// bestScore = score;
// bestLutIndex = i;
// }
// }
// int pixelValue = redDesc.FirstMappedValue + bestLutIndex;
// if (pixelValue < 0)
// pixelValue = 0;
// if (pixelValue > maxPixelValue)
// pixelValue = maxPixelValue;
// return pixelValue;
//}
//private static ushort[] GetPaletteLutDataAsUShortArray(
//DicomDataset dataset,
//DicomTag dataTag,
//PaletteLutDescriptor descriptor)
//{
// if (!dataset.TryGetSingleValue<byte[]>(dataTag, out var rawBytes) || rawBytes == null || rawBytes.Length == 0)
// {
// throw new NotSupportedException($"Missing palette LUT data: {dataTag}");
// }
// int entryCount = descriptor.EntryCount;
// int bitsPerEntry = descriptor.BitsPerEntry;
// if (bitsPerEntry <= 8)
// {
// if (rawBytes.Length < entryCount)
// {
// throw new NotSupportedException(
// $"Palette LUT data too short for {dataTag}. Expected at least {entryCount} bytes, actual {rawBytes.Length}.");
// }
// var result = new ushort[entryCount];
// for (int i = 0; i < entryCount; i++)
// {
// result[i] = rawBytes[i];
// }
// return result;
// }
// if (bitsPerEntry <= 16)
// {
// int requiredBytes = entryCount * 2;
// if (rawBytes.Length < requiredBytes)
// {
// throw new NotSupportedException(
// $"Palette LUT data too short for {dataTag}. Expected at least {requiredBytes} bytes, actual {rawBytes.Length}.");
// }
// var result = new ushort[entryCount];
// for (int i = 0; i < entryCount; i++)
// {
// int byteIndex = i * 2;
// result[i] = (ushort)(rawBytes[byteIndex] | (rawBytes[byteIndex + 1] << 8));
// }
// return result;
// }
// throw new NotSupportedException(
// $"Unsupported palette LUT bits per entry {bitsPerEntry} for {dataTag}.");
//}
//private readonly struct PaletteLutDescriptor
//{
// public int EntryCount { get; }
// public int FirstMappedValue { get; }
// public int BitsPerEntry { get; }
// public PaletteLutDescriptor(int entryCount, int firstMappedValue, int bitsPerEntry)
// {
// EntryCount = entryCount;
// FirstMappedValue = firstMappedValue;
// BitsPerEntry = bitsPerEntry;
// }
//}
//private static PaletteLutDescriptor GetPaletteDescriptor(DicomDataset dataset, DicomTag tag)
//{
// var values = dataset.GetValues<ushort>(tag);
// if (values == null || values.Length < 3)
// throw new NotSupportedException($"Missing or invalid palette LUT descriptor: {tag}");
// int entryCount = values[0] == 0 ? 65536 : values[0];
// // 第二个值在 DICOM 标准中是 signed short
// int firstMappedValue = (short)values[1];
// int bitsPerEntry = values[2];
// if (bitsPerEntry <= 0)
// throw new NotSupportedException($"Invalid palette LUT descriptor bits per entry: {bitsPerEntry}");
// return new PaletteLutDescriptor(entryCount, firstMappedValue, bitsPerEntry);
//}
#endregion
private static byte ResolveGrayscaleMaskValue8(string photometric, DicomMaskOptions options)
{
if (!options.AutoSelectGrayscaleMaskValue)
@ -864,7 +928,7 @@ public static class DicomPixelMasker
return unchecked((ushort)selected);
}
}
private static void ApplyMask_Grayscale8(
private static void ApplyMask_SingleSample8(
byte[] data,
int rows,
int cols,
@ -885,7 +949,7 @@ public static class DicomPixelMasker
}
}
}
private static void ApplyMask_Grayscale16(
private static void ApplyMask_SingleSample16(
byte[] data,
int rows,
int cols,

View File

@ -17242,17 +17242,17 @@
</member>
<member name="F:IRaCIS.Core.Application.ViewModel.AccessToDialogueEnum.Question">
<summary>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
质疑
</summary>
</member>
<member name="F:IRaCIS.Core.Application.ViewModel.AccessToDialogueEnum.Consistency">
<summary>
һ<EFBFBD><EFBFBD><EFBFBD>Ժ˲<EFBFBD>
一致性核查
</summary>
</member>
<member name="T:IRaCIS.Core.Application.ViewModel.CopyFrontAuditConfigItemDto">
<summary>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
复制
</summary>
</member>
<member name="T:IRaCIS.Core.Application.ViewModel.SystemNoticeView">