00001 
00002 
00003 #include "gdcmFile.h"
00004 #include "gdcmUtil.h"
00005 #include "jpeg/ljpg/jpegless.h"
00006 
00007 typedef std::pair<TagHeaderEntryHT::iterator,TagHeaderEntryHT::iterator> IterHT;
00008 
00009 
00010 
00026 gdcmFile::gdcmFile(gdcmHeader *header) {
00027    Header=header;
00028    SelfHeader=false;
00029    PixelRead=-1; 
00030 
00031    if (Header->IsReadable())
00032       SetPixelDataSizeFromHeader();
00033 }
00034 
00048 gdcmFile::gdcmFile(std::string & filename) {
00049    Header=new gdcmHeader(filename.c_str());
00050    SelfHeader=true;
00051    PixelRead=-1; 
00052 
00053    if (Header->IsReadable())
00054       SetPixelDataSizeFromHeader();
00055 }
00056 
00070  gdcmFile::gdcmFile(const char * filename) {
00071    Header=new gdcmHeader(filename);
00072    SelfHeader=true;
00073    PixelRead=-1; 
00074 
00075    if (Header->IsReadable())
00076       SetPixelDataSizeFromHeader();
00077 }
00078 
00085 gdcmFile::~gdcmFile(void) {
00086    if(SelfHeader)
00087       delete Header;
00088    Header=NULL;
00089 }
00090 
00091 
00092 
00093 
00094 
00095 
00101 gdcmHeader *gdcmFile::GetHeader(void) {
00102    return(Header);
00103 }
00104 
00113 void gdcmFile::SetPixelDataSizeFromHeader(void) {
00114    
00115    
00116    
00117    
00118    
00119    
00120    
00121    
00122    
00123    
00124    
00125    
00126    
00127    
00128 
00129    
00130    
00131    
00132    
00133    
00134 
00135    
00136    
00137    
00138    
00139 
00140    int nb;
00141    std::string str_nb;
00142    str_nb=Header->GetEntryByNumber(0x0028,0x0100);
00143    if (str_nb == GDCM_UNFOUND ) {
00144       nb = 16;
00145    } else {
00146       nb = atoi(str_nb.c_str() );
00147       if (nb == 12) nb =16;
00148    }
00149    lgrTotale =  lgrTotaleRaw = Header->GetXSize() * Header->GetYSize() 
00150               * Header->GetZSize() * (nb/8)* Header->GetSamplesPerPixel();
00151    std::string str_PhotometricInterpretation = 
00152                              Header->GetEntryByNumber(0x0028,0x0004);
00153                              
00154    
00155    
00156    
00157     if (Header->HasLUT()) { 
00158       lgrTotale*=3;
00159    }
00160 }
00161 
00168 size_t gdcmFile::GetImageDataSize(void) {
00169    return (lgrTotale);
00170 }
00171 
00181 size_t gdcmFile::GetImageDataSizeRaw(void) {
00182    return (lgrTotaleRaw);
00183 }
00184 
00195 void * gdcmFile::GetImageData (void) {
00196    PixelData = (void *) malloc(lgrTotale);
00197    if (PixelData)
00198       GetImageDataIntoVector(PixelData, lgrTotale);
00199    PixelRead=0; 
00200    return(PixelData);
00201 }
00202 
00224 size_t gdcmFile::GetImageDataIntoVector (void* destination, size_t MaxSize) {
00225    size_t l = GetImageDataIntoVectorRaw (destination, MaxSize);
00226    PixelRead=0 ; 
00227    if (!Header->HasLUT())
00228       return lgrTotale; 
00229                             
00230    
00231    unsigned char * newDest = (unsigned char *)malloc(lgrTotale);
00232    unsigned char * a       = (unsigned char *)destination;       
00233    unsigned char * lutRGBA =                  Header->GetLUTRGBA();
00234    if (lutRGBA) {           
00235       int l = lgrTotaleRaw;
00236       memmove(newDest, destination, l);
00237       int j;     
00238       for (int i=0;i<l; i++) {         
00239          j=newDest[i]*4;
00240          *a++ = lutRGBA[j]; 
00241          *a++ = lutRGBA[j+1];
00242          *a++ = lutRGBA[j+2];
00243       }
00244       free(newDest);
00245     
00246    
00247    
00248 
00249          
00250          
00251    std::string spp = "3";        
00252    Header->SetEntryByNumber(spp,0x0028,0x0002);
00253    std::string rgb= "RGB ";      
00254    Header->SetEntryByNumber(rgb,0x0028,0x0004);
00255    std::string planConfig = "0"; 
00256    Header->SetEntryByNumber(planConfig,0x0028,0x0006);
00257 
00258    } else { 
00259              
00260              
00261              
00262              
00263                                                   
00264          
00265          
00266          
00267          
00268                    
00269       std::string rgb= "MONOCHROME1 ";      
00270       Header->SetEntryByNumber(rgb,0x0028,0x0004);                                 
00271    }             
00272    
00273    return lgrTotale; 
00274 }
00275 
00286 void * gdcmFile::GetImageDataRaw (void) {
00287    if (Header->HasLUT())
00288       lgrTotale /= 3;  
00289                        
00290                        
00291    PixelData = (void *) malloc(lgrTotale);
00292    if (PixelData)
00293       GetImageDataIntoVectorRaw(PixelData, lgrTotale);
00294    PixelRead=1; 
00295    return(PixelData);
00296 }
00297 
00322 size_t gdcmFile::GetImageDataIntoVectorRaw (void* destination, size_t MaxSize) {
00323 
00324    int nb, nbu, highBit, signe;
00325    std::string str_nbFrames, str_nb, str_nbu, str_highBit, str_signe;
00326    PixelRead=1 ; 
00327  
00328    if ( lgrTotale > MaxSize ) {
00329       dbg.Verbose(0, "gdcmFile::GetImageDataIntoVector: pixel data bigger"
00330                      "than caller's expected MaxSize");
00331       return (size_t)0; 
00332    }
00333         
00334    (void)ReadPixelData(destination);
00335         
00336         
00337    str_nb = Header->GetEntryByNumber(0x0028,0x0100);
00338    if (str_nb == GDCM_UNFOUND ) {
00339       nb = 16;
00340    } else {
00341       nb = atoi(str_nb.c_str() );
00342    }    
00343         
00344    str_nbu=Header->GetEntryByNumber(0x0028,0x0101);
00345    if (str_nbu == GDCM_UNFOUND ) {
00346       nbu = nb;
00347    } else {
00348       nbu = atoi(str_nbu.c_str() );
00349    }            
00350         
00351    str_highBit=Header->GetEntryByNumber(0x0028,0x0102);
00352    if (str_highBit == GDCM_UNFOUND ) {
00353       highBit = nb - 1;
00354    } else {
00355       highBit = atoi(str_highBit.c_str() );
00356    }            
00357         
00358         
00359         
00360    str_signe=Header->GetEntryByNumber(0x0028,0x0103);
00361    if (str_signe == GDCM_UNFOUND ) {
00362       signe = 0;  
00363    } else {
00364       signe = atoi(str_signe.c_str() );
00365    }
00366 
00367    
00368    if (nb != 8)
00369      SwapZone(destination, Header->GetSwapCode(), lgrTotale, nb);
00370      
00371    
00372    if (nb==16 && nbu<nb && signe==0) {
00373      int l = (int)lgrTotale / (nb/8);
00374      guint16 *deb = (guint16 *)destination;
00375      for(int i = 0; i<l; i++) {
00376         if(*deb == 0xffff) 
00377            *deb=0; 
00378            deb++;   
00379          }
00380     }
00381 
00382    
00383    if (nbu != nb){
00384       int l = (int)lgrTotale / (nb/8);
00385       if (nb == 16) {
00386          guint16 mask = 0xffff;
00387          mask = mask >> (nb-nbu);
00388          guint16 *deb = (guint16 *)destination;
00389          for(int i = 0; i<l; i++) {
00390             *deb = (*deb >> (nbu-highBit-1)) & mask;
00391             deb ++;
00392          }
00393       } else if (nb == 32 ) {
00394          guint32 mask = 0xffffffff;
00395          mask = mask >> (nb-nbu);
00396          guint32 *deb = (guint32 *)destination;
00397          for(int i = 0; i<l; i++) {
00398             *deb = (*deb >> (nbu-highBit-1)) & mask;
00399             deb ++;
00400          }
00401       } else {
00402          dbg.Verbose(0, "gdcmFile::GetImageDataIntoVector: wierd image");
00403          return (size_t)0; 
00404       }
00405    } 
00406 
00407 
00408 
00409 
00410 
00411 
00412 
00413 
00414 
00415    
00416    
00417    
00418        std::string str_PhotometricInterpretation = 
00419                  Header->GetEntryByNumber(0x0028,0x0004);
00420                    
00421       if ( (str_PhotometricInterpretation == "MONOCHROME1 ") 
00422         || (str_PhotometricInterpretation == "MONOCHROME2 ") ) {
00423          return lgrTotale; 
00424       }
00425       
00426    
00427    
00428    
00429 
00430    
00431    
00432    
00433    
00434 
00435       int planConf=Header->GetPlanarConfiguration();  
00436 
00437       
00438       
00439       if (str_PhotometricInterpretation == "PALETTE COLOR ")
00440          planConf=2;
00441 
00442       switch (planConf) {
00443       case 0:                              
00444          
00445          break;
00446     
00447       case 1:
00448 
00449          {
00450          if (str_PhotometricInterpretation == "YBR_FULL") { 
00451          
00452    
00453    
00454          
00455          
00456          
00457          
00458          
00459          
00460             int l = Header->GetXSize()*Header->GetYSize();
00461             int nbFrames = Header->GetZSize();
00462 
00463             unsigned char * newDest = (unsigned char*) malloc(lgrTotale);
00464             unsigned char *x  = newDest;
00465             unsigned char * a = (unsigned char *)destination;
00466             unsigned char * b = a + l;
00467             unsigned char * c = b + l;
00468             double R,G,B;
00469 
00470             
00471             
00472             
00473             
00474             
00475             for (int i=0;i<nbFrames;i++) {
00476                for (int j=0;j<l; j++) {
00477                   R= 1.164 *(*a-16) + 1.596 *(*c -128) + 0.5;
00478                   G= 1.164 *(*a-16) - 0.813 *(*c -128) - 0.392 *(*b -128) + 0.5;
00479                   B= 1.164 *(*a-16) + 2.017 *(*b -128) + 0.5;
00480 
00481                   if (R<0.0)   R=0.0;
00482                   if (G<0.0)   G=0.0;
00483                   if (B<0.0)   B=0.0;
00484                   if (R>255.0) R=255.0;
00485                   if (G>255.0) G=255.0;
00486                   if (B>255.0) B=255.0;
00487 
00488                   *(x++) = (unsigned char)R;
00489                   *(x++) = (unsigned char)G;
00490                   *(x++) = (unsigned char)B;
00491                   a++; b++; c++;  
00492                }
00493            }
00494             memmove(destination,newDest,lgrTotale);
00495             free(newDest);
00496 
00497         } else {
00498          
00499          
00500          
00501 
00502             int l = Header->GetXSize()*Header->GetYSize()*Header->GetZSize();
00503 
00504             char * newDest = (char*) malloc(lgrTotale);
00505             char * x = newDest;
00506             char * a = (char *)destination;
00507             char * b = a + l;
00508             char * c = b + l;
00509 
00510             for (int j=0;j<l; j++) {
00511                *(x++) = *(a++);
00512                *(x++) = *(b++);
00513                *(x++) = *(c++);  
00514             }           
00515             memmove(destination,newDest,lgrTotale);
00516             free(newDest);
00517         }         
00518          break;
00519        }     
00520        case 2:                      
00521          
00522          
00523          return lgrTotale;        
00524    } 
00525    
00526    
00527 
00528    
00529 
00530    std::string spp = "3";        
00531    Header->SetEntryByNumber(spp,0x0028,0x0002);
00532    std::string rgb="RGB ";   
00533    Header->SetEntryByNumber(rgb,0x0028,0x0004);
00534 
00535    std::string planConfig = "0"; 
00536    Header->SetEntryByNumber(planConfig,0x0028,0x0006);
00537          
00538          
00539    return lgrTotale; 
00540 }
00541 
00553 bool gdcmFile::SetImageData(void * inData, size_t ExpectedSize) {
00554    Header->SetImageDataSize(ExpectedSize);
00555    PixelData = inData;
00556    lgrTotale = ExpectedSize;
00557    return(true);
00558 }
00559 
00570 bool gdcmFile::WriteRawData (std::string fileName) {
00571    FILE * fp1;
00572    fp1 = fopen(fileName.c_str(),"wb");
00573    if (fp1 == NULL) {
00574       printf("Fail to open (write) file [%s] \n",fileName.c_str());
00575       return (false);
00576    }    
00577    fwrite (PixelData,lgrTotale, 1, fp1);
00578    fclose (fp1);
00579    return(true);
00580 }
00581 
00591 bool gdcmFile::WriteDcmImplVR (std::string fileName) {
00592    return WriteBase(fileName, ImplicitVR);
00593 }
00594 
00603 bool gdcmFile::WriteDcmImplVR (const char* fileName) {
00604    return WriteDcmImplVR (std::string (fileName));
00605 }
00606         
00615 bool gdcmFile::WriteDcmExplVR (std::string fileName) {
00616    return WriteBase(fileName, ExplicitVR);
00617 }
00618         
00635 bool gdcmFile::WriteAcr (std::string fileName) {
00636    return WriteBase(fileName, ACR);
00637 }
00638 
00639 
00640 
00649 bool gdcmFile::WriteBase (std::string fileName, FileType type) {
00650 
00651    FILE * fp1;
00652    
00653    if (PixelRead==-1 && type != DICOMDIR) {
00654 
00655 
00656       return false;                
00657    }
00658 
00659    fp1 = fopen(fileName.c_str(),"wb");
00660    if (fp1 == NULL) {
00661       printf("Failed to open (write) File [%s] \n",fileName.c_str());
00662       return (false);
00663    }
00664 
00665    if ( (type == ImplicitVR) || (type == ExplicitVR) ) {
00666       char * filePreamble;
00667       
00668       filePreamble=(char*)calloc(128,1);
00669       fwrite(filePreamble,128,1,fp1);
00670       fwrite("DICM",4,1,fp1);
00671       free (filePreamble);
00672    }
00673 
00674    
00675    
00676    
00677    
00678    
00679    
00680    
00681    
00682    
00683 
00684    std::string rows, columns; 
00685    if ( Header->GetFileType() == ACR_LIBIDO){
00686          rows    = Header->GetEntryByNumber(0x0028, 0x0010);
00687          columns = Header->GetEntryByNumber(0x0028, 0x0011);
00688          Header->SetEntryByNumber(columns,  0x0028, 0x0010);
00689          Header->SetEntryByNumber(rows   ,  0x0028, 0x0011);
00690    }    
00691    
00692    
00693    
00694    
00695    guint16 grPixel =Header->GetGrPixel();
00696    guint16 numPixel=Header->GetNumPixel();;
00697     
00698    
00699    
00700           
00701    TagKey key = gdcmDictEntry::TranslateToKey(grPixel, numPixel); 
00702    TagHeaderEntryHT::iterator p2;
00703    gdcmHeaderEntry * PixelElement;
00704    
00705    IterHT it= Header->GetEntry().equal_range(key); 
00706 
00707    if (Header->GetEntry().count(key) == 1) 
00708       p2=it.first; 
00709    else
00710       p2=it.second;
00711    
00712    PixelElement=p2->second;        
00713   
00714   
00715  
00716    if (PixelRead==1)
00717       PixelElement->SetLength(lgrTotaleRaw);
00718    else if (PixelRead==0)
00719       PixelElement->SetLength(lgrTotale);
00720    
00721    
00722    
00723  
00724    Header->Write(fp1, type);
00725 
00726    
00727    
00728    
00729    
00730    
00731 
00732    if (Header->GetFileType() == ACR_LIBIDO){
00733          Header->SetEntryByNumber(rows   , 0x0028, 0x0010);
00734          Header->SetEntryByNumber(columns, 0x0028, 0x0011);
00735    }    
00736    
00737    
00738    fwrite(PixelData, lgrTotale, 1, fp1);
00739    fclose (fp1);
00740    return(true);
00741 }
00742 
00743 
00744 
00754 void gdcmFile::SwapZone(void* im, int swap, int lgr, int nb) {
00755 guint32 s32;
00756 guint16 fort,faible;
00757 int i;
00758 
00759 if(nb == 16)  
00760    switch(swap) {
00761       case 0:
00762       case 12:
00763       case 1234:
00764          break;
00765                 
00766       case 21:
00767       case 3412:
00768       case 2143:
00769       case 4321:
00770 
00771          for(i=0;i<lgr;i++)
00772             ((unsigned short int*)im)[i]= ((((unsigned short int*)im)[i])>>8)
00773                                         | ((((unsigned short int*)im)[i])<<8);
00774          break;
00775                         
00776       default:
00777          printf("SWAP value (16 bits) not allowed : %d\n", swap);
00778    } 
00779  
00780 if( nb == 32 )
00781    switch (swap) {
00782       case 0:
00783       case 1234:
00784          break;
00785 
00786       case 4321:
00787          for(i=0;i<lgr;i++) {
00788             faible=  ((unsigned long int*)im)[i]&0x0000ffff;    
00789             fort  =((unsigned long int*)im)[i]>>16;
00790             fort=  (fort>>8)   | (fort<<8);
00791             faible=(faible>>8) | (faible<<8);
00792             s32=faible;
00793             ((unsigned long int*)im)[i]=(s32<<16)|fort;
00794          }
00795          break;
00796 
00797       case 2143:
00798          for(i=0;i<lgr;i++) {
00799             faible=  ((unsigned long int*)im)[i]&0x0000ffff;    
00800             fort=((unsigned long int*)im)[i]>>16;
00801             fort=  (fort>>8)   | (fort<<8);
00802             faible=(faible>>8) | (faible<<8);
00803             s32=fort; 
00804             ((unsigned long int*)im)[i]=(s32<<16)|faible;
00805          }
00806          break;
00807   
00808       case 3412:
00809          for(i=0;i<lgr;i++) {
00810             faible=  ((unsigned long int*)im)[i]&0x0000ffff;    
00811             fort=((unsigned long int*)im)[i]>>16;                  
00812             s32=faible; 
00813             ((unsigned long int*)im)[i]=(s32<<16)|fort;
00814          }                 
00815          break; 
00816                                 
00817       default:
00818          printf("SWAP value (32 bits) not allowed : %d\n", swap);
00819    } 
00820 return;
00821 }
00822 
00830 bool gdcmFile::ReadPixelData(void* destination) {
00831 
00832    FILE *fp;
00833 
00834    if ( !(fp=Header->OpenFile()))
00835       return false;
00836    if ( fseek(fp, Header->GetPixelOffset(), SEEK_SET) == -1 ) {
00837       Header->CloseFile();
00838       return false;
00839    }
00840    
00841    
00842    
00843    
00844    
00845    if (Header->GetBitsAllocated()==12) {
00846       int nbPixels = Header->GetXSize() * Header->GetYSize();
00847       unsigned char b0, b1, b2;
00848       
00849       unsigned short int* pdestination = (unsigned short int*)destination;    
00850       for(int p=0;p<nbPixels;p+=2) {
00851          fread(&b0,1,1,fp);
00852          fread(&b1,1,1,fp);
00853          fread(&b2,1,1,fp);      
00854          
00855          *pdestination++ =  ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
00856                                                        
00857          *pdestination++ =  ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
00858                                                        
00859                   
00860         
00861       }
00862 
00863       Header->CloseFile();
00864       return(true);
00865    }        
00866 
00867    
00868    if ( !Header->IsDicomV3()                             ||
00869         Header->IsImplicitVRLittleEndianTransferSyntax() ||
00870         Header->IsExplicitVRLittleEndianTransferSyntax() ||
00871         Header->IsExplicitVRBigEndianTransferSyntax()    ||
00872         Header->IsDeflatedExplicitVRLittleEndianTransferSyntax() ) {
00873 
00874       size_t ItemRead = fread(destination, Header->GetPixelAreaLength(), 1, fp);
00875       if ( ItemRead != 1 ) {
00876          Header->CloseFile();
00877          return false;
00878       } else {
00879          Header->CloseFile();
00880          return true;
00881       }
00882    } 
00883 
00884    
00885    if (Header->IsRLELossLessTransferSyntax()) {
00886       bool res = (bool)gdcm_read_RLE_file (fp,destination);
00887       Header->CloseFile();
00888       return res; 
00889    }  
00890     
00891    
00892    int nb;
00893    std::string str_nb=Header->GetEntryByNumber(0x0028,0x0100);
00894    if (str_nb == GDCM_UNFOUND ) {
00895       nb = 16;
00896    } else {
00897       nb = atoi(str_nb.c_str() );
00898       if (nb == 12) nb =16;  
00899    }
00900 
00901    int nBytes= nb/8;
00902    
00903    int taille = Header->GetXSize() * Header->GetYSize()  
00904                * Header->GetSamplesPerPixel();    
00905    long fragmentBegining; 
00906 
00907    bool jpg2000 =     Header->IsJPEG2000();
00908    bool jpgLossless = Header->IsJPEGLossless();
00909     
00910    bool res = true;
00911    guint16 ItemTagGr,ItemTagEl;
00912    int ln;  
00913    
00914    
00915    
00916    fread(&ItemTagGr,2,1,fp);  
00917    fread(&ItemTagEl,2,1,fp);  
00918    if(Header->GetSwapCode()) {
00919       ItemTagGr=Header->SwapShort(ItemTagGr); 
00920       ItemTagEl=Header->SwapShort(ItemTagEl);            
00921    }
00922    fread(&ln,4,1,fp); 
00923    if(Header->GetSwapCode()) 
00924       ln=Header->SwapLong(ln);    
00925       
00926    if (ln != 0) {
00927       
00928       char *BasicOffsetTableItemValue = (char *)malloc(ln+1);        
00929       fread(BasicOffsetTableItemValue,ln,1,fp); 
00930    }
00931    
00932    
00933    fread(&ItemTagGr,2,1,fp);  
00934    fread(&ItemTagEl,2,1,fp);  
00935    if(Header->GetSwapCode()) {
00936       ItemTagGr=Header->SwapShort(ItemTagGr); 
00937       ItemTagEl=Header->SwapShort(ItemTagEl);            
00938    }
00939            
00940    
00941    while ( ( ItemTagGr == 0xfffe) && (ItemTagEl != 0xe0dd) ) { 
00942       
00943 
00944       fread(&ln,4,1,fp); 
00945       if(Header->GetSwapCode()) 
00946          ln=Header->SwapLong(ln);    
00947    
00948       fragmentBegining=ftell(fp);   
00949 
00950       if (jpg2000) {          
00951  
00952          res = (bool)gdcm_read_JPEG2000_file (fp,destination);  
00953 
00954       } 
00955         
00956       else if (jpgLossless) { 
00957                    
00958          JPEGLosslessDecodeImage (fp,  
00959                                      (unsigned short *)destination,
00960                                      Header->GetPixelSize()*8* Header->GetSamplesPerPixel(),
00961                                      ln);                                                          
00962          res=1; 
00963   
00964       } 
00965                
00966       else {                   
00967 
00968          if  (Header->GetBitsStored() == 8) {
00969             res = (bool)gdcm_read_JPEG_file (fp,destination);  
00970          } else {
00971             res = (bool)gdcm_read_JPEG_file12 (fp,destination);
00972          } 
00973       }  
00974          
00975       if (!res) break;
00976                
00977       destination = (char *)destination + taille * nBytes; 
00978                                                            
00979       
00980       fseek(fp,fragmentBegining,SEEK_SET); 
00981       fseek(fp,ln,SEEK_CUR);               
00982       
00983       ItemTagGr = ItemTagEl =0;
00984       fread(&ItemTagGr,2,1,fp);  
00985       fread(&ItemTagEl,2,1,fp);  
00986       if(Header->GetSwapCode()) {
00987          ItemTagGr=Header->SwapShort(ItemTagGr); 
00988          ItemTagEl=Header->SwapShort(ItemTagEl);            
00989       } 
00990    
00991    }     
00992  
00993    Header->CloseFile();
00994    return res;
00995 }
00996