/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * filename: m-acr.c * * * * UTIL C-source: Medical Image Conversion Utility * * * * purpose : read and write ACR/NEMA files * * * * project : (X)MedCon by Erik Nolf * * * * Functions : MdcCheckACR() - Check ACR/NEMA format * * MdcSwapTag() - Swap bytes in tag * * MdcFindAcrInfo() - Find readable tags in hacked file * * MdcGetAcrInfo() - Get data from tags in hacked file * * MdcHackACR() - Hack a file for ACR/NEMA tags * * MdcReadACR() - Read ACR/NEMA file * * MdcPrintTag() - Display tag content * * MdcGetStrVM() - Get VM string from an element * * MdcDicomInitStuff()- Initialize dicom stuff struct * * MdcDicomCheckVect()- Check dicom vector tags * * MdcDicomNrOfVect() - Give true number of vector items * * MdcDicomDoAcqData()- Check wheter to fill acq data * * MdcDicomSOPClass() - Handle SOP Class (modality) * * MdcGetHHMMSS() - Get hour, minute, sec from string * * MdcDoTag() - Handle the tag * * MdcPutGroupLength()- Write the group length * * MdcPutTag() - Write tag to file * * MdcPutGroup() - Write group to file * * MdcWriteACR() - Write ACR/NEMA file * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* $Id: m-acr.c,v 1.127 2007/08/22 00:32:58 enlf Exp $ */ /* Copyright (C) 1997-2007 by Erik Nolf This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Place - Suite 330, Boston, MA 02111-1307, USA. */ /**************************************************************************** H E A D E R S ****************************************************************************/ #include "m-depend.h" #include #include #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STRINGS_H #ifndef _WIN32 #include #endif #endif #include "medcon.h" /**************************************************************************** D E F I N E S ****************************************************************************/ #define MDC_TAGS_NEEDED 3 static Uint32 MDC_HACK_BYTES = 2048; static int MDC_HACK_SUCCESS; static long FP_G0008_E0001; MDC_DICOM_STUFF_T mdc_dicom_stuff; /**************************************************************************** F U N C T I O N S ****************************************************************************/ int MdcCheckACR(FILEINFO *fi) { MDC_ACR_TAG acrtag[3], *tag; Int8 FRMT = MDC_FRMT_NONE; fread((Uint8 *)&acrtag[0], 1, MDC_ACR_TAG_SIZE, fi->ifp); if (ferror(fi->ifp)) return (MDC_BAD_READ); if (acrtag[0].group == 0x0008) MDC_FILE_ENDIAN = MDC_HOST_ENDIAN; else { MDC_FILE_ENDIAN = !MDC_HOST_ENDIAN; } MdcSwapTag(&acrtag[0]); if (acrtag[0].group != 0x0008) return(MDC_FRMT_NONE); fseek(fi->ifp,(signed)acrtag[0].length,SEEK_CUR); fread((Uint8 *)&acrtag[1], 1, MDC_ACR_TAG_SIZE, fi->ifp); MdcSwapTag(&acrtag[1]); fseek(fi->ifp, (signed)acrtag[1].length, SEEK_CUR); fread((Uint8 *)&acrtag[2], 1, MDC_ACR_TAG_SIZE, fi->ifp); MdcSwapTag(&acrtag[2]); if (ferror(fi->ifp)) return(MDC_BAD_READ); if (acrtag[1].group != 0x0008) return(MDC_FRMT_NONE); if (acrtag[2].group != 0x0008) return (MDC_FRMT_NONE); /* return(MDC_FRMT_ACR) */ /* test on Acr/Nema Recognition code as well */ /* to prevent little implicit DICOM files */ fseek(fi->ifp,(signed)0,SEEK_SET); tag = (MDC_ACR_TAG *)&acrtag[0]; while( ftell(fi->ifp) < MDC_HACK_BYTES) { if (fread((Uint8 *)tag,1,MDC_ACR_TAG_SIZE,fi->ifp) != MDC_ACR_TAG_SIZE) return(MDC_BAD_READ); MdcSwapTag(tag); if (tag->length == 0xffffffff) tag->length = 0; if ((tag->group == 0x0008) && (tag->element == 0x0010)) { if ((tag->data=malloc(tag->length+1)) == NULL) return(MDC_BAD_ALLOC); tag->data[tag->length]='\0'; if (fread(tag->data,1,tag->length,fi->ifp) != tag->length) { MdcFree(tag->data); return(MDC_BAD_READ); } MdcLowStr((char *)tag->data); if (strstr((char *)tag->data,"acr-nema") != NULL) FRMT = MDC_FRMT_ACR; MdcFree(tag->data); return(FRMT); }else{ fseek(fi->ifp,(signed)tag->length,SEEK_CUR); } if (ferror(fi->ifp)) return(MDC_BAD_READ); } return(FRMT); } void MdcSwapTag(MDC_ACR_TAG *tag) { MdcSWAP(tag->group); MdcSWAP(tag->element); MdcSWAP(tag->length); } int MdcFindAcrInfo(FILEINFO *fi,Uint32 filesize, Uint32 *BeginAddress) { FILE *fp=fi->ifp; MDC_ACR_TAG acrtag, *tag=NULL; Uint32 AddressFound=(*BeginAddress); int HackSuccess=0, i; tag = (MDC_ACR_TAG *)&acrtag; fseek(fp,(signed)AddressFound,SEEK_SET); while( (ftell(fp) < MDC_HACK_BYTES) && (HackSuccesslength == 0xffffffff ) tag->length = 0; fseek(fp,(signed)tag->length,SEEK_CUR); tag->data=NULL; tag->length=0; /* leave data out */ MdcDoTag(NULL,tag,fi,0); if (MDC_HACK_SUCCESS) { MDC_HACK_SUCCESS = MDC_NO; HackSuccess+=1; }else{ MDC_HACK_SUCCESS = MDC_NO; HackSuccess=0; } } if (HackSuccess < MDC_TAGS_NEEDED) { AddressFound+=1; fseek(fp,(signed)AddressFound,SEEK_SET); } } *BeginAddress = AddressFound; if (HackSuccess < MDC_TAGS_NEEDED) return(MDC_NO); return(MDC_YES); } int MdcGetAcrInfo(FILEINFO *fi, Uint32 filesize, Uint32 offset) { FILE *fp = fi->ifp; MDC_ACR_TAG acrtag, *tag=NULL; Uint32 BytesPerImage; tag = (MDC_ACR_TAG *)&acrtag; fseek(fp,(signed)offset,SEEK_SET); while ( (ftell(fp) + MDC_ACR_TAG_SIZE) < filesize ) { if (fread((Uint8 *)tag,1,MDC_ACR_TAG_SIZE,fp) != MDC_ACR_TAG_SIZE) continue; MdcSwapTag(tag); if (tag->length == 0xffffffff) tag->length = 0; if ((tag->data=malloc(tag->length+1)) == NULL) { fseek(fp,(signed)tag->length,SEEK_CUR); continue; } tag->data[tag->length]='\0'; if (fread(tag->data,1,tag->length,fp) != tag->length) { MdcFree(tag->data); continue; } MdcDoTag(NULL,tag,fi,0); MdcFree(tag->data); } BytesPerImage = fi->image[0].width*fi->image[0].height; BytesPerImage *= MdcPixels2Bytes(fi->image[0].bits); if (BytesPerImage > 0 ) return(MDC_YES); return(MDC_NO); } /* experimental and will fail for images with different sizes */ char *MdcHackACR(FILEINFO *fi) { FILE *fp = fi->ifp; MDC_ACR_TAG acrtag, *tag=NULL; Uint32 filesize, BytesOffset, BeginAddress=0; Uint32 MaxImages=0, BytesPerImage=0, BytesPerPixel=0; Uint32 i, img=0, *ImagesOffsets=NULL; int found=MDC_NO; /* initialize some things */ MDC_INFO = MDC_NO; tag = (MDC_ACR_TAG *)&acrtag; fseek(fp,0L, SEEK_END); filesize = ftell(fp); fseek(fp,0L, SEEK_SET); /* MDC_HACK_BYTES = filesize; hack the whole file if you want */ MdcPrntScrn("\nACR Hacking <%s> for %u bytes ... ",fi->ifname ,MDC_HACK_BYTES); /* get an IMG_DATA struct */ if (!MdcGetStructID(fi,1)) return("ACR - Hack - Bad malloc IMG_DATA struct"); /* hack for HostEndian */ MDC_FILE_ENDIAN = MDC_HOST_ENDIAN; BeginAddress=0; while ( (!found) && (BeginAddress < MDC_HACK_BYTES)) { found=MdcFindAcrInfo(fi,filesize,&BeginAddress); if (found) found=MdcGetAcrInfo(fi,filesize,BeginAddress); if (!found) BeginAddress+=1; } if (found == MDC_NO) { /* hack for NoHostEndian */ MDC_FILE_ENDIAN = !MDC_HOST_ENDIAN; BeginAddress=0; while ( (!found) && (BeginAddress < MDC_HACK_BYTES)) { found=MdcFindAcrInfo(fi,filesize,&BeginAddress); if (found) found=MdcGetAcrInfo(fi,filesize,BeginAddress); if (!found) BeginAddress+=1; } } MDC_INFO=MDC_YES; /* print out/rework the information */ if (found == MDC_YES) { MdcPrntScrn("\n"); BytesPerPixel = MdcPixels2Bytes(fi->image[0].bits); BytesPerImage = fi->image[0].width*fi->image[0].height*BytesPerPixel; if (BytesPerImage > 0 ) MaxImages = filesize/BytesPerImage; if (MaxImages > 0) { ImagesOffsets=(Uint32 *)malloc((MaxImages+100)*sizeof(Uint32)); /* +100 as safe buffer */ if (ImagesOffsets == NULL) { return("ACR - Hack - Couldn't malloc ImagesOffsets array"); }else{ ImagesOffsets[0]=0; /* keeps the number of offsets */ } }else{ return("ACR - Hack - Failed to find number of images"); } fseek(fp,(signed)BeginAddress,SEEK_SET); while ( ((BytesOffset=ftell(fp)) + MDC_ACR_TAG_SIZE) <= filesize ) { if (fread((Uint8 *)tag,1,MDC_ACR_TAG_SIZE,fp) != MDC_ACR_TAG_SIZE) continue; MdcSwapTag(tag); if (tag->length == 0xffffffff ) tag->length = 0; if ((tag->data=malloc(tag->length+1)) == NULL) { fseek(fp,(signed)tag->length,SEEK_CUR); continue; } tag->data[tag->length]='\0'; if (fread(tag->data,1,tag->length,fp) != tag->length) { MdcFree(tag->data); continue; } MdcPrntScrn("\n==========>> BYTES OFFSET NEXT TAG: %u\n",BytesOffset); MdcDoTag(NULL,tag,fi,0); /* real Acr/Nema tag for image => real offset to image */ if (tag->group == 0x7fe0 && tag->element == 0x0010) { ImagesOffsets[img++]=BytesOffset + MDC_ACR_TAG_SIZE; }else if ((tag->length / BytesPerImage) == 1) { ImagesOffsets[img++]=BytesOffset + MDC_ACR_TAG_SIZE; } MdcFree(tag->data); } MdcPrntScrn("\n"); MdcPrntScrn("===================\n"); MdcPrntScrn("FINAL ACR-HACK INFO\n"); MdcPrntScrn("===================\n\n"); MdcPrntScrn("Patient/Study Info\n"); MdcPrntScrn("------------------\n"); MdcPrntScrn(" Patient Name : %s\n",fi->patient_name); MdcPrntScrn(" Patient Sex : %s\n",fi->patient_sex); MdcPrntScrn(" Patient ID : %s\n",fi->patient_id); MdcPrntScrn(" Study Descr : %s\n",fi->study_descr); MdcPrntScrn(" Study ID : %s\n",fi->study_id); MdcPrntScrn(" Study Date : %d/%d/%d [dd/mm/yyyy]\n",fi->study_date_day ,fi->study_date_month ,fi->study_date_year); MdcPrntScrn(" Study Time : %d:%d:%d [hh/mm/ss]\n",fi->study_time_hour ,fi->study_time_minute ,fi->study_time_second); MdcPrntScrn("\n"); MdcPrntScrn("Pixel/Slice Info\n"); MdcPrntScrn("------------------\n"); MdcPrntScrn(" Pixel Size : %+e [mm]\n",fi->image[0].pixel_ysize); MdcPrntScrn(" Slice Width : %+e [mm]\n",fi->image[0].slice_width); MdcPrntScrn("\n"); MdcPrntScrn("Images/Pixel Info\n"); MdcPrntScrn("------------------\n"); MdcPrntScrn(" Host Endian Type : %s\n",MdcGetStrEndian(MDC_HOST_ENDIAN)); MdcPrntScrn(" File Endian Type : %s\n",MdcGetStrEndian(MDC_FILE_ENDIAN)); MdcPrntScrn(" Offset First TAG : %u\n",BeginAddress); MdcPrntScrn(" Image Columns [X]: %u\n",fi->image[0].width); MdcPrntScrn(" Image Rows [Y]: %u\n",fi->image[0].height); MdcPrntScrn(" Bits / Pixel : %hd\n",fi->image[0].bits); MdcPrntScrn(" Bytes / Pixel : %u ",BytesPerPixel); switch(BytesPerPixel) { case 1: MdcPrntScrn("(Int8 , Uint8 , 1bit, ?)\n"); break; case 2: MdcPrntScrn("(Int16, Uint16, ?)\n"); break; case 4: MdcPrntScrn("(Int32, Uint32, float, ?)\n"); break; case 8: MdcPrntScrn("(Int64, Uint64, double, ?)\n"); break; default: MdcPrntScrn("(?)\n"); } MdcPrntScrn(" Possible Pix Type: %s\n" ,MdcGetStrPixelType(fi->image[0].type)); MdcPrntScrn(" Bytes / Image : %u\n",BytesPerImage); MdcPrntScrn(" Filesize : %u\n",filesize); if (BytesPerImage > 0) MdcPrntScrn(" Maximum Images : %u\n",MaxImages); else MdcPrntScrn(" Maximum Images : \n"); /* where to find the images? */ MdcPrntScrn("\n"); MdcPrntScrn("Possible Offsets to Images\n"); MdcPrntScrn("--------------------------\n"); MdcPrntScrn("\n a) tags->length ~ Bytes/Image:\n"); if (img == 0) { MdcPrntScrn("\n\t \n"); }else{ for (i=0; iifp; IMG_DATA *id = NULL; MDC_ACR_TAG acrtag, *tag = NULL; MDC_DICOM_STUFF_T *dicom=&mdc_dicom_stuff; Uint32 i, filesize, frames=1, t, number=0; int IMAGE = MDC_YES; const char *err=NULL; if (MDC_PROGRESS) MdcProgress(MDC_PROGRESS_BEGIN,0.,"Reading Acr/Nema:"); if (MDC_VERBOSE) MdcPrntMesg("ACR Reading <%s> ...",fi->ifname); fseek(fp,0L, SEEK_END); filesize = ftell(fp); fseek(fp,0L, SEEK_SET); tag = (MDC_ACR_TAG *)&acrtag; /* put some defaults we use */ fi->reconstructed = MDC_YES; fi->acquisition_type = MDC_ACQUISITION_TOMO; /* init dicom struct */ MdcDicomInitStuff(dicom); /* init MOD structs */ MdcGetStructMOD(fi); /* get endian of file */ fread((Uint8 *)tag, 1, MDC_ACR_TAG_SIZE, fi->ifp); if (tag->group == 0x0008) MDC_FILE_ENDIAN = MDC_HOST_ENDIAN; else { MDC_FILE_ENDIAN = !MDC_HOST_ENDIAN; } MdcSwapTag(tag); if (tag->group != 0x0008) return("ACR Bad initial group"); fseek(fp,0,SEEK_SET); while ( (ftell(fp) + MDC_ACR_TAG_SIZE) <= filesize ) { #if MDC_INCLUDE_DICM /* in case of MOSAIC, follow DICOM path */ if (MdcCheckMosaic(fi,dicom) == MDC_YES) { char *filename; MdcMergePath(fi->ipath,fi->idir,fi->ifname); MdcAddCompressionExt(fi->compression,fi->ipath); filename = malloc(strlen(fi->ipath)+1); if (filename != NULL) { strncpy(filename,fi->ipath,strlen(fi->ipath)+1); MdcCleanUpFI(fi); if (MdcOpenFile(fi,filename) == MDC_OK) err = MdcReadDICM(fi); MdcFree(filename); return(err); } return("ACR Handling as mosaic failed"); } #endif if (IMAGE) { if (MDC_PROGRESS) MdcProgress(MDC_PROGRESS_SET,0.0,NULL); if (!MdcGetStructID(fi,fi->number+1)) return("ACR Bad malloc IMG_DATA struct"); id = &fi->image[fi->number-1]; IMAGE = MDC_NO; } if (fread((Uint8 *)tag,1,MDC_ACR_TAG_SIZE,fp) != MDC_ACR_TAG_SIZE) return("ACR Bad read of tag"); MdcSwapTag(tag); if ((tag->group == 0x7fe0) && (tag->element == 0x0010)) { if (MDC_ECHO_ALIAS == MDC_YES) break; /* no interest in images */ frames = 1; for (t=3;tdim[t]; if (MDC_PROGRESS) MdcProgress(MDC_PROGRESS_SET,0.5,NULL); IMAGE = MDC_YES; tag->data=NULL; number+=1; if ((id->buf = MdcGetImgBuffer(tag->length)) == NULL) return("ACR Bad malloc image buffer"); if (fread(id->buf,1,tag->length,fp) != tag->length) { err=MdcHandleTruncated(fi,fi->number,MDC_NO); if (err != NULL) return(err); break; } if (id->bits == 12) { if (MdcUnpackBIT12(fi,fi->number-1) != MDC_YES) { return("ACR Unpacking 12 bits failed"); } } if (MDC_PROGRESS) MdcProgress(MDC_PROGRESS_SET,1.0,NULL); }else{ if (tag->length == 0xffffffff ) tag->length = 0; if (filesize - ftell(fp) >= tag->length) { /* not yet at end of file */ if ((tag->data=malloc(tag->length+1)) == NULL) return("ACR Bad malloc tag data"); tag->data[tag->length]='\0'; if (fread(tag->data,1,tag->length,fp) != tag->length) { MdcFree(tag->data); return("ACR Bad read tag data"); } }else{ /* position at the end of file */ fseek(fp,0,SEEK_END); } } err=MdcDoTag(NULL,tag,fi,fi->number-1); if (err!=NULL) return(err); MdcFree(tag->data); } if (MDC_ECHO_ALIAS == MDC_YES) { MdcEchoAliasName(fi); return(NULL); } if (fi->image[0].buf == NULL) return("ACR No valid images found"); if (number < fi->number) { /* file with some bogus tags after last image */ /* which incremented fi->number unexpected */ if (!MdcGetStructID(fi, number)) return("Couldn't realloc IMG_DATA structs"); } /* fill in FILEINFO */ fi->endian = MDC_FILE_ENDIAN; fi->bits = fi->image[0].bits; fi->dim[0] = 3; fi->dim[3] = fi->number; fi->pixdim[0] = 3.; fi->pixdim[1] = fi->image[0].pixel_xsize; fi->pixdim[2] = fi->image[0].pixel_ysize; fi->pixdim[3] = fi->image[0].slice_width; /* check Acr/Nema stuff per image */ for (i=0; inumber; i++) { id = &fi->image[i]; if (MDC_TRUE_GAP == MDC_YES) id->slice_spacing += id->slice_width; if (id->image_orient_pat[0] == 0.0 && id->image_orient_pat[1] == 0.0 && id->image_orient_pat[4] == 0.0 && id->image_orient_pat[5] == 0.0 ) { /* no patient coordinate system defines in Acr/Nema, try pat_orient */ fi->pat_slice_orient = MdcTryPatSliceOrient(fi->pat_orient); if (fi->pat_slice_orient != MDC_UNKNOWN) { MdcFillImgPos(fi,i,i%fi->dim[3],0.0); MdcFillImgOrient(fi,i); } } } MdcCloseFile(fi->ifp); if(fi->truncated) return("ACR Truncated image file"); return NULL; } /* just an experiment, but don't like to lose it */ /*void MdcHandleNUMARIS2(Uint8 *data) { Uint8 *pdata=data; char *ps; Int16 *i16; Int32 *i32; Int16 patient_info; MdcPrntScrn("\n"); MdcPrintLine('*',MDC_FULL_LENGTH); MdcPrntScrn("\n"); pdata = data; MdcPrntScrn("Entry Table:\n"); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Number of entries: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Entry length - words per entry: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Block length in byte: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("First free block in image file: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Number of first block of installation: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Length of installation in blocks: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Number of first block of measurement: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Length of measurement in blocks: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Number of first block of image text: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Length of image text in blocks: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Number of first i/r/a/p info: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Length of i/r/a/p info in blocks: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Number of first block of correction: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Length of correction blocks: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Number of first block NUMARIS1 #1: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Length of NUMARIS1 #1 in blocks: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Number of first block NUMARIS1 #2: %hd\n",*i16); i16=(Int16 *)pdata; pdata+=2; MdcPrntScrn("Length of NUMARIS1 #2 in blocks: %hd\n",*i16); MdcPrntScrn("\netc, etc, etc ...\n"); pdata = data; pdata+=44; i16=(Int16 *)pdata; patient_info=*i16 - 5; MdcPrntScrn("Patient_info block number: %hd\n",patient_info); pdata = data+(patient_info*512); ps = (char *)pdata; MdcPrntScrn("Patient name = %.26s\n",ps); pdata = data+(patient_info*512)+28; ps = (char *)pdata; MdcPrntScrn("Patient ID = %.12s\n",ps); MdcPrntScrn("\n"); MdcPrintLine('*',MDC_FULL_LENGTH); MdcPrntScrn("\n"); } */ void MdcPrintTag( FILEINFO *fi, MDC_ACR_TAG *tag, char *fmt, ...) { va_list args; if (MDC_INFO) { if (MDC_DEBUG) { MdcPrintLine('-',MDC_HALF_LENGTH); MdcPrntScrn("[next offset: %lu]\n",ftell(fi->ifp)); } MdcPrintLine('-',MDC_HALF_LENGTH); MdcPrntScrn("Group (2): 0x%.4x\n",tag->group); MdcPrntScrn("Element (2): 0x%.4x\n",tag->element); MdcPrntScrn("Length (4): %d\n",tag->length); } va_start(args, fmt); vsprintf(mdcbufr,fmt,args); if (MDC_INFO) { if ( tag->length == 0 ) MdcPrntScrn("%.30s \n",mdcbufr); else if ( tag->length > MDC_MAX_CHARS ) MdcPrntScrn("%.30s \n",mdcbufr); else MdcPrntScrn("%s",mdcbufr); } va_end(args); if (strstr(mdcbufr,"Unknown ") != NULL) { MDC_HACK_SUCCESS = MDC_NO; }else{ MDC_HACK_SUCCESS = MDC_YES; } } /* get nr (one based) element of a multiple value element with strings */ int MdcGetStrVM(char *dest,char *src, Uint32 nr) { int ret; ret = MdcGetSubStr(dest,src,MDC_2KB_OFFSET,'\\',(signed)nr); return(ret); } void MdcDicomInitStuff(MDC_DICOM_STUFF_T *dicom) { int i; dicom->type = BIT16_S; dicom->modality = M_NM; dicom->INVERT = MDC_NO; dicom->si_slope = 1.; dicom->si_intercept = 0.; dicom->acqnr = 0; dicom->dynnr = 0; dicom->motion = 0; for (i=0; iVectDO[i] = MDC_PASS0; dicom->VectNR[i] = 1; } dicom->timeslottime = 0.; dicom->frametime = 0.; dicom->framestart = 0.; dicom->frameduration = 0.; dicom->nrframes = 0.; dicom->window_low = 0.; dicom->window_high = 0.; dicom->scan_arc = 0.; dicom->intervals_acquired = 0.; dicom->intervals_rejected = 0.; dicom->heart_rate = 0; if (MDC_DICOM_MOSAIC_FORCED == MDC_YES) { dicom->MOSAIC = MDC_YES; dicom->mosaic_interlaced = mdc_mosaic_interlaced; }else{ dicom->MOSAIC = MDC_NO; dicom->mosaic_interlaced = MDC_NO; } dicom->mosaic_width = mdc_mosaic_width; dicom->mosaic_height= mdc_mosaic_height; dicom->mosaic_number= mdc_mosaic_number; } void MdcDicomCheckVect(MDC_DICOM_STUFF_T *dicom, MDC_ACR_TAG *tag, int VECTOR) { Uint16 *pu16, hval=1, vect; Uint32 vm, c; if (dicom->VectDO[VECTOR] == MDC_PASS1) { vm = tag->length / 2; pu16 = (Uint16 *)tag->data; for (c=0; c hval) hval = vect; } if (vm > 0 ) { dicom->VectNR[VECTOR] = hval; dicom->VectDO[VECTOR] = MDC_PASS2; } } } Uint32 MdcDicomNrOfVect(MDC_DICOM_STUFF_T *dicom, Uint16 nr, int VECTOR) { Uint32 rval=(Uint32)nr; if (dicom->VectDO[VECTOR] == MDC_PASS2) rval=(Uint32)dicom->VectNR[VECTOR]; return(rval); } int MdcDicomDoAcqData(FILEINFO *fi, MDC_DICOM_STUFF_T *dicom) { if ((dicom->acqnr > 0) && (dicom->acqnr <= fi->acqnr) && (fi->acqdata != NULL)) { return(MDC_YES); } return(MDC_NO); } int MdcDicomSOPClass(char *sopclass) { int mod = M_NM; if (strcmp(sopclass,"1.2.840.10008.5.1.4.1.1.2") == 0) mod = M_CT; else if (strcmp(sopclass,"1.2.840.10008.5.1.4.1.1.4") == 0) mod = M_MR; else if (strcmp(sopclass,"1.2.840.10008.5.1.4.1.1.20") == 0) mod = M_NM; else if (strcmp(sopclass,"1.2.840.10008.5.1.4.1.1.128") == 0) mod = M_PT; return (mod); } int MdcGetHHMMSS(char *time, Int16 *hour, Int16 *minute, Int16 *second) { char *pitem=time; while (!MdcIsDigit(pitem[0])) { if (strlen(pitem) > 1) pitem++; else break; } if (strlen(pitem) >= 2) sscanf(pitem,"%02hd",hour); if (strlen(pitem) > 2) pitem+=2; while (!MdcIsDigit(pitem[0])) { if (strlen(pitem) > 1) pitem++; else break; } if (strlen(pitem) >= 2) sscanf(pitem,"%02hd",minute); if (strlen(pitem) > 2) pitem+=2; while (!MdcIsDigit(pitem[0])) { if (strlen(pitem) > 1) pitem++; else break; } if (strlen(pitem) >= 2) sscanf(pitem,"%02hd",second); return(MDC_YES); } /* Note: index for IMG_DATA structs is 0-based */ char *MdcDoTag(MDC_SEQ_TAG *seq, MDC_ACR_TAG *tag, FILEINFO *fi, Uint32 index) { IMG_DATA *id; DYNAMIC_DATA *dd; MDC_DICOM_STUFF_T *dicom=&mdc_dicom_stuff; static Int16 bits_allocated = 0, bits_stored = 0; char databuffer[MDC_MAX_CHARS+1], *pc=NULL, *ps=NULL, *pitem=NULL; Int16 i16=0; Int32 i32=0; Uint16 ui16=0; Uint32 ui32=0; double flt64=0.; Uint16 group, element, *pu16; Uint32 i=index, bytes, c , vm, tmp; Uint8 FILL_STATIC_DATA = MDC_NO; Uint8 FILL_DYNAMIC_DATA = MDC_NO; float flt; memset(databuffer,'\0',MDC_MAX_CHARS+1); /*always a nul-terminated string*/ if (tag->data != NULL) { if (tag->length >= MDC_MAX_CHARS) { bytes=MDC_MAX_CHARS; }else{ bytes=tag->length; } if (bytes > 0) memcpy(databuffer,tag->data,bytes); } ps = databuffer; memcpy((char *)&i16,databuffer,sizeof(Int16)); MdcSWAP(i16); memcpy((char *)&i32,databuffer,sizeof(Int32)); MdcSWAP(i32); memcpy((char *)&ui16,databuffer,sizeof(Uint16)); MdcSWAP(ui16); memcpy((char *)&ui32,databuffer,sizeof(Uint32)); MdcSWAP(ui32); memcpy((char *)&flt64,databuffer,sizeof(FLT64)); MdcSWAP(flt64); id = &fi->image[i]; /* need of filling static data struct? */ if (id->sdata != NULL) FILL_STATIC_DATA = MDC_YES; /* need of filling dynamic data struct? */ if (fi->dyndata != NULL) FILL_DYNAMIC_DATA = MDC_YES; /* handle ordinary tags */ switch (tag->group) { /* group 0x0002 */ case 0x0002: switch (tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Meta Element - Group 0002\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %d\n",i32); break; case 0x0002: MdcPrintTag(fi,tag,"Media Storage SOPClassUID : %s\n",ps); dicom->modality = MdcDicomSOPClass(ps); break; case 0x0003: MdcPrintTag(fi,tag,"Media Storage SOPInstanceUID : %s\n",ps); break; case 0x0010: MdcPrintTag(fi,tag,"TransferSyntaxUID : %s\n",ps); break; case 0x0012: MdcPrintTag(fi,tag,"ImplementationClassUID : %s\n",ps); break; case 0x0013: MdcPrintTag(fi,tag,"Implementation Version Name : %s\n",ps); break; } break; /* group 0x0008 */ case 0x0008: switch (tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Identifying Information - Group 0008\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0001: MdcPrintTag(fi,tag,"Total Number of Bytes : %u\n",ui32); break; case 0x0005: MdcPrintTag(fi,tag,"Specific Character Set : %s\n",ps); break; case 0x0008: MdcPrintTag(fi,tag,"Image Type : %s\n",ps); if (MdcGetStrVM(mdcbufr,ps,3) == MDC_YES) { MdcKillSpaces(mdcbufr); if (strcasecmp(mdcbufr,"RECON GATED TOMO") == 0) { fi->acquisition_type = MDC_ACQUISITION_GSPECT; fi->reconstructed = MDC_YES; }else if (strcasecmp(mdcbufr,"RECON TOMO") == 0) { fi->acquisition_type = MDC_ACQUISITION_TOMO; fi->reconstructed = MDC_YES; }else if (strcasecmp(mdcbufr,"GATED TOMO") == 0) { fi->acquisition_type = MDC_ACQUISITION_GSPECT; fi->reconstructed = MDC_NO; }else if (strcasecmp(mdcbufr,"TOMO") == 0) { fi->acquisition_type = MDC_ACQUISITION_TOMO; fi->reconstructed = MDC_NO; }else if (strcasecmp(mdcbufr,"WHOLE BODY") == 0) { fi->acquisition_type = MDC_ACQUISITION_STATIC; fi->reconstructed = MDC_YES; fi->planar = MDC_YES; }else if (strcasecmp(mdcbufr,"GATED") == 0) { fi->acquisition_type = MDC_ACQUISITION_GATED; fi->reconstructed = MDC_YES; fi->planar = MDC_YES; }else if (strcasecmp(mdcbufr,"DYNAMIC") == 0) { fi->acquisition_type = MDC_ACQUISITION_DYNAMIC; fi->reconstructed = MDC_YES; fi->planar = MDC_YES; }else if (strcasecmp(mdcbufr,"STATIC") == 0) { fi->acquisition_type = MDC_ACQUISITION_STATIC; fi->reconstructed = MDC_YES; fi->planar = MDC_YES; }else{ fi->acquisition_type = MDC_ACQUISITION_TOMO; fi->reconstructed = MDC_YES; } } if (fi->acquisition_type == MDC_ACQUISITION_GATED || fi->acquisition_type == MDC_ACQUISITION_GSPECT ) { /* MARK: limited to one yet */ if (!MdcGetStructGD(fi,1)) { return("ACR Couldn't malloc GATED_DATA structs"); } } if (fi->acquisition_type == MDC_ACQUISITION_STATIC) { if (!MdcGetStructSD(fi,fi->number)) { return("ACR Couldn't malloc STATIC_DATA structs"); } } if (fi->reconstructed == MDC_NO) { dicom->acqnr = 1; if (!MdcGetStructAD(fi,dicom->acqnr)) { dicom->acqnr = 0; return("ACR Couldn't malloc ACQ_DATA struct"); } } break; case 0x0010: MdcPrintTag(fi,tag,"Recognition Code : %s\n",ps); break; case 0x0012: MdcPrintTag(fi,tag,"Instance Creation Date : %s\n",ps); break; case 0x0013: MdcPrintTag(fi,tag,"Instance Creation Time : %s\n",ps); break; case 0x0014: MdcPrintTag(fi,tag,"Instance Creator UID : %s\n",ps); break; case 0x0016: MdcPrintTag(fi,tag,"SOP Class UID : %s\n",ps); dicom->modality = MdcDicomSOPClass(ps); break; case 0x0018: MdcPrintTag(fi,tag,"SOP Instance UID : %s\n",ps); break; case 0x0020: MdcPrintTag(fi,tag,"Study Date : %s\n",ps); if (fi->mod != NULL) { MdcStringCopy(fi->mod->gn_info.study_date,ps,MDC_MAXSTR); } pitem = ps; while (!MdcIsDigit(pitem[0])) { if (strlen(pitem) > 1) pitem++; else break; } if (strlen(pitem) >= 4) sscanf(pitem,"%04hd",&fi->study_date_year); if (strlen(pitem) > 4) pitem+=4; while (!MdcIsDigit(pitem[0])) { if (strlen(pitem) > 1) pitem++; else break; } if (strlen(pitem) >= 2) sscanf(pitem,"%02hd",&fi->study_date_month); if (strlen(pitem) > 2) pitem+=2; while (!MdcIsDigit(pitem[0])) { if (strlen(pitem) > 1) pitem++; else break; } if (strlen(pitem) >= 2) sscanf(pitem,"%02hd",&fi->study_date_day); break; case 0x0021: MdcPrintTag(fi,tag,"Series Date : %s\n",ps); if (fi->mod != NULL) { MdcStringCopy(fi->mod->gn_info.series_date,ps,MDC_MAXSTR); } break; case 0x0022: MdcPrintTag(fi,tag,"Acquisition Date : %s\n",ps); if (fi->mod != NULL) { MdcStringCopy(fi->mod->gn_info.acquisition_date,ps,MDC_MAXSTR); } break; case 0x0023: MdcPrintTag(fi,tag,"Image Date : %s\n",ps); if (fi->mod != NULL) { MdcStringCopy(fi->mod->gn_info.image_date,ps,MDC_MAXSTR); } break; case 0x0030: MdcPrintTag(fi,tag,"Study Time : %s\n",ps); if (fi->mod != NULL) { MdcStringCopy(fi->mod->gn_info.study_time,ps,MDC_MAXSTR); } MdcGetHHMMSS(ps,&fi->study_time_hour ,&fi->study_time_minute ,&fi->study_time_second); break; case 0x0031: MdcPrintTag(fi,tag,"Series Time : %s\n",ps); if (fi->mod != NULL) { MdcStringCopy(fi->mod->gn_info.series_time,ps,MDC_MAXSTR); } break; case 0x0032: MdcPrintTag(fi,tag,"Acquisition Time : %s\n",ps); if (fi->mod != NULL) { MdcStringCopy(fi->mod->gn_info.acquisition_time,ps,MDC_MAXSTR); } if (FILL_STATIC_DATA == MDC_YES) { MdcGetHHMMSS(ps,&id->sdata->start_time_hour ,&id->sdata->start_time_minute ,&id->sdata->start_time_second); } break; case 0x0033: MdcPrintTag(fi,tag,"Image Time : %s\n",ps); if (fi->mod != NULL) { MdcStringCopy(fi->mod->gn_info.image_time,ps,MDC_MAXSTR); } break; case 0x0040: MdcPrintTag(fi,tag,"Data Set Type : 0x%.4x",ui16); if (MDC_INFO) switch (ui16) { case 0x0000: MdcPrntScrn(" (= image)\n"); break; case 0x0001: MdcPrntScrn(" (= compressed image)\n"); break; case 0x0002: MdcPrntScrn(" (= graphics)\n"); break; case 0x0003: MdcPrntScrn(" (= text)\n"); break; case 0x0010: MdcPrntScrn(" (= folder/raw)\n"); break; case 0x0100: MdcPrntScrn(" (= other)\n"); break; case 0x0101: MdcPrntScrn(" (= null)\n"); break; case 0x0102: MdcPrntScrn(" (= identifier)\n"); break; case 0x8000: MdcPrntScrn(" (= private image)\n"); break; case 0x8002: MdcPrntScrn(" (= private graphic)\n"); break; case 0x8003: MdcPrntScrn(" (= private text)\n"); break; default : MdcPrntScrn(" (= unknown)\n"); break; } break; case 0x0041: MdcPrintTag(fi,tag,"Data Set Subtype : %s\n",ps); break; case 0x0050: MdcPrintTag(fi,tag,"Accession Number : %s\n",ps); break; case 0x0060: MdcPrintTag(fi,tag,"Image Modality : %s\n",ps); fi->modality = MdcGetIntModality(ps); break; case 0x0070: MdcPrintTag(fi,tag,"Manufacturer : %s\n",ps); MdcStringCopy(fi->manufacturer,ps,tag->length); break; case 0x0080: MdcPrintTag(fi,tag,"Institution ID : %s\n",ps); MdcStringCopy(fi->institution,ps,tag->length); break; case 0x0090: MdcPrintTag(fi,tag,"Referring Physician : %s\n",ps); break; case 0x0100: MdcPrintTag(fi,tag,"Code Value : %s\n",ps); break; case 0x0102: MdcPrintTag(fi,tag,"Coding Scheme Designator : %s\n",ps); break; case 0x0104: MdcPrintTag(fi,tag,"Code Meaning : %s\n",ps); if (seq != NULL) { switch (seq->group) { case 0x0054: switch (seq->element) { case 0x0300: /* radionuclide (isotope) */ MdcStringCopy(fi->isotope_code,ps,strlen(ps)); break; case 0x0304: /* radiopharma */ MdcStringCopy(fi->radiopharma,ps,strlen(ps)); break; case 0x0220: /* static label */ if (FILL_STATIC_DATA == MDC_YES) MdcStringCopy(id->sdata->label,ps,strlen(ps)); break; } break; } } break; case 0x1000: MdcPrintTag(fi,tag,"Network ID : %s\n",ps); break; case 0x1010: MdcPrintTag(fi,tag,"Station ID : %s\n",ps); break; case 0x1030: MdcPrintTag(fi,tag,"Study Description : %s\n",ps); MdcKillSpaces(ps); MdcStringCopy(fi->study_descr,ps,tag->length); break; case 0x103E: MdcPrintTag(fi,tag,"Series Description : %s\n",ps); if (tag->length > 0) { MdcKillSpaces(ps); MdcStringCopy(fi->series_descr,ps,tag->length); } break; case 0x1040: MdcPrintTag(fi,tag,"Institutional Department : %s\n",ps); break; case 0x1050: MdcPrintTag(fi,tag,"Attending Physician : %s\n",ps); break; case 0x1060: MdcPrintTag(fi,tag,"Radiologist : %s\n",ps); break; case 0x1070: MdcPrintTag(fi,tag,"Operator : %s\n",ps); if (tag->length > 0) { MdcKillSpaces(ps); MdcStringCopy(fi->operator_name,ps,tag->length); } break; case 0x1080: MdcPrintTag(fi,tag,"Admitting Diagnosis : %s\n",ps); break; case 0x1090: MdcPrintTag(fi,tag,"Manufacturer Model : %s\n",ps); if (tag->length >= 16) { /* check for mosaic */ if (strncasecmp(ps,"MAGNETOM VISION",15) == 0) dicom->MOSAIC = MDC_YES; } break; case 0x1150: MdcPrintTag(fi,tag,"SOP Class UID : %s\n",ps); break; case 0x1155: MdcPrintTag(fi,tag,"SOP Instance UID : %s\n",ps); break; case 0x2111: MdcPrintTag(fi,tag,"Derivation Description : %s\n",ps); break; case 0x4000: MdcPrintTag(fi,tag,"Comments : %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x0009 */ case 0x0009: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Shadow Identifying Information - Group 0009\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0010: MdcPrintTag(fi,tag,"Shadow Owner Code : %s\n",ps); break; case 0x0011: MdcPrintTag(fi,tag,"Shadow Owner Code : %s\n",ps); break; case 0x0080: MdcPrintTag(fi,tag,"Owner ID : %s\n",ps); break; /* MARK BEGIN: GE DISCOVERY */ case 0x1001: MdcPrintTag(fi,tag,"Implentation Name : %s\n",ps); break; case 0x1002: MdcPrintTag(fi,tag,"Suite ID : %s\n",ps); break; case 0x1004: MdcPrintTag(fi,tag,"Product ID : %s\n",ps); break; case 0x1005: MdcPrintTag(fi,tag,"Patient DateTime : %s\n",ps); break; case 0x1006: MdcPrintTag(fi,tag,"Type : %s\n",ps); break; case 0x100a: MdcPrintTag(fi,tag,"Scan ID : %s\n",ps); break; case 0x100d: MdcPrintTag(fi,tag,"Scan DateTime : %s\n",ps); break; case 0x100e: MdcPrintTag(fi,tag,"Scan Ready : %s\n",ps); break; case 0x1013: MdcPrintTag(fi,tag,"For Identifier : %s\n",ps); break; case 0x1014: MdcPrintTag(fi,tag,"Landmark Name : %s\n",ps); break; case 0x1015: /* GE */ MdcPrintTag(fi,tag,"Landmark Abbreviation : %s\n",ps); /* SIEMENS */ MdcPrintTag(fi,tag,"Unique SPI Identifier : %s\n",ps); break; case 0x1016: MdcPrintTag(fi,tag,"Patient Position : %s\n",ps); break; case 0x1017: MdcPrintTag(fi,tag,"Scan Perspective : %s\n",ps); break; case 0x1018: MdcPrintTag(fi,tag,"Scan Type : %s\n",ps); break; case 0x1019: MdcPrintTag(fi,tag,"Scan Mode : %s\n",ps); break; case 0x101a: MdcPrintTag(fi,tag,"Start Condition : %s\n",ps); break; case 0x101b: MdcPrintTag(fi,tag,"Start Condition Data : %s\n",ps); break; case 0x101c: MdcPrintTag(fi,tag,"Sel Stop Condition : %s\n",ps); break; case 0x101d: MdcPrintTag(fi,tag,"Sel Stop Condition Data : %s\n",ps); break; case 0x101e: MdcPrintTag(fi,tag,"Collect Deadtime : %s\n",ps); break; case 0x101f: MdcPrintTag(fi,tag,"Collect Singles : %s\n",ps); break; case 0x1020: MdcPrintTag(fi,tag,"Collect Countrate : %s\n",ps); break; case 0x1021: MdcPrintTag(fi,tag,"Countrate Period : %s\n",ps); break; case 0x1022: MdcPrintTag(fi,tag,"Delayed Events : %s\n",ps); break; case 0x1023: MdcPrintTag(fi,tag,"Delayed Bias : %s\n",ps); break; case 0x1024: MdcPrintTag(fi,tag,"Word Size : %s\n",ps); break; case 0x1025: MdcPrintTag(fi,tag,"Axial Acceptance : %s\n",ps); break; case 0x1026: MdcPrintTag(fi,tag,"Axial Angle 3D : %s\n",ps); break; case 0x1027: /* 0x1027 tag was ambiguously defined in the GE Conformance Statement, */ /* once as "Image actual date" and once as "Theta Compression". */ MdcPrintTag(fi,tag,"Theta Compression : %s\n",ps); break; case 0x1028: MdcPrintTag(fi,tag,"Axial Compression : %s\n",ps); break; case 0x1029: MdcPrintTag(fi,tag,"Gantry Tilt Angle : %s\n",ps); break; case 0x102a: MdcPrintTag(fi,tag,"Collimation : %s\n",ps); break; case 0x102b: MdcPrintTag(fi,tag,"Scan FOV : %s\n",ps); break; case 0x102c: MdcPrintTag(fi,tag,"Axial FOV : %s\n",ps); break; case 0x102d: MdcPrintTag(fi,tag,"Event Separation : %s\n",ps); break; case 0x102e: MdcPrintTag(fi,tag,"Mask Width : %s\n",ps); break; case 0x102f: MdcPrintTag(fi,tag,"Binning Mode : %s\n",ps); break; case 0x1034: MdcPrintTag(fi,tag,"Triggers Acquired : %s\n",ps); break; case 0x1035: MdcPrintTag(fi,tag,"Triggers Rejected : %s\n",ps); break; case 0x1036: MdcPrintTag(fi,tag,"Tracer Name : %s\n",ps); break; case 0x1037: MdcPrintTag(fi,tag,"Batch Description : %s\n",ps); break; case 0x1038: MdcPrintTag(fi,tag,"Tracer Activity : %s\n",ps); break; case 0x1039: MdcPrintTag(fi,tag,"Measure DateTime : %s\n",ps); break; case 0x103a: MdcPrintTag(fi,tag,"Pre Injection Volume : %s\n",ps); break; case 0x103b: MdcPrintTag(fi,tag,"Admin DateTime : %s\n",ps); break; case 0x103c: MdcPrintTag(fi,tag,"Post Injection Activity : %s\n",ps); break; case 0x103d: MdcPrintTag(fi,tag,"Post Injection DateTime : %s\n",ps); break; case 0x103e: MdcPrintTag(fi,tag,"Radionuclide Name : %s\n",ps); break; case 0x103f: MdcPrintTag(fi,tag,"Half Life : %s\n",ps); break; case 0x1040: MdcPrintTag(fi,tag,"Positron Fraction : %s\n",ps); break; case 0x104d: MdcPrintTag(fi,tag,"Emission Present : %s\n",ps); break; case 0x104e: MdcPrintTag(fi,tag,"Lower Axial Acc : %s\n",ps); break; case 0x104f: MdcPrintTag(fi,tag,"Upper Axial Acc : %s\n",ps); break; case 0x1050: MdcPrintTag(fi,tag,"Lower Coincidence Limit : %s\n",ps); break; case 0x1051: MdcPrintTag(fi,tag,"Upper Coincidence Limit : %s\n",ps); break; case 0x1052: MdcPrintTag(fi,tag,"Coincidence Delay Offset : %s\n",ps); break; case 0x1053: MdcPrintTag(fi,tag,"Coincidence Output Mode : %s\n",ps); break; case 0x1054: MdcPrintTag(fi,tag,"Upper Energy Limit : %s\n",ps); break; case 0x1055: MdcPrintTag(fi,tag,"Lower Energy Limit : %s\n",ps); break; case 0x1056: MdcPrintTag(fi,tag,"Normal Cal ID : %s\n",ps); break; case 0x1057: MdcPrintTag(fi,tag,"Normal 2D Cal ID : %s\n",ps); break; case 0x1058: MdcPrintTag(fi,tag,"Blank Cal ID : %s\n",ps); break; case 0x1059: MdcPrintTag(fi,tag,"Well Counter Cal ID : %s\n",ps); break; case 0x105a: MdcPrintTag(fi,tag,"Derived : %s\n",ps); break; case 0x105c: MdcPrintTag(fi,tag,"Frame ID : %s\n",ps); break; case 0x105d: MdcPrintTag(fi,tag,"Scan ID : %s\n",ps); break; case 0x105e: MdcPrintTag(fi,tag,"Exam ID : %s\n",ps); break; case 0x105f: MdcPrintTag(fi,tag,"Patient ID : %s\n",ps); break; case 0x1062: MdcPrintTag(fi,tag,"Where is Frame : %s\n",ps); break; case 0x1063: MdcPrintTag(fi,tag,"Frame Size : %s\n",ps); break; case 0x1064: MdcPrintTag(fi,tag,"File Exists : %s\n",ps); break; case 0x1066: MdcPrintTag(fi,tag,"Table Height : %s\n",ps); break; case 0x1067: MdcPrintTag(fi,tag,"Table Z Position : %s\n",ps); break; case 0x1068: MdcPrintTag(fi,tag,"Landmark DateTime : %s\n",ps); break; case 0x1069: MdcPrintTag(fi,tag,"Slice Count : %s\n",ps); break; case 0x106a: MdcPrintTag(fi,tag,"Start Location : %s\n",ps); break; case 0x106b: MdcPrintTag(fi,tag,"Acquisition Delay : %s\n",ps); break; case 0x106c: MdcPrintTag(fi,tag,"Acquisition Start : %s\n",ps); break; case 0x106d: MdcPrintTag(fi,tag,"Acquisition Duration : %s\n",ps); break; case 0x1070: MdcPrintTag(fi,tag,"Actual Stop Condition : %s\n",ps); break; case 0x1071: MdcPrintTag(fi,tag,"Total Prompts : %s\n",ps); break; case 0x1072: MdcPrintTag(fi,tag,"Total Delays : %s\n",ps); break; case 0x1073: MdcPrintTag(fi,tag,"Frame Valid : %s\n",ps); break; case 0x1074: MdcPrintTag(fi,tag,"Validity Info : %s\n",ps); break; case 0x107c: MdcPrintTag(fi,tag,"Is Source : %s\n",ps); break; case 0x107d: MdcPrintTag(fi,tag,"Is Contents : %s\n",ps); break; case 0x107e: MdcPrintTag(fi,tag,"Is Type : %s\n",ps); break; case 0x107f: MdcPrintTag(fi,tag,"Is Reference : %s\n",ps); break; case 0x1080: MdcPrintTag(fi,tag,"Multi Patient : %s\n",ps); break; case 0x1081: MdcPrintTag(fi,tag,"Number of Normals : %s\n",ps); break; case 0x108b: MdcPrintTag(fi,tag,"Recon Method : %s\n",ps); break; case 0x108c: MdcPrintTag(fi,tag,"Attenuation : %s\n",ps); break; case 0x108d: MdcPrintTag(fi,tag,"Attenuation Coefficient : %s\n",ps); break; case 0x108e: MdcPrintTag(fi,tag,"BP Filter : %s\n",ps); break; case 0x108f: MdcPrintTag(fi,tag,"BP Filter Cutoff : %s\n",ps); break; case 0x1090: MdcPrintTag(fi,tag,"BP Filter Order : %s\n",ps); break; case 0x1091: MdcPrintTag(fi,tag,"BP Center L : %s\n",ps); break; case 0x1092: MdcPrintTag(fi,tag,"BP Center P : %s\n",ps); break; case 0x1093: MdcPrintTag(fi,tag,"Attenuation Smooth : %s\n",ps); break; case 0x1094: MdcPrintTag(fi,tag,"Attenuation Smooth Param : %s\n",ps); break; case 0x1095: MdcPrintTag(fi,tag,"Angle Smooth Param : %s\n",ps); break; case 0x1096: MdcPrintTag(fi,tag,"Well Counter Cal ID : %s\n",ps); break; case 0x1097: MdcPrintTag(fi,tag,"Trans Scan ID : %s\n",ps); break; case 0x1098: MdcPrintTag(fi,tag,"Norm Cal ID : %s\n",ps); break; case 0x109a: MdcPrintTag(fi,tag,"Cac Edge Threshold : %s\n",ps); break; case 0x109b: MdcPrintTag(fi,tag,"Cac Skull Offset : %s\n",ps); break; case 0x109d: MdcPrintTag(fi,tag,"Radial Filter 3D : %s\n",ps); break; case 0x109e: MdcPrintTag(fi,tag,"Radial Cutoff 3D : %s\n",ps); break; case 0x109f: MdcPrintTag(fi,tag,"Axial Filter 3D : %s\n",ps); break; case 0x10a0: MdcPrintTag(fi,tag,"Axial Cutoff 3D : %s\n",ps); break; case 0x10a1: MdcPrintTag(fi,tag,"Axial Start : %s\n",ps); break; case 0x10a2: MdcPrintTag(fi,tag,"Axial Spacing : %s\n",ps); break; case 0x10a3: MdcPrintTag(fi,tag,"Axial Angles Used : %s\n",ps); break; case 0x10a6: MdcPrintTag(fi,tag,"Slice Number : %s\n",ps); break; case 0x10a7: MdcPrintTag(fi,tag,"Total Counts : %s\n",ps); break; case 0x10ab: MdcPrintTag(fi,tag,"BP Center X : %s\n",ps); break; case 0x10ac: MdcPrintTag(fi,tag,"BP Center Y : %s\n",ps); break; case 0x10b2: MdcPrintTag(fi,tag,"IR Number Iterations : %s\n",ps); break; case 0x10b3: MdcPrintTag(fi,tag,"IR Number Subsets : %s\n",ps); break; case 0x10b4: MdcPrintTag(fi,tag,"IR Recon FOV : %s\n",ps); break; case 0x10b5: MdcPrintTag(fi,tag,"IR Corr Model : %s\n",ps); break; case 0x10b6: MdcPrintTag(fi,tag,"IR Loop Filter : %s\n",ps); break; case 0x10b7: MdcPrintTag(fi,tag,"IR Pre Filter Param : %s\n",ps); break; case 0x10b8: MdcPrintTag(fi,tag,"IR Loop Filter Param : %s\n",ps); break; case 0x10b9: MdcPrintTag(fi,tag,"Response Filter Param : %s\n",ps); break; case 0x10ba: MdcPrintTag(fi,tag,"Post Filter : %s\n",ps); break; case 0x10bb: MdcPrintTag(fi,tag,"Post Filter Param : %s\n",ps); break; case 0x10bc: MdcPrintTag(fi,tag,"IR Regularize : %s\n",ps); break; case 0x10bd: MdcPrintTag(fi,tag,"Regulative Param : %s\n",ps); break; case 0x10be: MdcPrintTag(fi,tag,"AC BP Filter : %s\n",ps); break; case 0x10bf: MdcPrintTag(fi,tag,"AC BP Filter Cut Off : %s\n",ps); break; case 0x10c0: MdcPrintTag(fi,tag,"AC BP Filter Order : %s\n",ps); break; case 0x10c1: MdcPrintTag(fi,tag,"AC Image Smooth : %s\n",ps); break; case 0x10c2: MdcPrintTag(fi,tag,"AC Image Smooth Param : %s\n",ps); break; case 0x10c3: MdcPrintTag(fi,tag,"Scatter Method : %s\n",ps); break; case 0x10c4: MdcPrintTag(fi,tag,"Scatter Number Iteration : %s\n",ps); break; case 0x10c5: MdcPrintTag(fi,tag,"Scatter Param : %s\n",ps); break; case 0x10c6: MdcPrintTag(fi,tag,"Seq QC Param : %s\n",ps); break; case 0x10c7: MdcPrintTag(fi,tag,"Overlap : %s\n",ps); break; case 0x10cb: MdcPrintTag(fi,tag,"VQC X Axis Trans : %s\n",ps); break; case 0x10cc: MdcPrintTag(fi,tag,"VQC X Axis Tilt : %s\n",ps); break; case 0x10cd: MdcPrintTag(fi,tag,"VQC Y Axis Trans : %s\n",ps); break; case 0x10ce: MdcPrintTag(fi,tag,"VQC Y Axis Swivel : %s\n",ps); break; case 0x10cf: MdcPrintTag(fi,tag,"VQC Z Axis Trans : %s\n",ps); break; case 0x10d0: MdcPrintTag(fi,tag,"VQC Z Axis Roll : %s\n",ps); break; case 0x10d5: MdcPrintTag(fi,tag,"Loop Filter Param : %s\n",ps); break; case 0x10d6: MdcPrintTag(fi,tag,"Image One Location : %s\n",ps); break; case 0x10d7: MdcPrintTag(fi,tag,"Image Index Location : %s\n",ps); break; case 0x10d8: MdcPrintTag(fi,tag,"Frame Number : %s\n",ps); break; case 0x10d9: MdcPrintTag(fi,tag,"List File Exists : %s\n",ps); break; case 0x10da: MdcPrintTag(fi,tag,"Where is List File : %s\n",ps); break; case 0x10db: MdcPrintTag(fi,tag,"IR Z Filter Flag : %s\n",ps); break; case 0x10dc: MdcPrintTag(fi,tag,"IR Z Filter Ratio : %s\n",ps); break; case 0x10df: MdcPrintTag(fi,tag,"Number of Slices : %s\n",ps); break; case 0x10e2: MdcPrintTag(fi,tag,"Rest Stress : %s\n",ps); break; case 0x10e5: MdcPrintTag(fi,tag,"Left Shift : %s\n",ps); break; case 0x10e6: MdcPrintTag(fi,tag,"Posterior Shift : %s\n",ps); break; case 0x10e7: MdcPrintTag(fi,tag,"Superior Shift : %s\n",ps); break; case 0x10e9: MdcPrintTag(fi,tag,"Acquisition Bin Dur Percent : %s\n",ps); break; case 0x1010: MdcPrintTag(fi,tag,"Hospital Name : %s\n",ps); /* MARK END: GE DISCOVERY */ /* MARK CONTINUE: SIEMENS */ MdcPrintTag(fi,tag,"SPI Version : %s\n",ps); break; case 0x1110: MdcPrintTag(fi,tag,"Modality Recognition Code : %s\n",ps); break; case 0x1130: MdcPrintTag(fi,tag,"Header Offset in Bytes : %hu\n",ui16); break; case 0x1131: MdcPrintTag(fi,tag,"Length of Header in Bytes : %hu\n",ui16); break; case 0x1140: MdcPrintTag(fi,tag,"Byte Offset to Pixel Field : %hu\n",ui16); break; case 0x1141: MdcPrintTag(fi,tag,"Length of Pixel Data in Bytes: %u\n",ui32); break; case 0x8000: MdcPrintTag(fi,tag,"Original File Name : %s\n",ps); break; case 0x8010: MdcPrintTag(fi,tag,"Original File Location : %s\n",ps); break; case 0x8018: MdcPrintTag(fi,tag,"Data Set Identifier (DSID) : %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x0010 */ case 0x0010: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Patient Information - Group 0010\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0010: MdcPrintTag(fi,tag,"Patient Name : %s\n",ps); MdcKillSpaces(ps); MdcStringCopy(fi->patient_name,ps,tag->length); /* remove caret signs */ pc = fi->patient_name; while (pc[0] != '\0') { if (pc[0] == '^') pc[0] = ' '; pc+=1; } MdcKillSpaces(fi->patient_name); break; case 0x0020: MdcPrintTag(fi,tag,"Patient ID : %s\n",ps); MdcKillSpaces(ps); MdcStringCopy(fi->patient_id,ps,tag->length); break; case 0x0030: MdcPrintTag(fi,tag,"Patient Birthday : %s\n",ps); MdcKillSpaces(ps); MdcStringCopy(fi->patient_dob,ps,tag->length); break; case 0x0040: MdcPrintTag(fi,tag,"Patient Sex : %s\n",ps); MdcKillSpaces(ps); MdcStringCopy(fi->patient_sex,ps,tag->length); break; case 0x1000: MdcPrintTag(fi,tag,"Other Patient IDs : %s\n",ps); break; case 0x1001: MdcPrintTag(fi,tag,"Other Patient Names : %s\n",ps); break; case 0x1005: MdcPrintTag(fi,tag,"Patient Maiden Name : %s\n",ps); break; case 0x1010: MdcPrintTag(fi,tag,"Patient Age : %s\n",ps); break; case 0x1020: MdcPrintTag(fi,tag,"Patient Size : %s\n",ps); fi->patient_height = (float)atof(ps); break; case 0x1030: MdcPrintTag(fi,tag,"Patient Weight : %s\n",ps); fi->patient_weight = (float)atof(ps); break; case 0x1040: MdcPrintTag(fi,tag,"Patient Address : %s\n",ps); break; case 0x1050: MdcPrintTag(fi,tag,"Insurance Plan ID : %s\n",ps); break; case 0x1060: MdcPrintTag(fi,tag,"Patient Mother's Maiden Name : %s\n",ps); break; case 0x21b0: MdcPrintTag(fi,tag,"Additional Patient History : %s\n",ps); break; case 0x4000: MdcPrintTag(fi,tag,"Comments : %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x0011 */ case 0x0011: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Shadow Patient Information - Group 0011\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0010: MdcPrintTag(fi,tag,"Shadow owner code : %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x0017 */ case 0x0017: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Calibration - Group 0017\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0010: MdcPrintTag(fi,tag,"Private Creator : %s\n",ps); break; case 0x1001: MdcPrintTag(fi,tag,"Correction Cal ID : %s\n",ps); break; case 0x1002: MdcPrintTag(fi,tag,"Compatible Version : %s\n",ps); break; case 0x1003: MdcPrintTag(fi,tag,"Software Version : %s\n",ps); break; case 0x1004: MdcPrintTag(fi,tag,"Cal DateTime : %s\n",ps); break; case 0x1005: MdcPrintTag(fi,tag,"Cal Description : %s\n",ps); break; case 0x1006: MdcPrintTag(fi,tag,"Cal Type : %s\n",ps); break; case 0x1007: MdcPrintTag(fi,tag,"Where is Correction : %s\n",ps); break; case 0x1008: MdcPrintTag(fi,tag,"Correction File Size : %s\n",ps); break; case 0x1009: MdcPrintTag(fi,tag,"Scan ID : %s\n",ps); break; case 0x100A: MdcPrintTag(fi,tag,"Scan DateTime : %s\n",ps); break; case 0x100B: MdcPrintTag(fi,tag,"Norm 2D Cal ID : %s\n",ps); break; case 0x100C: MdcPrintTag(fi,tag,"Hospital Identifier : %s\n",ps); break; case 0x100D: MdcPrintTag(fi,tag,"Archived : %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x0018 */ case 0x0018: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Acquisition Information - Group 0018\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0010: MdcPrintTag(fi,tag,"Contrast/Bolus Agent : %s\n",ps); break; case 0x0015: MdcPrintTag(fi,tag,"Body Part Examined : %s\n",ps); if (tag->length > 0) { MdcKillSpaces(ps); MdcStringCopy(fi->organ_code,ps,tag->length); } break; case 0x0020: MdcPrintTag(fi,tag,"Scanning Sequence : %s\n",ps); break; case 0x0022: MdcPrintTag(fi,tag,"Scan Mode : %s\n",ps); break; case 0x0030: MdcPrintTag(fi,tag,"Radionuclide : %s\n",ps); MdcStringCopy(fi->radiopharma,ps,tag->length); break; case 0x0031: MdcPrintTag(fi,tag,"Radiopharmaceutical : %s\n",ps); MdcStringCopy(fi->radiopharma,ps,tag->length); break; case 0x0040: MdcPrintTag(fi,tag,"Cine Rate : %s\n",ps); break; case 0x0050: MdcPrintTag(fi,tag,"Slice Thickness : %s [mm]\n",ps); fi->image[i].slice_width=(float)atof(ps); break; case 0x0060: MdcPrintTag(fi,tag,"KVP : %s\n",ps); break; case 0x0070: MdcPrintTag(fi,tag,"Counts Accumulated : %s\n",ps); break; case 0x0071: MdcPrintTag(fi,tag,"Acquisition Termination Condition : %s\n",ps); break; case 0x0073: MdcPrintTag(fi,tag,"Acquisition Start Condition : %s\n",ps); break; case 0x0074: MdcPrintTag(fi,tag,"Acquisition Start Condition Data : %s\n",ps); break; case 0x0075: MdcPrintTag(fi,tag,"Acquisition Termination Condition Data : %s\n" ,ps); break; case 0x0080: MdcPrintTag(fi,tag,"Repetition Time : %s [ms]\n",ps); if (fi->mod != NULL) { fi->mod->mr_info.repetition_time = atof(ps); } break; case 0x0081: MdcPrintTag(fi,tag,"Echo Time : %s [ms]\n",ps); if (fi->mod != NULL) { fi->mod->mr_info.echo_time = atof(ps); } break; case 0x0082: MdcPrintTag(fi,tag,"Inversion Time : %s [ms]\n",ps); if (fi->mod != NULL) { fi->mod->mr_info.inversion_time = atof(ps); } break; case 0x0083: MdcPrintTag(fi,tag,"Number of Averages : %s\n",ps); if (fi->mod != NULL) { fi->mod->mr_info.num_averages = atof(ps); } break; case 0x0084: MdcPrintTag(fi,tag,"Imaging Frequency : %s [MHz]\n",ps); if (fi->mod != NULL) { fi->mod->mr_info.imaging_freq = atof(ps); } break; case 0x0085: MdcPrintTag(fi,tag,"Imaged Nucleus : %s\n",ps); break; case 0x0086: MdcPrintTag(fi,tag,"Echo Number : %s\n",ps); break; case 0x0088: MdcPrintTag(fi,tag,"Slice Spacing : %s [mm]\n",ps); sscanf(ps,"%f",&id->slice_spacing); /* MARK: in DICOM, sign = direction, pfff! */ if (id->slice_spacing < 0.) id->slice_spacing = - id->slice_spacing; break; case 0x0090: MdcPrintTag(fi,tag,"Data Collection Diameter : %s\n",ps); break; case 0x0095: MdcPrintTag(fi,tag,"Pixel Bandwidth : %s\n",ps); if (fi->mod != NULL) { fi->mod->mr_info.pixel_bandwidth = atof(ps); } break; case 0x1000: MdcPrintTag(fi,tag,"Device Serial Number : %s\n",ps); break; case 0x1010: MdcPrintTag(fi,tag,"Film Scanner ID : %s\n",ps); break; case 0x1020: MdcPrintTag(fi,tag,"Software Version : %s\n",ps); break; case 0x1030: MdcPrintTag(fi,tag,"Protocol : %s\n",ps); break; case 0x1040: MdcPrintTag(fi,tag,"Contrast/Bolus Route : %s\n",ps); break; case 0x1041: MdcPrintTag(fi,tag,"Contrast/Bolus Volume : %s\n",ps); break; case 0x1042: MdcPrintTag(fi,tag,"Contrast/Bolus Start Time : %s\n",ps); break; case 0x1043: MdcPrintTag(fi,tag,"Contrast/Bolus Stop Time : %s\n",ps); break; case 0x1044: MdcPrintTag(fi,tag,"Contrast/Bolus Total Dose : %s\n",ps); break; case 0x1050: MdcPrintTag(fi,tag,"Spatial Resolution : %s\n",ps); break; case 0x1060: MdcPrintTag(fi,tag,"Trigger Time : %s\n",ps); break; case 0x1063: MdcPrintTag(fi,tag,"Frame Time : %s\n",ps); dicom->frametime = (float)atof(ps); break; case 0x1070: MdcPrintTag(fi,tag,"Radionuclide Route : %s\n",ps); break; case 0x1071: MdcPrintTag(fi,tag,"Radionuclide Volume : %s\n",ps); break; case 0x1072: MdcPrintTag(fi,tag,"Radionuclide Start Time : %s\n",ps); MdcGetHHMMSS(ps,&fi->dose_time_hour ,&fi->dose_time_minute ,&fi->dose_time_second); break; case 0x1073: MdcPrintTag(fi,tag,"Radionuclide Stop Time : %s\n",ps); break; case 0x1074: MdcPrintTag(fi,tag,"Radionuclide Total Dose : %s\n",ps); fi->injected_dose = (float)atof(ps); break; case 0x1075: MdcPrintTag(fi,tag,"Radionuclide Half Life : %s\n",ps); fi->isotope_halflife = (float)atof(ps); break; case 0x1076: MdcPrintTag(fi,tag,"Radionuclide Positron Fraction : %s\n",ps); break; case 0x1081: MdcPrintTag(fi,tag,"Low R-R Value : %s\n",ps); dicom->window_low = (float)atof(ps); break; case 0x1082: MdcPrintTag(fi,tag,"High R-R Value : %s\n",ps); dicom->window_high = (float)atof(ps); break; case 0x1083: MdcPrintTag(fi,tag,"Intervals Acquired : %s\n",ps); dicom->intervals_acquired += (float)atof(ps); break; case 0x1084: MdcPrintTag(fi,tag,"Intervals Rejected : %s\n",ps); dicom->intervals_rejected += (float)atof(ps); break; case 0x1088: MdcPrintTag(fi,tag,"Heart Rate : %s\n",ps); dicom->heart_rate = (Int16)atoi(ps); break; case 0x1100: MdcPrintTag(fi,tag,"Reconstruction Diameter : %s\n",ps); break; case 0x1110: MdcPrintTag(fi,tag,"Distance Source to Detector : %s\n",ps); break; case 0x1111: MdcPrintTag(fi,tag,"Distance Source to Patient : %s\n",ps); break; case 0x1120: MdcPrintTag(fi,tag,"Gantry Tilt : %s [degrees]\n" ,ps); fi->gantry_tilt = (float)atof(ps); break; case 0x1130: MdcPrintTag(fi,tag,"Table Height : %s\n",ps); break; case 0x1140: MdcPrintTag(fi,tag,"Rotation Direction : %s\n",ps); if (MdcDicomDoAcqData(fi,dicom) == MDC_YES) { tmp = dicom->acqnr - 1; if (strcasecmp(ps,"CW") == 0) { fi->acqdata[tmp].rotation_direction = MDC_ROTATION_CW; }else if (strcasecmp(ps,"CC") == 0) { fi->acqdata[tmp].rotation_direction = MDC_ROTATION_CC; } } break; case 0x1142: MdcPrintTag(fi,tag,"Radial Position : %s\n",ps); if (MdcDicomDoAcqData(fi,dicom) == MDC_YES) { tmp = dicom->acqnr - 1; sscanf(ps,"%g",&fi->acqdata[tmp].radial_position); } break; case 0x1143: MdcPrintTag(fi,tag,"Scan Arc : %s\n",ps); if (MdcDicomDoAcqData(fi,dicom) == MDC_YES) { tmp = dicom->acqnr - 1; sscanf(ps,"%g",&fi->acqdata[tmp].scan_arc); } sscanf(ps,"%g",&dicom->scan_arc); break; case 0x1144: MdcPrintTag(fi,tag,"Angular Step : %s\n",ps); if (MdcDicomDoAcqData(fi,dicom) == MDC_YES) { tmp = dicom->acqnr - 1; sscanf(ps,"%f",&fi->acqdata[tmp].angle_step); } break; case 0x1145: MdcPrintTag(fi,tag,"Center of Rotation Offset : %s\n",ps); if (MdcDicomDoAcqData(fi,dicom) == MDC_YES) { tmp = dicom->acqnr - 1; fi->acqdata[tmp].rotation_offset = atof(ps); } break; case 0x1147: MdcPrintTag(fi,tag,"Field of View Share : %s\n",ps); break; case 0x1149: MdcPrintTag(fi,tag,"Field of View Dimensions : %s\n",ps); break; case 0x1150: MdcPrintTag(fi,tag,"Exposure Time : %s\n",ps); break; case 0x1151: MdcPrintTag(fi,tag,"Exposure Rate : %s\n",ps); break; case 0x1152: MdcPrintTag(fi,tag,"Exposure : %s\n",ps); break; case 0x1160: MdcPrintTag(fi,tag,"Filter Type : %s\n",ps); MdcKillSpaces(ps); MdcStringCopy(fi->filter_type,ps,tag->length); break; case 0x1170: MdcPrintTag(fi,tag,"Generator Power : %s\n",ps); break; case 0x1180: MdcPrintTag(fi,tag,"Collimator/Grid : %s\n",ps); break; case 0x1181: MdcPrintTag(fi,tag,"Collimator Type : %s\n",ps); break; case 0x1190: MdcPrintTag(fi,tag,"Focal Spot : %s\n",ps); break; case 0x1200: MdcPrintTag(fi,tag,"Date of Last Calibration : %s\n",ps); break; case 0x1201: MdcPrintTag(fi,tag,"Time of Last Calibration : %s\n",ps); break; case 0x1210: MdcPrintTag(fi,tag,"Convolution Kernel : %s\n",ps); break; case 0x1240: MdcPrintTag(fi,tag,"Upper/Lower Pixel Values : %s\n",ps); break; case 0x1242: MdcPrintTag(fi,tag,"Actual Frame Duration : %s\n",ps); flt = (float)atof(ps); if (FILL_STATIC_DATA == MDC_YES) { id->sdata->image_duration = flt; } if (FILL_DYNAMIC_DATA == MDC_YES) { dd = &fi->dyndata[dicom->dynnr]; if (dd->time_frame_duration > 0.) { /* safely increment phase counter */ if (dicom->dynnr < (fi->dynnr - 1)) dicom->dynnr += 1; } dd = &fi->dyndata[dicom->dynnr]; dd->time_frame_duration = flt; } dicom->frameduration = flt; break; case 0x1243: MdcPrintTag(fi,tag,"Count Rate : %s\n",ps); break; case 0x1250: MdcPrintTag(fi,tag,"Receiving Coil : %s\n",ps); break; case 0x1251: MdcPrintTag(fi,tag,"Transmitting Coil : %s\n",ps); break; case 0x1260: MdcPrintTag(fi,tag,"Screen Type : %s\n",ps); break; case 0x1261: MdcPrintTag(fi,tag,"Phosphor Type : %s\n",ps); break; case 0x1314: MdcPrintTag(fi,tag,"Flip Angle : %s\n",ps); if (fi->mod != NULL) { fi->mod->mr_info.flip_angle = atof(ps); } break; case 0x1318: MdcPrintTag(fi,tag,"dBdt : %s\n",ps); if (fi->mod != NULL) { fi->mod->mr_info.dbdt = atof(ps); } break; case 0x4000: MdcPrintTag(fi,tag,"Comments : %s\n",ps); break; case 0x5000: MdcPrintTag(fi,tag,"Output Power : %s\n",ps); break; case 0x5010: MdcPrintTag(fi,tag,"Transducer Data : %s\n",ps); break; case 0x5020: MdcPrintTag(fi,tag,"Preprocessing Function : %s\n",ps); break; case 0x5021: MdcPrintTag(fi,tag,"Postprocessing Function : %s\n",ps); break; case 0x5030: MdcPrintTag(fi,tag,"Dynamic Range : %s\n",ps); break; case 0x5040: MdcPrintTag(fi,tag,"Total Gain : %s\n",ps); break; case 0x5050: MdcPrintTag(fi,tag,"Depth of Scan Field : %s\n",ps); break; case 0x5100: MdcPrintTag(fi,tag,"Patient Position : %s\n",ps); MdcStringCopy(fi->pat_pos,ps,tag->length); MdcUpStr(fi->pat_pos); break; case 0x6030: MdcPrintTag(fi,tag,"Transducer Frequency : %u\n",ui32); if (fi->mod != NULL) { fi->mod->mr_info.transducer_freq = ui32; } break; case 0x6031: MdcPrintTag(fi,tag,"Transducer Type : %s\n",ps); if (fi->mod != NULL) { MdcStringCopy(fi->mod->mr_info.transducer_type,ps,MDC_MAXSTR); } break; case 0x6032: MdcPrintTag(fi,tag,"Pulse Repetition Frequency : %u\n",ui32); if (fi->mod != NULL) { fi->mod->mr_info.pulse_repetition_freq = ui32; } break; case 0x9005: MdcPrintTag(fi,tag,"Pulse Sequence Name : %s\n",ps); if (fi->mod != NULL) { MdcStringCopy(fi->mod->mr_info.pulse_seq_name,ps,MDC_MAXSTR); } break; case 0x9017: MdcPrintTag(fi,tag,"Steady State Pulse Sequence : %s\n",ps); if (fi->mod != NULL) { MdcStringCopy(fi->mod->mr_info.steady_state_pulse_seq,ps,MDC_MAXSTR); } break; case 0x9104: MdcPrintTag(fi,tag,"Slab Thickness : %f\n",flt64); if (fi->mod != NULL) { fi->mod->mr_info.slab_thickness = flt64; } case 0x9305: MdcPrintTag(fi,tag,"Revolution Time : %s\n",ps); break; case 0x9306: MdcPrintTag(fi,tag,"Single Collimation Width : %s\n",ps); break; case 0x9307: MdcPrintTag(fi,tag,"Total Collimation Width : %s\n",ps); break; case 0x9309: MdcPrintTag(fi,tag,"Table Speed : %s\n",ps); break; case 0x9310: MdcPrintTag(fi,tag,"Table Feed per Rotation : %s\n",ps); break; case 0x9311: MdcPrintTag(fi,tag,"CT Pitch Factor : %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x0019 */ case 0x0019: switch (tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Shadow Relationship Information - Group 0019\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0010: MdcPrintTag(fi,tag,"Private Creator ID : %s\n",ps); break; case 0x1002: MdcPrintTag(fi,tag,"NumberOfCellsIInDetector : %s\n",ps); break; case 0x1003: MdcPrintTag(fi,tag,"CellNumberAtTheta : %s\n",ps); break; case 0x1004: MdcPrintTag(fi,tag,"Cell spacing : %s\n",ps); break; case 0x100F: MdcPrintTag(fi,tag,"HorizFrameOfRef : %s\n",ps); break; case 0x1011: MdcPrintTag(fi,tag,"SeriesContrast : %s\n",ps); break; case 0x1018: MdcPrintTag(fi,tag,"FirstScanRas : %s\n",ps); break; case 0x101A: MdcPrintTag(fi,tag,"LastScanRas : %s\n",ps); break; case 0x1023: MdcPrintTag(fi,tag,"TableSpeed : %s\n",ps); break; case 0x1024: MdcPrintTag(fi,tag,"MidScanTime : %s\n",ps); break; case 0x1025: MdcPrintTag(fi,tag,"MidScanFlag : %s\n",ps); break; case 0x1026: MdcPrintTag(fi,tag,"DegreesOfAzimuth : %s\n",ps); break; case 0x1027: MdcPrintTag(fi,tag,"GantryPeriod : %s\n",ps); break; case 0x102C: MdcPrintTag(fi,tag,"NumberOfTriggers : %s\n",ps); break; case 0x102E: MdcPrintTag(fi,tag,"AngleOfFirstView : %s\n",ps); break; case 0x102F: MdcPrintTag(fi,tag,"TriggerFrequency : %s\n",ps); break; case 0x1039: MdcPrintTag(fi,tag,"ScanFOVType : %s\n",ps); break; case 0x1042: MdcPrintTag(fi,tag,"SegmentNumber : %s\n",ps); break; case 0x1043: MdcPrintTag(fi,tag,"TotalSegmentsRequested : %s\n",ps); break; case 0x1047: MdcPrintTag(fi,tag,"ViewCompressionFactor : %s\n",ps); break; case 0x1052: MdcPrintTag(fi,tag,"ReconPostProcFlag : %s\n",ps); break; case 0x106A: MdcPrintTag(fi,tag,"DependentOnNumViewsProcessed : %s\n",ps); break; case 0x1220: MdcPrintTag(fi,tag,"Mosaic Image Width : %s\n",ps); sscanf(ps,"%u",&dicom->mosaic_width); break; case 0x1221: MdcPrintTag(fi,tag,"Mosaic Image Height : %s\n",ps); sscanf(ps,"%u",&dicom->mosaic_height); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x0020 */ case 0x0020: switch (tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Relationship Information - Group 0020\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x000d: MdcPrintTag(fi,tag,"Study Instance UID : %s\n",ps); break; case 0x000e: MdcPrintTag(fi,tag,"Series Instance UID : %s\n",ps); break; case 0x0010: MdcPrintTag(fi,tag,"Study ID : %s\n",ps); MdcStringCopy(fi->study_id,ps,tag->length); break; case 0x0011: MdcPrintTag(fi,tag,"Series Number : %s\n",ps); fi->nr_series = atoi(ps); break; case 0x0012: MdcPrintTag(fi,tag,"Acquisition Number : %s\n",ps); fi->nr_acquisition = atoi(ps); break; case 0x0013: MdcPrintTag(fi,tag,"Image Number : %s\n",ps); fi->nr_instance = atoi(ps); break; case 0x0020: MdcPrintTag(fi,tag,"Patient Orientation : %s\n",ps); MdcStringCopy(fi->pat_orient,ps,tag->length); break; case 0x0030: MdcPrintTag(fi,tag,"Image Position : %s [mm]\n",ps); sscanf(ps,"%f\\%f\\%f",&id->image_pos_dev[0], &id->image_pos_dev[1], &id->image_pos_dev[2]); break; case 0x0032: MdcPrintTag(fi,tag,"Image Position Patient : %s [mm]\n",ps); sscanf(ps,"%f\\%f\\%f",&id->image_pos_pat[0], &id->image_pos_pat[1], &id->image_pos_pat[2]); break; case 0x0035: MdcPrintTag(fi,tag,"Image Orientation : %s [mm]\n",ps); sscanf(ps,"%f\\%f\\%f\\%f\\%f\\%f",&id->image_orient_dev[0], &id->image_orient_dev[1], &id->image_orient_dev[2], &id->image_orient_dev[3], &id->image_orient_dev[4], &id->image_orient_dev[5]); break; case 0x0037: MdcPrintTag(fi,tag,"Image Orientation Patient : %s [mm]\n",ps); sscanf(ps,"%f\\%f\\%f\\%f\\%f\\%f",&id->image_orient_pat[0], &id->image_orient_pat[1], &id->image_orient_pat[2], &id->image_orient_pat[3], &id->image_orient_pat[4], &id->image_orient_pat[5]); fi->pat_slice_orient = MdcGetPatSliceOrient(fi,i); break; case 0x0050: MdcPrintTag(fi,tag,"Location : %s\n",ps); break; case 0x0052: MdcPrintTag(fi,tag,"Frame of Reference UID : %s\n",ps); break; case 0x0060: MdcPrintTag(fi,tag,"Laterality : %s\n",ps); break; case 0x0070: MdcPrintTag(fi,tag,"Image Geometrie Type : %s\n",ps); break; case 0x0080: MdcPrintTag(fi,tag,"Masking Image : %s\n",ps); break; case 0x1000: MdcPrintTag(fi,tag,"Series in Study : %s\n",ps); break; case 0x1001: MdcPrintTag(fi,tag,"Acquisitions in Series : %s\n",ps); break; case 0x1002: MdcPrintTag(fi,tag,"Images in Acquisition : %s\n",ps); break; case 0x1020: MdcPrintTag(fi,tag,"Reference : %s\n",ps); break; case 0x1040: MdcPrintTag(fi,tag,"Position Reference Indicator : %s\n",ps); break; case 0x1041: MdcPrintTag(fi,tag,"Slice Location : %s\n",ps); break; case 0x1070: MdcPrintTag(fi,tag,"Other Study Numbers : %s\n",ps); break; case 0x3401: MdcPrintTag(fi,tag,"Modifying Device ID : %s\n",ps); break; case 0x3402: MdcPrintTag(fi,tag,"Modified Image ID : %s\n",ps); break; case 0x3403: MdcPrintTag(fi,tag,"Modified Image Data : %s\n",ps); break; case 0x3404: MdcPrintTag(fi,tag,"Modifying Device Manufacturer: %s\n",ps); break; case 0x3405: MdcPrintTag(fi,tag,"Modified Image Time : %s\n",ps); break; case 0x3406: MdcPrintTag(fi,tag,"Modified Image Description : %s\n",ps); break; case 0x4000: MdcPrintTag(fi,tag,"Comments : %s\n",ps); break; case 0x5000: MdcPrintTag(fi,tag,"Original Image Identification: 0x%.4x\n",ui16); break; case 0x5002: MdcPrintTag(fi,tag,"Original Image Nomenclature : %s\n",ps); break; default: if ( (tag->element >= 0x3100) && (tag->element <= 0x31ff) ) { MdcPrintTag(fi,tag,"Source Image ID : %s\n",ps); }else{ MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } } break; /* group 0x0021 */ case 0x0021: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Shadow Relationship Information - Group 0021\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0010: MdcPrintTag(fi,tag,"Shadow Owner Code : %s\n",ps); break; case 0x0080: MdcPrintTag(fi,tag,"Owner ID : %s\n",ps); break; case 0x1003: MdcPrintTag(fi,tag,"SeriesFromWhichPrescribed : %s\n",ps); break; case 0x1010: MdcPrintTag(fi,tag,"Zoom Factor : %s\n",ps); break; case 0x1011: MdcPrintTag(fi,tag,"Target Coordinate : %s\n",ps); break; case 0x1020: MdcPrintTag(fi,tag,"Used ROI (mask) : %hu\n",ui16); break; case 0x1035: MdcPrintTag(fi,tag,"SeriesPrescribedFrom : %s\n",ps); break; case 0x1036: MdcPrintTag(fi,tag,"ImagePrescribedFrom : %s\n",ps); break; case 0x1091: MdcPrintTag(fi,tag,"BiopsyPosition : %s\n",ps); break; case 0x1092: MdcPrintTag(fi,tag,"BiopsyTLocation : %s\n",ps); break; case 0x1093: MdcPrintTag(fi,tag,"BiopsyRefLocation : %s\n",ps); break; case 0x1340: MdcPrintTag(fi,tag,"Number of Mosaic Images : %s\n",ps); sscanf(ps,"%u",&dicom->mosaic_number); break; case 0x134f: MdcPrintTag(fi,tag,"Mosaic Interlace Mode : %s\n",ps); if (strncmp(ps,"INTERL",6) == 0) dicom->mosaic_interlaced = MDC_YES; break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x0023 */ case 0x0023: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn(" - Group 0023\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0010: MdcPrintTag(fi,tag,"Private Creator : %s\n",ps); break; case 0x1023: MdcPrintTag(fi,tag,"Private Creator : %s\n",ps); break; case 0x1070: MdcPrintTag(fi,tag,"StartTimeSecsInFirstAxial : %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x0027 */ case 0x0027: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn(" CT Image - Group 0027\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0010: MdcPrintTag(fi,tag,"Private Creator : %s\n",ps); break; case 0x1010: MdcPrintTag(fi,tag,"ScoutType : %s\n",ps); break; case 0x101C: MdcPrintTag(fi,tag,"VmaMamp : %s\n",ps); break; case 0x101E: MdcPrintTag(fi,tag,"VmaMod : %s\n",ps); break; case 0x101F: MdcPrintTag(fi,tag,"VmaClip : %s\n",ps); break; case 0x1020: MdcPrintTag(fi,tag,"SmartScanOnOffFlag : %s\n",ps); break; case 0x1035: MdcPrintTag(fi,tag,"PlaneType : %s\n",ps); break; case 0x1042: MdcPrintTag(fi,tag,"CenterRCoordOfPlaneImage : %s\n",ps); break; case 0x1043: MdcPrintTag(fi,tag,"CenterACoordOfPlaneImage : %s\n",ps); break; case 0x1044: MdcPrintTag(fi,tag,"CenterSCoordOfPlaneImage : %s\n",ps); break; case 0x1045: MdcPrintTag(fi,tag,"NormalRCoord : %s\n",ps); break; case 0x1046: MdcPrintTag(fi,tag,"NormalACoord : %s\n",ps); break; case 0x1047: MdcPrintTag(fi,tag,"NormalSCoord : %s\n",ps); break; case 0x1050: MdcPrintTag(fi,tag,"TableStartLocation : %s\n",ps); break; case 0x1051: MdcPrintTag(fi,tag,"TableEndLocation : %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x0028 */ case 0x0028: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Image Presentation - Group 0028\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; MdcPrintTag(fi,tag,"CT Pitch Factor : %s\n",ps); case 0x0002: MdcPrintTag(fi,tag,"Samples Per Pixel : %hu\n",ui16); break; case 0x0004: MdcPrintTag(fi,tag,"Photometric Interpretation : %s\n",ps); MdcKillSpaces(ps); if (strcasecmp(ps,"MONOCHROME1") == 0 ) dicom->INVERT = MDC_YES; break; case 0x0005: MdcPrintTag(fi,tag,"Image Dimensions : %hu\n",ui16); break; case 0x0008: MdcPrintTag(fi,tag,"Number of Frames : %s\n",ps); fi->dim[3] = (Uint32)atol(ps); break; case 0x0009: MdcPrintTag(fi,tag,"Frame Increment Pointer : "); vm = tag->length / 2; pu16 = (Uint16 *)tag->data; for (c=0; cVectDO[MDC_VECT_ENERGYWINDOW]= MDC_PASS1; break; case 0x0020: dicom->VectDO[MDC_VECT_DETECTOR] = MDC_PASS1; break; case 0x0030: dicom->VectDO[MDC_VECT_PHASE] = MDC_PASS1; break; case 0x0050: dicom->VectDO[MDC_VECT_ROTATION] = MDC_PASS1; break; case 0x0060: dicom->VectDO[MDC_VECT_RRINTERVAL] = MDC_PASS1; break; case 0x0070: dicom->VectDO[MDC_VECT_TIMESLOT] = MDC_PASS1; break; case 0x0080: dicom->VectDO[MDC_VECT_SLICE] = MDC_PASS1; break; case 0x0090: dicom->VectDO[MDC_VECT_ANGULARVIEW] = MDC_PASS1; break; case 0x0100: dicom->VectDO[MDC_VECT_TIMESLICE] = MDC_PASS1; break; } } if (MDC_INFO) MdcPrntScrn("(%.4x:%.4x) ",group,element); } if (MDC_INFO) MdcPrntScrn("\n"); break; case 0x0010: MdcPrintTag(fi,tag,"Rows : %hu\n",ui16); fi->image[i].height = (Uint32)ui16; if ((Uint32)ui16 > fi->mheight) fi->mheight = ui16; if ((Uint32)ui16 != fi->mheight) fi->diff_size = MDC_YES; break; case 0x0011: MdcPrintTag(fi,tag,"Columns : %hu\n",ui16); fi->image[i].width = (Uint32)ui16; if ((Uint32)ui16 > fi->mwidth) fi->mwidth = ui16; if ((Uint32)ui16 != fi->mwidth) fi->diff_size = MDC_YES; break; case 0x0030: MdcPrintTag(fi,tag,"Pixel Size : %s [mm]\n",ps); { pc=strchr(ps,'\\'); if (pc != NULL) { pc+=1; fi->pixdim[1] = (float)atof(pc); pc-=1; pc[0]='\0'; }else{ /* no second value available */ fi->pixdim[1] = (float)atof(ps); } fi->pixdim[2] = (float)atof(ps); fi->image[i].pixel_xsize = fi->pixdim[1]; fi->image[i].pixel_ysize = fi->pixdim[2]; } break; case 0x0031: MdcPrintTag(fi,tag,"Zoom Factor : %s\n",ps); fi->image[i].ct_zoom_fctr = (float)atof(ps); break; case 0x0040: MdcPrintTag(fi,tag,"Image Format : %s\n",ps); break; case 0x0050: MdcPrintTag(fi,tag,"Manipulated Image : %s\n",ps); break; case 0x0051: MdcPrintTag(fi,tag,"Corrected Image : %s\n",ps); if (strstr(ps,"DECY") != NULL) fi->decay_corrected = MDC_YES; if (strstr(ps,"UNIF") != NULL) fi->flood_corrected = MDC_YES; break; case 0x0060: MdcPrintTag(fi,tag,"Compression Code : %s\n",ps); break; case 0x0100: MdcPrintTag(fi,tag,"Bits Allocated : %hu\n",ui16); switch (ui16 % 8) { case 0 : /* bytes */ case 1 : /* 1bit */ case 4 : /* 12bit */ bits_allocated = fi->image[i].bits = (Int16)ui16; break; default : return("ACR Unsupported pixel type"); } break; case 0x0101: MdcPrintTag(fi,tag,"Bits per Pixel : %hu\n",ui16); bits_stored = (Int16)ui16; break; case 0x0102: MdcPrintTag(fi,tag,"High Bit : %hu\n",ui16); if ((Int16)ui16 != (bits_stored - 1)) return ("ACR Unsupported bits packing"); break; case 0x0103: MdcPrintTag(fi,tag,"Pixel Representation : %hu",ui16); dicom->sign=(Int16)ui16; if (MDC_INFO) switch(ui16) { case 0: MdcPrntScrn(" (= unsigned)\n"); break; case 1: MdcPrntScrn(" (= signed)\n"); break; } switch (bits_allocated) { case 8: if (ui16) fi->image[i].type = BIT8_S; else fi->image[i].type = BIT8_U; break; case 16: if (ui16) fi->image[i].type = BIT16_S; else fi->image[i].type = BIT16_U; break; case 32: if (ui16) fi->image[i].type = BIT32_S; else fi->image[i].type = BIT32_U; break; #ifdef HAVE_8BYTE_INT case 64: if (ui16) fi->image[i].type = BIT64_S; else fi->image[i].type = BIT64_U; break; #endif } break; case 0x0104: MdcPrintTag(fi,tag,"Pixel Minimum : %hu\n",ui16); break; case 0x0105: MdcPrintTag(fi,tag,"Pixel Maximum : %hu\n",ui16); break; case 0x0106: MdcPrintTag(fi,tag,"Smallest Image Pixel Value : %s\n",ps); break; case 0x0107: MdcPrintTag(fi,tag,"Largest Image Pixel Value : %s\n",ps); break; case 0x0120: MdcPrintTag(fi,tag,"Pixel Padding Value : %s\n",ps); break; case 0x0200: MdcPrintTag(fi,tag,"Image Location : 0x%.4x\n",ui16); break; case 0x1050: MdcPrintTag(fi,tag,"Window Center : %s\n",ps); fi->window_centre = (float)atof(ps); break; case 0x1051: MdcPrintTag(fi,tag,"Window Width : %s\n",ps); fi->window_width = (float)atof(ps); break; case 0x1052: MdcPrintTag(fi,tag,"Rescale Intercept : %s\n",ps); dicom->si_intercept = (float)atof(ps); break; case 0x1053: MdcPrintTag(fi,tag,"Rescale Slope : %s\n",ps); dicom->si_slope = (float)atof(ps); break; case 0x1054: MdcPrintTag(fi,tag,"Rescale Type : %s\n",ps); break; case 0x1080: MdcPrintTag(fi,tag,"Gray Scale : %s\n",ps); break; case 0x1100: MdcPrintTag(fi,tag,"Lookup Table Descriptor-Gray : 0x%.4x\n",ui16); break; case 0x1101: MdcPrintTag(fi,tag,"Lookup Table Descriptor-Red : 0x%.4x\n",ui16); break; case 0x1102: MdcPrintTag(fi,tag,"Lookup Table Descriptor-Green: 0x%.4x\n",ui16); break; case 0x1103: MdcPrintTag(fi,tag,"Loopup Table Descriptor-Blue : 0x%.4x\n",ui16); break; case 0x1200: MdcPrintTag(fi,tag,"Lookup Data - Gray : 0x%.4x\n",ui16); break; case 0x1201: MdcPrintTag(fi,tag,"Lookup Data - Red : 0x%.4x\n",ui16); break; case 0x1202: MdcPrintTag(fi,tag,"Lookup Data - Green : 0x%.4x\n",ui16); break; case 0x1203: MdcPrintTag(fi,tag,"Lookup Data - Blue : 0x%.4x\n",ui16); break; case 0x2110: MdcPrintTag(fi,tag,"Lossy Image Compression : %s\n",ps); break; case 0x4000: MdcPrintTag(fi,tag,"Comments : %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x0032 */ case 0x0032: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Request Procedure - Group 0032\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x1032: MdcPrintTag(fi,tag,"Requesting Physician : %s\n",ps); break; case 0x1033: MdcPrintTag(fi,tag,"Requesting Service : %s\n",ps); break; case 0x1060: MdcPrintTag(fi,tag,"Requested Procedure Description : %s\n",ps); break; case 0x1064: MdcPrintTag(fi,tag,"Requested Procedure Code Sequence : %s\n",ps); break; case 0x1070: MdcPrintTag(fi,tag,"Requested Contrast Agent : %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x003A */ case 0x003A: switch(tag->element) { case 0x001A: MdcPrintTag(fi,tag,"Sampling Frequency : %s\n",ps); if (fi->mod != NULL) { fi->mod->mr_info.sampling_freq = atof(ps); } break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x0040 */ case 0x0040: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Text - Group 0040\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0002: MdcPrintTag(fi,tag,"Scheduled Procedure Step Start Date : %s\n",ps); break; case 0x0003: MdcPrintTag(fi,tag,"Scheduled Procedure Step Start Time : %s\n",ps); break; case 0x0006: MdcPrintTag(fi,tag,"Performing Physician : %s\n",ps); break; case 0x0007: MdcPrintTag(fi,tag,"Scheduled Procedure Step Description : %s\n",ps); break; case 0x0009: MdcPrintTag(fi,tag,"Scheduled Procedure Step ID : %s\n",ps); break; case 0x0010: MdcPrintTag(fi,tag,"Arbitrary : %s\n",ps); break; case 0x0244: MdcPrintTag(fi,tag,"Performed Procedure Step Start Date : %s\n",ps); break; case 0x0245: MdcPrintTag(fi,tag,"Performed Procedure Step Start Time : %s\n",ps); break; case 0x0253: MdcPrintTag(fi,tag,"Performed Procedure Step ID : %s\n",ps); break; case 0x0254: MdcPrintTag(fi,tag,"Performed Procedure Step Description : %s\n",ps); break; case 0x1001: MdcPrintTag(fi,tag,"Requested Procedure ID : %s\n",ps); break; case 0x4000: MdcPrintTag(fi,tag,"Comments : %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x0041 */ case 0x0041: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Folder Information - Group 0041\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0007: MdcPrintTag(fi,tag,"Scheduled Procedure Step Description : %s\n",ps); break; case 0x0009: MdcPrintTag(fi,tag,"Scheduled Procedure ID : %s\n",ps); break; case 0x0080: MdcPrintTag(fi,tag,"Owner ID : %s\n",ps); break; case 0x8000: MdcPrintTag(fi,tag,"Comments : %s\n",ps); break; case 0x8010: MdcPrintTag(fi,tag,"Folder Type : 0x%.4x\n",ui16); if (MDC_INFO) switch (ui16) { case 0x0001: MdcPrntScrn(" (= data exchange)\n"); break; case 0x0002: MdcPrntScrn(" (= teaching case)\n"); break; case 0x0003: MdcPrntScrn(" (= hard copy)\n"); break; case 0x0004: MdcPrntScrn(" (= history)\n"); break; case 0x0005: MdcPrntScrn(" (= case)\n"); break; case 0x0006: MdcPrntScrn(" (= patient)\n"); break; case 0x0007: MdcPrntScrn(" (= research)\n"); break; default: MdcPrntScrn(" (= unknown)\n"); } break; case 0x8011: MdcPrintTag(fi,tag,"Parent Folder Data Set ID : %s\n",ps); break; case 0x8020: MdcPrintTag(fi,tag,"Folder Name : %s\n",ps); break; case 0x8030: MdcPrintTag(fi,tag,"Creation Date : %s\n",ps); break; case 0x8032: MdcPrintTag(fi,tag,"Creation Time : %s\n",ps); break; case 0x8034: MdcPrintTag(fi,tag,"Modified Date : %s\n",ps); break; case 0x8036: MdcPrintTag(fi,tag,"Modified Time : %s\n",ps); break; case 0x8040: MdcPrintTag(fi,tag,"Owner Name : %s\n",ps); break; case 0x8050: MdcPrintTag(fi,tag,"Folder Status : %s\n",ps); break; case 0x8060: MdcPrintTag(fi,tag,"Number of Images : %u\n",ui32); break; case 0x8062: MdcPrintTag(fi,tag,"Number of Other : %u\n",ui32); break; case 0x80a0: if (MDC_INFO) MdcPrntScrn("\nFolder Elements - External References\n"); MdcPrintTag(fi,tag,"Folder Element DSID : %s\n",ps); break; case 0x80a1: MdcPrintTag(fi,tag,"Folder Element Data Set Type : 0x%.4x\n",ui16); break; case 0x80a2: MdcPrintTag(fi,tag,"Folder Element File Location : %s\n",ps); break; case 0x80a3: MdcPrintTag(fi,tag,"Folder Element Length : %u\n",ui32); break; case 0x80b0: if (MDC_INFO) MdcPrntScrn("\nFolder Elements - Internal References\n"); MdcPrintTag(fi,tag,"Folder Element DSID : %s\n",ps); break; case 0x80b1: MdcPrintTag(fi,tag,"Folder Element Data Set Type : 0x%.4x\n",ui16); break; case 0x80b2: MdcPrintTag(fi,tag,"Offset to Data Set : %u\n",ui32); break; case 0x80b3: MdcPrintTag(fi,tag,"Offset to Image : %u\n",ui32); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x0043 */ case 0x0043: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn(" CT Params - Group 0043\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0010: MdcPrintTag(fi,tag,"Private Creator ID : %s\n",ps); break; case 0x1064: MdcPrintTag(fi,tag,"ReconFilter : %s\n",ps); break; case 0x1010: MdcPrintTag(fi,tag,"WindowValue : %s\n",ps); break; case 0x1012: MdcPrintTag(fi,tag,"X-RayChain : %s\n",ps); break; case 0x1016: MdcPrintTag(fi,tag,"NumberOfOverranges : %s\n",ps); break; case 0x101E: MdcPrintTag(fi,tag,"DeltaStartTime : %s\n",ps); break; case 0x101F: MdcPrintTag(fi,tag,"MaxOverrangesInAView : %s\n",ps); break; case 0x1021: MdcPrintTag(fi,tag,"CorrectedAfterGlowTerms : %s\n",ps); break; case 0x1025: MdcPrintTag(fi,tag,"ReferenceChannels : %s\n",ps); break; case 0x1026: MdcPrintTag(fi,tag,"NoViewsRefChansBlocked : %s\n",ps); break; case 0x1027: MdcPrintTag(fi,tag,"ScanPitchRatio : %s\n",ps); break; case 0x1028: MdcPrintTag(fi,tag,"UniqueImageIden : %s\n",ps); break; case 0x102B: MdcPrintTag(fi,tag,"PrivateScanOptions : %s\n",ps); break; case 0x1031: MdcPrintTag(fi,tag,"RACordOfTargetReconCenter : %s\n",ps); break; case 0x1040: MdcPrintTag(fi,tag,"TriggerOnPosition : %s\n",ps); break; case 0x1041: MdcPrintTag(fi,tag,"DegreeOfRotation : %s\n",ps); break; case 0x1042: MdcPrintTag(fi,tag,"DASTriggerSource : %s\n",ps); break; case 0x1043: MdcPrintTag(fi,tag,"DASFpaGain : %s\n",ps); break; case 0x1044: MdcPrintTag(fi,tag,"DASOutputSource : %s\n",ps); break; case 0x1045: MdcPrintTag(fi,tag,"DASAdInput : %s\n",ps); break; case 0x1046: MdcPrintTag(fi,tag,"DASCalMode : %s\n",ps); break; case 0x104D: MdcPrintTag(fi,tag,"StartScanToX-RayOnDelay : %s\n",ps); break; case 0x104E: MdcPrintTag(fi,tag,"DurationOfX-RayOn : %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x0045 */ case 0x0045: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn(" HELIOS Cardiac - Group 0045\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0010: MdcPrintTag(fi,tag,"Private Creator : %s\n",ps); break; case 0x1001: MdcPrintTag(fi,tag,"NumberOfMacroRowsInDetector : %s\n",ps); break; case 0x1002: MdcPrintTag(fi,tag,"MacroWidthAtISOCenter : %s\n",ps); break; case 0x1003: MdcPrintTag(fi,tag,"DASType : %s\n",ps); break; case 0x1004: MdcPrintTag(fi,tag,"DASGain : %s\n",ps); break; case 0x1005: MdcPrintTag(fi,tag,"DASTemprature : %s\n",ps); break; case 0x1006: MdcPrintTag(fi,tag,"TableDirection : %s\n",ps); break; case 0x1007: MdcPrintTag(fi,tag,"ZSmoothingFactor : %s\n",ps); break; case 0x1008: MdcPrintTag(fi,tag,"ViewWeightingMode : %s\n",ps); break; case 0x1009: MdcPrintTag(fi,tag,"SigmaRowNumber : %s\n",ps); break; case 0x100A: MdcPrintTag(fi,tag,"MinimumDASValue : %s\n",ps); break; case 0x100B: MdcPrintTag(fi,tag,"MaximumOffsetValue : %s\n",ps); break; case 0x100C: MdcPrintTag(fi,tag,"NumberOfViewsShifted : %s\n",ps); break; case 0x100D: MdcPrintTag(fi,tag,"ZTrackingFlag : %s\n",ps); break; case 0x100E: MdcPrintTag(fi,tag,"MeanZError : %s\n",ps); break; case 0x100F: MdcPrintTag(fi,tag,"ZTrackingError : %s\n",ps); break; case 0x1010: MdcPrintTag(fi,tag,"StartView2A : %s\n",ps); break; case 0x1011: MdcPrintTag(fi,tag,"NumberOfViews2A : %s\n",ps); break; case 0x1012: MdcPrintTag(fi,tag,"StartView1A : %s\n",ps); break; case 0x1013: MdcPrintTag(fi,tag,"SigmaMode : %s\n",ps); break; case 0x1014: MdcPrintTag(fi,tag,"NumberOfViews1A : %s\n",ps); break; case 0x1015: MdcPrintTag(fi,tag,"StartView2B : %s\n",ps); break; case 0x1016: MdcPrintTag(fi,tag,"NumberViews2B : %s\n",ps); break; case 0x1017: MdcPrintTag(fi,tag,"StartView1B : %s\n",ps); break; case 0x1018: MdcPrintTag(fi,tag,"NumberOfViews1B : %s\n",ps); break; case 0x1021: MdcPrintTag(fi,tag,"IterboneFlag : %s\n",ps); break; case 0x1022: MdcPrintTag(fi,tag,"PerisstalticFlag : %s\n",ps); break; case 0x1030: MdcPrintTag(fi,tag,"Cardiacreconalgorithm : %s\n",ps); break; case 0x1031: MdcPrintTag(fi,tag,"Avgheartrateforimage : %s\n",ps); break; case 0x1032: MdcPrintTag(fi,tag,"Temporalresolution : %s\n",ps); break; case 0x1033: MdcPrintTag(fi,tag,"Pctrpeakdelay : %s\n",ps); break; case 0x1036: MdcPrintTag(fi,tag,"Ekgfullmastartphase : %s\n",ps); break; case 0x1037: MdcPrintTag(fi,tag,"Ekgfullmaendphase : %s\n",ps); break; case 0x1038: MdcPrintTag(fi,tag,"Kgmodulationmaxma : %s\n",ps); break; case 0x1039: MdcPrintTag(fi,tag,"Ekgmodulationminma : %s\n",ps); break; case 0x103B: MdcPrintTag(fi,tag,"Noisereductionimagefilterdesc: %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x0049 */ case 0x0049: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn(" CT Cardiac - Group 0049\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x1001: MdcPrintTag(fi,tag,"CTCardiacSequence : %s\n",ps); break; case 0x1002: MdcPrintTag(fi,tag,"Heartrateatconfirm : %s\n",ps); break; case 0x1003: MdcPrintTag(fi,tag,"Avgheartratepriortoconfirm : %s\n",ps); break; case 0x1004: MdcPrintTag(fi,tag,"Minheartratepriortoconfirm : %s\n",ps); break; case 0x1005: MdcPrintTag(fi,tag,"Maxheartratepriortoconfirm : %s\n",ps); break; case 0x1006: MdcPrintTag(fi,tag,"Stddevheartratepriortoconfirm : %s\n",ps); break; case 0x1007: MdcPrintTag(fi,tag,"Numheartratesamplespriortoconfirm : %s\n",ps); break; case 0x1008: MdcPrintTag(fi,tag,"Autoheartratedetectpredict : %s\n",ps); break; case 0x1009: MdcPrintTag(fi,tag,"Systemoptimizedheartrate : %s\n",ps); break; case 0x100A: MdcPrintTag(fi,tag,"Ekgmonitortype : %s\n",ps); break; case 0x100B: MdcPrintTag(fi,tag,"Numreconsectors : %s\n",ps); break; case 0x100C: MdcPrintTag(fi,tag,"Rpeaktimestamps : %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* DICOM specific tags to interpret */ /* group 0x0054 */ case 0x0054: switch (tag->element) { case 0x0010: /* energy window vector */ MdcDicomCheckVect(dicom,tag,MDC_VECT_ENERGYWINDOW); break; case 0x0011: /* number of energy windows */ MdcPrintTag(fi,tag,"Number of Energy Windows : %hu\n",ui16); fi->dim[7] = MdcDicomNrOfVect(dicom,ui16,MDC_VECT_ENERGYWINDOW); break; case 0x0020: /* detector vector */ MdcDicomCheckVect(dicom,tag,MDC_VECT_DETECTOR); break; case 0x0021: /* number of detectors */ MdcPrintTag(fi,tag,"Number of Detectors : %hu\n",ui16); fi->dim[6] = MdcDicomNrOfVect(dicom,ui16,MDC_VECT_DETECTOR); break; case 0x0030: /* phase vectory */ MdcDicomCheckVect(dicom,tag,MDC_VECT_PHASE); break; case 0x0031: /* phases (dyn) */ MdcPrintTag(fi,tag,"Number of Phases : %hu\n",ui16); MdcGetStructDD(fi,MdcDicomNrOfVect(dicom,ui16,MDC_VECT_PHASE)); if (fi->planar != MDC_YES) { fi->dim[4] = MdcDicomNrOfVect(dicom,ui16,MDC_VECT_PHASE); } break; case 0x0033: /* number of frames in phase */ MdcPrintTag(fi,tag,"Number of Frames in Phase : %hu\n",ui16); if (FILL_DYNAMIC_DATA == MDC_YES) { fi->dyndata[dicom->dynnr].nr_of_slices = (Uint32)ui16; }else{ fi->dim[3] = (Uint32)ui16; } break; case 0x0036: MdcPrintTag(fi,tag,"Phase Delay : %s\n",ps); if (FILL_DYNAMIC_DATA == MDC_YES) { fi->dyndata[dicom->dynnr].time_frame_delay = (float)atof(ps); } break; case 0x0038: MdcPrintTag(fi,tag,"Pause Between Frames : %s\n",ps); if (FILL_DYNAMIC_DATA == MDC_YES) { fi->dyndata[dicom->dynnr].delay_slices = (float)atof(ps); } break; case 0x0050: /* rotation vector */ MdcDicomCheckVect(dicom,tag,MDC_VECT_ROTATION); break; case 0x0051: /* number of rotations */ if (fi->reconstructed == MDC_NO) { if (!MdcGetStructAD(fi,(Uint32)ui16)) fi->acqnr = 0; } break; case 0x0052: /* rotation information sequence */ dicom->acqnr += 1; break; case 0x0053: MdcPrintTag(fi,tag,"Number Frames in Rotation : %hu\n",ui16); dicom->nrframes = (float)ui16; break; case 0x0060: /* R-R interval vector */ MdcDicomCheckVect(dicom,tag,MDC_VECT_RRINTERVAL); break; case 0x0061: /* R-R intervals */ MdcPrintTag(fi,tag,"Number of R-R intervals : %hu\n",ui16); fi->dim[5] = MdcDicomNrOfVect(dicom,ui16,MDC_VECT_RRINTERVAL); break; case 0x0070: /* time slot vector */ MdcDicomCheckVect(dicom,tag,MDC_VECT_TIMESLOT); break; case 0x0071: /* number of time slots (gated only stuff) */ MdcPrintTag(fi,tag,"Number of Time Slots : %hu\n",ui16); if (fi->acquisition_type == MDC_ACQUISITION_GATED) { /* MARK: for gated, time slot is the last dimension !! */ fi->dim[3] = MdcDicomNrOfVect(dicom,ui16,MDC_VECT_TIMESLOT); }else{ fi->dim[4] = MdcDicomNrOfVect(dicom,ui16,MDC_VECT_TIMESLOT); } break; case 0x0073: /* timeslottime */ MdcPrintTag(fi,tag,"Time Slot Time : %s\n",ps); dicom->timeslottime = (float)atof(ps); break; case 0x0080: /* slice vector */ MdcDicomCheckVect(dicom,tag,MDC_VECT_SLICE); break; case 0x0081: /* number of slices */ MdcPrintTag(fi,tag,"Number of Slices : %hu\n",ui16); fi->dim[3] = MdcDicomNrOfVect(dicom,ui16,MDC_VECT_SLICE); break; case 0x0090: /* angular view vector */ MdcDicomCheckVect(dicom,tag,MDC_VECT_ANGULARVIEW); fi->dim[3] = dicom->VectNR[MDC_VECT_ANGULARVIEW]; /* no number of angular views ? 0x0091*/ break; case 0x0100: /* time slice vector */ MdcDicomCheckVect(dicom,tag,MDC_VECT_TIMESLICE); break; case 0x0101: MdcPrintTag(fi,tag,"Number of Time Slices : %hu\n",ui16); if (dicom->modality == M_PT) { fi->dim[4] = MdcDicomNrOfVect(dicom,ui16,MDC_VECT_TIMESLICE); }else{ fi->dim[3] = MdcDicomNrOfVect(dicom,ui16,MDC_VECT_TIMESLICE); } break; case 0x0200: MdcPrintTag(fi,tag,"Start Angle : %s\n",ps); if (MdcDicomDoAcqData(fi,dicom) == MDC_YES) { float angle; tmp = dicom->acqnr - 1; sscanf(ps,"%f",&angle); fi->acqdata[tmp].angle_start = MdcRotateAngle(angle, 180.); } break; case 0x0202: MdcPrintTag(fi,tag,"Type of Detector Motion : %s\n",ps); if (MdcDicomDoAcqData(fi,dicom) == MDC_YES) { if (strcasecmp(ps,"STEP AND SHOOT") == 0) { dicom->motion = MDC_MOTION_STEP; }else if (strcasecmp(ps,"CONTINUOUS") == 0) { dicom->motion = MDC_MOTION_CONT; }else if (strcasecmp(ps,"ACQ DURING STEP") == 0) { dicom->motion = MDC_MOTION_DRNG; } for (tmp=0; tmp < fi->acqnr; tmp ++) { fi->acqdata[tmp].detector_motion = dicom->motion; } } break; case 0x1000: MdcPrintTag(fi,tag,"Series Type : %s\n",ps); if (MdcGetStrVM(mdcbufr,ps,1) == MDC_YES) { MdcKillSpaces(mdcbufr); if (strcasecmp(mdcbufr,"STATIC") == 0) { fi->acquisition_type = MDC_ACQUISITION_TOMO; }else if (strcasecmp(mdcbufr,"WHOLE_BODY") == 0) { fi->acquisition_type = MDC_ACQUISITION_TOMO; fi->reconstructed = MDC_NO; }else if (strcasecmp(mdcbufr,"DYNAMIC") == 0) { fi->acquisition_type = MDC_ACQUISITION_DYNAMIC; fi->reconstructed = MDC_NO; }else if (strcasecmp(mdcbufr,"GATED") == 0) { fi->acquisition_type = MDC_ACQUISITION_GSPECT; }else{ fi->acquisition_type = MDC_ACQUISITION_TOMO; } } if (MdcGetStrVM(mdcbufr,ps,2) == MDC_YES) { MdcKillSpaces(mdcbufr); if (strcasecmp(mdcbufr,"IMAGE") == 0) { fi->reconstructed = MDC_YES; }else{ fi->reconstructed = MDC_NO; } } break; case 0x1300: MdcPrintTag(fi,tag,"Frame Reference Time : %s\n",ps); flt = (float)atof(ps); dicom->framestart = flt; break; } break; /* group 0x7001 */ case 0x7001: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Shadow dummy - Group 7001\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0010: MdcPrintTag(fi,tag,"Shadow Owner Code : %s\n",ps); break; case 0x1010: MdcPrintTag(fi,tag,"Dummy Data Zero : %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x7003 */ case 0x7003: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Shadow Header - Group 7003\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0010: MdcPrintTag(fi,tag,"Shadow Owner Code : %s\n",ps); break; case 0x1010: MdcPrintTag(fi,tag,"Original NUMARIS2 Header : %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); break; } break; /* group 0x7005 */ case 0x7005: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Shadow Dummy - Group 7005\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0010: MdcPrintTag(fi,tag,"Shadow Owner Code : %s\n",ps); break; case 0x1010: MdcPrintTag(fi,tag,"Dummy Data Zero : %s\n",ps); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; /* group 0x7fe0 */ case 0x7fe0: switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Pixel Information - Group 7FE0\n"); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0010: MdcPrintTag(fi,tag,"Image Data : %u\n",ui32); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } break; default: if ( (tag->group >= 0x6000) && (tag->group <= 0x60e1) ) { switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Overlay - Group %.4x\n",tag->group); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Group Length : %u\n",ui32); break; case 0x0010: MdcPrintTag(fi,tag,"Rows : %hu\n",ui16); break; case 0x0011: MdcPrintTag(fi,tag,"Columns : %hu\n",ui16); break; case 0x0040: MdcPrintTag(fi,tag,"ROI : %s\n",ps); break; case 0x0050: MdcPrintTag(fi,tag,"Origin : %s\n",ps); break; case 0x0060: MdcPrintTag(fi,tag,"Compression Code : %s\n",ps); break; case 0x0100: MdcPrintTag(fi,tag,"Bits Allocated : %hu\n",ui16); break; case 0x0102: MdcPrintTag(fi,tag,"Bits Position : %hu\n",ui16); break; case 0x0110: MdcPrintTag(fi,tag,"Overlay Format : %s\n",ps); break; case 0x0200: MdcPrintTag(fi,tag,"Overlay Location : 0x%.4x\n",ui16); break; case 0x1100: MdcPrintTag(fi,tag,"Overlay Descriptor Gray : 0x%.4x\n",ui16); break; case 0x1101: MdcPrintTag(fi,tag,"Overlay Descriptor Red : 0x%.4x\n",ui16); break; case 0x1102: MdcPrintTag(fi,tag,"Overlay Descriptor Green : 0x%.4x\n",ui16); break; case 0x1103: MdcPrintTag(fi,tag,"Overlay Descriptor Blue : 0x%.4x\n",ui16); break; case 0x1200: MdcPrintTag(fi,tag,"Overlays Gray : 0x%.4x\n",ui16); break; case 0x1201: MdcPrintTag(fi,tag,"Overlays Red : 0x%.4x\n",ui16); break; case 0x1202: MdcPrintTag(fi,tag,"Overlays Green : 0x%.4x\n",ui16); break; case 0x1203: MdcPrintTag(fi,tag,"Overlays Blue : 0x%.4x\n",ui16); break; case 0x1301: MdcPrintTag(fi,tag,"ROI Area : %s\n",ps); break; case 0x1302: MdcPrintTag(fi,tag,"ROI Mean : %s\n",ps); break; case 0x1303: MdcPrintTag(fi,tag,"ROI Standard Deviation : %s\n",ps); break; case 0x3000: MdcPrintTag(fi,tag,"Overlay Data : 0x%.4x\n",ui16); break; default: MdcPrintTag(fi,tag,"Unknown Element : %s\n",ps); } }else{ switch(tag->element) { case 0x0000: if (MDC_INFO) { MdcPrntScrn("\n"); MdcPrintLine('-',MDC_FULL_LENGTH); MdcPrntScrn("Unknown Group - %.4x\n",tag->group); MdcPrintLine('-',MDC_FULL_LENGTH); } MdcPrintTag(fi,tag,"Unknown Group Length : %d\n",i32); break; default: MdcPrintTag(fi,tag,"Unknown Element : \n"); } } } return NULL; } /* 1 on success and 0 on error */ int MdcPutTag(FILE *fp,Uint16 group,Uint16 elem,Uint32 length,Uint8 *data) { MDC_ACR_TAG tag; Int8 MAKE_EVEN=0; if (length%2) MAKE_EVEN = 1; tag.group = group; tag.element = elem; tag.length = length + MAKE_EVEN; tag.data = data; MdcSwapTag(&tag); fwrite((Uint8 *)&tag,1,MDC_ACR_TAG_SIZE,fp); if (length > 0) fwrite(tag.data,1,length,fp); if (MAKE_EVEN) fputc('\0',fp); if (ferror(fp)) return(MDC_NO); return MDC_YES; } void MdcPutGroupLength(FILE *fp,Uint16 group, Uint32 gbegin) { Uint32 gend, glength; /* position */ gend = ftell(fp); fseek(fp,(signed)gbegin,SEEK_SET); /* get length and write */ glength = gend - gbegin - MDC_SIZE_E0000; MdcSWAP(glength); MdcPutTag(fp,group,0x0000,4,(Uint8 *)&glength); /* get back to end of file */ fseek(fp,0,SEEK_END); } /* 1 on success and 0 on error */ int MdcPutGroup(FILEINFO * fi, Uint16 group, Uint32 img) { IMG_DATA *id = &fi->image[img]; FILE *fp = fi->ofp; Uint16 i16, bits_allocated, bits_stored; Uint32 i32, gbegin=0; Int16 type; Uint8 *new_buf=NULL; char *pchar; if (MDC_QUANTIFY || MDC_CALIBRATE) { type = BIT16_S; /* printed as float, still an integer, */ /* for BIT32_S this could be like 2.147e+09 */ /* and that's a bit too confusing */ }else{ if ((id->type == FLT32) || (id->type == FLT64)) { /* no floats in ACR/NEMA */ type = BIT16_S; /* same reason as above */ }else{ type = id->type; } } /* Ola! there was a special integer request */ if (MDC_FORCE_INT != MDC_NO) { switch (MDC_FORCE_INT) { case BIT8_U : type = BIT8_U; break; case BIT16_S: type = BIT16_S; break; default : type = BIT16_S; } } switch(group) { case 0x0008: gbegin = ftell(fp); i32 = 0; /* write later */ MdcPutTag(fp,0x0008,0x0000,4,(Uint8 *)&i32); FP_G0008_E0001 = ftell(fp); i32 = 0; /* write later */ MdcPutTag(fp,0x0008,0x0001,4,(Uint8 *)&i32); strcpy(mdcbufr,"ACR-NEMA 2.0"); MdcPutTag(fp,0x0008,0x0010,strlen(mdcbufr),(Uint8 *)mdcbufr); sprintf(mdcbufr,"%04d.%02d.%02d",fi->study_date_year ,fi->study_date_month ,fi->study_date_day); MdcPutTag(fp,0x0008,0x0020,strlen(mdcbufr),(Uint8 *)mdcbufr); sprintf(mdcbufr,"%02d.%02d.%02d.0000",fi->study_time_hour ,fi->study_time_minute ,fi->study_time_second); MdcPutTag(fp,0x0008,0x0030,strlen(mdcbufr),(Uint8 *)mdcbufr); i16 = 0; MdcSWAP(i16); MdcPutTag(fp,0x0008,0x0040,2,(Uint8 *)&i16); pchar = MdcGetStrModality(fi->modality); /* already in mdcbufr */ MdcPutTag(fp,0x0008,0x0060,2,(Uint8 *)pchar); strcpy(mdcbufr,fi->manufacturer); MdcPutTag(fp,0x0008,0x0070,strlen(mdcbufr),(Uint8 *)mdcbufr); strcpy(mdcbufr,fi->institution); MdcPutTag(fp,0x0008,0x0080,strlen(mdcbufr),(Uint8 *)mdcbufr); MdcStringCopy(mdcbufr,fi->study_descr,strlen(fi->study_descr)); MdcPutTag(fp,0x0008,0x1030,strlen(mdcbufr),(Uint8 *)mdcbufr); MdcStringCopy(mdcbufr,fi->series_descr,strlen(fi->series_descr)); MdcPutTag(fp,0x0008,0x103E,strlen(mdcbufr),(Uint8 *)mdcbufr); MdcStringCopy(mdcbufr,fi->operator_name,strlen(fi->operator_name)); MdcPutTag(fp,0x0008,0x1070,strlen(mdcbufr),(Uint8 *)mdcbufr); strcpy(mdcbufr,MDC_LIBVERS); MdcPutTag(fp,0x0008,0x2111,strlen(mdcbufr),(Uint8 *)mdcbufr); break; case 0x0010: gbegin = ftell(fp); i32 = 0; /* write later */ MdcPutTag(fp,0x0010,0x0000,4,(Uint8 *)&i32); MdcStringCopy(mdcbufr,fi->patient_name,strlen(fi->patient_name)); MdcPutTag(fp,0x0010,0x0010,strlen(mdcbufr),(Uint8 *)mdcbufr); MdcStringCopy(mdcbufr,fi->patient_id,strlen(fi->patient_id)); MdcPutTag(fp,0x0010,0x0020,strlen(mdcbufr),(Uint8 *)mdcbufr); MdcStringCopy(mdcbufr,fi->patient_sex,strlen(fi->patient_sex)); MdcPutTag(fp,0x0010,0x0040,strlen(mdcbufr),(Uint8 *)mdcbufr); sprintf(mdcbufr,"%.2f",fi->patient_height); MdcPutTag(fp,0x0010,0x1020,strlen(mdcbufr),(Uint8 *)mdcbufr); sprintf(mdcbufr,"%.2f",fi->patient_weight); MdcPutTag(fp,0x0010,0x1030,strlen(mdcbufr),(Uint8 *)mdcbufr); break; case 0x0018: gbegin = ftell(fp); i32 = 0; /* write later */ MdcPutTag(fp,0x0018,0x0000,4,(Uint8 *)&i32); MdcStringCopy(mdcbufr,fi->radiopharma,strlen(fi->radiopharma)); MdcPutTag(fp,0x0018,0x0030,strlen(mdcbufr),(Uint8 *)mdcbufr); MdcStringCopy(mdcbufr,fi->radiopharma,strlen(fi->radiopharma)); MdcPutTag(fp,0x0018,0x0031,strlen(mdcbufr),(Uint8 *)mdcbufr); sprintf(mdcbufr,"%+e",id->slice_width); MdcPutTag(fp,0x0018,0x0050,strlen(mdcbufr),(Uint8 *)mdcbufr); sprintf(mdcbufr,"%+e",id->slice_spacing); MdcPutTag(fp,0x0018,0x0088,strlen(mdcbufr),(Uint8 *)mdcbufr); sprintf(mdcbufr,"%g",fi->injected_dose); MdcPutTag(fp,0x0018,0x1074,strlen(mdcbufr),(Uint8 *)mdcbufr); sprintf(mdcbufr,"%+e",fi->gantry_tilt); MdcPutTag(fp,0x0018,0x1120,strlen(mdcbufr),(Uint8 *)mdcbufr); MdcStringCopy(mdcbufr,fi->filter_type,strlen(fi->filter_type)); MdcPutTag(fp,0x0018,0x1160,strlen(mdcbufr),(Uint8 *)mdcbufr); MdcStringCopy(mdcbufr,fi->pat_pos,strlen(fi->pat_pos)); MdcPutTag(fp,0x0018,0x5100,strlen(mdcbufr),(Uint8 *)mdcbufr); break; case 0x0020: gbegin = ftell(fp); i32 = 0; /* write later */ MdcPutTag(fp,0x0020,0x0000,4,(Uint8 *)&i32); MdcStringCopy(mdcbufr,fi->study_id,strlen(fi->study_id)); MdcPutTag(fp,0x0020,0x0010,strlen(mdcbufr),(Uint8 *)mdcbufr); if (fi->nr_series >= 0) sprintf(mdcbufr,"%d",fi->nr_series); else strcpy(mdcbufr,"0"); MdcPutTag(fp,0x0020,0x0011,strlen(mdcbufr),(Uint8 *)mdcbufr); if (fi->nr_acquisition >= 0) sprintf(mdcbufr,"%d",fi->nr_acquisition); else strcpy(mdcbufr,"0"); MdcPutTag(fp,0x0020,0x0012,strlen(mdcbufr),(Uint8 *)mdcbufr); if (fi->nr_instance >= 0) sprintf(mdcbufr,"%d",fi->nr_instance); else sprintf(mdcbufr,"%u",img+1); MdcPutTag(fp,0x0020,0x0013,6,(Uint8 *)mdcbufr); MdcStringCopy(mdcbufr,fi->pat_orient,strlen(fi->pat_orient)); MdcPutTag(fp,0x0020,0x0020,strlen(mdcbufr),(Uint8 *)mdcbufr); sprintf(mdcbufr,"%+e\\%+e\\%+e",id->image_pos_dev[0], id->image_pos_dev[1], id->image_pos_dev[2]); MdcPutTag(fp,0x0020,0x0030,strlen(mdcbufr),(Uint8 *)mdcbufr); sprintf(mdcbufr,"%+e\\%+e\\%+e",id->image_pos_pat[0], id->image_pos_pat[1], id->image_pos_pat[2]); MdcPutTag(fp,0x0020,0x0032,strlen(mdcbufr),(Uint8 *)mdcbufr); sprintf(mdcbufr,"%+e\\%+e\\%+e\\%+e\\%+e\\%+e", id->image_orient_dev[0], id->image_orient_dev[1], id->image_orient_dev[2], id->image_orient_dev[3], id->image_orient_dev[4], id->image_orient_dev[5]); MdcPutTag(fp,0x0020,0x0035,strlen(mdcbufr),(Uint8 *)mdcbufr); sprintf(mdcbufr,"%+e\\%+e\\%+e\\%+e\\%+e\\%+e", id->image_orient_pat[0], id->image_orient_pat[1], id->image_orient_pat[2], id->image_orient_pat[3], id->image_orient_pat[4], id->image_orient_pat[5]); MdcPutTag(fp,0x0020,0x0037,strlen(mdcbufr),(Uint8 *)mdcbufr); break; case 0x0028: gbegin = ftell(fp); i32 = 0; /* write later */ MdcPutTag(fp,0x0028,0x0000,4,(Uint8 *)&i32); i16 = 1; MdcSWAP(i16); MdcPutTag(fp,0x0028,0x0002,2,(Uint8 *)&i16); i16 = 2; MdcSWAP(i16); MdcPutTag(fp,0x0028,0x0005,2,(Uint8 *)&i16); i16 = (Int16)id->height; MdcSWAP(i16); MdcPutTag(fp,0x0028,0x0010,2,(Uint8 *)&i16); i16 = (Int16)id->width; MdcSWAP(i16); MdcPutTag(fp,0x0028,0x0011,2,(Uint8 *)&i16); sprintf(mdcbufr,"%+e\\%+e",id->pixel_xsize,id->pixel_ysize); MdcPutTag(fp,0x0028,0x0030,strlen(mdcbufr),(Uint8 *)mdcbufr); strcpy(mdcbufr,"NONE"); MdcPutTag(fp,0x0028,0x0060,strlen(mdcbufr),(Uint8 *)mdcbufr); bits_allocated = (Uint16)MdcType2Bits(type); if (MDC_FORCE_INT == BIT16_S) { bits_stored = MDC_INT16_BITS_USED; }else{ bits_stored = MdcType2Bits(type); } i16 = bits_allocated; MdcSWAP(i16); MdcPutTag(fp,0x0028,0x0100,2,(Uint8 *)&i16); i16 = bits_stored; MdcSWAP(i16); MdcPutTag(fp,0x0028,0x0101,2,(Uint8 *)&i16); i16 = bits_stored - 1; MdcSWAP(i16); MdcPutTag(fp,0x0028,0x0102,2,(Uint8 *)&i16); switch (type) { case BIT8_U: case BIT16_U: case BIT32_U: case BIT64_U: i16 = 0; break; case BIT8_S: case BIT16_S: case BIT32_S: case BIT64_S: i16 = 1; break; default: i16 = 0; } if (type == BIT16_S && MDC_INT16_BITS_USED < 16) i16 = 0; /* unsigned */ MdcSWAP(i16); MdcPutTag(fp,0x0028,0x0103,2,(Uint8 *)&i16); i16 = 0x7fe0; MdcSWAP(i16); MdcPutTag(fp,0x0028,0x0200,2,(Uint8 *)&i16); break; case 0x7fe0: gbegin=ftell(fp); i32 = 0; /* write later */ MdcPutTag(fp,0x7fe0,0x0000,4,(Uint8 *)&i32); /* imagesize */ i32 = id->width * id->height * MdcType2Bytes(type); if (MDC_QUANTIFY || MDC_CALIBRATE || MDC_FORCE_INT) { switch (type) { case BIT8_U: new_buf = MdcGetImgBIT8_U(fi,img); break; case BIT16_S: new_buf = MdcGetImgBIT16_S(fi,img); break; default : new_buf = MdcGetImgBIT16_S(fi,img); } if (new_buf == NULL) { MdcPrntWarn("ACR Couldn't get normalized image"); return(MDC_NO); } if (MDC_FILE_ENDIAN != MDC_HOST_ENDIAN) MdcMakeImgSwapped(new_buf,fi,img,id->width,id->height,type); MdcPutTag(fp,0x7fe0,0x0010,i32,new_buf); MdcFree(new_buf); }else{ if ( (id->type == FLT32) || (id->type == FLT64) ) { /* ACR/NEMA doesn't accept float/double */ new_buf = MdcGetImgBIT16_S(fi,img); if (new_buf == NULL) { MdcPrntWarn("ACR Downscaling `float' failed"); return MDC_NO; } if (MDC_FILE_ENDIAN != MDC_HOST_ENDIAN) MdcMakeImgSwapped(new_buf,fi,img,id->width,id->height,type); MdcPutTag(fp,0x7fe0,0x0010,i32,new_buf); MdcFree(new_buf); }else{ /* ACR/NEMA accepts any integer */ if (MDC_FILE_ENDIAN != MDC_HOST_ENDIAN) { new_buf = MdcGetImgSwapped(fi,img); if (new_buf == NULL) { MdcPrntWarn("ACR Couldn't malloc swapped image"); return MDC_NO; } MdcPutTag(fp,0x7fe0,0x0010,i32,new_buf); MdcFree(new_buf); }else{ MdcPutTag(fp,0x7fe0,0x0010,i32,id->buf); } } } } MdcPutGroupLength(fp,group,gbegin); if (ferror(fp)) return MDC_NO; return MDC_YES; } const char *MdcWriteACR(FILEINFO *fi) { Uint32 i, FileBegin, FileEnd, FSIZE; MDC_FILE_ENDIAN = MDC_WRITE_ENDIAN; if (XMDC_GUI == MDC_NO) { MdcDefaultName(fi,MDC_FRMT_ACR,fi->ofname,fi->ifname); } if (MDC_PROGRESS) MdcProgress(MDC_PROGRESS_BEGIN,0.,"Writing Acr/Nema:"); if (MDC_VERBOSE) MdcPrntMesg("ACR Writing <%s> ...",fi->ofname); /* check for colored files */ if (fi->map == MDC_MAP_PRESENT) return("ACR Colored files unsupported"); if (MDC_FILE_STDOUT == MDC_YES) { fi->ofp = stdout; }else{ if (MdcKeepFile(fi->ofname)) return("ACR File exists!!"); if ( (fi->ofp=fopen(fi->ofname,"wb")) == NULL) return("ACR Couldn't open file"); } /* check supported things */ if (MDC_QUANTIFY || MDC_CALIBRATE) { MdcPrntWarn("ACR Normalization loses quantified values!"); } for (i=0; inumber; i++) { if (MDC_PROGRESS) MdcProgress(MDC_PROGRESS_INCR,1./(float)fi->number,NULL); FileBegin = ftell(fi->ofp); if (!MdcPutGroup(fi,0x0008,i)) return("ACR Bad write Identifying Info"); if (!MdcPutGroup(fi,0x0010,i)) return("ACR Bad write Patient Info"); if (!MdcPutGroup(fi,0x0018,i)) return("ACR Bad write Acquisition Info"); if (!MdcPutGroup(fi,0x0020,i)) return("ACR Bad write Relationship Info"); if (!MdcPutGroup(fi,0x0028,i)) return("ACR Bad write Image Presentation"); if (!MdcPutGroup(fi,0x7fe0,i)) return("ACR Bad write Image Array"); /* rewrite (0x0008,0x0001) tag */ FileEnd = ftell(fi->ofp); FSIZE = FileEnd-(FileBegin+MDC_SIZE_E0000+MDC_SIZE_E0001); MdcSWAP(FSIZE); fseek(fi->ofp,FP_G0008_E0001,SEEK_SET); MdcPutTag(fi->ofp,0x0008,0x0001,4,(Uint8 *)&FSIZE); fseek(fi->ofp,0,SEEK_END); } MdcCloseFile(fi->ofp); return NULL; }