├── examples ├── dcm_temp │ ├── placeholder.txt │ └── store_server.log ├── pdf.pdf ├── dean.dcm ├── test.dcm ├── test.jpg ├── store_server.php ├── get_tags_webbased.php ├── write_tags.php ├── get_tags.php ├── dcm_to_jpg.php ├── send_dcm.php ├── compress.php ├── uncompress.php ├── store_server_handler.php ├── send_directory.php ├── jpg_to_dcm.php ├── jpg_to_dcm.xml └── store_server_config.cfg ├── README └── class_dicom.php /examples/dcm_temp/placeholder.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/pdf.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vedicveko/class_dicom.php/HEAD/examples/pdf.pdf -------------------------------------------------------------------------------- /examples/dean.dcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vedicveko/class_dicom.php/HEAD/examples/dean.dcm -------------------------------------------------------------------------------- /examples/test.dcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vedicveko/class_dicom.php/HEAD/examples/test.dcm -------------------------------------------------------------------------------- /examples/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vedicveko/class_dicom.php/HEAD/examples/test.jpg -------------------------------------------------------------------------------- /examples/dcm_temp/store_server.log: -------------------------------------------------------------------------------- 1 | 20110407 13:52:46 - Received DAVIS^ALEXANDER-DOCUM from Dean -> Dean 2 | 20110407 13:52:46 - Received DAVIS^ALEXANDER from Dean -> Dean 3 | 20110407 13:52:46 - Received DAVIS^ALEXANDER from Dean -> Dean 4 | 20110407 14:22:54 - Received VAUGHAN^DEAN from example -> DEANO 5 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | A PHP class that lets you work with DICOM tags, convert to jpg, compress, uncompress, receive, and send images. 2 | 3 | My aim was to keep the interface as simple as possible while at the same time providing a class that would be easy to grow. 4 | 5 | SEE: http://www.deanvaughan.org/projects/class_dicom_php/ 6 | 7 | -------------------------------------------------------------------------------- /examples/store_server.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | store_server(104, './dcm_temp', './store_server_handler.php', 'store_server_config.cfg', 1); 12 | 13 | ?> 14 | -------------------------------------------------------------------------------- /examples/get_tags_webbased.php: -------------------------------------------------------------------------------- 1 | file = $file; 16 | $d->load_tags(); 17 | 18 | print "
";
19 |
20 | print_r($d->tags);
21 |
22 | $name = $d->get_tag('0010', '0010');
23 | print "Name: $name\n";
24 |
25 | ?>
26 |
--------------------------------------------------------------------------------
/examples/write_tags.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | file = 'dean.dcm';
10 |
11 | $new_tags = array(
12 | '0010,0010' => 'VAUGHAN^DEAN',
13 | '0008,0080' => 'DEANLAND, AR'
14 | );
15 |
16 |
17 | $result = $d->write_tags($new_tags);
18 |
19 | if($result) {
20 | print "$result\n";
21 | }
22 | else {
23 | system("./get_tags.php " . $d->file);
24 | }
25 |
26 | ?>
27 |
--------------------------------------------------------------------------------
/examples/get_tags.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | \n";
13 | exit;
14 | }
15 |
16 | if(!file_exists($file)) {
17 | print "$file: does not exist\n";
18 | exit;
19 | }
20 |
21 | $d = new dicom_tag($file);
22 | $d->load_tags();
23 |
24 | print_r($d->tags);
25 |
26 | $name = $d->get_tag('0010', '0010');
27 | print "Name: $name\n";
28 |
29 | ?>
30 |
--------------------------------------------------------------------------------
/examples/dcm_to_jpg.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | \n";
13 | exit;
14 | }
15 |
16 | if(!file_exists($file)) {
17 | print "$file: does not exist\n";
18 | exit;
19 | }
20 |
21 | $job_start = time();
22 |
23 | $d = new dicom_convert;
24 | $d->file = $file;
25 | $d->dcm_to_jpg();
26 | $d->dcm_to_tn();
27 |
28 | system("ls -lsh $file*");
29 |
30 | $job_end = time();
31 | $job_time = $job_end - $job_start;
32 | print "Created JPEG and thumbnail in $job_time seconds.\n";
33 |
34 |
35 | ?>
36 |
--------------------------------------------------------------------------------
/examples/send_dcm.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | \n";
13 | exit;
14 | }
15 |
16 | if(!file_exists($file)) {
17 | print "$file: does not exist\n";
18 | exit;
19 | }
20 |
21 | $d = new dicom_net;
22 | $d->file = $file;
23 |
24 | print "Sending file...\n";
25 |
26 | $out = $d->send_dcm('localhost', '104', 'DEANO', 'example');
27 |
28 | if($out) {
29 | print "$out\n\nSomething bad happened!\n";
30 | exit;
31 | }
32 |
33 | print "Sent!\n";
34 |
35 | ?>
36 |
--------------------------------------------------------------------------------
/examples/compress.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | \n";
13 | exit;
14 | }
15 |
16 | if(!file_exists($file)) {
17 | print "$file: does not exist\n";
18 | exit;
19 | }
20 |
21 | $d = new dicom_tag;
22 | $d->file = $file;
23 | $d->load_tags();
24 | $ts = $d->get_tag('0002', '0010');
25 | $fsize = filesize($file);
26 | print "Original: $ts ($fsize)\n";
27 |
28 | $c = new dicom_convert;
29 | $c->file = $file;
30 | $c->compress('compressed.dcm');
31 |
32 |
33 | $d->file = 'compressed.dcm';
34 | $d->load_tags();
35 | $ts = $d->get_tag('0002', '0010');
36 | $fsize = filesize($d->file);
37 | print "Compressed: $ts ($fsize)\n";
38 |
39 | ?>
40 |
--------------------------------------------------------------------------------
/examples/uncompress.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | \n";
13 | exit;
14 | }
15 |
16 | if(!file_exists($file)) {
17 | print "$file: does not exist\n";
18 | exit;
19 | }
20 |
21 | $d = new dicom_tag;
22 | $d->file = $file;
23 | $d->load_tags();
24 | $ts = $d->get_tag('0002', '0010');
25 | $fsize = filesize($d->file);
26 | print "Original: $ts ($fsize)\n";
27 |
28 | $c = new dicom_convert;
29 | $c->file = $file;
30 | $c->uncompress('uncompressed.dcm');
31 |
32 |
33 | $d->file = 'uncompressed.dcm';
34 | $d->load_tags();
35 | $ts = $d->get_tag('0002', '0010');
36 | $fsize = filesize($d->file);
37 | print "Uncompressed: $ts ($fsize)\n";
38 |
39 | ?>
40 |
--------------------------------------------------------------------------------
/examples/store_server_handler.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | file = "$dir/$file";
35 |
36 | if(!file_exists($d->file)) {
37 | logger($d->file . ": does not exist");
38 | exit;
39 | }
40 |
41 |
42 | $d->load_tags();
43 | $name = $d->get_tag('0010', '0010');
44 | logger("Received $name from $sent_to_ae -> $sent_from_ae");
45 |
46 | ?>
47 |
--------------------------------------------------------------------------------
/examples/send_directory.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | file = "$temp_dir/$file";
28 | $ret = $d->send_dcm($target_host, $target_port, $my_ae, $target_ae);
29 | if($ret) {
30 | print "Send Error: $ret\n";
31 | continue;
32 | }
33 | else {
34 | print "Good Send\n";
35 | print "Moving $temp_dir/$file\n";
36 | rename("$temp_dir/$file", "bk/$file");
37 | }
38 |
39 | }
40 | }
41 | closedir($handle);
42 | }
43 |
44 | ?>
45 |
--------------------------------------------------------------------------------
/examples/jpg_to_dcm.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | jpg_file = 'test.jpg';
11 | $d->template = 'jpg_to_dcm.xml';
12 | $d->temp_dir = 'dcm_temp';
13 |
14 | $tags = array(
15 | '0008,0012' => date('Ymd'),
16 | '0008,0013' => date('Gis'),
17 | '0008,0050' => 'ACCESSION123',
18 | '0008,0080' => 'General Hospital',
19 | '0008,0090' => 'Dr. Dean',
20 | '0008,1030' => 'Study Description',
21 | '0008,103e' => 'Series Description',
22 | '0010,0010' => 'VAUGHAN^DEAN',
23 | '0010,0020' => 'ID12345',
24 | '0010,0030' => '19700303',
25 | '0010,0040' => 'M',
26 | '0010,21b0' => 'Patient History',
27 | '0010,4000' => 'Patient Comments',
28 | '0018,0015' => 'Head',
29 | '0020,000d' => '1.3.51.0.7.2822962297.26312.19209.44846.7354.10266.42',
30 | '0020,000e' => '1.3.51.5156.4083.' . date('Ymd') .'.42',
31 | '0020,0011' => '1',
32 | '0020,0012' => '1',
33 | '0020,0013' => '1',
34 | );
35 |
36 | $dcm = $d->jpg_to_dcm($tags);
37 |
38 | print "New file is $dcm\n";
39 |
40 |
41 | ?>
42 |
--------------------------------------------------------------------------------
/examples/jpg_to_dcm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 180
5 | 1.2.840.10008.5.1.4.1.1.1
6 | 1.3.51.5156.4083.20080612.1175700.1
7 | 1.2.840.10008.1.2.1
8 | 1.2.276.0.7230010.3.0.3.5.4
9 | DEANO
10 |
11 |
12 | DERIVED\PRIMARY
13 | (0008,0012)
14 | (0008,0013)
15 | 1.2.840.10008.5.1.4.1.1.1
16 | 1.3.51.5156.4083.(0008,0012).1175700.1
17 | (0008,0012)
18 | (0008,0012)
19 | (0008,0013)
20 | (0008,0013)
21 | (0008,0050)
22 | CR
23 | DEANO
24 | (0008,0080)
25 | (0008,0090)
26 | DEANO
27 | (0008,1030)
28 | (0008,103e)
29 | DEANO
30 | DEANO
31 | (0010,0010)
32 | (0010,0020)
33 | (0010,0030)
34 | (0010,0040)
35 | (0010,21b0)
36 | (0010,4000)
37 | (0018,0015)
38 | (0020,000d)
39 | (0020,000e)
40 | DEAN
41 | (0020,0011)
42 | (0020,0013)
43 | (0020,0012)
44 |
45 |
46 |
--------------------------------------------------------------------------------
/examples/store_server_config.cfg:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2003-2006, OFFIS
3 | #
4 | # This software and supporting documentation were developed by
5 | #
6 | # Kuratorium OFFIS e.V.
7 | # Healthcare Information and Communication Systems
8 | # Escherweg 2
9 | # D-26121 Oldenburg, Germany
10 | #
11 | # THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND OFFIS MAKES NO WARRANTY
12 | # REGARDING THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR
13 | # FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES OR
14 | # ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND
15 | # PERFORMANCE OF THE SOFTWARE IS WITH THE USER.
16 | #
17 | # Module: dcmnet
18 | #
19 | # Author: Marco Eichelberg
20 | #
21 | # Purpose: Sample configuration file for storescp
22 | #
23 | # Last Update: $Author: meichel $
24 | # Update Date: $Date: 2006-06-15 15:30:50 $
25 | # CVS/RCS Revision: $Revision: 1.7 $
26 | # Status: $State: Exp $
27 | #
28 |
29 | # ============================================================================
30 | [[TransferSyntaxes]]
31 | # ============================================================================
32 |
33 | [AnyTransferSyntax]
34 | TransferSyntax1 = JPEGExtended:Process2+4
35 | TransferSyntax2 = JPEGBaseline
36 | TransferSyntax3 = JPEGLossless:Non-hierarchical-1stOrderPrediction
37 | TransferSyntax4 = JPEGLSLossy
38 | TransferSyntax5 = JPEGLSLossless
39 | TransferSyntax6 = RLELossless
40 | TransferSyntax7 = MPEG2MainProfile@MainLevel
41 | TransferSyntax8 = JPEG2000
42 | TransferSyntax9 = JPEG2000LosslessOnly
43 | TransferSyntax10 = DeflatedLittleEndianExplicit
44 | TransferSyntax11 = LocalEndianExplicit
45 | TransferSyntax12 = OppositeEndianExplicit
46 | TransferSyntax13 = LittleEndianImplicit
47 |
48 | [Uncompressed]
49 | TransferSyntax1 = LocalEndianExplicit
50 | TransferSyntax2 = OppositeEndianExplicit
51 | TransferSyntax3 = LittleEndianImplicit
52 |
53 | [UncompressedOrZlib]
54 | TransferSyntax1 = DeflatedLittleEndianExplicit
55 | TransferSyntax2 = LocalEndianExplicit
56 | TransferSyntax3 = OppositeEndianExplicit
57 | TransferSyntax4 = LittleEndianImplicit
58 |
59 |
60 | # ============================================================================
61 | [[PresentationContexts]]
62 | # ============================================================================
63 |
64 | [GenericStorageSCP]
65 | #
66 | # Don't forget to support the Verification SOP Class.
67 | #
68 | PresentationContext1 = VerificationSOPClass\Uncompressed
69 | #
70 | # Accept image SOP classes with virtually any transfer syntax we know.
71 | # Accept non-image SOP classes uncompressed or with zlib compression only.
72 | #
73 | PresentationContext2 = ComputedRadiographyImageStorage\AnyTransferSyntax
74 | PresentationContext3 = CTImageStorage\AnyTransferSyntax
75 | PresentationContext4 = DigitalIntraOralXRayImageStorageForPresentation\AnyTransferSyntax
76 | PresentationContext5 = DigitalIntraOralXRayImageStorageForProcessing\AnyTransferSyntax
77 | PresentationContext6 = DigitalMammographyXRayImageStorageForPresentation\AnyTransferSyntax
78 | PresentationContext7 = DigitalMammographyXRayImageStorageForProcessing\AnyTransferSyntax
79 | PresentationContext8 = DigitalXRayImageStorageForPresentation\AnyTransferSyntax
80 | PresentationContext9 = DigitalXRayImageStorageForProcessing\AnyTransferSyntax
81 | PresentationContext10 = EnhancedCTImageStorage\AnyTransferSyntax
82 | PresentationContext11 = EnhancedMRImageStorage\AnyTransferSyntax
83 | PresentationContext12 = EnhancedXAImageStorage\AnyTransferSyntax
84 | PresentationContext13 = EnhancedXRFImageStorage\AnyTransferSyntax
85 | PresentationContext14 = MRImageStorage\AnyTransferSyntax
86 | PresentationContext15 = MultiframeGrayscaleByteSecondaryCaptureImageStorage\AnyTransferSyntax
87 | PresentationContext16 = MultiframeGrayscaleWordSecondaryCaptureImageStorage\AnyTransferSyntax
88 | PresentationContext17 = MultiframeSingleBitSecondaryCaptureImageStorage\AnyTransferSyntax
89 | PresentationContext18 = MultiframeTrueColorSecondaryCaptureImageStorage\AnyTransferSyntax
90 | PresentationContext19 = NuclearMedicineImageStorage\AnyTransferSyntax
91 | PresentationContext20 = OphthalmicPhotography16BitImageStorage\AnyTransferSyntax
92 | PresentationContext21 = OphthalmicPhotography8BitImageStorage\AnyTransferSyntax
93 | PresentationContext22 = RETIRED_NuclearMedicineImageStorage\AnyTransferSyntax
94 | PresentationContext23 = RETIRED_UltrasoundImageStorage\AnyTransferSyntax
95 | PresentationContext24 = RETIRED_UltrasoundMultiframeImageStorage\AnyTransferSyntax
96 | PresentationContext25 = RETIRED_VLImageStorage\AnyTransferSyntax
97 | PresentationContext26 = RETIRED_VLMultiFrameImageStorage\AnyTransferSyntax
98 | PresentationContext27 = RETIRED_XRayAngiographicBiPlaneImageStorage\AnyTransferSyntax
99 | PresentationContext28 = RTImageStorage\AnyTransferSyntax
100 | PresentationContext29 = SecondaryCaptureImageStorage\AnyTransferSyntax
101 | PresentationContext30 = UltrasoundImageStorage\AnyTransferSyntax
102 | PresentationContext31 = UltrasoundMultiframeImageStorage\AnyTransferSyntax
103 | PresentationContext32 = VideoEndoscopicImageStorage\AnyTransferSyntax
104 | PresentationContext33 = VideoMicroscopicImageStorage\AnyTransferSyntax
105 | PresentationContext34 = VideoPhotographicImageStorage\AnyTransferSyntax
106 | PresentationContext35 = VLEndoscopicImageStorage\AnyTransferSyntax
107 | PresentationContext36 = VLMicroscopicImageStorage\AnyTransferSyntax
108 | PresentationContext37 = VLPhotographicImageStorage\AnyTransferSyntax
109 | PresentationContext38 = VLSlideCoordinatesMicroscopicImageStorage\AnyTransferSyntax
110 | #
111 | # the following presentation contexts are for non-image SOP classes
112 | #
113 | PresentationContext44 = AmbulatoryECGWaveformStorage\UncompressedOrZlib
114 | PresentationContext45 = BasicTextSR\UncompressedOrZlib
115 | PresentationContext46 = BasicVoiceAudioWaveformStorage\UncompressedOrZlib
116 | PresentationContext47 = BlendingSoftcopyPresentationStateStorage\UncompressedOrZlib
117 | PresentationContext48 = CardiacElectrophysiologyWaveformStorage\UncompressedOrZlib
118 | PresentationContext49 = ChestCADSR\UncompressedOrZlib
119 | PresentationContext50 = ColorSoftcopyPresentationStateStorage\UncompressedOrZlib
120 | PresentationContext51 = ComprehensiveSR\UncompressedOrZlib
121 | PresentationContext52 = EncapsulatedPDFStorage\UncompressedOrZlib
122 | PresentationContext53 = EnhancedSR\UncompressedOrZlib
123 | PresentationContext54 = GeneralECGWaveformStorage\UncompressedOrZlib
124 | PresentationContext55 = GrayscaleSoftcopyPresentationStateStorage\UncompressedOrZlib
125 | PresentationContext56 = HemodynamicWaveformStorage\UncompressedOrZlib
126 | PresentationContext57 = KeyObjectSelectionDocument\UncompressedOrZlib
127 | PresentationContext58 = MammographyCADSR\UncompressedOrZlib
128 | PresentationContext59 = MRSpectroscopyStorage\UncompressedOrZlib
129 | PresentationContext60 = PETCurveStorage\UncompressedOrZlib
130 | PresentationContext61 = ProcedureLogStorage\UncompressedOrZlib
131 | PresentationContext62 = PseudoColorSoftcopyPresentationStateStorage\UncompressedOrZlib
132 | PresentationContext63 = RawDataStorage\UncompressedOrZlib
133 | PresentationContext64 = RealWorldValueMappingStorage\UncompressedOrZlib
134 | PresentationContext65 = RTBeamsTreatmentRecordStorage\UncompressedOrZlib
135 | PresentationContext66 = RTBrachyTreatmentRecordStorage\UncompressedOrZlib
136 | PresentationContext67 = RTDoseStorage\UncompressedOrZlib
137 | PresentationContext68 = RTPlanStorage\UncompressedOrZlib
138 | PresentationContext69 = RTStructureSetStorage\UncompressedOrZlib
139 | PresentationContext70 = RTTreatmentSummaryRecordStorage\UncompressedOrZlib
140 | PresentationContext71 = SpatialFiducialsStorage\UncompressedOrZlib
141 | PresentationContext72 = SpatialRegistrationStorage\UncompressedOrZlib
142 | PresentationContext73 = StandaloneCurveStorage\UncompressedOrZlib
143 | PresentationContext74 = StandaloneModalityLUTStorage\UncompressedOrZlib
144 | PresentationContext75 = StandaloneOverlayStorage\UncompressedOrZlib
145 | PresentationContext76 = StandaloneVOILUTStorage\UncompressedOrZlib
146 | PresentationContext77 = StereometricRelationshipStorage\UncompressedOrZlib
147 | PresentationContext78 = StoredPrintStorage\UncompressedOrZlib
148 | PresentationContext79 = TwelveLeadECGWaveformStorage\UncompressedOrZlib
149 | PresentationContext80 = XRayRadiationDoseSR\UncompressedOrZlib
150 |
151 | # ============================================================================
152 | [[Profiles]]
153 | # ============================================================================
154 |
155 | [Default]
156 | PresentationContexts = GenericStorageSCP
157 | TransferSyntaxes = AnyTransferSyntax
158 |
--------------------------------------------------------------------------------
/class_dicom.php:
--------------------------------------------------------------------------------
1 |
4 | http://www.deanvaughan.org/projects/class_dicom_php/
5 | */
6 |
7 | define('TOOLKIT_DIR', '/usr/local/bin'); // CHANGE THIS IF YOU HAVE DCMTK INSTALLED SOMEWHERE ELSE
8 |
9 | // WINDOWS EXAMPLE
10 | // define('TOOLKIT_DIR', 'C:/dcmtk/bin');
11 |
12 | ////////////////
13 | ///////////////
14 | ///////////////
15 | // Are we running under Windows?
16 | if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
17 | define('RUNNING_WINDOWS', 1);
18 | }
19 | else {
20 | define('RUNNING_WINDOWS', 0);
21 | }
22 |
23 | // If we're running under windows change where we look for our binaries.
24 | // Just add .exe to the end of them.
25 | if(RUNNING_WINDOWS) {
26 | define('BIN_DCMDUMP', TOOLKIT_DIR . '/dcmdump.exe');
27 | define('BIN_STORESCU', TOOLKIT_DIR . '/storescu.exe');
28 | define('BIN_STORESCP', TOOLKIT_DIR . '/storescp.exe');
29 | define('BIN_ECHOSCU', TOOLKIT_DIR . '/echoscu.exe');
30 | define('BIN_DCMJ2PNM', TOOLKIT_DIR . '/dcmj2pnm.exe');
31 | define('BIN_DCMODIFY', TOOLKIT_DIR . '/dcmodify.exe');
32 | define('BIN_DCMCJPEG', TOOLKIT_DIR . '/dcmdjpeg.exe');
33 | define('BIN_DCMDJPEG', TOOLKIT_DIR . '/dcmcjpeg.exe');
34 | define('BIN_XML2DCM', TOOLKIT_DIR . '/xml2dcm.exe');
35 | define('BIN_IMG2DCM', TOOLKIT_DIR . '/img2dcm.exe');
36 | }
37 | else {
38 | define('BIN_DCMDUMP', TOOLKIT_DIR . '/dcmdump');
39 | define('BIN_STORESCU', TOOLKIT_DIR . '/storescu');
40 | define('BIN_STORESCP', TOOLKIT_DIR . '/storescp');
41 | define('BIN_ECHOSCU', TOOLKIT_DIR . '/echoscu');
42 | define('BIN_DCMJ2PNM', TOOLKIT_DIR . '/dcmj2pnm');
43 | define('BIN_DCMODIFY', TOOLKIT_DIR . '/dcmodify');
44 | define('BIN_DCMCJPEG', TOOLKIT_DIR . '/dcmdjpeg');
45 | define('BIN_DCMDJPEG', TOOLKIT_DIR . '/dcmcjpeg');
46 | define('BIN_XML2DCM', TOOLKIT_DIR . '/xml2dcm');
47 | define('BIN_IMG2DCM', TOOLKIT_DIR . '/img2dcm');
48 | }
49 |
50 | /*
51 | $d = new dicom_tag;
52 | $d->file = 'SOME_IMAGE.dcm';
53 | $d->load_tags();
54 | $name = $d->get_tag('0010', '0010');
55 | */
56 |
57 | class dicom_tag {
58 |
59 | var $tags = array();
60 | var $file = -1;
61 |
62 | function __construct($file = '') {
63 | $this->file = $file;
64 | if(file_exists($this->file)) {
65 | if(is_dcm($this->file)) {
66 | $this->load_tags();
67 | }
68 | }
69 | }
70 |
71 | ### LOAD DICOM TAGS FROM A FILE INTO AN ARRAY ($this->tags). $this->file is the filename of the image.
72 | function load_tags() {
73 | $file = $this->file;
74 | $dump_cmd = BIN_DCMDUMP . " -M +L +Qn $file";
75 | $dump = Execute($dump_cmd);
76 |
77 | if(!$dump) {
78 | return(0);
79 | }
80 |
81 | #print "$dump\n";
82 | #exit;
83 |
84 | $this->tags = array();
85 |
86 | foreach(explode("\n", $dump) as $line) {
87 |
88 | $ge = '';
89 |
90 | $t = preg_match_all("/\((.*)\) [A-Z][A-Z]/", $line, $matches);
91 | if(isset($matches[1][0])) {
92 | $ge = $matches[1][0];
93 | if(!isset($this->tags["$ge"])) {
94 | $this->tags["$ge"] = '';
95 | }
96 | }
97 |
98 | if(!$ge) {
99 | continue;
100 | }
101 |
102 | $val = '';
103 | $found = 0;
104 | $t = preg_match_all("/\[(.*)\]/", $line, $matches);
105 | if(isset($matches[1][0])) {
106 | $found = 1;
107 | $val = $matches[1][0];
108 |
109 | if(is_array($this->tags["$ge"])) { // Already an array
110 | $this->tags["$ge"][] = $val;
111 | }
112 | else { // Create new array
113 | $old_val = $this->tags["$ge"];
114 | if($old_val) {
115 | $this->tags["$ge"] = array();
116 | $this->tags["$ge"][] = $old_val;
117 | $this->tags["$ge"][] = $val;
118 | }
119 | else {
120 | $this->tags["$ge"] = $val;
121 | }
122 | }
123 | }
124 |
125 | if(is_array($this->tags["$ge"])) {
126 | $found = 1;
127 | }
128 |
129 | if(!$found) { // a couple of tags are not in [] preceded by =
130 | $t = preg_match_all("/\=(.*)\#/", $line, $matches);
131 | if(isset($matches[1][0])) {
132 | $found = 1;
133 | $val = $matches[1][0];
134 | $this->tags["$ge"] = rtrim($val);
135 | }
136 | }
137 |
138 | if(!$found) { // a couple of tags are not in []
139 | $t = preg_match_all("/[A-Z][A-Z] (.*)\#/", $line, $matches);
140 | if(isset($matches[1][0])) {
141 | $found = 1;
142 | $val = $matches[1][0];
143 | if(strstr($val, '(no value available)')) {
144 | $val = '';
145 | }
146 | $this->tags["$ge"] = rtrim($val);
147 | }
148 | }
149 | }
150 | }
151 |
152 | ### AFTER load_tags() HAS BEEN CALLED, USE THIS TO GET A SPECIFIC TAG
153 | function get_tag($group, $element) {
154 | $val = '';
155 | if(isset($this->tags["$group,$element"])) {
156 | $val = $this->tags["$group,$element"];
157 | }
158 | return($val);
159 | }
160 |
161 | ### WRITE TAGS INTO AN IMAGE, $tag_arr SHOULD LOOK LIKE:
162 | /*
163 | $tag_arr = array(
164 | '0010,0010' => 'VAUGHAN^DEAN',
165 | '0008,0080' => 'DEANLAND, AR'
166 | );
167 | */
168 | ### $this->file is the filename of the image.
169 | function write_tags($tag_arr) {
170 | if(!is_array($tag_arr)) {
171 | return(1);
172 | }
173 |
174 | $str = '';
175 | foreach($tag_arr as $group => $element) {
176 | $str .= "-i \"($group)=$element\" ";
177 | }
178 |
179 | $write_cmd = BIN_DCMODIFY . " $str " .
180 | "-nb \"" . $this->file . "\"";
181 | $out = Execute($write_cmd);
182 | if(!$out) {
183 | return(0);
184 | }
185 | else {
186 | return($out);
187 | }
188 | }
189 |
190 |
191 | }
192 |
193 | class dicom_convert {
194 |
195 | var $file = '';
196 | var $jpg_file = '';
197 | var $tn_file = '';
198 | var $jpg_quality = 100;
199 | var $tn_size = 125;
200 |
201 | function __construct($file = '') {
202 | $this->file = $file;
203 | }
204 |
205 | ### Convert a DICOM image to JPEG. $this->file is the filename of the image.
206 | ### $this->jpg_quality is an optional value (0-100) that'll set the quality of the JPEG produced
207 | function dcm_to_jpg() {
208 |
209 | $filesize = 0;
210 |
211 | $this->jpg_file = $this->file . '.jpg';
212 |
213 | $convert_cmd = BIN_DCMJ2PNM . " +oj +Jq " . $this->jpg_quality . " --use-window 1 \"" . $this->file . "\" \"" . $this->jpg_file . "\"";
214 | $out = Execute($convert_cmd);
215 |
216 | if(file_exists($this->jpg_file)) {
217 | $filesize = filesize($this->jpg_file);
218 | }
219 |
220 | if($filesize < 10) {
221 | $convert_cmd = BIN_DCMJ2PNM . " +Wm +oj +Jq " . $this->jpg_quality . " \"" . $this->file . "\" \"" . $this->jpg_file . "\"";
222 | $out = Execute($convert_cmd);
223 | }
224 |
225 | return($this->jpg_file);
226 |
227 | }
228 |
229 | ### Convert $this->file into a JPEG thumbnail.
230 | ### Optional $this->tn_size will let you change the width of the thumbnail produced
231 | function dcm_to_tn() {
232 | $filesize = 0;
233 | $this->tn_file = $this->file . '_tn.jpg';
234 |
235 | $convert_cmd = BIN_DCMJ2PNM . " +oj +Jq 75 +Sxv " . $this->tn_size . " --use-window 1 \"" . $this->file . "\" \"" . $this->tn_file . "\"";
236 | $out = Execute($convert_cmd);
237 |
238 | if(file_exists($this->tn_file)) {
239 | $filesize = filesize($this->tn_file);
240 | }
241 |
242 | if($filesize < 10) {
243 | $convert_cmd = BIN_DCMJ2PNM . " +Wm +oj +Jq 75 +Sxv " . $this->tn_size . " \"" . $this->file . "\" \"" . $this->tn_file . "\"";
244 | $out = Execute($convert_cmd);
245 | }
246 |
247 | return($this->tn_file);
248 | }
249 |
250 | ### This will uncompress $this->file.
251 | ### Optionally, you can give the output file a different name than the original by passing $new_file
252 | function uncompress($new_file = '') {
253 | if(!$new_file) {
254 | $new_file = $this->file;
255 | }
256 |
257 | $uncompress_cmd = BIN_DCMDJPEG . " \"" . $this->file . "\" \"" . $new_file . "\"";
258 | $out = Execute($uncompress_cmd);
259 | return($new_file);
260 | }
261 |
262 | // THIS REALLY SHOULD BE EXPANDED TO INCLUDE OTHER COMPRESSION OPTIONS
263 | ### This will JPEG losslessly compress $this->file
264 | ### Optionally, you can give the output file a different name than the original by passing $new_file
265 | function compress($new_file = '') {
266 | if(!$new_file) {
267 | $new_file = $this->file;
268 | }
269 |
270 | $uncompress_cmd = BIN_DCMCJPEG . " \"" . $this->file . "\" \"" . $new_file . "\"";
271 | $out = Execute($compress_cmd);
272 | return($new_file);
273 | }
274 |
275 | ### See examples/jpg_to_dcm.php for an example, it'll help things make sense.
276 | /*
277 | $this->jpg_file is the JPEG you plan on turning into a DICOM file.
278 |
279 | Make an array that maps the values to the tags you want your DICOM file to contain. Like this:
280 | $arr_info = array(
281 | '0010,0010' => 'VAUGHAN^DEAN', // Patient Name
282 | '0008,0080' => 'DEANLAND, AR' // Institution
283 | );
284 | You'll actually need to map more fields out to get a usable DICOM file. examples/jpg_to_dcm.php has an example of what's
285 | probably the minimum you need to keep most other DICOM software happy with the files you're producing.
286 |
287 | Point $this->template towards examples/jpg_to_dcm.xml You'll notice it's a shortened output of dcm2xml. I've put the tag
288 | name in () where I want the value to go.
289 |
290 | */
291 | function jpg_to_dcm($arr_info) {
292 |
293 | // USING THE DATA IN OUR ARRAY AND THE TEMPLATE, BUILD AN XML FILE FOR DCMTK
294 | $xml = file_get_contents($this->template);
295 | $temp_xml = $this->temp_dir . '/' . date('YmdGis') . rand(0, 30) . '.xml';
296 |
297 | foreach($arr_info as $tag => $value) {
298 | $xml = str_replace("($tag)", $value, $xml);
299 | }
300 |
301 | file_put_contents($temp_xml, $xml);
302 |
303 | // Make a DCM file using the XML we just made as the header info.
304 | $this->file = $this->jpg_file . '.dcm';
305 | $xml2dcm_cmd = BIN_XML2DCM . " $temp_xml " . $this->file;
306 | $out = Execute($xml2dcm_cmd);
307 | if($out) {
308 | return($out);
309 | }
310 | unlink($temp_xml); // NO LONGER NEEDED
311 |
312 | // Add the JPEG image to the DCM we just made
313 | $combine_cmd = BIN_IMG2DCM . " -df " . $this->file . " -stf " . $this->file . " -sef " . $this->file . " \"" . $this->jpg_file . "\" " . $this->file;
314 | $out = Execute($combine_cmd);
315 | if($out) {
316 | return($out);
317 | }
318 |
319 | return($this->file);
320 | }
321 |
322 | ### You will want to change $vid_cmd to be applicable to your system
323 | function multiframe_to_video($format = 'mp4', $framerate = 24, $temp_dir = "./video_temp") {
324 |
325 | $want = 7;
326 |
327 | $vid_file = basename($this->file) . ".$format";
328 |
329 | if(dirname($this->file) == '.') {
330 | $this->file = dirname(__FILE__) . '/' . $this->file;
331 | }
332 |
333 | if (!file_exists($temp_dir)) {
334 | mkdir($temp_dir, 0777);
335 | }
336 |
337 | # Split each frame into a jpeg
338 | $curr_dir = getcwd();
339 | chdir($temp_dir);
340 | $split_cmd = BIN_DCMJ2PNM . " +Fa +oj +Jq 100 \"" . $this->file . "\" frame";
341 | $out = Execute($split_cmd);
342 |
343 | if($out) {
344 | return("$split_cmd: $out");
345 | }
346 |
347 | ## rename our jpegs into something suited for ffmpeg (001, 002, 003, ect)
348 | $x = 0;
349 |
350 | if ($handle = opendir('.')) {
351 | while (false !== ($file = readdir($handle))) {
352 | if ($file == '.' || $file == '..') {
353 | continue;
354 | }
355 | if (!strstr($file, '.jpg')) {
356 | continue;
357 | }
358 |
359 | $new_name = str_replace('frame.', '', $file);
360 | $l = strlen($new_name);
361 | $diff = $want - $l;
362 | while ($diff) {
363 | $new_name = "0$new_name";
364 | $diff--;
365 | }
366 | if ($file != $new_name) {
367 | rename($file, $new_name);
368 | }
369 | $x++;
370 | }
371 | closedir($handle);
372 | }
373 |
374 | if ($x < 10) {
375 | $framerate = 10;
376 | }
377 |
378 | if(file_exists($vid_file)) {
379 | unlink($vid_file);
380 | }
381 |
382 | $vid_cmd = "ffmpeg -r $framerate -b 5000k -i %03d.jpg -vcodec libx264 \"$vid_file\"";
383 | $out = Execute($vid_cmd);
384 |
385 | /* This is a special case, probably only useful to me.
386 | if(strstr($out, 'height not divisible by 2')) {
387 | print "Running height fix\n";
388 | unlink($vid_file);
389 | $out = Execute("mogrify -resize 992x504 *.jpg");
390 | $vid_cmd = "/usr/local/bin/ffmpeg -r $framerate -b 5000k -i %03d.jpg -vcodec libx264 $vid_file";
391 | $out = Execute($vid_cmd);
392 | }
393 | */
394 |
395 | chdir($curr_dir);
396 |
397 | return ("$temp_dir/$vid_file");
398 | }
399 |
400 | ### SOME DAY...
401 | function pdf_to_dcm($arr_info) {
402 |
403 | }
404 |
405 | function pdf_to_dcmcr($arr_info) {
406 |
407 | }
408 |
409 | }
410 |
411 |
412 | class dicom_net {
413 |
414 | var $transfer_syntax = '';
415 | var $file = '';
416 |
417 | ### $port is the tcp port to listen on
418 | ### $dcm_dir is where the DICOM files go after being received.
419 | ### $handler_script is a program that will be ran after each DICOM file is received. The DICOM image's filename, $dcm_dir,
420 | ### and the AE titles will be passed via the command line
421 | ### $config_file is the storescp config file. man storescp will get you a run down. The file provided in
422 | ### examples/store_server_config.cfg will work with all of the common ways of doing things
423 | function store_server($port, $dcm_dir, $handler_script, $config_file, $debug = 0) {
424 | $dflag = '';
425 | if($debug) {
426 | $dflag = '-v -d ';
427 | }
428 |
429 | system(BIN_STORESCP . " $dflag -dhl -td 20 -ta 20 --fork -xf $config_file Default -od $dcm_dir -xcr \"$handler_script \"#p\" \"#f\" \"#c\" \"#a\"\" $port");
430 | }
431 |
432 | ### Performs an echoscu (DICOM ping) on $host $port
433 | function echoscu($host, $port, $my_ae = 'DEANO', $remote_ae = 'DEANO') {
434 | $ping_cmd = BIN_ECHOSCU . " -ta 5 -td 5 -to 5 -aet \"$my_ae\" -aec \"$remote_ae\" $host $port";
435 | $out = Execute($ping_cmd);
436 | if(!$out) {
437 | return(0);
438 | }
439 | return($out);
440 | }
441 |
442 | ### Sends $this_file to $host $port.
443 | ### If $send_batch is enabled it'll send all of the files in the same directory as $this->file in one association
444 | function send_dcm($host, $port, $my_ae = 'DEANO', $remote_ae = 'DEANO', $send_batch = 0) {
445 |
446 | if(!$this->transfer_syntax) {
447 | $tags = new dicom_tag;
448 | $tags->file = $this->file;
449 | $tags->load_tags();
450 | $this->transfer_syntax = $tags->get_tag('0002', '0010');
451 | }
452 |
453 | $ts_flag = '';
454 | switch($this->transfer_syntax) {
455 | case 'JPEGBaseline':
456 | $ts_flag = '-xy';
457 | break;
458 | case 'JPEGExtended:Process2+4':
459 | $ts_flag = '-xx';
460 | break;
461 | case 'JPEGLossless:Non-hierarchical-1stOrderPrediction':
462 | $ts_flag = '-xs';
463 | break;
464 | }
465 |
466 | $to_send = $this->file;
467 |
468 | if($send_batch) {
469 | $to_send = dirname($this->file);
470 | $send_command = BIN_STORESCU . " -ta 10 -td 10 -to 10 $ts_flag -aet \"$my_ae\" -aec $remote_ae $host $port +sd \"$to_send\"";
471 | }
472 | else {
473 | $send_command = BIN_STORESCU . " -ta 10 -td 10 -to 10 $ts_flag -aet \"$my_ae\" -aec $remote_ae $host $port \"$to_send\"";
474 | }
475 |
476 | $out = Execute($send_command);
477 | if($out) {
478 | return($out);
479 | }
480 | return(0);
481 |
482 | }
483 |
484 | }
485 |
486 | ### CAPTURES ALL OF THE GOOD OUTPUTS!
487 | function Execute($command) {
488 |
489 | $command .= ' 2>&1';
490 | $handle = popen($command, 'r');
491 | $log = '';
492 |
493 | while (!feof($handle)) {
494 | $line = fread($handle, 1024);
495 | $log .= $line;
496 | }
497 | pclose($handle);
498 |
499 | return $log;
500 | }
501 |
502 | ### I'm keeping this outside of the class so it is easier to get to. This may change in the future.
503 | function is_dcm($file) {
504 | $dump_cmd = BIN_DCMDUMP . " -M +L +Qn $file";
505 | $dump = Execute($dump_cmd);
506 |
507 | if(strstr($dump, 'error')) {
508 | return(0);
509 | }
510 | else if(strstr($dump, 'Modality')) {
511 | return(1);
512 | }
513 |
514 | return(0);
515 | }
516 |
517 |
518 |
519 | ?>
520 |
--------------------------------------------------------------------------------