自己做的一个用于生成DICOM文件的服务器

框架: .ner core web api  .net8.0

Program.cs代码如下

using Microsoft.AspNetCore.HttpsPolicy;
using System.Diagnostics;namespace PacsServer
{/* public class Program{public static void Main(string[] args){//配置服务var builder = WebApplication.CreateBuilder(args);// 添加控制器服务,允许控制器处理HTTP请求builder.Services.AddControllers();//创建服务器var app = builder.Build();// 设置自定义端口,默认为 5000var port = "5001";if (args.Length > 0){port = args[0]; // 从命令行参数中获取端口号}//监听端口app.Urls.Add($"http://localhost:{port}");app.MapControllers();//允许服务器app.Run();}}*/public class Program{public static void Main(string[] args){// 配置服务var builder = WebApplication.CreateBuilder(args);// 添加控制器服务,允许控制器处理 HTTP 请求builder.Services.AddControllers();//配置网页启动端/* builder.Services.AddEndpointsApiExplorer();builder.Services.AddSwaggerGen();*/// 创建服务器var app = builder.Build();// 设置自定义端口,默认为 5000,暂关闭/*var port = "45101";if (args.Length > 0){port = args[0]; // 从命令行参数中获取端口号}*/// 监听端口,部署iis上,暂关闭内部端口设置//app.Urls.Add($"http://localhost:{port}");//配置网页启动/* if (app.Environment.IsDevelopment()){ }app.UseSwagger();app.UseSwaggerUI();           app.UseHttpsRedirection();app.UseAuthorization();*/app.MapControllers();// 自动打开浏览器访问应用程序//var url = $"http://localhost:{port}/swagger/index.html";//var url = $"{Environment.GetEnvironmentVariable("ASPNETCORE_URLS")}/swagger/index.html";//OpenBrowser(url);// 允许服务器app.Run();}private static void OpenBrowser(string url){try{// 根据平台启动浏览器Process.Start(new ProcessStartInfo{FileName = url,UseShellExecute = true});}catch (Exception ex){Console.WriteLine($"无法启动浏览器: {ex.Message}");}}}}
Model.Patient的代码如下
 
using System;
using System.ComponentModel.DataAnnotations;
using System.Reflection;namespace PacsServer.Model
{public class Patient{public long CheckID { get; set; }public string PicturePath { get; set; }public string PatientName { get; set; }public int PatientAge { get; set; }public string PatientID { get; set; }public string CheckDate {  get; set; }public string DicomFilePath { get; set; }public bool AreRequiredPropertiesValid(){foreach (PropertyInfo prop in typeof(Patient).GetProperties()){if (prop.Name != nameof(PatientID) && prop.Name != nameof(DicomFilePath)){var value = prop.GetValue(this);if (value == null || (value is string strValue && string.IsNullOrWhiteSpace(strValue))){return false;}}}return true;}}
}
Func.DIcomFunc的代码如下
 
using FellowOakDicom;
using FellowOakDicom.Imaging;
using FellowOakDicom.IO.Buffer;
using FellowOakDicom.Network.Client;
using FellowOakDicom.Network;
using PacsServer.Controllers;
using PacsServer.Model;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using Xunit;
using Newtonsoft.Json;namespace PacsServer.Func
{public class DicomFunc{public DicomFunc(){        }public static void DicomCreat(Patient patientMsg){//判断数据是否存在异常if (!patientMsg.AreRequiredPropertiesValid()){return;}//检测图片格式是否正常string[] validExtensions = { ".jpg", ".jpeg", ".bmp", ".png", ".gif", ".tiff" };bool isTruePath = validExtensions.Any(ext => patientMsg.PicturePath.EndsWith(ext, StringComparison.OrdinalIgnoreCase));if (!isTruePath){return;}//日期格式纠正DateTime birthDate = DateTime.ParseExact(patientMsg.CheckDate, "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture).Date;patientMsg.CheckDate = birthDate.ToString("yyyyMMdd");//年龄纠正string patientAgeString = patientMsg.PatientAge.ToString("D3") + "Y";patientMsg.PatientID = patientMsg.PatientName + patientMsg.PatientAge;              //暂时定义为名字+年龄byte[] pixels;using (Bitmap bitmap = new Bitmap(patientMsg.PicturePath)){pixels = GetPixels(bitmap); // 读取像素数据// 在 using 语句块结束时,Bitmap 资源会被自动释放MemoryByteBuffer buffer = new MemoryByteBuffer(pixels);//设置数据集var dataset = new DicomDataset{{ DicomTag.SpecificCharacterSet,"GB18030" },{ DicomTag.PatientName, patientMsg.PatientName },{ DicomTag.PatientID, patientMsg.PatientID },{ DicomTag.PatientAge,  patientAgeString},{ DicomTag.StudyDate, patientMsg.CheckDate},{ DicomTag.SeriesDate,  patientMsg.CheckDate },{ DicomTag.PhotometricInterpretation, PhotometricInterpretation.Rgb.Value },{ DicomTag.Rows, (ushort)bitmap.Height },{ DicomTag.Columns, (ushort)bitmap.Width },{ DicomTag.BitsAllocated, (ushort)8 },{ DicomTag.BitsStored, (ushort)8 },{ DicomTag.HighBit, (ushort)7 },{ DicomTag.SamplesPerPixel, (ushort)3 },{ DicomTag.SOPClassUID, DicomUID.VideoEndoscopicImageStorage },    //内窥镜成像{ DicomTag.SOPInstanceUID, DicomUID.Generate() }};//同次检查判断PatientService _patientService = new PatientService();var uidClass = _patientService.GetOrCreateUIDs(patientMsg.CheckID);dataset.AddOrUpdate(DicomTag.StudyInstanceUID, uidClass.GetStudyInstanceUID());dataset.AddOrUpdate(DicomTag.SeriesInstanceUID, uidClass.GetSeriesInstanceUID());//设置像素数据DicomPixelData pixelData = DicomPixelData.Create(dataset, true);pixelData.BitsStored = 8;pixelData.SamplesPerPixel = 3;pixelData.HighBit = 7;pixelData.PixelRepresentation = PixelRepresentation.Unsigned;pixelData.PlanarConfiguration = PlanarConfiguration.Interleaved;pixelData.AddFrame(buffer);DicomFile dicomFile = new DicomFile(dataset);int index = patientMsg.PicturePath.LastIndexOf('\\');string filePath = patientMsg.PicturePath.Substring(0, index) + "\\dcmfile";string imagePath = patientMsg.PicturePath.Substring(index + 1);imagePath = System.IO.Path.GetFileNameWithoutExtension(imagePath);if (!Directory.Exists(filePath)){Directory.CreateDirectory(filePath);}patientMsg.DicomFilePath = filePath + "\\" + imagePath + ".dcm";dicomFile.Save(patientMsg.DicomFilePath);Console.WriteLine("createSuccess");//能否ping通if (PacsConfigController.IsServerReachable){DicomUpdataAsync(patientMsg.DicomFilePath);Console.WriteLine("uploadSuccess");}else{Console.WriteLine("pacs服务器不可达!");}}}/// <summary>/// 上传dcm文件/// </summary>/// <param name="dicomFilePath"></param>/// <exception cref="InvalidOperationException"></exception>/// <exception cref="TimeoutException"></exception>private static async void DicomUpdataAsync(string dicomFilePath){var client = DicomClientFactory.Create(ServerConfig.ServerAddress, int.Parse(ServerConfig.Port), false, "Colposcope", ServerConfig.AET);client.ClientOptions.AssociationRequestTimeoutInMs = (int)TimeSpan.FromMinutes(5).TotalMilliseconds;DicomCStoreResponse response = null;DicomRequest.OnTimeoutEventArgs timeout = null;try{var request = new DicomCStoreRequest(dicomFilePath){OnResponseReceived = (req, res) => response = res,OnTimeout = (sender, args) => timeout = args};await client.AddRequestAsync(request);await client.SendAsync();// 验证响应if (response == null) { throw new InvalidOperationException("Response is null."); }if (response.Status != DicomStatus.Success) { throw new InvalidOperationException("Response status is not successful."); }if (timeout != null) { throw new TimeoutException("Operation timed out."); }}catch (Exception ex){throw;}}public async static Task<bool> DicomPing(ServerConfigDTO server){var client = DicomClientFactory.Create(server.ServerAddress, int.Parse(server.Port), false, "Colposcope", server.AET);client.ClientOptions.AssociationRequestTimeoutInMs = (int)TimeSpan.FromMinutes(5).TotalMilliseconds; // 设置关联请求超时时间DicomCEchoResponse response = null;DicomRequest.OnTimeoutEventArgs timeout = null;var request = new DicomCEchoRequest{OnResponseReceived = (req, res) => response = res, // 响应接收事件OnTimeout = (sender, args) => timeout = args // 超时事件};await client.AddRequestAsync(request); // 添加C-Echo请求try{await client.SendAsync(); // 发送请求// 验证响应if (response == null) { return false; }if (response.Status != DicomStatus.Success){ return false;}if (timeout != null){ return false;}return true;}catch (Exception ex){return false;}}public static byte[] GetPixels(Bitmap bitmap){byte[] bytes = new byte[bitmap.Width * bitmap.Height * 3];int width = bitmap.Width;int height = bitmap.Height;int i = 0;for (int y = 0; y < height; y++)    //上到下{for (int x = 0; x < width; x++) //左到右{var srcColor = bitmap.GetPixel(x, y);//bytes[i] = (byte)(srcColor.R * .299 + srcColor.G * .587 + srcColor.B * .114);    // 取消注释生成灰度图bytes[i] = srcColor.R;i++;bytes[i] = srcColor.G;i++;bytes[i] = srcColor.B;i++;}}return bytes;}       }public class UIDClass{public string StudyInstanceUID { get; private set; }public string SeriesInstanceUID { get; private set; }public UIDClass(string studyInstanceUID, string seriesInstanceUID){StudyInstanceUID = studyInstanceUID;SeriesInstanceUID = seriesInstanceUID;}public string GetStudyInstanceUID(){return StudyInstanceUID;}public string GetSeriesInstanceUID(){return SeriesInstanceUID;}}public class PatientService{private readonly string filePath;public PatientService(){filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Patient.json");}// 加载表中的数据public Dictionary<long, UIDClass> LoadPatients(){if (!File.Exists(filePath)){return new Dictionary<long, UIDClass>();}var json = File.ReadAllText(filePath);return JsonConvert.DeserializeObject<Dictionary<long, UIDClass>>(json);}// 保存数据到表public void SavePatients(Dictionary<long, UIDClass> patients){var json = JsonConvert.SerializeObject(patients, Formatting.Indented);File.WriteAllText(filePath, json);}// 获取或创建UIDClass对象public UIDClass GetOrCreateUIDs(long patientID){var patients = LoadPatients();if (!patients.TryGetValue(patientID, out var uidClass)){uidClass = new UIDClass(DicomUID.Generate().UID,DicomUID.Generate().UID);patients[patientID] = uidClass;SavePatients(patients);}return uidClass;}}
}
Controllers.DicomController的代码如下
 
using Microsoft.AspNetCore.Mvc;
using PacsServer.Func;
using PacsServer.Model;
namespace PacsServer.Controllers
{[Route("api/[controller]")][ApiController]public class DicomController : ControllerBase{[HttpPost("execute")]public IActionResult Execute([FromBody] Patient patientMsg){if (patientMsg == null || !ModelState.IsValid){foreach (var error in ModelState.Values.SelectMany(v => v.Errors)){Console.WriteLine(error.ErrorMessage);}return BadRequest(ModelState);}DicomFunc.DicomCreat(patientMsg);return Ok("Request processed successfully");}}
}
Controllers.PacsConfigController1的代码如下
using Microsoft.AspNetCore.Mvc;
using PacsServer.Func;namespace PacsServer.Controllers
{[Route("api/[controller]")][ApiController]public class PacsConfigController : ControllerBase{public static bool IsServerReachable { get; set; } = false; //pacs服务器是否可达[HttpPut("config")]public async Task<IActionResult> Config([FromBody] ServerConfigDTO serverConfig){if (!ModelState.IsValid){return BadRequest(ModelState);}//赋值逻辑ServerConfig.ServerAddress = serverConfig.ServerAddress;ServerConfig.Port = serverConfig.Port;ServerConfig.AET = serverConfig.AET;IsServerReachable = await DicomFunc.DicomPing(serverConfig);      //测试服务器能否ping通if (IsServerReachable){Console.WriteLine("pingSuccess");return Ok();}else{return StatusCode(StatusCodes.Status500InternalServerError, "Failed to ping DICOM server");}}}public  class  ServerConfig{public static string ServerAddress { get; set; }public static string Port { get; set; }public static string AET { get; set; }}public class ServerConfigDTO{public string ServerAddress { get; set; } = string.Empty;public string Port { get; set; } = string.Empty;public string AET { get; set; } = string.Empty;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/52334.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(第三十三天)

1. 设置主从从 mysql57 服务器 &#xff08; 1 &#xff09;配置主数据库 [rootmsater_5 ~] # systemctl stop filewalld [rootmsater_5 ~] # setenforce 0 [rootmsater_5 ~] # systemctl disable filewalld [rootmsater_5 ~] # ls anaconda-ks.cfg mysql-5.7.44-linux-g…

Python实现贪心算法

目录 贪心算法简介贪心算法的基本思想贪心算法的应用场景活动选择问题 Python实现活动选择问题代码解释活动选择问题的解贪心算法的正确性分析贪心算法的其他应用贪心算法的局限性贪心算法的优化与变种总结 贪心算法简介 贪心算法&#xff08;Greedy Algorithm&#xff09;是一…

【Unity】通用GM QA工具 运行时数值修改 命令行 测试工具

GM工具使用: GM工具通常用于游戏运行时修改数值(加钱/血量)、解锁关卡等&#xff0c;用于快速无死角测试游戏。一个通用型GM工具对于游戏项目是非常实用且必要的&#xff0c;但通用不能向易用妥协&#xff0c;纯命令行GM门槛太高&#xff0c;对QA不友好。 这类运行时命令行工具…

进程的创建、终止

目录 前言1. 进程创建2. 进程终止3. exit && _exit 的异同3.1 相同点3.2 不同点 前言 紧接着进程地址空间之后&#xff0c;我们这篇文章开始谈论进程控制相关的内容&#xff0c;其中包括进程是如何创建的&#xff0c;进程终止的几种情况&#xff0c;以及进程异常终止的…

数学建模学习(115):主成分分析(PCA)与Python实践

文章目录 一.主成分分析简介1.1 数学背景与维度诅咒1.2 PCA的定义与应用二.协方差矩阵——特征值和特征向量三.如何为数据集选择主成分数量四.特征提取方法五.LDA——与PCA的区别六.PCA的应用七.PCA在异常检测中的应用八.总结一.主成分分析简介 1.1 数学背景与维度诅咒 主成成…

TOP10漏洞原理

## 本人为学习网安不久的新人&#xff0c;记一次学习笔记&#xff0c;有缺陷或者表述不对的地方欢迎大家指出&#xff0c;感谢&#xff01; ## 1、sql注入&#xff1a;web应用程序对用户输入的数据没有进行过滤&#xff0c;或者过滤不严&#xff0c;就把sql语句拼接进数据库…

二叉树的统一迭代法

目录 一&#xff1a;中序遍历&#xff1a; 二&#xff1a;前序遍历&#xff1a; 三&#xff1a;后序遍历 记忆法&#xff1a;跟序列的遍历相反&#xff1a; 比如中序是中左右结点遍历输出的&#xff0c;那压入栈的顺序就是右左中 st.push(node); …

Mac电脑遇到DNS解析失败,ip可以访问,域名无法访问

当Mac电脑遇到DNS解析失败的问题时&#xff0c;可以尝试以下几个解决方法‌&#xff1a; 1.检查网络连接‌&#xff1a;确保Mac已连接到可用的网络&#xff0c;并且网络连接正常。可以尝试重新连接Wi-Fi或使用有线连接来排除网络问题。 2.清除DNS缓存‌&#xff1a;打开终端应…

docker容器基本命令、docker进入容器的指令、容器的备份、镜像底层原理、使用commit命令制造镜像、将镜像推送到阿里云镜像仓库与私服仓库

除了exit 还有 ctrlpq exit退出停止 ctrlpq 退出不停止 将本地镜像推到阿里云 登入阿里云 容器镜像服务 实力列表 镜像仓库 创建镜像仓库 安装里面步骤来 这里192.168.10.145这部分用自己ifconfig地址

【Android 远程数据库操作】

按正常情况下&#xff0c;前端不应该直接进行远程数据库操作&#xff0c;这不是一个明智的方式&#xff0c;应该是后端提供对应接口来处理&#xff0c;奈何公司各方面原因需要前端这样做。 对此&#xff0c;我对远程数据库操作做了总结&#xff0c;便于自己复盘&#xff0c;同…

python绘制爱心代码

效果展示 完整代码 Python中绘制爱心的代码可以通过多种方式实现&#xff0c;高级的爱心代码通常指的是使用较复杂的算法或者图形库来生成更加精致的爱心图形。下面是一个使用Python的Turtle模块来绘制爱心的示例代码&#xff1a; import turtledef draw_love():turtle.speed…

[Other]-安装ruby、ascli、ascp

最近新接到这样一个需求&#xff0c;将生物原始数据上传到某中心&#xff0c;其中用到ascp命令&#xff0c;阴差阳错的装了ruby、ascli&#xff0c;这里就都一并介绍下安装方式&#xff0c;由于服务器老旧默认安装时ruby2.0&#xff0c;又 升级到2.7等引发的一系列问题&#xf…

XSS-DOM

文章目录 源码SVG标签Dom-Clobbringtostring 源码 <script>const data decodeURIComponent(location.hash.substr(1));;const root document.createElement(div);root.innerHTML data;// 这里模拟了XSS过滤的过程&#xff0c;方法是移除所有属性&#xff0c;sanitize…

AI工具革新:国内外设计艺术的融合

在人工智能的浪潮中&#xff0c;全球的创新者和开发者们推出了一系列令人惊叹的工具&#xff0c;它们正以前所未有的速度改变着我们的工作、学习和生活方式。从图像生成到语言处理&#xff0c;从数据分析到自动化设计&#xff0c;AI 作图工具展示了其强大的能力&#xff0c;帮助…

【RH134知识点问答题】第11章 管理网络安全

目录 1. 防火墙在 Linux 系统安全中有哪些重要的作用&#xff1f; 2. 简单说明一下 firewalld。 3. 系统管理员可以通过哪三种方式与 firewalld 交互&#xff1f; 4. 使用什么命令可以获取当前端口标签分配概述&#xff1f; 5. 要允许 httpd 服务侦听端口 82/TCP&#xff0…

DRF——Filter条件搜索模块

文章目录 条件搜索自定义Filter第三方Filter内置Filter 条件搜索 如果某个API需要传递一些条件进行搜索&#xff0c;其实就在是URL后面通过GET传参即可&#xff0c;例如&#xff1a; /api/users?age19&category12在drf中也有相应组件可以支持条件搜索。 自定义Filter …

面试题详解

前言&#xff1a;这一期我们专门来巩固所学知识&#xff0c;同时见识一些面试题。对知识做出一个总结。 1 不创建临时变量交换两个整数 . 第一种方法 #include<stdio.h> int main() {int a 0;int b 0;scanf("%d %d", &a, &b);printf("交换前…

神经网络算法 - 一文搞懂BERT(基于Transformer的双向编码器)

本文将从BERT的本质、BERT的原理、BERT的应用三个方面&#xff0c;带您一文搞懂Bidirectional Encoder Representations from Transformers | BERT。 Google BERT BERT架构&#xff1a; 一种基于多层Transformer编码器的预训练语言模型&#xff0c;通过结合Tokenization、多种E…

Java基于数据库、乐观锁、悲观锁、Redis、Zookeeper分布式锁的简单案例实现(保姆级教程)

1. 分布式锁的定义 分布式锁是一种在分布式系统中用来协调多个进程或线程对共享资源进行访问的机制。它确保在分布式环境下&#xff0c;多个节点&#xff08;如不同的服务器或进程&#xff09;不会同时访问同一个共享资源&#xff0c;从而避免数据不一致、资源竞争等问题。 2…

等保测评服务的业务连续性规划:确保信息安全服务的韧性

在当前的数字化转型浪潮中&#xff0c;信息安全已成为企业运营的关键一环。等保测评服务作为信息安全合规的重要组成部分&#xff0c;其业务连续性规划对于保障服务的稳定性和客户信息资产的安全至关重要。本文将探讨等保测评服务的业务连续性规划策略&#xff0c;旨在构建一个…