修改接收服务多帧判断
continuous-integration/drone/push Build is passing Details

Test_HIR_Net8
hang 2026-01-05 09:12:24 +08:00
parent 78597d6866
commit 8ad11f018b
1 changed files with 201 additions and 189 deletions

View File

@ -1,34 +1,35 @@
using FellowOakDicom.Network;
using FellowOakDicom;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using IRaCIS.Core.SCP.Service;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Infra.EFCore;
using Medallion.Threading;
using IRaCIS.Core.Domain.Share;
using Serilog;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using Microsoft.Extensions.Options;
using System.Data;
using FellowOakDicom;
using FellowOakDicom.Imaging;
using SharpCompress.Common;
using SixLabors.ImageSharp.Formats.Jpeg;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention;
using Newtonsoft.Json;
using FellowOakDicom.Imaging.Codec;
using FellowOakDicom.IO.Buffer;
using System.Diagnostics.CodeAnalysis;
using FellowOakDicom.Network;
using FellowOakDicom.Network.Client;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention;
using IRaCIS.Core.SCP.Service;
using MassTransit.Futures.Contracts;
using Medallion.Threading;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Identity.Client;
using Newtonsoft.Json;
using Serilog;
using SharpCompress.Common;
using SixLabors.ImageSharp.Formats.Jpeg;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace IRaCIS.Core.SCP.Service
{
@ -472,209 +473,217 @@ namespace IRaCIS.Core.SCP.Service
ms.Position = 0;
var dicomFile = DicomFile.Open(ms);
var pixelData = DicomPixelData.Create(dicomFile.Dataset);
var numberOfFrames = dicomFile.Dataset.GetSingleValueOrDefault(DicomTag.NumberOfFrames, 1);
if (pixelData != null)
//多帧处理逻辑
if(numberOfFrames > 1)
{
try
//一定要有像素数据才处理
var pixelData = DicomPixelData.Create(dicomFile.Dataset);
if (pixelData != null)
{
var syntax = pixelData.Syntax;
// 每个 fragment 固定大小 (64KB 示例,可以自己调整)
int fragmentSize = 20 * 1024;
var numberOfFrames = dicomFile.Dataset.GetSingleValueOrDefault(DicomTag.NumberOfFrames, 1);
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)
try
{
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} 开始处理多帧instanceId:{instanceId}");
var syntax = pixelData.Syntax;
// 每个 fragment 固定大小 (64KB 示例,可以自己调整)
int fragmentSize = 20 * 1024;
var newFragments = new DicomOtherByteFragment(DicomTag.PixelData);
#region test
//var newDicomFile = dicomFile.Clone();
var frag = dicomFile.Dataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData);
//var newDataset = newDicomFile.Dataset;
int fragmentCount = frag?.Fragments?.Count() ?? 0;
//var dstPd = DicomPixelData.Create(newDataset, true);
var originOffsetTable = frag?.OffsetTable; //有可能没有表,需要自己重建
//for (int i = 0; i < pixelData.NumberOfFrames; i++)
//{
// var frame = pixelData.GetFrame(i);
var bot = new List<uint>();
// dstPd.AddFrame(frame);
uint botOffset = 0;
// var data = frame.Data;
// int offset = 0;
// while (offset < data.Length)
// {
// 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;
// }
//}
//var newOffsetTable = newDataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData).OffsetTable;
//newFragments.OffsetTable.AddRange(newOffsetTable.ToArray());
#endregion
#region test fo-dicom auto bot
//var newDicomFile = dicomFile.Clone();
//var newDataset = newDicomFile.Dataset;
//var dstPd = DicomPixelData.Create(newDataset, true);
//for (int i = 0; i < pixelData.NumberOfFrames; i++)
//{
// var frame = pixelData.GetFrame(i);
// dstPd.AddFrame(frame);
//}
//var newOffsetTable = newDataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData).OffsetTable;
//Console.WriteLine(newOffsetTable.ToJsonStr());
#endregion
#region 暂时废弃
for (int n = 0; n < pixelData.NumberOfFrames; n++)
//需要拆成固定片段的
if (syntax.IsEncapsulated && fragmentCount == pixelData.NumberOfFrames && numberOfFrames > 1)
{
var frameData = pixelData.GetFrame(n); // 获取完整一帧
var data = frameData.Data;
int offset = 0;
bot.Add(botOffset);
botOffset += (uint)data.Length;
while (offset < data.Length)
var newFragments = new DicomOtherByteFragment(DicomTag.PixelData);
#region test
//var newDicomFile = dicomFile.Clone();
//var newDataset = newDicomFile.Dataset;
//var dstPd = DicomPixelData.Create(newDataset, true);
//for (int i = 0; i < pixelData.NumberOfFrames; i++)
//{
// var frame = pixelData.GetFrame(i);
// dstPd.AddFrame(frame);
// var data = frame.Data;
// int offset = 0;
// while (offset < data.Length)
// {
// 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;
// }
//}
//var newOffsetTable = newDataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData).OffsetTable;
//newFragments.OffsetTable.AddRange(newOffsetTable.ToArray());
#endregion
#region test fo-dicom auto bot
//var newDicomFile = dicomFile.Clone();
//var newDataset = newDicomFile.Dataset;
//var dstPd = DicomPixelData.Create(newDataset, true);
//for (int i = 0; i < pixelData.NumberOfFrames; i++)
//{
// var frame = pixelData.GetFrame(i);
// dstPd.AddFrame(frame);
//}
//var newOffsetTable = newDataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData).OffsetTable;
//Console.WriteLine(newOffsetTable.ToJsonStr());
#endregion
#region 最终使用
for (int n = 0; n < pixelData.NumberOfFrames; n++)
{
botOffset += 8;
var frameData = pixelData.GetFrame(n); // 获取完整一帧
var data = frameData.Data;
int offset = 0;
bot.Add(botOffset);
botOffset += (uint)data.Length;
int size = Math.Min(fragmentSize, data.Length - offset);
var buffer = new byte[size];
Buffer.BlockCopy(data, offset, buffer, 0, size);
while (offset < data.Length)
{
botOffset += 8;
newFragments.Fragments.Add(new MemoryByteBuffer(buffer));
offset += size;
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());
//Console.WriteLine(bot.ToJsonStr());
}
#endregion
dicomFile.Dataset.AddOrUpdate(newFragments);
// 重新保存 dicom 到流
ms.SetLength(0);
dicomFile.Save(ms);
}
//传递过来的就是拆分的,但是是没有偏移表的,我需要自己创建偏移表,不然生成缩略图失败
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)
if (originOffsetTable.Count == pixelData.NumberOfFrames)
{
isDiffrentBefore = false;
// 累加这一帧所有 fragment 的大小
offset += (uint)frameFragments.Size;
continue;
newFragments.OffsetTable.AddRange(originOffsetTable.ToArray());
}
else
{
offset += (uint)frameFragments.Size;
isDiffrentBefore = true;
newFragments.OffsetTable.AddRange(bot.ToArray());
//Console.WriteLine(bot.ToJsonStr());
}
if (isDiffrentBefore)
#endregion
dicomFile.Dataset.AddOrUpdate(newFragments);
// 重新保存 dicom 到流
ms.SetLength(0);
dicomFile.Save(ms);
}
//传递过来的就是拆分的,但是是没有偏移表的,我需要自己创建偏移表,不然生成缩略图失败
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)
{
//每个Fragment 也占用字节
offset += 8 * count;
bot.Add(offset);
count = 0;
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());
// 重新保存 DICOM 到流
ms.SetLength(0);
dicomFile.Save(ms);
}
bot.RemoveAt(bot.Count - 1);
// 设置到新的 PixelData
frag.OffsetTable.AddRange(bot.ToArray());
// 重新保存 DICOM 到流
ms.SetLength(0);
dicomFile.Save(ms);
}
}
catch (Exception mutiEx)
{
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} 处理多帧失败,上传原始文件:{mutiEx.ToString()}");
catch (Exception mutiEx)
{
Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} 处理多帧失败,上传原始文件:{mutiEx.ToString()}");
}
}
}
@ -683,6 +692,9 @@ namespace IRaCIS.Core.SCP.Service
#endregion