1 /*
2 *
3 * Copyright (C) 2013-2020, OFFIS e.V.
4 * All rights reserved. See COPYRIGHT file for details.
5 *
6 * This software and supporting documentation were developed by
7 *
8 * OFFIS e.V.
9 * R&D Division Health
10 * Escherweg 2
11 * D-26121 Oldenburg, Germany
12 *
13 *
14 * Module: dcmdata
15 *
16 * Author: Joerg Riesmeier
17 *
18 * Purpose: Implementation of class DcmOtherDouble
19 *
20 */
21
22
23 #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
24
25 #include "dcmtk/ofstd/ofuuid.h"
26 #include "dcmtk/ofstd/ofstd.h"
27
28 #include "dcmtk/dcmdata/dcvrod.h"
29 #include "dcmtk/dcmdata/dcswap.h"
30 #include "dcmtk/dcmdata/dcjson.h"
31
32
33 // ********************************
34
35
DcmOtherDouble(const DcmTag & tag,const Uint32 len)36 DcmOtherDouble::DcmOtherDouble(const DcmTag &tag,
37 const Uint32 len)
38 : DcmFloatingPointDouble(tag, len)
39 {
40 }
41
42
DcmOtherDouble(const DcmOtherDouble & old)43 DcmOtherDouble::DcmOtherDouble(const DcmOtherDouble &old)
44 : DcmFloatingPointDouble(old)
45 {
46 }
47
48
~DcmOtherDouble()49 DcmOtherDouble::~DcmOtherDouble()
50 {
51 }
52
53
operator =(const DcmOtherDouble & obj)54 DcmOtherDouble &DcmOtherDouble::operator=(const DcmOtherDouble &obj)
55 {
56 DcmFloatingPointDouble::operator=(obj);
57 return *this;
58 }
59
60
copyFrom(const DcmObject & rhs)61 OFCondition DcmOtherDouble::copyFrom(const DcmObject& rhs)
62 {
63 if (this != &rhs)
64 {
65 if (rhs.ident() != ident()) return EC_IllegalCall;
66 *this = OFstatic_cast(const DcmOtherDouble &, rhs);
67 }
68 return EC_Normal;
69 }
70
71
72 // ********************************
73
74
ident() const75 DcmEVR DcmOtherDouble::ident() const
76 {
77 return EVR_OD;
78 }
79
80
checkValue(const OFString &,const OFBool)81 OFCondition DcmOtherDouble::checkValue(const OFString & /*vm*/,
82 const OFBool /*oldFormat*/)
83 {
84 /* currently no checks are performed */
85 return EC_Normal;
86 }
87
88
getVM()89 unsigned long DcmOtherDouble::getVM()
90 {
91 /* value multiplicity for OD is defined as 1 */
92 return 1;
93 }
94
95
96 // ********************************
97
98
writeXML(STD_NAMESPACE ostream & out,const size_t flags)99 OFCondition DcmOtherDouble::writeXML(STD_NAMESPACE ostream &out,
100 const size_t flags)
101 {
102 /* always write XML start tag */
103 writeXMLStartTag(out, flags);
104 /* OD data requires special handling in the Native DICOM Model format */
105 if (flags & DCMTypes::XF_useNativeModel)
106 {
107 /* for an empty value field, we do not need to do anything */
108 if (getLengthField() > 0)
109 {
110 /* encode binary data as Base64 */
111 if (flags & DCMTypes::XF_encodeBase64)
112 {
113 out << "<InlineBinary>";
114 Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue());
115 /* Base64 encoder requires big endian input data */
116 swapIfNecessary(EBO_BigEndian, gLocalByteOrder, byteValues, getLengthField(), sizeof(Float64));
117 /* update the byte order indicator variable correspondingly */
118 setByteOrder(EBO_BigEndian);
119 OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField()));
120 out << "</InlineBinary>" << OFendl;
121 } else {
122 /* generate a new UID but the binary data is not (yet) written. */
123 OFUUID uuid;
124 out << "<BulkData uuid=\"";
125 uuid.print(out, OFUUID::ER_RepresentationHex);
126 out << "\"/>" << OFendl;
127 }
128 }
129 } else {
130 /* write element value (if loaded) */
131 if (valueLoaded())
132 {
133 Float64 *floatValues = NULL;
134 /* get and check 64 bit float data */
135 if (getFloat64Array(floatValues).good() && (floatValues != NULL))
136 {
137 const size_t count = getNumberOfValues();
138 /* count can be zero if we have an invalid element with less than eight bytes length */
139 if (count > 0)
140 {
141 /* increase default precision - see DcmFloatingPointDouble::print() */
142 const STD_NAMESPACE streamsize oldPrecision = out.precision(17);
143 /* print float values with separators */
144 out << (*(floatValues++));
145 for (unsigned long i = 1; i < count; i++)
146 out << "\\" << (*(floatValues++));
147 /* reset i/o manipulators */
148 out.precision(oldPrecision);
149 }
150 }
151 }
152 }
153 /* always write XML end tag */
154 writeXMLEndTag(out, flags);
155 /* always report success */
156 return EC_Normal;
157 }
158
159
160 // ********************************
161
162
writeJson(STD_NAMESPACE ostream & out,DcmJsonFormat & format)163 OFCondition DcmOtherDouble::writeJson(STD_NAMESPACE ostream &out,
164 DcmJsonFormat &format)
165 {
166 /* always write JSON Opener */
167 writeJsonOpener(out, format);
168 /* for an empty value field, we do not need to do anything */
169 if (getLengthField() > 0)
170 {
171 OFString value;
172 if (format.asBulkDataURI(getTag(), value))
173 {
174 /* return defined BulkDataURI */
175 format.printBulkDataURIPrefix(out);
176 DcmJsonFormat::printString(out, value);
177 }
178 else
179 {
180 /* encode binary data as Base64 */
181 format.printInlineBinaryPrefix(out);
182 out << "\"";
183 /* adjust byte order to little endian */
184 Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
185 OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField()));
186 out << "\"";
187 }
188 }
189 /* write JSON Closer */
190 writeJsonCloser(out, format);
191 /* always report success */
192 return EC_Normal;
193 }
194
195
196 // ********************************
197
198
createFloat64Array(const Uint32 numDoubles,Float64 * & doubleVals)199 OFCondition DcmOtherDouble::createFloat64Array(const Uint32 numDoubles,
200 Float64 *&doubleVals)
201 {
202 Uint32 bytesRequired = 0;
203 /* make sure that max length is not exceeded */
204 if (OFStandard::safeMult(numDoubles, OFstatic_cast(Uint32, sizeof(Float64)), bytesRequired))
205 errorFlag = createEmptyValue(bytesRequired);
206 else
207 errorFlag = EC_ElemLengthExceeds32BitField;
208 if (errorFlag.good())
209 doubleVals = OFstatic_cast(Float64 *, this->getValue());
210 else
211 doubleVals = NULL;
212 return errorFlag;
213 }
214