Skip to content

Commit 4bd0e5c

Browse files
authored
Merge pull request #50 from jcupitt/update-to-v0.2
Update to v0.2
2 parents 92f731d + 0b4b8f3 commit 4bd0e5c

File tree

13 files changed

+7529
-9046
lines changed

13 files changed

+7529
-9046
lines changed

TODO

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,24 @@
11
# TODO
22

3+
- need to be able to set a stop-at function on filehandles
4+
5+
36
# bot support
47

58
- need more tests and test images
69

710
- extended offset table support seems to be broken? see FIXME comment
811

9-
- bot frame offsets should be int64_t to match dcm_seekset(),
10-
pixel_data_offset, etc.
11-
12-
13-
# less copy-paste
12+
probably will never be used
1413

15-
- replace copy-paste code over types with a table
16-
dcm_element_clone()
14+
- a fast scanner to find the BOT table
1715

18-
- use a table for dcm_element_create_* as well
19-
20-
21-
# more enums
22-
23-
- element->vr should be an enum (not "UL" etc.)
24-
- swap all the strcmps for ==
25-
26-
- benchmark against the original
2716

2817
# data types
2918

19+
- bot frame offsets should be int64_t to match dcm_seekset(),
20+
pixel_data_offset, etc.
21+
3022
- should create_element() take a size_t for length?
3123

3224
- remove dcm_dataset_copy_tags() etc should not use uint32_t? what about
@@ -38,16 +30,6 @@
3830

3931
no, it's unsigned int
4032

41-
- dcm_dataset_print() should not use uint8_t
42-
43-
44-
# revise pointer ownership rules
45-
46-
- right now, _create funcs free passed in objects on error which feels very
47-
error-prone
48-
49-
instead, the caller should free on error ... how easy would this be to change?
50-
5133

5234
# asserts
5335

@@ -76,3 +58,8 @@
7658
- debug failing test with eg.
7759

7860
CK_FORK=no CK_RUN_CASE=frame gdb ./check_dicom
61+
62+
- leak check
63+
64+
CK_FORK=no valgrind --leak-check=full ./check_dicom
65+

doc/source/usage.rst

Lines changed: 93 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,22 @@
11
Usage
22
-----
33

4-
Memory management
5-
+++++++++++++++++
6-
7-
Each data structure (Data Element, Data Set, Sequence, Frame Item, etc.) takes
8-
over ownership of allocated memory for passed arguments upon object creation
9-
(``*_create()`` functions) and deallocates the memory upon object destruction
10-
(``*_destroy()`` functions). Note that if the creation of a data structure
11-
fails, the memory of the passed arguments will also be freed.
12-
13-
144
API overview
155
++++++++++++
166

