From c9a8d7ad4c414461f5ba66b720d3fd30f52438ce Mon Sep 17 00:00:00 2001 From: hang <872297557@qq.com> Date: Wed, 15 Apr 2026 13:50:20 +0800 Subject: [PATCH] =?UTF-8?q?YBR=5FFULL=5F422=20=20=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Helper/OtherTool/DicomSortHelper.cs | 540 ++++++++++-------- .../IRaCIS.Core.Application.xml | 6 +- 2 files changed, 305 insertions(+), 241 deletions(-) diff --git a/IRaCIS.Core.Application/Helper/OtherTool/DicomSortHelper.cs b/IRaCIS.Core.Application/Helper/OtherTool/DicomSortHelper.cs index 9bb5e2816..4bd94512d 100644 --- a/IRaCIS.Core.Application/Helper/OtherTool/DicomSortHelper.cs +++ b/IRaCIS.Core.Application/Helper/OtherTool/DicomSortHelper.cs @@ -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(DicomTag.Rows); - var cols = originalDataset.GetSingleValue(DicomTag.Columns); - var bitsAllocated = originalDataset.GetSingleValue(DicomTag.BitsAllocated); - var bitsStored = originalDataset.GetSingleValueOrDefault(DicomTag.BitsStored, bitsAllocated); - var samplesPerPixel = originalDataset.GetSingleValue(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(DicomTag.Rows); + var cols = workingDataset.GetSingleValue(DicomTag.Columns); + var bitsAllocated = workingDataset.GetSingleValue(DicomTag.BitsAllocated); + var bitsStored = workingDataset.GetSingleValueOrDefault(DicomTag.BitsStored, bitsAllocated); + var samplesPerPixel = workingDataset.GetSingleValue(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}"); } /// @@ -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 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 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 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 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(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(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, diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index 924e53f17..145e5913c 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -17242,17 +17242,17 @@ - ���� + 质疑 - һ���Ժ˲� + 一致性核查 - ���� + 复制