~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Tina4/src/file/dicom.old/dicom_io.c

Version: ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /**@(#)Functions to read DICOM files (based on the CTN library)
  2 */
  3 
  4 /*------------------------------------------------------------
  5 **
  6 **      d i c o m _ i o . c
  7 **
  8 **      DICOM functionality for TINA
  9 **      Using CTN-2.10.3
 10 **
 11 **
 12 **      Igor Hollander
 13 **      University of Manchester
 14 **
 15 **      22-Sep-00
 16 **
 17 **      REVISION HISTORY:
 18 **
 19 **      22-Sep-00       adapted for the real needs of Tina
 20 **
 21 **      10-May-00       dicom_hdr_... routines replaced by dummies
 22 **                      because seq_tool.c still needs them
 23 **
 24 **      9-May-00        The problem with element extraction fixed 
 25 **                      in a new way. To extract a non-pixel element,
 26 **                      use the sequence 
 27 **                              dicom_readheader_open(..);
 28 **                              dicom_readheader_get(...);
 29 **                              dicom_readheader_get(...);
 30 **                              ...
 31 **                              dicom_readheader_close();
 32 **
 33 **                      dicom_read_image is NOT extracting information
 34 **                      to image properties
 35 **
 36 **                      BUT the dicom_header_open routine needs the
 37 **                      the name of the DICOM file which is not
 38 **                      available via the Imrect structure
 39 **              
 40 **                      dicom_hdr_... routine completely deleted
 41 **      
 42 **                      pixel values are now being assigned to the image
 43 **                      using slope and intercept transform
 44 **
 45 **      29-Feb-00       attempt to fix TE (and other similar) object 
 46 **                      extraction.
 47 **                      Use of the dicom_hdrinfo_extract and the
 48 **                      dicom_hdr_... routines is strongly
 49 **                      discouraged as from now (they are only
 50 **                      included in this source for compatibility
 51 **                      reasons). Instead, 
 52 **                      the dicom_read_image routine will store
 53 **                      all information objects (if implemented) 
 54 **                      directly to the image properties.
 55 **
 56 **      4-Oct-99        first release
 57 **
 58 **------------------------------------------------------------
 59 **   Copyright (C) 1993, 1994, RSNA and Washington University
 60 **   (full copyright notice at the end)
 61 **------------------------------------------------------------
 62 */
 63 
 64 
 65 #include <stdio.h>
 66 #include <stdlib.h>
 67 #include <string.h>
 68 #include <sys/types.h>
 69 #include <sys/stat.h>
 70 #include <math.h>
 71 #include <tina/dicom/dicom.h>
 72 #include <tina/dicom/ctnthread.h> 
 73 #include <tina/dicom/condition.h>
 74 #include <tina/dicom/lst.h>
 75 #include <tina/dicom/dicom_uids.h>
 76 #include <tina/dicom/dicom_objects.h>
 77 #include <tina/dicom/dcmprivate.h>
 78 
 79 #include <tina/file.h>
 80 #include <tina/sysfuncs.h>
 81 #include <tina/temporal.h>
 82 
 83 /*------------------------------------------------------------*/
 84 /* TINA-related ...
 85 */
 86 
 87 #define VOXELS    450
 88 #define DYNSTIME  451
 89 #define TE_DATA   453
 90 #define PAT_DATA  454
 91 
 92 /*------------------------------------------------------------*/
 93 /* CTN-related ...
 94 */
 95 
 96 #define IHDCM_FILEOPENERROR   1000
 97 
 98 #define IHDCM_TYPE_SHORT                0
 99 #define IHDCM_TYPE_UNSIGNED_SHORT       1