177
A `Data Element
188
<http://dicom.nema.org/medical/dicom/current/output/chtml/part05/chapter_3.html#glossentry_DataElement>`_
199
(:c:type:`DcmElement`) is an immutable data container for
20-
storing values. Every Data Element has a `Value Representation (VR)
10+
storing values.
11+
12+
Every data element has a tag indicating its purpose. Tags are 32-bit
13+
unsigned ints with the top 16 bits indicating the group and the bottom 16 the
14+
element. They are usually written in hexadecimal, perhaps 0x00400554, meaning
15+
element 0x554 of group 0x40, or as keywords, in this case `SpecimenUID`. You
16+
can get the tag from its corresponding keyword with :c:func:`dcm_dict_tag_from_keyword()`,
17+
or find the keyword from a tag with :c:func:`dcm_dict_keyword_from_tag()`.
18+
19+
Every Data Element has a `Value Representation (VR)
2120
<http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_6.2.html>`_,
2221
which specifies the data type and format of the contained value. VRs can
2322
be conceptually grouped into numbers (integers or floating-point values),
@@ -26,17 +25,27 @@ or scientific notation), character strings (text of restriction length and
2625
character repertoire), or byte strings (unicode). Each VR is represented
2726
using a standard C type (e.g,. VR ``"US"`` has type ``uint16_t`` and VR
2827
``"UI"`` has type ``char *``) and additional value constraints may be checked
29-
at runtime (e.g., the maximal capacity of a character string). Depending
30-
on the VR, an individual Data Element may have a `Value Multiplicity (VM)
28+
at runtime (e.g., the maximal capacity of a character string).
29+
30+
The VR must be appropriate for the tag. Use :c:func:`dcm_vr_from_tag()` to
31+
find the set of allowed VRs for a tag. Use :c:func:`dcm_is_valid_vr_for_tag()`
32+
to check if a VR is allowed for a tag.
33+
34+
Depending on the VR, an individual Data
35+
Element may have a `Value Multiplicity (VM)
3136
<http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_6.4.html>`_
32-
greater than one, i.e., contain more than one value. Under the
33-
hood, a Data Element thus generally contains an array of values.
34-
A Data Element can be created via the VR-specific constructor
35-
function (e.g., :c:func:`dcm_element_create_UI()`) and destroyed
36-
via :c:func:`dcm_element_destroy()`. Upon creation, the Data Element
37-
takes over ownership of the memory allocated for the contained values.
38-
An individual value can be retrieved via the VR-specific getter function
39-
(e.g., :c:func:`dcm_element_get_value_UI()`). Note that in case of character
37+
greater than one, i.e., contain more than one value. Under the hood,
38+
a Data Element may thus contain an array of values.
39+
40+
A Data Element can be created with :c:func:`dcm_element_create()`, it can have
41+
a value assigned to it with eg.
42+
:c:func:`dcm_element_set_value_integer()`, and it can be destroyed with
43+
:c:func:`dcm_element_destroy()`. See `Memory management <Memory Management_>`_ below for details on
44+
pointer ownership.
45+
46+
An individual value can be retrieved via the getter functions like
47+
(e.g., :c:func:`dcm_element_get_value_integer()`). Note that in case of
48+
character
4049
string or binary values, the getter function returns the pointer to the
4150
stored character array (``const char *``) and that pointer is only valid
4251
for the lifetime of the Data Element. When a Data Element is destroyed,
@@ -51,17 +60,20 @@ created via :c:func:`dcm_dataset_create()` and destroyed via
5160
:c:func:`dcm_dataset_destroy()`. Data Elements can be added to a
5261
Data Set via :c:func:`dcm_dataset_insert()`, removed from a Data Set
5362
via :c:func:`dcm_dataset_remove()`, and retrieved from a Data Set via
54-
:c:func:`dcm_dataset_get()` or :c:func:`dcm_dataset_get_clone()`. When a
55-
Data Element is added to a Data Set, the Data Set takes over ownership
63+
:c:func:`dcm_dataset_get()` or :c:func:`dcm_dataset_get_clone()`.
64+
65+
When a Data Element is added to a Data Set, the Data Set takes over ownership
5666
of the memory allocated for contained Data Elements. When a Data Element
5767
is retrieved from a Data Set, it may either be borrowed with ownership of
5868
the memory allocated for the Data Element remaining with the Data Set in
5969
case of :c:func:`dcm_dataset_get()` or copied with the caller taking on
6070
ownership of the memory newly allocated for the Data Element in case of
61-
:c:func:`dcm_dataset_get_clone()`. Furthermore, an individual Data Element
62-
can only be part of only one Data Set. When a Data Element is removed from a
63-
Data Set, the memory allocated for the Data Element is freed. When a Data Set
64-
is destroyed, all contained Data Elements are also automatically destroyed.
71+
:c:func:`dcm_dataset_get_clone()`.
72+
73+
An individual Data Element can only be part of only one Data Set. When a
74+
Data Element is removed from a Data Set, the memory allocated for the Data
75+
Element is freed. When a Data Set is destroyed, all contained Data Elements
76+
are also automatically destroyed.
6577

