1 /*
2  *
3  *  Copyright (C) 1996-2018, OFFIS e.V.
4  *  All rights reserved.  See COPYRIGHT file for details.
5  *
6  *  This software and supporting documentation were developed by
7  *
8  *    OFFIS e.V.
9  *    R&D Division Health
10  *    Escherweg 2
11  *    D-26121 Oldenburg, Germany
12  *
13  *
14  *  Module:  dcmimgle
15  *
16  *  Author:  Joerg Riesmeier
17  *
18  *  Purpose: Utilities (Header)
19  *
20  */
21 
22 
23 #ifndef DIUTILS_H
24 #define DIUTILS_H
25 
26 #include "dcmtk/config/osconfig.h"
27 
28 #include "dcmtk/ofstd/oftypes.h"
29 #include "dcmtk/ofstd/ofcast.h"
30 
31 #include "dcmtk/oflog/oflog.h"
32 
33 #include "dcmtk/dcmimgle/didefine.h"
34 
35 extern DCMTK_DCMIMGLE_EXPORT OFLogger DCM_dcmimgleLogger;
36 
37 #define DCMIMGLE_TRACE(msg) OFLOG_TRACE(DCM_dcmimgleLogger, msg)
38 #define DCMIMGLE_DEBUG(msg) OFLOG_DEBUG(DCM_dcmimgleLogger, msg)
39 #define DCMIMGLE_INFO(msg)  OFLOG_INFO(DCM_dcmimgleLogger, msg)
40 #define DCMIMGLE_WARN(msg)  OFLOG_WARN(DCM_dcmimgleLogger, msg)
41 #define DCMIMGLE_ERROR(msg) OFLOG_ERROR(DCM_dcmimgleLogger, msg)
42 #define DCMIMGLE_FATAL(msg) OFLOG_FATAL(DCM_dcmimgleLogger, msg)
43 
44 
45 // include this file in doxygen documentation
46 
47 /** @file diutils.h
48  *  @brief type definitions, constants and helper functions for the dcmimgle/dcmimage module
49  */
50 
51 
52 /*---------------------*
53  *  const definitions  *
54  *---------------------*/
55 
56 /** @name configuration flags
57  */
58 
59 //@{
60 
61 /// compatibility with old ACR-NEMA images
62 const unsigned long CIF_AcrNemaCompatibility         = 0x0000001;
63 
64 /// accept wrong palette attribute tags
65 const unsigned long CIF_WrongPaletteAttributeTags    = 0x0000002;
66 
67 /// element pixel data may be detached if it is no longer needed by DicomImage
68 const unsigned long CIF_MayDetachPixelData           = 0x0000004;
69 
70 /// use presentation state instead of 'built-in' LUTs & overlays
71 const unsigned long CIF_UsePresentationState         = 0x0000008;
72 
73 /// don't convert YCbCr (Full and Full 4:2:2) color images to RGB
74 const unsigned long CIF_KeepYCbCrColorModel          = 0x0000010;
75 
76 /// take responsibility for the given external DICOM dataset, i.e. delete it on destruction
77 const unsigned long CIF_TakeOverExternalDataset      = 0x0000020;
78 
79 /// ignore modality transformation (rescale slope/intercept or LUT) stored in the dataset
80 const unsigned long CIF_IgnoreModalityTransformation = 0x0000040;
81 
82 /// ignore third value of the modality LUT descriptor, determine bit depth automatically
83 const unsigned long CIF_IgnoreModalityLutBitDepth    = 0x0000080;
84 
85 /// check third value of the LUT descriptor, compare with with expected bit depth based on LUT data
86 const unsigned long CIF_CheckLutBitDepth             = 0x0000100;
87 
88 /// use absolute (possible) pixel range for determining the internal representation (monochrome only)
89 const unsigned long CIF_UseAbsolutePixelRange        = 0x0000200;
90 
91 /// use partial access to pixel data, i.e. without decompressing or loading a complete multi-frame image.
92 /// Please note that the use of this flag can cause another copy of the pixel data to be created in memory,
93 /// e.g. in case the pixel data element value has already been loaded or decompressed completely in memory.
94 const unsigned long CIF_UsePartialAccessToPixelData  = 0x0000400;
95 
96 /// always decompress complete pixel data when processing an image, i.e. even if partial access is used
97 const unsigned long CIF_DecompressCompletePixelData  = 0x0000800;
98 
99 /// never access embedded overlays since this requires to load and uncompress the complete pixel data
100 const unsigned long CIF_NeverAccessEmbeddedOverlays  = 0x0001000;
101 //@}
102 
103 
104 // / true color color mode (for monochrome images only)
105 const int MI_PastelColor = -1;
106 
107 
108 /*--------------------*
109  *  type definitions  *
110  *--------------------*/
111 
112 /** constants for photometric interpretation
113  */
114 enum EP_Interpretation
115 {
116     /// unknown, undefined, invalid
117     EPI_Unknown,
118     /// no element value available
119     EPI_Missing,
120     /// monochrome 1
121     EPI_Monochrome1,
122     /// monochrome 2
123     EPI_Monochrome2,
124     /// palette color
125     EPI_PaletteColor,
126     /// RGB color
127     EPI_RGB,
128     /// HSV color (retired)
129     EPI_HSV,
130     /// ARGB color (retired)
131     EPI_ARGB,
132     /// CMYK color (retired)
133     EPI_CMYK,
134     /// YCbCr full
135     EPI_YBR_Full,
136     /// YCbCr full 4:2:2
137     EPI_YBR_Full_422,
138     /// YCbCr partial 4:2:2
139     EPI_YBR_Partial_422
140 };
141 
142 
143 /** structure for photometric string and related constant
144  */
145 struct DCMTK_DCMIMGLE_EXPORT SP_Interpretation
146 {
147     /// string (name of the color model without spaces and underscores)
148     const char *Name;
149     /// defined term according to the DICOM standard
150     const char *DefinedTerm;
151     /// integer constant
152     EP_Interpretation Type;
153 };
154 
155 
156 /** structure for BMP bitmap file header
157  */
158 struct DCMTK_DCMIMGLE_EXPORT SB_BitmapFileHeader
159 {
160     /// signature, must always be 'BM'
161     char bfType[2];
162     /// file size in bytes
163     Uint32 bfSize;
164     /// reserved, should be '0'
165     Uint16 bfReserved1;
166     /// reserved, should be '0'
167     Uint16 bfReserved2;
168     /// offset from the beginning of the file to the bitmap data (in bytes)
169     Uint32 bfOffBits;
170 };
171 
172 
173 /** structure for BMP bitmap info header
174  */
175 struct DCMTK_DCMIMGLE_EXPORT SB_BitmapInfoHeader
176 {
177     /// size of the BitmapInfoHeader, usually '40'
178     Uint32 biSize;
179     /// width of the image (in pixels)
180     Sint32 biWidth;
181     /// height of the image (in pixels)
182     Sint32 biHeight;
183     /// number of planes, usually '1'
184     Uint16 biPlanes;
185     /// bits per pixel, supported values: 8 = color palette with 256 entries, 24 = true color
186     Uint16 biBitCount;
187     /// type of compression, support value: 0 = BI_RGB, no compression
188     Uint32 biCompression;
189     /// size of the image data (in bytes), might be set to '0' if image is uncompressed
190     Uint32 biSizeImage;
191     /// horizontal resolution: pixels/meter, usually set to '0'
192     Sint32 biXPelsPerMeter;
193     /// vertical resolution: pixels/meter, usually set to '0'
194     Sint32 biYPelsPerMeter;
195     /// number of actually used colors, if '0' the number of colors is calculated using 'biBitCount'
196     Uint32 biClrUsed;
197     /// number of important colors, '0' means all
198     Uint32 biClrImportant;
199 };
200 
201 
202 /** internal representation of pixel data
203  */
204 enum EP_Representation
205 {
206     /// unsigned 8 bit integer
207     EPR_Uint8, EPR_MinUnsigned = EPR_Uint8,
208     /// signed 8 bit integer
209     EPR_Sint8, EPR_MinSigned = EPR_Sint8,
210     /// unsigned 16 bit integer
211     EPR_Uint16,
212     /// signed 16 bit integer
213     EPR_Sint16,
214     /// unsigned 32 bit integer
215     EPR_Uint32, EPR_MaxUnsigned = EPR_Uint32,
216     /// signed 32 bit integer
217     EPR_Sint32, EPR_MaxSigned = EPR_Sint32
218 };
219 
220 
221 /** image status code
222  */
223 enum EI_Status
224 {
225     /// normal, no error
226     EIS_Normal,
227     /// data dictionary not found
228     EIS_NoDataDictionary,
229     /// invalid dataset/file
230     EIS_InvalidDocument,
231     /// mandatory attribute missing
232     EIS_MissingAttribute,
233     /// invalid value for an important attribute
234     EIS_InvalidValue,
235     /// specified value for an attribute not supported
236     EIS_NotSupportedValue,
237     /// memory exhausted etc.
238     EIS_MemoryFailure,
239     /// invalid image, internal error
240     EIS_InvalidImage,
241     /// other error
242     EIS_OtherError
243 };
244 
245 
246 /** overlay modes.
247  *  This mode is used to define how to display an overlay plane.
248  */
249 enum EM_Overlay
250 {
251     /// default mode, as stored in the dataset
252     EMO_Default,
253     /// replace mode
254     EMO_Replace,
255     /// graphics overlay
256     EMO_Graphic = EMO_Replace,
257     /// threshold replace
258     EMO_ThresholdReplace,
259     /// complement
260     EMO_Complement,
261     /// invert the overlay bitmap
262     EMO_InvertBitmap,
263     /// region of interest (ROI)
264     EMO_RegionOfInterest,
265     /// bitmap shutter, used for GSPS objects
266     EMO_BitmapShutter
267 };
268 
269 
270 /** VOI LUT functions
271  */
272 enum EF_VoiLutFunction
273 {
274     /// default function (not explicitly set)
275     EFV_Default,
276     /// function LINEAR
277     EFV_Linear,
278     /// function SIGMOID
279     EFV_Sigmoid
280 };
281 
282 
283 /** presentation LUT shapes
284  */
285 enum ES_PresentationLut
286 {
287     /// default shape (not explicitly set)
288     ESP_Default,
289     /// shape IDENTITY
290     ESP_Identity,
291     /// shape INVERSE
292     ESP_Inverse,
293     /// shape LIN OD
294     ESP_LinOD
295 };
296 
297 
298 /** polarity
299  */
300 enum EP_Polarity
301 {
302     /// NORMAL
303     EPP_Normal,
304     /// REVERSE (opposite polarity)
305     EPP_Reverse
306 };
307 
308 
309 /** bits per table entry modes.
310  *  Specifies whether the given value in the LUT descriptor is used.
311  */
312 enum EL_BitsPerTableEntry
313 {
314     /// use given value
315     ELM_UseValue,
316     /// ignore given value, use auto detection
317     ELM_IgnoreValue,
318     /// check whether given value is consistent with LUT data
319     ELM_CheckValue
320 };
321 
322 /** type of VOI LUT transformation to apply.
323  *  Specifies which VOI LUT transformation should be applied to an image.
324  */
325 enum EW_WindowType
326 {
327     /// use given value
328     EWT_none,
329     /// use the n-th VOI window from the image file
330     EWT_window_from_file,
331     /// use the n-th VOI look up table from the image file
332     EWT_voi_lut_from_file,
333     /// compute VOI window using min-max algorithm
334     EWT_window_minmax,
335     /// compute VOI window using min-max algorithm ignoring extremes
336     EWT_window_minmax_n,
337     /// compute VOI window using min-max algorithm applied to region of interest
338     EWT_window_minmax_roi,
339     /// compute VOI window using Histogram algorithm, ignoring n percent
340     EWT_window_histogram,
341     /// compute VOI window using center and width
342     EWT_window_center_width
343 };
344 
345 /*----------------------------*
346  *  constant initializations  *
347  *----------------------------*/
348 
349 const SP_Interpretation PhotometricInterpretationNames[] =
350 {
351     {"MONOCHROME1",   "MONOCHROME1",     EPI_Monochrome1},
352     {"MONOCHROME2",   "MONOCHROME2",     EPI_Monochrome2},
353     {"PALETTECOLOR",  "PALETTE COLOR",   EPI_PaletteColor},        // space deleted to simplify detection
354     {"RGB",           "RGB",             EPI_RGB},
355     {"HSV",           "HSV",             EPI_HSV},
356     {"ARGB",          "ARGB",            EPI_ARGB},
357     {"CMYK",          "CMYK",            EPI_CMYK},
358     {"YBRFULL",       "YBR_FULL",        EPI_YBR_Full},            // underscore deleted to simplify detection
359     {"YBRFULL422",    "YBR_FULL_422",    EPI_YBR_Full_422},        // underscores deleted to simplify detection
360     {"YBRPARTIAL422", "YBR_PARTIAL_422", EPI_YBR_Partial_422},     // underscores deleted to simplify detection
361     {NULL,            NULL,              EPI_Unknown}
362 };
363 
364 
365 /*---------------------*
366  *  macro definitions  *
367  *---------------------*/
368 
369 #define MAX_UINT Uint32
370 #define MAX_SINT Sint32
371 
372 #define MAX_BITS 32
373 #define MAX_BITS_TYPE Uint32
374 #define MAX_RAWPPM_BITS 8
375 #define MAX_INTERPOLATION_BITS 16
376 
377 #define bitsof(expr) (sizeof(expr) << 3)
378 
379 
380 /*----------------------*
381  *  class declarations  *
382  *----------------------*/
383 
384 /** Class comprising several global functions and constants.
385  *  introduced to avoid problems with naming convention
386  */
387 class DCMTK_DCMIMGLE_EXPORT DicomImageClass
388 {
389 
390  public:
391 
392     /** calculate maximum value which could be stored in the specified number of bits
393      *
394      ** @param  mv_bits  number of bits
395      *  @param  mv_pos   value subtracted from the maximum value (0 or 1)
396      *
397      ** @return maximum value
398      */
399     static inline unsigned long maxval(const int mv_bits,
400                                        const unsigned long mv_pos = 1)
401     {
402         return (mv_bits < MAX_BITS) ?
403             (OFstatic_cast(unsigned long, 1) << mv_bits) - mv_pos : OFstatic_cast(MAX_BITS_TYPE, -1);
404     }
405 
406     /** calculate number of bits which are necessary to store the specified value
407      *
408      ** @param  tb_value  value to be stored
409      *  @param  tb_pos    value subtracted from the value (0 or 1) before converting
410      *
411      ** @return number of bits
412      */
413     static inline unsigned int tobits(unsigned long tb_value,
414                                       const unsigned long tb_pos = 1)
415     {
416         if (tb_value > 0)
417             tb_value -= tb_pos;
418         unsigned int tb_bits = 0;
419         while (tb_value > 0)
420         {
421             ++tb_bits;
422             tb_value >>= 1;
423         }
424         return tb_bits;
425     }
426 
427     /** calculate number of bits which are necessary to store the specified value range
428      *
429      ** @param  minvalue  minimum value to be stored
430      *  @param  maxvalue  maximum value to be stored
431      *
432      ** @return number of bits
433      */
434     static unsigned int rangeToBits(double minvalue,
435                                     double maxvalue);
436 
437     /** determine whether integer representation is signed or unsigned
438      *
439      ** @param  repres  integer representation (enum) to be checked
440      *
441      ** @return true if representation is signed, false if unsigned
442      */
443     static int isRepresentationSigned(EP_Representation repres);
444 
445     /** determine number of bits used for a particular integer representation
446      *
447      ** @param  repres  integer representation (enum) to be checked
448      *
449      ** @return number of bits
450      */
451     static unsigned int getRepresentationBits(EP_Representation repres);
452 
453     /** determine integer representation which is necessary to store values in the specified range
454      *
455      ** @param  minvalue  minimum value to be stored
456      *  @param  maxvalue  maximum value to be stored
457      *
458      ** @return integer representation (enum)
459      */
460     static EP_Representation determineRepresentation(double minvalue,
461                                                      double maxvalue);
462 
463 };
464 
465 
466 #endif
467