DICOM Tag Filter for Orthanc
A C++ Orthanc plugin that carries configurable tag filtering through ingestion, custom storage, duplicate tracking, and database crosswalk updates.
- Version
- Team project
- Status
- Complete; known date-helper issue
- Built with
- C++, Orthanc SDK, CMake, PostgreSQL
- My work
- Primary C++ implementation, CMake, and documentation

Project overview
This C++ plugin adds configurable DICOM tag filtering to Orthanc. A received instance passes through tag rules and optional date masking before the plugin writes its filtered representation to storage. The interesting part is carrying that work through Orthanc’s callbacks while keeping the stored data, duplicate tracking, and database records in agreement.
My part in the team
I wrote the primary C++ implementation, all or most of the CMake configuration, and the project documentation. My teammates mainly handled database work and project administration. The plugin connects those responsibilities: the C++ callbacks process instances and coordinate storage, while the database maintains the associated records and crosswalk information.
Following an instance into storage
The incoming-instance callback parses the DICOM data and applies configured blacklists or whitelists of tags. Date rules can retain selected components of a date while replacing others. The resulting buffer has to reach the storage callback, which is responsible for writing the filtered data rather than the incoming bytes.
These callbacks do not form one ordinary function call with a shared local variable. The plugin keeps transport state between them and tracks checksums for instances already being processed. An MD5 set rejects concurrent duplicates while that work is underway. Stored-instance handling then coordinates the file and database information.
Custom storage also supports configurable hardlink groupings. Several paths can refer to the same stored file, while database crosswalk updates retain checksums and original element values needed by the configured workflow. That makes the storage and database policy part of the design, rather than an incidental detail after filtering.
What a filtering rule actually promises
Removing a tag from the stored DICOM object does not mean its original value disappears from every part of the system. Values may remain in working memory or in the database crosswalk. A deployment therefore needs a deliberate policy for the filtered object, those retained values, and access to both. The plugin implements configurable transformations; the project does not establish a general de-identification guarantee.
Checking the small pieces independently
A later check of the date helper reproduced five original examples in an isolated driver. Comparing unchanged-date masks against an independent calendar exposed a gap those examples missed: 48 of 73,414 checks changed a valid leap day to February 28. The helper’s leap-year handling needs correction before relying on that behavior.
This is a completed team project with a known issue in its date helper. The isolated checks do not exercise an Orthanc server, PostgreSQL, concurrent ingestion, or a deployment’s privacy requirements. Those boundaries matter when deciding what the plugin is ready to support.


