Skip to content

Commit 7ec6004

Browse files
Update PACS docs to include image compression/resizing (#65)
1 parent b7666f4 commit 7ec6004

1 file changed

Lines changed: 45 additions & 14 deletions

File tree

docs/pacs/README.md

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ DICOM PACS (Picture Archiving and Communication System) server for receiving and
55
## Overview
66

77
The PACS server is a lightweight, production-ready DICOM storage solution that:
8+
89
- Receives medical images via DICOM C-STORE protocol
910
- Stores the images using hash-based directory structure
1011
- Indexes metadata in SQLite database
@@ -15,25 +16,50 @@ The PACS server is a lightweight, production-ready DICOM storage solution that:
1516
### Components
1617

1718
```
18-
┌─────────────────────────────────────────────────────────────┐
19-
│ PACS Server (Port 4244) │
20-
├─────────────────────────────────────────────────────────────┤
21-
│ │
22-
│ ┌──────────────┐ ┌──────────────┐ ┌──────────┐ │
23-
│ │ C-STORE │─────▶│ Storage │─────▶│ SQLite │ │
24-
│ │ Handler │ │ Layer │ │ Database │ │
25-
│ └──────────────┘ └──────────────┘ └──────────┘ │
26-
│ │ │ │
27-
│ │ ▼ │
28-
│ │ ┌──────────────┐ │
29-
│ └─────────────▶│ Filesystem │ │
30-
│ └──────────────┘ │
31-
└─────────────────────────────────────────────────────────────┘
19+
┌─────────────────────────────────────────────────────────────────────┐
20+
│ PACS Server (Port 4244) │
21+
├─────────────────────────────────────────────────────────────────────┤
22+
│ │
23+
│ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐ │
24+
│ │ C-STORE │──▶│ Resize │──▶│ Compress │ │
25+
│ │ Handler │ │ (Lanczos) │ │ (JPEG 2000) │ │
26+
│ └──────────────┘ └─────────────┘ └──────┬───────┘ │
27+
│ │ │
28+
│ ┌───────────────┴──────────────────┐ │
29+
│ │ Storage Layer │ │
30+
│ ├──────────────────┬───────────────┤ │
31+
│ │ SQLite Database │ Filesystem │ │
32+
│ └──────────────────┴───────────────┘ │
33+
└─────────────────────────────────────────────────────────────────────┘
3234
```
3335

36+
### Accepted SOP Classes
37+
38+
The server only negotiates presentation contexts for the two mammography SOP classes sent by the Hologic Selenia Dimensions/3Dimensions:
39+
40+
- Digital mammography x-ray image storage – for presentation
41+
- Digital mammography x-ray image storage – for processing
42+
43+
Other SOP classes (Secondary Capture, Breast Tomosynthesis, Dose SR, etc.) are rejected at association negotiation time so the modality knows not to send them.
44+
45+
### Image Processing Pipeline
46+
47+
When a C-STORE request arrives, the handler applies the following steps before writing to disk:
48+
49+
1. **Validate** — checks that required DICOM tags are present (`SOPInstanceUID`, `PatientID`, `StudyInstanceUID`, `SOPClassUID`) and that pixel data is consistent.
50+
2. **Decompress** — if the image arrives in a compressed transfer syntax, it is decompressed before further processing.
51+
3. **Resize** — if either dimension exceeds `DICOM_THUMBNAIL_SIZE` (default 400 px), the image is scaled down.
52+
4. **Compress** — the pixel data is re-encoded as JPEG 2000 lossy at the configured compression ratio (`DICOM_COMPRESSION_RATIO`, default 15:1).
53+
5. **Store** — the compressed DICOM file is written to the filesystem and indexed in the PACS database.
54+
55+
#### Why lossy compression and resizing?
56+
57+
Modalities send images in JPEG Lossless transfer syntax. The gateway PACS does not store clinical-grade images but rather reduced-resolution copies for display in Manage Breast Screening, where radiologists review appointment and worklist context rather than performing clinical reads. Full-resolution images remain on the BSU internal PACS. A 15:1 JPEG 2000 lossy compression ratio combined with a 400px resize reduces a typical mammography file from several hundred MB to tens of KB, which is appropriate for the thumbnail display use case and unproblematic for transferring via Azure Relay.
58+
3459
### Storage Structure
3560

3661
**Hash-based Directory Layout:**
62+
3763
```
3864
storage/
3965
├── b2/
@@ -48,6 +74,7 @@ storage/
4874
```
4975

5076
Each file is stored using SHA256 hash of its SOP Instance UID:
77+
5178
- First 2 characters → Level 1 directory
5279
- Characters 3-4 → Level 2 directory
5380
- First 16 characters + `.dcm` → Filename
@@ -100,6 +127,8 @@ Environment variables:
100127
| `PACS_PORT` | `4244` | DICOM service port |
101128
| `PACS_STORAGE_PATH` | `/var/lib/pacs/storage` | Directory for DICOM files |
102129
| `PACS_DB_PATH` | `/var/lib/pacs/pacs.db` | SQLite database path |
130+
| `DICOM_THUMBNAIL_SIZE` | `400` | Max pixel dimension after resize (px) |
131+
| `DICOM_COMPRESSION_RATIO` | `15` | JPEG 2000 lossy compression ratio |
103132
| `LOG_LEVEL` | `INFO` | Logging level |
104133

105134
## Verification
@@ -129,10 +158,12 @@ uv run pytest tests/integration/test_send_c_store_to_gateway.py -v
129158
## Security
130159

131160
**Current Implementation:**
161+
132162
- No authentication (intended for internal network)
133163
- No encryption (use VPN/private network)
134164
- File integrity via SHA256 hashes
135165

136166
**Future Considerations:**
167+
137168
- TLS support for encrypted transport
138169
- Application-level authentication

0 commit comments

Comments
 (0)