Main Page | File List | Related Pages

gdcmFile.cxx

00001 // gdcmFile.cxx
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 // Constructor / Destructor
00026 gdcmFile::gdcmFile(gdcmHeader *header) {
00027    Header=header;
00028    SelfHeader=false;
00029    PixelRead=-1; // no ImageData read yet.
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; // no ImageData read yet.
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; // no ImageData read yet.
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 // Print
00093 
00094 //-----------------------------------------------------------------------------
00095 // Public
00101 gdcmHeader *gdcmFile::GetHeader(void) {
00102    return(Header);
00103 }
00104 
00113 void gdcmFile::SetPixelDataSizeFromHeader(void) {
00114    // see PS 3.3-2003 : C.7.6.3.2.1  
00115    // 
00116    //   MONOCHROME1
00117    //   MONOCHROME2
00118    //   PALETTE COLOR
00119    //   RGB
00120    //   HSV  (Retired)
00121    //   ARGB (Retired)
00122    //   CMYK (Retired)
00123    //   YBR_FULL
00124    //   YBR_FULL_422 (no LUT, no Palette)
00125    //   YBR_PARTIAL_422
00126    //   YBR_ICT
00127    //   YBR_RCT
00128 
00129    // LUT's
00130    // ex : gdcm-US-ALOKA-16.dcm
00131    // 0028|1221 [OW]   [Segmented Red Palette Color Lookup Table Data]
00132    // 0028|1222 [OW]   [Segmented Green Palette Color Lookup Table Data]  
00133    // 0028|1223 [OW]   [Segmented Blue Palette Color Lookup Table Data]
00134 
00135    // ex  : OT-PAL-8-face.dcm
00136    // 0028|1201 [US]   [Red Palette Color Lookup Table Data]
00137    // 0028|1202 [US]   [Green Palette Color Lookup Table Data]
00138    // 0028|1203 [US]   [Blue Palette Color Lookup Table Data]
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    /*if ( str_PhotometricInterpretation == "PALETTE COLOR " )*/
00155    // pb when undealt Segmented Palette Color
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; // no PixelRaw
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 ; // no PixelRaw
00227    if (!Header->HasLUT())
00228       return lgrTotale; 
00229                             
00230    // from Lut R + Lut G + Lut B
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);// move Gray pixels to temp area     
00237       int j;     
00238       for (int i=0;i<l; i++) {         // Build RGB Pixels
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    // now, it's an RGB image
00247    // Lets's write it in the Header
00248 
00249          // CreateOrReplaceIfExist ?
00250          
00251    std::string spp = "3";        // Samples Per Pixel
00252    Header->SetEntryByNumber(spp,0x0028,0x0002);
00253    std::string rgb= "RGB ";      // Photometric Interpretation
00254    Header->SetEntryByNumber(rgb,0x0028,0x0004);
00255    std::string planConfig = "0"; // Planar Configuration
00256    Header->SetEntryByNumber(planConfig,0x0028,0x0006);
00257 
00258    } else { 
00259              // need to make RGB Pixels (?)
00260              //    from grey Pixels (?!)
00261              //     and Gray Lut  (!?!) 
00262              //    or Segmented xxx Palette Color Lookup Table Data and so on
00263                                                   
00264          // Oops! I get one (gdcm-US-ALOKA-16.dcm)
00265          // No idea how to manage such an image 
00266          // It seems that *no Dicom Viewer* has any idea :-(
00267          // Segmented xxx Palette Color are *more* than 65535 long ?!?
00268                    
00269       std::string rgb= "MONOCHROME1 ";      // Photometric Interpretation
00270       Header->SetEntryByNumber(rgb,0x0028,0x0004);                                 
00271    }             
00272    // TODO : Drop Palette Color out of the Header?           
00273    return lgrTotale; 
00274 }
00275 
00286 void * gdcmFile::GetImageDataRaw (void) {
00287    if (Header->HasLUT())
00288       lgrTotale /= 3;  // TODO Let gdcmHeadar user a chance 
00289                        // to get the right value
00290                        // Create a member lgrTotaleRaw ???
00291    PixelData = (void *) malloc(lgrTotale);
00292    if (PixelData)
00293       GetImageDataIntoVectorRaw(PixelData, lgrTotale);
00294    PixelRead=1; // PixelRaw
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 ; // PixelRaw
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         // Number of Bits Allocated for storing a Pixel
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         // Number of Bits actually used
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         // High Bit Position
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         // Pixel sign
00358         // 0 = Unsigned
00359         // 1 = Signed
00360    str_signe=Header->GetEntryByNumber(0x0028,0x0103);
00361    if (str_signe == GDCM_UNFOUND ) {
00362       signe = 0;  // default is unsigned
00363    } else {
00364       signe = atoi(str_signe.c_str() );
00365    }
00366 
00367    // re arange bytes inside the integer (processor endianity)
00368    if (nb != 8)
00369      SwapZone(destination, Header->GetSwapCode(), lgrTotale, nb);
00370      
00371    // to avoid pb with some xmedcon breakers images 
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    // re arange bits inside the bytes
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 // DO NOT remove this code commented out.
00407 // Nobody knows what's expecting you ...
00408 // Just to 'see' what was actually read on disk :-(
00409 
00410 //   FILE * f2;
00411 //   f2 = fopen("SpuriousFile.RAW","wb");
00412 //   fwrite(destination,lgrTotale,1,f2);
00413 //   fclose(f2);
00414 
00415    // Deal with the color
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    // Planar configuration = 0 : Pixels are already RGB
00427    // Planar configuration = 1 : 3 planes : R, G, B
00428    // Planar configuration = 2 : 1 gray Plane + 3 LUT
00429 
00430    // Well ... supposed to be !
00431    // See US-PAL-8-10x-echo.dcm: PlanarConfiguration=0,
00432    //                            PhotometricInterpretation=PALETTE COLOR
00433    // and heuristic has to be found :-( 
00434 
00435       int planConf=Header->GetPlanarConfiguration();  // 0028,0006
00436 
00437       // Whatever Planar Configuration is, 
00438       // "PALETTE COLOR " implies that we deal with the palette. 
00439       if (str_PhotometricInterpretation == "PALETTE COLOR ")
00440          planConf=2;
00441 
00442       switch (planConf) {
00443       case 0:                              
00444          //       Pixels are already RGB
00445          break;
00446     
00447       case 1:
00448 
00449          {
00450          if (str_PhotometricInterpretation == "YBR_FULL") { 
00451          
00452    // Warning : YBR_FULL_422 acts as RGB
00453    //         : we need to make RGB Pixels from Planes Y,cB,cR
00454          
00455          // to see the tricks about YBR_FULL, YBR_FULL_422, 
00456          // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at :
00457          //   ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf
00458          // and be *very* affraid
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             // TODO : Replace by the 'well known' 
00471             //        integer computation counterpart
00472             // see http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
00473             // for code optimisation
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          //       need to make RGB Pixels from R,G,B Planes
00500          //       (all the Frames at a time)
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          //       Palettes were found
00522          //       Let the user deal with them !
00523          return lgrTotale;        
00524    } 
00525    // now, it's an RGB image
00526    // Lets's write it in the Header
00527 
00528    // CreateOrReplaceIfExist ?
00529 
00530    std::string spp = "3";        // Samples Per Pixel
00531    Header->SetEntryByNumber(spp,0x0028,0x0002);
00532    std::string rgb="RGB ";   // Photometric Interpretation
00533    Header->SetEntryByNumber(rgb,0x0028,0x0004);
00534 
00535    std::string planConfig = "0"; // Planar Configuration
00536    Header->SetEntryByNumber(planConfig,0x0028,0x0006);
00537          
00538          // TODO : Drop Palette Color out of the Header? 
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 // Protected
00649 bool gdcmFile::WriteBase (std::string fileName, FileType type) {
00650 
00651    FILE * fp1;
00652    
00653    if (PixelRead==-1 && type != DICOMDIR) {
00654 /*      std::cout << "U never Read the pixels; U cannot write the file" 
00655                 << std::endl;*/
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       // writing Dicom File Preamble
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    // Special Patch to allow gdcm to re-write ACR-LibIDO formated images
00676    //
00677    // if recognition code tells us we dealt with a LibIDO image
00678    // we reproduce on disk the switch between lineNumber and columnNumber
00679    // just before writting ...
00680    
00681    // TODO : the best trick would be *change* the recognition code
00682    //        but pb expected if user deals with, e.g. COMPLEX images
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    // ----------------- End of Special Patch ----------------
00692    
00693    // TODO : get the grPixel, numPixel values (for some ACR-NEMA images only)
00694    
00695    guint16 grPixel =Header->GetGrPixel();
00696    guint16 numPixel=Header->GetNumPixel();;
00697     
00698    // Update Pixel Data Length
00699    // the *last* of the (GrPixel, NumPixel), if many.
00700           
00701    TagKey key = gdcmDictEntry::TranslateToKey(grPixel, numPixel); 
00702    TagHeaderEntryHT::iterator p2;
00703    gdcmHeaderEntry * PixelElement;
00704    
00705    IterHT it= Header->GetEntry().equal_range(key); // get a pair of iterators first-last synonym   
00706 
00707    if (Header->GetEntry().count(key) == 1) // only the first is significant
00708       p2=it.first; // iterator on the first (unique) synonym
00709    else
00710       p2=it.second;// iterator on the last synonym
00711    
00712    PixelElement=p2->second;        // H Table target column (2-nd col)
00713   // PixelElement->SetPrintLevel(2);
00714   // PixelElement->Print();      
00715  
00716    if (PixelRead==1)
00717       PixelElement->SetLength(lgrTotaleRaw);
00718    else if (PixelRead==0)
00719       PixelElement->SetLength(lgrTotale);
00720    
00721    //PixelElement->SetPrintLevel(2);
00722    //PixelElement->Print();    
00723  
00724    Header->Write(fp1, type);
00725 
00726    // --------------------------------------------------------------
00727    // Special Patch to allow gdcm to re-write ACR-LibIDO formated images
00728    // 
00729    // ...and we restore the Header to be Dicom Compliant again 
00730    // just after writting
00731 
00732    if (Header->GetFileType() == ACR_LIBIDO){
00733          Header->SetEntryByNumber(rows   , 0x0028, 0x0010);
00734          Header->SetEntryByNumber(columns, 0x0028, 0x0011);
00735    }    
00736    // ----------------- End of Special Patch ----------------
00737    
00738    fwrite(PixelData, lgrTotale, 1, fp1);
00739    fclose (fp1);
00740    return(true);
00741 }
00742 
00743 //-----------------------------------------------------------------------------
00744 // Private
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;    /* 4321 */
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;    /* 2143 */
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;    /* 3412 */
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    // ----------------------  Compacted File (12 Bits Per Pixel)
00841    /* unpack 12 Bits pixels into 16 Bits pixels */
00842    /* 2 pixels 12bit =     [0xABCDEF]           */
00843    /* 2 pixels 16bit = [0x0ABD] + [0x0FCE]      */
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          //Two steps is necessary to please VC++
00855          *pdestination++ =  ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
00856                               /* A */            /* B */             /* D */
00857          *pdestination++ =  ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
00858                              /* F */               /* C */           /* E */
00859                   
00860         // Troubles expected on Big-Endian processors ?       
00861       }
00862 
00863       Header->CloseFile();
00864       return(true);
00865    }        
00866 
00867    // ----------------------  Uncompressed File
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    // ---------------------- Run Length Encoding
00885    if (Header->IsRLELossLessTransferSyntax()) {
00886       bool res = (bool)gdcm_read_RLE_file (fp,destination);
00887       Header->CloseFile();
00888       return res; 
00889    }  
00890     
00891    // --------------- SingleFrame/Multiframe JPEG Lossless/Lossy/2000 
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;  // ?? 12 should be ACR-NEMA only ?
00899    }
00900 
00901    int nBytes= nb/8;
00902    
00903    int taille = Header->GetXSize() * Header->GetYSize()  
00904                * Header->GetSamplesPerPixel();    
00905    long fragmentBegining; // for ftell, fseek
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    //  Position on begining of Jpeg Pixels
00915    
00916    fread(&ItemTagGr,2,1,fp);  // Reading (fffe) : Item Tag Gr
00917    fread(&ItemTagEl,2,1,fp);  // Reading (e000) : Item Tag El
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);    // Basic Offset Table Item length
00925       
00926    if (ln != 0) {
00927       // What is it used for ?!?
00928       char *BasicOffsetTableItemValue = (char *)malloc(ln+1);        
00929       fread(BasicOffsetTableItemValue,ln,1,fp); 
00930    }
00931    
00932    // first Fragment initialisation
00933    fread(&ItemTagGr,2,1,fp);  // Reading (fffe) : Item Tag Gr
00934    fread(&ItemTagEl,2,1,fp);  // Reading (e000) : Item Tag El
00935    if(Header->GetSwapCode()) {
00936       ItemTagGr=Header->SwapShort(ItemTagGr); 
00937       ItemTagEl=Header->SwapShort(ItemTagEl);            
00938    }
00939            
00940    // parsing fragments until Sequence Delim. Tag found
00941    while ( ( ItemTagGr == 0xfffe) && (ItemTagEl != 0xe0dd) ) { 
00942       // --- for each Fragment
00943 
00944       fread(&ln,4,1,fp); 
00945       if(Header->GetSwapCode()) 
00946          ln=Header->SwapLong(ln);    // Fragment Item length
00947    
00948       fragmentBegining=ftell(fp);   
00949 
00950       if (jpg2000) {          // JPEG 2000 :    call to ???
00951  
00952          res = (bool)gdcm_read_JPEG2000_file (fp,destination);  // Not Yet written 
00953 
00954       } // ------------------------------------- endif (JPEG2000)
00955         
00956       else if (jpgLossless) { // JPEG LossLess : call to xmedcom JPEG
00957                    
00958          JPEGLosslessDecodeImage (fp,  // Reading Fragment pixels
00959                                      (unsigned short *)destination,
00960                                      Header->GetPixelSize()*8* Header->GetSamplesPerPixel(),
00961                                      ln);                                                          
00962          res=1; // in order not to break the loop
00963   
00964       } // ------------------------------------- endif (JPEGLossless)
00965                
00966       else {                   // JPEG Lossy : call to IJG 6b
00967 
00968          if  (Header->GetBitsStored() == 8) {
00969             res = (bool)gdcm_read_JPEG_file (fp,destination);  // Reading Fragment pixels         
00970          } else {
00971             res = (bool)gdcm_read_JPEG_file12 (fp,destination);// Reading Fragment pixels  
00972          } 
00973       }  // ------------------------------------- endif (JPEGLossy)    
00974          
00975       if (!res) break;
00976                
00977       destination = (char *)destination + taille * nBytes; // location in user's memory 
00978                                                            // for next fragment (if any) 
00979       
00980       fseek(fp,fragmentBegining,SEEK_SET); // To be sure we start 
00981       fseek(fp,ln,SEEK_CUR);               // at the begining of next fragment
00982       
00983       ItemTagGr = ItemTagEl =0;
00984       fread(&ItemTagGr,2,1,fp);  // Reading (fffe) : Item Tag Gr
00985       fread(&ItemTagEl,2,1,fp);  // Reading (e000) : Item Tag El
00986       if(Header->GetSwapCode()) {
00987          ItemTagGr=Header->SwapShort(ItemTagGr); 
00988          ItemTagEl=Header->SwapShort(ItemTagEl);            
00989       } 
00990    
00991    }     // endWhile parsing fragments until Sequence Delim. Tag found    
00992  
00993    Header->CloseFile();
00994    return res;
00995 }
00996 //-----------------------------------------------------------------------------

Generated on Mon Feb 14 16:13:44 2005 for gdcm by doxygen 1.3.6