<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Amr shadid </title>
    <description>The latest articles on DEV Community by Amr shadid  (@amrshadid).</description>
    <link>https://dev.to/amrshadid</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F551069%2F0ebfc72f-0b7b-49a2-b5bd-c55e49563e79.jpeg</url>
      <title>DEV Community: Amr shadid </title>
      <link>https://dev.to/amrshadid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amrshadid"/>
    <language>en</language>
    <item>
      <title>go-dicom — a pure Go DICOM library and CLI, no CGO</title>
      <dc:creator>Amr shadid </dc:creator>
      <pubDate>Sun, 16 Aug 2026 08:49:38 +0000</pubDate>
      <link>https://dev.to/amrshadid/go-dicom-a-pure-go-dicom-library-and-cli-no-cgo-17ij</link>
      <guid>https://dev.to/amrshadid/go-dicom-a-pure-go-dicom-library-and-cli-no-cgo-17ij</guid>
      <description>&lt;p&gt;If you work in Go and you need to handle medical images, your options until now were unpleasant. Bind to dcmtk or DCMTK-derived C libraries and accept CGO — losing static builds, easy cross-compilation, and a good chunk of your deployment simplicity. Shell out to a Python process running pydicom. Or write the parts of the DICOM standard you need yourself, which is how a lot of hospital integrations quietly end up with a half-finished parser in an internal repo.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://github.com/amrshadid/go-dicom" rel="noopener noreferrer"&gt;go-dicom&lt;/a&gt; because I hit that wall on a medical imaging platform I maintain. It is a complete DICOM implementation in pure Go — files, pixels, and the network protocol — with no C dependencies at all.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get github.com/amrshadid/go-dicom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, for the CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/amrshadid/go-dicom/main/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The installer works out your platform, downloads the matching build, and refuses to install unless the SHA256 checksum matches the release's &lt;code&gt;SHA256SUMS&lt;/code&gt;. It prefers a directory already on your &lt;code&gt;PATH&lt;/code&gt;, so nothing needs sudo, and it clears the macOS quarantine flag that otherwise stops Gatekeeper from running a downloaded binary.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Files.&lt;/strong&gt; Read and write DICOM in every form you meet in the wild: standard &lt;code&gt;.dcm&lt;/code&gt;, Siemens &lt;code&gt;.ima&lt;/code&gt;, DICOMDIR, raw data sets with no meta header — which is what modalities produce and what travels on the wire. 37 transfer syntaxes, implicit and explicit VR, little and big endian, deflated. 5,000+ standard tags and 10,500+ private vendor tags (GE, Siemens, Philips, Toshiba) with O(1) lookup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pixels.&lt;/strong&gt; Decoding for JPEG Baseline, JPEG Extended, JPEG Lossless, JPEG-LS, and RLE Lossless, including multi-frame extraction from encapsulated pixel data. An encoder for RLE and JPEG-LS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Networking.&lt;/strong&gt; The complete DIMSE surface, as both client (SCU) and server (SCP): C-ECHO, C-STORE, C-FIND, C-MOVE, C-GET, all six N-DIMSE services, Storage Commitment, Modality Worklist, MPPS, and UPS. Full association negotiation — presentation contexts, extended negotiation, async operations, SCP/SCU role selection, user identity. TLS on both ends.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clinical structures.&lt;/strong&gt; Structured reports with coded concepts (SNOMED-CT, LOINC). Physiological waveforms — ECG, EEG — with QRS detection. Overlays and ROI analysis. 169 storage SOP classes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privacy.&lt;/strong&gt; De-identification per PS3.15 Annex E, with the standard's profiles: basic, clean descriptors, clean graphics, and the retain-* options for longitudinal studies. It descends into sequences, which matters more than it sounds — a de-identified object that keeps its Referenced SOP Instance UIDs still links straight back to the original.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Internationalization.&lt;/strong&gt; 30+ character encodings including ISO 2022, CJK, Cyrillic, Arabic and Hebrew. Text is decoded to UTF-8 on read, so you get strings rather than bytes you have to know how to interpret.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why pure Go is the point
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;CGO_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux &lt;span class="nv"&gt;GOARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm64 go build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That works. It produces one static binary with no shared library dependencies, which means a &lt;code&gt;FROM scratch&lt;/code&gt; container, an ARM edge device sitting next to a modality, or a Lambda function — all from a laptop, with no cross-compilation toolchain and no C headers to hunt down.&lt;/p&gt;

&lt;p&gt;The concurrency model is Go's rather than a wrapper over someone else's. The SCP spawns a goroutine per association. C-FIND results stream back on a channel instead of accumulating in a list. Everything takes a &lt;code&gt;context.Context&lt;/code&gt;, so timeouts and graceful shutdown work the way you already expect them to.&lt;/p&gt;

