多帧进行拆分上传

Uat_IRC_Net8
hang 2026-05-07 11:28:32 +08:00
parent c330fdc145
commit 32a06be96d
1 changed files with 172 additions and 39 deletions

View File

@ -17,6 +17,7 @@ using Microsoft.Extensions.Hosting;
using NetTopologySuite.Algorithm;
using SharpCompress.Common;
using SkiaSharp;
using System.Data;
using System.Drawing;
using ZiggyCreatures.Caching.Fusion;
@ -77,9 +78,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
}
private static async Task<bool> TryWriteMergedDicomAsync(
Func<Task<Stream>> sourceFactory,
Stream output)
private static async Task<bool> TryWriteMergedDicomAsync(Func<Task<Stream>> sourceFactory, Stream output)
{
try
{
@ -125,6 +124,166 @@ Stream output)
}
}
private static async Task<DicomFile> TryWriteSplitDicomAsync(Stream input)
{
var dicomFile = await DicomFile.OpenAsync(input);
var numberOfFrames = dicomFile.Dataset.GetSingleValueOrDefault(DicomTag.NumberOfFrames, 1);
//多帧处理逻辑
if (numberOfFrames > 1)
{
//一定要有像素数据才处理
var pixelData = DicomPixelData.Create(dicomFile.Dataset);
if (pixelData != null)
{
try
{
var syntax = pixelData.Syntax;
// 每个 fragment 固定大小 (64KB 示例,可以自己调整)
int fragmentSize = 20 * 1024;
var frag = dicomFile.Dataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData);
int fragmentCount = frag?.Fragments?.Count() ?? 0;
var originOffsetTable = frag?.OffsetTable; //有可能没有表,需要自己重建
var bot = new List<uint>();
uint botOffset = 0;
//需要拆成固定片段的
if (syntax.IsEncapsulated && fragmentCount == pixelData.NumberOfFrames && numberOfFrames > 1)
{
var newFragments = new DicomOtherByteFragment(DicomTag.PixelData);
#region 最终使用
for (int n = 0; n < pixelData.NumberOfFrames; n++)
{
var frameData = pixelData.GetFrame(n); // 获取完整一帧
var data = frameData.Data;
int offset = 0;
bot.Add(botOffset);
botOffset += (uint)data.Length;
while (offset < data.Length)
{
botOffset += 8;
int size = Math.Min(fragmentSize, data.Length - offset);
var buffer = new byte[size];
Buffer.BlockCopy(data, offset, buffer, 0, size);
newFragments.Fragments.Add(new MemoryByteBuffer(buffer));
offset += size;
}
}
//保留原始偏移表
if (originOffsetTable.Count == pixelData.NumberOfFrames)
{
newFragments.OffsetTable.AddRange(originOffsetTable.ToArray());
}
else
{
newFragments.OffsetTable.AddRange(bot.ToArray());
}
#endregion
dicomFile.Dataset.AddOrUpdate(newFragments);
}
//传递过来的就是拆分的,但是是没有偏移表的,我需要自己创建偏移表,不然生成缩略图失败
else if (syntax.IsEncapsulated && fragmentCount > pixelData.NumberOfFrames && originOffsetTable.Count == 0)
{
uint offset = 0;
bot.Add(offset);
var fistSize = frag.Fragments.FirstOrDefault()?.Size ?? 0;
//和上一个大小不一样
var isDiffrentBefore = false;
uint count = 0;
// 假设你知道每帧对应的 fragment 数量
foreach (var frameFragments in frag.Fragments)
{
count++;
if (frameFragments.Size == fistSize)
{
isDiffrentBefore = false;
// 累加这一帧所有 fragment 的大小
offset += (uint)frameFragments.Size;
continue;
}
else
{
offset += (uint)frameFragments.Size;
isDiffrentBefore = true;
}
if (isDiffrentBefore)
{
//每个Fragment 也占用字节
offset += 8 * count;
bot.Add(offset);
count = 0;
}
}
bot.RemoveAt(bot.Count - 1);
// 设置到新的 PixelData
frag.OffsetTable.AddRange(bot.ToArray());
}
}
catch (Exception ex)
{
// 只记录,不传播
Log.Logger.Warning($"拆分 failed: {ex.Message}");
}
}
}
return dicomFile;
}
/// <summary>
/// 标注遮盖影像 路径后面加了.MaskImage 就是遮盖的新路径
/// </summary>
@ -164,7 +323,7 @@ Stream output)
await using var inputStream = new MemoryStream();
if (item.IsEncapsulated /*&& item.NumberOfFrames > 1*/)
if (item.IsEncapsulated)
{
var ok = await TryWriteMergedDicomAsync(() => _oSSService.GetStreamFromOSSAsync(path), inputStream);
@ -175,42 +334,10 @@ Stream output)
}
//await using var ms = new MemoryStream();
//await inputStream.CopyToAsync(ms);
//ms.Position = 0;
#region 测试废弃
//var localPath = Path.Combine(FileStoreHelper.GetDonwnloadImageFolder(_hostEnvironment), Path.GetFileName(path));
//await _oSSService.DownLoadFromOSSAsync(path, localPath);
//await using var input = File.OpenRead(localPath);
//var outputPath = Path.Combine(FileStoreHelper.GetDonwnloadImageFolder(_hostEnvironment), "After", Path.GetFileName(path));
//var outputFolder = Path.GetDirectoryName(outputPath);
//if (!string.IsNullOrEmpty(outputFolder))
//{
// Directory.CreateDirectory(outputFolder);
//}
//await using var output = File.Create(outputPath);
//await DicomPixelMasker.MaskAsync(inputStream, outputinCommand.MaskRegionList);
#endregion
var outPutStream = await DicomPixelMasker.MaskAsync(inputStream, inCommand.MaskRegionList);
var needUploadDicomFile = await TryWriteSplitDicomAsync(outPutStream);
var prefix = path.Substring(1, path.LastIndexOf('/') - 1);
//每次都用一个新的名字
@ -234,7 +361,13 @@ Stream output)
maskFileName = $"{Path.GetFileName(path)}.MaskDicom_{batchId}";
}
await _oSSService.UploadToOSSAsync(outPutStream, prefix, maskFileName, false);
// 直接写入内存
await using var uploadStream = new MemoryStream();
await needUploadDicomFile.SaveAsync(uploadStream);
uploadStream.Position = 0;
await _oSSService.UploadToOSSAsync(uploadStream, prefix, maskFileName, false);
var newPath = $"/{prefix}/{maskFileName}";