Announcing dicom-server-rs v0.1.0: A High-Performance DICOM Store SCP in Rust We are excited to announce the initial release of dicom-server-rs, a lightweight, high-performance DICOM server (Store SCP) built entirely in Rust. In the world of medical imaging, reliability and speed are non-negotiable. By leveraging the Rust ecosystem, dicom-server-rs provides a modern alternative for receiving and managing DICOM files with a focus on safety and efficiency. 🚀 Key Features Native Rust Implementation: Built using the dicom-rs ecosystem for robust parsing and protocol handling. ...
How to Build Scalable Cloud DICOM-WEB Services | DICOM Cloud
How to Build Scalable Cloud DICOM-WEB Services Learn how to build distributed DICOM-WEB services using open-source projects. Overall Architecture Apache Kafka as message queue. RedPanda can be used as alternative during development. Apache Doris as data warehouse. Provides storage for DicomStateMeta, DicomImageMeta, and WadoAccessLog, offering query and statistical analysis. PostgreSQL as database. Provides data storage and indexing functions. Stores only patient, study, and series level metadata to fully leverage ACID properties of relational databases. Can be scaled later with Citus. Redis as cache. Provides data caching functionality. Nginx as reverse proxy server. Provides load balancing, static files, and TLS termination. Files received by the storage service are first stored locally, then sent to the message queue via Kafka. ...
How to Use Multi-Related Stream to Upload DICOM Files | Cloud DICOM-WEB Service
How to Use Multi-Related Stream to Upload DICOM Files Implementing Multi-File Upload with CURL Scripts or .NET Core Applications During STOW-RS development, to test RESTful API interfaces, we created a CURL script that uploads multiple DICOM files. It’s important to note that RESTful interfaces require uploads to be in multipart/related format with Content-Type: multipart/related;boundary=DICOM_BOUNDARY;type=application/dicom. CURL Script Implementation #!/bin/bash # Check parameters if [ $# -eq 0 ]; then echo "Usage: $0 <dicom_directory>" echo "Example: $0 ~/amprData" exit 1 fi DICOM_DIR="$1" # Check if directory exists if [ ! -d "$DICOM_DIR" ]; then echo "Error: Directory '$DICOM_DIR' does not exist" exit 1 fi BOUNDARY="DICOM_BOUNDARY" TEMP_FILE="multipart_request_largdata.tmp" # Check for DICOM files DICOM_FILES=($(find "$DICOM_DIR" -type f -name "*.dcm")) if [ ${#DICOM_FILES[@]} -eq 0 ]; then echo "Warning: No DICOM files found in '$DICOM_DIR'" exit 0 fi echo "Found ${#DICOM_FILES[@]} DICOM files" # 1. Initialize file (without JSON part) > "$TEMP_FILE" # 2. Loop through all DICOM files (first file doesn't need prefix separator) for i in "${!DICOM_FILES[@]}"; do dicom_file="${DICOM_FILES[$i]}" # Add prefix separator for all files except the first if [ $i -gt 0 ]; then printf -- "\r\n--%s\r\n" "$BOUNDARY" >> "$TEMP_FILE" else # First file needs starting separator printf -- "--%s\r\n" "$BOUNDARY" >> "$TEMP_FILE" fi printf -- "Content-Type: application/dicom\r\n\r\n" >> "$TEMP_FILE" # Append DICOM file content cat "$dicom_file" >> "$TEMP_FILE" echo "Added file: $(basename "$dicom_file")" done # 3. Write ending separator for request body printf -- "\r\n--%s--\r\n" "$BOUNDARY" >> "$TEMP_FILE" # 4. Calculate file size CONTENT_LENGTH=$(wc -c < "$TEMP_FILE" | tr -d ' ') echo "Total content length: $CONTENT_LENGTH bytes" # 5. Send request curl -X POST http://localhost:9000/stow-rs/v1/studies \ -H "Content-Type: multipart/related; boundary=$BOUNDARY; type=application/dicom" \ -H "Accept: application/json" \ -H "x-tenant: 1234567890" \ -H "Content-Length: $CONTENT_LENGTH" \ --data-binary @"$TEMP_FILE" # 6. Clean up temporary file rm "$TEMP_FILE" echo "Upload completed" .NET Core Implementation using System.Text; namespace MakeMultirelate { public class ConstructPostRequest : IDisposable { private const string Boundary = "DICOM_BOUNDARY"; private readonly HttpClient _httpClient = new(); public async Task SendDicomFilesAsync(List<string> dicomFilePaths, string url, string tenantId) { // Estimate memory stream size for performance optimization long estimatedSize = 0; foreach (var filePath in dicomFilePaths) { if (!File.Exists(filePath)) throw new FileNotFoundException($"DICOM file not found: {filePath}"); // Get file size and accumulate var fileInfo = new FileInfo(filePath); estimatedSize += fileInfo.Length; } // Add estimated size for boundaries and headers (approximately 200 bytes per file for separators and headers) estimatedSize += dicomFilePaths.Count * 200; // Add end boundary size estimatedSize += Boundary.Length + 10; // Create memory stream to build multipart content with estimated size initialization using var memoryStream = new MemoryStream((int)Math.Min(estimatedSize, int.MaxValue)); // Build multipart content foreach (var filePath in dicomFilePaths) { if (!File.Exists(filePath)) throw new FileNotFoundException($"DICOM file not found: {filePath}"); // Add separator and header var separator = Encoding.UTF8.GetBytes($"\r\n--{Boundary}\r\n"); var header = Encoding.UTF8.GetBytes("Content-Type: application/dicom\r\n\r\n"); if (memoryStream.Length == 0) { // First part doesn't need leading separator separator = Encoding.UTF8.GetBytes($"--{Boundary}\r\n"); } await memoryStream.WriteAsync(separator, 0, separator.Length); await memoryStream.WriteAsync(header, 0, header.Length); // Read and add DICOM file content var fileBytes = await File.ReadAllBytesAsync(filePath); await memoryStream.WriteAsync(fileBytes, 0, fileBytes.Length); } // Add ending separator var endBoundary = Encoding.UTF8.GetBytes($"\r\n--{Boundary}--\r\n"); await memoryStream.WriteAsync(endBoundary, 0, endBoundary.Length); // Prepare request content var content = new ByteArrayContent(memoryStream.ToArray()); content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("multipart/related"); content.Headers.ContentType.Parameters.Add( new System.Net.Http.Headers.NameValueHeaderValue("boundary", Boundary)); content.Headers.ContentType.Parameters.Add( new System.Net.Http.Headers.NameValueHeaderValue("type", "application/dicom")); // Set request headers _httpClient.DefaultRequestHeaders.Clear(); _httpClient.DefaultRequestHeaders.Add("Accept", "application/json"); _httpClient.DefaultRequestHeaders.Add("x-tenant", tenantId); // Send request var response = await _httpClient.PostAsync(url, content); // Process response var responseContent = await response.Content.ReadAsStringAsync(); Console.WriteLine($"Status Code: {response.StatusCode}"); Console.WriteLine($"Response: {responseContent}"); } // Overloaded function: Recursively find DICOM files based on directory public async Task SendDicomFilesAsync(string dicomDirectory, string url, string tenantId) { if (!Directory.Exists(dicomDirectory)) throw new DirectoryNotFoundException($"DICOM directory not found: {dicomDirectory}"); // Recursively find all files with .dcm extension var dicomFiles = Directory.GetFiles(dicomDirectory, "*.dcm", SearchOption.AllDirectories); // If no files found, throw exception if (dicomFiles.Length == 0) throw new FileNotFoundException($"No DICOM files found in directory: {dicomDirectory}"); // Call original method to send files await SendDicomFilesAsync(dicomFiles.ToList(), url, tenantId); } public void Dispose() { _httpClient.Dispose(); } } } Key Implementation Points Multipart/Related Format Content-Type must be multipart/related;boundary=DICOM_BOUNDARY;type=application/dicom Each DICOM file requires proper boundary delimiters First file needs a starting boundary, subsequent files need separator boundaries ...
6.1 WADO-Consumer Service Implementation: Building Scalable Cloud DICOM-WEB Services
WADO-Consumer Module Documentation Overview storage_consumer.rs is the core consumption module in the WADO system, responsible for consuming DICOM storage messages from the Kafka message queue, performing batch processing, persistent storage, and republishing to other topics. Main Functions Message Consumption and Processing Flow Subscribe to DicomStoreMeta messages from Kafka topics Batch collect messages and process according to time and quantity thresholds Classify processed messages into state metadata and image metadata Persist to databases Republish to corresponding Kafka topics Core Components start_process Function System entry point, responsible for initializing the entire consumption process: ...
5.1 WADO-StoreSCP Service Implementation: Building DICOM C-STORE Services with Rust
Overview WADO-StoreSCP is a DICOM Storage SCP (C-STORE) service implementation written in Rust that can receive DICOM files sent from other DICOM devices. This project is part of the DICOM-rs project. Feature Set Supports DICOM C-STORE protocol Provides both synchronous and asynchronous operation modes Supports multiple transfer syntaxes Automatically transcodes unsupported transfer syntaxes Saves received DICOM files to local storage Sends metadata information via Kafka Supports multi-tenant (hospital/institution) environments Includes certificate validation mechanisms System Architecture Core Components Main Program main.rs ...
dabase access and DICOM Object Metadata Extraction - Comprehensive Medical Imaging Data Processing
DICOM Object Metadata Extraction System The [dicom_object_meta.rs] module provides comprehensive extraction capabilities for DICOM medical imaging metadata, processing hundreds of standardized DICOM tags to create structured data representations. Metadata Categories Patient Information Extracts critical patient identifiers and demographics: Patient name, ID, and demographics Birth date and sex Medical record numbers Accession numbers Study Metadata Processes study-level information: Study instance UID and description Study date and time Referring physician information Study ID and accession numbers Series Information Handles series-specific data: ...
DICOM File Transfer and Conversion - Medical Imaging Format Transformation
title: “DICOM File Transfer and Conversion - Medical Imaging Format Transformation” description: “Learn how DICOM file transfer and conversion capabilities handle various medical imaging transfer syntaxes with GDCM integration for seamless format transformation.” keywords: [“DICOM conversion”, “medical imaging”, “file transfer”, “transfer syntax”, “GDCM integration”, “image processing”, “format transformation”] date: 2024-01-01T00:00:00+08:00 draft: false DICOM File Transfer and Conversion System The [change_file_transfer.rs] module provides comprehensive DICOM file transfer syntax conversion capabilities, enabling seamless format transformation for medical imaging systems using GDCM integration. ...
DICOM Server Common Library: Building Scalable Medical Imaging Systems with Rust
DICOM Server Common Library This is a common library for DICOM medical imaging systems that provides various core functionality modules for building scalable healthcare applications. Feature Modules DICOM-Cloud Part Two 4.1 Common Module Introduction DICOM-Cloud Part Two 4.2 Storage Configuration DICOM-Cloud Part Two 4.3 Database Factory DICOM-Cloud Part Two 4.4 Redis Integration DICOM-Cloud Part Two 4.5 Kafka Message Publishing DICOM-Cloud Part Two 4.6 Extract DICOM Information DICOM-Cloud Part Two 4.7 Security DICOM-Cloud Part Two 4.8 Write File To Storage Project Overview The library is designed to provide reusable components for DICOM servers, including configuration loading, database access, cache management, messaging, and other essential functions for healthcare applications. ...
DICOM Server Configuration Management: Flexible Multi-Environment Setup
DICOM Server Configuration Management System The server_config.rs module provides a robust configuration management system for DICOM servers, supporting complex multi-environment deployments with flexible configuration sources. Configuration Architecture Multi-Source Configuration Loading The system supports configuration loading from multiple sources: JSON configuration files (application.dev.json, application.test.json) Environment variables with prefix support Secure credential management Environment-Specific Settings Different environments (development, testing, production) can have distinct configurations while maintaining consistency through shared structures. Core Configuration Components Database Configuration Supports multiple database backends including MySQL, PostgreSQL, and Doris with secure password handling and connection string generation. ...
DICOM Storage Configuration and |Medical Imaging Storage Management - Efficient DICOM File Organization
Storage Configuration and Management System The storage_config.rs module provides intelligent storage management for medical imaging systems, optimizing file organization and path management for large-scale DICOM archives. Storage Architecture Hierarchical Directory Structure Implements a logical directory hierarchy based on medical imaging metadata: Tenant-based organization for multi-tenant deployments Date-based grouping for efficient retrieval UID-based separation for unique identification Path Management Generates consistent, predictable paths for all DICOM files and associated metadata. Key Features UID Hashing Uses SeaHash algorithm to create fixed-length hashed identifiers for secure, predictable path generation while maintaining patient privacy. ...