&lt;h2&gt;
  
  
  The client
&lt;/h2&gt;

&lt;p&gt;Roughly the shape of &lt;code&gt;pynetdicom&lt;/code&gt;'s &lt;code&gt;AE().associate()&lt;/code&gt;, if you know that API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;scu&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewSCU&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SCUConfig&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;CallingAE&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"MY_APP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CalledAE&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;"PACS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;"pacs.hospital.com:11112"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;scu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Associate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;scu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// Verification&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;scu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Echo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Query — results stream as they arrive&lt;/span&gt;
&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;scu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;queryDataset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The server
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;scp&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewSCP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SCPConfig&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;AETitle&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"MY_SCP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="m"&gt;11112&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;scp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StorageHandler&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;OnStore&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sopClass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sopInstance&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ds&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dataset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;uint16&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Save to disk, a database, object storage, another PACS&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusSuccess&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are handler types for the common roles — echo, storage, query/retrieve, worklist — a composite handler when you want to mix them, and a &lt;code&gt;BaseHandler&lt;/code&gt; to embed when you want full control over one message type and defaults for the rest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading a file
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;dicomFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;filereader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadDICOMFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;ds&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;dicomFile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetDataset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetStringValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0x0010&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0x0010&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Data sets are thread-safe. All mutable structures use &lt;code&gt;sync.RWMutex&lt;/code&gt;, so concurrent readers with exclusive writers works without you building a lock layer on top.&lt;/p&gt;

&lt;h2&gt;
  
  
  It is also a CLI
&lt;/h2&gt;

&lt;p&gt;Sixteen commands, covering the same ground as the DCMTK tools you may already be using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Files&lt;/span&gt;
go-dicom show patient.dcm              &lt;span class="c"&gt;# display contents, sequences indented by depth&lt;/span&gt;
go-dicom info patient.dcm              &lt;span class="c"&gt;# metadata&lt;/span&gt;
go-dicom convert patient.dcm out.json  &lt;span class="c"&gt;# JSON, CSV or NIfTI&lt;/span&gt;
go-dicom codify patient.dcm            &lt;span class="c"&gt;# generate Go source that rebuilds the data set&lt;/span&gt;
go-dicom tag-doc 0010,0010             &lt;span class="c"&gt;# what does this tag mean&lt;/span&gt;

&lt;span class="c"&gt;# Network&lt;/span&gt;
go-dicom echoscu pacs:11112
go-dicom storescu &lt;span class="nt"&gt;-aec&lt;/span&gt; PACS pacs:11112 study/&lt;span class="k"&gt;*&lt;/span&gt;.dcm
go-dicom storescp &lt;span class="nt"&gt;-port&lt;/span&gt; 11112 &lt;span class="nt"&gt;-output&lt;/span&gt; ./received/
go-dicom findscu &lt;span class="nt"&gt;-patient-name&lt;/span&gt; &lt;span class="s2"&gt;"Smith*"&lt;/span&gt; &lt;span class="nt"&gt;-level&lt;/span&gt; STUDY pacs:11112
go-dicom movescu &lt;span class="nt"&gt;-dest&lt;/span&gt; MY_SCP &lt;span class="nt"&gt;-study&lt;/span&gt; 1.2.3.4 pacs:11112
go-dicom qrscp &lt;span class="nt"&gt;-port&lt;/span&gt; 11112             &lt;span class="c"&gt;# a working query/retrieve archive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last one is worth pausing on. &lt;code&gt;qrscp&lt;/code&gt; is backed by an on-disk instance store with a queryable index, so the library can &lt;em&gt;be&lt;/em&gt; the archive rather than only talk to one. For a test environment, a research pipeline, or an edge cache in front of a real PACS, that removes an entire piece of infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  On trust
&lt;/h2&gt;

&lt;p&gt;Medical imaging is a domain where a library quietly doing the wrong thing is genuinely dangerous, so I would rather over-share here than make claims you have to take on faith.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interoperability is tested against other implementations, in CI.&lt;/strong&gt; Every build runs against pynetdicom and dcmtk, and uses pydicom as the verifier rather than go-dicom's own reader. Correctness is measured against pydicom's test corpus — files I did not generate — not only against fixtures of my own making.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There is a conformance statement.&lt;/strong&gt; &lt;a href="https://github.com/amrshadid/go-dicom/blob/main/CONFORMANCE.md" rel="noopener noreferrer"&gt;CONFORMANCE.md&lt;/a&gt; follows the structure of PS3.2: SOP classes per role, transfer syntaxes negotiated versus those merely readable from a file, extended negotiation, configuration, character sets, enforced limits — and a plainly stated list of limitations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The limitations are written down.&lt;/strong&gt; JPEG 2000 is not encoded or decoded. The SCP side of asynchronous operations is not implemented. Sequence matching outside the standard's own matching keys is not supported. Where something is missing, the docs say so and say why, rather than leaving you to discover it in production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security is treated as part of correctness.&lt;/strong&gt; Peer-supplied lengths are bounded, malformed PDUs cannot crash the server or trigger huge allocations, and received instances are no longer written to paths derived from unvalidated peer-supplied UIDs. Each of those was a real defect that got found and fixed; the &lt;a href="https://github.com/amrshadid/go-dicom/blob/main/SECURITY.md" rel="noopener noreferrer"&gt;SECURITY.md&lt;/a&gt; policy covers how to report more.&lt;/p&gt;

