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 &center, 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