/src/dcmtk/dcmimgle/libsrc/diluptab.cc
Line | Count | Source |
1 | | /* |
2 | | * |
3 | | * Copyright (C) 1996-2026, 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: dcmimgle |
15 | | * |
16 | | * Author: Joerg Riesmeier |
17 | | * |
18 | | * Purpose: DicomLookupTable (Source) |
19 | | * |
20 | | */ |
21 | | |
22 | | |
23 | | #include "dcmtk/config/osconfig.h" |
24 | | #include "dcmtk/dcmdata/dcdeftag.h" |
25 | | #include "dcmtk/dcmdata/dcsequen.h" |
26 | | #include "dcmtk/dcmdata/dcitem.h" |
27 | | #include "dcmtk/dcmdata/dcvrobow.h" |
28 | | #include "dcmtk/dcmdata/dcvrus.h" |
29 | | |
30 | | #include "dcmtk/dcmimgle/dibaslut.h" |
31 | | #include "dcmtk/dcmimgle/diutils.h" |
32 | | #include "dcmtk/ofstd/ofbmanip.h" |
33 | | #include "dcmtk/ofstd/ofcast.h" |
34 | | |
35 | | #include "dcmtk/dcmimgle/diluptab.h" |
36 | | #include "dcmtk/dcmimgle/didocu.h" |
37 | | |
38 | | |
39 | | /*----------------* |
40 | | * constructors * |
41 | | *----------------*/ |
42 | | |
43 | | DiLookupTable::DiLookupTable(const DiDocument *docu, |
44 | | const DcmTagKey &descriptor, |
45 | | const DcmTagKey &data, |
46 | | const DcmTagKey &explanation, |
47 | | const EL_BitsPerTableEntry descripMode, |
48 | | EI_Status *status) |
49 | 0 | : DiBaseLUT(), |
50 | 0 | OriginalBitsAllocated(16), |
51 | 0 | OriginalData(NULL) |
52 | 0 | { |
53 | 0 | if (docu != NULL) |
54 | 0 | Init(docu, NULL, descriptor, data, explanation, descripMode, status); |
55 | 0 | } |
56 | | |
57 | | |
58 | | DiLookupTable::DiLookupTable(const DiDocument *docu, |
59 | | const DcmTagKey &sequence, |
60 | | const DcmTagKey &descriptor, |
61 | | const DcmTagKey &data, |
62 | | const DcmTagKey &explanation, |
63 | | const EL_BitsPerTableEntry descripMode, |
64 | | const unsigned long pos, |
65 | | unsigned long *card) |
66 | 0 | : DiBaseLUT(), |
67 | 0 | OriginalBitsAllocated(16), |
68 | 0 | OriginalData(NULL) |
69 | 0 | { |
70 | 0 | if (docu != NULL) |
71 | 0 | { |
72 | 0 | DcmSequenceOfItems *seq = NULL; |
73 | 0 | const unsigned long count = docu->getSequence(sequence, seq); |
74 | | /* store number of items in the optional return variable */ |
75 | 0 | if (card != NULL) |
76 | 0 | *card = count; |
77 | 0 | if ((seq != NULL) && (pos < count)) |
78 | 0 | { |
79 | 0 | DcmItem *item = seq->getItem(pos); |
80 | 0 | Init(docu, item, descriptor, data, explanation, descripMode); |
81 | 0 | } |
82 | 0 | } |
83 | 0 | } |
84 | | |
85 | | |
86 | | DiLookupTable::DiLookupTable(const DcmUnsignedShort &data, |
87 | | const DcmUnsignedShort &descriptor, |
88 | | const DcmLongString *explanation, |
89 | | const EL_BitsPerTableEntry descripMode, |
90 | | const signed long first, |
91 | | EI_Status *status) |
92 | 0 | : DiBaseLUT(), |
93 | 0 | OriginalBitsAllocated(16), |
94 | 0 | OriginalData(NULL) |
95 | 0 | { |
96 | 0 | const Uint16 *dataPtr = NULL; |
97 | 0 | const unsigned long count = DiDocument::getElemValue(OFreinterpret_cast(const DcmElement *, &data), dataPtr); |
98 | 0 | Init(dataPtr, count, descriptor, explanation, descripMode, first, status); |
99 | 0 | } |
100 | | |
101 | | |
102 | | DiLookupTable::DiLookupTable(const DcmOtherByteOtherWord &data, |
103 | | const DcmUnsignedShort &descriptor, |
104 | | const DcmLongString *explanation, |
105 | | const EL_BitsPerTableEntry descripMode, |
106 | | const signed long first, |
107 | | EI_Status *status) |
108 | 0 | : DiBaseLUT(), |
109 | 0 | OriginalBitsAllocated(16), |
110 | 0 | OriginalData(NULL) |
111 | 0 | { |
112 | | /* check whether we have OW (16 bit data) since OB (8 bit) is not permitted for LUT data */ |
113 | 0 | if (data.getVR() == EVR_OW) |
114 | 0 | { |
115 | 0 | const Uint16 *dataPtr = NULL; |
116 | 0 | const unsigned long count = DiDocument::getElemValue(OFreinterpret_cast(const DcmElement *, &data), dataPtr); |
117 | 0 | Init(dataPtr, count, descriptor, explanation, descripMode, first, status); |
118 | 0 | } else { |
119 | 0 | DCMIMGLE_ERROR("invalid VR for 'LookupTableData' " << data.getTag()); |
120 | 0 | *status = EIS_InvalidImage; |
121 | 0 | } |
122 | 0 | } |
123 | | |
124 | | |
125 | | DiLookupTable::DiLookupTable(Uint16 *buffer, |
126 | | const Uint32 count, |
127 | | const Uint16 bits) |
128 | 0 | : DiBaseLUT(buffer, count, bits), |
129 | 0 | OriginalBitsAllocated(16), |
130 | 0 | OriginalData(buffer) |
131 | 0 | { |
132 | 0 | checkTable(count, bits); |
133 | 0 | } |
134 | | |
135 | | |
136 | | /*--------------* |
137 | | * destructor * |
138 | | *--------------*/ |
139 | | |
140 | | DiLookupTable::~DiLookupTable() |
141 | 0 | { |
142 | 0 | } |
143 | | |
144 | | |
145 | | /********************************************************************/ |
146 | | |
147 | | |
148 | | void DiLookupTable::Init(const DiDocument *docu, |
149 | | DcmItem *item, |
150 | | const DcmTagKey &descriptor, |
151 | | const DcmTagKey &data, |
152 | | const DcmTagKey &explanation, |
153 | | const EL_BitsPerTableEntry descripMode, |
154 | | EI_Status *status) |
155 | 0 | { |
156 | 0 | Uint16 us = 0; |
157 | 0 | if (docu->getValue(descriptor, us, 0, item, OFTrue /*allowSigned*/) >= 3) // number of LUT entries |
158 | 0 | { |
159 | 0 | Count = (us == 0) ? MAX_TABLE_ENTRY_COUNT : us; // see DICOM supplement 5: "0" => 65536 |
160 | 0 | docu->getValue(descriptor, FirstEntry, 1, item, OFTrue /*allowSigned*/); // can be SS or US (will be typecasted later) |
161 | 0 | docu->getValue(descriptor, us, 2, item, OFTrue /*allowSigned*/); // bits per entry (only informational) |
162 | 0 | const unsigned long count = docu->getValue(data, Data, item); |
163 | 0 | OriginalData = OFstatic_cast(void *, OFconst_cast(Uint16 *, Data)); // store pointer to original data |
164 | 0 | if (explanation != DCM_UndefinedTagKey) |
165 | 0 | docu->getValue(explanation, Explanation, 0 /*vm pos*/, item); // explanation (free form text) |
166 | 0 | checkTable(count, us, descripMode, status); |
167 | 0 | } else { |
168 | 0 | if (status != NULL) |
169 | 0 | { |
170 | 0 | *status = EIS_MissingAttribute; |
171 | 0 | DCMIMGLE_ERROR("incomplete or missing 'LookupTableDescriptor' " << descriptor); |
172 | 0 | } else { |
173 | 0 | DCMIMGLE_WARN("incomplete or missing 'LookupTableDescriptor' " << descriptor |
174 | 0 | << " ... ignoring LUT"); |
175 | 0 | } |
176 | 0 | } |
177 | 0 | } |
178 | | |
179 | | |
180 | | void DiLookupTable::Init(const Uint16 *data, |
181 | | const unsigned long count, |
182 | | const DcmUnsignedShort &descriptor, |
183 | | const DcmLongString *explanation, |
184 | | const EL_BitsPerTableEntry descripMode, |
185 | | const signed long first, |
186 | | EI_Status *status) |
187 | 0 | { |
188 | 0 | Uint16 us = 0; |
189 | 0 | const DcmElement *descElem = OFreinterpret_cast(const DcmElement *, &descriptor); |
190 | 0 | if (DiDocument::getElemValue(descElem, us, 0, OFTrue /*allowSigned*/) >= 3) // number of LUT entries |
191 | 0 | { |
192 | 0 | Count = (us == 0) ? MAX_TABLE_ENTRY_COUNT : us; // see DICOM supplement 5: "0" => 65536 |
193 | 0 | DiDocument::getElemValue(descElem, FirstEntry, 1, OFTrue /*allowSigned*/); // can be SS or US (will be typecasted later) |
194 | 0 | if ((first >= 0) && (FirstEntry != OFstatic_cast(Uint16, first))) |
195 | 0 | { |
196 | 0 | DCMIMGLE_WARN("invalid value for 'FirstInputValueMapped' in lookup table (" |
197 | 0 | << FirstEntry << ") ... assuming " << first); |
198 | 0 | FirstEntry = OFstatic_cast(Uint16, first); |
199 | 0 | } |
200 | 0 | DiDocument::getElemValue(descElem, us, 2, OFTrue /*allowSigned*/); // bits per entry (only informational) |
201 | 0 | Data = data; // store pointer to passed data |
202 | 0 | OriginalData = OFstatic_cast(void *, OFconst_cast(Uint16 *, Data)); // store pointer to original data |
203 | 0 | if (explanation != NULL) |
204 | 0 | DiDocument::getElemValue(OFreinterpret_cast(const DcmElement *, explanation), Explanation); // explanation (free form text) |
205 | 0 | checkTable(count, us, descripMode, status); |
206 | 0 | } else { |
207 | 0 | if (status != NULL) |
208 | 0 | { |
209 | 0 | *status = EIS_MissingAttribute; |
210 | 0 | DCMIMGLE_ERROR("incomplete or missing 'LookupTableDescriptor' " << descriptor.getTag()); |
211 | 0 | } else { |
212 | 0 | DCMIMGLE_WARN("incomplete or missing 'LookupTableDescriptor' " << descriptor.getTag() |
213 | 0 | << " ... ignoring LUT"); |
214 | 0 | } |
215 | 0 | } |
216 | 0 | } |
217 | | |
218 | | |
219 | | void DiLookupTable::checkTable(unsigned long count, |
220 | | Uint16 bits, |
221 | | const EL_BitsPerTableEntry descripMode, |
222 | | EI_Status *status) |
223 | 0 | { |
224 | 0 | if (count > 0) // valid LUT |
225 | 0 | { |
226 | 0 | unsigned long i; |
227 | 0 | if (count > MAX_TABLE_ENTRY_COUNT) // cut LUT length to maximum |
228 | 0 | count = MAX_TABLE_ENTRY_COUNT; |
229 | 0 | if (count != Count) // length of LUT differs from number of LUT entries |
230 | 0 | { |
231 | 0 | if (count == ((Count + 1) >> 1)) // bits allocated 8, ignore padding |
232 | 0 | { |
233 | 0 | OriginalBitsAllocated = 8; |
234 | 0 | DCMIMGLE_DEBUG("lookup table uses 8 bits allocated ... converting to 16 bits"); |
235 | 0 | DataBuffer = new Uint16[Count]; // create new LUT |
236 | 0 | if ((DataBuffer != NULL) && (Data != NULL)) |
237 | 0 | { |
238 | 0 | const Uint8 *p = OFreinterpret_cast(const Uint8 *, Data); |
239 | 0 | Uint16 *q = DataBuffer; |
240 | 0 | if (gLocalByteOrder == EBO_BigEndian) // local machine has big endian byte ordering |
241 | 0 | { |
242 | 0 | DCMIMGLE_DEBUG("local machine has big endian byte ordering ... swapping 8 bit LUT entries"); |
243 | 0 | for (i = Count / 2; i != 0; --i) // copy pairs of 8 bit entries to new 16 bit LUT (swap hi/lo byte) |
244 | 0 | { |
245 | 0 | *(q++) = *(p + 1); // copy low byte ... |
246 | 0 | *(q++) = *p; // ... and then high byte |
247 | 0 | p += 2; // jump to next hi/lo byte pair |
248 | 0 | } |
249 | 0 | if (Count % 2 != 0) // odd number of entries: copy the trailing single entry (low byte) |
250 | 0 | *q = *(p + 1); // avoids writing one Uint16 past the 'Count'-entry buffer |
251 | 0 | } else { // local machine has little endian byte ordering (or unknown) |
252 | 0 | for (i = Count; i != 0; --i) |
253 | 0 | *(q++) = *(p++); // copy 8 bit entries to new 16 bit LUT |
254 | 0 | } |
255 | 0 | } |
256 | 0 | Data = DataBuffer; |
257 | 0 | } else { |
258 | 0 | DCMIMGLE_WARN("invalid value for 'NumberOfTableEntries' (" << Count << ") ... assuming " << count); |
259 | 0 | Count = OFstatic_cast(Uint32, count); |
260 | 0 | } |
261 | 0 | } |
262 | 0 | MinValue = OFstatic_cast(Uint16, DicomImageClass::maxval(MAX_TABLE_ENTRY_SIZE)); // set minimum to maximum value |
263 | 0 | const Uint16 *p = Data; |
264 | 0 | Uint16 value; |
265 | 0 | if (DataBuffer != NULL) // LUT entries have been copied 8 -> 16 bits |
266 | 0 | { |
267 | 0 | for (i = Count; i != 0; --i) |
268 | 0 | { |
269 | 0 | value = *(p++); |
270 | 0 | if (value < MinValue) // get global minimum |
271 | 0 | MinValue = value; |
272 | 0 | if (value > MaxValue) // get global maximum |
273 | 0 | MaxValue = value; |
274 | 0 | } |
275 | 0 | checkBits(bits, 8, 0, descripMode); // set 'Bits' |
276 | 0 | } else { |
277 | 0 | int cmp = 0; |
278 | 0 | for (i = Count; i != 0; --i) |
279 | 0 | { |
280 | 0 | value = *(p++); |
281 | 0 | if ((value >> 8) != 0) // if hi-byte is not zero |
282 | 0 | { |
283 | 0 | if ((value & 0xff) != (value >> 8)) // lo-byte not equal to hi-byte and ... |
284 | 0 | cmp = 1; |
285 | 0 | } |
286 | 0 | if (value < MinValue) // get global minimum |
287 | 0 | MinValue = value; |
288 | 0 | if (value > MaxValue) // get global maximum |
289 | 0 | MaxValue = value; |
290 | 0 | } |
291 | 0 | if (cmp == 0) // lo-byte is always equal to hi-byte |
292 | 0 | checkBits(bits, MIN_TABLE_ENTRY_SIZE, MAX_TABLE_ENTRY_SIZE, descripMode); // set 'Bits' |
293 | 0 | else |
294 | 0 | checkBits(bits, MAX_TABLE_ENTRY_SIZE, MIN_TABLE_ENTRY_SIZE, descripMode); |
295 | 0 | } |
296 | 0 | Uint16 mask = OFstatic_cast(Uint16, DicomImageClass::maxval(Bits)); // mask lo-byte (8) or full word (16) |
297 | 0 | if (((MinValue & mask) != MinValue) || ((MaxValue & mask) != MaxValue)) |
298 | 0 | { // mask table entries and copy them to new LUT |
299 | 0 | MinValue &= mask; |
300 | 0 | MaxValue &= mask; |
301 | 0 | if (DataBuffer == NULL) |
302 | 0 | DataBuffer = new Uint16[Count]; // create new LUT |
303 | 0 | if (DataBuffer != NULL) |
304 | 0 | { |
305 | 0 | p = Data; |
306 | 0 | Uint16 *q = DataBuffer; |
307 | 0 | for (i = Count; i != 0; --i) |
308 | 0 | *(q++) = *(p++) & mask; |
309 | 0 | } |
310 | 0 | Data = DataBuffer; |
311 | 0 | } |
312 | 0 | Valid = (Data != NULL); // lookup table is valid |
313 | 0 | } else { |
314 | 0 | if (status != NULL) |
315 | 0 | { |
316 | 0 | *status = EIS_InvalidValue; |
317 | 0 | DCMIMGLE_ERROR("empty 'LookupTableData' attribute"); |
318 | 0 | } else { |
319 | 0 | DCMIMGLE_WARN("empty 'LookupTableData' attribute ... ignoring LUT"); |
320 | 0 | } |
321 | 0 | } |
322 | 0 | } |
323 | | |
324 | | |
325 | | /********************************************************************/ |
326 | | |
327 | | |
328 | | void DiLookupTable::checkBits(const Uint16 bits, |
329 | | const Uint16 rightBits, |
330 | | const Uint16 wrongBits, |
331 | | const EL_BitsPerTableEntry descripMode) |
332 | 0 | { |
333 | | /* is stored bit depth out of range? */ |
334 | 0 | if ((descripMode == ELM_IgnoreValue) || (bits < MIN_TABLE_ENTRY_SIZE) || (bits > MAX_TABLE_ENTRY_SIZE)) |
335 | 0 | { |
336 | | /* check whether correct bit depth can be determined automatically */ |
337 | 0 | Bits = (MaxValue > 0) ? OFstatic_cast(Uint16, DicomImageClass::tobits(MaxValue, 0)) : bits; |
338 | | /* check bit depth (again) for valid range */ |
339 | 0 | if (Bits < MIN_TABLE_ENTRY_SIZE) |
340 | 0 | Bits = MIN_TABLE_ENTRY_SIZE; |
341 | 0 | else if (Bits > MAX_TABLE_ENTRY_SIZE) |
342 | 0 | Bits = MAX_TABLE_ENTRY_SIZE; |
343 | | /* check whether value has changed? */ |
344 | 0 | if (bits != Bits) |
345 | 0 | { |
346 | 0 | if (descripMode == ELM_IgnoreValue) |
347 | 0 | { |
348 | 0 | DCMIMGLE_INFO("ignoring value for 'BitsPerTableEntry' (" << bits << ") ... using " << Bits << " instead"); |
349 | 0 | } else { |
350 | 0 | DCMIMGLE_WARN("unsuitable value for 'BitsPerTableEntry' (" << bits << ") ... valid range " |
351 | 0 | << MIN_TABLE_ENTRY_SIZE << "-" << MAX_TABLE_ENTRY_SIZE << ", using " << Bits); |
352 | 0 | } |
353 | 0 | } |
354 | 0 | } |
355 | 0 | else if ((descripMode == ELM_CheckValue) && (bits == wrongBits)) |
356 | 0 | { |
357 | 0 | DCMIMGLE_WARN("unsuitable value for 'BitsPerTableEntry' (" << bits << ") ... assuming " << rightBits); |
358 | 0 | Bits = rightBits; |
359 | 0 | } else { |
360 | | /* assuming that the descriptor value is correct! */ |
361 | 0 | Bits = bits; |
362 | 0 | } |
363 | 0 | } |
364 | | |
365 | | |
366 | | int DiLookupTable::invertTable(const int flag) |
367 | 0 | { |
368 | 0 | int result = 0; |
369 | 0 | if ((Data != NULL) && (Count > 0) && (flag & 0x3)) |
370 | 0 | { |
371 | 0 | Uint32 i; |
372 | 0 | if (flag & 0x2) |
373 | 0 | { |
374 | 0 | if (OriginalData != NULL) |
375 | 0 | { |
376 | 0 | if (OriginalBitsAllocated == 8) |
377 | 0 | { |
378 | 0 | if (Bits <= 8) |
379 | 0 | { |
380 | 0 | const Uint8 *p = OFconst_cast(const Uint8 *, OFstatic_cast(Uint8 *, OriginalData)); |
381 | 0 | Uint8 *q = OFstatic_cast(Uint8 *, OriginalData); |
382 | 0 | const Uint8 max = OFstatic_cast(Uint8, DicomImageClass::maxval(Bits)); |
383 | 0 | for (i = Count; i != 0; --i) |
384 | 0 | *(q++) = max - *(p++); |
385 | 0 | result |= 0x2; |
386 | 0 | } |
387 | 0 | } else { |
388 | 0 | const Uint16 *p = OFconst_cast(const Uint16 *, OFstatic_cast(Uint16 *, OriginalData)); |
389 | 0 | Uint16 *q = OFstatic_cast(Uint16 *, OriginalData); |
390 | 0 | const Uint16 max = OFstatic_cast(Uint16, DicomImageClass::maxval(Bits)); |
391 | 0 | for (i = Count; i != 0; --i) |
392 | 0 | *(q++) = max - *(p++); |
393 | 0 | result |= 0x2; |
394 | 0 | } |
395 | 0 | } |
396 | 0 | } |
397 | 0 | if (flag & 0x1) |
398 | 0 | { |
399 | 0 | if (DataBuffer != NULL) |
400 | 0 | { |
401 | 0 | const Uint16 *p = OFconst_cast(const Uint16 *, DataBuffer); |
402 | 0 | Uint16 *q = DataBuffer; |
403 | 0 | const Uint16 max = OFstatic_cast(Uint16, DicomImageClass::maxval(Bits)); |
404 | 0 | for (i = Count; i != 0; --i) |
405 | 0 | *(q++) = max - *(p++); |
406 | 0 | result |= 0x1; |
407 | 0 | } |
408 | 0 | else if (!(flag & 0x2)) |
409 | 0 | { |
410 | 0 | DataBuffer = new Uint16[Count]; |
411 | 0 | if (DataBuffer != NULL) |
412 | 0 | { |
413 | 0 | const Uint16 *p = Data; |
414 | 0 | Uint16 *q = DataBuffer; |
415 | 0 | const Uint16 max = OFstatic_cast(Uint16, DicomImageClass::maxval(Bits)); |
416 | 0 | for (i = Count; i != 0; --i) |
417 | 0 | *(q++) = max - *(p++); |
418 | 0 | Data = DataBuffer; |
419 | 0 | result |= 0x1; |
420 | 0 | } |
421 | 0 | } |
422 | 0 | } |
423 | 0 | } |
424 | 0 | return result; |
425 | 0 | } |
426 | | |
427 | | |
428 | | int DiLookupTable::mirrorTable(const int flag) |
429 | 0 | { |
430 | 0 | int result = 0; |
431 | 0 | if ((Data != NULL) && (Count > 0) && (flag & 0x3)) |
432 | 0 | { |
433 | 0 | Uint32 i; |
434 | 0 | if (flag & 0x2) |
435 | 0 | { |
436 | 0 | if (OriginalData != NULL) |
437 | 0 | { |
438 | 0 | if (OriginalBitsAllocated == 8) |
439 | 0 | { |
440 | 0 | if (Bits <= 8) |
441 | 0 | { |
442 | 0 | Uint8 *p = OFstatic_cast(Uint8 *, OriginalData) + (Count - 1); |
443 | 0 | Uint8 *q = OFstatic_cast(Uint8 *, OriginalData); |
444 | 0 | Uint8 val; |
445 | 0 | const Uint32 mid = Count / 2; |
446 | 0 | for (i = mid; i != 0; --i) |
447 | 0 | { |
448 | 0 | val = *q; |
449 | 0 | *(q++) = *p; |
450 | 0 | *(p--) = val; |
451 | 0 | } |
452 | 0 | result |= 0x2; |
453 | 0 | } |
454 | 0 | } else { |
455 | 0 | Uint16 *p = OFstatic_cast(Uint16 *, OriginalData) + (Count - 1); |
456 | 0 | Uint16 *q = OFstatic_cast(Uint16 *, OriginalData); |
457 | 0 | Uint16 val; |
458 | 0 | const Uint32 mid = Count / 2; |
459 | 0 | for (i = mid; i != 0; --i) |
460 | 0 | { |
461 | 0 | val = *q; |
462 | 0 | *(q++) = *p; |
463 | 0 | *(p--) = val; |
464 | 0 | } |
465 | 0 | result |= 0x2; |
466 | 0 | } |
467 | 0 | } |
468 | 0 | } |
469 | 0 | if (flag & 0x1) |
470 | 0 | { |
471 | 0 | if (DataBuffer != NULL) |
472 | 0 | { |
473 | 0 | Uint16 *p = DataBuffer + (Count - 1); |
474 | 0 | Uint16 *q = DataBuffer; |
475 | 0 | Uint16 val; |
476 | 0 | const Uint32 mid = Count / 2; |
477 | 0 | for (i = mid; i != 0; --i) |
478 | 0 | { |
479 | 0 | val = *q; |
480 | 0 | *(q++) = *p; |
481 | 0 | *(p--) = val; |
482 | 0 | } |
483 | 0 | result |= 0x1; |
484 | 0 | } |
485 | 0 | else if (!(flag & 0x2)) |
486 | 0 | { |
487 | 0 | DataBuffer = new Uint16[Count]; |
488 | 0 | if (DataBuffer != NULL) |
489 | 0 | { |
490 | 0 | Uint16 *p = OFconst_cast(Uint16 *, Data) + (Count - 1); |
491 | 0 | Uint16 *q = DataBuffer; |
492 | 0 | Uint16 val; |
493 | 0 | const Uint32 mid = Count / 2; |
494 | 0 | for (i = mid; i != 0; --i) |
495 | 0 | { |
496 | 0 | val = *q; |
497 | 0 | *(q++) = *p; |
498 | 0 | *(p--) = val; |
499 | 0 | } |
500 | 0 | Data = DataBuffer; |
501 | 0 | result |= 0x1; |
502 | 0 | } |
503 | 0 | } |
504 | 0 | } |
505 | 0 | } |
506 | 0 | return result; |
507 | 0 | } |
508 | | |
509 | | |
510 | | DiLookupTable *DiLookupTable::createInverseLUT() const |
511 | 0 | { |
512 | 0 | DiLookupTable *lut = NULL; |
513 | 0 | if (Valid) |
514 | 0 | { |
515 | 0 | const Uint32 count = OFstatic_cast(Uint32, DicomImageClass::maxval(Bits, 0)); |
516 | 0 | const Uint16 bits = OFstatic_cast(Uint16, DicomImageClass::tobits(Count + FirstEntry)); |
517 | 0 | Uint16 *data = new Uint16[count]; |
518 | 0 | Uint8 *valid = new Uint8[count]; |
519 | 0 | if ((data != NULL) && (valid != NULL)) |
520 | 0 | { |
521 | 0 | OFBitmanipTemplate<Uint8>::zeroMem(valid, count); // initialize array |
522 | 0 | Uint32 i; |
523 | 0 | for (i = 0; i < Count; ++i) // 'copy' values to new array |
524 | 0 | { |
525 | 0 | if (!valid[Data[i]]) |
526 | 0 | data[Data[i]] = OFstatic_cast(Uint16, i + FirstEntry); |
527 | 0 | valid[Data[i]] = 1; |
528 | 0 | } |
529 | 0 | Uint32 last = 0; |
530 | 0 | i = 0; |
531 | 0 | while (i < count) // fill gaps with valid values |
532 | 0 | { |
533 | 0 | if (valid[i]) // skip valid values |
534 | 0 | last = i; |
535 | 0 | else |
536 | 0 | { |
537 | 0 | Uint32 j = i + 1; |
538 | 0 | while ((j < count) && !valid[j]) // find next valid value |
539 | 0 | ++j; |
540 | 0 | if (valid[last]) // check for starting conditions |
541 | 0 | { |
542 | 0 | const Uint32 mid = (j < count) ? (i + j) / 2 : count; |
543 | 0 | while (i < mid) |
544 | 0 | { // fill first half with 'left' value |
545 | 0 | data[i] = data[last]; |
546 | 0 | ++i; |
547 | 0 | } |
548 | 0 | } |
549 | 0 | if ((j < count) && valid[j]) |
550 | 0 | { |
551 | 0 | while (i < j) // fill second half with 'right' value |
552 | 0 | { |
553 | 0 | data[i] = data[j]; |
554 | 0 | ++i; |
555 | 0 | } |
556 | 0 | last = j; |
557 | 0 | } |
558 | 0 | } |
559 | 0 | ++i; |
560 | 0 | } |
561 | 0 | lut = new DiLookupTable(data, count, bits); // create new LUT |
562 | 0 | } |
563 | 0 | delete[] valid; |
564 | 0 | } |
565 | 0 | return lut; |
566 | 0 | } |
567 | | |
568 | | |
569 | | int DiLookupTable::compareLUT(const DcmOtherByteOtherWord &data, |
570 | | const DcmUnsignedShort &descriptor) |
571 | 0 | { |
572 | 0 | int result = 1; |
573 | 0 | DiBaseLUT *lut = new DiLookupTable(data, descriptor); |
574 | 0 | if (lut != NULL) |
575 | 0 | result = compare(lut); |
576 | 0 | delete lut; |
577 | 0 | return result; |
578 | 0 | } |
579 | | |
580 | | |
581 | | int DiLookupTable::compareLUT(const DcmUnsignedShort &data, |
582 | | const DcmUnsignedShort &descriptor) |
583 | 0 | { |
584 | 0 | int result = 1; |
585 | 0 | DiBaseLUT *lut = new DiLookupTable(data, descriptor); |
586 | 0 | if (lut != NULL) |
587 | 0 | result = compare(lut); |
588 | 0 | delete lut; |
589 | 0 | return result; |
590 | 0 | } |
591 | | |
592 | | |
593 | | OFBool DiLookupTable::operator==(const DiBaseLUT &lut) |
594 | 0 | { |
595 | 0 | return (compare(&lut) == 0); |
596 | 0 | } |
597 | | |
598 | | |
599 | | OFBool DiLookupTable::operator==(const DiLookupTable &lut) |
600 | 0 | { |
601 | 0 | return (compare(OFstatic_cast(const DiBaseLUT *, &lut)) == 0); |
602 | 0 | } |