100 #define IHDCM_TYPE_UNSIGNED_CHAR        2
101 
102 /*------------------------------------------------------------*/
103 /* miscellaneous ...
104 */
105 #define DICOM_IO_VERBOSE        0 
106 #define VERBOSE_VIA_STDOUT      1
107 
108 #ifdef VERBOSE_VIA_STDOUT
109 #define FORMAT  printf
110 #else
111 #define FORMAT  format
112 #endif
113 
114 /*------------------------------------------------------------*/
115 /* for IHDCM_read_header ...
116 */
117 #define READHEADER_OPEN         1 
118 #define READHEADER_GET          2 
119 #define READHEADER_CLOSE        3 
120 
121 /*------------------------------------------------------------*/
122 /* prototypes ...
123 */
124 
125 extern Bool  
126 fclose_2(FILE * stream, const char *pathname);
127 
128 extern FILE 
129 *fopen_2(const char *pathname, const char *mode);  
130 
131 static int 
132 pixel_clip(DCM_OBJECT ** object, void *pixels, int count,
133    int bitsAllocated, int bitsStored, int highBit, int pixelRepresentation);
134 
135 static int
136 get_slope_and_intercept(DCM_OBJECT ** object, void *pixels, int count,
137     int bitsAllocated, int bitsStored, int highBit, int pixelRepresentation,
138                     float *slopeValue,
139                     float *interceptValue);
140 
141 static int
142 map_color_to_intgrey(DCM_OBJECT ** object, void *pixels,
143                   int *mappedPixels, int count,
144                   char *photometricInterpretation,
145                   int bitsAllocated, int bitsStored, int highBit,
146                   int pixelRepresentation);
147 
148 static int
149 map_palette_color(DCM_OBJECT ** object, void *pixels,
150                   int *mappedPixels, int count,
151                   char *photometricInterpretation,
152                   int bitsAllocated, int bitsStored, int highBit,
153                   int pixelRepresentation);
154 
155 static CONDITION
156 MyDumpElements(DCM_OBJECT ** callerObject, long vm, FILE *headerdump);
157 
158 static CONDITION
159 checkObject(PRIVATE_OBJECT ** object, char *caller);
160 
161 static void
162 dumpSS(short *ss, long vm);
163 
164 static void
165 dumpSL(S32 * sl, long vm);
166 
167 static void
168 dumpUS(unsigned short *us, long vm);
169 
170 static void
171 dumpUL(U32 * ul, long vm);
172 
173 static void
174 dumpBinaryData(void *d, DCM_VALUEREPRESENTATION vr, long vm,
175                long vmLimit);
176 
177 static
178 int IHDCM_read_header(
179         int what,
180         char *infilename,
181         char inendian,
182         int elementType,
183         void **elementPointer,
184         U32 *elementLength
185         );
186 
187 /*------------------------------------------------------------*/
188 Imrect* 
189 dicom_read_image(char *filename){
190 
191 Imrect   *imrect=NULL;
192 Imregion imregion;
193 Vartype  vtype;
194 
195 int *pixels;
196 int rows;
197 int columns;
198 int type;
199 int minpixval;
200 int maxpixval;
201 float slope;
202 float intercept;
203 
204 int i,j;
205 int ret;
206 
207         /* for debugging only ... */
208         printf("DICOM reader %s %s\n",__DATE__,__TIME__); 
209 
210         ret=IHDCM_simple_read(
211                         filename,
212                         NULL,           /* no header file required      */
213                         0,              /* little endian                */
214                         &pixels,
215                         &rows,&columns,
216                         &type,
217                         &minpixval,&maxpixval,
218                         &slope,&intercept);
219 
220         if(ret>0){
221 #ifdef DICOM_IO_VERBOSE
222                 FORMAT("Failed to read DICOM file %s\n",filename); 
223 #endif
224                 return NULL;
225                 }
226 
227 #ifdef DICOM_IO_VERBOSE
228         FORMAT("DICOM file %s:\n",filename); 
229         FORMAT("   DICOM read return code: %d\n",ret); 
230         FORMAT("   %d rows\n",rows); 
231         FORMAT("   %d columns\n",columns); 
232         FORMAT("   type: ",columns); 
233 #endif
234 
235         switch(type){
236         case IHDCM_TYPE_UNSIGNED_SHORT:         
237                 vtype=ushort_v; 
238 #ifdef DICOM_IO_VERBOSE
239                 FORMAT("unsigned short",columns); 
240 #endif
241                 break;
242         case IHDCM_TYPE_SHORT:                  
243                 vtype=short_v; 
244 #ifdef DICOM_IO_VERBOSE
245                 FORMAT("short",columns); 
246 #endif
247                 break;
248         case IHDCM_TYPE_UNSIGNED_CHAR:          
249                 vtype=uchar_v;  
250 #ifdef DICOM_IO_VERBOSE
251                 FORMAT("unsigned char",columns); 
252 #endif
253                 break;
254         default:
255                 /* for debugging only */
256                 printf("The type is now %d\n",type);
257         
258         }
259 #ifdef DICOM_IO_VERBOSE
260         FORMAT("\n"); 
261 #endif
262 
263         
264         imrect = im_alloc(rows,columns,NULL,vtype);
265 
266         /* make sure we avoid zerodivide */
267         if(slope==0.0)slope=1.0;
268 
269         for(i=0;i<rows;i++)
270         for(j=0;j<columns;j++){
271                 im_put_pixf(
272                 (pixels[columns*i+j]-intercept)/slope,
273                 imrect,i,j);
274                 }
275 
276         free(pixels);
277 
278 
279         /* extract non-pixel information */
280 
281         {
282         int i;
283         unsigned int element_length;
284         void *element_data;
285         int ELEMENT_TO_EXTRACT[] = {
286                 DCM_PATNAME,
287                 DCM_PATBIRTHDATE,
288                 DCM_ACQECHOTIME,
289                 DCM_ACQSLICETHICKNESS,
290                 DCM_ACQSLICESPACING,
291                 DCM_IMGPIXELSPACING,
292                 DCM_RELIMAGENUMBER,
293                 DCM_RELACQUISITIONNUMBER,
294                 DCM_MAKETAG(0x0029,0x1010),
295                 DCM_MAKETAG(0x0029,0x1011)
296                 };
297         int NUMBER_OF_ELEMENTS_TO_EXTRACT = 10;
298 
299         dicom_readheader_open(filename);
300 
301         /* this is just an example 
302            (all these elements have got to be strings)... */
303 
304         for(i=0;i<NUMBER_OF_ELEMENTS_TO_EXTRACT;i++){
305                 if(!dicom_readheader_get(ELEMENT_TO_EXTRACT[i],
306                                 &element_data,&element_length)){
307                         ((char*)element_data)[element_length]='\0';     
308 #ifdef DICOM_IO_VERBOSE
309                         FORMAT("   %s\n",element_data); 
310 #endif
311                         }
312                 else {
313 #ifdef DICOM_IO_VERBOSE
314                         FORMAT("(failed to extract)\n");
315 #endif
316                         }
317                 if(element_data) free(element_data);
318                 }
319 
320         dicom_readheader_close();
321         }
322 
323 
324         /* assign image properties */
325         /*
326         (just an example (not working )) 
327 
328         imrect->props = proplist_rm(imrect->props,TE_DATA);
329         imrect->props = proplist_addifnp(imrect->props, 
330                         (void *)(&TE),TE_DATA,rfree,false);                                
331         */
332 
333         return imrect;
334 }
335 /*------------------------------------------------------------*/
336 int 
337 dicom_readheader_open(
338         char *filename)
339 /*
340 **      This procedure
341 **
342 **      - opens the DICOM file 'filename' for reading DICOM information
343 **        objects (as little endian)
344 **      - returns:      0  if OK, or 
345 **                      a positive integer error code otherwise
346 **
347 **      Any subsequent call to the dicom_readheader_get() routine
348 **      will read data from  'filename'.
349 */
350 
351 {
352         return IHDCM_read_header(READHEADER_OPEN,filename,0,0,NULL,NULL);
353 }
354 
355 /*------------------------------------------------------------*/
356 int 
357 dicom_readheader_get(
358         int objecttype,
359         void **objectp,
360         U32 *objectlength
361         )
362 /*
363 **      This procedure
364 **
365 **      - reads DICOM information object from the file opened
366 **        by preceding call to 'dicom_readheader_open'
367 **      - the type of the object is identified by the 
368 **        parameter 'objecttype'
369 **      - allocates the required amount of memore using 'malloc'
370 **      - fills the pointer 'objectp' with the location allocated
371 **        by malloc 
372 **      - fills the allocated memory with the value of the DICOM information
373 **        object
374 **      - fills the location '*objectlenght' with the amount of allocated
375 **        memory (the interpretation of this value depends on the
376 **        specific type of the information object)
377 **      - returns:      0  if OK, or 
378 **                      a positive integer error code otherwise
379 **
380 **      Procedure dicom_readheader_open MUST be called before this procedure
381 **      is called. This procedure reads the data from the DICOM file
382 **      referred to by the 'dicom_readheader_open'.
383 **
384 **      NOTE that only one DICOM file at a time
385 **      is accessible via this mechanism.
386 **
387 **      The application is responsible for freeing the memory allocated
388 **      internally by this procedure
389 */
390 {
391         return IHDCM_read_header(READHEADER_GET,NULL,0,
392                 objecttype,objectp,objectlength);
393 }
394 
395 /*------------------------------------------------------------*/
396 int 
397 dicom_readheader_close()
398 /*
399 **      This procedure
400 **
401 **      - closes the DICOM file opened
402 **        by preceding call to 'dicom_readheader_open'
403 **      - returns:      0  if OK, or 
404 **                      a positive integer error code otherwise
405 **
406 **      No more call to dicom_readheader_get is possible after closing
407 **      the file.
408 */
409 {
410         return IHDCM_read_header(READHEADER_CLOSE,NULL,0,0,NULL,NULL);
411 }
412 
413 /*------------------------------------------------------------*/
414 static int 
415 IHDCM_read_header(
416         int what,
417         char *infilename,
418         char inendian,
419         int elementType,
420         void **elementPointer,
421         U32 *elementLength
422         )                       
423 /*
424 **      This procedure
425 **      behaves according to the 'what' parameter:
426 **
427 **      if what==READHEADER_OPEN ...
428 **
429 **              - opens the DICOM file infile as:
430 **                      as LittleEndian if inendian=0
431 **                      as BigEndian    if inendian=1
432 **
433 **              - if an DICOM file is already opened, this call is ignored.
434 **      if what==READHEADER_GET ...
435 **
436 **              - reads DICOM information object from the file opened
437 **                by preceding call with what=READHEADER_OPEN 
438 **              - the type of the object is identified by the tag 'elementType'
439 **                (the tags are defined in the CTN file dicom_objects.h)
440 **              - allocates the required amount of memore using 'malloc'
441 **              - fills the pointer 'elementPointer' with the location allocated
442 **                by malloc 
443 **              - fills the allocated memory with 
444 **                the value of the DICOM information
445 **                object
446 **              - fills the location '*elementLenght' with 
447 **                the amount of allocated
448 **                memory (the interpretation of this value depends on the
449 **                specific type of the information object)
450 **
451 **
452 **              NOTE that only one DICOM file at a time
453 **              is accessible via this mechanism.
454 **
455 **              The application is responsible for freeing the memory allocated
456 **              internally by this procedure
457 **      
458 **      if what==READHEADER_CLOSE ...
459 **
460 **              - closes the DICOM file currently opened for reading header
461 **                (all other parameters are ignored)
462 **
463 **      - returns:      0  if OK, or 
464 **                      a positive integer error code otherwise
465 */
466 {
467 static DCM_OBJECT *object=NULL;
468 CONDITION cond;
469 void *ctx;
470 unsigned long options;
471 DCM_ELEMENT p;
472 
473 int ret  = 0;
474 
475 switch(what){
476 case READHEADER_OPEN:
477         if(object) {
478                 ret = 1;
479                 break;
480                 }
481         switch(inendian){
482         case 1: 
483                 options = DCM_ORDERBIGENDIAN;  break;
484         case 0:
485         default:
486                 options = DCM_ORDERLITTLEENDIAN;  break;
487         }
488         cond = DCM_OpenFile(infilename, options, &object);
489         if (cond != DCM_NORMAL) {
490                 ret = 2;
491                 }
492         break;
493 
494 case READHEADER_GET:
495         p.tag    = elementType;
496         if (DCM_GetElementSize(&object,p.tag,elementLength) != DCM_NORMAL) {
497                 ret = 3;
498                 break;
499                 }
500         if((*elementPointer=(void*)malloc(*elementLength))==NULL){
501                 ret = 4;
502                 break;
503                 }
504         ctx      = NULL;
505         p.length = *elementLength;
506         p.representation = 0; /*!!!!!!!!!!*/
507         p.d.ot   = *elementPointer;
508         if (DCM_GetElementValue(&object, &p, elementLength, &ctx) != DCM_NORMAL) {
509                 ret = 5;
510                 break;
511                 }
512 
513         break;
514 
515 case READHEADER_CLOSE:
516         if(!object) {
517                 ret = 3;
518                 break;
519                 }
520         DCM_CloseObject(&object);
521         object=NULL;
522         break;
523 }
524 
525 
526 
527 return ret;
528 }
529 
530 /*------------------------------------------------------------*/
531 int
532 IHDCM_simple_read(      
533         char *infilename, 
534         char *inheaderfilename, 
535         int inendian,
536         int *outpixels[], 
537         int *outrows, 
538         int *outcolumns,
539         int *outtype,
540         int *outminpixval,
541         int *outmaxpixval,
542         float *outslope,
543         float *outintercept)
544 
545 /*              
546 **      This procedure 
547 **
548 **      - opens the DICOM file infilename as:
549 **              as LittleEndian if inendian=0
550 **              as BigEndian    if inendian=1
551 **      - writes an ASCII-formatted information about all
552 **        data elements in the DICOM object to file inheaderfilename
553 **        (if inheaderfilename is NULL, this step is skipped)
554 **      - converts color image (RGB or PALETTE) to grey-scale, if applicable
555 **      - saves the values of the pixels to an integer array outpixels
556 **        (it also allocates the appropriate amount of memory using
557 **        malloc)
558 **      - stores the number of rows and columns in 
559 **        outrows and outcolumns, respectively. 
560 **      - stores the type of the data to outtype
561 **      - stores the minimum and maximum pixel value occuring in the image in 
562 **        outminpixval and outmaxpixval, respectively. 
563 **      - stores the slope and intercept in 
564 **        outslope and outintercept, respectively. 
565 **      - closes the DICOM file
566 **      - returns:      0  if OK, or 
567 **                      a positive integer error code otherwise
568 **
569 **      The user should free the memory allocated to outpixels
570 **      after using it.
571 */
572 
573 
574 {
575     DCM_OBJECT          *object = NULL;
576     CONDITION           cond;
577 
578     unsigned long       options;
579 
580     U32                 pixelLength,
581                         elementLength,
582                         frameLength;
583 
584     void                *pixels;
585 
586     int                 *newPixels;
587 
588     static 
589     unsigned short      bitsAllocated,
590                         bitsStored,
591                         highBit,
592                         pixelRepresentation,
593                         samplesPerPixel,
594                         rows,
595                         columns;
596 
597     float               intercept;
598     float               slope;
599 
600     int                 pixelCount;
601     
602     static char         photometricInterpretation[DICOM_CS_LENGTH + 1];
603 
604     void                *ctx;
605 
606     int                 type;
607 
608     int                 minpixval,
609                         maxpixval;
610 
611 #ifdef MAXINT
612 #define VERYSMALLNUMBER -MAXINT+1
613 #define VERYBIGNUMBER    MAXINT 
614 #else
615 #define VERYSMALLNUMBER -100000
616 #define VERYBIGNUMBER    100000 
617 #endif
618 
619     DCM_ELEMENT
620         p2 = {
621         DCM_PXLPIXELDATA, DCM_OT, "", 1, 0, NULL
622     };
623 
624     static DCM_ELEMENT list[] = {
625         {DCM_IMGBITSALLOCATED, DCM_US, "",
626         1, sizeof(bitsAllocated), (void *) &bitsAllocated},
627         {DCM_IMGBITSSTORED, DCM_US, "",
628         1, sizeof(bitsStored), (void *) &bitsStored},
629         {DCM_IMGHIGHBIT, DCM_US, "",
630         1, sizeof(highBit), (void *) &highBit},
631         {DCM_IMGPIXELREPRESENTATION, DCM_US, "",
632         1, sizeof(pixelRepresentation), (void *) &pixelRepresentation},
633         {DCM_IMGSAMPLESPERPIXEL, DCM_US, "",
634         1, sizeof(samplesPerPixel), (void *) &samplesPerPixel},
635         {DCM_IMGROWS, DCM_US, "",
636         1, sizeof(rows), (void *) &rows},
637         {DCM_IMGCOLUMNS, DCM_US, "",
638         1, sizeof(columns), (void *) &columns},
639         {DCM_IMGPHOTOMETRICINTERP, DCM_CS, "",
640         1, sizeof(photometricInterpretation), photometricInterpretation}
641     };
642     static DCM_TAG deleteTags[] = {
643         DCM_IMGRESCALEINTERCEPT,
644         DCM_IMGRESCALESLOPE,
645         DCM_IMGWINDOWCENTER,
646         DCM_IMGWINDOWWIDTH,
647         DCM_IMGPLANARCONFIGURATION
648     };
649 
650     FILE *headerdump=NULL;
651 
652 /* Initialize ... */
653 
654     switch(inendian){
655         case 1: 
656                 options = DCM_ORDERBIGENDIAN;  break;
657         case 0:
658         default:
659                 options = DCM_ORDERLITTLEENDIAN;  break;
660         }
661 
662     THR_Init();
663     /* DCM_Debug(verbose); */
664 
665 /* Open header file ... */
666 
667    if(inheaderfilename!=NULL){
668         if((headerdump=fopen(inheaderfilename,"w"))==NULL) 
669                         return IHDCM_FILEOPENERROR;
670         }
671     
672 /* Open DICOM file ... */
673 
674     cond = DCM_OpenFile(infilename, options, &object);
675     if (cond != DCM_NORMAL) {
676         /* COND_DumpConditions(); */
677         THR_Shutdown();
678         return 1;
679     }
680 
681 /* Dump non-pixel elements */
682 
683     if(headerdump!=NULL){
684     cond = MyDumpElements(&object, 0L, headerdump);
685     if (cond != DCM_NORMAL) {
686         /* fprintf(stderr, "Error retrieving bits allocated data element\n"); */
687         /* COND_DumpConditions(); */
688         THR_Shutdown();
689         return 21;
690     }
691     }
692 
693 /* Parse object ... */
694 
695     cond = DCM_ParseObject(&object, list, (int) DIM_OF(list), NULL, 0, NULL);
696     if (cond != DCM_NORMAL) {
697         /* fprintf(stderr, "Error retrieving bits allocated data element\n"); */
698         /* COND_DumpConditions(); */
699         THR_Shutdown();
700         return 2;
701     }
702 
703 /* Get pixel element size ... */
704 
705     cond = DCM_GetElementSize(&object, p2.tag, &pixelLength);
706     if (cond != DCM_NORMAL) {
707         /* fprintf(stderr, "Error finding length of pixel data\n"); */
708         /* COND_DumpConditions(); */
709         THR_Shutdown();
710         return 3;
711     }
712 
713 /* Compute frame length ... */
714 
715     frameLength = (U32) samplesPerPixel 
716                         *(U32) rows *(U32) columns *(U32) (bitsAllocated / 8);
717 
718     if (pixelLength != frameLength) {
719         /* fprintf(stderr, "Computed pixel length differs from actual: %s\n", *argv); */
720         THR_Shutdown();
721         printf ("frameLength = %d\n",frameLength);
722         printf ("pixelLength = %d\n",pixelLength);
723         return 4;
724     }
725 
726 
727 /* Allocate memory for DICOM pixel data ... */
728 
729     pixels = malloc(pixelLength);
730     if (pixels == NULL) {
731         /* perror("Malloc of pixel data"); */
732         THR_Shutdown();
733         return 5;
734     }
735 
736     pixelCount = (int) rows *(int) columns;
737 
738 /* Allocate memory for new pixel data... */
739 
740     newPixels = malloc((pixelCount + 1)*sizeof(int));
741     if (newPixels == NULL) {
742         /* perror("Malloc of pixel data"); */
743         THR_Shutdown();
744         return 6;
745     }
746 
747 /* Get pixel data... */
748 
749     p2.length = pixelLength;
750     p2.d.ot = pixels;
751     ctx = NULL;
752     if (DCM_GetElementValue(&object, &p2, &elementLength, &ctx) != DCM_NORMAL) {
753         /* fprintf(stderr, "Error retrieving pixels from image\n"); */
754         /* COND_DumpConditions(); */
755         THR_Shutdown();
756         return 7;
757     }
758 
759 /* Interpret pixel data ... */
760 
761     if (strcmp(photometricInterpretation, "MONOCHROME2") == 0 ||
762         strcmp(photometricInterpretation, "MONOCHROME1") == 0) {
763 
764         if(pixel_clip(&object, pixels, pixelCount, bitsAllocated, bitsStored,
765                    highBit, pixelRepresentation)>0) return 8;
766 
767 
768         if(get_slope_and_intercept(&object, pixels, pixelCount, bitsAllocated,
769                             bitsStored, highBit, pixelRepresentation,
770                             &slope,
771                             &intercept)>0) return 9;
772         if (intercept < 0.)
773             pixelRepresentation = DCM_PIXELTWOSCOMPLEMENT;
774 
775         { int i;
776         if(bitsAllocated==16){
777                 if(pixelRepresentation==0){
778                         unsigned short *p = pixels;
779                         for(i=0;i<pixelCount;i++) newPixels[i] = *p++;
780                         type = IHDCM_TYPE_UNSIGNED_SHORT;
781                         }
782                 else {
783                         short *p = pixels;
784                         for(i=0;i<pixelCount;i++) newPixels[i] = *p++;
785                         type = IHDCM_TYPE_SHORT;
786                         }
787                 }
788         else {
789                 unsigned char *p = pixels;
790                 for(i=0;i<pixelCount;i++) newPixels[i] = *p++;
791                 type = IHDCM_TYPE_UNSIGNED_CHAR;
792                 }
793         }
794 
795     } else {
796         if(map_color_to_intgrey(&object, pixels, newPixels, pixelCount,
797                        photometricInterpretation, bitsAllocated, bitsStored,
798                           highBit, pixelRepresentation)>0) return 10;
799     }
800 
801 /* Find maxval and minval */
802 
803     { int i;
804         maxpixval=VERYSMALLNUMBER;
805         minpixval=VERYBIGNUMBER;
806         for(i=0;i<pixelCount;i++){ 
807                 if(newPixels[i]>maxpixval){maxpixval=newPixels[i];}
808                 if(newPixels[i]<minpixval){minpixval=newPixels[i];}
809                 }
810     }
811 
812 
813 /* Assign return values */
814 
815     *outpixels    = newPixels;
816     *outrows      = rows;
817     *outcolumns   = columns;
818     *outtype      = type;
819     *outminpixval = minpixval;
820     *outmaxpixval = maxpixval;
821     *outslope     = slope;
822     *outintercept = intercept;
823 
824 /* Finish ... */
825 
826 /*
827  * a.lacey added these checks
828  */
829 
830     if (object != NULL)
831       DCM_CloseObject(&object);
832 
833 
834     if (headerdump != NULL)
835       fclose(headerdump);
836         
837     THR_Shutdown();
838     return 0;
839 }
840 
841 
842 /*-----------------------------------------------------------------------*/
843 
844 /*
845   recover information from nema headers ref'd in seq using hdrextract_func
846   which should store info in image propslist.  hdrextract_func should be
847   passed fileptr and imrect and should return Bool success. 
848 
849   IH : This is mimicking the nema_hdrinfo_extract
850 
851   a.lacey@man.ac.uk: added wildcard matching on filename (fname_resolve)
852 */
853 
854 Bool    
855 dicom_hdrinfo_extract(Sequence *seq, void (*hdrextract_func))
856 {
857   Ddlist       *store = (Ddlist *)get_start_el();
858   Bool         status = false, success = true ;
859   char        *pfname[1];
860   char         filename[512];
861   char         temp[512];
862   int          i;
863   
864   DCM_OBJECT   *dcm_object;
865   CONDITION    cond;
866   unsigned 
867   long         options =  DCM_ORDERLITTLEENDIAN;
868 
869                 /* options include:
870                     DCM_ORDERLITTLEENDIAN
871                     DCM_ORDERBIGENDIAN
872                 */
873 
874   strcpy(filename, "");
875   strcpy(temp, "");
876  
877   THR_Init();
878   for(i = (seq->seq_end); i >= seq->seq_start; i--)
879     {
880       dcm_object = NULL;
881       parse_fname(seq->filename, temp, i);
882       sprintf(filename, "%s%s", temp, ""); /* No default extension */
883       *pfname = filename;
884       if (strchr(filename, '*') && !fname_resolve(NULL, filename, pfname))
885       {
886         error("dicom_hdrinfo_extract: no such file or filename", warning);
887         return(false);
888       }
889 
890       if ((store == NULL) || (store->to == NULL))
891         continue;
892 
893       if ((cond=DCM_OpenFile(*pfname,options,&dcm_object))!=DCM_NORMAL){
894         continue;
895         }
896 
897       status = ((Bool (*) ())hdrextract_func)(&dcm_object, 
898                                              (Imrect *)(store->to));
899 
900 /*
901  * a.lacey added checks here
902  */
903      if (dcm_object != NULL)
904         DCM_CloseObject(&dcm_object);
905 
906       if (!status)
907         success = status;
908       store = store->next;
909     }
910     THR_Shutdown();
911 
912   return(success);
913 }
914 
915 
916 /*-----------------------------------------------------------------------*/
917 
918 static int 
919 pixel_clip(DCM_OBJECT ** object, void *pixels, int count,
920     int bitsAllocated, int bitsStored, int highBit, int pixelRepresentation)
921 {
922     unsigned short mask;
923     unsigned short signBit;
924     unsigned short *p16;
925     unsigned char *p8;
926 
927     if (bitsAllocated == 16) {
928         p16 = (unsigned short *) pixels;
929         if (pixelRepresentation == DCM_PIXELUNSIGNED) {
930             mask = 0xffff << (highBit + 1);
931             while (count-- > 0) {
932                 *(p16++) &= ~mask;
933             }
934         } else {
935             signBit = 1 << highBit;
936             mask = 0xffff << (highBit + 1);
937             while (count-- > 0) {
938                 if ((*p16 & signBit) != 0)
939                     *(p16++) |= mask;
940                 else
941                     *(p16++) &= ~mask;
942             }
943         }
944     } else {
945         p8 = (unsigned char *) pixels;
946         if (pixelRepresentation == 0) {
947             mask = 0xff << (highBit + 1);
948             while (count-- > 0) {
949                 *(p8++) &= ~mask;
950             }
951 
952         } else {
953             /* fprintf(stderr, "Expected pixel representation of 0 for 8 bit data\n"); */
954             return 1;
955         }
956     }
957     return 0;
958 }
959 
960 /*-----------------------------------------------------------------------*/
961 
962 static int 
963 get_slope_and_intercept(DCM_OBJECT ** object, void *pixels, int count,
964     int bitsAllocated, int bitsStored, int highBit, int pixelRepresentation,
965                     float *slopeValue,
966                     float *interceptValue)
967 {
968     static char
969         slopeString[256],
970         interceptString[256];
971     int i;
972     void *ctx;
973     U32 elementLength;
974     float
975         slope,
976         intercept;
977     long value;
978     short *p16;
979     unsigned char *p8;
980 
981     static DCM_ELEMENT list[] = {
982         {DCM_IMGRESCALEINTERCEPT, DCM_IS, "",
983         1, sizeof(interceptString), (void *) interceptString},
984         {DCM_IMGRESCALESLOPE, DCM_IS, "",
985         1, sizeof(slopeString), (void *) slopeString}
986     };
987 
988     *interceptValue = (float) 0.;
989 
990     for (i = 0; i < DIM_OF(list); i++) {
991         ctx = NULL;
992         if (DCM_GetElementValue(object, &list[i], &elementLength, &ctx) !=
993             DCM_NORMAL) {
994             (void) COND_PopCondition(TRUE);
995             return 1;
996         }
997     }
998     if (sscanf(slopeString, "%e", &slope) != 1) {
999         /* fprintf(stderr, "Error converting slope: %s\n", slopeString); */
1000         return 2;
1001     }
1002     if (sscanf(interceptString, "%e", &intercept) != 1) {
1003         /* fprintf(stderr, "Error converting intercept: %s\n", interceptString); */
1004         return 3;
1005     }
1006 
1007     *interceptValue = intercept;
1008     *slopeValue    = slope;
1009     return 0;
1010 }
1011 
1012 /*-----------------------------------------------------------------------*/
1013 
1014 #define RED_COMP        0.299
1015 #define GREEN_COMP      0.587
1016 #define BLUE_COMP       0.114
1017 
1018 static int 
1019 map_color_to_intgrey(DCM_OBJECT ** object, void *pixels,
1020                   int *mappedPixels, int count,
1021                   char *photometricInterpretation,
1022                   int bitsAllocated, int bitsStored, int highBit,
1023                   int pixelRepresentation)
1024 {
1025     static unsigned short planarConfig;
1026     DCM_ELEMENT l[] = {
1027         {DCM_IMGPLANARCONFIGURATION, DCM_US, "",
1028         1, sizeof(planarConfig), (void *) &planarConfig}
1029     };
1030     CONDITION cond;
1031     int i,
1032         intensity;
1033 
1034     if (strcmp(photometricInterpretation, "RGB") == 0) {
1035         cond = DCM_ParseObject(object, l, (int) DIM_OF(l), NULL, 0, NULL);
1036         if (cond != DCM_NORMAL) {
1037             /* COND_DumpConditions(); */
1038             return 3;
1039         }
1040         if (bitsAllocated == 8) {
1041             unsigned char *p8;
1042             p8 = (unsigned char *) pixels;
1043             if (planarConfig == 0) {    /* R1G1B1  R2G2B2 ... */
1044                 for (i = 0; i < count; i++) {
1045                     intensity =
1046                         (int) ((RED_COMP * (float) p8[0]) +
1047                                (GREEN_COMP * (float) p8[1]) +
1048                                (BLUE_COMP * (float) p8[2]));
1049                     *mappedPixels++ = intensity;
1050                     p8 += 3;
1051                 }
1052             } else {            /* R1R2R3.. G1G2G3... B1B2B3... */
1053                 for (i = 0; i < count; i++) {
1054                     intensity =
1055                         (int) ((RED_COMP * (float) p8[0]) +
1056                                (GREEN_COMP * (float) p8[count]) +
1057                                (BLUE_COMP * (float) p8[count]));
1058                     *mappedPixels++ = intensity;
1059                     p8++;
1060                 }
1061             }
1062         } else if (strcmp(photometricInterpretation, "PALETTE COLOR") == 0) {
1063             map_palette_color(object, pixels, mappedPixels, count,
1064                               photometricInterpretation,
1065                               bitsAllocated, bitsStored, highBit,
1066                               pixelRepresentation);
1067         } else {
1068             /* fprintf(stderr, "Can not handle 16 bits allocated for RGB image\n"); */
1069             return 1;
1070         }
1071     } else if (strcmp(photometricInterpretation, "PALETTE COLOR") == 0) {
1072         map_palette_color(object, pixels, mappedPixels, count,
1073                        photometricInterpretation, bitsAllocated, bitsStored,
1074                           highBit, pixelRepresentation);
1075     } else {
1076         /* fprintf(stderr, "Could not deal with %s\n", photometricInterpretation); */
1077         return 2;
1078     }
1079 
1080     return 0;
1081 }
1082 
1083 /*-----------------------------------------------------------------------*/
1084 static int 
1085 map_palette_color(DCM_OBJECT ** object, void *pixels,
1086                   int *mappedPixels, int count,
1087                   char *photometricInterpretation,
1088                   int bitsAllocated, int bitsStored, int highBit,
1089                   int pixelRepresentation)
1090 {
1091     static char
1092         WindowWidth[128] = "",  /* strings for TEXT (DCM_IS) elements */
1093         WindowCenter[128] = "",
1094         Slope[128] = "",
1095         Intercept[128] = "";
1096 
1097     static unsigned short
1098         sampsperpixel,
1099         nrows,
1100         ncols,
1101         bitsallocated,
1102         bitsstored,
1103         highbit,
1104         pixrep,
1105         planarconfig,
1106         s;                      /* Utility var used for shorts   */
1107 
1108     static short
1109         red_entries,            /* For PALETTE COLOR LUTS        */
1110         red_first_map,
1111         blue_entries,
1112         blue_first_map,
1113         green_entries,
1114         green_first_map;
1115 
1116     static unsigned short       /* These changed to unsigned shorts      */
1117        *red_table,              /* to address a problem with 8 bit data */
1118        *blue_table,
1119        *green_table;
1120 
1121     U32
1122         rtnLength;              /* Needed for Get Element calls  */
1123     void
1124        *ctx;
1125 
1126     short
1127        *stemp;
1128 
1129 /*
1130  * Initialize the Required Elements to prepare for retrieval...
1131  */
1132     static DCM_ELEMENT required[] = {
1133         {DCM_IMGSAMPLESPERPIXEL, DCM_US, "", 1,
1134         sizeof(sampsperpixel), (void *) &(sampsperpixel)},
1135         {DCM_IMGROWS, DCM_US, "", 1,
1136         sizeof(nrows), (void *) &(nrows)},
1137         {DCM_IMGCOLUMNS, DCM_US, "", 1,
1138         sizeof(ncols), (void *) &(ncols)},
1139         {DCM_IMGBITSALLOCATED, DCM_US, "", 1,
1140         sizeof(bitsallocated), (void *) &(bitsallocated)},
1141         {DCM_IMGBITSSTORED, DCM_US, "", 1,
1142         sizeof(bitsstored), (void *) &(bitsstored)},
1143         {DCM_IMGHIGHBIT, DCM_US, "", 1,
1144         sizeof(highbit), (void *) &(highbit)},
1145         {DCM_IMGPIXELREPRESENTATION, DCM_US, "", 1,
1146         sizeof(pixrep), (void *) &(pixrep)}
1147     };
1148 
1149     /*
1150      * These elements are optional...(except for pixel data) (Certain
1151      * elements are required depending on the photointerpretation) (i.e. if
1152      * photointerp is PALETTECOLOR, then the palette color lookup tables must
1153      * be present.)
1154      */
1155     DCM_ELEMENT
1156         redlutdesc = {
1157         DCM_IMGLUTDESCRIPTRED, DCM_OT, "",
1158             1, 0, NULL
1159     },
1160         bluelutdesc = {
1161         DCM_IMGLUTDESCRIPTBLUE, DCM_OT, "",
1162             1, 0, NULL
1163     },
1164         greenlutdesc = {
1165         DCM_IMGLUTDESCRIPTGREEN, DCM_OT, "",
1166             1, 0, NULL
1167     },
1168         redlut = {
1169         DCM_IMGLOOKUPDATARED, DCM_OT, "",
1170             1, 0, NULL
1171     },
1172         bluelut = {
1173         DCM_IMGLOOKUPDATABLUE, DCM_OT, "",
1174             1, 0, NULL
1175     },
1176         greenlut = {
1177         DCM_IMGLOOKUPDATAGREEN, DCM_OT, "",
1178             1, 0, NULL
1179     },
1180         slope = {
1181         DCM_IMGRESCALESLOPE, DCM_IS, "",
1182             1, sizeof(Slope), (void *) Slope
1183     },
1184         intercept = {
1185         DCM_IMGRESCALEINTERCEPT, DCM_IS, "",
1186             1, sizeof(Intercept), (void *) Intercept
1187     },
1188         window_center = {
1189         DCM_IMGWINDOWCENTER, DCM_IS, "",
1190             1, sizeof(WindowCenter), (void *) WindowCenter
1191     },
1192         window_width = {
1193         DCM_IMGWINDOWWIDTH, DCM_IS, "",
1194             1, sizeof(WindowWidth), (void *) WindowWidth
1195     },
1196         pc = {
1197         DCM_IMGPLANARCONFIGURATION, DCM_US, "",
1198             1, sizeof(planarconfig), (void *) &(planarconfig)
1199     };
1200 
1201     /*
1202      * Get the required elements...
1203      */
1204     if (DCM_ParseObject(object, required, (int) DIM_OF(required), NULL, 0, NULL) != DCM_NORMAL) {
1205         /* COND_DumpConditions(); */
1206         return 1;
1207     }
1208 /*
1209  * The planar configuration tells us if we need to intrepret multiple samples per pixel as
1210  * R1G1B1 R2G2B2.... or R1R2R3...G1G2G3...B1B2B3...
1211  */
1212     planarconfig = 0xfff;
1213     ctx = NULL;
1214     if (sampsperpixel > 1) {
1215         if (DCM_GetElementValue(object, &pc, &rtnLength, &ctx) != DCM_NORMAL) {
1216             /* COND_DumpConditions(); */
1217             return 2;
1218         }
1219     } {
1220         /*
1221          * Read in the color palette tables now b/c we need them for either
1222          * of the preceding methods
1223          */
1224         /*
1225          * Get the Look up table descriptors
1226          */
1227         if (DCM_GetElementSize(object, redlutdesc.tag, &rtnLength) != DCM_NORMAL) {
1228             /* COND_DumpConditions(); */
1229             return 3;
1230         }
1231         /*
1232          * Check the of the LUT descriptor to make sure we have the correct
1233          * amount...
1234          */
1235         if (rtnLength != 3 * sizeof(short)) {
1236             /* COND_DumpConditions(); */
1237             return 4;
1238         }
1239         /*
1240          * Allocate the memory to hold the LUT descriptor data and get it
1241          * from the DICOM file...
1242          */
1243         stemp = (void *) malloc(rtnLength);
1244         if (stemp == NULL) {
1245             /* COND_DumpConditions(); */
1246             return 5;
1247         }
1248         redlutdesc.length = rtnLength;
1249         redlutdesc.d.ot = stemp;
1250 
1251         ctx = NULL;
1252         if (DCM_GetElementValue(object, &redlutdesc, &rtnLength, &ctx) != DCM_NORMAL) {
1253             /* COND_DumpConditions(); */
1254             return 6;
1255         }
1256         red_entries = *stemp;
1257         red_first_map = *(stemp + 1);
1258 /*      red_bits_per_entry = *(stemp + 2); */
1259 
1260         if (DCM_GetElementSize(object, bluelutdesc.tag, &rtnLength) != DCM_NORMAL) {
1261             /* COND_DumpConditions(); */
1262             return 7;
1263         }
1264         /*
1265          * Check the of the LUT descriptor to make sure we have the correct
1266          * amount...
1267          */
1268         if (rtnLength != 3 * sizeof(short)) {
1269             /* COND_DumpConditions(); */
1270             return 8;
1271         }
1272         bluelutdesc.length = rtnLength;
1273         bluelutdesc.d.ot = stemp;
1274 
1275         ctx = NULL;
1276         if (DCM_GetElementValue(object, &bluelutdesc, &rtnLength, &ctx) != DCM_NORMAL) {
1277             /* COND_DumpConditions(); */
1278             return 9;
1279         }
1280         blue_entries = *stemp;
1281         blue_first_map = *(stemp + 1);
1282 /*      blue_bits_per_entry = *(stemp + 2); */
1283 
1284         if (DCM_GetElementSize(object, greenlutdesc.tag, &rtnLength) != DCM_NORMAL) {
1285             /* COND_DumpConditions(); */
1286             return 10;
1287         }
1288         /*
1289          * Check the of the LUT descriptor to make sure we have the correct
1290          * amount...
1291          */
1292         if (rtnLength != 3 * sizeof(short)) {
1293             /* COND_DumpConditions(); */
1294             return 11;
1295         }
1296         greenlutdesc.length = rtnLength;
1297         greenlutdesc.d.ot = stemp;
1298 
1299         ctx = NULL;
1300         if (DCM_GetElementValue(object, &greenlutdesc, &rtnLength, &ctx) != DCM_NORMAL) {
1301             /* COND_DumpConditions(); */
1302             return 12;
1303         }
1304         green_entries = *stemp;
1305         green_first_map = *(stemp + 1);
1306 /*      green_bits_per_entry = *(stemp + 2); */
1307 
1308         free(stemp);
1309         /*
1310          * Check to make sure all the luts have the same number of entries...
1311          */
1312         if ((red_entries != blue_entries) ||
1313             (red_entries != green_entries)) {
1314             return 13;
1315         }
1316         /*
1317          * Get the RED LUT...
1318          */
1319         if (DCM_GetElementSize(object, redlut.tag, &rtnLength) != DCM_NORMAL) {
1320             /* COND_DumpConditions(); */
1321             return 14;
1322         }
1323         /*
1324          * Check the of the LUT descriptor to make sure we have the correct
1325          * amount...
1326          */
1327         if (rtnLength != (red_entries * sizeof(short))) {
1328             return 15;
1329         }
1330         /*
1331          * Allocate the memory to hold the RED LUT data and get it from the
1332          * DICOM file...
1333          */
1334         stemp = (void *) malloc(rtnLength);
1335         if (stemp == NULL) {
1336             return 16;
1337         }
1338         redlut.length = rtnLength;
1339         redlut.d.ot = stemp;
1340 
1341         ctx = NULL;
1342         if (DCM_GetElementValue(object, &redlut, &rtnLength, &ctx) != DCM_NORMAL) {
1343             return 17;
1344         }
1345         red_table = (unsigned short *) stemp;
1346 
1347         /*
1348          * Get the BLUE LUT
1349          */
1350         if (DCM_GetElementSize(object, bluelut.tag, &rtnLength) != DCM_NORMAL) {
1351             return 18;
1352         }
1353         /*
1354          * Check the of the LUT descriptor to make sure we have the correct
1355          * amount...
1356          */
1357         if (rtnLength != (blue_entries * sizeof(short))) {
1358             return 19;
1359         }
1360         /*
1361          * Allocate the memory to hold the BLUE LUT data and get it from the
1362          * DICOM file...
1363          */
1364         stemp = (void *) malloc(rtnLength);
1365         if (stemp == NULL) {
1366             return 20;
1367         }
1368         bluelut.length = rtnLength;
1369         bluelut.d.ot = stemp;
1370 
1371         ctx = NULL;
1372         if (DCM_GetElementValue(object, &bluelut, &rtnLength, &ctx) != DCM_NORMAL) {
1373             return 21;
1374         }
1375         blue_table = (unsigned short *) stemp;
1376 
1377         /*
1378          * Get the GREEN LUT
1379          */
1380         if (DCM_GetElementSize(object, greenlut.tag, &rtnLength) != DCM_NORMAL) {
1381             return 22;
1382         }
1383         /*
1384          * Check the GREEN LUT descriptor to make sure we have the correct
1385          * amount...
1386          */
1387         if (rtnLength != (green_entries * sizeof(short))) {
1388             return 23;
1389         }
1390         /*
1391          * Allocate the memory to hold the LUT data and get it from the DICOM
1392          * file...
1393          */
1394         stemp = (void *) malloc(rtnLength);
1395         if (stemp == NULL) {
1396             return 24;
1397         }
1398         greenlut.length = rtnLength;
1399         greenlut.d.ot = stemp;
1400 
1401         ctx = NULL;
1402         if (DCM_GetElementValue(object, &greenlut, &rtnLength, &ctx) != DCM_NORMAL) {
1403             return 25;
1404         }
1405         green_table = (unsigned short *) stemp;
1406         /*
1407          * Now we check to see if we have 8 bit data, if so we will rescale
1408          * the LUTS from 0 to 255...we're going to lose it somewhere, so we
1409          * may as well rescale the smallest amount of data possible...
1410          */
1411         if (bitsAllocated == 8) {
1412             int max,
1413                 index;
1414             float sf;
1415             max = 0;
1416             for (index = 0; index < red_entries; index++) {
1417                 if ((int) red_table[index] > max)
1418                     max = red_table[index];
1419                 if ((int) green_table[index] > max)
1420                     max = green_table[index];
1421                 if ((int) blue_table[index] > max)
1422                     max = blue_table[index];
1423             }
1424             if (max > 0)
1425                 sf = (float) 255.0 / (float) max;
1426             else
1427                 sf = (float) 1.;
1428             for (index = 0; index < red_entries; index++) {
1429 /*lint -e524 */
1430                 red_table[index] *= sf;
1431                 green_table[index] *= sf;
1432                 blue_table[index] *= sf;
1433 /*lint +e524 */
1434             }
1435         } {
1436             int   *ncs;
1437             short  *cs;
1438             int   *nbs;
1439             unsigned char *bs;
1440             int index;
1441 
1442             if (bitsAllocated == 16) {  /* 16 bits per pixel and PALETTE
1443                                          * COLOR */
1444                 ncs = (int *) mappedPixels;
1445                 cs = (short *) pixels;
1446                 for (index = 0; index < count; index++) {
1447                     if (*cs < red_first_map) {
1448                         *ncs = (int) (
1449                                         (RED_COMP * (float) (*red_table)) +
1450                                      (GREEN_COMP * (float) (*green_table)) +
1451                                         (BLUE_COMP * (float) (*blue_table))
1452                             );
1453                     } else if (*cs > (red_first_map + red_entries - 1)) {
1454                         *ncs = (int) (
1455                                         (RED_COMP * (float) (*(red_table + red_entries - 1))) +
1456                                         (GREEN_COMP * (float) (*(green_table + green_entries - 1))) +
1457                                         (BLUE_COMP * (float) (*(blue_table + blue_entries - 1)))
1458                             );
1459                     } else {
1460                         *ncs = (int) (
1461                                         (RED_COMP * (float) (*(red_table + (*cs - red_first_map)))) +
1462                                         (GREEN_COMP * (float) (*(green_table + (*cs - green_first_map)))) +
1463                                         (BLUE_COMP * (float) (*(blue_table + (*cs - blue_first_map))))
1464                             );
1465                     }
1466                     ncs++;
1467                     cs++;
1468                 }
1469             } else {            /* 8 bits per pixel and PALETTE COLOR */
1470                 nbs = (int *) mappedPixels;
1471                 bs = (unsigned char *) pixels;
1472                 for (index = 0; index < count; index++) {
1473                     if (*bs < (unsigned char) red_first_map) {
1474                         *nbs = (int) (
1475                                          (RED_COMP * (float) (*red_table)) +
1476                                      (GREEN_COMP * (float) (*green_table)) +
1477                                          (BLUE_COMP * (float) (*blue_table))
1478                             );
1479                     } else if (*bs > (unsigned char) (red_first_map + red_entries - 1)) {
1480                         *nbs = (int) (
1481                                                 (RED_COMP * (float) (*(red_table + red_entries - 1))) +
1482                                                 (GREEN_COMP * (float) (*(green_table + green_entries - 1))) +
1483                                                 (BLUE_COMP * (float) (*(blue_table + blue_entries - 1)))
1484                             );
1485                     } else {
1486                         *nbs = (int) (
1487                                                 (RED_COMP * (float) (*(red_table + (*bs - red_first_map)))) +
1488                                                 (GREEN_COMP * (float) (*(green_table + (*bs - green_first_map)))) +
1489                                                 (BLUE_COMP * (float) (*(blue_table + (*bs - blue_first_map))))
1490                             );
1491                     }
1492                     nbs++;
1493                     bs++;
1494                 }
1495             }
1496         }
1497     }
1498 }
1499 
1500 /*-----------------------------------------------------------------------*/
1501 static
1502 CONDITION
1503 MyDumpElements(DCM_OBJECT ** callerObject, long vm, FILE* headerdump)
1504 /* IH's adaptation of the DCM_DumpElements routine */
1505 {
1506     PRV_GROUP_ITEM
1507         * groupItem;
1508     PRV_ELEMENT_ITEM
1509         * elementItem;
1510     PRIVATE_OBJECT
1511         ** object;
1512     CONDITION
1513         cond;
1514     DCM_SEQUENCE_ITEM
1515         * sq;
1516     char
1517         scratch[128];
1518     int
1519         stringLength;
1520 
1521     if(headerdump==NULL) return DCM_NORMAL;
1522 
1523     object = (PRIVATE_OBJECT **) callerObject;
1524 
1525     cond = checkObject(object, "MyDumpElements");
1526     if (cond != DCM_NORMAL)
1527         return cond;
1528 
1529     fprintf(headerdump,"\nDCM Dump Elements\n");
1530     switch ((*object)->objectType) {
1531     case DCM_OBJECTUNKNOWN:
1532         fprintf(headerdump,"Object type: COMMAND\n");
1533         break;
1534     case DCM_OBJECTIMAGE:
1535         fprintf(headerdump,"Object type: IMAGE\n");
1536         break;
1537     case DCM_OBJECTELEMENTLIST:
1538         fprintf(headerdump,"Object type: ELEMENT LIST\n");
1539         break;
1540     default:
1541         fprintf(headerdump,"Object type: Unknown (error)\n");
1542         break;
1543     }
1544     fprintf(headerdump,"Object size: %ld\n", (*object)->objectSize);
1545 
1546     groupItem = LST_Head(&(*object)->groupList);
1547     if (groupItem != NULL)
1548         (void) LST_Position(&(*object)->groupList, groupItem);
1549 
1550     while (groupItem != NULL) {
1551 #ifdef MACOS
1552         fprintf(headerdump,"Group: %04x, Length: %8ld\n", groupItem->group,
1553                groupItem->baseLength);
1554 #else
1555         fprintf(headerdump,"Group: %04x, Length: %8d\n", groupItem->group,
1556                groupItem->baseLength);
1557 #endif
1558         elementItem = LST_Head(&groupItem->elementList);
1559         if (elementItem != NULL)
1560             (void) LST_Position(&groupItem->elementList, elementItem);
1561         while (elementItem != NULL) {
1562 #ifdef MACOS
1563             (void) fprintf(headerdump,"%04x %04x %8ld ",
1564                           DCM_TAG_GROUP(elementItem->element.tag),
1565                           DCM_TAG_ELEMENT(elementItem->element.tag),
1566                           elementItem->element.length);
1567 #else
1568             (void) fprintf(headerdump,"%04x %04x %8d ",
1569                           DCM_TAG_GROUP(elementItem->element.tag),
1570                           DCM_TAG_ELEMENT(elementItem->element.tag),
1571                           elementItem->element.length);
1572 #endif
1573             (void) fprintf(headerdump,"//%31s//", elementItem->element.description);
1574             if (elementItem->element.d.ot == NULL)
1575                 (void) fprintf(headerdump,"Data on disk\n");
1576             else {
1577                 switch (elementItem->element.representation) {
1578                 case DCM_AE:
1579                 case DCM_AS:
1580                 case DCM_CS:
1581                 case DCM_DA:
1582                 case DCM_DT:
1583                     stringLength = MIN(sizeof(scratch) - 1, elementItem->element.length);
1584                     strncpy(scratch, elementItem->element.d.string, stringLength);
1585                     scratch[stringLength] = '\0';
1586                     (void) fprintf(headerdump,"%s\n", scratch);
1587                     break;
1588                 case DCM_DD:
1589                 case DCM_FD:
1590                 case DCM_FL:
1591                     (void) fprintf(headerdump,"Unimplemented\n");
1592                     break;
1593                 case DCM_DS:
1594                 case DCM_IS:
1595                 case DCM_LO:
1596                 case DCM_LT:
1597                 case DCM_PN:
1598                 case DCM_SH:
1599                     stringLength = MIN(sizeof(scratch) - 1, elementItem->element.length);
1600                     strncpy(scratch, elementItem->element.d.string, stringLength);
1601                     scratch[stringLength] = '\0';
1602                     (void) fprintf(headerdump,"%s\n", scratch);
1603                     break;
1604                 case DCM_SL:
1605 #ifdef MACOS
1606                     (void) fprintf(headerdump,"%8lx %ld\n", *elementItem->element.d.sl,
1607                                   *elementItem->element.d.sl);
1608 #else
1609                     (void) fprintf(headerdump,"%8x %d\n", *elementItem->element.d.sl,
1610                                   *elementItem->element.d.sl);
1611                     if (vm > 1)
1612                         dumpBinaryData(elementItem->element.d.ot,
1613                                        elementItem->element.representation,
1614                              elementItem->element.length / sizeof(U32), vm);
1615 #endif
1616                     break;
1617                 case DCM_SS:
1618                     (void) fprintf(headerdump,"%4x %d\n", *elementItem->element.d.ss,
1619                                   *elementItem->element.d.ss);
1620                     if (vm > 1)
1621                         dumpBinaryData(elementItem->element.d.ot,
1622                                        elementItem->element.representation,
1623                            elementItem->element.length / sizeof(short), vm);
1624                     break;
1625                 case DCM_SQ:
1626                     (void) fprintf(headerdump,"SEQUENCE\n");
1627                     sq = LST_Head(&elementItem->element.d.sq);
1628                     if (sq != NULL)
1629                         (void) LST_Position(&elementItem->element.d.sq, sq);
1630                     fprintf(headerdump,"DCM Dump Sequence\n");
1631                     while (sq != NULL) {
1632                         (void) MyDumpElements(&sq->object, vm,headerdump);
1633                         sq = LST_Next(&elementItem->element.d.sq);
1634                     }
1635                     fprintf(headerdump,"DCM Dump Sequence Complete\n");
1636                     break;
1637                 case DCM_ST:
1638                     stringLength = MIN(sizeof(scratch) - 1, elementItem->element.length);
1639                     strncpy(scratch, elementItem->element.d.string, stringLength);
1640                     scratch[stringLength] = '\0';
1641                     (void) fprintf(headerdump,"%s\n", scratch);
1642                     break;
1643                 case DCM_TM:
1644                 case DCM_UI:
1645                     stringLength = MIN(sizeof(scratch) - 1, elementItem->element.length);
1646                     strncpy(scratch, elementItem->element.d.string, stringLength);
1647                     scratch[stringLength] = '\0';
1648                     (void) fprintf(headerdump,"%s\n", scratch);
1649                     break;
1650                 case DCM_AT:
1651                 case DCM_UL:
1652 #ifdef MACOS
1653                     (void) fprintf(headerdump,"%8lx %ld\n", *elementItem->element.d.ul,
1654                                   *elementItem->element.d.ul);
1655 #else
1656                     (void) fprintf(headerdump,"%8x %d\n", *elementItem->element.d.ul,
1657                                   *elementItem->element.d.ul);
1658                     if (vm > 1)
1659                         dumpBinaryData(elementItem->element.d.ot,
1660                                        elementItem->element.representation,
1661                              elementItem->element.length / sizeof(U32), vm);
1662 #endif
1663                     break;
1664                 case DCM_US:
1665                     (void) fprintf(headerdump,"%4x %d\n", *elementItem->element.d.us,
1666                                   *elementItem->element.d.us);
1667                     if (vm > 1)
1668                         dumpBinaryData(elementItem->element.d.ot,
1669                                        elementItem->element.representation,
1670                                        elementItem->element.length / sizeof(unsigned short), vm);
1671                     break;
1672                 case DCM_OT:
1673                 case DCM_OW:
1674                 case DCM_OB:
1675                 case DCM_UNKNOWN:
1676                 case DCM_RET:
1677                     (void) fprintf(headerdump,"Unimplemented\n");
1678                     break;
1679                 default:
1680                     (void) fprintf(headerdump,"Some unimplemented logic if here\n");
1681                     break;
1682                 }
1683             }
1684             elementItem = LST_Next(&groupItem->elementList);
1685         }
1686         groupItem = LST_Next(&(*object)->groupList);
1687     }
1688 
1689     fprintf(headerdump,"DCM Dump Elements Complete\n\n");
1690 
1691     return DCM_NORMAL;
1692 }
1693 
1694 /*-----------------------------------------------------------------------*/
1695 
1696 static CONDITION
1697 checkObject(PRIVATE_OBJECT ** object, char *caller)
1698 {
1699     if (object == NULL)
1700         return COND_PushCondition(DCM_NULLOBJECT, DCM_Message(DCM_NULLOBJECT),
1701                                   caller);
1702     if (*object == NULL)
1703         return COND_PushCondition(DCM_NULLOBJECT, DCM_Message(DCM_NULLOBJECT),
1704                                   caller);
1705 
1706     if (strcmp((*object)->keyType, KEY_DCM_OBJECT) != 0)
1707         return COND_PushCondition(DCM_ILLEGALOBJECT,
1708                                   DCM_Message(DCM_ILLEGALOBJECT), caller);
1709     return DCM_NORMAL;
1710 }
1711 
1712 /*-----------------------------------------------------------------------*/
1713 
1714 static void
1715 dumpSS(short *ss, long vm)
1716 {
1717     long index = 0;
1718     while (index < vm) {
1719         printf("%7d ", *(ss++));
1720         if ((++index) % 8 == 0)
1721             printf("\n");
1722     }
1723     printf("\n");
1724 }
1725 
1726 static void
1727 dumpSL(S32 * sl, long vm)
1728 {
1729     long index = 0;
1730     while (index < vm) {
1731         printf("%7d ", *(sl++));
1732         if ((++index) % 8 == 0)
1733             printf("\n");
1734     }
1735     printf("\n");
1736 }
1737 
1738 static void
1739 dumpUS(unsigned short *us, long vm)
1740 {
1741     long index = 0;
1742     while (index < vm) {
1743         printf("%7d ", *(us++));
1744         if ((++index) % 8 == 0)
1745             printf("\n");
1746     }
1747     printf("\n");
1748 }
1749 
1750 static void
1751 dumpUL(U32 * ul, long vm)
1752 {
1753     long index = 0;
1754     while (index < vm) {
1755         printf("%7d ", *(ul++));
1756         if ((++index) % 8 == 0)
1757             printf("\n");
1758     }
1759     printf("\n");
1760 }
1761 
1762 
1763 /*-----------------------------------------------------------------------*/
1764 
1765 static void
1766 dumpBinaryData(void *d, DCM_VALUEREPRESENTATION vr, long vm,
1767                long vmLimit)
1768 {
1769     vm = (vm < vmLimit) ? vm : vmLimit;
1770 
1771     if (vm <= 1)
1772         return;
1773 
1774 
1775     switch (vr) {
1776     case DCM_SL:
1777         dumpSL((S32 *) d, vm);
1778         break;
1779     case DCM_UL:
1780         dumpUL((U32 *) d, vm);
1781         break;
1782     case DCM_SS:
1783         dumpSS((short *) d, vm);
1784         break;
1785     case DCM_US:
1786         dumpUS((unsigned short *) d, vm);
1787         break;
1788     default:
1789         break;
1790     }
1791 }
1792 
1793 dicom_hdr_dynstimes_extract(){};
1794 dicom_hdr_heartrate_extract(){};
1795 dicom_hdr_TE_extract(){};
1796 dicom_hdr_patientdetails_extract(){};
1797 dicom_hdr_voxelscale_extract(){};
1798 
1799 
1800 ih_identify_dicom_io(){
1801 printf("-------------------------------------------------\n"); 
1802 printf("dicom_io.c:  %s %s\n",__DATE__,__TIME__); 
1803 printf("-------------------------------------------------\n"); 
1804 }
1805 
1806 /*-----------------------------------------------------------------------*/
1807 /*
1808           Copyright (C) 1993, 1994, RSNA and Washington University
1809 
1810           The software and supporting documentation for the Radiological
1811           Society of North America (RSNA) 1993, 1994 Digital Imaging and
1812           Communications in Medicine (DICOM) Demonstration were developed
1813           at the
1814                   Electronic Radiology Laboratory
1815                   Mallinckrodt Institute of Radiology
1816                   Washington University School of Medicine
1817                   510 S. Kingshighway Blvd.
1818                   St. Louis, MO 63110
1819           as part of the 1993, 1994 DICOM Central Test Node project for, and
1820           under contract with, the Radiological Society of North America.
1821 
1822           THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND NEITHER RSNA NOR
1823           WASHINGTON UNIVERSITY MAKE ANY WARRANTY ABOUT THE SOFTWARE, ITS
1824           PERFORMANCE, ITS MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR
1825           USE, FREEDOM FROM ANY COMPUTER DISEASES OR ITS CONFORMITY TO ANY
1826           SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND PERFORMANCE OF
1827           THE SOFTWARE IS WITH THE USER.
1828 
1829           Copyright of the software and supporting documentation is
1830           jointly owned by RSNA and Washington University, and free access
1831           is hereby granted as a license to use this software, copy this
1832           software and prepare derivative works based upon this software.
1833           However, any distribution of this software source code or
1834           supporting documentation or derivative works (source code and
1835           supporting documentation) must include the three paragraphs of
1836           the copyright notice.
1837 */
1838 /*-----------------------------------------------------------------------*/
1839 
1840 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.