&lt;p&gt;Every commit builds and passes independently, so the history is bisectable. &lt;code&gt;gofmt&lt;/code&gt;, &lt;code&gt;go vet&lt;/code&gt; and &lt;code&gt;golangci-lint&lt;/code&gt; clean, tests under &lt;code&gt;-race&lt;/code&gt; on Linux, macOS and Windows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it fits
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;You need&lt;/th&gt;
&lt;th&gt;Today&lt;/th&gt;
&lt;th&gt;With go-dicom&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DICOM in a Go service&lt;/td&gt;
&lt;td&gt;CGO binding to dcmtk&lt;/td&gt;
&lt;td&gt;Import a package&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A container image&lt;/td&gt;
&lt;td&gt;Base image with C libs&lt;/td&gt;
&lt;td&gt;&lt;code&gt;FROM scratch&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ARM / edge deployment&lt;/td&gt;
&lt;td&gt;Cross-compilation toolchain&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GOARCH=arm64 go build&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A test PACS&lt;/td&gt;
&lt;td&gt;Install and configure one&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go-dicom qrscp&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anonymize a study&lt;/td&gt;
&lt;td&gt;Python subprocess&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;anonymize&lt;/code&gt; package&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The repository is at &lt;strong&gt;&lt;a href="https://github.com/amrshadid/go-dicom" rel="noopener noreferrer"&gt;github.com/amrshadid/go-dicom&lt;/a&gt;&lt;/strong&gt;. MIT licensed, no dependencies outside the Go standard library and &lt;code&gt;golang.org/x&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are complete runnable examples in &lt;a href="https://github.com/amrshadid/go-dicom/tree/main/examples" rel="noopener noreferrer"&gt;&lt;code&gt;examples/&lt;/code&gt;&lt;/a&gt; — reading, writing, modifying, sequences, image processing, and every networking pattern.&lt;/p&gt;

&lt;p&gt;What I would find most useful right now is people running it against real equipment. If you have a PACS, a modality, or an archive that go-dicom cannot talk to, open an issue with the association details and I will fix it — that kind of report has been the source of nearly every meaningful improvement in the project so far.&lt;/p&gt;

&lt;p&gt;And if it saves you from writing a DICOM parser this quarter, a star helps other people find it.&lt;/p&gt;

</description>
      <category>go</category>
      <category>opensource</category>
      <category>healthcare</category>
      <category>showdev</category>
    </item>
    <item>
      <title>React zoom and pan with draggable elements</title>
      <dc:creator>Amr shadid </dc:creator>
      <pubDate>Mon, 21 Mar 2022 00:04:53 +0000</pubDate>
      <link>https://dev.to/amrshadid/react-zoom-and-pan-with-draggable-elements-4mn8</link>
      <guid>https://dev.to/amrshadid/react-zoom-and-pan-with-draggable-elements-4mn8</guid>
      <description>&lt;p&gt;I just try to build drag-able elements then move them around the screen and zoom it using mouse events, So how we can implement that using React. &lt;/p&gt;

&lt;p&gt;I was searching in npm.io to find a package that can provide those features. Finally, I found some packages that can implement what I want, for that, I want to share the outcome here and highlight how I make integrate these packages with each other.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg41wu324c0mx861qvulz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg41wu324c0mx861qvulz.gif" alt="Sql builder, finally result" width="600" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first chapter will explain how we can create draggable elements,  is a great existing package called&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/react-draggable/v/4.4.3" rel="noopener noreferrer"&gt;&lt;strong&gt;react-draggable&lt;/strong&gt;&lt;/a&gt;, This package is powerful that can provide draggable elements using JavaScript.&lt;/p&gt;

&lt;p&gt;It's very easy to use and has powerful features. &lt;/p&gt;

&lt;p&gt;The below code snippet explains how we can create drag-able elements. Draggable elements have powerful functions that are called when on-drag start or on end to perform some routine like update state or do something.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as React from 'react'
import Draggable from 'react-draggable'

