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