]> Creatis software - gdcm.git/blob - src/gdcmRLE.cxx
* gdcmDirList : to parse a hard drive directory in recursive (or not)
[gdcm.git] / src / gdcmRLE.cxx
1 // gdcmRLE.cxx
2 //-----------------------------------------------------------------------------
3 #include <stdio.h>
4 #include "gdcmFile.h"
5 #include <ctype.h>              /* to declare isprint() */
6
7 #define str2num(str, typeNum) *((typeNum *)(str))
8
9 //-----------------------------------------------------------------------------
10 /**
11  * \ingroup   gdcmFile
12  * \brief     Reads a 'Run Length Encoded' Dicom encapsulated file
13  * @param     fp already open File Pointer
14  * @param     image_buffer destination Address (in caller's memory space) 
15  *            at which the pixel data should be copied
16  *   
17  * @return    Boolean 
18  */
19 bool gdcmFile::gdcm_read_RLE_file (FILE *fp,void * image_buffer) {
20    long fragmentBegining; // for ftell, fseek
21    char * im = (char *)image_buffer;
22
23    long RleSegmentLength[15],fragmentLength,uncompressedSegmentSize;;
24    long ftellRes, ln;
25    guint32 nbRleSegments;
26    guint32 RleSegmentOffsetTable[15];
27    guint16 ItemTagGr,ItemTagEl;
28    uncompressedSegmentSize=Header->GetXSize()*Header->GetYSize();
29    ftellRes=ftell(fp);
30    // Basic Offset Table with Item Value
31       // Item Tag
32    fread(&ItemTagGr,2,1,fp);  // Reading (fffe):Basic Offset Table Item Tag Gr
33    fread(&ItemTagEl,2,1,fp);  // Reading (e000):Basic Offset Table Item Tag El
34    if(Header->GetSwapCode()) {
35       ItemTagGr=Header->SwapShort(ItemTagGr); 
36       ItemTagEl=Header->SwapShort(ItemTagEl);      
37    }
38       // Item Length
39    ftellRes=ftell(fp);
40    fread(&ln,4,1,fp); 
41    if(Header->GetSwapCode()) 
42       ln=Header->SwapLong(ln);    // Basic Offset Table Item Lentgh
43    if (ln != 0) {
44       // What is it used for ??
45       char * BasicOffsetTableItemValue= (char *)malloc(ln+1);
46       fread(BasicOffsetTableItemValue,ln,1,fp); 
47       guint32 a;
48       for (int i=0;i<ln;i+=4){
49          a=str2num(&BasicOffsetTableItemValue[i],guint32);
50       }        
51    }
52
53    ftellRes=ftell(fp);
54    fread(&ItemTagGr,2,1,fp);  // Reading (fffe) : Item Tag Gr
55    fread(&ItemTagEl,2,1,fp);  // Reading (e000) : Item Tag El
56    if(Header->GetSwapCode()) {
57       ItemTagGr=Header->SwapShort(ItemTagGr); 
58       ItemTagEl=Header->SwapShort(ItemTagEl);      
59    }  
60
61    // while 'Sequence Delimiter Item' (fffe,e0dd) not found
62    while (  ( ItemTagGr == 0xfffe) && (ItemTagEl != 0xe0dd) ) { 
63    // Parse fragments of the current Fragment (Frame)    
64       ftellRes=ftell(fp);
65       fread(&fragmentLength,4,1,fp); 
66       if(Header->GetSwapCode()) 
67          fragmentLength=Header->SwapLong(fragmentLength);    // length
68
69           //------------------ scanning (not reading) fragment pixels
70  
71       fread(&nbRleSegments,4,1,fp);  // Reading : Number of RLE Segments        
72       if(Header->GetSwapCode()) 
73          nbRleSegments=Header->SwapLong(nbRleSegments);
74  
75       for(int k=1; k<=15; k++) { // Reading RLE Segments Offset Table
76          ftellRes=ftell(fp);
77          fread(&RleSegmentOffsetTable[k],4,1,fp);
78          if(Header->GetSwapCode())
79             RleSegmentOffsetTable[k]=Header->SwapLong(RleSegmentOffsetTable[k]);
80       }
81
82       if (nbRleSegments>1) { 
83          for(int k=1; k<=nbRleSegments-1; k++) { // reading RLE Segments
84             RleSegmentLength[k]=RleSegmentOffsetTable[k+1]-RleSegmentOffsetTable[k];
85             ftellRes=ftell(fp);
86             fragmentBegining=ftell(fp);   
87             gdcm_read_RLE_fragment (&im, RleSegmentLength[k],uncompressedSegmentSize,fp);
88             fseek(fp,fragmentBegining,SEEK_SET);  
89             fseek(fp,RleSegmentLength[k],SEEK_CUR);        
90          }
91       }
92       RleSegmentLength[nbRleSegments] = fragmentLength - RleSegmentOffsetTable[nbRleSegments];
93       ftellRes=ftell(fp);
94       fragmentBegining=ftell(fp);
95       gdcm_read_RLE_fragment (&im, RleSegmentLength[nbRleSegments],uncompressedSegmentSize, fp);
96       fseek(fp,fragmentBegining,SEEK_SET);  
97       fseek(fp,RleSegmentLength[nbRleSegments],SEEK_CUR);    
98       
99       // end of scanning fragment pixels       
100    
101       ftellRes=ftell(fp);
102       fread(&ItemTagGr,2,1,fp);  // Reading (fffe) : Item Tag Gr
103       fread(&ItemTagEl,2,1,fp);  // Reading (e000) : Item Tag El
104       if(Header->GetSwapCode()) {
105          ItemTagGr=Header->SwapShort(ItemTagGr); 
106          ItemTagEl=Header->SwapShort(ItemTagEl);      
107       }
108    } 
109    
110    if (Header->GetBitsAllocated()==16) { // try to deal with RLE 16 Bits
111    
112       im = (char *)image_buffer;
113          //  need to make 16 Bits Pixels from Low Byte and Hight Byte 'Planes'
114
115       int l = Header->GetXSize()*Header->GetYSize();
116       int nbFrames = Header->GetZSize();
117
118       char * newDest = (char*) malloc(l*nbFrames*2);
119       char *x  = newDest;
120       char * a = (char *)image_buffer;
121       char * b = a + l;
122
123       for (int i=0;i<nbFrames;i++) {
124          for (int j=0;j<l; j++) {
125             *(x++) = *(a++);
126             *(x++) = *(b++);
127          }
128       }
129       memmove(image_buffer,newDest,lgrTotale);
130       free(newDest);   
131    }
132       
133    return(true);
134 }
135
136
137 // ----------------------------------------------------------------------------
138 // RLE LossLess Fragment
139 int gdcmFile::gdcm_read_RLE_fragment(char **areaToRead, long lengthToDecode, 
140                                      long uncompressedSegmentSize, FILE *fp) {
141    long ftellRes;
142    int count;
143    long numberOfOutputBytes=0;
144    char n, car;
145    ftellRes =ftell(fp);
146
147    while(numberOfOutputBytes<uncompressedSegmentSize) {
148       ftellRes =ftell(fp);
149       fread(&n,sizeof(char),1,fp);
150       count=n;
151       if (count >= 0 && count <= 127) {
152          fread(*areaToRead,(count+1)*sizeof(char),1,fp);
153          *areaToRead+=count+1;
154          numberOfOutputBytes+=count+1;
155       } else {
156          if (count <= -1 && count >= -127) {
157             fread(&car,sizeof(char),1,fp);
158             for(int i=0; i<-count+1; i++) {
159                (*areaToRead)[i]=car;  
160             }
161             *areaToRead+=(-count+1);
162             numberOfOutputBytes+=(-count+1); 
163          }
164       } 
165       // if count = 128 output nothing (See : PS 3.5-2003 Page 86)
166    } 
167    return 1;
168 }
169
170 // ----------------------------------------------------------------------------