1 /*
2 *
3 * Copyright (C) 1996-2002, OFFIS
4 *
5 * This software and supporting documentation were developed by
6 *
7 * Kuratorium OFFIS e.V.
8 * Healthcare Information and Communication Systems
9 * Escherweg 2
10 * D-26121 Oldenburg, Germany
11 *
12 * THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND OFFIS MAKES NO WARRANTY
13 * REGARDING THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR
14 * FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES OR
15 * ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND
16 * PERFORMANCE OF THE SOFTWARE IS WITH THE USER.
17 *
18 * Module: dcmimgle
19 *
20 * Author: Joerg Riesmeier
21 *
22 * Purpose: DicomMonochromeImage (Source)
23 *
24 */
25
26
27 #include "osconfig.h"
28 #include "dctypes.h"
29 #include "dcdeftag.h"
30
31 #include "dimoimg.h"
32 #include "dimo2img.h"
33 #include "dimoipxt.h"
34 #include "dimocpt.h"
35 #include "dimosct.h"
36 #include "dimoflt.h"
37 #include "dimorot.h"
38 #include "dimoopxt.h"
39 #include "digsdfn.h"
40 #include "didocu.h"
41 #include "diutils.h"
42 #include "diregbas.h"
43
44 #define INCLUDE_CMATH
45 #include "ofstdinc.h"
46
47
48 /*---------------------*
49 * const definitions *
50 *---------------------*/
51
52 const unsigned int Default_MinDensity = 20;
53 const unsigned int Default_MaxDensity = 300;
54 const unsigned int Default_Reflection = 10;
55 const unsigned int Default_Illumination = 2000;
56
57
58 /*----------------*
59 * constructors *
60 *----------------*/
61
62 /*
63 * standard constructor to create mono-image
64 */
65
DiMonoImage(const DiDocument * docu,const EI_Status status)66 DiMonoImage::DiMonoImage(const DiDocument *docu,
67 const EI_Status status)
68 : DiImage(docu, status, 1),
69 WindowCenter(0),
70 WindowWidth(0),
71 WindowCount(0),
72 VoiLutCount(0),
73 ValidWindow(0),
74 VoiExplanation(),
75 PresLutShape(ESP_Default),
76 MinDensity(Default_MinDensity),
77 MaxDensity(Default_MaxDensity),
78 Reflection(Default_Reflection),
79 Illumination(Default_Illumination),
80 VoiLutData(NULL),
81 PresLutData(NULL),
82 InterData(NULL),
83 DisplayFunction(NULL),
84 OutputData(NULL),
85 OverlayData(NULL)
86 {
87 Overlays[0] = NULL;
88 Overlays[1] = NULL;
89 if ((Document != NULL) && (InputData != NULL) && (ImageStatus == EIS_Normal))
90 {
91 if (Document->getFlags() & CIF_UsePresentationState)
92 PresLutShape = ESP_Identity;
93 DiMonoModality *modality = new DiMonoModality(Document, InputData);
94 Init(modality);
95 }
96 }
97
98
DiMonoImage(const DiDocument * docu,const EI_Status status,const double slope,const double intercept)99 DiMonoImage::DiMonoImage(const DiDocument *docu,
100 const EI_Status status,
101 const double slope,
102 const double intercept)
103 : DiImage(docu, status, 1),
104 WindowCenter(0),
105 WindowWidth(0),
106 WindowCount(0),
107 VoiLutCount(0),
108 ValidWindow(0),
109 VoiExplanation(),
110 PresLutShape(ESP_Default),
111 MinDensity(Default_MinDensity),
112 MaxDensity(Default_MaxDensity),
113 Reflection(Default_Reflection),
114 Illumination(Default_Illumination),
115 VoiLutData(NULL),
116 PresLutData(NULL),
117 InterData(NULL),
118 DisplayFunction(NULL),
119 OutputData(NULL),
120 OverlayData(NULL)
121 {
122 Overlays[0] = NULL;
123 Overlays[1] = NULL;
124 if ((Document != NULL) && (InputData != NULL) && (ImageStatus == EIS_Normal))
125 {
126 if (Document->getFlags() & CIF_UsePresentationState)
127 PresLutShape = ESP_Identity;
128 DiMonoModality *modality = new DiMonoModality(Document, InputData, slope, intercept);
129 Init(modality);
130 }
131 }
132
133
DiMonoImage(const DiDocument * docu,const EI_Status status,const DcmUnsignedShort & data,const DcmUnsignedShort & descriptor,const DcmLongString * explanation)134 DiMonoImage::DiMonoImage(const DiDocument *docu,
135 const EI_Status status,
136 const DcmUnsignedShort &data,
137 const DcmUnsignedShort &descriptor,
138 const DcmLongString *explanation)
139 : DiImage(docu, status, 1),
140 WindowCenter(0),
141 WindowWidth(0),
142 WindowCount(0),
143 VoiLutCount(0),
144 ValidWindow(0),
145 VoiExplanation(),
146 PresLutShape(ESP_Default),
147 MinDensity(Default_MinDensity),
148 MaxDensity(Default_MaxDensity),
149 Reflection(Default_Reflection),
150 Illumination(Default_Illumination),
151 VoiLutData(NULL),
152 PresLutData(NULL),
153 InterData(NULL),
154 DisplayFunction(NULL),
155 OutputData(NULL),
156 OverlayData(NULL)
157 {
158 Overlays[0] = NULL;
159 Overlays[1] = NULL;
160 if ((Document != NULL) && (InputData != NULL) && (ImageStatus == EIS_Normal))
161 {
162 if (Document->getFlags() & CIF_UsePresentationState)
163 PresLutShape = ESP_Identity;
164 DiMonoModality *modality = new DiMonoModality(Document, InputData, data, descriptor, explanation);
165 Init(modality);
166 }
167 }
168
169
170 /*
171 * kind of copy-constructor, 'dummy' is necessary to differ from the above "standard"-constructor
172 */
173
DiMonoImage(const DiDocument * docu,const EI_Status status,const char)174 DiMonoImage::DiMonoImage(const DiDocument *docu,
175 const EI_Status status,
176 const char /*dummy*/)
177 : DiImage(docu, status/*, dummy*/),
178 WindowCenter(0),
179 WindowWidth(0),
180 WindowCount(0),
181 VoiLutCount(0),
182 ValidWindow(0),
183 VoiExplanation(),
184 PresLutShape(ESP_Default),
185 MinDensity(Default_MinDensity),
186 MaxDensity(Default_MaxDensity),
187 Reflection(Default_Reflection),
188 Illumination(Default_Illumination),
189 VoiLutData(NULL),
190 PresLutData(NULL),
191 InterData(NULL),
192 DisplayFunction(NULL),
193 OutputData(NULL),
194 OverlayData(NULL)
195 {
196 Overlays[0] = NULL;
197 Overlays[1] = NULL;
198 }
199
200
201 /*
202 * create image copy of specified frame range
203 */
204
DiMonoImage(const DiMonoImage * image,const unsigned long fstart,const unsigned long fcount)205 DiMonoImage::DiMonoImage(const DiMonoImage *image,
206 const unsigned long fstart,
207 const unsigned long fcount)
208 : DiImage(image, fstart, fcount),
209 WindowCenter(image->WindowCenter),
210 WindowWidth(image->WindowWidth),
211 WindowCount(image->WindowCount),
212 VoiLutCount(image->VoiLutCount),
213 ValidWindow(image->ValidWindow),
214 VoiExplanation(image->VoiExplanation),
215 PresLutShape(image->PresLutShape),
216 MinDensity(image->MinDensity),
217 MaxDensity(image->MaxDensity),
218 Reflection(image->Reflection),
219 Illumination(image->Illumination),
220 VoiLutData(image->VoiLutData),
221 PresLutData(image->PresLutData),
222 InterData(NULL),
223 DisplayFunction(image->DisplayFunction),
224 OutputData(NULL),
225 OverlayData(NULL)
226 {
227 Overlays[0] = image->Overlays[0];
228 Overlays[1] = image->Overlays[1];
229 if (image->InterData != NULL)
230 {
231 const unsigned long fsize = (unsigned long)Columns * (unsigned long)Rows;
232 switch (image->InterData->getRepresentation())
233 {
234 case EPR_Uint8:
235 InterData = new DiMonoCopyTemplate<Uint8>(image->InterData, fstart, fcount, fsize);
236 break;
237 case EPR_Sint8:
238 InterData = new DiMonoCopyTemplate<Sint8>(image->InterData, fstart, fcount, fsize);
239 break;
240 case EPR_Uint16:
241 InterData = new DiMonoCopyTemplate<Uint16>(image->InterData, fstart, fcount, fsize);
242 break;
243 case EPR_Sint16:
244 InterData = new DiMonoCopyTemplate<Sint16>(image->InterData, fstart, fcount, fsize);
245 break;
246 case EPR_Uint32:
247 InterData = new DiMonoCopyTemplate<Uint32>(image->InterData, fstart, fcount, fsize);
248 break;
249 case EPR_Sint32:
250 InterData = new DiMonoCopyTemplate<Sint32>(image->InterData, fstart, fcount, fsize);
251 break;
252 }
253 }
254 checkInterData();
255 for (int i = 0; i < 2; i++)
256 {
257 if (Overlays[i] != NULL)
258 Overlays[i]->addReference();
259 }
260 if (VoiLutData != NULL)
261 VoiLutData->addReference();
262 if (PresLutData != NULL)
263 PresLutData->addReference();
264 }
265
266
267 /*
268 * convert color-image to mono-image with given 'red', 'green' and 'blue' coefficients
269 */
270
DiMonoImage(const DiColorImage * image,const double red,const double green,const double blue)271 DiMonoImage::DiMonoImage(const DiColorImage *image,
272 const double red,
273 const double green,
274 const double blue)
275 : DiImage((DiImage *)image),
276 WindowCenter(0),
277 WindowWidth(0),
278 WindowCount(0),
279 VoiLutCount(0),
280 ValidWindow(0),
281 VoiExplanation(),
282 PresLutShape(ESP_Default),
283 MinDensity(Default_MinDensity),
284 MaxDensity(Default_MaxDensity),
285 Reflection(Default_Reflection),
286 Illumination(Default_Illumination),
287 VoiLutData(NULL),
288 PresLutData(NULL),
289 InterData(NULL),
290 DisplayFunction(NULL),
291 OutputData(NULL),
292 OverlayData(NULL)
293 {
294 Overlays[0] = NULL;
295 Overlays[1] = NULL;
296 if ((Document != NULL) && (Document->getFlags() & CIF_UsePresentationState))
297 PresLutShape = ESP_Identity;
298 if (DiRegisterBase::Pointer != NULL)
299 InterData = DiRegisterBase::Pointer->createMonoImageData(image, red, green, blue);
300 if ((InterData == NULL) || (InterData->getData() == NULL))
301 ImageStatus = EIS_InvalidImage;
302 }
303
304
305 /*
306 * scale 'image' to size given by 'columns' and 'rows', 'interpolate' always if parameter is true
307 */
308
DiMonoImage(const DiMonoImage * image,const signed long left_pos,const signed long top_pos,const Uint16 src_cols,const Uint16 src_rows,const Uint16 dest_cols,const Uint16 dest_rows,const int interpolate,const int aspect,const Uint16 pvalue)309 DiMonoImage::DiMonoImage(const DiMonoImage *image,
310 const signed long left_pos,
311 const signed long top_pos,
312 const Uint16 src_cols,
313 const Uint16 src_rows,
314 const Uint16 dest_cols,
315 const Uint16 dest_rows,
316 const int interpolate,
317 const int aspect,
318 const Uint16 pvalue)
319 : DiImage(image, dest_cols, dest_rows, aspect),
320 WindowCenter(image->WindowCenter),
321 WindowWidth(image->WindowWidth),
322 WindowCount(image->WindowCount),
323 VoiLutCount(image->VoiLutCount),
324 ValidWindow(image->ValidWindow),
325 VoiExplanation(image->VoiExplanation),
326 PresLutShape(image->PresLutShape),
327 MinDensity(image->MinDensity),
328 MaxDensity(image->MaxDensity),
329 Reflection(image->Reflection),
330 Illumination(image->Illumination),
331 VoiLutData(image->VoiLutData),
332 PresLutData(image->PresLutData),
333 InterData(NULL),
334 DisplayFunction(image->DisplayFunction),
335 OutputData(NULL),
336 OverlayData(NULL)
337 {
338 Overlays[0] = NULL;
339 Overlays[1] = NULL;
340 if (image->InterData != NULL)
341 {
342 switch (image->InterData->getRepresentation())
343 {
344 case EPR_Uint8:
345 InterData = new DiMonoScaleTemplate<Uint8>(image->InterData, image->Columns, image->Rows,
346 left_pos, top_pos, src_cols, src_rows, dest_cols, dest_rows, NumberOfFrames, interpolate, pvalue);
347 break;
348 case EPR_Sint8:
349 InterData = new DiMonoScaleTemplate<Sint8>(image->InterData, image->Columns, image->Rows,
350 left_pos, top_pos, src_cols, src_rows, dest_cols, dest_rows, NumberOfFrames, interpolate, pvalue);
351 break;
352 case EPR_Uint16:
353 InterData = new DiMonoScaleTemplate<Uint16>(image->InterData, image->Columns, image->Rows,
354 left_pos, top_pos, src_cols, src_rows, dest_cols, dest_rows, NumberOfFrames, interpolate, pvalue);
355 break;
356 case EPR_Sint16:
357 InterData = new DiMonoScaleTemplate<Sint16>(image->InterData, image->Columns, image->Rows,
358 left_pos, top_pos, src_cols, src_rows, dest_cols, dest_rows, NumberOfFrames, interpolate, pvalue);
359 break;
360 case EPR_Uint32:
361 InterData = new DiMonoScaleTemplate<Uint32>(image->InterData, image->Columns, image->Rows,
362 left_pos, top_pos, src_cols, src_rows, dest_cols, dest_rows, NumberOfFrames, interpolate, pvalue);
363 break;
364 case EPR_Sint32:
365 InterData = new DiMonoScaleTemplate<Sint32>(image->InterData, image->Columns, image->Rows,
366 left_pos, top_pos, src_cols, src_rows, dest_cols, dest_rows, NumberOfFrames, interpolate, pvalue);
367 break;
368 }
369 }
370 if (checkInterData(0))
371 {
372 for (int i = 0; i < 2; i++)
373 {
374 if ((image->Overlays[i] != NULL) && (image->Overlays[i]->getCount() > 0))
375 {
376 Overlays[i] = new DiOverlay(image->Overlays[i], left_pos, top_pos,
377 (double)dest_cols / (double)src_cols, (double)dest_rows / (double)src_rows);
378 }
379 }
380 }
381 if (VoiLutData != NULL)
382 VoiLutData->addReference();
383 if (PresLutData != NULL)
384 PresLutData->addReference();
385 }
386
387
388 /*
389 * flip
390 */
391
DiMonoImage(const DiMonoImage * image,const int horz,const int vert)392 DiMonoImage::DiMonoImage(const DiMonoImage *image,
393 const int horz,
394 const int vert)
395 : DiImage(image),
396 WindowCenter(image->WindowCenter),
397 WindowWidth(image->WindowWidth),
398 WindowCount(image->WindowCount),
399 VoiLutCount(image->VoiLutCount),
400 ValidWindow(image->ValidWindow),
401 VoiExplanation(image->VoiExplanation),
402 PresLutShape(image->PresLutShape),
403 MinDensity(image->MinDensity),
404 MaxDensity(image->MaxDensity),
405 Reflection(image->Reflection),
406 Illumination(image->Illumination),
407 VoiLutData(image->VoiLutData),
408 PresLutData(image->PresLutData),
409 InterData(NULL),
410 DisplayFunction(image->DisplayFunction),
411 OutputData(NULL),
412 OverlayData(NULL)
413 {
414 Overlays[0] = NULL;
415 Overlays[1] = NULL;
416 if (image->InterData != NULL)
417 {
418 switch (image->InterData->getRepresentation())
419 {
420 case EPR_Uint8:
421 InterData = new DiMonoFlipTemplate<Uint8>(image->InterData, Columns, Rows, NumberOfFrames, horz, vert);
422 break;
423 case EPR_Sint8:
424 InterData = new DiMonoFlipTemplate<Sint8>(image->InterData, Columns, Rows, NumberOfFrames, horz, vert);
425 break;
426 case EPR_Uint16:
427 InterData = new DiMonoFlipTemplate<Uint16>(image->InterData, Columns, Rows, NumberOfFrames, horz, vert);
428 break;
429 case EPR_Sint16:
430 InterData = new DiMonoFlipTemplate<Sint16>(image->InterData, Columns, Rows, NumberOfFrames, horz, vert);
431 break;
432 case EPR_Uint32:
433 InterData = new DiMonoFlipTemplate<Uint32>(image->InterData, Columns, Rows, NumberOfFrames, horz, vert);
434 break;
435 case EPR_Sint32:
436 InterData = new DiMonoFlipTemplate<Sint32>(image->InterData, Columns, Rows, NumberOfFrames, horz, vert);
437 break;
438 }
439 }
440 if (checkInterData(0))
441 {
442 for (int i = 0; i < 2; i++)
443 {
444 if ((image->Overlays[i] != NULL) && (image->Overlays[i]->getCount() > 0))
445 Overlays[i] = new DiOverlay(image->Overlays[i], horz, vert, Columns, Rows);
446 }
447 }
448 if (VoiLutData != NULL)
449 VoiLutData->addReference();
450 if (PresLutData != NULL)
451 PresLutData->addReference();
452 }
453
454
455 /*
456 * rotate
457 */
458
DiMonoImage(const DiMonoImage * image,const int degree)459 DiMonoImage::DiMonoImage(const DiMonoImage *image,
460 const int degree)
461 : DiImage(image, degree),
462 WindowCenter(image->WindowCenter),
463 WindowWidth(image->WindowWidth),
464 WindowCount(image->WindowCount),
465 VoiLutCount(image->VoiLutCount),
466 ValidWindow(image->ValidWindow),
467 VoiExplanation(image->VoiExplanation),
468 PresLutShape(image->PresLutShape),
469 MinDensity(image->MinDensity),
470 MaxDensity(image->MaxDensity),
471 Reflection(image->Reflection),
472 Illumination(image->Illumination),
473 VoiLutData(image->VoiLutData),
474 PresLutData(image->PresLutData),
475 InterData(NULL),
476 DisplayFunction(image->DisplayFunction),
477 OutputData(NULL),
478 OverlayData(NULL)
479 {
480 Overlays[0] = NULL;
481 Overlays[1] = NULL;
482 if (image->InterData != NULL)
483 {
484 switch (image->InterData->getRepresentation())
485 {
486 case EPR_Uint8:
487 InterData = new DiMonoRotateTemplate<Uint8>(image->InterData, image->Columns, image->Rows, Columns, Rows,
488 NumberOfFrames, degree);
489 break;
490 case EPR_Sint8:
491 InterData = new DiMonoRotateTemplate<Sint8>(image->InterData, image->Columns, image->Rows, Columns, Rows,
492 NumberOfFrames, degree);
493 break;
494 case EPR_Uint16:
495 InterData = new DiMonoRotateTemplate<Uint16>(image->InterData, image->Columns, image->Rows, Columns, Rows,
496 NumberOfFrames, degree);
497 break;
498 case EPR_Sint16:
499 InterData = new DiMonoRotateTemplate<Sint16>(image->InterData, image->Columns, image->Rows, Columns, Rows,
500 NumberOfFrames, degree);
501 break;
502 case EPR_Uint32:
503 InterData = new DiMonoRotateTemplate<Uint32>(image->InterData, image->Columns, image->Rows, Columns, Rows,
504 NumberOfFrames, degree);
505 break;
506 case EPR_Sint32:
507 InterData = new DiMonoRotateTemplate<Sint32>(image->InterData, image->Columns, image->Rows, Columns, Rows,
508 NumberOfFrames, degree);
509 break;
510 }
511 }
512 if (checkInterData(0))
513 {
514 for (int i = 0; i < 2; i++)
515 {
516 if ((image->Overlays[i] != NULL) && (image->Overlays[i]->getCount() > 0))
517 Overlays[i] = new DiOverlay(image->Overlays[i], degree, Columns, Rows);
518 }
519 }
520 if (VoiLutData != NULL)
521 VoiLutData->addReference();
522 if (PresLutData != NULL)
523 PresLutData->addReference();
524 }
525
526
527 /*
528 * this implementation is necessary to avoid linker errors on NeXTSTEP (gcc 2.5.8)
529 */
530
DiMonoImage(const DiMonoImage &)531 DiMonoImage::DiMonoImage(const DiMonoImage &)
532 : DiImage(NULL),
533 WindowCenter(0),
534 WindowWidth(0),
535 WindowCount(0),
536 VoiLutCount(0),
537 ValidWindow(0),
538 VoiExplanation(),
539 PresLutShape(ESP_Default),
540 MinDensity(Default_MinDensity),
541 MaxDensity(Default_MaxDensity),
542 Reflection(Default_Reflection),
543 Illumination(Default_Illumination),
544 VoiLutData(NULL),
545 PresLutData(NULL),
546 InterData(NULL),
547 DisplayFunction(NULL),
548 OutputData(NULL),
549 OverlayData(NULL)
550 {
551 if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_Errors))
552 {
553 ofConsole.lockCerr() << "ERROR in DiMonoImage copy-constructor !!!" << endl;
554 ofConsole.unlockCerr();
555 }
556 abort();
557 }
558
559
560 /*
561 * createMonoOutputImage
562 */
563
DiMonoImage(const DiMonoImage * image,const DiMonoOutputPixel * pixel,const unsigned long frame,const int stored,const int alloc)564 DiMonoImage::DiMonoImage(const DiMonoImage *image,
565 const DiMonoOutputPixel *pixel,
566 const unsigned long frame,
567 const int stored,
568 const int alloc)
569 : DiImage(image, frame, stored, alloc),
570 WindowCenter(0),
571 WindowWidth(0),
572 WindowCount(0),
573 VoiLutCount(0),
574 ValidWindow(0),
575 VoiExplanation(),
576 PresLutShape(ESP_Default),
577 MinDensity(Default_MinDensity),
578 MaxDensity(Default_MaxDensity),
579 Reflection(Default_Reflection),
580 Illumination(Default_Illumination),
581 VoiLutData(NULL),
582 PresLutData(NULL),
583 InterData(NULL),
584 DisplayFunction(NULL),
585 OutputData(NULL),
586 OverlayData(NULL)
587 {
588 Overlays[0] = NULL;
589 Overlays[1] = NULL;
590 if ((Document != NULL) && (Document->getFlags() & CIF_UsePresentationState))
591 PresLutShape = ESP_Identity;
592 if (pixel->getData() != NULL)
593 {
594 DiMonoModality *modality = new DiMonoModality(stored);
595 switch (pixel->getRepresentation())
596 {
597 case EPR_Uint8:
598 InterData = new DiMonoPixelTemplate<Uint8>(pixel, modality);
599 break;
600 case EPR_Uint16:
601 InterData = new DiMonoPixelTemplate<Uint16>(pixel, modality);
602 break;
603 case EPR_Uint32:
604 InterData = new DiMonoPixelTemplate<Uint32>(pixel, modality);
605 break;
606 default:
607 break;
608 }
609 }
610 checkInterData(0);
611 }
612
613
614 /*--------------*
615 * destructor *
616 *--------------*/
617
~DiMonoImage()618 DiMonoImage::~DiMonoImage()
619 {
620 delete InterData;
621 delete OutputData;
622 delete (char *)OverlayData; // type cast necessary to avoid compiler warnings using gcc 2.95
623 if (VoiLutData != NULL)
624 VoiLutData->removeReference(); // only delete if object is no longer referenced
625 if (PresLutData != NULL)
626 PresLutData->removeReference();
627 for (int i = 0; i < 2; i++)
628 {
629 if (Overlays[i] != NULL)
630 Overlays[i]->removeReference();
631 }
632 }
633
634
635 /*********************************************************************/
636
637
Init(DiMonoModality * modality)638 void DiMonoImage::Init(DiMonoModality *modality)
639 {
640 if (modality != NULL)
641 {
642 Overlays[0] = new DiOverlay(Document, BitsAllocated);
643 if ((Overlays[0] != NULL) && !(Document->getFlags() & CIF_UsePresentationState))
644 Overlays[0]->showAllPlanes(); // default: show all overlays with stored modes
645 if ((Overlays[0] == NULL) || (Overlays[0]->getCount() == 0) || (!Overlays[0]->hasEmbeddedData()))
646 detachPixelData(); // no longer needed, save memory
647 switch (InputData->getRepresentation())
648 {
649 case EPR_Uint8:
650 InitUint8(modality);
651 break;
652 case EPR_Sint8:
653 InitUint8(modality);
654 break;
655 case EPR_Uint16:
656 InitUint16(modality);
657 break;
658 case EPR_Sint16:
659 InitSint16(modality);
660 break;
661 case EPR_Uint32:
662 InitUint32(modality);
663 break;
664 case EPR_Sint32:
665 InitSint32(modality);
666 break;
667 }
668 deleteInputData(); // no longer needed, save memory
669 if ((modality->hasLookupTable()) && (modality->getTableData() != NULL))
670 BitsPerSample = modality->getTableData()->getBits();
671 /* get grayscale related attributes */
672 if (checkInterData() && !(Document->getFlags() & CIF_UsePresentationState))
673 {
674 /* VOI windows */
675 WindowCount = Document->getVM(DCM_WindowCenter);
676 const unsigned long count = Document->getVM(DCM_WindowWidth);
677 if (count < WindowCount) // determine number of VOI windows
678 WindowCount = count;
679 /* VOI LUT */
680 DcmSequenceOfItems *seq = NULL;
681 VoiLutCount = Document->getSequence(DCM_VOILUTSequence, seq);
682 /* Presentation LUT Shape */
683 OFString str;
684 if (Document->getValue(DCM_PresentationLUTShape, str))
685 {
686 if (str == "IDENTITY")
687 PresLutShape = ESP_Identity;
688 else if (str == "INVERSE")
689 PresLutShape = ESP_Inverse;
690 else
691 {
692 if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_Warnings))
693 {
694 ofConsole.lockCerr() << "WARNING: unknown value for 'PresentationLUTShape' ("
695 << str << ") ... ignoring !" << endl;
696 ofConsole.unlockCerr();
697 }
698 }
699 }
700 }
701 } else
702 detachPixelData();
703 }
704
705
InitUint8(DiMonoModality * modality)706 void DiMonoImage::InitUint8(DiMonoModality *modality)
707 {
708 if (modality != NULL)
709 {
710 switch (modality->getRepresentation())
711 {
712 case EPR_Uint8:
713 InterData = new DiMonoInputPixelTemplate<Uint8, Uint32, Uint8>(InputData, modality);
714 break;
715 case EPR_Sint8:
716 InterData = new DiMonoInputPixelTemplate<Uint8, Uint32, Sint8>(InputData, modality);
717 break;
718 case EPR_Uint16:
719 InterData = new DiMonoInputPixelTemplate<Uint8, Uint32, Uint16>(InputData, modality);
720 break;
721 case EPR_Sint16:
722 InterData = new DiMonoInputPixelTemplate<Uint8, Uint32, Sint16>(InputData, modality);
723 break;
724 case EPR_Uint32:
725 InterData = new DiMonoInputPixelTemplate<Uint8, Uint32, Uint32>(InputData, modality);
726 break;
727 case EPR_Sint32:
728 InterData = new DiMonoInputPixelTemplate<Uint8, Uint32, Sint32>(InputData, modality);
729 break;
730 }
731 }
732 }
733
734
InitSint8(DiMonoModality * modality)735 void DiMonoImage::InitSint8(DiMonoModality *modality)
736 {
737 if (modality != NULL)
738 {
739 switch (modality->getRepresentation())
740 {
741 case EPR_Uint8:
742 InterData = new DiMonoInputPixelTemplate<Sint8, Sint32, Uint8>(InputData, modality);
743 break;
744 case EPR_Sint8:
745 InterData = new DiMonoInputPixelTemplate<Sint8, Sint32, Sint8>(InputData, modality);
746 break;
747 case EPR_Uint16:
748 InterData = new DiMonoInputPixelTemplate<Sint8, Sint32, Uint16>(InputData, modality);
749 break;
750 case EPR_Sint16:
751 InterData = new DiMonoInputPixelTemplate<Sint8, Sint32, Sint16>(InputData, modality);
752 break;
753 case EPR_Uint32:
754 InterData = new DiMonoInputPixelTemplate<Sint8, Sint32, Uint32>(InputData, modality);
755 break;
756 case EPR_Sint32:
757 InterData = new DiMonoInputPixelTemplate<Sint8, Sint32, Sint32>(InputData, modality);
758 break;
759 }
760 }
761 }
762
InitUint16(DiMonoModality * modality)763 void DiMonoImage::InitUint16(DiMonoModality *modality)
764 {
765 if (modality != NULL)
766 {
767 switch (modality->getRepresentation())
768 {
769 case EPR_Uint8:
770 InterData = new DiMonoInputPixelTemplate<Uint16, Uint32, Uint8>(InputData, modality);
771 break;
772 case EPR_Sint8:
773 InterData = new DiMonoInputPixelTemplate<Uint16, Uint32, Sint8>(InputData, modality);
774 break;
775 case EPR_Uint16:
776 InterData = new DiMonoInputPixelTemplate<Uint16, Uint32, Uint16>(InputData, modality);
777 break;
778 case EPR_Sint16:
779 InterData = new DiMonoInputPixelTemplate<Uint16, Uint32, Sint16>(InputData, modality);
780 break;
781 case EPR_Uint32:
782 InterData = new DiMonoInputPixelTemplate<Uint16, Uint32, Uint32>(InputData, modality);
783 break;
784 case EPR_Sint32:
785 InterData = new DiMonoInputPixelTemplate<Uint16, Uint32, Sint32>(InputData, modality);
786 break;
787 }
788 }
789 }
790
791
InitSint16(DiMonoModality * modality)792 void DiMonoImage::InitSint16(DiMonoModality *modality)
793 {
794 if (modality != NULL)
795 {
796 switch (modality->getRepresentation())
797 {
798 case EPR_Uint8:
799 InterData = new DiMonoInputPixelTemplate<Sint16, Sint32, Uint8>(InputData, modality);
800 break;
801 case EPR_Sint8:
802 InterData = new DiMonoInputPixelTemplate<Sint16, Sint32, Sint8>(InputData, modality);
803 break;
804 case EPR_Uint16:
805 InterData = new DiMonoInputPixelTemplate<Sint16, Sint32, Uint16>(InputData, modality);
806 break;
807 case EPR_Sint16:
808 InterData = new DiMonoInputPixelTemplate<Sint16, Sint32, Sint16>(InputData, modality);
809 break;
810 case EPR_Uint32:
811 InterData = new DiMonoInputPixelTemplate<Sint16, Sint32, Uint32>(InputData, modality);
812 break;
813 case EPR_Sint32:
814 InterData = new DiMonoInputPixelTemplate<Sint16, Sint32, Sint32>(InputData, modality);
815 break;
816 }
817 }
818 }
819
820
InitUint32(DiMonoModality * modality)821 void DiMonoImage::InitUint32(DiMonoModality *modality)
822 {
823 if (modality != NULL)
824 {
825 switch (modality->getRepresentation())
826 {
827 case EPR_Uint8:
828 InterData = new DiMonoInputPixelTemplate<Uint32, Uint32, Uint8>(InputData, modality);
829 break;
830 case EPR_Sint8:
831 InterData = new DiMonoInputPixelTemplate<Uint32, Uint32, Sint8>(InputData, modality);
832 break;
833 case EPR_Uint16:
834 InterData = new DiMonoInputPixelTemplate<Uint32, Uint32, Uint16>(InputData, modality);
835 break;
836 case EPR_Sint16:
837 InterData = new DiMonoInputPixelTemplate<Uint32, Uint32, Sint16>(InputData, modality);
838 break;
839 case EPR_Uint32:
840 InterData = new DiMonoInputPixelTemplate<Uint32, Uint32, Uint32>(InputData, modality);
841 break;
842 case EPR_Sint32:
843 InterData = new DiMonoInputPixelTemplate<Uint32, Uint32, Sint32>(InputData, modality);
844 break;
845 }
846 }
847 }
848
849
InitSint32(DiMonoModality * modality)850 void DiMonoImage::InitSint32(DiMonoModality *modality)
851 {
852 if (modality != NULL)
853 {
854 switch (modality->getRepresentation())
855 {
856 case EPR_Uint8:
857 InterData = new DiMonoInputPixelTemplate<Sint32, Sint32, Uint8>(InputData, modality);
858 break;
859 case EPR_Sint8:
860 InterData = new DiMonoInputPixelTemplate<Sint32, Sint32, Sint8>(InputData, modality);
861 break;
862 case EPR_Uint16:
863 InterData = new DiMonoInputPixelTemplate<Sint32, Sint32, Uint16>(InputData, modality);
864 break;
865 case EPR_Sint16:
866 InterData = new DiMonoInputPixelTemplate<Sint32, Sint32, Sint16>(InputData, modality);
867 break;
868 case EPR_Uint32:
869 InterData = new DiMonoInputPixelTemplate<Sint32, Sint32, Uint32>(InputData, modality);
870 break;
871 case EPR_Sint32:
872 InterData = new DiMonoInputPixelTemplate<Sint32, Sint32, Sint32>(InputData, modality);
873 break;
874 }
875 }
876 }
877
878 /*********************************************************************/
879
880
checkInterData(const int mode)881 int DiMonoImage::checkInterData(const int mode)
882 {
883 if (InterData == NULL)
884 {
885 if (ImageStatus == EIS_Normal)
886 {
887 ImageStatus = EIS_MemoryFailure;
888 if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_Errors))
889 {
890 ofConsole.lockCerr() << "ERROR: can't allocate memory for inter-representation !" << endl;
891 ofConsole.unlockCerr();
892 }
893 } else
894 ImageStatus = EIS_InvalidImage;
895 }
896 else if (InterData->getData() == NULL)
897 ImageStatus = EIS_InvalidImage;
898 else if (mode && (ImageStatus == EIS_Normal))
899 {
900 const unsigned long count = (unsigned long)Columns * (unsigned long)Rows * NumberOfFrames;
901 if ((InterData->getInputCount() != count) && ((InterData->getInputCount() >> 1) != ((count + 1) >> 1)))
902 {
903 if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_Warnings))
904 {
905 ofConsole.lockCerr() << "WARNING: computed (" << count
906 << ") and stored (" << InterData->getInputCount() << ") "
907 << "pixel count differ !" << endl;
908 ofConsole.unlockCerr();
909 }
910 }
911 }
912 return (ImageStatus == EIS_Normal);
913 }
914
915
deleteOutputData()916 void DiMonoImage::deleteOutputData()
917 {
918 delete OutputData;
919 OutputData = NULL;
920 }
921
922
getOutputPlane(const int) const923 void *DiMonoImage::getOutputPlane(const int) const
924 {
925 if (OutputData != NULL)
926 return (void *)OutputData->getData(); // monochrome images don't have several planes
927 return NULL;
928 }
929
930
deleteOverlayData()931 void DiMonoImage::deleteOverlayData()
932 {
933 delete (char *)OverlayData; // type cast necessary to avoid compiler warnings using gcc 2.95
934 OverlayData = NULL;
935 }
936
937
938 /*********************************************************************/
939
940
getMinMaxValues(double & min,double & max,const int mode) const941 int DiMonoImage::getMinMaxValues(double &min,
942 double &max,
943 const int mode) const
944 {
945 if (InterData != NULL)
946 {
947 if (mode)
948 {
949 min = InterData->getAbsMinimum();
950 max = InterData->getAbsMaximum();
951 return 1;
952 }
953 return InterData->getMinMaxValues(min, max);
954 }
955 return 0;
956 }
957
958
setDisplayFunction(DiDisplayFunction * display)959 int DiMonoImage::setDisplayFunction(DiDisplayFunction *display)
960 {
961 DisplayFunction = display;
962 return (DisplayFunction != NULL) && (DisplayFunction->isValid());
963 }
964
965
setNoDisplayFunction()966 int DiMonoImage::setNoDisplayFunction()
967 {
968 if (DisplayFunction != NULL)
969 {
970 DisplayFunction = NULL;
971 return 1;
972 }
973 return 2;
974 }
975
976
convertPValueToDDL(const Uint16 pvalue,Uint16 & ddl,const int bits)977 int DiMonoImage::convertPValueToDDL(const Uint16 pvalue,
978 Uint16 &ddl,
979 const int bits)
980 {
981 const unsigned long maxvalue = DicomImageClass::maxval(bits);
982 if ((DisplayFunction != NULL) && (DisplayFunction->isValid()) && (DisplayFunction->getMaxDDLValue() == maxvalue))
983 {
984 const DiDisplayLUT *dlut = DisplayFunction->getLookupTable(WIDTH_OF_PVALUES);
985 if ((dlut != NULL) && (dlut->isValid()))
986 {
987 ddl = dlut->getValue(pvalue); // perform display transformation
988 return 1;
989 }
990 }
991 if ((bits >= 1) && (bits <= WIDTH_OF_PVALUES)) // no display function: perform linear scaling
992 {
993 ddl = (Uint16)((double)maxvalue * (double)pvalue / (double)DicomImageClass::maxval(WIDTH_OF_PVALUES));
994 return 2;
995 }
996 return 0;
997 }
998
999
setNoVoiTransformation()1000 int DiMonoImage::setNoVoiTransformation()
1001 {
1002 int old = 2;
1003 if (VoiLutData != NULL)
1004 {
1005 if (VoiLutData->isValid())
1006 old = 1;
1007 VoiLutData->removeReference();
1008 }
1009 VoiLutData = NULL;
1010 VoiExplanation = "";
1011 if (ValidWindow)
1012 old = 1;
1013 ValidWindow = 0;
1014 return old;
1015 }
1016
1017
setMinMaxWindow(const int idx)1018 int DiMonoImage::setMinMaxWindow(const int idx)
1019 {
1020 if (InterData != NULL)
1021 {
1022 double center;
1023 double width;
1024 if (InterData->getMinMaxWindow(idx != 0, center, width))
1025 return setWindow(center, width, "Min-Max Window");
1026 }
1027 return 0;
1028 }
1029
1030
setRoiWindow(const unsigned long left_pos,const unsigned long top_pos,const unsigned long width,const unsigned long height,const unsigned long frame)1031 int DiMonoImage::setRoiWindow(const unsigned long left_pos,
1032 const unsigned long top_pos,
1033 const unsigned long width,
1034 const unsigned long height,
1035 const unsigned long frame)
1036 {
1037 if ((InterData != NULL) && (frame < NumberOfFrames))
1038 {
1039 double voiCenter;
1040 double voiWidth;
1041 if (InterData->getRoiWindow(left_pos, top_pos, width, height, Columns, Rows, frame, voiCenter, voiWidth))
1042 return setWindow(voiCenter, voiWidth, "ROI Window");
1043 }
1044 return 0;
1045 }
1046
1047
setHistogramWindow(const double thresh)1048 int DiMonoImage::setHistogramWindow(const double thresh)
1049 {
1050 if (InterData != NULL)
1051 {
1052 double center;
1053 double width;
1054 if (InterData->getHistogramWindow(thresh, center, width))
1055 return setWindow(center, width, "Histogram Window");
1056 }
1057 return 0;
1058 }
1059
1060
setWindow(const unsigned long pos)1061 int DiMonoImage::setWindow(const unsigned long pos)
1062 {
1063 if (!(Document->getFlags() & CIF_UsePresentationState))
1064 {
1065 double center;
1066 double width;
1067 WindowCount = Document->getValue(DCM_WindowCenter, center, pos);
1068 unsigned long count = Document->getValue(DCM_WindowWidth, width, pos);
1069 if (count < WindowCount)
1070 WindowCount = count;
1071 if (pos < WindowCount)
1072 {
1073 /* save return value to be used later (setWindow clears the explanation string!) */
1074 const int result = setWindow(center, width);
1075 /* get the stored explanation string */
1076 Document->getValue(DCM_WindowCenterWidthExplanation, VoiExplanation, pos);
1077 return result;
1078 }
1079 }
1080 return 0;
1081 }
1082
1083
setWindow(const double center,const double width,const char * explanation)1084 int DiMonoImage::setWindow(const double center,
1085 const double width,
1086 const char *explanation)
1087 {
1088 if (VoiLutData != NULL)
1089 VoiLutData->removeReference();
1090 VoiLutData = NULL;
1091 if (explanation != NULL)
1092 VoiExplanation = explanation;
1093 else
1094 VoiExplanation = "";
1095 if (width < 1) // not valid, according to supplement 33
1096 return ValidWindow = 0;
1097 else if (!ValidWindow || (center != WindowCenter) || (width != WindowWidth))
1098 {
1099 WindowCenter = center;
1100 WindowWidth = width;
1101 return ValidWindow = 1;
1102 }
1103 return 2; // window is unchanged (and valid)
1104 }
1105
1106
getWindow(double & center,double & width)1107 int DiMonoImage::getWindow(double ¢er, double &width)
1108 {
1109 if (ValidWindow)
1110 {
1111 center = WindowCenter;
1112 width = WindowWidth;
1113 return 1;
1114 }
1115 return 0;
1116 }
1117
1118
setVoiLut(const DcmUnsignedShort & data,const DcmUnsignedShort & descriptor,const DcmLongString * explanation)1119 int DiMonoImage::setVoiLut(const DcmUnsignedShort &data,
1120 const DcmUnsignedShort &descriptor,
1121 const DcmLongString *explanation)
1122 {
1123 if (VoiLutData != NULL)
1124 VoiLutData->removeReference();
1125 VoiLutData = new DiLookupTable(data, descriptor, explanation);
1126 if (VoiLutData != NULL)
1127 {
1128 VoiExplanation = VoiLutData->getExplanation();
1129 return VoiLutData->isValid();
1130 }
1131 VoiExplanation = "";
1132 return 0;
1133 }
1134
1135
setVoiLut(const unsigned long pos)1136 int DiMonoImage::setVoiLut(const unsigned long pos)
1137 {
1138 if (!(Document->getFlags() & CIF_UsePresentationState))
1139 {
1140 if (VoiLutData != NULL)
1141 VoiLutData->removeReference();
1142 VoiLutData = new DiLookupTable(Document, DCM_VOILUTSequence, DCM_LUTDescriptor, DCM_LUTData,
1143 DCM_LUTExplanation, pos, &VoiLutCount);
1144 if (VoiLutData != NULL)
1145 {
1146 VoiExplanation = VoiLutData->getExplanation();
1147 return VoiLutData->isValid();
1148 }
1149 VoiExplanation = "";
1150 }
1151 return 0;
1152 }
1153
1154
getVoiWindowExplanation(const unsigned long pos,OFString & explanation) const1155 const char *DiMonoImage::getVoiWindowExplanation(const unsigned long pos,
1156 OFString &explanation) const
1157 {
1158 const char *result = NULL;
1159 /* get the stored explanation string */
1160 if (Document->getValue(DCM_WindowCenterWidthExplanation, explanation, pos) > 0)
1161 result = explanation.c_str();
1162 return result;
1163 }
1164
1165
getVoiLutExplanation(const unsigned long pos,OFString & explanation) const1166 const char *DiMonoImage::getVoiLutExplanation(const unsigned long pos,
1167 OFString &explanation) const
1168 {
1169 const char *result = NULL;
1170 /* get the given sequence item ... */
1171 DcmSequenceOfItems *seq = NULL;
1172 if ((pos < Document->getSequence(DCM_VOILUTSequence, seq)) && (seq != NULL))
1173 {
1174 /* ... and then the stored explanation string */
1175 if (Document->getValue(DCM_LUTExplanation, explanation, 0 /*vm pos*/, seq->getItem(pos)) > 0)
1176 result = explanation.c_str();
1177 }
1178 return result;
1179 }
1180
1181
setHardcopyParameters(const unsigned int min,const unsigned int max,const unsigned int reflect,const unsigned int illumin)1182 int DiMonoImage::setHardcopyParameters(const unsigned int min,
1183 const unsigned int max,
1184 const unsigned int reflect,
1185 const unsigned int illumin)
1186 {
1187 int result = 0;
1188 if (min < max)
1189 {
1190 result = 2;
1191 if (min != MinDensity)
1192 {
1193 MinDensity = min;
1194 result = 1;
1195 }
1196 if (max != MaxDensity)
1197 {
1198 MaxDensity = max;
1199 result = 1;
1200 }
1201 if (reflect != Reflection)
1202 {
1203 Reflection = reflect;
1204 result = 1;
1205 }
1206 if (illumin != Illumination)
1207 {
1208 Illumination = illumin;
1209 result = 1;
1210 }
1211 if ((result == 1) && (PresLutShape == ESP_LinOD) && (PresLutData != NULL))
1212 {
1213 PresLutData->removeReference(); // look-up table no longer valid
1214 PresLutData = NULL;
1215 }
1216 }
1217 return result;
1218 }
1219
1220
getPresentationLutShape() const1221 ES_PresentationLut DiMonoImage::getPresentationLutShape() const
1222 {
1223 return (PresLutData != NULL) ? ESP_Default : PresLutShape;
1224 }
1225
1226
setPresentationLutShape(const ES_PresentationLut shape)1227 int DiMonoImage::setPresentationLutShape(const ES_PresentationLut shape)
1228 {
1229 if (PresLutData != NULL)
1230 PresLutData->removeReference();
1231 PresLutData = NULL;
1232 if (shape != PresLutShape)
1233 {
1234 PresLutShape = shape;
1235 return 1;
1236 }
1237 return 2;
1238 }
1239
1240
setPresentationLut(const DcmUnsignedShort & data,const DcmUnsignedShort & descriptor,const DcmLongString * explanation)1241 int DiMonoImage::setPresentationLut(const DcmUnsignedShort &data,
1242 const DcmUnsignedShort &descriptor,
1243 const DcmLongString *explanation)
1244 {
1245 if (PresLutData != NULL)
1246 PresLutData->removeReference();
1247 PresLutData = new DiLookupTable(data, descriptor, explanation, 0);
1248 if (PresLutData != NULL)
1249 {
1250 PresLutShape = ESP_Default;
1251 return PresLutData->isValid();
1252 }
1253 return 0;
1254 }
1255
1256
setInversePresentationLut(const DcmUnsignedShort & data,const DcmUnsignedShort & descriptor)1257 int DiMonoImage::setInversePresentationLut(const DcmUnsignedShort &data,
1258 const DcmUnsignedShort &descriptor)
1259 {
1260 int status = 0;
1261 if (PresLutData != NULL)
1262 PresLutData->removeReference();
1263 PresLutData = NULL;
1264 DiLookupTable *lut = new DiLookupTable(data, descriptor, NULL, 0);
1265 if ((lut != NULL) && (lut->isValid()))
1266 {
1267 PresLutData = lut->createInverseLUT();
1268 if (PresLutData != NULL)
1269 status = PresLutData->isValid();
1270 }
1271 delete lut;
1272 return status;
1273 }
1274
1275
addOverlay(const unsigned int group,const signed int left_pos,const signed int top_pos,const unsigned int columns,const unsigned int rows,const DcmOverlayData & data,const DcmLongString & label,const DcmLongString & description,const EM_Overlay mode)1276 int DiMonoImage::addOverlay(const unsigned int group,
1277 const signed int left_pos,
1278 const signed int top_pos,
1279 const unsigned int columns,
1280 const unsigned int rows,
1281 const DcmOverlayData &data,
1282 const DcmLongString &label,
1283 const DcmLongString &description,
1284 const EM_Overlay mode)
1285 {
1286 if (Overlays[1] == NULL)
1287 Overlays[1] = new DiOverlay();
1288 if (Overlays[1] != NULL)
1289 return Overlays[1]->addPlane(group, left_pos, top_pos, columns, rows, data, label, description, mode);
1290 return 0;
1291 }
1292
1293
removeAllOverlays()1294 int DiMonoImage::removeAllOverlays()
1295 {
1296 if (Overlays[1] != NULL)
1297 {
1298 delete Overlays[1];
1299 Overlays[1] = NULL;
1300 return 1;
1301 }
1302 return 2;
1303 }
1304
1305
flip(const int horz,const int vert)1306 int DiMonoImage::flip(const int horz,
1307 const int vert)
1308 {
1309 switch (InterData->getRepresentation())
1310 {
1311 case EPR_Uint8:
1312 {
1313 DiFlipTemplate<Uint8> dummy(InterData, Columns, Rows, NumberOfFrames, horz, vert);
1314 }
1315 break;
1316 case EPR_Sint8:
1317 {
1318 DiFlipTemplate<Sint8> dummy(InterData, Columns, Rows, NumberOfFrames, horz, vert);
1319 }
1320 break;
1321 case EPR_Uint16:
1322 {
1323 DiFlipTemplate<Uint16> dummy(InterData, Columns, Rows, NumberOfFrames, horz, vert);
1324 }
1325 break;
1326 case EPR_Sint16:
1327 {
1328 DiFlipTemplate<Sint16> dummy(InterData, Columns, Rows, NumberOfFrames, horz, vert);
1329 }
1330 break;
1331 case EPR_Uint32:
1332 {
1333 DiFlipTemplate<Uint32> dummy(InterData, Columns, Rows, NumberOfFrames, horz, vert);
1334 }
1335 break;
1336 case EPR_Sint32:
1337 {
1338 DiFlipTemplate<Sint32> dummy(InterData, Columns, Rows, NumberOfFrames, horz, vert);
1339 }
1340 break;
1341 }
1342 for (int i = 0; i < 2; i++)
1343 {
1344 if ((Overlays[i] != NULL) && (Overlays[i]->getCount() > 0))
1345 {
1346 DiOverlay *old = Overlays[i];
1347 Overlays[i] = new DiOverlay(old, horz, vert, Columns, Rows);
1348 old->removeReference();
1349 }
1350 }
1351 return 1;
1352 }
1353
1354
rotate(const int degree)1355 int DiMonoImage::rotate(const int degree)
1356 {
1357 const Uint16 old_cols = Columns; // save old values
1358 const Uint16 old_rows = Rows;
1359 DiImage::rotate(degree); // swap width and height if necessary
1360 if ((Columns > 1) && (Rows > 1)) // re-interpret pixel data for cols = 1 or rows = 1
1361 {
1362 switch (InterData->getRepresentation())
1363 {
1364 case EPR_Uint8:
1365 {
1366 DiRotateTemplate<Uint8> dummy(InterData, old_cols, old_rows, Columns, Rows, NumberOfFrames, degree);
1367 }
1368 break;
1369 case EPR_Sint8:
1370 {
1371 DiRotateTemplate<Sint8> dummy(InterData, old_cols, old_rows, Columns, Rows, NumberOfFrames, degree);
1372 }
1373 break;
1374 case EPR_Uint16:
1375 {
1376 DiRotateTemplate<Uint16> dummy(InterData, old_cols, old_rows, Columns, Rows, NumberOfFrames, degree);
1377 }
1378 break;
1379 case EPR_Sint16:
1380 {
1381 DiRotateTemplate<Sint16> dummy(InterData, old_cols, old_rows, Columns, Rows, NumberOfFrames, degree);
1382 }
1383 break;
1384 case EPR_Uint32:
1385 {
1386 DiRotateTemplate<Uint32> dummy(InterData, old_cols, old_rows, Columns, Rows, NumberOfFrames, degree);
1387 }
1388 break;
1389 case EPR_Sint32:
1390 {
1391 DiRotateTemplate<Sint32> dummy(InterData, old_cols, old_rows, Columns, Rows, NumberOfFrames, degree);
1392 }
1393 break;
1394 }
1395 }
1396 for (int i = 0; i < 2; i++)
1397 {
1398 if ((Overlays[i] != NULL) && (Overlays[i]->getCount() > 0))
1399 {
1400 DiOverlay *old = Overlays[i];
1401 Overlays[i] = new DiOverlay(old, degree, Columns, Rows);
1402 old->removeReference();
1403 }
1404 }
1405 return 1;
1406 }
1407
1408
1409 /*********************************************************************/
1410
1411
1412 /*
1413 * create output data of 'frame' with depth of 'bits' and min/max values depending on 'negative' (support mono1/2)
1414 */
1415
getData(void * buffer,const unsigned long size,const unsigned long frame,int bits,const int,const int negative)1416 void *DiMonoImage::getData(void *buffer,
1417 const unsigned long size,
1418 const unsigned long frame,
1419 int bits,
1420 const int /*planar*/, /* not yet supported, needed for pastel color images !! */
1421 const int negative)
1422 {
1423 if ((InterData != NULL) && (ImageStatus == EIS_Normal) && (frame < NumberOfFrames) &&
1424 (((bits > 0) && (bits <= MAX_BITS)) || (bits == MI_PastelColor)))
1425 {
1426 int samples = 1;
1427 if (bits == MI_PastelColor) // use true color pastel mode
1428 {
1429 bits = 8;
1430 samples = 3;
1431 }
1432 if ((buffer == NULL) || (size >= (unsigned long)Columns * (unsigned long)Rows * samples * ((bits + 7) / 8)))
1433 {
1434 deleteOutputData(); // delete old image data
1435 if (!ValidWindow)
1436 WindowWidth = -1; // negative width means no window, saves additional parameter ;)
1437 Uint32 low;
1438 Uint32 high;
1439 if ((PresLutData == NULL) &&
1440 (PresLutShape == ESP_Inverse || (negative && (PresLutShape == ESP_Default))))
1441 {
1442 low = DicomImageClass::maxval(bits); // inverse/negative: white to black
1443 high = 0;
1444 } else {
1445 low = 0; // normal/positive: black to white
1446 high = DicomImageClass::maxval(bits);
1447 }
1448 if ((PresLutData == NULL) && (PresLutShape == ESP_LinOD))
1449 {
1450 if (!createLinODPresentationLut(4096, 16)) // create presentation LUT converting linOD data (on demand)
1451 {
1452 if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_Warnings))
1453 {
1454 ofConsole.lockCerr() << "WARNING: could not create presentation LUT for LinOD conversion" << endl
1455 << " ... ignoring presentation LUT shape LinOD !" << endl;
1456 ofConsole.unlockCerr();
1457 }
1458 }
1459 }
1460 if (Polarity == EPP_Reverse) // swap high and low value
1461 {
1462 Uint32 temp = low;
1463 low = high;
1464 high = temp;
1465 }
1466 DiDisplayFunction *disp = DisplayFunction;
1467 if ((disp != NULL) && (disp->isValid()) && (disp->getMaxDDLValue() != DicomImageClass::maxval(bits)))
1468 {
1469 if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_Warnings))
1470 {
1471 ofConsole.lockCerr() << "WARNING: selected display function doesn't fit to requested output depth ("
1472 << bits << ")" << endl << " ... ignoring display transformation !" << endl;
1473 ofConsole.unlockCerr();
1474 }
1475 disp = NULL;
1476 }
1477 switch (InterData->getRepresentation())
1478 {
1479 case EPR_Uint8:
1480 getDataUint8(buffer, disp, samples, frame, bits, low, high);
1481 break;
1482 case EPR_Sint8:
1483 getDataSint8(buffer, disp, samples, frame, bits, low, high);
1484 break;
1485 case EPR_Uint16:
1486 getDataUint16(buffer, disp, samples, frame, bits, low, high);
1487 break;
1488 case EPR_Sint16:
1489 getDataSint16(buffer, disp, samples, frame, bits, low, high);
1490 break;
1491 case EPR_Uint32:
1492 getDataUint32(buffer, disp, samples, frame, bits, low, high);
1493 break;
1494 case EPR_Sint32:
1495 getDataSint32(buffer, disp, samples, frame, bits, low, high);
1496 break;
1497 }
1498 if (OutputData == NULL)
1499 {
1500 ImageStatus = EIS_MemoryFailure;
1501 if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_Errors))
1502 {
1503 ofConsole.lockCerr() << "ERROR: can't allocate memory for output-representation !" << endl;
1504 ofConsole.unlockCerr();
1505 }
1506 }
1507 else
1508 return OutputData->getData(); // points to beginning of output data
1509 } else {
1510 if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_Errors))
1511 {
1512 ofConsole.lockCerr() << "ERROR: given output buffer is too small (only " << size << " bytes) !" << endl;
1513 ofConsole.unlockCerr();
1514 }
1515 }
1516 }
1517 return NULL;
1518 }
1519
1520
1521 /*
1522 * create 1/8/16-bit (bi-level) bitmap with overlay 'plane' data
1523 */
1524
getOverlayData(const unsigned long frame,const unsigned int plane,unsigned int & left_pos,unsigned int & top_pos,unsigned int & width,unsigned int & height,EM_Overlay & mode,const unsigned int idx,const int bits,const Uint16 fore,const Uint16 back)1525 const void *DiMonoImage::getOverlayData(const unsigned long frame,
1526 const unsigned int plane,
1527 unsigned int &left_pos,
1528 unsigned int &top_pos,
1529 unsigned int &width,
1530 unsigned int &height,
1531 EM_Overlay &mode,
1532 const unsigned int idx,
1533 const int bits,
1534 const Uint16 fore,
1535 const Uint16 back)
1536 {
1537 if ((ImageStatus == EIS_Normal) && (bits > 0) && (bits <= 16) && (fore != back))
1538 {
1539 int start = 1; // default: additional overlay planes hide dataset planes
1540 int end = 0;
1541 if (idx < 2) // specified index of overlay group
1542 start = end = idx;
1543 for (int i = start; i >= end; i--) // start searching with additional overlay planes
1544 {
1545 if ((Overlays[i] != NULL) && (Overlays[i]->hasPlane(plane)))
1546 {
1547 deleteOverlayData();
1548 OverlayData = Overlays[i]->getPlaneData(frame, plane, left_pos, top_pos, width, height,
1549 mode, Columns, Rows, bits, fore, back);
1550 return (const void *)OverlayData;
1551 }
1552 }
1553 }
1554 return NULL;
1555 }
1556
1557
1558 /*
1559 * create 1/8/16-bit (bi-level) bitmap with overlay 'plane' data
1560 */
1561
getFullOverlayData(const unsigned long frame,const unsigned int plane,unsigned int & width,unsigned int & height,const unsigned int idx,const int bits,const Uint16 fore,const Uint16 back)1562 const void *DiMonoImage::getFullOverlayData(const unsigned long frame,
1563 const unsigned int plane,
1564 unsigned int &width,
1565 unsigned int &height,
1566 const unsigned int idx,
1567 const int bits,
1568 const Uint16 fore,
1569 const Uint16 back)
1570 {
1571 if ((ImageStatus == EIS_Normal) && (bits > 0) && (bits <= 16) && (fore != back))
1572 {
1573 if ((idx < 2) && (Overlays[idx] != NULL) && (Overlays[idx]->hasPlane(plane)))
1574 {
1575 deleteOverlayData();
1576 OverlayData = Overlays[idx]->getFullPlaneData(frame, plane, width, height, bits, fore, back);
1577 return (const void *)OverlayData;
1578 }
1579 }
1580 return NULL;
1581 }
1582
1583
1584 /*
1585 * create 1-bit (bi-level) bitmap with overlay 'plane' data
1586 * as required for the (6xxx,3000) OverlayData format
1587 */
1588
create6xxx3000OverlayData(Uint8 * & buffer,const unsigned int plane,unsigned int & width,unsigned int & height,unsigned long & frames,const unsigned int idx)1589 unsigned long DiMonoImage::create6xxx3000OverlayData(Uint8 *&buffer,
1590 const unsigned int plane,
1591 unsigned int &width,
1592 unsigned int &height,
1593 unsigned long &frames,
1594 const unsigned int idx)
1595 {
1596 if (ImageStatus == EIS_Normal)
1597 {
1598 if ((idx < 2) && (Overlays[idx] != NULL) && (Overlays[idx]->hasPlane(plane)))
1599 return Overlays[idx]->create6xxx3000PlaneData(buffer, plane, width, height, frames);
1600 }
1601 return 0;
1602 }
1603
1604
1605 /*
1606 * create 8-bit palette/monochrome or 24/32-bit true color device independent bitmap (DIB) as needed by MS-Windows
1607 */
1608
createDIB(void * & data,const unsigned long size,const unsigned long frame,const int bits,const int upsideDown,const int padding)1609 unsigned long DiMonoImage::createDIB(void *&data,
1610 const unsigned long size,
1611 const unsigned long frame,
1612 const int bits,
1613 const int upsideDown,
1614 const int padding)
1615 {
1616 unsigned long bytes = 0;
1617 if (size == 0)
1618 data = NULL;
1619 if ((bits == 8) || (bits == 24) || (bits == 32))
1620 {
1621 getOutputData(frame, 8); // create output data with 8 bit depth
1622 if ((OutputData != NULL) && (OutputData->getData() != NULL))
1623 {
1624 const signed long nextRow = (upsideDown) ? -2 * (signed long)Columns : 0;
1625 register const Uint8 *p = (const Uint8 *)(OutputData->getData()) + ((upsideDown) ? (unsigned long)(Rows - 1) * (unsigned long)Columns : 0);
1626 if (bits == 8) // -- for idx color model (byte)
1627 {
1628 // each line has to start at 32-bit-address, if 'padding' is true
1629 const int gap = (padding) ? (4 - (Columns & 0x3)) & 0x3 : 0;
1630 const unsigned long count = (unsigned long)(Columns + gap) * (unsigned long)Rows;
1631 if ((gap > 0) || (nextRow != 0) || (data != NULL))
1632 {
1633 if ((data == NULL) || (size >= count))
1634 {
1635 if (data == NULL)
1636 data = new Uint8[count]; // allocated memory buffer
1637 if (data != NULL)
1638 {
1639 register Uint8 *q = (Uint8 *)data;
1640 register Uint16 x;
1641 register Uint16 y;
1642 for (y = Rows; y != 0; y--)
1643 {
1644 for (x = Columns; x != 0; x--)
1645 *(q++) = *(p++); // store gray value
1646 p += nextRow; // jump (backwards) to next row
1647 q += gap; // skip gap at the end of each line (32-bit boundary)
1648 }
1649 bytes = count;
1650 }
1651 }
1652 } else { // data already aligned and correctly oriented
1653 data = OutputData->getData();
1654 OutputData = NULL; // remove reference to internal memory
1655 bytes = count;
1656 }
1657 }
1658 else if (bits == 24) // -- for direct color model (24 bits/pixel)
1659 {
1660 const unsigned long col3 = (unsigned long)Columns * 3;
1661 // each line has to start at 32-bit-address, if 'padding' is true
1662 const int gap = (padding) ? (int)((4 - (col3 & 0x3)) & 0x3) : 0;
1663 const unsigned long count = (col3 + gap) * (unsigned long)Rows;
1664 if ((data == NULL) || (size >= count))
1665 {
1666 if (data == NULL)
1667 data = new Uint8[count]; // allocated memory buffer
1668 if (data != NULL)
1669 {
1670 register Uint8 *q = (Uint8 *)data;
1671 register Uint8 value;
1672 register Uint16 x;
1673 register Uint16 y;
1674 register int j;
1675 for (y = Rows; y != 0; y--)
1676 {
1677 for (x = Columns; x != 0; x--)
1678 {
1679 value = *(p++); // store gray value
1680 for (j = 3; j != 0; j--)
1681 *(q++) = value; // copy to the three RGB-planes
1682 }
1683 p += nextRow; // jump (backwards) to next row
1684 q += gap; // skip gap at the end of each line (32-bit boundary)
1685 }
1686 bytes = count;
1687 }
1688 }
1689 }
1690 else if (bits == 32) // -- for direct color model (32 bits/pixel)
1691 {
1692 const unsigned long count = (unsigned long)Columns * (unsigned long)Rows;
1693 if ((data == NULL) || (size >= count * 4))
1694 {
1695 if (data == NULL)
1696 data = new Uint32[count]; // allocated memory buffer
1697 if (data != NULL)
1698 {
1699 register Uint32 *q = (Uint32 *)data;
1700 register Uint32 value;
1701 register Uint16 x;
1702 register Uint16 y;
1703 for (y = Rows; y != 0; y--)
1704 {
1705 for (x = Columns; x != 0; x--)
1706 {
1707 value = *(p++); // store gray value
1708 *(q++) = (value << 24) |
1709 (value << 16) |
1710 (value << 8); // copy to the three RGB-planes
1711 }
1712 p += nextRow; // jump (backwards) to next row
1713 }
1714 bytes = count * 4;
1715 }
1716 }
1717 }
1718 }
1719 deleteOutputData(); // output data is no longer needed
1720 }
1721 return bytes;
1722 }
1723
1724
1725 /*
1726 * create 8-bit palette/monochrome or 32-bit true color bitmap as needed for Java/AWT
1727 */
1728
createAWTBitmap(void * & data,const unsigned long frame,const int bits)1729 unsigned long DiMonoImage::createAWTBitmap(void *&data,
1730 const unsigned long frame,
1731 const int bits)
1732 {
1733 data = NULL;
1734 unsigned long bytes = 0;
1735 if (bits == 8) // for idx color model (byte)
1736 {
1737 getOutputData(frame, 8); // create output data with 8 bit depth
1738 if ((OutputData != NULL) && (OutputData->getData() != NULL))
1739 {
1740 bytes = (unsigned long)Columns * (unsigned long)Rows;
1741 data = OutputData->getData();
1742 OutputData = NULL; // remove reference to internal memory
1743 }
1744 }
1745 else if (bits == 32) // for direct color model (long int)
1746 {
1747 getOutputData(frame, 8); // create output data with 8 bit depth
1748 if ((OutputData != NULL) && (OutputData->getData() != NULL))
1749 {
1750 const unsigned long count = (unsigned long)Columns * (unsigned long)Rows;
1751 data = new Uint32[count];
1752 if (data != NULL)
1753 {
1754 register const Uint8 *p = (const Uint8 *)(OutputData->getData());
1755 register Uint32 *q = (Uint32 *)data;
1756 register Uint32 value;
1757 register unsigned long i;
1758 for (i = count; i != 0; i--)
1759 {
1760 value = *(p++); // store gray value
1761 *(q++) = (value << 24) |
1762 (value << 16) |
1763 (value << 8); // copy to the three RGB-planes
1764 }
1765 bytes = count;
1766 }
1767 }
1768 deleteOutputData(); // output data is no longer needed
1769 }
1770 return bytes;
1771 }
1772
1773
1774 /*
1775 * create packed bitmap (e.g. 12 bit for DICOM printers), currently restricted to 12/16 bit
1776 */
1777
createPackedBitmap(const void * buffer,const unsigned long size,const unsigned long count,const int alloc,const int stored)1778 void *DiMonoImage::createPackedBitmap(const void *buffer,
1779 const unsigned long size,
1780 const unsigned long count,
1781 const int alloc, // number of bits allocated in buffer
1782 const int stored) // number of bits stored in buffer
1783 {
1784 if ((buffer != NULL) && (size > 0) && (alloc > 0) && (stored > 0) && (stored < alloc))
1785 {
1786 if ((alloc == 16) && (stored == 12) && ((size * 8 + alloc - 1) / alloc == count))
1787 {
1788 Uint16 *data = NULL;
1789 data = new Uint16[((count + 1) * stored - 1) / 16]; // create new memory buffer
1790 if (data != NULL)
1791 {
1792 register const Uint16 *p = (const Uint16 *)buffer;
1793 register Uint16 *q = data;
1794 register unsigned long i;
1795 register Uint16 value1;
1796 register Uint16 value2;
1797 for (i = 0; i < count - 3; i += 4) // make 3 items out of 4
1798 {
1799 value1 = *(p++);
1800 value2 = *(p++);
1801 *(q++) = (Uint16)((value1 & 0x0fff) | (value2 << 12));
1802 value1 = *(p++);
1803 *(q++) = (Uint16)(((value2 >> 4) & 0x00ff) | (value1 << 8));
1804 value2 = *(p++);
1805 *(q++) = (Uint16)(((value1 >> 8) & 0x000f) | (value2 << 4));
1806 }
1807 switch (count - i) // add remaining pixels
1808 {
1809 case 1: // add 1 pixel
1810 *(q++) = (Uint16)(*(p++) & 0x0fff);
1811 break;
1812 case 2: // add 2 pixels
1813 value1 = *(p++);
1814 value2 = *(p++);
1815 *(q++) = (Uint16)((value1 & 0x0fff) | (value2 << 12));
1816 *(q++) = (Uint16)((value2 >> 4) & 0x00ff);
1817 break;
1818 case 3: // add 3 pixels
1819 value1 = *(p++);
1820 value2 = *(p++);
1821 *(q++) = (Uint16)((value1 & 0x0fff) | (value2 << 12));
1822 value1 = *(p++);
1823 *(q++) = (Uint16)(((value2 >> 4) & 0x00ff) | (value1 << 8));
1824 *(q++) = (Uint16)((value1 >> 8) & 0x000f);
1825 break;
1826 default: // add no pixel
1827 ;
1828 }
1829 return (void *)data;
1830 }
1831 }
1832 }
1833 return NULL;
1834 }
1835
1836
createOutputImage(const unsigned long frame,const int bits)1837 DiImage *DiMonoImage::createOutputImage(const unsigned long frame,
1838 const int bits)
1839 {
1840 getOutputData(frame, bits);
1841 if ((OutputData != NULL) && (OutputData->getData() != NULL))
1842 {
1843 DiImage *image = new DiMono2Image(this, OutputData, frame, bits, OutputData->getItemSize() * 8);
1844 if (image != NULL)
1845 OutputData->removeDataReference(); // output data is now handled by new mono image
1846 return image;
1847 }
1848 return NULL;
1849 }
1850
1851
createLinODPresentationLut(const unsigned long count,const int bits)1852 int DiMonoImage::createLinODPresentationLut(const unsigned long count, const int bits)
1853 {
1854 if ((PresLutData == NULL) && (MinDensity < MaxDensity) &&
1855 (count > 1) && (count <= MAX_TABLE_ENTRY_COUNT) &&
1856 (bits > 0) && (bits <= MAX_TABLE_ENTRY_SIZE))
1857 {
1858 Uint16 *data = new Uint16[count];
1859 if (data != NULL)
1860 {
1861 const double l0 = (double)Illumination;
1862 const double la = (double)Reflection;
1863 const double dmin = (double)MinDensity / 100;
1864 const double dmax = (double)MaxDensity / 100;
1865 const double lmin = la + l0 * pow(10.0, -dmax);
1866 const double lmax = la + l0 * pow(10.0, -dmin);
1867 const double jmin = DiGSDFunction::getJNDIndex(lmin);
1868 const double jmax = DiGSDFunction::getJNDIndex(lmax);
1869 const double factor = (double)DicomImageClass::maxval(bits) / (jmax - jmin);
1870 const double density = (dmax - dmin) / (double)(count - 1);
1871 Uint16 *p = data;
1872 for (unsigned long i = 0; i < count; i++)
1873 *(p++) = (Uint16)((DiGSDFunction::getJNDIndex(la + l0 * pow(10.0, -(dmin + (double)i * density))) - jmin) * factor);
1874 PresLutData = new DiLookupTable(data, count, bits);
1875 return (PresLutData != NULL) && (PresLutData->isValid());
1876 }
1877 }
1878 return 0;
1879 }
1880
1881
1882 /*********************************************************************/
1883
updateImagePixelModuleAttributes(DcmItem & dataset)1884 void DiMonoImage::updateImagePixelModuleAttributes(DcmItem &dataset)
1885 {
1886 DiImage::updateImagePixelModuleAttributes(dataset);
1887 /* replace any modality transformation in the dataset */
1888 if (dataset.tagExists(DCM_RescaleIntercept) ||
1889 dataset.tagExists(DCM_RescaleSlope) ||
1890 dataset.tagExists(DCM_ModalityLUTSequence))
1891 {
1892 dataset.putAndInsertString(DCM_RescaleIntercept, "0");
1893 dataset.putAndInsertString(DCM_RescaleSlope, "1");
1894 delete dataset.remove(DCM_ModalityLUTSequence);
1895 }
1896 /* remove overlays */
1897 for (Uint16 grp = 0x6000; grp < 0x601f; grp += 2)
1898 {
1899 /* attributes from Overlay Plane Module in group 0x6000-0x601f */
1900 delete dataset.remove(DcmTagKey(grp, DCM_OverlayGroupLength.getElement()));
1901 delete dataset.remove(DcmTagKey(grp, DCM_OverlayRows.getElement()));
1902 delete dataset.remove(DcmTagKey(grp, DCM_OverlayColumns.getElement()));
1903 delete dataset.remove(DcmTagKey(grp, DCM_OverlayPlanes.getElement()));
1904 delete dataset.remove(DcmTagKey(grp, DCM_NumberOfFramesInOverlay.getElement()));
1905 delete dataset.remove(DcmTagKey(grp, DCM_OverlayDescription.getElement()));
1906 delete dataset.remove(DcmTagKey(grp, DCM_OverlayType.getElement()));
1907 delete dataset.remove(DcmTagKey(grp, DCM_OverlaySubtype.getElement()));
1908 delete dataset.remove(DcmTagKey(grp, DCM_OverlayOrigin.getElement()));
1909 delete dataset.remove(DcmTagKey(grp, DCM_ImageFrameOrigin.getElement()));
1910 delete dataset.remove(DcmTagKey(grp, DCM_OverlayPlaneOrigin.getElement()));
1911 delete dataset.remove(DcmTagKey(grp, DCM_OverlayBitsAllocated.getElement()));
1912 delete dataset.remove(DcmTagKey(grp, DCM_OverlayBitPosition.getElement()));
1913 delete dataset.remove(DcmTagKey(grp, DCM_OverlayLabel.getElement()));
1914 delete dataset.remove(DcmTagKey(grp, DCM_OverlayData.getElement()));
1915 }
1916 }
1917
1918
1919 // --- write current image to DICOM dataset
1920
writeImageToDataset(DcmItem & dataset)1921 int DiMonoImage::writeImageToDataset(DcmItem &dataset)
1922 {
1923 int result = 0;
1924 if (InterData != NULL)
1925 {
1926 void *pixel = InterData->getData();
1927 const unsigned long count = InterData->getCount();
1928 if ((BitsPerSample > 0) && (pixel != NULL) && (count > 0))
1929 {
1930 /* set color model */
1931 if (getInternalColorModel() == EPI_Monochrome1)
1932 dataset.putAndInsertString(DCM_PhotometricInterpretation, "MONOCHROME1");
1933 else
1934 dataset.putAndInsertString(DCM_PhotometricInterpretation, "MONOCHROME2");
1935 /* set image resolution */
1936 dataset.putAndInsertUint16(DCM_Columns, Columns);
1937 dataset.putAndInsertUint16(DCM_Rows, Rows);
1938 dataset.putAndInsertSint32(DCM_NumberOfFrames, NumberOfFrames);
1939 dataset.putAndInsertUint16(DCM_SamplesPerPixel, 1);
1940 /* set pixel encoding and data */
1941 switch (InterData->getRepresentation())
1942 {
1943 case EPR_Uint8:
1944 dataset.putAndInsertUint16(DCM_BitsAllocated, 8);
1945 dataset.putAndInsertUint16(DCM_PixelRepresentation, 0);
1946 dataset.putAndInsertUint8Array(DCM_PixelData, (Uint8 *)pixel, count);
1947 break;
1948 case EPR_Sint8:
1949 dataset.putAndInsertUint16(DCM_BitsAllocated, 8);
1950 dataset.putAndInsertUint16(DCM_PixelRepresentation, 1);
1951 dataset.putAndInsertUint8Array(DCM_PixelData, (Uint8 *)pixel, count);
1952 break;
1953 case EPR_Uint16:
1954 dataset.putAndInsertUint16(DCM_BitsAllocated, 16);
1955 dataset.putAndInsertUint16(DCM_PixelRepresentation, 0);
1956 dataset.putAndInsertUint16Array(DCM_PixelData, (Uint16 *)pixel, count);
1957 break;
1958 case EPR_Sint16:
1959 dataset.putAndInsertUint16(DCM_BitsAllocated, 16);
1960 dataset.putAndInsertUint16(DCM_PixelRepresentation, 1);
1961 dataset.putAndInsertUint16Array(DCM_PixelData, (Uint16 *)pixel, count);
1962 break;
1963 case EPR_Uint32:
1964 dataset.putAndInsertUint16(DCM_BitsAllocated, 32);
1965 dataset.putAndInsertUint16(DCM_PixelRepresentation, 0);
1966 dataset.putAndInsertUint16Array(DCM_PixelData, (Uint16 *)pixel, count);
1967 break;
1968 case EPR_Sint32:
1969 dataset.putAndInsertUint16(DCM_BitsAllocated, 32);
1970 dataset.putAndInsertUint16(DCM_PixelRepresentation, 1);
1971 dataset.putAndInsertUint16Array(DCM_PixelData, (Uint16 *)pixel, count);
1972 break;
1973 }
1974 dataset.putAndInsertUint16(DCM_BitsStored, BitsPerSample);
1975 dataset.putAndInsertUint16(DCM_HighBit, BitsPerSample - 1);
1976 /* update other DICOM attributes */
1977 updateImagePixelModuleAttributes(dataset);
1978 result = 1;
1979 }
1980 }
1981 return result;
1982 }
1983
1984
1985 /*
1986 * write output data of 'frame' with depth of 'bits' to C++-output 'stream' (format is PGM - portable gray map)
1987 */
1988
writePPM(ostream & stream,const unsigned long frame,const int bits)1989 int DiMonoImage::writePPM(ostream &stream,
1990 const unsigned long frame,
1991 const int bits)
1992 {
1993 getOutputData(frame, bits);
1994 if (OutputData != NULL)
1995 {
1996 if (bits == MI_PastelColor)
1997 {
1998 stream << "P3" << endl;
1999 stream << Columns << " " << Rows << endl;
2000 stream << "255" << endl;
2001 } else {
2002 stream << "P2" << endl;
2003 stream << Columns << " " << Rows << endl;
2004 stream << DicomImageClass::maxval(bits) << endl;
2005 }
2006 int ok = OutputData->writePPM(stream);
2007 deleteOutputData();
2008 return ok;
2009 }
2010 return 0;
2011 }
2012
2013
2014 /*
2015 * write output data of 'frame' with depth of 'bits' to C-file 'stream' (format is PGM - portable gray map)
2016 */
2017
writePPM(FILE * stream,const unsigned long frame,const int bits)2018 int DiMonoImage::writePPM(FILE *stream,
2019 const unsigned long frame,
2020 const int bits)
2021 {
2022 if (stream != NULL)
2023 {
2024 getOutputData(frame, bits);
2025 if (OutputData != NULL)
2026 {
2027 if (bits == MI_PastelColor)
2028 fprintf(stream, "P3\n%u %u\n255\n", Columns, Rows);
2029 else
2030 fprintf(stream, "P2\n%u %u\n%lu\n", Columns, Rows, DicomImageClass::maxval(bits));
2031 int ok = OutputData->writePPM(stream);
2032 deleteOutputData();
2033 return ok;
2034 }
2035 }
2036 return 0;
2037 }
2038
2039
2040 /*
2041 * write output data of 'frame' with depth of 'bits' (max. 8) to C-file 'stream' (format is RAW-PGM - binary PGM)
2042 */
2043
writeRawPPM(FILE * stream,const unsigned long frame,const int bits)2044 int DiMonoImage::writeRawPPM(FILE *stream,
2045 const unsigned long frame,
2046 const int bits)
2047 {
2048 if ((stream != NULL) && (bits <= MAX_RAWPPM_BITS))
2049 {
2050 getOutputData(frame, bits);
2051 if ((OutputData != NULL) && (OutputData->getData() != NULL))
2052 {
2053 if (bits == MI_PastelColor)
2054 fprintf(stream, "P6\n%u %u\n255\n", Columns, Rows);
2055 else
2056 fprintf(stream, "P5\n%u %u\n%lu\n", Columns, Rows, DicomImageClass::maxval(bits));
2057 fwrite(OutputData->getData(), (size_t)OutputData->getCount(), OutputData->getItemSize(), stream);
2058 deleteOutputData();
2059 return 1;
2060 }
2061 }
2062 return 0;
2063 }
2064
2065
2066 /*
2067 * write output data of 'frame' with depth of 'bits' (8 or 24) to C-file 'stream' (format is BMP)
2068 */
2069
writeBMP(FILE * stream,const unsigned long frame,const int bits)2070 int DiMonoImage::writeBMP(FILE *stream,
2071 const unsigned long frame,
2072 const int bits)
2073 {
2074 if ((bits == 0) || (bits == 8) || (bits == 24))
2075 return DiImage::writeBMP(stream, frame, (bits == 0) ? 8 : bits);
2076 return 0;
2077 }
2078