]> Creatis software - gdcm.git/blob - src/gdcmRLE.cxx
* src/*.h : add comments
[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 bool gdcmFile::gdcm_read_RLE_file (FILE *fp,void * image_buffer) {
32    long fragmentBegining; // for ftell, fseek
33    char * im = (char *)image_buffer;
34
35    long RleSegmentLength[15],fragmentLength,uncompressedSegmentSize;;
36    long ftellRes, ln;
37    guint32 nbRleSegments;
38    guint32 RleSegmentOffsetTable[15];
39    guint16 ItemTagGr,ItemTagEl;
40    uncompressedSegmentSize=Header->GetXSize()*Header->GetYSize();
41    ftellRes=ftell(fp);
42    // Basic Offset Table with Item Value
43       // Item Tag
44    fread(&ItemTagGr,2,1,fp);  // Reading (fffe):Basic Offset Table Item Tag Gr
45    fread(&ItemTagEl,2,1,fp);  // Reading (e000):Basic Offset Table Item Tag El
46    if(Header->GetSwapCode()) {
47       ItemTagGr=Header->SwapShort(ItemTagGr); 
48       ItemTagEl=Header->SwapShort(ItemTagEl);      
49    }
50       // Item Length
51    ftellRes=ftell(fp);
52    fread(&ln,4,1,fp); 
53    if(Header->GetSwapCode()) 
54       ln=Header->SwapLong(ln);    // Basic Offset Table Item Lentgh
55    if (ln != 0) {
56       // What is it used for ??
57       char * BasicOffsetTableItemValue= (char *)malloc(ln+1);
58       fread(BasicOffsetTableItemValue,ln,1,fp); 
59       guint32 a;
60       for (int i=0;i<ln;i+=4){
61          a=str2num(&BasicOffsetTableItemValue[i],guint32);
62       }        
63    }
64
65    ftellRes=ftell(fp);
66    fread(&ItemTagGr,2,1,fp);  // Reading (fffe) : Item Tag Gr
67    fread(&ItemTagEl,2,1,fp);  // Reading (e000) : Item Tag El
68    if(Header->GetSwapCode()) {
69       ItemTagGr=Header->SwapShort(ItemTagGr); 
70       ItemTagEl=Header->SwapShort(ItemTagEl);      
71    }  
72
73    // while 'Sequence Delimiter Item' (fffe,e0dd) not found
74    while (  ( ItemTagGr == 0xfffe) && (ItemTagEl != 0xe0dd) ) { 
75    // Parse fragments of the current Fragment (Frame)    
76       ftellRes=ftell(fp);
77       fread(&fragmentLength,4,1,fp); 
78       if(Header->GetSwapCode()) 
79          fragmentLength=Header->SwapLong(fragmentLength);    // length
80
81           //------------------ scanning (not reading) fragment pixels
82  
83       fread(&nbRleSegments,4,1,fp);  // Reading : Number of RLE Segments        
84       if(Header->GetSwapCode()) 
85          nbRleSegments=Header->SwapLong(nbRleSegments);
86  
87       for(int k=1; k<=15; k++) { // Reading RLE Segments Offset Table
88          ftellRes=ftell(fp);
89          fread(&RleSegmentOffsetTable[k],4,1,fp);
90          if(Header->GetSwapCode())
91             RleSegmentOffsetTable[k]=Header->SwapLong(RleSegmentOffsetTable[k]);
92       }
93
94       if (nbRleSegments>1) { 
95          for(int k=1; k<=nbRleSegments-1; k++) { // reading RLE Segments
96             RleSegmentLength[k]=RleSegmentOffsetTable[k+1]-RleSegmentOffsetTable[k];
97             ftellRes=ftell(fp);
98             fragmentBegining=ftell(fp);   
99             _gdcm_read_RLE_fragment (&im, RleSegmentLength[k],uncompressedSegmentSize,fp);
100             fseek(fp,fragmentBegining,SEEK_SET);  
101             fseek(fp,RleSegmentLength[k],SEEK_CUR);        
102          }
103       }
104       RleSegmentLength[nbRleSegments] = fragmentLength - RleSegmentOffsetTable[nbRleSegments];
105       ftellRes=ftell(fp);
106       fragmentBegining=ftell(fp);
107       _gdcm_read_RLE_fragment (&im, RleSegmentLength[nbRleSegments],uncompressedSegmentSize, fp);
108       fseek(fp,fragmentBegining,SEEK_SET);  
109       fseek(fp,RleSegmentLength[nbRleSegments],SEEK_CUR);    
110       
111       // end of scanning fragment pixels       
112    
113       ftellRes=ftell(fp);
114       fread(&ItemTagGr,2,1,fp);  // Reading (fffe) : Item Tag Gr
115       fread(&ItemTagEl,2,1,fp);  // Reading (e000) : Item Tag El
116       if(Header->GetSwapCode()) {
117          ItemTagGr=Header->SwapShort(ItemTagGr); 
118          ItemTagEl=Header->SwapShort(ItemTagEl);      
119       }
120    } 
121    
122    if (Header->GetBitsAllocated()==16) { // try to deal with RLE 16 Bits
123    
124       im = (char *)image_buffer;
125          //  need to make 16 Bits Pixels from Low Byte and Hight Byte 'Planes'
126
127       int l = Header->GetXSize()*Header->GetYSize();
128       int nbFrames = Header->GetZSize();
129
130       char * newDest = (char*) malloc(l*nbFrames*2);
131       char *x  = newDest;
132       char * a = (char *)image_buffer;
133       char * b = a + l;
134
135       for (int i=0;i<nbFrames;i++) {
136          for (int j=0;j<l; j++) {
137             *(x++) = *(a++);
138             *(x++) = *(b++);
139          }
140       }
141       memmove(image_buffer,newDest,lgrTotale);
142       free(newDest);   
143    }
144       
145    return(true);
146 }
147
148
149  /* -------------------------------------------------------------------- */
150  //
151  // RLE LossLess Fragment
152  //
153  /* -------------------------------------------------------------------- */
154
155    // static because nothing but gdcm_read_RLE_file can call it
156    // DO NOT doxygen !
157
158 static int
159 _gdcm_read_RLE_fragment (char ** areaToRead, 
160                          long lengthToDecode, 
161                          long uncompressedSegmentSize, 
162                          FILE* fp) {
163    long ftellRes;
164    int count;
165    long numberOfOutputBytes=0;
166    char n, car;
167    ftellRes =ftell(fp);
168
169    while(numberOfOutputBytes<uncompressedSegmentSize) {
170
171       ftellRes =ftell(fp);
172       fread(&n,sizeof(char),1,fp);
173       count=n;
174       if (count >= 0 && count <= 127) {
175          fread(*areaToRead,(count+1)*sizeof(char),1,fp);
176          *areaToRead+=count+1;
177          numberOfOutputBytes+=count+1;
178       } else {
179          if (count <= -1 && count >= -127) {
180             fread(&car,sizeof(char),1,fp);
181             for(int i=0; i<-count+1; i++) {
182                (*areaToRead)[i]=car;  
183             }
184             *areaToRead+=(-count+1);
185             numberOfOutputBytes+=(-count+1); 
186          }
187       } 
188       // if count = 128 output nothing (See : PS 3.5-2003 Page 86)
189    } 
190    return 1;
191 }