diff --git a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs index b4602194d..7ae40979d 100644 --- a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs +++ b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs @@ -864,7 +864,7 @@ namespace IRaCIS.Core.API.Controllers if (!System.IO.File.Exists(storePreviewPath)) { - ImageResizeHelper.ResizeSave(_fileStorePath, storePreviewPath); + ImageHelper.ResizeSave(_fileStorePath, storePreviewPath); } return new FileContentResult(await System.IO.File.ReadAllBytesAsync(storePreviewPath), "image/jpeg"); diff --git a/IRaCIS.Core.Application/Helper/FileStoreHelper.cs b/IRaCIS.Core.Application/Helper/FileStoreHelper.cs index 20633655a..95b145d77 100644 --- a/IRaCIS.Core.Application/Helper/FileStoreHelper.cs +++ b/IRaCIS.Core.Application/Helper/FileStoreHelper.cs @@ -271,6 +271,27 @@ public static class FileStoreHelper } + public static string GetSubjectVisitDicomFolderPhysicalPath(IWebHostEnvironment _hostEnvironment,Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId) + { + var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); + + return Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteId.ToString(), subjectId.ToString(), subjectVisitId.ToString(), StaticData.Folder.DicomFolder); + } + + public static string GetDicomInstanceFilePath(IWebHostEnvironment _hostEnvironment, Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId, Guid studyId, Guid instanceId) + { + var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); + + //加入访视层级 和Data + var path = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), + siteId.ToString(), subjectId.ToString(), subjectVisitId.ToString(), StaticData.Folder.DicomFolder, studyId.ToString()); + + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + } + return Path.Combine(path, instanceId.ToString() + ".dcm"); + } // 获取医生通用文件存放路径 diff --git a/IRaCIS.Core.Application/Helper/ImageHelper.cs b/IRaCIS.Core.Application/Helper/ImageHelper.cs new file mode 100644 index 000000000..59a3d6b98 --- /dev/null +++ b/IRaCIS.Core.Application/Helper/ImageHelper.cs @@ -0,0 +1,76 @@ + +using FellowOakDicom.Imaging; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Processing; +using System.Security.Cryptography; +using System.Text; + +namespace IRaCIS.Core.Application.Helper; + +public static class ImageHelper +{ + + // 采用ImageSharp组件 跨平台,不依赖windows 平台图像处理组件,这里大坑(net 6 下,之前由于Dicom处理最新组件 依赖了这个库的一个旧版本,导致缩略图bug,单独升级依赖组件才解决) + public static void ResizeSave(string filePath, string? fileStorePath) + { + + fileStorePath = fileStorePath ?? filePath + ".preview.jpeg"; + + using (var image = SixLabors.ImageSharp.Image.Load(filePath)) + { + + image.Mutate(x => x.Resize(500, 500)); + + image.Save(fileStorePath); + + } + } + + + + public static Stream RenderPreviewJpeg(string filePath) + { + string jpegPath = filePath + ".preview.jpg"; + + if (!File.Exists(jpegPath)) + { + using (Stream stream = new FileStream(jpegPath, FileMode.Create)) + { + DicomImage image = new DicomImage(filePath); + + var sharpimage = image.RenderImage().AsSharpImage(); + + sharpimage.Save(stream, new JpegEncoder()); + + } + } + + return new FileStream(jpegPath, FileMode.Open); + } + + public static void RemovePreviewJpeg(string filePath) + { + string jpegPath = filePath + ".preview.jpg"; + if (File.Exists(jpegPath)) File.Delete(jpegPath); + } + + +} + +static class IdentifierHelper +{ + private static MD5 md5 = MD5.Create(); + + private static object lockObj = new object(); + + public static Guid CreateGuid(params string[] parts) + { + lock (lockObj) + { + return new Guid(md5.ComputeHash(Encoding.UTF8.GetBytes(string.Concat(parts)))); + } + + } +} + diff --git a/IRaCIS.Core.Application/Helper/ImageResize.cs b/IRaCIS.Core.Application/Helper/ImageResize.cs deleted file mode 100644 index 147ff0bc5..000000000 --- a/IRaCIS.Core.Application/Helper/ImageResize.cs +++ /dev/null @@ -1,26 +0,0 @@ - -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Processing; - -namespace IRaCIS.Core.Application.Helper; - -public static class ImageResizeHelper -{ - - // 采用ImageSharp组件 跨平台,不依赖windows 平台图像处理组件,这里大坑(net 6 下,之前由于Dicom处理最新组件 依赖了这个库的一个旧版本,导致缩略图bug,单独升级依赖组件才解决) - public static void ResizeSave(string filePath, string? fileStorePath) - { - - fileStorePath = fileStorePath ?? filePath + ".preview.jpeg"; - - using (var image = SixLabors.ImageSharp.Image.Load(filePath)) - { - - image.Mutate(x => x.Resize(500, 500)); - - image.Save(fileStorePath); - - } - } -} - diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs index 02ff5f2e2..cc540f957 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs @@ -6,7 +6,8 @@ using IRaCIS.Core.Domain.Share; using Microsoft.Extensions.Hosting; using System.Text; using IRaCIS.Core.Application.Contracts; - +using IRaCIS.Core.Application.Helper; +using Microsoft.AspNetCore.Hosting; namespace IRaCIS.Core.Application.Services { @@ -19,19 +20,20 @@ namespace IRaCIS.Core.Application.Services private readonly IEasyCachingProvider _provider; private readonly DicomFileStoreHelper _dicomFileStoreHelper; + private readonly IWebHostEnvironment _hostEnvironment; private static object lockCodeGenerate = new object(); public DicomArchiveService(IRepository studyRepository, IRepository seriesRepository, IRepository instanceRepository, - IHostEnvironment hostEnvironment, + IWebHostEnvironment hostEnvironment, IRepository inspectionService, DicomFileStoreHelper dicomFileStoreHelper, IEasyCachingProvider provider) { _dicomFileStoreHelper = dicomFileStoreHelper; - + _hostEnvironment = hostEnvironment; _studyRepository = studyRepository; _seriesRepository = seriesRepository; @@ -144,7 +146,7 @@ namespace IRaCIS.Core.Application.Services - string filePath = _dicomFileStoreHelper.CreateInstanceFilePath(dicomStudy, dicomSeries.Id, dicomInstance.Id); + string filePath = FileStoreHelper.GetDicomInstanceFilePath(_hostEnvironment, dicomStudy.TrialId, dicomStudy.SiteId, dicomStudy.SubjectId, dicomStudy.SubjectVisitId, dicomStudy.Id, dicomInstance.Id); var samplesPerPixel = dataset.GetSingleValueOrDefault(DicomTag.SamplesPerPixel, string.Empty); var photometricInterpretation = dataset.GetSingleValueOrDefault(DicomTag.PhotometricInterpretation, string.Empty); diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/Helper/DicomRenderingHelper.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/Helper/DicomRenderingHelper.cs deleted file mode 100644 index 811a0fa34..000000000 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/Helper/DicomRenderingHelper.cs +++ /dev/null @@ -1,37 +0,0 @@ -using FellowOakDicom.Imaging; -using SixLabors.ImageSharp.Formats.Jpeg; - -namespace IRaCIS.Core.Application.Dicom -{ - public static class DicomRenderingHelper - { - public static Stream RenderPreviewJpeg(string filePath) - { - string jpegPath = filePath + ".preview.jpg"; - - if (!File.Exists(jpegPath)) - { - using (Stream stream = new FileStream(jpegPath, FileMode.Create)) - { - DicomImage image = new DicomImage(filePath); - //image.ShowOverlays = false; - //image.Scale = Math.Min(Math.Min(128.0 / image.Width, 128.0 / image.Height), 1.0); - //image.RenderImage().AsClonedBitmap().Save(stream, ImageFormat.Jpeg); - - var sharpimage = image.RenderImage().AsSharpImage(); - - sharpimage.Save(stream, new JpegEncoder()); - - } - } - - return new FileStream(jpegPath, FileMode.Open); - } - - public static void RemovePreviewJpeg(string filePath) - { - string jpegPath = filePath + ".preview.jpg"; - if (File.Exists(jpegPath)) File.Delete(jpegPath); - } - } -} diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/Helper/IdentifierHelper.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/Helper/IdentifierHelper.cs deleted file mode 100644 index a5c82f6dd..000000000 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/Helper/IdentifierHelper.cs +++ /dev/null @@ -1,24 +0,0 @@ - -using System.Security.Cryptography; -using System.Text; - -namespace IRaCIS.Core.Application.Services -{ - static class IdentifierHelper - { - //private static MD5 md5 = new MD5CryptoServiceProvider - // - private static MD5 md5 = MD5.Create(); - - private static object lockObj =new object(); - - public static Guid CreateGuid(params string[] parts) - { - lock (lockObj) - { - return new Guid(md5.ComputeHash(Encoding.UTF8.GetBytes(string.Concat(parts)))); - } - - } - } -} diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/InstanceService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/InstanceService.cs index 1cf95d62c..b2adf8ca5 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/InstanceService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/InstanceService.cs @@ -1,7 +1,7 @@ using Microsoft.AspNetCore.Mvc; -using IRaCIS.Core.Application.Dicom; using Microsoft.AspNetCore.Authorization; using IRaCIS.Core.Application.Contracts; +using IRaCIS.Core.Application.Helper; namespace IRaCIS.Core.Application.Services { @@ -58,11 +58,11 @@ namespace IRaCIS.Core.Application.Services DicomStudy dicomStudy = await _studyRepository.FirstOrDefaultAsync(s => s.Id == dicomInstance.StudyId).IfNullThrowException(); - path = _dicomFileStoreHelper.GetInstanceFilePath(dicomStudy, dicomInstance.SeriesId, dicomInstance.Id.ToString()); + path = FileStoreHelper.GetDicomInstanceFilePath(_hostEnvironment, dicomStudy.TrialId, dicomStudy.SiteId, dicomStudy.SubjectId, dicomStudy.SubjectVisitId, dicomStudy.Id, dicomInstance.Id); - using (var sw = DicomRenderingHelper.RenderPreviewJpeg(path)) + using (var sw = ImageHelper.RenderPreviewJpeg(path)) { var bytes = new byte[sw.Length]; sw.Read(bytes, 0, bytes.Length); @@ -81,12 +81,13 @@ namespace IRaCIS.Core.Application.Services DicomStudy dicomStudy = await _studyRepository.FirstOrDefaultAsync(s => s.Id == dicomInstance.StudyId).IfNullThrowException(); - if (dicomInstance.Anonymize) //被匿名化 - { - filePath = _dicomFileStoreHelper.GetInstanceFilePath(dicomStudy, dicomInstance.SeriesId, dicomInstance.Id + ".Anonymize"); - } + //if (dicomInstance.Anonymize) //被匿名化 + //{ + // filePath = _dicomFileStoreHelper.GetInstanceFilePath(dicomStudy, dicomInstance.SeriesId, dicomInstance.Id + ".Anonymize"); + //} - else filePath = _dicomFileStoreHelper.GetInstanceFilePath(dicomStudy, dicomInstance.SeriesId, dicomInstance.Id.ToString()); + //else + filePath = FileStoreHelper.GetDicomInstanceFilePath(_hostEnvironment, dicomStudy.TrialId, dicomStudy.SiteId, dicomStudy.SubjectId, dicomStudy.SubjectVisitId, dicomStudy.Id, dicomInstance.Id); diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/SeriesService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/SeriesService.cs index 7235b7c26..efcc8f900 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/SeriesService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/SeriesService.cs @@ -1,8 +1,8 @@ using IRaCIS.Core.Application.Contracts.Dicom.DTO; using Microsoft.AspNetCore.Mvc; -using IRaCIS.Core.Application.Dicom; using Microsoft.AspNetCore.Authorization; +using IRaCIS.Core.Application.Helper; namespace IRaCIS.Core.Application.Services { @@ -99,9 +99,9 @@ namespace IRaCIS.Core.Application.Services DicomStudy dicomStudy = await _studyRepository.FirstOrDefaultAsync(s => s.Id == dicomInstance.StudyId).IfNullThrowException(); - path = _dicomFileStoreHelper.GetInstanceFilePath(dicomStudy, dicomInstance.SeriesId, dicomInstance.Id.ToString()); + path = FileStoreHelper.GetDicomInstanceFilePath(_hostEnvironment, dicomStudy.TrialId, dicomStudy.SiteId, dicomStudy.SubjectId, dicomStudy.SubjectVisitId, dicomStudy.Id, dicomInstance.Id); - using (var sw = DicomRenderingHelper.RenderPreviewJpeg(path)) + using (var sw = ImageHelper.RenderPreviewJpeg(path)) { var bytes = new byte[sw.Length]; sw.Read(bytes, 0, bytes.Length); diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs index 8d11b8234..35662b042 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs @@ -1,11 +1,11 @@ using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Domain.Share; using Microsoft.AspNetCore.Mvc; -using IRaCIS.Core.Application.Dicom; using Microsoft.AspNetCore.Authorization; using IRaCIS.Core.Application.Services; using EasyCaching.Core; using System.Linq.Expressions; +using IRaCIS.Core.Application.Helper; namespace IRaCIS.Core.Application.Service.ImageAndDoc { @@ -324,11 +324,11 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc DicomStudy dicomStudy = await _repository.FirstOrDefaultAsync(s => s.Id == dicomInstance.StudyId); if (dicomStudy != null) { - path = _dicomFileStoreHelper.GetInstanceFilePath(dicomStudy, dicomInstance.SeriesId, dicomInstance.Id.ToString()); + path = FileStoreHelper.GetDicomInstanceFilePath(_hostEnvironment, dicomStudy.TrialId, dicomStudy.SiteId, dicomStudy.SubjectId, dicomStudy.SubjectVisitId, dicomStudy.Id, dicomInstance.Id); } } - using (var sw = DicomRenderingHelper.RenderPreviewJpeg(path)) + using (var sw = ImageHelper.RenderPreviewJpeg(path)) { var bytes = new byte[sw.Length]; sw.Read(bytes, 0, bytes.Length); diff --git a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs index 18645beef..63da2a948 100644 --- a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs +++ b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs @@ -13,6 +13,7 @@ using IRaCIS.Core.Application.Service.Inspection.DTO; using Nito.AsyncEx; using System.ComponentModel.DataAnnotations; using IRaCIS.Core.Application.Auth; +using IRaCIS.Core.Application.Helper; namespace IRaCIS.Core.Application.Image.QA { @@ -769,7 +770,9 @@ namespace IRaCIS.Core.Application.Image.QA instanceIdList.ForEach(t => { - var path = _dicomFileStoreHelper.GetInstanceFilePath(new DicomStudy() { Id = t.StudyId, SubjectId = t.SubjectId, TrialId = trialId, SiteId = t.SiteId, SubjectVisitId = subjectVisitId }, t.SeriesId, t.InstanceId.ToString()); + var dicomStudy = new DicomStudy() { Id = t.StudyId, SubjectId = t.SubjectId, TrialId = trialId, SiteId = t.SiteId, SubjectVisitId = subjectVisitId }; + var path = + FileStoreHelper.GetDicomInstanceFilePath(_hostEnvironment, dicomStudy.TrialId, dicomStudy.SiteId, dicomStudy.SubjectId, dicomStudy.SubjectVisitId, dicomStudy.Id, t.InstanceId); if (System.IO.File.Exists(path)) { @@ -1350,7 +1353,10 @@ namespace IRaCIS.Core.Application.Image.QA instanceIdList.ForEach(t => { - var path = _dicomFileStoreHelper.GetInstanceFilePath(new DicomStudy() { Id = t.StudyId, SubjectId = t.SubjectId, TrialId = trialId, SiteId = t.SiteId, SubjectVisitId = subjectVisitId }, t.SeriesId, t.InstanceId.ToString()); + var dicomStudy = new DicomStudy() { Id = t.StudyId, SubjectId = t.SubjectId, TrialId = trialId, SiteId = t.SiteId, SubjectVisitId = subjectVisitId }; + var path = + + FileStoreHelper.GetDicomInstanceFilePath(_hostEnvironment, dicomStudy.TrialId, dicomStudy.SiteId, dicomStudy.SubjectId, dicomStudy.SubjectVisitId, dicomStudy.Id, t.InstanceId); if (System.IO.File.Exists(path)) { @@ -1684,7 +1690,7 @@ namespace IRaCIS.Core.Application.Image.QA var targetPath = "/IMPORT-IMAGES/" + info.TrialCode + "_" + info.SubjectCode + "_" + info.VisitName; - var path = _dicomFileStoreHelper.GetSubjectVisitPath(info.TrialId, info.SiteId, info.SubjectId, info.SubjectVisitId); + var path = FileStoreHelper.GetSubjectVisitDicomFolderPhysicalPath(_hostEnvironment, info.TrialId, info.SiteId, info.SubjectId, info.SubjectVisitId); try {