File Coverage

blib/lib/DicomPack/IO/CommonUtil.pm
Criterion Covered Total %
statement 18 128 14.0
branch 0 54 0.0
condition 0 15 0.0
subroutine 6 14 42.8
pod n/a
total 24 211 11.3


line stmt bran cond sub pod time code
1             ##############################################################################
2             # CommonUtil.pm -- a module including common functions for internal use
3             #
4             # Copyright (c) 2010 Baoshe Zhang. All rights reserved.
5             # This file is part of "DicomPack". DicomPack is free software;
6             # you can redistribute it and/or modify it under the same
7             # terms as Perl itself.
8             ##############################################################################
9              
10             package DicomPack::IO::CommonUtil;
11              
12 1     1   5 use strict;
  1         1  
  1         27  
13 1     1   4 use warnings;
  1         1  
  1         22  
14              
15 1     1   2514 use DicomPack::DB::DicomTagDict qw/getTagDesc getTagID/;
  1         7  
  1         674  
16 1     1   18 use DicomPack::DB::DicomVRDict qw/getVR/;
  1         2  
  1         57  
17              
18 1     1   8 use vars qw(@ISA @EXPORT_OK);
  1         2  
  1         63  
19 1     1   5 use Exporter;
  1         2  
  1         1607  
20             @ISA = qw/Exporter/;
21             @EXPORT_OK = qw/_getEndian _pack _unpack _isLittleEndian _toString _getDicomValue _showDicomField _parseDicomFieldPath/;
22              
23             # get the endianness of current system. ">" for big endiannes, "<" for little endianness.
24             sub _getEndian
25             {
26 0     0     return ">" if pack("L", 1) eq pack("N", 1);
27 0           return "<";
28             }
29              
30             # a repalcement for pack function. The versions of perl prior to 5.10.0 do not support ">" and "<".
31             sub _pack
32             {
33 0     0     my ($dataType, $endianness, $data) = @_;
34              
35 0 0 0       if(eval("require 5.0100") or $endianness eq "")
36             {
37 0           return pack($dataType.$endianness."*", @$data);
38             }
39              
40 0 0         if($dataType !~ /^[sSiIlLqQjJfFdDpP]$/)
41             {
42 0           die "DataType: $dataType, not supporte!!!\n";
43             }
44              
45 0 0         if(ref($data) ne "ARRAY")
46             {
47 0           die "Data should be an ARRAY Ref!!!\n";
48             }
49              
50 0 0         if(_getEndian() eq $endianness)
51             {
52 0           return pack($dataType."*", @$data);
53             }
54             else
55             {
56 0           my $data_t = "";
57 0           foreach my $iData (@$data)
58             {
59 0           my $iData_t = pack "C*", reverse unpack("C*", pack($dataType, $iData));
60 0           $data_t .= $iData_t;
61             }
62 0           return $data_t;
63             }
64             }
65              
66             # A replacement for unpack. The versions of perl prior to 5.10.0 do not support ">" and "<".
67             sub _unpack
68             {
69 0     0     my ($dataType, $endianness, $data) = @_;
70              
71 0 0 0       if(eval("require 5.0100") or $endianness eq "")
72             {
73 0           return unpack($dataType.$endianness."*", $data);
74             }
75              
76 0 0         if($dataType !~ /^[sSiIlLqQjJfFdDpP]$/)
77             {
78 0           die "DataType: $dataType, not supporte!!!\n";
79             }
80              
81 0 0         if(_getEndian() eq $endianness)
82             {
83 0           return unpack($dataType."*", $data);
84             }
85             else # little endianness
86             {
87 0           my @data_t;
88 0           foreach my $iData (unpack($dataType."*", $data))
89             {
90 0           my $iData_t = unpack($dataType, pack("C*", reverse unpack("C*", pack($dataType, $iData))));
91 0           push @data_t, $iData_t;
92             }
93 0           return @data_t;
94             }
95             }
96              
97             # check the endianness of a dicom file according to "0002,0010" of meta info
98             sub _isLittleEndian
99             {
100 0     0     my $dicomFields = shift;
101 0           my $isLittleEndian = 1;
102 0 0         if(defined $dicomFields)
103             {
104 0 0         if(defined $dicomFields->{"0002,0010"})
105             {
106 0           my ($tt_t, $vv_t) = _getDicomValue($dicomFields->{"0002,0010"});
107 0           my $transferSyntax = $vv_t->[0];
108 0 0         if($transferSyntax eq "1.2.840.10008.1.2.2")
109             {
110 0           $isLittleEndian = 0;
111             }
112             }
113             }
114 0           return $isLittleEndian;
115             }
116              
117             # convert a composite dicom value to a string
118             sub _toString
119             {
120 0     0     my $dicomValue = shift;
121 0           my $isLittleEndian = shift;
122 0           my $verbose = shift;
123 0           my $indent = shift;
124              
125 0           my ($vr, $value) = _getDicomValue($dicomValue, $isLittleEndian);
126              
127 0           my $valueStr = "";
128              
129 0 0         if($verbose <= 1)
130             {
131 0           my $nPrint = scalar @$value;
132 0 0         if($nPrint > 15)
133             {
134 0           $nPrint = 15;
135             }
136 0           for(my $i=0; $i<$nPrint; $i++)
137             {
138 0           my $t = $value->[$i];
139 0           $valueStr .= $t.' ';
140             }
141 0 0         if($nPrint < scalar @$value)
142             {
143 0           $valueStr .= "...\n";
144             }
145              
146 0 0         if(length($valueStr) > 255)
147             {
148 0           $valueStr = substr($valueStr, 0, 255);
149 0           $valueStr .= "...\n";
150             }
151             }
152             else
153             {
154 0           for(my $i=0; $i
155             {
156 0           my $t = $value->[$i];
157 0           $valueStr .= $t.' ';
158 0 0         if(($i+1)%16 == 0)
159             {
160 0           $valueStr .= "\n"." ".$indent;
161             }
162             }
163             }
164              
165 0           return $vr.":".$valueStr;
166             }
167              
168             # process a composite dicom value
169             sub _getDicomValue
170             {
171 0     0     my $dicomValue = shift;
172 0           my $isLittleEndian = shift;
173              
174 0           my $vr = substr($dicomValue, 0, 2);
175 0           my $value = substr($dicomValue, 3);
176              
177 0           my @t_data;
178              
179 0           my $vrItem = getVR($vr);
180 0 0         if(defined $vrItem->{tailing})
181             {
182 0           $value =~ s/($vrItem->{tailing})+$//;
183             }
184 0 0         if(defined $vrItem->{leading})
185             {
186 0           $value =~ s/^($vrItem->{leading})+//;
187             }
188              
189 0 0         if(defined $vrItem->{type})
    0          
190             {
191 0           my $endianness = "<";
192 0 0         $endianness = ">" unless $isLittleEndian;
193 0 0 0       if($vrItem->{type} eq "C" or $vrItem->{type} eq "c")
194             {
195 0           $endianness = "";
196             }
197             #@t_data = unpack($vrItem->{type}.$endianness."*", $value);
198 0           @t_data = _unpack($vrItem->{type}, $endianness, $value);
199             }
200             elsif (defined $vrItem->{delimiter})
201             {
202 0           @t_data = split quotemeta($vrItem->{delimiter}), $value;
203             }
204             else
205             {
206 0           @t_data = $value;
207             }
208              
209 0           return ($vr, \@t_data);
210             }
211              
212             # show dicom file's structure and field data (recursive)
213             sub _showDicomField
214             {
215 0     0     my $dicomFields = shift;
216 0           my $depth = shift;
217 0           my $verbose = shift;
218              
219 0           my $isLittleEndian = shift;
220              
221 0           my $tagID = shift;
222              
223 0           my $indent = " " x (4*$depth);
224              
225 0 0         if(ref($dicomFields) eq "HASH")
    0          
226             {
227 0           foreach my $field_t (sort keys %$dicomFields)
228             {
229 0           my $desc = getTagDesc($field_t);
230 0           print $indent."$field_t"." [".$desc."]"."->\n";
231 0           _showDicomField($dicomFields->{$field_t}, $depth+1, $verbose, $isLittleEndian, $field_t);
232             }
233             }
234             elsif(ref($dicomFields) eq "ARRAY")
235             {
236 0           for(my $index=0; $index < scalar @$dicomFields; $index++)
237             {
238 0           print $indent."$index->\n";
239 0           _showDicomField($dicomFields->[$index], $depth+1, $verbose, $isLittleEndian);
240             }
241             }
242             else
243             {
244 0 0         if($verbose >= 1)
245             {
246 0 0 0       if(defined $tagID and $tagID =~ /^0002,/)
247             {
248 0           print $indent._toString($dicomFields, 1, $verbose, $indent), "\n";
249             }
250             else
251             {
252 0           print $indent._toString($dicomFields, $isLittleEndian, $verbose, $indent), "\n";
253             }
254             }
255             }
256             }
257              
258             sub _parseDicomFieldPath
259             {
260 0     0     my $fieldPath = shift;
261              
262 0           $fieldPath =~ s/^\s*\/*//;
263 0           $fieldPath =~ s/\/*\s*$//;
264 0           my @fieldID = split /\//, $fieldPath;
265              
266 0           my @tagIDList;
267              
268 0           my $nFields = scalar @fieldID;
269 0           for(my $i=0; $i<$nFields; $i++)
270             {
271 0           my $tagID = $fieldID[$i];
272              
273 0 0 0       $tagID = getTagID($tagID) if ($tagID !~ /^\d+$/ and $tagID ne "x");
274              
275 0 0         die "Tag: $fieldID[$i], not exists!!!" unless defined $tagID;
276              
277 0           push @tagIDList, $tagID;
278             }
279 0           return @tagIDList;
280             }
281              
282             1;
283