6678
A `Sequence
6779
<http://dicom.nema.org/medical/dicom/current/output/chtml/part05/chapter_3.html#glossentry_SequenceOfItems>`_
@@ -72,22 +84,27 @@ via :c:func:`dcm_sequence_create()` and destroyed via
7284
:c:func:`dcm_sequence_destroy()`. Data Sets can be added to a Sequence
7385
via :c:func:`dcm_sequence_append()`, removed from a Sequence via
7486
:c:func:`dcm_sequence_remove()`, and retrieved from a Sequence via
75-
:c:func:`dcm_sequence_get()`. When a Data Set is added to a sequence,
76-
the sequence takes over ownership of the memory allocated for the Data Set
77-
(and consequently of each contained Data Element). When a Data Set is
78-
retrieved from a sequence, it is only borrowed and ownership of the memory
79-
allocated for the Data Set remains with the sequence. Retrieved Data Sets
80-
are immutable (locked). When a Data Set is removed from a sequence, the
81-
Data Set is destroyed (i.e., the allocated memory is freed). When a Sequence
82-
is destroyed, all contained Data Sets are also automatically destroyed.
87+
:c:func:`dcm_sequence_get()`.
88+
89+
When a Data Set is added to a sequence, the sequence takes over ownership of
90+
the memory allocated for the Data Set (and consequently of each contained
91+
Data Element). When a Data Set is retrieved from a sequence, it is only
92+
borrowed and ownership of the memory allocated for the Data Set remains
93+
with the sequence. Retrieved Data Sets are immutable (locked). When a
94+
Data Set is removed from a sequence, the Data Set is destroyed (i.e., the
95+
allocated memory is freed). When a Sequence is destroyed, all contained
96+
Data Sets are also automatically destroyed.
8397

8498
A Filehandle (:c:type:`DcmFilehandle`) enables access of a `DICOM file
8599
<http://dicom.nema.org/medical/dicom/current/output/chtml/part10/chapter_3.html#glossentry_DICOMFile>`_,
86100
which contains an encoded Data Set representing a SOP Instance.
87101
A Filehandle can be created via :c:func:`dcm_filehandle_create_from_file()`
88-
and destroyed via :c:func:`dcm_filehandle_destroy()`, which open a
89-
Part10 file stored on disk and closes it, respectively. The content of
90-
a Part10 file can be read using various functions. The `File Meta Information
102+
or :c:func:`dcm_filehandle_create_from_memory()` , and destroyed via
103+
:c:func:`dcm_filehandle_destroy()`. You can make your own load functions
104+
to load from other IO sources, see :c:func:`dcm_filehandle_create()`.
105+
106+
The content of a Part10 file can be read
107+
using various functions. The `File Meta Information
91108
<http://dicom.nema.org/medical/dicom/current/output/chtml/part10/chapter_3.html#glossentry_FileMetaInformation>`_
92109
can be read via :c:func:`dcm_filehandle_read_file_meta()`. The metadata
93110
of the Data Set (i.e., all Data Elements with the exception of the Pixel
@@ -159,13 +176,44 @@ For example:
159176
return 0;
160177
}
161178
162-
Load from memory
163-
++++++++++++++++
179+
Memory management
180+
+++++++++++++++++
164181

165-
As well as :c:func:`dcm_filehandle_create_from_file()`, there's
166-
:c:func:`dcm_filehandle_create_from_memory()` to make a DcmFilehandle from
167-
a memory area containing a DICOM image. You can make your own load functions
168-
to load from other IO sources, see :c:func:`dcm_filehandle_create()`.
182+
libdicom objects (Data Element, Data Set, Sequence, Frame Item, etc.) can
183+
contain references to other libdicom objects. For example, you can set a
184+
sequence as the value of an element like this:
185+
186+
.. code-block:: c
187+
188+
if (!dcm_element_set_value_sequence(error, element, sequence)) {
189+
handle error;
190+
}
191+
192+
If this function succeeeds, ownership of the sequence object passes to the
193+
element, i.e., when the element is destroyed, the sequence will also be
194+
destroyed.
195+
196+
If this function fails, ownership does not transfer.
197+
198+
libdicom objects can also contain references to data structures allocated by
199+
other programs, for example, arrays of numeric values.
200+
201+
.. code-block:: c
202+
203+
int *values = pointer to array of integers;
204+
uint32_t vm = number of ints in array;
205+
if( !dcm_element_set_value_numeric_multi(error,
206+
element,
207+
values,
208+
vm,
209+
true)) {
210+
handle error;
211+
}
212+
213+
The final parameter, `steal` sets whether ownership of the pointer to the
214+
array should be "stolen" by libdicom. If it is true, then libdicom will use
215+
:c:func:`free()` to free the array when the element is freed. If it is false,
216+
libdiom will take a copy of the array.
169217

170218
Getting started
171219
+++++++++++++++
@@ -196,6 +244,7 @@ printing it to standard output:
196244
dcm_filehandle_destroy(filehandle);
197245
return 1;
198246
}
247+
199248
dcm_dataset_print(metadata, 0);
200249
201250
dcm_filehandle_destroy(filehandle);

0 commit comments

Comments
 (0)