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