export default function Table(props: ITableProps
                                    &amp;amp; ITableOptionsProps) {

    return (
        &amp;lt;Draggable onDrag={props.onDrag} onStop={props.onStop}&amp;gt;
            &amp;lt;div className='table'&amp;gt;

                &amp;lt;div className='table-name'&amp;gt;
                    &amp;lt;h3&amp;gt;{props.name}&amp;lt;/h3&amp;gt;
                &amp;lt;/div&amp;gt;

                {props.att.map((value,index)=&amp;gt;(

                    &amp;lt;div key={index} className='attribute' id={props.name+"."+value.name}&amp;gt;
                        &amp;lt;div className='element'&amp;gt;&amp;lt;h3&amp;gt;{value.name}&amp;lt;/h3&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className='element type'&amp;gt;&amp;lt;h3&amp;gt;{value.type}&amp;lt;/h3&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className='element null'&amp;gt;&amp;lt;h3&amp;gt;{value.null}&amp;lt;/h3&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className='element pk'&amp;gt;{value.pk?&amp;lt;h3&amp;gt;pk&amp;lt;/h3&amp;gt;:null}&amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                ))}
            &amp;lt;/div&amp;gt;
        &amp;lt;/Draggable&amp;gt;
    );}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.table{
  position: fixed;
  display: flex;
  flex-direction: column;
  cursor: move;
  align-items: center;
  background-color: transparent;
  min-width: 380px;
  min-height: 200px;
  border: 2px solid #9BA1A6;
  border-radius: 7px;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the output of the above code block is div have style class called table &lt;code&gt;&amp;lt;div className='table'&amp;gt;&lt;/code&gt; these table elements can drag around the page using mouse.&lt;/p&gt;

&lt;p&gt;Now the second chapter explains how we can build a transform Wrapper that can provide zoom and pan, of course using the great package called &lt;a href="https://github.com/prc5/react-zoom-pan-pinch" rel="noopener noreferrer"&gt;&lt;strong&gt;react-zoom-pan-pinch&lt;/strong&gt;&lt;/a&gt;, react-zoom-pan-pinch is a powerful package that provides transform wrapper, transform component, and zoom controlling features. &lt;/p&gt;

&lt;p&gt;After we create drag-able elements now we need to contain these elements in the transform wrapper to enable zoom controlling and pan the elements as a group.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as React from 'react';
import { AppContext } from '../../context';
import Table from '../table';
import { 
TransformWrapper, 
TransformComponent 
} from "react-zoom-pan-pinch";


export default function Main(props: IMainProps) {
  const context = React.useContext(AppContext)
  const [isMoveable, setIsMoveable] = React.useState&amp;lt;boolean&amp;gt;(false);

  const onDrag = () =&amp;gt; {
    setIsMoveable(true)
    //etc
  }
  const onStop = () =&amp;gt; {
    setIsMoveable(false)
    //etc 

  }


  return (
    &amp;lt;&amp;gt;
      &amp;lt;TransformWrapper
        initialScale={1}
        disabled={isMoveable}
        minScale={.5}
        maxScale={1}
        limitToBounds={false}
        onPanning={updateXarrow}
        onZoom={updateXarrow}
        pinch={{ step: 5 }}
      &amp;gt;

        &amp;lt;TransformComponent 
          contentClass='main' 
          wrapperStyle={{ height: '100vh', width: '80vw' }}&amp;gt;


          {context?.database.schema.map((value, index) =&amp;gt; (
            &amp;lt;Table 
              key={index} 
              name={value.name} 
              att={value.att} 
              onDrag={onDrag} 
              onStop={onStop}/&amp;gt;
          ))}

        &amp;lt;/TransformComponent&amp;gt;
      &amp;lt;/TransformWrapper&amp;gt;

    &amp;lt;/&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CSS for content on transform component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.main{
  display: flex;
  flex-direction: row;
  position: absolute;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we passed two functions to draggable element the first one is &lt;strong&gt;onDrag&lt;/strong&gt; this function will perform when the user start drag element and the last one &lt;strong&gt;onStop&lt;/strong&gt; is will perform when the user finished dragging element, The main ideas of using this function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;provide enable control for transform wrapper to fix a conflict between draggable elements and transform wrapper.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;perform some updater functions like when we have an arrow between two draggable elements and we move one then we need to update arrow positions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we have draggable elements and transform wrapper, you can visit &lt;a href="https://github.com/amrshadid/sqlbuilder-tool" rel="noopener noreferrer"&gt;sql builder tool&lt;/a&gt; on Github to get a full example with source code.&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>programming</category>
      <category>css</category>
    </item>
  </channel>
</rss>
